From 115cf04ba1e1006ae31ecabc0f19d6ab792678d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= <emilio@crisal.io>
Date: Sun, 1 Jul 2018 14:29:44 +0200
Subject: [PATCH] Bug 1472538: Update bindgen. r=xidorn

Surprisingly painless.

I'll update to 0.37.4 instead of .3, but that only contains
https://github.com/rust-lang-nursery/rust-bindgen/pull/1343 on top to prevent
build warnings.

MozReview-Commit-ID: H0uMtdGnXvL
---
 Cargo.lock                                    |  225 +-
 js/rust/Cargo.toml                            |    2 +-
 servo/components/style/Cargo.toml             |    2 +-
 .../rust/aho-corasick/.cargo-checksum.json    |    2 +-
 third_party/rust/aho-corasick/.travis.yml     |   13 +-
 third_party/rust/aho-corasick/Cargo.toml      |   69 +-
 third_party/rust/aho-corasick/README.md       |    2 +-
 .../rust/aho-corasick/benches/bench.rs        |   34 +
 third_party/rust/aho-corasick/ci/script.sh    |   20 +
 .../rust/aho-corasick/examples/dict-search.rs |   47 +-
 third_party/rust/aho-corasick/src/autiter.rs  |    6 +-
 third_party/rust/aho-corasick/src/full.rs     |   29 +-
 third_party/rust/aho-corasick/src/lib.rs      |  241 +-
 third_party/rust/bindgen/.cargo-checksum.json |    2 +-
 third_party/rust/bindgen/Cargo.toml           |   19 +-
 third_party/rust/bindgen/LICENSE              |   28 +
 third_party/rust/bindgen/README.md            |   45 +
 third_party/rust/bindgen/src/callbacks.rs     |   17 +-
 third_party/rust/bindgen/src/clang.rs         |   52 +-
 .../rust/bindgen/src/codegen/bitfield_unit.rs |   33 +-
 .../rust/bindgen/src/codegen/helpers.rs       |   48 +-
 .../bindgen/src/codegen/impl_partialeq.rs     |    5 +-
 third_party/rust/bindgen/src/codegen/mod.rs   |  376 +-
 .../rust/bindgen/src/codegen/struct_layout.rs |   51 +-
 third_party/rust/bindgen/src/features.rs      |   31 +-
 .../bindgen/src/ir/analysis/derive_copy.rs    |    6 +-
 .../bindgen/src/ir/analysis/derive_debug.rs   |    4 +-
 .../bindgen/src/ir/analysis/derive_default.rs |    4 +-
 .../bindgen/src/ir/analysis/derive_hash.rs    |    4 +-
 .../derive_partialeq_or_partialord.rs         |    4 +-
 .../src/ir/analysis/template_params.rs        |    4 +-
 third_party/rust/bindgen/src/ir/comment.rs    |    2 +-
 third_party/rust/bindgen/src/ir/comp.rs       |   20 +-
 third_party/rust/bindgen/src/ir/context.rs    |  210 +-
 third_party/rust/bindgen/src/ir/derive.rs     |    2 +-
 third_party/rust/bindgen/src/ir/dot.rs        |   18 +-
 third_party/rust/bindgen/src/ir/enum_ty.rs    |   80 +-
 third_party/rust/bindgen/src/ir/function.rs   |   31 +-
 third_party/rust/bindgen/src/ir/item.rs       |   18 +-
 third_party/rust/bindgen/src/ir/item_kind.rs  |    4 +-
 third_party/rust/bindgen/src/ir/layout.rs     |   29 +-
 third_party/rust/bindgen/src/ir/objc.rs       |    8 +-
 third_party/rust/bindgen/src/ir/template.rs   |   63 +-
 third_party/rust/bindgen/src/ir/traversal.rs  |   17 +-
 third_party/rust/bindgen/src/ir/ty.rs         |   39 +-
 third_party/rust/bindgen/src/ir/var.rs        |   20 +-
 third_party/rust/bindgen/src/lib.rs           |  228 +-
 third_party/rust/bindgen/src/options.rs       |   73 +-
 third_party/rust/bindgen/src/time.rs          |    2 +-
 .../rust/clang-sys/.cargo-checksum.json       |    2 +-
 third_party/rust/clang-sys/.travis.yml        |    7 -
 third_party/rust/clang-sys/CHANGELOG.md       |   18 +
 third_party/rust/clang-sys/CONTRIBUTING.md    |    7 -
 third_party/rust/clang-sys/Cargo.toml         |   16 +-
 third_party/rust/clang-sys/README.md          |   15 +-
 third_party/rust/clang-sys/build.rs           |   71 +-
 third_party/rust/clang-sys/ci/install.bat     |    2 +-
 third_party/rust/clang-sys/src/lib.rs         |   29 +-
 third_party/rust/clang-sys/src/link.rs        |    6 +-
 third_party/rust/clang-sys/src/support.rs     |    9 +-
 third_party/rust/libc/.cargo-checksum.json    |    2 +-
 third_party/rust/libc/.travis.yml             |   29 +-
 third_party/rust/libc/Cargo.toml              |    5 +-
 third_party/rust/libc/README.md               |   57 +-
 third_party/rust/libc/appveyor.yml            |    1 +
 third_party/rust/libc/ci/README.md            |   92 +-
 .../aarch64-unknown-linux-musl/Dockerfile     |   12 +-
 .../arm-unknown-linux-musleabihf/Dockerfile   |   12 +-
 .../docker/i686-unknown-linux-gnu/Dockerfile  |    2 +-
 .../docker/i686-unknown-linux-musl/Dockerfile |   13 +-
 .../docker/s390x-unknown-linux-gnu/Dockerfile |   16 +-
 .../sparc64-unknown-linux-gnu/Dockerfile      |   23 +-
 .../wasm32-unknown-emscripten/node-wrapper.sh |    4 +
 .../docker/x86_64-unknown-freebsd/Dockerfile  |    8 +-
 .../x86_64-unknown-linux-gnu/Dockerfile       |    2 +-
 .../x86_64-unknown-linux-gnux32/Dockerfile    |    2 +-
 .../x86_64-unknown-linux-musl/Dockerfile      |   12 +-
 third_party/rust/libc/ci/dox.sh               |    2 +-
 third_party/rust/libc/ci/emscripten-entry.sh  |    2 +-
 .../ci/ios/deploy_and_run_on_ios_simulator.rs |    1 +
 third_party/rust/libc/ci/linux-s390x.sh       |   18 +
 third_party/rust/libc/ci/linux-sparc64.sh     |   17 +
 third_party/rust/libc/ci/run.sh               |   24 +-
 third_party/rust/libc/ci/style.rs             |    4 +-
 third_party/rust/libc/ci/test-runner-linux    |   23 +
 third_party/rust/libc/src/cloudabi/aarch64.rs |    4 +
 third_party/rust/libc/src/cloudabi/arm.rs     |    4 +
 third_party/rust/libc/src/cloudabi/mod.rs     |  166 +
 third_party/rust/libc/src/cloudabi/x86.rs     |    4 +
 third_party/rust/libc/src/cloudabi/x86_64.rs  |    4 +
 third_party/rust/libc/src/dox.rs              |   71 +-
 third_party/rust/libc/src/fuchsia/aarch64.rs  |  336 +
 third_party/rust/libc/src/fuchsia/mod.rs      | 3999 +++++++++++
 .../rust/libc/src/fuchsia/powerpc64.rs        |   79 +
 third_party/rust/libc/src/fuchsia/x86_64.rs   |  447 ++
 third_party/rust/libc/src/lib.rs              |  397 +-
 third_party/rust/libc/src/macros.rs           |   25 +-
 third_party/rust/libc/src/redox/mod.rs        |   34 +
 third_party/rust/libc/src/redox/net.rs        |   14 +
 .../rust/libc/src/unix/bsd/apple/b32.rs       |    7 +
 .../rust/libc/src/unix/bsd/apple/b64.rs       |    9 +-
 .../rust/libc/src/unix/bsd/apple/mod.rs       |  417 +-
 .../src/unix/bsd/freebsdlike/dragonfly/mod.rs |   84 +
 .../src/unix/bsd/freebsdlike/freebsd/mod.rs   |  200 +-
 .../rust/libc/src/unix/bsd/freebsdlike/mod.rs |  110 +-
 third_party/rust/libc/src/unix/bsd/mod.rs     |   10 +-
 .../rust/libc/src/unix/bsd/netbsdlike/mod.rs  |   37 +-
 .../src/unix/bsd/netbsdlike/netbsd/mod.rs     |  157 +-
 .../openbsdlike/{bitrig.rs => bitrig/mod.rs}  |   36 +
 .../{other/b32/mod.rs => bitrig/x86.rs}       |    0
 .../{other/b64/mod.rs => bitrig/x86_64.rs}    |    0
 .../unix/bsd/netbsdlike/openbsdlike/mod.rs    |   55 +-
 .../bsd/netbsdlike/openbsdlike/openbsd.rs     |   35 -
 .../netbsdlike/openbsdlike/openbsd/aarch64.rs |    3 +
 .../bsd/netbsdlike/openbsdlike/openbsd/mod.rs |  279 +
 .../bsd/netbsdlike/openbsdlike/openbsd/x86.rs |    3 +
 .../netbsdlike/openbsdlike/openbsd/x86_64.rs  |    3 +
 .../bsd/netbsdlike/openbsdlike/other/mod.rs   |   11 -
 third_party/rust/libc/src/unix/haiku/mod.rs   |   55 +-
 .../rust/libc/src/unix/hermit/aarch64.rs      |    2 +
 third_party/rust/libc/src/unix/hermit/mod.rs  |  736 ++
 .../rust/libc/src/unix/hermit/x86_64.rs       |    2 +
 third_party/rust/libc/src/unix/mod.rs         |   54 +-
 .../rust/libc/src/unix/newlib/aarch64/mod.rs  |    5 +
 third_party/rust/libc/src/unix/newlib/mod.rs  |  118 +-
 .../libc/src/unix/notbsd/android/b32/mod.rs   |   16 -
 .../libc/src/unix/notbsd/android/b64/mod.rs   |   25 -
 .../rust/libc/src/unix/notbsd/android/mod.rs  |  590 ++
 .../rust/libc/src/unix/notbsd/emscripten.rs   |   81 +-
 .../libc/src/unix/notbsd/linux/mips/mips32.rs |   72 +-
 .../libc/src/unix/notbsd/linux/mips/mips64.rs |   68 +
 .../libc/src/unix/notbsd/linux/mips/mod.rs    |  246 +
 .../rust/libc/src/unix/notbsd/linux/mod.rs    |  826 ++-
 .../src/unix/notbsd/linux/musl/b32/arm.rs     |   85 +
 .../src/unix/notbsd/linux/musl/b32/mips.rs    |   85 +
 .../src/unix/notbsd/linux/musl/b32/mod.rs     |   24 +-
 .../src/unix/notbsd/linux/musl/b32/powerpc.rs |  866 +++
 .../src/unix/notbsd/linux/musl/b32/x86.rs     |   85 +
 .../src/unix/notbsd/linux/musl/b64/aarch64.rs |  135 +
 .../src/unix/notbsd/linux/musl/b64/mod.rs     |   62 -
 .../unix/notbsd/linux/musl/b64/powerpc64.rs   |  513 +-
 .../src/unix/notbsd/linux/musl/b64/x86_64.rs  |  136 +
 .../libc/src/unix/notbsd/linux/musl/mod.rs    |  104 +-
 .../src/unix/notbsd/linux/other/b32/mod.rs    |   70 +
 .../unix/notbsd/linux/other/b64/aarch64.rs    |   50 +
 .../unix/notbsd/linux/other/b64/not_x32.rs    |   70 +
 .../unix/notbsd/linux/other/b64/powerpc64.rs  |   69 +
 .../unix/notbsd/linux/other/b64/sparc64.rs    |  422 +-
 .../src/unix/notbsd/linux/other/b64/x32.rs    |   43 +
 .../src/unix/notbsd/linux/other/b64/x86_64.rs |    5 +
 .../libc/src/unix/notbsd/linux/other/mod.rs   |  328 +-
 .../rust/libc/src/unix/notbsd/linux/s390x.rs  |   91 +-
 third_party/rust/libc/src/unix/notbsd/mod.rs  |  210 +-
 third_party/rust/libc/src/unix/solaris/mod.rs |  146 +-
 .../rust/libc/src/unix/uclibc/mips/mips32.rs  |  372 +-
 .../rust/libc/src/unix/uclibc/mips/mips64.rs  |    5 +
 .../rust/libc/src/unix/uclibc/mips/mod.rs     |    2 +
 third_party/rust/libc/src/unix/uclibc/mod.rs  |  138 +-
 .../rust/libc/src/unix/uclibc/x86_64/l4re.rs  |    1 +
 .../rust/libc/src/unix/uclibc/x86_64/mod.rs   |   83 +-
 .../rust/libc/src/unix/uclibc/x86_64/other.rs |    4 +
 .../rust/libloading/.cargo-checksum.json      |    2 +-
 third_party/rust/libloading/Cargo.toml        |   28 +-
 third_party/rust/libloading/README.mkd        |    6 -
 third_party/rust/libloading/build.rs          |   30 +-
 third_party/rust/libloading/src/changelog.rs  |   34 +
 third_party/rust/libloading/src/lib.rs        |   49 +-
 .../libloading/src/os/unix/global_static.c    |   20 +
 .../rust/libloading/src/os/unix/mod.rs        |   43 +-
 .../rust/libloading/src/os/windows/mod.rs     |  111 +-
 .../rust/libloading/tests/functions.rs        |   66 +
 third_party/rust/libloading/tests/statics.rs  |   44 -
 .../rust/memchr-1.0.2/.cargo-checksum.json    |    1 +
 third_party/rust/memchr-1.0.2/.travis.yml     |   14 +
 third_party/rust/memchr-1.0.2/COPYING         |    3 +
 third_party/rust/memchr-1.0.2/Cargo.toml      |   44 +
 third_party/rust/memchr-1.0.2/LICENSE-MIT     |   21 +
 third_party/rust/memchr-1.0.2/Makefile        |   14 +
 third_party/rust/memchr-1.0.2/README.md       |   36 +
 third_party/rust/memchr-1.0.2/UNLICENSE       |   24 +
 third_party/rust/memchr-1.0.2/appveyor.yml    |   19 +
 .../rust/memchr-1.0.2/benches/bench.rs        |  117 +
 third_party/rust/memchr-1.0.2/ctags.rust      |   11 +
 third_party/rust/memchr-1.0.2/session.vim     |    1 +
 third_party/rust/memchr-1.0.2/src/lib.rs      |  881 +++
 third_party/rust/memchr/.cargo-checksum.json  |    2 +-
 third_party/rust/memchr/.travis.yml           |   12 +-
 third_party/rust/memchr/Cargo.toml            |    5 +-
 third_party/rust/memchr/README.md             |    2 +-
 third_party/rust/memchr/appveyor.yml          |    5 +-
 third_party/rust/memchr/ci/script.sh          |   20 +
 third_party/rust/memchr/src/lib.rs            |  345 +-
 .../proc-macro2-0.2.2/.cargo-checksum.json    |    1 +
 .../rust/proc-macro2-0.2.2/.travis.yml        |   31 +
 third_party/rust/proc-macro2-0.2.2/Cargo.toml |   31 +
 .../rust/proc-macro2-0.2.2/LICENSE-APACHE     |  201 +
 .../rust/proc-macro2-0.2.2/LICENSE-MIT        |   25 +
 third_party/rust/proc-macro2-0.2.2/README.md  |   98 +
 third_party/rust/proc-macro2-0.2.2/src/lib.rs |  337 +
 .../src/macros.rs                             |    0
 .../rust/proc-macro2-0.2.2/src/stable.rs      | 1206 ++++
 .../rust/proc-macro2-0.2.2/src/strnom.rs      |  447 ++
 .../rust/proc-macro2-0.2.2/src/unstable.rs    |  406 ++
 .../rust/proc-macro2-0.2.2/tests/test.rs      |  179 +
 .../rust/proc-macro2/.cargo-checksum.json     |    2 +-
 third_party/rust/proc-macro2/.travis.yml      |    1 +
 third_party/rust/proc-macro2/Cargo.toml       |    6 +-
 third_party/rust/proc-macro2/README.md        |    4 +-
 third_party/rust/proc-macro2/src/lib.rs       |  483 +-
 third_party/rust/proc-macro2/src/stable.rs    |  615 +-
 third_party/rust/proc-macro2/src/strnom.rs    |   88 +-
 third_party/rust/proc-macro2/src/unstable.rs  |  327 +-
 third_party/rust/proc-macro2/tests/test.rs    |  152 +-
 .../rust/quote-0.4.2/.cargo-checksum.json     |    1 +
 third_party/rust/quote-0.4.2/Cargo.toml       |   24 +
 third_party/rust/quote-0.4.2/LICENSE-APACHE   |  201 +
 third_party/rust/quote-0.4.2/LICENSE-MIT      |   25 +
 third_party/rust/quote-0.4.2/README.md        |  135 +
 third_party/rust/quote-0.4.2/src/lib.rs       |  501 ++
 third_party/rust/quote-0.4.2/src/to_tokens.rs |  175 +
 third_party/rust/quote-0.4.2/src/tokens.rs    |  264 +
 third_party/rust/quote-0.4.2/tests/test.rs    |  292 +
 third_party/rust/quote/.cargo-checksum.json   |    2 +-
 third_party/rust/quote/Cargo.toml             |   10 +-
 third_party/rust/quote/README.md              |   10 +-
 third_party/rust/quote/src/lib.rs             |   84 +-
 third_party/rust/quote/src/to_tokens.rs       |   64 +-
 third_party/rust/quote/src/tokens.rs          |   44 +-
 third_party/rust/quote/tests/test.rs          |   19 +-
 .../rust/regex-0.2.2/.cargo-checksum.json     |    1 +
 third_party/rust/regex-0.2.2/.travis.yml      |   28 +
 third_party/rust/regex-0.2.2/CHANGELOG.md     |  276 +
 third_party/rust/regex-0.2.2/Cargo.toml       |   94 +
 third_party/rust/regex-0.2.2/HACKING.md       |  315 +
 third_party/rust/regex-0.2.2/LICENSE-APACHE   |  201 +
 third_party/rust/regex-0.2.2/LICENSE-MIT      |   25 +
 third_party/rust/regex-0.2.2/PERFORMANCE.md   |  279 +
 third_party/rust/regex-0.2.2/README.md        |  240 +
 third_party/rust/regex-0.2.2/appveyor.yml     |   17 +
 .../rust/regex-0.2.2/ci/after_success.sh      |   34 +
 third_party/rust/regex-0.2.2/ci/run-kcov      |   58 +
 .../rust/regex-0.2.2/ci/run-shootout-test     |   18 +
 third_party/rust/regex-0.2.2/ci/script.sh     |   35 +
 .../{regex => regex-0.2.2}/examples/bug347.rs |    0
 .../regex-0.2.2/examples/regexdna-input.txt   | 1671 +++++
 .../regex-0.2.2/examples/regexdna-output.txt  |   13 +
 .../examples/shootout-regex-dna-bytes.rs      |   66 +
 .../examples/shootout-regex-dna-cheat.rs      |   88 +
 .../examples/shootout-regex-dna-replace.rs    |   19 +
 .../shootout-regex-dna-single-cheat.rs        |   73 +
 .../examples/shootout-regex-dna-single.rs     |   55 +
 .../examples/shootout-regex-dna.rs            |   66 +
 .../examples/shootout-regex-redux-1.rs        |    0
 .../examples/shootout-regex-redux-chunked.rs  |    0
 .../examples/shootout-regex-redux.rs          |    0
 .../rust/regex-0.2.2/scripts/frequencies.py   |   82 +
 .../regex-0.2.2/scripts/regex-match-tests.py  |  107 +
 .../{regex => regex-0.2.2}/scripts/unicode.py |    0
 third_party/rust/regex-0.2.2/src/backtrack.rs |  302 +
 third_party/rust/regex-0.2.2/src/compile.rs   | 1102 +++
 third_party/rust/regex-0.2.2/src/dfa.rs       | 1879 +++++
 third_party/rust/regex-0.2.2/src/error.rs     |   63 +
 third_party/rust/regex-0.2.2/src/exec.rs      | 1275 ++++
 third_party/rust/regex-0.2.2/src/expand.rs    |  215 +
 third_party/rust/regex-0.2.2/src/freqs.rs     |  271 +
 third_party/rust/regex-0.2.2/src/input.rs     |  425 ++
 third_party/rust/regex-0.2.2/src/lib.rs       |  648 ++
 .../{regex => regex-0.2.2}/src/literals.rs    |    0
 third_party/rust/regex-0.2.2/src/pattern.rs   |   62 +
 third_party/rust/regex-0.2.2/src/pikevm.rs    |  377 +
 third_party/rust/regex-0.2.2/src/prog.rs      |  426 ++
 .../rust/regex-0.2.2/src/re_builder.rs        |  263 +
 third_party/rust/regex-0.2.2/src/re_bytes.rs  | 1031 +++
 .../{regex => regex-0.2.2}/src/re_plugin.rs   |    0
 third_party/rust/regex-0.2.2/src/re_set.rs    |  411 ++
 third_party/rust/regex-0.2.2/src/re_trait.rs  |  268 +
 .../rust/regex-0.2.2/src/re_unicode.rs        | 1237 ++++
 .../src/simd_accel/mod.rs                     |    0
 .../src/simd_accel/teddy128.rs                |    0
 .../src/simd_fallback/mod.rs                  |    0
 .../src/simd_fallback/teddy128.rs             |    0
 third_party/rust/regex-0.2.2/src/sparse.rs    |   78 +
 .../rust/regex-0.2.2/src/testdata/LICENSE     |   19 +
 .../rust/regex-0.2.2/src/testdata/README      |   17 +
 .../rust/regex-0.2.2/src/testdata/basic.dat   |  221 +
 .../regex-0.2.2/src/testdata/nullsubexpr.dat  |   79 +
 .../regex-0.2.2/src/testdata/repetition.dat   |  163 +
 third_party/rust/regex-0.2.2/src/utf8.rs      |  290 +
 third_party/rust/regex-0.2.2/tests/api.rs     |  182 +
 third_party/rust/regex-0.2.2/tests/api_str.rs |   22 +
 third_party/rust/regex-0.2.2/tests/bytes.rs   |   62 +
 third_party/rust/regex-0.2.2/tests/crazy.rs   |   78 +
 third_party/rust/regex-0.2.2/tests/flags.rs   |   11 +
 third_party/rust/regex-0.2.2/tests/fowler.rs  |  371 +
 third_party/rust/regex-0.2.2/tests/macros.rs  |  149 +
 .../rust/regex-0.2.2/tests/macros_bytes.rs    |   41 +
 .../rust/regex-0.2.2/tests/macros_str.rs      |   40 +
 third_party/rust/regex-0.2.2/tests/misc.rs    |   14 +
 .../rust/regex-0.2.2/tests/multiline.rs       |   49 +
 third_party/rust/regex-0.2.2/tests/noparse.rs |   48 +
 .../{regex => regex-0.2.2}/tests/plugin.rs    |    0
 .../rust/regex-0.2.2/tests/regression.rs      |   92 +
 third_party/rust/regex-0.2.2/tests/replace.rs |   38 +
 .../rust/regex-0.2.2/tests/searcher.rs        |   66 +
 third_party/rust/regex-0.2.2/tests/set.rs     |   32 +
 .../rust/regex-0.2.2/tests/shortest_match.rs  |   14 +
 .../rust/regex-0.2.2/tests/suffix_reverse.rs  |   16 +
 .../rust/regex-0.2.2/tests/test_backtrack.rs  |   64 +
 .../regex-0.2.2/tests/test_backtrack_bytes.rs |   65 +
 .../tests/test_backtrack_utf8bytes.rs         |   65 +
 .../rust/regex-0.2.2/tests/test_default.rs    |   77 +
 .../regex-0.2.2/tests/test_default_bytes.rs   |   73 +
 .../rust/regex-0.2.2/tests/test_nfa.rs        |   60 +
 .../rust/regex-0.2.2/tests/test_nfa_bytes.rs  |   65 +
 .../regex-0.2.2/tests/test_nfa_utf8bytes.rs   |   61 +
 .../tests/test_plugin.rs                      |    0
 third_party/rust/regex-0.2.2/tests/unicode.rs |   31 +
 .../rust/regex-0.2.2/tests/word_boundary.rs   |   89 +
 .../regex-0.2.2/tests/word_boundary_ascii.rs  |    9 +
 .../tests/word_boundary_unicode.rs            |    8 +
 .../regex-syntax-0.4.1/.cargo-checksum.json   |    1 +
 .../rust/regex-syntax-0.4.1/Cargo.toml        |   13 +
 .../rust/regex-syntax-0.4.1/src/lib.rs        | 2214 ++++++
 .../src/literals.rs                           |    0
 .../rust/regex-syntax-0.4.1/src/parser.rs     | 3311 +++++++++
 .../src/properties.rs                         |    0
 .../rust/regex-syntax-0.4.1/src/unicode.rs    | 5715 +++++++++++++++
 .../rust/regex-syntax/.cargo-checksum.json    |    2 +-
 third_party/rust/regex-syntax/Cargo.toml      |   26 +-
 third_party/rust/regex-syntax/LICENSE-APACHE  |  201 +
 third_party/rust/regex-syntax/LICENSE-MIT     |   25 +
 .../rust/regex-syntax/benches/bench.rs        |   73 +
 third_party/rust/regex-syntax/src/ast/mod.rs  | 1515 ++++
 .../rust/regex-syntax/src/ast/parse.rs        | 5365 +++++++++++++++
 .../rust/regex-syntax/src/ast/print.rs        |  586 ++
 .../rust/regex-syntax/src/ast/visitor.rs      |  557 ++
 third_party/rust/regex-syntax/src/either.rs   |    8 +
 third_party/rust/regex-syntax/src/error.rs    |  297 +
 .../rust/regex-syntax/src/hir/interval.rs     |  490 ++
 .../rust/regex-syntax/src/hir/literal/mod.rs  | 1551 +++++
 third_party/rust/regex-syntax/src/hir/mod.rs  | 2055 ++++++
 .../rust/regex-syntax/src/hir/print.rs        |  375 +
 .../rust/regex-syntax/src/hir/translate.rs    | 2532 +++++++
 .../rust/regex-syntax/src/hir/visitor.rs      |  222 +
 third_party/rust/regex-syntax/src/lib.rs      | 2280 +-----
 third_party/rust/regex-syntax/src/parser.rs   | 3487 +---------
 third_party/rust/regex-syntax/src/unicode.rs  | 6098 ++---------------
 .../regex-syntax/src/unicode_tables/age.rs    |  455 ++
 .../src/unicode_tables/case_folding_simple.rs |  725 ++
 .../src/unicode_tables/general_category.rs    | 1907 ++++++
 .../regex-syntax/src/unicode_tables/mod.rs    |    9 +
 .../src/unicode_tables/perl_word.rs           |  188 +
 .../src/unicode_tables/property_bool.rs       | 2658 +++++++
 .../src/unicode_tables/property_names.rs      |  147 +
 .../src/unicode_tables/property_values.rs     |  289 +
 .../regex-syntax/src/unicode_tables/script.rs |  801 +++
 .../src/unicode_tables/script_extension.rs    |  829 +++
 third_party/rust/regex/.cargo-checksum.json   |    2 +-
 third_party/rust/regex/.cargo_vcs_info.json   |    5 +
 third_party/rust/regex/.travis.yml            |   11 +-
 third_party/rust/regex/CHANGELOG.md           |  248 +
 third_party/rust/regex/Cargo.toml             |  129 +-
 third_party/rust/regex/HACKING.md             |  116 +-
 third_party/rust/regex/PERFORMANCE.md         |    2 +-
 third_party/rust/regex/README.md              |   74 +-
 third_party/rust/regex/UNICODE.md             |  250 +
 third_party/rust/regex/appveyor.yml           |    6 +-
 third_party/rust/regex/build.rs               |   86 +
 third_party/rust/regex/ci/after_success.sh    |    9 -
 third_party/rust/regex/ci/run-kcov            |   16 +-
 third_party/rust/regex/ci/script.sh           |   41 +-
 third_party/rust/regex/ci/test-regex-capi     |    7 +
 .../examples/shootout-regex-dna-bytes.rs      |    2 +-
 .../examples/shootout-regex-dna-single.rs     |    2 +-
 .../rust/regex/examples/shootout-regex-dna.rs |    2 +-
 third_party/rust/regex/scripts/generate.py    |   45 +
 .../rust/regex/scripts/scrape_crates_io.py    |  189 +
 third_party/rust/regex/src/backtrack.rs       |    8 +-
 third_party/rust/regex/src/compile.rs         |  351 +-
 third_party/rust/regex/src/dfa.rs             |  169 +-
 third_party/rust/regex/src/error.rs           |   33 +-
 third_party/rust/regex/src/exec.rs            |  181 +-
 third_party/rust/regex/src/expand.rs          |    6 +-
 third_party/rust/regex/src/input.rs           |   33 +-
 third_party/rust/regex/src/lib.rs             |  119 +-
 third_party/rust/regex/src/literal/mod.rs     | 1141 +++
 .../regex/src/literal/teddy_avx2/fallback.rs  |   20 +
 .../rust/regex/src/literal/teddy_avx2/imp.rs  |  468 ++
 .../rust/regex/src/literal/teddy_avx2/mod.rs  |   14 +
 .../regex/src/literal/teddy_ssse3/fallback.rs |   20 +
 .../rust/regex/src/literal/teddy_ssse3/imp.rs |  776 +++
 .../rust/regex/src/literal/teddy_ssse3/mod.rs |   14 +
 third_party/rust/regex/src/pikevm.rs          |    4 +-
 third_party/rust/regex/src/prog.rs            |   32 +-
 third_party/rust/regex/src/re_builder.rs      |  137 +-
 third_party/rust/regex/src/re_bytes.rs        |  210 +-
 third_party/rust/regex/src/re_set.rs          |   20 +
 third_party/rust/regex/src/re_trait.rs        |   34 +-
 third_party/rust/regex/src/re_unicode.rs      |  422 +-
 third_party/rust/regex/src/utf8.rs            |   47 +-
 third_party/rust/regex/src/vector/avx2.rs     |  187 +
 third_party/rust/regex/src/vector/mod.rs      |    4 +
 third_party/rust/regex/src/vector/ssse3.rs    |  192 +
 third_party/rust/regex/tests/api_str.rs       |    9 +
 third_party/rust/regex/tests/bytes.rs         |   12 +-
 third_party/rust/regex/tests/consistent.rs    |  213 +
 third_party/rust/regex/tests/crates_regex.rs  | 3129 +++++++++
 third_party/rust/regex/tests/crazy.rs         |  323 +
 third_party/rust/regex/tests/macros.rs        |    2 +-
 third_party/rust/regex/tests/macros_bytes.rs  |    4 +-
 third_party/rust/regex/tests/macros_str.rs    |    6 +-
 third_party/rust/regex/tests/noparse.rs       |   12 +-
 third_party/rust/regex/tests/regression.rs    |   12 +-
 third_party/rust/regex/tests/replace.rs       |   12 +
 .../rust/regex/tests/test_crates_regex.rs     |   57 +
 third_party/rust/regex/tests/test_default.rs  |   10 +
 .../rust/regex/tests/test_default_bytes.rs    |    2 +-
 third_party/rust/regex/tests/unicode.rs       |   79 +
 .../rust/regex/tests/word_boundary_unicode.rs |    2 -
 .../rust/smallvec/.cargo-checksum.json        |    2 +-
 third_party/rust/smallvec/.travis.yml         |    8 +-
 third_party/rust/smallvec/Cargo.toml          |   10 +-
 third_party/rust/smallvec/LICENSE             |  374 -
 third_party/rust/smallvec/LICENSE-APACHE      |  201 +
 third_party/rust/smallvec/LICENSE-MIT         |   25 +
 third_party/rust/smallvec/benches/bench.rs    |  276 +-
 third_party/rust/smallvec/lib.rs              |  799 ++-
 .../rust/thread_local/.cargo-checksum.json    |    2 +-
 third_party/rust/thread_local/.travis.yml     |    2 +-
 third_party/rust/thread_local/Cargo.toml      |    9 +-
 third_party/rust/thread_local/src/lib.rs      |    4 +-
 .../rust/thread_local/src/unreachable.rs      |   74 +
 .../rust/ucd-util/.cargo-checksum.json        |    1 +
 third_party/rust/ucd-util/Cargo.toml          |   23 +
 third_party/rust/ucd-util/LICENSE-APACHE      |  201 +
 third_party/rust/ucd-util/LICENSE-MIT         |   21 +
 third_party/rust/ucd-util/README.md           |   23 +
 third_party/rust/ucd-util/src/hangul.rs       |  105 +
 third_party/rust/ucd-util/src/ideograph.rs    |   83 +
 third_party/rust/ucd-util/src/lib.rs          |   28 +
 third_party/rust/ucd-util/src/name.rs         |  180 +
 third_party/rust/ucd-util/src/property.rs     |  124 +
 .../src/unicode_tables/jamo_short_name.rs     |   22 +
 .../rust/ucd-util/src/unicode_tables/mod.rs   |    5 +
 .../src/unicode_tables/property_names.rs      |  146 +
 .../src/unicode_tables/property_values.rs     |  992 +++
 .../rust/utf8-ranges/.cargo-checksum.json     |    2 +-
 third_party/rust/utf8-ranges/.travis.yml      |    8 +-
 third_party/rust/utf8-ranges/Cargo.toml       |   26 +-
 third_party/rust/utf8-ranges/ci/script.sh     |   17 +
 450 files changed, 87492 insertions(+), 15546 deletions(-)
 create mode 100755 third_party/rust/aho-corasick/ci/script.sh
 create mode 100644 third_party/rust/bindgen/LICENSE
 create mode 100644 third_party/rust/bindgen/README.md
 delete mode 100644 third_party/rust/clang-sys/CONTRIBUTING.md
 create mode 100644 third_party/rust/libc/ci/linux-s390x.sh
 create mode 100644 third_party/rust/libc/ci/linux-sparc64.sh
 create mode 100755 third_party/rust/libc/ci/test-runner-linux
 create mode 100644 third_party/rust/libc/src/cloudabi/aarch64.rs
 create mode 100644 third_party/rust/libc/src/cloudabi/arm.rs
 create mode 100644 third_party/rust/libc/src/cloudabi/mod.rs
 create mode 100644 third_party/rust/libc/src/cloudabi/x86.rs
 create mode 100644 third_party/rust/libc/src/cloudabi/x86_64.rs
 create mode 100644 third_party/rust/libc/src/fuchsia/aarch64.rs
 create mode 100644 third_party/rust/libc/src/fuchsia/mod.rs
 create mode 100644 third_party/rust/libc/src/fuchsia/powerpc64.rs
 create mode 100644 third_party/rust/libc/src/fuchsia/x86_64.rs
 rename third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/{bitrig.rs => bitrig/mod.rs} (63%)
 rename third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/{other/b32/mod.rs => bitrig/x86.rs} (100%)
 rename third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/{other/b64/mod.rs => bitrig/x86_64.rs} (100%)
 delete mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs
 create mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/aarch64.rs
 create mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
 create mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86.rs
 create mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86_64.rs
 delete mode 100644 third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs
 create mode 100644 third_party/rust/libc/src/unix/hermit/aarch64.rs
 create mode 100644 third_party/rust/libc/src/unix/hermit/mod.rs
 create mode 100644 third_party/rust/libc/src/unix/hermit/x86_64.rs
 create mode 100644 third_party/rust/libc/src/unix/newlib/aarch64/mod.rs
 create mode 100644 third_party/rust/libc/src/unix/notbsd/linux/musl/b32/powerpc.rs
 create mode 100644 third_party/rust/libc/src/unix/uclibc/x86_64/other.rs
 create mode 100644 third_party/rust/libloading/src/os/unix/global_static.c
 delete mode 100644 third_party/rust/libloading/tests/statics.rs
 create mode 100644 third_party/rust/memchr-1.0.2/.cargo-checksum.json
 create mode 100644 third_party/rust/memchr-1.0.2/.travis.yml
 create mode 100644 third_party/rust/memchr-1.0.2/COPYING
 create mode 100644 third_party/rust/memchr-1.0.2/Cargo.toml
 create mode 100644 third_party/rust/memchr-1.0.2/LICENSE-MIT
 create mode 100644 third_party/rust/memchr-1.0.2/Makefile
 create mode 100644 third_party/rust/memchr-1.0.2/README.md
 create mode 100644 third_party/rust/memchr-1.0.2/UNLICENSE
 create mode 100644 third_party/rust/memchr-1.0.2/appveyor.yml
 create mode 100644 third_party/rust/memchr-1.0.2/benches/bench.rs
 create mode 100644 third_party/rust/memchr-1.0.2/ctags.rust
 create mode 100644 third_party/rust/memchr-1.0.2/session.vim
 create mode 100644 third_party/rust/memchr-1.0.2/src/lib.rs
 create mode 100755 third_party/rust/memchr/ci/script.sh
 create mode 100644 third_party/rust/proc-macro2-0.2.2/.cargo-checksum.json
 create mode 100644 third_party/rust/proc-macro2-0.2.2/.travis.yml
 create mode 100644 third_party/rust/proc-macro2-0.2.2/Cargo.toml
 create mode 100644 third_party/rust/proc-macro2-0.2.2/LICENSE-APACHE
 create mode 100644 third_party/rust/proc-macro2-0.2.2/LICENSE-MIT
 create mode 100644 third_party/rust/proc-macro2-0.2.2/README.md
 create mode 100644 third_party/rust/proc-macro2-0.2.2/src/lib.rs
 rename third_party/rust/{proc-macro2 => proc-macro2-0.2.2}/src/macros.rs (100%)
 create mode 100644 third_party/rust/proc-macro2-0.2.2/src/stable.rs
 create mode 100644 third_party/rust/proc-macro2-0.2.2/src/strnom.rs
 create mode 100644 third_party/rust/proc-macro2-0.2.2/src/unstable.rs
 create mode 100644 third_party/rust/proc-macro2-0.2.2/tests/test.rs
 create mode 100644 third_party/rust/quote-0.4.2/.cargo-checksum.json
 create mode 100644 third_party/rust/quote-0.4.2/Cargo.toml
 create mode 100644 third_party/rust/quote-0.4.2/LICENSE-APACHE
 create mode 100644 third_party/rust/quote-0.4.2/LICENSE-MIT
 create mode 100644 third_party/rust/quote-0.4.2/README.md
 create mode 100644 third_party/rust/quote-0.4.2/src/lib.rs
 create mode 100644 third_party/rust/quote-0.4.2/src/to_tokens.rs
 create mode 100644 third_party/rust/quote-0.4.2/src/tokens.rs
 create mode 100644 third_party/rust/quote-0.4.2/tests/test.rs
 create mode 100644 third_party/rust/regex-0.2.2/.cargo-checksum.json
 create mode 100644 third_party/rust/regex-0.2.2/.travis.yml
 create mode 100644 third_party/rust/regex-0.2.2/CHANGELOG.md
 create mode 100644 third_party/rust/regex-0.2.2/Cargo.toml
 create mode 100644 third_party/rust/regex-0.2.2/HACKING.md
 create mode 100644 third_party/rust/regex-0.2.2/LICENSE-APACHE
 create mode 100644 third_party/rust/regex-0.2.2/LICENSE-MIT
 create mode 100644 third_party/rust/regex-0.2.2/PERFORMANCE.md
 create mode 100644 third_party/rust/regex-0.2.2/README.md
 create mode 100644 third_party/rust/regex-0.2.2/appveyor.yml
 create mode 100755 third_party/rust/regex-0.2.2/ci/after_success.sh
 create mode 100755 third_party/rust/regex-0.2.2/ci/run-kcov
 create mode 100755 third_party/rust/regex-0.2.2/ci/run-shootout-test
 create mode 100755 third_party/rust/regex-0.2.2/ci/script.sh
 rename third_party/rust/{regex => regex-0.2.2}/examples/bug347.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/examples/regexdna-input.txt
 create mode 100644 third_party/rust/regex-0.2.2/examples/regexdna-output.txt
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna-bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna-cheat.rs
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna-replace.rs
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single-cheat.rs
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single.rs
 create mode 100644 third_party/rust/regex-0.2.2/examples/shootout-regex-dna.rs
 rename third_party/rust/{regex => regex-0.2.2}/examples/shootout-regex-redux-1.rs (100%)
 rename third_party/rust/{regex => regex-0.2.2}/examples/shootout-regex-redux-chunked.rs (100%)
 rename third_party/rust/{regex => regex-0.2.2}/examples/shootout-regex-redux.rs (100%)
 create mode 100755 third_party/rust/regex-0.2.2/scripts/frequencies.py
 create mode 100755 third_party/rust/regex-0.2.2/scripts/regex-match-tests.py
 rename third_party/rust/{regex => regex-0.2.2}/scripts/unicode.py (100%)
 create mode 100644 third_party/rust/regex-0.2.2/src/backtrack.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/compile.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/dfa.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/error.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/exec.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/expand.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/freqs.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/input.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/lib.rs
 rename third_party/rust/{regex => regex-0.2.2}/src/literals.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/src/pattern.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/pikevm.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/prog.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/re_builder.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/re_bytes.rs
 rename third_party/rust/{regex => regex-0.2.2}/src/re_plugin.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/src/re_set.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/re_trait.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/re_unicode.rs
 rename third_party/rust/{regex => regex-0.2.2}/src/simd_accel/mod.rs (100%)
 rename third_party/rust/{regex => regex-0.2.2}/src/simd_accel/teddy128.rs (100%)
 rename third_party/rust/{regex => regex-0.2.2}/src/simd_fallback/mod.rs (100%)
 rename third_party/rust/{regex => regex-0.2.2}/src/simd_fallback/teddy128.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/src/sparse.rs
 create mode 100644 third_party/rust/regex-0.2.2/src/testdata/LICENSE
 create mode 100644 third_party/rust/regex-0.2.2/src/testdata/README
 create mode 100644 third_party/rust/regex-0.2.2/src/testdata/basic.dat
 create mode 100644 third_party/rust/regex-0.2.2/src/testdata/nullsubexpr.dat
 create mode 100644 third_party/rust/regex-0.2.2/src/testdata/repetition.dat
 create mode 100644 third_party/rust/regex-0.2.2/src/utf8.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/api.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/api_str.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/crazy.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/flags.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/fowler.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/macros.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/macros_bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/macros_str.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/misc.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/multiline.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/noparse.rs
 rename third_party/rust/{regex => regex-0.2.2}/tests/plugin.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/tests/regression.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/replace.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/searcher.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/set.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/shortest_match.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/suffix_reverse.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_backtrack.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_backtrack_bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_backtrack_utf8bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_default.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_default_bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_nfa.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_nfa_bytes.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/test_nfa_utf8bytes.rs
 rename third_party/rust/{regex => regex-0.2.2}/tests/test_plugin.rs (100%)
 create mode 100644 third_party/rust/regex-0.2.2/tests/unicode.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/word_boundary.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/word_boundary_ascii.rs
 create mode 100644 third_party/rust/regex-0.2.2/tests/word_boundary_unicode.rs
 create mode 100644 third_party/rust/regex-syntax-0.4.1/.cargo-checksum.json
 create mode 100644 third_party/rust/regex-syntax-0.4.1/Cargo.toml
 create mode 100644 third_party/rust/regex-syntax-0.4.1/src/lib.rs
 rename third_party/rust/{regex-syntax => regex-syntax-0.4.1}/src/literals.rs (100%)
 create mode 100644 third_party/rust/regex-syntax-0.4.1/src/parser.rs
 rename third_party/rust/{regex-syntax => regex-syntax-0.4.1}/src/properties.rs (100%)
 create mode 100644 third_party/rust/regex-syntax-0.4.1/src/unicode.rs
 create mode 100644 third_party/rust/regex-syntax/LICENSE-APACHE
 create mode 100644 third_party/rust/regex-syntax/LICENSE-MIT
 create mode 100644 third_party/rust/regex-syntax/benches/bench.rs
 create mode 100644 third_party/rust/regex-syntax/src/ast/mod.rs
 create mode 100644 third_party/rust/regex-syntax/src/ast/parse.rs
 create mode 100644 third_party/rust/regex-syntax/src/ast/print.rs
 create mode 100644 third_party/rust/regex-syntax/src/ast/visitor.rs
 create mode 100644 third_party/rust/regex-syntax/src/either.rs
 create mode 100644 third_party/rust/regex-syntax/src/error.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/interval.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/literal/mod.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/mod.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/print.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/translate.rs
 create mode 100644 third_party/rust/regex-syntax/src/hir/visitor.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/age.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/case_folding_simple.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/general_category.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/mod.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/perl_word.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/property_bool.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/property_names.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/property_values.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/script.rs
 create mode 100644 third_party/rust/regex-syntax/src/unicode_tables/script_extension.rs
 create mode 100644 third_party/rust/regex/.cargo_vcs_info.json
 create mode 100644 third_party/rust/regex/UNICODE.md
 create mode 100644 third_party/rust/regex/build.rs
 create mode 100755 third_party/rust/regex/ci/test-regex-capi
 create mode 100755 third_party/rust/regex/scripts/generate.py
 create mode 100755 third_party/rust/regex/scripts/scrape_crates_io.py
 create mode 100644 third_party/rust/regex/src/literal/mod.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_avx2/fallback.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_avx2/imp.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_avx2/mod.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_ssse3/fallback.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_ssse3/imp.rs
 create mode 100644 third_party/rust/regex/src/literal/teddy_ssse3/mod.rs
 create mode 100644 third_party/rust/regex/src/vector/avx2.rs
 create mode 100644 third_party/rust/regex/src/vector/mod.rs
 create mode 100644 third_party/rust/regex/src/vector/ssse3.rs
 create mode 100644 third_party/rust/regex/tests/consistent.rs
 create mode 100644 third_party/rust/regex/tests/crates_regex.rs
 create mode 100644 third_party/rust/regex/tests/test_crates_regex.rs
 delete mode 100644 third_party/rust/smallvec/LICENSE
 create mode 100644 third_party/rust/smallvec/LICENSE-APACHE
 create mode 100644 third_party/rust/smallvec/LICENSE-MIT
 create mode 100644 third_party/rust/thread_local/src/unreachable.rs
 create mode 100644 third_party/rust/ucd-util/.cargo-checksum.json
 create mode 100644 third_party/rust/ucd-util/Cargo.toml
 create mode 100644 third_party/rust/ucd-util/LICENSE-APACHE
 create mode 100644 third_party/rust/ucd-util/LICENSE-MIT
 create mode 100644 third_party/rust/ucd-util/README.md
 create mode 100644 third_party/rust/ucd-util/src/hangul.rs
 create mode 100644 third_party/rust/ucd-util/src/ideograph.rs
 create mode 100644 third_party/rust/ucd-util/src/lib.rs
 create mode 100644 third_party/rust/ucd-util/src/name.rs
 create mode 100644 third_party/rust/ucd-util/src/property.rs
 create mode 100644 third_party/rust/ucd-util/src/unicode_tables/jamo_short_name.rs
 create mode 100644 third_party/rust/ucd-util/src/unicode_tables/mod.rs
 create mode 100644 third_party/rust/ucd-util/src/unicode_tables/property_names.rs
 create mode 100644 third_party/rust/ucd-util/src/unicode_tables/property_values.rs
 create mode 100755 third_party/rust/utf8-ranges/ci/script.sh

diff --git a/Cargo.lock b/Cargo.lock
index 4bfba0eb2f52..e25b35203639 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,19 +1,19 @@
 [[package]]
 name = "adler32"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "aho-corasick"
-version = "0.6.3"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "ansi_term"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -39,31 +39,31 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "atty"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "audioipc"
 version = "0.2.1"
 dependencies = [
  "bincode 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -73,33 +73,33 @@ dependencies = [
 name = "audioipc-client"
 version = "0.3.0"
 dependencies = [
  "audioipc 0.2.1",
  "cubeb-backend 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "audioipc-server"
 version = "0.2.2"
 dependencies = [
  "audioipc 0.2.1",
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
@@ -121,27 +121,28 @@ version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bindgen"
-version = "0.33.1"
+version = "0.37.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bitflags"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -180,26 +181,26 @@ dependencies = [
 ]
 
 [[package]]
 name = "bzip2"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bzip2-sys"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cc"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -221,22 +222,22 @@ version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "clang-sys"
-version = "0.21.1"
+version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "clap"
 version = "2.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -266,47 +267,47 @@ dependencies = [
 ]
 
 [[package]]
 name = "core-foundation"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-foundation-sys"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-graphics"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
 version = "9.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cose"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -366,17 +367,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -502,17 +503,17 @@ dependencies = [
 [[package]]
 name = "dwrote"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "either"
 version = "1.1.0"
@@ -566,25 +567,25 @@ dependencies = [
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fallible"
 version = "0.0.1"
 dependencies = [
  "hashglobe 0.1.0",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "flate2"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fnv"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -593,26 +594,26 @@ name = "foreign-types"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "freetype"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fs2"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fuchsia-zircon"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -685,24 +686,24 @@ dependencies = [
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "nsstring 0.1.0",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "gkrust"
 version = "0.1.0"
 dependencies = [
@@ -768,17 +769,17 @@ dependencies = [
 name = "glob"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "hashglobe"
 version = "0.1.0"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "httparse"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -814,17 +815,17 @@ dependencies = [
  "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "iovec"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itertools"
 version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -835,22 +836,22 @@ dependencies = [
 name = "itoa"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "js"
 version = "0.1.4"
 dependencies = [
- "bindgen 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozjs_sys 0.0.0",
  "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "kernel32-sys"
 version = "0.2.2"
@@ -882,53 +883,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lazycell"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.33"
+version = "0.2.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libloading"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libudev"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev-sys 0.1.3",
 ]
 
 [[package]]
 name = "libudev-sys"
 version = "0.1.3"
 dependencies = [
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libz-sys"
 version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "log"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -950,17 +950,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of_derive"
 version = "0.0.1"
 dependencies = [
  "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -973,27 +973,35 @@ name = "matches"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "memchr"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "memmap"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "memoffset"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -1006,52 +1014,52 @@ dependencies = [
 ]
 
 [[package]]
 name = "miniz_oxide"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "miniz_oxide_c_api"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mio"
 version = "0.6.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mio-uds"
 version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "miow"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1065,17 +1073,17 @@ dependencies = [
 name = "moz_cbor"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mozjs_sys"
 version = "0.0.0"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mozprofile"
 version = "0.3.0"
 dependencies = [
@@ -1142,17 +1150,17 @@ dependencies = [
 
 [[package]]
 name = "net2"
 version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "netwerk_helper"
 version = "0.0.1"
 dependencies = [
@@ -1228,17 +1236,17 @@ name = "num-traits"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num_cpus"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "ordered-float"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1264,19 +1272,19 @@ dependencies = [
 ]
 
 [[package]]
 name = "parking_lot_core"
 version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -1352,16 +1360,24 @@ version = "0.0.1"
 [[package]]
 name = "proc-macro2"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "proc-macro2"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "procedural-masquerade"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "pulse"
 version = "0.2.0"
@@ -1369,39 +1385,47 @@ dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulse-ffi 0.1.0",
 ]
 
 [[package]]
 name = "pulse-ffi"
 version = "0.1.0"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "quote"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1410,43 +1434,63 @@ dependencies = [
 
 [[package]]
 name = "rayon-core"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "regex"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "regex-syntax"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "regex-syntax"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ron"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1462,17 +1506,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rust_url_capi"
 version = "0.0.1"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-serialize"
 version = "0.3.24"
@@ -1510,17 +1554,17 @@ dependencies = [
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1587,18 +1631,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallbitvec"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallvec"
-version = "0.6.0"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "stable_deref_trait"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "strsim"
@@ -1607,17 +1654,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "style"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bindgen 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1638,17 +1685,17 @@ dependencies = [
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_derive 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1684,23 +1731,23 @@ name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "size_of_test 0.0.1",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
 [[package]]
 name = "syn"
 version = "0.11.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1748,17 +1795,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "term_size"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "textwrap"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1767,40 +1814,39 @@ dependencies = [
 ]
 
 [[package]]
 name = "thread-id"
 version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "thread_local"
-version = "0.3.4"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "thread_profiler"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "time"
 version = "0.1.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tokio-core"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1828,17 +1874,17 @@ dependencies = [
 [[package]]
 name = "tokio-uds"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1858,24 +1904,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "u2fhid"
 version = "0.1.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ucd-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "uluru"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1943,17 +1994,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "utf8-ranges"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "uuid"
 version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2022,17 +2073,17 @@ dependencies = [
  "gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
  "plane-split 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.57.0",
 ]
 
 [[package]]
 name = "webrender_api"
 version = "0.57.0"
@@ -2067,17 +2118,17 @@ dependencies = [
  "webrender 0.57.0",
 ]
 
 [[package]]
 name = "which"
 version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2128,17 +2179,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "xpcom"
 version = "0.1.0"
 dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "xpcom_macros 0.1.0",
 ]
 
 [[package]]
 name = "xpcom-gtest"
 version = "0.1.0"
@@ -2166,40 +2217,40 @@ dependencies = [
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [metadata]
 "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
-"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
+"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a"
 "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
 "checksum app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29069a9b483f7780aebb55dafb360c6225eefdc1f98c8d336a65148fd10c37b1"
 "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3fb369af639822830328794eba2501b3479652fcd021b2aeb1ed4984202afd"
-"checksum bindgen 0.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1657d607dd7a8e10b3181149f60f3b27ea0eac81058c09a1c791b8f6ead91f19"
+"checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
 "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
 "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
 "checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
-"checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"
+"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
 "checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
 "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
 "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
 "checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
 "checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
@@ -2252,24 +2303,25 @@ dependencies = [
 "checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum khronos_api 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d867c645cfeb8a7fec503731679eac03ac11b7105aa5a71cb8f8ee5271636add"
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
 "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
 "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
-"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
-"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"
+"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
+"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
 "checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
 "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
+"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"
 "checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
 "checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398"
 "checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5"
 "checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
 "checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
@@ -2295,25 +2347,29 @@ dependencies = [
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plane-split 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69c557e11e3a1533bc969fa596e5011e1d9f76dd61cd102ef942c9f8654b17a2"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1cb7aaaa4bf022ec2b14ff2f2ba1643a22f3cee88df014a85e14b392282c61d"
+"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
+"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
 "checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
 "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
 "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
+"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
+"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
 "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
 "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
 "checksum rust-ini 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22dab655e8122ccb15db25a56852ce62506f1486cdefd37e86371bf34ea8f601"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918"
@@ -2321,48 +2377,49 @@ dependencies = [
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
 "checksum serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)" = "<none>"
 "checksum serde_derive_internals 0.19.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)" = "<none>"
 "checksum simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd0805c7363ab51a829a1511ad24b6ed0349feaa756c4bc2f977f9f496e6673"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "79b776f00dfe01df905fa3b2eaa1659522e99e3fc4a7b1334171622205c4bdcf"
-"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
+"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1c669ed757c0ebd04337f6a5bb972d05e0c08fe2540dd3ee3dd9e4daf1604c"
 "checksum synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27e31aa4b09b9f4cb12dff3c30ba503e17b1a624413d764d32dab76e3920e5bc"
 "checksum synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "010366096045d8250555904c58da03377289e7f4b2ce7a5b1027e2b532f41000"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
-"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf947d192a9be60ef5131cc7a4648886ba89d712f16700ebbf80c8a69d05d48f"
 "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
 "checksum tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "febd81b3e2ef615c6c8077347b33f3f3deec3d708ecd08194c9707b7a1eccfc9"
 "checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af"
 "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
 "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
+"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9"
 "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
 "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2"
-"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
+"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
 "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
 "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
diff --git a/js/rust/Cargo.toml b/js/rust/Cargo.toml
index e0b4fe02da7c..fe6144670d93 100644
--- a/js/rust/Cargo.toml
+++ b/js/rust/Cargo.toml
@@ -3,17 +3,17 @@ name = "js"
 version = "0.1.4"
 authors = ["The Servo Project Developers"]
 build = "build.rs"
 license = "MPL-2.0"
 
 [build-dependencies]
 env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
 log = "0.3"
-bindgen = {version = "0.33.1", default-features = false} # disable `logging` to reduce code size
+bindgen = {version = "0.37", default-features = false} # disable `logging` to reduce code size
 cmake = "0.1"
 glob = "0.2.11"
 
 [[test]]
 name = "callback"
 [[test]]
 name = "enumerate"
 [[test]]
diff --git a/servo/components/style/Cargo.toml b/servo/components/style/Cargo.toml
index 88b64ca81445..6de2b912db16 100644
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -73,12 +73,12 @@ unicode-segmentation = "1.0"
 void = "1.0.2"
 
 [target.'cfg(windows)'.dependencies]
 kernel32-sys = "0.2"
 
 [build-dependencies]
 lazy_static = "1"
 log = "0.3"
-bindgen = { version = "0.33.1", optional = true, default-features = false }
+bindgen = { version = "0.37", optional = true, default-features = false }
 regex = {version = "0.2", optional = true}
 walkdir = "1.0"
 toml = {version = "0.2.1", optional = true, default-features = false}
diff --git a/third_party/rust/aho-corasick/.cargo-checksum.json b/third_party/rust/aho-corasick/.cargo-checksum.json
index 53199d265be1..b96ddb1bc6e7 100644
--- a/third_party/rust/aho-corasick/.cargo-checksum.json
+++ b/third_party/rust/aho-corasick/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"e17babe5ba0bdd19ec59a37b4a099fd4313bff58be63a2ff506075f9a97dc172","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"b3fa06c2147a4749cd984ded69024ddcc8b7d578ab763b60227b3ba474c3ec70","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"9bc60d2cec222b50f87c85cf9475349bb228a36f89796c5d6481c52560ddde3a","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"acf4844efadeafc7bc396c2b16f2a184e140b6c17d1084dbaf454196de2090cd","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","examples/dict-search.rs":"30eb44b1a0b599507db4c23a90f74199faabc64a8ae1d603ecdf3bba7428eb1e","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/autiter.rs":"98c31a7fbe21cfacaa858f90409f0d86edd46dda1b7651f4e800d929a50afb7b","src/full.rs":"b83a9c8ff3ef611c316b68650915df2d7f361a49b59dab103dc2c5476f2d8303","src/lib.rs":"68bf2ed02d58bebee6f7f7579038f1e4b60a2c4acc334263cb837bcbe15ffe94","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"}
\ No newline at end of file
+{"files":{".travis.yml":"5749b97291a6f4e6cc0b308d2d410e1ae20530f0976575581270d3d4eb60ed19","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"64af7d0a0a299d3a05f52baed2ea87cc0d783c4fdeaa555a595aed92e5d780a6","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"9fb3256ce6fc5b25c9a92fe3b8f7a82a26d380fcf6121c934c2bb6f85102fede","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"c74b297ed2217e4784614573a8b44c61dfe5173985c43616e43a3f608973ff2e","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","ci/script.sh":"061b81cf1dba37d34063500117f5aa164919445472086665549ef2aa6a43bf77","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","examples/dict-search.rs":"0dac88736039262dfb8df9ff85ece18de90dd4da9b8b895cf4d57bf33167b224","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/autiter.rs":"b3bd067bf6c25708109870afbb5d09e9a04d0f2f596f59c368e42ddbc7c65f93","src/full.rs":"acb6389d210e7bc4125f0ebb6f268b712e60ec50b58b9c4094a8083bb8f4caf2","src/lib.rs":"fdddbb688fbc71461242b94e1cfb3dfbf0a9f06b2c70a6e83de15a0e54804a28","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a"}
\ No newline at end of file
diff --git a/third_party/rust/aho-corasick/.travis.yml b/third_party/rust/aho-corasick/.travis.yml
index 897b3890a43a..b1df4f10c1bf 100644
--- a/third_party/rust/aho-corasick/.travis.yml
+++ b/third_party/rust/aho-corasick/.travis.yml
@@ -1,13 +1,10 @@
 language: rust
 rust:
-  - 1.12.0
+  - 1.13.0
   - stable
   - beta
   - nightly
-script:
-  - cargo build --verbose
-  - cargo test --verbose
-  - cargo doc
-  - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
-      cargo bench --verbose;
-    fi
+script: ci/script.sh
+branches:
+  only:
+    - master
diff --git a/third_party/rust/aho-corasick/Cargo.toml b/third_party/rust/aho-corasick/Cargo.toml
index f33ed53cd712..db3bb5c5ec91 100644
--- a/third_party/rust/aho-corasick/Cargo.toml
+++ b/third_party/rust/aho-corasick/Cargo.toml
@@ -1,47 +1,72 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
 name = "aho-corasick"
-version = "0.6.3"  #:version
+version = "0.6.8"
 authors = ["Andrew Gallant <jamslam@gmail.com>"]
+exclude = ["benches/sherlock.txt"]
 description = "Fast multiple substring searching with finite state machines."
-documentation = "http://burntsushi.net/rustdoc/aho_corasick/"
 homepage = "https://github.com/BurntSushi/aho-corasick"
-repository = "https://github.com/BurntSushi/aho-corasick"
 readme = "README.md"
 keywords = ["string", "search", "text", "aho", "corasick"]
 license = "Unlicense/MIT"
-exclude = ["benches/sherlock.txt"]
+repository = "https://github.com/BurntSushi/aho-corasick"
+[profile.test]
+debug = true
+
+[profile.bench]
+debug = true
+
+[profile.release]
+debug = true
 
 [lib]
 name = "aho_corasick"
 
 [[bin]]
 name = "aho-corasick-dot"
+path = "src/main.rs"
 test = false
-doc = false
 bench = false
-
-[dependencies]
-memchr = "1"
-
-[dev-dependencies]
-csv = "0.15"
-docopt = "0.7"
-memmap = "0.5"
-quickcheck = { version = "0.4", default-features = false }
-rand = "0.3"
-rustc-serialize = "0.3"
+doc = false
 
 [[bench]]
 name = "bench"
 path = "benches/bench.rs"
 test = false
 bench = true
+[dependencies.memchr]
+version = "2"
+[dev-dependencies.csv]
+version = "1"
 
-[profile.test]
-debug = true
+[dev-dependencies.docopt]
+version = "1"
 
-[profile.bench]
-debug = true
+[dev-dependencies.memmap]
+version = "0.6"
 
-[profile.release]
-debug = true
+[dev-dependencies.quickcheck]
+version = "0.7"
+default-features = false
+
+[dev-dependencies.rand]
+version = "0.5"
+
+[dev-dependencies.serde]
+version = "1"
+
+[dev-dependencies.serde_derive]
+version = "1"
+[badges.travis-ci]
+repository = "BurntSushi/aho-corasick"
diff --git a/third_party/rust/aho-corasick/README.md b/third_party/rust/aho-corasick/README.md
index 604cd3d683f3..25e9ef91736f 100644
--- a/third_party/rust/aho-corasick/README.md
+++ b/third_party/rust/aho-corasick/README.md
@@ -12,17 +12,17 @@ the length of the search text and `m` is the number of matches.
 [![Build status](https://api.travis-ci.org/BurntSushi/aho-corasick.png)](https://travis-ci.org/BurntSushi/aho-corasick)
 [![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick)
 
 Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
 
 
 ### Documentation
 
-[http://burntsushi.net/rustdoc/aho_corasick/](http://burntsushi.net/rustdoc/aho_corasick/).
+[https://docs.rs/aho-corasick/](https://docs.rs/aho-corasick/).
 
 
 ### Example
 
 The documentation contains several examples, and there is a more complete
 example as a full program in `examples/dict-search.rs`.
 
 Here is a quick example showing simple substring matching:
diff --git a/third_party/rust/aho-corasick/benches/bench.rs b/third_party/rust/aho-corasick/benches/bench.rs
index d51bcaeec975..0e68e2af02d8 100644
--- a/third_party/rust/aho-corasick/benches/bench.rs
+++ b/third_party/rust/aho-corasick/benches/bench.rs
@@ -52,16 +52,50 @@ fn bench_full_aut_overlapping_no_match<P: AsRef<[u8]>, T: Transitions>(
 
 fn bench_naive_no_match<S>(b: &mut Bencher, needles: Vec<S>, haystack: &str)
         where S: Into<String> {
     b.bytes = haystack.len() as u64;
     let needles: Vec<String> = needles.into_iter().map(Into::into).collect();
     b.iter(|| assert!(!naive_find(&needles, haystack)));
 }
 
+#[bench]
+fn bench_construction(b: &mut Bencher) {
+    b.iter(|| {
+        AcAutomaton::new(test::black_box(
+            [
+                "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL",
+                "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE",
+                "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK",
+                "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe",
+                "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt",
+                "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
+            ].iter()
+                .map(|x| *x),
+        ))
+    })
+}
+
+#[bench]
+fn bench_full_construction(b: &mut Bencher) {
+    b.iter(|| {
+        AcAutomaton::new(test::black_box(
+            [
+                "ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BAK", "BaK", "Bak", "BaK", "HOL",
+                "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh", "JoH", "Joh", "SHE",
+                "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat", "aDL", "aDl", "adL", "adl", "bAK",
+                "bAk", "bAK", "baK", "bak", "baK", "hOL", "hOl", "hoL", "hol", "iRE", "iRe",
+                "irE", "ire", "jOH", "jOh", "joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt",
+                "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
+            ].iter()
+                .map(|x| *x),
+        )).into_full()
+    })
+}
+
 fn haystack_same(letter: char) -> String {
     iter::repeat(letter).take(10000).collect()
 }
 
 macro_rules! aut_benches {
     ($prefix:ident, $aut:expr, $bench:expr) => {
         mod $prefix {
 #![allow(unused_imports)]
diff --git a/third_party/rust/aho-corasick/ci/script.sh b/third_party/rust/aho-corasick/ci/script.sh
new file mode 100755
index 000000000000..effebc4d8f88
--- /dev/null
+++ b/third_party/rust/aho-corasick/ci/script.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -ex
+
+cargo build --verbose
+cargo doc --verbose
+
+# If we're testing on an older version of Rust, then only check that we
+# can build the crate. This is because the dev dependencies might be updated
+# more frequently, and therefore might require a newer version of Rust.
+#
+# This isn't ideal. It's a compromise.
+if [ "$TRAVIS_RUST_VERSION" = "1.13.0" ]; then
+  exit
+fi
+
+cargo test --verbose
+if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  cargo bench --verbose --no-run
+fi
diff --git a/third_party/rust/aho-corasick/examples/dict-search.rs b/third_party/rust/aho-corasick/examples/dict-search.rs
index e4cb28854b22..b620cc284a7d 100644
--- a/third_party/rust/aho-corasick/examples/dict-search.rs
+++ b/third_party/rust/aho-corasick/examples/dict-search.rs
@@ -1,25 +1,27 @@
 // This example demonstrates how to use the Aho-Corasick algorithm to rapidly
 // scan text for matches in a large dictionary of keywords. This example by
 // default reads your system's dictionary (~120,000 words).
 extern crate aho_corasick;
 extern crate csv;
 extern crate docopt;
 extern crate memmap;
-extern crate rustc_serialize;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
 
 use std::error::Error;
 use std::fs::File;
 use std::io::{self, BufRead, Write};
 use std::process;
 
 use aho_corasick::{Automaton, AcAutomaton, Match};
 use docopt::Docopt;
-use memmap::{Mmap, Protection};
+use memmap::Mmap;
 
 static USAGE: &'static str = "
 Usage: dict-search [options] <input>
        dict-search --help
 
 Options:
     -d <path>, --dict <path>   Path to dictionary of keywords to search.
                                [default: /usr/share/dict/words]
@@ -28,30 +30,30 @@ Options:
     --overlapping              Report overlapping matches.
     -c, --count                Show only the numebr of matches.
     --memory-usage             Show memory usage of automaton.
     --full                     Use fully expanded transition matrix.
                                Warning: may use lots of memory.
     -h, --help                 Show this usage message.
 ";
 
-#[derive(Clone, Debug, RustcDecodable)]
+#[derive(Clone, Debug, Deserialize)]
 struct Args {
     arg_input: String,
     flag_dict: String,
     flag_min_len: usize,
     flag_overlapping: bool,
     flag_memory_usage: bool,
     flag_full: bool,
     flag_count: bool,
 }
 
 fn main() {
     let args: Args = Docopt::new(USAGE)
-                            .and_then(|d| d.decode())
+                            .and_then(|d| d.deserialize())
                             .unwrap_or_else(|e| e.exit());
     match run(&args) {
         Ok(()) => {}
         Err(err) => {
             writeln!(&mut io::stderr(), "{}", err).unwrap();
             process::exit(1);
         }
     }
@@ -65,76 +67,61 @@ fn run(args: &Args) -> Result<(), Box<Error>> {
             (aut.heap_bytes(), aut.num_states())
         } else {
             (aut.heap_bytes(), aut.num_states())
         };
         println!("{} bytes, {} states", bytes, states);
         return Ok(());
     }
 
+    let rdr = try!(File::open(&args.arg_input));
     if args.flag_full {
         let aut = aut.into_full();
         if args.flag_overlapping {
             if args.flag_count {
-                let mmap = Mmap::open_path(
-                    &args.arg_input, Protection::Read).unwrap();
-                let text = unsafe { mmap.as_slice() };
-                println!("{}", aut.find_overlapping(text).count());
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find_overlapping(&*mmap).count());
             } else {
-                let rdr = try!(File::open(&args.arg_input));
                 try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
             }
         } else {
             if args.flag_count {
-                let mmap = Mmap::open_path(
-                    &args.arg_input, Protection::Read).unwrap();
-                let text = unsafe { mmap.as_slice() };
-                println!("{}", aut.find(text).count());
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find(&*mmap).count());
             } else {
-                let rdr = try!(File::open(&args.arg_input));
                 try!(write_matches(&aut, aut.stream_find(rdr)));
             }
         }
     } else {
         if args.flag_overlapping {
             if args.flag_count {
-                let mmap = Mmap::open_path(
-                    &args.arg_input, Protection::Read).unwrap();
-                let text = unsafe { mmap.as_slice() };
-                println!("{}", aut.find_overlapping(text).count());
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find_overlapping(&*mmap).count());
             } else {
-                let rdr = try!(File::open(&args.arg_input));
                 try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
             }
         } else {
             if args.flag_count {
-                let mmap = Mmap::open_path(
-                    &args.arg_input, Protection::Read).unwrap();
-                let text = unsafe { mmap.as_slice() };
-                println!("{}", aut.find(text).count());
+                let mmap = unsafe { try!(Mmap::map(&rdr)) };
+                println!("{}", aut.find(&*mmap).count());
             } else {
-                let rdr = try!(File::open(&args.arg_input));
                 try!(write_matches(&aut, aut.stream_find(rdr)));
             }
         }
     }
     Ok(())
 }
 
 fn write_matches<A, I>(aut: &A, it: I) -> Result<(), Box<Error>>
         where A: Automaton<String>, I: Iterator<Item=io::Result<Match>> {
     let mut wtr = csv::Writer::from_writer(io::stdout());
-    try!(wtr.write(["pattern", "start", "end"].iter()));
+    try!(wtr.serialize(("pattern", "start", "end")));
     for m in it {
         let m = try!(m);
-        try!(wtr.write([
-            aut.pattern(m.pati),
-            &m.start.to_string(),
-            &m.end.to_string(),
-        ].iter()));
+        try!(wtr.serialize((aut.pattern(m.pati), m.start, m.end)));
     }
     try!(wtr.flush());
     Ok(())
 }
 
 fn build_automaton(
     dict_path: &str,
     min_len: usize,
diff --git a/third_party/rust/aho-corasick/src/autiter.rs b/third_party/rust/aho-corasick/src/autiter.rs
index 21a02a4cf10b..dfad28f67aa2 100644
--- a/third_party/rust/aho-corasick/src/autiter.rs
+++ b/third_party/rust/aho-corasick/src/autiter.rs
@@ -37,17 +37,17 @@ pub trait Automaton<P> {
     #[inline]
     fn len(&self) -> usize {
         self.patterns().len()
     }
 
     /// Returns true if the automaton has no patterns.
     #[inline]
     fn is_empty(&self) -> bool {
-        self.len() == 0
+        self.patterns().is_empty()
     }
 
     /// Returns an iterator of non-overlapping matches in `s`.
     fn find<'a, 's, Q: ?Sized + AsRef<[u8]>>(
         &'a self,
         s: &'s Q,
     ) -> Matches<'a, 's, P, Self>
     where Self: Sized {
@@ -376,17 +376,17 @@ impl<'a, R: io::Read, P, A: Automaton<P>>
 
     fn next(&mut self) -> Option<io::Result<Match>> {
         let mut m = None;
         let mut consumed = 0;
 'LOOP:  loop {
             self.buf.consume(consumed);
             let bs = match self.buf.fill_buf() {
                 Err(err) => return Some(Err(err)),
-                Ok(bs) if bs.len() == 0 => break,
+                Ok(bs) if bs.is_empty() => break,
                 Ok(bs) => bs,
             };
             consumed = bs.len(); // is shortened if we find a match
             for (i, &b) in bs.iter().enumerate() {
                 self.si = self.aut.next_state(self.si, b);
                 if self.aut.has_match(self.si, 0) {
                     m = Some(Ok(self.aut.get_match(self.si, 0, self.texti)));
                     consumed = i + 1;
@@ -500,17 +500,17 @@ impl<'a, R: io::Read, P, A: Automaton<P> + ?Sized>
         }
         let mut m = None;
         let mut consumed = 0;
         self.outi = 0;
 'LOOP:  loop {
             self.buf.consume(consumed);
             let bs = match self.buf.fill_buf() {
                 Err(err) => return Some(Err(err)),
-                Ok(bs) if bs.len() == 0 => break,
+                Ok(bs) if bs.is_empty() => break,
                 Ok(bs) => bs,
             };
             consumed = bs.len(); // is shortened if we find a match
             for (i, &b) in bs.iter().enumerate() {
                 self.si = self.aut.next_state(self.si, b);
                 if self.aut.has_match(self.si, self.outi) {
                     m = Some(Ok(self.aut.get_match(
                         self.si, self.outi, self.texti)));
diff --git a/third_party/rust/aho-corasick/src/full.rs b/third_party/rust/aho-corasick/src/full.rs
index f7d7c637e829..377940afabd8 100644
--- a/third_party/rust/aho-corasick/src/full.rs
+++ b/third_party/rust/aho-corasick/src/full.rs
@@ -39,33 +39,33 @@ impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
         fac.start_bytes = ac.start_bytes;
         fac
     }
 
     #[doc(hidden)]
     pub fn memory_usage(&self) -> usize {
         self.pats.iter()
             .map(|p| vec_bytes() + p.as_ref().len())
-            .fold(0, |a, b| a + b)
+            .sum::<usize>()
         + (4 * self.trans.len())
         + self.out.iter()
               .map(|v| vec_bytes() + (usize_bytes() * v.len()))
-              .fold(0, |a, b| a + b)
+              .sum::<usize>()
         + self.start_bytes.len()
     }
 
     #[doc(hidden)]
     pub fn heap_bytes(&self) -> usize {
         self.pats.iter()
             .map(|p| mem::size_of::<P>() + p.as_ref().len())
-            .fold(0, |a, b| a + b)
+            .sum::<usize>()
         + (4 * self.trans.len())
         + self.out.iter()
               .map(|v| vec_bytes() + (usize_bytes() * v.len()))
-              .fold(0, |a, b| a + b)
+              .sum::<usize>()
         + self.start_bytes.len()
     }
 
     fn set(&mut self, si: StateIdx, i: u8, goto: StateIdx) {
         let ns = self.num_states();
         self.trans[i as usize * ns + si as usize] = goto;
     }
 
@@ -114,23 +114,32 @@ impl<P: AsRef<[u8]>> Automaton<P> for FullAcAutomaton<P> {
     fn pattern(&self, i: usize) -> &P {
         &self.pats[i]
     }
 }
 
 impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
     fn build_matrix<T: Transitions>(&mut self, ac: &AcAutomaton<P, T>) {
         for (si, s) in ac.states.iter().enumerate().skip(1) {
-            for b in (0..256).map(|b| b as u8) {
-                self.set(si as StateIdx, b, ac.next_state(si as StateIdx, b));
-            }
-            for &pati in &s.out {
-                self.out[si].push(pati);
-            }
+            self.set_states(ac, si as StateIdx);
+            self.out[si].extend_from_slice(&s.out);
         }
     }
+
+    fn set_states<T: Transitions>(&mut self, ac: &AcAutomaton<P, T>, si: StateIdx) {
+        let current_state = &ac.states[si as usize];
+        let first_fail_state = current_state.fail;
+        current_state.for_each_transition(move |b, maybe_si| {
+            let goto = if maybe_si == FAIL_STATE {
+                ac.memoized_next_state(self, si, first_fail_state, b)
+            } else {
+                maybe_si
+            };
+            self.set(si, b, goto);
+        });
+    }
 }
 
 impl<P: AsRef<[u8]> + fmt::Debug> fmt::Debug for FullAcAutomaton<P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "FullAcAutomaton({:?})", self.pats)
     }
 }
diff --git a/third_party/rust/aho-corasick/src/lib.rs b/third_party/rust/aho-corasick/src/lib.rs
index 95ab071f6a7e..6ceb206414c6 100644
--- a/third_party/rust/aho-corasick/src/lib.rs
+++ b/third_party/rust/aho-corasick/src/lib.rs
@@ -116,18 +116,20 @@ let aut = AcAutomaton::<&str, Sparse>::with_transitions(vec!["abc", "a"]);
 let matches: Vec<_> = aut.find("abc").collect();
 assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]);
 ```
 */
 
 #![deny(missing_docs)]
 
 extern crate memchr;
-#[cfg(test)] extern crate quickcheck;
-#[cfg(test)] extern crate rand;
+#[cfg(test)]
+extern crate quickcheck;
+#[cfg(test)]
+extern crate rand;
 
 use std::collections::VecDeque;
 use std::fmt;
 use std::iter::FromIterator;
 use std::mem;
 
 pub use self::autiter::{
     Automaton, Match,
@@ -236,34 +238,57 @@ impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
     pub fn num_states(&self) -> usize {
         self.states.len()
     }
 
     #[doc(hidden)]
     pub fn heap_bytes(&self) -> usize {
         self.pats.iter()
             .map(|p| mem::size_of::<P>() + p.as_ref().len())
-            .fold(0, |a, b| a + b)
+            .sum::<usize>()
         + self.states.iter()
               .map(|s| mem::size_of::<State<T>>() + s.heap_bytes())
-              .fold(0, |a, b| a + b)
+              .sum::<usize>()
         + self.start_bytes.len()
     }
+
+    // The states of `full_automaton` should be set for all states < si
+    fn memoized_next_state(
+        &self,
+        full_automaton: &FullAcAutomaton<P>,
+        current_si: StateIdx,
+        mut si: StateIdx,
+        b: u8,
+    ) -> StateIdx {
+        loop {
+            if si < current_si {
+                return full_automaton.next_state(si, b);
+            }
+            let state = &self.states[si as usize];
+            let maybe_si = state.goto(b);
+            if maybe_si != FAIL_STATE {
+                return maybe_si;
+            } else {
+                si = state.fail;
+            }
+        }
+    }
 }
 
 impl<P: AsRef<[u8]>, T: Transitions> Automaton<P> for AcAutomaton<P, T> {
     #[inline]
     fn next_state(&self, mut si: StateIdx, b: u8) -> StateIdx {
         loop {
-            let maybe_si = self.states[si as usize].goto(b);
+            let state = &self.states[si as usize];
+            let maybe_si = state.goto(b);
             if maybe_si != FAIL_STATE {
                 si = maybe_si;
                 break;
             } else {
-                si = self.states[si as usize].fail;
+                si = state.fail;
             }
         }
         si
     }
 
     #[inline]
     fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
         let pati = self.states[si as usize].out[outi];
@@ -292,16 +317,39 @@ impl<P: AsRef<[u8]>, T: Transitions> Automaton<P> for AcAutomaton<P, T> {
     }
 
     #[inline]
     fn pattern(&self, i: usize) -> &P {
         &self.pats[i]
     }
 }
 
+// `(0..256).map(|b| b as u8)` optimizes poorly in debug builds so
+// we use this small explicit iterator instead
+struct AllBytesIter(i32);
+impl Iterator for AllBytesIter {
+    type Item = u8;
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.0 < 256 {
+            let b = self.0 as u8;
+            self.0 += 1;
+            Some(b)
+        } else {
+            None
+        }
+    }
+}
+
+impl AllBytesIter {
+    fn new() -> AllBytesIter {
+        AllBytesIter(0)
+    }
+}
+
 // Below contains code for *building* the automaton. It's a reasonably faithful
 // translation of the description/psuedo-code from:
 // http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
 
 impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
     // This is the first phase and builds the initial keyword tree.
     fn build(mut self, pats: Vec<P>) -> AcAutomaton<P, T> {
         for (pati, pat) in pats.iter().enumerate() {
@@ -316,21 +364,24 @@ impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
                     let depth = self.states[previ as usize].depth + 1;
                     let nexti = self.add_state(State::new(depth));
                     self.states[previ as usize].set_goto(b, nexti);
                     previ = nexti;
                 }
             }
             self.states[previ as usize].out.push(pati);
         }
-        for c in (0..256).into_iter().map(|c| c as u8) {
-            if self.states[ROOT_STATE as usize].goto(c) == FAIL_STATE {
-                self.states[ROOT_STATE as usize].set_goto(c, ROOT_STATE);
-            } else {
-                self.start_bytes.push(c);
+        {
+            let root_state = &mut self.states[ROOT_STATE as usize];
+            for c in AllBytesIter::new() {
+                if root_state.goto(c) == FAIL_STATE {
+                    root_state.set_goto(c, ROOT_STATE);
+                } else {
+                    self.start_bytes.push(c);
+                }
             }
         }
         // If any of the start bytes are non-ASCII, then remove them all,
         // because we don't want to be calling memchr on non-ASCII bytes.
         // (Well, we could, but it requires being more clever. Simply using
         // the prefix byte isn't good enough.)
         if self.start_bytes.iter().any(|&b| b > 0x7F) {
             self.start_bytes.clear();
@@ -339,36 +390,55 @@ impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
         self.fill()
     }
 
     // The second phase that fills in the back links.
     fn fill(mut self) -> AcAutomaton<P, T> {
         // Fill up the queue with all non-root transitions out of the root
         // node. Then proceed by breadth first traversal.
         let mut q = VecDeque::new();
-        for c in (0..256).into_iter().map(|c| c as u8) {
-            let si = self.states[ROOT_STATE as usize].goto(c);
+        self.states[ROOT_STATE as usize].for_each_transition(|_, si| {
             if si != ROOT_STATE {
                 q.push_front(si);
             }
-        }
+        });
+
+        let mut transitions = Vec::new();
+
         while let Some(si) = q.pop_back() {
-            for c in (0..256).into_iter().map(|c| c as u8) {
-                let u = self.states[si as usize].goto(c);
-                if u != FAIL_STATE {
-                    q.push_front(u);
-                    let mut v = self.states[si as usize].fail;
-                    while self.states[v as usize].goto(c) == FAIL_STATE {
-                        v = self.states[v as usize].fail;
+            self.states[si as usize].for_each_ok_transition(|c, u| {
+                transitions.push((c, u));
+                q.push_front(u);
+            });
+
+            for (c, u) in transitions.drain(..) {
+                let mut v = self.states[si as usize].fail;
+                loop {
+                    let state = &self.states[v as usize];
+                    if state.goto(c) == FAIL_STATE {
+                        v = state.fail;
+                    } else {
+                        break;
+                    }
+                }
+                let ufail = self.states[v as usize].goto(c);
+                self.states[u as usize].fail = ufail;
+
+                fn get_two<T>(xs: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
+                    if i < j {
+                        let (before, after) = xs.split_at_mut(j);
+                        (&mut before[i], &mut after[0])
+                    } else {
+                        let (before, after) = xs.split_at_mut(i);
+                        (&mut after[0], &mut before[j])
                     }
-                    let ufail = self.states[v as usize].goto(c);
-                    self.states[u as usize].fail = ufail;
-                    let ufail_out = self.states[ufail as usize].out.clone();
-                    self.states[u as usize].out.extend(ufail_out);
                 }
+
+                let (ufail_out, out) = get_two(&mut self.states, ufail as usize, u as usize);
+                out.out.extend_from_slice(&ufail_out.out);
             }
         }
         self
     }
 
     fn add_state(&mut self, state: State<T>) -> StateIdx {
         let i = self.states.len();
         self.states.push(state);
@@ -393,16 +463,28 @@ impl<T: Transitions> State<T> {
     fn set_goto(&mut self, b: u8, si: StateIdx) {
         self.goto.set_goto(b, si);
     }
 
     fn heap_bytes(&self) -> usize {
         (self.out.len() * usize_bytes())
         + self.goto.heap_bytes()
     }
+
+    fn for_each_transition<F>(&self, f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        self.goto.for_each_transition(f)
+    }
+
+    fn for_each_ok_transition<F>(&self, f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        self.goto.for_each_ok_transition(f)
+    }
 }
 
 /// An abstraction over state transition strategies.
 ///
 /// This is an attempt to let the caller choose the space/time trade offs
 /// used for state transitions.
 ///
 /// (It's possible that this interface is merely good enough for just the two
@@ -411,91 +493,158 @@ pub trait Transitions {
     /// Return a new state at the given depth.
     fn new(depth: u32) -> Self;
     /// Return the next state index given the next character.
     fn goto(&self, alpha: u8) -> StateIdx;
     /// Set the next state index for the character given.
     fn set_goto(&mut self, alpha: u8, si: StateIdx);
     /// The memory use in bytes (on the heap) of this set of transitions.
     fn heap_bytes(&self) -> usize;
+
+    /// Iterates over each state
+    fn for_each_transition<F>(&self, mut f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        for b in AllBytesIter::new() {
+            f(b, self.goto(b));
+        }
+    }
+
+    /// Iterates over each non-fail state
+    fn for_each_ok_transition<F>(&self, mut f: F)
+    where
+        F: FnMut(u8, StateIdx),
+    {
+        self.for_each_transition(|b, si| {
+            if si != FAIL_STATE {
+                f(b, si);
+            }
+        });
+    }
 }
 
 /// State transitions that can be stored either sparsely or densely.
 ///
 /// This uses less space but at the expense of slower matching.
 #[derive(Clone, Debug)]
 pub struct Dense(DenseChoice);
 
 #[derive(Clone, Debug)]
 enum DenseChoice {
-    Sparse(Vec<StateIdx>), // indexed by alphabet
+    Sparse(Box<Sparse>),
     Dense(Vec<(u8, StateIdx)>),
 }
 
 impl Transitions for Dense {
     fn new(depth: u32) -> Dense {
         if depth <= DENSE_DEPTH_THRESHOLD {
-            Dense(DenseChoice::Sparse(vec![0; 256]))
+            Dense(DenseChoice::Sparse(Box::new(Sparse::new(depth))))
         } else {
             Dense(DenseChoice::Dense(vec![]))
         }
     }
 
     fn goto(&self, b1: u8) -> StateIdx {
         match self.0 {
-            DenseChoice::Sparse(ref m) => m[b1 as usize],
+            DenseChoice::Sparse(ref m) => m.goto(b1),
             DenseChoice::Dense(ref m) => {
                 for &(b2, si) in m {
                     if b1 == b2 {
                         return si;
                     }
                 }
                 FAIL_STATE
             }
         }
     }
 
     fn set_goto(&mut self, b: u8, si: StateIdx) {
         match self.0 {
-            DenseChoice::Sparse(ref mut m) => m[b as usize] = si,
+            DenseChoice::Sparse(ref mut m) => m.set_goto(b, si),
             DenseChoice::Dense(ref mut m) => m.push((b, si)),
         }
     }
 
     fn heap_bytes(&self) -> usize {
         match self.0 {
-            DenseChoice::Sparse(ref m) => m.len() * 4,
+            DenseChoice::Sparse(_) => mem::size_of::<Sparse>(),
             DenseChoice::Dense(ref m) => m.len() * (1 + 4),
         }
     }
+
+    fn for_each_transition<F>(&self, mut f: F)
+        where F: FnMut(u8, StateIdx)
+    {
+        match self.0 {
+            DenseChoice::Sparse(ref m) => m.for_each_transition(f),
+            DenseChoice::Dense(ref m) => {
+                let mut iter = m.iter();
+                let mut b = 0i32;
+                while let Some(&(next_b, next_si)) = iter.next() {
+                    while (b as u8) < next_b {
+                        f(b as u8, FAIL_STATE);
+                        b += 1;
+                    }
+                    f(b as u8, next_si);
+                    b += 1;
+                }
+                while b < 256 {
+                    f(b as u8, FAIL_STATE);
+                    b += 1;
+                }
+            }
+        }
+    }
+    fn for_each_ok_transition<F>(&self, mut f: F)
+    where
+        F: FnMut(u8, StateIdx),
+    {
+        match self.0 {
+            DenseChoice::Sparse(ref m) => m.for_each_ok_transition(f),
+            DenseChoice::Dense(ref m) => for &(b, si) in m {
+                f(b, si)
+            }
+        }
+    }
 }
 
 /// State transitions that are always sparse.
 ///
 /// This can use enormous amounts of memory when there are many patterns,
 /// but matching is very fast.
-#[derive(Clone, Debug)]
-pub struct Sparse(Vec<StateIdx>);
+pub struct Sparse([StateIdx; 256]);
+
+impl Clone for Sparse {
+    fn clone(&self) -> Sparse {
+        Sparse(self.0)
+    }
+}
+
+impl fmt::Debug for Sparse {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Sparse").field(&&self.0[..]).finish()
+    }
+}
 
 impl Transitions for Sparse {
     fn new(_: u32) -> Sparse {
-        Sparse(vec![0; 256])
+        Sparse([0; 256])
     }
 
     #[inline]
     fn goto(&self, b: u8) -> StateIdx {
         self.0[b as usize]
     }
 
     fn set_goto(&mut self, b: u8, si: StateIdx) {
         self.0[b as usize] = si;
     }
 
     fn heap_bytes(&self) -> usize {
-        self.0.len() * 4
+        0
     }
 }
 
 impl<S: AsRef<[u8]>> FromIterator<S> for AcAutomaton<S> {
     /// Create an automaton from an iterator of strings.
     fn from_iter<T>(it: T) -> AcAutomaton<S> where T: IntoIterator<Item=S> {
         AcAutomaton::new(it)
     }
@@ -520,25 +669,23 @@ impl<P: AsRef<[u8]> + fmt::Debug, T: Transitions>
 
 impl<T: Transitions> State<T> {
     fn debug(&self, root: bool) -> String {
         format!("State {{ depth: {:?}, out: {:?}, fail: {:?}, goto: {{{}}} }}",
                 self.depth, self.out, self.fail, self.goto_string(root))
     }
 
     fn goto_string(&self, root: bool) -> String {
-        use std::char::from_u32;
-
         let mut goto = vec![];
-        for b in (0..256).map(|b| b as u8) {
+        for b in AllBytesIter::new() {
             let si = self.goto(b);
             if (!root && si == FAIL_STATE) || (root && si == ROOT_STATE) {
                 continue;
             }
-            goto.push(format!("{} => {}", from_u32(b as u32).unwrap(), si));
+            goto.push(format!("{} => {}", b as char, si));
         }
         goto.join(", ")
     }
 }
 
 impl<T: Transitions> fmt::Debug for State<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.debug(false))
@@ -558,23 +705,23 @@ impl<T: Transitions> AcAutomaton<String, T> {
 digraph automaton {{
     label=<<FONT POINT-SIZE="20">{}</FONT>>;
     labelloc="l";
     labeljust="l";
     rankdir="LR";
 "#, self.pats.join(", "));
         for (i, s) in self.states.iter().enumerate().skip(1) {
             let i = i as u32;
-            if s.out.len() == 0 {
+            if s.out.is_empty() {
                 w!(out, "    {};\n", i);
             } else {
                 w!(out, "    {} [peripheries=2];\n", i);
             }
             w!(out, "    {} -> {} [style=dashed];\n", i, s.fail);
-            for b in (0..256).map(|b| b as u8) {
+            for b in AllBytesIter::new() {
                 let si = s.goto(b);
                 if si == FAIL_STATE || (i == ROOT_STATE && si == ROOT_STATE) {
                     continue;
                 }
                 w!(out, "    {} -> {} [label={}];\n", i, si, b as char);
             }
         }
         w!(out, "}}");
@@ -592,18 +739,19 @@ fn usize_bytes() -> usize {
 }
 
 #[cfg(test)]
 mod tests {
     use std::collections::HashSet;
     use std::io;
 
     use quickcheck::{Arbitrary, Gen, quickcheck};
+    use rand::Rng;
 
-    use super::{Automaton, AcAutomaton, Match};
+    use super::{AcAutomaton, Automaton, Match, AllBytesIter};
 
     fn aut_find<S>(xs: &[S], haystack: &str) -> Vec<Match>
             where S: Clone + AsRef<[u8]> {
         AcAutomaton::new(xs.to_vec()).find(&haystack).collect()
     }
 
     fn aut_finds<S>(xs: &[S], haystack: &str) -> Vec<Match>
             where S: Clone + AsRef<[u8]> {
@@ -865,17 +1013,17 @@ mod tests {
     pub struct BiasAscii(String);
 
     impl Arbitrary for BiasAscii {
         fn arbitrary<G: Gen>(g: &mut G) -> BiasAscii {
             use std::char::from_u32;
             let size = { let s = g.size(); g.gen_range(0, s) };
             let mut s = String::with_capacity(size);
             for _ in 0..size {
-                if g.gen_weighted_bool(3) {
+                if g.gen_bool(0.3) {
                     s.push(char::arbitrary(g));
                 } else {
                     for _ in 0..5 {
                         s.push(from_u32(g.gen_range(97, 123)).unwrap());
                     }
                 }
             }
             BiasAscii(s)
@@ -917,9 +1065,18 @@ mod tests {
             // Ordering isn't always the same. I don't think we care, so do
             // an unordered comparison.
             let aset: HashSet<Match> = aut_matches.iter().cloned().collect();
             let nset: HashSet<Match> = naive_matches.iter().cloned().collect();
             aset == nset
         }
         quickcheck(prop as fn(Vec<SmallAscii>, BiasAscii) -> bool);
     }
+
+
+    #[test]
+    fn all_bytes_iter() {
+        let all_bytes = AllBytesIter::new().collect::<Vec<_>>();
+        assert_eq!(all_bytes[0], 0);
+        assert_eq!(all_bytes[255], 255);
+        assert!(AllBytesIter::new().enumerate().all(|(i, b)| b as usize == i));
+    }
 }
diff --git a/third_party/rust/bindgen/.cargo-checksum.json b/third_party/rust/bindgen/.cargo-checksum.json
index f4e3b52a361a..10d3b1595ace 100644
--- a/third_party/rust/bindgen/.cargo-checksum.json
+++ b/third_party/rust/bindgen/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"88154517e146758d019c015d3f194f364be77e927686c8018f0ff766cff9a756","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"a8b6c8cc227d5a01406a431109520c0a0467777bae430c4b769a1305b820926c","src/clang.rs":"c816d5291ccdc1d4ba028ae817ef385048e1fb8443911d026af5c721a6d57854","src/codegen/bitfield_unit.rs":"bd1a19701f1766d0bae3bcb97d7c3cb3881d4b182c56b8f4dfd24b7cc87b5338","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"bcb951f320fd0948e341d8eabdb58567296d77bf1ae5040c05d967e6435a15d5","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"e86050b98f57fa4496dbde0beea319a89e46290309d274f626361779549b95bd","src/codegen/mod.rs":"e154f6e30b29ce8fd075813a0052de363157a975446013b4032d4080dfd65cf3","src/codegen/struct_layout.rs":"3c4b2b4543c6aa1da03f7522ad7f831e95dc146cf5edd08ebd5facb1305daddb","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"8c2148a6f922ca9cb0de2dd3ad77c4dd5734c4c219a5bea9d6b22c4367acb187","src/ir/analysis/derive_copy.rs":"14b53c53b337be00d59424371c07c6712d7cfc9a6735f9d913cda043fddce797","src/ir/analysis/derive_debug.rs":"1d6621c0fa5d899310cc175cb99703606ed34fd7f7ad77bb60f012f25ba504af","src/ir/analysis/derive_default.rs":"4fac04fc3019562cd213586680ecdcf8a3b3544ca3a5c5117f68e5c26e7ee0d9","src/ir/analysis/derive_hash.rs":"a50e849b4388115264c2d6afef5ab07e309d2469f4c3342fb683c799451e9e19","src/ir/analysis/derive_partialeq_or_partialord.rs":"46611c7f3caa0fe78243187742c4a36003dbc266de4c4390642e136bb889c43f","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"5c6ee7a251a321ef5733e2e7ac3264621b4181268babcc008b69dbfc37691fb1","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"36f2a1d3970fdbf3d72c1f094043902747cde395215bdf7e9103926d9df011fd","src/ir/comp.rs":"d6811204a5cf68b4e9f1ef1dac80c7178394a18bc5165765e479925921671fa4","src/ir/context.rs":"7d28388430ad0587fab282ba50d3c536e58c53d84746ab557fe6d9dc0e917a01","src/ir/derive.rs":"1fd6ad621e3c60b950acbd51fbe386d1f0fadb7c1889c723245afff45e42e143","src/ir/dot.rs":"eca03a493a7fe48044b832c37c71d51f1bd4e8689feb6f1cb8bc0422541c7284","src/ir/enum_ty.rs":"05bfe0bc9abfee0f9692a443a9493b45b20ebf8275d15b1b4cba5c9cb63182b9","src/ir/function.rs":"a3ecac28cc75a61926a62f2082999c0ffe6ffeef2beb157367ade865cd899a9a","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"527b9a006dd1865cb77bac7e0e3826904c71b3b77679bcf7cd4ea63791dfa5ec","src/ir/item_kind.rs":"13048962657436a757ff9483d96f2ce351ec5f827ecab4921ed643f6f115c497","src/ir/layout.rs":"e3d1adf1ad2fa5bd96530cdd5097db3d9cc7b44d33ec23a04fcfccecd9cf4469","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"05068c4fbf42429c4ac2a233c874f18ffcf7dc1744398e400a5a48d0e7a972f2","src/ir/template.rs":"bcd750450a4df0200a6e7958f9c96a09b91e3ccd29c60712f2b9d3458f1234aa","src/ir/traversal.rs":"a108f2b2a1b3d2e679274eead8cf6f8fc78454e88943527d56bb30b5f071f104","src/ir/ty.rs":"4d5f1b2e11f6fb7df3348bdab7775cdfa209e136afe84a7b0e862068e53e7183","src/ir/var.rs":"96cca085d33d75493ae2b4465272a044d96a0e98f7732f13456313af3cf5beb8","src/lib.rs":"8a2a28797d2c7a014082a48a91361ed8090941de204e786ac107f2adae5d9cda","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"54b9fb74c8a998e3b3272f282493214371fbf42a9af6a54455824ef8b76d2445","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"a02befb48d10dcc31e3f9571b2fa1c40f97fafe6f6ae7d7fc4f8fd01f1a169ba"},"package":"1657d607dd7a8e10b3181149f60f3b27ea0eac81058c09a1c791b8f6ead91f19"}
\ No newline at end of file
+{"files":{"Cargo.toml":"3080fa2631c58e35cb1b32642139d8c303a609f8b554bfe69cd659a5374f18b9","LICENSE":"1d2e4bdb9d94ab020e9550136cae9ec73fc699c3c96a9d98078c542e9b93d294","README.md":"630d1a1d123c131bad0fec23173e263ba8ecc064b5cd8446d4cab7ffd197db45","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"9d41b7848cea37e8741fa7bc947ba58a83647824b1a0bbe7ff75012c412eab13","src/clang.rs":"5ce27d0772e66f9f2f94a55afd18c98d4a57aed4c1d57da53b025fbbbb81a287","src/codegen/bitfield_unit.rs":"88b0604322dc449fc9284850eadc1f5d14b42fa747d4258bae0b6b9535f52dfd","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"8badd4b5ba38b83477c3ee3fc6f9ca79059b5650f5b489b2723c335037e27d92","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"d69e2a9cdf2fdea74a60532109c0a1a75791f5a5ef931b28c5d447fa2915e5d3","src/codegen/mod.rs":"c923594d8d27dede9192dd1081acdedf97d67430f780e3dc4db39b8928a55d71","src/codegen/struct_layout.rs":"9bd0e3455e55e2a1faa4f332a327c2529a21bdfdd0fcb3a45bc5cdd7801d288f","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"a437e6f736c8fba81ff74d90e7ddd142192ae5ffb9240d8c885eb84be6f2fe45","src/ir/analysis/derive_copy.rs":"59c21e299af3a36c6c82d4d16454700238269abd5929ec2d67c8414aebf82c3b","src/ir/analysis/derive_debug.rs":"3530e27ab0e260ec013cee3ad78a81497970c656a8eed589b755cce8caf53040","src/ir/analysis/derive_default.rs":"20e9dac151fadc59a7926ed9276ee8ced47e59c3f0c43f69fdafb75706045aca","src/ir/analysis/derive_hash.rs":"85c73c5660dc311ab6c15a21b69c4c5d2aa380d740decaf59ad594a6728cbe1f","src/ir/analysis/derive_partialeq_or_partialord.rs":"fb9540c324fdfcc9b0ae816e7713af000b11f5e2768c512c22a3082f263bb6bc","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"6554dd1240142ec0e7299e678b696725f5cba99243d1c3d1cbf58d4764082fd6","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"000481754e5433d7c0886b9ce8b93b64c7ab1ae52867d211c73c7c4b336649a2","src/ir/comp.rs":"7b22f3ff19ca45a6fbfe7ea015109d43f4ddf65b33b47b1c37829fcb87cdff9b","src/ir/context.rs":"80679859b4efa52d74b0c7501bb5951b58c9705a97b96c9fc05134d1abe401c6","src/ir/derive.rs":"9550d01731ca66be28124c91fd0211a618743a065bec7b00e27c934afff82a84","src/ir/dot.rs":"d01f1621ab67e368d854a82bd6bb0b8dd52f3c2c733de8eaf81aece9543818cb","src/ir/enum_ty.rs":"3611100df8ddf01b010d2eae1d26a67df022e47b6236b0ed9d1b9b42340ebafd","src/ir/function.rs":"b86e665c6659c32bce39194240e7da6221c5a2ec51b362ad9f6e34f1bc396a6f","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"6f0d13615c6883b5e64c75f6d18d79b978b47aa3599ae1f4c196903d2d2cda68","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"17daab0a80564006de1f6b6190e7d9e6c5eb96990242fe707f8dc676f7110c18","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"828a890acdc8b10c44e69e2ed4a4f5d8c0e734606d3a8cc71658dcf43a49acf4","src/ir/template.rs":"21ba4cbacafce39b4a8013bc97e8054a906a8bc2f45a51aeef3b007caadde221","src/ir/traversal.rs":"eaca9aa6deb3eea9b8d7adc696781c70038796ff43e536bda47e90f84fe87d61","src/ir/ty.rs":"daa95f757288e4bfe84f9724c5f5df127b6f3a4452330691a24a94369db7d993","src/ir/var.rs":"57c8aa9f834c6f06418f7d471b1771bbb915821ef0d194b383be60092edca5f7","src/lib.rs":"d4217ac878659794c5990b1612f1de12f94f975257ea14307fb7dc63ac3a76da","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"f1be872e418a96582b048c095ceeeba012b92ffed8a9658cd1fd9ae0e192372d","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"3b763e6fee51d0eb01228dfe28bc28a9f692aff73b2a7b90a030902e0238fca6"},"package":"1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"}
\ No newline at end of file
diff --git a/third_party/rust/bindgen/Cargo.toml b/third_party/rust/bindgen/Cargo.toml
index 91d5f509e284..2007f727a8ed 100644
--- a/third_party/rust/bindgen/Cargo.toml
+++ b/third_party/rust/bindgen/Cargo.toml
@@ -7,21 +7,22 @@
 #
 # 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 = "bindgen"
-version = "0.33.1"
+version = "0.37.4"
 authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
 build = "build.rs"
-include = ["Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
+include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
 description = "Automatically generates Rust FFI bindings to C and C++ libraries."
+homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
 documentation = "https://docs.rs/bindgen"
 readme = "README.md"
 keywords = ["bindings", "ffi", "code-generation"]
 categories = ["external-ffi-bindings", "development-tools::ffi"]
 license = "BSD-3-Clause"
 repository = "https://github.com/rust-lang-nursery/rust-bindgen"
 
 [lib]
@@ -33,18 +34,18 @@ path = "src/main.rs"
 doc = false
 [dependencies.cexpr]
 version = "0.2"
 
 [dependencies.cfg-if]
 version = "0.1.0"
 
 [dependencies.clang-sys]
-version = "0.21.0"
-features = ["runtime", "clang_3_9"]
+version = "0.23"
+features = ["runtime", "clang_6_0"]
 
 [dependencies.clap]
 version = "2"
 
 [dependencies.env_logger]
 version = "0.5"
 optional = true
 
@@ -53,21 +54,26 @@ version = "1"
 
 [dependencies.log]
 version = "0.4"
 optional = true
 
 [dependencies.peeking_take_while]
 version = "0.1.2"
 
+[dependencies.proc-macro2]
+version = "0.3.2, < 0.3.6"
+default-features = false
+
 [dependencies.quote]
-version = "0.3.15"
+version = "0.5"
+default-features = false
 
 [dependencies.regex]
-version = "0.2"
+version = "1.0"
 
 [dependencies.which]
 version = "1.0.2"
 [dev-dependencies.clap]
 version = "2"
 
 [dev-dependencies.diff]
 version = "0.1"
@@ -79,10 +85,11 @@ version = "0.1"
 default = ["logging"]
 logging = ["env_logger", "log"]
 static = []
 testing_only_docs = []
 testing_only_extra_assertions = []
 testing_only_libclang_3_8 = []
 testing_only_libclang_3_9 = []
 testing_only_libclang_4 = []
+testing_only_libclang_5 = []
 [badges.travis-ci]
 repository = "rust-lang-nursery/rust-bindgen"
diff --git a/third_party/rust/bindgen/LICENSE b/third_party/rust/bindgen/LICENSE
new file mode 100644
index 000000000000..589b5326e624
--- /dev/null
+++ b/third_party/rust/bindgen/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2013, Jyun-Yan You
+
+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.
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS "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 AUTHORS 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.
diff --git a/third_party/rust/bindgen/README.md b/third_party/rust/bindgen/README.md
new file mode 100644
index 000000000000..27cefbffc969
--- /dev/null
+++ b/third_party/rust/bindgen/README.md
@@ -0,0 +1,45 @@
+# `bindgen`
+
+[`impl period`](https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html) has been started! Join us at [Gitter.im](https://gitter.im/rust-impl-period/WG-dev-tools-bindgen).
+
+**`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.**
+
+For example, given the C header `doggo.h`:
+
+```c
+typedef struct Doggo {
+    int many;
+    char wow;
+} Doggo;
+
+void eleven_out_of_ten_majestic_af(Doggo* pupper);
+```
+
+`bindgen` produces Rust FFI code allowing you to call into the `doggo` library's
+functions and use its types:
+
+```rust
+/* automatically generated by rust-bindgen */
+
+#[repr(C)]
+pub struct Doggo {
+    pub many: ::std::os::raw::c_int,
+    pub wow: ::std::os::raw::c_char,
+}
+
+extern "C" {
+    pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
+}
+```
+
+## Users Guide
+
+[📚 Read the `bindgen` users guide here! 📚](https://rust-lang-nursery.github.io/rust-bindgen)
+
+## API Reference
+
+[API reference documentation is on docs.rs](https://docs.rs/bindgen)
+
+## Contributing
+
+[See `CONTRIBUTING.md` for hacking on `bindgen`!](./CONTRIBUTING.md)
diff --git a/third_party/rust/bindgen/src/callbacks.rs b/third_party/rust/bindgen/src/callbacks.rs
index 469314c4ce93..71b98fc90b6b 100644
--- a/third_party/rust/bindgen/src/callbacks.rs
+++ b/third_party/rust/bindgen/src/callbacks.rs
@@ -30,20 +30,29 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
     }
 
     /// The integer kind an integer macro should have, given a name and the
     /// value of that macro, or `None` if you want the default to be chosen.
     fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
         None
     }
 
-    /// This function should return whether, given the a given enum variant
-    /// name, and value, returns whether this enum variant will forcibly be a
-    /// constant.
+    /// This function should return whether, given an enum variant
+    /// name, and value, this enum variant will forcibly be a constant.
     fn enum_variant_behavior(
         &self,
         _enum_name: Option<&str>,
-        _variant_name: &str,
+        _original_variant_name: &str,
         _variant_value: EnumVariantValue,
     ) -> Option<EnumVariantCustomBehavior> {
         None
     }
+
+    /// Allows to rename an enum variant, replacing `_original_variant_name`.
+    fn enum_variant_name(
+        &self,
+        _enum_name: Option<&str>,
+        _original_variant_name: &str,
+        _variant_value: EnumVariantValue,
+    ) -> Option<String> {
+        None
+    }
 }
diff --git a/third_party/rust/bindgen/src/clang.rs b/third_party/rust/bindgen/src/clang.rs
index c0c96e5efef6..eefc7cf1a0c3 100644
--- a/third_party/rust/bindgen/src/clang.rs
+++ b/third_party/rust/bindgen/src/clang.rs
@@ -898,24 +898,31 @@ impl Type {
             }
         }
     }
 
     /// Get the layout for this type, or an error describing why it does not
     /// have a valid layout.
     pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> {
         use ir::layout::Layout;
-        let size = try!(self.fallible_size());
-        let align = try!(self.fallible_align());
+        let size = self.fallible_size()?;
+        let align = self.fallible_align()?;
         Ok(Layout::new(size, align))
     }
 
     /// Get the number of template arguments this type has, or `None` if it is
     /// not some kind of template.
     pub fn num_template_args(&self) -> Option<u32> {
+        // If an old libclang is loaded, we have no hope of answering this
+        // question correctly. However, that's no reason to panic when
+        // generating bindings for simple C headers with an old libclang.
+        if !clang_Type_getNumTemplateArguments::is_loaded() {
+            return None
+        }
+
         let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
         if n >= 0 {
             Some(n as u32)
         } else {
             debug_assert_eq!(n, -1);
             None
         }
     }
@@ -970,17 +977,17 @@ impl Type {
         let num_elements_returned = unsafe { clang_getNumElements(self.x) };
         if num_elements_returned != -1 {
             Some(num_elements_returned as usize)
         } else {
             None
         }
     }
 
-    /// Get the canonical version of this type. This sees through `typdef`s and
+    /// Get the canonical version of this type. This sees through `typedef`s and
     /// aliases to get the underlying, canonical type.
     pub fn canonical_type(&self) -> Type {
         unsafe {
             Type {
                 x: clang_getCanonicalType(self.x),
             }
         }
     }
@@ -1634,18 +1641,21 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
         }
 
         print_indent(depth, format!(" {}cconv = {}", prefix, ty.call_conv()));
 
         print_indent(
             depth,
             format!(" {}spelling = \"{}\"", prefix, ty.spelling()),
         );
-        let num_template_args =
-            unsafe { clang_Type_getNumTemplateArguments(ty.x) };
+        let num_template_args = if clang_Type_getNumTemplateArguments::is_loaded() {
+            unsafe { clang_Type_getNumTemplateArguments(ty.x) }
+        } else {
+            -1
+        };
         if num_template_args >= 0 {
             print_indent(
                 depth,
                 format!(
                     " {}number-of-template-args = {}",
                     prefix,
                     num_template_args
                 ),
@@ -1807,8 +1817,40 @@ impl EvalResult {
     }
 }
 
 impl Drop for EvalResult {
     fn drop(&mut self) {
         unsafe { clang_EvalResult_dispose(self.x) };
     }
 }
+
+/// Target information obtained from libclang.
+#[derive(Debug)]
+pub struct TargetInfo {
+    /// The target triple.
+    pub triple: String,
+    /// The width of the pointer _in bits_.
+    pub pointer_width: usize,
+}
+
+impl TargetInfo {
+    /// Tries to obtain target information from libclang.
+    pub fn new(tu: &TranslationUnit) -> Option<Self> {
+        if !clang_getTranslationUnitTargetInfo::is_loaded() {
+            return None;
+        }
+        let triple;
+        let pointer_width;
+        unsafe {
+            let ti = clang_getTranslationUnitTargetInfo(tu.x);
+            triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
+            pointer_width = clang_TargetInfo_getPointerWidth(ti);
+            clang_TargetInfo_dispose(ti);
+        }
+        assert!(pointer_width > 0);
+        assert_eq!(pointer_width % 8, 0);
+        Some(TargetInfo {
+            triple,
+            pointer_width: pointer_width as usize,
+        })
+    }
+}
diff --git a/third_party/rust/bindgen/src/codegen/bitfield_unit.rs b/third_party/rust/bindgen/src/codegen/bitfield_unit.rs
index 3c7c9b7b8b3b..7f263fd12f29 100755
--- a/third_party/rust/bindgen/src/codegen/bitfield_unit.rs
+++ b/third_party/rust/bindgen/src/codegen/bitfield_unit.rs
@@ -22,32 +22,43 @@ where
 
     #[inline]
     pub fn get_bit(&self, index: usize) -> bool {
         debug_assert!(index / 8 < self.storage.as_ref().len());
 
         let byte_index = index / 8;
         let byte = self.storage.as_ref()[byte_index];
 
-        let bit_index = index % 8;
+        let bit_index =
+            if cfg!(target_endian = "big") {
+                7 - (index % 8)
+            } else {
+                index % 8
+            };
+
         let mask = 1 << bit_index;
 
         byte & mask == mask
     }
 
     #[inline]
     pub fn set_bit(&mut self, index: usize, val: bool) {
         debug_assert!(index / 8 < self.storage.as_ref().len());
 
         let byte_index = index / 8;
         let byte = &mut self.storage.as_mut()[byte_index];
 
-        let bit_index = index % 8;
-        let mask = 1 << bit_index;
+        let bit_index =
+            if cfg!(target_endian = "big") {
+                7 - (index % 8)
+            } else {
+                index % 8
+            };
 
+        let mask = 1 << bit_index;
         if val {
             *byte |= mask;
         } else {
             *byte &= !mask;
         }
     }
 
     #[inline]
@@ -55,28 +66,40 @@ where
         debug_assert!(bit_width <= 64);
         debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
         debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
 
         let mut val = 0;
 
         for i in 0..(bit_width as usize) {
             if self.get_bit(i + bit_offset) {
-                val |= 1 << i;
+                let index =
+                    if cfg!(target_endian = "big") {
+                        bit_width as usize - 1 - i
+                    } else {
+                        i
+                    };
+                val |= 1 << index;
             }
         }
 
         val
     }
 
     #[inline]
     pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
         debug_assert!(bit_width <= 64);
         debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
         debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
 
         for i in 0..(bit_width as usize) {
             let mask = 1 << i;
             let val_bit_is_set = val & mask == mask;
-            self.set_bit(i + bit_offset, val_bit_is_set);
+            let index =
+                if cfg!(target_endian = "big") {
+                    bit_width as usize - 1 - i
+                } else {
+                    i
+                };
+            self.set_bit(index + bit_offset, val_bit_is_set);
         }
     }
 }
diff --git a/third_party/rust/bindgen/src/codegen/helpers.rs b/third_party/rust/bindgen/src/codegen/helpers.rs
index 9905430572a0..f1007c51e617 100644
--- a/third_party/rust/bindgen/src/codegen/helpers.rs
+++ b/third_party/rust/bindgen/src/codegen/helpers.rs
@@ -1,53 +1,55 @@
 //! Helpers for code generation that don't need macro expansion.
 
 use ir::context::BindgenContext;
 use ir::layout::Layout;
 use quote;
 use std::mem;
+use proc_macro2::{Term, Span};
 
 pub mod attributes {
     use quote;
+    use proc_macro2::{Term, Span};
 
     pub fn repr(which: &str) -> quote::Tokens {
-        let which = quote::Ident::new(which);
+        let which = Term::new(which, Span::call_site());
         quote! {
             #[repr( #which )]
         }
     }
 
     pub fn repr_list(which_ones: &[&str]) -> quote::Tokens {
-        let which_ones = which_ones.iter().cloned().map(quote::Ident::new);
+        let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site()));
         quote! {
             #[repr( #( #which_ones ),* )]
         }
     }
 
     pub fn derives(which_ones: &[&str]) -> quote::Tokens {
-        let which_ones = which_ones.iter().cloned().map(quote::Ident::new);
+        let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site()));
         quote! {
             #[derive( #( #which_ones ),* )]
         }
     }
 
     pub fn inline() -> quote::Tokens {
         quote! {
             #[inline]
         }
     }
 
     pub fn doc(comment: String) -> quote::Tokens {
         // Doc comments are already preprocessed into nice `///` formats by the
         // time they get here. Just make sure that we have newlines around it so
         // that nothing else gets wrapped into the comment.
         let mut tokens = quote! {};
-        tokens.append("\n");
-        tokens.append(comment);
-        tokens.append("\n");
+        tokens.append(Term::new("\n", Span::call_site()));
+        tokens.append(Term::new(&comment, Span::call_site()));
+        tokens.append(Term::new("\n", Span::call_site()));
         tokens
     }
 
     pub fn link_name(name: &str) -> quote::Tokens {
         // LLVM mangles the name by default but it's already mangled.
         // Prefixing the name with \u{1} should tell LLVM to not mangle it.
         let name = format!("\u{1}{}", name);
         quote! {
@@ -68,17 +70,17 @@ pub fn blob(layout: Layout) -> quote::Tokens {
     let ty_name = match opaque.known_rust_type_for_array() {
         Some(ty) => ty,
         None => {
             warn!("Found unknown alignment on code generation!");
             "u8"
         }
     };
 
-    let ty_name = quote::Ident::new(ty_name);
+    let ty_name = Term::new(ty_name, Span::call_site());
 
     let data_len = opaque.array_size().unwrap_or(layout.size);
 
     if data_len == 1 {
         quote! {
             #ty_name
         }
     } else {
@@ -98,39 +100,40 @@ pub fn integer_type(layout: Layout) -> Option<quote::Tokens> {
     }
 }
 
 /// Generates a bitfield allocation unit type for a type with the given `Layout`.
 pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
     let mut tokens = quote! {};
 
     if ctx.options().enable_cxx_namespaces {
-        tokens.append(quote! { root:: });
+        tokens.append_all(quote! { root:: });
     }
 
     let align = match layout.align {
         n if n >= 8 => quote! { u64 },
         4 => quote! { u32 },
         2 => quote! { u16 },
         _ => quote! { u8  },
     };
 
     let size = layout.size;
-    tokens.append(quote! {
+    tokens.append_all(quote! {
         __BindgenBitfieldUnit<[u8; #size], #align>
     });
 
     tokens
 }
 
 pub mod ast_ty {
     use ir::context::BindgenContext;
     use ir::function::FunctionSig;
     use ir::ty::FloatKind;
     use quote;
+    use proc_macro2;
 
     pub fn raw_type(ctx: &BindgenContext, name: &str) -> quote::Tokens {
         let ident = ctx.rust_ident_raw(name);
         match ctx.options().ctypes_prefix {
             Some(ref prefix) => {
                 let prefix = ctx.rust_ident_raw(prefix.as_str());
                 quote! {
                     #prefix::#ident
@@ -161,59 +164,48 @@ pub mod ast_ty {
             (FloatKind::Double, false) |
             (FloatKind::LongDouble, false) => raw_type(ctx, "c_double"),
             (FloatKind::Float128, _) => quote! { [u8; 16] },
         }
     }
 
     pub fn int_expr(val: i64) -> quote::Tokens {
         // Don't use quote! { #val } because that adds the type suffix.
-        let mut tokens = quote! {};
-        tokens.append(val.to_string());
-        tokens
+        let val = proc_macro2::Literal::i64_unsuffixed(val);
+        quote!(#val)
     }
 
     pub fn uint_expr(val: u64) -> quote::Tokens {
         // Don't use quote! { #val } because that adds the type suffix.
-        let mut tokens = quote! {};
-        tokens.append(val.to_string());
-        tokens
+        let val = proc_macro2::Literal::u64_unsuffixed(val);
+        quote!(#val)
     }
 
     pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens {
         let mut bytes: Vec<_> = bytes.iter().cloned().collect();
         bytes.push(0);
-        quote! {
-            #bytes
-        }
+        quote! { [ #(#bytes),* ] }
     }
 
     pub fn cstr_expr(mut string: String) -> quote::Tokens {
         string.push('\0');
-        let b = quote::ByteStr(&string);
+        let b = proc_macro2::Literal::byte_string(&string.as_bytes());
         quote! {
             #b
         }
     }
 
     pub fn float_expr(
         ctx: &BindgenContext,
         f: f64,
     ) -> Result<quote::Tokens, ()> {
         if f.is_finite() {
-            let mut string = f.to_string();
-
-            // So it gets properly recognised as a floating point constant.
-            if !string.contains('.') {
-                string.push('.');
-            }
+            let val = proc_macro2::Literal::f64_unsuffixed(f);
 
-            let mut tokens = quote! {};
-            tokens.append(string);
-            return Ok(tokens);
+            return Ok(quote!(#val));
         }
 
         let prefix = ctx.trait_prefix();
 
         if f.is_nan() {
             return Ok(quote! {
                 ::#prefix::f64::NAN
             });
diff --git a/third_party/rust/bindgen/src/codegen/impl_partialeq.rs b/third_party/rust/bindgen/src/codegen/impl_partialeq.rs
index 027838089718..a05c65e7ff69 100644
--- a/third_party/rust/bindgen/src/codegen/impl_partialeq.rs
+++ b/third_party/rust/bindgen/src/codegen/impl_partialeq.rs
@@ -1,31 +1,32 @@
 
 use ir::comp::{CompInfo, CompKind, Field, FieldMethods};
 use ir::context::BindgenContext;
 use ir::item::{IsOpaque, Item};
 use ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
 use quote;
+use proc_macro2;
 
 /// Generate a manual implementation of `PartialEq` trait for the
 /// specified compound type.
 pub fn gen_partialeq_impl(
     ctx: &BindgenContext,
     comp_info: &CompInfo,
     item: &Item,
     ty_for_impl: &quote::Tokens,
 ) -> Option<quote::Tokens> {
     let mut tokens = vec![];
 
     if item.is_opaque(ctx, &()) {
         tokens.push(quote! {
             &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
         });
     } else if comp_info.kind() == CompKind::Union {
-        assert!(!ctx.options().rust_features().untagged_union());
+        assert!(!ctx.options().rust_features().untagged_union);
         tokens.push(quote! {
             &self.bindgen_union_field[..] == &other.bindgen_union_field[..]
         });
     } else {
         for base in comp_info.base_members().iter() {
             if !base.requires_storage(ctx) {
                 continue;
             }
@@ -66,17 +67,17 @@ pub fn gen_partialeq_impl(
     Some(quote! {
         fn eq(&self, other: & #ty_for_impl) -> bool {
             #( #tokens )&&*
         }
     })
 }
 
 fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens {
-    fn quote_equals(name_ident: quote::Ident) -> quote::Tokens {
+    fn quote_equals(name_ident: proc_macro2::Term) -> quote::Tokens {
         quote! { self.#name_ident == other.#name_ident }
     }
 
     let name_ident = ctx.rust_ident(name);
     let ty = ty_item.expect_type();
 
     match *ty.kind() {
         TypeKind::Void |
diff --git a/third_party/rust/bindgen/src/codegen/mod.rs b/third_party/rust/bindgen/src/codegen/mod.rs
index b21c0dc447bc..026e9475d071 100644
--- a/third_party/rust/bindgen/src/codegen/mod.rs
+++ b/third_party/rust/bindgen/src/codegen/mod.rs
@@ -33,24 +33,25 @@ use ir::item_kind::ItemKind;
 use ir::layout::Layout;
 use ir::module::Module;
 use ir::objc::{ObjCInterface, ObjCMethod};
 use ir::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters};
 use ir::ty::{Type, TypeKind};
 use ir::var::Var;
 
 use quote;
+use proc_macro2::{self, Term, Span};
 
+use std;
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::collections::{HashSet, VecDeque};
 use std::collections::hash_map::{Entry, HashMap};
 use std::fmt::Write;
 use std::iter;
-use std::mem;
 use std::ops;
 
 // Name of type defined in constified enum module
 pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type";
 
 fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec<quote::Tokens> {
     let mut path = vec![quote! { self }];
 
@@ -70,17 +71,17 @@ fn root_import(ctx: &BindgenContext, module: &Item) -> quote::Tokens {
     let mut path = top_level_path(ctx, module);
 
     let root = ctx.root_module().canonical_name(ctx);
     let root_ident = ctx.rust_ident(&root);
     path.push(quote! { #root_ident });
 
 
     let mut tokens = quote! {};
-    tokens.append_separated(path, "::");
+    tokens.append_separated(path, Term::new("::", Span::call_site()));
 
     quote! {
         #[allow(unused_imports)]
         use #tokens ;
     }
 }
 
 struct CodegenResult<'a> {
@@ -294,27 +295,22 @@ impl AppendImplicitTemplateParams for quote::Tokens {
             TypeKind::Enum(..) |
             TypeKind::BlockPointer |
             TypeKind::ObjCId |
             TypeKind::ObjCSel |
             TypeKind::TemplateInstantiation(..) => return,
             _ => {},
         }
 
-        if let Some(params) = item.used_template_params(ctx) {
-            if params.is_empty() {
-                return;
-            }
-
-            let params = params.into_iter().map(|p| {
-                p.try_to_rust_ty(ctx, &())
-                    .expect("template params cannot fail to be a rust type")
-            });
-
-            self.append(quote! {
+        let params: Vec<_> = item.used_template_params(ctx).iter().map(|p| {
+            p.try_to_rust_ty(ctx, &())
+                .expect("template params cannot fail to be a rust type")
+        }).collect();
+        if !params.is_empty() {
+            self.append_all(quote! {
                 < #( #params ),* >
             });
         }
     }
 }
 
 trait CodeGenerator {
     /// Extra information from the caller.
@@ -399,17 +395,17 @@ impl CodeGenerator for Module {
 
             if item.id() == ctx.root_module() {
                 if result.saw_bindgen_union {
                     utils::prepend_union_types(ctx, &mut *result);
                 }
                 if result.saw_incomplete_array {
                     utils::prepend_incomplete_array_types(ctx, &mut *result);
                 }
-                if ctx.need_bindegen_complex_type() {
+                if ctx.need_bindgen_complex_type() {
                     utils::prepend_complex_type(&mut *result);
                 }
                 if result.saw_objc {
                     utils::prepend_objc_header(ctx, &mut *result);
                 }
                 if result.saw_bitfield_unit {
                     utils::prepend_bitfield_unit_type(&mut *result);
                 }
@@ -422,35 +418,46 @@ impl CodeGenerator for Module {
         {
             codegen_self(result, &mut false);
             return;
         }
 
         let mut found_any = false;
         let inner_items = result.inner(|result| {
             result.push(root_import(ctx, item));
+
+            let path = item.namespace_aware_canonical_path(ctx).join("::");
+            if let Some(raw_lines) = ctx.options().module_lines.get(&path) {
+                for raw_line in raw_lines {
+                    found_any = true;
+                    // FIXME(emilio): The use of `Term` is an abuse, but we abuse it
+                    // in a bunch more places.
+                    let line = Term::new(raw_line, Span::call_site());
+                    result.push(quote! { #line });
+                }
+            }
+
             codegen_self(result, &mut found_any);
         });
 
         // Don't bother creating an empty module.
         if !found_any {
             return;
         }
 
         let name = item.canonical_name(ctx);
-
-        result.push(if name == "root" {
+        let ident = ctx.rust_ident(name);
+        result.push(if item.id() == ctx.root_module() {
             quote! {
                 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
-                pub mod root {
+                pub mod #ident {
                     #( #inner_items )*
                 }
             }
         } else {
-            let ident = ctx.rust_ident(name);
             quote! {
                 pub mod #ident {
                     #( #inner_items )*
                 }
             }
         });
     }
 }
@@ -474,21 +481,18 @@ impl CodeGenerator for Var {
         }
         result.saw_var(&canonical_name);
 
         let canonical_ident = ctx.rust_ident(&canonical_name);
 
         // We can't generate bindings to static variables of templates. The
         // number of actual variables for a single declaration are open ended
         // and we don't know what instantiations do or don't exist.
-        let type_params = item.all_template_params(ctx);
-        if let Some(params) = type_params {
-            if !params.is_empty() {
-                return;
-            }
+        if !item.all_template_params(ctx).is_empty() {
+            return;
         }
 
         let ty = self.ty().to_rust_ty_or_opaque(ctx, &());
 
         if let Some(val) = self.val() {
             match *val {
                 VarType::Bool(val) => {
                     result.push(quote! {
@@ -631,25 +635,20 @@ impl CodeGenerator for Type {
 
                 // If this is a known named type, disallow generating anything
                 // for it too.
                 let spelling = self.name().expect("Unnamed alias?");
                 if utils::type_from_named(ctx, spelling).is_some() {
                     return;
                 }
 
-                let mut outer_params = item.used_template_params(ctx)
-                    .and_then(|ps| if ps.is_empty() {
-                        None
-                    } else {
-                        Some(ps)
-                    });
+                let mut outer_params = item.used_template_params(ctx);
 
                 let inner_rust_type = if item.is_opaque(ctx, &()) {
-                    outer_params = None;
+                    outer_params = vec![];
                     self.to_opaque(ctx, item)
                 } else {
                     // Its possible that we have better layout information than
                     // the inner type does, so fall back to an opaque blob based
                     // on our layout if converting the inner item fails.
                     let mut inner_ty = inner_item
                         .try_to_rust_ty_or_opaque(ctx, &())
                         .unwrap_or_else(|_| self.to_opaque(ctx, item));
@@ -686,68 +685,66 @@ impl CodeGenerator for Type {
                 let mut tokens = if let Some(comment) = item.comment(ctx) {
                     attributes::doc(comment)
                 } else {
                     quote! {}
                 };
 
                 // We prefer using `pub use` over `pub type` because of:
                 // https://github.com/rust-lang/rust/issues/26264
-                if inner_rust_type.as_str()
+                if inner_rust_type.to_string()
                     .chars()
                     .all(|c| match c {
                         // These are the only characters allowed in simple
                         // paths, eg `good::dogs::Bront`.
                         'A'...'Z' | 'a'...'z' | '0'...'9' | ':' | '_' | ' ' => true,
                         _ => false,
                     }) &&
-                    outer_params.is_none() &&
+                    outer_params.is_empty() &&
                     inner_item.expect_type().canonical_type(ctx).is_enum()
                 {
-                    tokens.append(quote! {
+                    tokens.append_all(quote! {
                         pub use
                     });
                     let path = top_level_path(ctx, item);
-                    tokens.append_separated(path, "::");
-                    tokens.append(quote! {
+                    tokens.append_separated(path, Term::new("::", Span::call_site()));
+                    tokens.append_all(quote! {
                         :: #inner_rust_type  as #rust_name ;
                     });
                     result.push(tokens);
                     return;
                 }
 
-                tokens.append(quote! {
+                tokens.append_all(quote! {
                     pub type #rust_name
                 });
 
-                if let Some(params) = outer_params {
-                    let params: Vec<_> = params.into_iter()
-                        .filter_map(|p| p.as_template_param(ctx, &()))
-                        .collect();
-                    if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) {
-                        warn!(
-                            "Item contained invalid template \
-                             parameter: {:?}",
-                            item
-                        );
-                        return;
-                    }
-
-                    let params = params.iter()
-                        .map(|p| {
-                            p.try_to_rust_ty(ctx, &())
-                                .expect("type parameters can always convert to rust ty OK")
-                        });
+                let params: Vec<_> = outer_params.into_iter()
+                    .filter_map(|p| p.as_template_param(ctx, &()))
+                    .collect();
+                if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) {
+                    warn!(
+                        "Item contained invalid template \
+                         parameter: {:?}",
+                        item
+                    );
+                    return;
+                }
+                let params: Vec<_> = params.iter().map(|p| {
+                    p.try_to_rust_ty(ctx, &())
+                        .expect("type parameters can always convert to rust ty OK")
+                }).collect();
 
-                    tokens.append(quote! {
+                if !params.is_empty() {
+                    tokens.append_all(quote! {
                         < #( #params ),* >
                     });
                 }
 
-                tokens.append(quote! {
+                tokens.append_all(quote! {
                     = #inner_rust_type ;
                 });
 
                 result.push(tokens);
             }
             TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
             TypeKind::ObjCId | TypeKind::ObjCSel => {
                 result.saw_objc();
@@ -1054,21 +1051,21 @@ impl<'a> FieldCodegen<'a> for FieldData {
         let is_private = self.annotations().private_fields().unwrap_or(
             fields_should_be_private,
         );
 
         let accessor_kind =
             self.annotations().accessor_kind().unwrap_or(accessor_kind);
 
         if is_private {
-            field.append(quote! {
+            field.append_all(quote! {
                 #field_ident : #ty ,
             });
         } else {
-            field.append(quote! {
+            field.append_all(quote! {
                 pub #field_ident : #ty ,
             });
         }
 
         fields.extend(Some(field));
 
         // TODO: Factor the following code out, please!
         if accessor_kind == FieldAccessorKind::None {
@@ -1118,17 +1115,17 @@ impl<'a> FieldCodegen<'a> for FieldData {
             }
         }));
     }
 }
 
 impl BitfieldUnit {
     /// Get the constructor name for this bitfield unit.
     fn ctor_name(&self) -> quote::Tokens {
-        let ctor_name = quote::Ident::new(format!("new_bitfield_{}", self.nth()));
+        let ctor_name = Term::new(&format!("new_bitfield_{}", self.nth()), Span::call_site());
         quote! {
             #ctor_name
         }
     }
 }
 
 impl Bitfield {
     /// Extend an under construction bitfield unit constructor with this
@@ -1149,17 +1146,17 @@ impl Bitfield {
             "Bitfield without layout? Gah!",
         );
         let bitfield_int_ty = helpers::blob(bitfield_ty_layout);
 
         let offset = self.offset_into_unit();
         let width = self.width() as u8;
         let prefix = ctx.trait_prefix();
 
-        ctor_impl.append(quote! {
+        ctor_impl.append_all(quote! {
             __bindgen_bitfield_unit.set(
                 #offset,
                 #width,
                 {
                     let #param_name: #bitfield_int_ty = unsafe {
                         ::#prefix::mem::transmute(#param_name)
                     };
                     #param_name as u64
@@ -1317,17 +1314,17 @@ impl<'a> FieldCodegen<'a> for Bitfield {
         (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool),
     ) where
         F: Extend<quote::Tokens>,
         M: Extend<quote::Tokens>,
     {
         let prefix = ctx.trait_prefix();
         let getter_name = bitfield_getter_name(ctx, self);
         let setter_name = bitfield_setter_name(ctx, self);
-        let unit_field_ident = quote::Ident::new(unit_field_name);
+        let unit_field_ident = Term::new(unit_field_name, Span::call_site());
 
         let bitfield_ty_item = ctx.resolve_item(self.ty());
         let bitfield_ty = bitfield_ty_item.expect_type();
 
         let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
             "Bitfield without layout? Gah!",
         );
         let bitfield_int_ty = match helpers::integer_type(bitfield_ty_layout) {
@@ -1413,18 +1410,16 @@ impl CodeGenerator for CompInfo {
         debug_assert!(item.is_enabled_for_codegen(ctx));
 
         // Don't output classes with template parameters that aren't types, and
         // also don't output template specializations, neither total or partial.
         if self.has_non_type_template_params() {
             return;
         }
 
-        let used_template_params = item.used_template_params(ctx);
-
         let ty = item.expect_type();
         let layout = ty.layout(ctx);
         let mut packed = self.is_packed(ctx, &layout);
 
         let canonical_name = item.canonical_name(ctx);
         let canonical_ident = ctx.rust_ident(&canonical_name);
 
         // Generate the vtable from the method list if appropriate.
@@ -1522,23 +1517,26 @@ impl CodeGenerator for CompInfo {
                 struct_layout.saw_union(layout);
 
                 quote! {
                     pub bindgen_union_field: #ty ,
                 }
             });
         }
 
+        let mut explicit_align = None;
         if is_opaque {
             // Opaque item should not have generated methods, fields.
             debug_assert!(fields.is_empty());
             debug_assert!(methods.is_empty());
 
             match layout {
                 Some(l) => {
+                    explicit_align = Some(l.align);
+
                     let ty = helpers::blob(l);
                     fields.push(quote! {
                         pub _bindgen_opaque_blob: #ty ,
                     });
                 }
                 None => {
                     warn!("Opaque type without layout! Expect dragons!");
                 }
@@ -1550,16 +1548,17 @@ impl CodeGenerator for CompInfo {
                 fields.push(padding_field);
             }
 
             if let Some(layout) = layout {
                 if struct_layout.requires_explicit_align(layout) {
                     if layout.align == 1 {
                         packed = true;
                     } else {
+                        explicit_align = Some(layout.align);
                         let ty = helpers::blob(Layout::new(0, layout.align));
                         fields.push(quote! {
                             pub __bindgen_align: #ty ,
                         });
                     }
                 }
             }
         }
@@ -1592,31 +1591,29 @@ impl CodeGenerator for CompInfo {
                 fields.push(quote! {
                     pub _address: #ty,
                 });
             }
         }
 
         let mut generic_param_names = vec![];
 
-        if let Some(ref params) = used_template_params {
-            for (idx, ty) in params.iter().enumerate() {
-                let param = ctx.resolve_type(*ty);
-                let name = param.name().unwrap();
-                let ident = ctx.rust_ident(name);
-                generic_param_names.push(ident.clone());
+        for (idx, ty) in item.used_template_params(ctx).iter().enumerate() {
+            let param = ctx.resolve_type(*ty);
+            let name = param.name().unwrap();
+            let ident = ctx.rust_ident(name);
+            generic_param_names.push(ident.clone());
 
-                let prefix = ctx.trait_prefix();
-                let field_name = ctx.rust_ident(format!("_phantom_{}", idx));
-                fields.push(quote! {
-                    pub #field_name : ::#prefix::marker::PhantomData<
-                        ::#prefix::cell::UnsafeCell<#ident>
-                    > ,
-                });
-            }
+            let prefix = ctx.trait_prefix();
+            let field_name = ctx.rust_ident(format!("_phantom_{}", idx));
+            fields.push(quote! {
+                pub #field_name : ::#prefix::marker::PhantomData<
+                    ::#prefix::cell::UnsafeCell<#ident>
+                > ,
+            });
         }
 
         let generics = if !generic_param_names.is_empty() {
             let generic_param_names = generic_param_names.clone();
             quote! {
                 < #( #generic_param_names ),* >
             }
         } else {
@@ -1632,36 +1629,50 @@ impl CodeGenerator for CompInfo {
             attributes.push(attributes::doc(comment));
         }
         if packed && !is_opaque {
             attributes.push(attributes::repr_list(&["C", "packed"]));
         } else {
             attributes.push(attributes::repr("C"));
         }
 
+        if ctx.options().rust_features().repr_align {
+            if let Some(explicit) = explicit_align {
+                // Ensure that the struct has the correct alignment even in
+                // presence of alignas.
+                let explicit = helpers::ast_ty::int_expr(explicit as i64);
+                attributes.push(quote! {
+                    #[repr(align(#explicit))]
+                });
+            }
+        }
+
+
         let mut derives = vec![];
         if item.can_derive_debug(ctx) {
             derives.push("Debug");
         } else {
             needs_debug_impl = ctx.options().derive_debug &&
                 ctx.options().impl_debug
         }
 
         if item.can_derive_default(ctx) {
             derives.push("Default");
         } else {
             needs_default_impl =
                 ctx.options().derive_default && !self.is_forward_declaration();
         }
 
+        let all_template_params = item.all_template_params(ctx);
+
         if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
             derives.push("Copy");
 
-            if ctx.options().rust_features().builtin_clone_impls() ||
-                used_template_params.is_some()
+            if ctx.options().rust_features().builtin_clone_impls ||
+                !all_template_params.is_empty()
             {
                 // FIXME: This requires extra logic if you have a big array in a
                 // templated struct. The reason for this is that the magic:
                 //     fn clone(&self) -> Self { *self }
                 // doesn't work for templates.
                 //
                 // It's not hard to fix though.
                 derives.push("Clone");
@@ -1706,17 +1717,17 @@ impl CodeGenerator for CompInfo {
             }
         } else {
             quote! {
                 #( #attributes )*
                 pub struct #canonical_ident
             }
         };
 
-        tokens.append(quote! {
+        tokens.append_all(quote! {
             #generics {
                 #( #fields )*
             }
         });
         result.push(tokens);
 
         // Generate the inner types and all that stuff.
         //
@@ -1729,45 +1740,46 @@ impl CodeGenerator for CompInfo {
         }
 
         // NOTE: Some unexposed attributes (like alignment attributes) may
         // affect layout, so we're bad and pray to the gods for avoid sending
         // all the tests to shit when parsing things like max_align_t.
         if self.found_unknown_attr() {
             warn!(
                 "Type {} has an unkown attribute that may affect layout",
-                canonical_ident
+                canonical_ident.as_str()
             );
         }
 
-        if used_template_params.is_none() {
+        if all_template_params.is_empty() {
             if !is_opaque {
                 for var in self.inner_vars() {
                     ctx.resolve_item(*var).codegen(ctx, result, &());
                 }
             }
 
             if ctx.options().layout_tests && !self.is_forward_declaration() {
                 if let Some(layout) = layout {
                     let fn_name =
-                        format!("bindgen_test_layout_{}", canonical_ident);
+                        format!("bindgen_test_layout_{}", canonical_ident.as_str());
                     let fn_name = ctx.rust_ident_raw(fn_name);
                     let prefix = ctx.trait_prefix();
                     let size_of_expr = quote! {
                         ::#prefix::mem::size_of::<#canonical_ident>()
                     };
                     let align_of_expr = quote! {
                         ::#prefix::mem::align_of::<#canonical_ident>()
                     };
                     let size = layout.size;
                     let align = layout.align;
 
                     let check_struct_align =
-                        if align > mem::size_of::<*mut ()>() {
-                            // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready
+                        if align > ctx.target_pointer_size() &&
+                            !ctx.options().rust_features().repr_align
+                        {
                             None
                         } else {
                             Some(quote! {
                                 assert_eq!(#align_of_expr,
                                        #align,
                                        concat!("Alignment of ", stringify!(#canonical_ident)));
 
                             })
@@ -1991,17 +2003,17 @@ impl MethodCodegen for Method {
             _ => function.name().to_owned(),
         };
 
         let signature = match *signature_item.expect_type().kind() {
             TypeKind::Function(ref sig) => sig,
             _ => panic!("How in the world?"),
         };
 
-        if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
+        if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi) {
             return;
         }
 
         // Do not generate variadic methods, since rust does not allow
         // implementing them, and we don't do a good job at it anyway.
         if signature.is_variadic() {
             return;
         }
@@ -2087,55 +2099,84 @@ impl MethodCodegen for Method {
             pub unsafe fn #name ( #( #args ),* ) #ret {
                 #block
             }
         });
     }
 }
 
 /// A helper type that represents different enum variations.
-#[derive(Copy, Clone)]
-enum EnumVariation {
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum EnumVariation {
+    /// The code for this enum will use a Rust enum
     Rust,
+    /// The code for this enum will use a bitfield
     Bitfield,
+    /// The code for this enum will use consts
     Consts,
+    /// The code for this enum will use a module containing consts
     ModuleConsts
 }
 
 impl EnumVariation {
     fn is_rust(&self) -> bool {
         match *self {
             EnumVariation::Rust => true,
             _ => false
         }
     }
 
     fn is_bitfield(&self) -> bool {
         match *self {
-            EnumVariation::Bitfield => true,
+            EnumVariation::Bitfield {..} => true,
             _ => false
         }
     }
 
     /// Both the `Const` and `ModuleConsts` variants will cause this to return
     /// true.
     fn is_const(&self) -> bool {
         match *self {
             EnumVariation::Consts | EnumVariation::ModuleConsts => true,
             _ => false
         }
     }
 }
 
+impl Default for EnumVariation {
+    fn default() -> EnumVariation {
+        EnumVariation::Consts
+    }
+}
+
+impl std::str::FromStr for EnumVariation {
+    type Err = std::io::Error;
+
+    /// Create a `EnumVariation` from a string.
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "rust" => Ok(EnumVariation::Rust),
+            "bitfield" => Ok(EnumVariation::Bitfield),
+            "consts" => Ok(EnumVariation::Consts),
+            "moduleconsts" => Ok(EnumVariation::ModuleConsts),
+            _ => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
+                                         concat!("Got an invalid EnumVariation. Accepted values ",
+                                                 "are 'rust', 'bitfield', 'consts', and ",
+                                                 "'moduleconsts'."))),
+        }
+    }
+}
+
+
 /// A helper type to construct different enum variations.
 enum EnumBuilder<'a> {
     Rust {
         codegen_depth: usize,
         attrs: Vec<quote::Tokens>,
-        ident: quote::Ident,
+        ident: Term,
         tokens: quote::Tokens,
         emitted_any_variants: bool,
     },
     Bitfield {
         codegen_depth: usize,
         canonical_name: &'a str,
         tokens: quote::Tokens,
     },
@@ -2165,32 +2206,32 @@ impl<'a> EnumBuilder<'a> {
     /// the representation, and which variation it should be generated as.
     fn new(
         name: &'a str,
         attrs: Vec<quote::Tokens>,
         repr: quote::Tokens,
         enum_variation: EnumVariation,
         enum_codegen_depth: usize,
     ) -> Self {
-        let ident = quote::Ident::new(name);
+        let ident = Term::new(name, Span::call_site());
 
         match enum_variation {
             EnumVariation::Bitfield => {
                 EnumBuilder::Bitfield {
                     codegen_depth: enum_codegen_depth,
                     canonical_name: name,
                     tokens: quote! {
                         #( #attrs )*
                         pub struct #ident (pub #repr);
                     },
                 }
             }
 
             EnumVariation::Rust => {
-                let tokens = quote!{};
+                let tokens = quote!();
                 EnumBuilder::Rust {
                     codegen_depth: enum_codegen_depth + 1,
                     attrs,
                     ident,
                     tokens,
                     emitted_any_variants: false,
                 }
             }
@@ -2203,17 +2244,17 @@ impl<'a> EnumBuilder<'a> {
                             pub type #ident = #repr;
                         }
                     ],
                     codegen_depth: enum_codegen_depth,
                 }
             }
 
             EnumVariation::ModuleConsts => {
-                let ident = quote::Ident::new(CONSTIFIED_ENUM_MODULE_REPR_NAME);
+                let ident = Term::new(CONSTIFIED_ENUM_MODULE_REPR_NAME, Span::call_site());
                 let type_definition = quote! {
                     #( #attrs )*
                     pub type #ident = #repr;
                 };
 
                 EnumBuilder::ModuleConsts {
                     codegen_depth: enum_codegen_depth + 1,
                     module_name: name,
@@ -2223,19 +2264,20 @@ impl<'a> EnumBuilder<'a> {
         }
     }
 
     /// Add a variant to this enum.
     fn with_variant<'b>(
         self,
         ctx: &BindgenContext,
         variant: &EnumVariant,
-        mangling_prefix: Option<&String>,
+        mangling_prefix: Option<&str>,
         rust_ty: quote::Tokens,
         result: &mut CodegenResult<'b>,
+        is_ty_named: bool,
     ) -> Self {
         let variant_name = ctx.rust_mangle(variant.name());
         let expr = match variant.val() {
             EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
             EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
         };
 
         let mut doc = quote! {};
@@ -2257,29 +2299,38 @@ impl<'a> EnumBuilder<'a> {
                         #tokens
                         #doc
                         #name = #expr,
                     },
                     emitted_any_variants: true,
                 }
             }
 
-            EnumBuilder::Bitfield { .. } => {
-                let constant_name = match mangling_prefix {
-                    Some(prefix) => {
-                        Cow::Owned(format!("{}_{}", prefix, variant_name))
-                    }
-                    None => variant_name,
-                };
-
-                let ident = ctx.rust_ident(constant_name);
-                result.push(quote! {
-                    #doc
-                    pub const #ident : #rust_ty = #rust_ty ( #expr );
-                });
+            EnumBuilder::Bitfield { canonical_name, .. } => {
+                if ctx.options().rust_features().associated_const && is_ty_named {
+                    let enum_ident = ctx.rust_ident(canonical_name);
+                    let variant_ident = ctx.rust_ident(variant_name);
+                    result.push(quote! {
+                        impl #enum_ident {
+                            #doc
+                            pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
+                        }
+                    });
+                } else {
+                    let ident = ctx.rust_ident(match mangling_prefix {
+                        Some(prefix) => {
+                            Cow::Owned(format!("{}_{}", prefix, variant_name))
+                        }
+                        None => variant_name,
+                    });
+                    result.push(quote! {
+                        #doc
+                        pub const #ident : #rust_ty = #rust_ty ( #expr );
+                    });
+                }
 
                 self
             }
 
             EnumBuilder::Consts {
                 ..
             } => {
                 let constant_name = match mangling_prefix {
@@ -2456,25 +2507,28 @@ impl CodeGenerator for Enum {
             (true, 8) => "i64",
             (false, 8) => "u64",
             _ => {
                 warn!("invalid enum decl: signed: {}, size: {}", signed, size);
                 "i32"
             }
         };
 
-        let variation = if self.is_bitfield(ctx, item) {
+        // ModuleConsts has higher precedence before Rust in order to avoid problems with
+        // overlapping match patterns
+        let variation = if self.is_constified_enum_module(ctx, item) {
+            EnumVariation::ModuleConsts
+        } else if self.is_bitfield(ctx, item) {
             EnumVariation::Bitfield
         } else if self.is_rustified_enum(ctx, item) {
             EnumVariation::Rust
-        } else if self.is_constified_enum_module(ctx, item) {
-            EnumVariation::ModuleConsts
-        } else {
-            // We generate consts by default
+        } else if self.is_constified_enum(ctx, item) {
             EnumVariation::Consts
+        } else {
+            ctx.options().default_enum_style
         };
 
         let mut attrs = vec![];
 
         // TODO(emilio): Delegate this to the builders?
         if variation.is_rust() {
             attrs.push(attributes::repr(repr_name));
         } else if variation.is_bitfield() {
@@ -2490,28 +2544,28 @@ impl CodeGenerator for Enum {
                 &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"],
             ));
         }
 
         fn add_constant<'a>(
             ctx: &BindgenContext,
             enum_: &Type,
             // Only to avoid recomputing every time.
-            enum_canonical_name: &quote::Ident,
+            enum_canonical_name: &Term,
             // May be the same as "variant" if it's because the
             // enum is unnamed and we still haven't seen the
             // value.
             variant_name: &str,
-            referenced_name: &quote::Ident,
+            referenced_name: &Term,
             enum_rust_ty: quote::Tokens,
             result: &mut CodegenResult<'a>,
         ) {
             let constant_name = if enum_.name().is_some() {
                 if ctx.options().prepend_enum_name {
-                    format!("{}_{}", enum_canonical_name, variant_name)
+                    format!("{}_{}", enum_canonical_name.as_str(), variant_name)
                 } else {
                     variant_name.into()
                 }
             } else {
                 variant_name.into()
             };
             let constant_name = ctx.rust_ident(constant_name);
 
@@ -2530,32 +2584,32 @@ impl CodeGenerator for Enum {
             &name,
             attrs,
             repr,
             variation,
             item.codegen_depth(ctx),
         );
 
         // A map where we keep a value -> variant relation.
-        let mut seen_values = HashMap::<_, quote::Ident>::new();
+        let mut seen_values = HashMap::<_, Term>::new();
         let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
         let is_toplevel = item.is_toplevel(ctx);
 
         // Used to mangle the constants we generate in the unnamed-enum case.
         let parent_canonical_name = if is_toplevel {
             None
         } else {
             Some(item.parent_id().canonical_name(ctx))
         };
 
         let constant_mangling_prefix = if ctx.options().prepend_enum_name {
             if enum_ty.name().is_none() {
-                parent_canonical_name.as_ref().map(|n| &*n)
+                parent_canonical_name.as_ref().map(|n| &**n)
             } else {
-                Some(&name)
+                Some(&*name)
             }
         } else {
             None
         };
 
         // NB: We defer the creation of constified variants, in case we find
         // another variant with the same value (which is the common thing to
         // do).
@@ -2602,63 +2656,66 @@ impl CodeGenerator for Enum {
                         );
                     } else {
                         builder = builder.with_variant(
                             ctx,
                             variant,
                             constant_mangling_prefix,
                             enum_rust_ty.clone(),
                             result,
+                            enum_ty.name().is_some(),
                         );
                     }
                 }
                 Entry::Vacant(entry) => {
                     builder = builder.with_variant(
                         ctx,
                         variant,
                         constant_mangling_prefix,
                         enum_rust_ty.clone(),
                         result,
+                        enum_ty.name().is_some(),
                     );
 
                     let variant_name = ctx.rust_ident(variant.name());
 
                     // If it's an unnamed enum, or constification is enforced,
                     // we also generate a constant so it can be properly
                     // accessed.
                     if (variation.is_rust() && enum_ty.name().is_none()) ||
                         variant.force_constification()
                     {
                         let mangled_name = if is_toplevel {
                             variant_name.clone()
                         } else {
                             let parent_name =
                                 parent_canonical_name.as_ref().unwrap();
 
-                            quote::Ident::new(
-                                format!(
+                            Term::new(
+                                &format!(
                                     "{}_{}",
                                     parent_name,
-                                    variant_name
-                                )
+                                    variant_name.as_str()
+                                ),
+                                Span::call_site()
                             )
                         };
 
                         add_constant(
                             ctx,
                             enum_ty,
                             &ident,
-                            mangled_name.as_ref(),
+                            mangled_name.as_str(),
                             &variant_name,
                             enum_rust_ty.clone(),
                             result,
                         );
                     }
 
-                    entry.insert(quote::Ident::new(variant_name));
+                    entry.insert(variant_name);
                 }
             }
         }
 
         let item = builder.build(ctx, enum_rust_ty, result);
         result.push(item);
     }
 }
@@ -2697,19 +2754,18 @@ trait TryToOpaque {
 /// last resort, because C++ does not permit zero-sized types. See the note in
 /// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits
 /// and when each is appropriate.
 ///
 /// Don't implement this directly. Instead implement `TryToOpaque`, and then
 /// leverage the blanket impl for this trait.
 trait ToOpaque: TryToOpaque {
     fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
-        self.try_get_layout(ctx, extra).unwrap_or_else(
-            |_| Layout::for_size(1),
-        )
+        self.try_get_layout(ctx, extra)
+            .unwrap_or_else(|_| Layout::for_size(ctx, 1))
     }
 
     fn to_opaque(
         &self,
         ctx: &BindgenContext,
         extra: &Self::Extra,
     ) -> quote::Tokens {
         let layout = self.get_layout(ctx, extra);
@@ -2946,17 +3002,17 @@ impl TryToRustTy for Type {
                         Ok(quote! { [u64; 2] })
                     }
                 }
             }
             TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)),
             TypeKind::Complex(fk) => {
                 let float_path = float_kind_rust_type(ctx, fk);
 
-                ctx.generated_bindegen_complex();
+                ctx.generated_bindgen_complex();
                 Ok(if ctx.options().enable_cxx_namespaces {
                     quote! {
                         root::__BindgenComplex<#float_path>
                     }
                 } else {
                     quote! {
                         __BindgenComplex<#float_path>
                     }
@@ -2976,29 +3032,27 @@ impl TryToRustTy for Type {
             }
             TypeKind::Array(item, len) => {
                 let ty = item.try_to_rust_ty(ctx, &())?;
                 Ok(quote! {
                     [ #ty ; #len ]
                 })
             }
             TypeKind::Enum(..) => {
-                let mut tokens = quote! {};
                 let path = item.namespace_aware_canonical_path(ctx);
-                tokens.append_separated(path.into_iter().map(quote::Ident::new), "::");
-                Ok(tokens)
+                let path = Term::new(&path.join("::"), Span::call_site());
+                Ok(quote!(#path))
             }
             TypeKind::TemplateInstantiation(ref inst) => {
                 inst.try_to_rust_ty(ctx, item)
             }
             TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
             TypeKind::TemplateAlias(..) |
             TypeKind::Alias(..) => {
                 let template_params = item.used_template_params(ctx)
-                    .unwrap_or(vec![])
                     .into_iter()
                     .filter(|param| param.is_template_param(ctx, &()))
                     .collect::<Vec<_>>();
 
                 let spelling = self.name().expect("Unnamed alias?");
                 if item.is_opaque(ctx, &()) && !template_params.is_empty() {
                     self.try_to_opaque(ctx, item)
                 } else if let Some(ty) = utils::type_from_named(
@@ -3007,36 +3061,36 @@ impl TryToRustTy for Type {
                 )
                 {
                     Ok(ty)
                 } else {
                     utils::build_path(item, ctx)
                 }
             }
             TypeKind::Comp(ref info) => {
-                let template_params = item.used_template_params(ctx);
+                let template_params = item.all_template_params(ctx);
                 if info.has_non_type_template_params() ||
-                    (item.is_opaque(ctx, &()) && template_params.is_some())
+                    (item.is_opaque(ctx, &()) && !template_params.is_empty())
                 {
                     return self.try_to_opaque(ctx, item);
                 }
 
                 utils::build_path(item, ctx)
             }
             TypeKind::Opaque => self.try_to_opaque(ctx, item),
             TypeKind::BlockPointer => {
                 let void = raw_type(ctx, "c_void");
                 Ok(void.to_ptr(
                     /* is_const = */
                     false
                 ))
             }
             TypeKind::Pointer(inner) |
             TypeKind::Reference(inner) => {
-                let is_const = self.is_const() || ctx.resolve_type(inner).is_const();
+                let is_const = ctx.resolve_type(inner).is_const();
 
                 let inner = inner.into_resolver().through_type_refs().resolve(ctx);
                 let inner_ty = inner.expect_type();
 
                 // Regardless if we can properly represent the inner type, we
                 // should always generate a proper pointer here, so use
                 // infallible conversion of the inner type.
                 let mut ty = inner.to_rust_ty_or_opaque(ctx, &());
@@ -3101,30 +3155,28 @@ impl TryToRustTy for TemplateInstantiation {
 
         let def = self.template_definition()
             .into_resolver()
             .through_type_refs()
             .resolve(ctx);
 
         let mut ty = quote! {};
         let def_path = def.namespace_aware_canonical_path(ctx);
-        ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), "::");
-
-        let def_params = match def.self_template_params(ctx) {
-            Some(params) => params,
-            None => {
-                // This can happen if we generated an opaque type for a partial
-                // template specialization, and we've hit an instantiation of
-                // that partial specialization.
-                extra_assert!(
-                    def.is_opaque(ctx, &())
-                );
-                return Err(error::Error::InstantiationOfOpaqueType);
-            }
-        };
+        ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), Term::new("::", Span::call_site()));
+
+        let def_params = def.self_template_params(ctx);
+        if def_params.is_empty() {
+            // This can happen if we generated an opaque type for a partial
+            // template specialization, and we've hit an instantiation of
+            // that partial specialization.
+            extra_assert!(
+                def.is_opaque(ctx, &())
+            );
+            return Err(error::Error::InstantiationOfOpaqueType);
+        }
 
         // TODO: If the definition type is a template class/struct
         // definition's member template definition, it could rely on
         // generic template parameters from its outer template
         // class/struct. When we emit bindings for it, it could require
         // *more* type arguments than we have here, and we will need to
         // reconstruct them somehow. We don't have any means of doing
         // that reconstruction at this time.
@@ -3162,17 +3214,17 @@ impl TryToRustTy for FunctionSig {
         _: &(),
     ) -> error::Result<quote::Tokens> {
         // TODO: we might want to consider ignoring the reference return value.
         let ret = utils::fnsig_return_ty(ctx, &self);
         let arguments = utils::fnsig_arguments(ctx, &self);
         let abi = self.abi();
 
         match abi {
-            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
+            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
                 warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
                 Ok(quote::Tokens::new())
             }
             _ => {
                 Ok(quote! {
                     unsafe extern #abi fn ( #( #arguments ),* ) #ret
                 })
             }
@@ -3207,21 +3259,18 @@ impl CodeGenerator for Function {
             }
             _ => {},
         }
 
         // Similar to static member variables in a class template, we can't
         // generate bindings to template functions, because the set of
         // instantiations is open ended and we have no way of knowing which
         // monomorphizations actually exist.
-        let type_params = item.all_template_params(ctx);
-        if let Some(params) = type_params {
-            if !params.is_empty() {
-                return;
-            }
+        if !item.all_template_params(ctx).is_empty() {
+            return;
         }
 
         let name = self.name();
         let mut canonical_name = item.canonical_name(ctx);
         let mangled_name = self.mangled_name();
 
         {
             let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
@@ -3259,17 +3308,17 @@ impl CodeGenerator for Function {
         // Handle overloaded functions by giving each overload its own unique
         // suffix.
         let times_seen = result.overload_number(&canonical_name);
         if times_seen > 0 {
             write!(&mut canonical_name, "{}", times_seen).unwrap();
         }
 
         let abi = match signature.abi() {
-            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
+            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
                 warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
                 return;
             }
             Abi::Unknown(unknown_abi) => {
                 panic!(
                     "Invalid or unknown abi {:?} for function {:?} ({:?})",
                     unknown_abi,
                     canonical_name,
@@ -3314,17 +3363,17 @@ fn objc_method_codegen(
     };
 
     let methods_and_args = method.format_method_call(&fn_args);
 
     let body = if method.is_class_method() {
         let class_name = class_name
             .expect("Generating a class method without class name?")
             .to_owned();
-        let expect_msg = format!("Couldn't find {}", class_name);
+        let expect_msg = proc_macro2::Literal::string(&format!("Couldn't find {}", class_name));
         quote! {
             msg_send!(objc::runtime::Class::get(#class_name).expect(#expect_msg), #methods_and_args)
         }
     } else {
         quote! {
             msg_send!(self, #methods_and_args)
         }
     };
@@ -3440,21 +3489,22 @@ pub(crate) fn codegen(context: BindgenContext) -> (Vec<quote::Tokens>, BindgenOp
 
 mod utils {
     use super::{ToRustTyOrOpaque, error};
     use ir::context::BindgenContext;
     use ir::function::FunctionSig;
     use ir::item::{Item, ItemCanonicalPath};
     use ir::ty::TypeKind;
     use quote;
+    use proc_macro2::{Term, Span};
     use std::mem;
 
     pub fn prepend_bitfield_unit_type(result: &mut Vec<quote::Tokens>) {
-        let mut bitfield_unit_type = quote! {};
-        bitfield_unit_type.append(include_str!("./bitfield_unit.rs"));
+        let bitfield_unit_type = Term::new(include_str!("./bitfield_unit.rs"), Span::call_site());
+        let bitfield_unit_type = quote!(#bitfield_unit_type);
 
         let items = vec![bitfield_unit_type];
         let old_items = mem::replace(result, items);
         result.extend(old_items);
     }
 
     pub fn prepend_objc_header(
         ctx: &BindgenContext,
@@ -3670,20 +3720,22 @@ mod utils {
         let old_items = mem::replace(result, items);
         result.extend(old_items.into_iter());
     }
 
     pub fn build_path(
         item: &Item,
         ctx: &BindgenContext,
     ) -> error::Result<quote::Tokens> {
-        let path = item.namespace_aware_canonical_path(ctx);
+        use proc_macro2::{Term, Span};
 
-        let mut tokens = quote! {};
-        tokens.append_separated(path.into_iter().map(quote::Ident::new), "::");
+        let path = item.namespace_aware_canonical_path(ctx);
+        let path = Term::new(&path.join("::"), Span::call_site());
+        let tokens = quote! {#path};
+        //tokens.append_separated(path, "::");
 
         Ok(tokens)
     }
 
     fn primitive_ty(ctx: &BindgenContext, name: &str) -> quote::Tokens {
         let ident = ctx.rust_ident_raw(name);
         quote! {
             #ident
diff --git a/third_party/rust/bindgen/src/codegen/struct_layout.rs b/third_party/rust/bindgen/src/codegen/struct_layout.rs
index 32b489650663..6de7e03069f2 100644
--- a/third_party/rust/bindgen/src/codegen/struct_layout.rs
+++ b/third_party/rust/bindgen/src/codegen/struct_layout.rs
@@ -2,18 +2,18 @@
 
 use super::helpers;
 
 use ir::comp::CompInfo;
 use ir::context::BindgenContext;
 use ir::layout::Layout;
 use ir::ty::{Type, TypeKind};
 use quote;
+use proc_macro2::{Term, Span};
 use std::cmp;
-use std::mem;
 
 /// Trace the layout of struct.
 #[derive(Debug)]
 pub struct StructLayoutTracker<'a> {
     name: &'a str,
     ctx: &'a BindgenContext,
     comp: &'a CompInfo,
     is_packed: bool,
@@ -96,17 +96,17 @@ impl<'a> StructLayoutTracker<'a> {
             max_field_align: 0,
             last_field_was_bitfield: false,
         }
     }
 
     pub fn saw_vtable(&mut self) {
         debug!("saw vtable for {}", self.name);
 
-        let ptr_size = mem::size_of::<*mut ()>();
+        let ptr_size = self.ctx.target_pointer_size();
         self.latest_offset += ptr_size;
         self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
         self.max_field_align = ptr_size;
     }
 
     pub fn saw_base(&mut self, base_ty: &Type) {
         debug!("saw base for {}", self.name);
         if let Some(layout) = base_ty.layout(self.ctx) {
@@ -150,38 +150,33 @@ impl<'a> StructLayoutTracker<'a> {
     /// Add a padding field if necessary for a given new field _before_ adding
     /// that field.
     pub fn pad_field(
         &mut self,
         field_name: &str,
         field_ty: &Type,
         field_offset: Option<usize>,
     ) -> Option<quote::Tokens> {
-        let mut field_layout = match field_ty.layout(self.ctx) {
-            Some(l) => l,
-            None => return None,
-        };
+        let mut field_layout = field_ty.layout(self.ctx)?;
 
         if let TypeKind::Array(inner, len) =
             *field_ty.canonical_type(self.ctx).kind()
         {
             // FIXME(emilio): As an _ultra_ hack, we correct the layout returned
             // by arrays of structs that have a bigger alignment than what we
             // can support.
             //
             // This means that the structs in the array are super-unsafe to
-            // access, since they won't be properly aligned, but *shrug*.
-            if let Some(layout) = self.ctx.resolve_type(inner).layout(
-                self.ctx,
-            )
-            {
-                if layout.align > mem::size_of::<*mut ()>() {
-                    field_layout.size = align_to(layout.size, layout.align) *
-                        len;
-                    field_layout.align = mem::size_of::<*mut ()>();
+            // access, since they won't be properly aligned, but there's not too
+            // much we can do about it.
+            if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) {
+                if layout.align > self.ctx.target_pointer_size() {
+                    field_layout.size =
+                        align_to(layout.size, layout.align) * len;
+                    field_layout.align = self.ctx.target_pointer_size();
                 }
             }
         }
 
         let will_merge_with_bitfield = self.align_to_latest_field(field_layout);
 
         let padding_layout = if self.is_packed {
             None
@@ -191,17 +186,17 @@ impl<'a> StructLayoutTracker<'a> {
                     offset / 8 - self.latest_offset
                 }
                 _ if will_merge_with_bitfield || field_layout.align == 0 => 0,
                 _ => self.padding_bytes(field_layout),
             };
 
             // Otherwise the padding is useless.
             let need_padding = padding_bytes >= field_layout.align ||
-                field_layout.align > mem::size_of::<*mut ()>();
+                field_layout.align > self.ctx.target_pointer_size();
 
             self.latest_offset += padding_bytes;
 
             debug!(
                 "Offset: <padding>: {} -> {}",
                 self.latest_offset - padding_bytes,
                 self.latest_offset
             );
@@ -213,17 +208,17 @@ impl<'a> StructLayoutTracker<'a> {
                 field_offset.unwrap_or(0) / 8,
                 padding_bytes,
                 field_layout
             );
 
             if need_padding && padding_bytes != 0 {
                 Some(Layout::new(
                     padding_bytes,
-                    cmp::min(field_layout.align, mem::size_of::<*mut ()>()),
+                    cmp::min(field_layout.align, self.ctx.target_pointer_size())
                 ))
             } else {
                 None
             }
         };
 
         self.latest_offset += field_layout.size;
         self.latest_field_layout = Some(field_layout);
@@ -265,53 +260,63 @@ impl<'a> StructLayoutTracker<'a> {
         // Note that if the last field we saw was a bitfield, we may need to pad
         // regardless, because bitfields don't respect alignment as strictly as
         // other fields.
         if padding_bytes > 0 &&
             (padding_bytes >= layout.align ||
                  (self.last_field_was_bitfield &&
                       padding_bytes >=
                           self.latest_field_layout.unwrap().align) ||
-                 layout.align > mem::size_of::<*mut ()>())
+                 layout.align > self.ctx.target_pointer_size())
         {
             let layout = if self.is_packed {
                 Layout::new(padding_bytes, 1)
             } else if self.last_field_was_bitfield ||
-                       layout.align > mem::size_of::<*mut ()>()
+                       layout.align > self.ctx.target_pointer_size()
             {
                 // We've already given up on alignment here.
-                Layout::for_size(padding_bytes)
+                Layout::for_size(self.ctx, padding_bytes)
             } else {
                 Layout::new(padding_bytes, layout.align)
             };
 
             debug!("pad bytes to struct {}, {:?}", self.name, layout);
 
             Some(self.padding_field(layout))
         } else {
             None
         }
     }
 
     pub fn requires_explicit_align(&self, layout: Layout) -> bool {
-        self.max_field_align < layout.align &&
-            layout.align <= mem::size_of::<*mut ()>()
+        if self.max_field_align >= layout.align {
+            return false;
+        }
+        // At this point we require explicit alignment, but we may not be able
+        // to generate the right bits, let's double check.
+        if self.ctx.options().rust_features().repr_align {
+            return true;
+        }
+
+        // We can only generate up-to a word of alignment unless we support
+        // repr(align).
+        layout.align <= self.ctx.target_pointer_size()
     }
 
     fn padding_bytes(&self, layout: Layout) -> usize {
         align_to(self.latest_offset, layout.align) - self.latest_offset
     }
 
     fn padding_field(&mut self, layout: Layout) -> quote::Tokens {
         let ty = helpers::blob(layout);
         let padding_count = self.padding_count;
 
         self.padding_count += 1;
 
-        let padding_field_name = quote::Ident::new(format!("__bindgen_padding_{}", padding_count));
+        let padding_field_name = Term::new(&format!("__bindgen_padding_{}", padding_count), Span::call_site());
 
         self.max_field_align = cmp::max(self.max_field_align, layout.align);
 
         quote! {
             pub #padding_field_name : #ty ,
         }
     }
 
diff --git a/third_party/rust/bindgen/src/features.rs b/third_party/rust/bindgen/src/features.rs
index d4fbd928211e..93ebbc34b812 100644
--- a/third_party/rust/bindgen/src/features.rs
+++ b/third_party/rust/bindgen/src/features.rs
@@ -85,18 +85,22 @@ macro_rules! rust_target_values_def {
 /// Defines macro which takes a macro
 macro_rules! rust_target_base {
     ( $x_macro:ident ) => {
         $x_macro!(
             /// Rust stable 1.0
             => Stable_1_0 => 1.0;
             /// Rust stable 1.19
             => Stable_1_19 => 1.19;
+            /// Rust stable 1.20
+            => Stable_1_20 => 1.20;
             /// Rust stable 1.21
             => Stable_1_21 => 1.21;
+            /// Rust stable 1.25
+            => Stable_1_25 => 1.25;
             /// Nightly rust
             => Nightly => nightly;
         );
     }
 }
 
 rust_target_base!(rust_target_def);
 rust_target_base!(rust_target_values_def);
@@ -106,63 +110,69 @@ pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_21;
 
 /// Create RustFeatures struct definition, new(), and a getter for each field
 macro_rules! rust_feature_def {
     ( $( $( #[$attr:meta] )* => $feature:ident; )* ) => {
         /// Features supported by a rust target
         #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
         pub struct RustFeatures {
             $(
-                $feature: bool,
+                $(
+                    #[$attr]
+                )*
+                pub $feature: bool,
             )*
         }
 
         impl RustFeatures {
             /// Gives a RustFeatures struct with all features disabled
             fn new() -> Self {
                 RustFeatures {
                     $(
                         $feature: false,
                     )*
                 }
             }
-
-            $(
-                $(
-                    #[$attr]
-                )*
-                pub fn $feature(&self) -> bool {
-                    self.$feature
-                }
-            )*
         }
     }
 }
 
 rust_feature_def!(
     /// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
     => untagged_union;
     /// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
     => thiscall_abi;
     /// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
     => builtin_clone_impls;
+    /// repr(align) https://github.com/rust-lang/rust/pull/47006
+    => repr_align;
+    /// associated constants https://github.com/rust-lang/rust/issues/29646
+    => associated_const;
 );
 
 impl From<RustTarget> for RustFeatures {
     fn from(rust_target: RustTarget) -> Self {
         let mut features = RustFeatures::new();
 
         if rust_target >= RustTarget::Stable_1_19 {
             features.untagged_union = true;
         }
 
+        if rust_target >= RustTarget::Stable_1_20 {
+            features.associated_const = true;
+        }
+
         if rust_target >= RustTarget::Stable_1_21 {
             features.builtin_clone_impls = true;
         }
 
+        if rust_target >= RustTarget::Stable_1_25 {
+            features.repr_align = true;
+        }
+
         if rust_target >= RustTarget::Nightly {
             features.thiscall_abi = true;
         }
 
         features
     }
 }
 
@@ -184,11 +194,12 @@ mod test {
         assert_eq!(target, RustTarget::from_str(target_str).unwrap());
     }
 
     #[test]
     fn str_to_target() {
         test_target("1.0", RustTarget::Stable_1_0);
         test_target("1.19", RustTarget::Stable_1_19);
         test_target("1.21", RustTarget::Stable_1_21);
+        test_target("1.25", RustTarget::Stable_1_25);
         test_target("nightly", RustTarget::Nightly);
     }
 }
diff --git a/third_party/rust/bindgen/src/ir/analysis/derive_copy.rs b/third_party/rust/bindgen/src/ir/analysis/derive_copy.rs
index 94d457d54332..1e8dc8199dde 100644
--- a/third_party/rust/bindgen/src/ir/analysis/derive_copy.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/derive_copy.rs
@@ -229,30 +229,30 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
                 // default, the may have an explicit destructor in C++, so we can't
                 // defer this check just for the union case.
                 if self.ctx.lookup_has_destructor(id.expect_type_id(self.ctx)) {
                     trace!("    comp has destructor which cannot derive copy");
                     return self.insert(id);
                 }
 
                 if info.kind() == CompKind::Union {
-                    if !self.ctx.options().rust_features().untagged_union() {
+                    if !self.ctx.options().rust_features().untagged_union {
                         // NOTE: If there's no template parameters we can derive
                         // copy unconditionally, since arrays are magical for
                         // rustc, and __BindgenUnionField always implements
                         // copy.
                         trace!(
                             "    comp can always derive debug if it's a Union and no template parameters"
                         );
                         return ConstrainResult::Same;
                     }
 
                     // https://github.com/rust-lang/rust/issues/36640
-                    if info.self_template_params(self.ctx).is_some() ||
-                        item.used_template_params(self.ctx).is_some()
+                    if !info.self_template_params(self.ctx).is_empty() ||
+                        !item.all_template_params(self.ctx).is_empty()
                     {
                         trace!(
                             "    comp cannot derive copy because issue 36640"
                         );
                         return self.insert(id);
                     }
                 }
 
diff --git a/third_party/rust/bindgen/src/ir/analysis/derive_debug.rs b/third_party/rust/bindgen/src/ir/analysis/derive_debug.rs
index a1743ae9509c..b191d37da420 100644
--- a/third_party/rust/bindgen/src/ir/analysis/derive_debug.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/derive_debug.rs
@@ -145,17 +145,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
         };
 
         if item.is_opaque(self.ctx, &()) {
             let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
                 l.opaque().can_trivially_derive_debug()
             });
             return if layout_can_derive &&
                       !(ty.is_union() &&
-                        self.ctx.options().rust_features().untagged_union()) {
+                        self.ctx.options().rust_features().untagged_union) {
                 trace!("    we can trivially derive Debug for the layout");
                 ConstrainResult::Same
             } else {
                 trace!("    we cannot derive Debug for the layout");
                 self.insert(id)
             };
         }
 
@@ -230,17 +230,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
 
             TypeKind::Comp(ref info) => {
                 assert!(
                     !info.has_non_type_template_params(),
                     "The early ty.is_opaque check should have handled this case"
                 );
 
                 if info.kind() == CompKind::Union {
-                    if self.ctx.options().rust_features().untagged_union() {
+                    if self.ctx.options().rust_features().untagged_union {
                         trace!("    cannot derive Debug for Rust unions");
                         return self.insert(id);
                     }
 
                     if ty.layout(self.ctx).map_or(true, |l| {
                         l.opaque().can_trivially_derive_debug()
                     })
                     {
diff --git a/third_party/rust/bindgen/src/ir/analysis/derive_default.rs b/third_party/rust/bindgen/src/ir/analysis/derive_default.rs
index 2c79a4377ffe..e319166d3292 100644
--- a/third_party/rust/bindgen/src/ir/analysis/derive_default.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/derive_default.rs
@@ -172,17 +172,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
         };
 
         if item.is_opaque(self.ctx, &()) {
             let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
                 l.opaque().can_trivially_derive_default()
             });
             return if layout_can_derive &&
                       !(ty.is_union() &&
-                        self.ctx.options().rust_features().untagged_union()) {
+                        self.ctx.options().rust_features().untagged_union) {
                 trace!("    we can trivially derive Default for the layout");
                 ConstrainResult::Same
             } else {
                 trace!("    we cannot derive Default for the layout");
                 self.insert(id)
             };
         }
 
@@ -266,17 +266,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
                 );
 
                 if info.is_forward_declaration() {
                     trace!("    cannot derive Default for forward decls");
                     return self.insert(id);
                 }
 
                 if info.kind() == CompKind::Union {
-                    if self.ctx.options().rust_features().untagged_union() {
+                    if self.ctx.options().rust_features().untagged_union {
                         trace!("    cannot derive Default for Rust unions");
                         return self.insert(id);
                     }
 
                     if ty.layout(self.ctx).map_or(true, |l| {
                         l.opaque().can_trivially_derive_default()
                     })
                     {
diff --git a/third_party/rust/bindgen/src/ir/analysis/derive_hash.rs b/third_party/rust/bindgen/src/ir/analysis/derive_hash.rs
index 3fc31b39684e..c23a891e0455 100644
--- a/third_party/rust/bindgen/src/ir/analysis/derive_hash.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/derive_hash.rs
@@ -132,17 +132,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
         }
 
         if item.is_opaque(self.ctx, &()) {
             let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
                 l.opaque().can_trivially_derive_hash()
             });
             return if layout_can_derive &&
                 !(ty.is_union() &&
-                  self.ctx.options().rust_features().untagged_union()) {
+                  self.ctx.options().rust_features().untagged_union) {
                 trace!("    we can trivially derive Hash for the layout");
                 ConstrainResult::Same
             } else {
                 trace!("    we cannot derive Hash for the layout");
                 self.insert(id)
             };
         }
 
@@ -252,17 +252,17 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
                 );
 
                 if info.is_forward_declaration() {
                     trace!("    cannot derive Hash for forward decls");
                     return self.insert(id);
                 }
 
                 if info.kind() == CompKind::Union {
-                    if self.ctx.options().rust_features().untagged_union() {
+                    if self.ctx.options().rust_features().untagged_union {
                         trace!("    cannot derive Hash for Rust unions");
                         return self.insert(id);
                     }
 
                     if ty.layout(self.ctx).map_or(true, |l| {
                         l.opaque().can_trivially_derive_hash()
                     })
                     {
diff --git a/third_party/rust/bindgen/src/ir/analysis/derive_partialeq_or_partialord.rs b/third_party/rust/bindgen/src/ir/analysis/derive_partialeq_or_partialord.rs
index 2641d2b3f3af..cebdceefe479 100644
--- a/third_party/rust/bindgen/src/ir/analysis/derive_partialeq_or_partialord.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/derive_partialeq_or_partialord.rs
@@ -114,17 +114,17 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
 
         if self.ctx.no_partialeq_by_name(&item) {
             return CanDerive::No;
         }
 
         trace!("ty: {:?}", ty);
         if item.is_opaque(self.ctx, &()) {
             if ty.is_union()
-                && self.ctx.options().rust_features().untagged_union()
+                && self.ctx.options().rust_features().untagged_union
             {
                 trace!(
                     "    cannot derive `PartialEq`/`PartialOrd` for Rust unions"
                 );
                 return CanDerive::No;
             }
 
             let layout_can_derive = ty.layout(self.ctx)
@@ -237,17 +237,17 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
                 );
 
                 if info.is_forward_declaration() {
                     trace!("    cannot derive for forward decls");
                     return CanDerive::No;
                 }
 
                 if info.kind() == CompKind::Union {
-                    if self.ctx.options().rust_features().untagged_union() {
+                    if self.ctx.options().rust_features().untagged_union {
                         trace!(
                             "    cannot derive `PartialEq`/`PartialOrd` for Rust unions"
                         );
                         return CanDerive::No;
                     }
 
                     let layout_can_derive =
                         ty.layout(self.ctx).map_or(CanDerive::Yes, |l| {
diff --git a/third_party/rust/bindgen/src/ir/analysis/template_params.rs b/third_party/rust/bindgen/src/ir/analysis/template_params.rs
index 00504aa40e5e..b326e6b58b15 100644
--- a/third_party/rust/bindgen/src/ir/analysis/template_params.rs
+++ b/third_party/rust/bindgen/src/ir/analysis/template_params.rs
@@ -270,17 +270,17 @@ impl<'ctx> UsedTemplateParameters<'ctx> {
         used_by_this_id: &mut ItemSet,
         instantiation: &TemplateInstantiation,
     ) {
         trace!("    template instantiation");
 
         let decl = self.ctx.resolve_type(instantiation.template_definition());
         let args = instantiation.template_arguments();
 
-        let params = decl.self_template_params(self.ctx).unwrap_or(vec![]);
+        let params = decl.self_template_params(self.ctx);
 
         debug_assert!(this_id != instantiation.template_definition());
         let used_by_def = self.used
             .get(&instantiation.template_definition().into())
             .expect("Should have a used entry for instantiation's template definition")
             .as_ref()
             .expect("And it should be Some because only this_id's set is None, and an \
                      instantiation's template definition should never be the \
@@ -414,17 +414,17 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> {
                 &TypeKind::TemplateInstantiation(ref inst) => {
                     let decl = ctx.resolve_type(inst.template_definition());
                     let args = inst.template_arguments();
 
                     // Although template definitions should always have
                     // template parameters, there is a single exception:
                     // opaque templates. Hence the unwrap_or.
                     let params =
-                        decl.self_template_params(ctx).unwrap_or(vec![]);
+                        decl.self_template_params(ctx);
 
                     for (arg, param) in args.iter().zip(params.iter()) {
                         let arg = arg.into_resolver()
                             .through_type_aliases()
                             .through_type_refs()
                             .resolve(ctx)
                             .id();
 
diff --git a/third_party/rust/bindgen/src/ir/comment.rs b/third_party/rust/bindgen/src/ir/comment.rs
index afa2a38589ef..6a87c492afeb 100644
--- a/third_party/rust/bindgen/src/ir/comment.rs
+++ b/third_party/rust/bindgen/src/ir/comment.rs
@@ -34,17 +34,17 @@ fn kind(comment: &str) -> Option<Kind> {
 }
 
 fn make_indent(indent: usize) -> String {
     const RUST_INDENTATION: usize = 4;
 
     iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
 }
 
-/// Preprocesses mulitple single line comments.
+/// Preprocesses multiple single line comments.
 ///
 /// Handles lines starting with both `//` and `///`.
 fn preprocess_single_lines(comment: &str, indent: usize) -> String {
     debug_assert!(comment.starts_with("//"), "comment is not single line");
 
     let indent = make_indent(indent);
     let mut is_first = true;
     let lines: Vec<_> = comment
diff --git a/third_party/rust/bindgen/src/ir/comp.rs b/third_party/rust/bindgen/src/ir/comp.rs
index 50d0ddb16e2e..704c1776ff50 100644
--- a/third_party/rust/bindgen/src/ir/comp.rs
+++ b/third_party/rust/bindgen/src/ir/comp.rs
@@ -1164,17 +1164,17 @@ impl CompInfo {
         let mut kind = Self::kind_from_cursor(&cursor);
         if kind.is_err() {
             if let Some(location) = location {
                 kind = Self::kind_from_cursor(&location);
                 cursor = location;
             }
         }
 
-        let kind = try!(kind);
+        let kind = kind?;
 
         debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
 
         let mut ci = CompInfo::new(kind);
         ci.is_forward_declaration =
             location.map_or(true, |cur| match cur.kind() {
                 CXCursor_StructDecl |
                 CXCursor_UnionDecl |
@@ -1285,19 +1285,20 @@ impl CompInfo {
                     //
                     // [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/482
                     let is_inner_struct = cur.semantic_parent() == cursor ||
                                           cur.is_definition();
                     if !is_inner_struct {
                         return CXChildVisit_Continue;
                     }
 
+                    // Even if this is a definition, we may not be the semantic
+                    // parent, see #1281.
                     let inner = Item::parse(cur, Some(potential_id), ctx)
                         .expect("Inner ClassDecl");
-                    assert_eq!(ctx.resolve_item(inner).parent_id(), potential_id);
 
                     let inner = inner.expect_type_id(ctx);
 
                     ci.inner_types.push(inner);
 
                     // A declaration of an union or a struct without name could
                     // also be an unnamed field, unfortunately.
                     if cur.spelling().is_empty() &&
@@ -1350,17 +1351,17 @@ impl CompInfo {
 
                     // This used to not be here, but then I tried generating
                     // stylo bindings with this (without path filters), and
                     // cried a lot with a method in gfx/Point.h
                     // (ToUnknownPoint), that somehow was causing the same type
                     // to be inserted in the map two times.
                     //
                     // I couldn't make a reduced test case, but anyway...
-                    // Methods of template functions not only use to be inlined,
+                    // Methods of template functions not only used to be inlined,
                     // but also instantiated, and we wouldn't be able to call
                     // them, so just bail out.
                     if !ci.template_params.is_empty() {
                         return CXChildVisit_Continue;
                     }
 
                     // NB: This gets us an owned `Function`, not a
                     // `FunctionSig`.
@@ -1538,17 +1539,17 @@ impl CompInfo {
     }
 
     /// Returns whether the current union can be represented as a Rust `union`
     ///
     /// Requirements:
     ///     1. Current RustTarget allows for `untagged_union`
     ///     2. Each field can derive `Copy`
     pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool {
-        if !ctx.options().rust_features().untagged_union() {
+        if !ctx.options().rust_features().untagged_union {
             return false;
         }
 
         if self.is_forward_declaration() {
             return false;
         }
 
         self.fields().iter().all(|f| match *f {
@@ -1663,34 +1664,29 @@ impl IsOpaque for CompInfo {
         false
     }
 }
 
 impl TemplateParameters for CompInfo {
     fn self_template_params(
         &self,
         _ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
-        if self.template_params.is_empty() {
-            None
-        } else {
-            Some(self.template_params.clone())
-        }
+    ) -> Vec<TypeId> {
+        self.template_params.clone()
     }
 }
 
 impl Trace for CompInfo {
     type Extra = Item;
 
     fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
     where
         T: Tracer,
     {
-        let params = item.all_template_params(context).unwrap_or(vec![]);
-        for p in params {
+        for p in item.all_template_params(context) {
             tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition);
         }
 
         for ty in self.inner_types() {
             tracer.visit_kind(ty.into(), EdgeKind::InnerType);
         }
 
         for &var in self.inner_vars() {
diff --git a/third_party/rust/bindgen/src/ir/context.rs b/third_party/rust/bindgen/src/ir/context.rs
index 0a9145235fa6..86dcda568ff8 100644
--- a/third_party/rust/bindgen/src/ir/context.rs
+++ b/third_party/rust/bindgen/src/ir/context.rs
@@ -19,17 +19,17 @@ use super::ty::{FloatKind, Type, TypeKind};
 use super::function::Function;
 use super::super::time::Timer;
 use BindgenOptions;
 use callbacks::ParseCallbacks;
 use cexpr;
 use clang::{self, Cursor};
 use clang_sys;
 use parse::ClangItemParser;
-use quote;
+use proc_macro2::{Term, Span};
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::collections::{HashMap, HashSet, hash_map};
 use std::collections::btree_map::{self, BTreeMap};
 use std::iter::IntoIterator;
 use std::mem;
 
 /// An identifier for some kind of IR item.
@@ -361,21 +361,24 @@ pub struct BindgenContext {
     in_codegen: bool,
 
     /// The clang index for parsing.
     index: clang::Index,
 
     /// The translation unit for parsing.
     translation_unit: clang::TranslationUnit,
 
+    /// Target information that can be useful for some stuff.
+    target_info: Option<clang::TargetInfo>,
+
     /// The options given by the user via cli or other medium.
     options: BindgenOptions,
 
     /// Whether a bindgen complex was generated
-    generated_bindegen_complex: Cell<bool>,
+    generated_bindgen_complex: Cell<bool>,
 
     /// The set of `ItemId`s that are whitelisted. This the very first thing
     /// computed after parsing our IR, and before running any of our analyses.
     whitelisted: Option<ItemSet>,
 
     /// The set of `ItemId`s that are whitelisted for code generation _and_ that
     /// we should generate accounting for the codegen options.
     ///
@@ -470,23 +473,23 @@ struct WhitelistedItemsTraversal<'ctx> {
     >,
 }
 
 impl<'ctx> Iterator for WhitelistedItemsTraversal<'ctx> {
     type Item = ItemId;
 
     fn next(&mut self) -> Option<ItemId> {
         loop {
-            match self.traversal.next() {
-                None => return None,
-                Some(id) if self.ctx.resolve_item(id).is_blacklisted(self.ctx) => {
-                    continue
-                }
-                Some(id) => return Some(id),
+            let id = self.traversal.next()?;
+
+            if self.ctx.resolve_item(id).is_blacklisted(self.ctx) {
+                continue
             }
+
+            return Some(id);
         }
     }
 }
 
 impl<'ctx> WhitelistedItemsTraversal<'ctx> {
     /// Construct a new whitelisted items traversal.
     pub fn new<R>(
         ctx: &'ctx BindgenContext,
@@ -498,16 +501,19 @@ impl<'ctx> WhitelistedItemsTraversal<'ctx> {
     {
         WhitelistedItemsTraversal {
             ctx,
             traversal: ItemTraversal::new(ctx, roots, predicate),
         }
     }
 }
 
+const HOST_TARGET: &'static str =
+    include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
+
 /// Returns the effective target, and whether it was explicitly specified on the
 /// clang flags.
 fn find_effective_target(clang_args: &[String]) -> (String, bool) {
     use std::env;
 
     for opt in clang_args {
         if opt.starts_with("--target=") {
             let mut split = opt.split('=');
@@ -516,18 +522,16 @@ fn find_effective_target(clang_args: &[String]) -> (String, bool) {
         }
     }
 
     // If we're running from a build script, try to find the cargo target.
     if let Ok(t) = env::var("TARGET") {
         return (t, false)
     }
 
-    const HOST_TARGET: &'static str =
-        include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
     (HOST_TARGET.to_owned(), false)
 }
 
 impl BindgenContext {
     /// Construct the context for the given `options`.
     pub(crate) fn new(options: BindgenOptions) -> Self {
         use clang_sys;
 
@@ -556,16 +560,27 @@ impl BindgenContext {
                 &index,
                 "",
                 &clang_args,
                 &options.input_unsaved_files,
                 parse_options,
             ).expect("TranslationUnit::parse failed")
         };
 
+        let target_info = clang::TargetInfo::new(&translation_unit);
+
+        #[cfg(debug_assertions)]
+        {
+            if let Some(ref ti) = target_info {
+                if effective_target == HOST_TARGET {
+                    assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>());
+                }
+            }
+        }
+
         let root_module = Self::build_root_module(ItemId(0));
         let root_module_id = root_module.id().as_module_id_unchecked();
 
         let mut me = BindgenContext {
             items: Default::default(),
             types: Default::default(),
             type_params: Default::default(),
             modules: Default::default(),
@@ -573,20 +588,21 @@ impl BindgenContext {
             root_module: root_module_id,
             current_module: root_module_id,
             semantic_parents: Default::default(),
             currently_parsed_types: vec![],
             parsed_macros: Default::default(),
             replacements: Default::default(),
             collected_typerefs: false,
             in_codegen: false,
-            index: index,
-            translation_unit: translation_unit,
-            options: options,
-            generated_bindegen_complex: Cell::new(false),
+            index,
+            translation_unit,
+            target_info,
+            options,
+            generated_bindgen_complex: Cell::new(false),
             whitelisted: None,
             codegen_items: None,
             used_template_parameters: None,
             need_bitfield_allocation: Default::default(),
             cannot_derive_debug: None,
             cannot_derive_default: None,
             cannot_derive_copy: None,
             cannot_derive_copy_in_array: None,
@@ -606,16 +622,25 @@ impl BindgenContext {
 
     /// Creates a timer for the current bindgen phase. If time_phases is `true`,
     /// the timer will print to stderr when it is dropped, otherwise it will do
     /// nothing.
     pub fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
         Timer::new(name).with_output(self.options.time_phases)
     }
 
+    /// Returns the pointer width to use for the target for the current
+    /// translation.
+    pub fn target_pointer_size(&self) -> usize {
+        if let Some(ref ti) = self.target_info {
+            return ti.pointer_width / 8;
+        }
+        mem::size_of::<*mut ()>()
+    }
+
     /// Get the stack of partially parsed types that we are in the middle of
     /// parsing.
     pub fn currently_parsed_types(&self) -> &[PartialType] {
         &self.currently_parsed_types[..]
     }
 
     /// Begin parsing the given partial type, and push it onto the
     /// `currently_parsed_types` stack so that we won't infinite recurse if we
@@ -875,29 +900,29 @@ impl BindgenContext {
             s = s.replace("$", "_");
             s.push_str("_");
             return Cow::Owned(s);
         }
         Cow::Borrowed(name)
     }
 
     /// Returns a mangled name as a rust identifier.
-    pub fn rust_ident<S>(&self, name: S) -> quote::Ident
+    pub fn rust_ident<S>(&self, name: S) -> Term
     where
         S: AsRef<str>
     {
         self.rust_ident_raw(self.rust_mangle(name.as_ref()))
     }
 
     /// Returns a mangled name as a rust identifier.
-    pub fn rust_ident_raw<T>(&self, name: T) -> quote::Ident
+    pub fn rust_ident_raw<T>(&self, name: T) -> Term
     where
-        T: Into<quote::Ident>
+        T: AsRef<str>
     {
-        name.into()
+        Term::new(name.as_ref(), Span::call_site())
     }
 
     /// Iterate over all items that have been defined.
     pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> {
         self.items.iter()
     }
 
     /// Have we collected all unresolved type references yet?
@@ -1004,20 +1029,18 @@ impl BindgenContext {
 
     /// Assign a new generated name for each anonymous field.
     fn deanonymize_fields(&mut self) {
         let _t = self.timer("deanonymize_fields");
 
         let comp_item_ids: Vec<ItemId> = self.items
             .iter()
             .filter_map(|(id, item)| {
-                if let Some(ty) = item.kind().as_type() {
-                    if let Some(_comp) = ty.as_comp() {
-                        return Some(id);
-                    }
+                if item.kind().as_type()?.is_comp() {
+                    return Some(id);
                 }
                 None
             })
             .cloned()
             .collect();
 
         for id in comp_item_ids {
             self.with_loaned_item(id, |ctx, item| {
@@ -1057,16 +1080,17 @@ impl BindgenContext {
             let ty = match item.kind().as_type() {
                 Some(ty) => ty,
                 None => continue,
             };
 
             match *ty.kind() {
                 TypeKind::Comp(..) |
                 TypeKind::TemplateAlias(..) |
+                TypeKind::Enum(..) |
                 TypeKind::Alias(..) => {}
                 _ => continue,
             }
 
             let path = item.canonical_path(self);
             let replacement = self.replacements.get(&path[1..]);
 
             if let Some(replacement) = replacement {
@@ -1337,20 +1361,17 @@ impl BindgenContext {
             let used_params = analyze::<UsedTemplateParameters>(self);
             self.used_template_parameters = Some(used_params);
         } else {
             // If you aren't recursively whitelisting, then we can't really make
             // any sense of template parameter usage, and you're on your own.
             let mut used_params = HashMap::new();
             for &id in self.whitelisted_items() {
                 used_params.entry(id).or_insert(
-                    id.self_template_params(self).map_or(
-                        Default::default(),
-                        |params| params.into_iter().map(|p| p.into()).collect(),
-                    ),
+                    id.self_template_params(self).into_iter().map(|p| p.into()).collect()
                 );
             }
             self.used_template_parameters = Some(used_params);
         }
     }
 
     /// Return `true` if `item` uses the given `template_param`, `false`
     /// otherwise.
@@ -1512,36 +1533,37 @@ impl BindgenContext {
 
 
     /// Given a cursor pointing to the location of a template instantiation,
     /// return a tuple of the form `(declaration_cursor, declaration_id,
     /// num_expected_template_args)`.
     ///
     /// Note that `declaration_id` is not guaranteed to be in the context's item
     /// set! It is possible that it is a partial type that we are still in the
-    /// middle of parsign.
+    /// middle of parsing.
     fn get_declaration_info_for_template_instantiation(
         &self,
         instantiation: &Cursor,
     ) -> Option<(Cursor, ItemId, usize)> {
         instantiation
             .cur_type()
             .canonical_declaration(Some(instantiation))
             .and_then(|canon_decl| {
                 self.get_resolved_type(&canon_decl).and_then(
                     |template_decl_id| {
-                        template_decl_id.num_self_template_params(self).map(
-                            |num_params| {
-                                (
-                                    *canon_decl.cursor(),
-                                    template_decl_id.into(),
-                                    num_params,
-                                )
-                            },
-                        )
+                        let num_params = template_decl_id.num_self_template_params(self);
+                        if num_params == 0 {
+                            None
+                        } else {
+                            Some((
+                                *canon_decl.cursor(),
+                                template_decl_id.into(),
+                                num_params,
+                            ))
+                        }
                     },
                 )
             })
             .or_else(|| {
                 // If we haven't already parsed the declaration of
                 // the template being instantiated, then it *must*
                 // be on the stack of types we are currently
                 // parsing. If it wasn't then clang would have
@@ -1552,25 +1574,26 @@ impl BindgenContext {
                     .referenced()
                     .and_then(|referenced| {
                         self.currently_parsed_types()
                             .iter()
                             .find(|partial_ty| *partial_ty.decl() == referenced)
                             .cloned()
                     })
                     .and_then(|template_decl| {
-                        template_decl.num_self_template_params(self).map(
-                            |num_template_params| {
-                                (
-                                    *template_decl.decl(),
-                                    template_decl.id(),
-                                    num_template_params,
-                                )
-                            },
-                        )
+                        let num_template_params = template_decl.num_self_template_params(self);
+                        if num_template_params == 0 {
+                            None
+                        } else {
+                            Some((
+                                *template_decl.decl(),
+                                template_decl.id(),
+                                num_template_params,
+                            ))
+                        }
                     })
             })
     }
 
     /// Parse a template instantiation, eg `Foo<int>`.
     ///
     /// This is surprisingly difficult to do with libclang, due to the fact that
     /// it doesn't provide explicit template argument information, except for
@@ -1607,27 +1630,24 @@ impl BindgenContext {
         &mut self,
         with_id: ItemId,
         template: TypeId,
         ty: &clang::Type,
         location: clang::Cursor,
     ) -> Option<TypeId> {
         use clang_sys;
 
-        let num_expected_args = match self.resolve_type(template)
-            .num_self_template_params(self) {
-            Some(n) => n,
-            None => {
-                warn!(
-                    "Tried to instantiate a template for which we could not \
-                       determine any template parameters"
-                );
-                return None;
-            }
-        };
+        let num_expected_args = self.resolve_type(template).num_self_template_params(self);
+        if num_expected_args == 0 {
+            warn!(
+                "Tried to instantiate a template for which we could not \
+                   determine any template parameters"
+            );
+            return None;
+        }
 
         let mut args = vec![];
         let mut found_const_arg = false;
         let mut children = location.collect_children();
 
         if children.iter().all(|c| !c.has_children()) {
             // This is insanity... If clang isn't giving us a properly nested
             // AST for which template arguments belong to which template we are
@@ -1668,20 +1688,17 @@ impl BindgenContext {
                         *child,
                         Some(template.into()),
                         self,
                     );
                     args.push(ty);
                 }
                 clang_sys::CXCursor_TemplateRef => {
                     let (template_decl_cursor, template_decl_id, num_expected_template_args) =
-                        match self.get_declaration_info_for_template_instantiation(child) {
-                            Some(info) => info,
-                            None => return None,
-                        };
+                        self.get_declaration_info_for_template_instantiation(child)?;
 
                     if num_expected_template_args == 0 ||
                         child.has_at_least_num_children(
                             num_expected_template_args,
                         )
                     {
                         // Do a happy little parse. See comment in the TypeRef
                         // match arm about parent IDs.
@@ -1892,30 +1909,65 @@ impl BindgenContext {
 
         debug!("Not resolved, maybe builtin?");
         self.build_builtin_ty(ty)
     }
 
     /// Make a new item that is a resolved type reference to the `wrapped_id`.
     ///
     /// This is unfortunately a lot of bloat, but is needed to properly track
-    /// constness et. al.
+    /// constness et al.
     ///
     /// We should probably make the constness tracking separate, so it doesn't
     /// bloat that much, but hey, we already bloat the heck out of builtin
     /// types.
     pub fn build_ty_wrapper(
         &mut self,
         with_id: ItemId,
         wrapped_id: TypeId,
         parent_id: Option<ItemId>,
         ty: &clang::Type,
+    ) -> TypeId {
+        self.build_wrapper(
+            with_id,
+            wrapped_id,
+            parent_id,
+            ty,
+            ty.is_const(),
+        )
+    }
+
+    /// A wrapper over a type that adds a const qualifier explicitly.
+    ///
+    /// Needed to handle const methods in C++, wrapping the type .
+    pub fn build_const_wrapper(
+        &mut self,
+        with_id: ItemId,
+        wrapped_id: TypeId,
+        parent_id: Option<ItemId>,
+        ty: &clang::Type,
+    ) -> TypeId {
+        self.build_wrapper(
+            with_id,
+            wrapped_id,
+            parent_id,
+            ty,
+            /* is_const = */ true,
+        )
+    }
+
+    fn build_wrapper(
+        &mut self,
+        with_id: ItemId,
+        wrapped_id: TypeId,
+        parent_id: Option<ItemId>,
+        ty: &clang::Type,
+        is_const: bool,
     ) -> TypeId {
         let spelling = ty.spelling();
-        let is_const = ty.is_const();
         let layout = ty.fallible_layout().ok();
         let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
         let ty = Type::new(Some(spelling), layout, type_kind, is_const);
         let item = Item::new(
             with_id,
             None,
             None,
             parent_id.unwrap_or(self.current_module.into()),
@@ -2060,17 +2112,17 @@ impl BindgenContext {
             "You're not supposed to call this yet"
         );
         self.options.blacklisted_types.matches(&path[1..].join("::")) ||
             self.is_replaced_type(path, id)
     }
 
     /// Has the item with the given `name` and `id` been replaced by another
     /// type?
-    pub fn is_replaced_type<Id: Into<ItemId>>(&self, path: &[String], id: Id) -> bool {
+    fn is_replaced_type<Id: Into<ItemId>>(&self, path: &[String], id: Id) -> bool {
         let id = id.into();
         match self.replacements.get(path) {
             Some(replaced_by) if *replaced_by != id => true,
             _ => false,
         }
     }
 
     /// Is the type with the given `name` marked as opaque?
@@ -2290,17 +2342,21 @@ impl BindgenContext {
             roots.reverse();
             roots
         };
 
         let whitelisted_items_predicate =
             if self.options().whitelist_recursively {
                 traversal::all_edges
             } else {
-                traversal::no_edges
+                // Only follow InnerType edges from the whitelisted roots.
+                // Such inner types (e.g. anonymous structs/unions) are
+                // always emitted by codegen, and they need to be whitelisted
+                // to make sure they are processed by e.g. the derive analysis.
+                traversal::only_inner_type_edges
             };
 
         let whitelisted = WhitelistedItemsTraversal::new(
             self,
             roots.clone(),
             whitelisted_items_predicate,
         ).collect::<ItemSet>();
 
@@ -2315,32 +2371,32 @@ impl BindgenContext {
         };
 
         self.whitelisted = Some(whitelisted);
         self.codegen_items = Some(codegen_items);
     }
 
     /// Convenient method for getting the prefix to use for most traits in
     /// codegen depending on the `use_core` option.
-    pub fn trait_prefix(&self) -> quote::Ident {
+    pub fn trait_prefix(&self) -> Term {
         if self.options().use_core {
             self.rust_ident_raw("core")
         } else {
             self.rust_ident_raw("std")
         }
     }
 
-    /// Call if a binden complex is generated
-    pub fn generated_bindegen_complex(&self) {
-        self.generated_bindegen_complex.set(true)
+    /// Call if a bindgen complex is generated
+    pub fn generated_bindgen_complex(&self) {
+        self.generated_bindgen_complex.set(true)
     }
 
-    /// Whether we need to generate the binden complex type
-    pub fn need_bindegen_complex_type(&self) -> bool {
-        self.generated_bindegen_complex.get()
+    /// Whether we need to generate the bindgen complex type
+    pub fn need_bindgen_complex_type(&self) -> bool {
+        self.generated_bindgen_complex.get()
     }
 
     /// Compute whether we can derive debug.
     fn compute_cannot_derive_debug(&mut self) {
         let _t = self.timer("compute_cannot_derive_debug");
         assert!(self.cannot_derive_debug.is_none());
         if self.options.derive_debug {
             self.cannot_derive_debug = Some(analyze::<CannotDeriveDebug>(self));
@@ -2502,17 +2558,17 @@ impl BindgenContext {
     }
 
     /// Check if `--no-copy` flag is enabled for this item.
     pub fn no_copy_by_name(&self, item: &Item) -> bool {
         let name = item.canonical_path(self)[1..].join("::");
         self.options().no_copy_types.matches(&name)
     }
 
-    /// Chech if `--no-hash` flag is enabled for this item.
+    /// Check if `--no-hash` flag is enabled for this item.
     pub fn no_hash_by_name(&self, item: &Item) -> bool {
         let name = item.canonical_path(self)[1..].join("::");
         self.options().no_hash_types.matches(&name)
     }
 }
 
 /// A builder struct for configuring item resolution options.
 #[derive(Debug, Copy, Clone)]
@@ -2617,23 +2673,23 @@ impl PartialType {
         self.id
     }
 }
 
 impl TemplateParameters for PartialType {
     fn self_template_params(
         &self,
         _ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
+    ) -> Vec<TypeId> {
         // Maybe at some point we will eagerly parse named types, but for now we
         // don't and this information is unavailable.
-        None
+        vec![]
     }
 
-    fn num_self_template_params(&self, _ctx: &BindgenContext) -> Option<usize> {
+    fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
         // Wouldn't it be nice if libclang would reliably give us this
         // information‽
         match self.decl().kind() {
             clang_sys::CXCursor_ClassTemplate |
             clang_sys::CXCursor_FunctionTemplate |
             clang_sys::CXCursor_TypeAliasTemplateDecl => {
                 let mut num_params = 0;
                 self.decl().visit(|c| {
@@ -2642,14 +2698,14 @@ impl TemplateParameters for PartialType {
                         clang_sys::CXCursor_TemplateTemplateParameter |
                         clang_sys::CXCursor_NonTypeTemplateParameter => {
                             num_params += 1;
                         }
                         _ => {}
                     };
                     clang_sys::CXChildVisit_Continue
                 });
-                Some(num_params)
+                num_params
             }
-            _ => None,
+            _ => 0,
         }
     }
 }
diff --git a/third_party/rust/bindgen/src/ir/derive.rs b/third_party/rust/bindgen/src/ir/derive.rs
index b0a6912f8dbc..65c221582a33 100644
--- a/third_party/rust/bindgen/src/ir/derive.rs
+++ b/third_party/rust/bindgen/src/ir/derive.rs
@@ -38,17 +38,17 @@ pub trait CanTriviallyDeriveDebug {
 pub trait CanDeriveCopy<'a> {
     /// Return `true` if `Copy` can be derived for this thing, `false`
     /// otherwise.
     fn can_derive_copy(&'a self, ctx: &'a BindgenContext) -> bool;
 }
 
 /// A trait that encapsulates the logic for whether or not we can trivially
 /// derive `Copy` without looking at any other types or results of fix point
-/// analsyses. This is a helper trait for fix point analysis.
+/// analyses. This is a helper trait for fix point analysis.
 pub trait CanTriviallyDeriveCopy {
     /// Return `true` if `Copy` can be trivially derived for this thing, `false`
     /// otherwise.
     fn can_trivially_derive_copy(&self) -> bool;
 }
 
 /// A trait that encapsulates the logic for whether or not we can derive
 /// `Default` for a given thing.
diff --git a/third_party/rust/bindgen/src/ir/dot.rs b/third_party/rust/bindgen/src/ir/dot.rs
index 1181c32cb98e..48bd1d91648d 100644
--- a/third_party/rust/bindgen/src/ir/dot.rs
+++ b/third_party/rust/bindgen/src/ir/dot.rs
@@ -20,37 +20,37 @@ pub trait DotAttributes {
         W: io::Write;
 }
 
 /// Write a graphviz dot file containing our IR.
 pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
 where
     P: AsRef<Path>,
 {
-    let file = try!(File::create(path));
+    let file = File::create(path)?;
     let mut dot_file = io::BufWriter::new(file);
-    try!(writeln!(&mut dot_file, "digraph {{"));
+    writeln!(&mut dot_file, "digraph {{")?;
 
     let mut err: Option<io::Result<_>> = None;
 
     for (id, item) in ctx.items() {
         let is_whitelisted = ctx.whitelisted_items().contains(id);
 
-        try!(writeln!(
+        writeln!(
             &mut dot_file,
             r#"{} [fontname="courier", color={}, label=< <table border="0" align="left">"#,
             id.as_usize(),
             if is_whitelisted {
                 "black"
             } else {
                 "gray"
             }
-        ));
-        try!(item.dot_attributes(ctx, &mut dot_file));
-        try!(writeln!(&mut dot_file, r#"</table> >];"#));
+        )?;
+        item.dot_attributes(ctx, &mut dot_file)?;
+        writeln!(&mut dot_file, r#"</table> >];"#)?;
 
         item.trace(
             ctx,
             &mut |sub_id: ItemId, edge_kind| {
                 if err.is_some() {
                     return;
                 }
 
@@ -74,21 +74,21 @@ where
         );
 
         if let Some(err) = err {
             return err;
         }
 
         if let Some(module) = item.as_module() {
             for child in module.children() {
-                try!(writeln!(
+                writeln!(
                     &mut dot_file,
                     "{} -> {} [style=dotted, color=gray]",
                     item.id().as_usize(),
                     child.as_usize()
-                ));
+                )?;
             }
         }
     }
 
-    try!(writeln!(&mut dot_file, "}}"));
+    writeln!(&mut dot_file, "}}")?;
     Ok(())
 }
diff --git a/third_party/rust/bindgen/src/ir/enum_ty.rs b/third_party/rust/bindgen/src/ir/enum_ty.rs
index bc8e37ebb175..ee705f168aae 100644
--- a/third_party/rust/bindgen/src/ir/enum_ty.rs
+++ b/third_party/rust/bindgen/src/ir/enum_ty.rs
@@ -2,16 +2,17 @@
 
 use super::context::{BindgenContext, TypeId};
 use super::item::Item;
 use super::ty::TypeKind;
 use clang;
 use ir::annotations::Annotations;
 use ir::item::ItemCanonicalPath;
 use parse::{ClangItemParser, ParseError};
+use regex_set::RegexSet;
 
 /// An enum representing custom handling that can be given to a variant.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum EnumVariantCustomBehavior {
     /// This variant will be a module containing constants.
     ModuleConstify,
     /// This variant will be constified, that is, forced to generate a constant.
     Constify,
@@ -93,84 +94,85 @@ impl Enum {
             if cursor.kind() == CXCursor_EnumConstantDecl {
                 let value = if is_signed {
                     cursor.enum_val_signed().map(EnumVariantValue::Signed)
                 } else {
                     cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned)
                 };
                 if let Some(val) = value {
                     let name = cursor.spelling();
+                    let annotations = Annotations::new(&cursor);
                     let custom_behavior = ctx.parse_callbacks()
-                        .and_then(
-                            |t| t.enum_variant_behavior(type_name, &name, val),
-                        )
+                        .and_then(|callbacks| {
+                            callbacks.enum_variant_behavior(type_name, &name, val)
+                        })
                         .or_else(|| {
-                            Annotations::new(&cursor).and_then(
-                                |anno| if anno.hide() {
-                                    Some(EnumVariantCustomBehavior::Hide)
-                                } else if anno.constify_enum_variant() {
-                                    Some(EnumVariantCustomBehavior::Constify)
-                                } else {
-                                    None
-                                },
-                            )
+                            let annotations = annotations.as_ref()?;
+                            if annotations.hide() {
+                                Some(EnumVariantCustomBehavior::Hide)
+                            } else if annotations.constify_enum_variant() {
+                                Some(EnumVariantCustomBehavior::Constify)
+                            } else {
+                                None
+                            }
                         });
 
+                    let name = ctx.parse_callbacks()
+                        .and_then(|callbacks| {
+                            callbacks.enum_variant_name(type_name, &name, val)
+                        })
+                        .or_else(|| {
+                            annotations.as_ref()?.use_instead_of()?.last().cloned()
+                        })
+                        .unwrap_or(name);
+
                     let comment = cursor.raw_comment();
                     variants.push(EnumVariant::new(
                         name,
                         comment,
                         val,
                         custom_behavior,
                     ));
                 }
             }
             CXChildVisit_Continue
         });
         Ok(Enum::new(repr, variants))
     }
 
-    /// Whether the enum should be a bitfield
-    pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
+    fn is_matching_enum(&self, ctx: &BindgenContext, enums: &RegexSet, item: &Item) -> bool {
         let path = item.canonical_path(ctx);
         let enum_ty = item.expect_type();
 
-        ctx.options().bitfield_enums.matches(&path[1..].join("::")) ||
-            (enum_ty.name().is_none() &&
-                    self.variants().iter().any(|v| {
-                    ctx.options().bitfield_enums.matches(&v.name())
-                }))
+        let path_matches = enums.matches(&path[1..].join("::"));
+        let enum_is_anon = enum_ty.name().is_none();
+        let a_variant_matches = self.variants().iter().any(|v| {
+            enums.matches(&v.name())
+        });
+        path_matches || (enum_is_anon && a_variant_matches)
+    }
+
+    /// Whether the enum should be a bitfield
+    pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
+        self.is_matching_enum(ctx, &ctx.options().bitfield_enums, item)
     }
 
     /// Whether the enum should be an constified enum module
-    pub fn is_constified_enum_module(
-        &self,
-        ctx: &BindgenContext,
-        item: &Item,
-    ) -> bool {
-        let path = item.canonical_path(ctx);
-        let enum_ty = item.expect_type();
+    pub fn is_constified_enum_module(&self, ctx: &BindgenContext, item: &Item) -> bool {
+        self.is_matching_enum(ctx, &ctx.options().constified_enum_modules, item)
+    }
 
-        ctx.options().constified_enum_modules.matches(&path[1..].join("::")) ||
-            (enum_ty.name().is_none() &&
-                 self.variants().iter().any(|v| {
-                    ctx.options().constified_enum_modules.matches(&v.name())
-                }))
+    /// Whether the enum should be an set of constants
+    pub fn is_constified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
+        self.is_matching_enum(ctx, &ctx.options().constified_enums, item)
     }
 
     /// Whether the enum should be a Rust enum
     pub fn is_rustified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
-        let path = item.canonical_path(ctx);
-        let enum_ty = item.expect_type();
-
-        ctx.options().rustified_enums.matches(&path[1..].join("::")) ||
-            (enum_ty.name().is_none() &&
-                self.variants().iter().any(|v| {
-                    ctx.options().rustified_enums.matches(&v.name())
-            }))
+        self.is_matching_enum(ctx, &ctx.options().rustified_enums, item)
     }
 }
 
 /// A single enum variant, to be contained only in an enum.
 #[derive(Debug)]
 pub struct EnumVariant {
     /// The name of the variant.
     name: String,
diff --git a/third_party/rust/bindgen/src/ir/function.rs b/third_party/rust/bindgen/src/ir/function.rs
index 481ab9f72842..5e8d2fc8d583 100644
--- a/third_party/rust/bindgen/src/ir/function.rs
+++ b/third_party/rust/bindgen/src/ir/function.rs
@@ -146,21 +146,21 @@ impl DotAttributes for Function {
         out: &mut W,
     ) -> io::Result<()>
     where
         W: io::Write,
     {
         if let Some(ref mangled) = self.mangled_name {
             let mangled: String =
                 mangled.chars().flat_map(|c| c.escape_default()).collect();
-            try!(writeln!(
+            writeln!(
                 out,
                 "<tr><td>mangled name</td><td>{}</td></tr>",
                 mangled
-            ));
+            )?;
         }
 
         Ok(())
     }
 }
 
 /// An ABI extracted from a clang cursor.
 #[derive(Debug, Copy, Clone)]
@@ -188,17 +188,17 @@ impl Abi {
             Abi::Unknown(..) => true,
             _ => false,
         }
     }
 }
 
 impl quote::ToTokens for Abi {
     fn to_tokens(&self, tokens: &mut quote::Tokens) {
-        tokens.append(match *self {
+        tokens.append_all(match *self {
             Abi::C => quote! { "C" },
             Abi::Stdcall => quote! { "stdcall" },
             Abi::Fastcall => quote! { "fastcall" },
             Abi::ThisCall => quote! { "thiscall" },
             Abi::Aapcs => quote! { "aapcs" },
             Abi::Win64 => quote! { "win64" },
             Abi::Unknown(cc) => panic!(
                 "Cannot turn unknown calling convention to tokens: {:?}",
@@ -397,41 +397,54 @@ impl FunctionSig {
             return Err(ParseError::Continue);
         }
 
         if is_method || is_constructor || is_destructor {
             let is_const = is_method && cursor.method_is_const();
             let is_virtual = is_method && cursor.method_is_virtual();
             let is_static = is_method && cursor.method_is_static();
             if !is_static && !is_virtual {
-                let class = Item::parse(cursor.semantic_parent(), None, ctx)
+                let parent = cursor.semantic_parent();
+                let class = Item::parse(parent, None, ctx)
                     .expect("Expected to parse the class");
                 // The `class` most likely is not finished parsing yet, so use
                 // the unchecked variant.
                 let class = class.as_type_id_unchecked();
 
+                let class = if is_const {
+                    let const_class_id = ctx.next_item_id();
+                    ctx.build_const_wrapper(
+                        const_class_id,
+                        class,
+                        None,
+                        &parent.cur_type(),
+                    )
+                } else {
+                    class
+                };
+
                 let ptr =
-                    Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
+                    Item::builtin_type(TypeKind::Pointer(class), false, ctx);
                 args.insert(0, (Some("this".into()), ptr));
             } else if is_virtual {
                 let void = Item::builtin_type(TypeKind::Void, false, ctx);
                 let ptr =
                     Item::builtin_type(TypeKind::Pointer(void), false, ctx);
                 args.insert(0, (Some("this".into()), ptr));
             }
         }
 
         let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
             cursor.kind() == CXCursor_ObjCClassMethodDecl
         {
-            try!(ty.ret_type().or_else(|| cursor.ret_type()).ok_or(
+            ty.ret_type().or_else(|| cursor.ret_type()).ok_or(
                 ParseError::Continue,
-            ))
+            )?
         } else {
-            try!(ty.ret_type().ok_or(ParseError::Continue))
+            ty.ret_type().ok_or(ParseError::Continue)?
         };
         let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
         let call_conv = ty.call_conv();
         let abi = get_abi(call_conv);
 
         if abi.is_unknown() {
             warn!("Unknown calling convention: {:?}", call_conv);
         }
@@ -516,17 +529,17 @@ impl ClangSubItemParser for Function {
         let linkage = match linkage {
             CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
             CXLinkage_Internal => Linkage::Internal,
             _ => return Err(ParseError::Continue)
         };
 
         // Grab the signature using Item::from_ty.
         let sig =
-            try!(Item::from_ty(&cursor.cur_type(), cursor, None, context));
+            Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
 
         let mut name = cursor.spelling();
         assert!(!name.is_empty(), "Empty function name?");
 
         if cursor.kind() == CXCursor_Destructor {
             // Remove the leading `~`. The alternative to this is special-casing
             // code-generation for destructor functions, which seems less than
             // ideal.
diff --git a/third_party/rust/bindgen/src/ir/item.rs b/third_party/rust/bindgen/src/ir/item.rs
index 89ab2569a04e..91ec22b34bc1 100644
--- a/third_party/rust/bindgen/src/ir/item.rs
+++ b/third_party/rust/bindgen/src/ir/item.rs
@@ -1084,68 +1084,68 @@ impl DotAttributes for Item {
     fn dot_attributes<W>(
         &self,
         ctx: &BindgenContext,
         out: &mut W,
     ) -> io::Result<()>
     where
         W: io::Write,
     {
-        try!(writeln!(
+        writeln!(
             out,
             "<tr><td>{:?}</td></tr>
                        <tr><td>name</td><td>{}</td></tr>",
             self.id,
             self.name(ctx).get()
-        ));
+        )?;
 
         if self.is_opaque(ctx, &()) {
             writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
         }
 
         self.kind.dot_attributes(ctx, out)
     }
 }
 
 impl<T> TemplateParameters for T
 where
     T: Copy + Into<ItemId>
 {
     fn self_template_params(
         &self,
         ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
-        ctx.resolve_item_fallible(*self).and_then(|item| {
+    ) -> Vec<TypeId> {
+        ctx.resolve_item_fallible(*self).map_or(vec![], |item| {
             item.self_template_params(ctx)
         })
     }
 }
 
 impl TemplateParameters for Item {
     fn self_template_params(
         &self,
         ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
+    ) -> Vec<TypeId> {
         self.kind.self_template_params(ctx)
     }
 }
 
 impl TemplateParameters for ItemKind {
     fn self_template_params(
         &self,
         ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
+    ) -> Vec<TypeId> {
         match *self {
             ItemKind::Type(ref ty) => ty.self_template_params(ctx),
             // If we start emitting bindings to explicitly instantiated
             // functions, then we'll need to check ItemKind::Function for
             // template params.
             ItemKind::Function(_) |
             ItemKind::Module(_) |
-            ItemKind::Var(_) => None,
+            ItemKind::Var(_) => vec![],
         }
     }
 }
 
 // An utility function to handle recursing inside nested types.
 fn visit_child(
     cur: clang::Cursor,
     id: ItemId,
@@ -1444,18 +1444,18 @@ impl ClangItemParser for Item {
         {
 
             if ty.is_associated_type() ||
                 location.cur_type().is_associated_type()
             {
                 return Ok(Item::new_opaque_type(id, ty, ctx));
             }
 
-            if let Some(id) = Item::type_param(Some(id), location, ctx) {
-                return Ok(id);
+            if let Some(param_id) = Item::type_param(None, location, ctx) {
+                return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
             }
         }
 
         let decl = {
             let decl = ty.declaration();
             decl.definition().unwrap_or(decl)
         };
 
diff --git a/third_party/rust/bindgen/src/ir/item_kind.rs b/third_party/rust/bindgen/src/ir/item_kind.rs
index 58f99d0cabfe..1e755e242ac3 100644
--- a/third_party/rust/bindgen/src/ir/item_kind.rs
+++ b/third_party/rust/bindgen/src/ir/item_kind.rs
@@ -130,21 +130,21 @@ impl DotAttributes for ItemKind {
     fn dot_attributes<W>(
         &self,
         ctx: &BindgenContext,
         out: &mut W,
     ) -> io::Result<()>
     where
         W: io::Write,
     {
-        try!(writeln!(
+        writeln!(
             out,
             "<tr><td>kind</td><td>{}</td></tr>",
             self.kind_name()
-        ));
+        )?;
 
         match *self {
             ItemKind::Module(ref module) => module.dot_attributes(ctx, out),
             ItemKind::Type(ref ty) => ty.dot_attributes(ctx, out),
             ItemKind::Function(ref func) => func.dot_attributes(ctx, out),
             ItemKind::Var(ref var) => var.dot_attributes(ctx, out),
         }
     }
diff --git a/third_party/rust/bindgen/src/ir/layout.rs b/third_party/rust/bindgen/src/ir/layout.rs
index 0c99c7e77c6a..cca33cc3456b 100644
--- a/third_party/rust/bindgen/src/ir/layout.rs
+++ b/third_party/rust/bindgen/src/ir/layout.rs
@@ -1,65 +1,73 @@
 //! Intermediate representation for the physical layout of some type.
 
 use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug,
                     CanTriviallyDeriveDefault, CanTriviallyDeriveHash,
                     CanTriviallyDerivePartialEqOrPartialOrd, CanDerive};
 use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
+use ir::context::BindgenContext;
 use clang;
-use std::{cmp, mem};
+use std::cmp;
 
 /// A type that represents the struct layout of a type.
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub struct Layout {
     /// The size (in bytes) of this layout.
     pub size: usize,
     /// The alignment (in bytes) of this layout.
     pub align: usize,
     /// Whether this layout's members are packed or not.
     pub packed: bool,
 }
 
 #[test]
 fn test_layout_for_size() {
+    use std::mem;
+
     let ptr_size = mem::size_of::<*mut ()>();
-    assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size));
     assert_eq!(
-        Layout::for_size(3 * ptr_size),
+        Layout::for_size_internal(ptr_size, ptr_size),
+        Layout::new(ptr_size, ptr_size)
+    );
+    assert_eq!(
+        Layout::for_size_internal(ptr_size, 3 * ptr_size),
         Layout::new(3 * ptr_size, ptr_size)
     );
 }
 
 impl Layout {
     /// Construct a new `Layout` with the given `size` and `align`. It is not
     /// packed.
     pub fn new(size: usize, align: usize) -> Self {
         Layout {
             size,
             align,
             packed: false,
         }
     }
 
-    /// Creates a non-packed layout for a given size, trying to use the maximum
-    /// alignment possible.
-    pub fn for_size(size: usize) -> Self {
+    fn for_size_internal(ptr_size: usize, size: usize) -> Self {
         let mut next_align = 2;
-        while size % next_align == 0 &&
-            next_align <= mem::size_of::<*mut ()>()
-        {
+        while size % next_align == 0 && next_align <= ptr_size {
             next_align *= 2;
         }
         Layout {
             size: size,
             align: next_align / 2,
             packed: false,
         }
     }
 
+    /// Creates a non-packed layout for a given size, trying to use the maximum
+    /// alignment possible.
+    pub fn for_size(ctx: &BindgenContext, size: usize) -> Self {
+        Self::for_size_internal(ctx.target_pointer_size(), size)
+    }
+
     /// Is this a zero-sized layout?
     pub fn is_zero(&self) -> bool {
         self.size == 0 && self.align == 0
     }
 
     /// Construct a zero-sized layout.
     pub fn zero() -> Self {
         Self::new(0, 0)
@@ -75,17 +83,18 @@ impl Layout {
 #[derive(Clone, Debug, PartialEq)]
 pub struct Opaque(pub Layout);
 
 impl Opaque {
     /// Construct a new opaque type from the given clang type.
     pub fn from_clang_ty(ty: &clang::Type) -> Type {
         let layout = Layout::new(ty.size(), ty.align());
         let ty_kind = TypeKind::Opaque;
-        Type::new(None, Some(layout), ty_kind, false)
+        let is_const = ty.is_const();
+        Type::new(None, Some(layout), ty_kind, is_const)
     }
 
     /// Return the known rust type we should use to create a correctly-aligned
     /// field with this layout.
     pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
         Some(match self.0.align {
             8 => "u64",
             4 => "u32",
diff --git a/third_party/rust/bindgen/src/ir/objc.rs b/third_party/rust/bindgen/src/ir/objc.rs
index 0f72c39917ce..46c0802e872f 100644
--- a/third_party/rust/bindgen/src/ir/objc.rs
+++ b/third_party/rust/bindgen/src/ir/objc.rs
@@ -8,16 +8,17 @@ use clang;
 use clang_sys::CXChildVisit_Continue;
 use clang_sys::CXCursor_ObjCCategoryDecl;
 use clang_sys::CXCursor_ObjCClassMethodDecl;
 use clang_sys::CXCursor_ObjCClassRef;
 use clang_sys::CXCursor_ObjCInstanceMethodDecl;
 use clang_sys::CXCursor_ObjCProtocolDecl;
 use clang_sys::CXCursor_ObjCProtocolRef;
 use quote;
+use proc_macro2::{Term, Span};
 
 /// Objective C interface as used in TypeKind
 ///
 /// Also protocols and categories are parsed as this type
 #[derive(Debug)]
 pub struct ObjCInterface {
     /// The name
     /// like, NSObject
@@ -211,17 +212,17 @@ impl ObjCMethod {
         self.is_class_method
     }
 
     /// Formats the method call
     pub fn format_method_call(&self, args: &[quote::Tokens]) -> quote::Tokens {
         let split_name: Vec<_> = self.name
             .split(':')
             .filter(|p| !p.is_empty())
-            .map(quote::Ident::new)
+            .map(|name| Term::new(name, Span::call_site()))
             .collect();
 
         // No arguments
         if args.len() == 0 && split_name.len() == 1 {
             let name = &split_name[0];
             return quote! {
                 #name
             };
@@ -234,19 +235,20 @@ impl ObjCMethod {
                 args,
                 split_name
             );
         }
 
         // Get arguments without type signatures to pass to `msg_send!`
         let mut args_without_types = vec![];
         for arg in args.iter() {
-            let name_and_sig: Vec<&str> = arg.as_str().split(' ').collect();
+            let arg = arg.to_string();
+            let name_and_sig: Vec<&str> = arg.split(' ').collect();
             let name = name_and_sig[0];
-            args_without_types.push(quote::Ident::new(name))
+            args_without_types.push(Term::new(name, Span::call_site()))
         };
 
         let args = split_name
             .into_iter()
             .zip(args_without_types)
             .map(|(arg, arg_val)| quote! { #arg : #arg_val });
 
         quote! {
diff --git a/third_party/rust/bindgen/src/ir/template.rs b/third_party/rust/bindgen/src/ir/template.rs
index 11a799f4f640..61654fe888ba 100644
--- a/third_party/rust/bindgen/src/ir/template.rs
+++ b/third_party/rust/bindgen/src/ir/template.rs
@@ -76,112 +76,93 @@ use parse::ClangItemParser;
 /// ```
 ///
 /// The following table depicts the results of each trait method when invoked on
 /// each of the declarations above:
 ///
 /// +------+----------------------+--------------------------+------------------------+----
 /// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ...
 /// +------+----------------------+--------------------------+------------------------+----
-/// |Foo   | Some([T, U])         | Some(2)                  | Some([T, U])           | ...
-/// |Bar   | Some([V])            | Some(1)                  | Some([T, U, V])        | ...
-/// |Inner | None                 | None                     | Some([T, U])           | ...
-/// |Lol   | Some([W])            | Some(1)                  | Some([T, U, W])        | ...
-/// |Wtf   | Some([X])            | Some(1)                  | Some([T, U, X])        | ...
-/// |Qux   | None                 | None                     | None                   | ...
+/// |Foo   | [T, U]               | 2                        | [T, U]                 | ...
+/// |Bar   | [V]                  | 1                        | [T, U, V]              | ...
+/// |Inner | []                   | 0                        | [T, U]                 | ...
+/// |Lol   | [W]                  | 1                        | [T, U, W]              | ...
+/// |Wtf   | [X]                  | 1                        | [T, U, X]              | ...
+/// |Qux   | []                   | 0                        | []                     | ...
 /// +------+----------------------+--------------------------+------------------------+----
 ///
 /// ----+------+-----+----------------------+
 /// ... |Decl. | ... | used_template_params |
 /// ----+------+-----+----------------------+
-/// ... |Foo   | ... | Some([T, U])         |
-/// ... |Bar   | ... | Some([V])            |
-/// ... |Inner | ... | None                 |
-/// ... |Lol   | ... | Some([T])            |
-/// ... |Wtf   | ... | Some([T])            |
-/// ... |Qux   | ... | None                 |
+/// ... |Foo   | ... | [T, U]               |
+/// ... |Bar   | ... | [V]                  |
+/// ... |Inner | ... | []                   |
+/// ... |Lol   | ... | [T]                  |
+/// ... |Wtf   | ... | [T]                  |
+/// ... |Qux   | ... | []                   |
 /// ----+------+-----+----------------------+
 pub trait TemplateParameters {
     /// Get the set of `ItemId`s that make up this template declaration's free
     /// template parameters.
     ///
     /// Note that these might *not* all be named types: C++ allows
     /// constant-value template parameters as well as template-template
     /// parameters. Of course, Rust does not allow generic parameters to be
     /// anything but types, so we must treat them as opaque, and avoid
     /// instantiating them.
     fn self_template_params(&self, ctx: &BindgenContext)
-        -> Option<Vec<TypeId>>;
+        -> Vec<TypeId>;
 
     /// Get the number of free template parameters this template declaration
     /// has.
-    ///
-    /// Implementations *may* return `Some` from this method when
-    /// `template_params` returns `None`. This is useful when we only have
-    /// partial information about the template declaration, such as when we are
-    /// in the middle of parsing it.
-    fn num_self_template_params(&self, ctx: &BindgenContext) -> Option<usize> {
-        self.self_template_params(ctx).map(|params| params.len())
+    fn num_self_template_params(&self, ctx: &BindgenContext) -> usize {
+        self.self_template_params(ctx).len()
     }
 
     /// Get the complete set of template parameters that can affect this
     /// declaration.
     ///
     /// Note that this item doesn't need to be a template declaration itself for
     /// `Some` to be returned here (in contrast to `self_template_params`). If
     /// this item is a member of a template declaration, then the parent's
     /// template parameters are included here.
     ///
     /// In the example above, `Inner` depends on both of the `T` and `U` type
     /// parameters, even though it is not itself a template declaration and
     /// therefore has no type parameters itself. Perhaps it helps to think about
     /// how we would fully reference such a member type in C++:
     /// `Foo<int,char>::Inner`. `Foo` *must* be instantiated with template
     /// arguments before we can gain access to the `Inner` member type.
-    fn all_template_params(&self, ctx: &BindgenContext) -> Option<Vec<TypeId>>
+    fn all_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
     where
         Self: ItemAncestors,
     {
-        let each_self_params: Vec<Vec<_>> = self.ancestors(ctx)
-            .filter_map(|id| id.self_template_params(ctx))
-            .collect();
-        if each_self_params.is_empty() {
-            None
-        } else {
-            Some(
-                each_self_params
-                    .into_iter()
-                    .rev()
-                    .flat_map(|params| params)
-                    .collect(),
-            )
-        }
+        let ancestors: Vec<_> = self.ancestors(ctx).collect();
+        ancestors.into_iter().rev().flat_map(|id| {
+            id.self_template_params(ctx).into_iter()
+        }).collect()
     }
 
     /// Get only the set of template parameters that this item uses. This is a
     /// subset of `all_template_params` and does not necessarily contain any of
     /// `self_template_params`.
-    fn used_template_params(&self, ctx: &BindgenContext) -> Option<Vec<TypeId>>
+    fn used_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
     where
         Self: AsRef<ItemId>,
     {
         assert!(
             ctx.in_codegen_phase(),
             "template parameter usage is not computed until codegen"
         );
 
         let id = *self.as_ref();
-        ctx.resolve_item(id).all_template_params(ctx).map(
-            |all_params| {
-                all_params
+        ctx.resolve_item(id).all_template_params(ctx)
                     .into_iter()
                     .filter(|p| ctx.uses_template_parameter(id, *p))
                     .collect()
-            },
-        )
     }
 }
 
 /// A trait for things which may or may not be a named template type parameter.
 pub trait AsTemplateParam {
     /// Any extra information the implementor might need to make this decision.
     type Extra;
 
diff --git a/third_party/rust/bindgen/src/ir/traversal.rs b/third_party/rust/bindgen/src/ir/traversal.rs
index b9b3179a00fd..c37b0b5f859c 100644
--- a/third_party/rust/bindgen/src/ir/traversal.rs
+++ b/third_party/rust/bindgen/src/ir/traversal.rs
@@ -196,21 +196,23 @@ impl TraversalPredicate for for<'a> fn(&'a BindgenContext, Edge) -> bool {
 
 /// A `TraversalPredicate` implementation that follows all edges, and therefore
 /// traversals using this predicate will see the whole IR graph reachable from
 /// the traversal's roots.
 pub fn all_edges(_: &BindgenContext, _: Edge) -> bool {
     true
 }
 
-/// A `TraversalPredicate` implementation that never follows any edges, and
-/// therefore traversals using this predicate will only visit the traversal's
-/// roots.
-pub fn no_edges(_: &BindgenContext, _: Edge) -> bool {
-    false
+/// A `TraversalPredicate` implementation that only follows
+/// `EdgeKind::InnerType` edges, and therefore traversals using this predicate
+/// will only visit the traversal's roots and their inner types. This is used
+/// in no-recursive-whitelist mode, where inner types such as anonymous
+/// structs/unions still need to be processed.
+pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool {
+    edge.kind == EdgeKind::InnerType
 }
 
 /// A `TraversalPredicate` implementation that only follows edges to items that
 /// are enabled for code generation. This lets us skip considering items for
 /// which are not reachable from code generation.
 pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool {
     let cc = &ctx.options().codegen_config;
     match edge.kind {
@@ -464,20 +466,17 @@ impl<'ctx, Storage, Queue, Predicate> Iterator
 where
     Storage: TraversalStorage<'ctx>,
     Queue: TraversalQueue,
     Predicate: TraversalPredicate,
 {
     type Item = ItemId;
 
     fn next(&mut self) -> Option<Self::Item> {
-        let id = match self.queue.next() {
-            None => return None,
-            Some(id) => id,
-        };
+        let id = self.queue.next()?;
 
         let newly_discovered = self.seen.add(None, id);
         debug_assert!(
             !newly_discovered,
             "should have already seen anything we get out of our queue"
         );
         debug_assert!(
             self.ctx.resolve_item_fallible(id).is_some(),
diff --git a/third_party/rust/bindgen/src/ir/ty.rs b/third_party/rust/bindgen/src/ir/ty.rs
index e14860c26b22..b805dd624568 100644
--- a/third_party/rust/bindgen/src/ir/ty.rs
+++ b/third_party/rust/bindgen/src/ir/ty.rs
@@ -11,17 +11,16 @@ use super::layout::{Layout, Opaque};
 use super::objc::ObjCInterface;
 use super::template::{AsTemplateParam, TemplateInstantiation,
                       TemplateParameters};
 use super::traversal::{EdgeKind, Trace, Tracer};
 use clang::{self, Cursor};
 use parse::{ClangItemParser, ParseError, ParseResult};
 use std::borrow::Cow;
 use std::io;
-use std::mem;
 
 /// The base representation of a type in bindgen.
 ///
 /// A type has an optional name, which if present cannot be empty, a `layout`
 /// (size, alignment and packedness) if known, a `Kind`, which determines which
 /// kind of type it is, and whether the type is const.
 #[derive(Debug)]
 pub struct Type {
@@ -227,28 +226,26 @@ impl Type {
                 ctx.resolve_type(inner).is_incomplete_array(ctx)
             }
             _ => None,
         }
     }
 
     /// What is the layout of this type?
     pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
-        use std::mem;
-
         self.layout.or_else(|| {
             match self.kind {
                 TypeKind::Comp(ref ci) => ci.layout(ctx),
                 // FIXME(emilio): This is a hack for anonymous union templates.
                 // Use the actual pointer size!
                 TypeKind::Pointer(..) |
                 TypeKind::BlockPointer => {
                     Some(Layout::new(
-                        mem::size_of::<*mut ()>(),
-                        mem::align_of::<*mut ()>(),
+                        ctx.target_pointer_size(),
+                        ctx.target_pointer_size(),
                     ))
                 }
                 TypeKind::ResolvedTypeRef(inner) => {
                     ctx.resolve_type(inner).layout(ctx)
                 }
                 _ => None,
             }
         })
@@ -418,30 +415,30 @@ impl DotAttributes for Type {
         &self,
         ctx: &BindgenContext,
         out: &mut W,
     ) -> io::Result<()>
     where
         W: io::Write,
     {
         if let Some(ref layout) = self.layout {
-            try!(writeln!(
+            writeln!(
                 out,
                 "<tr><td>size</td><td>{}</td></tr>
                            <tr><td>align</td><td>{}</td></tr>",
                 layout.size,
                 layout.align
-            ));
+            )?;
             if layout.packed {
-                try!(writeln!(out, "<tr><td>packed</td><td>true</td></tr>"));
+                writeln!(out, "<tr><td>packed</td><td>true</td></tr>")?;
             }
         }
 
         if self.is_const {
-            try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>"));
+            writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
         }
 
         self.kind.dot_attributes(ctx, out)
     }
 }
 
 impl DotAttributes for TypeKind {
     fn dot_attributes<W>(
@@ -538,32 +535,32 @@ fn is_invalid_type_param_empty_name() {
     let ty = Type::new(Some("".into()), None, TypeKind::TypeParam, false);
     assert!(ty.is_invalid_type_param())
 }
 
 impl TemplateParameters for Type {
     fn self_template_params(
         &self,
         ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
+    ) -> Vec<TypeId> {
         self.kind.self_template_params(ctx)
     }
 }
 
 impl TemplateParameters for TypeKind {
     fn self_template_params(
         &self,
         ctx: &BindgenContext,
-    ) -> Option<Vec<TypeId>> {
+    ) -> Vec<TypeId> {
         match *self {
             TypeKind::ResolvedTypeRef(id) => {
                 ctx.resolve_type(id).self_template_params(ctx)
             }
             TypeKind::Comp(ref comp) => comp.self_template_params(ctx),
-            TypeKind::TemplateAlias(_, ref args) => Some(args.clone()),
+            TypeKind::TemplateAlias(_, ref args) => args.clone(),
 
             TypeKind::Opaque |
             TypeKind::TemplateInstantiation(..) |
             TypeKind::Void |
             TypeKind::NullPtr |
             TypeKind::Int(_) |
             TypeKind::Float(_) |
             TypeKind::Complex(_) |
@@ -573,17 +570,17 @@ impl TemplateParameters for TypeKind {
             TypeKind::Pointer(_) |
             TypeKind::BlockPointer |
             TypeKind::Reference(_) |
             TypeKind::UnresolvedTypeRef(..) |
             TypeKind::TypeParam |
             TypeKind::Alias(_) |
             TypeKind::ObjCId |
             TypeKind::ObjCSel |
-            TypeKind::ObjCInterface(_) => None,
+            TypeKind::ObjCInterface(_) => vec![],
         }
     }
 }
 
 /// The kind of float this type represents.
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub enum FloatKind {
     /// A `float`.
@@ -591,27 +588,16 @@ pub enum FloatKind {
     /// A `double`.
     Double,
     /// A `long double`.
     LongDouble,
     /// A `__float128`.
     Float128,
 }
 
-impl FloatKind {
-    /// If this type has a known size, return it (in bytes).
-    pub fn known_size(&self) -> usize {
-        match *self {
-            FloatKind::Float => mem::size_of::<f32>(),
-            FloatKind::Double | FloatKind::LongDouble => mem::size_of::<f64>(),
-            FloatKind::Float128 => mem::size_of::<f64>() * 2,
-        }
-    }
-}
-
 /// The different kinds of types that we can parse.
 #[derive(Debug)]
 pub enum TypeKind {
     /// The void type.
     Void,
 
     /// The `nullptr_t` type.
     NullPtr,
@@ -813,17 +799,17 @@ impl Type {
                 }
                 CXType_Unexposed | CXType_Invalid => {
                     // For some reason Clang doesn't give us any hint in some
                     // situations where we should generate a function pointer (see
                     // tests/headers/func_ptr_in_struct.h), so we do a guess here
                     // trying to see if it has a valid return type.
                     if ty.ret_type().is_some() {
                         let signature =
-                            try!(FunctionSig::from_ty(ty, &location, ctx));
+                            FunctionSig::from_ty(ty, &location, ctx)?;
                         TypeKind::Function(signature)
                     // Same here, with template specialisations we can safely
                     // assume this is a Comp(..)
                     } else if ty.is_fully_instantiated_template() {
                         debug!(
                             "Template specialization: {:?}, {:?} {:?}",
                             ty,
                             location,
@@ -1117,17 +1103,17 @@ impl Type {
                         None,
                         ctx,
                     ).expect("Not able to resolve array element?");
                     TypeKind::Array(inner, 0)
                 }
                 CXType_FunctionNoProto |
                 CXType_FunctionProto => {
                     let signature =
-                        try!(FunctionSig::from_ty(ty, &location, ctx));
+                        FunctionSig::from_ty(ty, &location, ctx)?;
                     TypeKind::Function(signature)
                 }
                 CXType_Typedef => {
                     let inner = cursor.typedef_type().expect("Not valid Type?");
                     let inner =
                         Item::from_ty_or_ref(inner, location, None, ctx);
                     TypeKind::Alias(inner)
                 }
@@ -1203,16 +1189,17 @@ impl Type {
                         location
                     );
                     return Err(ParseError::Continue);
                 }
             }
         };
 
         let name = if name.is_empty() { None } else { Some(name) };
+
         let is_const = ty.is_const();
 
         let ty = Type::new(name, layout, kind, is_const);
         // TODO: maybe declaration.canonical()?
         Ok(ParseResult::New(ty, Some(cursor.canonical())))
     }
 }
 
diff --git a/third_party/rust/bindgen/src/ir/var.rs b/third_party/rust/bindgen/src/ir/var.rs
index 84d6d9a0ab20..25ac56d2cdb0 100644
--- a/third_party/rust/bindgen/src/ir/var.rs
+++ b/third_party/rust/bindgen/src/ir/var.rs
@@ -93,25 +93,25 @@ impl DotAttributes for Var {
         &self,
         _ctx: &BindgenContext,
         out: &mut W,
     ) -> io::Result<()>
     where
         W: io::Write,
     {
         if self.is_const {
-            try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>"));
+            writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
         }
 
         if let Some(ref mangled) = self.mangled_name {
-            try!(writeln!(
+            writeln!(
                 out,
                 "<tr><td>mangled name</td><td>{}</td></tr>",
                 mangled
-            ));
+            )?;
         }
 
         Ok(())
     }
 }
 
 // TODO(emilio): we could make this more (or less) granular, I guess.
 fn default_macro_constant_type(value: i64) -> IntKind {
@@ -302,54 +302,46 @@ impl ClangSubItemParser for Var {
 
 /// Try and parse a macro using all the macros parsed until now.
 fn parse_macro(
     ctx: &BindgenContext,
     cursor: &clang::Cursor,
 ) -> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
     use cexpr::{expr, nom};
 
-    let mut cexpr_tokens = match cursor.cexpr_tokens() {
-        None => return None,
-        Some(tokens) => tokens,
-    };
+    let mut cexpr_tokens = cursor.cexpr_tokens()?;
 
     let parser = expr::IdentifierParser::new(ctx.parsed_macros());
 
     match parser.macro_definition(&cexpr_tokens) {
         nom::IResult::Done(_, (id, val)) => {
             return Some((id.into(), val));
         }
         _ => {}
     }
 
     // Try without the last token, to workaround a libclang bug in versions
     // previous to 4.0.
     //
     // See:
     //   https://bugs.llvm.org//show_bug.cgi?id=9069
     //   https://reviews.llvm.org/D26446
-    if cexpr_tokens.pop().is_none() {
-        return None;
-    }
+    cexpr_tokens.pop()?;
 
     match parser.macro_definition(&cexpr_tokens) {
         nom::IResult::Done(_, (id, val)) => Some((id.into(), val)),
         _ => None,
     }
 }
 
 fn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option<i64> {
     use cexpr::{expr, nom};
     use cexpr::expr::EvalResult;
 
-    let cexpr_tokens = match cursor.cexpr_tokens() {
-        None => return None,
-        Some(tokens) => tokens,
-    };
+    let cexpr_tokens = cursor.cexpr_tokens()?;
 
     // TODO(emilio): We can try to parse other kinds of literals.
     match expr::expr(&cexpr_tokens) {
         nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val),
         _ => None,
     }
 }
 
diff --git a/third_party/rust/bindgen/src/lib.rs b/third_party/rust/bindgen/src/lib.rs
index 1cd64b2e0320..7dd39138ff88 100644
--- a/third_party/rust/bindgen/src/lib.rs
+++ b/third_party/rust/bindgen/src/lib.rs
@@ -1,14 +1,17 @@
 //! Generate Rust bindings for C and C++ libraries.
 //!
 //! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
 //! functions and use types defined in the header.
 //!
 //! See the [`Builder`](./struct.Builder.html) struct for usage.
+//!
+//! See the [Users Guide](https://rust-lang-nursery.github.io/rust-bindgen/) for
+//! additional documentation.
 #![deny(missing_docs)]
 #![deny(warnings)]
 #![deny(unused_extern_crates)]
 // To avoid rather annoying warnings when matching with CXCursor_xxx as a
 // constant.
 #![allow(non_upper_case_globals)]
 // `quote!` nests quite deeply.
 #![recursion_limit="128"]
@@ -18,16 +21,17 @@ extern crate cexpr;
 #[allow(unused_extern_crates)]
 extern crate cfg_if;
 extern crate clang_sys;
 #[macro_use]
 extern crate lazy_static;
 extern crate peeking_take_while;
 #[macro_use]
 extern crate quote;
+extern crate proc_macro2;
 extern crate regex;
 extern crate which;
 
 #[cfg(feature = "logging")]
 #[macro_use]
 extern crate log;
 
 #[cfg(not(feature = "logging"))]
@@ -74,18 +78,20 @@ doc_mod!(parse, parse_docs);
 doc_mod!(regex_set, regex_set_docs);
 
 pub use features::{LATEST_STABLE_RUST, RUST_TARGET_STRINGS, RustTarget};
 use features::RustFeatures;
 use ir::context::{BindgenContext, ItemId};
 use ir::item::Item;
 use parse::{ClangItemParser, ParseError};
 use regex_set::RegexSet;
+pub use codegen::EnumVariation;
 
 use std::borrow::Cow;
+use std::collections::HashMap;
 use std::fs::{File, OpenOptions};
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::sync::Arc;
 
 /// A type used to indicate which kind of items do we have to generate.
@@ -142,24 +148,41 @@ impl Default for CodegenConfig {
 /// Configure and generate Rust bindings for a C/C++ header.
 ///
 /// This is the main entry point to the library.
 ///
 /// ```ignore
 /// use bindgen::builder;
 ///
 /// // Configure and generate bindings.
-/// let bindings = try!(builder().header("path/to/input/header")
-///                              .whitelisted_type("SomeCoolClass")
-///                              .whitelisted_function("do_some_cool_thing")
-///                              .generate());
+/// let bindings = builder().header("path/to/input/header")
+///     .whitelisted_type("SomeCoolClass")
+///     .whitelisted_function("do_some_cool_thing")
+///     .generate()?;
 ///
 /// // Write the generated bindings to an output file.
-/// try!(bindings.write_to_file("path/to/output.rs"));
+/// bindings.write_to_file("path/to/output.rs")?;
 /// ```
+///
+/// # Enums
+///
+/// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on
+/// the pattern passed to several methods:
+///
+/// 1. [`constified_enum_module()`](#method.constified_enum_module)
+/// 2. [`bitfield_enum()`](#method.bitfield_enum)
+/// 3. [`rustified_enum()`](#method.rustified_enum)
+///
+/// For each C enum, bindgen tries to match the pattern in the following order:
+///
+/// 1. Constified enum module
+/// 2. Bitfield enum
+/// 3. Rustified enum
+///
+/// If none of the above patterns match, then bindgen will generate a set of Rust constants.
 #[derive(Debug, Default)]
 pub struct Builder {
     options: BindgenOptions,
     input_headers: Vec<String>,
     // Tuples of unsaved file contents of the form (name, contents).
     input_header_contents: Vec<(String, String)>,
 }
 
@@ -176,16 +199,26 @@ impl Builder {
         if let Some(header) = self.input_headers.last().cloned() {
             // Positional argument 'header'
             output_vector.push(header);
         }
 
         output_vector.push("--rust-target".into());
         output_vector.push(self.options.rust_target.into());
 
+        if self.options.default_enum_style != Default::default() {
+            output_vector.push("--default-enum-variant=".into());
+            output_vector.push(match self.options.default_enum_style {
+                codegen::EnumVariation::Rust => "rust",
+                codegen::EnumVariation::Bitfield => "bitfield",
+                codegen::EnumVariation::Consts => "consts",
+                codegen::EnumVariation::ModuleConsts => "moduleconsts",
+            }.into())
+        }
+
         self.options
             .bitfield_enums
             .get_items()
             .iter()
             .map(|item| {
                 output_vector.push("--bitfield-enum".into());
                 output_vector.push(
                     item.trim_left_matches("^")
@@ -218,16 +251,30 @@ impl Builder {
                 output_vector.push(
                     item.trim_left_matches("^")
                         .trim_right_matches("$")
                         .into(),
                 );
             })
             .count();
 
+        self.options
+            .constified_enums
+            .get_items()
+            .iter()
+            .map(|item| {
+                output_vector.push("--constified-enum".into());
+                output_vector.push(
+                    item.trim_left_matches("^")
+                        .trim_right_matches("$")
+                        .into(),
+                );
+            })
+            .count();
+
         self.options
             .blacklisted_types
             .get_items()
             .iter()
             .map(|item| {
                 output_vector.push("--blacklist-type".into());
                 output_vector.push(
                     item.trim_left_matches("^")
@@ -321,29 +368,16 @@ impl Builder {
         }
         if self.options.enable_cxx_namespaces {
             output_vector.push("--enable-cxx-namespaces".into());
         }
         if self.options.disable_name_namespacing {
             output_vector.push("--disable-name-namespacing".into());
         }
 
-        self.options
-            .links
-            .iter()
-            .map(|&(ref item, _)| {
-                output_vector.push("--framework".into());
-                output_vector.push(
-                    item.trim_left_matches("^")
-                        .trim_right_matches("$")
-                        .into(),
-                );
-            })
-            .count();
-
         if !self.options.codegen_config.functions {
             output_vector.push("--ignore-functions".into());
         }
 
         output_vector.push("--generate".into());
 
         //Temporary placeholder for below 4 options
         let mut options: Vec<String> = Vec::new();
@@ -367,29 +401,16 @@ impl Builder {
         }
 
         output_vector.push(options.join(","));
 
         if !self.options.codegen_config.methods {
             output_vector.push("--ignore-methods".into());
         }
 
-        self.options
-            .links
-            .iter()
-            .map(|&(ref item, _)| {
-                output_vector.push("--clang-args".into());
-                output_vector.push(
-                    item.trim_left_matches("^")
-                        .trim_right_matches("$")
-                        .into(),
-                );
-            })
-            .count();
-
         if !self.options.convert_floats {
             output_vector.push("--no-convert-floats".into());
         }
 
         if !self.options.prepend_enum_name {
             output_vector.push("--no-prepend-enum-name".into());
         }
 
@@ -415,29 +436,16 @@ impl Builder {
                 output_vector.push(
                     item.trim_left_matches("^")
                         .trim_right_matches("$")
                         .into(),
                 );
             })
             .count();
 
-        self.options
-            .links
-            .iter()
-            .map(|&(ref item, _)| {
-                output_vector.push("--static".into());
-                output_vector.push(
-                    item.trim_left_matches("^")
-                        .trim_right_matches("$")
-                        .into(),
-                );
-            })
-            .count();
-
         if self.options.use_core {
             output_vector.push("--use-core".into());
         }
 
         if self.options.conservative_inline_namespaces {
             output_vector.push("--conservative-inline-namespaces".into());
         }
 
@@ -595,16 +603,22 @@ impl Builder {
     /// Specify the rust target
     ///
     /// The default is the latest stable Rust version
     pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
         self.options.set_rust_target(rust_target);
         self
     }
 
+    /// Disable support for native Rust unions, if supported.
+    pub fn disable_untagged_union(mut self) -> Self {
+        self.options.rust_features.untagged_union = false;
+        self
+    }
+
     /// Set the output graphviz file.
     pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
         let path = path.into();
         self.options.emit_ir_graphviz = Some(path);
         self
     }
 
     /// Whether the generated bindings should contain documentation comments or
@@ -637,17 +651,17 @@ impl Builder {
     /// function and the `MoonBoots` struct that it transitively references. By
     /// configuring with `whitelist_recursively(false)`, `bindgen` will not emit
     /// bindings for anything except the explicitly whitelisted items, and there
     /// would be no emitted struct definition for `MoonBoots`. However, the
     /// `initiate_dance_party` function would still reference `MoonBoots`!
     ///
     /// **Disabling this feature will almost certainly cause `bindgen` to emit
     /// bindings that will not compile!** If you disable this feature, then it
-    /// is *your* responsiblity to provide definitions for every type that is
+    /// is *your* responsibility to provide definitions for every type that is
     /// referenced from an explicitly whitelisted item. One way to provide the
     /// definitions is by using the [`Builder::raw_line`](#method.raw_line)
     /// method, another would be to define them in Rust and then `include!(...)`
     /// the bindings immediately afterwards.
     pub fn whitelist_recursively(mut self, doit: bool) -> Self {
         self.options.whitelist_recursively = doit;
         self
     }
@@ -668,17 +682,17 @@ impl Builder {
     /// [1]: https://github.com/rust-lang-nursery/rust-bindgen/issues/528
     pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
         self.options.enable_mangling = doit;
         self
     }
 
     /// Hide the given type from the generated bindings. Regular expressions are
     /// supported.
-    #[deprecated = "Use blacklist_type instead"]
+    #[deprecated(note = "Use blacklist_type instead")]
     pub fn hide_type<T: AsRef<str>>(self, arg: T) -> Builder {
         self.blacklist_type(arg)
     }
 
     /// Hide the given type from the generated bindings. Regular expressions are
     /// supported.
     pub fn blacklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.blacklisted_types.insert(arg);
@@ -690,17 +704,17 @@ impl Builder {
     pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.opaque_types.insert(arg);
         self
     }
 
     /// Whitelist the given type so that it (and all types that it transitively
     /// refers to) appears in the generated bindings. Regular expressions are
     /// supported.
-    #[deprecated = "use whitelist_type instead"]
+    #[deprecated(note = "use whitelist_type instead")]
     pub fn whitelisted_type<T: AsRef<str>>(self, arg: T) -> Builder {
         self.whitelist_type(arg)
     }
 
     /// Whitelist the given type so that it (and all types that it transitively
     /// refers to) appears in the generated bindings. Regular expressions are
     /// supported.
     pub fn whitelist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
@@ -714,37 +728,42 @@ impl Builder {
     pub fn whitelist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.whitelisted_functions.insert(arg);
         self
     }
 
     /// Whitelist the given function.
     ///
     /// Deprecated: use whitelist_function instead.
-    #[deprecated = "use whitelist_function instead"]
+    #[deprecated(note = "use whitelist_function instead")]
     pub fn whitelisted_function<T: AsRef<str>>(self, arg: T) -> Builder {
         self.whitelist_function(arg)
     }
 
     /// Whitelist the given variable so that it (and all types that it
     /// transitively refers to) appears in the generated bindings. Regular
     /// expressions are supported.
     pub fn whitelist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.whitelisted_vars.insert(arg);
         self
     }
 
     /// Whitelist the given variable.
     ///
     /// Deprecated: use whitelist_var instead.
-    #[deprecated = "use whitelist_var instead"]
+    #[deprecated(note = "use whitelist_var instead")]
     pub fn whitelisted_var<T: AsRef<str>>(self, arg: T) -> Builder {
         self.whitelist_var(arg)
     }
 
+    /// Set the default style of code to generate for enums
+    pub fn default_enum_style(mut self, arg: codegen::EnumVariation) -> Builder {
+        self.options.default_enum_style = arg;
+        self
+    }
 
     /// Mark the given enum (or set of enums, if using a pattern) as being
     /// bitfield-like. Regular expressions are supported.
     ///
     /// This makes bindgen generate a type that isn't a rust `enum`. Regular
     /// expressions are supported.
     pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.bitfield_enums.insert(arg);
@@ -761,33 +780,69 @@ impl Builder {
     /// you have complete control of the C/C++ code that you're binding to.
     /// Take a look at https://github.com/rust-lang/rust/issues/36927 for
     /// more information.
     pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.rustified_enums.insert(arg);
         self
     }
 
+    /// Mark the given enum (or set of enums, if using a pattern) as a set of
+    /// constants that are not to be put into a module.
+    pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+        self.options.constified_enums.insert(arg);
+        self
+    }
+
     /// Mark the given enum (or set of enums, if using a pattern) as a set of
     /// constants that should be put into a module.
     ///
     /// This makes bindgen generate modules containing constants instead of
     /// just constants. Regular expressions are supported.
     pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
         self.options.constified_enum_modules.insert(arg);
         self
     }
 
     /// Add a string to prepend to the generated bindings. The string is passed
     /// through without any modification.
-    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
+    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
         self.options.raw_lines.push(arg.into());
         self
     }
 
+    /// Add a given line to the beginning of module `mod`.
+    pub fn module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self
+    where
+        T: Into<String>,
+        U: Into<String>,
+    {
+        self.options
+            .module_lines
+            .entry(mod_.into())
+            .or_insert_with(Vec::new)
+            .push(line.into());
+        self
+    }
+
+    /// Add a given set of lines to the beginning of module `mod`.
+    pub fn module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self
+    where
+        T: Into<String>,
+        I: IntoIterator,
+        I::Item: Into<String>,
+    {
+        self.options
+            .module_lines
+            .entry(mod_.into())
+            .or_insert_with(Vec::new)
+            .extend(lines.into_iter().map(Into::into));
+        self
+    }
+
     /// Add an argument to be passed straight through to clang.
     pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
         self.options.clang_args.push(arg.into());
         self
     }
 
     /// Add arguments to be passed straight through to clang.
     pub fn clang_args<I>(mut self, iter: I) -> Builder
@@ -796,36 +851,16 @@ impl Builder {
         I::Item: AsRef<str>,
     {
         for arg in iter {
             self = self.clang_arg(arg.as_ref())
         }
         self
     }
 
-    /// Make the generated bindings link the given shared library.
-    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
-        self.options.links.push((library.into(), LinkType::Default));
-        self
-    }
-
-    /// Make the generated bindings link the given static library.
-    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
-        self.options.links.push((library.into(), LinkType::Static));
-        self
-    }
-
-    /// Make the generated bindings link the given framework.
-    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
-        self.options.links.push(
-            (library.into(), LinkType::Framework),
-        );
-        self
-    }
-
     /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
     /// in the generated Rust.
     pub fn emit_builtins(mut self) -> Builder {
         self.options.builtins = true;
         self
     }
 
     /// Avoid converting floats to `f32`/`f64` by default.
@@ -1237,31 +1272,34 @@ struct BindgenOptions {
     whitelisted_types: RegexSet,
 
     /// Whitelisted functions. See docs for `whitelisted_types` for more.
     whitelisted_functions: RegexSet,
 
     /// Whitelisted variables. See docs for `whitelisted_types` for more.
     whitelisted_vars: RegexSet,
 
+    /// The default style of code to generate for enums
+    default_enum_style: codegen::EnumVariation,
+
     /// The enum patterns to mark an enum as bitfield.
     bitfield_enums: RegexSet,
 
     /// The enum patterns to mark an enum as a Rust enum.
     rustified_enums: RegexSet,
 
     /// The enum patterns to mark an enum as a module of constants.
     constified_enum_modules: RegexSet,
 
+    /// The enum patterns to mark an enum as a set of constants.
+    constified_enums: RegexSet,
+
     /// Whether we should generate builtins or not.
     builtins: bool,
 
-    /// The set of libraries we should link in the generated Rust code.
-    links: Vec<(String, LinkType)>,
-
     /// True if we should dump the Clang AST for debugging purposes.
     emit_ast: bool,
 
     /// True if we should dump our internal IR for debugging purposes.
     emit_ir: bool,
 
     /// Output graphviz dot file.
     emit_ir_graphviz: Option<String>,
@@ -1276,17 +1314,17 @@ struct BindgenOptions {
     /// True if we should generate layout tests for generated structures.
     layout_tests: bool,
 
     /// True if we should implement the Debug trait for C/C++ structures and types
     /// that do not support automatically deriving Debug.
     impl_debug: bool,
 
     /// True if we should implement the PartialEq trait for C/C++ structures and types
-    /// that do not support autoamically deriving PartialEq.
+    /// that do not support automatically deriving PartialEq.
     impl_partialeq: bool,
 
     /// True if we should derive Copy trait implementations for C/C++ structures
     /// and types.
     derive_copy: bool,
 
     /// True if we should derive Debug trait implementations for C/C++ structures
     /// and types.
@@ -1330,19 +1368,25 @@ struct BindgenOptions {
     namespaced_constants: bool,
 
     /// True if we should use MSVC name mangling rules.
     msvc_mangling: bool,
 
     /// Whether we should convert float types to f32/f64 types.
     convert_floats: bool,
 
-    /// The set of raw lines to prepend to the generated Rust code.
+    /// The set of raw lines to prepend to the top-level module of generated
+    /// Rust code.
     raw_lines: Vec<String>,
 
+    /// The set of raw lines to prepend to each of the modules.
+    ///
+    /// This only makes sense if the `enable_cxx_namespaces` option is set.
+    module_lines: HashMap<String, Vec<String>>,
+
     /// The set of arguments to pass straight through to Clang.
     clang_args: Vec<String>,
 
     /// The input header file.
     input_header: Option<String>,
 
     /// Unsaved files for input.
     input_unsaved_files: Vec<clang::UnsavedFile>,
@@ -1355,27 +1399,27 @@ struct BindgenOptions {
     /// of them.
     codegen_config: CodegenConfig,
 
     /// Whether to treat inline namespaces conservatively.
     ///
     /// See the builder method description for more details.
     conservative_inline_namespaces: bool,
 
-    /// Wether to keep documentation comments in the generated output. See the
+    /// Whether to keep documentation comments in the generated output. See the
     /// documentation for more details.
     generate_comments: bool,
 
     /// Whether to generate inline functions. Defaults to false.
     generate_inline_functions: bool,
 
-    /// Wether to whitelist types recursively. Defaults to true.
+    /// Whether to whitelist types recursively. Defaults to true.
     whitelist_recursively: bool,
 
-    /// Intead of emitting 'use objc;' to files generated from objective c files,
+    /// Instead of emitting 'use objc;' to files generated from objective c files,
     /// generate '#[macro_use] extern crate objc;'
     objc_extern_crate: bool,
 
     /// Whether to use the clang-provided name mangling. This is true and
     /// probably needed for C++ features.
     ///
     /// However, some old libclang versions seem to return incorrect results in
     /// some cases for non-mangled functions, see [1], so we allow disabling it.
@@ -1418,16 +1462,17 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
 impl BindgenOptions {
     fn build(&mut self) {
         self.whitelisted_vars.build();
         self.whitelisted_types.build();
         self.whitelisted_functions.build();
         self.blacklisted_types.build();
         self.opaque_types.build();
         self.bitfield_enums.build();
+        self.constified_enums.build();
         self.constified_enum_modules.build();
         self.rustified_enums.build();
         self.no_partialeq_types.build();
         self.no_copy_types.build();
         self.no_hash_types.build();
     }
 
     /// Update rust target version
@@ -1452,21 +1497,22 @@ impl Default for BindgenOptions {
             rust_target: rust_target,
             rust_features: rust_target.into(),
             blacklisted_types: Default::default(),
             opaque_types: Default::default(),
             rustfmt_path: Default::default(),
             whitelisted_types: Default::default(),
             whitelisted_functions: Default::default(),
             whitelisted_vars: Default::default(),
+            default_enum_style: Default::default(),
             bitfield_enums: Default::default(),
             rustified_enums: Default::default(),
+            constified_enums: Default::default(),
             constified_enum_modules: Default::default(),
             builtins: false,
-            links: vec![],
             emit_ast: false,
             emit_ir: false,
             emit_ir_graphviz: None,
             layout_tests: true,
             impl_debug: false,
             impl_partialeq: false,
             derive_copy: true,
             derive_debug: true,
@@ -1479,16 +1525,17 @@ impl Default for BindgenOptions {
             enable_cxx_namespaces: false,
             disable_name_namespacing: false,
             use_core: false,
             ctypes_prefix: None,
             namespaced_constants: true,
             msvc_mangling: false,
             convert_floats: true,
             raw_lines: vec![],
+            module_lines: HashMap::default(),
             clang_args: vec![],
             input_header: None,
             input_unsaved_files: vec![],
             parse_callbacks: None,
             codegen_config: CodegenConfig::all(),
             conservative_inline_namespaces: false,
             generate_comments: true,
             generate_inline_functions: false,
@@ -1501,29 +1548,16 @@ impl Default for BindgenOptions {
             rustfmt_configuration_file: None,
             no_partialeq_types: Default::default(),
             no_copy_types: Default::default(),
             no_hash_types: Default::default(),
         }
     }
 }
 
-/// The linking type to use with a given library.
-///
-/// TODO: #104: This is ignored at the moment, but shouldn't be.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub enum LinkType {
-    /// Use shared library linking. This is the default.
-    Default,
-    /// Use static linking.
-    Static,
-    /// The library is an OSX framework.
-    Framework,
-}
-
 fn ensure_libclang_is_loaded() {
     if clang_sys::is_loaded() {
         return;
     }
 
     // XXX (issue #350): Ensure that our dynamically loaded `libclang`
     // doesn't get dropped prematurely, nor is loaded multiple times
     // across different threads.
@@ -1643,17 +1677,17 @@ impl Bindings {
         }
 
         let time_phases = options.time_phases;
         let mut context = BindgenContext::new(options);
 
         {
             let _t = time::Timer::new("parse")
                                   .with_output(time_phases);
-            try!(parse(&mut context));
+            parse(&mut context)?;
         }
 
         let (items, options) = codegen::codegen(context);
 
         Ok(Bindings {
             options: options,
             module: quote! {
                 #( #items )*
@@ -1691,25 +1725,25 @@ impl Bindings {
             writer.write(line.as_bytes())?;
             writer.write("\n".as_bytes())?;
         }
 
         if !self.options.raw_lines.is_empty() {
             writer.write("\n".as_bytes())?;
         }
 
-        let bindings = self.module.as_str().to_string();
+        let bindings = self.module.to_string();
 
         match self.rustfmt_generated_string(&bindings) {
             Ok(rustfmt_bindings) => {
                 writer.write(rustfmt_bindings.as_bytes())?;
             },
             Err(err) => {
                 eprintln!("{:?}", err);
-                writer.write(bindings.as_str().as_bytes())?;
+                writer.write(bindings.as_bytes())?;
             },
         }
         Ok(())
     }
 
     /// Checks if rustfmt_bindings is set and runs rustfmt on the string
     fn rustfmt_generated_string<'a>(
         &self,
@@ -1860,23 +1894,23 @@ fn parse(context: &mut BindgenContext) -> Result<(), ()> {
         "How did this happen?"
     );
     Ok(())
 }
 
 /// Extracted Clang version data
 #[derive(Debug)]
 pub struct ClangVersion {
-    /// Major and minor semvar, if parsing was successful
+    /// Major and minor semver, if parsing was successful
     pub parsed: Option<(u32, u32)>,
     /// full version string
     pub full: String,
 }
 
-/// Get the major and the minor semvar numbers of Clang's version
+/// Get the major and the minor semver numbers of Clang's version
 pub fn clang_version() -> ClangVersion {
     if !clang_sys::is_loaded() {
         // TODO(emilio): Return meaningful error (breaking).
         clang_sys::load().expect("Unable to find libclang");
     }
 
     let raw_v: String = clang::extract_clang_version();
     let split_v: Option<Vec<&str>> = raw_v.split_whitespace().nth(2).map(|v| {
diff --git a/third_party/rust/bindgen/src/options.rs b/third_party/rust/bindgen/src/options.rs
index 4079603cd432..5169fb9a28b6 100644
--- a/third_party/rust/bindgen/src/options.rs
+++ b/third_party/rust/bindgen/src/options.rs
@@ -1,9 +1,9 @@
-use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder};
+use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder, EnumVariation};
 use clap::{App, Arg};
 use std::fs::File;
 use std::io::{self, Error, ErrorKind, Write, stderr};
 use std::path::PathBuf;
 use std::str::FromStr;
 
 /// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
 pub fn builder_from_flags<I>(
@@ -21,36 +21,50 @@ where
     let matches = App::new("bindgen")
         .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"))
         .about("Generates Rust bindings from C/C++ headers.")
         .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
         .args(&[
             Arg::with_name("header")
                 .help("C or C++ header file")
                 .required(true),
+            Arg::with_name("default-enum-style")
+                .long("default-enum-style")
+                .help("The default style of code used to generate enums.")
+                .value_name("variant")
+                .default_value("consts")
+                .possible_values(&["consts", "moduleconsts", "bitfield", "rust"])
+                .multiple(false),
             Arg::with_name("bitfield-enum")
                 .long("bitfield-enum")
                 .help("Mark any enum whose name matches <regex> as a set of \
-                       bitfield flags instead of an enumeration.")
+                       bitfield flags.")
                 .value_name("regex")
                 .takes_value(true)
                 .multiple(true)
                 .number_of_values(1),
             Arg::with_name("rustified-enum")
                 .long("rustified-enum")
-                .help("Mark any enum whose name matches <regex> as a Rust enum \
-                       instead of a set of constants.")
+                .help("Mark any enum whose name matches <regex> as a Rust enum.")
+                .value_name("regex")
+                .takes_value(true)
+                .multiple(true)
+                .number_of_values(1),
+            Arg::with_name("constified-enum")
+                .long("constified-enum")
+                .help("Mark any enum whose name matches <regex> as a series of \
+                       constants.")
                 .value_name("regex")
                 .takes_value(true)
                 .multiple(true)
                 .number_of_values(1),
             Arg::with_name("constified-enum-module")
                 .long("constified-enum-module")
                 .help("Mark any enum whose name matches <regex> as a module of \
-                       constants instead of just constants.")
+                       constants.")
                 .value_name("regex")
                 .takes_value(true)
                 .multiple(true)
                 .number_of_values(1),
             Arg::with_name("blacklist-type")
                 .long("blacklist-type")
                 .help("Mark <type> as hidden.")
                 .value_name("type")
@@ -144,42 +158,29 @@ where
             Arg::with_name("enable-cxx-namespaces")
                 .long("enable-cxx-namespaces")
                 .help("Enable support for C++ namespaces."),
             Arg::with_name("disable-name-namespacing")
                 .long("disable-name-namespacing")
                 .help("Disable namespacing via mangling, causing bindgen to \
                        generate names like \"Baz\" instead of \"foo_bar_Baz\" \
                        for an input name \"foo::bar::Baz\"."),
-            Arg::with_name("framework")
-                .long("framework-link")
-                .help("Link to framework.")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
             Arg::with_name("ignore-functions")
                 .long("ignore-functions")
                 .help("Do not generate bindings for functions or methods. This \
                        is useful when you only care about struct layouts."),
             Arg::with_name("generate")
                 .long("generate")
                 .help("Generate only given items, split by commas. \
                        Valid values are \"functions\",\"types\", \"vars\", \
                        \"methods\", \"constructors\" and \"destructors\".")
                 .takes_value(true),
             Arg::with_name("ignore-methods")
                 .long("ignore-methods")
                 .help("Do not generate bindings for methods."),
-            Arg::with_name("dynamic")
-                .short("l")
-                .long("link")
-                .help("Link to dynamic library.")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
             Arg::with_name("no-convert-floats")
                 .long("no-convert-floats")
                 .help("Do not automatically convert floats to f32/f64."),
             Arg::with_name("no-prepend-enum-name")
                 .long("no-prepend-enum-name")
                 .help("Do not prepend the enum name to bitfield or constant variants."),
             Arg::with_name("unstable-rust")
                 .long("unstable-rust")
@@ -202,22 +203,16 @@ where
                 .help("Add a raw line of Rust code at the beginning of output.")
                 .takes_value(true)
                 .multiple(true)
                 .number_of_values(1),
             Arg::with_name("rust-target")
                 .long("rust-target")
                 .help(&rust_target_help)
                 .takes_value(true),
-            Arg::with_name("static")
-                .long("static-link")
-                .help("Link to static library.")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
             Arg::with_name("use-core")
                 .long("use-core")
                 .help("Use types from Rust core instead of std."),
             Arg::with_name("conservative-inline-namespaces")
                 .long("conservative-inline-namespaces")
                 .help("Conservatively generate inline namespaces to avoid name \
                        conflicts."),
             Arg::with_name("use-msvc-mangling")
@@ -317,28 +312,38 @@ where
             "warning: the `--unstable-rust` option is deprecated"
         ).expect("Unable to write error message");
     }
 
     if let Some(rust_target) = matches.value_of("rust-target") {
         builder = builder.rust_target(RustTarget::from_str(rust_target)?);
     }
 
+    if let Some(variant) = matches.value_of("default-enum-style") {
+        builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
+    }
+
     if let Some(bitfields) = matches.values_of("bitfield-enum") {
         for regex in bitfields {
             builder = builder.bitfield_enum(regex);
         }
     }
 
     if let Some(rustifieds) = matches.values_of("rustified-enum") {
         for regex in rustifieds {
             builder = builder.rustified_enum(regex);
         }
     }
 
+    if let Some(bitfields) = matches.values_of("constified-enum") {
+        for regex in bitfields {
+            builder = builder.constified_enum(regex);
+        }
+    }
+
     if let Some(constified_mods) = matches.values_of("constified-enum-module") {
         for regex in constified_mods {
             builder = builder.constified_enum_module(regex);
         }
     }
     if let Some(hidden_types) = matches.values_of("blacklist-type") {
         for ty in hidden_types {
             builder = builder.blacklist_type(ty);
@@ -404,22 +409,16 @@ where
     if matches.is_present("time-phases") {
         builder = builder.time_phases(true);
     }
 
     if let Some(prefix) = matches.value_of("ctypes-prefix") {
         builder = builder.ctypes_prefix(prefix);
     }
 
-    if let Some(links) = matches.values_of("dynamic") {
-        for library in links {
-            builder = builder.link(library);
-        }
-    }
-
     if let Some(what_to_generate) = matches.value_of("generate") {
         let mut config = CodegenConfig::nothing();
         for what in what_to_generate.split(",") {
             match what {
                 "functions" => config.functions = true,
                 "types" => config.types = true,
                 "vars" => config.vars = true,
                 "methods" => config.methods = true,
@@ -451,22 +450,16 @@ where
     if matches.is_present("enable-cxx-namespaces") {
         builder = builder.enable_cxx_namespaces();
     }
 
     if matches.is_present("disable-name-namespacing") {
         builder = builder.disable_name_namespacing();
     }
 
-    if let Some(links) = matches.values_of("framework") {
-        for framework in links {
-            builder = builder.link_framework(framework);
-        }
-    }
-
     if matches.is_present("ignore-functions") {
         builder = builder.ignore_functions();
     }
 
     if matches.is_present("ignore-methods") {
         builder = builder.ignore_methods();
     }
 
@@ -493,22 +486,16 @@ where
     }
 
     if let Some(lines) = matches.values_of("raw-line") {
         for line in lines {
             builder = builder.raw_line(line);
         }
     }
 
-    if let Some(links) = matches.values_of("static") {
-        for library in links {
-            builder = builder.link_static(library);
-        }
-    }
-
     if matches.is_present("use-core") {
         builder = builder.use_core();
     }
 
     if matches.is_present("distrust-clang-mangling") {
         builder = builder.trust_clang_mangling(false);
     }
 
@@ -540,17 +527,17 @@ where
 
     if let Some(args) = matches.values_of("clang-args") {
         for arg in args {
             builder = builder.clang_arg(arg);
         }
     }
 
     let output = if let Some(path) = matches.value_of("output") {
-        let file = try!(File::create(path));
+        let file = File::create(path)?;
         Box::new(io::BufWriter::new(file)) as Box<io::Write>
     } else {
         Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
     };
 
     if matches.is_present("dump-preprocessed-input") {
         builder.dump_preprocessed_input()?;
     }
diff --git a/third_party/rust/bindgen/src/time.rs b/third_party/rust/bindgen/src/time.rs
index c841bccff427..5bd0da8d61da 100644
--- a/third_party/rust/bindgen/src/time.rs
+++ b/third_party/rust/bindgen/src/time.rs
@@ -17,17 +17,17 @@ impl<'a> Timer<'a> {
     pub fn new(name: &'a str) -> Self {
         Timer {
             output: true,
             name,
             start: Instant::now()
         }
     }
 
-    /// Sets whether or not the Timer will print a mesage
+    /// Sets whether or not the Timer will print a message
     /// when it is dropped.
     pub fn with_output(mut self, output: bool) -> Self {
         self.output = output;
         self
     }
 
     /// Returns the time elapsed since the timer's creation
     pub fn elapsed(&self) -> Duration {
diff --git a/third_party/rust/clang-sys/.cargo-checksum.json b/third_party/rust/clang-sys/.cargo-checksum.json
index bc8859904e84..29d6230c0160 100644
--- a/third_party/rust/clang-sys/.cargo-checksum.json
+++ b/third_party/rust/clang-sys/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"136bc7c0b31a2317ca827c49b25aac46ae685e0c401a783a9b0505bb1405b30b","CHANGELOG.md":"ceef7978611ef048a460d1f0adf7d0691c79b5633896f119b7a772141805a0c4","CONTRIBUTING.md":"4e2a45992604f07a37030bb1fc598c6f54a1785747c4f37a15a37481bbdecce8","Cargo.toml":"4bc5eb5d8417ec3803017855be3b927844c998fbd1ad38e336a1ea0f79dd939e","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"3f0af7f23c53b744eb9725149c5619fdac5d2cd127baec23dc7ec9bbea6bd541","appveyor.yml":"c9ab8ab1ab028b27d2be176e994a0d6a255cf8bcc36e15868472b6b8abf33fac","build.rs":"acc5929fb75a7a84f18c8beb804dfe7c5c585a3be492e988938df07c54a1b37b","ci/before_install.sh":"711c9d0539fa0372980c3a288d9482a0e46d3ba0fb8f7c7c110d6488a8ec4de5","ci/install.bat":"828b814fbbda1c0df09de728913f2cd438f3006f2574dc79a857459ab49d38c2","ci/script.sh":"1bb1cd29bd9635cc126cdcbd6c02f3500620a231a86726bf2165a4b74baaf433","ci/test_script.bat":"73462f51aaa9a1c14ce9f55c41dc3672df64faa9789725384ae4f28d8ba3c90b","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"8cb04fe36afba7bff961e18bbfd228c3253af8683949237b563f8f9125313706","src/link.rs":"9ba06ee65e445ca30b43844e654302565f023afb310e8a37f08a5150451ce76e","src/support.rs":"9929cdf5ad0896248938282d0e621be34855bca9a1eb6b7a02a174ace58a9d86","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"e5e8a60bcaec3b5d043fde4a993d397adb56454d0b2a6adaa15df0535246f909"},"package":"00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"}
\ No newline at end of file
+{"files":{".travis.yml":"d5c89494c836e00ec8c3c02c9e228bf5dc34aabff203c37662a248e2da4bda05","CHANGELOG.md":"62fd8ba43afbc4da3dba40d448a5af482794aaaa99071d40dc7abf8fc1a2195b","Cargo.toml":"1ada60cd29713d4386050d2b61a9eed430827885520816b0412ed0380fa3fa8f","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"dff1b472fe1edbc6059ff5a96e595fa8dab9e9e133d10fd761cf5dfdcc80f4c6","appveyor.yml":"c9ab8ab1ab028b27d2be176e994a0d6a255cf8bcc36e15868472b6b8abf33fac","build.rs":"50be9c247e528ab0a354a7652fa9516906f79bbb4d128d54db7f5a9ee1ed2a86","ci/before_install.sh":"711c9d0539fa0372980c3a288d9482a0e46d3ba0fb8f7c7c110d6488a8ec4de5","ci/install.bat":"fb636c3511ba038ccf805755ef6542237cc595e905edcd61d56abd7163321f76","ci/script.sh":"1bb1cd29bd9635cc126cdcbd6c02f3500620a231a86726bf2165a4b74baaf433","ci/test_script.bat":"73462f51aaa9a1c14ce9f55c41dc3672df64faa9789725384ae4f28d8ba3c90b","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"d0a11284694f4f77448e72480addca613572d19c07fa92157e0fa717ed504abd","src/link.rs":"a0208e6b8e4840f1162b3b799b5e12dd559cc6f31a330b0eb1ba4ebe2385296d","src/support.rs":"70e77ea4337f740b13c394034c5705e962af6ee7ac4843fc7c9c7fe22ec2d074","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"e5e8a60bcaec3b5d043fde4a993d397adb56454d0b2a6adaa15df0535246f909"},"package":"d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"}
\ No newline at end of file
diff --git a/third_party/rust/clang-sys/.travis.yml b/third_party/rust/clang-sys/.travis.yml
index 34c7c6dccca4..b587b8d728ac 100644
--- a/third_party/rust/clang-sys/.travis.yml
+++ b/third_party/rust/clang-sys/.travis.yml
@@ -4,30 +4,23 @@ addons:
   apt:
     sources:
       - ubuntu-toolchain-r-test
     packages:
       - gcc-5
 
 os:
   - linux
-  - osx
 
 rust: stable
 
 env:
   - LLVM_VERSION=3.5 CLANG_VERSION=clang_3_5
   - LLVM_VERSION=5.0 CLANG_VERSION=clang_5_0
 
-# FIXME: I have no idea why this build is failing.
-matrix:
-  allow_failures:
-    - os: osx
-      env: LLVM_VERSION=5.0 CLANG_VERSION=clang_5_0
-
 cache:
   directories:
     - $HOME/.cargo
     - $HOME/.llvm
 
 before_install: . ./ci/before_install.sh
 
 script: . ./ci/script.sh
diff --git a/third_party/rust/clang-sys/CHANGELOG.md b/third_party/rust/clang-sys/CHANGELOG.md
index de9ac5090efe..612bf2458eee 100644
--- a/third_party/rust/clang-sys/CHANGELOG.md
+++ b/third_party/rust/clang-sys/CHANGELOG.md
@@ -1,8 +1,26 @@
+## [0.23.0] - 2018-06-16
+
+### Changed
+- Changed `Clang::find` to skip dynamic libraries for an incorrect architecture on Windows
+
+## [0.22.0] - 2018-03-11
+
+### Added
+- Added support for `clang` 6.0.x
+- Bumped `libc` version to `0.2.39`
+- Bumped `libloading` version to `0.5.0`
+
+## [0.21.2] - 2018-02-17
+
+### Changed
+- Added original errors to error messages
+- Added support for searching for libraries in `LD_LIBRARY_PATH` directories
+
 ## [0.21.1] - 2017-11-24
 
 ### Changed
 - Improved finding of versioned libraries (e.g., `libclang-3.9.so`)
 
 ### Fixed
 * Fixed compilation failures on the beta and nightly channels caused by a [compiler bug](https://github.com/KyleMayes/clang-sys/pull/69)
 
diff --git a/third_party/rust/clang-sys/CONTRIBUTING.md b/third_party/rust/clang-sys/CONTRIBUTING.md
deleted file mode 100644
index d9eda482ed08..000000000000
--- a/third_party/rust/clang-sys/CONTRIBUTING.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Contributing to clang-sys
-
-## Pull Requests
-
-If you are intending to make a pull request, please make your changes in a branch that originated
-from the `development` branch, not the `master` branch. Then, make your pull request against the
-`development` branch.
diff --git a/third_party/rust/clang-sys/Cargo.toml b/third_party/rust/clang-sys/Cargo.toml
index 5fa6000b2dc4..3a7452d7c430 100644
--- a/third_party/rust/clang-sys/Cargo.toml
+++ b/third_party/rust/clang-sys/Cargo.toml
@@ -7,53 +7,47 @@
 #
 # 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 = "clang-sys"
-version = "0.21.1"
+version = "0.23.0"
 authors = ["Kyle Mayes <kyle@mayeses.com>"]
 build = "build.rs"
 links = "clang"
 description = "Rust bindings for libclang."
 documentation = "https://kylemayes.github.io/clang-sys/3_5/clang_sys"
 readme = "README.md"
 license = "Apache-2.0"
 repository = "https://github.com/KyleMayes/clang-sys"
-[dependencies.clippy]
-version = "0.0.*"
-optional = true
-
 [dependencies.glob]
 version = "0.2.11"
 
 [dependencies.libc]
-version = "0.2.14"
+version = "0.2.39"
 
 [dependencies.libloading]
-version = "0.4.0"
+version = "0.5.0"
 optional = true
-[build-dependencies.clippy]
-version = "0.0.*"
-optional = true
-
 [build-dependencies.glob]
 version = "0.2.11"
 
 [features]
 clang_3_5 = []
 clang_3_6 = ["gte_clang_3_6"]
 clang_3_7 = ["gte_clang_3_6", "gte_clang_3_7"]
 clang_3_8 = ["gte_clang_3_6", "gte_clang_3_7", "gte_clang_3_8"]
 clang_3_9 = ["gte_clang_3_6", "gte_clang_3_7", "gte_clang_3_8", "gte_clang_3_9"]
 clang_4_0 = ["gte_clang_3_6", "gte_clang_3_7", "gte_clang_3_8", "gte_clang_3_9", "gte_clang_4_0"]
 clang_5_0 = ["gte_clang_3_6", "gte_clang_3_7", "gte_clang_3_8", "gte_clang_3_9", "gte_clang_4_0", "gte_clang_5_0"]
+clang_6_0 = ["gte_clang_3_6", "gte_clang_3_7", "gte_clang_3_8", "gte_clang_3_9", "gte_clang_4_0", "gte_clang_5_0", "gte_clang_6_0"]
 gte_clang_3_6 = []
 gte_clang_3_7 = []
 gte_clang_3_8 = []
 gte_clang_3_9 = []
 gte_clang_4_0 = []
 gte_clang_5_0 = []
+gte_clang_6_0 = []
 runtime = ["libloading"]
 static = []
diff --git a/third_party/rust/clang-sys/README.md b/third_party/rust/clang-sys/README.md
index e82e7515824a..29205b5a2c50 100644
--- a/third_party/rust/clang-sys/README.md
+++ b/third_party/rust/clang-sys/README.md
@@ -28,16 +28,18 @@ To target a version of `libclang`, enable one of the following Cargo features:
 * `clang_3_8` - requires `libclang` 3.8 or later
   ([Documentation](https://kylemayes.github.io/clang-sys/3_8/clang_sys))
 * `clang_3_9` - requires `libclang` 3.9 or later
   ([Documentation](https://kylemayes.github.io/clang-sys/3_9/clang_sys))
 * `clang_4_0` - requires `libclang` 4.0 or later
   ([Documentation](https://kylemayes.github.io/clang-sys/4_0/clang_sys))
 * `clang_5_0` - requires `libclang` 5.0 or later
   ([Documentation](https://kylemayes.github.io/clang-sys/5_0/clang_sys))
+* `clang_6_0` - requires `libclang` 6.0 or later
+  ([Documentation](https://kylemayes.github.io/clang-sys/6_0/clang_sys))
 
 If you do not enable one of these features, the API provided by `libclang` 3.5 will be available by
 default.
 
 ## Dependencies
 
 By default, this crate will attempt to link to `libclang` dynamically. In this case, this crate
 depends on the `libclang` shared library (`libclang.so` on Linux, `libclang.dylib` on OS X,
@@ -65,31 +67,32 @@ order of preference:
 library. This means you cannot link to any of these versions of `libclang` statically unless you
 build it from source.
 
 ## Environment Variables
 
 The following environment variables, if set, are used by this crate to find the required libraries
 and executables:
 
-* `LLVM_CONFIG_PATH` **(compile time)** - provides a path to an `llvm-config` executable
-* `LIBCLANG_PATH` **(compile time)** - provides a path to a directory containing a `libclang` shared
+* `LLVM_CONFIG_PATH` **(compiletime)** - provides a path to an `llvm-config` executable
+* `LIBCLANG_PATH` **(compiletime)** - provides a path to a directory containing a `libclang` shared
   library
-* `LIBCLANG_STATIC_PATH` **(compile time)** - provides a path to a directory containing LLVM and
+* `LIBCLANG_STATIC_PATH` **(compiletime)** - provides a path to a directory containing LLVM and
   Clang static libraries
-* `CLANG_PATH` **(run time)** - provides a path to a `clang` executable
+* `CLANG_PATH` **(runtime)** - provides a path to a `clang` executable
 
 ## Linking
 
 ### Dynamic
 
 First, the `libclang` shared library will be searched for in the directory provided by the
 `LIBCLANG_PATH` environment variable if it was set. If this fails, the directory returned by
-`llvm-config --libdir` will be searched. If neither of these approaches is successful, a list of
-likely directories will be searched (e.g., `/usr/local/lib` on Linux).
+`llvm-config --libdir` will be searched. Failing that, the directories in the `LD_LIBRARY_PATH`
+environment variable will be searched. If none of these approaches is successful, a list of likely
+directories will be searched (e.g., `/usr/local/lib` on Linux).
 
 On Linux, running an executable that has been dynamically linked to `libclang` may require you to
 add a path to `libclang.so` to the `LD_LIBRARY_PATH` environment variable. The same is true on OS
 X, except the `DYLD_LIBRARY_PATH` environment variable is used instead.
 
 On Windows, running an executable that has been dynamically linked to `libclang` requires that
 `libclang.dll` can be found by the executable at runtime. See
 [here](https://msdn.microsoft.com/en-us/library/7d83bc18.aspx) for more information.
diff --git a/third_party/rust/clang-sys/build.rs b/third_party/rust/clang-sys/build.rs
index e9050b8b3772..4066301eeccd 100644
--- a/third_party/rust/clang-sys/build.rs
+++ b/third_party/rust/clang-sys/build.rs
@@ -20,25 +20,21 @@
 //! static or dynamic libraries.
 //!
 //! * `LLVM_CONFIG_PATH` - provides a path to an `llvm-config` executable
 //! * `LIBCLANG_PATH` - provides a path to a directory containing a `libclang` shared library
 //! * `LIBCLANG_STATIC_PATH` - provides a path to a directory containing LLVM and Clang static libraries
 
 #![allow(unused_attributes)]
 
-#![cfg_attr(feature="clippy", feature(plugin))]
-#![cfg_attr(feature="clippy", plugin(clippy))]
-#![cfg_attr(feature="clippy", warn(clippy))]
-
 extern crate glob;
 
 use std::env;
 use std::fs::{self, File};
-use std::io::{Read};
+use std::io::{Read, Seek, SeekFrom};
 use std::path::{Path, PathBuf};
 use std::process::{Command};
 
 use glob::{MatchOptions};
 
 /// Returns the version in the supplied file if one can be found.
 fn find_version(file: &str) -> Option<&str> {
     if file.starts_with("libclang.so.") {
@@ -123,43 +119,85 @@ const SEARCH_OSX: &[&str] = &[
 
 /// Backup search directory globs for Windows.
 const SEARCH_WINDOWS: &[&str] = &[
     "C:\\LLVM\\lib",
     "C:\\Program Files*\\LLVM\\lib",
     "C:\\MSYS*\\MinGW*\\lib",
 ];
 
+/// Returns the ELF class from the ELF header in the supplied file.
+fn parse_elf_header(file: &PathBuf) -> Result<u8, String> {
+    let mut file = try!(File::open(file).map_err(|e| e.to_string()));
+    let mut elf = [0; 5];
+    try!(file.read_exact(&mut elf).map_err(|e| e.to_string()));
+    if elf[..4] == [127, 69, 76, 70] {
+        Ok(elf[4])
+    } else {
+        Err("invalid ELF header".into())
+    }
+}
+
+/// Returns the magic number from the PE header in the supplied file.
+fn parse_pe_header(file: &PathBuf) -> Result<u16, String> {
+    let mut file = try!(File::open(file).map_err(|e| e.to_string()));
+    let mut pe = [0; 4];
+
+    // Determine the header offset.
+    try!(file.seek(SeekFrom::Start(0x3C)).map_err(|e| e.to_string()));
+    try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
+    let offset = i32::from(pe[0]) + (i32::from(pe[1]) << 8) + (i32::from(pe[2]) << 16) + (i32::from(pe[3]) << 24);
+
+    // Determine the validity of the header.
+    try!(file.seek(SeekFrom::Start(offset as u64)).map_err(|e| e.to_string()));
+    try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
+    if pe != [80, 69, 0, 0] {
+        return Err("invalid PE header".into());
+    }
+
+    // Find the magic number.
+    try!(file.seek(SeekFrom::Current(20)).map_err(|e| e.to_string()));
+    try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
+    Ok(u16::from(pe[0]) + (u16::from(pe[1]) << 8))
+}
+
 /// Indicates the type of library being searched for.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum Library {
     Dynamic,
     Static,
 }
 
 impl Library {
     /// Checks whether the supplied file is a valid library for the architecture.
     fn check(&self, file: &PathBuf) -> Result<(), String> {
         if cfg!(any(target_os="freebsd", target_os="linux")) {
             if *self == Library::Static {
                 return Ok(());
             }
-            let mut file = try!(File::open(file).map_err(|e| e.to_string()));
-            let mut elf = [0; 5];
-            try!(file.read_exact(&mut elf).map_err(|e| e.to_string()));
-            if elf[..4] != [127, 69, 76, 70] {
-                return Err("invalid ELF header".into());
-            }
-            if cfg!(target_pointer_width="32") && elf[4] != 1 {
+            let class = try!(parse_elf_header(file));
+            if cfg!(target_pointer_width="32") && class != 1 {
                 return Err("invalid ELF class (64-bit)".into());
             }
-            if cfg!(target_pointer_width="64") && elf[4] != 2 {
+            if cfg!(target_pointer_width="64") && class != 2 {
                 return Err("invalid ELF class (32-bit)".into());
             }
             Ok(())
+        } else if cfg!(target_os="windows") {
+            if *self == Library::Static {
+                return Ok(());
+            }
+            let magic = try!(parse_pe_header(file));
+            if cfg!(target_pointer_width="32") && magic != 267 {
+                return Err("invalid DLL (64-bit)".into());
+            }
+            if cfg!(target_pointer_width="64") && magic != 523 {
+                return Err("invalid DLL (32-bit)".into());
+            }
+            Ok(())
         } else {
             Ok(())
         }
     }
 }
 
 /// Searches for a library, returning the directory it can be found in if the search was successful.
 fn find(library: Library, files: &[String], env: &str) -> Result<PathBuf, String> {
@@ -209,16 +247,23 @@ fn find(library: Library, files: &[String], env: &str) -> Result<PathBuf, String
             try_file!(file);
         }
         let lib = directory.join("lib");
         if let Some(file) = contains(&lib, files) {
             try_file!(file);
         }
     }
 
+    // Search the `LD_LIBRARY_PATH` directories.
+    if let Ok(path) = env::var("LD_LIBRARY_PATH") {
+        for directory in path.split(':').map(Path::new) {
+            search_directory!(directory);
+        }
+    }
+
     // Search the backup directories.
     let search = if cfg!(any(target_os="freebsd", target_os="linux")) {
         SEARCH_LINUX
     } else if cfg!(target_os="macos") {
         SEARCH_OSX
     } else if cfg!(target_os="windows") {
         SEARCH_WINDOWS
     } else {
diff --git a/third_party/rust/clang-sys/ci/install.bat b/third_party/rust/clang-sys/ci/install.bat
index 84fd55de247a..065d0dd7ce9f 100644
--- a/third_party/rust/clang-sys/ci/install.bat
+++ b/third_party/rust/clang-sys/ci/install.bat
@@ -1,8 +1,8 @@
-curl -sSf https://static.rust-lang.org/dist/rust-1.22.1-i686-pc-windows-msvc.exe -o rust.exe
+curl -sSf https://static.rust-lang.org/dist/rust-1.24.0-i686-pc-windows-msvc.exe -o rust.exe
 rust.exe /VERYSILENT /NORESTART /DIR="C:\Rust"
 set PATH=%PATH%;C:\Rust\bin
 
 curl -sSf http://releases.llvm.org/%LLVM_VERSION%/LLVM-%LLVM_VERSION%-win32.exe -o LLVM.exe
 7z x LLVM.exe -oC:\LLVM
 set PATH=%PATH%;C:\LLVM\bin
 set LIBCLANG_PATH=C:\LLVM\bin
diff --git a/third_party/rust/clang-sys/src/lib.rs b/third_party/rust/clang-sys/src/lib.rs
index b750b9d9c224..7e9dfe740aaa 100644
--- a/third_party/rust/clang-sys/src/lib.rs
+++ b/third_party/rust/clang-sys/src/lib.rs
@@ -18,37 +18,37 @@
 //!
 //! * 3.5 - [Documentation](https://kylemayes.github.io/clang-sys/3_5/clang_sys)
 //! * 3.6 - [Documentation](https://kylemayes.github.io/clang-sys/3_6/clang_sys)
 //! * 3.7 - [Documentation](https://kylemayes.github.io/clang-sys/3_7/clang_sys)
 //! * 3.8 - [Documentation](https://kylemayes.github.io/clang-sys/3_8/clang_sys)
 //! * 3.9 - [Documentation](https://kylemayes.github.io/clang-sys/3_9/clang_sys)
 //! * 4.0 - [Documentation](https://kylemayes.github.io/clang-sys/4_0/clang_sys)
 //! * 5.0 - [Documentation](https://kylemayes.github.io/clang-sys/5_0/clang_sys)
+//! * 6.0 - [Documentation](https://kylemayes.github.io/clang-sys/6_0/clang_sys)
 
 #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
 
-#![cfg_attr(feature="clippy", feature(plugin))]
-#![cfg_attr(feature="clippy", plugin(clippy))]
-#![cfg_attr(feature="clippy", warn(clippy))]
-#![cfg_attr(feature="clippy", allow(unreadable_literal))]
+#![cfg_attr(feature="cargo-clippy", allow(unreadable_literal))]
 
 extern crate glob;
 extern crate libc;
 #[cfg(feature="runtime")]
 extern crate libloading;
 
 pub mod support;
 
 #[macro_use]
 mod link;
 
 use std::mem;
 
 use libc::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong, c_void, time_t};
+#[cfg(feature="gte_clang_6_0")]
+use libc::{size_t};
 
 pub type CXClientData = *mut c_void;
 pub type CXCursorVisitor = extern fn(CXCursor, CXCursor, CXClientData) -> CXChildVisitResult;
 #[cfg(feature="gte_clang_3_7")]
 pub type CXFieldVisitor = extern fn(CXCursor, CXClientData) -> CXVisitorResult;
 pub type CXInclusionVisitor = extern fn(CXFile, *mut CXSourceLocation, c_uint, CXClientData);
 
 //================================================
@@ -648,16 +648,25 @@ cenum! {
     enum CXSaveError {
         const CXSaveError_None = 0,
         const CXSaveError_Unknown = 1,
         const CXSaveError_TranslationErrors = 2,
         const CXSaveError_InvalidTU = 3,
     }
 }
 
+cenum! {
+    #[cfg(feature="gte_clang_6_0")]
+    enum CXTLSKind {
+        const CXTLS_None = 0,
+        const CXTLS_Dynamic = 1,
+        const CXTLS_Static = 2,
+    }
+}
+
 cenum! {
     enum CXTUResourceUsageKind {
         const CXTUResourceUsage_AST = 1,
         const CXTUResourceUsage_Identifiers = 2,
         const CXTUResourceUsage_Selectors = 3,
         const CXTUResourceUsage_GlobalCompletionResults = 4,
         const CXTUResourceUsage_SourceManagerContentCache = 5,
         const CXTUResourceUsage_AST_SideTables = 6,
@@ -729,16 +738,18 @@ cenum! {
         const CXType_Dependent = 26,
         const CXType_ObjCId = 27,
         const CXType_ObjCClass = 28,
         const CXType_ObjCSel = 29,
         /// Only produced by `libclang` 3.9 and later.
         const CXType_Float128 = 30,
         /// Only produced by `libclang` 5.0 and later.
         const CXType_Half = 31,
+        /// Only produced by `libclang` 6.0 and later.
+        const CXType_Float16 = 32,
         const CXType_Complex = 100,
         const CXType_Pointer = 101,
         const CXType_BlockPointer = 102,
         const CXType_LValueReference = 103,
         const CXType_RValueReference = 104,
         const CXType_Record = 105,
         const CXType_Enum = 106,
         const CXType_Typedef = 107,
@@ -1453,32 +1464,36 @@ default!(IndexerCallbacks);
 // Functions
 //================================================
 
 link! {
     pub fn clang_CXCursorSet_contains(set: CXCursorSet, cursor: CXCursor) -> c_uint;
     pub fn clang_CXCursorSet_insert(set: CXCursorSet, cursor: CXCursor) -> c_uint;
     pub fn clang_CXIndex_getGlobalOptions(index: CXIndex) -> CXGlobalOptFlags;
     pub fn clang_CXIndex_setGlobalOptions(index: CXIndex, flags: CXGlobalOptFlags);
+    #[cfg(feature="gte_clang_6_0")]
+    pub fn clang_CXIndex_setInvocationEmissionPathOption(index: CXIndex, path: *const c_char);
     #[cfg(feature="gte_clang_3_9")]
     pub fn clang_CXXConstructor_isConvertingConstructor(cursor: CXCursor) -> c_uint;
     #[cfg(feature="gte_clang_3_9")]
     pub fn clang_CXXConstructor_isCopyConstructor(cursor: CXCursor) -> c_uint;
     #[cfg(feature="gte_clang_3_9")]
     pub fn clang_CXXConstructor_isDefaultConstructor(cursor: CXCursor) -> c_uint;
     #[cfg(feature="gte_clang_3_9")]
     pub fn clang_CXXConstructor_isMoveConstructor(cursor: CXCursor) -> c_uint;
     #[cfg(feature="gte_clang_3_8")]
     pub fn clang_CXXField_isMutable(cursor: CXCursor) -> c_uint;
     pub fn clang_CXXMethod_isConst(cursor: CXCursor) -> c_uint;
     #[cfg(feature="gte_clang_3_9")]
     pub fn clang_CXXMethod_isDefaulted(cursor: CXCursor) -> c_uint;
     pub fn clang_CXXMethod_isPureVirtual(cursor: CXCursor) -> c_uint;
     pub fn clang_CXXMethod_isStatic(cursor: CXCursor) -> c_uint;
     pub fn clang_CXXMethod_isVirtual(cursor: CXCursor) -> c_uint;
+    #[cfg(feature="gte_clang_6_0")]
+    pub fn clang_CXXRecord_isAbstract(cursor: CXCursor) -> c_uint;
     pub fn clang_CompilationDatabase_dispose(database: CXCompilationDatabase);
     pub fn clang_CompilationDatabase_fromDirectory(directory: *const c_char, error: *mut CXCompilationDatabase_Error) -> CXCompilationDatabase;
     pub fn clang_CompilationDatabase_getAllCompileCommands(database: CXCompilationDatabase) -> CXCompileCommands;
     pub fn clang_CompilationDatabase_getCompileCommands(database: CXCompilationDatabase, filename: *const c_char) -> CXCompileCommands;
     pub fn clang_CompileCommand_getArg(command: CXCompileCommand, index: c_uint) -> CXString;
     pub fn clang_CompileCommand_getDirectory(command: CXCompileCommand) -> CXString;
     #[cfg(feature="gte_clang_3_8")]
     pub fn clang_CompileCommand_getFilename(command: CXCompileCommand) -> CXString;
@@ -1499,16 +1514,18 @@ link! {
     pub fn clang_Cursor_getCommentRange(cursor: CXCursor) -> CXSourceRange;
     #[cfg(feature="gte_clang_3_6")]
     pub fn clang_Cursor_getMangling(cursor: CXCursor) -> CXString;
     pub fn clang_Cursor_getModule(cursor: CXCursor) -> CXModule;
     pub fn clang_Cursor_getNumArguments(cursor: CXCursor) -> c_int;
     #[cfg(feature="gte_clang_3_6")]
     pub fn clang_Cursor_getNumTemplateArguments(cursor: CXCursor) -> c_int;
     pub fn clang_Cursor_getObjCDeclQualifiers(cursor: CXCursor) -> CXObjCDeclQualifierKind;
+    #[cfg(feature="gte_clang_6_0")]
+    pub fn clang_Cursor_getObjCManglings(cursor: CXCursor) -> *mut CXStringSet;
     pub fn clang_Cursor_getObjCPropertyAttributes(cursor: CXCursor, reserved: c_uint) -> CXObjCPropertyAttrKind;
     pub fn clang_Cursor_getObjCSelectorIndex(cursor: CXCursor) -> c_int;
     #[cfg(feature="gte_clang_3_7")]
     pub fn clang_Cursor_getOffsetOfField(cursor: CXCursor) -> c_longlong;
     pub fn clang_Cursor_getRawCommentText(cursor: CXCursor) -> CXString;
     pub fn clang_Cursor_getReceiverType(cursor: CXCursor) -> CXType;
     pub fn clang_Cursor_getSpellingNameRange(cursor: CXCursor, index: c_uint, reserved: c_uint) -> CXSourceRange;
     #[cfg(feature="gte_clang_3_6")]
@@ -1679,16 +1696,18 @@ link! {
     pub fn clang_getCursorLinkage(cursor: CXCursor) -> CXLinkageKind;
     pub fn clang_getCursorLocation(cursor: CXCursor) -> CXSourceLocation;
     pub fn clang_getCursorPlatformAvailability(cursor: CXCursor, deprecated: *mut c_int, deprecated_message: *mut CXString, unavailable: *mut c_int, unavailable_message: *mut CXString, availability: *mut CXPlatformAvailability, n_availability: c_int) -> c_int;
     pub fn clang_getCursorReferenceNameRange(cursor: CXCursor, flags: CXNameRefFlags, index: c_uint) -> CXSourceRange;
     pub fn clang_getCursorReferenced(cursor: CXCursor) -> CXCursor;
     pub fn clang_getCursorResultType(cursor: CXCursor) -> CXType;
     pub fn clang_getCursorSemanticParent(cursor: CXCursor) -> CXCursor;
     pub fn clang_getCursorSpelling(cursor: CXCursor) -> CXString;
+    #[cfg(feature="gte_clang_6_0")]
+    pub fn clang_getCursorTLSKind(cursor: CXCursor) -> CXTLSKind;
     pub fn clang_getCursorType(cursor: CXCursor) -> CXType;
     pub fn clang_getCursorUSR(cursor: CXCursor) -> CXString;
     #[cfg(feature="gte_clang_3_8")]
     pub fn clang_getCursorVisibility(cursor: CXCursor) -> CXVisibilityKind;
     pub fn clang_getDeclObjCTypeEncoding(cursor: CXCursor) -> CXString;
     pub fn clang_getDefinitionSpellingAndExtent(cursor: CXCursor, start: *mut *const c_char, end: *mut *const c_char, start_line: *mut c_uint, start_column: *mut c_uint, end_line: *mut c_uint, end_column: *mut c_uint);
     pub fn clang_getDiagnostic(tu: CXTranslationUnit, index: c_uint) -> CXDiagnostic;
     pub fn clang_getDiagnosticCategory(diagnostic: CXDiagnostic) -> c_uint;
@@ -1708,16 +1727,18 @@ link! {
     pub fn clang_getEnumConstantDeclUnsignedValue(cursor: CXCursor) -> c_ulonglong;
     pub fn clang_getEnumConstantDeclValue(cursor: CXCursor) -> c_longlong;
     pub fn clang_getEnumDeclIntegerType(cursor: CXCursor) -> CXType;
     #[cfg(feature="gte_clang_5_0")]
     pub fn clang_getExceptionSpecificationType(type_: CXType) -> CXCursor_ExceptionSpecificationKind;
     pub fn clang_getExpansionLocation(location: CXSourceLocation, file: *mut CXFile, line: *mut c_uint, column: *mut c_uint, offset: *mut c_uint);
     pub fn clang_getFieldDeclBitWidth(cursor: CXCursor) -> c_int;
     pub fn clang_getFile(tu: CXTranslationUnit, file: *const c_char) -> CXFile;
+    #[cfg(feature="gte_clang_6_0")]
+    pub fn clang_getFileContents(tu: CXTranslationUnit, file: CXFile, size: *mut size_t) -> *const c_char;
     pub fn clang_getFileLocation(location: CXSourceLocation, file: *mut CXFile, line: *mut c_uint, column: *mut c_uint, offset: *mut c_uint);
     pub fn clang_getFileName(file: CXFile) -> CXString;
     pub fn clang_getFileTime(file: CXFile) -> time_t;
     pub fn clang_getFileUniqueID(file: CXFile, id: *mut CXFileUniqueID) -> c_int;
     pub fn clang_getFunctionTypeCallingConv(type_: CXType) -> CXCallingConv;
     pub fn clang_getIBOutletCollectionType(cursor: CXCursor) -> CXType;
     pub fn clang_getIncludedFile(cursor: CXCursor) -> CXFile;
     pub fn clang_getInclusions(tu: CXTranslationUnit, visitor: CXInclusionVisitor, data: CXClientData);
diff --git a/third_party/rust/clang-sys/src/link.rs b/third_party/rust/clang-sys/src/link.rs
index 8d25bbf39f73..a09d10280bea 100644
--- a/third_party/rust/clang-sys/src/link.rs
+++ b/third_party/rust/clang-sys/src/link.rs
@@ -75,17 +75,17 @@ macro_rules! link {
                 match l.borrow().as_ref() {
                     Some(library) => Some(f(&library)),
                     _ => None,
                 }
             })
         }
 
         $(
-            #[cfg_attr(feature="clippy", allow(too_many_arguments))]
+            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
             $(#[cfg($cfg)])*
             pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                 let f = with_library(|l| {
                     match l.functions.$name {
                         Some(f) => f,
                         _ => panic!(concat!("function not loaded: ", stringify!($name))),
                     }
                 }).expect("a `libclang` shared library is not loaded on this thread");
@@ -113,18 +113,18 @@ macro_rules! link {
         ///
         /// * a `libclang` shared library could not be found
         /// * the `libclang` shared library could not be opened
         pub fn load_manually() -> Result<SharedLibrary, String> {
             #[path="../build.rs"]
             mod build;
 
             let file = try!(build::find_shared_library());
-            let library = libloading::Library::new(&file).map_err(|_| {
-                format!("the `libclang` shared library could not be opened: {}", file.display())
+            let library = libloading::Library::new(&file).map_err(|e| {
+                format!("the `libclang` shared library at {} could not be opened: {}", file.display(), e)
             });
             let mut library = SharedLibrary::new(try!(library));
             $(load::$name(&mut library);)+
             Ok(library)
         }
 
         /// Loads a `libclang` shared library for use in the current thread.
         ///
diff --git a/third_party/rust/clang-sys/src/support.rs b/third_party/rust/clang-sys/src/support.rs
index 1e223086400b..68d912d57e40 100644
--- a/third_party/rust/clang-sys/src/support.rs
+++ b/third_party/rust/clang-sys/src/support.rs
@@ -58,22 +58,17 @@ pub struct Clang {
 
 impl Clang {
     //- Constructors -----------------------------
 
     fn new(path: PathBuf, args: &[String]) -> Clang {
         let version = parse_version(&path);
         let c_search_paths = parse_search_paths(&path, "c", args);
         let cpp_search_paths = parse_search_paths(&path, "c++", args);
-        Clang {
-            path: path,
-            version: version,
-            c_search_paths: c_search_paths,
-            cpp_search_paths: cpp_search_paths,
-        }
+        Clang { path, version, c_search_paths, cpp_search_paths }
     }
 
     /// Returns a `clang` executable if one can be found.
     ///
     /// If the `CLANG_PATH` environment variable is set, that is the instance of `clang` used.
     /// Otherwise, a series of directories are searched. First, If a path is supplied, that is the
     /// first directory searched. Then, the directory returned by `llvm-config --bindir` is
     /// searched. On OS X systems, `xcodebuild -find clang` will next be queried. Last, the
@@ -143,17 +138,17 @@ fn is_executable(_: &Path) -> io::Result<bool> {
 }
 
 /// Attempts to run an executable, returning the `stdout` and `stderr` output if successful.
 fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
     Command::new(executable).args(arguments).output().map(|o| {
         let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
         let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
         (stdout, stderr)
-    }).map_err(|_| format!("could not run executable: `{}`", executable))
+    }).map_err(|e| format!("could not run executable `{}`: {}", executable, e))
 }
 
 /// Runs `clang`, returning the `stdout` and `stderr` output.
 fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
     run(&path.to_string_lossy().into_owned(), arguments).unwrap()
 }
 
 /// Runs `llvm-config`, returning the `stdout` output if successful.
diff --git a/third_party/rust/libc/.cargo-checksum.json b/third_party/rust/libc/.cargo-checksum.json
index 6b765ee0e24f..fbebcfd35635 100644
--- a/third_party/rust/libc/.cargo-checksum.json
+++ b/third_party/rust/libc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"d323dad8a4a6a7f88471a3a671478ee56ef1a6b26472358650a0e7597b239c65","Cargo.toml":"3642623f8dc43de106c0f1e53ba38c09a06e709713360ac45ab661bab95527ed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"00fbfd7e989de6ecc270aed1f1c2c20560ac67e6c1564833622b8e34385c6170","appveyor.yml":"fec0ac820d19c40534301966f82524372e4855e4f61eeec486d42bf850d77f71","ci/README.md":"b8debdd9044a773dbccc85e574eed21008784117d77c24a15f207d4b2a173a14","ci/android-install-ndk.sh":"725db9025c5905849916bf7c910f98ff0e753484397c2a1f836d48a576d10890","ci/android-install-sdk.sh":"5c3fbe402ac611239ac7715a61f247d1c55fa012f33a5be0b0127dfc196965cf","ci/android-sysimage.sh":"901415631752827454c827e8c51906ba4260612e4021eda98eb7fff771c7d0e8","ci/docker/aarch64-linux-android/Dockerfile":"e17945fba1786dfe766006f50e79baf3f4151ca0c0c14ae96f91483bf345afd7","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"5f430271941e1eecdf9d1a5fb701dd5622e2c4b9da03140fd829bf216e55529d","ci/docker/aarch64-unknown-linux-musl/Dockerfile":"3e1cbf0fa728571b9be9769e5a6281c964fa5b26d586265117ccee017ca4022c","ci/docker/arm-linux-androideabi/Dockerfile":"4e0bdc13254f99bd0db195f91331c634050426e3e4a0fcc63ef25ab795fe2d46","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"dbb025b53b27e406893184290836a50133ecae8295711d5e05b4e41fac9bd262","ci/docker/arm-unknown-linux-musleabihf/Dockerfile":"7cb6e0f8fb91c97f142a9c827687bbbc1a5e7643a3081160025d0365593a596c","ci/docker/asmjs-unknown-emscripten/Dockerfile":"0d9aea5119c2cd136cc2c0a578105d91210e45901ac49b17c5e45f458b1c7551","ci/docker/i686-linux-android/Dockerfile":"4e8377ec0bd9ad2df23bf2c5373200a12750dc9f28c4f10bc83a0150fe1623ee","ci/docker/i686-unknown-linux-gnu/Dockerfile":"ca61f403bd3eaec7f3e51165ae7f74cd559a65ce657aed4700d726a2aabea648","ci/docker/i686-unknown-linux-musl/Dockerfile":"4ac86fe9e159d454616396a9f3f07ce0f5d99cc4b49898b8d2486e6bdbfed9e9","ci/docker/mips-unknown-linux-gnu/Dockerfile":"6d2a9daa299003497c1d441d07b69f730ad75ee49f34520f959b5158e60072e0","ci/docker/mips-unknown-linux-musl/Dockerfile":"4773b2656a7dd6a3b106fcb737428436652edf3d1f48181de3f62c16bf5bd49d","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"7c4d26232f1c1553a6612d9b0b3faac9887e139eaffa025f70d34113dcee812f","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"edb4144c07ade1a8bd65272ec1d3672ad794e9e6b7d01197896e159a70175b58","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"0ca9c12b5618c6d2df04ff820d56fb28e05b43e45eaa506480126b03c5072d48","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"4b247dcc399395815ec9153c1247cc03d764896c484eddcb196d0bf8650d6311","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"e949717a8ba5e123940729ff47ce1c45989c8b8247c576f1488f698b534e0283","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"018591017f499414a9f79477e1c39baa6a47f71fce6812fb1868fb0fcdfb8cea","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"63bb605e333b8351ee2366def0cfb77f206c66f43bc2d5d9ca18ee0119fa5672","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"6eae4d575de47aefc429dfb1957856bc7107fc7456883563acdfb9886154e5bb","ci/docker/wasm32-unknown-emscripten/Dockerfile":"bd072d6ae91a9160693e402dd77462d3c9dd0716711e719a62af330ae479eb4e","ci/docker/wasm32-unknown-emscripten/node-wrapper.sh":"6ec19745e08690b7b5d7f882004a8a63b69ac815d66e3f8c5a38d2c3e78b962e","ci/docker/x86_64-linux-android/Dockerfile":"aeeaa540189ca712369c564c9a14cbace63217dadcfaf879a2cb40fbdeb08199","ci/docker/x86_64-rumprun-netbsd/Dockerfile":"e8f9287b267c6058eec42d1bca0007cb9a78a1d244dd8e11088368cb61fb17d6","ci/docker/x86_64-rumprun-netbsd/runtest.rs":"53302e9ed39293c1ec68ab56287593907d4aaf5bac9c1c2857b29f754a71d62b","ci/docker/x86_64-unknown-freebsd/Dockerfile":"dfc00fa7d5dbb24e6864fb62cdbd48536c14c0be2d40fd02de53d1374e4b760a","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"342e16d6d1dd3c23b735b0705aa04e48261401746edcf24170910d5650eeda56","ci/docker/x86_64-unknown-linux-gnux32/Dockerfile":"ca61f403bd3eaec7f3e51165ae7f74cd559a65ce657aed4700d726a2aabea648","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"e145784741473150473b1bef7cc3c2cf0c6339d4fc480113ac41b4247a9b38ec","ci/dox.sh":"9ea240a4a607036235fd68c01b5d2a59f365768d103d3be774dcf34aa3ff563e","ci/emscripten-entry.sh":"1c1384b4a8b0c055d8095d9d9b2c9dccbdcdb2d5f90fdca34a1976ca8fc379c6","ci/emscripten.sh":"6f66c7b5c3d34a41afc59ceb0a8c3b0880cd6fd9a6344b874ae80bac0639ccb2","ci/ios/deploy_and_run_on_ios_simulator.rs":"3175066fd7f82390f6226d881e1a1dda9767ea2705656870e0d7774e2731800e","ci/landing-page-footer.html":"b70b3112c2147f5c967e7481061ef38bc2d79a28dd55a16fb916d9c9426da2c4","ci/landing-page-head.html":"ad69663fac7924f27d0209bc519d55838e86edfc4133713a6fd08caadac1b142","ci/run-docker.sh":"be83bc5a8b5ef913a7c9941ffca24734716028650c9a876123c4c160672c18de","ci/run-qemu.sh":"bb859421170871ef23a8940c5e150efec0c01b95e32d2ce2d37b79a45d9d346c","ci/run.sh":"f78a0aff66c19002b9a39ef557adb28dcf0a73e18c3eb4934943a4745df8b8fa","ci/runtest-android.rs":"a07ddbdd276aedda7876c7e676774178a60d9aeab95df01275a4ee95f59e3044","ci/style.rs":"60564abc1d5197ed1598426dd0d6ee9939a16d2875b03373538f58843bb616c4","src/dox.rs":"a2b4907054e260e2db31415379d4db87acd91a8d02fb2178679628079910404f","src/lib.rs":"5f6bee7224a6131862e6cba9dfff57a6340329694b97da9d9f30a668271c0f78","src/macros.rs":"e1b0bf5db89faa8fcb39a3fd46cdb5fdcfabb7f3524eb2192157f0188b8a764b","src/redox/mod.rs":"07ae6652bc6f7fe276255bda210eae7a197d3d64d9dede6dadce0478e8890e2b","src/redox/net.rs":"a1e9d2291e2c12833333ac8706b23f388ce5dbe1718bdd7b38fd68c74559f0b4","src/unix/bsd/apple/b32.rs":"d107376452f731f5d8a1e6b544bdcaac826c95a383d4b20e2032f115eb9f3256","src/unix/bsd/apple/b64.rs":"ab141ad0c8c58342c06858f6f34b75eef70e58cb58e7375d460a9be6739b5e6a","src/unix/bsd/apple/mod.rs":"a7e48a4e3edb132c433e76a3f60f85ae2fd3f28f48e79b41f7461076c7233859","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"62689b8aa80d308d425385daf9b4ea2ed20b19e0590dc57b6efa08b266945bbd","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"97132e2097411034271b8c927ecc94a208a361564680972a6c82998bd30a9826","src/unix/bsd/freebsdlike/freebsd/mod.rs":"9a8cb662cb2cbe5facba1b3519748f657b18b3eee30fa43b75125012745a5cb1","src/unix/bsd/freebsdlike/freebsd/x86.rs":"54311d3ebf2bb091ab22361e377e6ef9224aec2ecfe459fbfcedde4932db9c58","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"97132e2097411034271b8c927ecc94a208a361564680972a6c82998bd30a9826","src/unix/bsd/freebsdlike/mod.rs":"c9895c61e4b01f0b397cbd9d40c977e71774888cad85455bbb23eded85311284","src/unix/bsd/mod.rs":"1546c73fd87103a7282c3ceaa2d1e55f91b8bab2ec705c733351f715722e6b2f","src/unix/bsd/netbsdlike/mod.rs":"edbc1ff82f6a71999cc8664a4e10e43302d33f93b925649b52d97be3821c63d5","src/unix/bsd/netbsdlike/netbsd/mod.rs":"a20d0283670a6a700fa56d12c8a4285ff75ae5a2603706bc17c4cf9799ffd8c3","src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/netbsd/other/mod.rs":"4d9f7091af8e166943ac6f42ce85558909e5b6e61325039bff7adfbcf4b90212","src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs":"f8cd05dacd3a3136c58da5a2fbe26f703767823b28e74fe8a2b57a7bd98d6d5c","src/unix/bsd/netbsdlike/openbsdlike/mod.rs":"3ba4790618db8308e74f8fec16587ae7d584773eefb619948a25a7330b832b3f","src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs":"302817036aa7e7afbc82248cf66b040ef1edfbcb136c9ad243fe20f98df8d6f8","src/unix/bsd/netbsdlike/openbsdlike/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/openbsdlike/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs":"f5d8db6f54efd05520b31b764a6bacbf612e1aebce097d2d5bfaaef3b91f37b5","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"f3c940954b2a404e07afc512e78b4e496628b9a9036bd9221ee265b67c618f16","src/unix/mod.rs":"1d95051294ac738f852fc6bb85921618efd911b5772a321f7465a73dabb930e9","src/unix/newlib/arm/mod.rs":"2b6dba2e697ab9b4f4bc4dd5f28057249e9b596d1cb395a9322ec87605c4a5c4","src/unix/newlib/mod.rs":"49227cd0ec18911a91b6ab8a278da3b430321c562b393fbfac92edd354b0a7ee","src/unix/notbsd/android/b32/arm.rs":"3625a32c7e58cfe683a53486fbe3d42d4e28f00bea31e19cb46ed2bb0b6a140b","src/unix/notbsd/android/b32/mod.rs":"e9ec6f08e20ea235cd7095604ea6e37c739c1276e9f40fa31a4db4951fa005af","src/unix/notbsd/android/b32/x86.rs":"ae2b7f1d6278caddc007749bb1d09ca33f7593478a0fd7fe98b457dae86c7814","src/unix/notbsd/android/b64/aarch64.rs":"63d65629d79371814910f691672ef593d20244ee09be26f1ebe07ee6212d0163","src/unix/notbsd/android/b64/mod.rs":"63290adc8122c040f9be369ef4180975bcf1a967a717aa75d30371162d5d5fa9","src/unix/notbsd/android/b64/x86_64.rs":"5547aef8dcbaa5a932559f34606fd8d89f6c9c15173d2b1412c12d39b3c1045f","src/unix/notbsd/android/mod.rs":"7fa19bd63dc3582f12769be51e9a1b355d24744e17ea9aef67380f535b58e2b1","src/unix/notbsd/emscripten.rs":"f8d8acf5cef1acd1a6bdd41299054120820865d072c4c2e3c740fbd0c6e9b3e7","src/unix/notbsd/linux/mips/mips32.rs":"f769bbe5c48f77e6bc94e37deccd2866e7e52e7eb1b3cd7611dbad95574e82f8","src/unix/notbsd/linux/mips/mips64.rs":"ef678b48b571428d46fef5b2ca9bef7251b5f27fcd2c38d987d1b80f2ad3ece0","src/unix/notbsd/linux/mips/mod.rs":"515eb57ee1798fadb6654ce845fb49098593815c2130a30010959f36565e65f9","src/unix/notbsd/linux/mod.rs":"1e1a96e85a9ffcd618f7b459ef2a2ccf9487b3eb97c74cff6c7ce83bb115815e","src/unix/notbsd/linux/musl/b32/arm.rs":"d2998b13648696304bb34f0793715d821178baf8e88a45b532764a20b5294232","src/unix/notbsd/linux/musl/b32/mips.rs":"340be794362a4532d709ef23542b10762f710f7bfd0c4fafa5166a3fb9a15b4f","src/unix/notbsd/linux/musl/b32/mod.rs":"3cc7979546258a47df6b0fcd7ad64571826623671857633a7acafe87e05e56a1","src/unix/notbsd/linux/musl/b32/x86.rs":"df114102dcf35bc32f891d4a9e09ce02fbe4c096a196c6b98b10ff87b29dbe4d","src/unix/notbsd/linux/musl/b64/aarch64.rs":"12c590fde2a1450c08934234c4f5bcd94ee7b58ca21f8e93bc930148c15fb0b0","src/unix/notbsd/linux/musl/b64/mod.rs":"b1991ef46a00d2db7ce3e36f6596685c1d508786c4dd4e62cbbf65ac3c256cc0","src/unix/notbsd/linux/musl/b64/powerpc64.rs":"239c5754811e2d75723bd0d540e732630c9817c5f24513d1f02b63e6b27a3a57","src/unix/notbsd/linux/musl/b64/x86_64.rs":"bf8fc10a09bf700084db0381c484ddec3add79aa1726954cb14d21802ff7d199","src/unix/notbsd/linux/musl/mod.rs":"60cf407596bc7b369d2e6a4d8f2e821d203f6a4284cc5e71312d1fb141a81f1d","src/unix/notbsd/linux/other/b32/arm.rs":"d9892f7350b2978335f734f1cd2d7fed60f0f2e66aa05bee3f69549c031f8b14","src/unix/notbsd/linux/other/b32/mod.rs":"ea91ffe90cd71d45a6e00e7d001cfcfafc8a840aa2b372078798b160968bdaf6","src/unix/notbsd/linux/other/b32/powerpc.rs":"253fcd2f9978525285be1903cc08f3fec2dc3b12d1660a33e2995b4f6b810d1c","src/unix/notbsd/linux/other/b32/x86.rs":"49376e3ed0f3ff95c230ac20751911fe3c608dfe15c7c118b069fd7a954d8db9","src/unix/notbsd/linux/other/b64/aarch64.rs":"cd04a0c1f8d090753600143495b975d8fa4eacc96fc6eeacd8f378ba70d8c838","src/unix/notbsd/linux/other/b64/mod.rs":"63e1a3fdf5f4d1b9820934ab344c91aed5e458e7e05908535d2e942d51a08bf8","src/unix/notbsd/linux/other/b64/not_x32.rs":"e1cf87b9dbe89e9fff667c6fc8eff0166a02565ef65aae3dc9304dc70f7a5624","src/unix/notbsd/linux/other/b64/powerpc64.rs":"25de66d04d2200f00a2e6e0eb97484b43c466897cc789598c728323ee311000b","src/unix/notbsd/linux/other/b64/sparc64.rs":"f26439fa0506ffc5efb0314fcef63cd69964bb5602baec2a0bd1439444dac5e3","src/unix/notbsd/linux/other/b64/x32.rs":"e521bd43a2d66f09f03a045b2e1f69f2ca91cff37922ac5b7c437d888799cee6","src/unix/notbsd/linux/other/b64/x86_64.rs":"924d0282f549507ce46bddc4ac2c489641f883c0620438eea1f6d9fbbbdbbe4b","src/unix/notbsd/linux/other/mod.rs":"5b62146535521c1e7730ea7cba53fd9285831616318abcf5134af992d6cca4a3","src/unix/notbsd/linux/s390x.rs":"f11f595427393a90803a180fa9ca77b048d1d76da0634b92f4b038db07f5623b","src/unix/notbsd/mod.rs":"d2643df7dc6c4affb0ea43ff4471558df317e788942dfde5096c2479f6d42f08","src/unix/solaris/mod.rs":"972b7847f7a67135a93f7604928645103e13f2cf00d1b8bc82994a620101a145","src/unix/uclibc/mips/mips32.rs":"31b23e466cffb86116421ec9240b86e7419aacd84b0b1b04d23c7142c8717566","src/unix/uclibc/mips/mips64.rs":"e67eec1636a998b047d89a4cda1c99cb6bc3071db017762675179a68201c4438","src/unix/uclibc/mips/mod.rs":"74817a9b1ee3998d8e0b751a555d57225f70fd979c283c94ada344a162a8b856","src/unix/uclibc/mod.rs":"89429fbdca93bcdd84a35a36583a143dd67d3e282d7dcb6b7f73fd9a9c038108","src/unix/uclibc/x86_64/l4re.rs":"54b4e58ce5a671348c32bc41c1607dbc5c13fa6818cc3e0e0e2b409c300a305e","src/unix/uclibc/x86_64/mod.rs":"bd569360c45a6f2b585cfb47544d223e92243a2ff4f8429b78fecac6b889f9fd","src/windows.rs":"e41357d610608bad81abf285306ad8b127b6f02d5132f63c4942861980b47d59"},"package":"5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"}
\ No newline at end of file
+{"files":{".travis.yml":"8088167016d06169f8b1eb86ba5f413cdfcb776bd95af46f968d146665ff5afe","Cargo.toml":"74e837a30336b387d94fc92db3d1ece407b47318ca1362a2b8f37dfb28064e54","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"a550fd6c92b62c70925cc6a75dd1d40ae93f9a77e3c4e9baacdf014fa0cae550","appveyor.yml":"216f7ac4561aa5810dc84ce5a9950897a8c0496e0615d0211d62348b1c8dc720","ci/README.md":"2e3d7ad13f8c3202e57d2af73aeeebde306221dce7c0907e462e25767a692d6b","ci/android-install-ndk.sh":"725db9025c5905849916bf7c910f98ff0e753484397c2a1f836d48a576d10890","ci/android-install-sdk.sh":"5c3fbe402ac611239ac7715a61f247d1c55fa012f33a5be0b0127dfc196965cf","ci/android-sysimage.sh":"901415631752827454c827e8c51906ba4260612e4021eda98eb7fff771c7d0e8","ci/docker/aarch64-linux-android/Dockerfile":"e17945fba1786dfe766006f50e79baf3f4151ca0c0c14ae96f91483bf345afd7","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"5f430271941e1eecdf9d1a5fb701dd5622e2c4b9da03140fd829bf216e55529d","ci/docker/aarch64-unknown-linux-musl/Dockerfile":"1e8c66067bcbd718119db5eb6e69390c4f0ea72c1543e09b6846a36ef66cd21b","ci/docker/arm-linux-androideabi/Dockerfile":"4e0bdc13254f99bd0db195f91331c634050426e3e4a0fcc63ef25ab795fe2d46","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"dbb025b53b27e406893184290836a50133ecae8295711d5e05b4e41fac9bd262","ci/docker/arm-unknown-linux-musleabihf/Dockerfile":"12b50abdc5605e3a39eff6bb0d0fccb0885896933c5bfbb3d0cbde9068492a0f","ci/docker/asmjs-unknown-emscripten/Dockerfile":"0d9aea5119c2cd136cc2c0a578105d91210e45901ac49b17c5e45f458b1c7551","ci/docker/i686-linux-android/Dockerfile":"4e8377ec0bd9ad2df23bf2c5373200a12750dc9f28c4f10bc83a0150fe1623ee","ci/docker/i686-unknown-linux-gnu/Dockerfile":"f22ac412525ef15b33ab8ccd8193d97346faf421c17f6ddeffc25b651aba83b7","ci/docker/i686-unknown-linux-musl/Dockerfile":"f95cd8b514f48686d774b85e4dffccce1a5acd68749d8ff59b204419d448d575","ci/docker/mips-unknown-linux-gnu/Dockerfile":"6d2a9daa299003497c1d441d07b69f730ad75ee49f34520f959b5158e60072e0","ci/docker/mips-unknown-linux-musl/Dockerfile":"4773b2656a7dd6a3b106fcb737428436652edf3d1f48181de3f62c16bf5bd49d","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"7c4d26232f1c1553a6612d9b0b3faac9887e139eaffa025f70d34113dcee812f","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"edb4144c07ade1a8bd65272ec1d3672ad794e9e6b7d01197896e159a70175b58","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"0ca9c12b5618c6d2df04ff820d56fb28e05b43e45eaa506480126b03c5072d48","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"4b247dcc399395815ec9153c1247cc03d764896c484eddcb196d0bf8650d6311","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"e949717a8ba5e123940729ff47ce1c45989c8b8247c576f1488f698b534e0283","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"018591017f499414a9f79477e1c39baa6a47f71fce6812fb1868fb0fcdfb8cea","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"9860f478c5b2dc3bcf76d2cda7f71922a2a2ef54898cc2ed6ea9b9eff094a5c0","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"1471a694817758331ecdbb23857537563ad7ae56aa3a88e49bf9cd421addcafe","ci/docker/wasm32-unknown-emscripten/Dockerfile":"bd072d6ae91a9160693e402dd77462d3c9dd0716711e719a62af330ae479eb4e","ci/docker/wasm32-unknown-emscripten/node-wrapper.sh":"0eef37c3c4fb16dbc083148b7e7af45f2ae60bd9a1b3a77e1d43da79efbd30c6","ci/docker/x86_64-linux-android/Dockerfile":"aeeaa540189ca712369c564c9a14cbace63217dadcfaf879a2cb40fbdeb08199","ci/docker/x86_64-rumprun-netbsd/Dockerfile":"e8f9287b267c6058eec42d1bca0007cb9a78a1d244dd8e11088368cb61fb17d6","ci/docker/x86_64-rumprun-netbsd/runtest.rs":"53302e9ed39293c1ec68ab56287593907d4aaf5bac9c1c2857b29f754a71d62b","ci/docker/x86_64-unknown-freebsd/Dockerfile":"ab1f14c65c29f3721c7c091bdec2e865fb1abf45fdcdc867201d087966e396c4","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"ab3fa45765802b8155996796fcad9fb82096360ac587e38e6faa3ec345268796","ci/docker/x86_64-unknown-linux-gnux32/Dockerfile":"f22ac412525ef15b33ab8ccd8193d97346faf421c17f6ddeffc25b651aba83b7","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"0c31058e39d9f25c6f4f9b7fe78c7c8d135f32bfe52199e9b2e7fa10d5dc3940","ci/dox.sh":"d77171a9da467bb01fc702a28fc3b5099f82a485a627f3d5593a9830c3e1a77c","ci/emscripten-entry.sh":"c97bbec520b57af9b1ae264ca991560e99c3852c99b00a2f673c614d1ba17498","ci/emscripten.sh":"6f66c7b5c3d34a41afc59ceb0a8c3b0880cd6fd9a6344b874ae80bac0639ccb2","ci/ios/deploy_and_run_on_ios_simulator.rs":"be6d2ccfe78df5d77a2c4ee40ffbd22b1bb2ac0a0cf6b2a108f21406f22ce1a8","ci/landing-page-footer.html":"b70b3112c2147f5c967e7481061ef38bc2d79a28dd55a16fb916d9c9426da2c4","ci/landing-page-head.html":"ad69663fac7924f27d0209bc519d55838e86edfc4133713a6fd08caadac1b142","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/run-docker.sh":"be83bc5a8b5ef913a7c9941ffca24734716028650c9a876123c4c160672c18de","ci/run-qemu.sh":"bb859421170871ef23a8940c5e150efec0c01b95e32d2ce2d37b79a45d9d346c","ci/run.sh":"86b7d1ce555ed5eeeac6b44fd0e9563166ff38ba38e56a82d70800ace3b65946","ci/runtest-android.rs":"a07ddbdd276aedda7876c7e676774178a60d9aeab95df01275a4ee95f59e3044","ci/style.rs":"940c06a676cff1dfc1555b887e46867c6aacc473956cd6aaafaed71824facdb2","ci/test-runner-linux":"cb3713d9e4fa1d9a7c039dfd077af0939921c1f2bf969c9e680ee66e87dc30a4","src/cloudabi/aarch64.rs":"b8550bf1fd7344972aa4db29441486f39f31482d0327534981dbb75959c29114","src/cloudabi/arm.rs":"c197e2781c2839808bd6fcef219a29705b27b992d3ef920e9cf6ac96e2022bbf","src/cloudabi/mod.rs":"1c2dc787a1b3438970ccd04153c93538719b1a27445707913b90b6f0cdcdde77","src/cloudabi/x86.rs":"33eb97f272d2201f3838ae74d444583c7de8f67856852ca375293b20bbd05636","src/cloudabi/x86_64.rs":"400d85d4fe39e26cf2e6ece9ee31c75fe9e88c4bcf4d836ca9f765c05c9c5be3","src/dox.rs":"8f6037887281b828d8541ce8a549dacaed5d29c05fd9cf78b169838476b82741","src/fuchsia/aarch64.rs":"8366ac6f51e494aad9266ccab2b3a95c5ed7aa3a9f77ea672413283440919743","src/fuchsia/mod.rs":"e5b7e6ff40e670200c52919b53474627931b4def18d452323999de201953cf21","src/fuchsia/powerpc64.rs":"390e8db54271a1d5f512d54a21b328091a792378bf9b42b49b6c1a72388da4ec","src/fuchsia/x86_64.rs":"b4a3eff94dcf1ffe41e6500468ca2cff0e97ddbcc75fe079b6ac7adb1e493f56","src/lib.rs":"bbad6abf79078649e76c2379c3c3fcbc4198430736e726a01d96a8f1439e8cb1","src/macros.rs":"8ad55edea39fad158e80c5df0d7b520b6863f5088db4db286ba31c12cbc4d67d","src/redox/mod.rs":"685d4d39911e855bf0fd7879b9a02bc15cefebfb0f520382c1a1353364f0d523","src/redox/net.rs":"f2e1922883f208cb46c00744da4a68feccfbec576c6981978ad404e46f818c8b","src/unix/bsd/apple/b32.rs":"41699d2802327b0a4d4aa50cd20b1e366b442176cbedab27ca888ac0446c9156","src/unix/bsd/apple/b64.rs":"0cda592881a1db30f2d96ff0f67cf4214aa99881dfe4f2fb474ef7ec78bd204a","src/unix/bsd/apple/mod.rs":"ac02092ad74cb81fa789e89d541d79525d2298ac77842847b48e5fd1a83fff0d","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"7a8df4e8079ed60ad4ac35362901eb2fea4d53384709e4ac45930899b84f8eaf","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"97132e2097411034271b8c927ecc94a208a361564680972a6c82998bd30a9826","src/unix/bsd/freebsdlike/freebsd/mod.rs":"1b158199be42b37708f10d0e73164cf0b63a2b5ae0e6fcc1feab5944f5377f24","src/unix/bsd/freebsdlike/freebsd/x86.rs":"54311d3ebf2bb091ab22361e377e6ef9224aec2ecfe459fbfcedde4932db9c58","src/unix/bsd/freebsdlike/freebsd/x86_64.rs":"97132e2097411034271b8c927ecc94a208a361564680972a6c82998bd30a9826","src/unix/bsd/freebsdlike/mod.rs":"9ddcc86d3bb76f426e26c4df8d853b3715a7d6d9006acaa4fa26b2b0f5bb3314","src/unix/bsd/mod.rs":"a1030452eed4ec52a39e9f39040e8fae4309143c7af145efadd9b425caa39672","src/unix/bsd/netbsdlike/mod.rs":"6fb522d55eced39ef1bc28873f9ae8d5ab141acde09c5cb6a22aeca577d916ad","src/unix/bsd/netbsdlike/netbsd/mod.rs":"1cd66ed5967c788562d4ad626cfbeb1544f4b9267111de5f6790379b8327f28e","src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/netbsd/other/mod.rs":"4d9f7091af8e166943ac6f42ce85558909e5b6e61325039bff7adfbcf4b90212","src/unix/bsd/netbsdlike/openbsdlike/bitrig/mod.rs":"92459d80b8e5b570c0efe35a1d244d38f23072cd28b6581dfcb313dc9bfc3d51","src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86.rs":"bd251a102bed65d5cb3459275f6ec3310fe5803ff4c9651212115548f86256d0","src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86_64.rs":"927eeccaf3269d299db4c2a55f8010807bf43dfa894aea6a783215f5d3560baa","src/unix/bsd/netbsdlike/openbsdlike/mod.rs":"37fea61239bd53cd951fd7bc800229f663be2e9ad2e1539ebdf73767ca28b469","src/unix/bsd/netbsdlike/openbsdlike/openbsd/aarch64.rs":"820092e397c7ec259cd2de8f2444083a8e57071c02d73d678701dfa7807726e9","src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs":"973331fd80876db55467913556d81f45ea1ede03322fef9c5d552aba833d2207","src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86.rs":"44b7ea81cf363777b29935da175e702cbf45ed78f7498ae57faf44aa32335085","src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86_64.rs":"7c959cdb3415f68a0f948117b9aa87a17463e57ab97cc3235f2567454b706653","src/unix/haiku/b32.rs":"69ae47fc52c6880e85416b4744500d5655c9ec6131cb737f3b649fceaadce15a","src/unix/haiku/b64.rs":"73e64db09275a8da8d50a13cce2cfa2b136036ddf3a930d2939f337fc995900b","src/unix/haiku/mod.rs":"8b8a7a51e1bc20407e42b0ab6c1a0cd1c8fc4f3ef61a04ccb7c8e312495ce30b","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"a8bb096695eea74fb1c5c6766c1e680d28378c452dbc622fa5f91c6ce204306f","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/mod.rs":"af909129f76f9bbe571dee2e78f43afd63ff6e46c27a429da43c239537330283","src/unix/newlib/aarch64/mod.rs":"c408a990f22fb4292a824f38367e9b517e6e6f8623328397ee631cc88b3d1f7d","src/unix/newlib/arm/mod.rs":"2b6dba2e697ab9b4f4bc4dd5f28057249e9b596d1cb395a9322ec87605c4a5c4","src/unix/newlib/mod.rs":"d9f59ee9a994490122986b7ae5e3064bf9ce0b888349a388a50341a4c7069842","src/unix/notbsd/android/b32/arm.rs":"3625a32c7e58cfe683a53486fbe3d42d4e28f00bea31e19cb46ed2bb0b6a140b","src/unix/notbsd/android/b32/mod.rs":"2fbe398c1fb5251dda6213741a193e50aae4622807cb255d1dd2e82b536f0c65","src/unix/notbsd/android/b32/x86.rs":"ae2b7f1d6278caddc007749bb1d09ca33f7593478a0fd7fe98b457dae86c7814","src/unix/notbsd/android/b64/aarch64.rs":"63d65629d79371814910f691672ef593d20244ee09be26f1ebe07ee6212d0163","src/unix/notbsd/android/b64/mod.rs":"90d4f6b063fd4de42fd302cbc9d9902fd99ac1d71dc48cb8bc6ad7b4c902e481","src/unix/notbsd/android/b64/x86_64.rs":"5547aef8dcbaa5a932559f34606fd8d89f6c9c15173d2b1412c12d39b3c1045f","src/unix/notbsd/android/mod.rs":"eadc87bfea5f5e8ea50a3776b526cea2b0bfaf6d55240ba88134e19670f8a3a6","src/unix/notbsd/emscripten.rs":"d2d817af2b1496c1ee173f216c478a3a1c26223ef938797103bc50a265284662","src/unix/notbsd/linux/mips/mips32.rs":"a483ddfd10765b7d5090dc21686eee8842649cd21236828a42d634114885f5f9","src/unix/notbsd/linux/mips/mips64.rs":"9fff696e3943cf206b549d1ae13fa361828e9a8454e2d5730eeaa1c172ff370d","src/unix/notbsd/linux/mips/mod.rs":"af1b7bffff09aa5d8662e6452f72bc1e55b6639899b8c2a4be9cd1cfb245de01","src/unix/notbsd/linux/mod.rs":"081cb74be8b465c9cf86289f675cb7c6f7d7eee39713a6764e1871eabcbaee44","src/unix/notbsd/linux/musl/b32/arm.rs":"9d9bff31ab0925a1f62a20945d36a83b94ce3ab78dd202cd468bb31556b21725","src/unix/notbsd/linux/musl/b32/mips.rs":"cb38c463aebfc235f31880db158dd47c6e21f182a092d3f3087d92994b7711da","src/unix/notbsd/linux/musl/b32/mod.rs":"540928f168f145c136f9dd729ffa12b9d1838d9fe664fc642365d17d7fae648f","src/unix/notbsd/linux/musl/b32/powerpc.rs":"3930a2825657ac9208935341e29cfa62f6e37fc5c6b2c0d0dc9ac8c3b5569d59","src/unix/notbsd/linux/musl/b32/x86.rs":"c02dd333012cf65cb8873fa211eff5e63d466be55451a347510e3d4f50ed515e","src/unix/notbsd/linux/musl/b64/aarch64.rs":"4d79d86d11fbb8cb7a74084e410a1140e3c89dfc1842cdfb213f3a0ca93046df","src/unix/notbsd/linux/musl/b64/mod.rs":"caac00326693b372d6805e4dda239475e7fef36368881f372c006264844fda0d","src/unix/notbsd/linux/musl/b64/powerpc64.rs":"24514e41be4b5f5e0ffbe8a25a99dae8989489b607db59e8bfa345f8e65c9963","src/unix/notbsd/linux/musl/b64/x86_64.rs":"25340999290a63d564ec149532c905f59c312ec369f8806d6b15df66fa1b8857","src/unix/notbsd/linux/musl/mod.rs":"17c70acf9c6eabeb73916c2abb7d7e8b0310214090faae4a8dc2fd183a9b45ba","src/unix/notbsd/linux/other/b32/arm.rs":"d9892f7350b2978335f734f1cd2d7fed60f0f2e66aa05bee3f69549c031f8b14","src/unix/notbsd/linux/other/b32/mod.rs":"dac0fd1054a0fa163bce85df58c4ad4d222d8b7353bdb4364482b46c19991d03","src/unix/notbsd/linux/other/b32/powerpc.rs":"253fcd2f9978525285be1903cc08f3fec2dc3b12d1660a33e2995b4f6b810d1c","src/unix/notbsd/linux/other/b32/x86.rs":"49376e3ed0f3ff95c230ac20751911fe3c608dfe15c7c118b069fd7a954d8db9","src/unix/notbsd/linux/other/b64/aarch64.rs":"d57f3e06a0ac8affc5bf9d17e1f217ef1d1d714c947f47e647e0e038deaf48b2","src/unix/notbsd/linux/other/b64/mod.rs":"63e1a3fdf5f4d1b9820934ab344c91aed5e458e7e05908535d2e942d51a08bf8","src/unix/notbsd/linux/other/b64/not_x32.rs":"fa8636fb93eab230ed53bdec0a06f5b81d6d982cc0800103563c8c1eefcdb2d9","src/unix/notbsd/linux/other/b64/powerpc64.rs":"024057a910d0b885c63443165d34ce33f972973a9a8f5979906198180b19ad8b","src/unix/notbsd/linux/other/b64/sparc64.rs":"bb28f201e29c7f490a42dd2673eb8180fd82c1824a5d21aeb5aed674ffcc6e07","src/unix/notbsd/linux/other/b64/x32.rs":"06a26c5120ced30fc015c220799b67c4401be2f13fc6c7361bebd3d37ff4982d","src/unix/notbsd/linux/other/b64/x86_64.rs":"afba464e903d350325a1ca3d9d5af1659efc0ede83a43dbac4dbd60c522e2ad1","src/unix/notbsd/linux/other/mod.rs":"add154a8cfe9392d5a73b6055eb1419902e2b8b5458c22586a6ef8f90f89501b","src/unix/notbsd/linux/s390x.rs":"033cb7c4ee00af352698615de0248a5c6c9bcff57ba671ee22d31b70ef86fb4a","src/unix/notbsd/mod.rs":"134502158bab09d5189249ef400c9ddf7fdf5d1a1bd3134484ca82b80a0833e7","src/unix/solaris/mod.rs":"9c52a7479b56d3bc1f2c9ba5bb44f71ab1470989a54d3d0d85571e19489e4b7e","src/unix/uclibc/mips/mips32.rs":"9739c5fb47f389a0394ef08ee30da97a3de0a1300020731a8cc0a033616011b2","src/unix/uclibc/mips/mips64.rs":"230583280bbc7b3c7fcdb61244f51fa1af5944ca127c7cf83c598fe2313713d0","src/unix/uclibc/mips/mod.rs":"3f86061d05a8da7d923310550b7d40c6223f0c907d77edc86b7a78da1d647f76","src/unix/uclibc/mod.rs":"8cf2db30468476b917a60fdffe475917302875a3a4150f29a042ebee182545d1","src/unix/uclibc/x86_64/l4re.rs":"68fd3a833fd1f7caf784a084224f384bdbdfb8b5a14ef94c4f5155409afb3439","src/unix/uclibc/x86_64/mod.rs":"419182836aedd426a5c9e6b8667058adf86ac8f43af73ce8d00c503f8ff8f414","src/unix/uclibc/x86_64/other.rs":"f03b47842896f2f3ae6f8ebdcbcf0276454f880349d9cf00e3d304f8136893c5","src/windows.rs":"e41357d610608bad81abf285306ad8b127b6f02d5132f63c4942861980b47d59"},"package":"76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"}
\ No newline at end of file
diff --git a/third_party/rust/libc/.travis.yml b/third_party/rust/libc/.travis.yml
index 053abfe1dc5a..b6a73f00c278 100644
--- a/third_party/rust/libc/.travis.yml
+++ b/third_party/rust/libc/.travis.yml
@@ -16,58 +16,62 @@ script:
       export CARGO_TARGET_DIR=`pwd`/target;
       sh ci/run.sh $TARGET;
     fi
   - rustc ci/style.rs && ./style src
 env:
   global:
     secure: "e2/3QjgRN9atOuSHp22TrYG7QVKcYUWY48Hi9b60w+r1+BhPkTseIJLte7WefRhdXtqpjjUJTooKDhnurFOeHaCT+nmBgiv+FPU893sBl4bhesY4m0vgUJVbNZcs6lTImYekWVb+aqjGdgV/XAgCw7c3kPmrZV0MzGDWL64Xaps="
 matrix:
+  allow_failures:
+    # FIXME(#987) move back to include once 404 is fixed
+    - env: TARGET=s390x-unknown-linux-gnu
   include:
-    # 1.0.0 compat
+    # 1.13.0 compat
     - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
-      rust: 1.0.0
+      rust: 1.13.0
       script: rm -f Cargo.lock && cargo build
       install:
 
     # build documentation
     - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
       rust: nightly
       script: sh ci/dox.sh
 
     # stable compat
     - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
     - env: TARGET=i686-unknown-linux-gnu
     - os: osx
       env: TARGET=x86_64-apple-darwin NO_ADD=1
-      osx_image: xcode8.3
+      osx_image: xcode9.4
     - os: osx
       env: TARGET=i686-apple-darwin
-      osx_image: xcode8.3
+      osx_image: xcode9.4
     - env: TARGET=arm-linux-androideabi
     - env: TARGET=aarch64-linux-android
     # FIXME(#826) should reenable
     #- env: TARGET=i686-linux-android
     - env: TARGET=x86_64-linux-android
     - env: TARGET=x86_64-unknown-linux-musl
     - env: TARGET=i686-unknown-linux-musl
     - env: TARGET=arm-unknown-linux-gnueabihf
     - env: TARGET=arm-unknown-linux-musleabihf
     - env: TARGET=aarch64-unknown-linux-gnu
     - env: TARGET=aarch64-unknown-linux-musl
-      rust: beta
+      # FIXME(#856)
+      rust: 1.22.1
     - os: osx
-      osx_image: xcode8.2
+      osx_image: xcode9.4
       env: TARGET=i386-apple-ios
            CARGO_TARGET_I386_APPLE_IOS_RUNNER=$HOME/runtest
            RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0
       before_install:
         rustc ./ci/ios/deploy_and_run_on_ios_simulator.rs -o $HOME/runtest
     - os: osx
-      osx_image: xcode8.2
+      osx_image: xcode9.4
       env: TARGET=x86_64-apple-ios
            CARGO_TARGET_X86_64_APPLE_IOS_RUNNER=$HOME/runtest
            RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0
       before_install:
         rustc ./ci/ios/deploy_and_run_on_ios_simulator.rs -o $HOME/runtest
     - env: TARGET=x86_64-rumprun-netbsd
     - env: TARGET=powerpc-unknown-linux-gnu
     - env: TARGET=powerpc64-unknown-linux-gnu
@@ -82,31 +86,38 @@ matrix:
     - env: TARGET=asmjs-unknown-emscripten
     - env: TARGET=wasm32-unknown-emscripten
 
     # beta
     - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
       rust: beta
     - os: osx
       env: TARGET=x86_64-apple-darwin NO_ADD=1
-      osx_image: xcode8.3
+      osx_image: xcode9.4
       rust: beta
 
     # nightly
     - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
       rust: nightly
     - os: osx
       env: TARGET=x86_64-apple-darwin NO_ADD=1
-      osx_image: xcode8.3
+      osx_image: xcode9.4
       rust: nightly
     # not available on stable
     # without --release the build fails
     # see https://github.com/rust-lang/rust/issues/45417
     - env: TARGET=x86_64-unknown-linux-gnux32 OPT="--release"
       rust: nightly
 
     # QEMU based targets that compile in an emulator
     - env: TARGET=x86_64-unknown-freebsd
+  allow_failures:
+    - env: TARGET=i386-apple-ios
+           CARGO_TARGET_I386_APPLE_IOS_RUNNER=$HOME/runtest
+           RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0
+    - env: TARGET=x86_64-apple-ios
+           CARGO_TARGET_X86_64_APPLE_IOS_RUNNER=$HOME/runtest
+           RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0
 
 notifications:
   email:
     on_success: never
   webhooks: https://buildbot.rust-lang.org/homu/travis
diff --git a/third_party/rust/libc/Cargo.toml b/third_party/rust/libc/Cargo.toml
index 16f0ad234cd7..876b127c08f6 100644
--- a/third_party/rust/libc/Cargo.toml
+++ b/third_party/rust/libc/Cargo.toml
@@ -7,26 +7,27 @@
 #
 # 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 = "libc"
-version = "0.2.33"
+version = "0.2.43"
 authors = ["The Rust Project Developers"]
 description = "A library for types and bindings to native C functions often found in libc or\nother common platform libraries.\n"
 homepage = "https://github.com/rust-lang/libc"
 documentation = "http://doc.rust-lang.org/libc"
 readme = "README.md"
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-lang/libc"
 
 [features]
+align = []
 default = ["use_std"]
 use_std = []
 [badges.appveyor]
-repository = "rust-lang/libc"
 project_name = "rust-lang-libs/libc"
+repository = "rust-lang/libc"
 
 [badges.travis-ci]
 repository = "rust-lang/libc"
diff --git a/third_party/rust/libc/README.md b/third_party/rust/libc/README.md
index c3333da14707..a19a56ee0f4f 100644
--- a/third_party/rust/libc/README.md
+++ b/third_party/rust/libc/README.md
@@ -1,18 +1,20 @@
 libc
 ====
 
 A Rust library with native bindings to the types and functions commonly found on
 various systems, including libc.
 
 [![Build Status](https://travis-ci.org/rust-lang/libc.svg?branch=master)](https://travis-ci.org/rust-lang/libc)
 [![Build status](https://ci.appveyor.com/api/projects/status/github/rust-lang/libc?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/libc)
+[![Latest version](https://img.shields.io/crates/v/libc.svg)](https://crates.io/crates/libc)
+[![Documentation](https://docs.rs/libc/badge.svg)](https://docs.rs/libc)
+![License](https://img.shields.io/crates/l/libc.svg)
 
-[Documentation](#platforms-and-documentation)
 
 ## Usage
 
 First, add the following to your `Cargo.toml`:
 
 ```toml
 [dependencies]
 libc = "0.2"
@@ -28,16 +30,26 @@ Currently libc by default links to the standard library, but if you would
 instead like to use libc in a `#![no_std]` situation or crate you can request
 this via:
 
 ```toml
 [dependencies]
 libc = { version = "0.2", default-features = false }
 ```
 
+By default libc uses private fields in structs in order to enforce a certain
+memory alignment on them. These structs can be hard to instantiate outside of
+libc. To make libc use `#[repr(align(x))]`, instead of the private fields,
+activate the *align* feature. This requires Rust 1.25 or newer:
+
+```toml
+[dependencies]
+libc = { version = "0.2", features = ["align"] }
+```
+
 ## What is libc?
 
 The primary purpose of this crate is to provide all of the definitions necessary
 to easily interoperate with C code (or "C-like" code) on each of the platforms
 that Rust supports. This includes type definitions (e.g. `c_int`), constants
 (e.g. `EINVAL`) as well as function headers (e.g. `malloc`).
 
 This crate does not strive to have any form of compatibility across platforms,
@@ -117,43 +129,46 @@ it. If you'd like to get a release out ASAP you can follow these steps:
 
 [example]: https://github.com/rust-lang/libc/pull/583
 
 ## Platforms and Documentation
 
 The following platforms are currently tested and have documentation available:
 
 Tested:
-  * [`i686-pc-windows-msvc`](https://doc.rust-lang.org/libc/i686-pc-windows-msvc/libc/)
-  * [`x86_64-pc-windows-msvc`](https://doc.rust-lang.org/libc/x86_64-pc-windows-msvc/libc/)
+  * [`i686-pc-windows-msvc`](https://rust-lang.github.io/libc/i686-pc-windows-msvc/libc/)
+  * [`x86_64-pc-windows-msvc`](https://rust-lang.github.io/libc/x86_64-pc-windows-msvc/libc/)
     (Windows)
-  * [`i686-pc-windows-gnu`](https://doc.rust-lang.org/libc/i686-pc-windows-gnu/libc/)
-  * [`x86_64-pc-windows-gnu`](https://doc.rust-lang.org/libc/x86_64-pc-windows-gnu/libc/)
-  * [`i686-apple-darwin`](https://doc.rust-lang.org/libc/i686-apple-darwin/libc/)
-  * [`x86_64-apple-darwin`](https://doc.rust-lang.org/libc/x86_64-apple-darwin/libc/)
+  * [`i686-pc-windows-gnu`](https://rust-lang.github.io/libc/i686-pc-windows-gnu/libc/)
+  * [`x86_64-pc-windows-gnu`](https://rust-lang.github.io/libc/x86_64-pc-windows-gnu/libc/)
+  * [`i686-apple-darwin`](https://rust-lang.github.io/libc/i686-apple-darwin/libc/)
+  * [`x86_64-apple-darwin`](https://rust-lang.github.io/libc/x86_64-apple-darwin/libc/)
     (OSX)
   * `i386-apple-ios`
   * `x86_64-apple-ios`
-  * [`i686-unknown-linux-gnu`](https://doc.rust-lang.org/libc/i686-unknown-linux-gnu/libc/)
-  * [`x86_64-unknown-linux-gnu`](https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu/libc/)
+  * [`i686-unknown-linux-gnu`](https://rust-lang.github.io/libc/i686-unknown-linux-gnu/libc/)
+  * [`x86_64-unknown-linux-gnu`](https://rust-lang.github.io/libc/x86_64-unknown-linux-gnu/libc/)
     (Linux)
-  * [`x86_64-unknown-linux-musl`](https://doc.rust-lang.org/libc/x86_64-unknown-linux-musl/libc/)
+  * [`x86_64-unknown-linux-musl`](https://rust-lang.github.io/libc/x86_64-unknown-linux-musl/libc/)
     (Linux MUSL)
-  * [`aarch64-unknown-linux-gnu`](https://doc.rust-lang.org/libc/aarch64-unknown-linux-gnu/libc/)
+  * [`aarch64-unknown-linux-gnu`](https://rust-lang.github.io/libc/aarch64-unknown-linux-gnu/libc/)
     (Linux)
-  * [`aarch64-unknown-linux-musl`](https://doc.rust-lang.org/libc/aarch64-unknown-linux-musl/libc/)
+  * `aarch64-unknown-linux-musl`
     (Linux MUSL)
-  * [`mips-unknown-linux-gnu`](https://doc.rust-lang.org/libc/mips-unknown-linux-gnu/libc/)
-  * [`arm-unknown-linux-gnueabihf`](https://doc.rust-lang.org/libc/arm-unknown-linux-gnueabihf/libc/)
-  * [`arm-linux-androideabi`](https://doc.rust-lang.org/libc/arm-linux-androideabi/libc/)
+  * [`sparc64-unknown-linux-gnu`](https://rust-lang.github.io/libc/sparc64-unknown-linux-gnu/libc/)
+    (Linux)
+  * [`mips-unknown-linux-gnu`](https://rust-lang.github.io/libc/mips-unknown-linux-gnu/libc/)
+  * [`arm-unknown-linux-gnueabihf`](https://rust-lang.github.io/libc/arm-unknown-linux-gnueabihf/libc/)
+  * [`arm-linux-androideabi`](https://rust-lang.github.io/libc/arm-linux-androideabi/libc/)
     (Android)
-  * [`x86_64-unknown-freebsd`](https://doc.rust-lang.org/libc/x86_64-unknown-freebsd/libc/)
-  * [`x86_64-unknown-openbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-openbsd/libc/)
-  * [`x86_64-rumprun-netbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-netbsd/libc/)
+  * [`x86_64-unknown-freebsd`](https://rust-lang.github.io/libc/x86_64-unknown-freebsd/libc/)
+  * [`x86_64-unknown-openbsd`](https://rust-lang.github.io/libc/x86_64-unknown-openbsd/libc/)
+  * [`x86_64-rumprun-netbsd`](https://rust-lang.github.io/libc/x86_64-unknown-netbsd/libc/)
 
 The following may be supported, but are not guaranteed to always work:
 
   * `i686-unknown-freebsd`
-  * [`x86_64-unknown-bitrig`](https://doc.rust-lang.org/libc/x86_64-unknown-bitrig/libc/)
-  * [`x86_64-unknown-dragonfly`](https://doc.rust-lang.org/libc/x86_64-unknown-dragonfly/libc/)
+  * [`x86_64-unknown-bitrig`](https://rust-lang.github.io/libc/x86_64-unknown-bitrig/libc/)
+  * [`x86_64-unknown-dragonfly`](https://rust-lang.github.io/libc/x86_64-unknown-dragonfly/libc/)
   * `i686-unknown-haiku`
   * `x86_64-unknown-haiku`
-  * [`x86_64-unknown-netbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-netbsd/libc/)
+  * [`x86_64-unknown-netbsd`](https://rust-lang.github.io/libc/x86_64-unknown-netbsd/libc/)
+  * [`x86_64-sun-solaris`](https://rust-lang.github.io/libc/x86_64-sun-solaris/libc/)
diff --git a/third_party/rust/libc/appveyor.yml b/third_party/rust/libc/appveyor.yml
index 07ac4a92a5ae..fe2a332a1c42 100644
--- a/third_party/rust/libc/appveyor.yml
+++ b/third_party/rust/libc/appveyor.yml
@@ -19,9 +19,10 @@ install:
   - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
   - rustc -V
   - cargo -V
 
 build: false
 
 test_script:
   - cargo test --target %TARGET%
+  - cargo test --no-default-features --target %TARGET%
   - cargo test --manifest-path libc-test/Cargo.toml --target %TARGET%
diff --git a/third_party/rust/libc/ci/README.md b/third_party/rust/libc/ci/README.md
index aef6ef1db182..28152e5d00b9 100644
--- a/third_party/rust/libc/ci/README.md
+++ b/third_party/rust/libc/ci/README.md
@@ -123,42 +123,82 @@ testing almost everything!
 
 Below are some details of how to set up the initial OS images which are
 downloaded. Each image must be enabled have input/output over the serial
 console, log in automatically at the serial console, detect if a second drive in
 QEMU is available, and if so mount it, run a script (it'll specifically be
 `run-qemu.sh` in this folder which is copied into the generated image talked
 about above), and then shut down.
 
-### QEMU setup - FreeBSD
-
-1. Download CD installer (most minimal is fine)
-2. `qemu-img create -f qcow2 foo.qcow2 2G`
-3. `qemu -cdrom foo.iso -drive if=virtio,file=foo.qcow2 -net nic,model=virtio -net user`
-4. run installer
-5. `echo 'console="comconsole"' >> /boot/loader.conf`
-6. `echo 'autoboot_delay="0"' >> /boot/loader.conf`
-7. look at /etc/ttys, see what getty argument is for ttyu0
-8. edit /etc/gettytab, look for ttyu0 argument, prepend `:al=root` to line
-   beneath
-
-(note that the current image has a `freebsd` user, but this isn't really
-necessary)
-
-Once that's done, arrange for this script to run at login:
-
-```
-#!/bin/sh
-
-sudo kldload ext2fs
-[ -e /dev/vtbd1 ] || exit 0
-sudo mount -t ext2fs /dev/vtbd1 /mnt
-sh /mnt/run.sh /mnt
-sudo poweroff
-```
+### QEMU Setup - FreeBSD
+
+1. [Download the latest stable amd64-bootonly release ISO](https://www.freebsd.org/where.html).
+   E.g. FreeBSD-11.1-RELEASE-amd64-bootonly.iso
+2. Create the disk image: `qemu-img create -f qcow2 FreeBSD-11.1-RELEASE-amd64.qcow2 2G`
+3. Boot the machine: `qemu-system-x86_64 -cdrom FreeBSD-11.1-RELEASE-amd64-bootonly.iso -drive if=virtio,file=FreeBSD-11.1-RELEASE-amd64.qcow2 -net nic,model=virtio -net user`
+4. Run the installer, and install FreeBSD:
+   1. Install
+   1. Continue with default keymap
+   1. Set Hostname: freebsd-ci
+   1. Distribution Select:
+      1. Uncheck lib32
+      1. Uncheck ports
+   1. Network Configuration: vtnet0
+   1. Configure IPv4? Yes
+   1. DHCP? Yes
+   1. Configure IPv6? No
+   1. Resolver Configuration: Ok
+   1. Mirror Selection: Main Site
+   1. Partitioning: Auto (UFS)
+   1. Partition: Entire Disk
+   1. Partition Scheme: MBR
+   1. App Partition: Ok
+   1. Partition Editor: Finish
+   1. Confirmation: Commit
+   1. Wait for sets to install
+   1. Set the root password to nothing (press enter twice)
+   1. Set time zone to UTC
+   1. Set Date: Skip
+   1. Set Time: Skip
+   1. System Configuration:
+      1. Disable sshd
+      1. Disable dumpdev
+   1. System Hardening
+      1. Disable Sendmail service
+   1. Add User Accounts: No
+   1. Final Configuration: Exit
+   1. Manual Configuration: Yes
+   1. `echo 'console="comconsole"' >> /boot/loader.conf`
+   1. `echo 'autoboot_delay="0"' >> /boot/loader.conf`
+   1. `echo 'ext2fs_load="YES"' >> /boot/loader.conf`
+   1. Look at `/etc/ttys`, see what getty argument is for `ttyu0` (E.g. `3wire`)
+   1. Edit `/etc/gettytab` (with `vi` for example), look for `ttyu0` argument,
+      prepend `:al=root` to the line beneath to have the machine auto-login as
+      root. E.g.
+
+          3wire:\
+                   :np:nc:sp#0:
+      becomes:
+
+          3wire:\
+                   :al=root:np:nc:sp#0:
+
+   1. Edit `/root/.login` and put this in it:
+
+          [ -e /dev/vtbd1 ] || exit 0
+          mount -t ext2fs /dev/vtbd1 /mnt
+          sh /mnt/run.sh /mnt
+          poweroff
+
+   1. Exit the post install shell: `exit`
+   1. Back in in the installer choose Reboot
+   1. If all went well the machine should reboot and show a login prompt.
+      If you switch to the serial console by choosing View > serial0 in
+      the qemu menu, you should be logged in as root.
+   1. Shutdown the machine: `shutdown -p now`
 
 Helpful links
 
 * https://en.wikibooks.org/wiki/QEMU/Images
 * https://blog.nekoconeko.nl/blog/2015/06/04/creating-an-openstack-freebsd-image.html
 * https://www.freebsd.org/doc/handbook/serialconsole-setup.html
 
 
diff --git a/third_party/rust/libc/ci/docker/aarch64-unknown-linux-musl/Dockerfile b/third_party/rust/libc/ci/docker/aarch64-unknown-linux-musl/Dockerfile
index e86c4c0ae3d2..caec1572cbb9 100644
--- a/third_party/rust/libc/ci/docker/aarch64-unknown-linux-musl/Dockerfile
+++ b/third_party/rust/libc/ci/docker/aarch64-unknown-linux-musl/Dockerfile
@@ -1,27 +1,27 @@
 FROM ubuntu:17.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   gcc make libc6-dev git curl ca-certificates \
   gcc-aarch64-linux-gnu qemu-user
-RUN curl https://www.musl-libc.org/releases/musl-1.1.16.tar.gz | \
+RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \
     tar xzf - && \
-    cd musl-1.1.16 && \
+    cd musl-1.1.19 && \
     CC=aarch64-linux-gnu-gcc \
     ./configure --prefix=/musl-aarch64 --enable-wrapper=yes && \
     make install -j4 && \
     cd .. && \
-    rm -rf musl-1.1.16 && \
+    rm -rf musl-1.1.19
 # Install linux kernel headers sanitized for use with musl
-    curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \
+RUN curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \
     tar xzf - && \
-    cd kernel-headers-3.12.6-5 && \
+    cd kernel-headers-3.12.6-6 && \
     make ARCH=arm64 prefix=/musl-aarch64 install -j4 && \
     cd .. && \
-    rm -rf kernel-headers-3.12.6-5
+    rm -rf kernel-headers-3.12.6-6
 
 # FIXME: shouldn't need the `-lgcc` here, shouldn't that be in libstd?
 ENV PATH=$PATH:/musl-aarch64/bin:/rust/bin \
     CC_aarch64_unknown_linux_musl=musl-gcc \
     RUSTFLAGS='-Clink-args=-lgcc' \
     CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc \
     CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUNNER="qemu-aarch64 -L /musl-aarch64"
diff --git a/third_party/rust/libc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile b/third_party/rust/libc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile
index 130730b99733..86304130fe30 100644
--- a/third_party/rust/libc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile
+++ b/third_party/rust/libc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile
@@ -1,25 +1,25 @@
 FROM ubuntu:17.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   gcc make libc6-dev git curl ca-certificates \
   gcc-arm-linux-gnueabihf qemu-user
 
-RUN curl https://www.musl-libc.org/releases/musl-1.1.16.tar.gz | tar xzf -
-WORKDIR /musl-1.1.16
+RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | tar xzf -
+WORKDIR /musl-1.1.19
 RUN CC=arm-linux-gnueabihf-gcc \
     CFLAGS="-march=armv6 -marm" \
     ./configure --prefix=/musl-arm --enable-wrapper=yes
 RUN make install -j4
 
 # Install linux kernel headers sanitized for use with musl
-RUN \
-    curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \
+RUN curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \
     tar xzf - && \
-    cd kernel-headers-3.12.6-5 && \
+    cd kernel-headers-3.12.6-6 && \
     make ARCH=arm prefix=/musl-arm install -j4 && \
     cd .. && \
-    rm -rf kernel-headers-3.12.6-5
+    rm -rf kernel-headers-3.12.6-6
+
 ENV PATH=$PATH:/musl-arm/bin:/rust/bin \
     CC_arm_unknown_linux_musleabihf=musl-gcc \
     CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABIHF_LINKER=musl-gcc \
     CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABIHF_RUNNER="qemu-arm -L /musl-arm"
diff --git a/third_party/rust/libc/ci/docker/i686-unknown-linux-gnu/Dockerfile b/third_party/rust/libc/ci/docker/i686-unknown-linux-gnu/Dockerfile
index 1af41343e268..03f3e8e690e3 100644
--- a/third_party/rust/libc/ci/docker/i686-unknown-linux-gnu/Dockerfile
+++ b/third_party/rust/libc/ci/docker/i686-unknown-linux-gnu/Dockerfile
@@ -1,5 +1,5 @@
-FROM ubuntu:17.04
+FROM ubuntu:18.04
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
   gcc-multilib libc6-dev ca-certificates
 ENV PATH=$PATH:/rust/bin
diff --git a/third_party/rust/libc/ci/docker/i686-unknown-linux-musl/Dockerfile b/third_party/rust/libc/ci/docker/i686-unknown-linux-musl/Dockerfile
index 3adb92004084..49f37d70f2af 100644
--- a/third_party/rust/libc/ci/docker/i686-unknown-linux-musl/Dockerfile
+++ b/third_party/rust/libc/ci/docker/i686-unknown-linux-musl/Dockerfile
@@ -7,24 +7,25 @@ RUN apt-get install -y --no-install-recommends \
 # Below we're cross-compiling musl for i686 using the system compiler on an
 # x86_64 system. This is an awkward thing to be doing and so we have to jump
 # through a couple hoops to get musl to be happy. In particular:
 #
 # * We specifically pass -m32 in CFLAGS and override CC when running ./configure,
 #   since otherwise the script will fail to find a compiler.
 # * We manually unset CROSS_COMPILE when running make; otherwise the makefile
 #   will call the non-existent binary 'i686-ar'.
-RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \
+RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \
     tar xzf - && \
-    cd musl-1.1.15 && \
+    cd musl-1.1.19 && \
     CC=gcc CFLAGS=-m32 ./configure --prefix=/musl-i686 --disable-shared --target=i686 && \
     make CROSS_COMPILE= install -j4 && \
     cd .. && \
-    rm -rf musl-1.1.15 && \
+    rm -rf musl-1.1.19
 # Install linux kernel headers sanitized for use with musl
-    curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \
+RUN curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \
     tar xzf - && \
-    cd kernel-headers-3.12.6-5 && \
+    cd kernel-headers-3.12.6-6 && \
     make ARCH=i386 prefix=/musl-i686 install -j4 && \
     cd .. && \
-    rm -rf kernel-headers-3.12.6-5
+    rm -rf kernel-headers-3.12.6-6
+
 ENV PATH=$PATH:/musl-i686/bin:/rust/bin \
     CC_i686_unknown_linux_musl=musl-gcc
diff --git a/third_party/rust/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile b/third_party/rust/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile
index 49a277d884f5..861f4f9b00ee 100644
--- a/third_party/rust/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile
+++ b/third_party/rust/libc/ci/docker/s390x-unknown-linux-gnu/Dockerfile
@@ -1,12 +1,18 @@
 FROM ubuntu:17.10
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-s390x-linux-gnu libc6-dev-s390x-cross
+        curl ca-certificates \
+        gcc libc6-dev \
+        gcc-s390x-linux-gnu libc6-dev-s390x-cross \
+        qemu-system-s390x \
+        cpio
+
+COPY linux-s390x.sh /
+RUN bash /linux-s390x.sh
+
+COPY test-runner-linux /
 
 ENV CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_LINKER=s390x-linux-gnu-gcc \
-    # TODO: in theory we should execute this, but qemu segfaults immediately :(
-    # CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_RUNNER="qemu-s390x -L /usr/s390x-linux-gnu" \
-    CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_RUNNER=true \
+    CARGO_TARGET_S390X_UNKNOWN_LINUX_GNU_RUNNER="/test-runner-linux s390x" \
     CC_s390x_unknown_linux_gnu=s390x-linux-gnu-gcc \
     PATH=$PATH:/rust/bin
diff --git a/third_party/rust/libc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile b/third_party/rust/libc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile
index 2d53371add9c..d9edaab42635 100644
--- a/third_party/rust/libc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile
+++ b/third_party/rust/libc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile
@@ -1,14 +1,21 @@
-# link fails on 17.10
-FROM ubuntu:17.04
+FROM debian:stretch
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
-        gcc libc6-dev qemu-user ca-certificates \
-        gcc-sparc64-linux-gnu libc6-dev-sparc64-cross
+        curl ca-certificates \
+        gcc libc6-dev \
+        gcc-sparc64-linux-gnu libc6-dev-sparc64-cross \
+        qemu-system-sparc64 openbios-sparc seabios ipxe-qemu \
+        p7zip-full cpio linux-libc-dev-sparc64-cross linux-headers-4.9.0-3-common
+
+# Put linux/module.h into the right spot as it is not shipped by debian
+RUN cp /usr/src/linux-headers-4.9.0-3-common/include/uapi/linux/module.h /usr/sparc64-linux-gnu/include/linux/
+
+COPY linux-sparc64.sh /
+RUN bash /linux-sparc64.sh
+
+COPY test-runner-linux /
 
 ENV CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER=sparc64-linux-gnu-gcc \
-    # TODO: in theory we should execute this, but qemu segfaults immediately
-    #       see https://github.com/rust-lang/libc/issues/822
-    # CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_RUNNER="qemu-sparc64 -L /usr/sparc64-linux-gnu" \
-    CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_RUNNER=true \
+    CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_RUNNER="/test-runner-linux sparc64" \
     CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
     PATH=$PATH:/rust/bin
diff --git a/third_party/rust/libc/ci/docker/wasm32-unknown-emscripten/node-wrapper.sh b/third_party/rust/libc/ci/docker/wasm32-unknown-emscripten/node-wrapper.sh
index b1936f041070..3122e2e23b41 100755
--- a/third_party/rust/libc/ci/docker/wasm32-unknown-emscripten/node-wrapper.sh
+++ b/third_party/rust/libc/ci/docker/wasm32-unknown-emscripten/node-wrapper.sh
@@ -2,10 +2,14 @@
 
 set -e
 
 me=$1
 shift
 dir=$(dirname $me)
 file=$(basename $me)
 
+if echo $file | grep -q wasm; then
+  exit 0 # FIXME(rust-lang/cargo#4750)
+fi
+
 cd $dir
 exec node $file "$@"
diff --git a/third_party/rust/libc/ci/docker/x86_64-unknown-freebsd/Dockerfile b/third_party/rust/libc/ci/docker/x86_64-unknown-freebsd/Dockerfile
index 7ad3faff37c0..35f103657585 100644
--- a/third_party/rust/libc/ci/docker/x86_64-unknown-freebsd/Dockerfile
+++ b/third_party/rust/libc/ci/docker/x86_64-unknown-freebsd/Dockerfile
@@ -1,13 +1,13 @@
-FROM alexcrichton/port-prebuilt-freebsd:2017-09-16
+FROM wezm/port-prebuilt-freebsd11@sha256:43553e2265ec702ec72a63a765df333f50b1858b896e69385749e96d8624e9b0
 
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
-  qemu genext2fs
+  qemu genext2fs xz-utils
 RUN apt-get install -y curl ca-certificates gcc
 
 ENTRYPOINT ["sh"]
 
 ENV PATH=$PATH:/rust/bin \
-    QEMU=2016-11-06/freebsd.qcow2.gz \
+    QEMU=2018-03-15/FreeBSD-11.1-RELEASE-amd64.qcow2.xz \
     CAN_CROSS=1 \
-    CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER=x86_64-unknown-freebsd10-gcc
+    CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER=x86_64-unknown-freebsd11-gcc
diff --git a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
index c5ec6826d236..6ab9c9231955 100644
--- a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
+++ b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnu/Dockerfile
@@ -1,5 +1,5 @@
-FROM ubuntu:17.04
+FROM ubuntu:18.04
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
   gcc libc6-dev ca-certificates
 ENV PATH=$PATH:/rust/bin
diff --git a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile
index 1af41343e268..03f3e8e690e3 100644
--- a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile
+++ b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile
@@ -1,5 +1,5 @@
-FROM ubuntu:17.04
+FROM ubuntu:18.04
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
   gcc-multilib libc6-dev ca-certificates
 ENV PATH=$PATH:/rust/bin
diff --git a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile
index d9d651138661..6e2b7d9e5ea7 100644
--- a/third_party/rust/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile
+++ b/third_party/rust/libc/ci/docker/x86_64-unknown-linux-musl/Dockerfile
@@ -1,20 +1,20 @@
 FROM ubuntu:17.10
 
 RUN apt-get update
 RUN apt-get install -y --no-install-recommends \
   gcc make libc6-dev git curl ca-certificates
-RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \
+RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \
     tar xzf - && \
-    cd musl-1.1.15 && \
+    cd musl-1.1.19 && \
     ./configure --prefix=/musl-x86_64 && \
     make install -j4 && \
     cd .. && \
-    rm -rf musl-1.1.15 && \
+    rm -rf musl-1.1.19
 # Install linux kernel headers sanitized for use with musl
-    curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \
+RUN curl -L  https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \
     tar xzf - && \
-    cd kernel-headers-3.12.6-5 && \
+    cd kernel-headers-3.12.6-6 && \
     make ARCH=x86_64 prefix=/musl-x86_64 install -j4 && \
     cd .. && \
-    rm -rf kernel-headers-3.12.6-5
+    rm -rf kernel-headers-3.12.6-6
 ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin
diff --git a/third_party/rust/libc/ci/dox.sh b/third_party/rust/libc/ci/dox.sh
index 85e92439484c..b8ffa7dd0d07 100644
--- a/third_party/rust/libc/ci/dox.sh
+++ b/third_party/rust/libc/ci/dox.sh
@@ -11,17 +11,17 @@ TARGETS=`grep html_root_url src/lib.rs | sed 's/.*".*\/\(.*\)"/\1/'`
 rm -rf target/doc
 mkdir -p target/doc
 
 cp ci/landing-page-head.html target/doc/index.html
 
 for target in $TARGETS; do
   echo documenting $target
 
-  rustdoc -o target/doc/$target --target $target src/lib.rs --cfg dox \
+  rustdoc -o target/doc/$target --target $target src/lib.rs --cfg cross_platform_docs \
     --crate-name libc
 
   echo "<li><a href="/libc/$target/libc/index.html">$target</a></li>" \
     >> target/doc/index.html
 done
 
 cat ci/landing-page-footer.html >> target/doc/index.html
 
diff --git a/third_party/rust/libc/ci/emscripten-entry.sh b/third_party/rust/libc/ci/emscripten-entry.sh
index acaebfe8c7cb..22ae8b08a3ae 100755
--- a/third_party/rust/libc/ci/emscripten-entry.sh
+++ b/third_party/rust/libc/ci/emscripten-entry.sh
@@ -1,9 +1,9 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 # file at the top-level directory of this distribution and at
 # http://rust-lang.org/COPYRIGHT.
 #
 # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 # option. This file may not be copied, modified, or distributed
diff --git a/third_party/rust/libc/ci/ios/deploy_and_run_on_ios_simulator.rs b/third_party/rust/libc/ci/ios/deploy_and_run_on_ios_simulator.rs
index b14615036d02..95df52d76d59 100644
--- a/third_party/rust/libc/ci/ios/deploy_and_run_on_ios_simulator.rs
+++ b/third_party/rust/libc/ci/ios/deploy_and_run_on_ios_simulator.rs
@@ -118,16 +118,17 @@ fn run_app_on_simulator() {
     let output = t!(Command::new("xcrun")
                     .arg("simctl")
                     .arg("launch")
                     .arg("--console")
                     .arg("booted")
                     .arg("com.rust.unittests")
                     .output());
 
+    println!("status: {}", output.status);
     println!("stdout --\n{}\n", String::from_utf8_lossy(&output.stdout));
     println!("stderr --\n{}\n", String::from_utf8_lossy(&output.stderr));
 
     let stdout = String::from_utf8_lossy(&output.stdout);
     let passed = stdout.lines()
                        .find(|l| l.contains("PASSED"))
                        .map(|l| l.contains("tests"))
                        .unwrap_or(false);
diff --git a/third_party/rust/libc/ci/linux-s390x.sh b/third_party/rust/libc/ci/linux-s390x.sh
new file mode 100644
index 000000000000..972abeec569e
--- /dev/null
+++ b/third_party/rust/libc/ci/linux-s390x.sh
@@ -0,0 +1,18 @@
+set -ex
+
+mkdir -m 777 /qemu
+cd /qemu
+
+curl -LO https://github.com/qemu/qemu/raw/master/pc-bios/s390-ccw.img
+curl -LO http://ftp.debian.org/debian/dists/testing/main/installer-s390x/20170828/images/generic/kernel.debian
+curl -LO http://ftp.debian.org/debian/dists/testing/main/installer-s390x/20170828/images/generic/initrd.debian
+
+mv kernel.debian kernel
+mv initrd.debian initrd.gz
+
+mkdir init
+cd init
+gunzip -c ../initrd.gz | cpio -id
+rm ../initrd.gz
+cp /usr/s390x-linux-gnu/lib/libgcc_s.so.1 usr/lib/
+chmod a+w .
diff --git a/third_party/rust/libc/ci/linux-sparc64.sh b/third_party/rust/libc/ci/linux-sparc64.sh
new file mode 100644
index 000000000000..4452b120e1b6
--- /dev/null
+++ b/third_party/rust/libc/ci/linux-sparc64.sh
@@ -0,0 +1,17 @@
+set -ex
+
+mkdir -m 777 /qemu
+cd /qemu
+
+curl -LO https://cdimage.debian.org/cdimage/ports/9.0/sparc64/iso-cd/debian-9.0-sparc64-NETINST-1.iso
+7z e debian-9.0-sparc64-NETINST-1.iso boot/initrd.gz
+7z e debian-9.0-sparc64-NETINST-1.iso boot/sparc64
+mv sparc64 kernel
+rm debian-9.0-sparc64-NETINST-1.iso
+
+mkdir init
+cd init
+gunzip -c ../initrd.gz | cpio -id
+rm ../initrd.gz
+cp /usr/sparc64-linux-gnu/lib/libgcc_s.so.1 usr/lib/
+chmod a+w .
diff --git a/third_party/rust/libc/ci/run.sh b/third_party/rust/libc/ci/run.sh
index 420542a561c1..27ffc054a081 100755
--- a/third_party/rust/libc/ci/run.sh
+++ b/third_party/rust/libc/ci/run.sh
@@ -19,16 +19,23 @@ if [ "$QEMU" != "" ]; then
 
   if [ -z "${QEMU#*.gz}" ]; then
     # image is .gz : download and uncompress it
     qemufile=$(echo ${QEMU%.gz} | sed 's/\//__/g')
     if [ ! -f $tmpdir/$qemufile ]; then
       curl https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc/$QEMU | \
         gunzip -d > $tmpdir/$qemufile
     fi
+  elif [ -z "${QEMU#*.xz}" ]; then
+    # image is .xz : download and uncompress it
+    qemufile=$(echo ${QEMU%.xz} | sed 's/\//__/g')
+    if [ ! -f $tmpdir/$qemufile ]; then
+      curl https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc/$QEMU | \
+        unxz > $tmpdir/$qemufile
+    fi
   else
     # plain qcow2 image: just download it
     qemufile=$(echo ${QEMU} | sed 's/\//__/g')
     if [ ! -f $tmpdir/$qemufile ]; then
       curl https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc/$QEMU \
         > $tmpdir/$qemufile
     fi
   fi
@@ -36,17 +43,21 @@ if [ "$QEMU" != "" ]; then
   # Create a mount a fresh new filesystem image that we'll later pass to QEMU.
   # This will have a `run.sh` script will which use the artifacts inside to run
   # on the host.
   rm -f $tmpdir/libc-test.img
   mkdir $tmpdir/mount
 
   # Do the standard rigamarole of cross-compiling an executable and then the
   # script to run just executes the binary.
-  cargo build --manifest-path libc-test/Cargo.toml --target $TARGET --tests
+  cargo build \
+    --manifest-path libc-test/Cargo.toml \
+    --target $TARGET \
+    --test main
+  rm $CARGO_TARGET_DIR/$TARGET/debug/main-*.d
   cp $CARGO_TARGET_DIR/$TARGET/debug/main-* $tmpdir/mount/libc-test
   echo 'exec $1/libc-test' > $tmpdir/mount/run.sh
 
   du -sh $tmpdir/mount
   genext2fs \
       --root $tmpdir/mount \
       --size-in-blocks 100000 \
       $tmpdir/libc-test.img
@@ -63,16 +74,25 @@ if [ "$QEMU" != "" ]; then
     -drive if=virtio,file=$tmpdir/libc-test.img \
     -net nic,model=virtio \
     -net user \
     -nographic \
     -vga none 2>&1 | tee $CARGO_TARGET_DIR/out.log
   exec grep "^PASSED .* tests" $CARGO_TARGET_DIR/out.log
 fi
 
-# FIXME: x86_64-unknown-linux-gnux32 fail to compile wihout --release
+# FIXME: x86_64-unknown-linux-gnux32 fail to compile without --release
 # See https://github.com/rust-lang/rust/issues/45417
 opt=
 if [ "$TARGET" = "x86_64-unknown-linux-gnux32" ]; then
   opt="--release"
 fi
 
+# Building with --no-default-features is currently broken on rumprun because we
+# need cfg(target_vendor), which is currently unstable.
+if [ "$TARGET" != "x86_64-rumprun-netbsd" ]; then
+  cargo test $opt --no-default-features --manifest-path libc-test/Cargo.toml --target $TARGET
+fi
+# Test the #[repr(align(x))] feature if this is building on Rust >= 1.25
+if [ $(rustc --version | sed -E 's/^rustc 1\.([0-9]*)\..*/\1/') -ge 25 ]; then
+  cargo test $opt --features align --manifest-path libc-test/Cargo.toml --target $TARGET
+fi
 exec cargo test $opt --manifest-path libc-test/Cargo.toml --target $TARGET
diff --git a/third_party/rust/libc/ci/style.rs b/third_party/rust/libc/ci/style.rs
index 32e4ba772c5b..bf31576b909a 100644
--- a/third_party/rust/libc/ci/style.rs
+++ b/third_party/rust/libc/ci/style.rs
@@ -122,17 +122,19 @@ fn check_style(file: &str, path: &Path, err: &mut Errors) {
             err.error(path, i, "tab character");
         }
         if line.len() > 80 {
             err.error(path, i, "line longer than 80 chars");
         }
         if line.contains("extern \"C\"") {
             err.error(path, i, "use `extern` instead of `extern \"C\"");
         }
-        if line.contains("#[cfg(") && !line.contains(" if ") {
+        if line.contains("#[cfg(") && !line.contains(" if ")
+            && !line.contains("target_endian")
+        {
             if state != State::Structs {
                 err.error(path, i, "use cfg_if! and submodules \
                                     instead of #[cfg]");
             }
         }
 
         let line = line.trim_left();
         let is_pub = line.starts_with("pub ");
diff --git a/third_party/rust/libc/ci/test-runner-linux b/third_party/rust/libc/ci/test-runner-linux
new file mode 100755
index 000000000000..5f1fb237c28e
--- /dev/null
+++ b/third_party/rust/libc/ci/test-runner-linux
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+
+arch=$1
+prog=$2
+
+cd /qemu/init
+cp -f $2 prog
+find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz
+cd ..
+
+timeout 30s qemu-system-$arch \
+  -m 1024 \
+  -nographic \
+  -kernel kernel \
+  -initrd initrd.gz \
+  -append init=/prog > output || true
+
+# remove kernel messages
+tr -d '\r' < output | egrep -v '^\['
+
+grep PASSED output > /dev/null
diff --git a/third_party/rust/libc/src/cloudabi/aarch64.rs b/third_party/rust/libc/src/cloudabi/aarch64.rs
new file mode 100644
index 000000000000..4caa6d7bbcf4
--- /dev/null
+++ b/third_party/rust/libc/src/cloudabi/aarch64.rs
@@ -0,0 +1,4 @@
+pub type c_char = u8;
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type wchar_t = u32;
diff --git a/third_party/rust/libc/src/cloudabi/arm.rs b/third_party/rust/libc/src/cloudabi/arm.rs
new file mode 100644
index 000000000000..eca536074412
--- /dev/null
+++ b/third_party/rust/libc/src/cloudabi/arm.rs
@@ -0,0 +1,4 @@
+pub type c_char = u8;
+pub type c_long = i32;
+pub type c_ulong = u32;
+pub type wchar_t = u32;
diff --git a/third_party/rust/libc/src/cloudabi/mod.rs b/third_party/rust/libc/src/cloudabi/mod.rs
new file mode 100644
index 000000000000..e506414e3494
--- /dev/null
+++ b/third_party/rust/libc/src/cloudabi/mod.rs
@@ -0,0 +1,166 @@
+pub type in_addr_t = u32;
+pub type in_port_t = u16;
+pub type pthread_key_t = usize;
+pub type pthread_t = usize;
+pub type sa_family_t = u8;
+pub type socklen_t = usize;
+pub type time_t = i64;
+
+s! {
+    pub struct addrinfo {
+        pub ai_flags: ::c_int,
+        pub ai_family: ::c_int,
+        pub ai_socktype: ::c_int,
+        pub ai_protocol: ::c_int,
+        pub ai_addrlen: ::socklen_t,
+        pub ai_addr: *mut ::sockaddr,
+        pub ai_canonname: *mut ::c_char,
+        pub ai_next: *mut addrinfo,
+    }
+
+    pub struct in_addr {
+        pub s_addr: in_addr_t,
+    }
+
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+
+    pub struct pthread_attr_t {
+        __detachstate: ::c_int,
+        __stacksize: usize,
+    }
+
+    pub struct sockaddr {
+        pub sa_family: sa_family_t,
+        pub sa_data: [::c_char; 0],
+    }
+
+    pub struct sockaddr_in {
+        pub sin_family: ::sa_family_t,
+        pub sin_port: ::in_port_t,
+        pub sin_addr: ::in_addr,
+    }
+
+    pub struct sockaddr_in6 {
+        pub sin6_family: sa_family_t,
+        pub sin6_port: ::in_port_t,
+        pub sin6_flowinfo: u32,
+        pub sin6_addr: ::in6_addr,
+        pub sin6_scope_id: u32,
+    }
+
+    pub struct sockaddr_storage {
+        pub ss_family: ::sa_family_t,
+        __ss_data: [u8; 32],
+    }
+}
+
+pub const _SC_NPROCESSORS_ONLN: ::c_int = 52;
+pub const _SC_PAGESIZE: ::c_int = 54;
+
+pub const AF_INET: ::c_int = 1;
+pub const AF_INET6: ::c_int = 2;
+
+pub const EACCES: ::c_int = 2;
+pub const EADDRINUSE: ::c_int = 3;
+pub const EADDRNOTAVAIL: ::c_int = 4;
+pub const EAGAIN: ::c_int = 6;
+pub const ECONNABORTED: ::c_int = 13;
+pub const ECONNREFUSED: ::c_int = 14;
+pub const ECONNRESET: ::c_int = 15;
+pub const EEXIST: ::c_int = 20;
+pub const EINTR: ::c_int = 27;
+pub const EINVAL: ::c_int = 28;
+pub const ENOENT: ::c_int = 44;
+pub const ENOTCONN: ::c_int = 53;
+pub const EPERM: ::c_int = 63;
+pub const EPIPE: ::c_int = 64;
+pub const ETIMEDOUT: ::c_int = 73;
+pub const EWOULDBLOCK: ::c_int = EAGAIN;
+
+pub const EAI_SYSTEM: ::c_int = 9;
+
+pub const EXIT_FAILURE: ::c_int = 1;
+pub const EXIT_SUCCESS: ::c_int = 0;
+
+pub const PTHREAD_STACK_MIN: ::size_t = 1024;
+
+pub const SOCK_DGRAM: ::c_int = 128;
+pub const SOCK_STREAM: ::c_int = 130;
+
+extern {
+    pub fn arc4random_buf(buf: *const ::c_void, len: ::size_t);
+    pub fn freeaddrinfo(res: *mut addrinfo);
+    pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char;
+    pub fn getaddrinfo(
+        node: *const c_char,
+        service: *const c_char,
+        hints: *const addrinfo,
+        res: *mut *mut addrinfo,
+    ) -> ::c_int;
+    pub fn getsockopt(
+        sockfd: ::c_int,
+        level: ::c_int,
+        optname: ::c_int,
+        optval: *mut ::c_void,
+        optlen: *mut ::socklen_t,
+    ) -> ::c_int;
+    pub fn posix_memalign(
+        memptr: *mut *mut ::c_void,
+        align: ::size_t,
+        size: ::size_t,
+    ) -> ::c_int;
+    pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int;
+    pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int;
+    pub fn pthread_attr_setstacksize(
+        attr: *mut ::pthread_attr_t,
+        stack_size: ::size_t,
+    ) -> ::c_int;
+    pub fn pthread_create(
+        native: *mut ::pthread_t,
+        attr: *const ::pthread_attr_t,
+        f: extern fn(*mut ::c_void) -> *mut ::c_void,
+        value: *mut ::c_void,
+    ) -> ::c_int;
+    pub fn pthread_detach(thread: ::pthread_t) -> ::c_int;
+    pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void;
+    pub fn pthread_join(
+        native: ::pthread_t,
+        value: *mut *mut ::c_void,
+    ) -> ::c_int;
+    pub fn pthread_key_create(
+        key: *mut pthread_key_t,
+        dtor: Option<unsafe extern fn(*mut ::c_void)>,
+    ) -> ::c_int;
+    pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int;
+    pub fn pthread_setspecific(
+        key: pthread_key_t,
+        value: *const ::c_void,
+    ) -> ::c_int;
+    pub fn send(
+        socket: ::c_int,
+        buf: *const ::c_void,
+        len: ::size_t,
+        flags: ::c_int,
+    ) -> ::ssize_t;
+    pub fn sysconf(name: ::c_int) -> ::c_long;
+}
+
+cfg_if! {
+    if #[cfg(target_arch = "aarch64")] {
+        mod aarch64;
+        pub use self::aarch64::*;
+    } else if #[cfg(any(target_arch = "arm"))] {
+        mod arm;
+        pub use self::arm::*;
+    } else if #[cfg(any(target_arch = "x86"))] {
+        mod x86;
+        pub use self::x86::*;
+    } else if #[cfg(any(target_arch = "x86_64"))] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else {
+        // Unknown target_arch
+    }
+}
diff --git a/third_party/rust/libc/src/cloudabi/x86.rs b/third_party/rust/libc/src/cloudabi/x86.rs
new file mode 100644
index 000000000000..2f9f39c9b9ec
--- /dev/null
+++ b/third_party/rust/libc/src/cloudabi/x86.rs
@@ -0,0 +1,4 @@
+pub type c_char = i8;
+pub type c_long = i32;
+pub type c_ulong = u32;
+pub type wchar_t = i32;
diff --git a/third_party/rust/libc/src/cloudabi/x86_64.rs b/third_party/rust/libc/src/cloudabi/x86_64.rs
new file mode 100644
index 000000000000..bb17624b1dd7
--- /dev/null
+++ b/third_party/rust/libc/src/cloudabi/x86_64.rs
@@ -0,0 +1,4 @@
+pub type c_char = i8;
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type wchar_t = i32;
diff --git a/third_party/rust/libc/src/dox.rs b/third_party/rust/libc/src/dox.rs
index 6a1b6883df15..779641b3cc36 100644
--- a/third_party/rust/libc/src/dox.rs
+++ b/third_party/rust/libc/src/dox.rs
@@ -1,29 +1,39 @@
 pub use self::imp::*;
 
-#[cfg(not(dox))]
+#[cfg(not(cross_platform_docs))]
 mod imp {
     pub use core::option::Option;
     pub use core::clone::Clone;
     pub use core::marker::Copy;
     pub use core::mem;
 }
 
-#[cfg(dox)]
+#[cfg(cross_platform_docs)]
 mod imp {
     pub enum Option<T> {
         Some(T),
         None,
     }
     impl<T: Copy> Copy for Option<T> {}
     impl<T: Clone> Clone for Option<T> {
         fn clone(&self) -> Option<T> { loop {} }
     }
 
+    impl<T> Copy for *mut T {}
+    impl<T> Clone for *mut T {
+        fn clone(&self) -> *mut T { loop {} }
+    }
+
+    impl<T> Copy for *const T {}
+    impl<T> Clone for *const T {
+        fn clone(&self) -> *const T { loop {} }
+    }
+
     pub trait Clone {
         fn clone(&self) -> Self;
     }
 
     #[lang = "copy"]
     pub trait Copy {}
 
     #[lang = "freeze"]
@@ -53,45 +63,72 @@ mod imp {
             $mac!(i16);
             $mac!(i32);
             $mac!(i64);
             $mac!(isize);
         )
     }
 
     #[lang = "div"]
-    pub trait Div<RHS> {
+    pub trait Div<RHS=Self> {
         type Output;
         fn div(self, rhs: RHS) -> Self::Output;
     }
 
     #[lang = "shl"]
-    pub trait Shl<RHS> {
+    pub trait Shl<RHS=Self> {
         type Output;
         fn shl(self, rhs: RHS) -> Self::Output;
     }
 
     #[lang = "mul"]
     pub trait Mul<RHS=Self> {
         type Output;
         fn mul(self, rhs: RHS) -> Self::Output;
     }
 
     #[lang = "sub"]
     pub trait Sub<RHS=Self> {
         type Output;
         fn sub(self, rhs: RHS) -> Self::Output;
     }
 
+    #[lang = "bitand"]
+    pub trait BitAnd<RHS=Self> {
+        type Output;
+        fn bitand(self, rhs: RHS) -> Self::Output;
+    }
+
+    #[lang = "bitand_assign"]
+    pub trait BitAndAssign<RHS = Self> {
+        fn bitand_assign(&mut self, rhs: RHS);
+    }
+
     #[lang = "bitor"]
-    pub trait Bitor<RHS=Self> {
+    pub trait BitOr<RHS=Self> {
         type Output;
         fn bitor(self, rhs: RHS) -> Self::Output;
     }
 
+    #[lang = "bitor_assign"]
+    pub trait BitOrAssign<RHS = Self> {
+        fn bitor_assign(&mut self, rhs: RHS);
+    }
+
+    #[lang = "bitxor"]
+    pub trait BitXor<RHS=Self> {
+        type Output;
+        fn bitxor(self, rhs: RHS) -> Self::Output;
+    }
+
+    #[lang = "bitxor_assign"]
+    pub trait BitXorAssign<RHS = Self> {
+        fn bitxor_assign(&mut self, rhs: RHS);
+    }
+
     #[lang = "neg"]
     pub trait Neg {
         type Output;
         fn neg(self) -> Self::Output;
     }
 
     #[lang = "not"]
     pub trait Not {
@@ -119,32 +156,54 @@ mod imp {
                 type Output = $i;
                 fn mul(self, rhs: $i) -> $i { self * rhs }
             }
 
             impl Sub for $i {
                 type Output = $i;
                 fn sub(self, rhs: $i) -> $i { self - rhs }
             }
-            impl Bitor for $i {
+            impl BitAnd for $i {
+                type Output = $i;
+                fn bitand(self, rhs: $i) -> $i { self & rhs }
+            }
+            impl BitAndAssign for $i {
+                fn bitand_assign(&mut self, rhs: $i) { *self &= rhs; }
+            }
+            impl BitOr for $i {
                 type Output = $i;
                 fn bitor(self, rhs: $i) -> $i { self | rhs }
             }
+            impl BitOrAssign for $i {
+                fn bitor_assign(&mut self, rhs: $i) { *self |= rhs; }
+            }
+            impl BitXor for $i {
+                type Output = $i;
+                fn bitxor(self, rhs: $i) -> $i { self ^ rhs }
+            }
+            impl BitXorAssign for $i {
+                fn bitxor_assign(&mut self, rhs: $i) { *self ^= rhs; }
+            }
             impl Neg for $i {
                 type Output = $i;
                 fn neg(self) -> $i { -self }
             }
             impl Not for $i {
                 type Output = $i;
                 fn not(self) -> $i { !self }
             }
             impl Add<$i> for $i {
                 type Output = $i;
                 fn add(self, other: $i) -> $i { self + other }
             }
+            impl Copy for $i {}
+            impl Clone for $i {
+                fn clone(&self) -> $i { loop {} }
+            }
         )*)
     }
     each_int!(impl_traits);
 
     pub mod mem {
         pub fn size_of_val<T>(_: &T) -> usize { 4 }
+        pub const fn size_of<T>() -> usize { 4 }
     }
 }
diff --git a/third_party/rust/libc/src/fuchsia/aarch64.rs b/third_party/rust/libc/src/fuchsia/aarch64.rs
new file mode 100644
index 000000000000..157d3d6e9e73
--- /dev/null
+++ b/third_party/rust/libc/src/fuchsia/aarch64.rs
@@ -0,0 +1,336 @@
+pub type c_char = u8;
+pub type __u64 = ::c_ulonglong;
+pub type wchar_t = u32;
+pub type nlink_t = u32;
+pub type blksize_t = ::c_int;
+
+s! {
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __pad0: ::c_ulong,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        __pad1: ::c_int,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_uint; 2],
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __pad0: ::c_ulong,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        __pad1: ::c_int,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_uint; 2],
+    }
+
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_ushort,
+        __unused1: ::c_ulong,
+        __unused2: ::c_ulong,
+    }
+}
+
+pub const MINSIGSTKSZ: ::size_t = 6144;
+pub const SIGSTKSZ: ::size_t = 12288;
+
+#[doc(hidden)]
+pub const PF_MAX: ::c_int = 43;
+#[doc(hidden)]
+pub const AF_MAX: ::c_int = PF_MAX;
+
+pub const SYS_io_setup: ::c_long = 0;
+pub const SYS_io_destroy: ::c_long = 1;
+pub const SYS_io_submit: ::c_long = 2;
+pub const SYS_io_cancel: ::c_long = 3;
+pub const SYS_io_getevents: ::c_long = 4;
+pub const SYS_setxattr: ::c_long = 5;
+pub const SYS_lsetxattr: ::c_long = 6;
+pub const SYS_fsetxattr: ::c_long = 7;
+pub const SYS_getxattr: ::c_long = 8;
+pub const SYS_lgetxattr: ::c_long = 9;
+pub const SYS_fgetxattr: ::c_long = 10;
+pub const SYS_listxattr: ::c_long = 11;
+pub const SYS_llistxattr: ::c_long = 12;
+pub const SYS_flistxattr: ::c_long = 13;
+pub const SYS_removexattr: ::c_long = 14;
+pub const SYS_lremovexattr: ::c_long = 15;
+pub const SYS_fremovexattr: ::c_long = 16;
+pub const SYS_getcwd: ::c_long = 17;
+pub const SYS_lookup_dcookie: ::c_long = 18;
+pub const SYS_eventfd2: ::c_long = 19;
+pub const SYS_epoll_create1: ::c_long = 20;
+pub const SYS_epoll_ctl: ::c_long = 21;
+pub const SYS_epoll_pwait: ::c_long = 22;
+pub const SYS_dup: ::c_long = 23;
+pub const SYS_dup3: ::c_long = 24;
+pub const SYS_inotify_init1: ::c_long = 26;
+pub const SYS_inotify_add_watch: ::c_long = 27;
+pub const SYS_inotify_rm_watch: ::c_long = 28;
+pub const SYS_ioctl: ::c_long = 29;
+pub const SYS_ioprio_set: ::c_long = 30;
+pub const SYS_ioprio_get: ::c_long = 31;
+pub const SYS_flock: ::c_long = 32;
+pub const SYS_mknodat: ::c_long = 33;
+pub const SYS_mkdirat: ::c_long = 34;
+pub const SYS_unlinkat: ::c_long = 35;
+pub const SYS_symlinkat: ::c_long = 36;
+pub const SYS_linkat: ::c_long = 37;
+pub const SYS_renameat: ::c_long = 38;
+pub const SYS_umount2: ::c_long = 39;
+pub const SYS_mount: ::c_long = 40;
+pub const SYS_pivot_root: ::c_long = 41;
+pub const SYS_nfsservctl: ::c_long = 42;
+pub const SYS_fallocate: ::c_long = 47;
+pub const SYS_faccessat: ::c_long = 48;
+pub const SYS_chdir: ::c_long = 49;
+pub const SYS_fchdir: ::c_long = 50;
+pub const SYS_chroot: ::c_long = 51;
+pub const SYS_fchmod: ::c_long = 52;
+pub const SYS_fchmodat: ::c_long = 53;
+pub const SYS_fchownat: ::c_long = 54;
+pub const SYS_fchown: ::c_long = 55;
+pub const SYS_openat: ::c_long = 56;
+pub const SYS_close: ::c_long = 57;
+pub const SYS_vhangup: ::c_long = 58;
+pub const SYS_pipe2: ::c_long = 59;
+pub const SYS_quotactl: ::c_long = 60;
+pub const SYS_getdents64: ::c_long = 61;
+pub const SYS_read: ::c_long = 63;
+pub const SYS_write: ::c_long = 64;
+pub const SYS_readv: ::c_long = 65;
+pub const SYS_writev: ::c_long = 66;
+pub const SYS_pread64: ::c_long = 67;
+pub const SYS_pwrite64: ::c_long = 68;
+pub const SYS_preadv: ::c_long = 69;
+pub const SYS_pwritev: ::c_long = 70;
+pub const SYS_pselect6: ::c_long = 72;
+pub const SYS_ppoll: ::c_long = 73;
+pub const SYS_signalfd4: ::c_long = 74;
+pub const SYS_vmsplice: ::c_long = 75;
+pub const SYS_splice: ::c_long = 76;
+pub const SYS_tee: ::c_long = 77;
+pub const SYS_readlinkat: ::c_long = 78;
+pub const SYS_sync: ::c_long = 81;
+pub const SYS_fsync: ::c_long = 82;
+pub const SYS_fdatasync: ::c_long = 83;
+pub const SYS_sync_file_range: ::c_long = 84;
+pub const SYS_timerfd_create: ::c_long = 85;
+pub const SYS_timerfd_settime: ::c_long = 86;
+pub const SYS_timerfd_gettime: ::c_long = 87;
+pub const SYS_utimensat: ::c_long = 88;
+pub const SYS_acct: ::c_long = 89;
+pub const SYS_capget: ::c_long = 90;
+pub const SYS_capset: ::c_long = 91;
+pub const SYS_personality: ::c_long = 92;
+pub const SYS_exit: ::c_long = 93;
+pub const SYS_exit_group: ::c_long = 94;
+pub const SYS_waitid: ::c_long = 95;
+pub const SYS_set_tid_address: ::c_long = 96;
+pub const SYS_unshare: ::c_long = 97;
+pub const SYS_futex: ::c_long = 98;
+pub const SYS_set_robust_list: ::c_long = 99;
+pub const SYS_get_robust_list: ::c_long = 100;
+pub const SYS_nanosleep: ::c_long = 101;
+pub const SYS_getitimer: ::c_long = 102;
+pub const SYS_setitimer: ::c_long = 103;
+pub const SYS_kexec_load: ::c_long = 104;
+pub const SYS_init_module: ::c_long = 105;
+pub const SYS_delete_module: ::c_long = 106;
+pub const SYS_timer_create: ::c_long = 107;
+pub const SYS_timer_gettime: ::c_long = 108;
+pub const SYS_timer_getoverrun: ::c_long = 109;
+pub const SYS_timer_settime: ::c_long = 110;
+pub const SYS_timer_delete: ::c_long = 111;
+pub const SYS_clock_settime: ::c_long = 112;
+pub const SYS_clock_gettime: ::c_long = 113;
+pub const SYS_clock_getres: ::c_long = 114;
+pub const SYS_clock_nanosleep: ::c_long = 115;
+pub const SYS_syslog: ::c_long = 116;
+pub const SYS_ptrace: ::c_long = 117;
+pub const SYS_sched_setparam: ::c_long = 118;
+pub const SYS_sched_setscheduler: ::c_long = 119;
+pub const SYS_sched_getscheduler: ::c_long = 120;
+pub const SYS_sched_getparam: ::c_long = 121;
+pub const SYS_sched_setaffinity: ::c_long = 122;
+pub const SYS_sched_getaffinity: ::c_long = 123;
+pub const SYS_sched_yield: ::c_long = 124;
+pub const SYS_sched_get_priority_max: ::c_long = 125;
+pub const SYS_sched_get_priority_min: ::c_long = 126;
+pub const SYS_sched_rr_get_interval: ::c_long = 127;
+pub const SYS_restart_syscall: ::c_long = 128;
+pub const SYS_kill: ::c_long = 129;
+pub const SYS_tkill: ::c_long = 130;
+pub const SYS_tgkill: ::c_long = 131;
+pub const SYS_sigaltstack: ::c_long = 132;
+pub const SYS_rt_sigsuspend: ::c_long = 133;
+pub const SYS_rt_sigaction: ::c_long = 134;
+pub const SYS_rt_sigprocmask: ::c_long = 135;
+pub const SYS_rt_sigpending: ::c_long = 136;
+pub const SYS_rt_sigtimedwait: ::c_long = 137;
+pub const SYS_rt_sigqueueinfo: ::c_long = 138;
+pub const SYS_rt_sigreturn: ::c_long = 139;
+pub const SYS_setpriority: ::c_long = 140;
+pub const SYS_getpriority: ::c_long = 141;
+pub const SYS_reboot: ::c_long = 142;
+pub const SYS_setregid: ::c_long = 143;
+pub const SYS_setgid: ::c_long = 144;
+pub const SYS_setreuid: ::c_long = 145;
+pub const SYS_setuid: ::c_long = 146;
+pub const SYS_setresuid: ::c_long = 147;
+pub const SYS_getresuid: ::c_long = 148;
+pub const SYS_setresgid: ::c_long = 149;
+pub const SYS_getresgid: ::c_long = 150;
+pub const SYS_setfsuid: ::c_long = 151;
+pub const SYS_setfsgid: ::c_long = 152;
+pub const SYS_times: ::c_long = 153;
+pub const SYS_setpgid: ::c_long = 154;
+pub const SYS_getpgid: ::c_long = 155;
+pub const SYS_getsid: ::c_long = 156;
+pub const SYS_setsid: ::c_long = 157;
+pub const SYS_getgroups: ::c_long = 158;
+pub const SYS_setgroups: ::c_long = 159;
+pub const SYS_uname: ::c_long = 160;
+pub const SYS_sethostname: ::c_long = 161;
+pub const SYS_setdomainname: ::c_long = 162;
+pub const SYS_getrlimit: ::c_long = 163;
+pub const SYS_setrlimit: ::c_long = 164;
+pub const SYS_getrusage: ::c_long = 165;
+pub const SYS_umask: ::c_long = 166;
+pub const SYS_prctl: ::c_long = 167;
+pub const SYS_getcpu: ::c_long = 168;
+pub const SYS_gettimeofday: ::c_long = 169;
+pub const SYS_settimeofday: ::c_long = 170;
+pub const SYS_adjtimex: ::c_long = 171;
+pub const SYS_getpid: ::c_long = 172;
+pub const SYS_getppid: ::c_long = 173;
+pub const SYS_getuid: ::c_long = 174;
+pub const SYS_geteuid: ::c_long = 175;
+pub const SYS_getgid: ::c_long = 176;
+pub const SYS_getegid: ::c_long = 177;
+pub const SYS_gettid: ::c_long = 178;
+pub const SYS_sysinfo: ::c_long = 179;
+pub const SYS_mq_open: ::c_long = 180;
+pub const SYS_mq_unlink: ::c_long = 181;
+pub const SYS_mq_timedsend: ::c_long = 182;
+pub const SYS_mq_timedreceive: ::c_long = 183;
+pub const SYS_mq_notify: ::c_long = 184;
+pub const SYS_mq_getsetattr: ::c_long = 185;
+pub const SYS_msgget: ::c_long = 186;
+pub const SYS_msgctl: ::c_long = 187;
+pub const SYS_msgrcv: ::c_long = 188;
+pub const SYS_msgsnd: ::c_long = 189;
+pub const SYS_semget: ::c_long = 190;
+pub const SYS_semctl: ::c_long = 191;
+pub const SYS_semtimedop: ::c_long = 192;
+pub const SYS_semop: ::c_long = 193;
+pub const SYS_shmget: ::c_long = 194;
+pub const SYS_shmctl: ::c_long = 195;
+pub const SYS_shmat: ::c_long = 196;
+pub const SYS_shmdt: ::c_long = 197;
+pub const SYS_socket: ::c_long = 198;
+pub const SYS_socketpair: ::c_long = 199;
+pub const SYS_bind: ::c_long = 200;
+pub const SYS_listen: ::c_long = 201;
+pub const SYS_accept: ::c_long = 202;
+pub const SYS_connect: ::c_long = 203;
+pub const SYS_getsockname: ::c_long = 204;
+pub const SYS_getpeername: ::c_long = 205;
+pub const SYS_sendto: ::c_long = 206;
+pub const SYS_recvfrom: ::c_long = 207;
+pub const SYS_setsockopt: ::c_long = 208;
+pub const SYS_getsockopt: ::c_long = 209;
+pub const SYS_shutdown: ::c_long = 210;
+pub const SYS_sendmsg: ::c_long = 211;
+pub const SYS_recvmsg: ::c_long = 212;
+pub const SYS_readahead: ::c_long = 213;
+pub const SYS_brk: ::c_long = 214;
+pub const SYS_munmap: ::c_long = 215;
+pub const SYS_mremap: ::c_long = 216;
+pub const SYS_add_key: ::c_long = 217;
+pub const SYS_request_key: ::c_long = 218;
+pub const SYS_keyctl: ::c_long = 219;
+pub const SYS_clone: ::c_long = 220;
+pub const SYS_execve: ::c_long = 221;
+pub const SYS_swapon: ::c_long = 224;
+pub const SYS_swapoff: ::c_long = 225;
+pub const SYS_mprotect: ::c_long = 226;
+pub const SYS_msync: ::c_long = 227;
+pub const SYS_mlock: ::c_long = 228;
+pub const SYS_munlock: ::c_long = 229;
+pub const SYS_mlockall: ::c_long = 230;
+pub const SYS_munlockall: ::c_long = 231;
+pub const SYS_mincore: ::c_long = 232;
+pub const SYS_madvise: ::c_long = 233;
+pub const SYS_remap_file_pages: ::c_long = 234;
+pub const SYS_mbind: ::c_long = 235;
+pub const SYS_get_mempolicy: ::c_long = 236;
+pub const SYS_set_mempolicy: ::c_long = 237;
+pub const SYS_migrate_pages: ::c_long = 238;
+pub const SYS_move_pages: ::c_long = 239;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 240;
+pub const SYS_perf_event_open: ::c_long = 241;
+pub const SYS_accept4: ::c_long = 242;
+pub const SYS_recvmmsg: ::c_long = 243;
+pub const SYS_wait4: ::c_long = 260;
+pub const SYS_prlimit64: ::c_long = 261;
+pub const SYS_fanotify_init: ::c_long = 262;
+pub const SYS_fanotify_mark: ::c_long = 263;
+pub const SYS_name_to_handle_at: ::c_long = 264;
+pub const SYS_open_by_handle_at: ::c_long = 265;
+pub const SYS_clock_adjtime: ::c_long = 266;
+pub const SYS_syncfs: ::c_long = 267;
+pub const SYS_setns: ::c_long = 268;
+pub const SYS_sendmmsg: ::c_long = 269;
+pub const SYS_process_vm_readv: ::c_long = 270;
+pub const SYS_process_vm_writev: ::c_long = 271;
+pub const SYS_kcmp: ::c_long = 272;
+pub const SYS_finit_module: ::c_long = 273;
+pub const SYS_sched_setattr: ::c_long = 274;
+pub const SYS_sched_getattr: ::c_long = 275;
+pub const SYS_renameat2: ::c_long = 276;
+pub const SYS_seccomp: ::c_long = 277;
+pub const SYS_getrandom: ::c_long = 278;
+pub const SYS_memfd_create: ::c_long = 279;
+pub const SYS_bpf: ::c_long = 280;
+pub const SYS_execveat: ::c_long = 281;
+pub const SYS_userfaultfd: ::c_long = 282;
+pub const SYS_membarrier: ::c_long = 283;
+pub const SYS_mlock2: ::c_long = 284;
+pub const SYS_copy_file_range: ::c_long = 285;
+pub const SYS_preadv2: ::c_long = 286;
+pub const SYS_pwritev2: ::c_long = 287;
+pub const SYS_pkey_mprotect: ::c_long = 288;
+pub const SYS_pkey_alloc: ::c_long = 289;
+pub const SYS_pkey_free: ::c_long = 290;
diff --git a/third_party/rust/libc/src/fuchsia/mod.rs b/third_party/rust/libc/src/fuchsia/mod.rs
new file mode 100644
index 000000000000..e103292979c3
--- /dev/null
+++ b/third_party/rust/libc/src/fuchsia/mod.rs
@@ -0,0 +1,3999 @@
+//! Definitions found commonly among almost all Unix derivatives
+//!
+//! More functions and definitions can be found in the more specific modules
+//! according to the platform in question.
+
+use dox::{mem, Option};
+
+// PUB_TYPE
+
+pub type pid_t = i32;
+pub type uid_t = u32;
+pub type gid_t = u32;
+pub type in_addr_t = u32;
+pub type in_port_t = u16;
+pub type sighandler_t = ::size_t;
+pub type cc_t = ::c_uchar;
+pub type sa_family_t = u16;
+pub type pthread_key_t = ::c_uint;
+pub type speed_t = ::c_uint;
+pub type tcflag_t = ::c_uint;
+pub type clockid_t = ::c_int;
+pub type key_t = ::c_int;
+pub type id_t = ::c_uint;
+pub type useconds_t = u32;
+pub type dev_t = u64;
+pub type socklen_t = u32;
+pub type pthread_t = c_ulong;
+pub type mode_t = u32;
+pub type ino64_t = u64;
+pub type off64_t = i64;
+pub type blkcnt64_t = i64;
+pub type rlim64_t = u64;
+pub type mqd_t = ::c_int;
+pub type nfds_t = ::c_ulong;
+pub type nl_item = ::c_int;
+pub type idtype_t = ::c_uint;
+pub type loff_t = ::c_longlong;
+
+pub type __u8 = ::c_uchar;
+pub type __u16 = ::c_ushort;
+pub type __s16 = ::c_short;
+pub type __u32 = ::c_uint;
+pub type __s32 = ::c_int;
+
+pub type Elf32_Half = u16;
+pub type Elf32_Word = u32;
+pub type Elf32_Off = u32;
+pub type Elf32_Addr = u32;
+
+pub type Elf64_Half = u16;
+pub type Elf64_Word = u32;
+pub type Elf64_Off = u64;
+pub type Elf64_Addr = u64;
+pub type Elf64_Xword = u64;
+
+pub type clock_t = c_long;
+pub type time_t = c_long;
+pub type suseconds_t = c_long;
+pub type ino_t = u64;
+pub type off_t = i64;
+pub type blkcnt_t = i64;
+
+pub type shmatt_t = ::c_ulong;
+pub type msgqnum_t = ::c_ulong;
+pub type msglen_t = ::c_ulong;
+pub type fsblkcnt_t = ::c_ulonglong;
+pub type fsfilcnt_t = ::c_ulonglong;
+pub type rlim_t = ::c_ulonglong;
+
+pub type c_long = i64;
+pub type c_ulong = u64;
+
+// FIXME: why are these uninhabited types? that seems... wrong?
+// Presumably these should be `()` or an `extern type` (when that stabilizes).
+pub enum timezone {}
+pub enum DIR {}
+pub enum locale_t {}
+pub enum fpos64_t {} // TODO: fill this out with a struct
+
+// PUB_STRUCT
+
+s! {
+    pub struct group {
+        pub gr_name: *mut ::c_char,
+        pub gr_passwd: *mut ::c_char,
+        pub gr_gid: ::gid_t,
+        pub gr_mem: *mut *mut ::c_char,
+    }
+
+    pub struct utimbuf {
+        pub actime: time_t,
+        pub modtime: time_t,
+    }
+
+    pub struct timeval {
+        pub tv_sec: time_t,
+        pub tv_usec: suseconds_t,
+    }
+
+    // linux x32 compatibility
+    // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
+    pub struct timespec {
+        pub tv_sec: time_t,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pub tv_nsec: i64,
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pub tv_nsec: ::c_long,
+    }
+
+    pub struct rlimit {
+        pub rlim_cur: rlim_t,
+        pub rlim_max: rlim_t,
+    }
+
+    pub struct rusage {
+        pub ru_utime: timeval,
+        pub ru_stime: timeval,
+        pub ru_maxrss: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad1: u32,
+        pub ru_ixrss: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad2: u32,
+        pub ru_idrss: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad3: u32,
+        pub ru_isrss: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad4: u32,
+        pub ru_minflt: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad5: u32,
+        pub ru_majflt: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad6: u32,
+        pub ru_nswap: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad7: u32,
+        pub ru_inblock: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad8: u32,
+        pub ru_oublock: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad9: u32,
+        pub ru_msgsnd: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad10: u32,
+        pub ru_msgrcv: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad11: u32,
+        pub ru_nsignals: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad12: u32,
+        pub ru_nvcsw: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad13: u32,
+        pub ru_nivcsw: c_long,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        __pad14: u32,
+
+        #[cfg(any(target_env = "musl", target_os = "emscripten"))]
+        __reserved: [c_long; 16],
+    }
+
+    pub struct in_addr {
+        pub s_addr: in_addr_t,
+    }
+
+    #[cfg_attr(feature = "align", repr(align(4)))]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+        #[cfg(not(feature = "align"))]
+        __align: [u32; 0],
+    }
+
+    pub struct ip_mreq {
+        pub imr_multiaddr: in_addr,
+        pub imr_interface: in_addr,
+    }
+
+    pub struct ipv6_mreq {
+        pub ipv6mr_multiaddr: in6_addr,
+        #[cfg(target_os = "android")]
+        pub ipv6mr_interface: ::c_int,
+        #[cfg(not(target_os = "android"))]
+        pub ipv6mr_interface: ::c_uint,
+    }
+
+    pub struct hostent {
+        pub h_name: *mut ::c_char,
+        pub h_aliases: *mut *mut ::c_char,
+        pub h_addrtype: ::c_int,
+        pub h_length: ::c_int,
+        pub h_addr_list: *mut *mut ::c_char,
+    }
+
+    pub struct iovec {
+        pub iov_base: *mut ::c_void,
+        pub iov_len: ::size_t,
+    }
+
+    pub struct pollfd {
+        pub fd: ::c_int,
+        pub events: ::c_short,
+        pub revents: ::c_short,
+    }
+
+    pub struct winsize {
+        pub ws_row: ::c_ushort,
+        pub ws_col: ::c_ushort,
+        pub ws_xpixel: ::c_ushort,
+        pub ws_ypixel: ::c_ushort,
+    }
+
+    pub struct linger {
+        pub l_onoff: ::c_int,
+        pub l_linger: ::c_int,
+    }
+
+    pub struct sigval {
+        // Actually a union of an int and a void*
+        pub sival_ptr: *mut ::c_void
+    }
+
+    // <sys/time.h>
+    pub struct itimerval {
+        pub it_interval: ::timeval,
+        pub it_value: ::timeval,
+    }
+
+    // <sys/times.h>
+    pub struct tms {
+        pub tms_utime: ::clock_t,
+        pub tms_stime: ::clock_t,
+        pub tms_cutime: ::clock_t,
+        pub tms_cstime: ::clock_t,
+    }
+
+    pub struct servent {
+        pub s_name: *mut ::c_char,
+        pub s_aliases: *mut *mut ::c_char,
+        pub s_port: ::c_int,
+        pub s_proto: *mut ::c_char,
+    }
+
+    pub struct protoent {
+        pub p_name: *mut ::c_char,
+        pub p_aliases: *mut *mut ::c_char,
+        pub p_proto: ::c_int,
+    }
+
+    pub struct aiocb {
+        pub aio_fildes: ::c_int,
+        pub aio_lio_opcode: ::c_int,
+        pub aio_reqprio: ::c_int,
+        pub aio_buf: *mut ::c_void,
+        pub aio_nbytes: ::size_t,
+        pub aio_sigevent: ::sigevent,
+        __td: *mut ::c_void,
+        __lock: [::c_int; 2],
+        __err: ::c_int,
+        __ret: ::ssize_t,
+        pub aio_offset: off_t,
+        __next: *mut ::c_void,
+        __prev: *mut ::c_void,
+        #[cfg(target_pointer_width = "32")]
+        __dummy4: [::c_char; 24],
+        #[cfg(target_pointer_width = "64")]
+        __dummy4: [::c_char; 16],
+    }
+
+    pub struct sigaction {
+        pub sa_sigaction: ::sighandler_t,
+        pub sa_mask: ::sigset_t,
+        pub sa_flags: ::c_int,
+        pub sa_restorer: ::dox::Option<extern fn()>,
+    }
+
+    pub struct termios {
+        pub c_iflag: ::tcflag_t,
+        pub c_oflag: ::tcflag_t,
+        pub c_cflag: ::tcflag_t,
+        pub c_lflag: ::tcflag_t,
+        pub c_line: ::cc_t,
+        pub c_cc: [::cc_t; ::NCCS],
+        pub __c_ispeed: ::speed_t,
+        pub __c_ospeed: ::speed_t,
+    }
+
+    pub struct flock {
+        pub l_type: ::c_short,
+        pub l_whence: ::c_short,
+        pub l_start: ::off_t,
+        pub l_len: ::off_t,
+        pub l_pid: ::pid_t,
+    }
+
+    pub struct sysinfo {
+        pub uptime: ::c_ulong,
+        pub loads: [::c_ulong; 3],
+        pub totalram: ::c_ulong,
+        pub freeram: ::c_ulong,
+        pub sharedram: ::c_ulong,
+        pub bufferram: ::c_ulong,
+        pub totalswap: ::c_ulong,
+        pub freeswap: ::c_ulong,
+        pub procs: ::c_ushort,
+        pub pad: ::c_ushort,
+        pub totalhigh: ::c_ulong,
+        pub freehigh: ::c_ulong,
+        pub mem_unit: ::c_uint,
+        pub __reserved: [::c_char; 256],
+    }
+
+    pub struct ucred {
+        pub pid: ::pid_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+    }
+
+    pub struct sockaddr {
+        pub sa_family: sa_family_t,
+        pub sa_data: [::c_char; 14],
+    }
+
+    pub struct sockaddr_in {
+        pub sin_family: sa_family_t,
+        pub sin_port: ::in_port_t,
+        pub sin_addr: ::in_addr,
+        pub sin_zero: [u8; 8],
+    }
+
+    pub struct sockaddr_in6 {
+        pub sin6_family: sa_family_t,
+        pub sin6_port: ::in_port_t,
+        pub sin6_flowinfo: u32,
+        pub sin6_addr: ::in6_addr,
+        pub sin6_scope_id: u32,
+    }
+
+    pub struct sockaddr_un {
+        pub sun_family: sa_family_t,
+        pub sun_path: [::c_char; 108]
+    }
+
+    pub struct sockaddr_storage {
+        pub ss_family: sa_family_t,
+        __ss_align: ::size_t,
+        __ss_pad2: [u8; 128 - 2 * 8],
+    }
+
+    pub struct addrinfo {
+        pub ai_flags: ::c_int,
+        pub ai_family: ::c_int,
+        pub ai_socktype: ::c_int,
+        pub ai_protocol: ::c_int,
+        pub ai_addrlen: socklen_t,
+
+        pub ai_addr: *mut ::sockaddr,
+
+        pub ai_canonname: *mut c_char,
+
+        pub ai_next: *mut addrinfo,
+    }
+
+    pub struct sockaddr_nl {
+        pub nl_family: ::sa_family_t,
+        nl_pad: ::c_ushort,
+        pub nl_pid: u32,
+        pub nl_groups: u32
+    }
+
+    pub struct sockaddr_ll {
+        pub sll_family: ::c_ushort,
+        pub sll_protocol: ::c_ushort,
+        pub sll_ifindex: ::c_int,
+        pub sll_hatype: ::c_ushort,
+        pub sll_pkttype: ::c_uchar,
+        pub sll_halen: ::c_uchar,
+        pub sll_addr: [::c_uchar; 8]
+    }
+
+    pub struct fd_set {
+        fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE],
+    }
+
+    pub struct tm {
+        pub tm_sec: ::c_int,
+        pub tm_min: ::c_int,
+        pub tm_hour: ::c_int,
+        pub tm_mday: ::c_int,
+        pub tm_mon: ::c_int,
+        pub tm_year: ::c_int,
+        pub tm_wday: ::c_int,
+        pub tm_yday: ::c_int,
+        pub tm_isdst: ::c_int,
+        pub tm_gmtoff: ::c_long,
+        pub tm_zone: *const ::c_char,
+    }
+
+    pub struct sched_param {
+        pub sched_priority: ::c_int,
+        #[cfg(target_env = "musl")]
+        pub sched_ss_low_priority: ::c_int,
+        #[cfg(target_env = "musl")]
+        pub sched_ss_repl_period: ::timespec,
+        #[cfg(target_env = "musl")]
+        pub sched_ss_init_budget: ::timespec,
+        #[cfg(target_env = "musl")]
+        pub sched_ss_max_repl: ::c_int,
+    }
+
+    pub struct Dl_info {
+        pub dli_fname: *const ::c_char,
+        pub dli_fbase: *mut ::c_void,
+        pub dli_sname: *const ::c_char,
+        pub dli_saddr: *mut ::c_void,
+    }
+
+    #[cfg_attr(any(all(target_arch = "x86",
+                       not(target_env = "musl"),
+                       not(target_os = "android")),
+                   target_arch = "x86_64"),
+               repr(packed))]
+    pub struct epoll_event {
+        pub events: ::uint32_t,
+        pub u64: ::uint64_t,
+    }
+
+    pub struct utsname {
+        pub sysname: [::c_char; 65],
+        pub nodename: [::c_char; 65],
+        pub release: [::c_char; 65],
+        pub version: [::c_char; 65],
+        pub machine: [::c_char; 65],
+        pub domainname: [::c_char; 65]
+    }
+
+    pub struct lconv {
+        pub decimal_point: *mut ::c_char,
+        pub thousands_sep: *mut ::c_char,
+        pub grouping: *mut ::c_char,
+        pub int_curr_symbol: *mut ::c_char,
+        pub currency_symbol: *mut ::c_char,
+        pub mon_decimal_point: *mut ::c_char,
+        pub mon_thousands_sep: *mut ::c_char,
+        pub mon_grouping: *mut ::c_char,
+        pub positive_sign: *mut ::c_char,
+        pub negative_sign: *mut ::c_char,
+        pub int_frac_digits: ::c_char,
+        pub frac_digits: ::c_char,
+        pub p_cs_precedes: ::c_char,
+        pub p_sep_by_space: ::c_char,
+        pub n_cs_precedes: ::c_char,
+        pub n_sep_by_space: ::c_char,
+        pub p_sign_posn: ::c_char,
+        pub n_sign_posn: ::c_char,
+        pub int_p_cs_precedes: ::c_char,
+        pub int_p_sep_by_space: ::c_char,
+        pub int_n_cs_precedes: ::c_char,
+        pub int_n_sep_by_space: ::c_char,
+        pub int_p_sign_posn: ::c_char,
+        pub int_n_sign_posn: ::c_char,
+    }
+
+    pub struct sigevent {
+        pub sigev_value: ::sigval,
+        pub sigev_signo: ::c_int,
+        pub sigev_notify: ::c_int,
+        // Actually a union.  We only expose sigev_notify_thread_id because it's
+        // the most useful member
+        pub sigev_notify_thread_id: ::c_int,
+        #[cfg(target_pointer_width = "64")]
+        __unused1: [::c_int; 11],
+        #[cfg(target_pointer_width = "32")]
+        __unused1: [::c_int; 12]
+    }
+
+    pub struct dirent {
+        pub d_ino: ::ino_t,
+        pub d_off: ::off_t,
+        pub d_reclen: ::c_ushort,
+        pub d_type: ::c_uchar,
+        pub d_name: [::c_char; 256],
+    }
+
+    pub struct dirent64 {
+        pub d_ino: ::ino64_t,
+        pub d_off: ::off64_t,
+        pub d_reclen: ::c_ushort,
+        pub d_type: ::c_uchar,
+        pub d_name: [::c_char; 256],
+    }
+
+    pub struct rlimit64 {
+        pub rlim_cur: rlim64_t,
+        pub rlim_max: rlim64_t,
+    }
+
+    pub struct glob_t {
+        pub gl_pathc: ::size_t,
+        pub gl_pathv: *mut *mut c_char,
+        pub gl_offs: ::size_t,
+        pub gl_flags: ::c_int,
+
+        __unused1: *mut ::c_void,
+        __unused2: *mut ::c_void,
+        __unused3: *mut ::c_void,
+        __unused4: *mut ::c_void,
+        __unused5: *mut ::c_void,
+    }
+
+    pub struct ifaddrs {
+        pub ifa_next: *mut ifaddrs,
+        pub ifa_name: *mut c_char,
+        pub ifa_flags: ::c_uint,
+        pub ifa_addr: *mut ::sockaddr,
+        pub ifa_netmask: *mut ::sockaddr,
+        pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union
+        pub ifa_data: *mut ::c_void
+    }
+
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc",
+                       target_arch = "x86_64")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc",
+                               target_arch = "x86_64")))),
+               repr(align(8)))]
+    pub struct pthread_mutex_t {
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
+        __align: [::c_long; 0],
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
+        __align: [::c_longlong; 0],
+        size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
+    }
+
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc",
+                       target_arch = "x86_64")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc",
+                               target_arch = "x86_64")))),
+               repr(align(8)))]
+    pub struct pthread_rwlock_t {
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
+        __align: [::c_long; 0],
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
+        __align: [::c_longlong; 0],
+        size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
+    }
+
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "32",
+                       target_arch = "x86_64", target_arch = "powerpc64",
+                       target_arch = "mips64", target_arch = "s390x",
+                       target_arch = "sparc64",
+                       all(target_arch = "aarch64", target_env = "musl"))),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(any(target_pointer_width = "32",
+                           target_arch = "x86_64", target_arch = "powerpc64",
+                           target_arch = "mips64", target_arch = "s390x",
+                           target_arch = "sparc64",
+                           all(target_arch = "aarch64", target_env = "musl")))),
+               repr(align(8)))]
+    pub struct pthread_mutexattr_t {
+        #[cfg(all(not(features = "align"),
+                  any(target_arch = "x86_64", target_arch = "powerpc64",
+                      target_arch = "mips64", target_arch = "s390x",
+                      target_arch = "sparc64",
+                      all(target_arch = "aarch64", target_env = "musl"))))]
+        __align: [::c_int; 0],
+        #[cfg(all(not(features = "align"),
+                  not(any(target_arch = "x86_64", target_arch = "powerpc64",
+                          target_arch = "mips64", target_arch = "s390x",
+                          target_arch = "sparc64",
+                          all(target_arch = "aarch64", target_env = "musl")))))]
+        __align: [::c_long; 0],
+        size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
+    }
+
+    #[cfg_attr(all(feature = "align",
+                   any(target_env = "musl", target_pointer_width = "32")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   target_pointer_width = "64"),
+               repr(align(8)))]
+    pub struct pthread_rwlockattr_t {
+        #[cfg(all(not(feature = "align"), target_env = "musl"))]
+        __align: [::c_int; 0],
+        #[cfg(all(not(feature = "align"), not(target_env = "musl")))]
+        __align: [::c_long; 0],
+        size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T],
+    }
+
+    #[cfg_attr(all(feature = "align",
+                   target_env = "musl",
+                   target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   target_env = "musl",
+                   target_pointer_width = "64"),
+               repr(align(8)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   target_arch = "x86"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   not(target_arch = "x86")),
+               repr(align(8)))]
+    pub struct pthread_cond_t {
+        #[cfg(all(not(feature = "align"), target_env = "musl"))]
+        __align: [*const ::c_void; 0],
+        #[cfg(not(any(feature = "align", target_env = "musl")))]
+        __align: [::c_longlong; 0],
+        size: [u8; __SIZEOF_PTHREAD_COND_T],
+    }
+
+    #[cfg_attr(feature = "align", repr(align(4)))]
+    pub struct pthread_condattr_t {
+        #[cfg(not(feature = "align"))]
+        __align: [::c_int; 0],
+        size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
+    }
+
+    pub struct passwd {
+        pub pw_name: *mut ::c_char,
+        pub pw_passwd: *mut ::c_char,
+        pub pw_uid: ::uid_t,
+        pub pw_gid: ::gid_t,
+        pub pw_gecos: *mut ::c_char,
+        pub pw_dir: *mut ::c_char,
+        pub pw_shell: *mut ::c_char,
+    }
+
+    pub struct spwd {
+        pub sp_namp: *mut ::c_char,
+        pub sp_pwdp: *mut ::c_char,
+        pub sp_lstchg: ::c_long,
+        pub sp_min: ::c_long,
+        pub sp_max: ::c_long,
+        pub sp_warn: ::c_long,
+        pub sp_inact: ::c_long,
+        pub sp_expire: ::c_long,
+        pub sp_flag: ::c_ulong,
+    }
+
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        #[cfg(target_endian = "little")]
+        pub f_fsid: ::c_ulong,
+        #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))]
+        __f_unused: ::c_int,
+        #[cfg(target_endian = "big")]
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
+    pub struct dqblk {
+        pub dqb_bhardlimit: ::uint64_t,
+        pub dqb_bsoftlimit: ::uint64_t,
+        pub dqb_curspace: ::uint64_t,
+        pub dqb_ihardlimit: ::uint64_t,
+        pub dqb_isoftlimit: ::uint64_t,
+        pub dqb_curinodes: ::uint64_t,
+        pub dqb_btime: ::uint64_t,
+        pub dqb_itime: ::uint64_t,
+        pub dqb_valid: ::uint32_t,
+    }
+
+    pub struct signalfd_siginfo {
+        pub ssi_signo: ::uint32_t,
+        pub ssi_errno: ::int32_t,
+        pub ssi_code: ::int32_t,
+        pub ssi_pid: ::uint32_t,
+        pub ssi_uid: ::uint32_t,
+        pub ssi_fd: ::int32_t,
+        pub ssi_tid: ::uint32_t,
+        pub ssi_band: ::uint32_t,
+        pub ssi_overrun: ::uint32_t,
+        pub ssi_trapno: ::uint32_t,
+        pub ssi_status: ::int32_t,
+        pub ssi_int: ::int32_t,
+        pub ssi_ptr: ::uint64_t,
+        pub ssi_utime: ::uint64_t,
+        pub ssi_stime: ::uint64_t,
+        pub ssi_addr: ::uint64_t,
+        _pad: [::uint8_t; 48],
+    }
+
+    pub struct itimerspec {
+        pub it_interval: ::timespec,
+        pub it_value: ::timespec,
+    }
+
+    pub struct fsid_t {
+        __val: [::c_int; 2],
+    }
+
+    // x32 compatibility
+    // See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
+    pub struct mq_attr {
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pub mq_flags: i64,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pub mq_maxmsg: i64,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pub mq_msgsize: i64,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pub mq_curmsgs: i64,
+        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
+        pad: [i64; 4],
+
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pub mq_flags: ::c_long,
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pub mq_maxmsg: ::c_long,
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pub mq_msgsize: ::c_long,
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pub mq_curmsgs: ::c_long,
+        #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
+        pad: [::c_long; 4],
+    }
+
+    pub struct cpu_set_t {
+        #[cfg(all(target_pointer_width = "32",
+                  not(target_arch = "x86_64")))]
+        bits: [u32; 32],
+        #[cfg(not(all(target_pointer_width = "32",
+                      not(target_arch = "x86_64"))))]
+        bits: [u64; 16],
+    }
+
+    pub struct if_nameindex {
+        pub if_index: ::c_uint,
+        pub if_name: *mut ::c_char,
+    }
+
+    // System V IPC
+    pub struct msginfo {
+        pub msgpool: ::c_int,
+        pub msgmap: ::c_int,
+        pub msgmax: ::c_int,
+        pub msgmnb: ::c_int,
+        pub msgmni: ::c_int,
+        pub msgssz: ::c_int,
+        pub msgtql: ::c_int,
+        pub msgseg: ::c_ushort,
+    }
+
+    pub struct mmsghdr {
+        pub msg_hdr: ::msghdr,
+        pub msg_len: ::c_uint,
+    }
+
+    pub struct sembuf {
+        pub sem_num: ::c_ushort,
+        pub sem_op: ::c_short,
+        pub sem_flg: ::c_short,
+    }
+
+    pub struct input_event {
+        pub time: ::timeval,
+        pub type_: ::__u16,
+        pub code: ::__u16,
+        pub value: ::__s32,
+    }
+
+    pub struct input_id {
+        pub bustype: ::__u16,
+        pub vendor: ::__u16,
+        pub product: ::__u16,
+        pub version: ::__u16,
+    }
+
+    pub struct input_absinfo {
+        pub value: ::__s32,
+        pub minimum: ::__s32,
+        pub maximum: ::__s32,
+        pub fuzz: ::__s32,
+        pub flat: ::__s32,
+        pub resolution: ::__s32,
+    }
+
+    pub struct input_keymap_entry {
+        pub flags: ::__u8,
+        pub len: ::__u8,
+        pub index: ::__u16,
+        pub keycode: ::__u32,
+        pub scancode: [::__u8; 32],
+    }
+
+    pub struct input_mask {
+        pub type_: ::__u32,
+        pub codes_size: ::__u32,
+        pub codes_ptr: ::__u64,
+    }
+
+    pub struct ff_replay {
+        pub length: ::__u16,
+        pub delay: ::__u16,
+    }
+
+    pub struct ff_trigger {
+        pub button: ::__u16,
+        pub interval: ::__u16,
+    }
+
+    pub struct ff_envelope {
+        pub attack_length: ::__u16,
+        pub attack_level: ::__u16,
+        pub fade_length: ::__u16,
+        pub fade_level: ::__u16,
+    }
+
+    pub struct ff_constant_effect {
+        pub level: ::__s16,
+        pub envelope: ff_envelope,
+    }
+
+    pub struct ff_ramp_effect {
+        pub start_level: ::__s16,
+        pub end_level: ::__s16,
+        pub envelope: ff_envelope,
+    }
+
+    pub struct ff_condition_effect {
+        pub right_saturation: ::__u16,
+        pub left_saturation: ::__u16,
+
+        pub right_coeff: ::__s16,
+        pub left_coeff: ::__s16,
+
+        pub deadband: ::__u16,
+        pub center: ::__s16,
+    }
+
+    pub struct ff_periodic_effect {
+        pub waveform: ::__u16,
+        pub period: ::__u16,
+        pub magnitude: ::__s16,
+        pub offset: ::__s16,
+        pub phase: ::__u16,
+
+        pub envelope: ff_envelope,
+
+        pub custom_len: ::__u32,
+        pub custom_data: *mut ::__s16,
+    }
+
+    pub struct ff_rumble_effect {
+        pub strong_magnitude: ::__u16,
+        pub weak_magnitude: ::__u16,
+    }
+
+    pub struct ff_effect {
+        pub type_: ::__u16,
+        pub id: ::__s16,
+        pub direction: ::__u16,
+        pub trigger: ff_trigger,
+        pub replay: ff_replay,
+        // FIXME this is actually a union
+        #[cfg(target_pointer_width = "64")]
+        pub u: [u64; 4],
+        #[cfg(target_pointer_width = "32")]
+        pub u: [u32; 7],
+    }
+
+    pub struct dl_phdr_info {
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_addr: Elf64_Addr,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_addr: Elf32_Addr,
+
+        pub dlpi_name: *const ::c_char,
+
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_phdr: *const Elf64_Phdr,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_phdr: *const Elf32_Phdr,
+
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_phnum: Elf64_Half,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_phnum: Elf32_Half,
+
+        pub dlpi_adds: ::c_ulonglong,
+        pub dlpi_subs: ::c_ulonglong,
+        pub dlpi_tls_modid: ::size_t,
+        pub dlpi_tls_data: *mut ::c_void,
+    }
+
+    pub struct Elf32_Phdr {
+        pub p_type: Elf32_Word,
+        pub p_offset: Elf32_Off,
+        pub p_vaddr: Elf32_Addr,
+        pub p_paddr: Elf32_Addr,
+        pub p_filesz: Elf32_Word,
+        pub p_memsz: Elf32_Word,
+        pub p_flags: Elf32_Word,
+        pub p_align: Elf32_Word,
+    }
+
+    pub struct Elf64_Phdr {
+        pub p_type: Elf64_Word,
+        pub p_flags: Elf64_Word,
+        pub p_offset: Elf64_Off,
+        pub p_vaddr: Elf64_Addr,
+        pub p_paddr: Elf64_Addr,
+        pub p_filesz: Elf64_Xword,
+        pub p_memsz: Elf64_Xword,
+        pub p_align: Elf64_Xword,
+    }
+
+    pub struct statfs64 {
+        pub f_type: ::c_ulong,
+        pub f_bsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namelen: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_flags: ::c_ulong,
+        pub f_spare: [::c_ulong; 4],
+    }
+
+    pub struct statvfs64 {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: u64,
+        pub f_bfree: u64,
+        pub f_bavail: u64,
+        pub f_files: u64,
+        pub f_ffree: u64,
+        pub f_favail: u64,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
+    pub struct stack_t {
+        pub ss_sp: *mut ::c_void,
+        pub ss_flags: ::c_int,
+        pub ss_size: ::size_t
+    }
+
+    pub struct pthread_attr_t {
+        __size: [u64; 7]
+    }
+
+    pub struct sigset_t {
+        __val: [::c_ulong; 16],
+    }
+
+    pub struct shmid_ds {
+        pub shm_perm: ::ipc_perm,
+        pub shm_segsz: ::size_t,
+        pub shm_atime: ::time_t,
+        pub shm_dtime: ::time_t,
+        pub shm_ctime: ::time_t,
+        pub shm_cpid: ::pid_t,
+        pub shm_lpid: ::pid_t,
+        pub shm_nattch: ::c_ulong,
+        __pad1: ::c_ulong,
+        __pad2: ::c_ulong,
+    }
+
+    pub struct msqid_ds {
+        pub msg_perm: ::ipc_perm,
+        pub msg_stime: ::time_t,
+        pub msg_rtime: ::time_t,
+        pub msg_ctime: ::time_t,
+        __msg_cbytes: ::c_ulong,
+        pub msg_qnum: ::msgqnum_t,
+        pub msg_qbytes: ::msglen_t,
+        pub msg_lspid: ::pid_t,
+        pub msg_lrpid: ::pid_t,
+        __pad1: ::c_ulong,
+        __pad2: ::c_ulong,
+    }
+
+    pub struct statfs {
+        pub f_type: ::c_ulong,
+        pub f_bsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namelen: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_flags: ::c_ulong,
+        pub f_spare: [::c_ulong; 4],
+    }
+
+    pub struct msghdr {
+        pub msg_name: *mut ::c_void,
+        pub msg_namelen: ::socklen_t,
+        pub msg_iov: *mut ::iovec,
+        pub msg_iovlen: ::c_int,
+        __pad1: ::c_int,
+        pub msg_control: *mut ::c_void,
+        pub msg_controllen: ::socklen_t,
+        __pad2: ::socklen_t,
+        pub msg_flags: ::c_int,
+    }
+
+    pub struct cmsghdr {
+        pub cmsg_len: ::socklen_t,
+        pub __pad1: ::c_int,
+        pub cmsg_level: ::c_int,
+        pub cmsg_type: ::c_int,
+    }
+
+    pub struct sem_t {
+        __val: [::c_int; 8],
+    }
+
+    pub struct siginfo_t {
+        pub si_signo: ::c_int,
+        pub si_errno: ::c_int,
+        pub si_code: ::c_int,
+        pub _pad: [::c_int; 29],
+        _align: [usize; 0],
+    }
+
+    pub struct termios2 {
+        pub c_iflag: ::tcflag_t,
+        pub c_oflag: ::tcflag_t,
+        pub c_cflag: ::tcflag_t,
+        pub c_lflag: ::tcflag_t,
+        pub c_line: ::cc_t,
+        pub c_cc: [::cc_t; 19],
+        pub c_ispeed: ::speed_t,
+        pub c_ospeed: ::speed_t,
+    }
+}
+
+// PUB_CONST
+
+pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
+pub const SIG_IGN: sighandler_t = 1 as sighandler_t;
+pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
+
+pub const DT_FIFO: u8 = 1;
+pub const DT_CHR: u8 = 2;
+pub const DT_DIR: u8 = 4;
+pub const DT_BLK: u8 = 6;
+pub const DT_REG: u8 = 8;
+pub const DT_LNK: u8 = 10;
+pub const DT_SOCK: u8 = 12;
+
+pub const FD_CLOEXEC: ::c_int = 0x1;
+
+pub const USRQUOTA: ::c_int = 0;
+pub const GRPQUOTA: ::c_int = 1;
+
+pub const SIGIOT: ::c_int = 6;
+
+pub const S_ISUID: ::c_int = 0x800;
+pub const S_ISGID: ::c_int = 0x400;
+pub const S_ISVTX: ::c_int = 0x200;
+
+pub const IF_NAMESIZE: ::size_t = 16;
+
+pub const LOG_EMERG: ::c_int = 0;
+pub const LOG_ALERT: ::c_int = 1;
+pub const LOG_CRIT: ::c_int = 2;
+pub const LOG_ERR: ::c_int = 3;
+pub const LOG_WARNING: ::c_int = 4;
+pub const LOG_NOTICE: ::c_int = 5;
+pub const LOG_INFO: ::c_int = 6;
+pub const LOG_DEBUG: ::c_int = 7;
+
+pub const LOG_KERN: ::c_int = 0;
+pub const LOG_USER: ::c_int = 1 << 3;
+pub const LOG_MAIL: ::c_int = 2 << 3;
+pub const LOG_DAEMON: ::c_int = 3 << 3;
+pub const LOG_AUTH: ::c_int = 4 << 3;
+pub const LOG_SYSLOG: ::c_int = 5 << 3;
+pub const LOG_LPR: ::c_int = 6 << 3;
+pub const LOG_NEWS: ::c_int = 7 << 3;
+pub const LOG_UUCP: ::c_int = 8 << 3;
+pub const LOG_LOCAL0: ::c_int = 16 << 3;
+pub const LOG_LOCAL1: ::c_int = 17 << 3;
+pub const LOG_LOCAL2: ::c_int = 18 << 3;
+pub const LOG_LOCAL3: ::c_int = 19 << 3;
+pub const LOG_LOCAL4: ::c_int = 20 << 3;
+pub const LOG_LOCAL5: ::c_int = 21 << 3;
+pub const LOG_LOCAL6: ::c_int = 22 << 3;
+pub const LOG_LOCAL7: ::c_int = 23 << 3;
+
+pub const LOG_PID: ::c_int = 0x01;
+pub const LOG_CONS: ::c_int = 0x02;
+pub const LOG_ODELAY: ::c_int = 0x04;
+pub const LOG_NDELAY: ::c_int = 0x08;
+pub const LOG_NOWAIT: ::c_int = 0x10;
+
+pub const LOG_PRIMASK: ::c_int = 7;
+pub const LOG_FACMASK: ::c_int = 0x3f8;
+
+pub const PRIO_PROCESS: ::c_int = 0;
+pub const PRIO_PGRP: ::c_int = 1;
+pub const PRIO_USER: ::c_int = 2;
+
+pub const PRIO_MIN: ::c_int = -20;
+pub const PRIO_MAX: ::c_int = 20;
+
+pub const IPPROTO_ICMP: ::c_int = 1;
+pub const IPPROTO_ICMPV6: ::c_int = 58;
+pub const IPPROTO_TCP: ::c_int = 6;
+pub const IPPROTO_UDP: ::c_int = 17;
+pub const IPPROTO_IP: ::c_int = 0;
+pub const IPPROTO_IPV6: ::c_int = 41;
+
+pub const INADDR_LOOPBACK: in_addr_t = 2130706433;
+pub const INADDR_ANY: in_addr_t = 0;
+pub const INADDR_BROADCAST: in_addr_t = 4294967295;
+pub const INADDR_NONE: in_addr_t = 4294967295;
+
+pub const EXIT_FAILURE: ::c_int = 1;
+pub const EXIT_SUCCESS: ::c_int = 0;
+pub const RAND_MAX: ::c_int = 2147483647;
+pub const EOF: ::c_int = -1;
+pub const SEEK_SET: ::c_int = 0;
+pub const SEEK_CUR: ::c_int = 1;
+pub const SEEK_END: ::c_int = 2;
+pub const _IOFBF: ::c_int = 0;
+pub const _IONBF: ::c_int = 2;
+pub const _IOLBF: ::c_int = 1;
+
+pub const F_DUPFD: ::c_int = 0;
+pub const F_GETFD: ::c_int = 1;
+pub const F_SETFD: ::c_int = 2;
+pub const F_GETFL: ::c_int = 3;
+pub const F_SETFL: ::c_int = 4;
+
+// Linux-specific fcntls
+pub const F_SETLEASE: ::c_int = 1024;
+pub const F_GETLEASE: ::c_int = 1025;
+pub const F_NOTIFY: ::c_int = 1026;
+pub const F_CANCELLK: ::c_int = 1029;
+pub const F_DUPFD_CLOEXEC: ::c_int = 1030;
+pub const F_SETPIPE_SZ: ::c_int = 1031;
+pub const F_GETPIPE_SZ: ::c_int = 1032;
+pub const F_ADD_SEALS: ::c_int = 1033;
+pub const F_GET_SEALS: ::c_int = 1034;
+
+pub const F_SEAL_SEAL: ::c_int = 0x0001;
+pub const F_SEAL_SHRINK: ::c_int = 0x0002;
+pub const F_SEAL_GROW: ::c_int = 0x0004;
+pub const F_SEAL_WRITE: ::c_int = 0x0008;
+
+// TODO(#235): Include file sealing fcntls once we have a way to verify them.
+
+pub const SIGTRAP: ::c_int = 5;
+
+pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0;
+pub const PTHREAD_CREATE_DETACHED: ::c_int = 1;
+
+pub const CLOCK_REALTIME: ::clockid_t = 0;
+pub const CLOCK_MONOTONIC: ::clockid_t = 1;
+pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2;
+pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3;
+pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4;
+pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5;
+pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6;
+pub const CLOCK_BOOTTIME: ::clockid_t = 7;
+pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8;
+pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9;
+// TODO(#247) Someday our Travis shall have glibc 2.21 (released in Sep
+// 2014.) See also musl/mod.rs
+// pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;
+// pub const CLOCK_TAI: ::clockid_t = 11;
+pub const TIMER_ABSTIME: ::c_int = 1;
+
+pub const RLIMIT_CPU: ::c_int = 0;
+pub const RLIMIT_FSIZE: ::c_int = 1;
+pub const RLIMIT_DATA: ::c_int = 2;
+pub const RLIMIT_STACK: ::c_int = 3;
+pub const RLIMIT_CORE: ::c_int = 4;
+pub const RLIMIT_LOCKS: ::c_int = 10;
+pub const RLIMIT_SIGPENDING: ::c_int = 11;
+pub const RLIMIT_MSGQUEUE: ::c_int = 12;
+pub const RLIMIT_NICE: ::c_int = 13;
+pub const RLIMIT_RTPRIO: ::c_int = 14;
+
+pub const RUSAGE_SELF: ::c_int = 0;
+
+pub const O_RDONLY: ::c_int = 0;
+pub const O_WRONLY: ::c_int = 1;
+pub const O_RDWR: ::c_int = 2;
+
+pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC;
+
+pub const S_IFIFO: ::mode_t = 4096;
+pub const S_IFCHR: ::mode_t = 8192;
+pub const S_IFBLK: ::mode_t = 24576;
+pub const S_IFDIR: ::mode_t = 16384;
+pub const S_IFREG: ::mode_t = 32768;
+pub const S_IFLNK: ::mode_t = 40960;
+pub const S_IFSOCK: ::mode_t = 49152;
+pub const S_IFMT: ::mode_t = 61440;
+pub const S_IRWXU: ::mode_t = 448;
+pub const S_IXUSR: ::mode_t = 64;
+pub const S_IWUSR: ::mode_t = 128;
+pub const S_IRUSR: ::mode_t = 256;
+pub const S_IRWXG: ::mode_t = 56;
+pub const S_IXGRP: ::mode_t = 8;
+pub const S_IWGRP: ::mode_t = 16;
+pub const S_IRGRP: ::mode_t = 32;
+pub const S_IRWXO: ::mode_t = 7;
+pub const S_IXOTH: ::mode_t = 1;
+pub const S_IWOTH: ::mode_t = 2;
+pub const S_IROTH: ::mode_t = 4;
+pub const F_OK: ::c_int = 0;
+pub const R_OK: ::c_int = 4;
+pub const W_OK: ::c_int = 2;
+pub const X_OK: ::c_int = 1;
+pub const STDIN_FILENO: ::c_int = 0;
+pub const STDOUT_FILENO: ::c_int = 1;
+pub const STDERR_FILENO: ::c_int = 2;
+pub const SIGHUP: ::c_int = 1;
+pub const SIGINT: ::c_int = 2;
+pub const SIGQUIT: ::c_int = 3;
+pub const SIGILL: ::c_int = 4;
+pub const SIGABRT: ::c_int = 6;
+pub const SIGFPE: ::c_int = 8;
+pub const SIGKILL: ::c_int = 9;
+pub const SIGSEGV: ::c_int = 11;
+pub const SIGPIPE: ::c_int = 13;
+pub const SIGALRM: ::c_int = 14;
+pub const SIGTERM: ::c_int = 15;
+
+pub const PROT_NONE: ::c_int = 0;
+pub const PROT_READ: ::c_int = 1;
+pub const PROT_WRITE: ::c_int = 2;
+pub const PROT_EXEC: ::c_int = 4;
+
+pub const LC_CTYPE: ::c_int = 0;
+pub const LC_NUMERIC: ::c_int = 1;
+pub const LC_TIME: ::c_int = 2;
+pub const LC_COLLATE: ::c_int = 3;
+pub const LC_MONETARY: ::c_int = 4;
+pub const LC_MESSAGES: ::c_int = 5;
+pub const LC_ALL: ::c_int = 6;
+pub const LC_CTYPE_MASK: ::c_int = (1 << LC_CTYPE);
+pub const LC_NUMERIC_MASK: ::c_int = (1 << LC_NUMERIC);
+pub const LC_TIME_MASK: ::c_int = (1 << LC_TIME);
+pub const LC_COLLATE_MASK: ::c_int = (1 << LC_COLLATE);
+pub const LC_MONETARY_MASK: ::c_int = (1 << LC_MONETARY);
+pub const LC_MESSAGES_MASK: ::c_int = (1 << LC_MESSAGES);
+// LC_ALL_MASK defined per platform
+
+pub const MAP_FILE: ::c_int = 0x0000;
+pub const MAP_SHARED: ::c_int = 0x0001;
+pub const MAP_PRIVATE: ::c_int = 0x0002;
+pub const MAP_FIXED: ::c_int = 0x0010;
+
+pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void;
+
+// MS_ flags for msync(2)
+pub const MS_ASYNC: ::c_int = 0x0001;
+pub const MS_INVALIDATE: ::c_int = 0x0002;
+pub const MS_SYNC: ::c_int = 0x0004;
+
+// MS_ flags for mount(2)
+pub const MS_RDONLY: ::c_ulong = 0x01;
+pub const MS_NOSUID: ::c_ulong = 0x02;
+pub const MS_NODEV: ::c_ulong = 0x04;
+pub const MS_NOEXEC: ::c_ulong = 0x08;
+pub const MS_SYNCHRONOUS: ::c_ulong = 0x10;
+pub const MS_REMOUNT: ::c_ulong = 0x20;
+pub const MS_MANDLOCK: ::c_ulong = 0x40;
+pub const MS_DIRSYNC: ::c_ulong = 0x80;
+pub const MS_NOATIME: ::c_ulong = 0x0400;
+pub const MS_NODIRATIME: ::c_ulong = 0x0800;
+pub const MS_BIND: ::c_ulong = 0x1000;
+pub const MS_MOVE: ::c_ulong = 0x2000;
+pub const MS_REC: ::c_ulong = 0x4000;
+pub const MS_SILENT: ::c_ulong = 0x8000;
+pub const MS_POSIXACL: ::c_ulong = 0x010000;
+pub const MS_UNBINDABLE: ::c_ulong = 0x020000;
+pub const MS_PRIVATE: ::c_ulong = 0x040000;
+pub const MS_SLAVE: ::c_ulong = 0x080000;
+pub const MS_SHARED: ::c_ulong = 0x100000;
+pub const MS_RELATIME: ::c_ulong = 0x200000;
+pub const MS_KERNMOUNT: ::c_ulong = 0x400000;
+pub const MS_I_VERSION: ::c_ulong = 0x800000;
+pub const MS_STRICTATIME: ::c_ulong = 0x1000000;
+pub const MS_ACTIVE: ::c_ulong = 0x40000000;
+pub const MS_NOUSER: ::c_ulong = 0x80000000;
+pub const MS_MGC_VAL: ::c_ulong = 0xc0ed0000;
+pub const MS_MGC_MSK: ::c_ulong = 0xffff0000;
+pub const MS_RMT_MASK: ::c_ulong = 0x800051;
+
+pub const EPERM: ::c_int = 1;
+pub const ENOENT: ::c_int = 2;
+pub const ESRCH: ::c_int = 3;
+pub const EINTR: ::c_int = 4;
+pub const EIO: ::c_int = 5;
+pub const ENXIO: ::c_int = 6;
+pub const E2BIG: ::c_int = 7;
+pub const ENOEXEC: ::c_int = 8;
+pub const EBADF: ::c_int = 9;
+pub const ECHILD: ::c_int = 10;
+pub const EAGAIN: ::c_int = 11;
+pub const ENOMEM: ::c_int = 12;
+pub const EACCES: ::c_int = 13;
+pub const EFAULT: ::c_int = 14;
+pub const ENOTBLK: ::c_int = 15;
+pub const EBUSY: ::c_int = 16;
+pub const EEXIST: ::c_int = 17;
+pub const EXDEV: ::c_int = 18;
+pub const ENODEV: ::c_int = 19;
+pub const ENOTDIR: ::c_int = 20;
+pub const EISDIR: ::c_int = 21;
+pub const EINVAL: ::c_int = 22;
+pub const ENFILE: ::c_int = 23;
+pub const EMFILE: ::c_int = 24;
+pub const ENOTTY: ::c_int = 25;
+pub const ETXTBSY: ::c_int = 26;
+pub const EFBIG: ::c_int = 27;
+pub const ENOSPC: ::c_int = 28;
+pub const ESPIPE: ::c_int = 29;
+pub const EROFS: ::c_int = 30;
+pub const EMLINK: ::c_int = 31;
+pub const EPIPE: ::c_int = 32;
+pub const EDOM: ::c_int = 33;
+pub const ERANGE: ::c_int = 34;
+pub const EWOULDBLOCK: ::c_int = EAGAIN;
+
+pub const SCM_RIGHTS: ::c_int = 0x01;
+pub const SCM_CREDENTIALS: ::c_int = 0x02;
+
+pub const PROT_GROWSDOWN: ::c_int = 0x1000000;
+pub const PROT_GROWSUP: ::c_int = 0x2000000;
+
+pub const MAP_TYPE: ::c_int = 0x000f;
+
+pub const MADV_NORMAL: ::c_int = 0;
+pub const MADV_RANDOM: ::c_int = 1;
+pub const MADV_SEQUENTIAL: ::c_int = 2;
+pub const MADV_WILLNEED: ::c_int = 3;
+pub const MADV_DONTNEED: ::c_int = 4;
+pub const MADV_FREE: ::c_int = 8;
+pub const MADV_REMOVE: ::c_int = 9;
+pub const MADV_DONTFORK: ::c_int = 10;
+pub const MADV_DOFORK: ::c_int = 11;
+pub const MADV_MERGEABLE: ::c_int = 12;
+pub const MADV_UNMERGEABLE: ::c_int = 13;
+pub const MADV_HUGEPAGE: ::c_int = 14;
+pub const MADV_NOHUGEPAGE: ::c_int = 15;
+pub const MADV_DONTDUMP: ::c_int = 16;
+pub const MADV_DODUMP: ::c_int = 17;
+pub const MADV_HWPOISON: ::c_int = 100;
+pub const MADV_SOFT_OFFLINE: ::c_int = 101;
+
+pub const IFF_UP: ::c_int = 0x1;
+pub const IFF_BROADCAST: ::c_int = 0x2;
+pub const IFF_DEBUG: ::c_int = 0x4;
+pub const IFF_LOOPBACK: ::c_int = 0x8;
+pub const IFF_POINTOPOINT: ::c_int = 0x10;
+pub const IFF_NOTRAILERS: ::c_int = 0x20;
+pub const IFF_RUNNING: ::c_int = 0x40;
+pub const IFF_NOARP: ::c_int = 0x80;
+pub const IFF_PROMISC: ::c_int = 0x100;
+pub const IFF_ALLMULTI: ::c_int = 0x200;
+pub const IFF_MASTER: ::c_int = 0x400;
+pub const IFF_SLAVE: ::c_int = 0x800;
+pub const IFF_MULTICAST: ::c_int = 0x1000;
+pub const IFF_PORTSEL: ::c_int = 0x2000;
+pub const IFF_AUTOMEDIA: ::c_int = 0x4000;
+pub const IFF_DYNAMIC: ::c_int = 0x8000;
+pub const IFF_TUN: ::c_int = 0x0001;
+pub const IFF_TAP: ::c_int = 0x0002;
+pub const IFF_NO_PI: ::c_int = 0x1000;
+
+pub const SOL_IP: ::c_int = 0;
+pub const SOL_TCP: ::c_int = 6;
+pub const SOL_UDP: ::c_int = 17;
+pub const SOL_IPV6: ::c_int = 41;
+pub const SOL_ICMPV6: ::c_int = 58;
+pub const SOL_RAW: ::c_int = 255;
+pub const SOL_DECNET: ::c_int = 261;
+pub const SOL_X25: ::c_int = 262;
+pub const SOL_PACKET: ::c_int = 263;
+pub const SOL_ATM: ::c_int = 264;
+pub const SOL_AAL: ::c_int = 265;
+pub const SOL_IRDA: ::c_int = 266;
+pub const SOL_NETBEUI: ::c_int = 267;
+pub const SOL_LLC: ::c_int = 268;
+pub const SOL_DCCP: ::c_int = 269;
+pub const SOL_NETLINK: ::c_int = 270;
+pub const SOL_TIPC: ::c_int = 271;
+
+pub const AF_UNSPEC: ::c_int = 0;
+pub const AF_UNIX: ::c_int = 1;
+pub const AF_LOCAL: ::c_int = 1;
+pub const AF_INET: ::c_int = 2;
+pub const AF_AX25: ::c_int = 3;
+pub const AF_IPX: ::c_int = 4;
+pub const AF_APPLETALK: ::c_int = 5;
+pub const AF_NETROM: ::c_int = 6;
+pub const AF_BRIDGE: ::c_int = 7;
+pub const AF_ATMPVC: ::c_int = 8;
+pub const AF_X25: ::c_int = 9;
+pub const AF_INET6: ::c_int = 10;
+pub const AF_ROSE: ::c_int = 11;
+pub const AF_DECnet: ::c_int = 12;
+pub const AF_NETBEUI: ::c_int = 13;
+pub const AF_SECURITY: ::c_int = 14;
+pub const AF_KEY: ::c_int = 15;
+pub const AF_NETLINK: ::c_int = 16;
+pub const AF_ROUTE: ::c_int = AF_NETLINK;
+pub const AF_PACKET: ::c_int = 17;
+pub const AF_ASH: ::c_int = 18;
+pub const AF_ECONET: ::c_int = 19;
+pub const AF_ATMSVC: ::c_int = 20;
+pub const AF_RDS: ::c_int = 21;
+pub const AF_SNA: ::c_int = 22;
+pub const AF_IRDA: ::c_int = 23;
+pub const AF_PPPOX: ::c_int = 24;
+pub const AF_WANPIPE: ::c_int = 25;
+pub const AF_LLC: ::c_int = 26;
+pub const AF_CAN: ::c_int = 29;
+pub const AF_TIPC: ::c_int = 30;
+pub const AF_BLUETOOTH: ::c_int = 31;
+pub const AF_IUCV: ::c_int = 32;
+pub const AF_RXRPC: ::c_int = 33;
+pub const AF_ISDN: ::c_int = 34;
+pub const AF_PHONET: ::c_int = 35;
+pub const AF_IEEE802154: ::c_int = 36;
+pub const AF_CAIF: ::c_int = 37;
+pub const AF_ALG: ::c_int = 38;
+
+pub const PF_UNSPEC: ::c_int = AF_UNSPEC;
+pub const PF_UNIX: ::c_int = AF_UNIX;
+pub const PF_LOCAL: ::c_int = AF_LOCAL;
+pub const PF_INET: ::c_int = AF_INET;
+pub const PF_AX25: ::c_int = AF_AX25;
+pub const PF_IPX: ::c_int = AF_IPX;
+pub const PF_APPLETALK: ::c_int = AF_APPLETALK;
+pub const PF_NETROM: ::c_int = AF_NETROM;
+pub const PF_BRIDGE: ::c_int = AF_BRIDGE;
+pub const PF_ATMPVC: ::c_int = AF_ATMPVC;
+pub const PF_X25: ::c_int = AF_X25;
+pub const PF_INET6: ::c_int = AF_INET6;
+pub const PF_ROSE: ::c_int = AF_ROSE;
+pub const PF_DECnet: ::c_int = AF_DECnet;
+pub const PF_NETBEUI: ::c_int = AF_NETBEUI;
+pub const PF_SECURITY: ::c_int = AF_SECURITY;
+pub const PF_KEY: ::c_int = AF_KEY;
+pub const PF_NETLINK: ::c_int = AF_NETLINK;
+pub const PF_ROUTE: ::c_int = AF_ROUTE;
+pub const PF_PACKET: ::c_int = AF_PACKET;
+pub const PF_ASH: ::c_int = AF_ASH;
+pub const PF_ECONET: ::c_int = AF_ECONET;
+pub const PF_ATMSVC: ::c_int = AF_ATMSVC;
+pub const PF_RDS: ::c_int = AF_RDS;
+pub const PF_SNA: ::c_int = AF_SNA;
+pub const PF_IRDA: ::c_int = AF_IRDA;
+pub const PF_PPPOX: ::c_int = AF_PPPOX;
+pub const PF_WANPIPE: ::c_int = AF_WANPIPE;
+pub const PF_LLC: ::c_int = AF_LLC;
+pub const PF_CAN: ::c_int = AF_CAN;
+pub const PF_TIPC: ::c_int = AF_TIPC;
+pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH;
+pub const PF_IUCV: ::c_int = AF_IUCV;
+pub const PF_RXRPC: ::c_int = AF_RXRPC;
+pub const PF_ISDN: ::c_int = AF_ISDN;
+pub const PF_PHONET: ::c_int = AF_PHONET;
+pub const PF_IEEE802154: ::c_int = AF_IEEE802154;
+pub const PF_CAIF: ::c_int = AF_CAIF;
+pub const PF_ALG: ::c_int = AF_ALG;
+
+pub const SOMAXCONN: ::c_int = 128;
+
+pub const MSG_OOB: ::c_int = 1;
+pub const MSG_PEEK: ::c_int = 2;
+pub const MSG_DONTROUTE: ::c_int = 4;
+pub const MSG_CTRUNC: ::c_int = 8;
+pub const MSG_TRUNC: ::c_int = 0x20;
+pub const MSG_DONTWAIT: ::c_int = 0x40;
+pub const MSG_EOR: ::c_int = 0x80;
+pub const MSG_WAITALL: ::c_int = 0x100;
+pub const MSG_FIN: ::c_int = 0x200;
+pub const MSG_SYN: ::c_int = 0x400;
+pub const MSG_CONFIRM: ::c_int = 0x800;
+pub const MSG_RST: ::c_int = 0x1000;
+pub const MSG_ERRQUEUE: ::c_int = 0x2000;
+pub const MSG_NOSIGNAL: ::c_int = 0x4000;
+pub const MSG_MORE: ::c_int = 0x8000;
+pub const MSG_WAITFORONE: ::c_int = 0x10000;
+pub const MSG_FASTOPEN: ::c_int = 0x20000000;
+pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000;
+
+pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
+
+pub const SOCK_RAW: ::c_int = 3;
+pub const SOCK_RDM: ::c_int = 4;
+pub const IP_MULTICAST_IF: ::c_int = 32;
+pub const IP_MULTICAST_TTL: ::c_int = 33;
+pub const IP_MULTICAST_LOOP: ::c_int = 34;
+pub const IP_TTL: ::c_int = 2;
+pub const IP_HDRINCL: ::c_int = 3;
+pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
+pub const IP_DROP_MEMBERSHIP: ::c_int = 36;
+pub const IP_TRANSPARENT: ::c_int = 19;
+pub const IPV6_UNICAST_HOPS: ::c_int = 16;
+pub const IPV6_MULTICAST_IF: ::c_int = 17;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 18;
+pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
+pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20;
+pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21;
+pub const IPV6_V6ONLY: ::c_int = 26;
+
+pub const TCP_NODELAY: ::c_int = 1;
+pub const TCP_MAXSEG: ::c_int = 2;
+pub const TCP_CORK: ::c_int = 3;
+pub const TCP_KEEPIDLE: ::c_int = 4;
+pub const TCP_KEEPINTVL: ::c_int = 5;
+pub const TCP_KEEPCNT: ::c_int = 6;
+pub const TCP_SYNCNT: ::c_int = 7;
+pub const TCP_LINGER2: ::c_int = 8;
+pub const TCP_DEFER_ACCEPT: ::c_int = 9;
+pub const TCP_WINDOW_CLAMP: ::c_int = 10;
+pub const TCP_INFO: ::c_int = 11;
+pub const TCP_QUICKACK: ::c_int = 12;
+pub const TCP_CONGESTION: ::c_int = 13;
+
+pub const SO_DEBUG: ::c_int = 1;
+
+pub const SHUT_RD: ::c_int = 0;
+pub const SHUT_WR: ::c_int = 1;
+pub const SHUT_RDWR: ::c_int = 2;
+
+pub const LOCK_SH: ::c_int = 1;
+pub const LOCK_EX: ::c_int = 2;
+pub const LOCK_NB: ::c_int = 4;
+pub const LOCK_UN: ::c_int = 8;
+
+pub const SS_ONSTACK: ::c_int = 1;
+pub const SS_DISABLE: ::c_int = 2;
+
+pub const PATH_MAX: ::c_int = 4096;
+
+pub const FD_SETSIZE: usize = 1024;
+
+pub const EPOLLIN: ::c_int = 0x1;
+pub const EPOLLPRI: ::c_int = 0x2;
+pub const EPOLLOUT: ::c_int = 0x4;
+pub const EPOLLRDNORM: ::c_int = 0x40;
+pub const EPOLLRDBAND: ::c_int = 0x80;
+pub const EPOLLWRNORM: ::c_int = 0x100;
+pub const EPOLLWRBAND: ::c_int = 0x200;
+pub const EPOLLMSG: ::c_int = 0x400;
+pub const EPOLLERR: ::c_int = 0x8;
+pub const EPOLLHUP: ::c_int = 0x10;
+pub const EPOLLET: ::c_int = 0x80000000;
+
+pub const EPOLL_CTL_ADD: ::c_int = 1;
+pub const EPOLL_CTL_MOD: ::c_int = 3;
+pub const EPOLL_CTL_DEL: ::c_int = 2;
+
+pub const MNT_DETACH: ::c_int = 0x2;
+pub const MNT_EXPIRE: ::c_int = 0x4;
+
+pub const Q_GETFMT: ::c_int = 0x800004;
+pub const Q_GETINFO: ::c_int = 0x800005;
+pub const Q_SETINFO: ::c_int = 0x800006;
+pub const QIF_BLIMITS: ::uint32_t = 1;
+pub const QIF_SPACE: ::uint32_t = 2;
+pub const QIF_ILIMITS: ::uint32_t = 4;
+pub const QIF_INODES: ::uint32_t = 8;
+pub const QIF_BTIME: ::uint32_t = 16;
+pub const QIF_ITIME: ::uint32_t = 32;
+pub const QIF_LIMITS: ::uint32_t = 5;
+pub const QIF_USAGE: ::uint32_t = 10;
+pub const QIF_TIMES: ::uint32_t = 48;
+pub const QIF_ALL: ::uint32_t = 63;
+
+pub const MNT_FORCE: ::c_int = 0x1;
+
+pub const Q_SYNC: ::c_int = 0x800001;
+pub const Q_QUOTAON: ::c_int = 0x800002;
+pub const Q_QUOTAOFF: ::c_int = 0x800003;
+pub const Q_GETQUOTA: ::c_int = 0x800007;
+pub const Q_SETQUOTA: ::c_int = 0x800008;
+
+pub const TCIOFF: ::c_int = 2;
+pub const TCION: ::c_int = 3;
+pub const TCOOFF: ::c_int = 0;
+pub const TCOON: ::c_int = 1;
+pub const TCIFLUSH: ::c_int = 0;
+pub const TCOFLUSH: ::c_int = 1;
+pub const TCIOFLUSH: ::c_int = 2;
+pub const NL0: ::c_int  = 0x00000000;
+pub const NL1: ::c_int  = 0x00000100;
+pub const TAB0: ::c_int = 0x00000000;
+pub const CR0: ::c_int  = 0x00000000;
+pub const FF0: ::c_int  = 0x00000000;
+pub const BS0: ::c_int  = 0x00000000;
+pub const VT0: ::c_int  = 0x00000000;
+pub const VERASE: usize = 2;
+pub const VKILL: usize = 3;
+pub const VINTR: usize = 0;
+pub const VQUIT: usize = 1;
+pub const VLNEXT: usize = 15;
+pub const IGNBRK: ::tcflag_t = 0x00000001;
+pub const BRKINT: ::tcflag_t = 0x00000002;
+pub const IGNPAR: ::tcflag_t = 0x00000004;
+pub const PARMRK: ::tcflag_t = 0x00000008;
+pub const INPCK: ::tcflag_t = 0x00000010;
+pub const ISTRIP: ::tcflag_t = 0x00000020;
+pub const INLCR: ::tcflag_t = 0x00000040;
+pub const IGNCR: ::tcflag_t = 0x00000080;
+pub const ICRNL: ::tcflag_t = 0x00000100;
+pub const IXANY: ::tcflag_t = 0x00000800;
+pub const IMAXBEL: ::tcflag_t = 0x00002000;
+pub const OPOST: ::tcflag_t = 0x1;
+pub const CS5: ::tcflag_t = 0x00000000;
+pub const CRTSCTS: ::tcflag_t = 0x80000000;
+pub const ECHO: ::tcflag_t = 0x00000008;
+pub const OCRNL:  ::tcflag_t = 0o000010;
+pub const ONOCR:  ::tcflag_t = 0o000020;
+pub const ONLRET: ::tcflag_t = 0o000040;
+pub const OFILL:  ::tcflag_t = 0o000100;
+pub const OFDEL:  ::tcflag_t = 0o000200;
+
+pub const CLONE_VM: ::c_int = 0x100;
+pub const CLONE_FS: ::c_int = 0x200;
+pub const CLONE_FILES: ::c_int = 0x400;
+pub const CLONE_SIGHAND: ::c_int = 0x800;
+pub const CLONE_PTRACE: ::c_int = 0x2000;
+pub const CLONE_VFORK: ::c_int = 0x4000;
+pub const CLONE_PARENT: ::c_int = 0x8000;
+pub const CLONE_THREAD: ::c_int = 0x10000;
+pub const CLONE_NEWNS: ::c_int = 0x20000;
+pub const CLONE_SYSVSEM: ::c_int = 0x40000;
+pub const CLONE_SETTLS: ::c_int = 0x80000;
+pub const CLONE_PARENT_SETTID: ::c_int = 0x100000;
+pub const CLONE_CHILD_CLEARTID: ::c_int = 0x200000;
+pub const CLONE_DETACHED: ::c_int = 0x400000;
+pub const CLONE_UNTRACED: ::c_int = 0x800000;
+pub const CLONE_CHILD_SETTID: ::c_int = 0x01000000;
+pub const CLONE_NEWUTS: ::c_int = 0x04000000;
+pub const CLONE_NEWIPC: ::c_int = 0x08000000;
+pub const CLONE_NEWUSER: ::c_int = 0x10000000;
+pub const CLONE_NEWPID: ::c_int = 0x20000000;
+pub const CLONE_NEWNET: ::c_int = 0x40000000;
+pub const CLONE_IO: ::c_int = 0x80000000;
+pub const CLONE_NEWCGROUP: ::c_int = 0x02000000;
+
+pub const WNOHANG: ::c_int = 0x00000001;
+pub const WUNTRACED: ::c_int = 0x00000002;
+pub const WSTOPPED: ::c_int = WUNTRACED;
+pub const WEXITED: ::c_int = 0x00000004;
+pub const WCONTINUED: ::c_int = 0x00000008;
+pub const WNOWAIT: ::c_int = 0x01000000;
+
+// Options set using PTRACE_SETOPTIONS.
+pub const PTRACE_O_TRACESYSGOOD: ::c_int = 0x00000001;
+pub const PTRACE_O_TRACEFORK: ::c_int = 0x00000002;
+pub const PTRACE_O_TRACEVFORK: ::c_int = 0x00000004;
+pub const PTRACE_O_TRACECLONE: ::c_int = 0x00000008;
+pub const PTRACE_O_TRACEEXEC: ::c_int = 0x00000010;
+pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 0x00000020;
+pub const PTRACE_O_TRACEEXIT: ::c_int = 0x00000040;
+pub const PTRACE_O_TRACESECCOMP: ::c_int = 0x00000080;
+pub const PTRACE_O_EXITKILL: ::c_int = 0x00100000;
+pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 0x00200000;
+pub const PTRACE_O_MASK: ::c_int = 0x003000ff;
+
+// Wait extended result codes for the above trace options.
+pub const PTRACE_EVENT_FORK: ::c_int = 1;
+pub const PTRACE_EVENT_VFORK: ::c_int = 2;
+pub const PTRACE_EVENT_CLONE: ::c_int = 3;
+pub const PTRACE_EVENT_EXEC: ::c_int = 4;
+pub const PTRACE_EVENT_VFORK_DONE: ::c_int = 5;
+pub const PTRACE_EVENT_EXIT: ::c_int = 6;
+pub const PTRACE_EVENT_SECCOMP: ::c_int = 7;
+// PTRACE_EVENT_STOP was added to glibc in 2.26
+// pub const PTRACE_EVENT_STOP: ::c_int = 128;
+
+pub const __WNOTHREAD: ::c_int = 0x20000000;
+pub const __WALL: ::c_int = 0x40000000;
+pub const __WCLONE: ::c_int = 0x80000000;
+
+pub const SPLICE_F_MOVE: ::c_uint = 0x01;
+pub const SPLICE_F_NONBLOCK: ::c_uint = 0x02;
+pub const SPLICE_F_MORE: ::c_uint = 0x04;
+pub const SPLICE_F_GIFT: ::c_uint = 0x08;
+
+pub const RTLD_LOCAL: ::c_int = 0;
+pub const RTLD_LAZY: ::c_int = 1;
+
+pub const POSIX_FADV_NORMAL: ::c_int = 0;
+pub const POSIX_FADV_RANDOM: ::c_int = 1;
+pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2;
+pub const POSIX_FADV_WILLNEED: ::c_int = 3;
+
+pub const AT_FDCWD: ::c_int = -100;
+pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x100;
+pub const AT_REMOVEDIR: ::c_int = 0x200;
+pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400;
+pub const AT_NO_AUTOMOUNT: ::c_int = 0x800;
+pub const AT_EMPTY_PATH: ::c_int = 0x1000;
+
+pub const LOG_CRON: ::c_int = 9 << 3;
+pub const LOG_AUTHPRIV: ::c_int = 10 << 3;
+pub const LOG_FTP: ::c_int = 11 << 3;
+pub const LOG_PERROR: ::c_int = 0x20;
+
+pub const PIPE_BUF: usize = 4096;
+
+pub const SI_LOAD_SHIFT: ::c_uint = 16;
+
+pub const SIGEV_SIGNAL: ::c_int = 0;
+pub const SIGEV_NONE: ::c_int = 1;
+pub const SIGEV_THREAD: ::c_int = 2;
+
+pub const P_ALL: idtype_t = 0;
+pub const P_PID: idtype_t = 1;
+pub const P_PGID: idtype_t = 2;
+
+pub const UTIME_OMIT: c_long = 1073741822;
+pub const UTIME_NOW: c_long = 1073741823;
+
+pub const POLLIN: ::c_short = 0x1;
+pub const POLLPRI: ::c_short = 0x2;
+pub const POLLOUT: ::c_short = 0x4;
+pub const POLLERR: ::c_short = 0x8;
+pub const POLLHUP: ::c_short = 0x10;
+pub const POLLNVAL: ::c_short = 0x20;
+pub const POLLRDNORM: ::c_short = 0x040;
+pub const POLLRDBAND: ::c_short = 0x080;
+
+pub const ABDAY_1: ::nl_item = 0x20000;
+pub const ABDAY_2: ::nl_item = 0x20001;
+pub const ABDAY_3: ::nl_item = 0x20002;
+pub const ABDAY_4: ::nl_item = 0x20003;
+pub const ABDAY_5: ::nl_item = 0x20004;
+pub const ABDAY_6: ::nl_item = 0x20005;
+pub const ABDAY_7: ::nl_item = 0x20006;
+
+pub const DAY_1: ::nl_item = 0x20007;
+pub const DAY_2: ::nl_item = 0x20008;
+pub const DAY_3: ::nl_item = 0x20009;
+pub const DAY_4: ::nl_item = 0x2000A;
+pub const DAY_5: ::nl_item = 0x2000B;
+pub const DAY_6: ::nl_item = 0x2000C;
+pub const DAY_7: ::nl_item = 0x2000D;
+
+pub const ABMON_1: ::nl_item = 0x2000E;
+pub const ABMON_2: ::nl_item = 0x2000F;
+pub const ABMON_3: ::nl_item = 0x20010;
+pub const ABMON_4: ::nl_item = 0x20011;
+pub const ABMON_5: ::nl_item = 0x20012;
+pub const ABMON_6: ::nl_item = 0x20013;
+pub const ABMON_7: ::nl_item = 0x20014;
+pub const ABMON_8: ::nl_item = 0x20015;
+pub const ABMON_9: ::nl_item = 0x20016;
+pub const ABMON_10: ::nl_item = 0x20017;
+pub const ABMON_11: ::nl_item = 0x20018;
+pub const ABMON_12: ::nl_item = 0x20019;
+
+pub const MON_1: ::nl_item = 0x2001A;
+pub const MON_2: ::nl_item = 0x2001B;
+pub const MON_3: ::nl_item = 0x2001C;
+pub const MON_4: ::nl_item = 0x2001D;
+pub const MON_5: ::nl_item = 0x2001E;
+pub const MON_6: ::nl_item = 0x2001F;
+pub const MON_7: ::nl_item = 0x20020;
+pub const MON_8: ::nl_item = 0x20021;
+pub const MON_9: ::nl_item = 0x20022;
+pub const MON_10: ::nl_item = 0x20023;
+pub const MON_11: ::nl_item = 0x20024;
+pub const MON_12: ::nl_item = 0x20025;
+
+pub const AM_STR: ::nl_item = 0x20026;
+pub const PM_STR: ::nl_item = 0x20027;
+
+pub const D_T_FMT: ::nl_item = 0x20028;
+pub const D_FMT: ::nl_item = 0x20029;
+pub const T_FMT: ::nl_item = 0x2002A;
+pub const T_FMT_AMPM: ::nl_item = 0x2002B;
+
+pub const ERA: ::nl_item = 0x2002C;
+pub const ERA_D_FMT: ::nl_item = 0x2002E;
+pub const ALT_DIGITS: ::nl_item = 0x2002F;
+pub const ERA_D_T_FMT: ::nl_item = 0x20030;
+pub const ERA_T_FMT: ::nl_item = 0x20031;
+
+pub const CODESET: ::nl_item = 14;
+
+pub const CRNCYSTR: ::nl_item = 0x4000F;
+
+pub const RUSAGE_THREAD: ::c_int = 1;
+pub const RUSAGE_CHILDREN: ::c_int = -1;
+
+pub const RADIXCHAR: ::nl_item = 0x10000;
+pub const THOUSEP: ::nl_item = 0x10001;
+
+pub const YESEXPR: ::nl_item = 0x50000;
+pub const NOEXPR: ::nl_item = 0x50001;
+pub const YESSTR: ::nl_item = 0x50002;
+pub const NOSTR: ::nl_item = 0x50003;
+
+pub const FILENAME_MAX: ::c_uint = 4096;
+pub const L_tmpnam: ::c_uint = 20;
+pub const _PC_LINK_MAX: ::c_int = 0;
+pub const _PC_MAX_CANON: ::c_int = 1;
+pub const _PC_MAX_INPUT: ::c_int = 2;
+pub const _PC_NAME_MAX: ::c_int = 3;
+pub const _PC_PATH_MAX: ::c_int = 4;
+pub const _PC_PIPE_BUF: ::c_int = 5;
+pub const _PC_CHOWN_RESTRICTED: ::c_int = 6;
+pub const _PC_NO_TRUNC: ::c_int = 7;
+pub const _PC_VDISABLE: ::c_int = 8;
+pub const _PC_SYNC_IO: ::c_int = 9;
+pub const _PC_ASYNC_IO: ::c_int = 10;
+pub const _PC_PRIO_IO: ::c_int = 11;
+pub const _PC_SOCK_MAXBUF: ::c_int = 12;
+pub const _PC_FILESIZEBITS: ::c_int = 13;
+pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14;
+pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15;
+pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16;
+pub const _PC_REC_XFER_ALIGN: ::c_int = 17;
+pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18;
+pub const _PC_SYMLINK_MAX: ::c_int = 19;
+pub const _PC_2_SYMLINKS: ::c_int = 20;
+
+pub const _SC_ARG_MAX: ::c_int = 0;
+pub const _SC_CHILD_MAX: ::c_int = 1;
+pub const _SC_CLK_TCK: ::c_int = 2;
+pub const _SC_NGROUPS_MAX: ::c_int = 3;
+pub const _SC_OPEN_MAX: ::c_int = 4;
+pub const _SC_STREAM_MAX: ::c_int = 5;
+pub const _SC_TZNAME_MAX: ::c_int = 6;
+pub const _SC_JOB_CONTROL: ::c_int = 7;
+pub const _SC_SAVED_IDS: ::c_int = 8;
+pub const _SC_REALTIME_SIGNALS: ::c_int = 9;
+pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10;
+pub const _SC_TIMERS: ::c_int = 11;
+pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12;
+pub const _SC_PRIORITIZED_IO: ::c_int = 13;
+pub const _SC_SYNCHRONIZED_IO: ::c_int = 14;
+pub const _SC_FSYNC: ::c_int = 15;
+pub const _SC_MAPPED_FILES: ::c_int = 16;
+pub const _SC_MEMLOCK: ::c_int = 17;
+pub const _SC_MEMLOCK_RANGE: ::c_int = 18;
+pub const _SC_MEMORY_PROTECTION: ::c_int = 19;
+pub const _SC_MESSAGE_PASSING: ::c_int = 20;
+pub const _SC_SEMAPHORES: ::c_int = 21;
+pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22;
+pub const _SC_AIO_LISTIO_MAX: ::c_int = 23;
+pub const _SC_AIO_MAX: ::c_int = 24;
+pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25;
+pub const _SC_DELAYTIMER_MAX: ::c_int = 26;
+pub const _SC_MQ_OPEN_MAX: ::c_int = 27;
+pub const _SC_MQ_PRIO_MAX: ::c_int = 28;
+pub const _SC_VERSION: ::c_int = 29;
+pub const _SC_PAGESIZE: ::c_int = 30;
+pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE;
+pub const _SC_RTSIG_MAX: ::c_int = 31;
+pub const _SC_SEM_NSEMS_MAX: ::c_int = 32;
+pub const _SC_SEM_VALUE_MAX: ::c_int = 33;
+pub const _SC_SIGQUEUE_MAX: ::c_int = 34;
+pub const _SC_TIMER_MAX: ::c_int = 35;
+pub const _SC_BC_BASE_MAX: ::c_int = 36;
+pub const _SC_BC_DIM_MAX: ::c_int = 37;
+pub const _SC_BC_SCALE_MAX: ::c_int = 38;
+pub const _SC_BC_STRING_MAX: ::c_int = 39;
+pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40;
+pub const _SC_EXPR_NEST_MAX: ::c_int = 42;
+pub const _SC_LINE_MAX: ::c_int = 43;
+pub const _SC_RE_DUP_MAX: ::c_int = 44;
+pub const _SC_2_VERSION: ::c_int = 46;
+pub const _SC_2_C_BIND: ::c_int = 47;
+pub const _SC_2_C_DEV: ::c_int = 48;
+pub const _SC_2_FORT_DEV: ::c_int = 49;
+pub const _SC_2_FORT_RUN: ::c_int = 50;
+pub const _SC_2_SW_DEV: ::c_int = 51;
+pub const _SC_2_LOCALEDEF: ::c_int = 52;
+pub const _SC_UIO_MAXIOV: ::c_int = 60;
+pub const _SC_IOV_MAX: ::c_int = 60;
+pub const _SC_THREADS: ::c_int = 67;
+pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68;
+pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69;
+pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70;
+pub const _SC_LOGIN_NAME_MAX: ::c_int = 71;
+pub const _SC_TTY_NAME_MAX: ::c_int = 72;
+pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73;
+pub const _SC_THREAD_KEYS_MAX: ::c_int = 74;
+pub const _SC_THREAD_STACK_MIN: ::c_int = 75;
+pub const _SC_THREAD_THREADS_MAX: ::c_int = 76;
+pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77;
+pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78;
+pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79;
+pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80;
+pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81;
+pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82;
+pub const _SC_NPROCESSORS_CONF: ::c_int = 83;
+pub const _SC_NPROCESSORS_ONLN: ::c_int = 84;
+pub const _SC_PHYS_PAGES: ::c_int = 85;
+pub const _SC_AVPHYS_PAGES: ::c_int = 86;
+pub const _SC_ATEXIT_MAX: ::c_int = 87;
+pub const _SC_PASS_MAX: ::c_int = 88;
+pub const _SC_XOPEN_VERSION: ::c_int = 89;
+pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90;
+pub const _SC_XOPEN_UNIX: ::c_int = 91;
+pub const _SC_XOPEN_CRYPT: ::c_int = 92;
+pub const _SC_XOPEN_ENH_I18N: ::c_int = 93;
+pub const _SC_XOPEN_SHM: ::c_int = 94;
+pub const _SC_2_CHAR_TERM: ::c_int = 95;
+pub const _SC_2_UPE: ::c_int = 97;
+pub const _SC_XOPEN_XPG2: ::c_int = 98;
+pub const _SC_XOPEN_XPG3: ::c_int = 99;
+pub const _SC_XOPEN_XPG4: ::c_int = 100;
+pub const _SC_NZERO: ::c_int = 109;
+pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125;
+pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126;
+pub const _SC_XBS5_LP64_OFF64: ::c_int = 127;
+pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128;
+pub const _SC_XOPEN_LEGACY: ::c_int = 129;
+pub const _SC_XOPEN_REALTIME: ::c_int = 130;
+pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131;
+pub const _SC_ADVISORY_INFO: ::c_int = 132;
+pub const _SC_BARRIERS: ::c_int = 133;
+pub const _SC_CLOCK_SELECTION: ::c_int = 137;
+pub const _SC_CPUTIME: ::c_int = 138;
+pub const _SC_THREAD_CPUTIME: ::c_int = 139;
+pub const _SC_MONOTONIC_CLOCK: ::c_int = 149;
+pub const _SC_READER_WRITER_LOCKS: ::c_int = 153;
+pub const _SC_SPIN_LOCKS: ::c_int = 154;
+pub const _SC_REGEXP: ::c_int = 155;
+pub const _SC_SHELL: ::c_int = 157;
+pub const _SC_SPAWN: ::c_int = 159;
+pub const _SC_SPORADIC_SERVER: ::c_int = 160;
+pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161;
+pub const _SC_TIMEOUTS: ::c_int = 164;
+pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165;
+pub const _SC_2_PBS: ::c_int = 168;
+pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169;
+pub const _SC_2_PBS_LOCATE: ::c_int = 170;
+pub const _SC_2_PBS_MESSAGE: ::c_int = 171;
+pub const _SC_2_PBS_TRACK: ::c_int = 172;
+pub const _SC_SYMLOOP_MAX: ::c_int = 173;
+pub const _SC_STREAMS: ::c_int = 174;
+pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175;
+pub const _SC_V6_ILP32_OFF32: ::c_int = 176;
+pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177;
+pub const _SC_V6_LP64_OFF64: ::c_int = 178;
+pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179;
+pub const _SC_HOST_NAME_MAX: ::c_int = 180;
+pub const _SC_TRACE: ::c_int = 181;
+pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182;
+pub const _SC_TRACE_INHERIT: ::c_int = 183;
+pub const _SC_TRACE_LOG: ::c_int = 184;
+pub const _SC_IPV6: ::c_int = 235;
+pub const _SC_RAW_SOCKETS: ::c_int = 236;
+pub const _SC_V7_ILP32_OFF32: ::c_int = 237;
+pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238;
+pub const _SC_V7_LP64_OFF64: ::c_int = 239;
+pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240;
+pub const _SC_SS_REPL_MAX: ::c_int = 241;
+pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242;
+pub const _SC_TRACE_NAME_MAX: ::c_int = 243;
+pub const _SC_TRACE_SYS_MAX: ::c_int = 244;
+pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245;
+pub const _SC_XOPEN_STREAMS: ::c_int = 246;
+pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247;
+pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248;
+
+pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY;
+pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY;
+
+pub const GLOB_ERR: ::c_int = 1 << 0;
+pub const GLOB_MARK: ::c_int = 1 << 1;
+pub const GLOB_NOSORT: ::c_int = 1 << 2;
+pub const GLOB_DOOFFS: ::c_int = 1 << 3;
+pub const GLOB_NOCHECK: ::c_int = 1 << 4;
+pub const GLOB_APPEND: ::c_int = 1 << 5;
+pub const GLOB_NOESCAPE: ::c_int = 1 << 6;
+
+pub const GLOB_NOSPACE: ::c_int = 1;
+pub const GLOB_ABORTED: ::c_int = 2;
+pub const GLOB_NOMATCH: ::c_int = 3;
+
+pub const POSIX_MADV_NORMAL: ::c_int = 0;
+pub const POSIX_MADV_RANDOM: ::c_int = 1;
+pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2;
+pub const POSIX_MADV_WILLNEED: ::c_int = 3;
+
+pub const S_IEXEC: mode_t = 64;
+pub const S_IWRITE: mode_t = 128;
+pub const S_IREAD: mode_t = 256;
+
+pub const F_LOCK: ::c_int = 1;
+pub const F_TEST: ::c_int = 3;
+pub const F_TLOCK: ::c_int = 2;
+pub const F_ULOCK: ::c_int = 0;
+
+pub const IFF_LOWER_UP: ::c_int = 0x10000;
+pub const IFF_DORMANT: ::c_int = 0x20000;
+pub const IFF_ECHO: ::c_int = 0x40000;
+
+pub const ST_RDONLY: ::c_ulong = 1;
+pub const ST_NOSUID: ::c_ulong = 2;
+pub const ST_NODEV: ::c_ulong = 4;
+pub const ST_NOEXEC: ::c_ulong = 8;
+pub const ST_SYNCHRONOUS: ::c_ulong = 16;
+pub const ST_MANDLOCK: ::c_ulong = 64;
+pub const ST_WRITE: ::c_ulong = 128;
+pub const ST_APPEND: ::c_ulong = 256;
+pub const ST_IMMUTABLE: ::c_ulong = 512;
+pub const ST_NOATIME: ::c_ulong = 1024;
+pub const ST_NODIRATIME: ::c_ulong = 2048;
+
+pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void;
+pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
+pub const RTLD_NODELETE: ::c_int = 0x1000;
+pub const RTLD_NOW: ::c_int = 0x2;
+
+pub const TCP_MD5SIG: ::c_int = 14;
+
+align_const! {
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        size: [0; __SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
+pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
+pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
+pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
+pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL;
+pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0;
+pub const PTHREAD_PROCESS_SHARED: ::c_int = 1;
+pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
+
+pub const RENAME_NOREPLACE: ::c_int = 1;
+pub const RENAME_EXCHANGE: ::c_int = 2;
+pub const RENAME_WHITEOUT: ::c_int = 4;
+
+pub const SCHED_OTHER: ::c_int = 0;
+pub const SCHED_FIFO: ::c_int = 1;
+pub const SCHED_RR: ::c_int = 2;
+pub const SCHED_BATCH: ::c_int = 3;
+pub const SCHED_IDLE: ::c_int = 5;
+
+// netinet/in.h
+// NOTE: These are in addition to the constants defined in src/unix/mod.rs
+
+// IPPROTO_IP defined in src/unix/mod.rs
+/// Hop-by-hop option header
+pub const IPPROTO_HOPOPTS: ::c_int = 0;
+// IPPROTO_ICMP defined in src/unix/mod.rs
+/// group mgmt protocol
+pub const IPPROTO_IGMP: ::c_int = 2;
+/// for compatibility
+pub const IPPROTO_IPIP: ::c_int = 4;
+// IPPROTO_TCP defined in src/unix/mod.rs
+/// exterior gateway protocol
+pub const IPPROTO_EGP: ::c_int = 8;
+/// pup
+pub const IPPROTO_PUP: ::c_int = 12;
+// IPPROTO_UDP defined in src/unix/mod.rs
+/// xns idp
+pub const IPPROTO_IDP: ::c_int = 22;
+/// tp-4 w/ class negotiation
+pub const IPPROTO_TP: ::c_int = 29;
+/// DCCP
+pub const IPPROTO_DCCP: ::c_int = 33;
+// IPPROTO_IPV6 defined in src/unix/mod.rs
+/// IP6 routing header
+pub const IPPROTO_ROUTING: ::c_int = 43;
+/// IP6 fragmentation header
+pub const IPPROTO_FRAGMENT: ::c_int = 44;
+/// resource reservation
+pub const IPPROTO_RSVP: ::c_int = 46;
+/// General Routing Encap.
+pub const IPPROTO_GRE: ::c_int = 47;
+/// IP6 Encap Sec. Payload
+pub const IPPROTO_ESP: ::c_int = 50;
+/// IP6 Auth Header
+pub const IPPROTO_AH: ::c_int = 51;
+// IPPROTO_ICMPV6 defined in src/unix/mod.rs
+/// IP6 no next header
+pub const IPPROTO_NONE: ::c_int = 59;
+/// IP6 destination option
+pub const IPPROTO_DSTOPTS: ::c_int = 60;
+pub const IPPROTO_MTP: ::c_int = 92;
+pub const IPPROTO_BEETPH: ::c_int = 94;
+/// encapsulation header
+pub const IPPROTO_ENCAP: ::c_int = 98;
+/// Protocol indep. multicast
+pub const IPPROTO_PIM: ::c_int = 103;
+/// IP Payload Comp. Protocol
+pub const IPPROTO_COMP: ::c_int = 108;
+/// SCTP
+pub const IPPROTO_SCTP: ::c_int = 132;
+pub const IPPROTO_MH: ::c_int = 135;
+pub const IPPROTO_UDPLITE: ::c_int = 136;
+pub const IPPROTO_MPLS: ::c_int = 137;
+/// raw IP packet
+pub const IPPROTO_RAW: ::c_int = 255;
+pub const IPPROTO_MAX: ::c_int = 256;
+
+pub const AF_IB: ::c_int = 27;
+pub const AF_MPLS: ::c_int = 28;
+pub const AF_NFC: ::c_int = 39;
+pub const AF_VSOCK: ::c_int = 40;
+pub const PF_IB: ::c_int = AF_IB;
+pub const PF_MPLS: ::c_int = AF_MPLS;
+pub const PF_NFC: ::c_int = AF_NFC;
+pub const PF_VSOCK: ::c_int = AF_VSOCK;
+
+// System V IPC
+pub const IPC_PRIVATE: ::key_t = 0;
+
+pub const IPC_CREAT: ::c_int = 0o1000;
+pub const IPC_EXCL: ::c_int = 0o2000;
+pub const IPC_NOWAIT: ::c_int = 0o4000;
+
+pub const IPC_RMID: ::c_int = 0;
+pub const IPC_SET: ::c_int = 1;
+pub const IPC_STAT: ::c_int = 2;
+pub const IPC_INFO: ::c_int = 3;
+pub const MSG_STAT: ::c_int = 11;
+pub const MSG_INFO: ::c_int = 12;
+
+pub const MSG_NOERROR: ::c_int = 0o10000;
+pub const MSG_EXCEPT: ::c_int = 0o20000;
+pub const MSG_COPY: ::c_int = 0o40000;
+
+pub const SHM_R: ::c_int = 0o400;
+pub const SHM_W: ::c_int = 0o200;
+
+pub const SHM_RDONLY: ::c_int = 0o10000;
+pub const SHM_RND: ::c_int = 0o20000;
+pub const SHM_REMAP: ::c_int = 0o40000;
+pub const SHM_EXEC: ::c_int = 0o100000;
+
+pub const SHM_LOCK: ::c_int = 11;
+pub const SHM_UNLOCK: ::c_int = 12;
+
+pub const SHM_HUGETLB: ::c_int = 0o4000;
+pub const SHM_NORESERVE: ::c_int = 0o10000;
+
+pub const EPOLLRDHUP: ::c_int = 0x2000;
+pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000;
+pub const EPOLLONESHOT: ::c_int = 0x40000000;
+
+pub const QFMT_VFS_OLD: ::c_int = 1;
+pub const QFMT_VFS_V0: ::c_int = 2;
+pub const QFMT_VFS_V1: ::c_int = 4;
+
+pub const EFD_SEMAPHORE: ::c_int = 0x1;
+
+pub const LOG_NFACILITIES: ::c_int = 24;
+
+pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t;
+
+pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32;
+pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32;
+pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32;
+pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32;
+pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 as i32;
+pub const RB_SW_SUSPEND: ::c_int = 0xd000fce2u32 as i32;
+pub const RB_KEXEC: ::c_int = 0x45584543u32 as i32;
+
+pub const AI_PASSIVE: ::c_int = 0x0001;
+pub const AI_CANONNAME: ::c_int = 0x0002;
+pub const AI_NUMERICHOST: ::c_int = 0x0004;
+pub const AI_V4MAPPED: ::c_int = 0x0008;
+pub const AI_ALL: ::c_int = 0x0010;
+pub const AI_ADDRCONFIG: ::c_int = 0x0020;
+
+pub const AI_NUMERICSERV: ::c_int = 0x0400;
+
+pub const EAI_BADFLAGS: ::c_int = -1;
+pub const EAI_NONAME: ::c_int = -2;
+pub const EAI_AGAIN: ::c_int = -3;
+pub const EAI_FAIL: ::c_int = -4;
+pub const EAI_FAMILY: ::c_int = -6;
+pub const EAI_SOCKTYPE: ::c_int = -7;
+pub const EAI_SERVICE: ::c_int = -8;
+pub const EAI_MEMORY: ::c_int = -10;
+pub const EAI_OVERFLOW: ::c_int = -12;
+
+pub const NI_NUMERICHOST: ::c_int = 1;
+pub const NI_NUMERICSERV: ::c_int = 2;
+pub const NI_NOFQDN: ::c_int = 4;
+pub const NI_NAMEREQD: ::c_int = 8;
+pub const NI_DGRAM: ::c_int = 16;
+
+pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1;
+pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2;
+pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4;
+
+pub const EAI_SYSTEM: ::c_int = -11;
+
+pub const AIO_CANCELED: ::c_int = 0;
+pub const AIO_NOTCANCELED: ::c_int = 1;
+pub const AIO_ALLDONE: ::c_int = 2;
+pub const LIO_READ: ::c_int = 0;
+pub const LIO_WRITE: ::c_int = 1;
+pub const LIO_NOP: ::c_int = 2;
+pub const LIO_WAIT: ::c_int = 0;
+pub const LIO_NOWAIT: ::c_int = 1;
+
+pub const MREMAP_MAYMOVE: ::c_int = 1;
+pub const MREMAP_FIXED: ::c_int = 2;
+
+pub const PR_SET_PDEATHSIG: ::c_int = 1;
+pub const PR_GET_PDEATHSIG: ::c_int = 2;
+
+pub const PR_GET_DUMPABLE: ::c_int = 3;
+pub const PR_SET_DUMPABLE: ::c_int = 4;
+
+pub const PR_GET_UNALIGN: ::c_int = 5;
+pub const PR_SET_UNALIGN: ::c_int = 6;
+pub const PR_UNALIGN_NOPRINT: ::c_int = 1;
+pub const PR_UNALIGN_SIGBUS: ::c_int = 2;
+
+pub const PR_GET_KEEPCAPS: ::c_int = 7;
+pub const PR_SET_KEEPCAPS: ::c_int = 8;
+
+pub const PR_GET_FPEMU: ::c_int = 9;
+pub const PR_SET_FPEMU: ::c_int = 10;
+pub const PR_FPEMU_NOPRINT: ::c_int = 1;
+pub const PR_FPEMU_SIGFPE: ::c_int = 2;
+
+pub const PR_GET_FPEXC: ::c_int = 11;
+pub const PR_SET_FPEXC: ::c_int = 12;
+pub const PR_FP_EXC_SW_ENABLE: ::c_int = 0x80;
+pub const PR_FP_EXC_DIV: ::c_int = 0x010000;
+pub const PR_FP_EXC_OVF: ::c_int = 0x020000;
+pub const PR_FP_EXC_UND: ::c_int = 0x040000;
+pub const PR_FP_EXC_RES: ::c_int = 0x080000;
+pub const PR_FP_EXC_INV: ::c_int = 0x100000;
+pub const PR_FP_EXC_DISABLED: ::c_int = 0;
+pub const PR_FP_EXC_NONRECOV: ::c_int = 1;
+pub const PR_FP_EXC_ASYNC: ::c_int = 2;
+pub const PR_FP_EXC_PRECISE: ::c_int = 3;
+
+pub const PR_GET_TIMING: ::c_int = 13;
+pub const PR_SET_TIMING: ::c_int = 14;
+pub const PR_TIMING_STATISTICAL: ::c_int = 0;
+pub const PR_TIMING_TIMESTAMP: ::c_int = 1;
+
+pub const PR_SET_NAME: ::c_int = 15;
+pub const PR_GET_NAME: ::c_int = 16;
+
+pub const PR_GET_ENDIAN: ::c_int = 19;
+pub const PR_SET_ENDIAN: ::c_int = 20;
+pub const PR_ENDIAN_BIG: ::c_int = 0;
+pub const PR_ENDIAN_LITTLE: ::c_int = 1;
+pub const PR_ENDIAN_PPC_LITTLE: ::c_int = 2;
+
+pub const PR_GET_SECCOMP: ::c_int = 21;
+pub const PR_SET_SECCOMP: ::c_int = 22;
+
+pub const PR_CAPBSET_READ: ::c_int = 23;
+pub const PR_CAPBSET_DROP: ::c_int = 24;
+
+pub const PR_GET_TSC: ::c_int = 25;
+pub const PR_SET_TSC: ::c_int = 26;
+pub const PR_TSC_ENABLE: ::c_int = 1;
+pub const PR_TSC_SIGSEGV: ::c_int = 2;
+
+pub const PR_GET_SECUREBITS: ::c_int = 27;
+pub const PR_SET_SECUREBITS: ::c_int = 28;
+
+pub const PR_SET_TIMERSLACK: ::c_int = 29;
+pub const PR_GET_TIMERSLACK: ::c_int = 30;
+
+pub const PR_TASK_PERF_EVENTS_DISABLE: ::c_int = 31;
+pub const PR_TASK_PERF_EVENTS_ENABLE: ::c_int = 32;
+
+pub const PR_MCE_KILL: ::c_int = 33;
+pub const PR_MCE_KILL_CLEAR: ::c_int = 0;
+pub const PR_MCE_KILL_SET: ::c_int = 1;
+
+pub const PR_MCE_KILL_LATE: ::c_int = 0;
+pub const PR_MCE_KILL_EARLY: ::c_int = 1;
+pub const PR_MCE_KILL_DEFAULT: ::c_int = 2;
+
+pub const PR_MCE_KILL_GET: ::c_int = 34;
+
+pub const PR_SET_MM: ::c_int = 35;
+pub const PR_SET_MM_START_CODE: ::c_int = 1;
+pub const PR_SET_MM_END_CODE: ::c_int = 2;
+pub const PR_SET_MM_START_DATA: ::c_int = 3;
+pub const PR_SET_MM_END_DATA: ::c_int = 4;
+pub const PR_SET_MM_START_STACK: ::c_int = 5;
+pub const PR_SET_MM_START_BRK: ::c_int = 6;
+pub const PR_SET_MM_BRK: ::c_int = 7;
+pub const PR_SET_MM_ARG_START: ::c_int = 8;
+pub const PR_SET_MM_ARG_END: ::c_int = 9;
+pub const PR_SET_MM_ENV_START: ::c_int = 10;
+pub const PR_SET_MM_ENV_END: ::c_int = 11;
+pub const PR_SET_MM_AUXV: ::c_int = 12;
+pub const PR_SET_MM_EXE_FILE: ::c_int = 13;
+pub const PR_SET_MM_MAP: ::c_int = 14;
+pub const PR_SET_MM_MAP_SIZE: ::c_int = 15;
+
+pub const PR_SET_PTRACER: ::c_int = 0x59616d61;
+
+pub const PR_SET_CHILD_SUBREAPER: ::c_int = 36;
+pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37;
+
+pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38;
+pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39;
+
+pub const PR_GET_TID_ADDRESS: ::c_int = 40;
+
+pub const PR_SET_THP_DISABLE: ::c_int = 41;
+pub const PR_GET_THP_DISABLE: ::c_int = 42;
+
+pub const PR_MPX_ENABLE_MANAGEMENT: ::c_int = 43;
+pub const PR_MPX_DISABLE_MANAGEMENT: ::c_int = 44;
+
+pub const PR_SET_FP_MODE: ::c_int = 45;
+pub const PR_GET_FP_MODE: ::c_int = 46;
+pub const PR_FP_MODE_FR: ::c_int = 1 << 0;
+pub const PR_FP_MODE_FRE: ::c_int = 1 << 1;
+
+pub const PR_CAP_AMBIENT: ::c_int = 47;
+pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1;
+pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2;
+pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3;
+pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4;
+
+pub const GRND_NONBLOCK: ::c_uint = 0x0001;
+pub const GRND_RANDOM: ::c_uint = 0x0002;
+
+pub const ITIMER_REAL: ::c_int = 0;
+pub const ITIMER_VIRTUAL: ::c_int = 1;
+pub const ITIMER_PROF: ::c_int = 2;
+
+pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC;
+pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK;
+pub const TFD_TIMER_ABSTIME: ::c_int = 1;
+
+pub const XATTR_CREATE: ::c_int = 0x1;
+pub const XATTR_REPLACE: ::c_int = 0x2;
+
+pub const _POSIX_VDISABLE: ::cc_t = 0;
+
+pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01;
+pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02;
+pub const FALLOC_FL_COLLAPSE_RANGE: ::c_int = 0x08;
+pub const FALLOC_FL_ZERO_RANGE: ::c_int = 0x10;
+pub const FALLOC_FL_INSERT_RANGE: ::c_int = 0x20;
+pub const FALLOC_FL_UNSHARE_RANGE: ::c_int = 0x40;
+
+// On Linux, libc doesn't define this constant, libattr does instead.
+// We still define it for Linux as it's defined by libc on other platforms,
+// and it's mentioned in the man pages for getxattr and setxattr.
+pub const ENOATTR: ::c_int = ::ENODATA;
+
+pub const SO_ORIGINAL_DST: ::c_int = 80;
+pub const IUTF8: ::tcflag_t = 0x00004000;
+pub const CMSPAR: ::tcflag_t = 0o10000000000;
+
+pub const MFD_CLOEXEC: ::c_uint = 0x0001;
+pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002;
+
+// these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has
+// the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32
+// so we can use that type here to avoid having to cast.
+pub const PT_NULL: u32 = 0;
+pub const PT_LOAD: u32 = 1;
+pub const PT_DYNAMIC: u32 = 2;
+pub const PT_INTERP: u32 = 3;
+pub const PT_NOTE: u32 = 4;
+pub const PT_SHLIB: u32 = 5;
+pub const PT_PHDR: u32 = 6;
+pub const PT_TLS: u32 = 7;
+pub const PT_NUM: u32 = 8;
+pub const PT_LOOS: u32 = 0x60000000;
+pub const PT_GNU_EH_FRAME: u32 = 0x6474e550;
+pub const PT_GNU_STACK: u32 = 0x6474e551;
+pub const PT_GNU_RELRO: u32 = 0x6474e552;
+
+pub const SFD_CLOEXEC: ::c_int = 0x080000;
+
+pub const NCCS: usize = 32;
+
+pub const O_TRUNC:   ::c_int = 0x00040000;
+pub const O_NOATIME: ::c_int = 0x00002000;
+pub const O_CLOEXEC: ::c_int = 0x00000100;
+pub const O_TMPFILE: ::c_int = 0x00004000;
+
+pub const EBFONT: ::c_int = 59;
+pub const ENOSTR: ::c_int = 60;
+pub const ENODATA: ::c_int = 61;
+pub const ETIME: ::c_int = 62;
+pub const ENOSR: ::c_int = 63;
+pub const ENONET: ::c_int = 64;
+pub const ENOPKG: ::c_int = 65;
+pub const EREMOTE: ::c_int = 66;
+pub const ENOLINK: ::c_int = 67;
+pub const EADV: ::c_int = 68;
+pub const ESRMNT: ::c_int = 69;
+pub const ECOMM: ::c_int = 70;
+pub const EPROTO: ::c_int = 71;
+pub const EDOTDOT: ::c_int = 73;
+
+pub const SA_NODEFER: ::c_int = 0x40000000;
+pub const SA_RESETHAND: ::c_int = 0x80000000;
+pub const SA_RESTART: ::c_int = 0x10000000;
+pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
+
+pub const EPOLL_CLOEXEC: ::c_int = 0x80000;
+
+pub const EFD_CLOEXEC: ::c_int = 0x80000;
+
+pub const BUFSIZ: ::c_uint = 1024;
+pub const TMP_MAX: ::c_uint = 10000;
+pub const FOPEN_MAX: ::c_uint = 1000;
+pub const O_PATH: ::c_int = 0x00400000;
+pub const O_EXEC: ::c_int = O_PATH;
+pub const O_SEARCH: ::c_int = O_PATH;
+pub const O_ACCMODE: ::c_int = (03 | O_SEARCH);
+pub const O_NDELAY: ::c_int = O_NONBLOCK;
+pub const NI_MAXHOST: ::socklen_t = 255;
+pub const PTHREAD_STACK_MIN: ::size_t = 2048;
+pub const POSIX_FADV_DONTNEED: ::c_int = 4;
+pub const POSIX_FADV_NOREUSE: ::c_int = 5;
+
+pub const POSIX_MADV_DONTNEED: ::c_int = 4;
+
+pub const RLIM_INFINITY: ::rlim_t = !0;
+pub const RLIMIT_RTTIME: ::c_int = 15;
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+
+pub const MAP_ANONYMOUS: ::c_int = MAP_ANON;
+
+pub const SOCK_DCCP: ::c_int = 6;
+pub const SOCK_PACKET: ::c_int = 10;
+
+pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15;
+pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16;
+pub const TCP_THIN_DUPACK: ::c_int = 17;
+pub const TCP_USER_TIMEOUT: ::c_int = 18;
+pub const TCP_REPAIR: ::c_int = 19;
+pub const TCP_REPAIR_QUEUE: ::c_int = 20;
+pub const TCP_QUEUE_SEQ: ::c_int = 21;
+pub const TCP_REPAIR_OPTIONS: ::c_int = 22;
+pub const TCP_FASTOPEN: ::c_int = 23;
+pub const TCP_TIMESTAMP: ::c_int = 24;
+
+pub const SIGUNUSED: ::c_int = ::SIGSYS;
+
+pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
+pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
+pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
+
+pub const CPU_SETSIZE: ::c_int = 128;
+
+pub const PTRACE_TRACEME: ::c_int = 0;
+pub const PTRACE_PEEKTEXT: ::c_int = 1;
+pub const PTRACE_PEEKDATA: ::c_int = 2;
+pub const PTRACE_PEEKUSER: ::c_int = 3;
+pub const PTRACE_POKETEXT: ::c_int = 4;
+pub const PTRACE_POKEDATA: ::c_int = 5;
+pub const PTRACE_POKEUSER: ::c_int = 6;
+pub const PTRACE_CONT: ::c_int = 7;
+pub const PTRACE_KILL: ::c_int = 8;
+pub const PTRACE_SINGLESTEP: ::c_int = 9;
+pub const PTRACE_GETREGS: ::c_int = 12;
+pub const PTRACE_SETREGS: ::c_int = 13;
+pub const PTRACE_GETFPREGS: ::c_int = 14;
+pub const PTRACE_SETFPREGS: ::c_int = 15;
+pub const PTRACE_ATTACH: ::c_int = 16;
+pub const PTRACE_DETACH: ::c_int = 17;
+pub const PTRACE_GETFPXREGS: ::c_int = 18;
+pub const PTRACE_SETFPXREGS: ::c_int = 19;
+pub const PTRACE_SYSCALL: ::c_int = 24;
+pub const PTRACE_SETOPTIONS: ::c_int = 0x4200;
+pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201;
+pub const PTRACE_GETSIGINFO: ::c_int = 0x4202;
+pub const PTRACE_SETSIGINFO: ::c_int = 0x4203;
+pub const PTRACE_GETREGSET: ::c_int = 0x4204;
+pub const PTRACE_SETREGSET: ::c_int = 0x4205;
+pub const PTRACE_SEIZE: ::c_int = 0x4206;
+pub const PTRACE_INTERRUPT: ::c_int = 0x4207;
+pub const PTRACE_LISTEN: ::c_int = 0x4208;
+pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209;
+
+pub const EPOLLWAKEUP: ::c_int = 0x20000000;
+
+pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK;
+
+pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK;
+
+pub const TCSANOW: ::c_int = 0;
+pub const TCSADRAIN: ::c_int = 1;
+pub const TCSAFLUSH: ::c_int = 2;
+
+pub const TIOCINQ: ::c_int = ::FIONREAD;
+
+pub const RTLD_GLOBAL: ::c_int = 0x100;
+pub const RTLD_NOLOAD: ::c_int = 0x4;
+
+// TODO(#247) Temporarily musl-specific (available since musl 0.9.12 / Linux
+// kernel 3.10).  See also notbsd/mod.rs
+pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;
+pub const CLOCK_TAI: ::clockid_t = 11;
+
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+
+pub const B0: ::speed_t = 0o000000;
+pub const B50: ::speed_t = 0o000001;
+pub const B75: ::speed_t = 0o000002;
+pub const B110: ::speed_t = 0o000003;
+pub const B134: ::speed_t = 0o000004;
+pub const B150: ::speed_t = 0o000005;
+pub const B200: ::speed_t = 0o000006;
+pub const B300: ::speed_t = 0o000007;
+pub const B600: ::speed_t = 0o000010;
+pub const B1200: ::speed_t = 0o000011;
+pub const B1800: ::speed_t = 0o000012;
+pub const B2400: ::speed_t = 0o000013;
+pub const B4800: ::speed_t = 0o000014;
+pub const B9600: ::speed_t = 0o000015;
+pub const B19200: ::speed_t = 0o000016;
+pub const B38400: ::speed_t = 0o000017;
+pub const EXTA: ::speed_t = B19200;
+pub const EXTB: ::speed_t = B38400;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
+
+pub const SO_BINDTODEVICE: ::c_int = 25;
+pub const SO_TIMESTAMP: ::c_int = 29;
+pub const SO_MARK: ::c_int = 36;
+pub const SO_RXQ_OVFL: ::c_int = 40;
+pub const SO_PEEK_OFF: ::c_int = 42;
+pub const SO_BUSY_POLL: ::c_int = 46;
+
+pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
+pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
+
+pub const O_ASYNC: ::c_int = 0x00000400;
+
+pub const FIOCLEX: ::c_int = 0x5451;
+pub const FIONBIO: ::c_int = 0x5421;
+
+pub const RLIMIT_RSS: ::c_int = 5;
+pub const RLIMIT_NOFILE: ::c_int = 7;
+pub const RLIMIT_AS: ::c_int = 9;
+pub const RLIMIT_NPROC: ::c_int = 6;
+pub const RLIMIT_MEMLOCK: ::c_int = 8;
+
+pub const O_APPEND: ::c_int = 0x00100000;
+pub const O_CREAT:  ::c_int = 0x00010000;
+pub const O_EXCL:   ::c_int = 0x00020000;
+pub const O_NOCTTY: ::c_int = 0x00000200;
+pub const O_NONBLOCK: ::c_int = 0x00000010;
+pub const O_SYNC:   ::c_int = (0x00000040 | O_DSYNC);
+pub const O_RSYNC:  ::c_int = O_SYNC;
+pub const O_DSYNC:  ::c_int = 0x00000020;
+
+pub const SOCK_NONBLOCK: ::c_int = 2048;
+
+pub const MAP_ANON: ::c_int = 0x0020;
+pub const MAP_GROWSDOWN: ::c_int = 0x0100;
+pub const MAP_DENYWRITE: ::c_int = 0x0800;
+pub const MAP_EXECUTABLE: ::c_int = 0x01000;
+pub const MAP_LOCKED: ::c_int = 0x02000;
+pub const MAP_NORESERVE: ::c_int = 0x04000;
+pub const MAP_POPULATE: ::c_int = 0x08000;
+pub const MAP_NONBLOCK: ::c_int = 0x010000;
+pub const MAP_STACK: ::c_int = 0x020000;
+
+pub const SOCK_STREAM: ::c_int = 1;
+pub const SOCK_DGRAM: ::c_int = 2;
+pub const SOCK_SEQPACKET: ::c_int = 5;
+
+pub const SOL_SOCKET: ::c_int = 1;
+
+pub const EDEADLK: ::c_int = 35;
+pub const ENAMETOOLONG: ::c_int = 36;
+pub const ENOLCK: ::c_int = 37;
+pub const ENOSYS: ::c_int = 38;
+pub const ENOTEMPTY: ::c_int = 39;
+pub const ELOOP: ::c_int = 40;
+pub const ENOMSG: ::c_int = 42;
+pub const EIDRM: ::c_int = 43;
+pub const ECHRNG: ::c_int = 44;
+pub const EL2NSYNC: ::c_int = 45;
+pub const EL3HLT: ::c_int = 46;
+pub const EL3RST: ::c_int = 47;
+pub const ELNRNG: ::c_int = 48;
+pub const EUNATCH: ::c_int = 49;
+pub const ENOCSI: ::c_int = 50;
+pub const EL2HLT: ::c_int = 51;
+pub const EBADE: ::c_int = 52;
+pub const EBADR: ::c_int = 53;
+pub const EXFULL: ::c_int = 54;
+pub const ENOANO: ::c_int = 55;
+pub const EBADRQC: ::c_int = 56;
+pub const EBADSLT: ::c_int = 57;
+pub const EDEADLOCK: ::c_int = EDEADLK;
+pub const EMULTIHOP: ::c_int = 72;
+pub const EBADMSG: ::c_int = 74;
+pub const EOVERFLOW: ::c_int = 75;
+pub const ENOTUNIQ: ::c_int = 76;
+pub const EBADFD: ::c_int = 77;
+pub const EREMCHG: ::c_int = 78;
+pub const ELIBACC: ::c_int = 79;
+pub const ELIBBAD: ::c_int = 80;
+pub const ELIBSCN: ::c_int = 81;
+pub const ELIBMAX: ::c_int = 82;
+pub const ELIBEXEC: ::c_int = 83;
+pub const EILSEQ: ::c_int = 84;
+pub const ERESTART: ::c_int = 85;
+pub const ESTRPIPE: ::c_int = 86;
+pub const EUSERS: ::c_int = 87;
+pub const ENOTSOCK: ::c_int = 88;
+pub const EDESTADDRREQ: ::c_int = 89;
+pub const EMSGSIZE: ::c_int = 90;
+pub const EPROTOTYPE: ::c_int = 91;
+pub const ENOPROTOOPT: ::c_int = 92;
+pub const EPROTONOSUPPORT: ::c_int = 93;
+pub const ESOCKTNOSUPPORT: ::c_int = 94;
+pub const EOPNOTSUPP: ::c_int = 95;
+pub const ENOTSUP: ::c_int = EOPNOTSUPP;
+pub const EPFNOSUPPORT: ::c_int = 96;
+pub const EAFNOSUPPORT: ::c_int = 97;
+pub const EADDRINUSE: ::c_int = 98;
+pub const EADDRNOTAVAIL: ::c_int = 99;
+pub const ENETDOWN: ::c_int = 100;
+pub const ENETUNREACH: ::c_int = 101;
+pub const ENETRESET: ::c_int = 102;
+pub const ECONNABORTED: ::c_int = 103;
+pub const ECONNRESET: ::c_int = 104;
+pub const ENOBUFS: ::c_int = 105;
+pub const EISCONN: ::c_int = 106;
+pub const ENOTCONN: ::c_int = 107;
+pub const ESHUTDOWN: ::c_int = 108;
+pub const ETOOMANYREFS: ::c_int = 109;
+pub const ETIMEDOUT: ::c_int = 110;
+pub const ECONNREFUSED: ::c_int = 111;
+pub const EHOSTDOWN: ::c_int = 112;
+pub const EHOSTUNREACH: ::c_int = 113;
+pub const EALREADY: ::c_int = 114;
+pub const EINPROGRESS: ::c_int = 115;
+pub const ESTALE: ::c_int = 116;
+pub const EUCLEAN: ::c_int = 117;
+pub const ENOTNAM: ::c_int = 118;
+pub const ENAVAIL: ::c_int = 119;
+pub const EISNAM: ::c_int = 120;
+pub const EREMOTEIO: ::c_int = 121;
+pub const EDQUOT: ::c_int = 122;
+pub const ENOMEDIUM: ::c_int = 123;
+pub const EMEDIUMTYPE: ::c_int = 124;
+pub const ECANCELED: ::c_int = 125;
+pub const ENOKEY: ::c_int = 126;
+pub const EKEYEXPIRED: ::c_int = 127;
+pub const EKEYREVOKED: ::c_int = 128;
+pub const EKEYREJECTED: ::c_int = 129;
+pub const EOWNERDEAD: ::c_int = 130;
+pub const ENOTRECOVERABLE: ::c_int = 131;
+pub const ERFKILL: ::c_int = 132;
+pub const EHWPOISON: ::c_int = 133;
+
+pub const SO_REUSEADDR: ::c_int = 2;
+pub const SO_TYPE: ::c_int = 3;
+pub const SO_ERROR: ::c_int = 4;
+pub const SO_DONTROUTE: ::c_int = 5;
+pub const SO_BROADCAST: ::c_int = 6;
+pub const SO_SNDBUF: ::c_int = 7;
+pub const SO_RCVBUF: ::c_int = 8;
+pub const SO_KEEPALIVE: ::c_int = 9;
+pub const SO_OOBINLINE: ::c_int = 10;
+pub const SO_NO_CHECK: ::c_int = 11;
+pub const SO_PRIORITY: ::c_int = 12;
+pub const SO_LINGER: ::c_int = 13;
+pub const SO_BSDCOMPAT: ::c_int = 14;
+pub const SO_REUSEPORT: ::c_int = 15;
+pub const SO_PASSCRED: ::c_int = 16;
+pub const SO_PEERCRED: ::c_int = 17;
+pub const SO_RCVLOWAT: ::c_int = 18;
+pub const SO_SNDLOWAT: ::c_int = 19;
+pub const SO_RCVTIMEO: ::c_int = 20;
+pub const SO_SNDTIMEO: ::c_int = 21;
+pub const SO_ACCEPTCONN: ::c_int = 30;
+pub const SO_SNDBUFFORCE: ::c_int = 32;
+pub const SO_RCVBUFFORCE: ::c_int = 33;
+pub const SO_PROTOCOL: ::c_int = 38;
+pub const SO_DOMAIN: ::c_int = 39;
+
+pub const SA_ONSTACK: ::c_int = 0x08000000;
+pub const SA_SIGINFO: ::c_int = 0x00000004;
+pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
+
+pub const SIGCHLD: ::c_int = 17;
+pub const SIGBUS: ::c_int = 7;
+pub const SIGTTIN: ::c_int = 21;
+pub const SIGTTOU: ::c_int = 22;
+pub const SIGXCPU: ::c_int = 24;
+pub const SIGXFSZ: ::c_int = 25;
+pub const SIGVTALRM: ::c_int = 26;
+pub const SIGPROF: ::c_int = 27;
+pub const SIGWINCH: ::c_int = 28;
+pub const SIGUSR1: ::c_int = 10;
+pub const SIGUSR2: ::c_int = 12;
+pub const SIGCONT: ::c_int = 18;
+pub const SIGSTOP: ::c_int = 19;
+pub const SIGTSTP: ::c_int = 20;
+pub const SIGURG: ::c_int = 23;
+pub const SIGIO: ::c_int = 29;
+pub const SIGSYS: ::c_int = 31;
+pub const SIGSTKFLT: ::c_int = 16;
+pub const SIGPOLL: ::c_int = 29;
+pub const SIGPWR: ::c_int = 30;
+pub const SIG_SETMASK: ::c_int = 2;
+pub const SIG_BLOCK: ::c_int = 0x000000;
+pub const SIG_UNBLOCK: ::c_int = 0x01;
+
+pub const EXTPROC: ::tcflag_t = 0x00010000;
+
+pub const MAP_HUGETLB: ::c_int = 0x040000;
+
+pub const F_GETLK: ::c_int = 5;
+pub const F_GETOWN: ::c_int = 9;
+pub const F_SETLK: ::c_int = 6;
+pub const F_SETLKW: ::c_int = 7;
+pub const F_SETOWN: ::c_int = 8;
+
+pub const VEOF: usize = 4;
+pub const VEOL: usize = 11;
+pub const VEOL2: usize = 16;
+pub const VMIN: usize = 6;
+pub const IEXTEN: ::tcflag_t = 0x00008000;
+pub const TOSTOP: ::tcflag_t = 0x00000100;
+pub const FLUSHO: ::tcflag_t = 0x00001000;
+
+pub const TCGETS: ::c_int = 0x5401;
+pub const TCSETS: ::c_int = 0x5402;
+pub const TCSETSW: ::c_int = 0x5403;
+pub const TCSETSF: ::c_int = 0x5404;
+pub const TCGETA: ::c_int = 0x5405;
+pub const TCSETA: ::c_int = 0x5406;
+pub const TCSETAW: ::c_int = 0x5407;
+pub const TCSETAF: ::c_int = 0x5408;
+pub const TCSBRK: ::c_int = 0x5409;
+pub const TCXONC: ::c_int = 0x540A;
+pub const TCFLSH: ::c_int = 0x540B;
+pub const TIOCGSOFTCAR: ::c_int = 0x5419;
+pub const TIOCSSOFTCAR: ::c_int = 0x541A;
+pub const TIOCLINUX: ::c_int = 0x541C;
+pub const TIOCGSERIAL: ::c_int = 0x541E;
+pub const TIOCEXCL: ::c_int = 0x540C;
+pub const TIOCNXCL: ::c_int = 0x540D;
+pub const TIOCSCTTY: ::c_int = 0x540E;
+pub const TIOCGPGRP: ::c_int = 0x540F;
+pub const TIOCSPGRP: ::c_int = 0x5410;
+pub const TIOCOUTQ: ::c_int = 0x5411;
+pub const TIOCSTI: ::c_int = 0x5412;
+pub const TIOCGWINSZ: ::c_int = 0x5413;
+pub const TIOCSWINSZ: ::c_int = 0x5414;
+pub const TIOCMGET: ::c_int = 0x5415;
+pub const TIOCMBIS: ::c_int = 0x5416;
+pub const TIOCMBIC: ::c_int = 0x5417;
+pub const TIOCMSET: ::c_int = 0x5418;
+pub const FIONREAD: ::c_int = 0x541B;
+pub const TIOCCONS: ::c_int = 0x541D;
+
+pub const POLLWRNORM: ::c_short = 0x100;
+pub const POLLWRBAND: ::c_short = 0x200;
+
+pub const TIOCM_LE: ::c_int = 0x001;
+pub const TIOCM_DTR: ::c_int = 0x002;
+pub const TIOCM_RTS: ::c_int = 0x004;
+pub const TIOCM_ST: ::c_int = 0x008;
+pub const TIOCM_SR: ::c_int = 0x010;
+pub const TIOCM_CTS: ::c_int = 0x020;
+pub const TIOCM_CAR: ::c_int = 0x040;
+pub const TIOCM_RNG: ::c_int = 0x080;
+pub const TIOCM_DSR: ::c_int = 0x100;
+pub const TIOCM_CD: ::c_int = TIOCM_CAR;
+pub const TIOCM_RI: ::c_int = TIOCM_RNG;
+
+pub const O_DIRECTORY: ::c_int = 0x00080000;
+pub const O_DIRECT:    ::c_int = 0x00000800;
+pub const O_LARGEFILE: ::c_int = 0x00001000;
+pub const O_NOFOLLOW:  ::c_int = 0x00000080;
+
+// intentionally not public, only used for fd_set
+cfg_if! {
+    if #[cfg(target_pointer_width = "32")] {
+        const ULONG_SIZE: usize = 32;
+    } else if #[cfg(target_pointer_width = "64")] {
+        const ULONG_SIZE: usize = 64;
+    } else {
+        // Unknown target_pointer_width
+    }
+}
+
+// END_PUB_CONST
+
+f! {
+    pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
+        (*set).fds_bits[fd / size] &= !(1 << (fd % size));
+        return
+    }
+
+    pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
+        return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0
+    }
+
+    pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
+        (*set).fds_bits[fd / size] |= 1 << (fd % size);
+        return
+    }
+
+    pub fn FD_ZERO(set: *mut fd_set) -> () {
+        for slot in (*set).fds_bits.iter_mut() {
+            *slot = 0;
+        }
+    }
+
+    pub fn WIFSTOPPED(status: ::c_int) -> bool {
+        (status & 0xff) == 0x7f
+    }
+
+    pub fn WSTOPSIG(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
+
+    pub fn WIFCONTINUED(status: ::c_int) -> bool {
+        status == 0xffff
+    }
+
+    pub fn WIFSIGNALED(status: ::c_int) -> bool {
+        ((status & 0x7f) + 1) as i8 >= 2
+    }
+
+    pub fn WTERMSIG(status: ::c_int) -> ::c_int {
+        status & 0x7f
+    }
+
+    pub fn WIFEXITED(status: ::c_int) -> bool {
+        (status & 0x7f) == 0
+    }
+
+    pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
+
+    pub fn WCOREDUMP(status: ::c_int) -> bool {
+        (status & 0x80) != 0
+    }
+
+    pub fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int {
+        (cmd << 8) | (type_ & 0x00ff)
+    }
+
+    pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () {
+        for slot in cpuset.bits.iter_mut() {
+            *slot = 0;
+        }
+    }
+
+    pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () {
+        let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
+        let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+        cpuset.bits[idx] |= 1 << offset;
+        ()
+    }
+
+    pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () {
+        let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
+        let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+        cpuset.bits[idx] &= !(1 << offset);
+        ()
+    }
+
+    pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool {
+        let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]);
+        let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
+        0 != (cpuset.bits[idx] & (1 << offset))
+    }
+
+    pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool {
+        set1.bits == set2.bits
+    }
+
+    pub fn major(dev: ::dev_t) -> ::c_uint {
+        let mut major = 0;
+        major |= (dev & 0x00000000000fff00) >> 8;
+        major |= (dev & 0xfffff00000000000) >> 32;
+        major as ::c_uint
+    }
+
+    pub fn minor(dev: ::dev_t) -> ::c_uint {
+        let mut minor = 0;
+        minor |= (dev & 0x00000000000000ff) >> 0;
+        minor |= (dev & 0x00000ffffff00000) >> 12;
+        minor as ::c_uint
+    }
+
+    pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+        let major = major as ::dev_t;
+        let minor = minor as ::dev_t;
+        let mut dev = 0;
+        dev |= (major & 0x00000fff) << 8;
+        dev |= (major & 0xfffff000) << 32;
+        dev |= (minor & 0x000000ff) << 0;
+        dev |= (minor & 0xffffff00) << 12;
+        dev
+    }
+}
+
+// EXTERN_FN
+
+#[link(name = "c")]
+#[link(name = "fdio")]
+extern {}
+
+extern {
+    pub fn getpwnam(name: *const ::c_char) -> *mut passwd;
+    pub fn getpwuid(uid: ::uid_t) -> *mut passwd;
+
+    pub fn fprintf(stream: *mut ::FILE,
+                   format: *const ::c_char, ...) -> ::c_int;
+    pub fn printf(format: *const ::c_char, ...) -> ::c_int;
+    pub fn snprintf(s: *mut ::c_char, n: ::size_t,
+                    format: *const ::c_char, ...) -> ::c_int;
+    pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int;
+    pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int;
+    pub fn scanf(format: *const ::c_char, ...) -> ::c_int;
+    pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int;
+    pub fn getchar_unlocked() -> ::c_int;
+    pub fn putchar_unlocked(c: ::c_int) -> ::c_int;
+
+    pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int;
+    pub fn connect(socket: ::c_int, address: *const sockaddr,
+                   len: socklen_t) -> ::c_int;
+    pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int;
+    pub fn accept(socket: ::c_int, address: *mut sockaddr,
+                  address_len: *mut socklen_t) -> ::c_int;
+    pub fn getpeername(socket: ::c_int, address: *mut sockaddr,
+                       address_len: *mut socklen_t) -> ::c_int;
+    pub fn getsockname(socket: ::c_int, address: *mut sockaddr,
+                       address_len: *mut socklen_t) -> ::c_int;
+    pub fn setsockopt(socket: ::c_int, level: ::c_int, name: ::c_int,
+                      value: *const ::c_void,
+                      option_len: socklen_t) -> ::c_int;
+    pub fn socketpair(domain: ::c_int, type_: ::c_int, protocol: ::c_int,
+                      socket_vector: *mut ::c_int) -> ::c_int;
+    pub fn sendto(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                  flags: ::c_int, addr: *const sockaddr,
+                  addrlen: socklen_t) -> ::ssize_t;
+    pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int;
+
+    pub fn chmod(path: *const c_char, mode: mode_t) -> ::c_int;
+    pub fn fchmod(fd: ::c_int, mode: mode_t) -> ::c_int;
+
+    pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int;
+
+    pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int;
+
+    pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int;
+
+    pub fn pclose(stream: *mut ::FILE) -> ::c_int;
+    pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE;
+    pub fn fileno(stream: *mut ::FILE) -> ::c_int;
+
+    pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int;
+    pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int;
+    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
+
+    pub fn opendir(dirname: *const c_char) -> *mut ::DIR;
+    pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent;
+    pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent,
+                     result: *mut *mut ::dirent) -> ::c_int;
+    pub fn closedir(dirp: *mut ::DIR) -> ::c_int;
+    pub fn rewinddir(dirp: *mut ::DIR);
+
+    pub fn openat(dirfd: ::c_int, pathname: *const ::c_char,
+                  flags: ::c_int, ...) -> ::c_int;
+    pub fn fchmodat(dirfd: ::c_int, pathname: *const ::c_char,
+                    mode: ::mode_t, flags: ::c_int) -> ::c_int;
+    pub fn fchown(fd: ::c_int,
+                  owner: ::uid_t,
+                  group: ::gid_t) -> ::c_int;
+    pub fn fchownat(dirfd: ::c_int, pathname: *const ::c_char,
+                    owner: ::uid_t, group: ::gid_t,
+                    flags: ::c_int) -> ::c_int;
+    pub fn fstatat(dirfd: ::c_int, pathname: *const ::c_char,
+                   buf: *mut stat, flags: ::c_int) -> ::c_int;
+    pub fn linkat(olddirfd: ::c_int, oldpath: *const ::c_char,
+                  newdirfd: ::c_int, newpath: *const ::c_char,
+                  flags: ::c_int) -> ::c_int;
+    pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char,
+                   mode: ::mode_t) -> ::c_int;
+    pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char,
+                      buf: *mut ::c_char, bufsiz: ::size_t) -> ::ssize_t;
+    pub fn renameat(olddirfd: ::c_int, oldpath: *const ::c_char,
+                    newdirfd: ::c_int, newpath: *const ::c_char)
+                    -> ::c_int;
+    pub fn symlinkat(target: *const ::c_char, newdirfd: ::c_int,
+                     linkpath: *const ::c_char) -> ::c_int;
+    pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char,
+                    flags: ::c_int) -> ::c_int;
+
+    pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int;
+    pub fn alarm(seconds: ::c_uint) -> ::c_uint;
+    pub fn chdir(dir: *const c_char) -> ::c_int;
+    pub fn fchdir(dirfd: ::c_int) -> ::c_int;
+    pub fn chown(path: *const c_char, uid: uid_t,
+                 gid: gid_t) -> ::c_int;
+    pub fn lchown(path: *const c_char, uid: uid_t,
+                  gid: gid_t) -> ::c_int;
+    pub fn close(fd: ::c_int) -> ::c_int;
+    pub fn dup(fd: ::c_int) -> ::c_int;
+    pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int;
+    pub fn execl(path: *const c_char,
+                 arg0: *const c_char, ...) -> ::c_int;
+    pub fn execle(path: *const ::c_char,
+                  arg0: *const ::c_char, ...) -> ::c_int;
+    pub fn execlp(file: *const ::c_char,
+                  arg0: *const ::c_char, ...) -> ::c_int;
+    pub fn execv(prog: *const c_char,
+                 argv: *const *const c_char) -> ::c_int;
+    pub fn execve(prog: *const c_char, argv: *const *const c_char,
+                  envp: *const *const c_char)
+                  -> ::c_int;
+    pub fn execvp(c: *const c_char,
+                  argv: *const *const c_char) -> ::c_int;
+    pub fn fork() -> pid_t;
+    pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long;
+    pub fn getcwd(buf: *mut c_char, size: ::size_t) -> *mut c_char;
+    pub fn getegid() -> gid_t;
+    pub fn geteuid() -> uid_t;
+    pub fn getgid() -> gid_t;
+    pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t)
+                     -> ::c_int;
+    pub fn getlogin() -> *mut c_char;
+    pub fn getopt(argc: ::c_int, argv: *const *mut c_char,
+                  optstr: *const c_char) -> ::c_int;
+    pub fn getpgid(pid: pid_t) -> pid_t;
+    pub fn getpgrp() -> pid_t;
+    pub fn getpid() -> pid_t;
+    pub fn getppid() -> pid_t;
+    pub fn getuid() -> uid_t;
+    pub fn isatty(fd: ::c_int) -> ::c_int;
+    pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int;
+    pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t;
+    pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long;
+    pub fn pause() -> ::c_int;
+    pub fn pipe(fds: *mut ::c_int) -> ::c_int;
+    pub fn posix_memalign(memptr: *mut *mut ::c_void,
+                      align: ::size_t,
+                      size: ::size_t) -> ::c_int;
+    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
+                -> ::ssize_t;
+    pub fn rmdir(path: *const c_char) -> ::c_int;
+    pub fn seteuid(uid: uid_t) -> ::c_int;
+    pub fn setgid(gid: gid_t) -> ::c_int;
+    pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int;
+    pub fn setsid() -> pid_t;
+    pub fn setuid(uid: uid_t) -> ::c_int;
+    pub fn sleep(secs: ::c_uint) -> ::c_uint;
+    pub fn nanosleep(rqtp: *const timespec,
+                     rmtp: *mut timespec) -> ::c_int;
+    pub fn tcgetpgrp(fd: ::c_int) -> pid_t;
+    pub fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int;
+    pub fn ttyname(fd: ::c_int) -> *mut c_char;
+    pub fn unlink(c: *const c_char) -> ::c_int;
+    pub fn wait(status: *mut ::c_int) -> pid_t;
+    pub fn waitpid(pid: pid_t, status: *mut ::c_int, options: ::c_int)
+                   -> pid_t;
+    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
+                 -> ::ssize_t;
+    pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t,
+                 offset: off_t) -> ::ssize_t;
+    pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t,
+                  offset: off_t) -> ::ssize_t;
+    pub fn umask(mask: mode_t) -> mode_t;
+
+    pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int;
+
+    pub fn kill(pid: pid_t, sig: ::c_int) -> ::c_int;
+
+    pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int;
+    pub fn munlock(addr: *const ::c_void, len: ::size_t) -> ::c_int;
+    pub fn mlockall(flags: ::c_int) -> ::c_int;
+    pub fn munlockall() -> ::c_int;
+
+    pub fn mmap(addr: *mut ::c_void,
+                len: ::size_t,
+                prot: ::c_int,
+                flags: ::c_int,
+                fd: ::c_int,
+                offset: off_t)
+                -> *mut ::c_void;
+    pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int;
+
+    pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint;
+    pub fn if_indextoname(ifindex: ::c_uint,
+                          ifname: *mut ::c_char) -> *mut ::c_char;
+
+    pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int;
+
+    pub fn fsync(fd: ::c_int) -> ::c_int;
+
+    pub fn setenv(name: *const c_char, val: *const c_char,
+                  overwrite: ::c_int) -> ::c_int;
+    pub fn unsetenv(name: *const c_char) -> ::c_int;
+
+    pub fn symlink(path1: *const c_char,
+                   path2: *const c_char) -> ::c_int;
+
+    pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int;
+
+    pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t;
+
+    pub fn getrlimit(resource: ::c_int, rlim: *mut rlimit) -> ::c_int;
+    pub fn setrlimit(resource: ::c_int, rlim: *const rlimit) -> ::c_int;
+    pub fn getrusage(resource: ::c_int, usage: *mut rusage) -> ::c_int;
+
+    pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char)
+                    -> *mut ::c_char;
+
+    pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int;
+
+    pub fn gettimeofday(tp: *mut ::timeval,
+                        tz: *mut ::c_void) -> ::c_int;
+    pub fn times(buf: *mut ::tms) -> ::clock_t;
+
+    pub fn pthread_self() -> ::pthread_t;
+    pub fn pthread_join(native: ::pthread_t,
+                        value: *mut *mut ::c_void) -> ::c_int;
+    pub fn pthread_exit(value: *mut ::c_void);
+    pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int;
+    pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int;
+    pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t,
+                                     stack_size: ::size_t) -> ::c_int;
+    pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t,
+                                       state: ::c_int) -> ::c_int;
+    pub fn pthread_detach(thread: ::pthread_t) -> ::c_int;
+    pub fn sched_yield() -> ::c_int;
+    pub fn pthread_key_create(key: *mut pthread_key_t,
+                              dtor: Option<unsafe extern fn(*mut ::c_void)>)
+                              -> ::c_int;
+    pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int;
+    pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void;
+    pub fn pthread_setspecific(key: pthread_key_t, value: *const ::c_void)
+                               -> ::c_int;
+    pub fn pthread_mutex_init(lock: *mut pthread_mutex_t,
+                              attr: *const pthread_mutexattr_t) -> ::c_int;
+    pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> ::c_int;
+    pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> ::c_int;
+    pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> ::c_int;
+    pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> ::c_int;
+
+    pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int;
+    pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int;
+    pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t,
+                                     _type: ::c_int) -> ::c_int;
+
+    pub fn pthread_cond_init(cond: *mut pthread_cond_t,
+                             attr: *const pthread_condattr_t) -> ::c_int;
+    pub fn pthread_cond_wait(cond: *mut pthread_cond_t,
+                             lock: *mut pthread_mutex_t) -> ::c_int;
+    pub fn pthread_cond_timedwait(cond: *mut pthread_cond_t,
+                              lock: *mut pthread_mutex_t,
+                              abstime: *const ::timespec) -> ::c_int;
+    pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> ::c_int;
+    pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> ::c_int;
+    pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int;
+    pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> ::c_int;
+    pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> ::c_int;
+    pub fn pthread_rwlock_init(lock: *mut pthread_rwlock_t,
+                               attr: *const pthread_rwlockattr_t) -> ::c_int;
+    pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int;
+    pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int;
+    pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t)
+                                      -> ::c_int;
+    pub fn strerror_r(errnum: ::c_int, buf: *mut c_char,
+                      buflen: ::size_t) -> ::c_int;
+
+    pub fn getsockopt(sockfd: ::c_int,
+                      level: ::c_int,
+                      optname: ::c_int,
+                      optval: *mut ::c_void,
+                      optlen: *mut ::socklen_t) -> ::c_int;
+    pub fn raise(signum: ::c_int) -> ::c_int;
+    pub fn sigaction(signum: ::c_int,
+                     act: *const sigaction,
+                     oldact: *mut sigaction) -> ::c_int;
+
+    pub fn utimes(filename: *const ::c_char,
+                  times: *const ::timeval) -> ::c_int;
+    pub fn dlopen(filename: *const ::c_char,
+                  flag: ::c_int) -> *mut ::c_void;
+    pub fn dlerror() -> *mut ::c_char;
+    pub fn dlsym(handle: *mut ::c_void,
+                 symbol: *const ::c_char) -> *mut ::c_void;
+    pub fn dlclose(handle: *mut ::c_void) -> ::c_int;
+    pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int;
+
+    pub fn getaddrinfo(node: *const c_char,
+                       service: *const c_char,
+                       hints: *const addrinfo,
+                       res: *mut *mut addrinfo) -> ::c_int;
+    pub fn freeaddrinfo(res: *mut addrinfo);
+    pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char;
+    pub fn res_init() -> ::c_int;
+
+    pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm;
+    pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm;
+    pub fn mktime(tm: *mut tm) -> time_t;
+    pub fn time(time: *mut time_t) -> time_t;
+    pub fn gmtime(time_p: *const time_t) -> *mut tm;
+    pub fn localtime(time_p: *const time_t) -> *mut tm;
+
+    pub fn mknod(pathname: *const ::c_char, mode: ::mode_t,
+                 dev: ::dev_t) -> ::c_int;
+    pub fn uname(buf: *mut ::utsname) -> ::c_int;
+    pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
+    pub fn getservbyname(name: *const ::c_char,
+                         proto: *const ::c_char) -> *mut servent;
+    pub fn getprotobyname(name: *const ::c_char) -> *mut protoent;
+    pub fn getprotobynumber(proto: ::c_int) -> *mut protoent;
+    pub fn chroot(name: *const ::c_char) -> ::c_int;
+    pub fn usleep(secs: ::c_uint) -> ::c_int;
+    pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
+    pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
+    pub fn putenv(string: *mut c_char) -> ::c_int;
+    pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int;
+    pub fn select(nfds: ::c_int,
+                  readfs: *mut fd_set,
+                  writefds: *mut fd_set,
+                  errorfds: *mut fd_set,
+                  timeout: *mut timeval) -> ::c_int;
+    pub fn setlocale(category: ::c_int,
+                     locale: *const ::c_char) -> *mut ::c_char;
+    pub fn localeconv() -> *mut lconv;
+
+    pub fn sem_destroy(sem: *mut sem_t) -> ::c_int;
+    pub fn sem_wait(sem: *mut sem_t) -> ::c_int;
+    pub fn sem_trywait(sem: *mut sem_t) -> ::c_int;
+    pub fn sem_post(sem: *mut sem_t) -> ::c_int;
+    pub fn sem_init(sem: *mut sem_t,
+                    pshared: ::c_int,
+                    value: ::c_uint)
+                    -> ::c_int;
+    pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int;
+    pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int;
+
+    pub fn readlink(path: *const c_char,
+                    buf: *mut c_char,
+                    bufsz: ::size_t)
+                    -> ::ssize_t;
+
+    pub fn sigemptyset(set: *mut sigset_t) -> ::c_int;
+    pub fn sigaddset(set: *mut sigset_t, signum: ::c_int) -> ::c_int;
+    pub fn sigfillset(set: *mut sigset_t) -> ::c_int;
+    pub fn sigdelset(set: *mut sigset_t, signum: ::c_int) -> ::c_int;
+    pub fn sigismember(set: *const sigset_t, signum: ::c_int) -> ::c_int;
+
+    pub fn sigprocmask(how: ::c_int,
+                       set: *const sigset_t,
+                       oldset: *mut sigset_t)
+                       -> ::c_int;
+    pub fn sigpending(set: *mut sigset_t) -> ::c_int;
+
+    pub fn timegm(tm: *mut ::tm) -> time_t;
+
+    pub fn getsid(pid: pid_t) -> pid_t;
+
+    pub fn sysconf(name: ::c_int) -> ::c_long;
+
+    pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int;
+
+    pub fn pselect(nfds: ::c_int,
+                   readfs: *mut fd_set,
+                   writefds: *mut fd_set,
+                   errorfds: *mut fd_set,
+                   timeout: *const timespec,
+                   sigmask: *const sigset_t) -> ::c_int;
+    pub fn fseeko(stream: *mut ::FILE,
+                  offset: ::off_t,
+                  whence: ::c_int) -> ::c_int;
+    pub fn ftello(stream: *mut ::FILE) -> ::off_t;
+    pub fn tcdrain(fd: ::c_int) -> ::c_int;
+    pub fn cfgetispeed(termios: *const ::termios) -> ::speed_t;
+    pub fn cfgetospeed(termios: *const ::termios) -> ::speed_t;
+    pub fn cfmakeraw(termios: *mut ::termios);
+    pub fn cfsetispeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int;
+    pub fn cfsetospeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int;
+    pub fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int;
+    pub fn tcgetattr(fd: ::c_int, termios: *mut ::termios) -> ::c_int;
+    pub fn tcsetattr(fd: ::c_int,
+                     optional_actions: ::c_int,
+                     termios: *const ::termios) -> ::c_int;
+    pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int;
+    pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int;
+    pub fn tcgetsid(fd: ::c_int) -> ::pid_t;
+    pub fn tcsendbreak(fd: ::c_int, duration: ::c_int) -> ::c_int;
+    pub fn mkstemp(template: *mut ::c_char) -> ::c_int;
+    pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char;
+
+    pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char;
+
+    pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int);
+    pub fn closelog();
+    pub fn setlogmask(maskpri: ::c_int) -> ::c_int;
+    pub fn syslog(priority: ::c_int, message: *const ::c_char, ...);
+    pub fn nice(incr: ::c_int) -> ::c_int;
+
+    pub fn grantpt(fd: ::c_int) -> ::c_int;
+    pub fn posix_openpt(flags: ::c_int) -> ::c_int;
+    pub fn ptsname(fd: ::c_int) -> *mut ::c_char;
+    pub fn unlockpt(fd: ::c_int) -> ::c_int;
+
+    pub fn fdatasync(fd: ::c_int) -> ::c_int;
+    pub fn mincore(addr: *mut ::c_void, len: ::size_t,
+                   vec: *mut ::c_uchar) -> ::c_int;
+    pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
+    pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
+    pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int;
+    pub fn dirfd(dirp: *mut ::DIR) -> ::c_int;
+
+    pub fn pthread_getattr_np(native: ::pthread_t,
+                              attr: *mut ::pthread_attr_t) -> ::c_int;
+    pub fn pthread_attr_getstack(attr: *const ::pthread_attr_t,
+                                 stackaddr: *mut *mut ::c_void,
+                                 stacksize: *mut ::size_t) -> ::c_int;
+    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
+    pub fn setgroups(ngroups: ::size_t,
+                     ptr: *const ::gid_t) -> ::c_int;
+    pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int;
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn statfs64(path: *const ::c_char, buf: *mut statfs64) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs64(fd: ::c_int, buf: *mut statfs64) -> ::c_int;
+    pub fn statvfs64(path: *const ::c_char, buf: *mut statvfs64) -> ::c_int;
+    pub fn fstatvfs64(fd: ::c_int, buf: *mut statvfs64) -> ::c_int;
+    pub fn memrchr(cx: *const ::c_void,
+                   c: ::c_int,
+                   n: ::size_t) -> *mut ::c_void;
+
+    pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t,
+                         advise: ::c_int) -> ::c_int;
+    pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int;
+    pub fn utimensat(dirfd: ::c_int, path: *const ::c_char,
+                     times: *const ::timespec, flag: ::c_int) -> ::c_int;
+    pub fn duplocale(base: ::locale_t) -> ::locale_t;
+    pub fn freelocale(loc: ::locale_t);
+    pub fn newlocale(mask: ::c_int,
+                     locale: *const ::c_char,
+                     base: ::locale_t) -> ::locale_t;
+    pub fn uselocale(loc: ::locale_t) -> ::locale_t;
+    pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int;
+    pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int;
+    pub fn fstatat64(dirfd: ::c_int, pathname: *const c_char,
+                     buf: *mut stat64, flags: ::c_int) -> ::c_int;
+    pub fn ftruncate64(fd: ::c_int, length: off64_t) -> ::c_int;
+    pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int;
+    pub fn lseek64(fd: ::c_int, offset: off64_t, whence: ::c_int) -> off64_t;
+    pub fn lstat64(path: *const c_char, buf: *mut stat64) -> ::c_int;
+    pub fn mmap64(addr: *mut ::c_void,
+                  len: ::size_t,
+                  prot: ::c_int,
+                  flags: ::c_int,
+                  fd: ::c_int,
+                  offset: off64_t)
+                  -> *mut ::c_void;
+    pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int;
+    pub fn openat64(fd: ::c_int,
+                    path: *const c_char,
+                    oflag: ::c_int, ...) -> ::c_int;
+    pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t,
+                   offset: off64_t) -> ::ssize_t;
+    pub fn preadv64(fd: ::c_int,
+                    iov: *const ::iovec,
+                    iovcnt: ::c_int,
+                    offset: ::off64_t) -> ::ssize_t;
+    pub fn pwrite64(fd: ::c_int, buf: *const ::c_void, count: ::size_t,
+                    offset: off64_t) -> ::ssize_t;
+    pub fn pwritev64(fd: ::c_int,
+                     iov: *const ::iovec,
+                     iovcnt: ::c_int,
+                     offset: ::off64_t) -> ::ssize_t;
+    pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64;
+    pub fn readdir64_r(dirp: *mut ::DIR, entry: *mut ::dirent64,
+                       result: *mut *mut ::dirent64) -> ::c_int;
+    pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;
+    pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int;
+    pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int;
+
+    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
+
+    pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
+                   mode: ::mode_t, dev: dev_t) -> ::c_int;
+    pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t,
+                                     clock_id: *mut clockid_t) -> ::c_int;
+    pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
+                                     clock_id: ::clockid_t) -> ::c_int;
+    pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t,
+                                       pshared: ::c_int) -> ::c_int;
+    pub fn accept4(fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t,
+                   flg: ::c_int) -> ::c_int;
+    pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t,
+                                        pshared: ::c_int) -> ::c_int;
+    pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t,
+                                         val: *mut ::c_int) -> ::c_int;
+    pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t,
+                                         val: ::c_int) -> ::c_int;
+    pub fn ptsname_r(fd: ::c_int,
+                     buf: *mut ::c_char,
+                     buflen: ::size_t) -> ::c_int;
+    pub fn clearenv() -> ::c_int;
+    pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t,
+                  options: ::c_int) -> ::c_int;
+    pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int;
+    pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int;
+    pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t,
+                     suid: *mut ::uid_t) -> ::c_int;
+    pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t,
+                     sgid: *mut ::gid_t) -> ::c_int;
+    pub fn acct(filename: *const ::c_char) -> ::c_int;
+    pub fn brk(addr: *mut ::c_void) -> ::c_int;
+    pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void;
+    pub fn vfork() -> ::pid_t;
+    pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int;
+    pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int;
+    pub fn wait4(pid: ::pid_t, status: *mut ::c_int, options: ::c_int,
+                 rusage: *mut ::rusage) -> ::pid_t;
+    pub fn openpty(amaster: *mut ::c_int,
+                aslave: *mut ::c_int,
+                name: *mut ::c_char,
+                termp: *const termios,
+                winp: *const ::winsize) -> ::c_int;
+    pub fn execvpe(file: *const ::c_char, argv: *const *const ::c_char,
+                   envp: *const *const ::c_char) -> ::c_int;
+    pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
+                   envp: *const *const ::c_char)
+                   -> ::c_int;
+
+    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+    pub fn ptrace(request: ::c_int, ...) -> ::c_long;
+    pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
+    pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
+
+    pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int;
+    pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int;
+    pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int;
+    pub fn aio_error(aiocbp: *const aiocb) -> ::c_int;
+    pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t;
+    pub fn aio_suspend(aiocb_list: *const *const aiocb, nitems: ::c_int,
+                       timeout: *const ::timespec) -> ::c_int;
+    pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int;
+    pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb,
+                      nitems: ::c_int, sevp: *mut ::sigevent) -> ::c_int;
+
+    pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int;
+
+    pub fn setpwent();
+    pub fn endpwent();
+    pub fn getpwent() -> *mut passwd;
+    pub fn setspent();
+    pub fn endspent();
+    pub fn getspent() -> *mut spwd;
+    pub fn getspnam(__name: *const ::c_char) -> *mut spwd;
+
+    pub fn shm_open(name: *const c_char, oflag: ::c_int,
+                    mode: mode_t) -> ::c_int;
+
+    // System V IPC
+    pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int;
+    pub fn shmat(shmid: ::c_int,
+                 shmaddr: *const ::c_void,
+                 shmflg: ::c_int) -> *mut ::c_void;
+    pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int;
+    pub fn shmctl(shmid: ::c_int,
+                  cmd: ::c_int,
+                  buf: *mut ::shmid_ds) -> ::c_int;
+    pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t;
+    pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int;
+    pub fn semop(semid: ::c_int,
+                 sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int;
+    pub fn semctl(semid: ::c_int,
+                  semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int;
+    pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int;
+    pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int;
+    pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t,
+                  msgtyp: ::c_long, msgflg: ::c_int) -> ::ssize_t;
+    pub fn msgsnd(msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t,
+                  msgflg: ::c_int) -> ::c_int;
+
+    pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int)
+                    -> ::c_int;
+    pub fn __errno_location() -> *mut ::c_int;
+
+    pub fn fopen64(filename: *const c_char,
+                   mode: *const c_char) -> *mut ::FILE;
+    pub fn freopen64(filename: *const c_char, mode: *const c_char,
+                     file: *mut ::FILE) -> *mut ::FILE;
+    pub fn tmpfile64() -> *mut ::FILE;
+    pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int;
+    pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int;
+    pub fn fseeko64(stream: *mut ::FILE,
+                    offset: ::off64_t,
+                    whence: ::c_int) -> ::c_int;
+    pub fn ftello64(stream: *mut ::FILE) -> ::off64_t;
+    pub fn fallocate(fd: ::c_int, mode: ::c_int,
+                     offset: ::off_t, len: ::off_t) -> ::c_int;
+    pub fn posix_fallocate(fd: ::c_int, offset: ::off_t,
+                           len: ::off_t) -> ::c_int;
+    pub fn readahead(fd: ::c_int, offset: ::off64_t,
+                     count: ::size_t) -> ::ssize_t;
+    pub fn getxattr(path: *const c_char, name: *const c_char,
+                    value: *mut ::c_void, size: ::size_t) -> ::ssize_t;
+    pub fn lgetxattr(path: *const c_char, name: *const c_char,
+                     value: *mut ::c_void, size: ::size_t) -> ::ssize_t;
+    pub fn fgetxattr(filedes: ::c_int, name: *const c_char,
+                     value: *mut ::c_void, size: ::size_t) -> ::ssize_t;
+    pub fn setxattr(path: *const c_char, name: *const c_char,
+                    value: *const ::c_void, size: ::size_t,
+                    flags: ::c_int) -> ::c_int;
+    pub fn lsetxattr(path: *const c_char, name: *const c_char,
+                     value: *const ::c_void, size: ::size_t,
+                     flags: ::c_int) -> ::c_int;
+    pub fn fsetxattr(filedes: ::c_int, name: *const c_char,
+                     value: *const ::c_void, size: ::size_t,
+                     flags: ::c_int) -> ::c_int;
+    pub fn listxattr(path: *const c_char, list: *mut c_char,
+                     size: ::size_t) -> ::ssize_t;
+    pub fn llistxattr(path: *const c_char, list: *mut c_char,
+                      size: ::size_t) -> ::ssize_t;
+    pub fn flistxattr(filedes: ::c_int, list: *mut c_char,
+                      size: ::size_t) -> ::ssize_t;
+    pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int;
+    pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int;
+    pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int;
+    pub fn signalfd(fd: ::c_int,
+                    mask: *const ::sigset_t,
+                    flags: ::c_int) -> ::c_int;
+    pub fn timerfd_create(clockid: ::c_int, flags: ::c_int) -> ::c_int;
+    pub fn timerfd_gettime(fd: ::c_int,
+                           curr_value: *mut itimerspec) -> ::c_int;
+    pub fn timerfd_settime(fd: ::c_int,
+                           flags: ::c_int,
+                           new_value: *const itimerspec,
+                           old_value: *mut itimerspec) -> ::c_int;
+    pub fn pwritev(fd: ::c_int,
+                   iov: *const ::iovec,
+                   iovcnt: ::c_int,
+                   offset: ::off_t) -> ::ssize_t;
+    pub fn preadv(fd: ::c_int,
+                  iov: *const ::iovec,
+                  iovcnt: ::c_int,
+                  offset: ::off_t) -> ::ssize_t;
+    pub fn quotactl(cmd: ::c_int,
+                    special: *const ::c_char,
+                    id: ::c_int,
+                    data: *mut ::c_char) -> ::c_int;
+    pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t;
+    pub fn mq_close(mqd: ::mqd_t) -> ::c_int;
+    pub fn mq_unlink(name: *const ::c_char) -> ::c_int;
+    pub fn mq_receive(mqd: ::mqd_t,
+                      msg_ptr: *mut ::c_char,
+                      msg_len: ::size_t,
+                      msq_prio: *mut ::c_uint) -> ::ssize_t;
+    pub fn mq_send(mqd: ::mqd_t,
+                   msg_ptr: *const ::c_char,
+                   msg_len: ::size_t,
+                   msq_prio: ::c_uint) -> ::c_int;
+    pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int;
+    pub fn mq_setattr(mqd: ::mqd_t,
+                      newattr: *const ::mq_attr,
+                      oldattr: *mut ::mq_attr) -> ::c_int;
+    pub fn epoll_pwait(epfd: ::c_int,
+                       events: *mut ::epoll_event,
+                       maxevents: ::c_int,
+                       timeout: ::c_int,
+                       sigmask: *const ::sigset_t) -> ::c_int;
+    pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int;
+    pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int;
+    pub fn mkostemps(template: *mut ::c_char,
+                     suffixlen: ::c_int,
+                     flags: ::c_int) -> ::c_int;
+    pub fn sigtimedwait(set: *const sigset_t,
+                        info: *mut siginfo_t,
+                        timeout: *const ::timespec) -> ::c_int;
+    pub fn sigwaitinfo(set: *const sigset_t,
+                       info: *mut siginfo_t) -> ::c_int;
+    pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char;
+    pub fn getnameinfo(sa: *const ::sockaddr,
+                       salen: ::socklen_t,
+                       host: *mut ::c_char,
+                       hostlen: ::socklen_t,
+                       serv: *mut ::c_char,
+                       sevlen: ::socklen_t,
+                       flags: ::c_int) -> ::c_int;
+    pub fn pthread_setschedprio(native: ::pthread_t,
+                                priority: ::c_int) -> ::c_int;
+    pub fn prlimit(pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit,
+                   old_limit: *mut ::rlimit) -> ::c_int;
+    pub fn prlimit64(pid: ::pid_t,
+                     resource: ::c_int,
+                     new_limit: *const ::rlimit64,
+                     old_limit: *mut ::rlimit64) -> ::c_int;
+    pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int;
+    pub fn process_vm_readv(pid: ::pid_t,
+                            local_iov: *const ::iovec,
+                            liovcnt: ::c_ulong,
+                            remote_iov: *const ::iovec,
+                            riovcnt: ::c_ulong,
+                            flags: ::c_ulong) -> isize;
+    pub fn process_vm_writev(pid: ::pid_t,
+                             local_iov: *const ::iovec,
+                             liovcnt: ::c_ulong,
+                             remote_iov: *const ::iovec,
+                             riovcnt: ::c_ulong,
+                             flags: ::c_ulong) -> isize;
+    pub fn reboot(how_to: ::c_int) -> ::c_int;
+    pub fn setfsgid(gid: ::gid_t) -> ::c_int;
+    pub fn setfsuid(uid: ::uid_t) -> ::c_int;
+
+    // Not available now on Android
+    pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
+                    mode: ::mode_t) -> ::c_int;
+    pub fn if_nameindex() -> *mut if_nameindex;
+    pub fn if_freenameindex(ptr: *mut if_nameindex);
+    pub fn sync_file_range(fd: ::c_int, offset: ::off64_t,
+                           nbytes: ::off64_t, flags: ::c_uint) -> ::c_int;
+    pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int;
+    pub fn freeifaddrs(ifa: *mut ::ifaddrs);
+
+    pub fn mremap(addr: *mut ::c_void,
+                  len: ::size_t,
+                  new_len: ::size_t,
+                  flags: ::c_int,
+                  ...) -> *mut ::c_void;
+
+    pub fn glob(pattern: *const c_char,
+                flags: ::c_int,
+                errfunc: Option<extern fn(epath: *const c_char,
+                                          errno: ::c_int) -> ::c_int>,
+                pglob: *mut ::glob_t) -> ::c_int;
+    pub fn globfree(pglob: *mut ::glob_t);
+
+    pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int)
+                         -> ::c_int;
+
+    pub fn shm_unlink(name: *const ::c_char) -> ::c_int;
+
+    pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long);
+
+    pub fn telldir(dirp: *mut ::DIR) -> ::c_long;
+    pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int)
+                  -> ::c_int;
+
+    pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
+
+    pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                    flags: ::c_int, addr: *mut ::sockaddr,
+                    addrlen: *mut ::socklen_t) -> ::ssize_t;
+    pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
+    pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int;
+    pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
+
+    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
+                address_len: ::socklen_t) -> ::c_int;
+
+    pub fn writev(fd: ::c_int,
+                  iov: *const ::iovec,
+                  iovcnt: ::c_int) -> ::ssize_t;
+    pub fn readv(fd: ::c_int,
+                 iov: *const ::iovec,
+                 iovcnt: ::c_int) -> ::ssize_t;
+
+    pub fn sendmsg(fd: ::c_int,
+                   msg: *const ::msghdr,
+                   flags: ::c_int) -> ::ssize_t;
+    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
+                   -> ::ssize_t;
+    pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
+    pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int;
+    pub fn vhangup() -> ::c_int;
+    pub fn sendmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
+                    flags: ::c_int) -> ::c_int;
+    pub fn recvmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
+                    flags: ::c_int, timeout: *mut ::timespec) -> ::c_int;
+    pub fn sync();
+    pub fn syscall(num: ::c_long, ...) -> ::c_long;
+    pub fn sched_getaffinity(pid: ::pid_t,
+                             cpusetsize: ::size_t,
+                             cpuset: *mut cpu_set_t) -> ::c_int;
+    pub fn sched_setaffinity(pid: ::pid_t,
+                             cpusetsize: ::size_t,
+                             cpuset: *const cpu_set_t) -> ::c_int;
+    pub fn epoll_create(size: ::c_int) -> ::c_int;
+    pub fn epoll_create1(flags: ::c_int) -> ::c_int;
+    pub fn epoll_wait(epfd: ::c_int,
+                      events: *mut ::epoll_event,
+                      maxevents: ::c_int,
+                      timeout: ::c_int) -> ::c_int;
+    pub fn epoll_ctl(epfd: ::c_int,
+                     op: ::c_int,
+                     fd: ::c_int,
+                     event: *mut ::epoll_event) -> ::c_int;
+    pub fn pthread_getschedparam(native: ::pthread_t,
+                                 policy: *mut ::c_int,
+                                 param: *mut ::sched_param) -> ::c_int;
+    pub fn unshare(flags: ::c_int) -> ::c_int;
+    pub fn umount(target: *const ::c_char) -> ::c_int;
+    pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int;
+    pub fn tee(fd_in: ::c_int,
+               fd_out: ::c_int,
+               len: ::size_t,
+               flags: ::c_uint) -> ::ssize_t;
+    pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int;
+    pub fn splice(fd_in: ::c_int,
+                  off_in: *mut ::loff_t,
+                  fd_out: ::c_int,
+                  off_out: *mut ::loff_t,
+                  len: ::size_t,
+                  flags: ::c_uint) -> ::ssize_t;
+    pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;
+    pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int;
+    pub fn sem_timedwait(sem: *mut sem_t,
+                         abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
+    pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int;
+    pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int;
+    pub fn swapoff(puath: *const ::c_char) -> ::c_int;
+    pub fn vmsplice(fd: ::c_int,
+                    iov: *const ::iovec,
+                    nr_segs: ::size_t,
+                    flags: ::c_uint) -> ::ssize_t;
+    pub fn mount(src: *const ::c_char,
+                 target: *const ::c_char,
+                 fstype: *const ::c_char,
+                 flags: ::c_ulong,
+                 data: *const ::c_void) -> ::c_int;
+    pub fn personality(persona: ::c_ulong) -> ::c_int;
+    pub fn prctl(option: ::c_int, ...) -> ::c_int;
+    pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int;
+    pub fn ppoll(fds: *mut ::pollfd,
+                 nfds: nfds_t,
+                 timeout: *const ::timespec,
+                 sigmask: *const sigset_t) -> ::c_int;
+    pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
+                                   abstime: *const ::timespec) -> ::c_int;
+    pub fn clone(cb: extern fn(*mut ::c_void) -> ::c_int,
+                 child_stack: *mut ::c_void,
+                 flags: ::c_int,
+                 arg: *mut ::c_void, ...) -> ::c_int;
+    pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int;
+    pub fn clock_nanosleep(clk_id: ::clockid_t,
+                           flags: ::c_int,
+                           rqtp: *const ::timespec,
+                           rmtp:  *mut ::timespec) -> ::c_int;
+    pub fn pthread_attr_getguardsize(attr: *const ::pthread_attr_t,
+                                     guardsize: *mut ::size_t) -> ::c_int;
+    pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int;
+    pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int;
+    pub fn pthread_condattr_getpshared(attr: *const pthread_condattr_t,
+                                       pshared: *mut ::c_int) -> ::c_int;
+    pub fn sysinfo(info: *mut ::sysinfo) -> ::c_int;
+    pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int;
+    pub fn pthread_setschedparam(native: ::pthread_t,
+                                 policy: ::c_int,
+                                 param: *const ::sched_param) -> ::c_int;
+    pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int;
+    pub fn sched_setscheduler(pid: ::pid_t,
+                              policy: ::c_int,
+                              param: *const ::sched_param) -> ::c_int;
+    pub fn sendfile(out_fd: ::c_int,
+                    in_fd: ::c_int,
+                    offset: *mut off_t,
+                    count: ::size_t) -> ::ssize_t;
+    pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int;
+    pub fn getgrgid_r(uid: ::uid_t,
+                      grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
+    pub fn sigaltstack(ss: *const stack_t,
+                       oss: *mut stack_t) -> ::c_int;
+    pub fn sem_close(sem: *mut sem_t) -> ::c_int;
+    pub fn getdtablesize() -> ::c_int;
+    pub fn getgrnam_r(name: *const ::c_char,
+                      grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
+    pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int;
+    pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t,
+                           oldset: *mut sigset_t) -> ::c_int;
+    pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t;
+    pub fn getgrnam(name: *const ::c_char) -> *mut ::group;
+    pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int;
+    pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int;
+    pub fn sem_unlink(name: *const ::c_char) -> ::c_int;
+    pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int;
+    pub fn getpwnam_r(name: *const ::c_char,
+                      pwd: *mut passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut passwd) -> ::c_int;
+    pub fn getpwuid_r(uid: ::uid_t,
+                      pwd: *mut passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut passwd) -> ::c_int;
+    pub fn sigwait(set: *const sigset_t,
+                   sig: *mut ::c_int) -> ::c_int;
+    pub fn pthread_atfork(prepare: Option<unsafe extern fn()>,
+                          parent: Option<unsafe extern fn()>,
+                          child: Option<unsafe extern fn()>) -> ::c_int;
+    pub fn getgrgid(gid: ::gid_t) -> *mut ::group;
+    pub fn getgrouplist(user: *const ::c_char,
+                        group: ::gid_t,
+                        groups: *mut ::gid_t,
+                        ngroups: *mut ::c_int) -> ::c_int;
+    pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t,
+                                        pshared: *mut ::c_int) -> ::c_int;
+    pub fn popen(command: *const c_char,
+                 mode: *const c_char) -> *mut ::FILE;
+    pub fn faccessat(dirfd: ::c_int, pathname: *const ::c_char,
+                     mode: ::c_int, flags: ::c_int) -> ::c_int;
+    pub fn pthread_create(native: *mut ::pthread_t,
+                          attr: *const ::pthread_attr_t,
+                          f: extern fn(*mut ::c_void) -> *mut ::c_void,
+                          value: *mut ::c_void) -> ::c_int;
+    pub fn dl_iterate_phdr(
+        callback: Option<unsafe extern fn(
+            info: *mut ::dl_phdr_info,
+            size: ::size_t,
+            data: *mut ::c_void
+        ) -> ::c_int>,
+        data: *mut ::c_void
+    ) -> ::c_int;
+}
+
+cfg_if! {
+    if #[cfg(target_arch = "aarch64")] {
+        mod aarch64;
+        pub use self::aarch64::*;
+    } else if #[cfg(any(target_arch = "powerpc64"))] {
+        mod powerpc64;
+        pub use self::powerpc64::*;
+    } else if #[cfg(any(target_arch = "x86_64"))] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else {
+        // Unknown target_arch
+    }
+}
diff --git a/third_party/rust/libc/src/fuchsia/powerpc64.rs b/third_party/rust/libc/src/fuchsia/powerpc64.rs
new file mode 100644
index 000000000000..112cd4351440
--- /dev/null
+++ b/third_party/rust/libc/src/fuchsia/powerpc64.rs
@@ -0,0 +1,79 @@
+pub type c_char = u8;
+pub type wchar_t = i32;
+pub type __u64 = ::c_ulong;
+pub type nlink_t = u64;
+pub type blksize_t = ::c_long;
+
+s! {
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_nlink: ::nlink_t,
+        pub st_mode: ::mode_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        __pad0: ::c_int,
+        pub st_rdev: ::dev_t,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_long; 3],
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino64_t,
+        pub st_nlink: ::nlink_t,
+        pub st_mode: ::mode_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        __pad0: ::c_int,
+        pub st_rdev: ::dev_t,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt64_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __reserved: [::c_long; 3],
+    }
+
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __unused1: ::c_long,
+        __unused2: ::c_long
+    }
+}
+
+pub const SYS_pivot_root: ::c_long = 203;
+pub const SYS_gettid: ::c_long = 207;
+pub const SYS_perf_event_open: ::c_long = 319;
+pub const SYS_memfd_create: ::c_long = 360;
+
+pub const MAP_32BIT: ::c_int = 0x0040;
+
+pub const SIGSTKSZ: ::size_t = 8192;
+pub const MINSIGSTKSZ: ::size_t = 2048;
+
+#[doc(hidden)]
+pub const AF_MAX: ::c_int = 42;
+#[doc(hidden)]
+pub const PF_MAX: ::c_int = AF_MAX;
+
+// Syscall table
+pub const SYS_renameat2: ::c_long = 357;
diff --git a/third_party/rust/libc/src/fuchsia/x86_64.rs b/third_party/rust/libc/src/fuchsia/x86_64.rs
new file mode 100644
index 000000000000..2e4ecccbf790
--- /dev/null
+++ b/third_party/rust/libc/src/fuchsia/x86_64.rs
@@ -0,0 +1,447 @@
+pub type c_char = i8;
+pub type wchar_t = i32;
+pub type nlink_t = u64;
+pub type blksize_t = ::c_long;
+pub type __u64 = ::c_ulonglong;
+
+s! {
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_nlink: ::nlink_t,
+        pub st_mode: ::mode_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        __pad0: ::c_int,
+        pub st_rdev: ::dev_t,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_long; 3],
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino64_t,
+        pub st_nlink: ::nlink_t,
+        pub st_mode: ::mode_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        __pad0: ::c_int,
+        pub st_rdev: ::dev_t,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt64_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __reserved: [::c_long; 3],
+    }
+
+    pub struct mcontext_t {
+        __private: [u64; 32],
+    }
+
+    pub struct ucontext_t {
+        pub uc_flags: ::c_ulong,
+        pub uc_link: *mut ucontext_t,
+        pub uc_stack: ::stack_t,
+        pub uc_mcontext: mcontext_t,
+        pub uc_sigmask: ::sigset_t,
+        __private: [u8; 512],
+    }
+
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __unused1: ::c_long,
+        __unused2: ::c_long
+    }
+}
+
+// Syscall table
+
+pub const SYS_read: ::c_long = 0;
+pub const SYS_write: ::c_long = 1;
+pub const SYS_open: ::c_long = 2;
+pub const SYS_close: ::c_long = 3;
+pub const SYS_stat: ::c_long = 4;
+pub const SYS_fstat: ::c_long = 5;
+pub const SYS_lstat: ::c_long = 6;
+pub const SYS_poll: ::c_long = 7;
+pub const SYS_lseek: ::c_long = 8;
+pub const SYS_mmap: ::c_long = 9;
+pub const SYS_mprotect: ::c_long = 10;
+pub const SYS_munmap: ::c_long = 11;
+pub const SYS_brk: ::c_long = 12;
+pub const SYS_rt_sigaction: ::c_long = 13;
+pub const SYS_rt_sigprocmask: ::c_long = 14;
+pub const SYS_rt_sigreturn: ::c_long = 15;
+pub const SYS_ioctl: ::c_long = 16;
+pub const SYS_pread64: ::c_long = 17;
+pub const SYS_pwrite64: ::c_long = 18;
+pub const SYS_readv: ::c_long = 19;
+pub const SYS_writev: ::c_long = 20;
+pub const SYS_access: ::c_long = 21;
+pub const SYS_pipe: ::c_long = 22;
+pub const SYS_select: ::c_long = 23;
+pub const SYS_sched_yield: ::c_long = 24;
+pub const SYS_mremap: ::c_long = 25;
+pub const SYS_msync: ::c_long = 26;
+pub const SYS_mincore: ::c_long = 27;
+pub const SYS_madvise: ::c_long = 28;
+pub const SYS_shmget: ::c_long = 29;
+pub const SYS_shmat: ::c_long = 30;
+pub const SYS_shmctl: ::c_long = 31;
+pub const SYS_dup: ::c_long = 32;
+pub const SYS_dup2: ::c_long = 33;
+pub const SYS_pause: ::c_long = 34;
+pub const SYS_nanosleep: ::c_long = 35;
+pub const SYS_getitimer: ::c_long = 36;
+pub const SYS_alarm: ::c_long = 37;
+pub const SYS_setitimer: ::c_long = 38;
+pub const SYS_getpid: ::c_long = 39;
+pub const SYS_sendfile: ::c_long = 40;
+pub const SYS_socket: ::c_long = 41;
+pub const SYS_connect: ::c_long = 42;
+pub const SYS_accept: ::c_long = 43;
+pub const SYS_sendto: ::c_long = 44;
+pub const SYS_recvfrom: ::c_long = 45;
+pub const SYS_sendmsg: ::c_long = 46;
+pub const SYS_recvmsg: ::c_long = 47;
+pub const SYS_shutdown: ::c_long = 48;
+pub const SYS_bind: ::c_long = 49;
+pub const SYS_listen: ::c_long = 50;
+pub const SYS_getsockname: ::c_long = 51;
+pub const SYS_getpeername: ::c_long = 52;
+pub const SYS_socketpair: ::c_long = 53;
+pub const SYS_setsockopt: ::c_long = 54;
+pub const SYS_getsockopt: ::c_long = 55;
+pub const SYS_clone: ::c_long = 56;
+pub const SYS_fork: ::c_long = 57;
+pub const SYS_vfork: ::c_long = 58;
+pub const SYS_execve: ::c_long = 59;
+pub const SYS_exit: ::c_long = 60;
+pub const SYS_wait4: ::c_long = 61;
+pub const SYS_kill: ::c_long = 62;
+pub const SYS_uname: ::c_long = 63;
+pub const SYS_semget: ::c_long = 64;
+pub const SYS_semop: ::c_long = 65;
+pub const SYS_semctl: ::c_long = 66;
+pub const SYS_shmdt: ::c_long = 67;
+pub const SYS_msgget: ::c_long = 68;
+pub const SYS_msgsnd: ::c_long = 69;
+pub const SYS_msgrcv: ::c_long = 70;
+pub const SYS_msgctl: ::c_long = 71;
+pub const SYS_fcntl: ::c_long = 72;
+pub const SYS_flock: ::c_long = 73;
+pub const SYS_fsync: ::c_long = 74;
+pub const SYS_fdatasync: ::c_long = 75;
+pub const SYS_truncate: ::c_long = 76;
+pub const SYS_ftruncate: ::c_long = 77;
+pub const SYS_getdents: ::c_long = 78;
+pub const SYS_getcwd: ::c_long = 79;
+pub const SYS_chdir: ::c_long = 80;
+pub const SYS_fchdir: ::c_long = 81;
+pub const SYS_rename: ::c_long = 82;
+pub const SYS_mkdir: ::c_long = 83;
+pub const SYS_rmdir: ::c_long = 84;
+pub const SYS_creat: ::c_long = 85;
+pub const SYS_link: ::c_long = 86;
+pub const SYS_unlink: ::c_long = 87;
+pub const SYS_symlink: ::c_long = 88;
+pub const SYS_readlink: ::c_long = 89;
+pub const SYS_chmod: ::c_long = 90;
+pub const SYS_fchmod: ::c_long = 91;
+pub const SYS_chown: ::c_long = 92;
+pub const SYS_fchown: ::c_long = 93;
+pub const SYS_lchown: ::c_long = 94;
+pub const SYS_umask: ::c_long = 95;
+pub const SYS_gettimeofday: ::c_long = 96;
+pub const SYS_getrlimit: ::c_long = 97;
+pub const SYS_getrusage: ::c_long = 98;
+pub const SYS_sysinfo: ::c_long = 99;
+pub const SYS_times: ::c_long = 100;
+pub const SYS_ptrace: ::c_long = 101;
+pub const SYS_getuid: ::c_long = 102;
+pub const SYS_syslog: ::c_long = 103;
+pub const SYS_getgid: ::c_long = 104;
+pub const SYS_setuid: ::c_long = 105;
+pub const SYS_setgid: ::c_long = 106;
+pub const SYS_geteuid: ::c_long = 107;
+pub const SYS_getegid: ::c_long = 108;
+pub const SYS_setpgid: ::c_long = 109;
+pub const SYS_getppid: ::c_long = 110;
+pub const SYS_getpgrp: ::c_long = 111;
+pub const SYS_setsid: ::c_long = 112;
+pub const SYS_setreuid: ::c_long = 113;
+pub const SYS_setregid: ::c_long = 114;
+pub const SYS_getgroups: ::c_long = 115;
+pub const SYS_setgroups: ::c_long = 116;
+pub const SYS_setresuid: ::c_long = 117;
+pub const SYS_getresuid: ::c_long = 118;
+pub const SYS_setresgid: ::c_long = 119;
+pub const SYS_getresgid: ::c_long = 120;
+pub const SYS_getpgid: ::c_long = 121;
+pub const SYS_setfsuid: ::c_long = 122;
+pub const SYS_setfsgid: ::c_long = 123;
+pub const SYS_getsid: ::c_long = 124;
+pub const SYS_capget: ::c_long = 125;
+pub const SYS_capset: ::c_long = 126;
+pub const SYS_rt_sigpending: ::c_long = 127;
+pub const SYS_rt_sigtimedwait: ::c_long = 128;
+pub const SYS_rt_sigqueueinfo: ::c_long = 129;
+pub const SYS_rt_sigsuspend: ::c_long = 130;
+pub const SYS_sigaltstack: ::c_long = 131;
+pub const SYS_utime: ::c_long = 132;
+pub const SYS_mknod: ::c_long = 133;
+pub const SYS_uselib: ::c_long = 134;
+pub const SYS_personality: ::c_long = 135;
+pub const SYS_ustat: ::c_long = 136;
+pub const SYS_statfs: ::c_long = 137;
+pub const SYS_fstatfs: ::c_long = 138;
+pub const SYS_sysfs: ::c_long = 139;
+pub const SYS_getpriority: ::c_long = 140;
+pub const SYS_setpriority: ::c_long = 141;
+pub const SYS_sched_setparam: ::c_long = 142;
+pub const SYS_sched_getparam: ::c_long = 143;
+pub const SYS_sched_setscheduler: ::c_long = 144;
+pub const SYS_sched_getscheduler: ::c_long = 145;
+pub const SYS_sched_get_priority_max: ::c_long = 146;
+pub const SYS_sched_get_priority_min: ::c_long = 147;
+pub const SYS_sched_rr_get_interval: ::c_long = 148;
+pub const SYS_mlock: ::c_long = 149;
+pub const SYS_munlock: ::c_long = 150;
+pub const SYS_mlockall: ::c_long = 151;
+pub const SYS_munlockall: ::c_long = 152;
+pub const SYS_vhangup: ::c_long = 153;
+pub const SYS_modify_ldt: ::c_long = 154;
+pub const SYS_pivot_root: ::c_long = 155;
+pub const SYS__sysctl: ::c_long = 156;
+pub const SYS_prctl: ::c_long = 157;
+pub const SYS_arch_prctl: ::c_long = 158;
+pub const SYS_adjtimex: ::c_long = 159;
+pub const SYS_setrlimit: ::c_long = 160;
+pub const SYS_chroot: ::c_long = 161;
+pub const SYS_sync: ::c_long = 162;
+pub const SYS_acct: ::c_long = 163;
+pub const SYS_settimeofday: ::c_long = 164;
+pub const SYS_mount: ::c_long = 165;
+pub const SYS_umount2: ::c_long = 166;
+pub const SYS_swapon: ::c_long = 167;
+pub const SYS_swapoff: ::c_long = 168;
+pub const SYS_reboot: ::c_long = 169;
+pub const SYS_sethostname: ::c_long = 170;
+pub const SYS_setdomainname: ::c_long = 171;
+pub const SYS_iopl: ::c_long = 172;
+pub const SYS_ioperm: ::c_long = 173;
+pub const SYS_create_module: ::c_long = 174;
+pub const SYS_init_module: ::c_long = 175;
+pub const SYS_delete_module: ::c_long = 176;
+pub const SYS_get_kernel_syms: ::c_long = 177;
+pub const SYS_query_module: ::c_long = 178;
+pub const SYS_quotactl: ::c_long = 179;
+pub const SYS_nfsservctl: ::c_long = 180;
+pub const SYS_getpmsg: ::c_long = 181;
+pub const SYS_putpmsg: ::c_long = 182;
+pub const SYS_afs_syscall: ::c_long = 183;
+pub const SYS_tuxcall: ::c_long = 184;
+pub const SYS_security: ::c_long = 185;
+pub const SYS_gettid: ::c_long = 186;
+pub const SYS_readahead: ::c_long = 187;
+pub const SYS_setxattr: ::c_long = 188;
+pub const SYS_lsetxattr: ::c_long = 189;
+pub const SYS_fsetxattr: ::c_long = 190;
+pub const SYS_getxattr: ::c_long = 191;
+pub const SYS_lgetxattr: ::c_long = 192;
+pub const SYS_fgetxattr: ::c_long = 193;
+pub const SYS_listxattr: ::c_long = 194;
+pub const SYS_llistxattr: ::c_long = 195;
+pub const SYS_flistxattr: ::c_long = 196;
+pub const SYS_removexattr: ::c_long = 197;
+pub const SYS_lremovexattr: ::c_long = 198;
+pub const SYS_fremovexattr: ::c_long = 199;
+pub const SYS_tkill: ::c_long = 200;
+pub const SYS_time: ::c_long = 201;
+pub const SYS_futex: ::c_long = 202;
+pub const SYS_sched_setaffinity: ::c_long = 203;
+pub const SYS_sched_getaffinity: ::c_long = 204;
+pub const SYS_set_thread_area: ::c_long = 205;
+pub const SYS_io_setup: ::c_long = 206;
+pub const SYS_io_destroy: ::c_long = 207;
+pub const SYS_io_getevents: ::c_long = 208;
+pub const SYS_io_submit: ::c_long = 209;
+pub const SYS_io_cancel: ::c_long = 210;
+pub const SYS_get_thread_area: ::c_long = 211;
+pub const SYS_lookup_dcookie: ::c_long = 212;
+pub const SYS_epoll_create: ::c_long = 213;
+pub const SYS_epoll_ctl_old: ::c_long = 214;
+pub const SYS_epoll_wait_old: ::c_long = 215;
+pub const SYS_remap_file_pages: ::c_long = 216;
+pub const SYS_getdents64: ::c_long = 217;
+pub const SYS_set_tid_address: ::c_long = 218;
+pub const SYS_restart_syscall: ::c_long = 219;
+pub const SYS_semtimedop: ::c_long = 220;
+pub const SYS_fadvise64: ::c_long = 221;
+pub const SYS_timer_create: ::c_long = 222;
+pub const SYS_timer_settime: ::c_long = 223;
+pub const SYS_timer_gettime: ::c_long = 224;
+pub const SYS_timer_getoverrun: ::c_long = 225;
+pub const SYS_timer_delete: ::c_long = 226;
+pub const SYS_clock_settime: ::c_long = 227;
+pub const SYS_clock_gettime: ::c_long = 228;
+pub const SYS_clock_getres: ::c_long = 229;
+pub const SYS_clock_nanosleep: ::c_long = 230;
+pub const SYS_exit_group: ::c_long = 231;
+pub const SYS_epoll_wait: ::c_long = 232;
+pub const SYS_epoll_ctl: ::c_long = 233;
+pub const SYS_tgkill: ::c_long = 234;
+pub const SYS_utimes: ::c_long = 235;
+pub const SYS_vserver: ::c_long = 236;
+pub const SYS_mbind: ::c_long = 237;
+pub const SYS_set_mempolicy: ::c_long = 238;
+pub const SYS_get_mempolicy: ::c_long = 239;
+pub const SYS_mq_open: ::c_long = 240;
+pub const SYS_mq_unlink: ::c_long = 241;
+pub const SYS_mq_timedsend: ::c_long = 242;
+pub const SYS_mq_timedreceive: ::c_long = 243;
+pub const SYS_mq_notify: ::c_long = 244;
+pub const SYS_mq_getsetattr: ::c_long = 245;
+pub const SYS_kexec_load: ::c_long = 246;
+pub const SYS_waitid: ::c_long = 247;
+pub const SYS_add_key: ::c_long = 248;
+pub const SYS_request_key: ::c_long = 249;
+pub const SYS_keyctl: ::c_long = 250;
+pub const SYS_ioprio_set: ::c_long = 251;
+pub const SYS_ioprio_get: ::c_long = 252;
+pub const SYS_inotify_init: ::c_long = 253;
+pub const SYS_inotify_add_watch: ::c_long = 254;
+pub const SYS_inotify_rm_watch: ::c_long = 255;
+pub const SYS_migrate_pages: ::c_long = 256;
+pub const SYS_openat: ::c_long = 257;
+pub const SYS_mkdirat: ::c_long = 258;
+pub const SYS_mknodat: ::c_long = 259;
+pub const SYS_fchownat: ::c_long = 260;
+pub const SYS_futimesat: ::c_long = 261;
+pub const SYS_newfstatat: ::c_long = 262;
+pub const SYS_unlinkat: ::c_long = 263;
+pub const SYS_renameat: ::c_long = 264;
+pub const SYS_linkat: ::c_long = 265;
+pub const SYS_symlinkat: ::c_long = 266;
+pub const SYS_readlinkat: ::c_long = 267;
+pub const SYS_fchmodat: ::c_long = 268;
+pub const SYS_faccessat: ::c_long = 269;
+pub const SYS_pselect6: ::c_long = 270;
+pub const SYS_ppoll: ::c_long = 271;
+pub const SYS_unshare: ::c_long = 272;
+pub const SYS_set_robust_list: ::c_long = 273;
+pub const SYS_get_robust_list: ::c_long = 274;
+pub const SYS_splice: ::c_long = 275;
+pub const SYS_tee: ::c_long = 276;
+pub const SYS_sync_file_range: ::c_long = 277;
+pub const SYS_vmsplice: ::c_long = 278;
+pub const SYS_move_pages: ::c_long = 279;
+pub const SYS_utimensat: ::c_long = 280;
+pub const SYS_epoll_pwait: ::c_long = 281;
+pub const SYS_signalfd: ::c_long = 282;
+pub const SYS_timerfd_create: ::c_long = 283;
+pub const SYS_eventfd: ::c_long = 284;
+pub const SYS_fallocate: ::c_long = 285;
+pub const SYS_timerfd_settime: ::c_long = 286;
+pub const SYS_timerfd_gettime: ::c_long = 287;
+pub const SYS_accept4: ::c_long = 288;
+pub const SYS_signalfd4: ::c_long = 289;
+pub const SYS_eventfd2: ::c_long = 290;
+pub const SYS_epoll_create1: ::c_long = 291;
+pub const SYS_dup3: ::c_long = 292;
+pub const SYS_pipe2: ::c_long = 293;
+pub const SYS_inotify_init1: ::c_long = 294;
+pub const SYS_preadv: ::c_long = 295;
+pub const SYS_pwritev: ::c_long = 296;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 297;
+pub const SYS_perf_event_open: ::c_long = 298;
+pub const SYS_recvmmsg: ::c_long = 299;
+pub const SYS_fanotify_init: ::c_long = 300;
+pub const SYS_fanotify_mark: ::c_long = 301;
+pub const SYS_prlimit64: ::c_long = 302;
+pub const SYS_name_to_handle_at: ::c_long = 303;
+pub const SYS_open_by_handle_at: ::c_long = 304;
+pub const SYS_clock_adjtime: ::c_long = 305;
+pub const SYS_syncfs: ::c_long = 306;
+pub const SYS_sendmmsg: ::c_long = 307;
+pub const SYS_setns: ::c_long = 308;
+pub const SYS_getcpu: ::c_long = 309;
+pub const SYS_process_vm_readv: ::c_long = 310;
+pub const SYS_process_vm_writev: ::c_long = 311;
+pub const SYS_kcmp: ::c_long = 312;
+pub const SYS_finit_module: ::c_long = 313;
+pub const SYS_sched_setattr: ::c_long = 314;
+pub const SYS_sched_getattr: ::c_long = 315;
+pub const SYS_renameat2: ::c_long = 316;
+pub const SYS_seccomp: ::c_long = 317;
+pub const SYS_getrandom: ::c_long = 318;
+pub const SYS_memfd_create: ::c_long = 319;
+pub const SYS_kexec_file_load: ::c_long = 320;
+pub const SYS_bpf: ::c_long = 321;
+pub const SYS_execveat: ::c_long = 322;
+pub const SYS_userfaultfd: ::c_long = 323;
+pub const SYS_membarrier: ::c_long = 324;
+pub const SYS_mlock2: ::c_long = 325;
+pub const SYS_copy_file_range: ::c_long = 326;
+pub const SYS_preadv2: ::c_long = 327;
+pub const SYS_pwritev2: ::c_long = 328;
+// FIXME syscalls 329-331 have been added in musl 1.16
+// See discussion https://github.com/rust-lang/libc/pull/699
+
+// offsets in user_regs_structs, from sys/reg.h
+pub const R15: ::c_int = 0;
+pub const R14: ::c_int = 1;
+pub const R13: ::c_int = 2;
+pub const R12: ::c_int = 3;
+pub const RBP: ::c_int = 4;
+pub const RBX: ::c_int = 5;
+pub const R11: ::c_int = 6;
+pub const R10: ::c_int = 7;
+pub const R9: ::c_int = 8;
+pub const R8: ::c_int = 9;
+pub const RAX: ::c_int = 10;
+pub const RCX: ::c_int = 11;
+pub const RDX: ::c_int = 12;
+pub const RSI: ::c_int = 13;
+pub const RDI: ::c_int = 14;
+pub const ORIG_RAX: ::c_int = 15;
+pub const RIP: ::c_int = 16;
+pub const CS: ::c_int = 17;
+pub const EFLAGS: ::c_int = 18;
+pub const RSP: ::c_int = 19;
+pub const SS: ::c_int = 20;
+pub const FS_BASE: ::c_int = 21;
+pub const GS_BASE: ::c_int = 22;
+pub const DS: ::c_int = 23;
+pub const ES: ::c_int = 24;
+pub const FS: ::c_int = 25;
+pub const GS: ::c_int = 26;
+
+pub const MAP_32BIT: ::c_int = 0x0040;
+
+pub const SIGSTKSZ: ::size_t = 8192;
+pub const MINSIGSTKSZ: ::size_t = 2048;
+
+#[doc(hidden)]
+pub const AF_MAX: ::c_int = 42;
+#[doc(hidden)]
+pub const PF_MAX: ::c_int = AF_MAX;
diff --git a/third_party/rust/libc/src/lib.rs b/third_party/rust/libc/src/lib.rs
index 366ccff1714a..b6b5cdb1618c 100644
--- a/third_party/rust/libc/src/lib.rs
+++ b/third_party/rust/libc/src/lib.rs
@@ -8,281 +8,298 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 //! Crate docs
 
 #![allow(bad_style, overflowing_literals, improper_ctypes)]
 #![crate_type = "rlib"]
 #![crate_name = "libc"]
-#![cfg_attr(dox, feature(no_core, lang_items))]
-#![cfg_attr(dox, no_core)]
+#![cfg_attr(cross_platform_docs, feature(no_core, lang_items, const_fn))]
+#![cfg_attr(cross_platform_docs, no_core)]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico")]
 
 #![cfg_attr(all(target_os = "linux", target_arch = "x86_64"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-linux-gnu"
 ))]
 #![cfg_attr(all(target_os = "linux", target_arch = "x86"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/i686-unknown-linux-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/i686-unknown-linux-gnu"
 ))]
 #![cfg_attr(all(target_os = "linux", target_arch = "arm"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/arm-unknown-linux-gnueabihf"
+    html_root_url = "https://rust-lang.github.io/libc/arm-unknown-linux-gnueabihf"
 ))]
 #![cfg_attr(all(target_os = "linux", target_arch = "mips"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/mips-unknown-linux-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/mips-unknown-linux-gnu"
 ))]
 #![cfg_attr(all(target_os = "linux", target_arch = "aarch64"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/aarch64-unknown-linux-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/aarch64-unknown-linux-gnu"
 ))]
 #![cfg_attr(all(target_os = "linux", target_env = "musl"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-linux-musl"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-linux-musl"
 ))]
 #![cfg_attr(all(target_os = "macos", target_arch = "x86_64"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-apple-darwin"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-apple-darwin"
 ))]
 #![cfg_attr(all(target_os = "macos", target_arch = "x86"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/i686-apple-darwin"
+    html_root_url = "https://rust-lang.github.io/libc/i686-apple-darwin"
 ))]
 #![cfg_attr(all(windows, target_arch = "x86_64", target_env = "gnu"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-pc-windows-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-pc-windows-gnu"
 ))]
 #![cfg_attr(all(windows, target_arch = "x86", target_env = "gnu"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/i686-pc-windows-gnu"
+    html_root_url = "https://rust-lang.github.io/libc/i686-pc-windows-gnu"
 ))]
 #![cfg_attr(all(windows, target_arch = "x86_64", target_env = "msvc"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-pc-windows-msvc"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-pc-windows-msvc"
 ))]
 #![cfg_attr(all(windows, target_arch = "x86", target_env = "msvc"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/i686-pc-windows-msvc"
+    html_root_url = "https://rust-lang.github.io/libc/i686-pc-windows-msvc"
 ))]
 #![cfg_attr(target_os = "android", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/arm-linux-androideabi"
+    html_root_url = "https://rust-lang.github.io/libc/arm-linux-androideabi"
 ))]
 #![cfg_attr(target_os = "freebsd", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-freebsd"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-freebsd"
 ))]
 #![cfg_attr(target_os = "openbsd", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-openbsd"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-openbsd"
 ))]
 #![cfg_attr(target_os = "bitrig", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-bitrig"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-bitrig"
 ))]
 #![cfg_attr(target_os = "netbsd", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-netbsd"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-netbsd"
 ))]
 #![cfg_attr(target_os = "dragonfly", doc(
-    html_root_url = "https://doc.rust-lang.org/libc/x86_64-unknown-dragonfly"
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-unknown-dragonfly"
+))]
+#![cfg_attr(target_os = "solaris", doc(
+    html_root_url = "https://rust-lang.github.io/libc/x86_64-sun-solaris"
 ))]
 #![cfg_attr(all(target_os = "emscripten", target_arch = "asmjs"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/asmjs-unknown-emscripten"
+    html_root_url = "https://rust-lang.github.io/libc/asmjs-unknown-emscripten"
 ))]
 #![cfg_attr(all(target_os = "emscripten", target_arch = "wasm32"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/wasm32-unknown-emscripten"
+    html_root_url = "https://rust-lang.github.io/libc/wasm32-unknown-emscripten"
 ))]
-#![cfg_attr(all(target_os = "linux", target_arch = "xparc64"), doc(
-    html_root_url = "https://doc.rust-lang.org/libc/sparc64-unknown-linux-gnu"
+#![cfg_attr(all(target_os = "linux", target_arch = "sparc64"), doc(
+    html_root_url = "https://rust-lang.github.io/libc/sparc64-unknown-linux-gnu"
 ))]
 
 // Attributes needed when building as part of the standard library
-#![cfg_attr(feature = "stdbuild", feature(no_std, staged_api, custom_attribute, cfg_target_vendor))]
-#![cfg_attr(feature = "stdbuild", feature(link_cfg))]
-#![cfg_attr(feature = "stdbuild", no_std)]
-#![cfg_attr(feature = "stdbuild", staged_api)]
+#![cfg_attr(feature = "stdbuild", feature(staged_api, cfg_target_vendor))]
+#![cfg_attr(feature = "stdbuild", feature(link_cfg, repr_packed))]
 #![cfg_attr(feature = "stdbuild", allow(warnings))]
 #![cfg_attr(feature = "stdbuild", unstable(feature = "libc",
                                reason = "use `libc` from crates.io",
                                issue = "27783"))]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
 
-#[cfg(all(not(dox), feature = "use_std"))]
+#[cfg(all(not(cross_platform_docs), feature = "use_std"))]
 extern crate std as core;
 
 #[macro_use] mod macros;
 mod dox;
 
-// Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable
-// more optimization opportunities around it recognizing things like
-// malloc/free.
-#[repr(u8)]
-pub enum c_void {
-    // Two dummy variants so the #[repr] attribute can be used.
-    #[doc(hidden)]
-    __variant1,
-    #[doc(hidden)]
-    __variant2,
-}
+cfg_if! {
+    if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
+        // empty ...
+    } else {
 
-pub type int8_t = i8;
-pub type int16_t = i16;
-pub type int32_t = i32;
-pub type int64_t = i64;
-pub type uint8_t = u8;
-pub type uint16_t = u16;
-pub type uint32_t = u32;
-pub type uint64_t = u64;
+        // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable
+        // more optimization opportunities around it recognizing things like
+        // malloc/free.
+        #[repr(u8)]
+        pub enum c_void {
+            // Two dummy variants so the #[repr] attribute can be used.
+            #[doc(hidden)]
+            __variant1,
+            #[doc(hidden)]
+            __variant2,
+        }
 
-pub type c_schar = i8;
-pub type c_uchar = u8;
-pub type c_short = i16;
-pub type c_ushort = u16;
-pub type c_int = i32;
-pub type c_uint = u32;
-pub type c_float = f32;
-pub type c_double = f64;
-pub type c_longlong = i64;
-pub type c_ulonglong = u64;
-pub type intmax_t = i64;
-pub type uintmax_t = u64;
+        pub type int8_t = i8;
+        pub type int16_t = i16;
+        pub type int32_t = i32;
+        pub type int64_t = i64;
+        pub type uint8_t = u8;
+        pub type uint16_t = u16;
+        pub type uint32_t = u32;
+        pub type uint64_t = u64;
 
-pub type size_t = usize;
-pub type ptrdiff_t = isize;
-pub type intptr_t = isize;
-pub type uintptr_t = usize;
-pub type ssize_t = isize;
+        pub type c_schar = i8;
+        pub type c_uchar = u8;
+        pub type c_short = i16;
+        pub type c_ushort = u16;
+        pub type c_int = i32;
+        pub type c_uint = u32;
+        pub type c_float = f32;
+        pub type c_double = f64;
+        pub type c_longlong = i64;
+        pub type c_ulonglong = u64;
+        pub type intmax_t = i64;
+        pub type uintmax_t = u64;
 
-pub enum FILE {}
-pub enum fpos_t {} // TODO: fill this out with a struct
+        pub type size_t = usize;
+        pub type ptrdiff_t = isize;
+        pub type intptr_t = isize;
+        pub type uintptr_t = usize;
+        pub type ssize_t = isize;
 
-extern {
-    pub fn isalnum(c: c_int) -> c_int;
-    pub fn isalpha(c: c_int) -> c_int;
-    pub fn iscntrl(c: c_int) -> c_int;
-    pub fn isdigit(c: c_int) -> c_int;
-    pub fn isgraph(c: c_int) -> c_int;
-    pub fn islower(c: c_int) -> c_int;
-    pub fn isprint(c: c_int) -> c_int;
-    pub fn ispunct(c: c_int) -> c_int;
-    pub fn isspace(c: c_int) -> c_int;
-    pub fn isupper(c: c_int) -> c_int;
-    pub fn isxdigit(c: c_int) -> c_int;
-    pub fn tolower(c: c_int) -> c_int;
-    pub fn toupper(c: c_int) -> c_int;
+        pub enum FILE {}
+        pub enum fpos_t {} // TODO: fill this out with a struct
 
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "fopen$UNIX2003")]
-    pub fn fopen(filename: *const c_char,
-                 mode: *const c_char) -> *mut FILE;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "freopen$UNIX2003")]
-    pub fn freopen(filename: *const c_char, mode: *const c_char,
-                   file: *mut FILE) -> *mut FILE;
-    pub fn fflush(file: *mut FILE) -> c_int;
-    pub fn fclose(file: *mut FILE) -> c_int;
-    pub fn remove(filename: *const c_char) -> c_int;
-    pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int;
-    pub fn tmpfile() -> *mut FILE;
-    pub fn setvbuf(stream: *mut FILE,
-                   buffer: *mut c_char,
-                   mode: c_int,
-                   size: size_t) -> c_int;
-    pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
-    pub fn getchar() -> c_int;
-    pub fn putchar(c: c_int) -> c_int;
-    pub fn fgetc(stream: *mut FILE) -> c_int;
-    pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char;
-    pub fn fputc(c: c_int, stream: *mut FILE) -> c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "fputs$UNIX2003")]
-    pub fn fputs(s: *const c_char, stream: *mut FILE)-> c_int;
-    pub fn puts(s: *const c_char) -> c_int;
-    pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int;
-    pub fn fread(ptr: *mut c_void,
-                 size: size_t,
-                 nobj: size_t,
-                 stream: *mut FILE)
-                 -> size_t;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "fwrite$UNIX2003")]
-    pub fn fwrite(ptr: *const c_void,
-                  size: size_t,
-                  nobj: size_t,
-                  stream: *mut FILE)
-                  -> size_t;
-    pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int;
-    pub fn ftell(stream: *mut FILE) -> c_long;
-    pub fn rewind(stream: *mut FILE);
-    #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")]
-    pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int;
-    #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")]
-    pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int;
-    pub fn feof(stream: *mut FILE) -> c_int;
-    pub fn ferror(stream: *mut FILE) -> c_int;
-    pub fn perror(s: *const c_char);
-    pub fn atoi(s: *const c_char) -> c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "strtod$UNIX2003")]
-    pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
-    pub fn strtol(s: *const c_char,
-                  endp: *mut *mut c_char, base: c_int) -> c_long;
-    pub fn strtoul(s: *const c_char, endp: *mut *mut c_char,
-                   base: c_int) -> c_ulong;
-    pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
-    pub fn malloc(size: size_t) -> *mut c_void;
-    pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
-    pub fn free(p: *mut c_void);
-    pub fn abort() -> !;
-    pub fn exit(status: c_int) -> !;
-    pub fn _exit(status: c_int) -> !;
-    pub fn atexit(cb: extern fn()) -> c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "system$UNIX2003")]
-    pub fn system(s: *const c_char) -> c_int;
-    pub fn getenv(s: *const c_char) -> *mut c_char;
+        pub const INT_MIN: c_int = -2147483648;
+        pub const INT_MAX: c_int = 2147483647;
 
-    pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char;
-    pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t)
-                   -> *mut c_char;
-    pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char;
-    pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char;
-    pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int;
-    pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int;
-    pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
-    pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char;
-    pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char;
-    pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t;
-    pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t;
-    pub fn strdup(cs: *const c_char) -> *mut c_char;
-    pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char;
-    pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
-    pub fn strlen(cs: *const c_char) -> size_t;
-    pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "strerror$UNIX2003")]
-    pub fn strerror(n: c_int) -> *mut c_char;
-    pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char;
-    pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t;
-    pub fn wcslen(buf: *const wchar_t) -> size_t;
-    pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t;
+        extern {
+            pub fn isalnum(c: c_int) -> c_int;
+            pub fn isalpha(c: c_int) -> c_int;
+            pub fn iscntrl(c: c_int) -> c_int;
+            pub fn isdigit(c: c_int) -> c_int;
+            pub fn isgraph(c: c_int) -> c_int;
+            pub fn islower(c: c_int) -> c_int;
+            pub fn isprint(c: c_int) -> c_int;
+            pub fn ispunct(c: c_int) -> c_int;
+            pub fn isspace(c: c_int) -> c_int;
+            pub fn isupper(c: c_int) -> c_int;
+            pub fn isxdigit(c: c_int) -> c_int;
+            pub fn tolower(c: c_int) -> c_int;
+            pub fn toupper(c: c_int) -> c_int;
 
-    pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
-    pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int;
-    pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
-    pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
-    pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
-}
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "fopen$UNIX2003")]
+            pub fn fopen(filename: *const c_char,
+                         mode: *const c_char) -> *mut FILE;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "freopen$UNIX2003")]
+            pub fn freopen(filename: *const c_char, mode: *const c_char,
+                           file: *mut FILE) -> *mut FILE;
+            pub fn fflush(file: *mut FILE) -> c_int;
+            pub fn fclose(file: *mut FILE) -> c_int;
+            pub fn remove(filename: *const c_char) -> c_int;
+            pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int;
+            pub fn tmpfile() -> *mut FILE;
+            pub fn setvbuf(stream: *mut FILE,
+                           buffer: *mut c_char,
+                           mode: c_int,
+                           size: size_t) -> c_int;
+            pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
+            pub fn getchar() -> c_int;
+            pub fn putchar(c: c_int) -> c_int;
+            pub fn fgetc(stream: *mut FILE) -> c_int;
+            pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char;
+            pub fn fputc(c: c_int, stream: *mut FILE) -> c_int;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "fputs$UNIX2003")]
+            pub fn fputs(s: *const c_char, stream: *mut FILE)-> c_int;
+            pub fn puts(s: *const c_char) -> c_int;
+            pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int;
+            pub fn fread(ptr: *mut c_void,
+                         size: size_t,
+                         nobj: size_t,
+                         stream: *mut FILE)
+                         -> size_t;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "fwrite$UNIX2003")]
+            pub fn fwrite(ptr: *const c_void,
+                          size: size_t,
+                          nobj: size_t,
+                          stream: *mut FILE)
+                          -> size_t;
+            pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int;
+            pub fn ftell(stream: *mut FILE) -> c_long;
+            pub fn rewind(stream: *mut FILE);
+            #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")]
+            pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int;
+            #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")]
+            pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int;
+            pub fn feof(stream: *mut FILE) -> c_int;
+            pub fn ferror(stream: *mut FILE) -> c_int;
+            pub fn perror(s: *const c_char);
+            pub fn atoi(s: *const c_char) -> c_int;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "strtod$UNIX2003")]
+            pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
+            pub fn strtol(s: *const c_char,
+                          endp: *mut *mut c_char, base: c_int) -> c_long;
+            pub fn strtoul(s: *const c_char, endp: *mut *mut c_char,
+                           base: c_int) -> c_ulong;
+            pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
+            pub fn malloc(size: size_t) -> *mut c_void;
+            pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
+            pub fn free(p: *mut c_void);
+            pub fn abort() -> !;
+            pub fn exit(status: c_int) -> !;
+            pub fn _exit(status: c_int) -> !;
+            pub fn atexit(cb: extern fn()) -> c_int;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "system$UNIX2003")]
+            pub fn system(s: *const c_char) -> c_int;
+            pub fn getenv(s: *const c_char) -> *mut c_char;
+
+            pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char;
+            pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t)
+                           -> *mut c_char;
+            pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char;
+            pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char;
+            pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int;
+            pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int;
+            pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
+            pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char;
+            pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char;
+            pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t;
+            pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t;
+            pub fn strdup(cs: *const c_char) -> *mut c_char;
+            pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char;
+            pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
+            pub fn strlen(cs: *const c_char) -> size_t;
+            pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "strerror$UNIX2003")]
+            pub fn strerror(n: c_int) -> *mut c_char;
+            pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char;
+            pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t;
+            pub fn wcslen(buf: *const wchar_t) -> size_t;
+            pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t;
 
-// These are all inline functions on android, so they end up just being entirely
-// missing on that platform.
-#[cfg(not(target_os = "android"))]
-extern {
-    pub fn abs(i: c_int) -> c_int;
-    pub fn atof(s: *const c_char) -> c_double;
-    pub fn labs(i: c_long) -> c_long;
-    pub fn rand() -> c_int;
-    pub fn srand(seed: c_uint);
+            pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
+            pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int;
+            pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
+            pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
+            pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
+        }
+
+        // These are all inline functions on android, so they end up just being entirely
+        // missing on that platform.
+        #[cfg(not(target_os = "android"))]
+        extern {
+            pub fn abs(i: c_int) -> c_int;
+            pub fn atof(s: *const c_char) -> c_double;
+            pub fn labs(i: c_long) -> c_long;
+            pub fn rand() -> c_int;
+            pub fn srand(seed: c_uint);
+        }
+    }
 }
 
 cfg_if! {
     if #[cfg(windows)] {
         mod windows;
         pub use windows::*;
     } else if #[cfg(target_os = "redox")] {
         mod redox;
         pub use redox::*;
+    } else if #[cfg(target_os = "cloudabi")] {
+        mod cloudabi;
+        pub use cloudabi::*;
+    } else if #[cfg(target_os = "fuchsia")] {
+        mod fuchsia;
+        pub use fuchsia::*;
     } else if #[cfg(unix)] {
         mod unix;
         pub use unix::*;
     } else {
         // Unknown target_family
     }
 }
diff --git a/third_party/rust/libc/src/macros.rs b/third_party/rust/libc/src/macros.rs
index 842944201441..f48ad45941f6 100644
--- a/third_party/rust/libc/src/macros.rs
+++ b/third_party/rust/libc/src/macros.rs
@@ -30,42 +30,59 @@ macro_rules! __cfg_if_items {
 
 macro_rules! __cfg_if_apply {
     ($m:meta, $($it:item)*) => {
         $(#[$m] $it)*
     }
 }
 
 macro_rules! s {
-    ($($(#[$attr:meta])* pub struct $i:ident { $($field:tt)* })*) => ($(
+    ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
         __item! {
             #[repr(C)]
             $(#[$attr])*
-            pub struct $i { $($field)* }
+            pub $t $i { $($field)* }
         }
         impl ::dox::Copy for $i {}
         impl ::dox::Clone for $i {
             fn clone(&self) -> $i { *self }
         }
     )*)
 }
 
 macro_rules! f {
     ($(pub fn $i:ident($($arg:ident: $argty:ty),*) -> $ret:ty {
         $($body:stmt);*
     })*) => ($(
         #[inline]
-        #[cfg(not(dox))]
+        #[cfg(not(cross_platform_docs))]
         pub unsafe extern fn $i($($arg: $argty),*) -> $ret {
             $($body);*
         }
 
-        #[cfg(dox)]
+        #[cfg(cross_platform_docs)]
         #[allow(dead_code)]
         pub unsafe extern fn $i($($arg: $argty),*) -> $ret {
             loop {}
         }
     )*)
 }
 
 macro_rules! __item {
     ($i:item) => ($i)
 }
+
+#[allow(unused_macros)]
+macro_rules! align_const {
+    ($($(#[$attr:meta])* pub const $name:ident : $t1:ty = $t2:ident { $($field:tt)* };)*) => ($(
+        #[cfg(feature = "align")]
+        $(#[$attr])*
+        pub const $name : $t1 = $t2 {
+            $($field)*
+        };
+        #[cfg(not(feature = "align"))]
+        $(#[$attr])*
+        pub const $name : $t1 = $t2 {
+            $($field)*
+            __align: [],
+        };
+    )*)
+}
diff --git a/third_party/rust/libc/src/redox/mod.rs b/third_party/rust/libc/src/redox/mod.rs
index 82b296f96553..e32c4b385b17 100644
--- a/third_party/rust/libc/src/redox/mod.rs
+++ b/third_party/rust/libc/src/redox/mod.rs
@@ -80,17 +80,51 @@ pub const O_CREAT: ::c_int =      0x0200_0000;
 pub const O_TRUNC: ::c_int =      0x0400_0000;
 pub const O_EXCL: ::c_int =       0x0800_0000;
 pub const O_DIRECTORY: ::c_int =  0x1000_0000;
 pub const O_STAT: ::c_int =       0x2000_0000;
 pub const O_SYMLINK: ::c_int =    0x4000_0000;
 pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
 pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;
 
+pub const SIGHUP:    ::c_int = 1;
+pub const SIGINT:    ::c_int = 2;
+pub const SIGQUIT:   ::c_int = 3;
+pub const SIGILL:    ::c_int = 4;
+pub const SIGTRAP:   ::c_int = 5;
+pub const SIGABRT:   ::c_int = 6;
+pub const SIGBUS:    ::c_int = 7;
+pub const SIGFPE:    ::c_int = 8;
+pub const SIGKILL:   ::c_int = 9;
+pub const SIGUSR1:   ::c_int = 10;
+pub const SIGSEGV:   ::c_int = 11;
+pub const SIGUSR2:   ::c_int = 12;
+pub const SIGPIPE:   ::c_int = 13;
+pub const SIGALRM:   ::c_int = 14;
+pub const SIGTERM:   ::c_int = 15;
+pub const SIGSTKFLT: ::c_int = 16;
+pub const SIGCHLD:   ::c_int = 17;
+pub const SIGCONT:   ::c_int = 18;
+pub const SIGSTOP:   ::c_int = 19;
+pub const SIGTSTP:   ::c_int = 20;
+pub const SIGTTIN:   ::c_int = 21;
+pub const SIGTTOU:   ::c_int = 22;
+pub const SIGURG:    ::c_int = 23;
+pub const SIGXCPU:   ::c_int = 24;
+pub const SIGXFSZ:   ::c_int = 25;
+pub const SIGVTALRM: ::c_int = 26;
+pub const SIGPROF:   ::c_int = 27;
+pub const SIGWINCH:  ::c_int = 28;
+pub const SIGIO:     ::c_int = 29;
+pub const SIGPWR:    ::c_int = 30;
+pub const SIGSYS:    ::c_int = 31;
+
 extern {
+    pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
+    pub fn getpid() -> pid_t;
     pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
     pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                 -> ::ssize_t;
     pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                  -> ::ssize_t;
     pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
     pub fn close(fd: ::c_int) -> ::c_int;
 }
diff --git a/third_party/rust/libc/src/redox/net.rs b/third_party/rust/libc/src/redox/net.rs
index 091691643014..fcbb181c3297 100644
--- a/third_party/rust/libc/src/redox/net.rs
+++ b/third_party/rust/libc/src/redox/net.rs
@@ -4,18 +4,20 @@ pub type in_port_t = u16;
 pub type socklen_t = u32;
 pub type sa_family_t = u16;
 
 s! {
     pub struct in_addr {
         pub s_addr: in_addr_t,
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct in6_addr {
         pub s6_addr: [u8; 16],
+        #[cfg(not(feature = "align"))]
         __align: [u32; 0],
     }
 
     pub struct ip_mreq {
         pub imr_multiaddr: in_addr,
         pub imr_interface: in_addr,
     }
 
@@ -102,9 +104,21 @@ extern {
     pub fn getsockopt(sockfd: ::c_int,
                       level: ::c_int,
                       optname: ::c_int,
                       optval: *mut ::c_void,
                       optlen: *mut ::socklen_t) -> ::c_int;
     pub fn setsockopt(socket: ::c_int, level: ::c_int, name: ::c_int,
                       value: *const ::c_void,
                       option_len: socklen_t) -> ::c_int;
+    pub fn getpeername(socket: ::c_int, address: *mut sockaddr,
+                       address_len: *mut socklen_t) -> ::c_int;
+    pub fn sendto(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                  flags: ::c_int, addr: *const sockaddr,
+                  addrlen: socklen_t) -> ::ssize_t;
+    pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
+    pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                    flags: ::c_int, addr: *mut ::sockaddr,
+                    addrlen: *mut ::socklen_t) -> ::ssize_t;
+    pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
 }
diff --git a/third_party/rust/libc/src/unix/bsd/apple/b32.rs b/third_party/rust/libc/src/unix/bsd/apple/b32.rs
index 53fc0ae19df1..5dea472ccb6b 100644
--- a/third_party/rust/libc/src/unix/bsd/apple/b32.rs
+++ b/third_party/rust/libc/src/unix/bsd/apple/b32.rs
@@ -36,16 +36,23 @@ s! {
         pub ifi_recvtiming: u32,
         pub ifi_xmittiming: u32,
         pub ifi_lastchange: ::timeval,
         pub ifi_unused2: u32,
         pub ifi_hwassist: u32,
         pub ifi_reserved1: u32,
         pub ifi_reserved2: u32,
     }
+
+    pub struct bpf_hdr {
+        pub bh_tstamp: ::timeval,
+        pub bh_caplen: ::uint32_t,
+        pub bh_datalen: ::uint32_t,
+        pub bh_hdrlen: ::c_ushort,
+    }
 }
 
 pub const __PTHREAD_MUTEX_SIZE__: usize = 40;
 pub const __PTHREAD_COND_SIZE__: usize = 24;
 pub const __PTHREAD_CONDATTR_SIZE__: usize = 4;
 pub const __PTHREAD_RWLOCK_SIZE__: usize = 124;
 pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 12;
 
diff --git a/third_party/rust/libc/src/unix/bsd/apple/b64.rs b/third_party/rust/libc/src/unix/bsd/apple/b64.rs
index e4a398194128..ca98f2095236 100644
--- a/third_party/rust/libc/src/unix/bsd/apple/b64.rs
+++ b/third_party/rust/libc/src/unix/bsd/apple/b64.rs
@@ -41,20 +41,25 @@ s! {
         pub ifi_recvtiming: u32,
         pub ifi_xmittiming: u32,
         pub ifi_lastchange: timeval32,
         pub ifi_unused2: u32,
         pub ifi_hwassist: u32,
         pub ifi_reserved1: u32,
         pub ifi_reserved2: u32,
     }
+
+    pub struct bpf_hdr {
+        pub bh_tstamp: ::timeval32,
+        pub bh_caplen: ::uint32_t,
+        pub bh_datalen: ::uint32_t,
+        pub bh_hdrlen: ::c_ushort,
+    }
 }
 
 pub const __PTHREAD_MUTEX_SIZE__: usize = 56;
 pub const __PTHREAD_COND_SIZE__: usize = 40;
 pub const __PTHREAD_CONDATTR_SIZE__: usize = 8;
 pub const __PTHREAD_RWLOCK_SIZE__: usize = 192;
 pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 16;
 
 pub const TIOCTIMESTAMP: ::c_ulong = 0x40107459;
 pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40107458;
-
-pub const FIONREAD: ::c_ulong = 0x4004667f;
diff --git a/third_party/rust/libc/src/unix/bsd/apple/mod.rs b/third_party/rust/libc/src/unix/bsd/apple/mod.rs
index 5b774703d768..cf48528b4af2 100644
--- a/third_party/rust/libc/src/unix/bsd/apple/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/apple/mod.rs
@@ -1,12 +1,13 @@
 //! Apple (ios/darwin)-specific definitions
 //!
 //! This covers *-apple-* triples currently
 
+pub type c_char = i8;
 pub type clock_t = c_ulong;
 pub type time_t = c_long;
 pub type suseconds_t = i32;
 pub type dev_t = i32;
 pub type ino_t = u64;
 pub type mode_t = u16;
 pub type nlink_t = u16;
 pub type blksize_t = i32;
@@ -18,16 +19,24 @@ pub type clockid_t = ::c_uint;
 pub type fsblkcnt_t = ::c_uint;
 pub type fsfilcnt_t = ::c_uint;
 pub type speed_t = ::c_ulong;
 pub type tcflag_t = ::c_ulong;
 pub type nl_item = ::c_int;
 pub type id_t = ::c_uint;
 pub type sem_t = ::c_int;
 pub type idtype_t = ::c_uint;
+pub type integer_t = ::c_int;
+pub type cpu_type_t = integer_t;
+pub type cpu_subtype_t = integer_t;
+pub type vm_prot_t = ::c_int;
+pub type posix_spawnattr_t = *mut ::c_void;
+pub type posix_spawn_file_actions_t = *mut ::c_void;
+pub type key_t = ::c_int;
+pub type shmatt_t = ::c_ushort;
 
 pub enum timezone {}
 
 s! {
     pub struct aiocb {
         pub aio_fildes: ::c_int,
         pub aio_offset: ::off_t,
         pub aio_buf: *mut ::c_void,
@@ -231,17 +240,17 @@ s! {
         pub f_flags: ::uint32_t,
         pub f_fssubtype: ::uint32_t,
         pub f_fstypename: [::c_char; 16],
         pub f_mntonname: [::c_char; 1024],
         pub f_mntfromname: [::c_char; 1024],
         pub f_reserved: [::uint32_t; 8],
     }
 
-    // FIXME: this should have align 4 but it's got align 8 on 64-bit
+    #[cfg_attr(feature = "stdbuild", repr(packed(4)))]
     pub struct kevent {
         pub ident: ::uintptr_t,
         pub filter: ::int16_t,
         pub flags: ::uint16_t,
         pub fflags: ::uint32_t,
         pub data: ::intptr_t,
         pub udata: *mut ::c_void,
     }
@@ -413,16 +422,146 @@ s! {
     }
 
     pub struct xucred {
         pub cr_version: ::c_uint,
         pub cr_uid: ::uid_t,
         pub cr_ngroups: ::c_short,
         pub cr_groups: [::gid_t;16]
     }
+
+    pub struct mach_header {
+        pub magic: u32,
+        pub cputype: cpu_type_t,
+        pub cpusubtype: cpu_subtype_t,
+        pub filetype: u32,
+        pub ncmds: u32,
+        pub sizeofcmds: u32,
+        pub flags: u32,
+    }
+
+    pub struct mach_header_64 {
+        pub magic: u32,
+        pub cputype: cpu_type_t,
+        pub cpusubtype: cpu_subtype_t,
+        pub filetype: u32,
+        pub ncmds: u32,
+        pub sizeofcmds: u32,
+        pub flags: u32,
+        pub reserved: u32,
+    }
+
+    pub struct segment_command {
+        pub cmd: u32,
+        pub cmdsize: u32,
+        pub segname: [::c_char; 16],
+        pub vmaddr: u32,
+        pub vmsize: u32,
+        pub fileoff: u32,
+        pub filesize: u32,
+        pub maxprot: vm_prot_t,
+        pub initprot: vm_prot_t,
+        pub nsects: u32,
+        pub flags: u32,
+    }
+
+    pub struct segment_command_64 {
+        pub cmd: u32,
+        pub cmdsize: u32,
+        pub segname: [::c_char; 16],
+        pub vmaddr: u64,
+        pub vmsize: u64,
+        pub fileoff: u64,
+        pub filesize: u64,
+        pub maxprot: vm_prot_t,
+        pub initprot: vm_prot_t,
+        pub nsects: u32,
+        pub flags: u32,
+    }
+
+    pub struct load_command {
+        pub cmd: u32,
+        pub cmdsize: u32,
+    }
+
+    pub struct sockaddr_dl {
+        pub sdl_len: ::c_uchar,
+        pub sdl_family: ::c_uchar,
+        pub sdl_index: ::c_ushort,
+        pub sdl_type: ::c_uchar,
+        pub sdl_nlen: ::c_uchar,
+        pub sdl_alen: ::c_uchar,
+        pub sdl_slen: ::c_uchar,
+        pub sdl_data: [::c_char; 12],
+    }
+
+    pub struct sockaddr_inarp {
+        pub sin_len: ::c_uchar,
+        pub sin_family: ::c_uchar,
+        pub sin_port: ::c_ushort,
+        pub sin_addr: ::in_addr,
+        pub sin_srcaddr: ::in_addr,
+        pub sin_tos: ::c_ushort,
+        pub sin_other: ::c_ushort,
+    }
+
+    pub struct sockaddr_ctl {
+        pub sc_len: ::c_uchar,
+        pub sc_family: ::c_uchar,
+        pub ss_sysaddr: ::uint16_t,
+        pub sc_id: ::uint32_t,
+        pub sc_unit: ::uint32_t,
+        pub sc_reserved: [::uint32_t; 5],
+    }
+
+    pub struct in_pktinfo {
+        pub ipi_ifindex: ::c_uint,
+        pub ipi_spec_dst: ::in_addr,
+        pub ipi_addr: ::in_addr,
+    }
+
+    pub struct in6_pktinfo {
+        pub ipi6_addr: ::in6_addr,
+        pub ipi6_ifindex: ::c_uint,
+    }
+
+    // sys/ipc.h:
+
+    pub struct ipc_perm {
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub _seq: ::c_ushort,
+        pub _key: ::key_t,
+    }
+
+    #[cfg_attr(feature = "stdbuild", repr(packed(4)))]
+    pub struct shmid_ds {
+        pub shm_perm: ipc_perm,
+        pub shm_segsz: ::size_t,
+        pub shm_lpid: ::pid_t,
+        pub shm_cpid: ::pid_t,
+        pub shm_nattch: ::shmatt_t,
+        pub shm_atime: ::time_t,  // FIXME: 64-bit wrong align => wrong offset
+        pub shm_dtime: ::time_t,  // FIXME: 64-bit wrong align => wrong offset
+        pub shm_ctime: ::time_t,  // FIXME: 64-bit wrong align => wrong offset
+        // FIXME: 64-bit wrong align => wrong offset:
+        pub shm_internal: *mut ::c_void,
+
+    }
+
+    pub struct arphdr {
+        pub ar_hrd: u16,
+        pub ar_pro: u16,
+        pub ar_hln: u8,
+        pub ar_pln: u8,
+        pub ar_op: u16,
+    }
 }
 
 pub const _UTX_USERSIZE: usize = 256;
 pub const _UTX_LINESIZE: usize = 32;
 pub const _UTX_IDSIZE: usize = 4;
 pub const _UTX_HOSTSIZE: usize = 256;
 
 pub const EMPTY: ::c_short = 0;
@@ -621,26 +760,18 @@ pub const VM_FLAGS_RANDOM_ADDR: ::c_int = 0x0008;
 pub const VM_FLAGS_NO_CACHE: ::c_int = 0x0010;
 pub const VM_FLAGS_RESILIENT_CODESIGN: ::c_int = 0x0020;
 pub const VM_FLAGS_RESILIENT_MEDIA: ::c_int = 0x0040;
 pub const VM_FLAGS_OVERWRITE: ::c_int = 0x4000;
 pub const VM_FLAGS_SUPERPAGE_MASK: ::c_int = 0x70000;
 pub const VM_FLAGS_RETURN_DATA_ADDR: ::c_int = 0x100000;
 pub const VM_FLAGS_RETURN_4K_DATA_ADDR: ::c_int = 0x800000;
 pub const VM_FLAGS_ALIAS_MASK: ::c_int = 0xFF000000;
-pub const VM_FLAGS_USER_ALLOCATE: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE |
-                                            VM_FLAGS_PURGABLE |
-                                            VM_FLAGS_RANDOM_ADDR |
-                                            VM_FLAGS_NO_CACHE |
-                                            VM_FLAGS_OVERWRITE |
-                                            VM_FLAGS_SUPERPAGE_MASK |
-                                            VM_FLAGS_ALIAS_MASK;
-pub const VM_FLAGS_USER_MAP: ::c_int = VM_FLAGS_USER_ALLOCATE |
-                                       VM_FLAGS_RETURN_4K_DATA_ADDR |
-                                       VM_FLAGS_RETURN_DATA_ADDR;
+pub const VM_FLAGS_USER_ALLOCATE: ::c_int = 0xff07401b;
+pub const VM_FLAGS_USER_MAP: ::c_int = 0xff97401b;
 pub const VM_FLAGS_USER_REMAP: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE |
                                         VM_FLAGS_RANDOM_ADDR |
                                         VM_FLAGS_OVERWRITE |
                                         VM_FLAGS_RETURN_DATA_ADDR |
                                         VM_FLAGS_RESILIENT_CODESIGN;
 
 pub const VM_FLAGS_SUPERPAGE_SHIFT: ::c_int = 16;
 pub const SUPERPAGE_NONE: ::c_int = 0;
@@ -836,17 +967,27 @@ pub const EPROTO: ::c_int = 100;
 pub const ETIME: ::c_int = 101;
 pub const EOPNOTSUPP: ::c_int = 102;
 pub const ENOPOLICY: ::c_int = 103;
 pub const ENOTRECOVERABLE: ::c_int = 104;
 pub const EOWNERDEAD: ::c_int = 105;
 pub const EQFULL: ::c_int = 106;
 pub const ELAST: ::c_int = 106;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
 
 pub const F_DUPFD: ::c_int = 0;
 pub const F_DUPFD_CLOEXEC: ::c_int = 67;
 pub const F_GETFD: ::c_int = 1;
 pub const F_SETFD: ::c_int = 2;
 pub const F_GETFL: ::c_int = 3;
 pub const F_SETFL: ::c_int = 4;
 pub const F_PREALLOCATE: ::c_int = 42;
@@ -931,16 +1072,23 @@ pub const TIOCMSDTRWAIT: ::c_ulong = 0x8004745b;
 pub const TIOCMGDTRWAIT: ::c_ulong = 0x4004745a;
 pub const TIOCSDRAINWAIT: ::c_ulong = 0x80047457;
 pub const TIOCGDRAINWAIT: ::c_ulong = 0x40047456;
 pub const TIOCDSIMICROCODE: ::c_uint = 0x20007455;
 pub const TIOCPTYGRANT: ::c_uint = 0x20007454;
 pub const TIOCPTYGNAME: ::c_uint = 0x40807453;
 pub const TIOCPTYUNLK: ::c_uint = 0x20007452;
 
+pub const FIONCLEX: ::c_uint = 0x20006602;
+pub const FIONREAD: ::c_ulong = 0x4004667f;
+pub const FIOASYNC: ::c_ulong = 0x8004667d;
+pub const FIOSETOWN: ::c_ulong = 0x8004667c;
+pub const FIOGETOWN: ::c_ulong = 0x4004667b;
+pub const FIODTYPE: ::c_ulong = 0x4004667a;
+
 pub const B0: speed_t = 0;
 pub const B50: speed_t = 50;
 pub const B75: speed_t = 75;
 pub const B110: speed_t = 110;
 pub const B134: speed_t = 134;
 pub const B150: speed_t = 150;
 pub const B200: speed_t = 200;
 pub const B300: speed_t = 300;
@@ -1005,16 +1153,17 @@ pub const _SC_XOPEN_CRYPT: ::c_int = 108;
 pub const _SC_XOPEN_ENH_I18N: ::c_int = 109;
 pub const _SC_XOPEN_LEGACY: ::c_int = 110;
 pub const _SC_XOPEN_REALTIME: ::c_int = 111;
 pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 112;
 pub const _SC_XOPEN_SHM: ::c_int = 113;
 pub const _SC_XOPEN_UNIX: ::c_int = 115;
 pub const _SC_XOPEN_VERSION: ::c_int = 116;
 pub const _SC_XOPEN_XCU_VERSION: ::c_int = 121;
+pub const _SC_PHYS_PAGES: ::c_int = 200;
 
 pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 2;
 pub const PTHREAD_PROCESS_SHARED: ::c_int = 1;
 pub const PTHREAD_CREATE_JOINABLE: ::c_int = 1;
 pub const PTHREAD_CREATE_DETACHED: ::c_int = 2;
 pub const PTHREAD_STACK_MIN: ::size_t = 8192;
 
 pub const RLIMIT_CPU: ::c_int = 0;
@@ -1058,17 +1207,17 @@ pub const MINCORE_MODIFIED_OTHER: ::c_int = 0x10;
 // NOTE: These are in addition to the constants defined in src/unix/mod.rs
 
 // IPPROTO_IP defined in src/unix/mod.rs
 /// IP6 hop-by-hop options
 pub const IPPROTO_HOPOPTS: ::c_int = 0;
 // IPPROTO_ICMP defined in src/unix/mod.rs
 /// group mgmt protocol
 pub const IPPROTO_IGMP: ::c_int = 2;
-/// gateway^2 (deprecated)
+/// gateway<sup>2</sup> (deprecated)
 pub const IPPROTO_GGP: ::c_int = 3;
 /// for compatibility
 pub const IPPROTO_IPIP: ::c_int = 4;
 // IPPROTO_TCP defined in src/unix/mod.rs
 /// Stream protocol II.
 pub const IPPROTO_ST: ::c_int = 7;
 /// exterior gateway protocol
 pub const IPPROTO_EGP: ::c_int = 8;
@@ -1368,18 +1517,21 @@ pub const SOCK_STREAM: ::c_int = 1;
 pub const SOCK_DGRAM: ::c_int = 2;
 pub const SOCK_RAW: ::c_int = 3;
 pub const SOCK_RDM: ::c_int = 4;
 pub const SOCK_SEQPACKET: ::c_int = 5;
 pub const IP_TTL: ::c_int = 4;
 pub const IP_HDRINCL: ::c_int = 2;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
+pub const IP_PKTINFO: ::c_int = 26;
 pub const IPV6_JOIN_GROUP: ::c_int = 12;
 pub const IPV6_LEAVE_GROUP: ::c_int = 13;
+pub const IPV6_PKTINFO: ::c_int = 46;
+pub const IPV6_RECVPKTINFO: ::c_int = 61;
 
 pub const TCP_NODELAY: ::c_int = 0x01;
 pub const TCP_KEEPALIVE: ::c_int = 0x10;
 
 pub const SOL_LOCAL: ::c_int = 0;
 
 pub const LOCAL_PEERCRED: ::c_int = 0x001;
 pub const LOCAL_PEERPID: ::c_int = 0x002;
@@ -1438,17 +1590,34 @@ pub const MSG_HOLD: ::c_int = 0x800;
 pub const MSG_SEND: ::c_int = 0x1000;
 pub const MSG_HAVEMORE: ::c_int = 0x2000;
 pub const MSG_RCVMORE: ::c_int = 0x4000;
 // pub const MSG_COMPAT: ::c_int = 0x8000;
 
 pub const SCM_TIMESTAMP: ::c_int = 0x02;
 pub const SCM_CREDS: ::c_int = 0x03;
 
-pub const IFF_LOOPBACK: ::c_int = 0x8;
+// https://github.com/aosm/xnu/blob/master/bsd/net/if.h#L140-L156
+pub const IFF_UP: ::c_int          = 0x1;  // interface is up
+pub const IFF_BROADCAST: ::c_int   = 0x2;  // broadcast address valid
+pub const IFF_DEBUG: ::c_int       = 0x4;  // turn on debugging
+pub const IFF_LOOPBACK: ::c_int    = 0x8;  // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link
+pub const IFF_NOTRAILERS: ::c_int  = 0x20; // obsolete: avoid use of trailers
+pub const IFF_RUNNING: ::c_int     = 0x40; // resources allocated
+pub const IFF_NOARP: ::c_int       = 0x80; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int     = 0x100;// receive all packets
+pub const IFF_ALLMULTI: ::c_int    = 0x200;// receive all multicast packets
+pub const IFF_OACTIVE: ::c_int     = 0x400;// transmission in progress
+pub const IFF_SIMPLEX: ::c_int     = 0x800;// can't hear own transmissions
+pub const IFF_LINK0: ::c_int       = 0x1000;// per link layer defined bit
+pub const IFF_LINK1: ::c_int   = 0x2000;// per link layer defined bit
+pub const IFF_LINK2: ::c_int   = 0x4000;// per link layer defined bit
+pub const IFF_ALTPHYS: ::c_int = IFF_LINK2;// use alternate physical connection
+pub const IFF_MULTICAST: ::c_int = 0x8000;// supports multicast
 
 pub const SHUT_RD: ::c_int = 0;
 pub const SHUT_WR: ::c_int = 1;
 pub const SHUT_RDWR: ::c_int = 2;
 
 pub const LOCK_SH: ::c_int = 1;
 pub const LOCK_EX: ::c_int = 2;
 pub const LOCK_NB: ::c_int = 4;
@@ -1693,16 +1862,19 @@ pub const VT1: ::c_int  = 0x00010000;
 pub const IUTF8: ::tcflag_t = 0x00004000;
 pub const CRTSCTS: ::tcflag_t = 0x00030000;
 
 pub const NI_MAXHOST: ::socklen_t = 1025;
 
 pub const Q_GETQUOTA: ::c_int = 0x300;
 pub const Q_SETQUOTA: ::c_int = 0x400;
 
+pub const RENAME_SWAP: ::c_uint = 0x00000002;
+pub const RENAME_EXCL: ::c_uint = 0x00000004;
+
 pub const RTLD_LOCAL: ::c_int = 0x4;
 pub const RTLD_FIRST: ::c_int = 0x100;
 pub const RTLD_NODELETE: ::c_int = 0x80;
 pub const RTLD_NOLOAD: ::c_int = 0x10;
 pub const RTLD_GLOBAL: ::c_int = 0x8;
 
 pub const _WSTOPPED: ::c_int = 0o177;
 
@@ -1950,28 +2122,171 @@ pub const P_PGID: idtype_t = 2;
 pub const XATTR_NOFOLLOW: ::c_int = 0x0001;
 pub const XATTR_CREATE: ::c_int = 0x0002;
 pub const XATTR_REPLACE: ::c_int = 0x0004;
 pub const XATTR_NOSECURITY: ::c_int = 0x0008;
 pub const XATTR_NODEFAULT: ::c_int = 0x0010;
 pub const XATTR_SHOWCOMPRESSION: ::c_int = 0x0020;
 
 pub const NET_RT_IFLIST2: ::c_int = 0x0006;
-pub const RTM_IFINFO2: ::c_int = 0x0012;
+
+// net/route.h
+pub const RTF_UP: ::c_int = 0x1;
+pub const RTF_GATEWAY: ::c_int = 0x2;
+pub const RTF_HOST: ::c_int = 0x4;
+pub const RTF_REJECT: ::c_int = 0x8;
+pub const RTF_DYNAMIC: ::c_int = 0x10;
+pub const RTF_MODIFIED: ::c_int = 0x20;
+pub const RTF_DONE: ::c_int = 0x40;
+pub const RTF_DELCLONE: ::c_int = 0x80;
+pub const RTF_CLONING: ::c_int = 0x100;
+pub const RTF_XRESOLVE: ::c_int = 0x200;
+pub const RTF_LLINFO: ::c_int = 0x400;
+pub const RTF_STATIC: ::c_int = 0x800;
+pub const RTF_BLACKHOLE: ::c_int = 0x1000;
+pub const RTF_NOIFREF: ::c_int = 0x2000;
+pub const RTF_PROTO2: ::c_int = 0x4000;
+pub const RTF_PROTO1: ::c_int = 0x8000;
+pub const RTF_PRCLONING: ::c_int = 0x10000;
+pub const RTF_WASCLONED: ::c_int = 0x20000;
+pub const RTF_PROTO3: ::c_int = 0x40000;
+pub const RTF_PINNED: ::c_int = 0x100000;
+pub const RTF_LOCAL: ::c_int = 0x200000;
+pub const RTF_BROADCAST: ::c_int = 0x400000;
+pub const RTF_MULTICAST: ::c_int = 0x800000;
+pub const RTF_IFSCOPE: ::c_int = 0x1000000;
+pub const RTF_CONDEMNED: ::c_int = 0x2000000;
+pub const RTF_IFREF: ::c_int = 0x4000000;
+pub const RTF_PROXY: ::c_int = 0x8000000;
+pub const RTF_ROUTER: ::c_int = 0x10000000;
+
+pub const RTM_VERSION: ::c_int = 5;
+
+// Message types
+pub const RTM_ADD: ::c_int = 0x1;
+pub const RTM_DELETE: ::c_int = 0x2;
+pub const RTM_CHANGE: ::c_int = 0x3;
+pub const RTM_GET: ::c_int = 0x4;
+pub const RTM_LOSING: ::c_int = 0x5;
+pub const RTM_REDIRECT: ::c_int = 0x6;
+pub const RTM_MISS: ::c_int = 0x7;
+pub const RTM_LOCK: ::c_int = 0x8;
+pub const RTM_OLDADD: ::c_int = 0x9;
+pub const RTM_OLDDEL: ::c_int = 0xa;
+pub const RTM_RESOLVE: ::c_int = 0xb;
+pub const RTM_NEWADDR: ::c_int = 0xc;
+pub const RTM_DELADDR: ::c_int = 0xd;
+pub const RTM_IFINFO: ::c_int = 0xe;
+pub const RTM_NEWMADDR: ::c_int = 0xf;
+pub const RTM_DELMADDR: ::c_int = 0x10;
+pub const RTM_IFINFO2: ::c_int = 0x12;
+pub const RTM_NEWMADDR2: ::c_int = 0x13;
+pub const RTM_GET2: ::c_int = 0x14;
+
+// Bitmask values for rtm_inits and rmx_locks.
+pub const RTV_MTU: ::c_int = 0x1;
+pub const RTV_HOPCOUNT: ::c_int = 0x2;
+pub const RTV_EXPIRE: ::c_int = 0x4;
+pub const RTV_RPIPE: ::c_int = 0x8;
+pub const RTV_SPIPE: ::c_int = 0x10;
+pub const RTV_SSTHRESH: ::c_int = 0x20;
+pub const RTV_RTT: ::c_int = 0x40;
+pub const RTV_RTTVAR: ::c_int = 0x80;
+
+// Bitmask values for rtm_addrs.
+pub const RTA_DST: ::c_int = 0x1;
+pub const RTA_GATEWAY: ::c_int = 0x2;
+pub const RTA_NETMASK: ::c_int = 0x4;
+pub const RTA_GENMASK: ::c_int = 0x8;
+pub const RTA_IFP: ::c_int = 0x10;
+pub const RTA_IFA: ::c_int = 0x20;
+pub const RTA_AUTHOR: ::c_int = 0x40;
+pub const RTA_BRD: ::c_int = 0x80;
+
+// Index offsets for sockaddr array for alternate internal encoding.
+pub const RTAX_DST: ::c_int = 0;
+pub const RTAX_GATEWAY: ::c_int = 1;
+pub const RTAX_NETMASK: ::c_int = 2;
+pub const RTAX_GENMASK: ::c_int = 3;
+pub const RTAX_IFP: ::c_int = 4;
+pub const RTAX_IFA: ::c_int = 5;
+pub const RTAX_AUTHOR: ::c_int = 6;
+pub const RTAX_BRD: ::c_int = 7;
+pub const RTAX_MAX: ::c_int = 8;
 
 pub const KERN_PROCARGS2: ::c_int = 49;
 
 pub const PROC_PIDTASKALLINFO: ::c_int = 2;
 pub const PROC_PIDTASKINFO: ::c_int = 4;
 pub const PROC_PIDTHREADINFO: ::c_int = 5;
 pub const MAXCOMLEN: usize = 16;
 pub const MAXTHREADNAMESIZE: usize = 64;
 
 pub const XUCRED_VERSION: ::c_uint = 0;
 
+pub const LC_SEGMENT: u32 = 0x1;
+pub const LC_SEGMENT_64: u32 = 0x19;
+
+pub const MH_MAGIC: u32 = 0xfeedface;
+pub const MH_MAGIC_64: u32 = 0xfeedfacf;
+
+// net/if_utun.h
+pub const UTUN_OPT_FLAGS: ::c_int = 1;
+pub const UTUN_OPT_IFNAME: ::c_int = 2;
+
+// net/bpf.h
+pub const DLT_NULL: ::c_uint = 0;         // no link-layer encapsulation
+pub const DLT_EN10MB: ::c_uint = 1;       // Ethernet (10Mb)
+pub const DLT_EN3MB: ::c_uint = 2;        // Experimental Ethernet (3Mb)
+pub const DLT_AX25: ::c_uint = 3;         // Amateur Radio AX.25
+pub const DLT_PRONET: ::c_uint = 4;       // Proteon ProNET Token Ring
+pub const DLT_CHAOS: ::c_uint = 5;        // Chaos
+pub const DLT_IEEE802: ::c_uint = 6;      // IEEE 802 Networks
+pub const DLT_ARCNET: ::c_uint = 7;       // ARCNET
+pub const DLT_SLIP: ::c_uint = 8;         // Serial Line IP
+pub const DLT_PPP: ::c_uint = 9;          // Point-to-point Protocol
+pub const DLT_FDDI: ::c_uint = 10;        // FDDI
+pub const DLT_ATM_RFC1483: ::c_uint = 11; // LLC/SNAP encapsulated atm
+pub const DLT_RAW: ::c_uint = 12;         // raw IP
+pub const DLT_LOOP: ::c_uint = 108;
+
+// https://github.com/apple/darwin-xnu/blob/master/bsd/net/bpf.h#L100
+// sizeof(int32_t)
+pub const BPF_ALIGNMENT: ::c_int = 4;
+
+// sys/spawn.h:
+pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01;
+pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02;
+pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x04;
+pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x08;
+pub const POSIX_SPAWN_SETEXEC: ::c_int = 0x40;
+pub const POSIX_SPAWN_START_SUSPENDED: ::c_int = 0x80;
+pub const POSIX_SPAWN_CLOEXEC_DEFAULT: ::c_int = 0x4000;
+
+// sys/ipc.h:
+pub const IPC_CREAT: ::c_int = 0x200;
+pub const IPC_EXCL: ::c_int = 0x400;
+pub const IPC_NOWAIT: ::c_int = 0x800;
+pub const IPC_PRIVATE: key_t = 0;
+
+pub const IPC_RMID: ::c_int = 0;
+pub const IPC_SET: ::c_int = 1;
+pub const IPC_STAT: ::c_int = 2;
+
+pub const IPC_R: ::c_int = 0x100;
+pub const IPC_W: ::c_int = 0x80;
+pub const IPC_M: ::c_int = 0x1000;
+
+// sys/shm.h
+pub const SHM_RDONLY: ::c_int = 0x1000;
+pub const SHM_RND: ::c_int = 0x2000;
+pub const SHMLBA: ::c_int = 4096;
+pub const SHM_R: ::c_int = IPC_R;
+pub const SHM_W: ::c_int = IPC_W;
+
 f! {
     pub fn WSTOPSIG(status: ::c_int) -> ::c_int {
         status >> 8
     }
 
     pub fn _WSTATUS(status: ::c_int) -> ::c_int {
         status & 0x7f
     }
@@ -2030,16 +2345,24 @@ extern {
                            mibp: *mut ::c_int,
                            sizep: *mut ::size_t)
                            -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "mprotect$UNIX2003")]
     pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int)
                     -> ::c_int;
     pub fn shm_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::c_int;
+    pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void,
+                 shmflg: ::c_int) -> *mut ::c_void;
+    pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int;
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+               link_name = "shmctl$UNIX2003")]
+    pub fn shmctl(shmid: ::c_int, cmd: ::c_int,
+                  buf: *mut ::shmid_ds) -> ::c_int;
+    pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int;
     pub fn sysctl(name: *mut ::c_int,
                   namelen: ::c_uint,
                   oldp: *mut ::c_void,
                   oldlenp: *mut ::size_t,
                   newp: *mut ::c_void,
                   newlen: ::size_t)
                   -> ::c_int;
     pub fn sysctlbyname(name: *const ::c_char,
@@ -2118,17 +2441,18 @@ extern {
     pub fn localeconv_l(loc: ::locale_t) -> *mut lconv;
     pub fn newlocale(mask: ::c_int,
                      locale: *const ::c_char,
                      base: ::locale_t) -> ::locale_t;
     pub fn uselocale(loc: ::locale_t) -> ::locale_t;
     pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char;
     pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
     pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
-
+    pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int;
+    pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int;
     pub fn getxattr(path: *const ::c_char, name: *const ::c_char,
                     value: *mut ::c_void, size: ::size_t, position: u32,
                     flags: ::c_int) -> ::ssize_t;
     pub fn fgetxattr(filedes: ::c_int, name: *const ::c_char,
                      value: *mut ::c_void, size: ::size_t, position: u32,
                      flags: ::c_int) -> ::ssize_t;
     pub fn setxattr(path: *const ::c_char, name: *const ::c_char,
                     value: *const ::c_void, size: ::size_t, position: u32,
@@ -2137,32 +2461,95 @@ extern {
                      value: *const ::c_void, size: ::size_t, position: u32,
                      flags: ::c_int) -> ::c_int;
     pub fn listxattr(path: *const ::c_char, list: *mut ::c_char,
                      size: ::size_t, flags: ::c_int) -> ::ssize_t;
     pub fn flistxattr(filedes: ::c_int, list: *mut ::c_char,
                       size: ::size_t, flags: ::c_int) -> ::ssize_t;
     pub fn removexattr(path: *const ::c_char, name: *const ::c_char,
                        flags: ::c_int) -> ::c_int;
+    pub fn renamex_np(from: *const ::c_char, to: *const ::c_char,
+                      flags: ::c_uint) -> ::c_int;
+    pub fn renameatx_np(fromfd: ::c_int, from: *const ::c_char,
+                        tofd: ::c_int, to: *const ::c_char,
+                        flags: ::c_uint) -> ::c_int;
     pub fn fremovexattr(filedes: ::c_int, name: *const ::c_char,
                         flags: ::c_int) -> ::c_int;
 
     pub fn getgrouplist(name: *const ::c_char,
                         basegid: ::c_int,
                         groups: *mut ::c_int,
                         ngroups: *mut ::c_int) -> ::c_int;
     pub fn initgroups(user: *const ::c_char, basegroup: ::c_int) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "waitid$UNIX2003")]
     pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t,
                   options: ::c_int) -> ::c_int;
     pub fn brk(addr: *const ::c_void) -> *mut ::c_void;
     pub fn sbrk(increment: ::c_int) -> *mut ::c_void;
     pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int;
+    pub fn _dyld_image_count() -> u32;
+    pub fn _dyld_get_image_header(image_index: u32) -> *const mach_header;
+    pub fn _dyld_get_image_vmaddr_slide(image_index: u32) -> ::intptr_t;
+    pub fn _dyld_get_image_name(image_index: u32) -> *const ::c_char;
+
+    pub fn posix_spawn(pid: *mut ::pid_t,
+                       path: *const ::c_char,
+                       file_actions: *const ::posix_spawn_file_actions_t,
+                       attrp: *const ::posix_spawnattr_t,
+                       argv: *const *mut ::c_char,
+                       envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnp(pid: *mut ::pid_t,
+                       file: *const ::c_char,
+                        file_actions: *const ::posix_spawn_file_actions_t,
+                        attrp: *const ::posix_spawnattr_t,
+                        argv: *const *mut ::c_char,
+                        envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigdefault(attr: *const posix_spawnattr_t,
+                                         default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigdefault(attr: *mut posix_spawnattr_t,
+                                         default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigmask(attr: *const posix_spawnattr_t,
+                                      default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigmask(attr: *mut posix_spawnattr_t,
+                                      default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t,
+                                    flags: *mut ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t,
+                                    flags: ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_getpgroup(attr: *const posix_spawnattr_t,
+                                     flags: *mut ::pid_t) -> ::c_int;
+    pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t,
+                                     flags: ::pid_t) -> ::c_int;
+
+    pub fn posix_spawn_file_actions_init(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_destroy(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addopen(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        path: *const ::c_char,
+        oflag: ::c_int,
+        mode: ::mode_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addclose(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_adddup2(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        newfd: ::c_int,
+    ) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(any(target_arch = "arm", target_arch = "x86"))] {
         mod b32;
         pub use self::b32::*;
     } else if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] {
         mod b64;
diff --git a/third_party/rust/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/third_party/rust/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index ebfcd4b9d8a3..9e1082e53bf8 100644
--- a/third_party/rust/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -1,10 +1,11 @@
 pub type clock_t = u64;
 pub type ino_t = u64;
+pub type lwpid_t = i32;
 pub type nlink_t = u32;
 pub type blksize_t = i64;
 pub type clockid_t = ::c_ulong;
 
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type time_t = i64;
 pub type suseconds_t = i64;
@@ -67,16 +68,23 @@ s! {
         pub time_low: u32,
         pub time_mid: u16,
         pub time_hi_and_version: u16,
         pub clock_seq_hi_and_reserved: u8,
         pub clock_seq_low: u8,
         pub node: [u8; 6],
     }
 
+    pub struct mq_attr {
+        pub mq_flags: ::c_long,
+        pub mq_maxmsg: ::c_long,
+        pub mq_msgsize: ::c_long,
+        pub mq_curmsgs: ::c_long,
+    }
+
     pub struct sigevent {
         pub sigev_notify: ::c_int,
         // The union is 8-byte in size, so it is aligned at a 8-byte offset.
         #[cfg(target_pointer_width = "64")]
         __unused1: ::c_int,
         pub sigev_signo: ::c_int,       //actually a union
         // pad the union
         #[cfg(target_pointer_width = "64")]
@@ -102,16 +110,37 @@ s! {
         pub f_syncreads: u64,
         pub f_syncwrites: u64,
         pub f_asyncreads: u64,
         pub f_asyncwrites: u64,
         pub f_fsid_uuid: ::uuid_t,
         pub f_uid_uuid: ::uuid_t,
     }
 
+    pub struct statfs {
+        pub f_bsize: ::c_long,
+        pub f_iosize: ::c_long,
+        pub f_blocks: ::c_long,
+        pub f_bfree: ::c_long,
+        pub f_bavail: ::c_long,
+        pub f_files: ::c_long,
+        pub f_ffree: ::c_long,
+        pub f_fsid: ::fsid_t,
+        pub f_owner: ::uid_t,
+        pub f_type: ::int32_t,
+        pub f_flags: ::int32_t,
+        pub f_syncwrites: ::c_long,
+        pub f_asyncwrites: ::c_long,
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntonname: [::c_char; 90],
+        pub f_syncreads: ::c_long,
+        pub f_asyncreads: ::c_long,
+        pub f_mntfromname: [::c_char; 90],
+    }
+
     pub struct stat {
         pub st_ino: ::ino_t,
         pub st_nlink: ::nlink_t,
         pub st_dev: ::dev_t,
         pub st_mode: ::mode_t,
         pub st_padding1: ::uint16_t,
         pub st_uid: ::uid_t,
         pub st_gid: ::gid_t,
@@ -163,22 +192,36 @@ s! {
         pub ifm_msglen: ::c_ushort,
         pub ifm_version: ::c_uchar,
         pub ifm_type: ::c_uchar,
         pub ifm_addrs: ::c_int,
         pub ifm_flags: ::c_int,
         pub ifm_index: ::c_ushort,
         pub ifm_data: if_data,
     }
+
+    pub struct sockaddr_dl {
+        pub sdl_len: ::c_uchar,
+        pub sdl_family: ::c_uchar,
+        pub sdl_index: ::c_ushort,
+        pub sdl_type: ::c_uchar,
+        pub sdl_nlen: ::c_uchar,
+        pub sdl_alen: ::c_uchar,
+        pub sdl_slen: ::c_uchar,
+        pub sdl_data: [::c_char; 12],
+        pub sdl_rcf: ::c_ushort,
+        pub sdl_route: [::c_ushort; 16],
+    }
 }
 
 pub const RAND_MAX: ::c_int = 0x7fff_ffff;
 pub const PTHREAD_STACK_MIN: ::size_t = 16384;
 pub const SIGSTKSZ: ::size_t = 40960;
 pub const MADV_INVAL: ::c_int = 10;
+pub const MADV_SETMAP: ::c_int = 11;
 pub const O_CLOEXEC: ::c_int = 0x00020000;
 pub const O_DIRECTORY: ::c_int = 0x08000000;
 pub const F_GETLK: ::c_int = 7;
 pub const F_SETLK: ::c_int = 8;
 pub const F_SETLKW: ::c_int = 9;
 pub const ELAST: ::c_int = 99;
 pub const RLIMIT_POSIXLOCKS: ::c_int = 11;
 pub const RLIM_NLIMITS: ::rlim_t = 12;
@@ -381,16 +424,42 @@ pub const NOTE_PDATAMASK: ::uint32_t = 0x000fffff;
 pub const NOTE_PCTRLMASK: ::uint32_t = 0xf0000000;
 pub const NOTE_TRACK: ::uint32_t = 0x00000001;
 pub const NOTE_TRACKERR: ::uint32_t = 0x00000002;
 pub const NOTE_CHILD: ::uint32_t = 0x00000004;
 
 pub const SO_SNDSPACE: ::c_int = 0x100a;
 pub const SO_CPUHINT: ::c_int = 0x1030;
 
+// https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/net/if.h#L101
+pub const IFF_UP: ::c_int = 0x1; // interface is up
+pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link
+pub const IFF_SMART: ::c_int = 0x20; // interface manages own routes
+pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated
+pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets
+pub const IFF_OACTIVE_COMPAT: ::c_int = 0x400; // was transmission in progress
+pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
+// was interface is in polling mode
+pub const IFF_POLLING_COMPAT: ::c_int = 0x10000;
+pub const IFF_PPROMISC: ::c_int = 0x20000; // user-requested promisc mode
+pub const IFF_MONITOR: ::c_int = 0x40000; // user-requested monitor mode
+pub const IFF_STATICARP: ::c_int = 0x80000; // static ARP
+pub const IFF_NPOLLING: ::c_int = 0x100000; // interface is in polling mode
+pub const IFF_IDIRECT: ::c_int = 0x200000; // direct input
+
 //
 // sys/netinet/in.h
 // Protocols (RFC 1700)
 // NOTE: These are in addition to the constants defined in src/unix/mod.rs
 
 // IPPROTO_IP defined in src/unix/mod.rs
 /// IP6 hop-by-hop options
 pub const IPPROTO_HOPOPTS: ::c_int = 0;
@@ -682,22 +751,37 @@ pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 23;
 
 pub const _SC_V7_ILP32_OFF32: ::c_int = 122;
 pub const _SC_V7_ILP32_OFFBIG: ::c_int = 123;
 pub const _SC_V7_LP64_OFF64: ::c_int = 124;
 pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 125;
 pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 126;
 pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 127;
 
+pub const WCONTINUED: ::c_int = 4;
+pub const WSTOPPED: ::c_int = 0o177;
+
+// Values for struct rtprio (type_ field)
+pub const RTP_PRIO_REALTIME: ::c_ushort = 0;
+pub const RTP_PRIO_NORMAL: ::c_ushort = 1;
+pub const RTP_PRIO_IDLE: ::c_ushort = 2;
+pub const RTP_PRIO_THREAD: ::c_ushort = 3;
+
 extern {
     pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int)
                     -> ::c_int;
     pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int;
 
     pub fn setutxdb(_type: ::c_uint, file: *mut ::c_char) -> ::c_int;
 
     pub fn aio_waitcomplete(iocbp: *mut *mut aiocb,
                             timeout: *mut ::timespec) -> ::c_int;
 
     pub fn freelocale(loc: ::locale_t);
+
+    pub fn lwp_rtprio(function: ::c_int, pid: ::pid_t, lwpid: lwpid_t,
+                      rtp: *mut super::rtprio) -> ::c_int;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
 }
diff --git a/third_party/rust/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/third_party/rust/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
index 0ac797ce4c68..a64dbc468f0d 100644
--- a/third_party/rust/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
@@ -1,25 +1,28 @@
 pub type fflags_t = u32;
 pub type clock_t = i32;
 pub type ino_t = u32;
 pub type lwpid_t = i32;
 pub type nlink_t = u16;
-pub type blksize_t = u32;
+pub type blksize_t = i32;
 pub type clockid_t = ::c_int;
 pub type sem_t = _sem;
 
 pub type fsblkcnt_t = ::uint64_t;
 pub type fsfilcnt_t = ::uint64_t;
 pub type idtype_t = ::c_uint;
 
 pub type key_t = ::c_long;
 pub type msglen_t = ::c_ulong;
 pub type msgqnum_t = ::c_ulong;
 
+pub type posix_spawnattr_t = *mut ::c_void;
+pub type posix_spawn_file_actions_t = *mut ::c_void;
+
 s! {
     pub struct utmpx {
         pub ut_type: ::c_short,
         pub ut_tv: ::timeval,
         pub ut_id: [::c_char; 8],
         pub ut_pid: ::pid_t,
         pub ut_user: [::c_char; 32],
         pub ut_line: [::c_char; 16],
@@ -57,16 +60,24 @@ s! {
         pub hostname: *mut ::c_char,
         pub jailname: *mut ::c_char,
         pub ip4s: ::c_uint,
         pub ip6s: ::c_uint,
         pub ip4: *mut ::in_addr,
         pub ip6: *mut ::in6_addr,
     }
 
+    pub struct mq_attr {
+        pub mq_flags: ::c_long,
+        pub mq_maxmsg: ::c_long,
+        pub mq_msgsize: ::c_long,
+        pub mq_curmsgs: ::c_long,
+        __reserved: [::c_long; 4]
+    }
+
     pub struct sigevent {
         pub sigev_notify: ::c_int,
         pub sigev_signo: ::c_int,
         pub sigev_value: ::sigval,
         //The rest of the structure is actually a union.  We expose only
         //sigev_notify_thread_id because it's the most useful union member.
         pub sigev_notify_thread_id: ::lwpid_t,
         #[cfg(target_pointer_width = "64")]
@@ -83,16 +94,41 @@ s! {
         pub f_files: ::fsfilcnt_t,
         pub f_bsize: ::c_ulong,
         pub f_flag: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_fsid: ::c_ulong,
         pub f_namemax: ::c_ulong,
     }
 
+    pub struct statfs {
+        pub f_version: ::uint32_t,
+        pub f_type: ::uint32_t,
+        pub f_flags: ::uint64_t,
+        pub f_bsize: ::uint64_t,
+        pub f_iosize: ::uint64_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::int64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::int64_t,
+        pub f_syncwrites: ::uint64_t,
+        pub f_asyncwrites: ::uint64_t,
+        pub f_syncreads: ::uint64_t,
+        pub f_asyncreads: ::uint64_t,
+        f_spare: [::uint64_t; 10],
+        pub f_namemax: ::uint32_t,
+        pub f_owner: ::uid_t,
+        pub f_fsid: ::fsid_t,
+        f_charspare: [::c_char; 80],
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntfromname: [::c_char; 88],
+        pub f_mntonname: [::c_char; 88],
+    }
+
     // internal structure has changed over time
     pub struct _sem {
         data: [u32; 4],
     }
 
     pub struct ipc_perm {
         pub cuid: ::uid_t,
         pub cgid: ::gid_t,
@@ -130,38 +166,57 @@ s! {
 
     pub struct xucred {
         pub cr_version: ::c_uint,
         pub cr_uid: ::uid_t,
         pub cr_ngroups: ::c_short,
         pub cr_groups: [::gid_t;16],
         __cr_unused1: *mut ::c_void,
     }
+
+    pub struct sockaddr_dl {
+        pub sdl_len: ::c_uchar,
+        pub sdl_family: ::c_uchar,
+        pub sdl_index: ::c_ushort,
+        pub sdl_type: ::c_uchar,
+        pub sdl_nlen: ::c_uchar,
+        pub sdl_alen: ::c_uchar,
+        pub sdl_slen: ::c_uchar,
+        pub sdl_data: [::c_char; 46],
+    }
 }
 
 pub const SIGEV_THREAD_ID: ::c_int = 4;
 
 pub const RAND_MAX: ::c_int = 0x7fff_fffd;
 pub const PTHREAD_STACK_MIN: ::size_t = 2048;
 pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 4;
 pub const SIGSTKSZ: ::size_t = 34816;
 pub const SF_NODISKIO: ::c_int = 0x00000001;
 pub const SF_MNOWAIT: ::c_int = 0x00000002;
 pub const SF_SYNC: ::c_int = 0x00000004;
+pub const SF_USER_READAHEAD: ::c_int = 0x00000008;
+pub const SF_NOCACHE: ::c_int = 0x00000010;
 pub const O_CLOEXEC: ::c_int = 0x00100000;
 pub const O_DIRECTORY: ::c_int = 0x00020000;
 pub const O_EXEC: ::c_int = 0x00040000;
 pub const O_TTY_INIT: ::c_int = 0x00080000;
 pub const F_GETLK: ::c_int = 11;
 pub const F_SETLK: ::c_int = 12;
 pub const F_SETLKW: ::c_int = 13;
+pub const ENOTCAPABLE: ::c_int = 93;
+pub const ECAPMODE: ::c_int = 94;
+pub const ENOTRECOVERABLE: ::c_int = 95;
+pub const EOWNERDEAD: ::c_int = 96;
 pub const ELAST: ::c_int = 96;
 pub const RLIMIT_NPTS: ::c_int = 11;
 pub const RLIMIT_SWAP: ::c_int = 12;
-pub const RLIM_NLIMITS: ::rlim_t = 13;
+pub const RLIMIT_KQUEUES: ::c_int = 13;
+pub const RLIMIT_UMTXP: ::c_int = 14;
+pub const RLIM_NLIMITS: ::rlim_t = 15;
 
 pub const Q_GETQUOTA: ::c_int = 0x700;
 pub const Q_SETQUOTA: ::c_int = 0x800;
 
 pub const POSIX_FADV_NORMAL: ::c_int = 0;
 pub const POSIX_FADV_RANDOM: ::c_int = 1;
 pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2;
 pub const POSIX_FADV_WILLNEED: ::c_int = 3;
@@ -172,19 +227,22 @@ pub const POLLINIGNEOF: ::c_short = 0x2000;
 
 pub const EVFILT_READ: ::int16_t = -1;
 pub const EVFILT_WRITE: ::int16_t = -2;
 pub const EVFILT_AIO: ::int16_t = -3;
 pub const EVFILT_VNODE: ::int16_t = -4;
 pub const EVFILT_PROC: ::int16_t = -5;
 pub const EVFILT_SIGNAL: ::int16_t = -6;
 pub const EVFILT_TIMER: ::int16_t = -7;
+pub const EVFILT_PROCDESC: ::int16_t = -8;
 pub const EVFILT_FS: ::int16_t = -9;
 pub const EVFILT_LIO: ::int16_t = -10;
 pub const EVFILT_USER: ::int16_t = -11;
+pub const EVFILT_SENDFILE: ::int16_t = -12;
+pub const EVFILT_EMPTY: ::int16_t = -13;
 
 pub const EV_ADD: ::uint16_t = 0x1;
 pub const EV_DELETE: ::uint16_t = 0x2;
 pub const EV_ENABLE: ::uint16_t = 0x4;
 pub const EV_DISABLE: ::uint16_t = 0x8;
 pub const EV_ONESHOT: ::uint16_t = 0x10;
 pub const EV_CLEAR: ::uint16_t = 0x20;
 pub const EV_RECEIPT: ::uint16_t = 0x40;
@@ -420,16 +478,48 @@ pub const AF_SCLUSTER: ::c_int = 34;
 pub const AF_ARP: ::c_int = 35;
 pub const AF_BLUETOOTH: ::c_int = 36;
 pub const AF_IEEE80211: ::c_int = 37;
 pub const AF_INET_SDP: ::c_int = 40;
 pub const AF_INET6_SDP: ::c_int = 42;
 #[doc(hidden)]
 pub const AF_MAX: ::c_int = 42;
 
+// https://github.com/freebsd/freebsd/blob/master/sys/net/if.h#L140
+pub const IFF_UP: ::c_int = 0x1; // (n) interface is up
+pub const IFF_BROADCAST: ::c_int = 0x2; // (i) broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x4; // (n) turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x8; // (i) is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // (i) is a point-to-point link
+// 0x20           was IFF_SMART
+pub const IFF_RUNNING: ::c_int = 0x40; // (d) resources allocated
+#[doc(hidden)]
+// IFF_DRV_RUNNING is deprecated.  Use the portable `IFF_RUNNING` instead
+pub const IFF_DRV_RUNNING: ::c_int = 0x40;
+pub const IFF_NOARP: ::c_int = 0x80; // (n) no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x100; // (n) receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x200; // (n) receive all multicast packets
+pub const IFF_OACTIVE: ::c_int = 0x400; // (d) tx hardware queue is full
+#[doc(hidden)]
+// IFF_DRV_OACTIVE is deprecated.  Use the portable `IFF_OACTIVE` instead
+pub const IFF_DRV_OACTIVE: ::c_int = 0x400;
+pub const IFF_SIMPLEX: ::c_int = 0x800; // (i) can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection
+pub const IFF_MULTICAST: ::c_int = 0x8000; // (i) supports multicast
+// (i) unconfigurable using ioctl(2)
+pub const IFF_CANTCONFIG: ::c_int = 0x10000;
+pub const IFF_PPROMISC: ::c_int = 0x20000; // (n) user-requested promisc mode
+pub const IFF_MONITOR: ::c_int = 0x40000; // (n) user-requested monitor mode
+pub const IFF_STATICARP: ::c_int = 0x80000; // (n) static ARP
+pub const IFF_DYING: ::c_int = 0x200000; // (n) interface is winding down
+pub const IFF_RENAMING: ::c_int = 0x400000; // (n) interface is being renamed
+
 // sys/netinet/in.h
 // Protocols (RFC 1700)
 // NOTE: These are in addition to the constants defined in src/unix/mod.rs
 
 // IPPROTO_IP defined in src/unix/mod.rs
 /// IP6 hop-by-hop options
 pub const IPPROTO_HOPOPTS: ::c_int = 0;
 // IPPROTO_ICMP defined in src/unix/mod.rs
@@ -698,16 +788,17 @@ pub const MSG_NOERROR: ::c_int = 0o10000;
 pub const SHM_RDONLY: ::c_int = 0o10000;
 pub const SHM_RND: ::c_int = 0o20000;
 pub const SHM_R: ::c_int = 0o400;
 pub const SHM_W: ::c_int = 0o200;
 pub const SHM_LOCK: ::c_int = 11;
 pub const SHM_UNLOCK: ::c_int = 12;
 pub const SHM_STAT: ::c_int = 13;
 pub const SHM_INFO: ::c_int = 14;
+pub const SHM_ANON: *mut ::c_char = 1 as *mut ::c_char;
 
 // The *_MAXID constants never should've been used outside of the
 // FreeBSD base system.  And with the exception of CTL_P1003_1B_MAXID,
 // they were all removed in svn r262489.  They remain here for backwards
 // compatibility only, and are scheduled to be removed in libc 1.0.0.
 #[doc(hidden)]
 pub const NET_MAXID: ::c_int = AF_MAX;
 #[doc(hidden)]
@@ -734,20 +825,20 @@ pub const NEW_TIME: ::c_short = 3;
 pub const USER_PROCESS: ::c_short = 4;
 pub const INIT_PROCESS: ::c_short = 5;
 pub const LOGIN_PROCESS: ::c_short = 6;
 pub const DEAD_PROCESS: ::c_short = 7;
 pub const SHUTDOWN_TIME: ::c_short = 8;
 
 pub const LC_COLLATE_MASK: ::c_int = (1 << 0);
 pub const LC_CTYPE_MASK: ::c_int = (1 << 1);
-pub const LC_MESSAGES_MASK: ::c_int = (1 << 2);
-pub const LC_MONETARY_MASK: ::c_int = (1 << 3);
-pub const LC_NUMERIC_MASK: ::c_int = (1 << 4);
-pub const LC_TIME_MASK: ::c_int = (1 << 5);
+pub const LC_MONETARY_MASK: ::c_int =(1 << 2);
+pub const LC_NUMERIC_MASK: ::c_int = (1 << 3);
+pub const LC_TIME_MASK: ::c_int = (1 << 4);
+pub const LC_MESSAGES_MASK: ::c_int = (1 << 5);
 pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK
                                | LC_CTYPE_MASK
                                | LC_MESSAGES_MASK
                                | LC_MONETARY_MASK
                                | LC_NUMERIC_MASK
                                | LC_TIME_MASK;
 
 pub const WSTOPPED: ::c_int = 2; // same as WUNTRACED
@@ -777,16 +868,33 @@ pub const TAB3: ::tcflag_t = 0x00000004;
 
 pub const _PC_ACL_NFS4: ::c_int = 64;
 
 pub const _SC_CPUSET_SIZE: ::c_int = 122;
 
 pub const XU_NGROUPS: ::c_int = 16;
 pub const XUCRED_VERSION: ::c_uint = 0;
 
+// Flags which can be passed to pdfork(2)
+pub const PD_DAEMON: ::c_int = 0x00000001;
+pub const PD_CLOEXEC: ::c_int = 0x00000002;
+pub const PD_ALLOWED_AT_FORK: ::c_int = PD_DAEMON | PD_CLOEXEC;
+
+// Values for struct rtprio (type_ field)
+pub const RTP_PRIO_REALTIME: ::c_ushort = 2;
+pub const RTP_PRIO_NORMAL: ::c_ushort = 3;
+pub const RTP_PRIO_IDLE: ::c_ushort = 4;
+
+pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01;
+pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02;
+pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x04;
+pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x08;
+pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x10;
+pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x20;
+
 extern {
     pub fn __error() -> *mut ::c_int;
 
     pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int)
                     -> ::c_int;
 
     pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
@@ -795,16 +903,17 @@ extern {
     pub fn jail(jail: *mut ::jail) -> ::c_int;
     pub fn jail_attach(jid: ::c_int) -> ::c_int;
     pub fn jail_remove(jid: ::c_int) -> ::c_int;
     pub fn jail_get(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int)
                     -> ::c_int;
     pub fn jail_set(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int)
                     -> ::c_int;
 
+    pub fn fdatasync(fd: ::c_int) -> ::c_int;
     pub fn posix_fallocate(fd: ::c_int, offset: ::off_t,
                            len: ::off_t) -> ::c_int;
     pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t,
                          advise: ::c_int) -> ::c_int;
     pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int;
     pub fn mkostemps(template: *mut ::c_char,
                      suffixlen: ::c_int,
                      flags: ::c_int) -> ::c_int;
@@ -829,16 +938,95 @@ extern {
     pub fn msgctl(msqid: ::c_int, cmd: ::c_int,
         buf: *mut ::msqid_ds) -> ::c_int;
     pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int;
     pub fn msgrcv(msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t,
         msgtyp: ::c_long, msgflg: ::c_int) -> ::c_int;
     pub fn msgsnd(msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t,
         msgflg: ::c_int) -> ::c_int;
     pub fn cfmakesane(termios: *mut ::termios);
+    pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
+                   envp: *const *const ::c_char)
+                   -> ::c_int;
+
+    pub fn pdfork(fdp: *mut ::c_int, flags: ::c_int) -> ::pid_t;
+    pub fn pdgetpid(fd: ::c_int, pidp: *mut ::pid_t) -> ::c_int;
+    pub fn pdkill(fd: ::c_int, signum: ::c_int) -> ::c_int;
+
+    pub fn rtprio_thread(function: ::c_int, lwpid: ::lwpid_t,
+                         rtp: *mut super::rtprio) -> ::c_int;
+
+    pub fn posix_spawn(pid: *mut ::pid_t,
+                       path: *const ::c_char,
+                       file_actions: *const ::posix_spawn_file_actions_t,
+                       attrp: *const ::posix_spawnattr_t,
+                       argv: *const *mut ::c_char,
+                       envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnp(pid: *mut ::pid_t,
+                       file: *const ::c_char,
+                        file_actions: *const ::posix_spawn_file_actions_t,
+                        attrp: *const ::posix_spawnattr_t,
+                        argv: *const *mut ::c_char,
+                        envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigdefault(attr: *const posix_spawnattr_t,
+                                         default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigdefault(attr: *mut posix_spawnattr_t,
+                                         default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigmask(attr: *const posix_spawnattr_t,
+                                      default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigmask(attr: *mut posix_spawnattr_t,
+                                      default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t,
+                                    flags: *mut ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t,
+                                    flags: ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_getpgroup(attr: *const posix_spawnattr_t,
+                                     flags: *mut ::pid_t) -> ::c_int;
+    pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t,
+                                     flags: ::pid_t) -> ::c_int;
+    pub fn posix_spawnattr_getschedpolicy(attr: *const posix_spawnattr_t,
+                                          flags: *mut ::c_int) -> ::c_int;
+    pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t,
+                                          flags: ::c_int) -> ::c_int;
+    pub fn posix_spawnattr_getschedparam(
+        attr: *const posix_spawnattr_t,
+        param: *mut ::sched_param,
+    ) -> ::c_int;
+    pub fn posix_spawnattr_setschedparam(
+        attr: *mut posix_spawnattr_t,
+        param: *const ::sched_param,
+    ) -> ::c_int;
+
+    pub fn posix_spawn_file_actions_init(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_destroy(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addopen(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        path: *const ::c_char,
+        oflag: ::c_int,
+        mode: ::mode_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addclose(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_adddup2(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        newfd: ::c_int,
+    ) -> ::c_int;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(target_arch = "x86")] {
         mod x86;
         pub use self::x86::*;
     } else if #[cfg(target_arch = "x86_64")] {
         mod x86_64;
diff --git a/third_party/rust/libc/src/unix/bsd/freebsdlike/mod.rs b/third_party/rust/libc/src/unix/bsd/freebsdlike/mod.rs
index 8cc87ce9f52b..75a7a670e932 100644
--- a/third_party/rust/libc/src/unix/bsd/freebsdlike/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/freebsdlike/mod.rs
@@ -1,12 +1,14 @@
+pub type c_char = i8;
 pub type dev_t = u32;
 pub type mode_t = u16;
 pub type pthread_attr_t = *mut ::c_void;
 pub type rlim_t = i64;
+pub type mqd_t = *mut ::c_void;
 pub type pthread_mutex_t = *mut ::c_void;
 pub type pthread_mutexattr_t = *mut ::c_void;
 pub type pthread_cond_t = *mut ::c_void;
 pub type pthread_condattr_t = *mut ::c_void;
 pub type pthread_rwlock_t = *mut ::c_void;
 pub type pthread_rwlockattr_t = *mut ::c_void;
 pub type pthread_key_t = ::c_int;
 pub type tcflag_t = ::c_uint;
@@ -154,16 +156,43 @@ s! {
         pub n_sign_posn: ::c_char,
         pub int_p_cs_precedes: ::c_char,
         pub int_n_cs_precedes: ::c_char,
         pub int_p_sep_by_space: ::c_char,
         pub int_n_sep_by_space: ::c_char,
         pub int_p_sign_posn: ::c_char,
         pub int_n_sign_posn: ::c_char,
     }
+
+    pub struct cmsgcred {
+        pub cmcred_pid: ::pid_t,
+        pub cmcred_uid: ::uid_t,
+        pub cmcred_euid: ::uid_t,
+        pub cmcred_gid: ::gid_t,
+        pub cmcred_ngroups: ::c_short,
+        pub cmcred_groups: [::gid_t; CMGROUP_MAX],
+    }
+
+    pub struct rtprio {
+        pub type_: ::c_ushort,
+        pub prio: ::c_ushort,
+    }
+
+    pub struct in6_pktinfo {
+        pub ipi6_addr: ::in6_addr,
+        pub ipi6_ifindex: ::c_uint,
+    }
+
+    pub struct arphdr {
+        pub ar_hrd: u16,
+        pub ar_pro: u16,
+        pub ar_hln: u8,
+        pub ar_pln: u8,
+        pub ar_op: u16,
+    }
 }
 
 pub const AIO_LISTIO_MAX: ::c_int = 16;
 pub const AIO_CANCELED: ::c_int = 1;
 pub const AIO_NOTCANCELED: ::c_int = 2;
 pub const AIO_ALLDONE: ::c_int = 3;
 pub const LIO_NOP: ::c_int = 0;
 pub const LIO_WRITE: ::c_int = 1;
@@ -441,17 +470,26 @@ pub const EBADMSG: ::c_int = 89;
 pub const EMULTIHOP: ::c_int = 90;
 pub const ENOLINK: ::c_int = 91;
 pub const EPROTO: ::c_int = 92;
 
 pub const POLLSTANDARD: ::c_short = ::POLLIN | ::POLLPRI | ::POLLOUT |
     ::POLLRDNORM | ::POLLRDBAND | ::POLLWRBAND | ::POLLERR |
     ::POLLHUP | ::POLLNVAL;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
 
 pub const F_DUPFD: ::c_int = 0;
 pub const F_GETFD: ::c_int = 1;
 pub const F_SETFD: ::c_int = 2;
 pub const F_GETFL: ::c_int = 3;
 pub const F_SETFL: ::c_int = 4;
 
 pub const SIGTRAP: ::c_int = 5;
@@ -605,23 +643,30 @@ pub const SOCK_DGRAM: ::c_int = 2;
 pub const SOCK_RAW: ::c_int = 3;
 pub const SOCK_RDM: ::c_int = 4;
 pub const SOCK_SEQPACKET: ::c_int = 5;
 pub const SOCK_CLOEXEC: ::c_int = 0x10000000;
 pub const SOCK_NONBLOCK: ::c_int = 0x20000000;
 pub const SOCK_MAXADDRLEN: ::c_int = 255;
 pub const IP_TTL: ::c_int = 4;
 pub const IP_HDRINCL: ::c_int = 2;
+pub const IP_RECVDSTADDR: ::c_int = 7;
+pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
 pub const IPV6_JOIN_GROUP: ::c_int = 12;
 pub const IPV6_LEAVE_GROUP: ::c_int = 13;
+pub const IPV6_RECVPKTINFO: ::c_int = 36;
+pub const IPV6_PKTINFO: ::c_int = 46;
+
+pub const TCP_NODELAY:   ::c_int = 1;
+pub const TCP_KEEPIDLE:  ::c_int = 256;
+pub const TCP_KEEPINTVL: ::c_int = 512;
+pub const TCP_KEEPCNT:   ::c_int = 1024;
 
-pub const TCP_NODELAY: ::c_int = 1;
-pub const TCP_KEEPIDLE: ::c_int = 256;
 pub const SOL_SOCKET: ::c_int = 0xffff;
 pub const SO_DEBUG: ::c_int = 0x01;
 pub const SO_ACCEPTCONN: ::c_int = 0x0002;
 pub const SO_REUSEADDR: ::c_int = 0x0004;
 pub const SO_KEEPALIVE: ::c_int = 0x0008;
 pub const SO_DONTROUTE: ::c_int = 0x0010;
 pub const SO_BROADCAST: ::c_int = 0x0020;
 pub const SO_USELOOPBACK: ::c_int = 0x0040;
@@ -635,18 +680,16 @@ pub const SO_SNDBUF: ::c_int = 0x1001;
 pub const SO_RCVBUF: ::c_int = 0x1002;
 pub const SO_SNDLOWAT: ::c_int = 0x1003;
 pub const SO_RCVLOWAT: ::c_int = 0x1004;
 pub const SO_SNDTIMEO: ::c_int = 0x1005;
 pub const SO_RCVTIMEO: ::c_int = 0x1006;
 pub const SO_ERROR: ::c_int = 0x1007;
 pub const SO_TYPE: ::c_int = 0x1008;
 
-pub const IFF_LOOPBACK: ::c_int = 0x8;
-
 pub const SHUT_RD: ::c_int = 0;
 pub const SHUT_WR: ::c_int = 1;
 pub const SHUT_RDWR: ::c_int = 2;
 
 pub const LOCK_SH: ::c_int = 1;
 pub const LOCK_EX: ::c_int = 2;
 pub const LOCK_NB: ::c_int = 4;
 pub const LOCK_UN: ::c_int = 8;
@@ -931,16 +974,28 @@ pub const CRTS_IFLOW: ::tcflag_t = 0x00020000;
 pub const CDTR_IFLOW: ::tcflag_t = 0x00040000;
 pub const CDSR_OFLOW: ::tcflag_t = 0x00080000;
 pub const CCAR_OFLOW: ::tcflag_t = 0x00100000;
 pub const VERASE2: usize = 7;
 pub const OCRNL: ::tcflag_t = 0x10;
 pub const ONOCR: ::tcflag_t = 0x20;
 pub const ONLRET: ::tcflag_t = 0x40;
 
+pub const CMGROUP_MAX: usize = 16;
+
+// https://github.com/freebsd/freebsd/blob/master/sys/net/bpf.h
+// sizeof(long)
+pub const BPF_ALIGNMENT: ::c_int = 8;
+
+// Values for rtprio struct (prio field) and syscall (function argument)
+pub const RTP_PRIO_MIN: ::c_ushort = 0;
+pub const RTP_PRIO_MAX: ::c_ushort = 31;
+pub const RTP_LOOKUP: ::c_int = 0;
+pub const RTP_SET: ::c_int = 1;
+
 f! {
     pub fn WIFCONTINUED(status: ::c_int) -> bool {
         status == 0x13
     }
 
     pub fn WSTOPSIG(status: ::c_int) -> ::c_int {
         status >> 8
     }
@@ -964,16 +1019,51 @@ extern {
     pub fn setutxent();
     pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int;
     pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int;
     pub fn getgrouplist(name: *const ::c_char,
                         basegid: ::gid_t,
                         groups: *mut ::gid_t,
                         ngroups: *mut ::c_int) -> ::c_int;
     pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int;
+    #[cfg_attr(target_os = "netbsd", link_name = "__getpwent_r50")]
+    pub fn getpwent_r(pwd: *mut ::passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::passwd) -> ::c_int;
+    pub fn getgrent_r(grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
+    pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t;
+    pub fn mq_close(mqd: ::mqd_t) -> ::c_int;
+    pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int;
+    pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int;
+    pub fn mq_receive(mqd: ::mqd_t,
+                      msg_ptr: *mut ::c_char,
+                      msg_len: ::size_t,
+                      msq_prio: *mut ::c_uint) -> ::ssize_t;
+    pub fn mq_send(mqd: ::mqd_t,
+                   msg_ptr: *const ::c_char,
+                   msg_len: ::size_t,
+                   msq_prio: ::c_uint) -> ::c_int;
+    pub fn mq_setattr(mqd: ::mqd_t,
+                      newattr: *const ::mq_attr,
+                      oldattr: *mut ::mq_attr) -> ::c_int;
+    pub fn mq_timedreceive(mqd: ::mqd_t,
+                           msg_ptr: *mut ::c_char,
+                           msg_len: ::size_t,
+                           msq_prio: *mut ::c_uint,
+                           abs_timeout: *const ::timespec) -> ::ssize_t;
+    pub fn mq_timedsend(mqd: ::mqd_t,
+                        msg_ptr: *const ::c_char,
+                        msg_len: ::size_t,
+                        msq_prio: ::c_uint,
+                        abs_timeout: *const ::timespec) -> ::c_int;
+    pub fn mq_unlink(name: *const ::c_char) -> ::c_int;
 }
 
 #[link(name = "util")]
 extern {
     pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_error(aiocbp: *const aiocb) -> ::c_int;
@@ -986,16 +1076,17 @@ extern {
     pub fn dirfd(dirp: *mut ::DIR) -> ::c_int;
     pub fn getnameinfo(sa: *const ::sockaddr,
                        salen: ::socklen_t,
                        host: *mut ::c_char,
                        hostlen: ::size_t,
                        serv: *mut ::c_char,
                        servlen: ::size_t,
                        flags: ::c_int) -> ::c_int;
+    #[cfg_attr(target_os = "freebsd", link_name = "kevent@FBSD_1.0")]
     pub fn kevent(kq: ::c_int,
                   changelist: *const ::kevent,
                   nchanges: ::c_int,
                   eventlist: *mut ::kevent,
                   nevents: ::c_int,
                   timeout: *const ::timespec) -> ::c_int;
     pub fn mincore(addr: *const ::c_void, len: ::size_t,
                    vec: *mut ::c_char) -> ::c_int;
@@ -1080,41 +1171,42 @@ extern {
     pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t,
                                         pshared: *mut ::c_int) -> ::c_int;
     pub fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t,
                                          val: *mut ::c_int) -> ::c_int;
     pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t,
                                          val: ::c_int) -> ::c_int;
     pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int;
     pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int;
+    pub fn rtprio(function: ::c_int, pid: ::pid_t, rtp: *mut rtprio) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
+    #[cfg_attr(target_os = "freebsd", link_name = "mknodat@FBSD_1.1")]
     pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
                   mode: ::mode_t, dev: dev_t) -> ::c_int;
     pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t) -> ::c_int;
     pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t,
                                      clock_id: *mut clockid_t) -> ::c_int;
     pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
                                      clock_id: ::clockid_t) -> ::c_int;
     pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
                                    abstime: *const ::timespec) -> ::c_int;
     pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int;
     pub fn ppoll(fds: *mut ::pollfd,
                  nfds: ::nfds_t,
                  timeout: *const ::timespec,
                  sigmask: *const sigset_t) -> ::c_int;
     pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int;
-    pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
-                   envp: *const *const ::c_char)
-                   -> ::c_int;
+    pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int;
+    pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(target_os = "freebsd")] {
         mod freebsd;
         pub use self::freebsd::*;
     } else if #[cfg(target_os = "dragonfly")] {
         mod dragonfly;
diff --git a/third_party/rust/libc/src/unix/bsd/mod.rs b/third_party/rust/libc/src/unix/bsd/mod.rs
index a9f9fa87d9ae..47f82bdf59c4 100644
--- a/third_party/rust/libc/src/unix/bsd/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/mod.rs
@@ -1,11 +1,10 @@
 use dox::{mem, Option};
 
-pub type c_char = i8;
 pub type wchar_t = i32;
 pub type off_t = i64;
 pub type useconds_t = u32;
 pub type blkcnt_t = i64;
 pub type socklen_t = u32;
 pub type sa_family_t = u8;
 pub type pthread_t = ::uintptr_t;
 pub type nfds_t = ::c_uint;
@@ -179,16 +178,19 @@ pub const SIGINFO: ::c_int = 29;
 pub const SIG_SETMASK: ::c_int = 3;
 pub const SIG_BLOCK: ::c_int = 0x1;
 pub const SIG_UNBLOCK: ::c_int = 0x2;
 
 pub const IP_MULTICAST_IF: ::c_int = 9;
 pub const IP_MULTICAST_TTL: ::c_int = 10;
 pub const IP_MULTICAST_LOOP: ::c_int = 11;
 
+pub const IPV6_UNICAST_HOPS: ::c_int = 4;
+pub const IPV6_MULTICAST_IF: ::c_int = 9;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 10;
 pub const IPV6_MULTICAST_LOOP: ::c_int = 11;
 pub const IPV6_V6ONLY: ::c_int = 27;
 
 pub const ST_RDONLY: ::c_ulong = 1;
 
 pub const SCM_RIGHTS: ::c_int = 0x01;
 
 pub const NCCS: usize = 20;
@@ -381,34 +383,40 @@ extern {
     pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int;
     pub fn kqueue() -> ::c_int;
     pub fn unmount(target: *const ::c_char, arg: ::c_int) -> ::c_int;
     pub fn syscall(num: ::c_int, ...) -> ::c_int;
     #[cfg_attr(target_os = "netbsd", link_name = "__getpwent50")]
     pub fn getpwent() -> *mut passwd;
     pub fn setpwent();
     pub fn endpwent();
+    pub fn setgrent();
+    pub fn endgrent();
+    pub fn getgrent() -> *mut ::group;
+
     pub fn getprogname() -> *const ::c_char;
     pub fn setprogname(name: *const ::c_char);
     pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int;
     pub fn if_nameindex() -> *mut if_nameindex;
     pub fn if_freenameindex(ptr: *mut if_nameindex);
 
     pub fn getpeereid(socket: ::c_int,
                       euid: *mut ::uid_t,
                       egid: *mut ::gid_t) -> ::c_int;
 
     #[cfg_attr(target_os = "macos", link_name = "glob$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__glob30")]
+    #[cfg_attr(target_os = "freebsd", link_name = "glob@FBSD_1.0")]
     pub fn glob(pattern: *const ::c_char,
                 flags: ::c_int,
                 errfunc: Option<extern fn(epath: *const ::c_char,
                                           errno: ::c_int) -> ::c_int>,
                 pglob: *mut ::glob_t) -> ::c_int;
     #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")]
+    #[cfg_attr(target_os = "freebsd", link_name = "globfree@FBSD_1.0")]
     pub fn globfree(pglob: *mut ::glob_t);
 
     pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int)
                          -> ::c_int;
 
     pub fn shm_unlink(name: *const ::c_char) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/mod.rs
index f9caca9e7af3..6384a29f8c12 100644
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/mod.rs
@@ -30,16 +30,21 @@ s! {
     pub struct sockaddr_in {
         pub sin_len: u8,
         pub sin_family: ::sa_family_t,
         pub sin_port: ::in_port_t,
         pub sin_addr: ::in_addr,
         pub sin_zero: [::int8_t; 8],
     }
 
+    pub struct in6_pktinfo {
+        pub ipi6_addr: ::in6_addr,
+        pub ipi6_ifindex: ::c_uint,
+    }
+
     pub struct termios {
         pub c_iflag: ::tcflag_t,
         pub c_oflag: ::tcflag_t,
         pub c_cflag: ::tcflag_t,
         pub c_lflag: ::tcflag_t,
         pub c_cc: [::cc_t; ::NCCS],
         pub c_ispeed: ::c_int,
         pub c_ospeed: ::c_int,
@@ -172,17 +177,16 @@ pub const SIGILL : ::c_int = 4;
 pub const SIGABRT : ::c_int = 6;
 pub const SIGEMT: ::c_int = 7;
 pub const SIGFPE : ::c_int = 8;
 pub const SIGKILL : ::c_int = 9;
 pub const SIGSEGV : ::c_int = 11;
 pub const SIGPIPE : ::c_int = 13;
 pub const SIGALRM : ::c_int = 14;
 pub const SIGTERM : ::c_int = 15;
-pub const SIGSTKSZ : ::size_t = 40960;
 
 pub const PROT_NONE : ::c_int = 0;
 pub const PROT_READ : ::c_int = 1;
 pub const PROT_WRITE : ::c_int = 2;
 pub const PROT_EXEC : ::c_int = 4;
 
 pub const MAP_FILE : ::c_int = 0x0000;
 pub const MAP_SHARED : ::c_int = 0x0001;
@@ -408,18 +412,21 @@ pub const SOCK_STREAM: ::c_int = 1;
 pub const SOCK_DGRAM: ::c_int = 2;
 pub const SOCK_RAW: ::c_int = 3;
 pub const SOCK_RDM: ::c_int = 4;
 pub const SOCK_SEQPACKET: ::c_int = 5;
 pub const IP_TTL: ::c_int = 4;
 pub const IP_HDRINCL: ::c_int = 2;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
+pub const IPV6_RECVPKTINFO: ::c_int = 36;
+pub const IPV6_PKTINFO: ::c_int = 46;
+
+pub const TCP_NODELAY:    ::c_int = 0x01;
 
-pub const TCP_NODELAY: ::c_int = 0x01;
 pub const SOL_SOCKET: ::c_int = 0xffff;
 pub const SO_DEBUG: ::c_int = 0x01;
 pub const SO_ACCEPTCONN: ::c_int = 0x0002;
 pub const SO_REUSEADDR: ::c_int = 0x0004;
 pub const SO_KEEPALIVE: ::c_int = 0x0008;
 pub const SO_DONTROUTE: ::c_int = 0x0010;
 pub const SO_BROADCAST: ::c_int = 0x0020;
 pub const SO_USELOOPBACK: ::c_int = 0x0040;
@@ -443,18 +450,16 @@ pub const MSG_TRUNC: ::c_int = 0x10;
 pub const MSG_CTRUNC: ::c_int = 0x20;
 pub const MSG_WAITALL: ::c_int = 0x40;
 pub const MSG_DONTWAIT: ::c_int = 0x80;
 pub const MSG_BCAST: ::c_int = 0x100;
 pub const MSG_MCAST: ::c_int = 0x200;
 pub const MSG_NOSIGNAL: ::c_int = 0x400;
 pub const MSG_CMSG_CLOEXEC: ::c_int = 0x800;
 
-pub const IFF_LOOPBACK: ::c_int = 0x8;
-
 pub const SHUT_RD: ::c_int = 0;
 pub const SHUT_WR: ::c_int = 1;
 pub const SHUT_RDWR: ::c_int = 2;
 
 pub const LOCK_SH: ::c_int = 1;
 pub const LOCK_EX: ::c_int = 2;
 pub const LOCK_NB: ::c_int = 4;
 pub const LOCK_UN: ::c_int = 8;
@@ -529,16 +534,34 @@ pub const EXTB: speed_t = 38400;
 
 pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t;
 
 pub const CRTSCTS: ::tcflag_t = 0x00010000;
 pub const CRTS_IFLOW: ::tcflag_t = CRTSCTS;
 pub const CCTS_OFLOW: ::tcflag_t = CRTSCTS;
 pub const OCRNL: ::tcflag_t = 0x10;
 
+pub const TIOCEXCL: ::c_ulong = 0x2000740d;
+pub const TIOCNXCL: ::c_ulong = 0x2000740e;
+pub const TIOCFLUSH: ::c_ulong = 0x80047410;
+pub const TIOCGETA: ::c_ulong = 0x402c7413;
+pub const TIOCSETA: ::c_ulong = 0x802c7414;
+pub const TIOCSETAW: ::c_ulong = 0x802c7415;
+pub const TIOCSETAF: ::c_ulong = 0x802c7416;
+pub const TIOCGETD: ::c_ulong = 0x4004741a;
+pub const TIOCSETD: ::c_ulong = 0x8004741b;
+pub const TIOCMGET: ::c_ulong = 0x4004746a;
+pub const TIOCMBIC: ::c_ulong = 0x8004746b;
+pub const TIOCMBIS: ::c_ulong = 0x8004746c;
+pub const TIOCMSET: ::c_ulong = 0x8004746d;
+pub const TIOCSTART: ::c_ulong = 0x2000746e;
+pub const TIOCSTOP: ::c_ulong = 0x2000746f;
+pub const TIOCSCTTY: ::c_ulong = 0x20007461;
+pub const TIOCGWINSZ: ::c_ulong = 0x40087468;
+pub const TIOCSWINSZ: ::c_ulong = 0x80087467;
 pub const TIOCM_LE: ::c_int = 0o0001;
 pub const TIOCM_DTR: ::c_int = 0o0002;
 pub const TIOCM_RTS: ::c_int = 0o0004;
 pub const TIOCM_ST: ::c_int = 0o0010;
 pub const TIOCM_SR: ::c_int = 0o0020;
 pub const TIOCM_CTS: ::c_int = 0o0040;
 pub const TIOCM_CAR: ::c_int = 0o0100;
 pub const TIOCM_RNG: ::c_int = 0o0200;
@@ -599,39 +622,41 @@ extern {
                    winp: *mut ::winsize) -> ::c_int;
     pub fn forkpty(amaster: *mut ::c_int,
                    name: *mut ::c_char,
                    termp: *mut termios,
                    winp: *mut ::winsize) -> ::pid_t;
     pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
     pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
     pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
                    mode: ::mode_t, dev: dev_t) -> ::c_int;
     pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
                                      clock_id: ::clockid_t) -> ::c_int;
     pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int;
     pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
                                    abstime: *const ::timespec) -> ::c_int;
     pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int;
 
     pub fn getgrouplist(name: *const ::c_char,
                         basegid: ::gid_t,
                         groups: *mut ::gid_t,
                         ngroups: *mut ::c_int) -> ::c_int;
     pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int;
     pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
                    envp: *const *const ::c_char)
                    -> ::c_int;
+    pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
+    pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(target_os = "netbsd")] {
         mod netbsd;
         pub use self::netbsd::*;
     } else if #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] {
         mod openbsdlike;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
index cc9798c764dd..065f6bd36a22 100644
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -1,15 +1,19 @@
+use dox::mem;
+
+pub type c_char = i8;
 pub type clock_t = ::c_uint;
 pub type suseconds_t = ::c_int;
 pub type dev_t = u64;
 pub type blksize_t = ::int32_t;
 pub type fsblkcnt_t = ::uint64_t;
 pub type fsfilcnt_t = ::uint64_t;
 pub type idtype_t = ::c_int;
+pub type mqd_t = ::c_int;
 
 s! {
     pub struct aiocb {
         pub aio_offset: ::off_t,
         pub aio_buf: *mut ::c_void,
         pub aio_nbytes: ::size_t,
         pub aio_fildes: ::c_int,
         pub aio_lio_opcode: ::c_int,
@@ -39,16 +43,23 @@ s! {
 
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
         __unused6: *mut ::c_void,
         __unused7: *mut ::c_void,
         __unused8: *mut ::c_void,
     }
 
+    pub struct mq_attr {
+        pub mq_flags: ::c_long,
+        pub mq_maxmsg: ::c_long,
+        pub mq_msgsize: ::c_long,
+        pub mq_curmsgs: ::c_long,
+    }
+
     pub struct sigevent {
         pub sigev_notify: ::c_int,
         pub sigev_signo: ::c_int,
         pub sigev_value: ::sigval,
         __unused1: *mut ::c_void,       //actually a function pointer
         pub sigev_notify_attributes: *mut ::c_void
     }
 
@@ -276,16 +287,51 @@ s! {
         pub ifm_msglen: ::c_ushort,
         pub ifm_version: ::c_uchar,
         pub ifm_type: ::c_uchar,
         pub ifm_addrs: ::c_int,
         pub ifm_flags: ::c_int,
         pub ifm_index: ::c_ushort,
         pub ifm_data: if_data,
     }
+
+    pub struct sockcred {
+        pub sc_pid: ::pid_t,
+        pub sc_uid: ::uid_t,
+        pub sc_euid: ::uid_t,
+        pub sc_gid: ::gid_t,
+        pub sc_egid: ::gid_t,
+        pub sc_ngroups: ::c_int,
+        pub sc_groups: [::gid_t; 1],
+    }
+
+    pub struct sockaddr_dl {
+        pub sdl_len: ::c_uchar,
+        pub sdl_family: ::c_uchar,
+        pub sdl_index: ::c_ushort,
+        pub sdl_type: ::uint8_t,
+        pub sdl_nlen: ::uint8_t,
+        pub sdl_alen: ::uint8_t,
+        pub sdl_slen: ::uint8_t,
+        pub sdl_data: [::c_char; 12],
+    }
+
+    pub struct in_pktinfo {
+        pub ipi_addr: ::in_addr,
+        pub ipi_ifindex: ::c_uint,
+    }
+
+    #[repr(packed)]
+    pub struct arphdr {
+        pub ar_hrd: u16,
+        pub ar_pro: u16,
+        pub ar_hln: u8,
+        pub ar_pln: u8,
+        pub ar_op: u16,
+    }
 }
 
 pub const AT_FDCWD: ::c_int = -100;
 pub const AT_EACCESS: ::c_int = 0x100;
 pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x200;
 pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400;
 pub const AT_REMOVEDIR: ::c_int = 0x800;
 
@@ -311,46 +357,79 @@ pub const O_DIRECTORY: ::c_int = 0x200000;
 pub const O_DIRECT : ::c_int = 0x00080000;
 pub const O_RSYNC : ::c_int = 0x00020000;
 
 pub const MS_SYNC : ::c_int = 0x4;
 pub const MS_INVALIDATE : ::c_int = 0x2;
 
 pub const RLIM_NLIMITS: ::c_int = 12;
 
-pub const ENOATTR : ::c_int = 93;
-pub const EILSEQ : ::c_int = 85;
-pub const EOVERFLOW : ::c_int = 84;
-pub const ECANCELED : ::c_int = 87;
-pub const EIDRM : ::c_int = 82;
-pub const ENOMSG : ::c_int = 83;
-pub const ENOTSUP : ::c_int = 86;
-pub const ELAST : ::c_int = 96;
+pub const EIDRM: ::c_int = 82;
+pub const ENOMSG: ::c_int = 83;
+pub const EOVERFLOW: ::c_int = 84;
+pub const EILSEQ: ::c_int = 85;
+pub const ENOTSUP: ::c_int = 86;
+pub const ECANCELED: ::c_int = 87;
+pub const EBADMSG: ::c_int = 88;
+pub const ENODATA: ::c_int = 89;
+pub const ENOSR: ::c_int = 90;
+pub const ENOSTR: ::c_int = 91;
+pub const ETIME: ::c_int = 92;
+pub const ENOATTR: ::c_int = 93;
+pub const EMULTIHOP: ::c_int = 94;
+pub const ENOLINK: ::c_int = 95;
+pub const EPROTO: ::c_int = 96;
+pub const ELAST: ::c_int = 96;
 
 pub const F_DUPFD_CLOEXEC : ::c_int = 12;
 pub const F_CLOSEM: ::c_int = 10;
 pub const F_GETNOSIGPIPE: ::c_int = 13;
 pub const F_SETNOSIGPIPE: ::c_int = 14;
 pub const F_MAXFD: ::c_int = 11;
 
+pub const IP_PKTINFO: ::c_int = 25;
+pub const IP_RECVPKTINFO: ::c_int = 26;
 pub const IPV6_JOIN_GROUP: ::c_int = 12;
 pub const IPV6_LEAVE_GROUP: ::c_int = 13;
 
+pub const TCP_KEEPIDLE:  ::c_int = 3;
+pub const TCP_KEEPINTVL: ::c_int = 5;
+pub const TCP_KEEPCNT:   ::c_int = 6;
+pub const TCP_KEEPINIT:  ::c_int = 7;
+
 pub const SOCK_CONN_DGRAM: ::c_int = 6;
 pub const SOCK_DCCP: ::c_int = SOCK_CONN_DGRAM;
 pub const SOCK_NOSIGPIPE: ::c_int = 0x40000000;
 pub const SOCK_FLAGS_MASK: ::c_int = 0xf0000000;
 
 pub const SO_SNDTIMEO: ::c_int = 0x100b;
 pub const SO_RCVTIMEO: ::c_int = 0x100c;
 pub const SO_ACCEPTFILTER: ::c_int = 0x1000;
 pub const SO_TIMESTAMP: ::c_int = 0x2000;
 pub const SO_OVERFLOWED: ::c_int = 0x1009;
 pub const SO_NOHEADER: ::c_int = 0x100a;
 
+// https://github.com/NetBSD/src/blob/trunk/sys/net/if.h#L373
+pub const IFF_UP: ::c_int = 0x0001; // interface is up
+pub const IFF_BROADCAST: ::c_int = 0x0002; // broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x0004; // turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x0008; // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x0010; // interface is point-to-point link
+pub const IFF_NOTRAILERS: ::c_int = 0x0020; // avoid use of trailers
+pub const IFF_RUNNING: ::c_int = 0x0040; // resources allocated
+pub const IFF_NOARP: ::c_int = 0x0080; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x0100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x0200; // receive all multicast packets
+pub const IFF_OACTIVE: ::c_int = 0x0400; // transmission in progress
+pub const IFF_SIMPLEX: ::c_int = 0x0800; // can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
+
 // sys/netinet/in.h
 // Protocols (RFC 1700)
 // NOTE: These are in addition to the constants defined in src/unix/mod.rs
 
 // IPPROTO_IP defined in src/unix/mod.rs
 /// Hop-by-hop option header
 pub const IPPROTO_HOPOPTS: ::c_int = 0;
 // IPPROTO_ICMP defined in src/unix/mod.rs
@@ -839,17 +918,27 @@ pub const KERN_PROC_RUID: ::c_int = 6;
 pub const KERN_PROC_GID: ::c_int = 7;
 pub const KERN_PROC_RGID: ::c_int = 8;
 pub const KERN_PROC_ARGV: ::c_int = 1;
 pub const KERN_PROC_NARGV: ::c_int = 2;
 pub const KERN_PROC_ENV: ::c_int = 3;
 pub const KERN_PROC_NENV: ::c_int = 4;
 pub const KERN_PROC_PATHNAME: ::c_int = 5;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
 
 pub const AIO_CANCELED: ::c_int = 1;
 pub const AIO_NOTCANCELED: ::c_int = 2;
 pub const AIO_ALLDONE: ::c_int = 3;
 pub const LIO_NOP: ::c_int = 0;
 pub const LIO_WRITE: ::c_int = 1;
 pub const LIO_READ: ::c_int = 2;
 pub const LIO_WAIT: ::c_int = 1;
@@ -874,27 +963,38 @@ pub const B921600: ::speed_t = 921600;
 pub const ONOCR: ::tcflag_t = 0x20;
 pub const ONLRET: ::tcflag_t = 0x40;
 pub const CDTRCTS: ::tcflag_t = 0x00020000;
 pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS | ::CDTRCTS;
 
 pub const SOCK_CLOEXEC: ::c_int = 0x10000000;
 pub const SOCK_NONBLOCK: ::c_int = 0x20000000;
 
+pub const SIGSTKSZ : ::size_t = 40960;
+
 // dirfd() is a macro on netbsd to access
 // the first field of the struct where dirp points to:
 // http://cvsweb.netbsd.org/bsdweb.cgi/src/include/dirent.h?rev=1.36
 f! {
     pub fn dirfd(dirp: *mut ::DIR) -> ::c_int {
-        unsafe { *(dirp as *const ::c_int) }
+        *(dirp as *const ::c_int)
     }
 
     pub fn WIFCONTINUED(status: ::c_int) -> bool {
         status == 0xffff
     }
+
+    pub fn SOCKCREDSIZE(ngrps: usize) -> usize {
+        let ngrps = if ngrps > 0 {
+            ngrps - 1
+        } else {
+            0
+        };
+        mem::size_of::<sockcred>() + mem::size_of::<::gid_t>() * ngrps
+    }
 }
 
 extern {
     pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_error(aiocbp: *const aiocb) -> ::c_int;
     pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t;
@@ -936,16 +1036,42 @@ extern {
                   nevents: ::size_t,
                   timeout: *const ::timespec) -> ::c_int;
     #[link_name = "__mount50"]
     pub fn mount(src: *const ::c_char,
                  target: *const ::c_char,
                  flags: ::c_int,
                  data: *mut ::c_void,
                  size: ::size_t) -> ::c_int;
+    pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t;
+    pub fn mq_close(mqd: ::mqd_t) -> ::c_int;
+    pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int;
+    pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int;
+    pub fn mq_receive(mqd: ::mqd_t,
+                      msg_ptr: *mut ::c_char,
+                      msg_len: ::size_t,
+                      msq_prio: *mut ::c_uint) -> ::ssize_t;
+    pub fn mq_send(mqd: ::mqd_t,
+                   msg_ptr: *const ::c_char,
+                   msg_len: ::size_t,
+                   msq_prio: ::c_uint) -> ::c_int;
+    pub fn mq_setattr(mqd: ::mqd_t,
+                      newattr: *const ::mq_attr,
+                      oldattr: *mut ::mq_attr) -> ::c_int;
+    pub fn mq_timedreceive(mqd: ::mqd_t,
+                           msg_ptr: *mut ::c_char,
+                           msg_len: ::size_t,
+                           msq_prio: *mut ::c_uint,
+                           abs_timeout: *const ::timespec) -> ::ssize_t;
+    pub fn mq_timedsend(mqd: ::mqd_t,
+                        msg_ptr: *const ::c_char,
+                        msg_len: ::size_t,
+                        msq_prio: ::c_uint,
+                        abs_timeout: *const ::timespec) -> ::c_int;
+    pub fn mq_unlink(name: *const ::c_char) -> ::c_int;
     pub fn ptrace(request: ::c_int,
                   pid: ::pid_t,
                   addr: *mut ::c_void,
                   data: ::c_int) -> ::c_int;
     pub fn pthread_setname_np(t: ::pthread_t,
                               name: *const ::c_char,
                               arg: *mut ::c_void) -> ::c_int;
     pub fn pthread_getattr_np(native: ::pthread_t,
@@ -966,10 +1092,23 @@ extern {
     pub fn localeconv_l(loc: ::locale_t) -> *mut lconv;
     pub fn newlocale(mask: ::c_int,
                      locale: *const ::c_char,
                      base: ::locale_t) -> ::locale_t;
     #[link_name = "__settimeofday50"]
     pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int;
 }
 
+#[link(name = "util")]
+extern {
+    #[cfg_attr(target_os = "netbsd", link_name = "__getpwent_r50")]
+    pub fn getpwent_r(pwd: *mut ::passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::passwd) -> ::c_int;
+    pub fn getgrent_r(grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
+}
+
 mod other;
 pub use self::other::*;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/mod.rs
similarity index 63%
rename from third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs
rename to third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/mod.rs
index 695cf68dc5a4..557420485a6a 100644
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig.rs
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/mod.rs
@@ -1,8 +1,10 @@
+pub type c_char = i8;
+
 s! {
     pub struct lconv {
         pub decimal_point: *mut ::c_char,
         pub thousands_sep: *mut ::c_char,
         pub grouping: *mut ::c_char,
         pub int_curr_symbol: *mut ::c_char,
         pub currency_symbol: *mut ::c_char,
         pub mon_decimal_point: *mut ::c_char,
@@ -58,18 +60,52 @@ pub const ALTMON_7: ::nl_item = 64;
 pub const ALTMON_8: ::nl_item = 65;
 pub const ALTMON_9: ::nl_item = 66;
 pub const ALTMON_10: ::nl_item = 67;
 pub const ALTMON_11: ::nl_item = 68;
 pub const ALTMON_12: ::nl_item = 69;
 
 pub const KERN_RND: ::c_int = 31;
 
+// https://github.com/bitrig/bitrig/blob/master/sys/net/if.h#L187
+pub const IFF_UP: ::c_int = 0x1; // interface is up
+pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link
+pub const IFF_NOTRAILERS: ::c_int = 0x20; // avoid use of trailers
+pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated
+pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets
+pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress
+pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
+
+pub const SIGSTKSZ : ::size_t = 40960;
+
 extern {
     pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char;
     pub fn duplocale(base: ::locale_t) -> ::locale_t;
     pub fn freelocale(loc: ::locale_t) -> ::c_int;
     pub fn newlocale(mask: ::c_int,
                      locale: *const ::c_char,
                      base: ::locale_t) -> ::locale_t;
     pub fn uselocale(loc: ::locale_t) -> ::locale_t;
+    pub fn pledge(promises: *const ::c_char,
+                  paths: *mut *const ::c_char) -> ::c_int;
     pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char;
 }
+
+cfg_if! {
+    if #[cfg(target_arch = "x86")] {
+        mod x86;
+        pub use self::x86::*;
+    } else if #[cfg(target_arch = "x86_64")] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else {
+        // Unknown target_arch
+    }
+}
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/b32/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86.rs
similarity index 100%
rename from third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/b32/mod.rs
rename to third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86.rs
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/b64/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86_64.rs
similarity index 100%
rename from third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/b64/mod.rs
rename to third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/bitrig/x86_64.rs
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs
index 227e8b365946..bf5ddd2e7a8e 100644
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs
@@ -171,16 +171,41 @@ s! {
         pub ifm_tableid: ::c_ushort,
         pub ifm_pad1: ::c_uchar,
         pub ifm_pad2: ::c_uchar,
         pub ifm_addrs: ::c_int,
         pub ifm_flags: ::c_int,
         pub ifm_xflags: ::c_int,
         pub ifm_data: if_data,
     }
+
+    pub struct sockaddr_dl {
+        pub sdl_len: ::c_uchar,
+        pub sdl_family: ::c_uchar,
+        pub sdl_index: ::c_ushort,
+        pub sdl_type: ::c_uchar,
+        pub sdl_nlen: ::c_uchar,
+        pub sdl_alen: ::c_uchar,
+        pub sdl_slen: ::c_uchar,
+        pub sdl_data: [::c_char; 24],
+    }
+
+    pub struct sockpeercred {
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub pid: ::pid_t,
+    }
+
+    pub struct arphdr {
+        pub ar_hrd: u16,
+        pub ar_pro: u16,
+        pub ar_hln: u8,
+        pub ar_pln: u8,
+        pub ar_op: u16,
+    }
 }
 
 pub const UT_NAMESIZE: usize = 32;
 pub const UT_LINESIZE: usize = 8;
 pub const UT_HOSTSIZE: usize = 256;
 
 pub const O_CLOEXEC: ::c_int = 0x10000;
 pub const O_DIRECTORY: ::c_int = 0x20000;
@@ -195,17 +220,21 @@ pub const POLLNORM: ::c_short = ::POLLRDNORM;
 
 pub const ENOATTR : ::c_int = 83;
 pub const EILSEQ : ::c_int = 84;
 pub const EOVERFLOW : ::c_int = 87;
 pub const ECANCELED : ::c_int = 88;
 pub const EIDRM : ::c_int = 89;
 pub const ENOMSG : ::c_int = 90;
 pub const ENOTSUP : ::c_int = 91;
-pub const ELAST : ::c_int = 91;
+pub const EBADMSG : ::c_int = 92;
+pub const ENOTRECOVERABLE : ::c_int = 93;
+pub const EOWNERDEAD : ::c_int = 94;
+pub const EPROTO : ::c_int = 95;
+pub const ELAST : ::c_int = 95;
 
 pub const F_DUPFD_CLOEXEC : ::c_int = 10;
 
 pub const AT_FDCWD: ::c_int = -100;
 pub const AT_EACCESS: ::c_int = 0x01;
 pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x02;
 pub const AT_SYMLINK_FOLLOW: ::c_int = 0x04;
 pub const AT_REMOVEDIR: ::c_int = 0x08;
@@ -282,16 +311,19 @@ pub const IPPROTO_MPLS: ::c_int = 137;
 /// PFSYNC
 pub const IPPROTO_PFSYNC: ::c_int = 240;
 pub const IPPROTO_MAX: ::c_int = 256;
 
 /* Only used internally, so it can be outside the range of valid IP protocols */
 /// Divert sockets
 pub const IPPROTO_DIVERT: ::c_int = 258;
 
+pub const IP_RECVDSTADDR: ::c_int = 7;
+pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR;
+
 pub const AF_ECMA: ::c_int = 8;
 pub const AF_ROUTE: ::c_int = 17;
 pub const AF_ENCAP: ::c_int = 28;
 pub const AF_SIP: ::c_int = 29;
 pub const AF_KEY: ::c_int = 30;
 pub const pseudo_AF_HDRCMPLT: ::c_int = 31;
 pub const AF_BLUETOOTH: ::c_int = 32;
 pub const AF_MPLS: ::c_int = 33;
@@ -334,17 +366,27 @@ pub const O_DSYNC : ::c_int = 128;
 pub const MAP_RENAME : ::c_int = 0x0000;
 pub const MAP_NORESERVE : ::c_int = 0x0000;
 pub const MAP_HASSEMAPHORE : ::c_int = 0x0000;
 
 pub const EIPSEC : ::c_int = 82;
 pub const ENOMEDIUM : ::c_int = 85;
 pub const EMEDIUMTYPE : ::c_int = 86;
 
+pub const EAI_BADFLAGS: ::c_int = -1;
+pub const EAI_NONAME: ::c_int = -2;
+pub const EAI_AGAIN: ::c_int = -3;
+pub const EAI_FAIL: ::c_int = -4;
+pub const EAI_NODATA: ::c_int = -5;
+pub const EAI_FAMILY: ::c_int = -6;
+pub const EAI_SOCKTYPE: ::c_int = -7;
+pub const EAI_SERVICE: ::c_int = -8;
+pub const EAI_MEMORY: ::c_int = -10;
 pub const EAI_SYSTEM: ::c_int = -11;
+pub const EAI_OVERFLOW: ::c_int = -14;
 
 pub const RUSAGE_THREAD: ::c_int = 1;
 
 pub const MAP_COPY : ::c_int = 0x0002;
 pub const MAP_NOEXTEND : ::c_int = 0x0000;
 
 pub const _PC_LINK_MAX : ::c_int = 1;
 pub const _PC_MAX_CANON : ::c_int = 2;
@@ -540,16 +582,17 @@ pub const CTL_VM: ::c_int = 2;
 pub const CTL_FS: ::c_int = 3;
 pub const CTL_NET: ::c_int = 4;
 pub const CTL_DEBUG: ::c_int = 5;
 pub const CTL_HW: ::c_int = 6;
 pub const CTL_MACHDEP: ::c_int = 7;
 pub const CTL_DDB: ::c_int = 9;
 pub const CTL_VFS: ::c_int = 10;
 pub const CTL_MAXID: ::c_int = 11;
+pub const HW_NCPUONLINE: ::c_int = 25;
 pub const KERN_OSTYPE: ::c_int = 1;
 pub const KERN_OSRELEASE: ::c_int = 2;
 pub const KERN_OSREV: ::c_int = 3;
 pub const KERN_VERSION: ::c_int = 4;
 pub const KERN_MAXVNODES: ::c_int = 5;
 pub const KERN_MAXPROC: ::c_int = 6;
 pub const KERN_MAXFILES: ::c_int = 7;
 pub const KERN_ARGMAX: ::c_int = 8;
@@ -614,17 +657,18 @@ pub const KERN_CONSDEV: ::c_int = 75;
 pub const KERN_NETLIVELOCKS: ::c_int = 76;
 pub const KERN_POOL_DEBUG: ::c_int = 77;
 pub const KERN_PROC_CWD: ::c_int = 78;
 pub const KERN_PROC_NOBROADCASTKILL: ::c_int = 79;
 pub const KERN_PROC_VMMAP: ::c_int = 80;
 pub const KERN_GLOBAL_PTRACE: ::c_int = 81;
 pub const KERN_CONSBUFSIZE: ::c_int = 82;
 pub const KERN_CONSBUF: ::c_int = 83;
-pub const KERN_MAXID: ::c_int = 84;
+pub const KERN_AUDIO: ::c_int = 84;
+pub const KERN_MAXID: ::c_int = 85;
 pub const KERN_PROC_ALL: ::c_int = 0;
 pub const KERN_PROC_PID: ::c_int = 1;
 pub const KERN_PROC_PGRP: ::c_int = 2;
 pub const KERN_PROC_SESSION: ::c_int = 3;
 pub const KERN_PROC_TTY: ::c_int = 4;
 pub const KERN_PROC_UID: ::c_int = 5;
 pub const KERN_PROC_RUID: ::c_int = 6;
 pub const KERN_PROC_KTHREAD: ::c_int = 7;
@@ -646,16 +690,18 @@ pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS;
 pub const OLCUC: ::tcflag_t = 0x20;
 pub const ONOCR: ::tcflag_t = 0x40;
 pub const ONLRET: ::tcflag_t = 0x80;
 
 pub const SOCK_CLOEXEC: ::c_int = 0x8000;
 pub const SOCK_NONBLOCK: ::c_int = 0x4000;
 pub const SOCK_DNS: ::c_int = 0x1000;
 
+pub const WCONTINUED: ::c_int = 8;
+
 f! {
     pub fn WIFCONTINUED(status: ::c_int) -> bool {
         status & 0o177777 == 0o177777
     }
 }
 
 extern {
     pub fn dirfd(dirp: *mut ::DIR) -> ::c_int;
@@ -681,28 +727,23 @@ extern {
     pub fn sysctl(name: *const ::c_int,
                   namelen: ::c_uint,
                   oldp: *mut ::c_void,
                   oldlenp: *mut ::size_t,
                   newp: *mut ::c_void,
                   newlen: ::size_t)
                   -> ::c_int;
     pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int;
-    pub fn pledge(promises: *const ::c_char,
-                  paths: *mut *const ::c_char) -> ::c_int;
     pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int;
     pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(target_os = "openbsd")] {
         mod openbsd;
         pub use self::openbsd::*;
     } else if #[cfg(target_os = "bitrig")] {
         mod bitrig;
         pub use self::bitrig::*;
     } else {
         // Unknown target_os
     }
 }
-
-mod other;
-pub use self::other::*;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs
deleted file mode 100644
index 5c804473adec..000000000000
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-s! {
-    pub struct lconv {
-        pub decimal_point: *mut ::c_char,
-        pub thousands_sep: *mut ::c_char,
-        pub grouping: *mut ::c_char,
-        pub int_curr_symbol: *mut ::c_char,
-        pub currency_symbol: *mut ::c_char,
-        pub mon_decimal_point: *mut ::c_char,
-        pub mon_thousands_sep: *mut ::c_char,
-        pub mon_grouping: *mut ::c_char,
-        pub positive_sign: *mut ::c_char,
-        pub negative_sign: *mut ::c_char,
-        pub int_frac_digits: ::c_char,
-        pub frac_digits: ::c_char,
-        pub p_cs_precedes: ::c_char,
-        pub p_sep_by_space: ::c_char,
-        pub n_cs_precedes: ::c_char,
-        pub n_sep_by_space: ::c_char,
-        pub p_sign_posn: ::c_char,
-        pub n_sign_posn: ::c_char,
-        pub int_p_cs_precedes: ::c_char,
-        pub int_p_sep_by_space: ::c_char,
-        pub int_n_cs_precedes: ::c_char,
-        pub int_n_sep_by_space: ::c_char,
-        pub int_p_sign_posn: ::c_char,
-        pub int_n_sign_posn: ::c_char,
-    }
-}
-
-extern {
-    pub fn accept4(s: ::c_int, addr: *mut ::sockaddr,
-                   addrlen: *mut ::socklen_t, flags: ::c_int) -> ::c_int;
-    pub fn execvpe(file: *const ::c_char, argv: *const *const ::c_char,
-                   envp: *const *const ::c_char) -> ::c_int;
-}
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/aarch64.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/aarch64.rs
new file mode 100644
index 000000000000..6aa9950ed105
--- /dev/null
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/aarch64.rs
@@ -0,0 +1,3 @@
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type c_char = u8;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
new file mode 100644
index 000000000000..5e6948115f86
--- /dev/null
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs
@@ -0,0 +1,279 @@
+s! {
+    pub struct lconv {
+        pub decimal_point: *mut ::c_char,
+        pub thousands_sep: *mut ::c_char,
+        pub grouping: *mut ::c_char,
+        pub int_curr_symbol: *mut ::c_char,
+        pub currency_symbol: *mut ::c_char,
+        pub mon_decimal_point: *mut ::c_char,
+        pub mon_thousands_sep: *mut ::c_char,
+        pub mon_grouping: *mut ::c_char,
+        pub positive_sign: *mut ::c_char,
+        pub negative_sign: *mut ::c_char,
+        pub int_frac_digits: ::c_char,
+        pub frac_digits: ::c_char,
+        pub p_cs_precedes: ::c_char,
+        pub p_sep_by_space: ::c_char,
+        pub n_cs_precedes: ::c_char,
+        pub n_sep_by_space: ::c_char,
+        pub p_sign_posn: ::c_char,
+        pub n_sign_posn: ::c_char,
+        pub int_p_cs_precedes: ::c_char,
+        pub int_p_sep_by_space: ::c_char,
+        pub int_n_cs_precedes: ::c_char,
+        pub int_n_sep_by_space: ::c_char,
+        pub int_p_sign_posn: ::c_char,
+        pub int_n_sign_posn: ::c_char,
+    }
+
+    pub struct statfs {
+        pub f_flags: ::uint32_t,
+        pub f_bsize: ::uint32_t,
+        pub f_iosize: ::uint32_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::int64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::uint64_t,
+        pub f_favail: ::int64_t,
+        pub f_syncwrites: ::uint64_t,
+        pub f_syncreads: ::uint64_t,
+        pub f_asyncwrites: ::uint64_t,
+        pub f_asyncreads: ::uint64_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namemax: ::uint32_t,
+        pub f_owner: ::uid_t,
+        pub f_ctime: ::uint64_t,
+        pub f_fstypename: [::c_char; 16],
+        pub f_mntonname: [::c_char; 90],
+        pub f_mntfromname: [::c_char; 90],
+        pub f_mntfromspec: [::c_char; 90],
+        pub mount_info: mount_info,
+    }
+
+    pub union mount_info {
+        pub ufs_args: ufs_args,
+        pub mfs_args: mfs_args,
+        pub nfs_args: nfs_args,
+        pub iso_args: iso_args,
+        pub msdosfs_args: msdosfs_args,
+        pub ntfs_args: ntfs_args,
+        pub tmpfs_args: tmpfs_args,
+        align: [::c_char; 160],
+    }
+
+    pub struct ufs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+    }
+
+    pub struct mfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        // https://github.com/openbsd/src/blob/master/sys/sys/types.h#L134
+        pub base: *mut ::c_char,
+        pub size: ::c_ulong,
+    }
+
+    pub struct iso_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub flags: ::c_int,
+        pub sess: ::c_int,
+    }
+
+    pub struct nfs_args {
+        pub version: ::c_int,
+        pub addr: *mut ::sockaddr,
+        pub addrlen: ::c_int,
+        pub sotype: ::c_int,
+        pub proto: ::c_int,
+        pub fh: *mut ::c_uchar,
+        pub fhsize: ::c_int,
+        pub flags: ::c_int,
+        pub wsize: ::c_int,
+        pub rsize: ::c_int,
+        pub readdirsize: ::c_int,
+        pub timeo: ::c_int,
+        pub retrans: ::c_int,
+        pub maxgrouplist: ::c_int,
+        pub readahead: ::c_int,
+        pub leaseterm: ::c_int,
+        pub deadthresh: ::c_int,
+        pub hostname: *mut ::c_char,
+        pub acregmin: ::c_int,
+        pub acregmax: ::c_int,
+        pub acdirmin: ::c_int,
+        pub acdirmax: ::c_int,
+    }
+
+    pub struct msdosfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub mask: ::mode_t,
+        pub flags: ::c_int,
+    }
+
+    pub struct ntfs_args {
+        pub fspec: *mut ::c_char,
+        pub export_info: export_args,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub mode: ::mode_t,
+        pub flag: ::c_ulong,
+    }
+
+    pub struct udf_args {
+        pub fspec: *mut ::c_char,
+        pub lastblock: ::uint32_t,
+    }
+
+    pub struct tmpfs_args {
+        pub ta_version: ::c_int,
+        pub ta_nodes_max: ::ino_t,
+        pub ta_size_max: ::off_t,
+        pub ta_root_uid: ::uid_t,
+        pub ta_root_gid: ::gid_t,
+        pub ta_root_mode: ::mode_t,
+    }
+
+    pub struct fusefs_args {
+        pub name: *mut ::c_char,
+        pub fd: ::c_int,
+        pub max_read: ::c_int,
+        pub allow_other: ::c_int,
+    }
+
+    pub struct xucred {
+        pub cr_uid: ::uid_t,
+        pub cr_gid: ::gid_t,
+        pub cr_ngroups: ::c_short,
+        //https://github.com/openbsd/src/blob/master/sys/sys/syslimits.h#L44
+        pub cr_groups: [::gid_t; 16],
+    }
+
+    pub struct export_args {
+        pub ex_flags: ::c_int,
+        pub ex_root: ::uid_t,
+        pub ex_anon: xucred,
+        pub ex_addr: *mut ::sockaddr,
+        pub ex_addrlen: ::c_int,
+        pub ex_mask: *mut ::sockaddr,
+        pub ex_masklen: ::c_int,
+    }
+}
+
+//https://github.com/openbsd/src/blob/master/sys/sys/mount.h
+pub const ISOFSMNT_NORRIP: ::c_int = 0x1; // disable Rock Ridge Ext
+pub const ISOFSMNT_GENS: ::c_int = 0x2; // enable generation numbers
+pub const ISOFSMNT_EXTATT: ::c_int = 0x4; // enable extended attr
+pub const ISOFSMNT_NOJOLIET: ::c_int = 0x8; // disable Joliet Ext
+pub const ISOFSMNT_SESS: ::c_int = 0x10; // use iso_args.sess
+
+pub const NFS_ARGSVERSION: ::c_int = 4; // change when nfs_args changes
+
+pub const NFSMNT_RESVPORT: ::c_int = 0; // always use reserved ports
+pub const NFSMNT_SOFT: ::c_int = 0x1; // soft mount (hard is default)
+pub const NFSMNT_WSIZE: ::c_int = 0x2; // set write size
+pub const NFSMNT_RSIZE: ::c_int = 0x4; // set read size
+pub const NFSMNT_TIMEO: ::c_int = 0x8; // set initial timeout
+pub const NFSMNT_RETRANS: ::c_int = 0x10; // set number of request retries
+pub const NFSMNT_MAXGRPS: ::c_int = 0x20; // set maximum grouplist size
+pub const NFSMNT_INT: ::c_int = 0x40; // allow interrupts on hard mount
+pub const NFSMNT_NOCONN: ::c_int = 0x80; // Don't Connect the socket
+pub const NFSMNT_NQNFS: ::c_int = 0x100; // Use Nqnfs protocol
+pub const NFSMNT_NFSV3: ::c_int = 0x200; // Use NFS Version 3 protocol
+pub const NFSMNT_KERB: ::c_int = 0x400; // Use Kerberos authentication
+pub const NFSMNT_DUMBTIMR: ::c_int = 0x800; // Don't estimate rtt dynamically
+pub const NFSMNT_LEASETERM: ::c_int = 0x1000; // set lease term (nqnfs)
+pub const NFSMNT_READAHEAD: ::c_int = 0x2000; // set read ahead
+pub const NFSMNT_DEADTHRESH: ::c_int = 0x4000; // set dead server retry thresh
+pub const NFSMNT_NOAC: ::c_int = 0x8000; // disable attribute cache
+pub const NFSMNT_RDIRPLUS: ::c_int = 0x10000; // Use Readdirplus for V3
+pub const NFSMNT_READDIRSIZE: ::c_int = 0x20000; // Set readdir size
+
+/* Flags valid only in mount syscall arguments */
+pub const NFSMNT_ACREGMIN: ::c_int = 0x40000; // acregmin field valid
+pub const NFSMNT_ACREGMAX: ::c_int = 0x80000; // acregmax field valid
+pub const NFSMNT_ACDIRMIN: ::c_int = 0x100000; // acdirmin field valid
+pub const NFSMNT_ACDIRMAX: ::c_int = 0x200000; // acdirmax field valid
+
+/* Flags valid only in kernel */
+pub const NFSMNT_INTERNAL: ::c_int = 0xfffc0000; // Bits set internally
+pub const NFSMNT_HASWRITEVERF: ::c_int = 0x40000; // Has write verifier for V3
+pub const NFSMNT_GOTPATHCONF: ::c_int = 0x80000; // Got the V3 pathconf info
+pub const NFSMNT_GOTFSINFO: ::c_int = 0x100000; // Got the V3 fsinfo
+pub const NFSMNT_MNTD: ::c_int = 0x200000; // Mnt server for mnt point
+pub const NFSMNT_DISMINPROG: ::c_int = 0x400000; // Dismount in progress
+pub const NFSMNT_DISMNT: ::c_int = 0x800000; // Dismounted
+pub const NFSMNT_SNDLOCK: ::c_int = 0x1000000; // Send socket lock
+pub const NFSMNT_WANTSND: ::c_int = 0x2000000; // Want above
+pub const NFSMNT_RCVLOCK: ::c_int = 0x4000000; // Rcv socket lock
+pub const NFSMNT_WANTRCV: ::c_int = 0x8000000; // Want above
+pub const NFSMNT_WAITAUTH: ::c_int = 0x10000000; // Wait for authentication
+pub const NFSMNT_HASAUTH: ::c_int = 0x20000000; // Has authenticator
+pub const NFSMNT_WANTAUTH: ::c_int = 0x40000000; // Wants an authenticator
+pub const NFSMNT_AUTHERR: ::c_int = 0x80000000; // Authentication error
+
+pub const MSDOSFSMNT_SHORTNAME: ::c_int = 0x1; // Force old DOS short names only
+pub const MSDOSFSMNT_LONGNAME: ::c_int = 0x2; // Force Win'95 long names
+pub const MSDOSFSMNT_NOWIN95: ::c_int = 0x4; // Completely ignore Win95 entries
+
+pub const NTFS_MFLAG_CASEINS: ::c_int = 0x1;
+pub const NTFS_MFLAG_ALLNAMES: ::c_int = 0x2;
+
+pub const TMPFS_ARGS_VERSION: ::c_int = 1;
+
+pub const MAP_STACK : ::c_int = 0x4000;
+
+// https://github.com/openbsd/src/blob/master/sys/net/if.h#L187
+pub const IFF_UP: ::c_int = 0x1; // interface is up
+pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link
+pub const IFF_STATICARP: ::c_int = 0x20; // only static ARP
+pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated
+pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets
+pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress
+pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
+
+pub const SIGSTKSZ : ::size_t = 28672;
+
+extern {
+    pub fn accept4(s: ::c_int, addr: *mut ::sockaddr,
+                   addrlen: *mut ::socklen_t, flags: ::c_int) -> ::c_int;
+    pub fn execvpe(file: *const ::c_char, argv: *const *const ::c_char,
+                   envp: *const *const ::c_char) -> ::c_int;
+    pub fn pledge(promises: *const ::c_char,
+                  execpromises: *const ::c_char) -> ::c_int;
+    pub fn strtonum(nptr: *const ::c_char, minval: ::c_longlong,
+                    maxval: ::c_longlong,
+                    errstr: *mut *const ::c_char) -> ::c_longlong;
+
+    pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
+    pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
+}
+
+cfg_if! {
+    if #[cfg(target_arch = "x86")] {
+        mod x86;
+        pub use self::x86::*;
+    } else if #[cfg(target_arch = "x86_64")] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else if #[cfg(target_arch = "aarch64")] {
+        mod aarch64;
+        pub use self::aarch64::*;
+    } else {
+        // Unknown target_arch
+    }
+}
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86.rs
new file mode 100644
index 000000000000..a00e3337ef58
--- /dev/null
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86.rs
@@ -0,0 +1,3 @@
+pub type c_long = i32;
+pub type c_ulong = u32;
+pub type c_char = i8;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86_64.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86_64.rs
new file mode 100644
index 000000000000..27b94126688f
--- /dev/null
+++ b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/x86_64.rs
@@ -0,0 +1,3 @@
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type c_char = i8;
diff --git a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs b/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs
deleted file mode 100644
index e4087da7bc23..000000000000
--- a/third_party/rust/libc/src/unix/bsd/netbsdlike/openbsdlike/other/mod.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-cfg_if! {
-    if #[cfg(target_arch = "x86_64")] {
-        mod b64;
-        pub use self::b64::*;
-    } else if #[cfg(target_arch = "x86")] {
-        mod b32;
-        pub use self::b32::*;
-    } else {
-        // Unknown target_arch
-    }
-}
diff --git a/third_party/rust/libc/src/unix/haiku/mod.rs b/third_party/rust/libc/src/unix/haiku/mod.rs
index 2b05e8ef87e2..2ef36f8f38e9 100644
--- a/third_party/rust/libc/src/unix/haiku/mod.rs
+++ b/third_party/rust/libc/src/unix/haiku/mod.rs
@@ -374,24 +374,25 @@ pub const PTHREAD_CREATE_DETACHED: ::c_int = 1;
 pub const CLOCK_REALTIME: ::c_int = -1;
 pub const CLOCK_MONOTONIC: ::c_int = 0;
 
 pub const RLIMIT_CORE: ::c_int = 0;
 pub const RLIMIT_CPU: ::c_int = 1;
 pub const RLIMIT_DATA: ::c_int = 2;
 pub const RLIMIT_FSIZE: ::c_int = 3;
 pub const RLIMIT_NOFILE: ::c_int = 4;
+pub const RLIMIT_STACK: ::c_int = 5;
 pub const RLIMIT_AS: ::c_int = 6;
 // Haiku specific
 pub const RLIMIT_NOVMON: ::c_int = 7;
 pub const RLIMIT_NLIMITS: ::c_int = 8;
 
 pub const RUSAGE_SELF: ::c_int = 0;
 
-pub const RTLD_LAXY: ::c_int = 0;
+pub const RTLD_LAZY: ::c_int = 0;
 
 pub const NCCS: usize = 11;
 
 pub const O_RDONLY: ::c_int = 0x0000;
 pub const O_WRONLY: ::c_int = 0x0001;
 pub const O_RDWR: ::c_int = 0x0002;
 pub const O_ACCMODE: ::c_int = 0x0003;
 
@@ -473,17 +474,27 @@ pub const SIGBUS: ::c_int = 30;
 pub const SIG_BLOCK: ::c_int = 1;
 pub const SIG_UNBLOCK: ::c_int = 2;
 pub const SIG_SETMASK: ::c_int = 3;
 
 pub const SIGEV_NONE: ::c_int = 0;
 pub const SIGEV_SIGNAL: ::c_int = 1;
 pub const SIGEV_THREAD: ::c_int = 2;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
 
 pub const PROT_NONE: ::c_int = 0;
 pub const PROT_READ: ::c_int = 1;
 pub const PROT_WRITE: ::c_int = 2;
 pub const PROT_EXEC: ::c_int = 4;
 
 pub const LC_ALL: ::c_int = 0;
 pub const LC_COLLATE: ::c_int = 1;
@@ -601,48 +612,82 @@ pub const IPPROTO_RAW: ::c_int = 255;
 
 // These are prefixed with POSIX_ on Haiku
 pub const MADV_NORMAL: ::c_int = 1;
 pub const MADV_SEQUENTIAL: ::c_int = 2;
 pub const MADV_RANDOM: ::c_int = 3;
 pub const MADV_WILLNEED: ::c_int = 4;
 pub const MADV_DONTNEED: ::c_int = 5;
 
+// https://github.com/haiku/haiku/blob/master/headers/posix/net/if.h#L80
+pub const IFF_UP: ::c_int = 0x0001;
+pub const IFF_BROADCAST: ::c_int = 0x0002; // valid broadcast address
 pub const IFF_LOOPBACK: ::c_int = 0x0008;
+pub const IFF_POINTOPOINT: ::c_int = 0x0010; // point-to-point link
+pub const IFF_NOARP: ::c_int = 0x0040; // no address resolution
+pub const IFF_AUTOUP: ::c_int = 0x0080; // auto dial
+pub const IFF_PROMISC: ::c_int = 0x0100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x0200; // receive all multicast packets
+pub const IFF_SIMPLEX: ::c_int = 0x0800; // doesn't receive own transmissions
+pub const IFF_LINK: ::c_int = 0x1000; // has link
+pub const IFF_AUTO_CONFIGURED: ::c_int = 0x2000;
+pub const IFF_CONFIGURING: ::c_int = 0x4000;
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
 
 pub const AF_UNSEC: ::c_int = 0;
 pub const AF_INET: ::c_int = 1;
 pub const AF_APPLETALK: ::c_int = 2;
 pub const AF_ROUTE: ::c_int = 3;
 pub const AF_LINK: ::c_int = 4;
 pub const AF_INET6: ::c_int = 5;
 pub const AF_DLI: ::c_int = 6;
 pub const AF_IPX: ::c_int = 7;
 pub const AF_NOTIFY: ::c_int = 8;
 pub const AF_LOCAL: ::c_int = 9;
 pub const AF_UNIX: ::c_int = AF_LOCAL;
 pub const AF_BLUETOOTH: ::c_int = 10;
 pub const AF_MAX: ::c_int = 11;
 
+pub const IP_OPTIONS: ::c_int = 1;
+pub const IP_HDRINCL: ::c_int = 2;
+pub const IP_TOS: ::c_int = 3;
+pub const IP_TTL: ::c_int = 4;
+pub const IP_RECVOPTS: ::c_int = 5;
+pub const IP_RECVRETOPTS: ::c_int = 6;
+pub const IP_RECVDSTADDR: ::c_int = 7;
+pub const IP_RETOPTS: ::c_int = 8;
+pub const IP_MULTICAST_IF: ::c_int = 9;
 pub const IP_MULTICAST_TTL: ::c_int = 10;
 pub const IP_MULTICAST_LOOP: ::c_int = 11;
-pub const IP_TTL: ::c_int = 4;
-pub const IP_HDRINCL: ::c_int = 2;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
+pub const IP_BLOCK_SOURCE: ::c_int = 14;
+pub const IP_UNBLOCK_SOURCE: ::c_int = 15;
+pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 16;
+pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 17;
 
 pub const TCP_NODELAY: ::c_int = 0x01;
 pub const TCP_MAXSEG: ::c_int = 0x02;
 pub const TCP_NOPUSH: ::c_int = 0x04;
 pub const TCP_NOOPT: ::c_int = 0x08;
 
+pub const IPV6_MULTICAST_IF: ::c_int = 24;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 25;
 pub const IPV6_MULTICAST_LOOP: ::c_int = 26;
+pub const IPV6_UNICAST_HOPS: ::c_int = 27;
 pub const IPV6_JOIN_GROUP: ::c_int = 28;
 pub const IPV6_LEAVE_GROUP: ::c_int = 29;
 pub const IPV6_V6ONLY: ::c_int = 30;
+pub const IPV6_PKTINFO: ::c_int = 31;
+pub const IPV6_RECVPKTINFO: ::c_int = 32;
+pub const IPV6_HOPLIMIT: ::c_int = 33;
+pub const IPV6_REVCHOPLIMIT: ::c_int = 34;
+pub const IPV6_HOPOPTS: ::c_int = 35;
+pub const IPV6_DSTOPTS: ::c_int = 36;
+pub const IPV6_RTHDR: ::c_int = 37;
 
 pub const MSG_OOB: ::c_int = 0x0001;
 pub const MSG_PEEK: ::c_int = 0x0002;
 pub const MSG_DONTROUTE: ::c_int = 0x0004;
 pub const MSG_EOR: ::c_int = 0x0008;
 pub const MSG_TRUNC: ::c_int = 0x0010;
 pub const MSG_CTRUNC: ::c_int = 0x0020;
 pub const MSG_WAITALL: ::c_int = 0x0040;
@@ -673,17 +718,19 @@ pub const SA_RESTART: ::c_int = 0x10;
 pub const SA_ONSTACK: ::c_int = 0x20;
 pub const SA_SIGINFO: ::c_int = 0x40;
 pub const SA_NOMASK: ::c_int = SA_NODEFER;
 pub const SA_STACK: ::c_int = SA_ONSTACK;
 pub const SA_ONESHOT: ::c_int = SA_RESETHAND;
 
 pub const FD_SETSIZE: usize = 1024;
 
+pub const RTLD_LOCAL: ::c_int = 0x0;
 pub const RTLD_NOW: ::c_int = 0x1;
+pub const RTLD_GLOBAL: ::c_int = 0x2;
 pub const RTLD_DEFAULT: *mut ::c_void = 0isize as *mut ::c_void;
 
 pub const BUFSIZ: ::c_uint = 8192;
 pub const FILENAME_MAX: ::c_uint = 256;
 pub const FOPEN_MAX: ::c_uint = 128;
 pub const L_tmpnam: ::c_uint = 512;
 pub const TMP_MAX: ::c_uint = 32768;
 
@@ -1066,17 +1113,16 @@ extern {
                        serv: *mut ::c_char,
                        sevlen: ::size_t,
                        flags: ::c_int) -> ::c_int;
     pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
                                    abstime: *const ::timespec) -> ::c_int;
     pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t,
                   options: ::c_int) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
     pub fn glob(pattern: *const ::c_char,
                 flags: ::c_int,
                 errfunc: Option<extern fn(epath: *const ::c_char,
                                           errno: ::c_int) -> ::c_int>,
                 pglob: *mut ::glob_t) -> ::c_int;
     pub fn globfree(pglob: *mut ::glob_t);
 
     pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int)
@@ -1094,16 +1140,17 @@ extern {
 
     pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
 
     pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
                     flags: ::c_int, addr: *mut ::sockaddr,
                     addrlen: *mut ::socklen_t) -> ::ssize_t;
     pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
     pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int;
+    pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int;
     pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
 
     pub fn bind(socket: ::c_int, address: *const ::sockaddr,
                 address_len: ::socklen_t) -> ::c_int;
 
     pub fn writev(fd: ::c_int,
                   iov: *const ::iovec,
                   iovcnt: ::c_int) -> ::ssize_t;
diff --git a/third_party/rust/libc/src/unix/hermit/aarch64.rs b/third_party/rust/libc/src/unix/hermit/aarch64.rs
new file mode 100644
index 000000000000..1a92e3b4fa34
--- /dev/null
+++ b/third_party/rust/libc/src/unix/hermit/aarch64.rs
@@ -0,0 +1,2 @@
+pub type c_char = u8;
+pub type wchar_t = u32;
diff --git a/third_party/rust/libc/src/unix/hermit/mod.rs b/third_party/rust/libc/src/unix/hermit/mod.rs
new file mode 100644
index 000000000000..bed6f7ae7f79
--- /dev/null
+++ b/third_party/rust/libc/src/unix/hermit/mod.rs
@@ -0,0 +1,736 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// liblibc port for HermitCore (https://hermitcore.org)
+// HermitCore is a unikernel based on lwIP, newlib, and
+// pthread-embedded.
+// Consider these definitions when porting liblibc to another
+// lwIP/newlib/pte-based target.
+//
+// Ported by Colin Finck <colin.finck@rwth-aachen.de>
+
+pub type c_long = i64;
+pub type c_ulong = u64;
+
+pub type uid_t = u16;
+pub type gid_t = u16;
+pub type speed_t = ::c_uint;
+pub type mode_t = u32;
+pub type dev_t = i16;
+pub type nfds_t = ::c_ulong;
+pub type socklen_t = u32;
+pub type sa_family_t = u8;
+pub type clock_t = c_ulong;
+pub type time_t = c_long;
+pub type suseconds_t = c_long;
+pub type off_t = i64;
+pub type rlim_t = ::c_ulonglong;
+pub type sigset_t = ::c_ulong;
+pub type ino_t = u16;
+pub type nlink_t = u16;
+pub type blksize_t = c_long;
+pub type blkcnt_t = c_long;
+pub type stat64 = stat;
+pub type clockid_t = c_ulong;
+pub type pthread_t = pte_handle_t;
+pub type pthread_attr_t = usize;
+pub type pthread_cond_t = usize;
+pub type pthread_condattr_t = usize;
+pub type pthread_key_t = usize;
+pub type pthread_mutex_t = usize;
+pub type pthread_mutexattr_t = usize;
+pub type pthread_rwlock_t = usize;
+pub type pthread_rwlockattr_t = usize;
+
+s! {
+    pub struct addrinfo {
+        pub ai_flags: ::c_int,
+        pub ai_family: ::c_int,
+        pub ai_socktype: ::c_int,
+        pub ai_protocol: ::c_int,
+        pub ai_addrlen: socklen_t,
+        pub ai_addr: *mut ::sockaddr,
+        pub ai_canonname: *mut c_char,
+        pub ai_next: *mut addrinfo,
+    }
+
+    pub struct dirent {
+        pub d_ino: ::c_long,
+        pub d_off: off_t,
+        pub d_reclen: u16,
+        pub d_name: [::c_char; 256],
+    }
+
+    pub struct Dl_info {}
+
+    pub struct fd_set {
+        fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE],
+    }
+
+    pub struct lconv {
+        pub decimal_point: *mut ::c_char,
+        pub thousands_sep: *mut ::c_char,
+        pub grouping: *mut ::c_char,
+        pub int_curr_symbol: *mut ::c_char,
+        pub currency_symbol: *mut ::c_char,
+        pub mon_decimal_point: *mut ::c_char,
+        pub mon_thousands_sep: *mut ::c_char,
+        pub mon_grouping: *mut ::c_char,
+        pub positive_sign: *mut ::c_char,
+        pub negative_sign: *mut ::c_char,
+        pub int_frac_digits: ::c_char,
+        pub frac_digits: ::c_char,
+        pub p_cs_precedes: ::c_char,
+        pub p_sep_by_space: ::c_char,
+        pub n_cs_precedes: ::c_char,
+        pub n_sep_by_space: ::c_char,
+        pub p_sign_posn: ::c_char,
+        pub n_sign_posn: ::c_char,
+        pub int_p_cs_precedes: ::c_char,
+        pub int_p_sep_by_space: ::c_char,
+        pub int_n_cs_precedes: ::c_char,
+        pub int_n_sep_by_space: ::c_char,
+        pub int_p_sign_posn: ::c_char,
+        pub int_n_sign_posn: ::c_char,
+    }
+
+    pub struct passwd { // Unverified
+        pub pw_name: *mut ::c_char,
+        pub pw_passwd: *mut ::c_char,
+        pub pw_uid: ::uid_t,
+        pub pw_gid: ::gid_t,
+        pub pw_gecos: *mut ::c_char,
+        pub pw_dir: *mut ::c_char,
+        pub pw_shell: *mut ::c_char,
+    }
+
+    pub struct pte_handle_t {
+        pub p: usize,
+        pub x: ::c_uint,
+    }
+
+    pub struct sched_param {
+        pub sched_priority: ::c_int,
+    }
+
+    pub struct sem_t {
+        pub value: i32,
+        pub lock: usize,
+        pub sem: usize,
+    }
+
+    pub struct sigaction {
+        pub sa_flags: ::c_int,
+        pub sa_mask: sigset_t,
+        pub sa_handler: usize,
+    }
+
+    pub struct sockaddr {
+        pub sa_len: u8,
+        pub sa_family: sa_family_t,
+        pub sa_data: [::c_char; 14],
+    }
+
+    pub struct sockaddr_in {
+        pub sin_len: u8,
+        pub sin_family: sa_family_t,
+        pub sin_port: ::in_port_t,
+        pub sin_addr: ::in_addr,
+        pub sin_zero: [::c_char; 8],
+    }
+
+    pub struct sockaddr_in6 {
+        pub sin6_len: u8,
+        pub sin6_family: sa_family_t,
+        pub sin6_port: ::in_port_t,
+        pub sin6_flowinfo: u32,
+        pub sin6_addr: ::in6_addr,
+        pub sin6_scope_id: u32,
+    }
+
+    pub struct sockaddr_storage {
+        pub s2_len: u8,
+        pub ss_family: sa_family_t,
+        pub s2_data1: [::c_char; 2],
+        pub s2_data2: [u32; 3],
+        pub s2_data3: [u32; 3],
+    }
+
+    // Dummy
+    pub struct sockaddr_un {
+        pub sun_family: sa_family_t,
+        pub sun_path: [::c_char; 108],
+    }
+
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: dev_t,
+        pub st_size: off_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: ::c_long,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_spare4: [::c_long; 2],
+    }
+
+    pub struct statvfs {}
+
+    pub struct tm {
+        pub tm_sec: ::c_int,
+        pub tm_min: ::c_int,
+        pub tm_hour: ::c_int,
+        pub tm_mday: ::c_int,
+        pub tm_mon: ::c_int,
+        pub tm_year: ::c_int,
+        pub tm_wday: ::c_int,
+        pub tm_yday: ::c_int,
+        pub tm_isdst: ::c_int,
+    }
+
+    pub struct tms {
+        pub tms_utime: ::clock_t,
+        pub tms_stime: ::clock_t,
+        pub tms_cutime: ::clock_t,
+        pub tms_cstime: ::clock_t,
+    }
+
+    pub struct termios {}
+
+    pub struct utsname {}
+}
+
+pub const AF_UNSPEC: ::c_int = 0;
+pub const AF_INET: ::c_int = 2;
+pub const AF_INET6: ::c_int = 10;
+
+// Dummy
+pub const AF_UNIX: ::c_int = 1;
+
+pub const CLOCK_REALTIME: ::clockid_t = 1;
+pub const CLOCK_MONOTONIC: ::clockid_t = 4;
+
+// Dummy
+pub const EAI_SYSTEM: ::c_int = -11;
+
+pub const EPERM: ::c_int = 1;
+pub const ENOENT: ::c_int = 2;
+pub const ESRCH: ::c_int = 3;
+pub const EINTR: ::c_int = 4;
+pub const EIO: ::c_int = 5;
+pub const ENXIO: ::c_int = 6;
+pub const E2BIG: ::c_int = 7;
+pub const ENOEXEC: ::c_int = 8;
+pub const EBADF: ::c_int = 9;
+pub const ECHILD: ::c_int = 10;
+pub const EAGAIN: ::c_int = 11;
+pub const ENOMEM: ::c_int = 12;
+pub const EACCES: ::c_int = 13;
+pub const EFAULT: ::c_int = 14;
+pub const EBUSY: ::c_int = 16;
+pub const EEXIST: ::c_int = 17;
+pub const EXDEV: ::c_int = 18;
+pub const ENODEV: ::c_int = 19;
+pub const ENOTDIR: ::c_int = 20;
+pub const EISDIR: ::c_int = 21;
+pub const EINVAL: ::c_int = 22;
+pub const ENFILE: ::c_int = 23;
+pub const EMFILE: ::c_int = 24;
+pub const ENOTTY: ::c_int = 25;
+pub const ETXTBSY: ::c_int = 26;
+pub const EFBIG: ::c_int = 27;
+pub const ENOSPC: ::c_int = 28;
+pub const ESPIPE: ::c_int = 29;
+pub const EROFS: ::c_int = 30;
+pub const EMLINK: ::c_int = 31;
+pub const EPIPE: ::c_int = 32;
+pub const EDOM: ::c_int = 33;
+pub const ERANGE: ::c_int = 34;
+pub const EDEADLK: ::c_int = 35;
+pub const ENAMETOOLONG: ::c_int = 36;
+pub const ENOLCK: ::c_int = 37;
+pub const ENOSYS: ::c_int = 38;
+pub const ENOTEMPTY: ::c_int = 39;
+pub const ELOOP: ::c_int = 40;
+pub const EWOULDBLOCK: ::c_int = EAGAIN;
+pub const ENOMSG: ::c_int = 42;
+pub const EIDRM: ::c_int = 43;
+pub const ECHRNG: ::c_int = 44;
+pub const EL2NSYNC: ::c_int = 45;
+pub const EL3HLT: ::c_int = 46;
+pub const EL3RST: ::c_int = 47;
+pub const ELNRNG: ::c_int = 48;
+pub const EUNATCH: ::c_int = 49;
+pub const ENOCSI: ::c_int = 50;
+pub const EL2HLT: ::c_int = 51;
+pub const EBADE: ::c_int = 52;
+pub const EBADR: ::c_int = 53;
+pub const EXFULL: ::c_int = 54;
+pub const ENOANO: ::c_int = 55;
+pub const EBADRQC: ::c_int = 56;
+pub const EBADSLT: ::c_int = 57;
+pub const EDEADLOCK: ::c_int = EDEADLK;
+pub const EBFONT: ::c_int = 59;
+pub const ENOSTR: ::c_int = 60;
+pub const ENODATA: ::c_int = 61;
+pub const ETIME: ::c_int = 62;
+pub const ENOSR: ::c_int = 63;
+pub const ENONET: ::c_int = 64;
+pub const ENOPKG: ::c_int = 65;
+pub const EREMOTE: ::c_int = 66;
+pub const ENOLINK: ::c_int = 67;
+pub const EADV: ::c_int = 68;
+pub const ESRMNT: ::c_int = 69;
+pub const ECOMM: ::c_int = 70;
+pub const EPROTO: ::c_int = 71;
+pub const EMULTIHOP: ::c_int = 72;
+pub const EDOTDOT: ::c_int = 73;
+pub const EBADMSG: ::c_int = 74;
+pub const EOVERFLOW: ::c_int = 75;
+pub const ENOTUNIQ: ::c_int = 76;
+pub const EBADFD: ::c_int = 77;
+pub const EREMCHG: ::c_int = 78;
+pub const ELIBACC: ::c_int = 79;
+pub const ELIBBAD: ::c_int = 80;
+pub const ELIBSCN: ::c_int = 81;
+pub const ELIBMAX: ::c_int = 82;
+pub const ELIBEXEC: ::c_int = 83;
+pub const EILSEQ: ::c_int = 84;
+pub const ERESTART: ::c_int = 85;
+pub const ESTRPIPE: ::c_int = 86;
+pub const EUSERS: ::c_int = 87;
+pub const ENOTSOCK: ::c_int = 88;
+pub const EDESTADDRREQ: ::c_int = 89;
+pub const EMSGSIZE: ::c_int = 90;
+pub const EPROTOTYPE: ::c_int = 91;
+pub const ENOPROTOOPT: ::c_int = 92;
+pub const EPROTONOSUPPORT: ::c_int = 93;
+pub const ESOCKTNOSUPPORT: ::c_int = 94;
+pub const EOPNOTSUPP: ::c_int = 95;
+pub const EPFNOSUPPORT: ::c_int = 96;
+pub const EAFNOSUPPORT: ::c_int = 97;
+pub const EADDRINUSE: ::c_int = 98;
+pub const EADDRNOTAVAIL: ::c_int = 99;
+pub const ENETDOWN: ::c_int = 100;
+pub const ENETUNREACH: ::c_int = 101;
+pub const ENETRESET: ::c_int = 102;
+pub const ECONNABORTED: ::c_int = 103;
+pub const ECONNRESET: ::c_int = 104;
+pub const ENOBUFS: ::c_int = 105;
+pub const EISCONN: ::c_int = 106;
+pub const ENOTCONN: ::c_int = 107;
+pub const ESHUTDOWN: ::c_int = 108;
+pub const ETOOMANYREFS: ::c_int = 109;
+pub const ETIMEDOUT: ::c_int = 110;
+pub const ECONNREFUSED: ::c_int = 111;
+pub const EHOSTDOWN: ::c_int = 112;
+pub const EHOSTUNREACH: ::c_int = 113;
+pub const EALREADY: ::c_int = 114;
+pub const EINPROGRESS: ::c_int = 115;
+pub const ESTALE: ::c_int = 116;
+pub const EUCLEAN: ::c_int = 117;
+pub const ENOTNAM: ::c_int = 118;
+pub const ENAVAIL: ::c_int = 119;
+pub const EISNAM: ::c_int = 120;
+pub const EREMOTEIO: ::c_int = 121;
+pub const EDQUOT: ::c_int = 122;
+pub const ENOMEDIUM: ::c_int = 123;
+pub const EMEDIUMTYPE: ::c_int = 124;
+pub const ECANCELED: ::c_int = 125;
+pub const ENOKEY: ::c_int = 126;
+pub const EKEYEXPIRED: ::c_int = 127;
+pub const EKEYREVOKED: ::c_int = 128;
+pub const EKEYREJECTED: ::c_int = 129;
+pub const EOWNERDEAD: ::c_int = 130;
+pub const ENOTRECOVERABLE: ::c_int = 131;
+pub const ERFKILL: ::c_int = 132;
+pub const EHWPOISON: ::c_int = 133;
+
+pub const EXIT_FAILURE: ::c_int = 1;
+pub const EXIT_SUCCESS: ::c_int = 0;
+
+pub const F_DUPFD: ::c_int = 0;
+pub const F_GETFD: ::c_int = 1;
+pub const F_SETFD: ::c_int = 2;
+pub const F_GETFL: ::c_int = 3;
+pub const F_SETFL: ::c_int = 4;
+pub const F_GETOWN: ::c_int = 5;
+pub const F_SETOWN: ::c_int = 6;
+pub const F_GETLK: ::c_int = 7;
+pub const F_SETLK: ::c_int = 8;
+pub const F_SETLKW: ::c_int = 9;
+pub const F_RGETLK: ::c_int = 10;
+pub const F_RSETLK: ::c_int = 11;
+pub const F_CNVT: ::c_int = 12;
+pub const F_RSETLKW: ::c_int = 13;
+pub const F_DUPFD_CLOEXEC: ::c_int = 14;
+
+pub const FD_SETSIZE: usize = 1024;
+
+// Dummy
+pub const FIOCLEX: ::c_int = 0x5451;
+
+pub const FIONBIO: ::c_int = 0x8004667e;
+pub const FIONREAD: ::c_int = 0x4004667f;
+
+pub const IP_ADD_MEMBERSHIP: ::c_int = 3;
+pub const IP_DROP_MEMBERSHIP: ::c_int = 4;
+
+pub const IP_TOS: ::c_int = 1;
+pub const IP_TTL: ::c_int = 2;
+
+pub const IP_MULTICAST_TTL: ::c_int = 5;
+pub const IP_MULTICAST_IF: ::c_int = 6;
+pub const IP_MULTICAST_LOOP: ::c_int = 7;
+
+pub const IPV6_JOIN_GROUP: ::c_int = 12;
+pub const IPV6_ADD_MEMBERSHIP: ::c_int = 12;
+pub const IPV6_LEAVE_GROUP: ::c_int = 13;
+pub const IPV6_DROP_MEMBERSHIP: ::c_int = 13;
+pub const IPV6_V6ONLY: ::c_int = 27;
+
+// Dummy
+pub const IPV6_MULTICAST_LOOP: ::c_int = 7;
+
+pub const MSG_PEEK: ::c_int = 0x01;
+pub const MSG_WAITALL: ::c_int = 0x02;
+pub const MSG_OOB: ::c_int = 0x04;
+pub const MSG_DONTWAIT: ::c_int = 0x08;
+pub const MSG_MORE: ::c_int = 0x10;
+
+pub const O_ACCMODE: ::c_int = 3;
+pub const O_RDONLY: ::c_int = 0;
+pub const O_WRONLY: ::c_int = 1;
+pub const O_RDWR: ::c_int = 2;
+pub const O_APPEND: ::c_int = 1024;
+pub const O_CREAT: ::c_int = 64;
+pub const O_EXCL: ::c_int = 128;
+pub const O_NOCTTY: ::c_int = 256;
+pub const O_NONBLOCK: ::c_int = 2048;
+pub const O_TRUNC: ::c_int = 512;
+pub const O_CLOEXEC: ::c_int = 524288;
+
+pub const POLLIN: ::c_short = 0x1;
+pub const POLLPRI: ::c_short = 0x2;
+pub const POLLOUT: ::c_short = 0x4;
+pub const POLLERR: ::c_short = 0x8;
+pub const POLLHUP: ::c_short = 0x10;
+pub const POLLNVAL: ::c_short = 0x20;
+
+pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = usize::max_value();
+pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = usize::max_value();
+pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = usize::max_value();
+
+pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
+pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
+pub const PTHREAD_STACK_MIN: ::size_t = 0;
+
+// Dummy
+pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
+
+pub const _SC_ARG_MAX: ::c_int = 0;
+pub const _SC_CHILD_MAX: ::c_int = 1;
+pub const _SC_CLK_TCK: ::c_int = 2;
+pub const _SC_NGROUPS_MAX: ::c_int = 3;
+pub const _SC_OPEN_MAX: ::c_int = 4;
+pub const _SC_JOB_CONTROL: ::c_int = 5;
+pub const _SC_SAVED_IDS: ::c_int = 6;
+pub const _SC_VERSION: ::c_int = 7;
+pub const _SC_PAGESIZE: ::c_int = 8;
+pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE;
+pub const _SC_NPROCESSORS_CONF: ::c_int = 9;
+pub const _SC_NPROCESSORS_ONLN: ::c_int = 10;
+pub const _SC_PHYS_PAGES: ::c_int = 11;
+pub const _SC_AVPHYS_PAGES: ::c_int = 12;
+pub const _SC_MQ_OPEN_MAX: ::c_int = 13;
+pub const _SC_MQ_PRIO_MAX: ::c_int = 14;
+pub const _SC_RTSIG_MAX: ::c_int = 15;
+pub const _SC_SEM_NSEMS_MAX: ::c_int = 16;
+pub const _SC_SEM_VALUE_MAX: ::c_int = 17;
+pub const _SC_SIGQUEUE_MAX: ::c_int = 18;
+pub const _SC_TIMER_MAX: ::c_int = 19;
+pub const _SC_TZNAME_MAX: ::c_int = 20;
+pub const _SC_ASYNCHRONOUS_IO: ::c_int = 21;
+pub const _SC_FSYNC: ::c_int = 22;
+pub const _SC_MAPPED_FILES: ::c_int = 23;
+pub const _SC_MEMLOCK: ::c_int = 24;
+pub const _SC_MEMLOCK_RANGE: ::c_int = 25;
+pub const _SC_MEMORY_PROTECTION: ::c_int = 26;
+pub const _SC_MESSAGE_PASSING: ::c_int = 27;
+pub const _SC_PRIORITIZED_IO: ::c_int = 28;
+pub const _SC_REALTIME_SIGNALS: ::c_int = 29;
+pub const _SC_SEMAPHORES: ::c_int = 30;
+pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 31;
+pub const _SC_SYNCHRONIZED_IO: ::c_int = 32;
+pub const _SC_TIMERS: ::c_int = 33;
+pub const _SC_AIO_LISTIO_MAX: ::c_int = 34;
+pub const _SC_AIO_MAX: ::c_int = 35;
+pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 36;
+pub const _SC_DELAYTIMER_MAX: ::c_int = 37;
+pub const _SC_THREAD_KEYS_MAX: ::c_int = 38;
+pub const _SC_THREAD_STACK_MIN: ::c_int = 39;
+pub const _SC_THREAD_THREADS_MAX: ::c_int = 40;
+pub const _SC_TTY_NAME_MAX: ::c_int = 41;
+pub const _SC_THREADS: ::c_int = 42;
+pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 43;
+pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 44;
+pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 45;
+pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 46;
+pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 47;
+pub const _SC_THREAD_PRIO_CEILING: ::c_int = _SC_THREAD_PRIO_PROTECT;
+pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 48;
+pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 49;
+pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 50;
+pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;
+pub const _SC_LOGIN_NAME_MAX: ::c_int = 52;
+pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 53;
+pub const _SC_ADVISORY_INFO: ::c_int = 54;
+pub const _SC_ATEXIT_MAX: ::c_int = 55;
+pub const _SC_BARRIERS: ::c_int = 56;
+pub const _SC_BC_BASE_MAX: ::c_int = 57;
+pub const _SC_BC_DIM_MAX: ::c_int = 58;
+pub const _SC_BC_SCALE_MAX: ::c_int = 59;
+pub const _SC_BC_STRING_MAX: ::c_int = 60;
+pub const _SC_CLOCK_SELECTION: ::c_int = 61;
+pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 62;
+pub const _SC_CPUTIME: ::c_int = 63;
+pub const _SC_EXPR_NEST_MAX: ::c_int = 64;
+pub const _SC_HOST_NAME_MAX: ::c_int = 65;
+pub const _SC_IOV_MAX: ::c_int = 66;
+pub const _SC_IPV6: ::c_int = 67;
+pub const _SC_LINE_MAX: ::c_int = 68;
+pub const _SC_MONOTONIC_CLOCK: ::c_int = 69;
+pub const _SC_RAW_SOCKETS: ::c_int = 70;
+pub const _SC_READER_WRITER_LOCKS: ::c_int = 71;
+pub const _SC_REGEXP: ::c_int = 72;
+pub const _SC_RE_DUP_MAX: ::c_int = 73;
+pub const _SC_SHELL: ::c_int = 74;
+pub const _SC_SPAWN: ::c_int = 75;
+pub const _SC_SPIN_LOCKS: ::c_int = 76;
+pub const _SC_SPORADIC_SERVER: ::c_int = 77;
+pub const _SC_SS_REPL_MAX: ::c_int = 78;
+pub const _SC_SYMLOOP_MAX: ::c_int = 79;
+pub const _SC_THREAD_CPUTIME: ::c_int = 80;
+pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 81;
+pub const _SC_TIMEOUTS: ::c_int = 82;
+pub const _SC_TRACE: ::c_int = 83;
+pub const _SC_TRACE_EVENT_FILTER: ::c_int = 84;
+pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 85;
+pub const _SC_TRACE_INHERIT: ::c_int = 86;
+pub const _SC_TRACE_LOG: ::c_int = 87;
+pub const _SC_TRACE_NAME_MAX: ::c_int = 88;
+pub const _SC_TRACE_SYS_MAX: ::c_int = 89;
+pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 90;
+pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 91;
+pub const _SC_V7_ILP32_OFF32: ::c_int = 92;
+pub const _SC_V6_ILP32_OFF32: ::c_int =_SC_V7_ILP32_OFF32;
+pub const _SC_XBS5_ILP32_OFF32: ::c_int = _SC_V7_ILP32_OFF32;
+pub const _SC_V7_ILP32_OFFBIG: ::c_int = 93;
+pub const _SC_V6_ILP32_OFFBIG: ::c_int = _SC_V7_ILP32_OFFBIG;
+pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = _SC_V7_ILP32_OFFBIG;
+pub const _SC_V7_LP64_OFF64: ::c_int = 94;
+pub const _SC_V6_LP64_OFF64: ::c_int = _SC_V7_LP64_OFF64;
+pub const _SC_XBS5_LP64_OFF64: ::c_int = _SC_V7_LP64_OFF64;
+pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 95;
+pub const _SC_V6_LPBIG_OFFBIG: ::c_int = _SC_V7_LPBIG_OFFBIG;
+pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = _SC_V7_LPBIG_OFFBIG;
+pub const _SC_XOPEN_CRYPT: ::c_int = 96;
+pub const _SC_XOPEN_ENH_I18N: ::c_int = 97;
+pub const _SC_XOPEN_LEGACY: ::c_int = 98;
+pub const _SC_XOPEN_REALTIME: ::c_int = 99;
+pub const _SC_STREAM_MAX: ::c_int = 100;
+pub const _SC_PRIORITY_SCHEDULING: ::c_int = 101;
+pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 102;
+pub const _SC_XOPEN_SHM: ::c_int = 103;
+pub const _SC_XOPEN_STREAMS: ::c_int = 104;
+pub const _SC_XOPEN_UNIX: ::c_int = 105;
+pub const _SC_XOPEN_VERSION: ::c_int = 106;
+pub const _SC_2_CHAR_TERM: ::c_int = 107;
+pub const _SC_2_C_BIND: ::c_int = 108;
+pub const _SC_2_C_DEV: ::c_int = 109;
+pub const _SC_2_FORT_DEV: ::c_int = 110;
+pub const _SC_2_FORT_RUN: ::c_int = 111;
+pub const _SC_2_LOCALEDEF: ::c_int = 112;
+pub const _SC_2_PBS: ::c_int = 113;
+pub const _SC_2_PBS_ACCOUNTING: ::c_int = 114;
+pub const _SC_2_PBS_CHECKPOINT: ::c_int = 115;
+pub const _SC_2_PBS_LOCATE: ::c_int = 116;
+pub const _SC_2_PBS_MESSAGE: ::c_int = 117;
+pub const _SC_2_PBS_TRACK: ::c_int = 118;
+pub const _SC_2_SW_DEV: ::c_int = 119;
+pub const _SC_2_UPE: ::c_int = 120;
+pub const _SC_2_VERSION: ::c_int = 121;
+pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 122;
+pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 123;
+pub const _SC_XOPEN_UUCP: ::c_int = 124;
+pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 125;
+pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 126;
+pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 127;
+pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 128;
+pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 129;
+pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 130;
+pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 131;
+pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 132;
+pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 133;
+pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 134;
+pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 135;
+pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 136;
+pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 137;
+pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 138;
+pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 139;
+
+pub const S_BLKSIZE: ::mode_t = 1024;
+pub const S_IREAD: ::mode_t = 256;
+pub const S_IWRITE: ::mode_t = 128;
+pub const S_IEXEC: ::mode_t = 64;
+pub const S_ENFMT: ::mode_t = 1024;
+pub const S_IFMT: ::mode_t = 61440;
+pub const S_IFDIR: ::mode_t = 16384;
+pub const S_IFCHR: ::mode_t = 8192;
+pub const S_IFBLK: ::mode_t = 24576;
+pub const S_IFREG: ::mode_t = 32768;
+pub const S_IFLNK: ::mode_t = 40960;
+pub const S_IFSOCK: ::mode_t = 49152;
+pub const S_IFIFO: ::mode_t = 4096;
+pub const S_IRUSR: ::mode_t = 256;
+pub const S_IWUSR: ::mode_t = 128;
+pub const S_IXUSR: ::mode_t = 64;
+pub const S_IRGRP: ::mode_t = 32;
+pub const S_IWGRP: ::mode_t = 16;
+pub const S_IXGRP: ::mode_t = 8;
+pub const S_IROTH: ::mode_t = 4;
+pub const S_IWOTH: ::mode_t = 2;
+pub const S_IXOTH: ::mode_t = 1;
+
+pub const SEEK_SET: ::c_int = 0;
+pub const SEEK_CUR: ::c_int = 1;
+pub const SEEK_END: ::c_int = 2;
+
+pub const SHUT_RD: ::c_int = 0;
+pub const SHUT_WR: ::c_int = 1;
+pub const SHUT_RDWR: ::c_int = 2;
+
+pub const SIG_SETMASK: ::c_int = 0;
+
+pub const SIGHUP: ::c_int = 1;
+pub const SIGINT: ::c_int = 2;
+pub const SIGQUIT: ::c_int = 3;
+pub const SIGILL: ::c_int = 4;
+pub const SIGABRT: ::c_int = 6;
+pub const SIGEMT: ::c_int = 7;
+pub const SIGFPE: ::c_int = 8;
+pub const SIGKILL: ::c_int = 9;
+pub const SIGSEGV: ::c_int = 11;
+pub const SIGPIPE: ::c_int = 13;
+pub const SIGALRM: ::c_int = 14;
+pub const SIGTERM: ::c_int = 15;
+
+pub const SO_DEBUG: ::c_int = 0x0001;
+pub const SO_ACCEPTCONN: ::c_int = 0x0002;
+pub const SO_REUSEADDR: ::c_int = 0x0004;
+pub const SO_KEEPALIVE: ::c_int = 0x0008;
+pub const SO_DONTROUTE: ::c_int = 0x0010;
+pub const SO_BROADCAST: ::c_int = 0x0020;
+pub const SO_USELOOPBACK: ::c_int = 0x0040;
+pub const SO_LINGER: ::c_int = 0x0080;
+pub const SO_OOBINLINE: ::c_int = 0x0100;
+pub const SO_REUSEPORT: ::c_int = 0x0200;
+pub const SO_SNDBUF: ::c_int = 0x1001;
+pub const SO_RCVBUF: ::c_int = 0x1002;
+pub const SO_SNDLOWAT: ::c_int = 0x1003;
+pub const SO_RCVLOWAT: ::c_int = 0x1004;
+pub const SO_SNDTIMEO: ::c_int = 0x1005;
+pub const SO_RCVTIMEO: ::c_int = 0x1006;
+pub const SO_ERROR: ::c_int = 0x1007;
+pub const SO_TYPE: ::c_int = 0x1008;
+pub const SO_CONTIMEO: ::c_int = 0x1009;
+pub const SO_NO_CHECK: ::c_int = 0x100a;
+
+pub const SOCK_STREAM: ::c_int = 1;
+pub const SOCK_DGRAM: ::c_int = 2;
+pub const SOCK_RAW: ::c_int = 3;
+
+pub const SOL_SOCKET: ::c_int = 0xfff;
+
+pub const STDIN_FILENO: ::c_int = 0;
+pub const STDOUT_FILENO: ::c_int = 1;
+pub const STDERR_FILENO: ::c_int = 2;
+
+pub const TCP_NODELAY: ::c_int = 0x01;
+pub const TCP_KEEPALIVE: ::c_int = 0x02;
+pub const TCP_KEEPIDLE: ::c_int = 0x03;
+pub const TCP_KEEPINTVL: ::c_int = 0x04;
+pub const TCP_KEEPCNT: ::c_int = 0x05;
+
+const ULONG_SIZE: usize = 64;
+
+pub const WNOHANG: ::c_int = 0x00000001;
+
+f! {
+    pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
+
+    pub fn WIFEXITED(status: ::c_int) -> bool {
+        (status & 0xff) == 0
+    }
+
+    pub fn WTERMSIG(status: ::c_int) -> ::c_int {
+        status & 0x7f
+    }
+}
+
+extern {
+    pub fn bind(s: ::c_int, name: *const ::sockaddr, namelen: ::socklen_t)
+        -> ::c_int;
+
+    pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
+
+    pub fn getpwuid_r(uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char,
+        buflen: ::size_t, result: *mut *mut passwd) -> ::c_int;
+
+    // Dummy
+    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+
+    pub fn memalign(align: ::size_t, nbytes: ::size_t) -> *mut ::c_void;
+
+    pub fn pthread_create(tid: *mut ::pthread_t, attr: *const ::pthread_attr_t,
+        start: extern fn(*mut ::c_void) -> *mut ::c_void, arg: *mut ::c_void)
+        -> ::c_int;
+
+    pub fn pthread_sigmask(how: ::c_int, set: *const ::sigset_t,
+        oset: *mut ::sigset_t) -> ::c_int;
+
+    pub fn recvfrom(s: ::c_int, mem: *mut ::c_void, len: ::size_t,
+        flags: ::c_int, from: *mut ::sockaddr, fromlen: *mut ::socklen_t)
+        -> ::c_int;
+
+    pub fn setgroups(ngroups: ::c_int, grouplist: *const ::gid_t) -> ::c_int;
+}
+
+cfg_if! {
+    if #[cfg(target_arch = "aarch64")] {
+        mod aarch64;
+        pub use self::aarch64::*;
+    } else if #[cfg(target_arch = "x86_64")] {
+        mod x86_64;
+        pub use self::x86_64::*;
+    } else {
+        // Unknown target_arch
+    }
+}
diff --git a/third_party/rust/libc/src/unix/hermit/x86_64.rs b/third_party/rust/libc/src/unix/hermit/x86_64.rs
new file mode 100644
index 000000000000..76ec3ce823e8
--- /dev/null
+++ b/third_party/rust/libc/src/unix/hermit/x86_64.rs
@@ -0,0 +1,2 @@
+pub type c_char = i8;
+pub type wchar_t = i32;
diff --git a/third_party/rust/libc/src/unix/mod.rs b/third_party/rust/libc/src/unix/mod.rs
index 87e6a19655d4..9c68178ad15c 100644
--- a/third_party/rust/libc/src/unix/mod.rs
+++ b/third_party/rust/libc/src/unix/mod.rs
@@ -99,18 +99,20 @@ s! {
         __reserved: [c_long; 16],
     }
 
     #[cfg_attr(target_os = "netbsd", repr(packed))]
     pub struct in_addr {
         pub s_addr: in_addr_t,
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct in6_addr {
         pub s6_addr: [u8; 16],
+        #[cfg(not(feature = "align"))]
         __align: [u32; 0],
     }
 
     pub struct ip_mreq {
         pub imr_multiaddr: in_addr,
         pub imr_interface: in_addr,
     }
 
@@ -185,16 +187,17 @@ s! {
         pub p_proto: ::c_int,
     }
 }
 
 pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
 pub const SIG_IGN: sighandler_t = 1 as sighandler_t;
 pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
 
+pub const DT_UNKNOWN: u8 = 0;
 pub const DT_FIFO: u8 = 1;
 pub const DT_CHR: u8 = 2;
 pub const DT_DIR: u8 = 4;
 pub const DT_BLK: u8 = 6;
 pub const DT_REG: u8 = 8;
 pub const DT_LNK: u8 = 10;
 pub const DT_SOCK: u8 = 12;
 
@@ -205,16 +208,17 @@ pub const GRPQUOTA: ::c_int = 1;
 
 pub const SIGIOT: ::c_int = 6;
 
 pub const S_ISUID: ::c_int = 0x800;
 pub const S_ISGID: ::c_int = 0x400;
 pub const S_ISVTX: ::c_int = 0x200;
 
 pub const IF_NAMESIZE: ::size_t = 16;
+pub const IFNAMSIZ: ::size_t = IF_NAMESIZE;
 
 pub const LOG_EMERG: ::c_int = 0;
 pub const LOG_ALERT: ::c_int = 1;
 pub const LOG_CRIT: ::c_int = 2;
 pub const LOG_ERR: ::c_int = 3;
 pub const LOG_WARNING: ::c_int = 4;
 pub const LOG_NOTICE: ::c_int = 5;
 pub const LOG_INFO: ::c_int = 6;
@@ -261,32 +265,44 @@ pub const IPPROTO_UDP: ::c_int = 17;
 pub const IPPROTO_IP: ::c_int = 0;
 pub const IPPROTO_IPV6: ::c_int = 41;
 
 pub const INADDR_LOOPBACK: in_addr_t = 2130706433;
 pub const INADDR_ANY: in_addr_t = 0;
 pub const INADDR_BROADCAST: in_addr_t = 4294967295;
 pub const INADDR_NONE: in_addr_t = 4294967295;
 
+pub const ARPOP_REQUEST: u16 = 1;
+pub const ARPOP_REPLY: u16 = 2;
+
+pub const ATF_COM: ::c_int = 0x02;
+pub const ATF_PERM: ::c_int = 0x04;
+pub const ATF_PUBL: ::c_int = 0x08;
+pub const ATF_USETRAILERS: ::c_int = 0x10;
+
 cfg_if! {
-    if #[cfg(dox)] {
+    if #[cfg(cross_platform_docs)] {
         // on dox builds don't pull in anything
     } else if #[cfg(target_os = "l4re")] {
         // required libraries for L4Re are linked externally, ATM
     } else if #[cfg(feature = "use_std")] {
         // cargo build, don't pull in anything extra as the libstd dep
         // already pulls in all libs.
-    } else if #[cfg(any(all(target_env = "musl", not(target_arch = "mips"))))] {
-        #[link(name = "c", kind = "static", cfg(target_feature = "crt-static"))]
-        #[link(name = "c", cfg(not(target_feature = "crt-static")))]
+    } else if #[cfg(target_env = "musl")] {
+        #[cfg_attr(feature = "stdbuild",
+                   link(name = "c", kind = "static",
+                        cfg(target_feature = "crt-static")))]
+        #[cfg_attr(feature = "stdbuild",
+                   link(name = "c", cfg(not(target_feature = "crt-static"))))]
         extern {}
     } else if #[cfg(target_os = "emscripten")] {
         #[link(name = "c")]
         extern {}
-    } else if #[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))] {
+    } else if #[cfg(all(target_os = "netbsd",
+                        feature = "stdbuild", target_vendor = "rumprun"))] {
         // Since we don't use -nodefaultlibs on Rumprun, libc is always pulled
         // in automatically by the linker. We avoid passing it explicitly, as it
         // causes some versions of binutils to crash with an assertion failure.
         #[link(name = "m")]
         extern {}
     } else if #[cfg(any(target_os = "macos",
                         target_os = "ios",
                         target_os = "android",
@@ -302,16 +318,21 @@ cfg_if! {
     } else if #[cfg(target_os = "fuchsia")] {
         #[link(name = "c")]
         #[link(name = "fdio")]
         extern {}
     } else if #[cfg(target_env = "newlib")] {
         #[link(name = "c")]
         #[link(name = "m")]
         extern {}
+    } else if #[cfg(target_os = "hermit")] {
+        // no_default_libraries is set to false for HermitCore, so only a link
+        // to "pthread" needs to be added.
+        #[link(name = "pthread")]
+        extern {}
     } else {
         #[link(name = "c")]
         #[link(name = "m")]
         #[link(name = "rt")]
         #[link(name = "pthread")]
         extern {}
     }
 }
@@ -373,22 +394,24 @@ extern {
                link_name = "chmod$UNIX2003")]
     pub fn chmod(path: *const c_char, mode: mode_t) -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "fchmod$UNIX2003")]
     pub fn fchmod(fd: ::c_int, mode: mode_t) -> ::c_int;
 
     #[cfg_attr(target_os = "macos", link_name = "fstat$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")]
+    #[cfg_attr(target_os = "freebsd", link_name = "fstat@FBSD_1.0")]
     pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int;
 
     pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int;
 
     #[cfg_attr(target_os = "macos", link_name = "stat$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__stat50")]
+    #[cfg_attr(target_os = "freebsd", link_name = "stat@FBSD_1.0")]
     pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int;
 
     pub fn pclose(stream: *mut ::FILE) -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "fdopen$UNIX2003")]
     pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE;
     pub fn fileno(stream: *mut ::FILE) -> ::c_int;
 
@@ -403,22 +426,31 @@ extern {
     pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
                link_name = "opendir$INODE64")]
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "opendir$INODE64$UNIX2003")]
     #[cfg_attr(target_os = "netbsd", link_name = "__opendir30")]
     pub fn opendir(dirname: *const c_char) -> *mut ::DIR;
+
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
+               link_name = "fdopendir$INODE64")]
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+               link_name = "fdopendir$INODE64$UNIX2003")]
+    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
+
     #[cfg_attr(target_os = "macos", link_name = "readdir$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__readdir30")]
+    #[cfg_attr(target_os = "freebsd", link_name = "readdir@FBSD_1.0")]
     pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent;
     #[cfg_attr(target_os = "macos", link_name = "readdir_r$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")]
     #[cfg_attr(target_os = "solaris", link_name = "__posix_readdir_r")]
+    #[cfg_attr(target_os = "freebsd", link_name = "readdir_r@FBSD_1.0")]
     pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent,
                      result: *mut *mut ::dirent) -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "closedir$UNIX2003")]
     pub fn closedir(dirp: *mut ::DIR) -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
                link_name = "rewinddir$INODE64")]
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
@@ -431,16 +463,17 @@ extern {
                     mode: ::mode_t, flags: ::c_int) -> ::c_int;
     pub fn fchown(fd: ::c_int,
                   owner: ::uid_t,
                   group: ::gid_t) -> ::c_int;
     pub fn fchownat(dirfd: ::c_int, pathname: *const ::c_char,
                     owner: ::uid_t, group: ::gid_t,
                     flags: ::c_int) -> ::c_int;
     #[cfg_attr(target_os = "macos", link_name = "fstatat$INODE64")]
+    #[cfg_attr(target_os = "freebsd", link_name = "fstatat@FBSD_1.1")]
     pub fn fstatat(dirfd: ::c_int, pathname: *const ::c_char,
                    buf: *mut stat, flags: ::c_int) -> ::c_int;
     pub fn linkat(olddirfd: ::c_int, oldpath: *const ::c_char,
                   newdirfd: ::c_int, newpath: *const ::c_char,
                   flags: ::c_int) -> ::c_int;
     pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char,
                    mode: ::mode_t) -> ::c_int;
     pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char,
@@ -556,16 +589,19 @@ extern {
     pub fn umask(mask: mode_t) -> mode_t;
 
     #[cfg_attr(target_os = "netbsd", link_name = "__utime50")]
     pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                    link_name = "kill$UNIX2003")]
     pub fn kill(pid: pid_t, sig: ::c_int) -> ::c_int;
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+               link_name = "killpg$UNIX2003")]
+    pub fn killpg(pgrp: pid_t, sig: ::c_int) -> ::c_int;
 
     pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int;
     pub fn munlock(addr: *const ::c_void, len: ::size_t) -> ::c_int;
     pub fn mlockall(flags: ::c_int) -> ::c_int;
     pub fn munlockall() -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "mmap$UNIX2003")]
@@ -581,16 +617,17 @@ extern {
     pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int;
 
     pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint;
     pub fn if_indextoname(ifindex: ::c_uint,
                           ifname: *mut ::c_char) -> *mut ::c_char;
 
     #[cfg_attr(target_os = "macos", link_name = "lstat$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")]
+    #[cfg_attr(target_os = "freebsd", link_name = "lstat@FBSD_1.0")]
     pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "fsync$UNIX2003")]
     pub fn fsync(fd: ::c_int) -> ::c_int;
 
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "setenv$UNIX2003")]
@@ -761,18 +798,21 @@ extern {
     #[cfg_attr(target_os = "netbsd", link_name = "__mktime50")]
     pub fn mktime(tm: *mut tm) -> time_t;
     #[cfg_attr(target_os = "netbsd", link_name = "__time50")]
     pub fn time(time: *mut time_t) -> time_t;
     #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")]
     pub fn gmtime(time_p: *const time_t) -> *mut tm;
     #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")]
     pub fn localtime(time_p: *const time_t) -> *mut tm;
+    #[cfg_attr(target_os = "netbsd", link_name = "__difftime50")]
+    pub fn difftime(time1: time_t, time0: time_t) -> ::c_double;
 
     #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")]
+    #[cfg_attr(target_os = "freebsd", link_name = "mknod@FBSD_1.0")]
     pub fn mknod(pathname: *const ::c_char, mode: ::mode_t,
                  dev: ::dev_t) -> ::c_int;
     pub fn uname(buf: *mut ::utsname) -> ::c_int;
     pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
     pub fn getservbyname(name: *const ::c_char,
                          proto: *const ::c_char) -> *mut servent;
     pub fn getprotobyname(name: *const ::c_char) -> *mut protoent;
     pub fn getprotobynumber(proto: ::c_int) -> *mut protoent;
@@ -891,16 +931,17 @@ extern {
     pub fn mkstemp(template: *mut ::c_char) -> ::c_int;
     pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char;
 
     pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char;
 
     pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int);
     pub fn closelog();
     pub fn setlogmask(maskpri: ::c_int) -> ::c_int;
+    #[cfg_attr(target_os = "macos", link_name = "syslog$DARWIN_EXTSN")]
     pub fn syslog(priority: ::c_int, message: *const ::c_char, ...);
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "nice$UNIX2003")]
     pub fn nice(incr: ::c_int) -> ::c_int;
 
     pub fn grantpt(fd: ::c_int) -> ::c_int;
     pub fn posix_openpt(flags: ::c_int) -> ::c_int;
     pub fn ptsname(fd: ::c_int) -> *mut ::c_char;
@@ -930,12 +971,15 @@ cfg_if! {
         mod bsd;
         pub use self::bsd::*;
     } else if #[cfg(target_os = "solaris")] {
         mod solaris;
         pub use self::solaris::*;
     } else if #[cfg(target_os = "haiku")] {
         mod haiku;
         pub use self::haiku::*;
+    } else if #[cfg(target_os = "hermit")] {
+        mod hermit;
+        pub use self::hermit::*;
     } else {
         // Unknown target_os
     }
 }
diff --git a/third_party/rust/libc/src/unix/newlib/aarch64/mod.rs b/third_party/rust/libc/src/unix/newlib/aarch64/mod.rs
new file mode 100644
index 000000000000..96f381a39113
--- /dev/null
+++ b/third_party/rust/libc/src/unix/newlib/aarch64/mod.rs
@@ -0,0 +1,5 @@
+pub type c_char = u8;
+pub type wchar_t = u32;
+
+pub type c_long = i64;
+pub type c_ulong = u64;
diff --git a/third_party/rust/libc/src/unix/newlib/mod.rs b/third_party/rust/libc/src/unix/newlib/mod.rs
index d895541124d6..9968d3668503 100644
--- a/third_party/rust/libc/src/unix/newlib/mod.rs
+++ b/third_party/rust/libc/src/unix/newlib/mod.rs
@@ -233,78 +233,127 @@ s! {
     pub struct cpu_set_t { // Unverified
         bits: [u32; 32],
     }
 
     pub struct pthread_attr_t { // Unverified
         __size: [u64; 7]
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_mutex_t { // Unverified
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_rwlock_t { // Unverified
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "32",
+                       target_arch = "x86_64", target_arch = "powerpc64",
+                       target_arch = "mips64", target_arch = "s390x",
+                       target_arch = "sparc64")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(any(target_pointer_width = "32",
+                           target_arch = "x86_64", target_arch = "powerpc64",
+                           target_arch = "mips64", target_arch = "s390x",
+                           target_arch = "sparc64"))),
+               repr(align(8)))]
     pub struct pthread_mutexattr_t { // Unverified
-        #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64",
-                  target_arch = "mips64", target_arch = "s390x",
-                  target_arch = "sparc64"))]
-        __align: [::c_int; 0],
-        #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64",
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "x86_64", target_arch = "powerpc64",
                       target_arch = "mips64", target_arch = "s390x",
                       target_arch = "sparc64")))]
+        __align: [::c_int; 0],
+        #[cfg(all(not(feature = "align"),
+                  not(any(target_arch = "x86_64", target_arch = "powerpc64",
+                          target_arch = "mips64", target_arch = "s390x",
+                          target_arch = "sparc64"))))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
     }
 
     pub struct pthread_rwlockattr_t { // Unverified
         __lockkind: ::c_int,
         __pshared: ::c_int,
     }
 
+    #[cfg_attr(feature = "align", repr(align(8)))]
     pub struct pthread_cond_t { // Unverified
+        #[cfg(not(feature = "align"))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_condattr_t { // Unverified
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
     }
 
 }
 
 // unverified constants
-pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_MUTEX_T],
-};
-pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_COND_T],
-};
-pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
-};
+align_const! {
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        size: [0; __SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
 pub const NCCS: usize = 32;
 pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
@@ -512,16 +561,36 @@ pub const SO_SNDLOWAT: ::c_int = 4099;
 pub const SO_RCVLOWAT: ::c_int = 4100;
 pub const SO_TYPE: ::c_int = 4104;
 pub const SO_ERROR: ::c_int = 4105;
 
 pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC;
 
 pub const INET_ADDRSTRLEN: ::c_int = 16;
 
+// https://github.
+// com/bminor/newlib/blob/master/newlib/libc/sys/linux/include/net/if.h#L121
+pub const IFF_UP: ::c_int = 0x1; // interface is up
+pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link
+pub const IFF_NOTRAILERS: ::c_int = 0x20; // avoid use of trailers
+pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated
+pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol
+pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets
+pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress
+pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions
+pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit
+pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit
+pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit
+pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection
+pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast
+
 pub const IPPROTO_IP: ::c_int = 0;
 pub const IPPROTO_UDP: ::c_int = 17;
 pub const IPPROTO_TCP: ::c_int = 6;
 
 pub const TCP_NODELAY: ::c_int = 8193;
 pub const TCP_MAXSEG: ::c_int = 8194;
 
 pub const IP_TOS: ::c_int = 7;
@@ -654,14 +723,17 @@ extern {
     pub fn popen(command: *const c_char,
                  mode: *const c_char) -> *mut ::FILE;
 }
 
 cfg_if! {
     if #[cfg(target_arch = "arm")] {
         mod arm;
         pub use self::arm::*;
+    } else if #[cfg(target_arch = "aarch64")] {
+        mod aarch64;
+        pub use self::aarch64::*;
     } else {
         // Only tested on ARM so far. Other platforms might have different
         // definitions for types and constants.
         pub use target_arch_not_implemented;
     }
 }
diff --git a/third_party/rust/libc/src/unix/notbsd/android/b32/mod.rs b/third_party/rust/libc/src/unix/notbsd/android/b32/mod.rs
index 99af6d8ab31c..394abe8fe24c 100644
--- a/third_party/rust/libc/src/unix/notbsd/android/b32/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/android/b32/mod.rs
@@ -193,32 +193,16 @@ pub const __CPU_BITS: ::size_t = 32;
 pub const UT_LINESIZE: usize = 8;
 pub const UT_NAMESIZE: usize = 8;
 pub const UT_HOSTSIZE: usize = 16;
 
 pub const SIGSTKSZ: ::size_t = 8192;
 pub const MINSIGSTKSZ: ::size_t = 2048;
 
 extern {
-    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
-                address_len: socklen_t) -> ::c_int;
-
-    pub fn writev(fd: ::c_int,
-                  iov: *const ::iovec,
-                  iovcnt: ::c_int) -> ::ssize_t;
-    pub fn readv(fd: ::c_int,
-                 iov: *const ::iovec,
-                 iovcnt: ::c_int) -> ::ssize_t;
-
-    pub fn sendmsg(fd: ::c_int,
-                   msg: *const ::msghdr,
-                   flags: ::c_int) -> ::ssize_t;
-    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
-                   -> ::ssize_t;
-
     pub fn timegm64(tm: *const ::tm) -> ::time64_t;
 }
 
 cfg_if! {
     if #[cfg(target_arch = "x86")] {
         mod x86;
         pub use self::x86::*;
     } else if #[cfg(target_arch = "arm")] {
diff --git a/third_party/rust/libc/src/unix/notbsd/android/b64/mod.rs b/third_party/rust/libc/src/unix/notbsd/android/b64/mod.rs
index 4aa69977a7e1..fb943349b398 100644
--- a/third_party/rust/libc/src/unix/notbsd/android/b64/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/android/b64/mod.rs
@@ -149,41 +149,16 @@ pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
 pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 4;
 pub const CPU_SETSIZE: ::size_t = 1024;
 pub const __CPU_BITS: ::size_t = 64;
 
 pub const UT_LINESIZE: usize = 32;
 pub const UT_NAMESIZE: usize = 32;
 pub const UT_HOSTSIZE: usize = 256;
 
-// Some weirdness in Android
-extern {
-    // address_len should be socklen_t, but it is c_int!
-    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
-                address_len: ::c_int) -> ::c_int;
-
-    // the return type should be ::ssize_t, but it is c_int!
-    pub fn writev(fd: ::c_int,
-                  iov: *const ::iovec,
-                  iovcnt: ::c_int) -> ::c_int;
-
-    // the return type should be ::ssize_t, but it is c_int!
-    pub fn readv(fd: ::c_int,
-                 iov: *const ::iovec,
-                 iovcnt: ::c_int) -> ::c_int;
-
-    // the return type should be ::ssize_t, but it is c_int!
-    pub fn sendmsg(fd: ::c_int,
-                   msg: *const ::msghdr,
-                   flags: ::c_int) -> ::c_int;
-
-    // the return type should be ::ssize_t, but it is c_int!
-    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::c_int;
-}
-
 cfg_if! {
     if #[cfg(target_arch = "x86_64")] {
         mod x86_64;
         pub use self::x86_64::*;
     } else if #[cfg(target_arch = "aarch64")] {
         mod aarch64;
         pub use self::aarch64::*;
     } else {
diff --git a/third_party/rust/libc/src/unix/notbsd/android/mod.rs b/third_party/rust/libc/src/unix/notbsd/android/mod.rs
index 88e5cea2366d..3e10acd5056f 100644
--- a/third_party/rust/libc/src/unix/notbsd/android/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/android/mod.rs
@@ -180,16 +180,65 @@ s! {
         _pad: [::uint8_t; 46],
     }
 
     pub struct ucred {
         pub pid: ::pid_t,
         pub uid: ::uid_t,
         pub gid: ::gid_t,
     }
+
+    pub struct genlmsghdr {
+        pub cmd: u8,
+        pub version: u8,
+        pub reserved: u16,
+    }
+
+    pub struct nlmsghdr {
+        pub nlmsg_len: u32,
+        pub nlmsg_type: u16,
+        pub nlmsg_flags: u16,
+        pub nlmsg_seq: u32,
+        pub nlmsg_pid: u32,
+    }
+
+    pub struct nlmsgerr {
+        pub error: ::c_int,
+        pub msg: nlmsghdr,
+    }
+
+    pub struct nl_pktinfo {
+        pub group: u32,
+    }
+
+    pub struct nl_mmap_req {
+        pub nm_block_size: ::c_uint,
+        pub nm_block_nr: ::c_uint,
+        pub nm_frame_size: ::c_uint,
+        pub nm_frame_nr: ::c_uint,
+    }
+
+    pub struct nl_mmap_hdr {
+        pub nm_status: ::c_uint,
+        pub nm_len: ::c_uint,
+        pub nm_group: u32,
+        pub nm_pid: u32,
+        pub nm_uid: u32,
+        pub nm_gid: u32,
+    }
+
+    pub struct nlattr {
+        pub nla_len: u16,
+        pub nla_type: u16,
+    }
+
+    pub struct in6_pktinfo {
+        pub ipi6_addr: ::in6_addr,
+        pub ipi6_ifindex: ::c_int,
+    }
 }
 
 pub const O_TRUNC: ::c_int = 512;
 pub const O_CLOEXEC: ::c_int = 0x80000;
 pub const O_PATH: ::c_int = 0o10000000;
 pub const O_NOATIME: ::c_int = 0o1000000;
 
 pub const EBFONT: ::c_int = 59;
@@ -337,16 +386,59 @@ pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 83;
 pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 84;
 pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 85;
 pub const _SC_NPROCESSORS_CONF: ::c_int = 96;
 pub const _SC_NPROCESSORS_ONLN: ::c_int = 97;
 pub const _SC_PHYS_PAGES: ::c_int = 98;
 pub const _SC_AVPHYS_PAGES: ::c_int = 99;
 pub const _SC_MONOTONIC_CLOCK: ::c_int = 100;
 
+pub const _SC_2_PBS: ::c_int = 101;
+pub const _SC_2_PBS_ACCOUNTING: ::c_int = 102;
+pub const _SC_2_PBS_CHECKPOINT: ::c_int = 103;
+pub const _SC_2_PBS_LOCATE: ::c_int = 104;
+pub const _SC_2_PBS_MESSAGE: ::c_int = 105;
+pub const _SC_2_PBS_TRACK: ::c_int = 106;
+pub const _SC_ADVISORY_INFO: ::c_int = 107;
+pub const _SC_BARRIERS: ::c_int = 108;
+pub const _SC_CLOCK_SELECTION: ::c_int = 109;
+pub const _SC_CPUTIME: ::c_int = 110;
+pub const _SC_HOST_NAME_MAX: ::c_int = 111;
+pub const _SC_IPV6: ::c_int = 112;
+pub const _SC_RAW_SOCKETS: ::c_int = 113;
+pub const _SC_READER_WRITER_LOCKS: ::c_int = 114;
+pub const _SC_REGEXP: ::c_int = 115;
+pub const _SC_SHELL: ::c_int = 116;
+pub const _SC_SPAWN: ::c_int = 117;
+pub const _SC_SPIN_LOCKS: ::c_int = 118;
+pub const _SC_SPORADIC_SERVER: ::c_int = 119;
+pub const _SC_SS_REPL_MAX: ::c_int = 120;
+pub const _SC_SYMLOOP_MAX: ::c_int = 121;
+pub const _SC_THREAD_CPUTIME: ::c_int = 122;
+pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 123;
+pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 124;
+pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 125;
+pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 126;
+pub const _SC_TIMEOUTS: ::c_int = 127;
+pub const _SC_TRACE: ::c_int = 128;
+pub const _SC_TRACE_EVENT_FILTER: ::c_int = 129;
+pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 130;
+pub const _SC_TRACE_INHERIT: ::c_int = 131;
+pub const _SC_TRACE_LOG: ::c_int = 132;
+pub const _SC_TRACE_NAME_MAX: ::c_int = 133;
+pub const _SC_TRACE_SYS_MAX: ::c_int = 134;
+pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 135;
+pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 136;
+pub const _SC_V7_ILP32_OFF32: ::c_int = 137;
+pub const _SC_V7_ILP32_OFFBIG: ::c_int = 138;
+pub const _SC_V7_LP64_OFF64: ::c_int = 139;
+pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 140;
+pub const _SC_XOPEN_STREAMS: ::c_int = 141;
+pub const _SC_XOPEN_UUCP: ::c_int = 142;
+
 pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
 pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
 pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL;
 
 pub const FIOCLEX: ::c_int = 0x5451;
 
 pub const SA_ONSTACK: ::c_ulong = 0x08000000;
@@ -679,16 +771,26 @@ pub const TIOCGWINSZ: ::c_int = 0x5413;
 pub const TIOCSWINSZ: ::c_int = 0x5414;
 pub const TIOCMGET: ::c_int = 0x5415;
 pub const TIOCMBIS: ::c_int = 0x5416;
 pub const TIOCMBIC: ::c_int = 0x5417;
 pub const TIOCMSET: ::c_int = 0x5418;
 pub const FIONREAD: ::c_int = 0x541B;
 pub const TIOCCONS: ::c_int = 0x541D;
 
+pub const ST_RDONLY: ::c_ulong = 1;
+pub const ST_NOSUID: ::c_ulong = 2;
+pub const ST_NODEV: ::c_ulong = 4;
+pub const ST_NOEXEC: ::c_ulong = 8;
+pub const ST_SYNCHRONOUS: ::c_ulong = 16;
+pub const ST_MANDLOCK: ::c_ulong = 64;
+pub const ST_NOATIME: ::c_ulong = 1024;
+pub const ST_NODIRATIME: ::c_ulong = 2048;
+pub const ST_RELATIME: ::c_ulong = 4096;
+
 pub const RTLD_NOLOAD: ::c_int = 0x4;
 
 pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t;
 
 pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead;
 pub const LINUX_REBOOT_MAGIC2: ::c_int = 672274793;
 pub const LINUX_REBOOT_MAGIC2A: ::c_int = 85072278;
 pub const LINUX_REBOOT_MAGIC2B: ::c_int = 369367448;
@@ -786,17 +888,27 @@ pub const B1000000: ::speed_t = 0o010010;
 pub const B1152000: ::speed_t = 0o010011;
 pub const B1500000: ::speed_t = 0o010012;
 pub const B2000000: ::speed_t = 0o010013;
 pub const B2500000: ::speed_t = 0o010014;
 pub const B3000000: ::speed_t = 0o010015;
 pub const B3500000: ::speed_t = 0o010016;
 pub const B4000000: ::speed_t = 0o010017;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
 
 pub const NETLINK_ROUTE: ::c_int = 0;
 pub const NETLINK_UNUSED: ::c_int = 1;
 pub const NETLINK_USERSOCK: ::c_int = 2;
 pub const NETLINK_FIREWALL: ::c_int = 3;
 pub const NETLINK_SOCK_DIAG: ::c_int = 4;
 pub const NETLINK_NFLOG: ::c_int = 5;
 pub const NETLINK_XFRM: ::c_int = 6;
@@ -835,28 +947,80 @@ pub const NLM_F_CREATE: ::c_int = 0x400;
 pub const NLM_F_APPEND: ::c_int = 0x800;
 
 pub const NLMSG_NOOP: ::c_int = 0x1;
 pub const NLMSG_ERROR: ::c_int = 0x2;
 pub const NLMSG_DONE: ::c_int = 0x3;
 pub const NLMSG_OVERRUN: ::c_int = 0x4;
 pub const NLMSG_MIN_TYPE: ::c_int = 0x10;
 
+pub const GENL_NAMSIZ: ::c_int = 16;
+
+pub const GENL_MIN_ID: ::c_int = NLMSG_MIN_TYPE;
+pub const GENL_MAX_ID: ::c_int = 1023;
+
+pub const GENL_ADMIN_PERM: ::c_int = 0x01;
+pub const GENL_CMD_CAP_DO: ::c_int = 0x02;
+pub const GENL_CMD_CAP_DUMP: ::c_int = 0x04;
+pub const GENL_CMD_CAP_HASPOL: ::c_int = 0x08;
+pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10;
+
+pub const GENL_ID_CTRL: ::c_int = NLMSG_MIN_TYPE;
+pub const GENL_ID_VFS_DQUOT: ::c_int = NLMSG_MIN_TYPE + 1;
+pub const GENL_ID_PMCRAID: ::c_int = NLMSG_MIN_TYPE + 2;
+
+pub const CTRL_CMD_UNSPEC: ::c_int = 0;
+pub const CTRL_CMD_NEWFAMILY: ::c_int = 1;
+pub const CTRL_CMD_DELFAMILY: ::c_int = 2;
+pub const CTRL_CMD_GETFAMILY: ::c_int = 3;
+pub const CTRL_CMD_NEWOPS: ::c_int = 4;
+pub const CTRL_CMD_DELOPS: ::c_int = 5;
+pub const CTRL_CMD_GETOPS: ::c_int = 6;
+pub const CTRL_CMD_NEWMCAST_GRP: ::c_int = 7;
+pub const CTRL_CMD_DELMCAST_GRP: ::c_int = 8;
+pub const CTRL_CMD_GETMCAST_GRP: ::c_int = 9;
+
+pub const CTRL_ATTR_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_FAMILY_ID: ::c_int = 1;
+pub const CTRL_ATTR_FAMILY_NAME: ::c_int = 2;
+pub const CTRL_ATTR_VERSION: ::c_int = 3;
+pub const CTRL_ATTR_HDRSIZE: ::c_int = 4;
+pub const CTRL_ATTR_MAXATTR: ::c_int = 5;
+pub const CTRL_ATTR_OPS: ::c_int = 6;
+pub const CTRL_ATTR_MCAST_GROUPS: ::c_int = 7;
+
+pub const CTRL_ATTR_OP_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_OP_ID: ::c_int = 1;
+pub const CTRL_ATTR_OP_FLAGS: ::c_int = 2;
+
+pub const CTRL_ATTR_MCAST_GRP_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1;
+pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2;
+
 pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1;
 pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2;
 pub const NETLINK_PKTINFO: ::c_int = 3;
 pub const NETLINK_BROADCAST_ERROR: ::c_int = 4;
 pub const NETLINK_NO_ENOBUFS: ::c_int = 5;
 pub const NETLINK_RX_RING: ::c_int = 6;
 pub const NETLINK_TX_RING: ::c_int = 7;
 
+pub const GRND_NONBLOCK: ::c_uint = 0x0001;
+pub const GRND_RANDOM: ::c_uint = 0x0002;
+
+pub const SECCOMP_MODE_DISABLED: ::c_uint = 0;
+pub const SECCOMP_MODE_STRICT: ::c_uint = 1;
+pub const SECCOMP_MODE_FILTER: ::c_uint = 2;
+
 pub const NLA_F_NESTED: ::c_int = 1 << 15;
 pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14;
 pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER);
 
+pub const NLA_ALIGNTO: ::c_int = 4;
+
 pub const SIGEV_THREAD_ID: ::c_int = 4;
 
 pub const CIBAUD: ::tcflag_t = 0o02003600000;
 pub const CBAUDEX: ::tcflag_t = 0o010000;
 
 pub const TIOCM_LE: ::c_int = 0x001;
 pub const TIOCM_DTR: ::c_int = 0x002;
 pub const TIOCM_RTS: ::c_int = 0x004;
@@ -877,16 +1041,435 @@ pub const SFD_NONBLOCK: ::c_int = O_NONBLOCK;
 
 pub const SOCK_NONBLOCK: ::c_int = O_NONBLOCK;
 
 pub const SO_ORIGINAL_DST: ::c_int = 80;
 pub const IUTF8: ::tcflag_t = 0x00004000;
 pub const CMSPAR: ::tcflag_t = 0o10000000000;
 pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
+pub const MFD_CLOEXEC: ::c_uint = 0x0001;
+pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002;
+
+// linux/netfilter.h
+pub const NF_DROP: ::c_int = 0;
+pub const NF_ACCEPT: ::c_int =  1;
+pub const NF_STOLEN: ::c_int =  2;
+pub const NF_QUEUE: ::c_int =  3;
+pub const NF_REPEAT: ::c_int =  4;
+pub const NF_STOP: ::c_int =  5;
+pub const NF_MAX_VERDICT: ::c_int = NF_STOP;
+
+pub const NF_VERDICT_MASK: ::c_int = 0x000000ff;
+pub const NF_VERDICT_FLAG_QUEUE_BYPASS: ::c_int = 0x00008000;
+
+pub const NF_VERDICT_QMASK: ::c_int = 0xffff0000;
+pub const NF_VERDICT_QBITS: ::c_int = 16;
+
+pub const NF_VERDICT_BITS: ::c_int = 16;
+
+pub const NF_INET_PRE_ROUTING: ::c_int = 0;
+pub const NF_INET_LOCAL_IN: ::c_int = 1;
+pub const NF_INET_FORWARD: ::c_int = 2;
+pub const NF_INET_LOCAL_OUT: ::c_int = 3;
+pub const NF_INET_POST_ROUTING: ::c_int = 4;
+pub const NF_INET_NUMHOOKS: ::c_int = 5;
+
+pub const NF_NETDEV_INGRESS: ::c_int = 0;
+pub const NF_NETDEV_NUMHOOKS: ::c_int = 1;
+
+pub const NFPROTO_UNSPEC: ::c_int = 0;
+pub const NFPROTO_INET: ::c_int = 1;
+pub const NFPROTO_IPV4: ::c_int = 2;
+pub const NFPROTO_ARP: ::c_int = 3;
+pub const NFPROTO_NETDEV: ::c_int = 5;
+pub const NFPROTO_BRIDGE: ::c_int = 7;
+pub const NFPROTO_IPV6: ::c_int = 10;
+pub const NFPROTO_DECNET: ::c_int = 12;
+pub const NFPROTO_NUMPROTO: ::c_int = 13;
+
+// linux/netfilter_ipv4.h
+pub const NF_IP_PRE_ROUTING: ::c_int = 0;
+pub const NF_IP_LOCAL_IN: ::c_int = 1;
+pub const NF_IP_FORWARD: ::c_int = 2;
+pub const NF_IP_LOCAL_OUT: ::c_int = 3;
+pub const NF_IP_POST_ROUTING: ::c_int = 4;
+pub const NF_IP_NUMHOOKS: ::c_int = 5;
+
+pub const NF_IP_PRI_FIRST: ::c_int = ::INT_MIN;
+pub const NF_IP_PRI_CONNTRACK_DEFRAG: ::c_int = -400;
+pub const NF_IP_PRI_RAW: ::c_int = -300;
+pub const NF_IP_PRI_SELINUX_FIRST: ::c_int = -225;
+pub const NF_IP_PRI_CONNTRACK: ::c_int = -200;
+pub const NF_IP_PRI_MANGLE: ::c_int = -150;
+pub const NF_IP_PRI_NAT_DST: ::c_int = -100;
+pub const NF_IP_PRI_FILTER: ::c_int = 0;
+pub const NF_IP_PRI_SECURITY: ::c_int = 50;
+pub const NF_IP_PRI_NAT_SRC: ::c_int = 100;
+pub const NF_IP_PRI_SELINUX_LAST: ::c_int = 225;
+pub const NF_IP_PRI_CONNTRACK_HELPER: ::c_int = 300;
+pub const NF_IP_PRI_CONNTRACK_CONFIRM: ::c_int = ::INT_MAX;
+pub const NF_IP_PRI_LAST: ::c_int = ::INT_MAX;
+
+// linux/netfilter_ipv6.h
+pub const NF_IP6_PRE_ROUTING: ::c_int = 0;
+pub const NF_IP6_LOCAL_IN: ::c_int = 1;
+pub const NF_IP6_FORWARD: ::c_int = 2;
+pub const NF_IP6_LOCAL_OUT: ::c_int = 3;
+pub const NF_IP6_POST_ROUTING: ::c_int = 4;
+pub const NF_IP6_NUMHOOKS: ::c_int = 5;
+
+pub const NF_IP6_PRI_FIRST: ::c_int = ::INT_MIN;
+pub const NF_IP6_PRI_CONNTRACK_DEFRAG: ::c_int = -400;
+pub const NF_IP6_PRI_RAW: ::c_int = -300;
+pub const NF_IP6_PRI_SELINUX_FIRST: ::c_int = -225;
+pub const NF_IP6_PRI_CONNTRACK: ::c_int = -200;
+pub const NF_IP6_PRI_MANGLE: ::c_int = -150;
+pub const NF_IP6_PRI_NAT_DST: ::c_int = -100;
+pub const NF_IP6_PRI_FILTER: ::c_int = 0;
+pub const NF_IP6_PRI_SECURITY: ::c_int = 50;
+pub const NF_IP6_PRI_NAT_SRC: ::c_int = 100;
+pub const NF_IP6_PRI_SELINUX_LAST: ::c_int = 225;
+pub const NF_IP6_PRI_CONNTRACK_HELPER: ::c_int = 300;
+pub const NF_IP6_PRI_LAST: ::c_int = ::INT_MAX;
+
+// linux/netfilter/nf_tables.h
+pub const NFT_TABLE_MAXNAMELEN: ::c_int = 32;
+pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 32;
+pub const NFT_SET_MAXNAMELEN: ::c_int = 32;
+pub const NFT_OBJ_MAXNAMELEN: ::c_int = 32;
+pub const NFT_USERDATA_MAXLEN: ::c_int = 256;
+
+pub const NFT_REG_VERDICT: ::c_int = 0;
+pub const NFT_REG_1: ::c_int = 1;
+pub const NFT_REG_2: ::c_int = 2;
+pub const NFT_REG_3: ::c_int = 3;
+pub const NFT_REG_4: ::c_int = 4;
+pub const __NFT_REG_MAX: ::c_int = 5;
+pub const NFT_REG32_00: ::c_int = 8;
+pub const NFT_REG32_01: ::c_int = 9;
+pub const NFT_REG32_02: ::c_int = 10;
+pub const NFT_REG32_03: ::c_int = 11;
+pub const NFT_REG32_04: ::c_int = 12;
+pub const NFT_REG32_05: ::c_int = 13;
+pub const NFT_REG32_06: ::c_int = 14;
+pub const NFT_REG32_07: ::c_int = 15;
+pub const NFT_REG32_08: ::c_int = 16;
+pub const NFT_REG32_09: ::c_int = 17;
+pub const NFT_REG32_10: ::c_int = 18;
+pub const NFT_REG32_11: ::c_int = 19;
+pub const NFT_REG32_12: ::c_int = 20;
+pub const NFT_REG32_13: ::c_int = 21;
+pub const NFT_REG32_14: ::c_int = 22;
+pub const NFT_REG32_15: ::c_int = 23;
+
+pub const NFT_REG_SIZE: ::c_int = 16;
+pub const NFT_REG32_SIZE: ::c_int = 4;
+
+pub const NFT_CONTINUE: ::c_int = -1;
+pub const NFT_BREAK: ::c_int = -2;
+pub const NFT_JUMP: ::c_int = -3;
+pub const NFT_GOTO: ::c_int = -4;
+pub const NFT_RETURN: ::c_int = -5;
+
+pub const NFT_MSG_NEWTABLE: ::c_int = 0;
+pub const NFT_MSG_GETTABLE: ::c_int = 1;
+pub const NFT_MSG_DELTABLE: ::c_int = 2;
+pub const NFT_MSG_NEWCHAIN: ::c_int = 3;
+pub const NFT_MSG_GETCHAIN: ::c_int = 4;
+pub const NFT_MSG_DELCHAIN: ::c_int = 5;
+pub const NFT_MSG_NEWRULE: ::c_int = 6;
+pub const NFT_MSG_GETRULE: ::c_int = 7;
+pub const NFT_MSG_DELRULE: ::c_int = 8;
+pub const NFT_MSG_NEWSET: ::c_int = 9;
+pub const NFT_MSG_GETSET: ::c_int = 10;
+pub const NFT_MSG_DELSET: ::c_int = 11;
+pub const NFT_MSG_NEWSETELEM: ::c_int = 12;
+pub const NFT_MSG_GETSETELEM: ::c_int = 13;
+pub const NFT_MSG_DELSETELEM: ::c_int = 14;
+pub const NFT_MSG_NEWGEN: ::c_int = 15;
+pub const NFT_MSG_GETGEN: ::c_int = 16;
+pub const NFT_MSG_TRACE: ::c_int = 17;
+pub const NFT_MSG_NEWOBJ: ::c_int = 18;
+pub const NFT_MSG_GETOBJ: ::c_int = 19;
+pub const NFT_MSG_DELOBJ: ::c_int = 20;
+pub const NFT_MSG_GETOBJ_RESET: ::c_int = 21;
+pub const NFT_MSG_MAX: ::c_int = 22;
+
+pub const NFT_SET_ANONYMOUS: ::c_int = 0x1;
+pub const NFT_SET_CONSTANT: ::c_int = 0x2;
+pub const NFT_SET_INTERVAL: ::c_int = 0x4;
+pub const NFT_SET_MAP: ::c_int = 0x8;
+pub const NFT_SET_TIMEOUT: ::c_int = 0x10;
+pub const NFT_SET_EVAL: ::c_int = 0x20;
+
+pub const NFT_SET_POL_PERFORMANCE: ::c_int = 0;
+pub const NFT_SET_POL_MEMORY: ::c_int = 1;
+
+pub const NFT_SET_ELEM_INTERVAL_END: ::c_int = 0x1;
+
+pub const NFT_DATA_VALUE: ::c_uint = 0;
+pub const NFT_DATA_VERDICT: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_RESERVED_MASK: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_VALUE_MAXLEN: ::c_int = 64;
+
+pub const NFT_BYTEORDER_NTOH: ::c_int = 0;
+pub const NFT_BYTEORDER_HTON: ::c_int = 1;
+
+pub const NFT_CMP_EQ: ::c_int = 0;
+pub const NFT_CMP_NEQ: ::c_int = 1;
+pub const NFT_CMP_LT: ::c_int = 2;
+pub const NFT_CMP_LTE: ::c_int = 3;
+pub const NFT_CMP_GT: ::c_int = 4;
+pub const NFT_CMP_GTE: ::c_int = 5;
+
+pub const NFT_RANGE_EQ: ::c_int = 0;
+pub const NFT_RANGE_NEQ: ::c_int = 1;
+
+pub const NFT_LOOKUP_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_DYNSET_OP_ADD: ::c_int = 0;
+pub const NFT_DYNSET_OP_UPDATE: ::c_int = 1;
+
+pub const NFT_DYNSET_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_PAYLOAD_LL_HEADER: ::c_int = 0;
+pub const NFT_PAYLOAD_NETWORK_HEADER: ::c_int = 1;
+pub const NFT_PAYLOAD_TRANSPORT_HEADER: ::c_int = 2;
+
+pub const NFT_PAYLOAD_CSUM_NONE: ::c_int = 0;
+pub const NFT_PAYLOAD_CSUM_INET: ::c_int = 1;
+
+pub const NFT_META_LEN: ::c_int = 0;
+pub const NFT_META_PROTOCOL: ::c_int = 1;
+pub const NFT_META_PRIORITY: ::c_int = 2;
+pub const NFT_META_MARK: ::c_int = 3;
+pub const NFT_META_IIF: ::c_int = 4;
+pub const NFT_META_OIF: ::c_int = 5;
+pub const NFT_META_IIFNAME: ::c_int = 6;
+pub const NFT_META_OIFNAME: ::c_int = 7;
+pub const NFT_META_IIFTYPE: ::c_int = 8;
+pub const NFT_META_OIFTYPE: ::c_int = 9;
+pub const NFT_META_SKUID: ::c_int = 10;
+pub const NFT_META_SKGID: ::c_int = 11;
+pub const NFT_META_NFTRACE: ::c_int = 12;
+pub const NFT_META_RTCLASSID: ::c_int = 13;
+pub const NFT_META_SECMARK: ::c_int = 14;
+pub const NFT_META_NFPROTO: ::c_int = 15;
+pub const NFT_META_L4PROTO: ::c_int = 16;
+pub const NFT_META_BRI_IIFNAME: ::c_int = 17;
+pub const NFT_META_BRI_OIFNAME: ::c_int = 18;
+pub const NFT_META_PKTTYPE: ::c_int = 19;
+pub const NFT_META_CPU: ::c_int = 20;
+pub const NFT_META_IIFGROUP: ::c_int = 21;
+pub const NFT_META_OIFGROUP: ::c_int = 22;
+pub const NFT_META_CGROUP: ::c_int = 23;
+pub const NFT_META_PRANDOM: ::c_int = 24;
+
+pub const NFT_CT_STATE: ::c_int = 0;
+pub const NFT_CT_DIRECTION: ::c_int = 1;
+pub const NFT_CT_STATUS: ::c_int = 2;
+pub const NFT_CT_MARK: ::c_int = 3;
+pub const NFT_CT_SECMARK: ::c_int = 4;
+pub const NFT_CT_EXPIRATION: ::c_int = 5;
+pub const NFT_CT_HELPER: ::c_int = 6;
+pub const NFT_CT_L3PROTOCOL: ::c_int = 7;
+pub const NFT_CT_SRC: ::c_int = 8;
+pub const NFT_CT_DST: ::c_int = 9;
+pub const NFT_CT_PROTOCOL: ::c_int = 10;
+pub const NFT_CT_PROTO_SRC: ::c_int = 11;
+pub const NFT_CT_PROTO_DST: ::c_int = 12;
+pub const NFT_CT_LABELS: ::c_int = 13;
+pub const NFT_CT_PKTS: ::c_int = 14;
+pub const NFT_CT_BYTES: ::c_int = 15;
+
+pub const NFT_LIMIT_PKTS: ::c_int = 0;
+pub const NFT_LIMIT_PKT_BYTES: ::c_int = 1;
+
+pub const NFT_LIMIT_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_QUEUE_FLAG_BYPASS: ::c_int = 0x01;
+pub const NFT_QUEUE_FLAG_CPU_FANOUT: ::c_int = 0x02;
+pub const NFT_QUEUE_FLAG_MASK: ::c_int = 0x03;
+
+pub const NFT_QUOTA_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_REJECT_ICMP_UNREACH: ::c_int = 0;
+pub const NFT_REJECT_TCP_RST: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_UNREACH: ::c_int = 2;
+
+pub const NFT_REJECT_ICMPX_NO_ROUTE: ::c_int = 0;
+pub const NFT_REJECT_ICMPX_PORT_UNREACH: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_HOST_UNREACH: ::c_int = 2;
+pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: ::c_int = 3;
+
+pub const NFT_NAT_SNAT: ::c_int = 0;
+pub const NFT_NAT_DNAT: ::c_int = 1;
+
+pub const NFT_TRACETYPE_UNSPEC: ::c_int = 0;
+pub const NFT_TRACETYPE_POLICY: ::c_int = 1;
+pub const NFT_TRACETYPE_RETURN: ::c_int = 2;
+pub const NFT_TRACETYPE_RULE: ::c_int = 3;
+
+pub const NFT_NG_INCREMENTAL: ::c_int = 0;
+pub const NFT_NG_RANDOM: ::c_int = 1;
+
+pub const IFF_TUN: ::c_int = 0x0001;
+pub const IFF_TAP: ::c_int = 0x0002;
+pub const IFF_NO_PI: ::c_int = 0x1000;
+
+// start android/platform/bionic/libc/kernel/uapi/linux/if_ether.h
+// from https://android.googlesource.com/
+// platform/bionic/+/master/libc/kernel/uapi/linux/if_ether.h
+pub const ETH_ALEN: ::c_int = 6;
+pub const ETH_HLEN: ::c_int = 14;
+pub const ETH_ZLEN: ::c_int = 60;
+pub const ETH_DATA_LEN: ::c_int = 1500;
+pub const ETH_FRAME_LEN: ::c_int = 1514;
+pub const ETH_FCS_LEN: ::c_int = 4;
+pub const ETH_MIN_MTU: ::c_int = 68;
+pub const ETH_MAX_MTU: ::c_int = 0xFFFF;
+pub const ETH_P_LOOP: ::c_int = 0x0060;
+pub const ETH_P_PUP: ::c_int = 0x0200;
+pub const ETH_P_PUPAT: ::c_int = 0x0201;
+pub const ETH_P_TSN: ::c_int = 0x22F0;
+pub const ETH_P_IP: ::c_int = 0x0800;
+pub const ETH_P_X25: ::c_int = 0x0805;
+pub const ETH_P_ARP: ::c_int = 0x0806;
+pub const ETH_P_BPQ: ::c_int = 0x08FF;
+pub const ETH_P_IEEEPUP: ::c_int = 0x0a00;
+pub const ETH_P_IEEEPUPAT: ::c_int = 0x0a01;
+pub const ETH_P_BATMAN: ::c_int = 0x4305;
+pub const ETH_P_DEC: ::c_int = 0x6000;
+pub const ETH_P_DNA_DL: ::c_int = 0x6001;
+pub const ETH_P_DNA_RC: ::c_int = 0x6002;
+pub const ETH_P_DNA_RT: ::c_int = 0x6003;
+pub const ETH_P_LAT: ::c_int = 0x6004;
+pub const ETH_P_DIAG: ::c_int = 0x6005;
+pub const ETH_P_CUST: ::c_int = 0x6006;
+pub const ETH_P_SCA: ::c_int = 0x6007;
+pub const ETH_P_TEB: ::c_int = 0x6558;
+pub const ETH_P_RARP: ::c_int = 0x8035;
+pub const ETH_P_ATALK: ::c_int = 0x809B;
+pub const ETH_P_AARP: ::c_int = 0x80F3;
+pub const ETH_P_8021Q: ::c_int = 0x8100;
+/* see rust-lang/libc#924 pub const ETH_P_ERSPAN: ::c_int = 0x88BE;*/
+pub const ETH_P_IPX: ::c_int = 0x8137;
+pub const ETH_P_IPV6: ::c_int = 0x86DD;
+pub const ETH_P_PAUSE: ::c_int = 0x8808;
+pub const ETH_P_SLOW: ::c_int = 0x8809;
+pub const ETH_P_WCCP: ::c_int = 0x883E;
+pub const ETH_P_MPLS_UC: ::c_int = 0x8847;
+pub const ETH_P_MPLS_MC: ::c_int = 0x8848;
+pub const ETH_P_ATMMPOA: ::c_int = 0x884c;
+pub const ETH_P_PPP_DISC: ::c_int = 0x8863;
+pub const ETH_P_PPP_SES: ::c_int = 0x8864;
+pub const ETH_P_LINK_CTL: ::c_int = 0x886c;
+pub const ETH_P_ATMFATE: ::c_int = 0x8884;
+pub const ETH_P_PAE: ::c_int = 0x888E;
+pub const ETH_P_AOE: ::c_int = 0x88A2;
+pub const ETH_P_8021AD: ::c_int = 0x88A8;
+pub const ETH_P_802_EX1: ::c_int = 0x88B5;
+pub const ETH_P_TIPC: ::c_int = 0x88CA;
+pub const ETH_P_MACSEC: ::c_int = 0x88E5;
+pub const ETH_P_8021AH: ::c_int = 0x88E7;
+pub const ETH_P_MVRP: ::c_int = 0x88F5;
+pub const ETH_P_1588: ::c_int = 0x88F7;
+pub const ETH_P_NCSI: ::c_int = 0x88F8;
+pub const ETH_P_PRP: ::c_int = 0x88FB;
+pub const ETH_P_FCOE: ::c_int = 0x8906;
+/* see rust-lang/libc#924 pub const ETH_P_IBOE: ::c_int = 0x8915;*/
+pub const ETH_P_TDLS: ::c_int = 0x890D;
+pub const ETH_P_FIP: ::c_int = 0x8914;
+pub const ETH_P_80221: ::c_int = 0x8917;
+pub const ETH_P_HSR: ::c_int = 0x892F;
+/* see rust-lang/libc#924 pub const ETH_P_NSH: ::c_int = 0x894F;*/
+pub const ETH_P_LOOPBACK: ::c_int = 0x9000;
+pub const ETH_P_QINQ1: ::c_int = 0x9100;
+pub const ETH_P_QINQ2: ::c_int = 0x9200;
+pub const ETH_P_QINQ3: ::c_int = 0x9300;
+pub const ETH_P_EDSA: ::c_int = 0xDADA;
+/* see rust-lang/libc#924 pub const ETH_P_IFE: ::c_int = 0xED3E;*/
+pub const ETH_P_AF_IUCV: ::c_int = 0xFBFB;
+pub const ETH_P_802_3_MIN: ::c_int = 0x0600;
+pub const ETH_P_802_3: ::c_int = 0x0001;
+pub const ETH_P_AX25: ::c_int = 0x0002;
+pub const ETH_P_ALL: ::c_int = 0x0003;
+pub const ETH_P_802_2: ::c_int = 0x0004;
+pub const ETH_P_SNAP: ::c_int = 0x0005;
+pub const ETH_P_DDCMP: ::c_int = 0x0006;
+pub const ETH_P_WAN_PPP: ::c_int = 0x0007;
+pub const ETH_P_PPP_MP: ::c_int = 0x0008;
+pub const ETH_P_LOCALTALK: ::c_int = 0x0009;
+pub const ETH_P_CAN: ::c_int = 0x000C;
+pub const ETH_P_CANFD: ::c_int = 0x000D;
+pub const ETH_P_PPPTALK: ::c_int = 0x0010;
+pub const ETH_P_TR_802_2: ::c_int = 0x0011;
+pub const ETH_P_MOBITEX: ::c_int = 0x0015;
+pub const ETH_P_CONTROL: ::c_int = 0x0016;
+pub const ETH_P_IRDA: ::c_int = 0x0017;
+pub const ETH_P_ECONET: ::c_int = 0x0018;
+pub const ETH_P_HDLC: ::c_int = 0x0019;
+pub const ETH_P_ARCNET: ::c_int = 0x001A;
+pub const ETH_P_DSA: ::c_int = 0x001B;
+pub const ETH_P_TRAILER: ::c_int = 0x001C;
+pub const ETH_P_PHONET: ::c_int = 0x00F5;
+pub const ETH_P_IEEE802154: ::c_int = 0x00F6;
+pub const ETH_P_CAIF: ::c_int = 0x00F7;
+pub const ETH_P_XDSA: ::c_int = 0x00F8;
+/* see rust-lang/libc#924 pub const ETH_P_MAP: ::c_int = 0x00F9;*/
+// end android/platform/bionic/libc/kernel/uapi/linux/if_ether.h
+
+pub const SIOCADDRT: ::c_ulong = 0x0000890B;
+pub const SIOCDELRT: ::c_ulong = 0x0000890C;
+pub const SIOCGIFNAME: ::c_ulong = 0x00008910;
+pub const SIOCSIFLINK: ::c_ulong = 0x00008911;
+pub const SIOCGIFCONF: ::c_ulong = 0x00008912;
+pub const SIOCGIFFLAGS: ::c_ulong = 0x00008913;
+pub const SIOCSIFFLAGS: ::c_ulong = 0x00008914;
+pub const SIOCGIFADDR: ::c_ulong = 0x00008915;
+pub const SIOCSIFADDR: ::c_ulong = 0x00008916;
+pub const SIOCGIFDSTADDR: ::c_ulong = 0x00008917;
+pub const SIOCSIFDSTADDR: ::c_ulong = 0x00008918;
+pub const SIOCGIFBRDADDR: ::c_ulong = 0x00008919;
+pub const SIOCSIFBRDADDR: ::c_ulong = 0x0000891A;
+pub const SIOCGIFNETMASK: ::c_ulong = 0x0000891B;
+pub const SIOCSIFNETMASK: ::c_ulong = 0x0000891C;
+pub const SIOCGIFMETRIC: ::c_ulong = 0x0000891D;
+pub const SIOCSIFMETRIC: ::c_ulong = 0x0000891E;
+pub const SIOCGIFMEM: ::c_ulong = 0x0000891F;
+pub const SIOCSIFMEM: ::c_ulong = 0x00008920;
+pub const SIOCGIFMTU: ::c_ulong = 0x00008921;
+pub const SIOCSIFMTU: ::c_ulong = 0x00008922;
+pub const SIOCSIFHWADDR: ::c_ulong = 0x00008924;
+pub const SIOCGIFENCAP: ::c_ulong = 0x00008925;
+pub const SIOCSIFENCAP: ::c_ulong = 0x00008926;
+pub const SIOCGIFHWADDR: ::c_ulong = 0x00008927;
+pub const SIOCGIFSLAVE: ::c_ulong = 0x00008929;
+pub const SIOCSIFSLAVE: ::c_ulong = 0x00008930;
+pub const SIOCADDMULTI: ::c_ulong = 0x00008931;
+pub const SIOCDELMULTI: ::c_ulong = 0x00008932;
+pub const SIOCDARP: ::c_ulong = 0x00008953;
+pub const SIOCGARP: ::c_ulong = 0x00008954;
+pub const SIOCSARP: ::c_ulong = 0x00008955;
+pub const SIOCDRARP: ::c_ulong = 0x00008960;
+pub const SIOCGRARP: ::c_ulong = 0x00008961;
+pub const SIOCSRARP: ::c_ulong = 0x00008962;
+pub const SIOCGIFMAP: ::c_ulong = 0x00008970;
+pub const SIOCSIFMAP: ::c_ulong = 0x00008971;
+
+// linux/module.h
+pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001;
+pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002;
+
+// Similarity to Linux it's not used but defined for compatibility.
+pub const ENOATTR: ::c_int = ::ENODATA;
+
 f! {
     pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () {
         for slot in cpuset.__bits.iter_mut() {
             *slot = 0;
         }
     }
 
     pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () {
@@ -918,16 +1501,20 @@ f! {
     pub fn minor(dev: ::dev_t) -> ::c_int {
         ((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int
     }
     pub fn makedev(ma: ::c_int, mi: ::c_int) -> ::dev_t {
         let ma = ma as ::dev_t;
         let mi = mi as ::dev_t;
         ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
     }
+
+    pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
+        return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
+    }
 }
 
 extern {
     static mut __progname: *mut ::c_char;
 }
 
 extern {
     pub fn madvise(addr: *const ::c_void, len: ::size_t, advice: ::c_int)
@@ -996,16 +1583,18 @@ extern {
                   fd_out: ::c_int,
                   off_out: *mut ::loff_t,
                   len: ::size_t,
                   flags: ::c_uint) -> ::ssize_t;
     pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;
     pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int;
     pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int;
     pub fn swapoff(puath: *const ::c_char) -> ::c_int;
     pub fn vmsplice(fd: ::c_int,
                     iov: *const ::iovec,
                     nr_segs: ::size_t,
                     flags: ::c_uint) -> ::ssize_t;
     pub fn mount(src: *const ::c_char,
@@ -1116,16 +1705,17 @@ extern {
     pub fn popen(command: *const c_char,
                  mode: *const c_char) -> *mut ::FILE;
     pub fn faccessat(dirfd: ::c_int, pathname: *const ::c_char,
                      mode: ::c_int, flags: ::c_int) -> ::c_int;
     pub fn pthread_create(native: *mut ::pthread_t,
                           attr: *const ::pthread_attr_t,
                           f: extern fn(*mut ::c_void) -> *mut ::c_void,
                           value: *mut ::c_void) -> ::c_int;
+    pub fn __errno() -> *mut ::c_int;
 }
 
 cfg_if! {
     if #[cfg(target_pointer_width = "32")] {
         mod b32;
         pub use self::b32::*;
     } else if #[cfg(target_pointer_width = "64")] {
         mod b64;
diff --git a/third_party/rust/libc/src/unix/notbsd/emscripten.rs b/third_party/rust/libc/src/unix/notbsd/emscripten.rs
index 90c056cafe38..b30fee32323d 100644
--- a/third_party/rust/libc/src/unix/notbsd/emscripten.rs
+++ b/third_party/rust/libc/src/unix/notbsd/emscripten.rs
@@ -67,52 +67,57 @@ s! {
 
         __unused1: *mut ::c_void,
         __unused2: *mut ::c_void,
         __unused3: *mut ::c_void,
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
     }
 
-    pub struct ifaddrs {
-        pub ifa_next: *mut ifaddrs,
-        pub ifa_name: *mut c_char,
-        pub ifa_flags: ::c_uint,
-        pub ifa_addr: *mut ::sockaddr,
-        pub ifa_netmask: *mut ::sockaddr,
-        pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union
-        pub ifa_data: *mut ::c_void
-    }
-
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_mutex_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_rwlock_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_mutexattr_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_rwlockattr_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T],
     }
 
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct pthread_cond_t {
+        #[cfg(not(feature = "align"))]
         __align: [*const ::c_void; 0],
         size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_condattr_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
     }
 
     pub struct passwd {
         pub pw_name: *mut ::c_char,
         pub pw_passwd: *mut ::c_char,
         pub pw_uid: ::uid_t,
@@ -456,16 +461,25 @@ s! {
         pub f_ffree: u32,
         pub f_favail: u32,
         pub f_fsid: ::c_ulong,
         __f_unused: ::c_int,
         pub f_flag: ::c_ulong,
         pub f_namemax: ::c_ulong,
         __f_spare: [::c_int; 6],
     }
+
+    pub struct arpd_request {
+        pub req: ::c_ushort,
+        pub ip: u32,
+        pub dev: ::c_ulong,
+        pub stamp: ::c_ulong,
+        pub updated: ::c_ulong,
+        pub ha: [::c_uchar; ::MAX_ADDR_LEN],
+    }
 }
 
 pub const ABDAY_1: ::nl_item = 0x20000;
 pub const ABDAY_2: ::nl_item = 0x20001;
 pub const ABDAY_3: ::nl_item = 0x20002;
 pub const ABDAY_4: ::nl_item = 0x20003;
 pub const ABDAY_5: ::nl_item = 0x20004;
 pub const ABDAY_6: ::nl_item = 0x20005;
@@ -743,28 +757,28 @@ pub const ST_NODIRATIME: ::c_ulong = 2048;
 
 pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void;
 pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
 pub const RTLD_NODELETE: ::c_int = 0x1000;
 pub const RTLD_NOW: ::c_int = 0x2;
 
 pub const TCP_MD5SIG: ::c_int = 14;
 
-pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_MUTEX_T],
-};
-pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_COND_T],
-};
-pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
-};
+align_const! {
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        size: [0; __SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
+
 pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
 pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
 pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL;
 pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0;
 pub const PTHREAD_PROCESS_SHARED: ::c_int = 1;
 pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
 
@@ -1479,16 +1493,22 @@ pub const TIOCM_SR: ::c_int = 0x010;
 pub const TIOCM_CTS: ::c_int = 0x020;
 pub const TIOCM_CAR: ::c_int = 0x040;
 pub const TIOCM_RNG: ::c_int = 0x080;
 pub const TIOCM_DSR: ::c_int = 0x100;
 pub const TIOCM_CD: ::c_int = TIOCM_CAR;
 pub const TIOCM_RI: ::c_int = TIOCM_RNG;
 pub const O_TMPFILE: ::c_int = 0x400000;
 
+pub const MAX_ADDR_LEN: usize = 7;
+pub const ARPD_UPDATE: ::c_ushort = 0x01;
+pub const ARPD_LOOKUP: ::c_ushort = 0x02;
+pub const ARPD_FLUSH: ::c_ushort = 0x03;
+pub const ATF_MAGIC: ::c_int = 0x80;
+
 f! {
     pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () {
         for slot in cpuset.bits.iter_mut() {
             *slot = 0;
         }
     }
 
     pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () {
@@ -1595,18 +1615,16 @@ extern {
                        flags: ::c_int) -> ::c_int;
     pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int;
 
     // Not available now on Android
     pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t) -> ::c_int;
     pub fn if_nameindex() -> *mut if_nameindex;
     pub fn if_freenameindex(ptr: *mut if_nameindex);
-    pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int;
-    pub fn freeifaddrs(ifa: *mut ::ifaddrs);
 
     pub fn mremap(addr: *mut ::c_void,
                   len: ::size_t,
                   new_len: ::size_t,
                   flags: ::c_int,
                   ...) -> *mut ::c_void;
 
     pub fn glob(pattern: *const c_char,
@@ -1630,31 +1648,16 @@ extern {
     pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
 
     pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
                     flags: ::c_int, addr: *mut ::sockaddr,
                     addrlen: *mut ::socklen_t) -> ::ssize_t;
     pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
     pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
 
-    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
-                address_len: ::socklen_t) -> ::c_int;
-
-    pub fn writev(fd: ::c_int,
-                  iov: *const ::iovec,
-                  iovcnt: ::c_int) -> ::ssize_t;
-    pub fn readv(fd: ::c_int,
-                 iov: *const ::iovec,
-                 iovcnt: ::c_int) -> ::ssize_t;
-
-    pub fn sendmsg(fd: ::c_int,
-                   msg: *const ::msghdr,
-                   flags: ::c_int) -> ::ssize_t;
-    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
-                   -> ::ssize_t;
     pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
     pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int;
     pub fn sendmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
                     flags: ::c_int) -> ::c_int;
     pub fn recvmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
                     flags: ::c_int, timeout: *mut ::timespec) -> ::c_int;
     pub fn sync();
     pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/mips/mips32.rs b/third_party/rust/libc/src/unix/notbsd/linux/mips/mips32.rs
index 8fad85b006eb..a6c08a5ad71b 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/mips/mips32.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/mips/mips32.rs
@@ -1,8 +1,10 @@
+use pthread_mutex_t;
+
 pub type c_char = i8;
 pub type c_long = i32;
 pub type c_ulong = u32;
 pub type clock_t = i32;
 pub type time_t = i32;
 pub type suseconds_t = i32;
 pub type wchar_t = i32;
 pub type off_t = i32;
@@ -86,30 +88,43 @@ s! {
         pub f_ffree: u64,
         pub f_bavail: u64,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::c_long,
         pub f_flags: ::c_long,
         pub f_spare: [::c_long; 5],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        __f_unused: ::c_int,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct statvfs64 {
         pub f_bsize: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_blocks: u64,
         pub f_bfree: u64,
         pub f_bavail: u64,
         pub f_files: u64,
         pub f_ffree: u64,
         pub f_favail: u64,
-        #[cfg(target_endian = "little")]
         pub f_fsid: ::c_ulong,
         __f_unused: ::c_int,
-        #[cfg(target_endian = "big")]
-        pub f_fsid: ::c_ulong,
         pub f_flag: ::c_ulong,
         pub f_namemax: ::c_ulong,
         __f_spare: [::c_int; 6],
     }
 
     pub struct pthread_attr_t {
         __size: [u32; 9]
     }
@@ -260,16 +275,67 @@ s! {
 }
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
 
+align_const! {
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+}
+
 pub const O_LARGEFILE: ::c_int = 0x2000;
 
 pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff;
 
 pub const SYS_syscall: ::c_long = 4000 + 0;
 pub const SYS_exit: ::c_long = 4000 + 1;
 pub const SYS_fork: ::c_long = 4000 + 2;
 pub const SYS_read: ::c_long = 4000 + 3;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/mips/mips64.rs b/third_party/rust/libc/src/unix/notbsd/linux/mips/mips64.rs
index 45b3df8fc147..e8b02a36b0e7 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/mips/mips64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/mips/mips64.rs
@@ -1,8 +1,10 @@
+use pthread_mutex_t;
+
 pub type blkcnt_t = i64;
 pub type blksize_t = i64;
 pub type c_char = i8;
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type ino_t = u64;
 pub type nlink_t = u64;
 pub type off_t = i64;
@@ -86,16 +88,31 @@ s! {
         pub f_ffree: u64,
         pub f_bavail: u64,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::c_long,
         pub f_flags: ::c_long,
         pub f_spare: [::c_long; 5],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct statvfs64 {
         pub f_bsize: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_blocks: u64,
         pub f_bfree: u64,
         pub f_bavail: u64,
         pub f_files: u64,
         pub f_ffree: u64,
@@ -242,16 +259,67 @@ s! {
 }
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
 
+align_const! {
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 pub const O_LARGEFILE: ::c_int = 0;
 
 pub const RLIM_INFINITY: ::rlim_t = 0xffff_ffff_ffff_ffff;
 
 pub const SYS_read: ::c_long = 5000 + 0;
 pub const SYS_write: ::c_long = 5000 + 1;
 pub const SYS_open: ::c_long = 5000 + 2;
 pub const SYS_close: ::c_long = 5000 + 3;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/mips/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/mips/mod.rs
index 1b4eb25cfada..4c14d12ebced 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/mips/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/mips/mod.rs
@@ -16,45 +16,89 @@ s! {
         __unused1: *mut ::c_void,
         __unused2: *mut ::c_void,
         __unused3: *mut ::c_void,
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
     }
 
     // FIXME this is actually a union
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t {
         #[cfg(target_pointer_width = "32")]
         __size: [::c_char; 16],
         #[cfg(target_pointer_width = "64")]
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
 
     pub struct termios2 {
         pub c_iflag: ::tcflag_t,
         pub c_oflag: ::tcflag_t,
         pub c_cflag: ::tcflag_t,
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; 23],
         pub c_ispeed: ::speed_t,
         pub c_ospeed: ::speed_t,
     }
+
+    pub struct nlmsghdr {
+        pub nlmsg_len: u32,
+        pub nlmsg_type: u16,
+        pub nlmsg_flags: u16,
+        pub nlmsg_seq: u32,
+        pub nlmsg_pid: u32,
+    }
+
+    pub struct nlmsgerr {
+        pub error: ::c_int,
+        pub msg: nlmsghdr,
+    }
+
+    pub struct nl_pktinfo {
+        pub group: u32,
+    }
+
+    pub struct nl_mmap_req {
+        pub nm_block_size: ::c_uint,
+        pub nm_block_nr: ::c_uint,
+        pub nm_frame_size: ::c_uint,
+        pub nm_frame_nr: ::c_uint,
+    }
+
+    pub struct nl_mmap_hdr {
+        pub nm_status: ::c_uint,
+        pub nm_len: ::c_uint,
+        pub nm_group: u32,
+        pub nm_pid: u32,
+        pub nm_uid: u32,
+        pub nm_gid: u32,
+    }
+
+    pub struct nlattr {
+        pub nla_len: u16,
+        pub nla_type: u16,
+    }
 }
 
 pub const SFD_CLOEXEC: ::c_int = 0x080000;
 
 pub const NCCS: usize = 32;
 
 pub const O_TRUNC: ::c_int = 512;
 
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_CLOEXEC: ::c_int = 0x80000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const EBFONT: ::c_int = 59;
 pub const ENOSTR: ::c_int = 60;
 pub const ENODATA: ::c_int = 61;
 pub const ETIME: ::c_int = 62;
 pub const ENOSR: ::c_int = 63;
 pub const ENONET: ::c_int = 64;
 pub const ENOPKG: ::c_int = 65;
@@ -419,16 +463,17 @@ pub const SIGPWR: ::c_int = 19;
 pub const SIG_SETMASK: ::c_int = 3;
 pub const SIG_BLOCK: ::c_int = 0x1;
 pub const SIG_UNBLOCK: ::c_int = 0x2;
 
 pub const POLLWRNORM: ::c_short = 0x004;
 pub const POLLWRBAND: ::c_short = 0x100;
 
 pub const PTHREAD_STACK_MIN: ::size_t = 131072;
+pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 3;
 
 pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5;
 pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff;
 pub const CODA_SUPER_MAGIC: ::c_long = 0x73757245;
 pub const CRAMFS_MAGIC: ::c_long = 0x28cd3d45;
 pub const EFS_SUPER_MAGIC: ::c_long = 0x00414a53;
 pub const EXT2_SUPER_MAGIC: ::c_long = 0x0000ef53;
 pub const EXT3_SUPER_MAGIC: ::c_long = 0x0000ef53;
@@ -656,21 +701,222 @@ pub const TIOCM_CD: ::c_int = TIOCM_CAR;
 pub const TIOCM_RNG: ::c_int = 0x200;
 pub const TIOCM_RI: ::c_int = TIOCM_RNG;
 pub const TIOCM_DSR: ::c_int = 0x400;
 
 pub const EHWPOISON: ::c_int = 168;
 pub const SIGEV_THREAD_ID: ::c_int = 4;
 pub const EPOLLWAKEUP: ::c_int = 0x20000000;
 
+pub const NF_NETDEV_INGRESS: ::c_int = 0;
+pub const NF_NETDEV_NUMHOOKS: ::c_int = 1;
+
+pub const NFPROTO_INET: ::c_int = 1;
+pub const NFPROTO_NETDEV: ::c_int = 5;
+
+pub const NLA_ALIGNTO: ::c_int = 4;
+
+pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10;
+
+pub const GENL_ID_VFS_DQUOT: ::c_int = ::NLMSG_MIN_TYPE + 1;
+pub const GENL_ID_PMCRAID: ::c_int = ::NLMSG_MIN_TYPE + 2;
+
+pub const NFT_TABLE_MAXNAMELEN: ::c_int = 32;
+pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 32;
+pub const NFT_SET_MAXNAMELEN: ::c_int = 32;
+pub const NFT_OBJ_MAXNAMELEN: ::c_int = 32;
+pub const NFT_USERDATA_MAXLEN: ::c_int = 256;
+
+pub const NFT_REG_VERDICT: ::c_int = 0;
+pub const NFT_REG_1: ::c_int = 1;
+pub const NFT_REG_2: ::c_int = 2;
+pub const NFT_REG_3: ::c_int = 3;
+pub const NFT_REG_4: ::c_int = 4;
+pub const __NFT_REG_MAX: ::c_int = 5;
+pub const NFT_REG32_00: ::c_int = 8;
+pub const NFT_REG32_01: ::c_int = 9;
+pub const NFT_REG32_02: ::c_int = 10;
+pub const NFT_REG32_03: ::c_int = 11;
+pub const NFT_REG32_04: ::c_int = 12;
+pub const NFT_REG32_05: ::c_int = 13;
+pub const NFT_REG32_06: ::c_int = 14;
+pub const NFT_REG32_07: ::c_int = 15;
+pub const NFT_REG32_08: ::c_int = 16;
+pub const NFT_REG32_09: ::c_int = 17;
+pub const NFT_REG32_10: ::c_int = 18;
+pub const NFT_REG32_11: ::c_int = 19;
+pub const NFT_REG32_12: ::c_int = 20;
+pub const NFT_REG32_13: ::c_int = 21;
+pub const NFT_REG32_14: ::c_int = 22;
+pub const NFT_REG32_15: ::c_int = 23;
+
+pub const NFT_REG_SIZE: ::c_int = 16;
+pub const NFT_REG32_SIZE: ::c_int = 4;
+
+pub const NFT_CONTINUE: ::c_int = -1;
+pub const NFT_BREAK: ::c_int = -2;
+pub const NFT_JUMP: ::c_int = -3;
+pub const NFT_GOTO: ::c_int = -4;
+pub const NFT_RETURN: ::c_int = -5;
+
+pub const NFT_MSG_NEWTABLE: ::c_int = 0;
+pub const NFT_MSG_GETTABLE: ::c_int = 1;
+pub const NFT_MSG_DELTABLE: ::c_int = 2;
+pub const NFT_MSG_NEWCHAIN: ::c_int = 3;
+pub const NFT_MSG_GETCHAIN: ::c_int = 4;
+pub const NFT_MSG_DELCHAIN: ::c_int = 5;
+pub const NFT_MSG_NEWRULE: ::c_int = 6;
+pub const NFT_MSG_GETRULE: ::c_int = 7;
+pub const NFT_MSG_DELRULE: ::c_int = 8;
+pub const NFT_MSG_NEWSET: ::c_int = 9;
+pub const NFT_MSG_GETSET: ::c_int = 10;
+pub const NFT_MSG_DELSET: ::c_int = 11;
+pub const NFT_MSG_NEWSETELEM: ::c_int = 12;
+pub const NFT_MSG_GETSETELEM: ::c_int = 13;
+pub const NFT_MSG_DELSETELEM: ::c_int = 14;
+pub const NFT_MSG_NEWGEN: ::c_int = 15;
+pub const NFT_MSG_GETGEN: ::c_int = 16;
+pub const NFT_MSG_TRACE: ::c_int = 17;
+pub const NFT_MSG_NEWOBJ: ::c_int = 18;
+pub const NFT_MSG_GETOBJ: ::c_int = 19;
+pub const NFT_MSG_DELOBJ: ::c_int = 20;
+pub const NFT_MSG_GETOBJ_RESET: ::c_int = 21;
+pub const NFT_MSG_MAX: ::c_int = 22;
+
+pub const NFT_SET_ANONYMOUS: ::c_int = 0x1;
+pub const NFT_SET_CONSTANT: ::c_int = 0x2;
+pub const NFT_SET_INTERVAL: ::c_int = 0x4;
+pub const NFT_SET_MAP: ::c_int = 0x8;
+pub const NFT_SET_TIMEOUT: ::c_int = 0x10;
+pub const NFT_SET_EVAL: ::c_int = 0x20;
+
+pub const NFT_SET_POL_PERFORMANCE: ::c_int = 0;
+pub const NFT_SET_POL_MEMORY: ::c_int = 1;
+
+pub const NFT_SET_ELEM_INTERVAL_END: ::c_int = 0x1;
+
+pub const NFT_DATA_VALUE: ::c_uint = 0;
+pub const NFT_DATA_VERDICT: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_RESERVED_MASK: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_VALUE_MAXLEN: ::c_int = 64;
+
+pub const NFT_BYTEORDER_NTOH: ::c_int = 0;
+pub const NFT_BYTEORDER_HTON: ::c_int = 1;
+
+pub const NFT_CMP_EQ: ::c_int = 0;
+pub const NFT_CMP_NEQ: ::c_int = 1;
+pub const NFT_CMP_LT: ::c_int = 2;
+pub const NFT_CMP_LTE: ::c_int = 3;
+pub const NFT_CMP_GT: ::c_int = 4;
+pub const NFT_CMP_GTE: ::c_int = 5;
+
+pub const NFT_RANGE_EQ: ::c_int = 0;
+pub const NFT_RANGE_NEQ: ::c_int = 1;
+
+pub const NFT_LOOKUP_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_DYNSET_OP_ADD: ::c_int = 0;
+pub const NFT_DYNSET_OP_UPDATE: ::c_int = 1;
+
+pub const NFT_DYNSET_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_PAYLOAD_LL_HEADER: ::c_int = 0;
+pub const NFT_PAYLOAD_NETWORK_HEADER: ::c_int = 1;
+pub const NFT_PAYLOAD_TRANSPORT_HEADER: ::c_int = 2;
+
+pub const NFT_PAYLOAD_CSUM_NONE: ::c_int = 0;
+pub const NFT_PAYLOAD_CSUM_INET: ::c_int = 1;
+
+pub const NFT_META_LEN: ::c_int = 0;
+pub const NFT_META_PROTOCOL: ::c_int = 1;
+pub const NFT_META_PRIORITY: ::c_int = 2;
+pub const NFT_META_MARK: ::c_int = 3;
+pub const NFT_META_IIF: ::c_int = 4;
+pub const NFT_META_OIF: ::c_int = 5;
+pub const NFT_META_IIFNAME: ::c_int = 6;
+pub const NFT_META_OIFNAME: ::c_int = 7;
+pub const NFT_META_IIFTYPE: ::c_int = 8;
+pub const NFT_META_OIFTYPE: ::c_int = 9;
+pub const NFT_META_SKUID: ::c_int = 10;
+pub const NFT_META_SKGID: ::c_int = 11;
+pub const NFT_META_NFTRACE: ::c_int = 12;
+pub const NFT_META_RTCLASSID: ::c_int = 13;
+pub const NFT_META_SECMARK: ::c_int = 14;
+pub const NFT_META_NFPROTO: ::c_int = 15;
+pub const NFT_META_L4PROTO: ::c_int = 16;
+pub const NFT_META_BRI_IIFNAME: ::c_int = 17;
+pub const NFT_META_BRI_OIFNAME: ::c_int = 18;
+pub const NFT_META_PKTTYPE: ::c_int = 19;
+pub const NFT_META_CPU: ::c_int = 20;
+pub const NFT_META_IIFGROUP: ::c_int = 21;
+pub const NFT_META_OIFGROUP: ::c_int = 22;
+pub const NFT_META_CGROUP: ::c_int = 23;
+pub const NFT_META_PRANDOM: ::c_int = 24;
+
+pub const NFT_CT_STATE: ::c_int = 0;
+pub const NFT_CT_DIRECTION: ::c_int = 1;
+pub const NFT_CT_STATUS: ::c_int = 2;
+pub const NFT_CT_MARK: ::c_int = 3;
+pub const NFT_CT_SECMARK: ::c_int = 4;
+pub const NFT_CT_EXPIRATION: ::c_int = 5;
+pub const NFT_CT_HELPER: ::c_int = 6;
+pub const NFT_CT_L3PROTOCOL: ::c_int = 7;
+pub const NFT_CT_SRC: ::c_int = 8;
+pub const NFT_CT_DST: ::c_int = 9;
+pub const NFT_CT_PROTOCOL: ::c_int = 10;
+pub const NFT_CT_PROTO_SRC: ::c_int = 11;
+pub const NFT_CT_PROTO_DST: ::c_int = 12;
+pub const NFT_CT_LABELS: ::c_int = 13;
+pub const NFT_CT_PKTS: ::c_int = 14;
+pub const NFT_CT_BYTES: ::c_int = 15;
+
+pub const NFT_LIMIT_PKTS: ::c_int = 0;
+pub const NFT_LIMIT_PKT_BYTES: ::c_int = 1;
+
+pub const NFT_LIMIT_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_QUEUE_FLAG_BYPASS: ::c_int = 0x01;
+pub const NFT_QUEUE_FLAG_CPU_FANOUT: ::c_int = 0x02;
+pub const NFT_QUEUE_FLAG_MASK: ::c_int = 0x03;
+
+pub const NFT_QUOTA_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_REJECT_ICMP_UNREACH: ::c_int = 0;
+pub const NFT_REJECT_TCP_RST: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_UNREACH: ::c_int = 2;
+
+pub const NFT_REJECT_ICMPX_NO_ROUTE: ::c_int = 0;
+pub const NFT_REJECT_ICMPX_PORT_UNREACH: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_HOST_UNREACH: ::c_int = 2;
+pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: ::c_int = 3;
+
+pub const NFT_NAT_SNAT: ::c_int = 0;
+pub const NFT_NAT_DNAT: ::c_int = 1;
+
+pub const NFT_TRACETYPE_UNSPEC: ::c_int = 0;
+pub const NFT_TRACETYPE_POLICY: ::c_int = 1;
+pub const NFT_TRACETYPE_RETURN: ::c_int = 2;
+pub const NFT_TRACETYPE_RULE: ::c_int = 3;
+
+pub const NFT_NG_INCREMENTAL: ::c_int = 0;
+pub const NFT_NG_RANDOM: ::c_int = 1;
+
 #[doc(hidden)]
 pub const AF_MAX: ::c_int = 42;
 #[doc(hidden)]
 pub const PF_MAX: ::c_int = AF_MAX;
 
+f! {
+    pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
+        return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
+    }
+}
+
 #[link(name = "util")]
 extern {
     pub fn sysctl(name: *mut ::c_int,
                   namelen: ::c_int,
                   oldp: *mut ::c_void,
                   oldlenp: *mut ::size_t,
                   newp: *mut ::c_void,
                   newlen: ::size_t)
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/mod.rs
index e85797670f87..6bc7db191c94 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/mod.rs
@@ -18,16 +18,27 @@ pub type idtype_t = ::c_uint;
 pub type loff_t = ::c_longlong;
 
 pub type __u8 = ::c_uchar;
 pub type __u16 = ::c_ushort;
 pub type __s16 = ::c_short;
 pub type __u32 = ::c_uint;
 pub type __s32 = ::c_int;
 
+pub type Elf32_Half = u16;
+pub type Elf32_Word = u32;
+pub type Elf32_Off = u32;
+pub type Elf32_Addr = u32;
+
+pub type Elf64_Half = u16;
+pub type Elf64_Word = u32;
+pub type Elf64_Off = u64;
+pub type Elf64_Addr = u64;
+pub type Elf64_Xword = u64;
+
 pub enum fpos64_t {} // TODO: fill this out with a struct
 
 s! {
     pub struct dirent {
         pub d_ino: ::ino_t,
         pub d_off: ::off_t,
         pub d_reclen: ::c_ushort,
         pub d_type: ::c_uchar,
@@ -55,91 +66,156 @@ s! {
 
         __unused1: *mut ::c_void,
         __unused2: *mut ::c_void,
         __unused3: *mut ::c_void,
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
     }
 
-    pub struct ifaddrs {
-        pub ifa_next: *mut ifaddrs,
-        pub ifa_name: *mut c_char,
-        pub ifa_flags: ::c_uint,
-        pub ifa_addr: *mut ::sockaddr,
-        pub ifa_netmask: *mut ::sockaddr,
-        pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union
-        pub ifa_data: *mut ::c_void
-    }
-
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc",
+                       target_arch = "x86_64",
+                       target_arch = "x86")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc",
+                               target_arch = "x86_64",
+                               target_arch = "x86")))),
+               repr(align(8)))]
     pub struct pthread_mutex_t {
-        #[cfg(any(target_arch = "mips",
-                  target_arch = "arm",
-                  target_arch = "powerpc",
-                  all(target_arch = "x86_64",
-                      target_pointer_width = "32")))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
                       target_arch = "arm",
                       target_arch = "powerpc",
                       all(target_arch = "x86_64",
                           target_pointer_width = "32"))))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc",
+                       target_arch = "x86_64",
+                       target_arch = "x86")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc",
+                               target_arch = "x86_64",
+                               target_arch = "x86")))),
+               repr(align(8)))]
     pub struct pthread_rwlock_t {
-        #[cfg(any(target_arch = "mips",
-                  target_arch = "arm",
-                  target_arch = "powerpc",
-                  all(target_arch = "x86_64",
-                      target_pointer_width = "32")))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc",
+                      all(target_arch = "x86_64",
+                          target_pointer_width = "32"))))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
                       target_arch = "arm",
                       target_arch = "powerpc",
                       all(target_arch = "x86_64",
                           target_pointer_width = "32"))))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "32",
+                       target_arch = "x86_64", target_arch = "powerpc64",
+                       target_arch = "mips64", target_arch = "s390x",
+                       target_arch = "sparc64",
+                       all(target_arch = "aarch64", target_env = "musl"))),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(any(target_pointer_width = "32",
+                           target_arch = "x86_64", target_arch = "powerpc64",
+                           target_arch = "mips64", target_arch = "s390x",
+                           target_arch = "sparc64",
+                           all(target_arch = "aarch64", target_env = "musl")))),
+               repr(align(8)))]
     pub struct pthread_mutexattr_t {
-        #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64",
-                  target_arch = "mips64", target_arch = "s390x",
-                  target_arch = "sparc64"))]
-        __align: [::c_int; 0],
-        #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64",
+        #[cfg(all(not(features = "align"),
+                  any(target_arch = "x86_64", target_arch = "powerpc64",
                       target_arch = "mips64", target_arch = "s390x",
-                      target_arch = "sparc64", target_arch = "aarch64")))]
-        __align: [::c_long; 0],
-        #[cfg(all(target_arch = "aarch64", target_env = "gnu"))]
-        __align: [::c_long; 0],
-        #[cfg(all(target_arch = "aarch64", target_env = "musl"))]
+                      target_arch = "sparc64",
+                      all(target_arch = "aarch64", target_env = "musl"))))]
         __align: [::c_int; 0],
+        #[cfg(all(not(features = "align"),
+                  not(any(target_arch = "x86_64", target_arch = "powerpc64",
+                          target_arch = "mips64", target_arch = "s390x",
+                          target_arch = "sparc64",
+                          all(target_arch = "aarch64", target_env = "musl")))))]
+        __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   any(target_env = "musl", target_pointer_width = "32")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct pthread_rwlockattr_t {
-        #[cfg(any(target_env = "musl"))]
+        #[cfg(all(not(feature = "align"), target_env = "musl"))]
         __align: [::c_int; 0],
-        #[cfg(not(any(target_env = "musl")))]
+        #[cfg(all(not(feature = "align"), not(target_env = "musl")))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_env = "musl",
+                   target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   target_env = "musl",
+                   target_pointer_width = "64"),
+               repr(align(8)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   target_arch = "x86"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(target_env = "musl"),
+                   not(target_arch = "x86")),
+               repr(align(8)))]
     pub struct pthread_cond_t {
-        #[cfg(any(target_env = "musl"))]
+        #[cfg(all(not(feature = "align"), target_env = "musl"))]
         __align: [*const ::c_void; 0],
-        #[cfg(not(any(target_env = "musl")))]
+        #[cfg(not(any(feature = "align", target_env = "musl")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_condattr_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
     }
 
     pub struct passwd {
         pub pw_name: *mut ::c_char,
         pub pw_passwd: *mut ::c_char,
         pub pw_uid: ::uid_t,
@@ -156,36 +232,16 @@ s! {
         pub sp_min: ::c_long,
         pub sp_max: ::c_long,
         pub sp_warn: ::c_long,
         pub sp_inact: ::c_long,
         pub sp_expire: ::c_long,
         pub sp_flag: ::c_ulong,
     }
 
-    pub struct statvfs {
-        pub f_bsize: ::c_ulong,
-        pub f_frsize: ::c_ulong,
-        pub f_blocks: ::fsblkcnt_t,
-        pub f_bfree: ::fsblkcnt_t,
-        pub f_bavail: ::fsblkcnt_t,
-        pub f_files: ::fsfilcnt_t,
-        pub f_ffree: ::fsfilcnt_t,
-        pub f_favail: ::fsfilcnt_t,
-        #[cfg(target_endian = "little")]
-        pub f_fsid: ::c_ulong,
-        #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))]
-        __f_unused: ::c_int,
-        #[cfg(target_endian = "big")]
-        pub f_fsid: ::c_ulong,
-        pub f_flag: ::c_ulong,
-        pub f_namemax: ::c_ulong,
-        __f_spare: [::c_int; 6],
-    }
-
     pub struct dqblk {
         pub dqb_bhardlimit: ::uint64_t,
         pub dqb_bsoftlimit: ::uint64_t,
         pub dqb_curspace: ::uint64_t,
         pub dqb_ihardlimit: ::uint64_t,
         pub dqb_isoftlimit: ::uint64_t,
         pub dqb_curinodes: ::uint64_t,
         pub dqb_btime: ::uint64_t,
@@ -243,16 +299,23 @@ s! {
         #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
         pub mq_msgsize: ::c_long,
         #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
         pub mq_curmsgs: ::c_long,
         #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
         pad: [::c_long; 4],
     }
 
+    pub struct packet_mreq {
+        pub mr_ifindex: ::c_int,
+        pub mr_type: ::c_ushort,
+        pub mr_alen: ::c_ushort,
+        pub mr_address: [::c_uchar; 8],
+    }
+
     pub struct cpu_set_t {
         #[cfg(all(target_pointer_width = "32",
                   not(target_arch = "x86_64")))]
         bits: [u32; 32],
         #[cfg(not(all(target_pointer_width = "32",
                       not(target_arch = "x86_64"))))]
         bits: [u64; 16],
     }
@@ -386,16 +449,117 @@ s! {
         pub trigger: ff_trigger,
         pub replay: ff_replay,
         // FIXME this is actually a union
         #[cfg(target_pointer_width = "64")]
         pub u: [u64; 4],
         #[cfg(target_pointer_width = "32")]
         pub u: [u32; 7],
     }
+
+    pub struct dl_phdr_info {
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_addr: Elf64_Addr,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_addr: Elf32_Addr,
+
+        pub dlpi_name: *const ::c_char,
+
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_phdr: *const Elf64_Phdr,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_phdr: *const Elf32_Phdr,
+
+        #[cfg(target_pointer_width = "64")]
+        pub dlpi_phnum: Elf64_Half,
+        #[cfg(target_pointer_width = "32")]
+        pub dlpi_phnum: Elf32_Half,
+
+        pub dlpi_adds: ::c_ulonglong,
+        pub dlpi_subs: ::c_ulonglong,
+        pub dlpi_tls_modid: ::size_t,
+        pub dlpi_tls_data: *mut ::c_void,
+    }
+
+    pub struct Elf32_Phdr {
+        pub p_type: Elf32_Word,
+        pub p_offset: Elf32_Off,
+        pub p_vaddr: Elf32_Addr,
+        pub p_paddr: Elf32_Addr,
+        pub p_filesz: Elf32_Word,
+        pub p_memsz: Elf32_Word,
+        pub p_flags: Elf32_Word,
+        pub p_align: Elf32_Word,
+    }
+
+    pub struct Elf64_Phdr {
+        pub p_type: Elf64_Word,
+        pub p_flags: Elf64_Word,
+        pub p_offset: Elf64_Off,
+        pub p_vaddr: Elf64_Addr,
+        pub p_paddr: Elf64_Addr,
+        pub p_filesz: Elf64_Xword,
+        pub p_memsz: Elf64_Xword,
+        pub p_align: Elf64_Xword,
+    }
+
+    pub struct ucred {
+        pub pid: ::pid_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+    }
+
+    pub struct mntent {
+        pub mnt_fsname: *mut ::c_char,
+        pub mnt_dir: *mut ::c_char,
+        pub mnt_type: *mut ::c_char,
+        pub mnt_opts: *mut ::c_char,
+        pub mnt_freq: ::c_int,
+        pub mnt_passno: ::c_int,
+    }
+
+    pub struct posix_spawn_file_actions_t {
+        __allocated: ::c_int,
+        __used: ::c_int,
+        __actions: *mut ::c_int,
+        __pad: [::c_int; 16],
+    }
+
+    pub struct posix_spawnattr_t {
+        __flags: ::c_short,
+        __pgrp: ::pid_t,
+        __sd: ::sigset_t,
+        __ss: ::sigset_t,
+        #[cfg(target_env = "musl")]
+        __prio: ::c_int,
+        #[cfg(not(target_env = "musl"))]
+        __sp: ::sched_param,
+        __policy: ::c_int,
+        __pad: [::c_int; 16],
+    }
+
+    pub struct genlmsghdr {
+        pub cmd: u8,
+        pub version: u8,
+        pub reserved: u16,
+    }
+
+    pub struct in6_pktinfo {
+        pub ipi6_addr: ::in6_addr,
+        pub ipi6_ifindex: ::c_uint,
+    }
+
+    pub struct arpd_request {
+        pub req: ::c_ushort,
+        pub ip: u32,
+        pub dev: ::c_ulong,
+        pub stamp: ::c_ulong,
+        pub updated: ::c_ulong,
+        pub ha: [::c_uchar; ::MAX_ADDR_LEN],
+    }
 }
 
 pub const ABDAY_1: ::nl_item = 0x20000;
 pub const ABDAY_2: ::nl_item = 0x20001;
 pub const ABDAY_3: ::nl_item = 0x20002;
 pub const ABDAY_4: ::nl_item = 0x20003;
 pub const ABDAY_5: ::nl_item = 0x20004;
 pub const ABDAY_6: ::nl_item = 0x20005;
@@ -658,16 +822,37 @@ pub const F_LOCK: ::c_int = 1;
 pub const F_TEST: ::c_int = 3;
 pub const F_TLOCK: ::c_int = 2;
 pub const F_ULOCK: ::c_int = 0;
 
 pub const IFF_LOWER_UP: ::c_int = 0x10000;
 pub const IFF_DORMANT: ::c_int = 0x20000;
 pub const IFF_ECHO: ::c_int = 0x40000;
 
+// linux/if_tun.h
+pub const IFF_TUN: ::c_short = 0x0001;
+pub const IFF_TAP: ::c_short = 0x0002;
+pub const IFF_NO_PI: ::c_short = 0x1000;
+// Read queue size
+pub const TUN_READQ_SIZE: ::c_short = 500;
+// TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead.
+pub const TUN_TUN_DEV: ::c_short   = ::IFF_TUN;
+pub const TUN_TAP_DEV: ::c_short   = ::IFF_TAP;
+pub const TUN_TYPE_MASK: ::c_short = 0x000f;
+// This flag has no real effect
+pub const IFF_ONE_QUEUE: ::c_short    = 0x2000;
+pub const IFF_VNET_HDR: ::c_short     = 0x4000;
+pub const IFF_TUN_EXCL: ::c_short     = 0x8000;
+pub const IFF_MULTI_QUEUE: ::c_short  = 0x0100;
+pub const IFF_ATTACH_QUEUE: ::c_short = 0x0200;
+pub const IFF_DETACH_QUEUE: ::c_short = 0x0400;
+// read-only flag
+pub const IFF_PERSIST: ::c_short  = 0x0800;
+pub const IFF_NOFILTER: ::c_short = 0x1000;
+
 pub const ST_RDONLY: ::c_ulong = 1;
 pub const ST_NOSUID: ::c_ulong = 2;
 pub const ST_NODEV: ::c_ulong = 4;
 pub const ST_NOEXEC: ::c_ulong = 8;
 pub const ST_SYNCHRONOUS: ::c_ulong = 16;
 pub const ST_MANDLOCK: ::c_ulong = 64;
 pub const ST_WRITE: ::c_ulong = 128;
 pub const ST_APPEND: ::c_ulong = 256;
@@ -677,28 +862,27 @@ pub const ST_NODIRATIME: ::c_ulong = 2048;
 
 pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void;
 pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
 pub const RTLD_NODELETE: ::c_int = 0x1000;
 pub const RTLD_NOW: ::c_int = 0x2;
 
 pub const TCP_MD5SIG: ::c_int = 14;
 
-pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_MUTEX_T],
-};
-pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_COND_T],
-};
-pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
-};
+align_const! {
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        size: [0; __SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
 pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
 pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
 pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL;
 pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0;
 pub const PTHREAD_PROCESS_SHARED: ::c_int = 1;
 pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
 
@@ -841,34 +1025,34 @@ pub const AI_ALL: ::c_int = 0x0010;
 pub const AI_ADDRCONFIG: ::c_int = 0x0020;
 
 pub const AI_NUMERICSERV: ::c_int = 0x0400;
 
 pub const EAI_BADFLAGS: ::c_int = -1;
 pub const EAI_NONAME: ::c_int = -2;
 pub const EAI_AGAIN: ::c_int = -3;
 pub const EAI_FAIL: ::c_int = -4;
+pub const EAI_NODATA: ::c_int = -5;
 pub const EAI_FAMILY: ::c_int = -6;
 pub const EAI_SOCKTYPE: ::c_int = -7;
 pub const EAI_SERVICE: ::c_int = -8;
 pub const EAI_MEMORY: ::c_int = -10;
+pub const EAI_SYSTEM: ::c_int = -11;
 pub const EAI_OVERFLOW: ::c_int = -12;
 
 pub const NI_NUMERICHOST: ::c_int = 1;
 pub const NI_NUMERICSERV: ::c_int = 2;
 pub const NI_NOFQDN: ::c_int = 4;
 pub const NI_NAMEREQD: ::c_int = 8;
 pub const NI_DGRAM: ::c_int = 16;
 
 pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1;
 pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2;
 pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4;
 
-pub const EAI_SYSTEM: ::c_int = -11;
-
 pub const AIO_CANCELED: ::c_int = 0;
 pub const AIO_NOTCANCELED: ::c_int = 1;
 pub const AIO_ALLDONE: ::c_int = 2;
 pub const LIO_READ: ::c_int = 0;
 pub const LIO_WRITE: ::c_int = 1;
 pub const LIO_NOP: ::c_int = 2;
 pub const LIO_WAIT: ::c_int = 0;
 pub const LIO_NOWAIT: ::c_int = 1;
@@ -991,16 +1175,23 @@ pub const PR_FP_MODE_FR: ::c_int = 1 << 0;
 pub const PR_FP_MODE_FRE: ::c_int = 1 << 1;
 
 pub const PR_CAP_AMBIENT: ::c_int = 47;
 pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1;
 pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2;
 pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3;
 pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4;
 
+pub const GRND_NONBLOCK: ::c_uint = 0x0001;
+pub const GRND_RANDOM: ::c_uint = 0x0002;
+
+pub const SECCOMP_MODE_DISABLED: ::c_uint = 0;
+pub const SECCOMP_MODE_STRICT: ::c_uint = 1;
+pub const SECCOMP_MODE_FILTER: ::c_uint = 2;
+
 pub const ITIMER_REAL: ::c_int = 0;
 pub const ITIMER_VIRTUAL: ::c_int = 1;
 pub const ITIMER_PROF: ::c_int = 2;
 
 pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC;
 pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK;
 pub const TFD_TIMER_ABSTIME: ::c_int = 1;
 
@@ -1019,17 +1210,376 @@ pub const FALLOC_FL_UNSHARE_RANGE: ::c_int = 0x40;
 // On Linux, libc doesn't define this constant, libattr does instead.
 // We still define it for Linux as it's defined by libc on other platforms,
 // and it's mentioned in the man pages for getxattr and setxattr.
 pub const ENOATTR: ::c_int = ::ENODATA;
 
 pub const SO_ORIGINAL_DST: ::c_int = 80;
 pub const IUTF8: ::tcflag_t = 0x00004000;
 pub const CMSPAR: ::tcflag_t = 0o10000000000;
-pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
+
+pub const MFD_CLOEXEC: ::c_uint = 0x0001;
+pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002;
+
+// these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has
+// the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32
+// so we can use that type here to avoid having to cast.
+pub const PT_NULL: u32 = 0;
+pub const PT_LOAD: u32 = 1;
+pub const PT_DYNAMIC: u32 = 2;
+pub const PT_INTERP: u32 = 3;
+pub const PT_NOTE: u32 = 4;
+pub const PT_SHLIB: u32 = 5;
+pub const PT_PHDR: u32 = 6;
+pub const PT_TLS: u32 = 7;
+pub const PT_NUM: u32 = 8;
+pub const PT_LOOS: u32 = 0x60000000;
+pub const PT_GNU_EH_FRAME: u32 = 0x6474e550;
+pub const PT_GNU_STACK: u32 = 0x6474e551;
+pub const PT_GNU_RELRO: u32 = 0x6474e552;
+
+// linux/if_ether.h
+pub const ETH_ALEN: ::c_int = 6;
+pub const ETH_HLEN: ::c_int = 14;
+pub const ETH_ZLEN: ::c_int = 60;
+pub const ETH_DATA_LEN: ::c_int = 1500;
+pub const ETH_FRAME_LEN: ::c_int = 1514;
+pub const ETH_FCS_LEN: ::c_int = 4;
+
+// These are the defined Ethernet Protocol ID's.
+pub const ETH_P_LOOP: ::c_int = 0x0060;
+pub const ETH_P_PUP: ::c_int = 0x0200;
+pub const ETH_P_PUPAT: ::c_int = 0x0201;
+pub const ETH_P_IP: ::c_int = 0x0800;
+pub const ETH_P_X25: ::c_int = 0x0805;
+pub const ETH_P_ARP: ::c_int = 0x0806;
+pub const ETH_P_BPQ: ::c_int = 0x08FF;
+pub const ETH_P_IEEEPUP: ::c_int = 0x0a00;
+pub const ETH_P_IEEEPUPAT: ::c_int = 0x0a01;
+pub const ETH_P_BATMAN: ::c_int = 0x4305;
+pub const ETH_P_DEC: ::c_int = 0x6000;
+pub const ETH_P_DNA_DL: ::c_int = 0x6001;
+pub const ETH_P_DNA_RC: ::c_int = 0x6002;
+pub const ETH_P_DNA_RT: ::c_int = 0x6003;
+pub const ETH_P_LAT: ::c_int = 0x6004;
+pub const ETH_P_DIAG: ::c_int = 0x6005;
+pub const ETH_P_CUST: ::c_int = 0x6006;
+pub const ETH_P_SCA: ::c_int = 0x6007;
+pub const ETH_P_TEB: ::c_int = 0x6558;
+pub const ETH_P_RARP: ::c_int = 0x8035;
+pub const ETH_P_ATALK: ::c_int = 0x809B;
+pub const ETH_P_AARP: ::c_int = 0x80F3;
+pub const ETH_P_8021Q: ::c_int = 0x8100;
+pub const ETH_P_IPX: ::c_int = 0x8137;
+pub const ETH_P_IPV6: ::c_int = 0x86DD;
+pub const ETH_P_PAUSE: ::c_int = 0x8808;
+pub const ETH_P_SLOW: ::c_int = 0x8809;
+pub const ETH_P_WCCP: ::c_int = 0x883E;
+pub const ETH_P_MPLS_UC: ::c_int = 0x8847;
+pub const ETH_P_MPLS_MC: ::c_int = 0x8848;
+pub const ETH_P_ATMMPOA: ::c_int = 0x884c;
+pub const ETH_P_PPP_DISC: ::c_int = 0x8863;
+pub const ETH_P_PPP_SES: ::c_int = 0x8864;
+pub const ETH_P_LINK_CTL: ::c_int = 0x886c;
+pub const ETH_P_ATMFATE: ::c_int = 0x8884;
+pub const ETH_P_PAE: ::c_int = 0x888E;
+pub const ETH_P_AOE: ::c_int = 0x88A2;
+pub const ETH_P_8021AD: ::c_int = 0x88A8;
+pub const ETH_P_802_EX1: ::c_int = 0x88B5;
+pub const ETH_P_TIPC: ::c_int = 0x88CA;
+pub const ETH_P_MACSEC: ::c_int = 0x88E5;
+pub const ETH_P_8021AH: ::c_int = 0x88E7;
+pub const ETH_P_MVRP: ::c_int = 0x88F5;
+pub const ETH_P_1588: ::c_int = 0x88F7;
+pub const ETH_P_PRP: ::c_int = 0x88FB;
+pub const ETH_P_FCOE: ::c_int = 0x8906;
+pub const ETH_P_TDLS: ::c_int = 0x890D;
+pub const ETH_P_FIP: ::c_int = 0x8914;
+pub const ETH_P_80221: ::c_int = 0x8917;
+pub const ETH_P_LOOPBACK: ::c_int = 0x9000;
+pub const ETH_P_QINQ1: ::c_int = 0x9100;
+pub const ETH_P_QINQ2: ::c_int = 0x9200;
+pub const ETH_P_QINQ3: ::c_int = 0x9300;
+pub const ETH_P_EDSA: ::c_int = 0xDADA;
+pub const ETH_P_AF_IUCV: ::c_int = 0xFBFB;
+
+pub const ETH_P_802_3_MIN: ::c_int = 0x0600;
+
+// Non DIX types. Won't clash for 1500 types.
+pub const ETH_P_802_3: ::c_int = 0x0001;
+pub const ETH_P_AX25: ::c_int = 0x0002;
+pub const ETH_P_ALL: ::c_int = 0x0003;
+pub const ETH_P_802_2: ::c_int = 0x0004;
+pub const ETH_P_SNAP: ::c_int = 0x0005;
+pub const ETH_P_DDCMP: ::c_int = 0x0006;
+pub const ETH_P_WAN_PPP: ::c_int = 0x0007;
+pub const ETH_P_PPP_MP: ::c_int = 0x0008;
+pub const ETH_P_LOCALTALK: ::c_int = 0x0009;
+pub const ETH_P_CANFD: ::c_int = 0x000D;
+pub const ETH_P_PPPTALK: ::c_int = 0x0010;
+pub const ETH_P_TR_802_2: ::c_int = 0x0011;
+pub const ETH_P_MOBITEX: ::c_int = 0x0015;
+pub const ETH_P_CONTROL: ::c_int = 0x0016;
+pub const ETH_P_IRDA: ::c_int = 0x0017;
+pub const ETH_P_ECONET: ::c_int = 0x0018;
+pub const ETH_P_HDLC: ::c_int = 0x0019;
+pub const ETH_P_ARCNET: ::c_int = 0x001A;
+pub const ETH_P_DSA: ::c_int = 0x001B;
+pub const ETH_P_TRAILER: ::c_int = 0x001C;
+pub const ETH_P_PHONET: ::c_int = 0x00F5;
+pub const ETH_P_IEEE802154: ::c_int = 0x00F6;
+pub const ETH_P_CAIF: ::c_int = 0x00F7;
+
+pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01;
+pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02;
+pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x04;
+pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x08;
+pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x10;
+pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x20;
+
+pub const NLMSG_NOOP: ::c_int = 0x1;
+pub const NLMSG_ERROR: ::c_int = 0x2;
+pub const NLMSG_DONE: ::c_int = 0x3;
+pub const NLMSG_OVERRUN: ::c_int = 0x4;
+pub const NLMSG_MIN_TYPE: ::c_int = 0x10;
+
+pub const GENL_NAMSIZ: ::c_int = 16;
+
+pub const GENL_MIN_ID: ::c_int = NLMSG_MIN_TYPE;
+pub const GENL_MAX_ID: ::c_int = 1023;
+
+pub const GENL_ADMIN_PERM: ::c_int = 0x01;
+pub const GENL_CMD_CAP_DO: ::c_int = 0x02;
+pub const GENL_CMD_CAP_DUMP: ::c_int = 0x04;
+pub const GENL_CMD_CAP_HASPOL: ::c_int = 0x08;
+
+pub const GENL_ID_CTRL: ::c_int = NLMSG_MIN_TYPE;
+
+pub const CTRL_CMD_UNSPEC: ::c_int = 0;
+pub const CTRL_CMD_NEWFAMILY: ::c_int = 1;
+pub const CTRL_CMD_DELFAMILY: ::c_int = 2;
+pub const CTRL_CMD_GETFAMILY: ::c_int = 3;
+pub const CTRL_CMD_NEWOPS: ::c_int = 4;
+pub const CTRL_CMD_DELOPS: ::c_int = 5;
+pub const CTRL_CMD_GETOPS: ::c_int = 6;
+pub const CTRL_CMD_NEWMCAST_GRP: ::c_int = 7;
+pub const CTRL_CMD_DELMCAST_GRP: ::c_int = 8;
+pub const CTRL_CMD_GETMCAST_GRP: ::c_int = 9;
+
+pub const CTRL_ATTR_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_FAMILY_ID: ::c_int = 1;
+pub const CTRL_ATTR_FAMILY_NAME: ::c_int = 2;
+pub const CTRL_ATTR_VERSION: ::c_int = 3;
+pub const CTRL_ATTR_HDRSIZE: ::c_int = 4;
+pub const CTRL_ATTR_MAXATTR: ::c_int = 5;
+pub const CTRL_ATTR_OPS: ::c_int = 6;
+pub const CTRL_ATTR_MCAST_GROUPS: ::c_int = 7;
+
+pub const CTRL_ATTR_OP_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_OP_ID: ::c_int = 1;
+pub const CTRL_ATTR_OP_FLAGS: ::c_int = 2;
+
+pub const CTRL_ATTR_MCAST_GRP_UNSPEC: ::c_int = 0;
+pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1;
+pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2;
+
+// linux/if_packet.h
+pub const PACKET_ADD_MEMBERSHIP: ::c_int = 1;
+pub const PACKET_DROP_MEMBERSHIP: ::c_int = 2;
+
+pub const PACKET_MR_MULTICAST: ::c_int = 0;
+pub const PACKET_MR_PROMISC: ::c_int = 1;
+pub const PACKET_MR_ALLMULTI: ::c_int = 2;
+pub const PACKET_MR_UNICAST: ::c_int = 3;
+
+// linux/netfilter.h
+pub const NF_DROP: ::c_int = 0;
+pub const NF_ACCEPT: ::c_int =  1;
+pub const NF_STOLEN: ::c_int =  2;
+pub const NF_QUEUE: ::c_int =  3;
+pub const NF_REPEAT: ::c_int =  4;
+pub const NF_STOP: ::c_int =  5;
+pub const NF_MAX_VERDICT: ::c_int = NF_STOP;
+
+pub const NF_VERDICT_MASK: ::c_int = 0x000000ff;
+pub const NF_VERDICT_FLAG_QUEUE_BYPASS: ::c_int = 0x00008000;
+
+pub const NF_VERDICT_QMASK: ::c_int = 0xffff0000;
+pub const NF_VERDICT_QBITS: ::c_int = 16;
+
+pub const NF_VERDICT_BITS: ::c_int = 16;
+
+pub const NF_INET_PRE_ROUTING: ::c_int = 0;
+pub const NF_INET_LOCAL_IN: ::c_int = 1;
+pub const NF_INET_FORWARD: ::c_int = 2;
+pub const NF_INET_LOCAL_OUT: ::c_int = 3;
+pub const NF_INET_POST_ROUTING: ::c_int = 4;
+pub const NF_INET_NUMHOOKS: ::c_int = 5;
+
+// Some NFPROTO are not compatible with musl and are defined in submodules.
+pub const NFPROTO_UNSPEC: ::c_int = 0;
+pub const NFPROTO_IPV4: ::c_int = 2;
+pub const NFPROTO_ARP: ::c_int = 3;
+pub const NFPROTO_BRIDGE: ::c_int = 7;
+pub const NFPROTO_IPV6: ::c_int = 10;
+pub const NFPROTO_DECNET: ::c_int = 12;
+pub const NFPROTO_NUMPROTO: ::c_int = 13;
+
+// linux/netfilter_ipv4.h
+pub const NF_IP_PRE_ROUTING: ::c_int = 0;
+pub const NF_IP_LOCAL_IN: ::c_int = 1;
+pub const NF_IP_FORWARD: ::c_int = 2;
+pub const NF_IP_LOCAL_OUT: ::c_int = 3;
+pub const NF_IP_POST_ROUTING: ::c_int = 4;
+pub const NF_IP_NUMHOOKS: ::c_int = 5;
+
+pub const NF_IP_PRI_FIRST: ::c_int = ::INT_MIN;
+pub const NF_IP_PRI_CONNTRACK_DEFRAG: ::c_int = -400;
+pub const NF_IP_PRI_RAW: ::c_int = -300;
+pub const NF_IP_PRI_SELINUX_FIRST: ::c_int = -225;
+pub const NF_IP_PRI_CONNTRACK: ::c_int = -200;
+pub const NF_IP_PRI_MANGLE: ::c_int = -150;
+pub const NF_IP_PRI_NAT_DST: ::c_int = -100;
+pub const NF_IP_PRI_FILTER: ::c_int = 0;
+pub const NF_IP_PRI_SECURITY: ::c_int = 50;
+pub const NF_IP_PRI_NAT_SRC: ::c_int = 100;
+pub const NF_IP_PRI_SELINUX_LAST: ::c_int = 225;
+pub const NF_IP_PRI_CONNTRACK_HELPER: ::c_int = 300;
+pub const NF_IP_PRI_CONNTRACK_CONFIRM: ::c_int = ::INT_MAX;
+pub const NF_IP_PRI_LAST: ::c_int = ::INT_MAX;
+
+// linux/netfilter_ipv6.h
+pub const NF_IP6_PRE_ROUTING: ::c_int = 0;
+pub const NF_IP6_LOCAL_IN: ::c_int = 1;
+pub const NF_IP6_FORWARD: ::c_int = 2;
+pub const NF_IP6_LOCAL_OUT: ::c_int = 3;
+pub const NF_IP6_POST_ROUTING: ::c_int = 4;
+pub const NF_IP6_NUMHOOKS: ::c_int = 5;
+
+pub const NF_IP6_PRI_FIRST: ::c_int = ::INT_MIN;
+pub const NF_IP6_PRI_CONNTRACK_DEFRAG: ::c_int = -400;
+pub const NF_IP6_PRI_RAW: ::c_int = -300;
+pub const NF_IP6_PRI_SELINUX_FIRST: ::c_int = -225;
+pub const NF_IP6_PRI_CONNTRACK: ::c_int = -200;
+pub const NF_IP6_PRI_MANGLE: ::c_int = -150;
+pub const NF_IP6_PRI_NAT_DST: ::c_int = -100;
+pub const NF_IP6_PRI_FILTER: ::c_int = 0;
+pub const NF_IP6_PRI_SECURITY: ::c_int = 50;
+pub const NF_IP6_PRI_NAT_SRC: ::c_int = 100;
+pub const NF_IP6_PRI_SELINUX_LAST: ::c_int = 225;
+pub const NF_IP6_PRI_CONNTRACK_HELPER: ::c_int = 300;
+pub const NF_IP6_PRI_LAST: ::c_int = ::INT_MAX;
+
+pub const SIOCADDRT: ::c_ulong = 0x0000890B;
+pub const SIOCDELRT: ::c_ulong = 0x0000890C;
+pub const SIOCGIFNAME: ::c_ulong = 0x00008910;
+pub const SIOCSIFLINK: ::c_ulong = 0x00008911;
+pub const SIOCGIFCONF: ::c_ulong = 0x00008912;
+pub const SIOCGIFFLAGS: ::c_ulong = 0x00008913;
+pub const SIOCSIFFLAGS: ::c_ulong = 0x00008914;
+pub const SIOCGIFADDR: ::c_ulong = 0x00008915;
+pub const SIOCSIFADDR: ::c_ulong = 0x00008916;
+pub const SIOCGIFDSTADDR: ::c_ulong = 0x00008917;
+pub const SIOCSIFDSTADDR: ::c_ulong = 0x00008918;
+pub const SIOCGIFBRDADDR: ::c_ulong = 0x00008919;
+pub const SIOCSIFBRDADDR: ::c_ulong = 0x0000891A;
+pub const SIOCGIFNETMASK: ::c_ulong = 0x0000891B;
+pub const SIOCSIFNETMASK: ::c_ulong = 0x0000891C;
+pub const SIOCGIFMETRIC: ::c_ulong = 0x0000891D;
+pub const SIOCSIFMETRIC: ::c_ulong = 0x0000891E;
+pub const SIOCGIFMEM: ::c_ulong = 0x0000891F;
+pub const SIOCSIFMEM: ::c_ulong = 0x00008920;
+pub const SIOCGIFMTU: ::c_ulong = 0x00008921;
+pub const SIOCSIFMTU: ::c_ulong = 0x00008922;
+pub const SIOCSIFHWADDR: ::c_ulong = 0x00008924;
+pub const SIOCGIFENCAP: ::c_ulong = 0x00008925;
+pub const SIOCSIFENCAP: ::c_ulong = 0x00008926;
+pub const SIOCGIFHWADDR: ::c_ulong = 0x00008927;
+pub const SIOCGIFSLAVE: ::c_ulong = 0x00008929;
+pub const SIOCSIFSLAVE: ::c_ulong = 0x00008930;
+pub const SIOCADDMULTI: ::c_ulong = 0x00008931;
+pub const SIOCDELMULTI: ::c_ulong = 0x00008932;
+pub const SIOCDARP: ::c_ulong = 0x00008953;
+pub const SIOCGARP: ::c_ulong = 0x00008954;
+pub const SIOCSARP: ::c_ulong = 0x00008955;
+pub const SIOCDRARP: ::c_ulong = 0x00008960;
+pub const SIOCGRARP: ::c_ulong = 0x00008961;
+pub const SIOCSRARP: ::c_ulong = 0x00008962;
+pub const SIOCGIFMAP: ::c_ulong = 0x00008970;
+pub const SIOCSIFMAP: ::c_ulong = 0x00008971;
+
+pub const IPTOS_TOS_MASK: u8 = 0x1E;
+pub const IPTOS_PREC_MASK: u8 = 0xE0;
+
+pub const RTF_UP: ::c_ushort = 0x0001;
+pub const RTF_GATEWAY: ::c_ushort = 0x0002;
+
+pub const RTF_HOST: ::c_ushort = 0x0004;
+pub const RTF_REINSTATE: ::c_ushort = 0x0008;
+pub const RTF_DYNAMIC: ::c_ushort = 0x0010;
+pub const RTF_MODIFIED: ::c_ushort = 0x0020;
+pub const RTF_MTU: ::c_ushort = 0x0040;
+pub const RTF_MSS: ::c_ushort = RTF_MTU;
+pub const RTF_WINDOW: ::c_ushort = 0x0080;
+pub const RTF_IRTT: ::c_ushort = 0x0100;
+pub const RTF_REJECT: ::c_ushort = 0x0200;
+pub const RTF_STATIC: ::c_ushort = 0x0400;
+pub const RTF_XRESOLVE: ::c_ushort = 0x0800;
+pub const RTF_NOFORWARD: ::c_ushort = 0x1000;
+pub const RTF_THROW: ::c_ushort = 0x2000;
+pub const RTF_NOPMTUDISC: ::c_ushort = 0x4000;
+
+pub const RTF_DEFAULT: u32 = 0x00010000;
+pub const RTF_ALLONLINK: u32 = 0x00020000;
+pub const RTF_ADDRCONF: u32 = 0x00040000;
+pub const RTF_LINKRT: u32 = 0x00100000;
+pub const RTF_NONEXTHOP: u32 = 0x00200000;
+pub const RTF_CACHE: u32 = 0x01000000;
+pub const RTF_FLOW: u32 = 0x02000000;
+pub const RTF_POLICY: u32 = 0x04000000;
+
+pub const RTCF_VALVE: u32 = 0x00200000;
+pub const RTCF_MASQ: u32 = 0x00400000;
+pub const RTCF_NAT: u32 = 0x00800000;
+pub const RTCF_DOREDIRECT: u32 = 0x01000000;
+pub const RTCF_LOG: u32 = 0x02000000;
+pub const RTCF_DIRECTSRC: u32 = 0x04000000;
+
+pub const RTF_LOCAL: u32 = 0x80000000;
+pub const RTF_INTERFACE: u32 = 0x40000000;
+pub const RTF_MULTICAST: u32 = 0x20000000;
+pub const RTF_BROADCAST: u32 = 0x10000000;
+pub const RTF_NAT: u32 = 0x08000000;
+pub const RTF_ADDRCLASSMASK: u32 = 0xF8000000;
+
+pub const RT_CLASS_UNSPEC: u8 = 0;
+pub const RT_CLASS_DEFAULT: u8 = 253;
+pub const RT_CLASS_MAIN: u8 = 254;
+pub const RT_CLASS_LOCAL: u8 = 255;
+pub const RT_CLASS_MAX: u8 = 255;
+
+pub const RTMSG_OVERRUN: u32 = ::NLMSG_OVERRUN as u32;
+pub const RTMSG_NEWDEVICE: u32 = 0x11;
+pub const RTMSG_DELDEVICE: u32 = 0x12;
+pub const RTMSG_NEWROUTE: u32 = 0x21;
+pub const RTMSG_DELROUTE: u32 = 0x22;
+pub const RTMSG_NEWRULE: u32 = 0x31;
+pub const RTMSG_DELRULE: u32 = 0x32;
+pub const RTMSG_CONTROL: u32 = 0x40;
+pub const RTMSG_AR_FAILED: u32 = 0x51;
+
+pub const MAX_ADDR_LEN: usize = 7;
+pub const ARPD_UPDATE: ::c_ushort = 0x01;
+pub const ARPD_LOOKUP: ::c_ushort = 0x02;
+pub const ARPD_FLUSH: ::c_ushort = 0x03;
+pub const ATF_MAGIC: ::c_int = 0x80;
+
+// linux/module.h
+pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001;
+pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002;
 
 f! {
     pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () {
         for slot in cpuset.bits.iter_mut() {
             *slot = 0;
         }
     }
 
@@ -1076,16 +1626,36 @@ f! {
         let minor = minor as ::dev_t;
         let mut dev = 0;
         dev |= (major & 0x00000fff) << 8;
         dev |= (major & 0xfffff000) << 32;
         dev |= (minor & 0x000000ff) << 0;
         dev |= (minor & 0xffffff00) << 12;
         dev
     }
+
+    pub fn IPTOS_TOS(tos: u8) -> u8 {
+        tos & IPTOS_TOS_MASK
+    }
+
+    pub fn IPTOS_PREC(tos: u8) -> u8 {
+        tos & IPTOS_PREC_MASK
+    }
+
+    pub fn RT_TOS(tos: u8) -> u8 {
+        tos & ::IPTOS_TOS_MASK
+    }
+
+    pub fn RT_ADDRCLASS(flags: u32) -> u32 {
+        flags >> 23
+    }
+
+    pub fn RT_LOCALADDR(flags: u32) -> bool {
+        (flags & RTF_ADDRCLASSMASK) == (RTF_LOCAL | RTF_INTERFACE)
+    }
 }
 
 extern {
     pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int;
     pub fn aio_error(aiocbp: *const aiocb) -> ::c_int;
     pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t;
@@ -1095,19 +1665,23 @@ extern {
     pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb,
                       nitems: ::c_int, sevp: *mut ::sigevent) -> ::c_int;
 
     pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int;
 
     pub fn setpwent();
     pub fn endpwent();
     pub fn getpwent() -> *mut passwd;
+    pub fn setgrent();
+    pub fn endgrent();
+    pub fn getgrent() -> *mut ::group;
     pub fn setspent();
     pub fn endspent();
     pub fn getspent() -> *mut spwd;
+
     pub fn getspnam(__name: *const ::c_char) -> *mut spwd;
 
     pub fn shm_open(name: *const c_char, oflag: ::c_int,
                     mode: mode_t) -> ::c_int;
 
     // System V IPC
     pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int;
     pub fn shmat(shmid: ::c_int,
@@ -1262,19 +1836,16 @@ extern {
 
     // Not available now on Android
     pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t) -> ::c_int;
     pub fn if_nameindex() -> *mut if_nameindex;
     pub fn if_freenameindex(ptr: *mut if_nameindex);
     pub fn sync_file_range(fd: ::c_int, offset: ::off64_t,
                            nbytes: ::off64_t, flags: ::c_uint) -> ::c_int;
-    pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int;
-    pub fn freeifaddrs(ifa: *mut ::ifaddrs);
-
     pub fn mremap(addr: *mut ::c_void,
                   len: ::size_t,
                   new_len: ::size_t,
                   flags: ::c_int,
                   ...) -> *mut ::c_void;
 
     pub fn glob(pattern: *const c_char,
                 flags: ::c_int,
@@ -1290,39 +1861,25 @@ extern {
 
     pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long);
 
     pub fn telldir(dirp: *mut ::DIR) -> ::c_long;
     pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int)
                   -> ::c_int;
 
     pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
-
+    pub fn remap_file_pages(addr: *mut ::c_void, size: ::size_t, prot: ::c_int,
+                            pgoff: ::size_t, flags: ::c_int) -> ::c_int;
     pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
                     flags: ::c_int, addr: *mut ::sockaddr,
                     addrlen: *mut ::socklen_t) -> ::ssize_t;
     pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
     pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int;
     pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
 
-    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
-                address_len: ::socklen_t) -> ::c_int;
-
-    pub fn writev(fd: ::c_int,
-                  iov: *const ::iovec,
-                  iovcnt: ::c_int) -> ::ssize_t;
-    pub fn readv(fd: ::c_int,
-                 iov: *const ::iovec,
-                 iovcnt: ::c_int) -> ::ssize_t;
-
-    pub fn sendmsg(fd: ::c_int,
-                   msg: *const ::msghdr,
-                   flags: ::c_int) -> ::ssize_t;
-    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
-                   -> ::ssize_t;
     pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
     pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int;
     pub fn vhangup() -> ::c_int;
     pub fn sendmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
                     flags: ::c_int) -> ::c_int;
     pub fn recvmmsg(sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint,
                     flags: ::c_int, timeout: *mut ::timespec) -> ::c_int;
     pub fn sync();
@@ -1359,16 +1916,18 @@ extern {
                   fd_out: ::c_int,
                   off_out: *mut ::loff_t,
                   len: ::size_t,
                   flags: ::c_uint) -> ::ssize_t;
     pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;
     pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int;
     pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int;
     pub fn swapoff(puath: *const ::c_char) -> ::c_int;
     pub fn vmsplice(fd: ::c_int,
                     iov: *const ::iovec,
                     nr_segs: ::size_t,
                     flags: ::c_uint) -> ::ssize_t;
     pub fn mount(src: *const ::c_char,
@@ -1478,16 +2037,103 @@ extern {
     pub fn popen(command: *const c_char,
                  mode: *const c_char) -> *mut ::FILE;
     pub fn faccessat(dirfd: ::c_int, pathname: *const ::c_char,
                      mode: ::c_int, flags: ::c_int) -> ::c_int;
     pub fn pthread_create(native: *mut ::pthread_t,
                           attr: *const ::pthread_attr_t,
                           f: extern fn(*mut ::c_void) -> *mut ::c_void,
                           value: *mut ::c_void) -> ::c_int;
+    pub fn dl_iterate_phdr(
+        callback: Option<unsafe extern fn(
+            info: *mut ::dl_phdr_info,
+            size: ::size_t,
+            data: *mut ::c_void
+        ) -> ::c_int>,
+        data: *mut ::c_void
+    ) -> ::c_int;
+
+    pub fn setmntent(filename: *const ::c_char,
+                     ty: *const ::c_char) -> *mut ::FILE;
+    pub fn getmntent(stream: *mut ::FILE) -> *mut ::mntent;
+    pub fn addmntent(stream: *mut ::FILE, mnt: *const ::mntent) -> ::c_int;
+    pub fn endmntent(streamp: *mut ::FILE) -> ::c_int;
+    pub fn hasmntopt(mnt: *const ::mntent,
+                     opt: *const ::c_char) -> *mut ::c_char;
+
+    pub fn posix_spawn(pid: *mut ::pid_t,
+                       path: *const ::c_char,
+                       file_actions: *const ::posix_spawn_file_actions_t,
+                       attrp: *const ::posix_spawnattr_t,
+                       argv: *const *mut ::c_char,
+                       envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnp(pid: *mut ::pid_t,
+                       file: *const ::c_char,
+                        file_actions: *const ::posix_spawn_file_actions_t,
+                        attrp: *const ::posix_spawnattr_t,
+                        argv: *const *mut ::c_char,
+                        envp: *const *mut ::c_char) -> ::c_int;
+    pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigdefault(attr: *const posix_spawnattr_t,
+                                         default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigdefault(attr: *mut posix_spawnattr_t,
+                                         default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getsigmask(attr: *const posix_spawnattr_t,
+                                      default: *mut ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_setsigmask(attr: *mut posix_spawnattr_t,
+                                      default: *const ::sigset_t) -> ::c_int;
+    pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t,
+                                    flags: *mut ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t,
+                                    flags: ::c_short) -> ::c_int;
+    pub fn posix_spawnattr_getpgroup(attr: *const posix_spawnattr_t,
+                                     flags: *mut ::pid_t) -> ::c_int;
+    pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t,
+                                     flags: ::pid_t) -> ::c_int;
+    pub fn posix_spawnattr_getschedpolicy(attr: *const posix_spawnattr_t,
+                                          flags: *mut ::c_int) -> ::c_int;
+    pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t,
+                                          flags: ::c_int) -> ::c_int;
+    pub fn posix_spawnattr_getschedparam(
+        attr: *const posix_spawnattr_t,
+        param: *mut ::sched_param,
+    ) -> ::c_int;
+    pub fn posix_spawnattr_setschedparam(
+        attr: *mut posix_spawnattr_t,
+        param: *const ::sched_param,
+    ) -> ::c_int;
+
+    pub fn posix_spawn_file_actions_init(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_destroy(
+        actions: *mut posix_spawn_file_actions_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addopen(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        path: *const ::c_char,
+        oflag: ::c_int,
+        mode: ::mode_t,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_addclose(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+    ) -> ::c_int;
+    pub fn posix_spawn_file_actions_adddup2(
+        actions: *mut posix_spawn_file_actions_t,
+        fd: ::c_int,
+        newfd: ::c_int,
+    ) -> ::c_int;
+    pub fn fread_unlocked(ptr: *mut ::c_void,
+        size: ::size_t,
+        nobj: ::size_t,
+        stream: *mut ::FILE
+    ) -> ::size_t;
 }
 
 cfg_if! {
     if #[cfg(any(target_env = "musl", target_os = "fuchsia"))] {
         mod musl;
         pub use self::musl::*;
     } else if #[cfg(any(target_arch = "mips",
                         target_arch = "mips64"))] {
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/arm.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/arm.rs
index 22bf16c1fda9..20fa33a3f776 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/arm.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/arm.rs
@@ -47,16 +47,28 @@ s! {
     }
 
     pub struct stack_t {
         pub ss_sp: *mut ::c_void,
         pub ss_flags: ::c_int,
         pub ss_size: ::size_t
     }
 
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __unused1: ::c_long,
+        __unused2: ::c_long
+    }
+
     pub struct shmid_ds {
         pub shm_perm: ::ipc_perm,
         pub shm_segsz: ::size_t,
         pub shm_atime: ::time_t,
         __unused1: ::c_int,
         pub shm_dtime: ::time_t,
         __unused2: ::c_int,
         pub shm_ctime: ::time_t,
@@ -146,30 +158,103 @@ s! {
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; 19],
         pub c_ispeed: ::speed_t,
         pub c_ospeed: ::speed_t,
     }
 }
 
+pub const SIGSTKSZ: ::size_t = 8192;
+pub const MINSIGSTKSZ: ::size_t = 2048;
+
 pub const O_DIRECT: ::c_int = 0x10000;
 pub const O_DIRECTORY: ::c_int = 0x4000;
 pub const O_NOFOLLOW: ::c_int = 0x8000;
 pub const O_ASYNC: ::c_int = 0x2000;
 pub const O_LARGEFILE: ::c_int = 0o400000;
 
 pub const FIOCLEX: ::c_int = 0x5451;
 pub const FIONBIO: ::c_int = 0x5421;
 
 pub const RLIMIT_RSS: ::c_int = 5;
 pub const RLIMIT_NOFILE: ::c_int = 7;
 pub const RLIMIT_AS: ::c_int = 9;
 pub const RLIMIT_NPROC: ::c_int = 6;
 pub const RLIMIT_MEMLOCK: ::c_int = 8;
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
 
 pub const O_APPEND: ::c_int = 1024;
 pub const O_CREAT: ::c_int = 64;
 pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mips.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mips.rs
index 89231a0c7516..bfde73c563dc 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mips.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mips.rs
@@ -49,16 +49,28 @@ s! {
     }
 
     pub struct stack_t {
         pub ss_sp: *mut ::c_void,
         pub ss_size: ::size_t,
         pub ss_flags: ::c_int,
     }
 
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __unused1: ::c_long,
+        __unused2: ::c_long
+    }
+
     pub struct shmid_ds {
         pub shm_perm: ::ipc_perm,
         pub shm_segsz: ::size_t,
         pub shm_atime: ::time_t,
         pub shm_dtime: ::time_t,
         pub shm_ctime: ::time_t,
         pub shm_cpid: ::pid_t,
         pub shm_lpid: ::pid_t,
@@ -157,30 +169,103 @@ s! {
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; 23],
         pub c_ispeed: ::speed_t,
         pub c_ospeed: ::speed_t,
     }
 }
 
+pub const SIGSTKSZ: ::size_t = 8192;
+pub const MINSIGSTKSZ: ::size_t = 2048;
+
 pub const O_DIRECT: ::c_int = 0o100000;
 pub const O_DIRECTORY: ::c_int = 0o200000;
 pub const O_NOFOLLOW: ::c_int = 0o400000;
 pub const O_ASYNC: ::c_int = 0o10000;
 pub const O_LARGEFILE: ::c_int = 0x2000;
 
 pub const FIOCLEX: ::c_int = 0x6601;
 pub const FIONBIO: ::c_int = 0x667E;
 
 pub const RLIMIT_RSS: ::c_int = 7;
 pub const RLIMIT_NOFILE: ::c_int = 5;
 pub const RLIMIT_AS: ::c_int = 6;
 pub const RLIMIT_NPROC: ::c_int = 8;
 pub const RLIMIT_MEMLOCK: ::c_int = 9;
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
 
 pub const O_APPEND: ::c_int = 0o010;
 pub const O_CREAT: ::c_int = 0o400;
 pub const O_EXCL: ::c_int = 0o2000;
 pub const O_NOCTTY: ::c_int = 0o4000;
 pub const O_NONBLOCK: ::c_int = 0o200;
 pub const O_SYNC: ::c_int = 0o40020;
 pub const O_RSYNC: ::c_int = 0o40020;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mod.rs
index f6e19d981ddc..4128a8e4da6d 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/mod.rs
@@ -27,42 +27,36 @@ s! {
         pub cmsg_len: ::socklen_t,
         pub cmsg_level: ::c_int,
         pub cmsg_type: ::c_int,
     }
 
     pub struct sem_t {
         __val: [::c_int; 4],
     }
-
-    pub struct ipc_perm {
-        pub __ipc_perm_key: ::key_t,
-        pub uid: ::uid_t,
-        pub gid: ::gid_t,
-        pub cuid: ::uid_t,
-        pub cgid: ::gid_t,
-        pub mode: ::mode_t,
-        pub __seq: ::c_int,
-        __unused1: ::c_long,
-        __unused2: ::c_long
-    }
 }
 
-pub const SIGSTKSZ: ::size_t = 8192;
-pub const MINSIGSTKSZ: ::size_t = 2048;
-
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24;
 
+pub const TIOCINQ: ::c_int = ::FIONREAD;
+
+extern {
+    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+}
+
 cfg_if! {
     if #[cfg(any(target_arch = "x86"))] {
         mod x86;
         pub use self::x86::*;
     } else if #[cfg(any(target_arch = "mips"))] {
         mod mips;
         pub use self::mips::*;
     } else if #[cfg(any(target_arch = "arm"))] {
         mod arm;
         pub use self::arm::*;
+    } else if #[cfg(any(target_arch = "powerpc"))] {
+        mod powerpc;
+        pub use self::powerpc::*;
     } else {
         // Unknown target_arch
     }
 }
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/powerpc.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/powerpc.rs
new file mode 100644
index 000000000000..50b6b57ef11a
--- /dev/null
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/powerpc.rs
@@ -0,0 +1,866 @@
+pub type c_char = u8;
+pub type wchar_t = i32;
+
+s! {
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __st_rdev_padding: ::c_short,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_long; 2],
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::mode_t,
+        pub st_nlink: ::nlink_t,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __st_rdev_padding: ::c_short,
+        pub st_size: ::off_t,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::blkcnt_t,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_long,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_long,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_long,
+        __unused: [::c_long; 2],
+    }
+
+    pub struct stack_t {
+        pub ss_sp: *mut ::c_void,
+        pub ss_flags: ::c_int,
+        pub ss_size: ::size_t
+    }
+
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __pad1: ::c_int,
+        __pad2: ::c_longlong,
+        __pad3: ::c_longlong
+    }
+
+    pub struct shmid_ds {
+        pub shm_perm: ::ipc_perm,
+        __unused1: ::c_int,
+        pub shm_atime: ::time_t,
+        __unused2: ::c_int,
+        pub shm_dtime: ::time_t,
+        __unused3: ::c_int,
+        pub shm_ctime: ::time_t,
+        __unused4: ::c_int,
+        pub shm_segsz: ::size_t,
+        pub shm_cpid: ::pid_t,
+        pub shm_lpid: ::pid_t,
+        pub shm_nattch: ::c_ulong,
+        __pad1: ::c_ulong,
+        __pad2: ::c_ulong,
+    }
+
+    pub struct msqid_ds {
+        pub msg_perm: ::ipc_perm,
+        __unused1: ::c_int,
+        pub msg_stime: ::time_t,
+        __unused2: ::c_int,
+        pub msg_rtime: ::time_t,
+        __unused3: ::c_int,
+        pub msg_ctime: ::time_t,
+        __msg_cbytes: ::c_ulong,
+        pub msg_qnum: ::msgqnum_t,
+        pub msg_qbytes: ::msglen_t,
+        pub msg_lspid: ::pid_t,
+        pub msg_lrpid: ::pid_t,
+        __pad1: ::c_ulong,
+        __pad2: ::c_ulong,
+    }
+
+    pub struct statfs {
+        pub f_type: ::c_ulong,
+        pub f_bsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namelen: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_flags: ::c_ulong,
+        pub f_spare: [::c_ulong; 4],
+    }
+
+    pub struct siginfo_t {
+        pub si_signo: ::c_int,
+        pub si_errno: ::c_int,
+        pub si_code: ::c_int,
+        pub _pad: [::c_int; 29],
+        _align: [usize; 0],
+    }
+
+    pub struct statfs64 {
+        pub f_type: ::c_ulong,
+        pub f_bsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_fsid: ::fsid_t,
+        pub f_namelen: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_flags: ::c_ulong,
+        pub f_spare: [::c_ulong; 4],
+    }
+
+    pub struct statvfs64 {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: u64,
+        pub f_bfree: u64,
+        pub f_bavail: u64,
+        pub f_files: u64,
+        pub f_ffree: u64,
+        pub f_favail: u64,
+        #[cfg(target_endian = "little")]
+        pub f_fsid: ::c_ulong,
+        __f_unused: ::c_int,
+        #[cfg(target_endian = "big")]
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
+    pub struct termios2 {
+        pub c_iflag: ::tcflag_t,
+        pub c_oflag: ::tcflag_t,
+        pub c_cflag: ::tcflag_t,
+        pub c_lflag: ::tcflag_t,
+        pub c_cc: [::cc_t; 19],
+        pub c_line: ::cc_t,
+        pub c_ispeed: ::speed_t,
+        pub c_ospeed: ::speed_t,
+    }
+}
+
+pub const SIGSTKSZ: ::size_t = 10240;
+pub const MINSIGSTKSZ: ::size_t = 4096;
+
+pub const O_DIRECT: ::c_int = 0x20000;
+pub const O_DIRECTORY: ::c_int = 0x4000;
+pub const O_NOFOLLOW: ::c_int = 0x8000;
+pub const O_ASYNC: ::c_int = 0x2000;
+pub const O_LARGEFILE: ::c_int = 0x10000;
+
+pub const FIOCLEX: ::c_int = 0x20006601;
+pub const FIONBIO: ::c_int = 0x8004667E;
+
+pub const RLIMIT_RSS: ::c_int = 5;
+pub const RLIMIT_NOFILE: ::c_int = 7;
+pub const RLIMIT_AS: ::c_int = 9;
+pub const RLIMIT_NPROC: ::c_int = 6;
+pub const RLIMIT_MEMLOCK: ::c_int = 8;
+pub const RLIMIT_NLIMITS: ::c_int = 15;
+
+pub const MCL_CURRENT: ::c_int = 0x2000;
+pub const MCL_FUTURE: ::c_int = 0x4000;
+pub const CBAUD: ::tcflag_t = 0o0000377;
+pub const TAB1: ::c_int = 0x00000400;
+pub const TAB2: ::c_int = 0x00000800;
+pub const TAB3: ::c_int = 0x00000C00;
+pub const CR1: ::c_int  = 0x00001000;
+pub const CR2: ::c_int  = 0x00002000;
+pub const CR3: ::c_int  = 0x00003000;
+pub const FF1: ::c_int  = 0x00004000;
+pub const BS1: ::c_int  = 0x00008000;
+pub const VT1: ::c_int  = 0x00010000;
+pub const VWERASE: usize = 10;
+pub const VREPRINT: usize = 11;
+pub const VSUSP: usize = 12;
+pub const VSTART: usize = 13;
+pub const VSTOP: usize = 14;
+pub const VDISCARD: usize = 16;
+pub const VTIME: usize = 7;
+pub const IXON: ::tcflag_t = 0x00000200;
+pub const IXOFF: ::tcflag_t = 0x00000400;
+pub const ONLCR: ::tcflag_t = 0x00000002;
+pub const CSIZE: ::tcflag_t = 0x00000300;
+pub const CS6: ::tcflag_t = 0x00000100;
+pub const CS7: ::tcflag_t = 0x00000200;
+pub const CS8: ::tcflag_t = 0x00000300;
+pub const CSTOPB: ::tcflag_t = 0x00000400;
+pub const CREAD: ::tcflag_t = 0x00000800;
+pub const PARENB: ::tcflag_t = 0x00001000;
+pub const PARODD: ::tcflag_t = 0x00002000;
+pub const HUPCL: ::tcflag_t = 0x00004000;
+pub const CLOCAL: ::tcflag_t = 0x00008000;
+pub const ECHOKE: ::tcflag_t = 0x00000001;
+pub const ECHOE: ::tcflag_t = 0x00000002;
+pub const ECHOK: ::tcflag_t = 0x00000004;
+pub const ECHONL: ::tcflag_t = 0x00000010;
+pub const ECHOPRT: ::tcflag_t = 0x00000020;
+pub const ECHOCTL: ::tcflag_t = 0x00000040;
+pub const ISIG: ::tcflag_t = 0x00000080;
+pub const ICANON: ::tcflag_t = 0x00000100;
+pub const PENDIN: ::tcflag_t = 0x20000000;
+pub const NOFLSH: ::tcflag_t = 0x80000000;
+pub const CIBAUD: ::tcflag_t = 0o00077600000;
+pub const CBAUDEX: ::tcflag_t = 0o000020;
+pub const VSWTC: usize = 9;
+pub const OLCUC:  ::tcflag_t = 0o000004;
+pub const NLDLY:  ::tcflag_t = 0o001400;
+pub const CRDLY:  ::tcflag_t = 0o030000;
+pub const TABDLY: ::tcflag_t = 0o006000;
+pub const BSDLY:  ::tcflag_t = 0o100000;
+pub const FFDLY:  ::tcflag_t = 0o040000;
+pub const VTDLY:  ::tcflag_t = 0o200000;
+pub const XTABS:  ::tcflag_t = 0o006000;
+pub const B57600: ::speed_t = 0o000020;
+pub const B115200: ::speed_t = 0o000021;
+pub const B230400: ::speed_t = 0o000022;
+pub const B460800: ::speed_t = 0o000023;
+pub const B500000: ::speed_t = 0o000024;
+pub const B576000: ::speed_t = 0o000025;
+pub const B921600: ::speed_t = 0o000026;
+pub const B1000000: ::speed_t = 0o000027;
+pub const B1152000: ::speed_t = 0o000030;
+pub const B1500000: ::speed_t = 0o000031;
+pub const B2000000: ::speed_t = 0o000032;
+pub const B2500000: ::speed_t = 0o000033;
+pub const B3000000: ::speed_t = 0o000034;
+pub const B3500000: ::speed_t = 0o000035;
+pub const B4000000: ::speed_t = 0o000036;
+
+pub const O_APPEND: ::c_int = 1024;
+pub const O_CREAT: ::c_int = 64;
+pub const O_EXCL: ::c_int = 128;
+pub const O_NOCTTY: ::c_int = 256;
+pub const O_NONBLOCK: ::c_int = 2048;
+pub const O_SYNC: ::c_int = 1052672;
+pub const O_RSYNC: ::c_int = 1052672;
+pub const O_DSYNC: ::c_int = 4096;
+
+pub const SOCK_NONBLOCK: ::c_int = 2048;
+
+pub const MAP_ANON: ::c_int = 0x0020;
+pub const MAP_GROWSDOWN: ::c_int = 0x0100;
+pub const MAP_DENYWRITE: ::c_int = 0x0800;
+pub const MAP_EXECUTABLE: ::c_int = 0x01000;
+pub const MAP_LOCKED: ::c_int = 0x00080;
+pub const MAP_NORESERVE: ::c_int = 0x00040;
+pub const MAP_POPULATE: ::c_int = 0x08000;
+pub const MAP_NONBLOCK: ::c_int = 0x010000;
+pub const MAP_STACK: ::c_int = 0x020000;
+
+pub const SOCK_STREAM: ::c_int = 1;
+pub const SOCK_DGRAM: ::c_int = 2;
+pub const SOCK_SEQPACKET: ::c_int = 5;
+
+pub const SOL_SOCKET: ::c_int = 1;
+
+pub const EDEADLK: ::c_int = 35;
+pub const ENAMETOOLONG: ::c_int = 36;
+pub const ENOLCK: ::c_int = 37;
+pub const ENOSYS: ::c_int = 38;
+pub const ENOTEMPTY: ::c_int = 39;
+pub const ELOOP: ::c_int = 40;
+pub const ENOMSG: ::c_int = 42;
+pub const EIDRM: ::c_int = 43;
+pub const ECHRNG: ::c_int = 44;
+pub const EL2NSYNC: ::c_int = 45;
+pub const EL3HLT: ::c_int = 46;
+pub const EL3RST: ::c_int = 47;
+pub const ELNRNG: ::c_int = 48;
+pub const EUNATCH: ::c_int = 49;
+pub const ENOCSI: ::c_int = 50;
+pub const EL2HLT: ::c_int = 51;
+pub const EBADE: ::c_int = 52;
+pub const EBADR: ::c_int = 53;
+pub const EXFULL: ::c_int = 54;
+pub const ENOANO: ::c_int = 55;
+pub const EBADRQC: ::c_int = 56;
+pub const EBADSLT: ::c_int = 57;
+pub const EDEADLOCK: ::c_int = 58;
+pub const EMULTIHOP: ::c_int = 72;
+pub const EBADMSG: ::c_int = 74;
+pub const EOVERFLOW: ::c_int = 75;
+pub const ENOTUNIQ: ::c_int = 76;
+pub const EBADFD: ::c_int = 77;
+pub const EREMCHG: ::c_int = 78;
+pub const ELIBACC: ::c_int = 79;
+pub const ELIBBAD: ::c_int = 80;
+pub const ELIBSCN: ::c_int = 81;
+pub const ELIBMAX: ::c_int = 82;
+pub const ELIBEXEC: ::c_int = 83;
+pub const EILSEQ: ::c_int = 84;
+pub const ERESTART: ::c_int = 85;
+pub const ESTRPIPE: ::c_int = 86;
+pub const EUSERS: ::c_int = 87;
+pub const ENOTSOCK: ::c_int = 88;
+pub const EDESTADDRREQ: ::c_int = 89;
+pub const EMSGSIZE: ::c_int = 90;
+pub const EPROTOTYPE: ::c_int = 91;
+pub const ENOPROTOOPT: ::c_int = 92;
+pub const EPROTONOSUPPORT: ::c_int = 93;
+pub const ESOCKTNOSUPPORT: ::c_int = 94;
+pub const EOPNOTSUPP: ::c_int = 95;
+pub const ENOTSUP: ::c_int = EOPNOTSUPP;
+pub const EPFNOSUPPORT: ::c_int = 96;
+pub const EAFNOSUPPORT: ::c_int = 97;
+pub const EADDRINUSE: ::c_int = 98;
+pub const EADDRNOTAVAIL: ::c_int = 99;
+pub const ENETDOWN: ::c_int = 100;
+pub const ENETUNREACH: ::c_int = 101;
+pub const ENETRESET: ::c_int = 102;
+pub const ECONNABORTED: ::c_int = 103;
+pub const ECONNRESET: ::c_int = 104;
+pub const ENOBUFS: ::c_int = 105;
+pub const EISCONN: ::c_int = 106;
+pub const ENOTCONN: ::c_int = 107;
+pub const ESHUTDOWN: ::c_int = 108;
+pub const ETOOMANYREFS: ::c_int = 109;
+pub const ETIMEDOUT: ::c_int = 110;
+pub const ECONNREFUSED: ::c_int = 111;
+pub const EHOSTDOWN: ::c_int = 112;
+pub const EHOSTUNREACH: ::c_int = 113;
+pub const EALREADY: ::c_int = 114;
+pub const EINPROGRESS: ::c_int = 115;
+pub const ESTALE: ::c_int = 116;
+pub const EUCLEAN: ::c_int = 117;
+pub const ENOTNAM: ::c_int = 118;
+pub const ENAVAIL: ::c_int = 119;
+pub const EISNAM: ::c_int = 120;
+pub const EREMOTEIO: ::c_int = 121;
+pub const EDQUOT: ::c_int = 122;
+pub const ENOMEDIUM: ::c_int = 123;
+pub const EMEDIUMTYPE: ::c_int = 124;
+pub const ECANCELED: ::c_int = 125;
+pub const ENOKEY: ::c_int = 126;
+pub const EKEYEXPIRED: ::c_int = 127;
+pub const EKEYREVOKED: ::c_int = 128;
+pub const EKEYREJECTED: ::c_int = 129;
+pub const EOWNERDEAD: ::c_int = 130;
+pub const ENOTRECOVERABLE: ::c_int = 131;
+pub const ERFKILL: ::c_int = 132;
+pub const EHWPOISON: ::c_int = 133;
+
+pub const SO_REUSEADDR: ::c_int = 2;
+pub const SO_TYPE: ::c_int = 3;
+pub const SO_ERROR: ::c_int = 4;
+pub const SO_DONTROUTE: ::c_int = 5;
+pub const SO_BROADCAST: ::c_int = 6;
+pub const SO_SNDBUF: ::c_int = 7;
+pub const SO_RCVBUF: ::c_int = 8;
+pub const SO_KEEPALIVE: ::c_int = 9;
+pub const SO_OOBINLINE: ::c_int = 10;
+pub const SO_NO_CHECK: ::c_int = 11;
+pub const SO_PRIORITY: ::c_int = 12;
+pub const SO_LINGER: ::c_int = 13;
+pub const SO_BSDCOMPAT: ::c_int = 14;
+pub const SO_REUSEPORT: ::c_int = 15;
+pub const SO_RCVLOWAT: ::c_int = 16;
+pub const SO_SNDLOWAT: ::c_int = 17;
+pub const SO_RCVTIMEO: ::c_int = 18;
+pub const SO_SNDTIMEO: ::c_int = 19;
+pub const SO_PASSCRED: ::c_int = 20;
+pub const SO_PEERCRED: ::c_int = 21;
+pub const SO_ACCEPTCONN: ::c_int = 30;
+pub const SO_SNDBUFFORCE: ::c_int = 32;
+pub const SO_RCVBUFFORCE: ::c_int = 33;
+pub const SO_PROTOCOL: ::c_int = 38;
+pub const SO_DOMAIN: ::c_int = 39;
+
+pub const SA_ONSTACK: ::c_int = 0x08000000;
+pub const SA_SIGINFO: ::c_int = 0x00000004;
+pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
+
+pub const SIGCHLD: ::c_int = 17;
+pub const SIGBUS: ::c_int = 7;
+pub const SIGTTIN: ::c_int = 21;
+pub const SIGTTOU: ::c_int = 22;
+pub const SIGXCPU: ::c_int = 24;
+pub const SIGXFSZ: ::c_int = 25;
+pub const SIGVTALRM: ::c_int = 26;
+pub const SIGPROF: ::c_int = 27;
+pub const SIGWINCH: ::c_int = 28;
+pub const SIGUSR1: ::c_int = 10;
+pub const SIGUSR2: ::c_int = 12;
+pub const SIGCONT: ::c_int = 18;
+pub const SIGSTOP: ::c_int = 19;
+pub const SIGTSTP: ::c_int = 20;
+pub const SIGURG: ::c_int = 23;
+pub const SIGIO: ::c_int = 29;
+pub const SIGSYS: ::c_int = 31;
+pub const SIGSTKFLT: ::c_int = 16;
+pub const SIGPOLL: ::c_int = 29;
+pub const SIGPWR: ::c_int = 30;
+pub const SIG_SETMASK: ::c_int = 2;
+pub const SIG_BLOCK: ::c_int = 0x000000;
+pub const SIG_UNBLOCK: ::c_int = 0x01;
+
+pub const EXTPROC: ::tcflag_t = 0x10000000;
+
+pub const MAP_HUGETLB: ::c_int = 0x040000;
+
+pub const F_GETLK: ::c_int = 12;
+pub const F_GETOWN: ::c_int = 9;
+pub const F_SETLK: ::c_int = 13;
+pub const F_SETLKW: ::c_int = 14;
+pub const F_SETOWN: ::c_int = 8;
+
+pub const VEOF: usize = 4;
+pub const VEOL: usize = 6;
+pub const VEOL2: usize = 8;
+pub const VMIN: usize = 5;
+pub const IEXTEN: ::tcflag_t = 0x00000400;
+pub const TOSTOP: ::tcflag_t = 0x00400000;
+pub const FLUSHO: ::tcflag_t = 0x00800000;
+
+pub const TCGETS: ::c_int = 0x402C7413;
+pub const TCSETS: ::c_int = 0x802C7414;
+pub const TCSETSW: ::c_int = 0x802C7415;
+pub const TCSETSF: ::c_int = 0x802C7416;
+pub const TCGETA: ::c_int = 0x40147417;
+pub const TCSETA: ::c_int = 0x80147418;
+pub const TCSETAW: ::c_int = 0x80147419;
+pub const TCSETAF: ::c_int = 0x8014741C;
+pub const TCSBRK: ::c_int = 0x2000741D;
+pub const TCXONC: ::c_int = 0x2000741E;
+pub const TCFLSH: ::c_int = 0x2000741F;
+pub const TIOCGSOFTCAR: ::c_int = 0x5419;
+pub const TIOCSSOFTCAR: ::c_int = 0x541A;
+pub const TIOCLINUX: ::c_int = 0x541C;
+pub const TIOCGSERIAL: ::c_int = 0x541E;
+pub const TIOCEXCL: ::c_int = 0x540C;
+pub const TIOCNXCL: ::c_int = 0x540D;
+pub const TIOCSCTTY: ::c_int = 0x540E;
+pub const TIOCGPGRP: ::c_int = 0x40047477;
+pub const TIOCSPGRP: ::c_int = 0x80047476;
+pub const TIOCOUTQ: ::c_int = 0x40047473;
+pub const TIOCSTI: ::c_int = 0x5412;
+pub const TIOCGWINSZ: ::c_int = 0x40087468;
+pub const TIOCSWINSZ: ::c_int = 0x80087467;
+pub const TIOCMGET: ::c_int = 0x5415;
+pub const TIOCMBIS: ::c_int = 0x5416;
+pub const TIOCMBIC: ::c_int = 0x5417;
+pub const TIOCMSET: ::c_int = 0x5418;
+pub const FIONREAD: ::c_int = 0x4004667F;
+pub const TIOCCONS: ::c_int = 0x541D;
+
+pub const POLLWRNORM: ::c_short = 0x100;
+pub const POLLWRBAND: ::c_short = 0x200;
+
+pub const TIOCM_LE: ::c_int = 0x001;
+pub const TIOCM_DTR: ::c_int = 0x002;
+pub const TIOCM_RTS: ::c_int = 0x004;
+pub const TIOCM_ST: ::c_int = 0x008;
+pub const TIOCM_SR: ::c_int = 0x010;
+pub const TIOCM_CTS: ::c_int = 0x020;
+pub const TIOCM_CAR: ::c_int = 0x040;
+pub const TIOCM_RNG: ::c_int = 0x080;
+pub const TIOCM_DSR: ::c_int = 0x100;
+pub const TIOCM_CD: ::c_int = TIOCM_CAR;
+pub const TIOCM_RI: ::c_int = TIOCM_RNG;
+
+// Syscall table
+pub const SYS_restart_syscall: ::c_long = 0;
+pub const SYS_exit: ::c_long = 1;
+pub const SYS_fork: ::c_long = 2;
+pub const SYS_read: ::c_long = 3;
+pub const SYS_write: ::c_long = 4;
+pub const SYS_open: ::c_long = 5;
+pub const SYS_close: ::c_long = 6;
+pub const SYS_waitpid: ::c_long = 7;
+pub const SYS_creat: ::c_long = 8;
+pub const SYS_link: ::c_long = 9;
+pub const SYS_unlink: ::c_long = 10;
+pub const SYS_execve: ::c_long = 11;
+pub const SYS_chdir: ::c_long = 12;
+pub const SYS_time: ::c_long = 13;
+pub const SYS_mknod: ::c_long = 14;
+pub const SYS_chmod: ::c_long = 15;
+pub const SYS_lchown: ::c_long = 16;
+pub const SYS_break: ::c_long = 17;
+pub const SYS_oldstat: ::c_long = 18;
+pub const SYS_lseek: ::c_long = 19;
+pub const SYS_getpid: ::c_long = 20;
+pub const SYS_mount: ::c_long = 21;
+pub const SYS_umount: ::c_long = 22;
+pub const SYS_setuid: ::c_long = 23;
+pub const SYS_getuid: ::c_long = 24;
+pub const SYS_stime: ::c_long = 25;
+pub const SYS_ptrace: ::c_long = 26;
+pub const SYS_alarm: ::c_long = 27;
+pub const SYS_oldfstat: ::c_long = 28;
+pub const SYS_pause: ::c_long = 29;
+pub const SYS_utime: ::c_long = 30;
+pub const SYS_stty: ::c_long = 31;
+pub const SYS_gtty: ::c_long = 32;
+pub const SYS_access: ::c_long = 33;
+pub const SYS_nice: ::c_long = 34;
+pub const SYS_ftime: ::c_long = 35;
+pub const SYS_sync: ::c_long = 36;
+pub const SYS_kill: ::c_long = 37;
+pub const SYS_rename: ::c_long = 38;
+pub const SYS_mkdir: ::c_long = 39;
+pub const SYS_rmdir: ::c_long = 40;
+pub const SYS_dup: ::c_long = 41;
+pub const SYS_pipe: ::c_long = 42;
+pub const SYS_times: ::c_long = 43;
+pub const SYS_prof: ::c_long = 44;
+pub const SYS_brk: ::c_long = 45;
+pub const SYS_setgid: ::c_long = 46;
+pub const SYS_getgid: ::c_long = 47;
+pub const SYS_signal: ::c_long = 48;
+pub const SYS_geteuid: ::c_long = 49;
+pub const SYS_getegid: ::c_long = 50;
+pub const SYS_acct: ::c_long = 51;
+pub const SYS_umount2: ::c_long = 52;
+pub const SYS_lock: ::c_long = 53;
+pub const SYS_ioctl: ::c_long = 54;
+pub const SYS_fcntl: ::c_long = 55;
+pub const SYS_mpx: ::c_long = 56;
+pub const SYS_setpgid: ::c_long = 57;
+pub const SYS_ulimit: ::c_long = 58;
+pub const SYS_oldolduname: ::c_long = 59;
+pub const SYS_umask: ::c_long = 60;
+pub const SYS_chroot: ::c_long = 61;
+pub const SYS_ustat: ::c_long = 62;
+pub const SYS_dup2: ::c_long = 63;
+pub const SYS_getppid: ::c_long = 64;
+pub const SYS_getpgrp: ::c_long = 65;
+pub const SYS_setsid: ::c_long = 66;
+pub const SYS_sigaction: ::c_long = 67;
+pub const SYS_sgetmask: ::c_long = 68;
+pub const SYS_ssetmask: ::c_long = 69;
+pub const SYS_setreuid: ::c_long = 70;
+pub const SYS_setregid: ::c_long = 71;
+pub const SYS_sigsuspend: ::c_long = 72;
+pub const SYS_sigpending: ::c_long = 73;
+pub const SYS_sethostname: ::c_long = 74;
+pub const SYS_setrlimit: ::c_long = 75;
+pub const SYS_getrlimit: ::c_long = 76;
+pub const SYS_getrusage: ::c_long = 77;
+pub const SYS_gettimeofday: ::c_long = 78;
+pub const SYS_settimeofday: ::c_long = 79;
+pub const SYS_getgroups: ::c_long = 80;
+pub const SYS_setgroups: ::c_long = 81;
+pub const SYS_select: ::c_long = 82;
+pub const SYS_symlink: ::c_long = 83;
+pub const SYS_oldlstat: ::c_long = 84;
+pub const SYS_readlink: ::c_long = 85;
+pub const SYS_uselib: ::c_long = 86;
+pub const SYS_swapon: ::c_long = 87;
+pub const SYS_reboot: ::c_long = 88;
+pub const SYS_readdir: ::c_long = 89;
+pub const SYS_mmap: ::c_long = 90;
+pub const SYS_munmap: ::c_long = 91;
+pub const SYS_truncate: ::c_long = 92;
+pub const SYS_ftruncate: ::c_long = 93;
+pub const SYS_fchmod: ::c_long = 94;
+pub const SYS_fchown: ::c_long = 95;
+pub const SYS_getpriority: ::c_long = 96;
+pub const SYS_setpriority: ::c_long = 97;
+pub const SYS_profil: ::c_long = 98;
+pub const SYS_statfs: ::c_long = 99;
+pub const SYS_fstatfs: ::c_long = 100;
+pub const SYS_ioperm: ::c_long = 101;
+pub const SYS_socketcall: ::c_long = 102;
+pub const SYS_syslog: ::c_long = 103;
+pub const SYS_setitimer: ::c_long = 104;
+pub const SYS_getitimer: ::c_long = 105;
+pub const SYS_stat: ::c_long = 106;
+pub const SYS_lstat: ::c_long = 107;
+pub const SYS_fstat: ::c_long = 108;
+pub const SYS_olduname: ::c_long = 109;
+pub const SYS_iopl: ::c_long = 110;
+pub const SYS_vhangup: ::c_long = 111;
+pub const SYS_idle: ::c_long = 112;
+pub const SYS_vm86: ::c_long = 113;
+pub const SYS_wait4: ::c_long = 114;
+pub const SYS_swapoff: ::c_long = 115;
+pub const SYS_sysinfo: ::c_long = 116;
+pub const SYS_ipc: ::c_long = 117;
+pub const SYS_fsync: ::c_long = 118;
+pub const SYS_sigreturn: ::c_long = 119;
+pub const SYS_clone: ::c_long = 120;
+pub const SYS_setdomainname: ::c_long = 121;
+pub const SYS_uname: ::c_long = 122;
+pub const SYS_modify_ldt: ::c_long = 123;
+pub const SYS_adjtimex: ::c_long = 124;
+pub const SYS_mprotect: ::c_long = 125;
+pub const SYS_sigprocmask: ::c_long = 126;
+pub const SYS_create_module: ::c_long = 127;
+pub const SYS_init_module: ::c_long = 128;
+pub const SYS_delete_module: ::c_long = 129;
+pub const SYS_get_kernel_syms: ::c_long = 130;
+pub const SYS_quotactl: ::c_long = 131;
+pub const SYS_getpgid: ::c_long = 132;
+pub const SYS_fchdir: ::c_long = 133;
+pub const SYS_bdflush: ::c_long = 134;
+pub const SYS_sysfs: ::c_long = 135;
+pub const SYS_personality: ::c_long = 136;
+pub const SYS_afs_syscall: ::c_long = 137;
+pub const SYS_setfsuid: ::c_long = 138;
+pub const SYS_setfsgid: ::c_long = 139;
+pub const SYS__llseek: ::c_long = 140;
+pub const SYS_getdents: ::c_long = 141;
+pub const SYS__newselect: ::c_long = 142;
+pub const SYS_flock: ::c_long = 143;
+pub const SYS_msync: ::c_long = 144;
+pub const SYS_readv: ::c_long = 145;
+pub const SYS_writev: ::c_long = 146;
+pub const SYS_getsid: ::c_long = 147;
+pub const SYS_fdatasync: ::c_long = 148;
+pub const SYS__sysctl: ::c_long = 149;
+pub const SYS_mlock: ::c_long = 150;
+pub const SYS_munlock: ::c_long = 151;
+pub const SYS_mlockall: ::c_long = 152;
+pub const SYS_munlockall: ::c_long = 153;
+pub const SYS_sched_setparam: ::c_long = 154;
+pub const SYS_sched_getparam: ::c_long = 155;
+pub const SYS_sched_setscheduler: ::c_long = 156;
+pub const SYS_sched_getscheduler: ::c_long = 157;
+pub const SYS_sched_yield: ::c_long = 158;
+pub const SYS_sched_get_priority_max: ::c_long = 159;
+pub const SYS_sched_get_priority_min: ::c_long = 160;
+pub const SYS_sched_rr_get_interval: ::c_long = 161;
+pub const SYS_nanosleep: ::c_long = 162;
+pub const SYS_mremap: ::c_long = 163;
+pub const SYS_setresuid: ::c_long = 164;
+pub const SYS_getresuid: ::c_long = 165;
+pub const SYS_query_module: ::c_long = 166;
+pub const SYS_poll: ::c_long = 167;
+pub const SYS_nfsservctl: ::c_long = 168;
+pub const SYS_setresgid: ::c_long = 169;
+pub const SYS_getresgid: ::c_long = 170;
+pub const SYS_prctl: ::c_long = 171;
+pub const SYS_rt_sigreturn: ::c_long = 172;
+pub const SYS_rt_sigaction: ::c_long = 173;
+pub const SYS_rt_sigprocmask: ::c_long = 174;
+pub const SYS_rt_sigpending: ::c_long = 175;
+pub const SYS_rt_sigtimedwait: ::c_long = 176;
+pub const SYS_rt_sigqueueinfo: ::c_long = 177;
+pub const SYS_rt_sigsuspend: ::c_long = 178;
+pub const SYS_pread64: ::c_long = 179;
+pub const SYS_pwrite64: ::c_long = 180;
+pub const SYS_chown: ::c_long = 181;
+pub const SYS_getcwd: ::c_long = 182;
+pub const SYS_capget: ::c_long = 183;
+pub const SYS_capset: ::c_long = 184;
+pub const SYS_sigaltstack: ::c_long = 185;
+pub const SYS_sendfile: ::c_long = 186;
+pub const SYS_getpmsg: ::c_long = 187;
+pub const SYS_putpmsg: ::c_long = 188;
+pub const SYS_vfork: ::c_long = 189;
+pub const SYS_ugetrlimit: ::c_long = 190;
+pub const SYS_readahead: ::c_long = 191;
+pub const SYS_mmap2: ::c_long = 192;
+pub const SYS_truncate64: ::c_long = 193;
+pub const SYS_ftruncate64: ::c_long = 194;
+pub const SYS_stat64: ::c_long = 195;
+pub const SYS_lstat64: ::c_long = 196;
+pub const SYS_fstat64: ::c_long = 197;
+pub const SYS_pciconfig_read: ::c_long = 198;
+pub const SYS_pciconfig_write: ::c_long = 199;
+pub const SYS_pciconfig_iobase: ::c_long = 200;
+pub const SYS_multiplexer: ::c_long = 201;
+pub const SYS_getdents64: ::c_long = 202;
+pub const SYS_pivot_root: ::c_long = 203;
+pub const SYS_fcntl64: ::c_long = 204;
+pub const SYS_madvise: ::c_long = 205;
+pub const SYS_mincore: ::c_long = 206;
+pub const SYS_gettid: ::c_long = 207;
+pub const SYS_tkill: ::c_long = 208;
+pub const SYS_setxattr: ::c_long = 209;
+pub const SYS_lsetxattr: ::c_long = 210;
+pub const SYS_fsetxattr: ::c_long = 211;
+pub const SYS_getxattr: ::c_long = 212;
+pub const SYS_lgetxattr: ::c_long = 213;
+pub const SYS_fgetxattr: ::c_long = 214;
+pub const SYS_listxattr: ::c_long = 215;
+pub const SYS_llistxattr: ::c_long = 216;
+pub const SYS_flistxattr: ::c_long = 217;
+pub const SYS_removexattr: ::c_long = 218;
+pub const SYS_lremovexattr: ::c_long = 219;
+pub const SYS_fremovexattr: ::c_long = 220;
+pub const SYS_futex: ::c_long = 221;
+pub const SYS_sched_setaffinity: ::c_long = 222;
+pub const SYS_sched_getaffinity: ::c_long = 223;
+pub const SYS_tuxcall: ::c_long = 225;
+pub const SYS_sendfile64: ::c_long = 226;
+pub const SYS_io_setup: ::c_long = 227;
+pub const SYS_io_destroy: ::c_long = 228;
+pub const SYS_io_getevents: ::c_long = 229;
+pub const SYS_io_submit: ::c_long = 230;
+pub const SYS_io_cancel: ::c_long = 231;
+pub const SYS_set_tid_address: ::c_long = 232;
+pub const SYS_fadvise64: ::c_long = 233;
+pub const SYS_exit_group: ::c_long = 234;
+pub const SYS_lookup_dcookie: ::c_long = 235;
+pub const SYS_epoll_create: ::c_long = 236;
+pub const SYS_epoll_ctl: ::c_long = 237;
+pub const SYS_epoll_wait: ::c_long = 238;
+pub const SYS_remap_file_pages: ::c_long = 239;
+pub const SYS_timer_create: ::c_long = 240;
+pub const SYS_timer_settime: ::c_long = 241;
+pub const SYS_timer_gettime: ::c_long = 242;
+pub const SYS_timer_getoverrun: ::c_long = 243;
+pub const SYS_timer_delete: ::c_long = 244;
+pub const SYS_clock_settime: ::c_long = 245;
+pub const SYS_clock_gettime: ::c_long = 246;
+pub const SYS_clock_getres: ::c_long = 247;
+pub const SYS_clock_nanosleep: ::c_long = 248;
+pub const SYS_swapcontext: ::c_long = 249;
+pub const SYS_tgkill: ::c_long = 250;
+pub const SYS_utimes: ::c_long = 251;
+pub const SYS_statfs64: ::c_long = 252;
+pub const SYS_fstatfs64: ::c_long = 253;
+pub const SYS_fadvise64_64: ::c_long = 254;
+pub const SYS_rtas: ::c_long = 255;
+pub const SYS_sys_debug_setcontext: ::c_long = 256;
+pub const SYS_migrate_pages: ::c_long = 258;
+pub const SYS_mbind: ::c_long = 259;
+pub const SYS_get_mempolicy: ::c_long = 260;
+pub const SYS_set_mempolicy: ::c_long = 261;
+pub const SYS_mq_open: ::c_long = 262;
+pub const SYS_mq_unlink: ::c_long = 263;
+pub const SYS_mq_timedsend: ::c_long = 264;
+pub const SYS_mq_timedreceive: ::c_long = 265;
+pub const SYS_mq_notify: ::c_long = 266;
+pub const SYS_mq_getsetattr: ::c_long = 267;
+pub const SYS_kexec_load: ::c_long = 268;
+pub const SYS_add_key: ::c_long = 269;
+pub const SYS_request_key: ::c_long = 270;
+pub const SYS_keyctl: ::c_long = 271;
+pub const SYS_waitid: ::c_long = 272;
+pub const SYS_ioprio_set: ::c_long = 273;
+pub const SYS_ioprio_get: ::c_long = 274;
+pub const SYS_inotify_init: ::c_long = 275;
+pub const SYS_inotify_add_watch: ::c_long = 276;
+pub const SYS_inotify_rm_watch: ::c_long = 277;
+pub const SYS_spu_run: ::c_long = 278;
+pub const SYS_spu_create: ::c_long = 279;
+pub const SYS_pselect6: ::c_long = 280;
+pub const SYS_ppoll: ::c_long = 281;
+pub const SYS_unshare: ::c_long = 282;
+pub const SYS_splice: ::c_long = 283;
+pub const SYS_tee: ::c_long = 284;
+pub const SYS_vmsplice: ::c_long = 285;
+pub const SYS_openat: ::c_long = 286;
+pub const SYS_mkdirat: ::c_long = 287;
+pub const SYS_mknodat: ::c_long = 288;
+pub const SYS_fchownat: ::c_long = 289;
+pub const SYS_futimesat: ::c_long = 290;
+pub const SYS_fstatat64: ::c_long = 291;
+pub const SYS_unlinkat: ::c_long = 292;
+pub const SYS_renameat: ::c_long = 293;
+pub const SYS_linkat: ::c_long = 294;
+pub const SYS_symlinkat: ::c_long = 295;
+pub const SYS_readlinkat: ::c_long = 296;
+pub const SYS_fchmodat: ::c_long = 297;
+pub const SYS_faccessat: ::c_long = 298;
+pub const SYS_get_robust_list: ::c_long = 299;
+pub const SYS_set_robust_list: ::c_long = 300;
+pub const SYS_move_pages: ::c_long = 301;
+pub const SYS_getcpu: ::c_long = 302;
+pub const SYS_epoll_pwait: ::c_long = 303;
+pub const SYS_utimensat: ::c_long = 304;
+pub const SYS_signalfd: ::c_long = 305;
+pub const SYS_timerfd_create: ::c_long = 306;
+pub const SYS_eventfd: ::c_long = 307;
+pub const SYS_sync_file_range2: ::c_long = 308;
+pub const SYS_fallocate: ::c_long = 309;
+pub const SYS_subpage_prot: ::c_long = 310;
+pub const SYS_timerfd_settime: ::c_long = 311;
+pub const SYS_timerfd_gettime: ::c_long = 312;
+pub const SYS_signalfd4: ::c_long = 313;
+pub const SYS_eventfd2: ::c_long = 314;
+pub const SYS_epoll_create1: ::c_long = 315;
+pub const SYS_dup3: ::c_long = 316;
+pub const SYS_pipe2: ::c_long = 317;
+pub const SYS_inotify_init1: ::c_long = 318;
+pub const SYS_perf_event_open: ::c_long = 319;
+pub const SYS_preadv: ::c_long = 320;
+pub const SYS_pwritev: ::c_long = 321;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 322;
+pub const SYS_fanotify_init: ::c_long = 323;
+pub const SYS_fanotify_mark: ::c_long = 324;
+pub const SYS_prlimit64: ::c_long = 325;
+pub const SYS_socket: ::c_long = 326;
+pub const SYS_bind: ::c_long = 327;
+pub const SYS_connect: ::c_long = 328;
+pub const SYS_listen: ::c_long = 329;
+pub const SYS_accept: ::c_long = 330;
+pub const SYS_getsockname: ::c_long = 331;
+pub const SYS_getpeername: ::c_long = 332;
+pub const SYS_socketpair: ::c_long = 333;
+pub const SYS_send: ::c_long = 334;
+pub const SYS_sendto: ::c_long = 335;
+pub const SYS_recv: ::c_long = 336;
+pub const SYS_recvfrom: ::c_long = 337;
+pub const SYS_shutdown: ::c_long = 338;
+pub const SYS_setsockopt: ::c_long = 339;
+pub const SYS_getsockopt: ::c_long = 340;
+pub const SYS_sendmsg: ::c_long = 341;
+pub const SYS_recvmsg: ::c_long = 342;
+pub const SYS_recvmmsg: ::c_long = 343;
+pub const SYS_accept4: ::c_long = 344;
+pub const SYS_name_to_handle_at: ::c_long = 345;
+pub const SYS_open_by_handle_at: ::c_long = 346;
+pub const SYS_clock_adjtime: ::c_long = 347;
+pub const SYS_syncfs: ::c_long = 348;
+pub const SYS_sendmmsg: ::c_long = 349;
+pub const SYS_setns: ::c_long = 350;
+pub const SYS_process_vm_readv: ::c_long = 351;
+pub const SYS_process_vm_writev: ::c_long = 352;
+pub const SYS_finit_module: ::c_long = 353;
+pub const SYS_kcmp: ::c_long = 354;
+pub const SYS_sched_setattr: ::c_long = 355;
+pub const SYS_sched_getattr: ::c_long = 356;
+pub const SYS_renameat2: ::c_long = 357;
+pub const SYS_seccomp: ::c_long = 358;
+pub const SYS_getrandom: ::c_long = 359;
+pub const SYS_memfd_create: ::c_long = 360;
+pub const SYS_bpf: ::c_long = 361;
+pub const SYS_execveat: ::c_long = 362;
+pub const SYS_switch_endian: ::c_long = 363;
+pub const SYS_userfaultfd: ::c_long = 364;
+pub const SYS_membarrier: ::c_long = 365;
+pub const SYS_mlock2: ::c_long = 378;
+pub const SYS_copy_file_range: ::c_long = 379;
+pub const SYS_preadv2: ::c_long = 380;
+pub const SYS_pwritev2: ::c_long = 381;
+pub const SYS_kexec_file_load: ::c_long = 382;
+pub const SYS_statx: ::c_long = 383;
+pub const SYS_pkey_alloc: ::c_long = 384;
+pub const SYS_pkey_free: ::c_long = 385;
+pub const SYS_pkey_mprotect: ::c_long = 386;
+
+#[doc(hidden)]
+pub const AF_MAX: ::c_int = 43;
+#[doc(hidden)]
+pub const PF_MAX: ::c_int = AF_MAX;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/x86.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/x86.rs
index fa570248c729..9f704c7fac9c 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/x86.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b32/x86.rs
@@ -47,16 +47,28 @@ s! {
     }
 
     pub struct stack_t {
         pub ss_sp: *mut ::c_void,
         pub ss_flags: ::c_int,
         pub ss_size: ::size_t
     }
 
+    pub struct ipc_perm {
+        pub __ipc_perm_key: ::key_t,
+        pub uid: ::uid_t,
+        pub gid: ::gid_t,
+        pub cuid: ::uid_t,
+        pub cgid: ::gid_t,
+        pub mode: ::mode_t,
+        pub __seq: ::c_int,
+        __unused1: ::c_long,
+        __unused2: ::c_long
+    }
+
     pub struct shmid_ds {
         pub shm_perm: ::ipc_perm,
         pub shm_segsz: ::size_t,
         pub shm_atime: ::time_t,
         __unused1: ::c_int,
         pub shm_dtime: ::time_t,
         __unused2: ::c_int,
         pub shm_ctime: ::time_t,
@@ -159,30 +171,103 @@ s! {
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; 19],
         pub c_ispeed: ::speed_t,
         pub c_ospeed: ::speed_t,
     }
 }
 
+pub const SIGSTKSZ: ::size_t = 8192;
+pub const MINSIGSTKSZ: ::size_t = 2048;
+
 pub const O_DIRECT: ::c_int = 0x4000;
 pub const O_DIRECTORY: ::c_int = 0x10000;
 pub const O_NOFOLLOW: ::c_int = 0x20000;
 pub const O_ASYNC: ::c_int = 0x2000;
 pub const O_LARGEFILE: ::c_int = 0o0100000;
 
 pub const FIOCLEX: ::c_int = 0x5451;
 pub const FIONBIO: ::c_int = 0x5421;
 
 pub const RLIMIT_RSS: ::c_int = 5;
 pub const RLIMIT_NOFILE: ::c_int = 7;
 pub const RLIMIT_AS: ::c_int = 9;
 pub const RLIMIT_NPROC: ::c_int = 6;
 pub const RLIMIT_MEMLOCK: ::c_int = 8;
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
 
 pub const O_APPEND: ::c_int = 1024;
 pub const O_CREAT: ::c_int = 64;
 pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs
index da0827a7750a..98c53dc4f2b1 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/aarch64.rs
@@ -334,8 +334,143 @@ pub const SYS_userfaultfd: ::c_long = 282;
 pub const SYS_membarrier: ::c_long = 283;
 pub const SYS_mlock2: ::c_long = 284;
 pub const SYS_copy_file_range: ::c_long = 285;
 pub const SYS_preadv2: ::c_long = 286;
 pub const SYS_pwritev2: ::c_long = 287;
 pub const SYS_pkey_mprotect: ::c_long = 288;
 pub const SYS_pkey_alloc: ::c_long = 289;
 pub const SYS_pkey_free: ::c_long = 290;
+
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+pub const TIOCINQ: ::c_int = ::FIONREAD;
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
+
+pub const FIOCLEX: ::c_int = 0x5451;
+pub const FIONBIO: ::c_int = 0x5421;
+pub const EDEADLK: ::c_int = 35;
+pub const EDEADLOCK: ::c_int = EDEADLK;
+pub const SO_PASSCRED: ::c_int = 16;
+pub const SO_PEERCRED: ::c_int = 17;
+pub const SO_RCVLOWAT: ::c_int = 18;
+pub const SO_SNDLOWAT: ::c_int = 19;
+pub const SO_RCVTIMEO: ::c_int = 20;
+pub const SO_SNDTIMEO: ::c_int = 21;
+pub const EXTPROC: ::tcflag_t = 0x00010000;
+pub const VEOL: usize = 11;
+pub const VEOL2: usize = 16;
+pub const VMIN: usize = 6;
+pub const IEXTEN: ::tcflag_t = 0x00008000;
+pub const TOSTOP: ::tcflag_t = 0x00000100;
+pub const FLUSHO: ::tcflag_t = 0x00001000;
+pub const TCGETS: ::c_int = 0x5401;
+pub const TCSETS: ::c_int = 0x5402;
+pub const TCSETSW: ::c_int = 0x5403;
+pub const TCSETSF: ::c_int = 0x5404;
+pub const TCGETA: ::c_int = 0x5405;
+pub const TCSETA: ::c_int = 0x5406;
+pub const TCSETAW: ::c_int = 0x5407;
+pub const TCSETAF: ::c_int = 0x5408;
+pub const TCSBRK: ::c_int = 0x5409;
+pub const TCXONC: ::c_int = 0x540A;
+pub const TCFLSH: ::c_int = 0x540B;
+pub const TIOCGSOFTCAR: ::c_int = 0x5419;
+pub const TIOCSSOFTCAR: ::c_int = 0x541A;
+pub const TIOCLINUX: ::c_int = 0x541C;
+pub const TIOCGSERIAL: ::c_int = 0x541E;
+pub const TIOCEXCL: ::c_int = 0x540C;
+pub const TIOCNXCL: ::c_int = 0x540D;
+pub const TIOCSCTTY: ::c_int = 0x540E;
+pub const TIOCGPGRP: ::c_int = 0x540F;
+pub const TIOCSPGRP: ::c_int = 0x5410;
+pub const TIOCOUTQ: ::c_int = 0x5411;
+pub const TIOCSTI: ::c_int = 0x5412;
+pub const TIOCGWINSZ: ::c_int = 0x5413;
+pub const TIOCSWINSZ: ::c_int = 0x5414;
+pub const TIOCMGET: ::c_int = 0x5415;
+pub const TIOCMBIS: ::c_int = 0x5416;
+pub const TIOCMBIC: ::c_int = 0x5417;
+pub const TIOCMSET: ::c_int = 0x5418;
+pub const FIONREAD: ::c_int = 0x541B;
+pub const TIOCCONS: ::c_int = 0x541D;
+
+pub const TIOCM_LE: ::c_int = 0x001;
+pub const TIOCM_DTR: ::c_int = 0x002;
+pub const TIOCM_RTS: ::c_int = 0x004;
+pub const TIOCM_ST: ::c_int = 0x008;
+pub const TIOCM_SR: ::c_int = 0x010;
+pub const TIOCM_CTS: ::c_int = 0x020;
+pub const TIOCM_CAR: ::c_int = 0x040;
+pub const TIOCM_RNG: ::c_int = 0x080;
+pub const TIOCM_DSR: ::c_int = 0x100;
+pub const TIOCM_CD: ::c_int = TIOCM_CAR;
+pub const TIOCM_RI: ::c_int = TIOCM_RNG;
+
+extern {
+    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+}
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/mod.rs
index 70baf8277a9b..5c2e815fd608 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/mod.rs
@@ -131,19 +131,16 @@ s! {
     }
 }
 
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 
 pub const O_ASYNC: ::c_int = 0x2000;
 
-pub const FIOCLEX: ::c_int = 0x5451;
-pub const FIONBIO: ::c_int = 0x5421;
-
 pub const RLIMIT_RSS: ::c_int = 5;
 pub const RLIMIT_NOFILE: ::c_int = 7;
 pub const RLIMIT_AS: ::c_int = 9;
 pub const RLIMIT_NPROC: ::c_int = 6;
 pub const RLIMIT_MEMLOCK: ::c_int = 8;
 
 pub const O_APPEND: ::c_int = 1024;
 pub const O_CREAT: ::c_int = 64;
@@ -167,17 +164,16 @@ pub const MAP_NONBLOCK: ::c_int = 0x010000;
 pub const MAP_STACK: ::c_int = 0x020000;
 
 pub const SOCK_STREAM: ::c_int = 1;
 pub const SOCK_DGRAM: ::c_int = 2;
 pub const SOCK_SEQPACKET: ::c_int = 5;
 
 pub const SOL_SOCKET: ::c_int = 1;
 
-pub const EDEADLK: ::c_int = 35;
 pub const ENAMETOOLONG: ::c_int = 36;
 pub const ENOLCK: ::c_int = 37;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTEMPTY: ::c_int = 39;
 pub const ELOOP: ::c_int = 40;
 pub const ENOMSG: ::c_int = 42;
 pub const EIDRM: ::c_int = 43;
 pub const ECHRNG: ::c_int = 44;
@@ -189,17 +185,16 @@ pub const EUNATCH: ::c_int = 49;
 pub const ENOCSI: ::c_int = 50;
 pub const EL2HLT: ::c_int = 51;
 pub const EBADE: ::c_int = 52;
 pub const EBADR: ::c_int = 53;
 pub const EXFULL: ::c_int = 54;
 pub const ENOANO: ::c_int = 55;
 pub const EBADRQC: ::c_int = 56;
 pub const EBADSLT: ::c_int = 57;
-pub const EDEADLOCK: ::c_int = EDEADLK;
 pub const EMULTIHOP: ::c_int = 72;
 pub const EBADMSG: ::c_int = 74;
 pub const EOVERFLOW: ::c_int = 75;
 pub const ENOTUNIQ: ::c_int = 76;
 pub const EBADFD: ::c_int = 77;
 pub const EREMCHG: ::c_int = 78;
 pub const ELIBACC: ::c_int = 79;
 pub const ELIBBAD: ::c_int = 80;
@@ -267,22 +262,16 @@ pub const SO_SNDBUF: ::c_int = 7;
 pub const SO_RCVBUF: ::c_int = 8;
 pub const SO_KEEPALIVE: ::c_int = 9;
 pub const SO_OOBINLINE: ::c_int = 10;
 pub const SO_NO_CHECK: ::c_int = 11;
 pub const SO_PRIORITY: ::c_int = 12;
 pub const SO_LINGER: ::c_int = 13;
 pub const SO_BSDCOMPAT: ::c_int = 14;
 pub const SO_REUSEPORT: ::c_int = 15;
-pub const SO_PASSCRED: ::c_int = 16;
-pub const SO_PEERCRED: ::c_int = 17;
-pub const SO_RCVLOWAT: ::c_int = 18;
-pub const SO_SNDLOWAT: ::c_int = 19;
-pub const SO_RCVTIMEO: ::c_int = 20;
-pub const SO_SNDTIMEO: ::c_int = 21;
 pub const SO_ACCEPTCONN: ::c_int = 30;
 pub const SO_SNDBUFFORCE: ::c_int = 32;
 pub const SO_RCVBUFFORCE: ::c_int = 33;
 pub const SO_PROTOCOL: ::c_int = 38;
 pub const SO_DOMAIN: ::c_int = 39;
 
 pub const SA_ONSTACK: ::c_int = 0x08000000;
 pub const SA_SIGINFO: ::c_int = 0x00000004;
@@ -307,80 +296,29 @@ pub const SIGIO: ::c_int = 29;
 pub const SIGSYS: ::c_int = 31;
 pub const SIGSTKFLT: ::c_int = 16;
 pub const SIGPOLL: ::c_int = 29;
 pub const SIGPWR: ::c_int = 30;
 pub const SIG_SETMASK: ::c_int = 2;
 pub const SIG_BLOCK: ::c_int = 0x000000;
 pub const SIG_UNBLOCK: ::c_int = 0x01;
 
-pub const EXTPROC: ::tcflag_t = 0x00010000;
-
 pub const MAP_HUGETLB: ::c_int = 0x040000;
 
 pub const F_GETLK: ::c_int = 5;
 pub const F_GETOWN: ::c_int = 9;
 pub const F_SETLK: ::c_int = 6;
 pub const F_SETLKW: ::c_int = 7;
 pub const F_SETOWN: ::c_int = 8;
 
 pub const VEOF: usize = 4;
-pub const VEOL: usize = 11;
-pub const VEOL2: usize = 16;
-pub const VMIN: usize = 6;
-pub const IEXTEN: ::tcflag_t = 0x00008000;
-pub const TOSTOP: ::tcflag_t = 0x00000100;
-pub const FLUSHO: ::tcflag_t = 0x00001000;
-
-pub const TCGETS: ::c_int = 0x5401;
-pub const TCSETS: ::c_int = 0x5402;
-pub const TCSETSW: ::c_int = 0x5403;
-pub const TCSETSF: ::c_int = 0x5404;
-pub const TCGETA: ::c_int = 0x5405;
-pub const TCSETA: ::c_int = 0x5406;
-pub const TCSETAW: ::c_int = 0x5407;
-pub const TCSETAF: ::c_int = 0x5408;
-pub const TCSBRK: ::c_int = 0x5409;
-pub const TCXONC: ::c_int = 0x540A;
-pub const TCFLSH: ::c_int = 0x540B;
-pub const TIOCGSOFTCAR: ::c_int = 0x5419;
-pub const TIOCSSOFTCAR: ::c_int = 0x541A;
-pub const TIOCLINUX: ::c_int = 0x541C;
-pub const TIOCGSERIAL: ::c_int = 0x541E;
-pub const TIOCEXCL: ::c_int = 0x540C;
-pub const TIOCNXCL: ::c_int = 0x540D;
-pub const TIOCSCTTY: ::c_int = 0x540E;
-pub const TIOCGPGRP: ::c_int = 0x540F;
-pub const TIOCSPGRP: ::c_int = 0x5410;
-pub const TIOCOUTQ: ::c_int = 0x5411;
-pub const TIOCSTI: ::c_int = 0x5412;
-pub const TIOCGWINSZ: ::c_int = 0x5413;
-pub const TIOCSWINSZ: ::c_int = 0x5414;
-pub const TIOCMGET: ::c_int = 0x5415;
-pub const TIOCMBIS: ::c_int = 0x5416;
-pub const TIOCMBIC: ::c_int = 0x5417;
-pub const TIOCMSET: ::c_int = 0x5418;
-pub const FIONREAD: ::c_int = 0x541B;
-pub const TIOCCONS: ::c_int = 0x541D;
 
 pub const POLLWRNORM: ::c_short = 0x100;
 pub const POLLWRBAND: ::c_short = 0x200;
 
-pub const TIOCM_LE: ::c_int = 0x001;
-pub const TIOCM_DTR: ::c_int = 0x002;
-pub const TIOCM_RTS: ::c_int = 0x004;
-pub const TIOCM_ST: ::c_int = 0x008;
-pub const TIOCM_SR: ::c_int = 0x010;
-pub const TIOCM_CTS: ::c_int = 0x020;
-pub const TIOCM_CAR: ::c_int = 0x040;
-pub const TIOCM_RNG: ::c_int = 0x080;
-pub const TIOCM_DSR: ::c_int = 0x100;
-pub const TIOCM_CD: ::c_int = TIOCM_CAR;
-pub const TIOCM_RI: ::c_int = TIOCM_RNG;
-
 cfg_if! {
     if #[cfg(target_arch = "aarch64")] {
         mod aarch64;
         pub use self::aarch64::*;
     } else if #[cfg(any(target_arch = "powerpc64"))] {
         mod powerpc64;
         pub use self::powerpc64::*;
     } else if #[cfg(any(target_arch = "x86_64"))] {
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs
index 1574bff5a606..2ac39bf0cd5d 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/powerpc64.rs
@@ -55,29 +55,518 @@ s! {
         pub cgid: ::gid_t,
         pub mode: ::mode_t,
         pub __seq: ::c_int,
         __unused1: ::c_long,
         __unused2: ::c_long
     }
 }
 
-pub const SYS_pivot_root: ::c_long = 203;
-pub const SYS_gettid: ::c_long = 207;
-pub const SYS_perf_event_open: ::c_long = 319;
-pub const SYS_memfd_create: ::c_long = 360;
-
 pub const MAP_32BIT: ::c_int = 0x0040;
-pub const O_DIRECT: ::c_int = 0x4000;
-pub const O_DIRECTORY: ::c_int = 0x10000;
-pub const O_LARGEFILE: ::c_int = 0;
-pub const O_NOFOLLOW: ::c_int = 0x20000;
+pub const O_DIRECT: ::c_int = 0x20000;
+pub const O_DIRECTORY: ::c_int = 0x4000;
+pub const O_LARGEFILE: ::c_int = 0x10000;
+pub const O_NOFOLLOW: ::c_int = 0x8000;
 
-pub const SIGSTKSZ: ::size_t = 8192;
-pub const MINSIGSTKSZ: ::size_t = 2048;
+pub const SIGSTKSZ: ::size_t = 10240;
+pub const MINSIGSTKSZ: ::size_t = 4096;
 
 #[doc(hidden)]
-pub const AF_MAX: ::c_int = 42;
+pub const AF_MAX: ::c_int = 43;
 #[doc(hidden)]
 pub const PF_MAX: ::c_int = AF_MAX;
 
 // Syscall table
+pub const SYS_restart_syscall: ::c_long = 0;
+pub const SYS_exit: ::c_long = 1;
+pub const SYS_fork: ::c_long = 2;
+pub const SYS_read: ::c_long = 3;
+pub const SYS_write: ::c_long = 4;
+pub const SYS_open: ::c_long = 5;
+pub const SYS_close: ::c_long = 6;
+pub const SYS_waitpid: ::c_long = 7;
+pub const SYS_creat: ::c_long = 8;
+pub const SYS_link: ::c_long = 9;
+pub const SYS_unlink: ::c_long = 10;
+pub const SYS_execve: ::c_long = 11;
+pub const SYS_chdir: ::c_long = 12;
+pub const SYS_time: ::c_long = 13;
+pub const SYS_mknod: ::c_long = 14;
+pub const SYS_chmod: ::c_long = 15;
+pub const SYS_lchown: ::c_long = 16;
+pub const SYS_break: ::c_long = 17;
+pub const SYS_oldstat: ::c_long = 18;
+pub const SYS_lseek: ::c_long = 19;
+pub const SYS_getpid: ::c_long = 20;
+pub const SYS_mount: ::c_long = 21;
+pub const SYS_umount: ::c_long = 22;
+pub const SYS_setuid: ::c_long = 23;
+pub const SYS_getuid: ::c_long = 24;
+pub const SYS_stime: ::c_long = 25;
+pub const SYS_ptrace: ::c_long = 26;
+pub const SYS_alarm: ::c_long = 27;
+pub const SYS_oldfstat: ::c_long = 28;
+pub const SYS_pause: ::c_long = 29;
+pub const SYS_utime: ::c_long = 30;
+pub const SYS_stty: ::c_long = 31;
+pub const SYS_gtty: ::c_long = 32;
+pub const SYS_access: ::c_long = 33;
+pub const SYS_nice: ::c_long = 34;
+pub const SYS_ftime: ::c_long = 35;
+pub const SYS_sync: ::c_long = 36;
+pub const SYS_kill: ::c_long = 37;
+pub const SYS_rename: ::c_long = 38;
+pub const SYS_mkdir: ::c_long = 39;
+pub const SYS_rmdir: ::c_long = 40;
+pub const SYS_dup: ::c_long = 41;
+pub const SYS_pipe: ::c_long = 42;
+pub const SYS_times: ::c_long = 43;
+pub const SYS_prof: ::c_long = 44;
+pub const SYS_brk: ::c_long = 45;
+pub const SYS_setgid: ::c_long = 46;
+pub const SYS_getgid: ::c_long = 47;
+pub const SYS_signal: ::c_long = 48;
+pub const SYS_geteuid: ::c_long = 49;
+pub const SYS_getegid: ::c_long = 50;
+pub const SYS_acct: ::c_long = 51;
+pub const SYS_umount2: ::c_long = 52;
+pub const SYS_lock: ::c_long = 53;
+pub const SYS_ioctl: ::c_long = 54;
+pub const SYS_fcntl: ::c_long = 55;
+pub const SYS_mpx: ::c_long = 56;
+pub const SYS_setpgid: ::c_long = 57;
+pub const SYS_ulimit: ::c_long = 58;
+pub const SYS_oldolduname: ::c_long = 59;
+pub const SYS_umask: ::c_long = 60;
+pub const SYS_chroot: ::c_long = 61;
+pub const SYS_ustat: ::c_long = 62;
+pub const SYS_dup2: ::c_long = 63;
+pub const SYS_getppid: ::c_long = 64;
+pub const SYS_getpgrp: ::c_long = 65;
+pub const SYS_setsid: ::c_long = 66;
+pub const SYS_sigaction: ::c_long = 67;
+pub const SYS_sgetmask: ::c_long = 68;
+pub const SYS_ssetmask: ::c_long = 69;
+pub const SYS_setreuid: ::c_long = 70;
+pub const SYS_setregid: ::c_long = 71;
+pub const SYS_sigsuspend: ::c_long = 72;
+pub const SYS_sigpending: ::c_long = 73;
+pub const SYS_sethostname: ::c_long = 74;
+pub const SYS_setrlimit: ::c_long = 75;
+pub const SYS_getrlimit: ::c_long = 76;
+pub const SYS_getrusage: ::c_long = 77;
+pub const SYS_gettimeofday: ::c_long = 78;
+pub const SYS_settimeofday: ::c_long = 79;
+pub const SYS_getgroups: ::c_long = 80;
+pub const SYS_setgroups: ::c_long = 81;
+pub const SYS_select: ::c_long = 82;
+pub const SYS_symlink: ::c_long = 83;
+pub const SYS_oldlstat: ::c_long = 84;
+pub const SYS_readlink: ::c_long = 85;
+pub const SYS_uselib: ::c_long = 86;
+pub const SYS_swapon: ::c_long = 87;
+pub const SYS_reboot: ::c_long = 88;
+pub const SYS_readdir: ::c_long = 89;
+pub const SYS_mmap: ::c_long = 90;
+pub const SYS_munmap: ::c_long = 91;
+pub const SYS_truncate: ::c_long = 92;
+pub const SYS_ftruncate: ::c_long = 93;
+pub const SYS_fchmod: ::c_long = 94;
+pub const SYS_fchown: ::c_long = 95;
+pub const SYS_getpriority: ::c_long = 96;
+pub const SYS_setpriority: ::c_long = 97;
+pub const SYS_profil: ::c_long = 98;
+pub const SYS_statfs: ::c_long = 99;
+pub const SYS_fstatfs: ::c_long = 100;
+pub const SYS_ioperm: ::c_long = 101;
+pub const SYS_socketcall: ::c_long = 102;
+pub const SYS_syslog: ::c_long = 103;
+pub const SYS_setitimer: ::c_long = 104;
+pub const SYS_getitimer: ::c_long = 105;
+pub const SYS_stat: ::c_long = 106;
+pub const SYS_lstat: ::c_long = 107;
+pub const SYS_fstat: ::c_long = 108;
+pub const SYS_olduname: ::c_long = 109;
+pub const SYS_iopl: ::c_long = 110;
+pub const SYS_vhangup: ::c_long = 111;
+pub const SYS_idle: ::c_long = 112;
+pub const SYS_vm86: ::c_long = 113;
+pub const SYS_wait4: ::c_long = 114;
+pub const SYS_swapoff: ::c_long = 115;
+pub const SYS_sysinfo: ::c_long = 116;
+pub const SYS_ipc: ::c_long = 117;
+pub const SYS_fsync: ::c_long = 118;
+pub const SYS_sigreturn: ::c_long = 119;
+pub const SYS_clone: ::c_long = 120;
+pub const SYS_setdomainname: ::c_long = 121;
+pub const SYS_uname: ::c_long = 122;
+pub const SYS_modify_ldt: ::c_long = 123;
+pub const SYS_adjtimex: ::c_long = 124;
+pub const SYS_mprotect: ::c_long = 125;
+pub const SYS_sigprocmask: ::c_long = 126;
+pub const SYS_create_module: ::c_long = 127;
+pub const SYS_init_module: ::c_long = 128;
+pub const SYS_delete_module: ::c_long = 129;
+pub const SYS_get_kernel_syms: ::c_long = 130;
+pub const SYS_quotactl: ::c_long = 131;
+pub const SYS_getpgid: ::c_long = 132;
+pub const SYS_fchdir: ::c_long = 133;
+pub const SYS_bdflush: ::c_long = 134;
+pub const SYS_sysfs: ::c_long = 135;
+pub const SYS_personality: ::c_long = 136;
+pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */
+pub const SYS_setfsuid: ::c_long = 138;
+pub const SYS_setfsgid: ::c_long = 139;
+pub const SYS__llseek: ::c_long = 140;
+pub const SYS_getdents: ::c_long = 141;
+pub const SYS__newselect: ::c_long = 142;
+pub const SYS_flock: ::c_long = 143;
+pub const SYS_msync: ::c_long = 144;
+pub const SYS_readv: ::c_long = 145;
+pub const SYS_writev: ::c_long = 146;
+pub const SYS_getsid: ::c_long = 147;
+pub const SYS_fdatasync: ::c_long = 148;
+pub const SYS__sysctl: ::c_long = 149;
+pub const SYS_mlock: ::c_long = 150;
+pub const SYS_munlock: ::c_long = 151;
+pub const SYS_mlockall: ::c_long = 152;
+pub const SYS_munlockall: ::c_long = 153;
+pub const SYS_sched_setparam: ::c_long = 154;
+pub const SYS_sched_getparam: ::c_long = 155;
+pub const SYS_sched_setscheduler: ::c_long = 156;
+pub const SYS_sched_getscheduler: ::c_long = 157;
+pub const SYS_sched_yield: ::c_long = 158;
+pub const SYS_sched_get_priority_max: ::c_long = 159;
+pub const SYS_sched_get_priority_min: ::c_long = 160;
+pub const SYS_sched_rr_get_interval: ::c_long = 161;
+pub const SYS_nanosleep: ::c_long = 162;
+pub const SYS_mremap: ::c_long = 163;
+pub const SYS_setresuid: ::c_long = 164;
+pub const SYS_getresuid: ::c_long = 165;
+pub const SYS_query_module: ::c_long = 166;
+pub const SYS_poll: ::c_long = 167;
+pub const SYS_nfsservctl: ::c_long = 168;
+pub const SYS_setresgid: ::c_long = 169;
+pub const SYS_getresgid: ::c_long = 170;
+pub const SYS_prctl: ::c_long = 171;
+pub const SYS_rt_sigreturn: ::c_long = 172;
+pub const SYS_rt_sigaction: ::c_long = 173;
+pub const SYS_rt_sigprocmask: ::c_long = 174;
+pub const SYS_rt_sigpending: ::c_long = 175;
+pub const SYS_rt_sigtimedwait: ::c_long = 176;
+pub const SYS_rt_sigqueueinfo: ::c_long = 177;
+pub const SYS_rt_sigsuspend: ::c_long = 178;
+pub const SYS_pread64: ::c_long = 179;
+pub const SYS_pwrite64: ::c_long = 180;
+pub const SYS_chown: ::c_long = 181;
+pub const SYS_getcwd: ::c_long = 182;
+pub const SYS_capget: ::c_long = 183;
+pub const SYS_capset: ::c_long = 184;
+pub const SYS_sigaltstack: ::c_long = 185;
+pub const SYS_sendfile: ::c_long = 186;
+pub const SYS_getpmsg: ::c_long = 187; /* some people actually want streams */
+pub const SYS_putpmsg: ::c_long = 188; /* some people actually want streams */
+pub const SYS_vfork: ::c_long = 189;
+pub const SYS_ugetrlimit: ::c_long = 190; /* SuS compliant getrlimit */
+pub const SYS_readahead: ::c_long = 191;
+pub const SYS_pciconfig_read: ::c_long = 198;
+pub const SYS_pciconfig_write: ::c_long = 199;
+pub const SYS_pciconfig_iobase: ::c_long = 200;
+pub const SYS_multiplexer: ::c_long = 201;
+pub const SYS_getdents64: ::c_long = 202;
+pub const SYS_pivot_root: ::c_long = 203;
+pub const SYS_madvise: ::c_long = 205;
+pub const SYS_mincore: ::c_long = 206;
+pub const SYS_gettid: ::c_long = 207;
+pub const SYS_tkill: ::c_long = 208;
+pub const SYS_setxattr: ::c_long = 209;
+pub const SYS_lsetxattr: ::c_long = 210;
+pub const SYS_fsetxattr: ::c_long = 211;
+pub const SYS_getxattr: ::c_long = 212;
+pub const SYS_lgetxattr: ::c_long = 213;
+pub const SYS_fgetxattr: ::c_long = 214;
+pub const SYS_listxattr: ::c_long = 215;
+pub const SYS_llistxattr: ::c_long = 216;
+pub const SYS_flistxattr: ::c_long = 217;
+pub const SYS_removexattr: ::c_long = 218;
+pub const SYS_lremovexattr: ::c_long = 219;
+pub const SYS_fremovexattr: ::c_long = 220;
+pub const SYS_futex: ::c_long = 221;
+pub const SYS_sched_setaffinity: ::c_long = 222;
+pub const SYS_sched_getaffinity: ::c_long = 223;
+pub const SYS_tuxcall: ::c_long = 225;
+pub const SYS_io_setup: ::c_long = 227;
+pub const SYS_io_destroy: ::c_long = 228;
+pub const SYS_io_getevents: ::c_long = 229;
+pub const SYS_io_submit: ::c_long = 230;
+pub const SYS_io_cancel: ::c_long = 231;
+pub const SYS_set_tid_address: ::c_long = 232;
+pub const SYS_exit_group: ::c_long = 234;
+pub const SYS_lookup_dcookie: ::c_long = 235;
+pub const SYS_epoll_create: ::c_long = 236;
+pub const SYS_epoll_ctl: ::c_long = 237;
+pub const SYS_epoll_wait: ::c_long = 238;
+pub const SYS_remap_file_pages: ::c_long = 239;
+pub const SYS_timer_create: ::c_long = 240;
+pub const SYS_timer_settime: ::c_long = 241;
+pub const SYS_timer_gettime: ::c_long = 242;
+pub const SYS_timer_getoverrun: ::c_long = 243;
+pub const SYS_timer_delete: ::c_long = 244;
+pub const SYS_clock_settime: ::c_long = 245;
+pub const SYS_clock_gettime: ::c_long = 246;
+pub const SYS_clock_getres: ::c_long = 247;
+pub const SYS_clock_nanosleep: ::c_long = 248;
+pub const SYS_swapcontext: ::c_long = 249;
+pub const SYS_tgkill: ::c_long = 250;
+pub const SYS_utimes: ::c_long = 251;
+pub const SYS_statfs64: ::c_long = 252;
+pub const SYS_fstatfs64: ::c_long = 253;
+pub const SYS_rtas: ::c_long = 255;
+pub const SYS_sys_debug_setcontext: ::c_long = 256;
+pub const SYS_migrate_pages: ::c_long = 258;
+pub const SYS_mbind: ::c_long = 259;
+pub const SYS_get_mempolicy: ::c_long = 260;
+pub const SYS_set_mempolicy: ::c_long = 261;
+pub const SYS_mq_open: ::c_long = 262;
+pub const SYS_mq_unlink: ::c_long = 263;
+pub const SYS_mq_timedsend: ::c_long = 264;
+pub const SYS_mq_timedreceive: ::c_long = 265;
+pub const SYS_mq_notify: ::c_long = 266;
+pub const SYS_mq_getsetattr: ::c_long = 267;
+pub const SYS_kexec_load: ::c_long = 268;
+pub const SYS_add_key: ::c_long = 269;
+pub const SYS_request_key: ::c_long = 270;
+pub const SYS_keyctl: ::c_long = 271;
+pub const SYS_waitid: ::c_long = 272;
+pub const SYS_ioprio_set: ::c_long = 273;
+pub const SYS_ioprio_get: ::c_long = 274;
+pub const SYS_inotify_init: ::c_long = 275;
+pub const SYS_inotify_add_watch: ::c_long = 276;
+pub const SYS_inotify_rm_watch: ::c_long = 277;
+pub const SYS_spu_run: ::c_long = 278;
+pub const SYS_spu_create: ::c_long = 279;
+pub const SYS_pselect6: ::c_long = 280;
+pub const SYS_ppoll: ::c_long = 281;
+pub const SYS_unshare: ::c_long = 282;
+pub const SYS_splice: ::c_long = 283;
+pub const SYS_tee: ::c_long = 284;
+pub const SYS_vmsplice: ::c_long = 285;
+pub const SYS_openat: ::c_long = 286;
+pub const SYS_mkdirat: ::c_long = 287;
+pub const SYS_mknodat: ::c_long = 288;
+pub const SYS_fchownat: ::c_long = 289;
+pub const SYS_futimesat: ::c_long = 290;
+pub const SYS_newfstatat: ::c_long = 291;
+pub const SYS_unlinkat: ::c_long = 292;
+pub const SYS_renameat: ::c_long = 293;
+pub const SYS_linkat: ::c_long = 294;
+pub const SYS_symlinkat: ::c_long = 295;
+pub const SYS_readlinkat: ::c_long = 296;
+pub const SYS_fchmodat: ::c_long = 297;
+pub const SYS_faccessat: ::c_long = 298;
+pub const SYS_get_robust_list: ::c_long = 299;
+pub const SYS_set_robust_list: ::c_long = 300;
+pub const SYS_move_pages: ::c_long = 301;
+pub const SYS_getcpu: ::c_long = 302;
+pub const SYS_epoll_pwait: ::c_long = 303;
+pub const SYS_utimensat: ::c_long = 304;
+pub const SYS_signalfd: ::c_long = 305;
+pub const SYS_timerfd_create: ::c_long = 306;
+pub const SYS_eventfd: ::c_long = 307;
+pub const SYS_sync_file_range2: ::c_long = 308;
+pub const SYS_fallocate: ::c_long = 309;
+pub const SYS_subpage_prot: ::c_long = 310;
+pub const SYS_timerfd_settime: ::c_long = 311;
+pub const SYS_timerfd_gettime: ::c_long = 312;
+pub const SYS_signalfd4: ::c_long = 313;
+pub const SYS_eventfd2: ::c_long = 314;
+pub const SYS_epoll_create1: ::c_long = 315;
+pub const SYS_dup3: ::c_long = 316;
+pub const SYS_pipe2: ::c_long = 317;
+pub const SYS_inotify_init1: ::c_long = 318;
+pub const SYS_perf_event_open: ::c_long = 319;
+pub const SYS_preadv: ::c_long = 320;
+pub const SYS_pwritev: ::c_long = 321;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 322;
+pub const SYS_fanotify_init: ::c_long = 323;
+pub const SYS_fanotify_mark: ::c_long = 324;
+pub const SYS_prlimit64: ::c_long = 325;
+pub const SYS_socket: ::c_long = 326;
+pub const SYS_bind: ::c_long = 327;
+pub const SYS_connect: ::c_long = 328;
+pub const SYS_listen: ::c_long = 329;
+pub const SYS_accept: ::c_long = 330;
+pub const SYS_getsockname: ::c_long = 331;
+pub const SYS_getpeername: ::c_long = 332;
+pub const SYS_socketpair: ::c_long = 333;
+pub const SYS_send: ::c_long = 334;
+pub const SYS_sendto: ::c_long = 335;
+pub const SYS_recv: ::c_long = 336;
+pub const SYS_recvfrom: ::c_long = 337;
+pub const SYS_shutdown: ::c_long = 338;
+pub const SYS_setsockopt: ::c_long = 339;
+pub const SYS_getsockopt: ::c_long = 340;
+pub const SYS_sendmsg: ::c_long = 341;
+pub const SYS_recvmsg: ::c_long = 342;
+pub const SYS_recvmmsg: ::c_long = 343;
+pub const SYS_accept4: ::c_long = 344;
+pub const SYS_name_to_handle_at: ::c_long = 345;
+pub const SYS_open_by_handle_at: ::c_long = 346;
+pub const SYS_clock_adjtime: ::c_long = 347;
+pub const SYS_syncfs: ::c_long = 348;
+pub const SYS_sendmmsg: ::c_long = 349;
+pub const SYS_setns: ::c_long = 350;
+pub const SYS_process_vm_readv: ::c_long = 351;
+pub const SYS_process_vm_writev: ::c_long = 352;
+pub const SYS_finit_module: ::c_long = 353;
+pub const SYS_kcmp: ::c_long = 354;
+pub const SYS_sched_setattr: ::c_long = 355;
+pub const SYS_sched_getattr: ::c_long = 356;
 pub const SYS_renameat2: ::c_long = 357;
+pub const SYS_seccomp: ::c_long = 358;
+pub const SYS_getrandom: ::c_long = 359;
+pub const SYS_memfd_create: ::c_long = 360;
+pub const SYS_bpf: ::c_long = 361;
+pub const SYS_execveat: ::c_long = 362;
+pub const SYS_switch_endian: ::c_long = 363;
+pub const SYS_userfaultfd: ::c_long = 364;
+pub const SYS_membarrier: ::c_long = 365;
+pub const SYS_mlock2: ::c_long = 378;
+pub const SYS_copy_file_range: ::c_long = 379;
+pub const SYS_preadv2: ::c_long = 380;
+pub const SYS_pwritev2: ::c_long = 381;
+pub const SYS_kexec_file_load: ::c_long = 382;
+
+pub const FIOCLEX: ::c_ulong = 0x20006601;
+pub const FIONBIO: ::c_ulong = 0x8004667e;
+pub const EDEADLK: ::c_int = 58;
+pub const EDEADLOCK: ::c_int = EDEADLK;
+pub const SO_PASSCRED: ::c_int = 20;
+pub const SO_PEERCRED: ::c_int = 21;
+pub const SO_RCVLOWAT: ::c_int = 16;
+pub const SO_SNDLOWAT: ::c_int = 17;
+pub const SO_RCVTIMEO: ::c_int = 18;
+pub const SO_SNDTIMEO: ::c_int = 19;
+pub const EXTPROC: ::tcflag_t = 0x10000000;
+pub const VEOL: usize = 6;
+pub const VEOL2: usize = 8;
+pub const VMIN: usize = 5;
+pub const IEXTEN: ::tcflag_t = 0x00000400;
+pub const TOSTOP: ::tcflag_t = 0x00400000;
+pub const FLUSHO: ::tcflag_t = 0x00800000;
+pub const TCGETS: ::c_ulong = 0x403c7413;
+pub const TCSETS: ::c_ulong = 0x803c7414;
+pub const TCSETSW: ::c_ulong = 0x803c7415;
+pub const TCSETSF: ::c_ulong = 0x803c7416;
+pub const TCGETA: ::c_ulong = 0x40147417;
+pub const TCSETA: ::c_ulong = 0x80147418;
+pub const TCSETAW: ::c_ulong = 0x80147419;
+pub const TCSETAF: ::c_ulong = 0x8014741c;
+pub const TCSBRK: ::c_ulong = 0x2000741d;
+pub const TCXONC: ::c_ulong = 0x2000741e;
+pub const TCFLSH: ::c_ulong = 0x2000741f;
+pub const TIOCGSOFTCAR: ::c_ulong = 0x5419;
+pub const TIOCSSOFTCAR: ::c_ulong = 0x541A;
+pub const TIOCLINUX: ::c_ulong = 0x541C;
+pub const TIOCGSERIAL: ::c_ulong = 0x541E;
+pub const TIOCEXCL: ::c_ulong = 0x540C;
+pub const TIOCNXCL: ::c_ulong = 0x540D;
+pub const TIOCSCTTY: ::c_ulong = 0x540E;
+pub const TIOCGPGRP: ::c_ulong = 0x40047477;
+pub const TIOCSPGRP: ::c_ulong = 0x80047476;
+pub const TIOCOUTQ: ::c_ulong = 0x40047473;
+pub const TIOCGWINSZ: ::c_ulong = 0x40087468;
+pub const TIOCSWINSZ: ::c_ulong = 0x80087467;
+pub const TIOCMGET: ::c_ulong = 0x5415;
+pub const TIOCMBIS: ::c_ulong = 0x5416;
+pub const TIOCMBIC: ::c_ulong = 0x5417;
+pub const TIOCMSET: ::c_ulong = 0x5418;
+pub const FIONREAD: ::c_ulong = 0x4004667f;
+pub const TIOCCONS: ::c_ulong = 0x541D;
+pub const TIOCM_LE: ::c_ulong = 0x001;
+pub const TIOCM_DTR: ::c_ulong = 0x002;
+pub const TIOCM_RTS: ::c_ulong = 0x004;
+pub const TIOCM_ST: ::c_ulong = 0x008;
+pub const TIOCM_SR: ::c_ulong = 0x010;
+pub const TIOCM_CTS: ::c_ulong = 0x020;
+pub const TIOCM_CAR: ::c_ulong = 0x040;
+pub const TIOCM_RNG: ::c_ulong = 0x080;
+pub const TIOCM_DSR: ::c_ulong = 0x100;
+pub const TIOCM_CD: ::c_ulong = TIOCM_CAR;
+pub const TIOCM_RI: ::c_ulong = TIOCM_RNG;
+
+pub const RLIMIT_NLIMITS: ::c_int = 15;
+pub const TIOCINQ: ::c_ulong = ::FIONREAD;
+pub const MCL_CURRENT: ::c_int = 0x2000;
+pub const MCL_FUTURE: ::c_int = 0x4000;
+pub const CBAUD: ::tcflag_t = 0xff;
+pub const TAB1: ::c_int = 0x400;
+pub const TAB2: ::c_int = 0x800;
+pub const TAB3: ::c_int = 0xc00;
+pub const CR1: ::c_int  = 0x1000;
+pub const CR2: ::c_int  = 0x2000;
+pub const CR3: ::c_int  = 0x3000;
+pub const FF1: ::c_int  = 0x4000;
+pub const BS1: ::c_int  = 0x8000;
+pub const VT1: ::c_int  = 0x10000;
+pub const VWERASE: usize = 10;
+pub const VREPRINT: usize = 11;
+pub const VSUSP: usize = 12;
+pub const VSTART: usize = 13;
+pub const VSTOP: usize = 14;
+pub const VDISCARD: usize = 16;
+pub const VTIME: usize = 7;
+pub const IXON: ::tcflag_t = 0x00000200;
+pub const IXOFF: ::tcflag_t = 0x00000400;
+pub const ONLCR: ::tcflag_t = 0x2;
+pub const CSIZE: ::tcflag_t = 0x00000300;
+
+pub const CS6: ::tcflag_t = 0x00000100;
+pub const CS7: ::tcflag_t = 0x00000200;
+pub const CS8: ::tcflag_t = 0x00000300;
+pub const CSTOPB: ::tcflag_t = 0x00000400;
+pub const CREAD: ::tcflag_t = 0x00000800;
+pub const PARENB: ::tcflag_t = 0x00001000;
+pub const PARODD: ::tcflag_t = 0x00002000;
+pub const HUPCL: ::tcflag_t = 0x00004000;
+pub const CLOCAL: ::tcflag_t = 0x00008000;
+pub const ECHOKE: ::tcflag_t = 0x00000001;
+pub const ECHOE: ::tcflag_t = 0x00000002;
+pub const ECHOK: ::tcflag_t = 0x00000004;
+pub const ECHONL: ::tcflag_t = 0x00000010;
+pub const ECHOPRT: ::tcflag_t = 0x00000020;
+pub const ECHOCTL: ::tcflag_t = 0x00000040;
+pub const ISIG: ::tcflag_t = 0x00000080;
+pub const ICANON: ::tcflag_t = 0x00000100;
+pub const PENDIN: ::tcflag_t = 0x20000000;
+pub const NOFLSH: ::tcflag_t = 0x80000000;
+
+pub const CIBAUD: ::tcflag_t = 0o77600000;
+pub const CBAUDEX: ::tcflag_t = 0o0000020;
+pub const VSWTC: usize = 9;
+pub const OLCUC:  ::tcflag_t = 0o000004;
+pub const NLDLY:  ::tcflag_t = 0o0001400;
+pub const CRDLY:  ::tcflag_t = 0o0030000;
+pub const TABDLY: ::tcflag_t = 0o0006000;
+pub const BSDLY:  ::tcflag_t = 0o0100000;
+pub const FFDLY:  ::tcflag_t = 0o0040000;
+pub const VTDLY:  ::tcflag_t = 0o0200000;
+pub const XTABS:  ::tcflag_t = 0o00006000;
+
+pub const B57600: ::speed_t = 0o00020;
+pub const B115200: ::speed_t = 0o00021;
+pub const B230400: ::speed_t = 0o00022;
+pub const B460800: ::speed_t = 0o00023;
+pub const B500000: ::speed_t = 0o00024;
+pub const B576000: ::speed_t = 0o00025;
+pub const B921600: ::speed_t = 0o00026;
+pub const B1000000: ::speed_t = 0o00027;
+pub const B1152000: ::speed_t = 0o00030;
+pub const B1500000: ::speed_t = 0o00031;
+pub const B2000000: ::speed_t = 0o00032;
+pub const B2500000: ::speed_t = 0o00033;
+pub const B3000000: ::speed_t = 0o00034;
+pub const B3500000: ::speed_t = 0o00035;
+pub const B4000000: ::speed_t = 0o00036;
+
+extern {
+    pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int;
+}
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs
index 78d38e49e8f9..0e0fcec4d2e7 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/b64/x86_64.rs
@@ -444,8 +444,144 @@ pub const O_NOFOLLOW: ::c_int = 0x20000;
 
 pub const SIGSTKSZ: ::size_t = 8192;
 pub const MINSIGSTKSZ: ::size_t = 2048;
 
 #[doc(hidden)]
 pub const AF_MAX: ::c_int = 42;
 #[doc(hidden)]
 pub const PF_MAX: ::c_int = AF_MAX;
+
+pub const RLIMIT_NLIMITS: ::c_int = 16;
+pub const TIOCINQ: ::c_int = ::FIONREAD;
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+pub const CBAUD: ::tcflag_t = 0o0010017;
+pub const TAB1: ::c_int = 0x00000800;
+pub const TAB2: ::c_int = 0x00001000;
+pub const TAB3: ::c_int = 0x00001800;
+pub const CR1: ::c_int  = 0x00000200;
+pub const CR2: ::c_int  = 0x00000400;
+pub const CR3: ::c_int  = 0x00000600;
+pub const FF1: ::c_int  = 0x00008000;
+pub const BS1: ::c_int  = 0x00002000;
+pub const VT1: ::c_int  = 0x00004000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 5;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x4;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x00000010;
+pub const CS7: ::tcflag_t = 0x00000020;
+pub const CS8: ::tcflag_t = 0x00000030;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOPRT: ::tcflag_t = 0x00000400;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const PENDIN: ::tcflag_t = 0x00004000;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const CIBAUD: ::tcflag_t = 0o02003600000;
+pub const CBAUDEX: ::tcflag_t = 0o010000;
+pub const VSWTC: usize = 7;
+pub const OLCUC:  ::tcflag_t = 0o000002;
+pub const NLDLY:  ::tcflag_t = 0o000400;
+pub const CRDLY:  ::tcflag_t = 0o003000;
+pub const TABDLY: ::tcflag_t = 0o014000;
+pub const BSDLY:  ::tcflag_t = 0o020000;
+pub const FFDLY:  ::tcflag_t = 0o100000;
+pub const VTDLY:  ::tcflag_t = 0o040000;
+pub const XTABS:  ::tcflag_t = 0o014000;
+pub const B57600: ::speed_t = 0o010001;
+pub const B115200: ::speed_t = 0o010002;
+pub const B230400: ::speed_t = 0o010003;
+pub const B460800: ::speed_t = 0o010004;
+pub const B500000: ::speed_t = 0o010005;
+pub const B576000: ::speed_t = 0o010006;
+pub const B921600: ::speed_t = 0o010007;
+pub const B1000000: ::speed_t = 0o010010;
+pub const B1152000: ::speed_t = 0o010011;
+pub const B1500000: ::speed_t = 0o010012;
+pub const B2000000: ::speed_t = 0o010013;
+pub const B2500000: ::speed_t = 0o010014;
+pub const B3000000: ::speed_t = 0o010015;
+pub const B3500000: ::speed_t = 0o010016;
+pub const B4000000: ::speed_t = 0o010017;
+
+pub const FIOCLEX: ::c_int = 0x5451;
+pub const FIONBIO: ::c_int = 0x5421;
+pub const EDEADLK: ::c_int = 35;
+pub const EDEADLOCK: ::c_int = EDEADLK;
+pub const SO_PASSCRED: ::c_int = 16;
+pub const SO_PEERCRED: ::c_int = 17;
+pub const SO_RCVLOWAT: ::c_int = 18;
+pub const SO_SNDLOWAT: ::c_int = 19;
+pub const SO_RCVTIMEO: ::c_int = 20;
+pub const SO_SNDTIMEO: ::c_int = 21;
+pub const EXTPROC: ::tcflag_t = 0x00010000;
+pub const VEOL: usize = 11;
+pub const VEOL2: usize = 16;
+pub const VMIN: usize = 6;
+pub const IEXTEN: ::tcflag_t = 0x00008000;
+pub const TOSTOP: ::tcflag_t = 0x00000100;
+pub const FLUSHO: ::tcflag_t = 0x00001000;
+pub const TCGETS: ::c_int = 0x5401;
+pub const TCSETS: ::c_int = 0x5402;
+pub const TCSETSW: ::c_int = 0x5403;
+pub const TCSETSF: ::c_int = 0x5404;
+pub const TCGETA: ::c_int = 0x5405;
+pub const TCSETA: ::c_int = 0x5406;
+pub const TCSETAW: ::c_int = 0x5407;
+pub const TCSETAF: ::c_int = 0x5408;
+pub const TCSBRK: ::c_int = 0x5409;
+pub const TCXONC: ::c_int = 0x540A;
+pub const TCFLSH: ::c_int = 0x540B;
+pub const TIOCGSOFTCAR: ::c_int = 0x5419;
+pub const TIOCSSOFTCAR: ::c_int = 0x541A;
+pub const TIOCLINUX: ::c_int = 0x541C;
+pub const TIOCGSERIAL: ::c_int = 0x541E;
+pub const TIOCEXCL: ::c_int = 0x540C;
+pub const TIOCNXCL: ::c_int = 0x540D;
+pub const TIOCSCTTY: ::c_int = 0x540E;
+pub const TIOCGPGRP: ::c_int = 0x540F;
+pub const TIOCSPGRP: ::c_int = 0x5410;
+pub const TIOCOUTQ: ::c_int = 0x5411;
+pub const TIOCSTI: ::c_int = 0x5412;
+pub const TIOCGWINSZ: ::c_int = 0x5413;
+pub const TIOCSWINSZ: ::c_int = 0x5414;
+pub const TIOCMGET: ::c_int = 0x5415;
+pub const TIOCMBIS: ::c_int = 0x5416;
+pub const TIOCMBIC: ::c_int = 0x5417;
+pub const TIOCMSET: ::c_int = 0x5418;
+pub const FIONREAD: ::c_int = 0x541B;
+pub const TIOCCONS: ::c_int = 0x541D;
+
+pub const TIOCM_LE: ::c_int = 0x001;
+pub const TIOCM_DTR: ::c_int = 0x002;
+pub const TIOCM_RTS: ::c_int = 0x004;
+pub const TIOCM_ST: ::c_int = 0x008;
+pub const TIOCM_SR: ::c_int = 0x010;
+pub const TIOCM_CTS: ::c_int = 0x020;
+pub const TIOCM_CAR: ::c_int = 0x040;
+pub const TIOCM_RNG: ::c_int = 0x080;
+pub const TIOCM_DSR: ::c_int = 0x100;
+pub const TIOCM_CD: ::c_int = TIOCM_CAR;
+pub const TIOCM_RI: ::c_int = TIOCM_RNG;
+
+extern {
+    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+}
+
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/musl/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/musl/mod.rs
index 4ac058db10a2..10d61ebebefa 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/musl/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/musl/mod.rs
@@ -35,16 +35,36 @@ s! {
 
     pub struct sigaction {
         pub sa_sigaction: ::sighandler_t,
         pub sa_mask: ::sigset_t,
         pub sa_flags: ::c_int,
         pub sa_restorer: ::dox::Option<extern fn()>,
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        #[cfg(target_endian = "little")]
+        pub f_fsid: ::c_ulong,
+        #[cfg(target_pointer_width = "32")]
+        __f_unused: ::c_int,
+        #[cfg(target_endian = "big")]
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct termios {
         pub c_iflag: ::tcflag_t,
         pub c_oflag: ::tcflag_t,
         pub c_cflag: ::tcflag_t,
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; ::NCCS],
         pub __c_ispeed: ::speed_t,
@@ -70,31 +90,26 @@ s! {
         pub freeswap: ::c_ulong,
         pub procs: ::c_ushort,
         pub pad: ::c_ushort,
         pub totalhigh: ::c_ulong,
         pub freehigh: ::c_ulong,
         pub mem_unit: ::c_uint,
         pub __reserved: [::c_char; 256],
     }
-
-    pub struct ucred {
-        pub pid: ::pid_t,
-        pub uid: ::uid_t,
-        pub gid: ::gid_t,
-    }
 }
 
 pub const SFD_CLOEXEC: ::c_int = 0x080000;
 
 pub const NCCS: usize = 32;
 
 pub const O_TRUNC: ::c_int = 512;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_CLOEXEC: ::c_int = 0x80000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const EBFONT: ::c_int = 59;
 pub const ENOSTR: ::c_int = 60;
 pub const ENODATA: ::c_int = 61;
 pub const ETIME: ::c_int = 62;
 pub const ENOSR: ::c_int = 63;
 pub const ENONET: ::c_int = 64;
 pub const ENOPKG: ::c_int = 65;
@@ -127,17 +142,16 @@ pub const NI_MAXHOST: ::socklen_t = 255;
 pub const PTHREAD_STACK_MIN: ::size_t = 2048;
 pub const POSIX_FADV_DONTNEED: ::c_int = 4;
 pub const POSIX_FADV_NOREUSE: ::c_int = 5;
 
 pub const POSIX_MADV_DONTNEED: ::c_int = 4;
 
 pub const RLIM_INFINITY: ::rlim_t = !0;
 pub const RLIMIT_RTTIME: ::c_int = 15;
-pub const RLIMIT_NLIMITS: ::c_int = 16;
 
 pub const MAP_ANONYMOUS: ::c_int = MAP_ANON;
 
 pub const SOCK_DCCP: ::c_int = 6;
 pub const SOCK_PACKET: ::c_int = 10;
 
 pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15;
 pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16;
@@ -193,81 +207,24 @@ pub const EPOLLWAKEUP: ::c_int = 0x20000000;
 pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK;
 
 pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK;
 
 pub const TCSANOW: ::c_int = 0;
 pub const TCSADRAIN: ::c_int = 1;
 pub const TCSAFLUSH: ::c_int = 2;
 
-pub const TIOCINQ: ::c_int = ::FIONREAD;
-
 pub const RTLD_GLOBAL: ::c_int = 0x100;
 pub const RTLD_NOLOAD: ::c_int = 0x4;
 
 // TODO(#247) Temporarily musl-specific (available since musl 0.9.12 / Linux
 // kernel 3.10).  See also notbsd/mod.rs
 pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;
 pub const CLOCK_TAI: ::clockid_t = 11;
 
-pub const MCL_CURRENT: ::c_int = 0x0001;
-pub const MCL_FUTURE: ::c_int = 0x0002;
-
-pub const CBAUD: ::tcflag_t = 0o0010017;
-pub const TAB1: ::c_int = 0x00000800;
-pub const TAB2: ::c_int = 0x00001000;
-pub const TAB3: ::c_int = 0x00001800;
-pub const CR1: ::c_int  = 0x00000200;
-pub const CR2: ::c_int  = 0x00000400;
-pub const CR3: ::c_int  = 0x00000600;
-pub const FF1: ::c_int  = 0x00008000;
-pub const BS1: ::c_int  = 0x00002000;
-pub const VT1: ::c_int  = 0x00004000;
-pub const VWERASE: usize = 14;
-pub const VREPRINT: usize = 12;
-pub const VSUSP: usize = 10;
-pub const VSTART: usize = 8;
-pub const VSTOP: usize = 9;
-pub const VDISCARD: usize = 13;
-pub const VTIME: usize = 5;
-pub const IXON: ::tcflag_t = 0x00000400;
-pub const IXOFF: ::tcflag_t = 0x00001000;
-pub const ONLCR: ::tcflag_t = 0x4;
-pub const CSIZE: ::tcflag_t = 0x00000030;
-pub const CS6: ::tcflag_t = 0x00000010;
-pub const CS7: ::tcflag_t = 0x00000020;
-pub const CS8: ::tcflag_t = 0x00000030;
-pub const CSTOPB: ::tcflag_t = 0x00000040;
-pub const CREAD: ::tcflag_t = 0x00000080;
-pub const PARENB: ::tcflag_t = 0x00000100;
-pub const PARODD: ::tcflag_t = 0x00000200;
-pub const HUPCL: ::tcflag_t = 0x00000400;
-pub const CLOCAL: ::tcflag_t = 0x00000800;
-pub const ECHOKE: ::tcflag_t = 0x00000800;
-pub const ECHOE: ::tcflag_t = 0x00000010;
-pub const ECHOK: ::tcflag_t = 0x00000020;
-pub const ECHONL: ::tcflag_t = 0x00000040;
-pub const ECHOPRT: ::tcflag_t = 0x00000400;
-pub const ECHOCTL: ::tcflag_t = 0x00000200;
-pub const ISIG: ::tcflag_t = 0x00000001;
-pub const ICANON: ::tcflag_t = 0x00000002;
-pub const PENDIN: ::tcflag_t = 0x00004000;
-pub const NOFLSH: ::tcflag_t = 0x00000080;
-pub const CIBAUD: ::tcflag_t = 0o02003600000;
-pub const CBAUDEX: ::tcflag_t = 0o010000;
-pub const VSWTC: usize = 7;
-pub const OLCUC:  ::tcflag_t = 0o000002;
-pub const NLDLY:  ::tcflag_t = 0o000400;
-pub const CRDLY:  ::tcflag_t = 0o003000;
-pub const TABDLY: ::tcflag_t = 0o014000;
-pub const BSDLY:  ::tcflag_t = 0o020000;
-pub const FFDLY:  ::tcflag_t = 0o100000;
-pub const VTDLY:  ::tcflag_t = 0o040000;
-pub const XTABS:  ::tcflag_t = 0o014000;
-
 pub const B0: ::speed_t = 0o000000;
 pub const B50: ::speed_t = 0o000001;
 pub const B75: ::speed_t = 0o000002;
 pub const B110: ::speed_t = 0o000003;
 pub const B134: ::speed_t = 0o000004;
 pub const B150: ::speed_t = 0o000005;
 pub const B200: ::speed_t = 0o000006;
 pub const B300: ::speed_t = 0o000007;
@@ -276,51 +233,36 @@ pub const B1200: ::speed_t = 0o000011;
 pub const B1800: ::speed_t = 0o000012;
 pub const B2400: ::speed_t = 0o000013;
 pub const B4800: ::speed_t = 0o000014;
 pub const B9600: ::speed_t = 0o000015;
 pub const B19200: ::speed_t = 0o000016;
 pub const B38400: ::speed_t = 0o000017;
 pub const EXTA: ::speed_t = B19200;
 pub const EXTB: ::speed_t = B38400;
-pub const B57600: ::speed_t = 0o010001;
-pub const B115200: ::speed_t = 0o010002;
-pub const B230400: ::speed_t = 0o010003;
-pub const B460800: ::speed_t = 0o010004;
-pub const B500000: ::speed_t = 0o010005;
-pub const B576000: ::speed_t = 0o010006;
-pub const B921600: ::speed_t = 0o010007;
-pub const B1000000: ::speed_t = 0o010010;
-pub const B1152000: ::speed_t = 0o010011;
-pub const B1500000: ::speed_t = 0o010012;
-pub const B2000000: ::speed_t = 0o010013;
-pub const B2500000: ::speed_t = 0o010014;
-pub const B3000000: ::speed_t = 0o010015;
-pub const B3500000: ::speed_t = 0o010016;
-pub const B4000000: ::speed_t = 0o010017;
 
 pub const SO_BINDTODEVICE: ::c_int = 25;
 pub const SO_TIMESTAMP: ::c_int = 29;
 pub const SO_MARK: ::c_int = 36;
 pub const SO_RXQ_OVFL: ::c_int = 40;
 pub const SO_PEEK_OFF: ::c_int = 42;
 pub const SO_BUSY_POLL: ::c_int = 46;
 
 extern {
-    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
     pub fn ptrace(request: ::c_int, ...) -> ::c_long;
     pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
     pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(any(target_arch = "x86_64",
                  target_arch = "aarch64",
                  target_arch = "powerpc64"))] {
         mod b64;
         pub use self::b64::*;
     } else if #[cfg(any(target_arch = "x86",
                         target_arch = "mips",
-                        target_arch = "arm"))] {
+                        target_arch = "arm",
+                        target_arch = "powerpc"))] {
         mod b32;
         pub use self::b32::*;
     } else { }
 }
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b32/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b32/mod.rs
index 727bebaca299..5b0142ab89a8 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b32/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b32/mod.rs
@@ -1,10 +1,12 @@
 //! 32-bit specific definitions for linux-like values
 
+use pthread_mutex_t;
+
 pub type c_long = i32;
 pub type c_ulong = u32;
 pub type clock_t = i32;
 pub type time_t = i32;
 pub type suseconds_t = i32;
 pub type ino_t = u32;
 pub type off_t = i32;
 pub type blkcnt_t = i32;
@@ -39,16 +41,32 @@ s! {
         pub st_mtime: ::time_t,
         pub st_mtime_nsec: ::c_long,
         pub st_ctime: ::time_t,
         pub st_ctime_nsec: ::c_long,
         __unused4: ::c_long,
         __unused5: ::c_long,
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        __f_unused: ::c_int,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct pthread_attr_t {
         __size: [u32; 9]
     }
 
     pub struct sigset_t {
         __val: [::c_ulong; 32],
     }
 
@@ -82,16 +100,17 @@ pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
 pub const O_DSYNC: ::c_int = 4096;
 pub const O_FSYNC: ::c_int = 0x101000;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const MAP_GROWSDOWN: ::c_int = 0x0100;
 
 pub const EDEADLK: ::c_int = 35;
 pub const ENAMETOOLONG: ::c_int = 36;
 pub const ENOLCK: ::c_int = 37;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTEMPTY: ::c_int = 39;
@@ -277,16 +296,67 @@ pub const EPOLL_CLOEXEC: ::c_int = 0x80000;
 pub const EFD_CLOEXEC: ::c_int = 0x80000;
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
 
+align_const! {
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+                0, 0, 0,
+            ],
+        };
+}
+
 pub const PTRACE_GETFPREGS: ::c_uint = 14;
 pub const PTRACE_SETFPREGS: ::c_uint = 15;
 pub const PTRACE_GETREGS: ::c_uint = 12;
 pub const PTRACE_SETREGS: ::c_uint = 13;
 
 #[link(name = "util")]
 extern {
     pub fn sysctl(name: *mut ::c_int,
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/aarch64.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/aarch64.rs
index 1a95fcc8a451..2ba27a72b895 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/aarch64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/aarch64.rs
@@ -1,10 +1,12 @@
 //! AArch64-specific definitions for 64-bit linux-like values
 
+use pthread_mutex_t;
+
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type c_char = u8;
 pub type wchar_t = u32;
 pub type nlink_t = u32;
 pub type blksize_t = i32;
 pub type suseconds_t = i64;
 pub type __u64 = ::c_ulonglong;
@@ -64,16 +66,31 @@ s! {
         pub f_ffree: u64,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::__fsword_t,
         pub f_frsize: ::__fsword_t,
         pub f_flags: ::__fsword_t,
         pub f_spare: [::__fsword_t; 4],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct statvfs64 {
         pub f_bsize: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_blocks: u64,
         pub f_bfree: u64,
         pub f_bavail: u64,
         pub f_files: u64,
         pub f_ffree: u64,
@@ -140,16 +157,17 @@ pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
 pub const O_DSYNC: ::c_int = 4096;
 pub const O_FSYNC: ::c_int = 0x101000;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const MAP_GROWSDOWN: ::c_int = 0x0100;
 
 pub const EDEADLK: ::c_int = 35;
 pub const ENAMETOOLONG: ::c_int = 36;
 pub const ENOLCK: ::c_int = 37;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTEMPTY: ::c_int = 39;
@@ -365,16 +383,43 @@ pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
 pub const EPOLL_CLOEXEC: ::c_int = 0x80000;
 
 pub const EFD_CLOEXEC: ::c_int = 0x80000;
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 48;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 8;
 
+align_const! {
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 pub const O_DIRECT: ::c_int = 0x10000;
 pub const O_DIRECTORY: ::c_int = 0x4000;
 pub const O_NOFOLLOW: ::c_int = 0x8000;
 
 pub const MAP_LOCKED: ::c_int = 0x02000;
 pub const MAP_NORESERVE: ::c_int = 0x04000;
 
 pub const EDEADLOCK: ::c_int = 35;
@@ -521,16 +566,17 @@ pub const SYS_fremovexattr: ::c_long = 16;
 pub const SYS_getcwd: ::c_long = 17;
 pub const SYS_lookup_dcookie: ::c_long = 18;
 pub const SYS_eventfd2: ::c_long = 19;
 pub const SYS_epoll_create1: ::c_long = 20;
 pub const SYS_epoll_ctl: ::c_long = 21;
 pub const SYS_epoll_pwait: ::c_long = 22;
 pub const SYS_dup: ::c_long = 23;
 pub const SYS_dup3: ::c_long = 24;
+pub const SYS_fcntl: ::c_long = 25;
 pub const SYS_inotify_init1: ::c_long = 26;
 pub const SYS_inotify_add_watch: ::c_long = 27;
 pub const SYS_inotify_rm_watch: ::c_long = 28;
 pub const SYS_ioctl: ::c_long = 29;
 pub const SYS_ioprio_set: ::c_long = 30;
 pub const SYS_ioprio_get: ::c_long = 31;
 pub const SYS_flock: ::c_long = 32;
 pub const SYS_mknodat: ::c_long = 33;
@@ -553,31 +599,34 @@ pub const SYS_fchmodat: ::c_long = 53;
 pub const SYS_fchownat: ::c_long = 54;
 pub const SYS_fchown: ::c_long = 55;
 pub const SYS_openat: ::c_long = 56;
 pub const SYS_close: ::c_long = 57;
 pub const SYS_vhangup: ::c_long = 58;
 pub const SYS_pipe2: ::c_long = 59;
 pub const SYS_quotactl: ::c_long = 60;
 pub const SYS_getdents64: ::c_long = 61;
+pub const SYS_lseek: ::c_long = 62;
 pub const SYS_read: ::c_long = 63;
 pub const SYS_write: ::c_long = 64;
 pub const SYS_readv: ::c_long = 65;
 pub const SYS_writev: ::c_long = 66;
 pub const SYS_pread64: ::c_long = 67;
 pub const SYS_pwrite64: ::c_long = 68;
 pub const SYS_preadv: ::c_long = 69;
 pub const SYS_pwritev: ::c_long = 70;
 pub const SYS_pselect6: ::c_long = 72;
 pub const SYS_ppoll: ::c_long = 73;
 pub const SYS_signalfd4: ::c_long = 74;
 pub const SYS_vmsplice: ::c_long = 75;
 pub const SYS_splice: ::c_long = 76;
 pub const SYS_tee: ::c_long = 77;
 pub const SYS_readlinkat: ::c_long = 78;
+pub const SYS_newfstatat: ::c_long = 79;
+pub const SYS_fstat: ::c_long = 80;
 pub const SYS_sync: ::c_long = 81;
 pub const SYS_fsync: ::c_long = 82;
 pub const SYS_fdatasync: ::c_long = 83;
 pub const SYS_sync_file_range: ::c_long = 84;
 pub const SYS_timerfd_create: ::c_long = 85;
 pub const SYS_timerfd_settime: ::c_long = 86;
 pub const SYS_timerfd_gettime: ::c_long = 87;
 pub const SYS_utimensat: ::c_long = 88;
@@ -709,16 +758,17 @@ pub const SYS_readahead: ::c_long = 213;
 pub const SYS_brk: ::c_long = 214;
 pub const SYS_munmap: ::c_long = 215;
 pub const SYS_mremap: ::c_long = 216;
 pub const SYS_add_key: ::c_long = 217;
 pub const SYS_request_key: ::c_long = 218;
 pub const SYS_keyctl: ::c_long = 219;
 pub const SYS_clone: ::c_long = 220;
 pub const SYS_execve: ::c_long = 221;
+pub const SYS_mmap: ::c_long = 222;
 pub const SYS_swapon: ::c_long = 224;
 pub const SYS_swapoff: ::c_long = 225;
 pub const SYS_mprotect: ::c_long = 226;
 pub const SYS_msync: ::c_long = 227;
 pub const SYS_mlock: ::c_long = 228;
 pub const SYS_munlock: ::c_long = 229;
 pub const SYS_mlockall: ::c_long = 230;
 pub const SYS_munlockall: ::c_long = 231;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/not_x32.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/not_x32.rs
index fb30a3149065..e3e449807f89 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/not_x32.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/not_x32.rs
@@ -1,14 +1,84 @@
+use pthread_mutex_t;
+
 pub type c_long = i64;
 pub type c_ulong = u64;
 
+s! {
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+}
+
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 
+align_const! {
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 // Syscall table
 
 pub const SYS_read: ::c_long = 0;
 pub const SYS_write: ::c_long = 1;
 pub const SYS_open: ::c_long = 2;
 pub const SYS_close: ::c_long = 3;
 pub const SYS_stat: ::c_long = 4;
 pub const SYS_fstat: ::c_long = 5;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs
index 77f82290fa4f..9dd91f0fdd2c 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/powerpc64.rs
@@ -1,10 +1,12 @@
 //! PowerPC64-specific definitions for 64-bit linux-like values
 
+use pthread_mutex_t;
+
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type c_char = u8;
 pub type wchar_t = i32;
 pub type nlink_t = u64;
 pub type blksize_t = i64;
 pub type suseconds_t = i64;
 pub type __u64 = ::c_ulong;
@@ -62,16 +64,31 @@ s! {
         pub f_ffree: u64,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::__fsword_t,
         pub f_frsize: ::__fsword_t,
         pub f_flags: ::__fsword_t,
         pub f_spare: [::__fsword_t; 4],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct statvfs64 {
         pub f_bsize: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_blocks: u64,
         pub f_bfree: u64,
         pub f_bavail: u64,
         pub f_files: u64,
         pub f_ffree: u64,
@@ -127,16 +144,17 @@ pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
 pub const O_DSYNC: ::c_int = 4096;
 pub const O_FSYNC: ::c_int = 0x101000;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const MAP_GROWSDOWN: ::c_int = 0x0100;
 
 pub const EDEADLK: ::c_int = 35;
 pub const ENAMETOOLONG: ::c_int = 36;
 pub const ENOLCK: ::c_int = 37;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTEMPTY: ::c_int = 39;
@@ -352,16 +370,67 @@ pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
 pub const EPOLL_CLOEXEC: ::c_int = 0x80000;
 
 pub const EFD_CLOEXEC: ::c_int = 0x80000;
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 
+align_const! {
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "little")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    #[cfg(target_endian = "big")]
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 pub const O_DIRECTORY: ::c_int = 0x4000;
 pub const O_NOFOLLOW: ::c_int = 0x8000;
 pub const O_DIRECT: ::c_int = 0x20000;
 
 pub const MAP_LOCKED: ::c_int = 0x00080;
 pub const MAP_NORESERVE: ::c_int = 0x00040;
 
 pub const EDEADLOCK: ::c_int = 58;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/sparc64.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/sparc64.rs
index f3e4fe604d72..34438a73537e 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/sparc64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/sparc64.rs
@@ -1,10 +1,12 @@
 //! SPARC64-specific definitions for 64-bit linux-like values
 
+use pthread_mutex_t;
+
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type c_char = i8;
 pub type wchar_t = i32;
 pub type nlink_t = u32;
 pub type blksize_t = i64;
 pub type suseconds_t = i32;
 pub type __u64 = ::c_ulonglong;
@@ -64,16 +66,31 @@ s! {
         pub f_ffree: u64,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::__fsword_t,
         pub f_frsize: ::__fsword_t,
         pub f_flags: ::__fsword_t,
         pub f_spare: [::__fsword_t; 4],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct statvfs64 {
         pub f_bsize: ::c_ulong,
         pub f_frsize: ::c_ulong,
         pub f_blocks: u64,
         pub f_bfree: u64,
         pub f_bavail: u64,
         pub f_files: u64,
         pub f_ffree: u64,
@@ -140,16 +157,17 @@ pub const O_EXCL: ::c_int = 0x800;
 pub const O_NOCTTY: ::c_int = 0x8000;
 pub const O_NONBLOCK: ::c_int = 0x4000;
 pub const O_SYNC: ::c_int = 0x802000;
 pub const O_RSYNC: ::c_int = 0x802000;
 pub const O_DSYNC: ::c_int = 0x2000;
 pub const O_FSYNC: ::c_int = 0x802000;
 pub const O_NOATIME: ::c_int = 0x200000;
 pub const O_PATH: ::c_int = 0x1000000;
+pub const O_TMPFILE: ::c_int = 0x2000000 | O_DIRECTORY;
 
 pub const MAP_GROWSDOWN: ::c_int = 0x0200;
 
 pub const EDEADLK: ::c_int = 78;
 pub const ENAMETOOLONG: ::c_int = 63;
 pub const ENOLCK: ::c_int = 79;
 pub const ENOSYS: ::c_int = 90;
 pub const ENOTEMPTY: ::c_int = 66;
@@ -237,16 +255,18 @@ pub const SO_RXQ_OVFL: ::c_int = 0x0024;
 pub const SO_PEEK_OFF: ::c_int = 0x0026;
 pub const SO_BUSY_POLL: ::c_int = 0x0030;
 pub const SO_TYPE: ::c_int = 0x1008;
 pub const SO_ERROR: ::c_int = 0x1007;
 pub const SO_DONTROUTE: ::c_int = 16;
 pub const SO_BROADCAST: ::c_int = 32;
 pub const SO_SNDBUF: ::c_int = 0x1001;
 pub const SO_RCVBUF: ::c_int = 0x1002;
+pub const SO_SNDBUFFORCE: ::c_int = 0x100a;
+pub const SO_RCVBUFFORCE: ::c_int = 0x100b;
 pub const SO_DOMAIN: ::c_int = 0x1029;
 pub const SO_KEEPALIVE: ::c_int = 8;
 pub const SO_OOBINLINE: ::c_int = 0x100;
 pub const SO_LINGER: ::c_int = 128;
 pub const SO_REUSEPORT: ::c_int = 0x200;
 pub const SO_ACCEPTCONN: ::c_int = 0x8000;
 
 pub const SA_ONSTACK: ::c_int = 1;
@@ -326,16 +346,40 @@ pub const SA_NOCLDSTOP: ::c_int = 0x00000008;
 
 pub const EPOLL_CLOEXEC: ::c_int = 0x400000;
 
 pub const EFD_CLOEXEC: ::c_int = 0x400000;
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 
+align_const! {
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 pub const O_DIRECTORY: ::c_int = 0o200000;
 pub const O_NOFOLLOW: ::c_int = 0o400000;
 pub const O_DIRECT: ::c_int = 0x100000;
 
 pub const MAP_LOCKED: ::c_int = 0x0100;
 pub const MAP_NORESERVE: ::c_int = 0x00040;
 
 pub const EDEADLOCK: ::c_int = 108;
@@ -344,19 +388,16 @@ pub const SO_PEERCRED: ::c_int = 0x40;
 pub const SO_RCVLOWAT: ::c_int = 0x800;
 pub const SO_SNDLOWAT: ::c_int = 0x1000;
 pub const SO_RCVTIMEO: ::c_int = 0x2000;
 pub const SO_SNDTIMEO: ::c_int = 0x4000;
 
 pub const FIOCLEX: ::c_ulong = 0x20006601;
 pub const FIONBIO: ::c_ulong = 0x8004667e;
 
-pub const SYS_gettid: ::c_long = 143;
-pub const SYS_perf_event_open: ::c_long = 327;
-
 pub const MCL_CURRENT: ::c_int = 0x2000;
 pub const MCL_FUTURE: ::c_int = 0x4000;
 
 pub const SIGSTKSZ: ::size_t = 16384;
 pub const MINSIGSTKSZ: ::size_t = 4096;
 pub const CBAUD: ::tcflag_t = 0x0000100f;
 pub const TAB1: ::c_int = 0x800;
 pub const TAB2: ::c_int = 0x1000;
@@ -404,16 +445,51 @@ pub const OLCUC:  ::tcflag_t = 0o000002;
 pub const NLDLY:  ::tcflag_t = 0o000400;
 pub const CRDLY:  ::tcflag_t = 0o003000;
 pub const TABDLY: ::tcflag_t = 0o014000;
 pub const BSDLY:  ::tcflag_t = 0o020000;
 pub const FFDLY:  ::tcflag_t = 0o100000;
 pub const VTDLY:  ::tcflag_t = 0o040000;
 pub const XTABS:  ::tcflag_t = 0o014000;
 
+pub const B0: ::speed_t = 0o000000;
+pub const B50: ::speed_t = 0o000001;
+pub const B75: ::speed_t = 0o000002;
+pub const B110: ::speed_t = 0o000003;
+pub const B134: ::speed_t = 0o000004;
+pub const B150: ::speed_t = 0o000005;
+pub const B200: ::speed_t = 0o000006;
+pub const B300: ::speed_t = 0o000007;
+pub const B600: ::speed_t = 0o000010;
+pub const B1200: ::speed_t = 0o000011;
+pub const B1800: ::speed_t = 0o000012;
+pub const B2400: ::speed_t = 0o000013;
+pub const B4800: ::speed_t = 0o000014;
+pub const B9600: ::speed_t = 0o000015;
+pub const B19200: ::speed_t = 0o000016;
+pub const B38400: ::speed_t = 0o000017;
+pub const EXTA: ::speed_t = B19200;
+pub const EXTB: ::speed_t = B38400;
+pub const BOTHER: ::speed_t = 0x1000;
+pub const B57600: ::speed_t = 0x1001;
+pub const B115200: ::speed_t = 0x1002;
+pub const B230400: ::speed_t = 0x1003;
+pub const B460800: ::speed_t = 0x1004;
+pub const B76800: ::speed_t = 0x1005;
+pub const B153600: ::speed_t = 0x1006;
+pub const B307200: ::speed_t = 0x1007;
+pub const B614400: ::speed_t = 0x1008;
+pub const B921600: ::speed_t = 0x1009;
+pub const B500000: ::speed_t = 0x100a;
+pub const B576000: ::speed_t = 0x100b;
+pub const B1000000: ::speed_t = 0x100c;
+pub const B1152000: ::speed_t = 0x100d;
+pub const B1500000: ::speed_t = 0x100e;
+pub const B2000000: ::speed_t = 0x100f;
+
 pub const VEOL: usize = 5;
 pub const VEOL2: usize = 6;
 pub const VMIN: usize = 4;
 pub const IEXTEN: ::tcflag_t = 0x8000;
 pub const TOSTOP: ::tcflag_t = 0x100;
 pub const FLUSHO: ::tcflag_t = 0x2000;
 pub const EXTPROC: ::tcflag_t = 0x10000;
 pub const TCGETS: ::c_ulong = 0x40245408;
@@ -430,16 +506,356 @@ pub const TCFLSH: ::c_ulong = 0x20005407;
 pub const TIOCINQ: ::c_ulong = 0x4004667f;
 pub const TIOCGPGRP: ::c_ulong = 0x40047483;
 pub const TIOCSPGRP: ::c_ulong = 0x80047482;
 pub const TIOCOUTQ: ::c_ulong = 0x40047473;
 pub const TIOCGWINSZ: ::c_ulong = 0x40087468;
 pub const TIOCSWINSZ: ::c_ulong = 0x80087467;
 pub const FIONREAD: ::c_ulong = 0x4004667f;
 
+pub const SYS_restart_syscall: ::c_long = 0;
+pub const SYS_exit: ::c_long = 1;
+pub const SYS_fork: ::c_long = 2;
+pub const SYS_read: ::c_long = 3;
+pub const SYS_write: ::c_long = 4;
+pub const SYS_open: ::c_long = 5;
+pub const SYS_close: ::c_long = 6;
+pub const SYS_wait4: ::c_long = 7;
+pub const SYS_creat: ::c_long = 8;
+pub const SYS_link: ::c_long = 9;
+pub const SYS_unlink: ::c_long = 10;
+pub const SYS_execv: ::c_long = 11;
+pub const SYS_chdir: ::c_long = 12;
+pub const SYS_chown: ::c_long = 13;
+pub const SYS_mknod: ::c_long = 14;
+pub const SYS_chmod: ::c_long = 15;
+pub const SYS_lchown: ::c_long = 16;
+pub const SYS_brk: ::c_long = 17;
+pub const SYS_perfctr: ::c_long = 18;
+pub const SYS_lseek: ::c_long = 19;
+pub const SYS_getpid: ::c_long = 20;
+pub const SYS_capget: ::c_long = 21;
+pub const SYS_capset: ::c_long = 22;
+pub const SYS_setuid: ::c_long = 23;
+pub const SYS_getuid: ::c_long = 24;
+pub const SYS_vmsplice: ::c_long = 25;
+pub const SYS_ptrace: ::c_long = 26;
+pub const SYS_alarm: ::c_long = 27;
+pub const SYS_sigaltstack: ::c_long = 28;
+pub const SYS_pause: ::c_long = 29;
+pub const SYS_utime: ::c_long = 30;
+pub const SYS_access: ::c_long = 33;
+pub const SYS_nice: ::c_long = 34;
+pub const SYS_sync: ::c_long = 36;
+pub const SYS_kill: ::c_long = 37;
+pub const SYS_stat: ::c_long = 38;
+pub const SYS_sendfile: ::c_long = 39;
+pub const SYS_lstat: ::c_long = 40;
+pub const SYS_dup: ::c_long = 41;
+pub const SYS_pipe: ::c_long = 42;
+pub const SYS_times: ::c_long = 43;
+pub const SYS_umount2: ::c_long = 45;
+pub const SYS_setgid: ::c_long = 46;
+pub const SYS_getgid: ::c_long = 47;
+pub const SYS_signal: ::c_long = 48;
+pub const SYS_geteuid: ::c_long = 49;
+pub const SYS_getegid: ::c_long = 50;
+pub const SYS_acct: ::c_long = 51;
+pub const SYS_memory_ordering: ::c_long = 52;
+pub const SYS_ioctl: ::c_long = 54;
+pub const SYS_reboot: ::c_long = 55;
+pub const SYS_symlink: ::c_long = 57;
+pub const SYS_readlink: ::c_long = 58;
+pub const SYS_execve: ::c_long = 59;
+pub const SYS_umask: ::c_long = 60;
+pub const SYS_chroot: ::c_long = 61;
+pub const SYS_fstat: ::c_long = 62;
+pub const SYS_fstat64: ::c_long = 63;
+pub const SYS_getpagesize: ::c_long = 64;
+pub const SYS_msync: ::c_long = 65;
+pub const SYS_vfork: ::c_long = 66;
+pub const SYS_pread64: ::c_long = 67;
+pub const SYS_pwrite64: ::c_long = 68;
+pub const SYS_mmap: ::c_long = 71;
+pub const SYS_munmap: ::c_long = 73;
+pub const SYS_mprotect: ::c_long = 74;
+pub const SYS_madvise: ::c_long = 75;
+pub const SYS_vhangup: ::c_long = 76;
+pub const SYS_mincore: ::c_long = 78;
+pub const SYS_getgroups: ::c_long = 79;
+pub const SYS_setgroups: ::c_long = 80;
+pub const SYS_getpgrp: ::c_long = 81;
+pub const SYS_setitimer: ::c_long = 83;
+pub const SYS_swapon: ::c_long = 85;
+pub const SYS_getitimer: ::c_long = 86;
+pub const SYS_sethostname: ::c_long = 88;
+pub const SYS_dup2: ::c_long = 90;
+pub const SYS_fcntl: ::c_long = 92;
+pub const SYS_select: ::c_long = 93;
+pub const SYS_fsync: ::c_long = 95;
+pub const SYS_setpriority: ::c_long = 96;
+pub const SYS_socket: ::c_long = 97;
+pub const SYS_connect: ::c_long = 98;
+pub const SYS_accept: ::c_long = 99;
+pub const SYS_getpriority: ::c_long = 100;
+pub const SYS_rt_sigreturn: ::c_long = 101;
+pub const SYS_rt_sigaction: ::c_long = 102;
+pub const SYS_rt_sigprocmask: ::c_long = 103;
+pub const SYS_rt_sigpending: ::c_long = 104;
+pub const SYS_rt_sigtimedwait: ::c_long = 105;
+pub const SYS_rt_sigqueueinfo: ::c_long = 106;
+pub const SYS_rt_sigsuspend: ::c_long = 107;
+pub const SYS_setresuid: ::c_long = 108;
+pub const SYS_getresuid: ::c_long = 109;
+pub const SYS_setresgid: ::c_long = 110;
+pub const SYS_getresgid: ::c_long = 111;
+pub const SYS_recvmsg: ::c_long = 113;
+pub const SYS_sendmsg: ::c_long = 114;
+pub const SYS_gettimeofday: ::c_long = 116;
+pub const SYS_getrusage: ::c_long = 117;
+pub const SYS_getsockopt: ::c_long = 118;
+pub const SYS_getcwd: ::c_long = 119;
+pub const SYS_readv: ::c_long = 120;
+pub const SYS_writev: ::c_long = 121;
+pub const SYS_settimeofday: ::c_long = 122;
+pub const SYS_fchown: ::c_long = 123;
+pub const SYS_fchmod: ::c_long = 124;
+pub const SYS_recvfrom: ::c_long = 125;
+pub const SYS_setreuid: ::c_long = 126;
+pub const SYS_setregid: ::c_long = 127;
+pub const SYS_rename: ::c_long = 128;
+pub const SYS_truncate: ::c_long = 129;
+pub const SYS_ftruncate: ::c_long = 130;
+pub const SYS_flock: ::c_long = 131;
+pub const SYS_lstat64: ::c_long = 132;
+pub const SYS_sendto: ::c_long = 133;
+pub const SYS_shutdown: ::c_long = 134;
+pub const SYS_socketpair: ::c_long = 135;
+pub const SYS_mkdir: ::c_long = 136;
+pub const SYS_rmdir: ::c_long = 137;
+pub const SYS_utimes: ::c_long = 138;
+pub const SYS_stat64: ::c_long = 139;
+pub const SYS_sendfile64: ::c_long = 140;
+pub const SYS_getpeername: ::c_long = 141;
+pub const SYS_futex: ::c_long = 142;
+pub const SYS_gettid: ::c_long = 143;
+pub const SYS_getrlimit: ::c_long = 144;
+pub const SYS_setrlimit: ::c_long = 145;
+pub const SYS_pivot_root: ::c_long = 146;
+pub const SYS_prctl: ::c_long = 147;
+pub const SYS_pciconfig_read: ::c_long = 148;
+pub const SYS_pciconfig_write: ::c_long = 149;
+pub const SYS_getsockname: ::c_long = 150;
+pub const SYS_inotify_init: ::c_long = 151;
+pub const SYS_inotify_add_watch: ::c_long = 152;
+pub const SYS_poll: ::c_long = 153;
+pub const SYS_getdents64: ::c_long = 154;
+pub const SYS_inotify_rm_watch: ::c_long = 156;
+pub const SYS_statfs: ::c_long = 157;
+pub const SYS_fstatfs: ::c_long = 158;
+pub const SYS_umount: ::c_long = 159;
+pub const SYS_sched_set_affinity: ::c_long = 160;
+pub const SYS_sched_get_affinity: ::c_long = 161;
+pub const SYS_getdomainname: ::c_long = 162;
+pub const SYS_setdomainname: ::c_long = 163;
+pub const SYS_utrap_install: ::c_long = 164;
+pub const SYS_quotactl: ::c_long = 165;
+pub const SYS_set_tid_address: ::c_long = 166;
+pub const SYS_mount: ::c_long = 167;
+pub const SYS_ustat: ::c_long = 168;
+pub const SYS_setxattr: ::c_long = 169;
+pub const SYS_lsetxattr: ::c_long = 170;
+pub const SYS_fsetxattr: ::c_long = 171;
+pub const SYS_getxattr: ::c_long = 172;
+pub const SYS_lgetxattr: ::c_long = 173;
+pub const SYS_getdents: ::c_long = 174;
+pub const SYS_setsid: ::c_long = 175;
+pub const SYS_fchdir: ::c_long = 176;
+pub const SYS_fgetxattr: ::c_long = 177;
+pub const SYS_listxattr: ::c_long = 178;
+pub const SYS_llistxattr: ::c_long = 179;
+pub const SYS_flistxattr: ::c_long = 180;
+pub const SYS_removexattr: ::c_long = 181;
+pub const SYS_lremovexattr: ::c_long = 182;
+pub const SYS_sigpending: ::c_long = 183;
+pub const SYS_query_module: ::c_long = 184;
+pub const SYS_setpgid: ::c_long = 185;
+pub const SYS_fremovexattr: ::c_long = 186;
+pub const SYS_tkill: ::c_long = 187;
+pub const SYS_exit_group: ::c_long = 188;
+pub const SYS_uname: ::c_long = 189;
+pub const SYS_init_module: ::c_long = 190;
+pub const SYS_personality: ::c_long = 191;
+pub const SYS_remap_file_pages: ::c_long = 192;
+pub const SYS_epoll_create: ::c_long = 193;
+pub const SYS_epoll_ctl: ::c_long = 194;
+pub const SYS_epoll_wait: ::c_long = 195;
+pub const SYS_ioprio_set: ::c_long = 196;
+pub const SYS_getppid: ::c_long = 197;
+pub const SYS_sigaction: ::c_long = 198;
+pub const SYS_sgetmask: ::c_long = 199;
+pub const SYS_ssetmask: ::c_long = 200;
+pub const SYS_sigsuspend: ::c_long = 201;
+pub const SYS_oldlstat: ::c_long = 202;
+pub const SYS_uselib: ::c_long = 203;
+pub const SYS_readdir: ::c_long = 204;
+pub const SYS_readahead: ::c_long = 205;
+pub const SYS_socketcall: ::c_long = 206;
+pub const SYS_syslog: ::c_long = 207;
+pub const SYS_lookup_dcookie: ::c_long = 208;
+pub const SYS_fadvise64: ::c_long = 209;
+pub const SYS_fadvise64_64: ::c_long = 210;
+pub const SYS_tgkill: ::c_long = 211;
+pub const SYS_waitpid: ::c_long = 212;
+pub const SYS_swapoff: ::c_long = 213;
+pub const SYS_sysinfo: ::c_long = 214;
+pub const SYS_ipc: ::c_long = 215;
+pub const SYS_sigreturn: ::c_long = 216;
+pub const SYS_clone: ::c_long = 217;
+pub const SYS_ioprio_get: ::c_long = 218;
+pub const SYS_adjtimex: ::c_long = 219;
+pub const SYS_sigprocmask: ::c_long = 220;
+pub const SYS_create_module: ::c_long = 221;
+pub const SYS_delete_module: ::c_long = 222;
+pub const SYS_get_kernel_syms: ::c_long = 223;
+pub const SYS_getpgid: ::c_long = 224;
+pub const SYS_bdflush: ::c_long = 225;
+pub const SYS_sysfs: ::c_long = 226;
+pub const SYS_afs_syscall: ::c_long = 227;
+pub const SYS_setfsuid: ::c_long = 228;
+pub const SYS_setfsgid: ::c_long = 229;
+pub const SYS__newselect: ::c_long = 230;
+pub const SYS_splice: ::c_long = 232;
+pub const SYS_stime: ::c_long = 233;
+pub const SYS_statfs64: ::c_long = 234;
+pub const SYS_fstatfs64: ::c_long = 235;
+pub const SYS__llseek: ::c_long = 236;
+pub const SYS_mlock: ::c_long = 237;
+pub const SYS_munlock: ::c_long = 238;
+pub const SYS_mlockall: ::c_long = 239;
+pub const SYS_munlockall: ::c_long = 240;
+pub const SYS_sched_setparam: ::c_long = 241;
+pub const SYS_sched_getparam: ::c_long = 242;
+pub const SYS_sched_setscheduler: ::c_long =243;
+pub const SYS_sched_getscheduler: ::c_long =244;
+pub const SYS_sched_yield: ::c_long = 245;
+pub const SYS_sched_get_priority_max: ::c_long =246;
+pub const SYS_sched_get_priority_min: ::c_long =247;
+pub const SYS_sched_rr_get_interval: ::c_long = 248;
+pub const SYS_nanosleep: ::c_long = 249;
+pub const SYS_mremap: ::c_long = 250;
+pub const SYS__sysctl: ::c_long = 251;
+pub const SYS_getsid: ::c_long = 252;
+pub const SYS_fdatasync: ::c_long = 253;
+pub const SYS_nfsservctl: ::c_long = 254;
+pub const SYS_sync_file_range: ::c_long = 255;
+pub const SYS_clock_settime: ::c_long = 256;
+pub const SYS_clock_gettime: ::c_long = 257;
+pub const SYS_clock_getres: ::c_long = 258;
+pub const SYS_clock_nanosleep: ::c_long = 259;
+pub const SYS_sched_getaffinity: ::c_long = 260;
+pub const SYS_sched_setaffinity: ::c_long = 261;
+pub const SYS_timer_settime: ::c_long = 262;
+pub const SYS_timer_gettime: ::c_long = 263;
+pub const SYS_timer_getoverrun: ::c_long = 264;
+pub const SYS_timer_delete: ::c_long = 265;
+pub const SYS_timer_create: ::c_long = 266;
+pub const SYS_io_setup: ::c_long = 268;
+pub const SYS_io_destroy: ::c_long = 269;
+pub const SYS_io_submit: ::c_long = 270;
+pub const SYS_io_cancel: ::c_long = 271;
+pub const SYS_io_getevents: ::c_long = 272;
+pub const SYS_mq_open: ::c_long = 273;
+pub const SYS_mq_unlink: ::c_long = 274;
+pub const SYS_mq_timedsend: ::c_long = 275;
+pub const SYS_mq_timedreceive: ::c_long = 276;
+pub const SYS_mq_notify: ::c_long = 277;
+pub const SYS_mq_getsetattr: ::c_long = 278;
+pub const SYS_waitid: ::c_long = 279;
+pub const SYS_tee: ::c_long = 280;
+pub const SYS_add_key: ::c_long = 281;
+pub const SYS_request_key: ::c_long = 282;
+pub const SYS_keyctl: ::c_long = 283;
+pub const SYS_openat: ::c_long = 284;
+pub const SYS_mkdirat: ::c_long = 285;
+pub const SYS_mknodat: ::c_long = 286;
+pub const SYS_fchownat: ::c_long = 287;
+pub const SYS_futimesat: ::c_long = 288;
+pub const SYS_fstatat64: ::c_long = 289;
+pub const SYS_unlinkat: ::c_long = 290;
+pub const SYS_renameat: ::c_long = 291;
+pub const SYS_linkat: ::c_long = 292;
+pub const SYS_symlinkat: ::c_long = 293;
+pub const SYS_readlinkat: ::c_long = 294;
+pub const SYS_fchmodat: ::c_long = 295;
+pub const SYS_faccessat: ::c_long = 296;
+pub const SYS_pselect6: ::c_long = 297;
+pub const SYS_ppoll: ::c_long = 298;
+pub const SYS_unshare: ::c_long = 299;
+pub const SYS_set_robust_list: ::c_long = 300;
+pub const SYS_get_robust_list: ::c_long = 301;
+pub const SYS_migrate_pages: ::c_long =302;
+pub const SYS_mbind: ::c_long = 303;
+pub const SYS_get_mempolicy: ::c_long = 304;
+pub const SYS_set_mempolicy: ::c_long = 305;
+pub const SYS_kexec_load: ::c_long = 306;
+pub const SYS_move_pages: ::c_long = 307;
+pub const SYS_getcpu: ::c_long = 308;
+pub const SYS_epoll_pwait: ::c_long = 309;
+pub const SYS_utimensat: ::c_long = 310;
+pub const SYS_signalfd: ::c_long = 311;
+pub const SYS_timerfd_create: ::c_long = 312;
+pub const SYS_eventfd: ::c_long = 313;
+pub const SYS_fallocate: ::c_long = 314;
+pub const SYS_timerfd_settime: ::c_long = 315;
+pub const SYS_timerfd_gettime: ::c_long = 316;
+pub const SYS_signalfd4: ::c_long = 317;
+pub const SYS_eventfd2: ::c_long = 318;
+pub const SYS_epoll_create1: ::c_long = 319;
+pub const SYS_dup3: ::c_long = 320;
+pub const SYS_pipe2: ::c_long = 321;
+pub const SYS_inotify_init1: ::c_long = 322;
+pub const SYS_accept4: ::c_long = 323;
+pub const SYS_preadv: ::c_long = 324;
+pub const SYS_pwritev: ::c_long = 325;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 326;
+pub const SYS_perf_event_open: ::c_long = 327;
+pub const SYS_recvmmsg: ::c_long = 328;
+pub const SYS_fanotify_init: ::c_long = 329;
+pub const SYS_fanotify_mark: ::c_long = 330;
+pub const SYS_prlimit64: ::c_long = 331;
+pub const SYS_name_to_handle_at: ::c_long = 332;
+pub const SYS_open_by_handle_at: ::c_long = 333;
+pub const SYS_clock_adjtime: ::c_long = 334;
+pub const SYS_syncfs: ::c_long = 335;
+pub const SYS_sendmmsg: ::c_long = 336;
+pub const SYS_setns: ::c_long = 337;
+pub const SYS_process_vm_readv: ::c_long = 338;
+pub const SYS_process_vm_writev: ::c_long = 339;
+pub const SYS_kern_features: ::c_long = 340;
+pub const SYS_kcmp: ::c_long = 341;
+pub const SYS_finit_module: ::c_long = 342;
+pub const SYS_sched_setattr: ::c_long = 343;
+pub const SYS_sched_getattr: ::c_long = 344;
+pub const SYS_renameat2: ::c_long = 345;
+pub const SYS_seccomp: ::c_long = 346;
+pub const SYS_getrandom: ::c_long = 347;
+pub const SYS_memfd_create: ::c_long = 348;
+pub const SYS_bpf: ::c_long = 349;
+pub const SYS_execveat: ::c_long = 350;
+pub const SYS_membarrier: ::c_long = 351;
+pub const SYS_userfaultfd: ::c_long = 352;
+pub const SYS_bind: ::c_long = 353;
+pub const SYS_listen: ::c_long = 354;
+pub const SYS_setsockopt: ::c_long = 355;
+pub const SYS_mlock2: ::c_long = 356;
+pub const SYS_copy_file_range: ::c_long = 357;
+pub const SYS_preadv2: ::c_long = 358;
+pub const SYS_pwritev2: ::c_long = 359;
+
 #[link(name = "util")]
 extern {
     pub fn sysctl(name: *mut ::c_int,
                   namelen: ::c_int,
                   oldp: *mut ::c_void,
                   oldlenp: *mut ::size_t,
                   newp: *mut ::c_void,
                   newlen: ::size_t)
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x32.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x32.rs
index 2e97061fba7d..d88dbafed83c 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x32.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x32.rs
@@ -1,14 +1,57 @@
+use pthread_mutex_t;
+
 pub type c_long = i32;
 pub type c_ulong = u32;
 
+s! {
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+}
+
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 44;
 
+align_const! {
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 // Syscall table
 
 pub const __X32_SYSCALL_BIT: ::c_long = 0x40000000;
 
 pub const SYS_read: ::c_long = __X32_SYSCALL_BIT + 0;
 pub const SYS_write: ::c_long = __X32_SYSCALL_BIT + 1;
 pub const SYS_open: ::c_long = __X32_SYSCALL_BIT + 2;
 pub const SYS_close: ::c_long = __X32_SYSCALL_BIT + 3;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x86_64.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x86_64.rs
index f64332511337..7596eba492e7 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x86_64.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/b64/x86_64.rs
@@ -244,16 +244,17 @@ pub const O_EXCL: ::c_int = 128;
 pub const O_NOCTTY: ::c_int = 256;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const O_SYNC: ::c_int = 1052672;
 pub const O_RSYNC: ::c_int = 1052672;
 pub const O_DSYNC: ::c_int = 4096;
 pub const O_FSYNC: ::c_int = 0x101000;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const MAP_GROWSDOWN: ::c_int = 0x0100;
 
 pub const EDEADLK: ::c_int = 35;
 pub const ENAMETOOLONG: ::c_int = 36;
 pub const ENOLCK: ::c_int = 37;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTEMPTY: ::c_int = 39;
@@ -421,16 +422,20 @@ pub const PTRACE_DETACH: ::c_uint = 17;
 pub const EFD_NONBLOCK: ::c_int = 0x800;
 
 pub const F_GETLK: ::c_int = 5;
 pub const F_GETOWN: ::c_int = 9;
 pub const F_SETOWN: ::c_int = 8;
 pub const F_SETLK: ::c_int = 6;
 pub const F_SETLKW: ::c_int = 7;
 
+pub const F_RDLCK: ::c_int = 0;
+pub const F_WRLCK: ::c_int = 1;
+pub const F_UNLCK: ::c_int = 2;
+
 pub const SFD_NONBLOCK: ::c_int = 0x0800;
 
 pub const TIOCEXCL: ::c_ulong = 0x540C;
 pub const TIOCNXCL: ::c_ulong = 0x540D;
 pub const TIOCSCTTY: ::c_ulong = 0x540E;
 pub const TIOCSTI: ::c_ulong = 0x5412;
 pub const TIOCMGET: ::c_ulong = 0x5415;
 pub const TIOCMBIS: ::c_ulong = 0x5416;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/other/mod.rs b/third_party/rust/libc/src/unix/notbsd/linux/other/mod.rs
index ad54ecf571bb..93b710b8df09 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/other/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/other/mod.rs
@@ -99,22 +99,16 @@ s! {
 
         __unused1: *mut ::c_void,
         __unused2: *mut ::c_void,
         __unused3: *mut ::c_void,
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
     }
 
-    pub struct ucred {
-        pub pid: ::pid_t,
-        pub uid: ::uid_t,
-        pub gid: ::gid_t,
-    }
-
     pub struct statfs {
         pub f_type: __fsword_t,
         pub f_bsize: __fsword_t,
         pub f_blocks: ::fsblkcnt_t,
         pub f_bfree: ::fsblkcnt_t,
         pub f_bavail: ::fsblkcnt_t,
 
         pub f_files: ::fsfilcnt_t,
@@ -159,23 +153,100 @@ s! {
         pub l_type: ::c_short,
         pub l_whence: ::c_short,
         pub l_start: ::off_t,
         pub l_len: ::off_t,
         pub l_pid: ::pid_t,
     }
 
     // FIXME this is actually a union
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t {
         #[cfg(target_pointer_width = "32")]
         __size: [::c_char; 16],
         #[cfg(target_pointer_width = "64")]
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
+
+    pub struct mallinfo {
+        pub arena: ::c_int,
+        pub ordblks: ::c_int,
+        pub smblks: ::c_int,
+        pub hblks: ::c_int,
+        pub hblkhd: ::c_int,
+        pub usmblks: ::c_int,
+        pub fsmblks: ::c_int,
+        pub uordblks: ::c_int,
+        pub fordblks: ::c_int,
+        pub keepcost: ::c_int,
+    }
+
+    pub struct nlmsghdr {
+        pub nlmsg_len: u32,
+        pub nlmsg_type: u16,
+        pub nlmsg_flags: u16,
+        pub nlmsg_seq: u32,
+        pub nlmsg_pid: u32,
+    }
+
+    pub struct nlmsgerr {
+        pub error: ::c_int,
+        pub msg: nlmsghdr,
+    }
+
+    pub struct nl_pktinfo {
+        pub group: u32,
+    }
+
+    pub struct nl_mmap_req {
+        pub nm_block_size: ::c_uint,
+        pub nm_block_nr: ::c_uint,
+        pub nm_frame_size: ::c_uint,
+        pub nm_frame_nr: ::c_uint,
+    }
+
+    pub struct nl_mmap_hdr {
+        pub nm_status: ::c_uint,
+        pub nm_len: ::c_uint,
+        pub nm_group: u32,
+        pub nm_pid: u32,
+        pub nm_uid: u32,
+        pub nm_gid: u32,
+    }
+
+    pub struct nlattr {
+        pub nla_len: u16,
+        pub nla_type: u16,
+    }
+
+    pub struct rtentry {
+        pub rt_pad1: ::c_ulong,
+        pub rt_dst: ::sockaddr,
+        pub rt_gateway: ::sockaddr,
+        pub rt_genmask: ::sockaddr,
+        pub rt_flags: ::c_ushort,
+        pub rt_pad2: ::c_short,
+        pub rt_pad3: ::c_ulong,
+        pub rt_tos: ::c_uchar,
+        pub rt_class: ::c_uchar,
+        #[cfg(target_pointer_width = "64")]
+        pub rt_pad4: [::c_short; 3usize],
+        #[cfg(not(target_pointer_width = "64"))]
+        pub rt_pad4: ::c_short,
+        pub rt_metric: ::c_short,
+        pub rt_dev: *mut ::c_char,
+        pub rt_mtu: ::c_ulong,
+        pub rt_window: ::c_ulong,
+        pub rt_irtt: ::c_ushort,
+    }
 }
 
 pub const __UT_LINESIZE: usize = 32;
 pub const __UT_NAMESIZE: usize = 32;
 pub const __UT_HOSTSIZE: usize = 256;
 pub const EMPTY: ::c_short = 0;
 pub const RUN_LVL: ::c_short = 1;
 pub const BOOT_TIME: ::c_short = 2;
@@ -505,64 +576,281 @@ pub const NLM_F_MATCH: ::c_int = 0x200;
 pub const NLM_F_ATOMIC: ::c_int = 0x400;
 pub const NLM_F_DUMP: ::c_int = NLM_F_ROOT | NLM_F_MATCH;
 
 pub const NLM_F_REPLACE: ::c_int = 0x100;
 pub const NLM_F_EXCL: ::c_int = 0x200;
 pub const NLM_F_CREATE: ::c_int = 0x400;
 pub const NLM_F_APPEND: ::c_int = 0x800;
 
-pub const NLMSG_NOOP: ::c_int = 0x1;
-pub const NLMSG_ERROR: ::c_int = 0x2;
-pub const NLMSG_DONE: ::c_int = 0x3;
-pub const NLMSG_OVERRUN: ::c_int = 0x4;
-pub const NLMSG_MIN_TYPE: ::c_int = 0x10;
-
 pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1;
 pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2;
 pub const NETLINK_PKTINFO: ::c_int = 3;
 pub const NETLINK_BROADCAST_ERROR: ::c_int = 4;
 pub const NETLINK_NO_ENOBUFS: ::c_int = 5;
 pub const NETLINK_RX_RING: ::c_int = 6;
 pub const NETLINK_TX_RING: ::c_int = 7;
 pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8;
 pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9;
 pub const NETLINK_CAP_ACK: ::c_int = 10;
 
 pub const NLA_F_NESTED: ::c_int = 1 << 15;
 pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14;
 pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER);
 
+pub const NLA_ALIGNTO: ::c_int = 4;
+
+pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10;
+
+pub const GENL_ID_VFS_DQUOT: ::c_int = ::NLMSG_MIN_TYPE + 1;
+pub const GENL_ID_PMCRAID: ::c_int = ::NLMSG_MIN_TYPE + 2;
+
 pub const TIOCM_LE: ::c_int = 0x001;
 pub const TIOCM_DTR: ::c_int = 0x002;
 pub const TIOCM_RTS: ::c_int = 0x004;
 pub const TIOCM_ST: ::c_int = 0x008;
 pub const TIOCM_SR: ::c_int = 0x010;
 pub const TIOCM_CTS: ::c_int = 0x020;
 pub const TIOCM_CAR: ::c_int = 0x040;
 pub const TIOCM_RNG: ::c_int = 0x080;
 pub const TIOCM_DSR: ::c_int = 0x100;
 pub const TIOCM_CD: ::c_int = TIOCM_CAR;
 pub const TIOCM_RI: ::c_int = TIOCM_RNG;
 
+pub const NF_NETDEV_INGRESS: ::c_int = 0;
+pub const NF_NETDEV_NUMHOOKS: ::c_int = 1;
+
+pub const NFPROTO_INET: ::c_int = 1;
+pub const NFPROTO_NETDEV: ::c_int = 5;
+
+// linux/netfilter/nf_tables.h
+cfg_if!{
+    if #[cfg(any(target_arch = "arm", target_arch = "powerpc",
+                 target_arch = "powerpc64", target_arch = "aarch64"))] {
+        pub const NFT_TABLE_MAXNAMELEN: ::c_int = 32;
+        pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 32;
+        pub const NFT_SET_MAXNAMELEN: ::c_int = 32;
+        pub const NFT_OBJ_MAXNAMELEN: ::c_int = 32;
+    } else if #[cfg(target_arch = "sparc64")] {
+        pub const NFT_TABLE_MAXNAMELEN: ::c_int = 32;
+        pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 32;
+        pub const NFT_SET_MAXNAMELEN: ::c_int = 32;
+    } else {
+        pub const NFT_TABLE_MAXNAMELEN: ::c_int = 256;
+        pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 256;
+        pub const NFT_SET_MAXNAMELEN: ::c_int = 256;
+        pub const NFT_OBJ_MAXNAMELEN: ::c_int = 256;
+    }
+}
+pub const NFT_USERDATA_MAXLEN: ::c_int = 256;
+
+pub const NFT_REG_VERDICT: ::c_int = 0;
+pub const NFT_REG_1: ::c_int = 1;
+pub const NFT_REG_2: ::c_int = 2;
+pub const NFT_REG_3: ::c_int = 3;
+pub const NFT_REG_4: ::c_int = 4;
+pub const __NFT_REG_MAX: ::c_int = 5;
+pub const NFT_REG32_00: ::c_int = 8;
+pub const NFT_REG32_01: ::c_int = 9;
+pub const NFT_REG32_02: ::c_int = 10;
+pub const NFT_REG32_03: ::c_int = 11;
+pub const NFT_REG32_04: ::c_int = 12;
+pub const NFT_REG32_05: ::c_int = 13;
+pub const NFT_REG32_06: ::c_int = 14;
+pub const NFT_REG32_07: ::c_int = 15;
+pub const NFT_REG32_08: ::c_int = 16;
+pub const NFT_REG32_09: ::c_int = 17;
+pub const NFT_REG32_10: ::c_int = 18;
+pub const NFT_REG32_11: ::c_int = 19;
+pub const NFT_REG32_12: ::c_int = 20;
+pub const NFT_REG32_13: ::c_int = 21;
+pub const NFT_REG32_14: ::c_int = 22;
+pub const NFT_REG32_15: ::c_int = 23;
+
+pub const NFT_REG_SIZE: ::c_int = 16;
+pub const NFT_REG32_SIZE: ::c_int = 4;
+
+pub const NFT_CONTINUE: ::c_int = -1;
+pub const NFT_BREAK: ::c_int = -2;
+pub const NFT_JUMP: ::c_int = -3;
+pub const NFT_GOTO: ::c_int = -4;
+pub const NFT_RETURN: ::c_int = -5;
+
+pub const NFT_MSG_NEWTABLE: ::c_int = 0;
+pub const NFT_MSG_GETTABLE: ::c_int = 1;
+pub const NFT_MSG_DELTABLE: ::c_int = 2;
+pub const NFT_MSG_NEWCHAIN: ::c_int = 3;
+pub const NFT_MSG_GETCHAIN: ::c_int = 4;
+pub const NFT_MSG_DELCHAIN: ::c_int = 5;
+pub const NFT_MSG_NEWRULE: ::c_int = 6;
+pub const NFT_MSG_GETRULE: ::c_int = 7;
+pub const NFT_MSG_DELRULE: ::c_int = 8;
+pub const NFT_MSG_NEWSET: ::c_int = 9;
+pub const NFT_MSG_GETSET: ::c_int = 10;
+pub const NFT_MSG_DELSET: ::c_int = 11;
+pub const NFT_MSG_NEWSETELEM: ::c_int = 12;
+pub const NFT_MSG_GETSETELEM: ::c_int = 13;
+pub const NFT_MSG_DELSETELEM: ::c_int = 14;
+pub const NFT_MSG_NEWGEN: ::c_int = 15;
+pub const NFT_MSG_GETGEN: ::c_int = 16;
+pub const NFT_MSG_TRACE: ::c_int = 17;
+cfg_if! {
+    if #[cfg(not(target_arch = "sparc64"))] {
+        pub const NFT_MSG_NEWOBJ: ::c_int = 18;
+        pub const NFT_MSG_GETOBJ: ::c_int = 19;
+        pub const NFT_MSG_DELOBJ: ::c_int = 20;
+        pub const NFT_MSG_GETOBJ_RESET: ::c_int = 21;
+        pub const NFT_MSG_MAX: ::c_int = 22;
+    } else {
+        pub const NFT_MSG_MAX: ::c_int = 18;
+    }
+}
+
+pub const NFT_SET_ANONYMOUS: ::c_int = 0x1;
+pub const NFT_SET_CONSTANT: ::c_int = 0x2;
+pub const NFT_SET_INTERVAL: ::c_int = 0x4;
+pub const NFT_SET_MAP: ::c_int = 0x8;
+pub const NFT_SET_TIMEOUT: ::c_int = 0x10;
+pub const NFT_SET_EVAL: ::c_int = 0x20;
+
+pub const NFT_SET_POL_PERFORMANCE: ::c_int = 0;
+pub const NFT_SET_POL_MEMORY: ::c_int = 1;
+
+pub const NFT_SET_ELEM_INTERVAL_END: ::c_int = 0x1;
+
+pub const NFT_DATA_VALUE: ::c_uint = 0;
+pub const NFT_DATA_VERDICT: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_RESERVED_MASK: ::c_uint = 0xffffff00;
+
+pub const NFT_DATA_VALUE_MAXLEN: ::c_int = 64;
+
+pub const NFT_BYTEORDER_NTOH: ::c_int = 0;
+pub const NFT_BYTEORDER_HTON: ::c_int = 1;
+
+pub const NFT_CMP_EQ: ::c_int = 0;
+pub const NFT_CMP_NEQ: ::c_int = 1;
+pub const NFT_CMP_LT: ::c_int = 2;
+pub const NFT_CMP_LTE: ::c_int = 3;
+pub const NFT_CMP_GT: ::c_int = 4;
+pub const NFT_CMP_GTE: ::c_int = 5;
+
+pub const NFT_RANGE_EQ: ::c_int = 0;
+pub const NFT_RANGE_NEQ: ::c_int = 1;
+
+pub const NFT_LOOKUP_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_DYNSET_OP_ADD: ::c_int = 0;
+pub const NFT_DYNSET_OP_UPDATE: ::c_int = 1;
+
+pub const NFT_DYNSET_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_PAYLOAD_LL_HEADER: ::c_int = 0;
+pub const NFT_PAYLOAD_NETWORK_HEADER: ::c_int = 1;
+pub const NFT_PAYLOAD_TRANSPORT_HEADER: ::c_int = 2;
+
+pub const NFT_PAYLOAD_CSUM_NONE: ::c_int = 0;
+pub const NFT_PAYLOAD_CSUM_INET: ::c_int = 1;
+
+pub const NFT_META_LEN: ::c_int = 0;
+pub const NFT_META_PROTOCOL: ::c_int = 1;
+pub const NFT_META_PRIORITY: ::c_int = 2;
+pub const NFT_META_MARK: ::c_int = 3;
+pub const NFT_META_IIF: ::c_int = 4;
+pub const NFT_META_OIF: ::c_int = 5;
+pub const NFT_META_IIFNAME: ::c_int = 6;
+pub const NFT_META_OIFNAME: ::c_int = 7;
+pub const NFT_META_IIFTYPE: ::c_int = 8;
+pub const NFT_META_OIFTYPE: ::c_int = 9;
+pub const NFT_META_SKUID: ::c_int = 10;
+pub const NFT_META_SKGID: ::c_int = 11;
+pub const NFT_META_NFTRACE: ::c_int = 12;
+pub const NFT_META_RTCLASSID: ::c_int = 13;
+pub const NFT_META_SECMARK: ::c_int = 14;
+pub const NFT_META_NFPROTO: ::c_int = 15;
+pub const NFT_META_L4PROTO: ::c_int = 16;
+pub const NFT_META_BRI_IIFNAME: ::c_int = 17;
+pub const NFT_META_BRI_OIFNAME: ::c_int = 18;
+pub const NFT_META_PKTTYPE: ::c_int = 19;
+pub const NFT_META_CPU: ::c_int = 20;
+pub const NFT_META_IIFGROUP: ::c_int = 21;
+pub const NFT_META_OIFGROUP: ::c_int = 22;
+pub const NFT_META_CGROUP: ::c_int = 23;
+pub const NFT_META_PRANDOM: ::c_int = 24;
+
+pub const NFT_CT_STATE: ::c_int = 0;
+pub const NFT_CT_DIRECTION: ::c_int = 1;
+pub const NFT_CT_STATUS: ::c_int = 2;
+pub const NFT_CT_MARK: ::c_int = 3;
+pub const NFT_CT_SECMARK: ::c_int = 4;
+pub const NFT_CT_EXPIRATION: ::c_int = 5;
+pub const NFT_CT_HELPER: ::c_int = 6;
+pub const NFT_CT_L3PROTOCOL: ::c_int = 7;
+pub const NFT_CT_SRC: ::c_int = 8;
+pub const NFT_CT_DST: ::c_int = 9;
+pub const NFT_CT_PROTOCOL: ::c_int = 10;
+pub const NFT_CT_PROTO_SRC: ::c_int = 11;
+pub const NFT_CT_PROTO_DST: ::c_int = 12;
+pub const NFT_CT_LABELS: ::c_int = 13;
+pub const NFT_CT_PKTS: ::c_int = 14;
+pub const NFT_CT_BYTES: ::c_int = 15;
+
+pub const NFT_LIMIT_PKTS: ::c_int = 0;
+pub const NFT_LIMIT_PKT_BYTES: ::c_int = 1;
+
+pub const NFT_LIMIT_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_QUEUE_FLAG_BYPASS: ::c_int = 0x01;
+pub const NFT_QUEUE_FLAG_CPU_FANOUT: ::c_int = 0x02;
+pub const NFT_QUEUE_FLAG_MASK: ::c_int = 0x03;
+
+pub const NFT_QUOTA_F_INV: ::c_int = (1 << 0);
+
+pub const NFT_REJECT_ICMP_UNREACH: ::c_int = 0;
+pub const NFT_REJECT_TCP_RST: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_UNREACH: ::c_int = 2;
+
+pub const NFT_REJECT_ICMPX_NO_ROUTE: ::c_int = 0;
+pub const NFT_REJECT_ICMPX_PORT_UNREACH: ::c_int = 1;
+pub const NFT_REJECT_ICMPX_HOST_UNREACH: ::c_int = 2;
+pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: ::c_int = 3;
+
+pub const NFT_NAT_SNAT: ::c_int = 0;
+pub const NFT_NAT_DNAT: ::c_int = 1;
+
+pub const NFT_TRACETYPE_UNSPEC: ::c_int = 0;
+pub const NFT_TRACETYPE_POLICY: ::c_int = 1;
+pub const NFT_TRACETYPE_RETURN: ::c_int = 2;
+pub const NFT_TRACETYPE_RULE: ::c_int = 3;
+
+pub const NFT_NG_INCREMENTAL: ::c_int = 0;
+pub const NFT_NG_RANDOM: ::c_int = 1;
+
 #[doc(hidden)]
 pub const AF_MAX: ::c_int = 42;
 #[doc(hidden)]
 pub const PF_MAX: ::c_int = AF_MAX;
 
 cfg_if! {
     if #[cfg(any(target_arch = "arm", target_arch = "x86",
                  target_arch = "x86_64"))] {
         pub const PTHREAD_STACK_MIN: ::size_t = 16384;
     } else if #[cfg(target_arch = "sparc64")] {
         pub const PTHREAD_STACK_MIN: ::size_t = 0x6000;
     } else {
         pub const PTHREAD_STACK_MIN: ::size_t = 131072;
     }
 }
+pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 3;
+
+f! {
+    pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
+        return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
+    }
+}
 
 extern {
     pub fn utmpxname(file: *const ::c_char) -> ::c_int;
     pub fn getutxent() -> *mut utmpx;
     pub fn getutxid(ut: *const utmpx) -> *mut utmpx;
     pub fn getutxline(ut: *const utmpx) -> *mut utmpx;
     pub fn pututxline(ut: *const utmpx) -> *mut utmpx;
     pub fn setutxent();
@@ -598,16 +886,32 @@ extern {
     pub fn pthread_setaffinity_np(thread: ::pthread_t,
                                   cpusetsize: ::size_t,
                                   cpuset: *const ::cpu_set_t) -> ::c_int;
     pub fn pthread_rwlockattr_getkind_np(attr: *const ::pthread_rwlockattr_t,
                                          val: *mut ::c_int) -> ::c_int;
     pub fn pthread_rwlockattr_setkind_np(attr: *mut ::pthread_rwlockattr_t,
                                          val: ::c_int) -> ::c_int;
     pub fn sched_getcpu() -> ::c_int;
+    pub fn mallinfo() -> ::mallinfo;
+    pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t;
+    pub fn getauxval(type_: ::c_ulong) -> ::c_ulong;
+    #[cfg_attr(target_os = "netbsd", link_name = "__getpwent_r50")]
+    #[cfg_attr(target_os = "solaris", link_name = "__posix_getpwent_r")]
+    pub fn getpwent_r(pwd: *mut ::unix::notbsd::linux::passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::unix::notbsd
+                                        ::linux::passwd) -> ::c_int;
+    #[cfg_attr(target_os = "netbsd", link_name = "__getgrent_r50")]
+    #[cfg_attr(target_os = "solaris", link_name = "__posix_getgrent_r")]
+    pub fn getgrent_r(grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
 }
 
 cfg_if! {
     if #[cfg(any(target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "powerpc"))] {
         mod b32;
         pub use self::b32::*;
diff --git a/third_party/rust/libc/src/unix/notbsd/linux/s390x.rs b/third_party/rust/libc/src/unix/notbsd/linux/s390x.rs
index c2373f5744b4..9196f88b453a 100644
--- a/third_party/rust/libc/src/unix/notbsd/linux/s390x.rs
+++ b/third_party/rust/libc/src/unix/notbsd/linux/s390x.rs
@@ -1,8 +1,10 @@
+use pthread_mutex_t;
+
 pub type blkcnt_t = i64;
 pub type blksize_t = i64;
 pub type c_char = u8;
 pub type c_long = i64;
 pub type c_ulong = u64;
 pub type fsblkcnt_t = u64;
 pub type fsfilcnt_t = u64;
 pub type ino_t = u64;
@@ -148,16 +150,31 @@ s! {
         pub f_ffree: ::fsfilcnt_t,
         pub f_fsid: ::fsid_t,
         pub f_namelen: ::c_uint,
         pub f_frsize: ::c_uint,
         pub f_flags: ::c_uint,
         f_spare: [::c_uint; 4],
     }
 
+    pub struct statvfs {
+        pub f_bsize: ::c_ulong,
+        pub f_frsize: ::c_ulong,
+        pub f_blocks: ::fsblkcnt_t,
+        pub f_bfree: ::fsblkcnt_t,
+        pub f_bavail: ::fsblkcnt_t,
+        pub f_files: ::fsfilcnt_t,
+        pub f_ffree: ::fsfilcnt_t,
+        pub f_favail: ::fsfilcnt_t,
+        pub f_fsid: ::c_ulong,
+        pub f_flag: ::c_ulong,
+        pub f_namemax: ::c_ulong,
+        __f_spare: [::c_int; 6],
+    }
+
     pub struct msghdr {
         pub msg_name: *mut ::c_void,
         pub msg_namelen: ::socklen_t,
         pub msg_iov: *mut ::iovec,
         pub msg_iovlen: ::size_t,
         pub msg_control: *mut ::c_void,
         pub msg_controllen: ::size_t,
         pub msg_flags: ::c_int,
@@ -216,33 +233,32 @@ s! {
 
         __unused1: *mut ::c_void,
         __unused2: *mut ::c_void,
         __unused3: *mut ::c_void,
         __unused4: *mut ::c_void,
         __unused5: *mut ::c_void,
     }
 
-    pub struct ucred {
-        pub pid: ::pid_t,
-        pub uid: ::uid_t,
-        pub gid: ::gid_t,
-    }
-
     pub struct flock {
         pub l_type: ::c_short,
         pub l_whence: ::c_short,
         pub l_start: ::off_t,
         pub l_len: ::off_t,
         pub l_pid: ::pid_t,
     }
 
     // FIXME this is actually a union
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t {
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
 
     pub struct __psw_t {
         pub mask: u64,
         pub addr: u64,
     }
 
@@ -318,20 +334,21 @@ s! {
     }
 }
 
 pub const SFD_CLOEXEC: ::c_int = 0x080000;
 
 pub const NCCS: usize = 32;
 
 pub const O_TRUNC: ::c_int = 512;
-pub const O_LARGEFILE: ::c_int = 0o0100000;
+pub const O_LARGEFILE: ::c_int = 0;
 pub const O_NOATIME: ::c_int = 0o1000000;
 pub const O_CLOEXEC: ::c_int = 0x80000;
 pub const O_PATH: ::c_int = 0o10000000;
+pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY;
 
 pub const EBFONT: ::c_int = 59;
 pub const ENOSTR: ::c_int = 60;
 pub const ENODATA: ::c_int = 61;
 pub const ETIME: ::c_int = 62;
 pub const ENOSR: ::c_int = 63;
 pub const ENONET: ::c_int = 64;
 pub const ENOPKG: ::c_int = 65;
@@ -356,16 +373,40 @@ pub const POSIX_FADV_DONTNEED: ::c_int = 6;
 pub const POSIX_FADV_NOREUSE: ::c_int = 7;
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
 
+align_const! {
+    pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+    pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t =
+        pthread_mutex_t {
+            size: [
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            ],
+        };
+}
+
 pub const EADDRINUSE: ::c_int = 98;
 pub const EADDRNOTAVAIL: ::c_int = 99;
 pub const ECONNABORTED: ::c_int = 103;
 pub const ECONNREFUSED: ::c_int = 111;
 pub const ECONNRESET: ::c_int = 104;
 pub const EDEADLK: ::c_int = 35;
 pub const ENOSYS: ::c_int = 38;
 pub const ENOTCONN: ::c_int = 107;
@@ -374,16 +415,17 @@ pub const FIOCLEX: ::c_ulong = 0x5451;
 pub const FIONBIO: ::c_ulong = 0x5421;
 pub const MAP_ANON: ::c_int = 0x20;
 pub const O_ACCMODE: ::c_int = 3;
 pub const O_APPEND: ::c_int = 1024;
 pub const O_CREAT: ::c_int = 64;
 pub const O_EXCL: ::c_int = 128;
 pub const O_NONBLOCK: ::c_int = 2048;
 pub const PTHREAD_STACK_MIN: ::size_t = 16384;
+pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 3;
 pub const RLIM_INFINITY: ::rlim_t = 0xffffffffffffffff;
 pub const SA_NOCLDWAIT: ::c_int = 2;
 pub const SA_ONSTACK: ::c_int = 0x08000000;
 pub const SA_SIGINFO: ::c_int = 4;
 pub const SIGBUS: ::c_int = 7;
 pub const SIGSTKSZ: ::size_t = 0x2000;
 pub const MINSIGSTKSZ: ::size_t = 2048;
 pub const SIG_SETMASK: ::c_int = 2;
@@ -735,16 +777,19 @@ pub const PTRACE_GETSIGINFO: ::c_uint = 0x4202;
 pub const PTRACE_SETSIGINFO: ::c_uint = 0x4203;
 pub const PTRACE_GETREGSET: ::c_uint = 0x4204;
 pub const PTRACE_SETREGSET: ::c_uint = 0x4205;
 pub const PTRACE_SEIZE: ::c_uint = 0x4206;
 pub const PTRACE_INTERRUPT: ::c_uint = 0x4207;
 pub const PTRACE_LISTEN: ::c_uint = 0x4208;
 pub const PTRACE_PEEKSIGINFO: ::c_uint = 0x4209;
 
+pub const MCL_CURRENT: ::c_int = 0x0001;
+pub const MCL_FUTURE: ::c_int = 0x0002;
+
 pub const EPOLLWAKEUP: ::c_int = 0x20000000;
 
 pub const MAP_HUGETLB: ::c_int = 0x040000;
 
 pub const EFD_NONBLOCK: ::c_int = 0x800;
 
 pub const F_GETLK: ::c_int = 5;
 pub const F_GETOWN: ::c_int = 9;
@@ -908,18 +953,18 @@ pub const ECHOE: ::tcflag_t = 0o000020;
 pub const ECHOK: ::tcflag_t = 0o000040;
 pub const ECHONL: ::tcflag_t = 0o000100;
 pub const NOFLSH: ::tcflag_t = 0o000200;
 pub const ECHOCTL: ::tcflag_t = 0o001000;
 pub const ECHOPRT: ::tcflag_t = 0o002000;
 pub const ECHOKE: ::tcflag_t = 0o004000;
 pub const PENDIN: ::tcflag_t = 0o040000;
 
-pub const POLLWRNORM: ::c_short = 0x004;
-pub const POLLWRBAND: ::c_short = 0x100;
+pub const POLLWRNORM: ::c_short = 0x100;
+pub const POLLWRBAND: ::c_short = 0x200;
 
 pub const IXON: ::tcflag_t = 0o002000;
 pub const IXOFF: ::tcflag_t = 0o010000;
 
 pub const SYS_exit: ::c_long = 1;
 pub const SYS_fork: ::c_long = 2;
 pub const SYS_read: ::c_long = 3;
 pub const SYS_write: ::c_long = 4;
@@ -1214,30 +1259,30 @@ pub const SYS_sendto: ::c_long = 369;
 pub const SYS_sendmsg: ::c_long = 370;
 pub const SYS_recvfrom: ::c_long = 371;
 pub const SYS_recvmsg: ::c_long = 372;
 pub const SYS_shutdown: ::c_long = 373;
 pub const SYS_mlock2: ::c_long = 374;
 pub const SYS_copy_file_range: ::c_long = 375;
 pub const SYS_preadv2: ::c_long = 376;
 pub const SYS_pwritev2: ::c_long = 377;
-pub const SYS_lchown: ::c_long = 16;
-pub const SYS_setuid: ::c_long = 23;
-pub const SYS_getuid: ::c_long = 24;
-pub const SYS_setgid: ::c_long = 46;
-pub const SYS_getgid: ::c_long = 47;
-pub const SYS_geteuid: ::c_long = 49;
-pub const SYS_setreuid: ::c_long = 70;
-pub const SYS_setregid: ::c_long = 71;
-pub const SYS_getrlimit: ::c_long = 76;
-pub const SYS_getgroups: ::c_long = 80;
-pub const SYS_fchown: ::c_long = 95;
-pub const SYS_setresuid: ::c_long = 164;
-pub const SYS_setresgid: ::c_long = 170;
-pub const SYS_getresgid: ::c_long = 171;
+pub const SYS_lchown: ::c_long = 198;
+pub const SYS_setuid: ::c_long = 213;
+pub const SYS_getuid: ::c_long = 199;
+pub const SYS_setgid: ::c_long = 214;
+pub const SYS_getgid: ::c_long = 200;
+pub const SYS_geteuid: ::c_long = 201;
+pub const SYS_setreuid: ::c_long = 203;
+pub const SYS_setregid: ::c_long = 204;
+pub const SYS_getrlimit: ::c_long = 191;
+pub const SYS_getgroups: ::c_long = 205;
+pub const SYS_fchown: ::c_long = 207;
+pub const SYS_setresuid: ::c_long = 208;
+pub const SYS_setresgid: ::c_long = 210;
+pub const SYS_getresgid: ::c_long = 211;
 pub const SYS_select: ::c_long = 142;
 pub const SYS_getegid: ::c_long = 202;
 pub const SYS_setgroups: ::c_long = 206;
 pub const SYS_getresuid: ::c_long = 209;
 pub const SYS_chown: ::c_long = 212;
 pub const SYS_setfsuid: ::c_long = 215;
 pub const SYS_setfsgid: ::c_long = 216;
 pub const SYS_newfstatat: ::c_long = 293;
diff --git a/third_party/rust/libc/src/unix/notbsd/mod.rs b/third_party/rust/libc/src/unix/notbsd/mod.rs
index 07a60430321f..eead3fd84724 100644
--- a/third_party/rust/libc/src/unix/notbsd/mod.rs
+++ b/third_party/rust/libc/src/unix/notbsd/mod.rs
@@ -172,16 +172,68 @@ s! {
         // Actually a union.  We only expose sigev_notify_thread_id because it's
         // the most useful member
         pub sigev_notify_thread_id: ::c_int,
         #[cfg(target_pointer_width = "64")]
         __unused1: [::c_int; 11],
         #[cfg(target_pointer_width = "32")]
         __unused1: [::c_int; 12]
     }
+
+    pub struct in_pktinfo {
+        pub ipi_ifindex: ::c_int,
+        pub ipi_spec_dst: ::in_addr,
+        pub ipi_addr: ::in_addr,
+    }
+
+    pub struct ifaddrs {
+        pub ifa_next: *mut ifaddrs,
+        pub ifa_name: *mut c_char,
+        pub ifa_flags: ::c_uint,
+        pub ifa_addr: *mut ::sockaddr,
+        pub ifa_netmask: *mut ::sockaddr,
+        pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union
+        pub ifa_data: *mut ::c_void
+    }
+
+    pub struct in6_rtmsg {
+        rtmsg_dst: ::in6_addr,
+        rtmsg_src: ::in6_addr,
+        rtmsg_gateway: ::in6_addr,
+        rtmsg_type: u32,
+        rtmsg_dst_len: u16,
+        rtmsg_src_len: u16,
+        rtmsg_metric: u32,
+        rtmsg_info: ::c_ulong,
+        rtmsg_flags: u32,
+        rtmsg_ifindex: ::c_int,
+    }
+
+    pub struct arpreq {
+        pub arp_pa: ::sockaddr,
+        pub arp_ha: ::sockaddr,
+        pub arp_flags: ::c_int,
+        pub arp_netmask: ::sockaddr,
+        pub arp_dev: [::c_char; 16],
+    }
+
+    pub struct arpreq_old {
+        pub arp_pa: ::sockaddr,
+        pub arp_ha: ::sockaddr,
+        pub arp_flags: ::c_int,
+        pub arp_netmask: ::sockaddr,
+    }
+
+    pub struct arphdr {
+        pub ar_hrd: u16,
+        pub ar_pro: u16,
+        pub ar_hln: u8,
+        pub ar_pln: u8,
+        pub ar_op: u16,
+    }
 }
 
 // intentionally not public, only used for fd_set
 cfg_if! {
     if #[cfg(target_pointer_width = "32")] {
         const ULONG_SIZE: usize = 32;
     } else if #[cfg(target_pointer_width = "64")] {
         const ULONG_SIZE: usize = 64;
@@ -568,39 +620,44 @@ pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP;
 
 pub const SOCK_RAW: ::c_int = 3;
 pub const SOCK_RDM: ::c_int = 4;
 pub const IP_MULTICAST_IF: ::c_int = 32;
 pub const IP_MULTICAST_TTL: ::c_int = 33;
 pub const IP_MULTICAST_LOOP: ::c_int = 34;
 pub const IP_TTL: ::c_int = 2;
 pub const IP_HDRINCL: ::c_int = 3;
+pub const IP_PKTINFO: ::c_int = 8;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 36;
 pub const IP_TRANSPARENT: ::c_int = 19;
+pub const IPV6_UNICAST_HOPS: ::c_int = 16;
+pub const IPV6_MULTICAST_IF: ::c_int = 17;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 18;
+pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
 pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20;
 pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21;
+pub const IPV6_V6ONLY: ::c_int = 26;
+pub const IPV6_RECVPKTINFO: ::c_int = 49;
+pub const IPV6_PKTINFO: ::c_int = 50;
 
 pub const TCP_NODELAY: ::c_int = 1;
 pub const TCP_MAXSEG: ::c_int = 2;
 pub const TCP_CORK: ::c_int = 3;
 pub const TCP_KEEPIDLE: ::c_int = 4;
 pub const TCP_KEEPINTVL: ::c_int = 5;
 pub const TCP_KEEPCNT: ::c_int = 6;
 pub const TCP_SYNCNT: ::c_int = 7;
 pub const TCP_LINGER2: ::c_int = 8;
 pub const TCP_DEFER_ACCEPT: ::c_int = 9;
 pub const TCP_WINDOW_CLAMP: ::c_int = 10;
 pub const TCP_INFO: ::c_int = 11;
 pub const TCP_QUICKACK: ::c_int = 12;
 pub const TCP_CONGESTION: ::c_int = 13;
 
-pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
-pub const IPV6_V6ONLY: ::c_int = 26;
-
 pub const SO_DEBUG: ::c_int = 1;
 
 pub const SHUT_RD: ::c_int = 0;
 pub const SHUT_WR: ::c_int = 1;
 pub const SHUT_RDWR: ::c_int = 2;
 
 pub const LOCK_SH: ::c_int = 1;
 pub const LOCK_EX: ::c_int = 2;
@@ -798,16 +855,132 @@ pub const POLLIN: ::c_short = 0x1;
 pub const POLLPRI: ::c_short = 0x2;
 pub const POLLOUT: ::c_short = 0x4;
 pub const POLLERR: ::c_short = 0x8;
 pub const POLLHUP: ::c_short = 0x10;
 pub const POLLNVAL: ::c_short = 0x20;
 pub const POLLRDNORM: ::c_short = 0x040;
 pub const POLLRDBAND: ::c_short = 0x080;
 
+pub const IPTOS_LOWDELAY: u8 = 0x10;
+pub const IPTOS_THROUGHPUT: u8 = 0x08;
+pub const IPTOS_RELIABILITY: u8 = 0x04;
+pub const IPTOS_MINCOST: u8 = 0x02;
+
+pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0;
+pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0;
+pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0;
+pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80;
+pub const IPTOS_PREC_FLASH: u8 = 0x60;
+pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40;
+pub const IPTOS_PREC_PRIORITY: u8 = 0x20;
+pub const IPTOS_PREC_ROUTINE: u8 = 0x00;
+
+pub const IPOPT_COPY: u8 = 0x80;
+pub const IPOPT_CLASS_MASK: u8 = 0x60;
+pub const IPOPT_NUMBER_MASK: u8 = 0x1f;
+
+pub const IPOPT_CONTROL: u8 = 0x00;
+pub const IPOPT_RESERVED1: u8 = 0x20;
+pub const IPOPT_MEASUREMENT: u8 = 0x40;
+pub const IPOPT_RESERVED2: u8 = 0x60;
+pub const IPOPT_END: u8 = (0 |IPOPT_CONTROL);
+pub const IPOPT_NOOP: u8 = (1 |IPOPT_CONTROL);
+pub const IPOPT_SEC: u8 = (2 |IPOPT_CONTROL|IPOPT_COPY);
+pub const IPOPT_LSRR: u8 = (3 |IPOPT_CONTROL|IPOPT_COPY);
+pub const IPOPT_TIMESTAMP: u8 = (4 |IPOPT_MEASUREMENT);
+pub const IPOPT_RR: u8 = (7 |IPOPT_CONTROL);
+pub const IPOPT_SID: u8 = (8 |IPOPT_CONTROL|IPOPT_COPY);
+pub const IPOPT_SSRR: u8 = (9 |IPOPT_CONTROL|IPOPT_COPY);
+pub const IPOPT_RA: u8 = (20|IPOPT_CONTROL|IPOPT_COPY);
+pub const IPVERSION: u8 = 4;
+pub const MAXTTL: u8 = 255;
+pub const IPDEFTTL: u8 = 64;
+pub const IPOPT_OPTVAL: u8 = 0;
+pub const IPOPT_OLEN: u8 = 1;
+pub const IPOPT_OFFSET: u8 = 2;
+pub const IPOPT_MINOFF: u8 = 4;
+pub const MAX_IPOPTLEN: u8 = 40;
+pub const IPOPT_NOP: u8 = IPOPT_NOOP;
+pub const IPOPT_EOL: u8 = IPOPT_END;
+pub const IPOPT_TS: u8 = IPOPT_TIMESTAMP;
+pub const IPOPT_TS_TSONLY: u8 = 0;
+pub const IPOPT_TS_TSANDADDR: u8 = 1;
+pub const IPOPT_TS_PRESPEC: u8 = 3;
+
+pub const ARPOP_RREQUEST: u16 = 3;
+pub const ARPOP_RREPLY: u16 = 4;
+pub const ARPOP_InREQUEST: u16 = 8;
+pub const ARPOP_InREPLY: u16 = 9;
+pub const ARPOP_NAK: u16 = 10;
+
+pub const ATF_NETMASK: ::c_int = 0x20;
+pub const ATF_DONTPUB: ::c_int = 0x40;
+
+pub const ARPHRD_NETROM: u16 = 0;
+pub const ARPHRD_ETHER: u16 = 1;
+pub const ARPHRD_EETHER: u16 = 2;
+pub const ARPHRD_AX25: u16 = 3;
+pub const ARPHRD_PRONET: u16 = 4;
+pub const ARPHRD_CHAOS: u16 = 5;
+pub const ARPHRD_IEEE802: u16 = 6;
+pub const ARPHRD_ARCNET: u16 = 7;
+pub const ARPHRD_APPLETLK: u16 = 8;
+pub const ARPHRD_DLCI: u16 = 15;
+pub const ARPHRD_ATM: u16 = 19;
+pub const ARPHRD_METRICOM: u16 = 23;
+pub const ARPHRD_IEEE1394: u16 = 24;
+pub const ARPHRD_EUI64: u16 = 27;
+pub const ARPHRD_INFINIBAND: u16 = 32;
+
+pub const ARPHRD_SLIP: u16 = 256;
+pub const ARPHRD_CSLIP: u16 = 257;
+pub const ARPHRD_SLIP6: u16 = 258;
+pub const ARPHRD_CSLIP6: u16 = 259;
+pub const ARPHRD_RSRVD: u16 = 260;
+pub const ARPHRD_ADAPT: u16 = 264;
+pub const ARPHRD_ROSE: u16 = 270;
+pub const ARPHRD_X25: u16 = 271;
+pub const ARPHRD_HWX25: u16 = 272;
+pub const ARPHRD_PPP: u16 = 512;
+pub const ARPHRD_CISCO: u16 = 513;
+pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO;
+pub const ARPHRD_LAPB: u16 = 516;
+pub const ARPHRD_DDCMP: u16 = 517;
+pub const ARPHRD_RAWHDLC: u16 = 518;
+
+pub const ARPHRD_TUNNEL: u16 = 768;
+pub const ARPHRD_TUNNEL6: u16 = 769;
+pub const ARPHRD_FRAD: u16 = 770;
+pub const ARPHRD_SKIP: u16 = 771;
+pub const ARPHRD_LOOPBACK: u16 = 772;
+pub const ARPHRD_LOCALTLK: u16 = 773;
+pub const ARPHRD_FDDI: u16 = 774;
+pub const ARPHRD_BIF: u16 = 775;
+pub const ARPHRD_SIT: u16 = 776;
+pub const ARPHRD_IPDDP: u16 = 777;
+pub const ARPHRD_IPGRE: u16 = 778;
+pub const ARPHRD_PIMREG: u16 = 779;
+pub const ARPHRD_HIPPI: u16 = 780;
+pub const ARPHRD_ASH: u16 = 781;
+pub const ARPHRD_ECONET: u16 = 782;
+pub const ARPHRD_IRDA: u16 = 783;
+pub const ARPHRD_FCPP: u16 = 784;
+pub const ARPHRD_FCAL: u16 = 785;
+pub const ARPHRD_FCPL: u16 = 786;
+pub const ARPHRD_FCFABRIC: u16 = 787;
+pub const ARPHRD_IEEE802_TR: u16 = 800;
+pub const ARPHRD_IEEE80211: u16 = 801;
+pub const ARPHRD_IEEE80211_PRISM: u16 = 802;
+pub const ARPHRD_IEEE80211_RADIOTAP: u16 = 803;
+pub const ARPHRD_IEEE802154: u16 = 804;
+
+pub const ARPHRD_VOID: u16 = 0xFFFF;
+pub const ARPHRD_NONE: u16 = 0xFFFE;
+
 f! {
     pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
         let fd = fd as usize;
         let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
         (*set).fds_bits[fd / size] &= !(1 << (fd % size));
         return
     }
 
@@ -860,16 +1033,28 @@ f! {
 
     pub fn WCOREDUMP(status: ::c_int) -> bool {
         (status & 0x80) != 0
     }
 
     pub fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int {
         (cmd << 8) | (type_ & 0x00ff)
     }
+
+    pub fn IPOPT_COPIED(o: u8) -> u8 {
+        o & IPOPT_COPY
+    }
+
+    pub fn IPOPT_CLASS(o: u8) -> u8 {
+        o & IPOPT_CLASS_MASK
+    }
+
+    pub fn IPOPT_NUMBER(o: u8) -> u8 {
+        o & IPOPT_NUMBER_MASK
+    }
 }
 
 extern {
     pub fn fdatasync(fd: ::c_int) -> ::c_int;
     pub fn mincore(addr: *mut ::c_void, len: ::size_t,
                    vec: *mut ::c_uchar) -> ::c_int;
     pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
@@ -939,18 +1124,16 @@ extern {
                      offset: ::off64_t) -> ::ssize_t;
     pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64;
     pub fn readdir64_r(dirp: *mut ::DIR, entry: *mut ::dirent64,
                        result: *mut *mut ::dirent64) -> ::c_int;
     pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;
     pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int;
     pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
     pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
                    mode: ::mode_t, dev: dev_t) -> ::c_int;
     pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t,
                                      clock_id: *mut clockid_t) -> ::c_int;
     pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
                                      clock_id: ::clockid_t) -> ::c_int;
     pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t,
                                        pshared: ::c_int) -> ::c_int;
@@ -987,16 +1170,33 @@ extern {
                 name: *mut ::c_char,
                 termp: *const termios,
                 winp: *const ::winsize) -> ::c_int;
     pub fn execvpe(file: *const ::c_char, argv: *const *const ::c_char,
                    envp: *const *const ::c_char) -> ::c_int;
     pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
                    envp: *const *const ::c_char)
                    -> ::c_int;
+    pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int;
+    pub fn freeifaddrs(ifa: *mut ::ifaddrs);
+    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
+                address_len: ::socklen_t) -> ::c_int;
+
+    pub fn writev(fd: ::c_int,
+                  iov: *const ::iovec,
+                  iovcnt: ::c_int) -> ::ssize_t;
+    pub fn readv(fd: ::c_int,
+                 iov: *const ::iovec,
+                 iovcnt: ::c_int) -> ::ssize_t;
+
+    pub fn sendmsg(fd: ::c_int,
+                   msg: *const ::msghdr,
+                   flags: ::c_int) -> ::ssize_t;
+    pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
+                   -> ::ssize_t;
 }
 
 cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         mod emscripten;
         pub use self::emscripten::*;
     } else if #[cfg(any(target_os = "linux", target_os = "fuchsia"))] {
         mod linux;
diff --git a/third_party/rust/libc/src/unix/solaris/mod.rs b/third_party/rust/libc/src/unix/solaris/mod.rs
index a6c2d4bf9767..f285191677cf 100644
--- a/third_party/rust/libc/src/unix/solaris/mod.rs
+++ b/third_party/rust/libc/src/unix/solaris/mod.rs
@@ -27,17 +27,16 @@ pub type nfds_t = ::c_ulong;
 pub type suseconds_t = ::c_long;
 pub type off_t = ::c_long;
 pub type useconds_t = ::c_uint;
 pub type socklen_t = ::c_uint;
 pub type sa_family_t = u16;
 pub type pthread_t = ::c_uint;
 pub type pthread_key_t = ::c_uint;
 pub type blksize_t = ::c_int;
-pub type fflags_t = ::c_int;
 pub type nl_item = ::c_int;
 pub type id_t = ::c_int;
 pub type idtype_t = ::c_uint;
 
 pub enum timezone {}
 
 s! {
     pub struct sockaddr {
@@ -114,17 +113,17 @@ s! {
         pub msg_iov: *mut ::iovec,
         pub msg_iovlen: ::c_int,
         pub msg_control: *mut ::c_void,
         pub msg_controllen: ::socklen_t,
         pub msg_flags: ::c_int,
     }
 
     pub struct cmsghdr {
-        pub cmsg_len: ::size_t,
+        pub cmsg_len: ::socklen_t,
         pub cmsg_level: ::c_int,
         pub cmsg_type: ::c_int,
     }
 
     pub struct fd_set {
         #[cfg(target_pointer_width = "64")]
         fds_bits: [i64; FD_SETSIZE / 64],
         #[cfg(target_pointer_width = "32")]
@@ -172,17 +171,17 @@ s! {
     pub struct pthread_rwlockattr_t {
         __pthread_rwlockattrp: *mut ::c_void,
     }
 
     pub struct dirent {
         pub d_ino: ::ino_t,
         pub d_off: ::off_t,
         pub d_reclen: u16,
-        pub d_name: [::c_char; 1]
+        pub d_name: [::c_char; 3]
     }
 
     pub struct glob_t {
         pub gl_pathc: ::size_t,
         pub gl_pathv:  *mut *mut ::c_char,
         pub gl_offs: ::size_t,
         __unused1: *mut ::c_void,
         __unused2: ::c_int,
@@ -347,17 +346,23 @@ s! {
         pub if_name: *mut ::c_char,
     }
 
     pub struct port_event {
         pub portev_events: ::c_int,
         pub portev_source: ::c_ushort,
         pub portev_pad: ::c_ushort,
         pub portev_object: ::uintptr_t,
-        pub portev_user: ::uintptr_t,
+        pub portev_user: *mut ::c_void,
+    }
+
+    #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
+    pub struct epoll_event {
+        pub events: ::uint32_t,
+        pub u64: ::uint64_t,
     }
 }
 
 pub const LC_CTYPE: ::c_int = 0;
 pub const LC_NUMERIC: ::c_int = 1;
 pub const LC_TIME: ::c_int = 2;
 pub const LC_COLLATE: ::c_int = 3;
 pub const LC_MONETARY: ::c_int = 4;
@@ -465,16 +470,19 @@ pub const FIOGETOWN: ::c_int = 0x4004667b;
 
 pub const SIGCHLD: ::c_int = 18;
 pub const SIGBUS: ::c_int = 10;
 pub const SIGINFO: ::c_int = 41;
 pub const SIG_BLOCK: ::c_int = 1;
 pub const SIG_UNBLOCK: ::c_int = 2;
 pub const SIG_SETMASK: ::c_int = 3;
 
+pub const IPV6_UNICAST_HOPS: ::c_int = 0x5;
+pub const IPV6_MULTICAST_IF: ::c_int = 0x6;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 0x7;
 pub const IPV6_MULTICAST_LOOP: ::c_int = 0x8;
 pub const IPV6_V6ONLY: ::c_int = 0x27;
 
 cfg_if! {
     if #[cfg(target_pointer_width = "64")] {
         pub const FD_SETSIZE: usize = 65536;
     } else {
         pub const FD_SETSIZE: usize = 1024;
@@ -742,17 +750,27 @@ pub const ETOOMANYREFS: ::c_int = 144;
 pub const ETIMEDOUT: ::c_int = 145;
 pub const ECONNREFUSED: ::c_int = 146;
 pub const EHOSTDOWN: ::c_int = 147;
 pub const EHOSTUNREACH: ::c_int = 148;
 pub const EWOULDBLOCK: ::c_int = EAGAIN;
 pub const EALREADY: ::c_int = 149;
 pub const EINPROGRESS: ::c_int = 150;
 
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_SOCKTYPE: ::c_int = 10;
 pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 12;
 
 pub const F_DUPFD: ::c_int = 0;
 pub const F_GETFD: ::c_int = 1;
 pub const F_SETFD: ::c_int = 2;
 pub const F_GETFL: ::c_int = 3;
 pub const F_SETFL: ::c_int = 4;
 
 pub const SIGTRAP: ::c_int = 5;
@@ -830,16 +848,17 @@ pub const MADV_FREE: ::c_int = 5;
 pub const AF_INET: ::c_int = 2;
 pub const AF_INET6: ::c_int = 26;
 pub const AF_UNIX: ::c_int = 1;
 pub const SOCK_DGRAM: ::c_int = 1;
 pub const SOCK_STREAM: ::c_int = 2;
 pub const SOCK_RAW: ::c_int = 4;
 pub const SOCK_RDM: ::c_int = 5;
 pub const SOCK_SEQPACKET: ::c_int = 6;
+pub const IP_MULTICAST_IF: ::c_int = 16;
 pub const IP_MULTICAST_TTL: ::c_int = 17;
 pub const IP_MULTICAST_LOOP: ::c_int = 18;
 pub const IP_TTL: ::c_int = 4;
 pub const IP_HDRINCL: ::c_int = 2;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 19;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 20;
 pub const IPV6_JOIN_GROUP: ::c_int = 9;
 pub const IPV6_LEAVE_GROUP: ::c_int = 10;
@@ -862,17 +881,58 @@ pub const SO_SNDLOWAT: ::c_int = 0x1003;
 pub const SO_RCVLOWAT: ::c_int = 0x1004;
 pub const SO_SNDTIMEO: ::c_int = 0x1005;
 pub const SO_RCVTIMEO: ::c_int = 0x1006;
 pub const SO_ERROR: ::c_int = 0x1007;
 pub const SO_TYPE: ::c_int = 0x1008;
 
 pub const MSG_PEEK: ::c_int = 0x2;
 
-pub const IFF_LOOPBACK: ::c_int = 0x8;
+// https://docs.oracle.com/cd/E23824_01/html/821-1475/if-7p.html
+pub const IFF_UP: ::c_int = 0x0000000001; // Address is up
+pub const IFF_BROADCAST: ::c_int = 0x0000000002; // Broadcast address valid
+pub const IFF_DEBUG: ::c_int = 0x0000000004; // Turn on debugging
+pub const IFF_LOOPBACK: ::c_int = 0x0000000008; // Loopback net
+pub const IFF_POINTOPOINT: ::c_int = 0x0000000010; // Interface is p-to-p
+pub const IFF_NOTRAILERS: ::c_int = 0x0000000020; // Avoid use of trailers
+pub const IFF_RUNNING: ::c_int = 0x0000000040; // Resources allocated
+pub const IFF_NOARP: ::c_int = 0x0000000080; // No address res. protocol
+pub const IFF_PROMISC: ::c_int = 0x0000000100; // Receive all packets
+pub const IFF_ALLMULTI: ::c_int = 0x0000000200; // Receive all multicast pkts
+pub const IFF_INTELLIGENT: ::c_int = 0x0000000400; // Protocol code on board
+pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
+// Multicast using broadcst. add.
+pub const IFF_MULTI_BCAST: ::c_int = 0x0000001000;
+pub const IFF_UNNUMBERED: ::c_int = 0x0000002000; // Non-unique address
+pub const IFF_DHCPRUNNING: ::c_int = 0x0000004000; // DHCP controls interface
+pub const IFF_PRIVATE: ::c_int = 0x0000008000; // Do not advertise
+pub const IFF_NOXMIT: ::c_int = 0x0000010000; // Do not transmit pkts
+// No address - just on-link subnet
+pub const IFF_NOLOCAL: ::c_int = 0x0000020000;
+pub const IFF_DEPRECATED: ::c_int = 0x0000040000; // Address is deprecated
+pub const IFF_ADDRCONF: ::c_int = 0x0000080000; // Addr. from stateless addrconf
+pub const IFF_ROUTER: ::c_int = 0x0000100000; // Router on interface
+pub const IFF_NONUD: ::c_int = 0x0000200000; // No NUD on interface
+pub const IFF_ANYCAST: ::c_int = 0x0000400000; // Anycast address
+pub const IFF_NORTEXCH: ::c_int = 0x0000800000; // Don't xchange rout. info
+pub const IFF_IPV4: ::c_int = 0x0001000000; // IPv4 interface
+pub const IFF_IPV6: ::c_int = 0x0002000000; // IPv6 interface
+pub const IFF_NOFAILOVER: ::c_int = 0x0008000000; // in.mpathd test address
+pub const IFF_FAILED: ::c_int = 0x0010000000; // Interface has failed
+pub const IFF_STANDBY: ::c_int = 0x0020000000; // Interface is a hot-spare
+pub const IFF_INACTIVE: ::c_int = 0x0040000000; // Functioning but not used
+pub const IFF_OFFLINE: ::c_int = 0x0080000000; // Interface is offline
+// If CoS marking is supported
+pub const IFF_COS_ENABLED: ::c_longlong = 0x0200000000;
+pub const IFF_PREFERRED: ::c_longlong = 0x0400000000; // Prefer as source addr.
+pub const IFF_TEMPORARY: ::c_longlong = 0x0800000000; // RFC3041
+pub const IFF_FIXEDMTU: ::c_longlong = 0x1000000000; // MTU set with SIOCSLIFMTU
+pub const IFF_VIRTUAL: ::c_longlong = 0x2000000000; // Cannot send/receive pkts
+pub const IFF_DUPLICATE: ::c_longlong = 0x4000000000; // Local address in use
+pub const IFF_IPMP: ::c_longlong = 0x8000000000; // IPMP IP interface
 
 pub const SHUT_RD: ::c_int = 0;
 pub const SHUT_WR: ::c_int = 1;
 pub const SHUT_RDWR: ::c_int = 2;
 
 pub const LOCK_SH: ::c_int = 1;
 pub const LOCK_EX: ::c_int = 2;
 pub const LOCK_NB: ::c_int = 4;
@@ -1072,16 +1132,19 @@ pub const _SC_RAW_SOCKETS: ::c_int = 763;
 pub const _MUTEX_MAGIC: u16 = 0x4d58; // MX
 pub const _COND_MAGIC: u16 = 0x4356;  // CV
 pub const _RWL_MAGIC: u16 = 0x5257;   // RW
 
 pub const NCCS: usize = 19;
 
 pub const LOG_CRON: ::c_int = 15 << 3;
 
+pub const SYS_epoll_create: ::c_long = 213;
+pub const SYS_epoll_create1: ::c_long = 291;
+
 pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
     __pthread_mutex_flag1: 0,
     __pthread_mutex_flag2: 0,
     __pthread_mutex_ceiling: 0,
     __pthread_mutex_type: PTHREAD_PROCESS_PRIVATE,
     __pthread_mutex_magic: _MUTEX_MAGIC,
     __pthread_mutex_lock: 0,
     __pthread_mutex_data: 0
@@ -1127,16 +1190,35 @@ pub const PORT_SOURCE_TIMER: ::c_int = 2;
 pub const PORT_SOURCE_USER: ::c_int = 3;
 pub const PORT_SOURCE_FD: ::c_int = 4;
 pub const PORT_SOURCE_ALERT: ::c_int = 5;
 pub const PORT_SOURCE_MQ: ::c_int = 6;
 pub const PORT_SOURCE_FILE: ::c_int = 7;
 pub const PORT_SOURCE_POSTWAIT: ::c_int = 8;
 pub const PORT_SOURCE_SIGNAL: ::c_int = 9;
 
+pub const EPOLLIN: ::c_int = 0x1;
+pub const EPOLLPRI: ::c_int = 0x2;
+pub const EPOLLOUT: ::c_int = 0x4;
+pub const EPOLLRDNORM: ::c_int = 0x40;
+pub const EPOLLRDBAND: ::c_int = 0x80;
+pub const EPOLLWRNORM: ::c_int = 0x100;
+pub const EPOLLWRBAND: ::c_int = 0x200;
+pub const EPOLLMSG: ::c_int = 0x400;
+pub const EPOLLERR: ::c_int = 0x8;
+pub const EPOLLHUP: ::c_int = 0x10;
+pub const EPOLLET: ::c_int = 0x80000000;
+pub const EPOLLRDHUP: ::c_int = 0x2000;
+pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000;
+pub const EPOLLONESHOT: ::c_int = 0x40000000;
+pub const EPOLL_CLOEXEC: ::c_int = 0x80000;
+pub const EPOLL_CTL_ADD: ::c_int = 1;
+pub const EPOLL_CTL_MOD: ::c_int = 3;
+pub const EPOLL_CTL_DEL: ::c_int = 2;
+
 f! {
     pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
         let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8;
         let fd = fd as usize;
         (*set).fds_bits[fd / bits] &= !(1 << (fd % bits));
         return
     }
 
@@ -1179,16 +1261,17 @@ extern {
     pub fn stack_getbounds(sp: *mut ::stack_t) -> ::c_int;
     pub fn mincore(addr: *const ::c_void, len: ::size_t,
                    vec: *mut c_char) -> ::c_int;
     pub fn setgroups(ngroups: ::c_int,
                      ptr: *const ::gid_t) -> ::c_int;
     pub fn ioctl(fildes: ::c_int, request: ::c_int, ...) -> ::c_int;
     pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int)
                     -> ::c_int;
+    pub fn ___errno() -> *mut ::c_int;
     pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
     pub fn clock_nanosleep(clk_id: ::clockid_t,
                            flags: ::c_int,
                            rqtp: *const ::timespec,
                            rmtp:  *mut ::timespec) -> ::c_int;
     pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int;
     pub fn getnameinfo(sa: *const ::sockaddr,
@@ -1210,35 +1293,35 @@ extern {
                      base: ::locale_t) -> ::locale_t;
     pub fn uselocale(loc: ::locale_t) -> ::locale_t;
     pub fn getprogname() -> *const ::c_char;
     pub fn setprogname(name: *const ::c_char);
     pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int;
     pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int;
     pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
     pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
                    mode: ::mode_t, dev: dev_t) -> ::c_int;
     pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t) -> ::c_int;
-    pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int;
+    pub fn sethostname(name: *mut ::c_char, len: ::c_int) -> ::c_int;
     pub fn if_nameindex() -> *mut if_nameindex;
     pub fn if_freenameindex(ptr: *mut if_nameindex);
     pub fn pthread_create(native: *mut ::pthread_t,
                           attr: *const ::pthread_attr_t,
                           f: extern fn(*mut ::c_void) -> *mut ::c_void,
                           value: *mut ::c_void) -> ::c_int;
     pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t,
                                      clock_id: *mut clockid_t) -> ::c_int;
     pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
                                      clock_id: ::clockid_t) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
                                    abstime: *const ::timespec) -> ::c_int;
     pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t,
                   options: ::c_int) -> ::c_int;
 
     pub fn glob(pattern: *const ::c_char,
                 flags: ::c_int,
                 errfunc: Option<extern fn(epath: *const ::c_char,
@@ -1261,17 +1344,18 @@ extern {
     pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
 
     pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
 
     pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
                     flags: ::c_int, addr: *mut ::sockaddr,
                     addrlen: *mut ::socklen_t) -> ::ssize_t;
     pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
-    pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int;
+    pub fn futimesat(fd: ::c_int, path: *const ::c_char,
+                     times: *const ::timeval) -> ::c_int;
     pub fn utimensat(dirfd: ::c_int, path: *const ::c_char,
                      times: *const ::timespec, flag: ::c_int) -> ::c_int;
     pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
 
     pub fn bind(socket: ::c_int, address: *const ::sockaddr,
                 address_len: ::socklen_t) -> ::c_int;
 
     pub fn writev(fd: ::c_int,
@@ -1284,75 +1368,91 @@ extern {
     pub fn sendmsg(fd: ::c_int,
                    msg: *const ::msghdr,
                    flags: ::c_int) -> ::ssize_t;
     pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int)
                    -> ::ssize_t;
 
     pub fn port_create() -> ::c_int;
     pub fn port_associate(port: ::c_int, source: ::c_int, object: ::uintptr_t,
-                          events: ::c_int, user: ::uintptr_t) -> ::c_int;
+                          events: ::c_int, user: *mut ::c_void) -> ::c_int;
     pub fn port_dissociate(port: ::c_int, source: ::c_int, object: ::uintptr_t)
                            -> ::c_int;
     pub fn port_get(port: ::c_int, pe: *mut port_event,
-                    timeout: *const ::timespec) -> ::c_int;
+                    timeout: *mut ::timespec) -> ::c_int;
     pub fn port_getn(port: ::c_int, pe_list: *mut port_event, max: ::c_uint,
-                     nget: *mut ::c_uint, timeout: *const ::timespec)
+                     nget: *mut ::c_uint, timeout: *mut ::timespec)
                      -> ::c_int;
     pub fn fexecve(fd: ::c_int, argv: *const *const ::c_char,
                    envp: *const *const ::c_char)
                    -> ::c_int;
     #[cfg_attr(target_os = "solaris", link_name = "__posix_getgrgid_r")]
     pub fn getgrgid_r(uid: ::uid_t,
                       grp: *mut ::group,
                       buf: *mut ::c_char,
                       buflen: ::size_t,
                       result: *mut *mut ::group) -> ::c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "sigaltstack$UNIX2003")]
-    #[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")]
     pub fn sigaltstack(ss: *const stack_t,
                        oss: *mut stack_t) -> ::c_int;
     pub fn sem_close(sem: *mut sem_t) -> ::c_int;
     pub fn getdtablesize() -> ::c_int;
+
+    pub fn epoll_pwait(epfd: ::c_int,
+                       events: *mut ::epoll_event,
+                       maxevents: ::c_int,
+                       timeout: ::c_int,
+                       sigmask: *const ::sigset_t) -> ::c_int;
+    pub fn epoll_create(size: ::c_int) -> ::c_int;
+    pub fn epoll_create1(flags: ::c_int) -> ::c_int;
+    pub fn epoll_wait(epfd: ::c_int,
+                      events: *mut ::epoll_event,
+                      maxevents: ::c_int,
+                      timeout: ::c_int) -> ::c_int;
+    pub fn epoll_ctl(epfd: ::c_int,
+                     op: ::c_int,
+                     fd: ::c_int,
+                     event: *mut ::epoll_event) -> ::c_int;
+
     #[cfg_attr(target_os = "solaris", link_name = "__posix_getgrnam_r")]
     pub fn getgrnam_r(name: *const ::c_char,
                       grp: *mut ::group,
                       buf: *mut ::c_char,
                       buflen: ::size_t,
                       result: *mut *mut ::group) -> ::c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "pthread_sigmask$UNIX2003")]
     pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t,
                            oldset: *mut sigset_t) -> ::c_int;
     pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t;
     pub fn getgrnam(name: *const ::c_char) -> *mut ::group;
     pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int;
     pub fn sem_unlink(name: *const ::c_char) -> ::c_int;
     pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int;
-    #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam_r50")]
     #[cfg_attr(target_os = "solaris", link_name = "__posix_getpwnam_r")]
     pub fn getpwnam_r(name: *const ::c_char,
                       pwd: *mut passwd,
                       buf: *mut ::c_char,
                       buflen: ::size_t,
                       result: *mut *mut passwd) -> ::c_int;
-    #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")]
     #[cfg_attr(target_os = "solaris", link_name = "__posix_getpwuid_r")]
     pub fn getpwuid_r(uid: ::uid_t,
                       pwd: *mut passwd,
                       buf: *mut ::c_char,
                       buflen: ::size_t,
                       result: *mut *mut passwd) -> ::c_int;
-    #[cfg_attr(all(target_os = "macos", target_arch ="x86"),
-               link_name = "sigwait$UNIX2003")]
+    #[cfg_attr(target_os = "solaris", link_name = "__posix_getpwent_r")]
+    pub fn getpwent_r(pwd: *mut passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut passwd) -> ::c_int;
+    #[cfg_attr(target_os = "solaris", link_name = "__posix_getgrent_r")]
+    pub fn getgrent_r(grp: *mut ::group,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut ::group) -> ::c_int;
     #[cfg_attr(target_os = "solaris", link_name = "__posix_sigwait")]
     pub fn sigwait(set: *const sigset_t,
                    sig: *mut ::c_int) -> ::c_int;
     pub fn pthread_atfork(prepare: Option<unsafe extern fn()>,
                           parent: Option<unsafe extern fn()>,
                           child: Option<unsafe extern fn()>) -> ::c_int;
     pub fn getgrgid(gid: ::gid_t) -> *mut ::group;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "popen$UNIX2003")]
     pub fn popen(command: *const c_char,
                  mode: *const c_char) -> *mut ::FILE;
 }
diff --git a/third_party/rust/libc/src/unix/uclibc/mips/mips32.rs b/third_party/rust/libc/src/unix/uclibc/mips/mips32.rs
index a81e884e0bc6..dcbfcf8ff2bd 100644
--- a/third_party/rust/libc/src/unix/uclibc/mips/mips32.rs
+++ b/third_party/rust/libc/src/unix/uclibc/mips/mips32.rs
@@ -217,33 +217,403 @@ s! {
         pub pad: ::c_ushort,
         pub totalhigh: ::c_ulong,
         pub freehigh: ::c_ulong,
         pub mem_unit: ::c_uint,
         pub _f: [::c_char; 8],
     }
 
     // FIXME this is actually a union
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t {
         #[cfg(target_pointer_width = "32")]
         __size: [::c_char; 16],
         #[cfg(target_pointer_width = "64")]
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
 }
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 
 pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff;
 
-pub const SYS_gettid: ::c_long = 4222;   // Valid for O32
+pub const SYS_syscall: ::c_long = 4000 + 0;
+pub const SYS_exit: ::c_long = 4000 + 1;
+pub const SYS_fork: ::c_long = 4000 + 2;
+pub const SYS_read: ::c_long = 4000 + 3;
+pub const SYS_write: ::c_long = 4000 + 4;
+pub const SYS_open: ::c_long = 4000 + 5;
+pub const SYS_close: ::c_long = 4000 + 6;
+pub const SYS_waitpid: ::c_long = 4000 + 7;
+pub const SYS_creat: ::c_long = 4000 + 8;
+pub const SYS_link: ::c_long = 4000 + 9;
+pub const SYS_unlink: ::c_long = 4000 +  10;
+pub const SYS_execve: ::c_long = 4000 +  11;
+pub const SYS_chdir: ::c_long = 4000 +  12;
+pub const SYS_time: ::c_long = 4000 +  13;
+pub const SYS_mknod: ::c_long = 4000 +  14;
+pub const SYS_chmod: ::c_long = 4000 +  15;
+pub const SYS_lchown: ::c_long = 4000 +  16;
+pub const SYS_break: ::c_long = 4000 +  17;
+pub const SYS_unused18: ::c_long = 4000 +  18;
+pub const SYS_lseek: ::c_long = 4000 +  19;
+pub const SYS_getpid: ::c_long = 4000 +  20;
+pub const SYS_mount: ::c_long = 4000 +  21;
+pub const SYS_umount: ::c_long = 4000 +  22;
+pub const SYS_setuid: ::c_long = 4000 +  23;
+pub const SYS_getuid: ::c_long = 4000 +  24;
+pub const SYS_stime: ::c_long = 4000 +  25;
+pub const SYS_ptrace: ::c_long = 4000 +  26;
+pub const SYS_alarm: ::c_long = 4000 +  27;
+pub const SYS_unused28: ::c_long = 4000 +  28;
+pub const SYS_pause: ::c_long = 4000 +  29;
+pub const SYS_utime: ::c_long = 4000 +  30;
+pub const SYS_stty: ::c_long = 4000 +  31;
+pub const SYS_gtty: ::c_long = 4000 +  32;
+pub const SYS_access: ::c_long = 4000 +  33;
+pub const SYS_nice: ::c_long = 4000 +  34;
+pub const SYS_ftime: ::c_long = 4000 +  35;
+pub const SYS_sync: ::c_long = 4000 +  36;
+pub const SYS_kill: ::c_long = 4000 +  37;
+pub const SYS_rename: ::c_long = 4000 +  38;
+pub const SYS_mkdir: ::c_long = 4000 +  39;
+pub const SYS_rmdir: ::c_long = 4000 +  40;
+pub const SYS_dup: ::c_long = 4000 +  41;
+pub const SYS_pipe: ::c_long = 4000 +  42;
+pub const SYS_times: ::c_long = 4000 +  43;
+pub const SYS_prof: ::c_long = 4000 +  44;
+pub const SYS_brk: ::c_long = 4000 +  45;
+pub const SYS_setgid: ::c_long = 4000 +  46;
+pub const SYS_getgid: ::c_long = 4000 +  47;
+pub const SYS_signal: ::c_long = 4000 +  48;
+pub const SYS_geteuid: ::c_long = 4000 +  49;
+pub const SYS_getegid: ::c_long = 4000 +  50;
+pub const SYS_acct: ::c_long = 4000 +  51;
+pub const SYS_umount2: ::c_long = 4000 +  52;
+pub const SYS_lock: ::c_long = 4000 +  53;
+pub const SYS_ioctl: ::c_long = 4000 +  54;
+pub const SYS_fcntl: ::c_long = 4000 +  55;
+pub const SYS_mpx: ::c_long = 4000 +  56;
+pub const SYS_setpgid: ::c_long = 4000 +  57;
+pub const SYS_ulimit: ::c_long = 4000 +  58;
+pub const SYS_unused59: ::c_long = 4000 +  59;
+pub const SYS_umask: ::c_long = 4000 +  60;
+pub const SYS_chroot: ::c_long = 4000 +  61;
+pub const SYS_ustat: ::c_long = 4000 +  62;
+pub const SYS_dup2: ::c_long = 4000 +  63;
+pub const SYS_getppid: ::c_long = 4000 +  64;
+pub const SYS_getpgrp: ::c_long = 4000 +  65;
+pub const SYS_setsid: ::c_long = 4000 +  66;
+pub const SYS_sigaction: ::c_long = 4000 +  67;
+pub const SYS_sgetmask: ::c_long = 4000 +  68;
+pub const SYS_ssetmask: ::c_long = 4000 +  69;
+pub const SYS_setreuid: ::c_long = 4000 +  70;
+pub const SYS_setregid: ::c_long = 4000 +  71;
+pub const SYS_sigsuspend: ::c_long = 4000 +  72;
+pub const SYS_sigpending: ::c_long = 4000 +  73;
+pub const SYS_sethostname: ::c_long = 4000 +  74;
+pub const SYS_setrlimit: ::c_long = 4000 +  75;
+pub const SYS_getrlimit: ::c_long = 4000 +  76;
+pub const SYS_getrusage: ::c_long = 4000 +  77;
+pub const SYS_gettimeofday: ::c_long = 4000 +  78;
+pub const SYS_settimeofday: ::c_long = 4000 +  79;
+pub const SYS_getgroups: ::c_long = 4000 +  80;
+pub const SYS_setgroups: ::c_long = 4000 +  81;
+pub const SYS_reserved82: ::c_long = 4000 +  82;
+pub const SYS_symlink: ::c_long = 4000 +  83;
+pub const SYS_unused84: ::c_long = 4000 +  84;
+pub const SYS_readlink: ::c_long = 4000 +  85;
+pub const SYS_uselib: ::c_long = 4000 +  86;
+pub const SYS_swapon: ::c_long = 4000 +  87;
+pub const SYS_reboot: ::c_long = 4000 +  88;
+pub const SYS_readdir: ::c_long = 4000 +  89;
+pub const SYS_mmap: ::c_long = 4000 +  90;
+pub const SYS_munmap: ::c_long = 4000 +  91;
+pub const SYS_truncate: ::c_long = 4000 +  92;
+pub const SYS_ftruncate: ::c_long = 4000 +  93;
+pub const SYS_fchmod: ::c_long = 4000 +  94;
+pub const SYS_fchown: ::c_long = 4000 +  95;
+pub const SYS_getpriority: ::c_long = 4000 +  96;
+pub const SYS_setpriority: ::c_long = 4000 +  97;
+pub const SYS_profil: ::c_long = 4000 +  98;
+pub const SYS_statfs: ::c_long = 4000 +  99;
+pub const SYS_fstatfs: ::c_long = 4000 + 100;
+pub const SYS_ioperm: ::c_long = 4000 + 101;
+pub const SYS_socketcall: ::c_long = 4000 + 102;
+pub const SYS_syslog: ::c_long = 4000 + 103;
+pub const SYS_setitimer: ::c_long = 4000 + 104;
+pub const SYS_getitimer: ::c_long = 4000 + 105;
+pub const SYS_stat: ::c_long = 4000 + 106;
+pub const SYS_lstat: ::c_long = 4000 + 107;
+pub const SYS_fstat: ::c_long = 4000 + 108;
+pub const SYS_unused109: ::c_long = 4000 + 109;
+pub const SYS_iopl: ::c_long = 4000 + 110;
+pub const SYS_vhangup: ::c_long = 4000 + 111;
+pub const SYS_idle: ::c_long = 4000 + 112;
+pub const SYS_vm86: ::c_long = 4000 + 113;
+pub const SYS_wait4: ::c_long = 4000 + 114;
+pub const SYS_swapoff: ::c_long = 4000 + 115;
+pub const SYS_sysinfo: ::c_long = 4000 + 116;
+pub const SYS_ipc: ::c_long = 4000 + 117;
+pub const SYS_fsync: ::c_long = 4000 + 118;
+pub const SYS_sigreturn: ::c_long = 4000 + 119;
+pub const SYS_clone: ::c_long = 4000 + 120;
+pub const SYS_setdomainname: ::c_long = 4000 + 121;
+pub const SYS_uname: ::c_long = 4000 + 122;
+pub const SYS_modify_ldt: ::c_long = 4000 + 123;
+pub const SYS_adjtimex: ::c_long = 4000 + 124;
+pub const SYS_mprotect: ::c_long = 4000 + 125;
+pub const SYS_sigprocmask: ::c_long = 4000 + 126;
+pub const SYS_create_module: ::c_long = 4000 + 127;
+pub const SYS_init_module: ::c_long = 4000 + 128;
+pub const SYS_delete_module: ::c_long = 4000 + 129;
+pub const SYS_get_kernel_syms: ::c_long = 4000 + 130;
+pub const SYS_quotactl: ::c_long = 4000 + 131;
+pub const SYS_getpgid: ::c_long = 4000 + 132;
+pub const SYS_fchdir: ::c_long = 4000 + 133;
+pub const SYS_bdflush: ::c_long = 4000 + 134;
+pub const SYS_sysfs: ::c_long = 4000 + 135;
+pub const SYS_personality: ::c_long = 4000 + 136;
+pub const SYS_afs_syscall: ::c_long = 4000 + 137;
+pub const SYS_setfsuid: ::c_long = 4000 + 138;
+pub const SYS_setfsgid: ::c_long = 4000 + 139;
+pub const SYS__llseek: ::c_long = 4000 + 140;
+pub const SYS_getdents: ::c_long = 4000 + 141;
+pub const SYS__newselect: ::c_long = 4000 + 142;
+pub const SYS_flock: ::c_long = 4000 + 143;
+pub const SYS_msync: ::c_long = 4000 + 144;
+pub const SYS_readv: ::c_long = 4000 + 145;
+pub const SYS_writev: ::c_long = 4000 + 146;
+pub const SYS_cacheflush: ::c_long = 4000 + 147;
+pub const SYS_cachectl: ::c_long = 4000 + 148;
+pub const SYS_sysmips: ::c_long = 4000 + 149;
+pub const SYS_unused150: ::c_long = 4000 + 150;
+pub const SYS_getsid: ::c_long = 4000 + 151;
+pub const SYS_fdatasync: ::c_long = 4000 + 152;
+pub const SYS__sysctl: ::c_long = 4000 + 153;
+pub const SYS_mlock: ::c_long = 4000 + 154;
+pub const SYS_munlock: ::c_long = 4000 + 155;
+pub const SYS_mlockall: ::c_long = 4000 + 156;
+pub const SYS_munlockall: ::c_long = 4000 + 157;
+pub const SYS_sched_setparam: ::c_long = 4000 + 158;
+pub const SYS_sched_getparam: ::c_long = 4000 + 159;
+pub const SYS_sched_setscheduler: ::c_long = 4000 + 160;
+pub const SYS_sched_getscheduler: ::c_long = 4000 + 161;
+pub const SYS_sched_yield: ::c_long = 4000 + 162;
+pub const SYS_sched_get_priority_max: ::c_long = 4000 + 163;
+pub const SYS_sched_get_priority_min: ::c_long = 4000 + 164;
+pub const SYS_sched_rr_get_interval: ::c_long = 4000 + 165;
+pub const SYS_nanosleep: ::c_long = 4000 + 166;
+pub const SYS_mremap: ::c_long = 4000 + 167;
+pub const SYS_accept: ::c_long = 4000 + 168;
+pub const SYS_bind: ::c_long = 4000 + 169;
+pub const SYS_connect: ::c_long = 4000 + 170;
+pub const SYS_getpeername: ::c_long = 4000 + 171;
+pub const SYS_getsockname: ::c_long = 4000 + 172;
+pub const SYS_getsockopt: ::c_long = 4000 + 173;
+pub const SYS_listen: ::c_long = 4000 + 174;
+pub const SYS_recv: ::c_long = 4000 + 175;
+pub const SYS_recvfrom: ::c_long = 4000 + 176;
+pub const SYS_recvmsg: ::c_long = 4000 + 177;
+pub const SYS_send: ::c_long = 4000 + 178;
+pub const SYS_sendmsg: ::c_long = 4000 + 179;
+pub const SYS_sendto: ::c_long = 4000 + 180;
+pub const SYS_setsockopt: ::c_long = 4000 + 181;
+pub const SYS_shutdown: ::c_long = 4000 + 182;
+pub const SYS_socket: ::c_long = 4000 + 183;
+pub const SYS_socketpair: ::c_long = 4000 + 184;
+pub const SYS_setresuid: ::c_long = 4000 + 185;
+pub const SYS_getresuid: ::c_long = 4000 + 186;
+pub const SYS_query_module: ::c_long = 4000 + 187;
+pub const SYS_poll: ::c_long = 4000 + 188;
+pub const SYS_nfsservctl: ::c_long = 4000 + 189;
+pub const SYS_setresgid: ::c_long = 4000 + 190;
+pub const SYS_getresgid: ::c_long = 4000 + 191;
+pub const SYS_prctl: ::c_long = 4000 + 192;
+pub const SYS_rt_sigreturn: ::c_long = 4000 + 193;
+pub const SYS_rt_sigaction: ::c_long = 4000 + 194;
+pub const SYS_rt_sigprocmask: ::c_long = 4000 + 195;
+pub const SYS_rt_sigpending: ::c_long = 4000 + 196;
+pub const SYS_rt_sigtimedwait: ::c_long = 4000 + 197;
+pub const SYS_rt_sigqueueinfo: ::c_long = 4000 + 198;
+pub const SYS_rt_sigsuspend: ::c_long = 4000 + 199;
+pub const SYS_pread64: ::c_long = 4000 + 200;
+pub const SYS_pwrite64: ::c_long = 4000 + 201;
+pub const SYS_chown: ::c_long = 4000 + 202;
+pub const SYS_getcwd: ::c_long = 4000 + 203;
+pub const SYS_capget: ::c_long = 4000 + 204;
+pub const SYS_capset: ::c_long = 4000 + 205;
+pub const SYS_sigaltstack: ::c_long = 4000 + 206;
+pub const SYS_sendfile: ::c_long = 4000 + 207;
+pub const SYS_getpmsg: ::c_long = 4000 + 208;
+pub const SYS_putpmsg: ::c_long = 4000 + 209;
+pub const SYS_mmap2: ::c_long = 4000 + 210;
+pub const SYS_truncate64: ::c_long = 4000 + 211;
+pub const SYS_ftruncate64: ::c_long = 4000 + 212;
+pub const SYS_stat64: ::c_long = 4000 + 213;
+pub const SYS_lstat64: ::c_long = 4000 + 214;
+pub const SYS_fstat64: ::c_long = 4000 + 215;
+pub const SYS_pivot_root: ::c_long = 4000 + 216;
+pub const SYS_mincore: ::c_long = 4000 + 217;
+pub const SYS_madvise: ::c_long = 4000 + 218;
+pub const SYS_getdents64: ::c_long = 4000 + 219;
+pub const SYS_fcntl64: ::c_long = 4000 + 220;
+pub const SYS_reserved221: ::c_long = 4000 + 221;
+pub const SYS_gettid: ::c_long = 4000 + 222;
+pub const SYS_readahead: ::c_long = 4000 + 223;
+pub const SYS_setxattr: ::c_long = 4000 + 224;
+pub const SYS_lsetxattr: ::c_long = 4000 + 225;
+pub const SYS_fsetxattr: ::c_long = 4000 + 226;
+pub const SYS_getxattr: ::c_long = 4000 + 227;
+pub const SYS_lgetxattr: ::c_long = 4000 + 228;
+pub const SYS_fgetxattr: ::c_long = 4000 + 229;
+pub const SYS_listxattr: ::c_long = 4000 + 230;
+pub const SYS_llistxattr: ::c_long = 4000 + 231;
+pub const SYS_flistxattr: ::c_long = 4000 + 232;
+pub const SYS_removexattr: ::c_long = 4000 + 233;
+pub const SYS_lremovexattr: ::c_long = 4000 + 234;
+pub const SYS_fremovexattr: ::c_long = 4000 + 235;
+pub const SYS_tkill: ::c_long = 4000 + 236;
+pub const SYS_sendfile64: ::c_long = 4000 + 237;
+pub const SYS_futex: ::c_long = 4000 + 238;
+pub const SYS_sched_setaffinity: ::c_long = 4000 + 239;
+pub const SYS_sched_getaffinity: ::c_long = 4000 + 240;
+pub const SYS_io_setup: ::c_long = 4000 + 241;
+pub const SYS_io_destroy: ::c_long = 4000 + 242;
+pub const SYS_io_getevents: ::c_long = 4000 + 243;
+pub const SYS_io_submit: ::c_long = 4000 + 244;
+pub const SYS_io_cancel: ::c_long = 4000 + 245;
+pub const SYS_exit_group: ::c_long = 4000 + 246;
+pub const SYS_lookup_dcookie: ::c_long = 4000 + 247;
+pub const SYS_epoll_create: ::c_long = 4000 + 248;
+pub const SYS_epoll_ctl: ::c_long = 4000 + 249;
+pub const SYS_epoll_wait: ::c_long = 4000 + 250;
+pub const SYS_remap_file_pages: ::c_long = 4000 + 251;
+pub const SYS_set_tid_address: ::c_long = 4000 + 252;
+pub const SYS_restart_syscall: ::c_long = 4000 + 253;
+pub const SYS_fadvise64: ::c_long = 4000 + 254;
+pub const SYS_statfs64: ::c_long = 4000 + 255;
+pub const SYS_fstatfs64: ::c_long = 4000 + 256;
+pub const SYS_timer_create: ::c_long = 4000 + 257;
+pub const SYS_timer_settime: ::c_long = 4000 + 258;
+pub const SYS_timer_gettime: ::c_long = 4000 + 259;
+pub const SYS_timer_getoverrun: ::c_long = 4000 + 260;
+pub const SYS_timer_delete: ::c_long = 4000 + 261;
+pub const SYS_clock_settime: ::c_long = 4000 + 262;
+pub const SYS_clock_gettime: ::c_long = 4000 + 263;
+pub const SYS_clock_getres: ::c_long = 4000 + 264;
+pub const SYS_clock_nanosleep: ::c_long = 4000 + 265;
+pub const SYS_tgkill: ::c_long = 4000 + 266;
+pub const SYS_utimes: ::c_long = 4000 + 267;
+pub const SYS_mbind: ::c_long = 4000 + 268;
+pub const SYS_get_mempolicy: ::c_long = 4000 + 269;
+pub const SYS_set_mempolicy: ::c_long = 4000 + 270;
+pub const SYS_mq_open: ::c_long = 4000 + 271;
+pub const SYS_mq_unlink: ::c_long = 4000 + 272;
+pub const SYS_mq_timedsend: ::c_long = 4000 + 273;
+pub const SYS_mq_timedreceive: ::c_long = 4000 + 274;
+pub const SYS_mq_notify: ::c_long = 4000 + 275;
+pub const SYS_mq_getsetattr: ::c_long = 4000 + 276;
+pub const SYS_vserver: ::c_long = 4000 + 277;
+pub const SYS_waitid: ::c_long = 4000 + 278;
+/* pub const SYS_sys_setaltroot: ::c_long = 4000 + 279; */
+pub const SYS_add_key: ::c_long = 4000 + 280;
+pub const SYS_request_key: ::c_long = 4000 + 281;
+pub const SYS_keyctl: ::c_long = 4000 + 282;
+pub const SYS_set_thread_area: ::c_long = 4000 + 283;
+pub const SYS_inotify_init: ::c_long = 4000 + 284;
+pub const SYS_inotify_add_watch: ::c_long = 4000 + 285;
+pub const SYS_inotify_rm_watch: ::c_long = 4000 + 286;
+pub const SYS_migrate_pages: ::c_long = 4000 + 287;
+pub const SYS_openat: ::c_long = 4000 + 288;
+pub const SYS_mkdirat: ::c_long = 4000 + 289;
+pub const SYS_mknodat: ::c_long = 4000 + 290;
+pub const SYS_fchownat: ::c_long = 4000 + 291;
+pub const SYS_futimesat: ::c_long = 4000 + 292;
+pub const SYS_fstatat64: ::c_long = 4000 + 293;
+pub const SYS_unlinkat: ::c_long = 4000 + 294;
+pub const SYS_renameat: ::c_long = 4000 + 295;
+pub const SYS_linkat: ::c_long = 4000 + 296;
+pub const SYS_symlinkat: ::c_long = 4000 + 297;
+pub const SYS_readlinkat: ::c_long = 4000 + 298;
+pub const SYS_fchmodat: ::c_long = 4000 + 299;
+pub const SYS_faccessat: ::c_long = 4000 + 300;
+pub const SYS_pselect6: ::c_long = 4000 + 301;
+pub const SYS_ppoll: ::c_long = 4000 + 302;
+pub const SYS_unshare: ::c_long = 4000 + 303;
+pub const SYS_splice: ::c_long = 4000 + 304;
+pub const SYS_sync_file_range: ::c_long = 4000 + 305;
+pub const SYS_tee: ::c_long = 4000 + 306;
+pub const SYS_vmsplice: ::c_long = 4000 + 307;
+pub const SYS_move_pages: ::c_long = 4000 + 308;
+pub const SYS_set_robust_list: ::c_long = 4000 + 309;
+pub const SYS_get_robust_list: ::c_long = 4000 + 310;
+pub const SYS_kexec_load: ::c_long = 4000 + 311;
+pub const SYS_getcpu: ::c_long = 4000 + 312;
+pub const SYS_epoll_pwait: ::c_long = 4000 + 313;
+pub const SYS_ioprio_set: ::c_long = 4000 + 314;
+pub const SYS_ioprio_get: ::c_long = 4000 + 315;
+pub const SYS_utimensat: ::c_long = 4000 + 316;
+pub const SYS_signalfd: ::c_long = 4000 + 317;
+pub const SYS_timerfd: ::c_long = 4000 + 318;
+pub const SYS_eventfd: ::c_long = 4000 + 319;
+pub const SYS_fallocate: ::c_long = 4000 + 320;
+pub const SYS_timerfd_create: ::c_long = 4000 + 321;
+pub const SYS_timerfd_gettime: ::c_long = 4000 + 322;
+pub const SYS_timerfd_settime: ::c_long = 4000 + 323;
+pub const SYS_signalfd4: ::c_long = 4000 + 324;
+pub const SYS_eventfd2: ::c_long = 4000 + 325;
+pub const SYS_epoll_create1: ::c_long = 4000 + 326;
+pub const SYS_dup3: ::c_long = 4000 + 327;
+pub const SYS_pipe2: ::c_long = 4000 + 328;
+pub const SYS_inotify_init1: ::c_long = 4000 + 329;
+pub const SYS_preadv: ::c_long = 4000 + 330;
+pub const SYS_pwritev: ::c_long = 4000 + 331;
+pub const SYS_rt_tgsigqueueinfo: ::c_long = 4000 + 332;
+pub const SYS_perf_event_open: ::c_long = 4000 + 333;
+pub const SYS_accept4: ::c_long = 4000 + 334;
+pub const SYS_recvmmsg: ::c_long = 4000 + 335;
+pub const SYS_fanotify_init: ::c_long = 4000 + 336;
+pub const SYS_fanotify_mark: ::c_long = 4000 + 337;
+pub const SYS_prlimit64: ::c_long = 4000 + 338;
+pub const SYS_name_to_handle_at: ::c_long = 4000 + 339;
+pub const SYS_open_by_handle_at: ::c_long = 4000 + 340;
+pub const SYS_clock_adjtime: ::c_long = 4000 + 341;
+pub const SYS_syncfs: ::c_long = 4000 + 342;
+pub const SYS_sendmmsg: ::c_long = 4000 + 343;
+pub const SYS_setns: ::c_long = 4000 + 344;
+pub const SYS_process_vm_readv: ::c_long = 4000 + 345;
+pub const SYS_process_vm_writev: ::c_long = 4000 + 346;
+pub const SYS_kcmp: ::c_long = 4000 + 347;
+pub const SYS_finit_module: ::c_long = 4000 + 348;
+pub const SYS_sched_setattr: ::c_long = 4000 + 349;
+pub const SYS_sched_getattr: ::c_long = 4000 + 350;
+pub const SYS_renameat2: ::c_long = 4000 + 351;
+pub const SYS_seccomp: ::c_long = 4000 + 352;
+pub const SYS_getrandom: ::c_long = 4000 + 353;
+pub const SYS_memfd_create: ::c_long = 4000 + 354;
+pub const SYS_bpf: ::c_long = 4000 + 355;
+pub const SYS_execveat: ::c_long = 4000 + 356;
+pub const SYS_userfaultfd: ::c_long = 4000 + 357;
+pub const SYS_membarrier: ::c_long = 4000 + 358;
+pub const SYS_mlock2: ::c_long = 4000 + 359;
+pub const SYS_copy_file_range: ::c_long = 4000 + 360;
+pub const SYS_preadv2: ::c_long = 4000 + 361;
+pub const SYS_pwritev2: ::c_long = 4000 + 362;
+pub const SYS_pkey_mprotect: ::c_long = 4000 + 363;
+pub const SYS_pkey_alloc: ::c_long = 4000 + 364;
+pub const SYS_pkey_free: ::c_long = 4000 + 365;
 
 #[link(name = "util")]
 extern {
     pub fn sysctl(name: *mut ::c_int,
                   namelen: ::c_int,
                   oldp: *mut ::c_void,
                   oldlenp: *mut ::size_t,
                   newp: *mut ::c_void,
diff --git a/third_party/rust/libc/src/unix/uclibc/mips/mips64.rs b/third_party/rust/libc/src/unix/uclibc/mips/mips64.rs
index 79bac1fa8a47..e35938b1fc8d 100644
--- a/third_party/rust/libc/src/unix/uclibc/mips/mips64.rs
+++ b/third_party/rust/libc/src/unix/uclibc/mips/mips64.rs
@@ -183,18 +183,23 @@ s! {
         pub pad: ::c_ushort,
         pub totalhigh: ::c_ulong,
         pub freehigh: ::c_ulong,
         pub mem_unit: ::c_uint,
         pub _f: [::c_char; 0],
     }
 
     // FIXME this is actually a union
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t {
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
 }
 
 pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
 pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
diff --git a/third_party/rust/libc/src/unix/uclibc/mips/mod.rs b/third_party/rust/libc/src/unix/uclibc/mips/mod.rs
index cc3ddf254d73..d197249d0579 100644
--- a/third_party/rust/libc/src/unix/uclibc/mips/mod.rs
+++ b/third_party/rust/libc/src/unix/uclibc/mips/mod.rs
@@ -1,8 +1,10 @@
+pub type pthread_t = ::c_ulong;
+
 pub const SFD_CLOEXEC: ::c_int = 0x080000;
 
 pub const NCCS: usize = 32;
 
 pub const O_TRUNC: ::c_int = 512;
 
 pub const O_CLOEXEC: ::c_int = 0x80000;
 
diff --git a/third_party/rust/libc/src/unix/uclibc/mod.rs b/third_party/rust/libc/src/unix/uclibc/mod.rs
index 87521b2a816c..e3606c226640 100644
--- a/third_party/rust/libc/src/unix/uclibc/mod.rs
+++ b/third_party/rust/libc/src/unix/uclibc/mod.rs
@@ -6,17 +6,16 @@ pub type speed_t = ::c_uint;
 pub type tcflag_t = ::c_uint;
 pub type loff_t = ::c_longlong;
 pub type clockid_t = ::c_int;
 pub type key_t = ::c_int;
 pub type id_t = ::c_uint;
 pub type useconds_t = u32;
 pub type dev_t = u64;
 pub type socklen_t = u32;
-pub type pthread_t = ::c_ulong;
 pub type mode_t = u32;
 pub type ino64_t = u64;
 pub type off64_t = i64;
 pub type blkcnt64_t = i64;
 pub type rlim64_t = u64;
 pub type shmatt_t = ::c_ulong;
 pub type mqd_t = ::c_int;
 pub type msgqnum_t = ::c_ulong;
@@ -220,59 +219,109 @@ s! {
         pub ifa_name: *mut c_char,
         pub ifa_flags: ::c_uint,
         pub ifa_addr: *mut ::sockaddr,
         pub ifa_netmask: *mut ::sockaddr,
         pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union
         pub ifa_data: *mut ::c_void
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_mutex_t {
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_rwlock_t {
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "32",
+                       target_arch = "x86_64", target_arch = "powerpc64",
+                       target_arch = "mips64", target_arch = "s390x",
+                       target_arch = "sparc64")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(any(target_pointer_width = "32",
+                           target_arch = "x86_64", target_arch = "powerpc64",
+                           target_arch = "mips64", target_arch = "s390x",
+                           target_arch = "sparc64"))),
+               repr(align(8)))]
     pub struct pthread_mutexattr_t {
-        #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64",
-                  target_arch = "mips64", target_arch = "s390x",
-                  target_arch = "sparc64"))]
-        __align: [::c_int; 0],
-        #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64",
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "x86_64", target_arch = "powerpc64",
                       target_arch = "mips64", target_arch = "s390x",
                       target_arch = "sparc64")))]
+        __align: [::c_int; 0],
+        #[cfg(all(not(feature = "align"),
+                  not(any(target_arch = "x86_64", target_arch = "powerpc64",
+                          target_arch = "mips64", target_arch = "s390x",
+                          target_arch = "sparc64"))))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
     }
 
     pub struct pthread_rwlockattr_t {
         __lockkind: ::c_int,
         __pshared: ::c_int,
     }
 
+    #[cfg_attr(feature = "align", repr(align(8)))]
     pub struct pthread_cond_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_condattr_t {
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
     }
 
     pub struct passwd {
         pub pw_name: *mut ::c_char,
         pub pw_passwd: *mut ::c_char,
         pub pw_uid: ::uid_t,
@@ -648,31 +697,34 @@ pub const MADV_WILLNEED: ::c_int = 3;
 pub const MADV_DONTNEED: ::c_int = 4;
 pub const MADV_REMOVE: ::c_int = 9;
 pub const MADV_DONTFORK: ::c_int = 10;
 pub const MADV_DOFORK: ::c_int = 11;
 pub const MADV_MERGEABLE: ::c_int = 12;
 pub const MADV_UNMERGEABLE: ::c_int = 13;
 pub const MADV_HWPOISON: ::c_int = 100;
 
-pub const IFF_UP: ::c_int = 0x1;
-pub const IFF_BROADCAST: ::c_int = 0x2;
-pub const IFF_DEBUG: ::c_int = 0x4;
-pub const IFF_LOOPBACK: ::c_int = 0x8;
-pub const IFF_POINTOPOINT: ::c_int = 0x10;
-pub const IFF_NOTRAILERS: ::c_int = 0x20;
-pub const IFF_RUNNING: ::c_int = 0x40;
-pub const IFF_NOARP: ::c_int = 0x80;
-pub const IFF_PROMISC: ::c_int = 0x100;
-pub const IFF_ALLMULTI: ::c_int = 0x200;
-pub const IFF_MASTER: ::c_int = 0x400;
-pub const IFF_SLAVE: ::c_int = 0x800;
-pub const IFF_MULTICAST: ::c_int = 0x1000;
-pub const IFF_PORTSEL: ::c_int = 0x2000;
-pub const IFF_AUTOMEDIA: ::c_int = 0x4000;
+// https://github.com/kraj/uClibc/blob/master/include/net/if.h#L44
+pub const IFF_UP: ::c_int = 0x1; // Interface is up.
+pub const IFF_BROADCAST: ::c_int = 0x2; // Broadcast address valid.
+pub const IFF_DEBUG: ::c_int = 0x4; // Turn on debugging.
+pub const IFF_LOOPBACK: ::c_int = 0x8; // Is a loopback net.
+pub const IFF_POINTOPOINT: ::c_int = 0x10; // Interface is point-to-point link.
+pub const IFF_NOTRAILERS: ::c_int = 0x20; // Avoid use of trailers.
+pub const IFF_RUNNING: ::c_int = 0x40; // Resources allocated.
+pub const IFF_NOARP: ::c_int = 0x80; // No address resolution protocol.
+pub const IFF_PROMISC: ::c_int = 0x100; // Receive all packets.
+// Not supported
+pub const IFF_ALLMULTI: ::c_int = 0x200; // Receive all multicast packets.
+pub const IFF_MASTER: ::c_int = 0x400; // Master of a load balancer.
+pub const IFF_SLAVE: ::c_int = 0x800; // Slave of a load balancer.
+pub const IFF_MULTICAST: ::c_int = 0x1000; // Supports multicast.
+pub const IFF_PORTSEL: ::c_int = 0x2000; // Can set media type.
+pub const IFF_AUTOMEDIA: ::c_int = 0x4000; // Auto media select active.
+// Dialup device with changing addresses.
 pub const IFF_DYNAMIC: ::c_int = 0x8000;
 
 pub const SOL_IP: ::c_int = 0;
 pub const SOL_TCP: ::c_int = 6;
 pub const SOL_IPV6: ::c_int = 41;
 pub const SOL_ICMPV6: ::c_int = 58;
 pub const SOL_RAW: ::c_int = 255;
 pub const SOL_DECNET: ::c_int = 261;
@@ -782,16 +834,18 @@ pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000;
 
 pub const SOCK_RAW: ::c_int = 3;
 pub const IP_MULTICAST_TTL: ::c_int = 33;
 pub const IP_MULTICAST_LOOP: ::c_int = 34;
 pub const IP_TTL: ::c_int = 2;
 pub const IP_HDRINCL: ::c_int = 3;
 pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
 pub const IP_DROP_MEMBERSHIP: ::c_int = 36;
+pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20;
+pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21;
 
 pub const IPV6_JOIN_GROUP: ::c_int = 20;
 pub const IPV6_LEAVE_GROUP: ::c_int = 21;
 
 pub const TCP_NODELAY: ::c_int = 1;
 pub const TCP_MAXSEG: ::c_int = 2;
 pub const TCP_CORK: ::c_int = 3;
 pub const TCP_KEEPIDLE: ::c_int = 4;
@@ -1107,28 +1161,27 @@ pub const ST_NODIRATIME: ::c_ulong = 2048;
 
 pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void;
 pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
 pub const RTLD_NODELETE: ::c_int = 0x1000;
 pub const RTLD_NOW: ::c_int = 0x2;
 
 pub const TCP_MD5SIG: ::c_int = 14;
 
-pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_MUTEX_T],
-};
-pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_COND_T],
-};
-pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
-    __align: [],
-    size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
-};
+align_const! {
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        size: [0; __SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
 pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
 pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2;
 pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL;
 pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
 
 pub const SCHED_OTHER: ::c_int = 0;
 pub const SCHED_FIFO: ::c_int = 1;
@@ -1319,16 +1372,19 @@ pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37;
 pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38;
 pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39;
 
 pub const PR_GET_TID_ADDRESS: ::c_int = 40;
 
 pub const PR_SET_THP_DISABLE: ::c_int = 41;
 pub const PR_GET_THP_DISABLE: ::c_int = 42;
 
+pub const GRND_NONBLOCK: ::c_uint = 0x0001;
+pub const GRND_RANDOM: ::c_uint = 0x0002;
+
 pub const ABDAY_1: ::nl_item = 0x300;
 pub const ABDAY_2: ::nl_item = 0x301;
 pub const ABDAY_3: ::nl_item = 0x302;
 pub const ABDAY_4: ::nl_item = 0x303;
 pub const ABDAY_5: ::nl_item = 0x304;
 pub const ABDAY_6: ::nl_item = 0x305;
 pub const ABDAY_7: ::nl_item = 0x306;
 
@@ -1600,18 +1656,16 @@ extern {
     pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64;
     pub fn readdir64_r(dirp: *mut ::DIR, entry: *mut ::dirent64,
                        result: *mut *mut ::dirent64) -> ::c_int;
     pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;
     pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int;
     pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int;
     pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;
 
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
     pub fn mknodat(dirfd: ::c_int, pathname: *const ::c_char,
                    mode: ::mode_t, dev: dev_t) -> ::c_int;
     pub fn ppoll(fds: *mut ::pollfd,
                  nfds: nfds_t,
                  timeout: *const ::timespec,
                  sigmask: *const sigset_t) -> ::c_int;
     pub fn pthread_condattr_getclock(attr: *const pthread_condattr_t,
                                      clock_id: *mut clockid_t) -> ::c_int;
@@ -1625,16 +1679,18 @@ extern {
                              cpusetsize: ::size_t,
                              cpuset: *mut cpu_set_t) -> ::c_int;
     pub fn sched_setaffinity(pid: ::pid_t,
                              cpusetsize: ::size_t,
                              cpuset: *const cpu_set_t) -> ::c_int;
     pub fn unshare(flags: ::c_int) -> ::c_int;
     pub fn sem_timedwait(sem: *mut sem_t,
                          abstime: *const ::timespec) -> ::c_int;
+    pub fn sem_getvalue(sem: *mut sem_t,
+                        sval: *mut ::c_int) -> ::c_int;
     pub fn accept4(fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t,
                    flg: ::c_int) -> ::c_int;
     pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t,
                                    abstime: *const ::timespec) -> ::c_int;
     pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t,
                                         pshared: ::c_int) -> ::c_int;
     pub fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t,
                                         pshared: *mut ::c_int) -> ::c_int;
diff --git a/third_party/rust/libc/src/unix/uclibc/x86_64/l4re.rs b/third_party/rust/libc/src/unix/uclibc/x86_64/l4re.rs
index f047a82e004e..4f5811d17dfe 100644
--- a/third_party/rust/libc/src/unix/uclibc/x86_64/l4re.rs
+++ b/third_party/rust/libc/src/unix/uclibc/x86_64/l4re.rs
@@ -1,14 +1,15 @@
 /// L4Re specifics
 /// This module contains definitions required by various L4Re libc backends.
 /// Some of them are formally not part of the libc, but are a dependency of the
 /// libc and hence we should provide them here.
 
 pub type l4_umword_t = ::c_ulong; // Unsigned machine word.
+pub type pthread_t = *mut ::c_void;
 
 s! {
     /// CPU sets.
     pub struct l4_sched_cpu_set_t {
         // from the L4Re docs
         /// Combination of granularity and offset.
         ///
         /// The granularity defines how many CPUs each bit in map describes.
diff --git a/third_party/rust/libc/src/unix/uclibc/x86_64/mod.rs b/third_party/rust/libc/src/unix/uclibc/x86_64/mod.rs
index 7d082589d04a..bc6571aff98c 100644
--- a/third_party/rust/libc/src/unix/uclibc/x86_64/mod.rs
+++ b/third_party/rust/libc/src/unix/uclibc/x86_64/mod.rs
@@ -128,16 +128,17 @@ s! {
     // ------------------------------------------------------------
     // definitions below are *unverified* and might **break** the software
 //    pub struct in_addr {
 //        pub s_addr: in_addr_t,
 //    }
 //
 //    pub struct in6_addr {
 //        pub s6_addr: [u8; 16],
+//        #[cfg(not(feature = "align"))]
 //        __align: [u32; 0],
 //    }
 
     pub struct stat {
         pub st_dev: ::c_ulong,
         pub st_ino: ::ino_t,
         // According to uclibc/libc/sysdeps/linux/x86_64/bits/stat.h, order of
         // nlink and mode are swapped on 64 bit systems.
@@ -199,61 +200,116 @@ s! {
         pub c_iflag: ::tcflag_t,
         pub c_oflag: ::tcflag_t,
         pub c_cflag: ::tcflag_t,
         pub c_lflag: ::tcflag_t,
         pub c_line: ::cc_t,
         pub c_cc: [::cc_t; ::NCCS],
     }
 
+    #[cfg_attr(all(feature = "align", target_pointer_width = "32"),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align", target_pointer_width = "64"),
+               repr(align(8)))]
     pub struct sem_t { // ToDo
         #[cfg(target_pointer_width = "32")]
         __size: [::c_char; 16],
         #[cfg(target_pointer_width = "64")]
         __size: [::c_char; 32],
+        #[cfg(not(feature = "align"))]
         __align: [::c_long; 0],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_mutex_t { // ToDo
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "32",
+                       target_arch = "x86_64", target_arch = "powerpc64",
+                       target_arch = "mips64", target_arch = "s390x",
+                       target_arch = "sparc64")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   not(any(target_pointer_width = "32",
+                           target_arch = "x86_64", target_arch = "powerpc64",
+                           target_arch = "mips64", target_arch = "s390x",
+                           target_arch = "sparc64"))),
+               repr(align(8)))]
     pub struct pthread_mutexattr_t { // ToDo
-        #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64",
-                  target_arch = "mips64", target_arch = "s390x",
-                  target_arch = "sparc64"))]
-        __align: [::c_int; 0],
-        #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64",
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "x86_64", target_arch = "powerpc64",
                       target_arch = "mips64", target_arch = "s390x",
                       target_arch = "sparc64")))]
+        __align: [::c_int; 0],
+        #[cfg(all(not(feature = "align"),
+                  not(any(target_arch = "x86_64", target_arch = "powerpc64",
+                          target_arch = "mips64", target_arch = "s390x",
+                          target_arch = "sparc64"))))]
         __align: [::c_long; 0],
         size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(8)))]
     pub struct pthread_cond_t { // ToDo
+        #[cfg(not(feature = "align"))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
 
+    #[cfg_attr(feature = "align", repr(align(4)))]
     pub struct pthread_condattr_t { // ToDo
+        #[cfg(not(feature = "align"))]
         __align: [::c_int; 0],
         size: [u8; __SIZEOF_PTHREAD_CONDATTR_T],
     }
 
+    #[cfg_attr(all(feature = "align",
+                   target_pointer_width = "32",
+                   any(target_arch = "mips",
+                       target_arch = "arm",
+                       target_arch = "powerpc")),
+               repr(align(4)))]
+    #[cfg_attr(all(feature = "align",
+                   any(target_pointer_width = "64",
+                       not(any(target_arch = "mips",
+                               target_arch = "arm",
+                               target_arch = "powerpc")))),
+               repr(align(8)))]
     pub struct pthread_rwlock_t { // ToDo
-        #[cfg(any(target_arch = "mips", target_arch = "arm",
-                  target_arch = "powerpc"))]
+        #[cfg(all(not(feature = "align"),
+                  any(target_arch = "mips",
+                      target_arch = "arm",
+                      target_arch = "powerpc")))]
         __align: [::c_long; 0],
-        #[cfg(not(any(target_arch = "mips", target_arch = "arm",
+        #[cfg(not(any(feature = "align",
+                      target_arch = "mips",
+                      target_arch = "arm",
                       target_arch = "powerpc")))]
         __align: [::c_longlong; 0],
         size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
     pub struct sigset_t { // ToDo
         __val: [::c_ulong; 16],
     }
@@ -347,11 +403,14 @@ pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
 extern {
     pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
 }
 
 cfg_if! {
     if #[cfg(target_os = "l4re")] {
         mod l4re;
         pub use self::l4re::*;
-    } else { }
+    } else {
+        mod other;
+        pub use other::*;
+    }
 }
 
diff --git a/third_party/rust/libc/src/unix/uclibc/x86_64/other.rs b/third_party/rust/libc/src/unix/uclibc/x86_64/other.rs
new file mode 100644
index 000000000000..1cc521df992a
--- /dev/null
+++ b/third_party/rust/libc/src/unix/uclibc/x86_64/other.rs
@@ -0,0 +1,4 @@
+// Thestyle checker discourages the use of #[cfg], so this has to go into a
+// separate module
+pub type pthread_t = ::c_ulong;
+
diff --git a/third_party/rust/libloading/.cargo-checksum.json b/third_party/rust/libloading/.cargo-checksum.json
index 797ab00d7406..33b8d7522287 100644
--- a/third_party/rust/libloading/.cargo-checksum.json
+++ b/third_party/rust/libloading/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"3c9d7103068d644d68f5d0f9dd6a9ba00eb86bfb4cfc2c2c14c8a853144fcf09","Cargo.toml":"538efc8b4fd54f900e4706d6904b7696dbf071578d16fe76df1db8c82566635b","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"34dc610b01f8c3e56d95de1972120ca0d53cee787f636a3ce96526ab343878b5","appveyor.yml":"8382c7f1769f6cf78029a221058c4d73f35a48308b5dfc38d875facabec1c139","build.rs":"dd767f79832741a368fd46a846b7d53cdd05337becad6f7addad71e9618c2769","src/changelog.rs":"b1cbfc5b62c13693e06ca9b3196b359661a0c27d4bdc5eb093554ff86ce34a72","src/lib.rs":"665c5eeecdf77afc0dbe7de4232b2d5f5da5e19a5fd851ac433c89d600b801ee","src/os/mod.rs":"51d733e5522dacd6069642ad66aa6d7acf6c82950c934eb040e8dfd112e6d610","src/os/unix/mod.rs":"1cd2b6f51a34e492b7c88d054f25d89b825037bd81e62a2950ca13720e760061","src/os/windows/mod.rs":"2ed3564e9b88a601cd93b13affb286af7beee165b710279d55c953c74b783310","src/test_helpers.rs":"3a55052e8cd5231e97d9282b43398c2f144c57ced2d2df64bde7f482f5c778e7","src/util.rs":"0b0155448a26db4b00b2a6ca129e0e1f6f75870c56c9777d262941818c7581b7","tests/functions.rs":"dbed3ad32d6a31c8c0df5943f686ca328f020c5d49a9111281458971caa40e62","tests/markers.rs":"8e9c1b883404d9190e4f23ed39b3d6cbbccb3a07883f733b04aed4357b9c6aca","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/statics.rs":"8fd0955d38cdf3d56d1ece03ad159192702dbc049aa1af146f28fb10f1cf2fcc","tests/windows.rs":"7711dfe19062d91356cd127546542b1b6e13aeef76ad3098f32c8a6ae319b66a"},"package":"be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"}
\ No newline at end of file
+{"files":{".travis.yml":"3c9d7103068d644d68f5d0f9dd6a9ba00eb86bfb4cfc2c2c14c8a853144fcf09","Cargo.toml":"5bc50b6714c71bebc3b616d276e3c73c34ebd375ec99fcaba76b29ac5685e696","LICENSE":"b29f8b01452350c20dd1af16ef83b598fea3053578ccc1c7a0ef40e57be2620f","README.mkd":"b4cd83f110d01dc5aa8fcaf3da34bdbe1478efdba767d73abc14d4d87e4775fa","appveyor.yml":"8382c7f1769f6cf78029a221058c4d73f35a48308b5dfc38d875facabec1c139","build.rs":"dd60f6fc4cef3f02f56b74b6f03ed665ee8ce47e4040e2919282289affa1aca8","src/changelog.rs":"1ac991741280fdd9c5268d617ae7279d08146cfb3222b86e32315ff90b392598","src/lib.rs":"c17a20b5b9125b5a6d7b0913c35448ee688795f3e03f7bf1bf0aaf3e7e4e729e","src/os/mod.rs":"51d733e5522dacd6069642ad66aa6d7acf6c82950c934eb040e8dfd112e6d610","src/os/unix/global_static.c":"b1096dedf7d4aed5c28b658fc917f6603339ffd92390c84e25cb543bdc9460ac","src/os/unix/mod.rs":"717c09d09c20b14b8b8344899ffc3448ef23cf230ec61536a9fd53e8900d05ee","src/os/windows/mod.rs":"0b648941117a1573501ce1be5fcd11416361e1fe9c19a49f0826569a6cbc400a","src/test_helpers.rs":"3a55052e8cd5231e97d9282b43398c2f144c57ced2d2df64bde7f482f5c778e7","src/util.rs":"0b0155448a26db4b00b2a6ca129e0e1f6f75870c56c9777d262941818c7581b7","tests/functions.rs":"4633f3673db6a5b3623ea8927b13314c25502c9fbb63bb17a5a35650ea489012","tests/markers.rs":"8e9c1b883404d9190e4f23ed39b3d6cbbccb3a07883f733b04aed4357b9c6aca","tests/nagisa32.dll":"5c69b2bd9c8a6ad04165c221075fc9fade1dd66ca697399ace528a5a62328e36","tests/nagisa64.dll":"e20b95e3036f3289421abd100760874d4f455afd33c3b5b64fec56b191f7d477","tests/windows.rs":"7711dfe19062d91356cd127546542b1b6e13aeef76ad3098f32c8a6ae319b66a"},"package":"9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"}
\ No newline at end of file
diff --git a/third_party/rust/libloading/Cargo.toml b/third_party/rust/libloading/Cargo.toml
index a1dfcd561ee1..ccb1134bd1e9 100644
--- a/third_party/rust/libloading/Cargo.toml
+++ b/third_party/rust/libloading/Cargo.toml
@@ -1,17 +1,27 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
 name = "libloading"
-version = "0.4.0"
+version = "0.5.0"
 authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
 build = "build.rs"
 description = "A safer binding to platform’s dynamic library loading utilities"
+documentation = "https://docs.rs/libloading/"
 keywords = ["dlopen", "load", "shared", "dylib"]
 license = "ISC"
 repository = "https://github.com/nagisa/rust_libloading/"
-documentation = "https://docs.rs/libloading/"
-
-[dependencies]
-lazy_static = "0.2"
-
-[target.'cfg(windows)'.dependencies]
-winapi = "0.2"
-kernel32-sys = "0.2"
+[build-dependencies.cc]
+version = "1.0"
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3"
+features = ["winerror", "errhandlingapi", "libloaderapi"]
diff --git a/third_party/rust/libloading/README.mkd b/third_party/rust/libloading/README.mkd
index 58f4ad53826e..da7815863ce7 100644
--- a/third_party/rust/libloading/README.mkd
+++ b/third_party/rust/libloading/README.mkd
@@ -14,14 +14,8 @@ functions and static variables these libraries contain.
 
 * [Documentation][docs]
 * [Changelog][changelog]
 
 [docs]: https://docs.rs/libloading/
 [changelog]: https://docs.rs/libloading/*/libloading/changelog/index.html
 
 libloading is distributed under ISC (MIT-like) license.
-
----
-
-Note, that this library is not a drop-in replacement for the deprecated `dynamic_lib`. Many
-dubious APIs (notably, library search path modification) were prunned and string arguments
-take types that match conventions and system APIs better.
diff --git a/third_party/rust/libloading/build.rs b/third_party/rust/libloading/build.rs
index 200e08f1d16b..88c8c5fa44a7 100644
--- a/third_party/rust/libloading/build.rs
+++ b/third_party/rust/libloading/build.rs
@@ -1,45 +1,31 @@
+extern crate cc;
+
 use std::io::Write;
 use std::env;
 
 fn main(){
     let target_os = env::var("CARGO_CFG_TARGET_OS");
+    let is_unix = env::var_os("CARGO_CFG_UNIX").is_some();
     match target_os.as_ref().map(|x| &**x) {
         Ok("linux") | Ok("android") => println!("cargo:rustc-link-lib=dl"),
         Ok("freebsd") | Ok("dragonfly") => println!("cargo:rustc-link-lib=c"),
         // netbsd claims dl* will be available to any dynamically linked binary, but I haven’t
         // found any libraries that have to be linked to on other platforms.
         // What happens if the executable is not linked up dynamically?
         Ok("openbsd") | Ok("bitrig") | Ok("netbsd") | Ok("macos") | Ok("ios") => {}
+        Ok("solaris") => {}
         // dependencies come with winapi
         Ok("windows") => {}
         tos => {
             writeln!(::std::io::stderr(),
                      "Building for an unknown target_os=`{:?}`!\nPlease report an issue ",
                      tos).expect("could not report the error");
             ::std::process::exit(0xfc);
         }
     }
-    maybe_test_helpers();
-}
-
-fn maybe_test_helpers() {
-    if env::var("OPT_LEVEL").ok().and_then(|v| v.parse().ok()).unwrap_or(0u64) != 0 {
-        // certainly not for testing, just skip.
-        return;
+    if is_unix {
+        cc::Build::new()
+            .file("src/os/unix/global_static.c")
+            .compile("global_static");
     }
-    let mut outpath = if let Some(od) = env::var_os("OUT_DIR") { od } else { return };
-    let target = if let Some(t) = env::var_os("TARGET") { t } else { return };
-    let rustc = env::var_os("RUSTC").unwrap_or_else(|| { "rustc".into() });
-    outpath.push("/libtest_helpers.dll"); // extension for windows required, POSIX does not care.
-    let _ = ::std::process::Command::new(rustc)
-        .arg("src/test_helpers.rs")
-        .arg("-o")
-        .arg(outpath)
-        .arg("-O")
-        .arg("--target")
-        .arg(target)
-        .output();
-    // Ignore the failures here. We do not want failures of this thing to inhibit people from
-    // building and using the library. Might make it hard to debug why tests fail in case this
-    // library does not get built, though.
 }
diff --git a/third_party/rust/libloading/src/changelog.rs b/third_party/rust/libloading/src/changelog.rs
index 1d71d08e2e21..3e63f02d5acd 100644
--- a/third_party/rust/libloading/src/changelog.rs
+++ b/third_party/rust/libloading/src/changelog.rs
@@ -1,10 +1,44 @@
 //! Project changelog
 
+/// Release 0.5.0 (2018-01-11)
+///
+/// * Update to `winapi = ^0.3`;
+///
+/// ## Breaking changes
+///
+/// * libloading now requires a C compiler to build on UNIX;
+///   * This is a temporary measure until the [`linkage`] attribute is stablised;
+///   * Necessary to resolve [#32].
+///
+/// [`linkage`]: https://github.com/rust-lang/rust/issues/29603
+/// [#32]: https://github.com/nagisa/rust_libloading/issues/32
+pub mod r0_5_0 {}
+
+/// Release 0.4.3 (2017-12-07)
+///
+/// * Bump lazy-static dependency to `^1.0`;
+/// * `cargo test --release` now works when testing libloading.
+pub mod r0_4_3 {}
+
+
+/// Release 0.4.2 (2017-09-24)
+///
+/// * Improved error and race-condition handling on Windows;
+/// * Improved documentation about thread-safety of Library;
+/// * Added `Symbol::<Option<T>::lift_option() -> Option<Symbol<T>>` convenience method.
+pub mod r0_4_2 {}
+
+
+/// Release 0.4.1 (2017-08-29)
+///
+/// * Solaris support
+pub mod r0_4_1 {}
+
 /// Release 0.4.0 (2017-05-01)
 ///
 /// * Remove build-time dependency on target_build_utils (and by extension serde/phf);
 /// * Require at least version 1.14.0 of rustc to build;
 ///   * Actually, it is cargo which has to be more recent here. The one shipped with rustc 1.14.0
 ///     is what’s being required from now on.
 pub mod r0_4_0 {}
 
diff --git a/third_party/rust/libloading/src/lib.rs b/third_party/rust/libloading/src/lib.rs
index 81955580b0ef..75f55957a96e 100644
--- a/third_party/rust/libloading/src/lib.rs
+++ b/third_party/rust/libloading/src/lib.rs
@@ -12,44 +12,40 @@
 //! [`os::platform`](os/index.html) module for details.
 //!
 //! # Usage
 //!
 //! Add dependency to this library to your `Cargo.toml`:
 //!
 //! ```toml
 //! [dependencies]
-//! libloading = "0.3"
+//! libloading = "0.5"
 //! ```
 //!
 //! Then inside your project
 //!
 //! ```no_run
 //! extern crate libloading as lib;
 //!
 //! fn call_dynamic() -> lib::Result<u32> {
-//!     let lib = try!(lib::Library::new("/path/to/liblibrary.so"));
+//!     let lib = lib::Library::new("/path/to/liblibrary.so")?;
 //!     unsafe {
-//!         let func: lib::Symbol<unsafe extern fn() -> u32> = try!(lib.get(b"my_func"));
+//!         let func: lib::Symbol<unsafe extern fn() -> u32> = lib.get(b"my_func")?;
 //!         Ok(func())
 //!     }
 //! }
 //! ```
 //!
 //! The compiler will ensure that the loaded `function` will not outlive the `Library` it comes
 //! from, preventing a common cause of undefined behaviour and memory safety problems.
 use std::ffi::OsStr;
 use std::fmt;
 use std::ops;
 use std::marker;
 
-#[cfg(unix)]
-#[macro_use]
-extern crate lazy_static;
-
 #[cfg(unix)]
 use self::os::unix as imp;
 #[cfg(windows)]
 use self::os::windows as imp;
 
 pub mod os;
 pub mod changelog;
 mod util;
@@ -63,25 +59,37 @@ impl Library {
     /// Find and load a dynamic library.
     ///
     /// The `filename` argument may be any of:
     ///
     /// * A library filename;
     /// * Absolute path to the library;
     /// * Relative (to the current working directory) path to the library.
     ///
-    /// ## Platform-specific behaviour
+    /// ## Thread-safety
     ///
-    /// When a plain library filename is supplied, locations where library is searched for is
-    /// platform specific and cannot be adjusted in a portable manner.
+    /// The implementation strives to be as MT-safe as sanely possible, however due to certain
+    /// error-handling related resources not always being safe, this library is not MT-safe either.
+    ///
+    /// * On Windows Vista and earlier error handling falls back to [`SetErrorMode`], which is not
+    ///   MT-safe. MT-scenarios involving this function may cause a traditional data race;
+    /// * On some UNIX targets `dlerror` might not be MT-safe, resulting in garbage error messages
+    ///   in certain MT-scenarios.
+    ///
+    /// [`SetErrorMode`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
     ///
     /// Calling this function from multiple threads is not safe if used in conjunction with
     /// path-less filename and library search path is modified (`SetDllDirectory` function on
     /// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
     ///
+    /// ## Platform-specific behaviour
+    ///
+    /// When a plain library filename is supplied, locations where library is searched for is
+    /// platform specific and cannot be adjusted in a portable manner.
+    ///
     /// ### Windows
     ///
     /// If the `filename` specifies a library filename without path and with extension omitted,
     /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
     /// trailing `.` to the `filename`.
     ///
     /// If the library contains thread local variables (MSVC’s `_declspec(thread)`, Rust’s
     /// `#[thread_local]` attributes), loading the library will fail on versions prior to Windows
@@ -249,16 +257,37 @@ impl<'lib, T> Symbol<'lib, T> {
     pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, _: &'lib L) -> Symbol<'lib, T> {
         Symbol {
             inner: sym,
             pd: marker::PhantomData
         }
     }
 }
 
+impl<'lib, T> Symbol<'lib, Option<T>> {
+    /// Lift Option out of the symbol.
+    ///
+    /// ## Examples
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// let lib = Library::new("/path/to/awesome.module").unwrap();
+    /// unsafe {
+    ///     let symbol: Symbol<Option<*mut u32>> = lib.get(b"symbol\0").unwrap();
+    ///     let symbol: Symbol<*mut u32> = symbol.lift_option().expect("static is not null");
+    /// }
+    /// ```
+    pub fn lift_option(self) -> Option<Symbol<'lib, T>> {
+        self.inner.lift_option().map(|is| Symbol {
+            inner: is,
+            pd: marker::PhantomData,
+        })
+    }
+}
+
 impl<'lib, T> Clone for Symbol<'lib, T> {
     fn clone(&self) -> Symbol<'lib, T> {
         Symbol {
             inner: self.inner.clone(),
             pd: marker::PhantomData
         }
     }
 }
diff --git a/third_party/rust/libloading/src/os/unix/global_static.c b/third_party/rust/libloading/src/os/unix/global_static.c
new file mode 100644
index 000000000000..a90578086519
--- /dev/null
+++ b/third_party/rust/libloading/src/os/unix/global_static.c
@@ -0,0 +1,20 @@
+#include <pthread.h>
+#include <stdlib.h>
+
+pthread_mutex_t __attribute__((weak)) rust_libloading_dlerror_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void __attribute__((weak))
+rust_libloading_dlerror_mutex_lock(void)
+{
+    if (pthread_mutex_lock(&rust_libloading_dlerror_mutex) != 0) {
+        abort();
+    }
+}
+
+void __attribute__((weak))
+rust_libloading_dlerror_mutex_unlock(void)
+{
+    if (pthread_mutex_unlock(&rust_libloading_dlerror_mutex) != 0) {
+        abort();
+    }
+}
diff --git a/third_party/rust/libloading/src/os/unix/mod.rs b/third_party/rust/libloading/src/os/unix/mod.rs
index 0b6cae1d6cd2..a6f6f12ff412 100644
--- a/third_party/rust/libloading/src/os/unix/mod.rs
+++ b/third_party/rust/libloading/src/os/unix/mod.rs
@@ -1,41 +1,60 @@
 use util::{ensure_compatible_types, cstr_cow_from_bytes};
 
 use std::ffi::{CStr, OsStr};
 use std::{fmt, io, marker, mem, ptr};
 use std::os::raw;
 use std::os::unix::ffi::OsStrExt;
-use std::sync::Mutex;
 
-lazy_static! {
-    static ref DLERROR_MUTEX: Mutex<()> = Mutex::new(());
+extern "C" {
+    fn rust_libloading_dlerror_mutex_lock();
+    fn rust_libloading_dlerror_mutex_unlock();
+}
+
+struct DlerrorMutexGuard(());
+
+impl DlerrorMutexGuard {
+    fn new() -> DlerrorMutexGuard {
+        unsafe {
+            rust_libloading_dlerror_mutex_lock();
+        }
+        DlerrorMutexGuard(())
+    }
+}
+
+impl Drop for DlerrorMutexGuard {
+    fn drop(&mut self) {
+        unsafe {
+            rust_libloading_dlerror_mutex_unlock();
+        }
+    }
 }
 
 // libdl is crazy.
 //
 // First of all, whole error handling scheme in libdl is done via setting and querying some global
 // state, therefore it is not safe to use libdl in MT-capable environment at all. Only in POSIX
 // 2008+TC1 a thread-local state was allowed, which for our purposes is way too late.
 fn with_dlerror<T, F>(closure: F) -> Result<T, Option<io::Error>>
 where F: FnOnce() -> Option<T> {
     // We will guard all uses of libdl library with our own mutex. This makes libdl
     // safe to use in MT programs provided the only way a program uses libdl is via this library.
-    let _lock = DLERROR_MUTEX.lock();
+    let _lock = DlerrorMutexGuard::new();
     // While we could could call libdl here to clear the previous error value, only the dlsym
     // depends on it being cleared beforehand and only in some cases too. We will instead clear the
     // error inside the dlsym binding instead.
     //
     // In all the other cases, clearing the error here will only be hiding misuse of these bindings
     // or the libdl.
     closure().ok_or_else(|| unsafe {
         // This code will only get executed if the `closure` returns `None`.
         let error = dlerror();
         if error.is_null() {
-            // In non-dlsym case this may happen when there’s bugs in our bindings or there’s
+            // In non-dlsym case this may happen when there’re bugs in our bindings or there’s
             // non-libloading user of libdl; possibly in another thread.
             None
         } else {
             // You can’t even rely on error string being static here; call to subsequent dlerror
             // may invalidate or overwrite the error message. Why couldn’t they simply give up the
             // ownership over the message?
             // TODO: should do locale-aware conversion here. OTOH Rust doesn’t seem to work well in
             // any system that uses non-utf8 locale, so I doubt there’s a problem here.
@@ -197,16 +216,30 @@ impl fmt::Debug for Library {
 ///
 /// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
 /// `Symbol` does not outlive `Library` it comes from.
 pub struct Symbol<T> {
     pointer: *mut raw::c_void,
     pd: marker::PhantomData<T>
 }
 
+impl<T> Symbol<Option<T>> {
+    /// Lift Option out of the symbol.
+    pub fn lift_option(self) -> Option<Symbol<T>> {
+        if self.pointer.is_null() {
+            None
+        } else {
+            Some(Symbol {
+                pointer: self.pointer,
+                pd: marker::PhantomData,
+            })
+        }
+    }
+}
+
 unsafe impl<T: Send> Send for Symbol<T> {}
 unsafe impl<T: Sync> Sync for Symbol<T> {}
 
 impl<T> Clone for Symbol<T> {
     fn clone(&self) -> Symbol<T> {
         Symbol { ..*self }
     }
 }
diff --git a/third_party/rust/libloading/src/os/windows/mod.rs b/third_party/rust/libloading/src/os/windows/mod.rs
index 128e3ff91a4e..d2fa0f4d1d27 100644
--- a/third_party/rust/libloading/src/os/windows/mod.rs
+++ b/third_party/rust/libloading/src/os/windows/mod.rs
@@ -1,21 +1,24 @@
 extern crate winapi;
-extern crate kernel32;
+use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
+use self::winapi::shared::ntdef::WCHAR;
+use self::winapi::shared::winerror;
+use self::winapi::um::{errhandlingapi, libloaderapi};
 
 use util::{ensure_compatible_types, cstr_cow_from_bytes};
 
 use std::ffi::{OsStr, OsString};
 use std::{fmt, io, marker, mem, ptr};
 use std::os::windows::ffi::{OsStrExt, OsStringExt};
 use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 
 
 /// A platform-specific equivalent of the cross-platform `Library`.
-pub struct Library(winapi::HMODULE);
+pub struct Library(HMODULE);
 
 unsafe impl Send for Library {}
 // Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
 // the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldn’t
 // say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
 //
 // My investigation ended up with a question about thread-safety properties of the API involved
 // being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
@@ -35,17 +38,17 @@ impl Library {
     #[inline]
     pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
         let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
         let _guard = ErrorModeGuard::new();
 
         let ret = with_get_last_error(|| {
             // Make sure no winapi calls as a result of drop happen inside this closure, because
             // otherwise that might change the return value of the GetLastError.
-            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
+            let handle = unsafe { libloaderapi::LoadLibraryW(wide_filename.as_ptr()) };
             if handle.is_null()  {
                 None
             } else {
                 Some(Library(handle))
             }
         }).map_err(|e| e.unwrap_or_else(||
             panic!("LoadLibraryW failed but GetLastError did not report the error")
         ));
@@ -63,20 +66,20 @@ impl Library {
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
     /// most likely invalid.
     ///
     /// ## Unsafety
     ///
     /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
     /// undefined.
     pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
-        ensure_compatible_types::<T, winapi::FARPROC>();
+        ensure_compatible_types::<T, FARPROC>();
         let symbol = try!(cstr_cow_from_bytes(symbol));
         with_get_last_error(|| {
-            let symbol = kernel32::GetProcAddress(self.0, symbol.as_ptr());
+            let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
             if symbol.is_null() {
                 None
             } else {
                 Some(Symbol {
                     pointer: symbol,
                     pd: marker::PhantomData
                 })
             }
@@ -86,21 +89,21 @@ impl Library {
     }
 
     /// Get a pointer to function or static variable by ordinal number.
     ///
     /// ## Unsafety
     ///
     /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
     /// undefined.
-    pub unsafe fn get_ordinal<T>(&self, ordinal: winapi::WORD) -> ::Result<Symbol<T>> {
-        ensure_compatible_types::<T, winapi::FARPROC>();
+    pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> ::Result<Symbol<T>> {
+        ensure_compatible_types::<T, FARPROC>();
         with_get_last_error(|| {
             let ordinal = ordinal as usize as *mut _;
-            let symbol = kernel32::GetProcAddress(self.0, ordinal);
+            let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
             if symbol.is_null() {
                 None
             } else {
                 Some(Symbol {
                     pointer: symbol,
                     pd: marker::PhantomData
                 })
             }
@@ -108,50 +111,64 @@ impl Library {
             panic!("GetProcAddress failed but GetLastError did not report the error")
         ))
     }
 }
 
 impl Drop for Library {
     fn drop(&mut self) {
         with_get_last_error(|| {
-            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
+            if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
                 None
             } else {
                 Some(())
             }
         }).unwrap()
     }
 }
 
 impl fmt::Debug for Library {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe {
-            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
-            let len = kernel32::GetModuleFileNameW(self.0,
+            let mut buf: [WCHAR; 1024] = mem::uninitialized();
+            let len = libloaderapi::GetModuleFileNameW(self.0,
                                                    (&mut buf[..]).as_mut_ptr(), 1024) as usize;
             if len == 0 {
                 f.write_str(&format!("Library@{:p}", self.0))
             } else {
                 let string: OsString = OsString::from_wide(&buf[..len]);
                 f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
             }
         }
     }
 }
 
 /// Symbol from a library.
 ///
 /// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
 /// `Symbol` does not outlive `Library` it comes from.
 pub struct Symbol<T> {
-    pointer: winapi::FARPROC,
+    pointer: FARPROC,
     pd: marker::PhantomData<T>
 }
 
+impl<T> Symbol<Option<T>> {
+    /// Lift Option out of the symbol.
+    pub fn lift_option(self) -> Option<Symbol<T>> {
+        if self.pointer.is_null() {
+            None
+        } else {
+            Some(Symbol {
+                pointer: self.pointer,
+                pd: marker::PhantomData,
+            })
+        }
+    }
+}
+
 unsafe impl<T: Send> Send for Symbol<T> {}
 unsafe impl<T: Sync> Sync for Symbol<T> {}
 
 impl<T> Clone for Symbol<T> {
     fn clone(&self) -> Symbol<T> {
         Symbol { ..*self }
     }
 }
@@ -169,74 +186,102 @@ impl<T> ::std::ops::Deref for Symbol<T> {
 impl<T> fmt::Debug for Symbol<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&format!("Symbol@{:p}", self.pointer))
     }
 }
 
 
 static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
-struct ErrorModeGuard(winapi::DWORD);
+struct ErrorModeGuard(DWORD);
 
 impl ErrorModeGuard {
-    fn new() -> ErrorModeGuard {
-        let mut ret = ErrorModeGuard(0);
-
-        if !USE_ERRORMODE.load(Ordering::Acquire) {
-            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
-                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
-                USE_ERRORMODE.store(true, Ordering::Release);
-            } else {
-                return ret;
+    fn new() -> Option<ErrorModeGuard> {
+        const SEM_FAILCE: DWORD = 1;
+        unsafe {
+            if !USE_ERRORMODE.load(Ordering::Acquire) {
+                let mut previous_mode = 0;
+                let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
+                if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
+                    USE_ERRORMODE.store(true, Ordering::Release);
+                } else if !success {
+                    // SetThreadErrorMode failed with some other error? How in the world is it
+                    // possible for what is essentially a simple variable swap to fail?
+                    // For now we just ignore the error -- the worst that can happen here is
+                    // the previous mode staying on and user seeing a dialog error on older Windows
+                    // machines.
+                    return None;
+                } else if previous_mode == SEM_FAILCE {
+                    return None;
+                } else {
+                    return Some(ErrorModeGuard(previous_mode));
+                }
+            }
+            match errhandlingapi::SetErrorMode(SEM_FAILCE) {
+                SEM_FAILCE => {
+                    // This is important to reduce racy-ness when this library is used on multiple
+                    // threads. In particular this helps with following race condition:
+                    //
+                    // T1: SetErrorMode(SEM_FAILCE)
+                    // T2: SetErrorMode(SEM_FAILCE)
+                    // T1: SetErrorMode(old_mode) # not SEM_FAILCE
+                    // T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
+                    //
+                    // This is still somewhat racy in a sense that T1 might resture the error
+                    // mode before T2 finishes loading the library, but that is less of a
+                    // concern – it will only end up in end user seeing a dialog.
+                    //
+                    // Also, SetErrorMode itself is probably not an atomic operation.
+                    None
+                }
+                a => Some(ErrorModeGuard(a))
             }
         }
-        ret.0 = unsafe { kernel32::SetErrorMode(1) };
-        ret
     }
 }
 
 impl Drop for ErrorModeGuard {
     fn drop(&mut self) {
         unsafe {
             if !USE_ERRORMODE.load(Ordering::Relaxed) {
-                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
+                errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
             } else {
-                kernel32::SetErrorMode(self.0);
+                errhandlingapi::SetErrorMode(self.0);
             }
         }
     }
 }
 
 fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<io::Error>>
 where F: FnOnce() -> Option<T> {
     closure().ok_or_else(|| {
-        let error = unsafe { kernel32::GetLastError() };
+        let error = unsafe { errhandlingapi::GetLastError() };
         if error == 0 {
             None
         } else {
             Some(io::Error::from_raw_os_error(error as i32))
         }
     })
 }
 
 #[test]
 fn works_getlasterror() {
     let lib = Library::new("kernel32.dll").unwrap();
-    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
+    let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
         lib.get(b"GetLastError").unwrap()
     };
     unsafe {
-        kernel32::SetLastError(42);
-        assert_eq!(kernel32::GetLastError(), gle())
+        errhandlingapi::SetLastError(42);
+        assert_eq!(errhandlingapi::GetLastError(), gle())
     }
 }
 
 #[test]
 fn works_getlasterror0() {
     let lib = Library::new("kernel32.dll").unwrap();
-    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
+    let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
         lib.get(b"GetLastError\0").unwrap()
     };
     unsafe {
-        kernel32::SetLastError(42);
-        assert_eq!(kernel32::GetLastError(), gle())
+        errhandlingapi::SetLastError(42);
+        assert_eq!(errhandlingapi::GetLastError(), gle())
     }
 }
diff --git a/third_party/rust/libloading/tests/functions.rs b/third_party/rust/libloading/tests/functions.rs
index 109689bc5fce..c9bc067eacda 100644
--- a/third_party/rust/libloading/tests/functions.rs
+++ b/third_party/rust/libloading/tests/functions.rs
@@ -1,15 +1,32 @@
 extern crate libloading;
 use libloading::{Symbol, Library};
 
 const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.dll");
 
+fn make_helpers() {
+    static ONCE: ::std::sync::Once = ::std::sync::ONCE_INIT;
+    ONCE.call_once(|| {
+        let mut outpath = String::from(if let Some(od) = option_env!("OUT_DIR") { od } else { return });
+        let rustc = option_env!("RUSTC").unwrap_or_else(|| { "rustc".into() });
+        outpath.push_str(&"/libtest_helpers.dll"); // extension for windows required, POSIX does not care.
+        let _ = ::std::process::Command::new(rustc)
+            .arg("src/test_helpers.rs")
+            .arg("-o")
+            .arg(outpath)
+            .arg("-O")
+            .output()
+            .expect("could not compile the test helpers!");
+    });
+}
+
 #[test]
 fn test_id_u32() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         let f: Symbol<unsafe extern fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
         assert_eq!(42, f(42));
     }
 }
 
 #[repr(C)]
@@ -18,68 +35,117 @@ struct S {
     a: u64,
     b: u32,
     c: u16,
     d: u8
 }
 
 #[test]
 fn test_id_struct() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
         assert_eq!(S { a: 1, b: 2, c: 3, d: 4 }, f(S { a: 1, b: 2, c: 3, d: 4 }));
     }
 }
 
 #[test]
 fn test_0_no_0() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
         let f2: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
         assert_eq!(*f, *f2);
     }
 }
 
 #[test]
 fn wrong_name_fails() {
     Library::new(concat!(env!("OUT_DIR"), "/libtest_help")).err().unwrap();
 }
 
 #[test]
 fn missing_symbol_fails() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
         lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
     }
 }
 
 #[test]
 fn interior_null_fails() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
         lib.get::<*mut ()>(b"test\0_does_not_exist\0").err().unwrap();
     }
 }
 
 #[test]
 #[should_panic]
 fn test_incompatible_type() {
+    make_helpers();
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         let _ = lib.get::<()>(b"test_identity_u32\0");
     }
 }
 
 #[test]
 #[should_panic]
 fn test_incompatible_type_named_fn() {
+    make_helpers();
     unsafe fn get<'a, T>(l: &'a Library, _: T) -> libloading::Result<Symbol<'a, T>> {
         l.get::<T>(b"test_identity_u32\0")
     }
     let lib = Library::new(LIBPATH).unwrap();
     unsafe {
         let _ = get(&lib, test_incompatible_type_named_fn);
     }
 }
+
+#[test]
+fn test_static_u32() {
+    make_helpers();
+    let lib = Library::new(LIBPATH).unwrap();
+    unsafe {
+        let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
+        **var = 42;
+        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_static_u32\0").unwrap();
+        assert_eq!(42, help());
+    }
+}
+
+#[test]
+fn test_static_ptr() {
+    make_helpers();
+    let lib = Library::new(LIBPATH).unwrap();
+    unsafe {
+        let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
+        **var = *var as *mut _;
+        let works: Symbol<unsafe extern fn() -> bool> =
+            lib.get(b"test_check_static_ptr\0").unwrap();
+        assert!(works());
+    }
+}
+
+#[cfg(any(windows, target_os="linux"))]
+#[cfg(test_nightly)]
+#[test]
+fn test_tls_static() {
+    make_helpers();
+    let lib = Library::new(LIBPATH).unwrap();
+    unsafe {
+        let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap();
+        **var = 84;
+        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
+        assert_eq!(84, help());
+    }
+    ::std::thread::spawn(move || unsafe {
+        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
+        assert_eq!(0, help());
+    }).join().unwrap();
+}
diff --git a/third_party/rust/libloading/tests/statics.rs b/third_party/rust/libloading/tests/statics.rs
deleted file mode 100644
index 7a7f4e9a3b5d..000000000000
--- a/third_party/rust/libloading/tests/statics.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-extern crate libloading;
-use libloading::{Symbol, Library};
-
-const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.dll");
-
-#[test]
-fn test_static_u32() {
-    let lib = Library::new(LIBPATH).unwrap();
-    unsafe {
-        let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
-        **var = 42;
-        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_static_u32\0").unwrap();
-        assert_eq!(42, help());
-    }
-}
-
-#[test]
-fn test_static_ptr() {
-    let lib = Library::new(LIBPATH).unwrap();
-    unsafe {
-        let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
-        **var = *var as *mut _;
-        let works: Symbol<unsafe extern fn() -> bool> =
-            lib.get(b"test_check_static_ptr\0").unwrap();
-        assert!(works());
-    }
-}
-
-#[cfg(any(windows, target_os="linux"))]
-#[cfg(test_nightly)]
-#[test]
-fn test_tls_static() {
-    let lib = Library::new(LIBPATH).unwrap();
-    unsafe {
-        let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap();
-        **var = 84;
-        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
-        assert_eq!(84, help());
-    }
-    ::std::thread::spawn(move || unsafe {
-        let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
-        assert_eq!(0, help());
-    }).join().unwrap();
-}
diff --git a/third_party/rust/memchr-1.0.2/.cargo-checksum.json b/third_party/rust/memchr-1.0.2/.cargo-checksum.json
new file mode 100644
index 000000000000..872391ed2a88
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".travis.yml":"7c44542bc6662b5af4f15a98b2bcf052a57190922eb280bce93688785c31e323","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"38694643a2d98dc66c1ea8583b9ee49210e8d92205835e43d9a8cc3216e680fe","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"74e385c51a2402527a61a500d66e509fea97961f15bfffab85040064e576fe31","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","appveyor.yml":"b5c1a28f805854370f24e530df912764a9520f4581b33da090f44cec0eef181c","benches/bench.rs":"87cfb76154c3c322691201c6f5649b37665ed8bf1cf303bca971309a4eef6b61","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"98c86c86fd996455d7ec94bdfdcedd3ded3b2a7016480d3474808cfe36d00a63"},"package":"148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"}
\ No newline at end of file
diff --git a/third_party/rust/memchr-1.0.2/.travis.yml b/third_party/rust/memchr-1.0.2/.travis.yml
new file mode 100644
index 000000000000..9120fc1d1f4d
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/.travis.yml
@@ -0,0 +1,14 @@
+language: rust
+rust:
+  - 1.12.0
+  - stable
+  - beta
+  - nightly
+script:
+  - cargo build --verbose --no-default-features
+  - cargo build --verbose
+  - cargo test --verbose
+  - cargo doc
+  - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+      cargo bench --verbose;
+    fi
diff --git a/third_party/rust/memchr-1.0.2/COPYING b/third_party/rust/memchr-1.0.2/COPYING
new file mode 100644
index 000000000000..bb9c20a094e4
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/COPYING
@@ -0,0 +1,3 @@
+This project is dual-licensed under the Unlicense and MIT licenses.
+
+You may use this code under the terms of either license.
diff --git a/third_party/rust/memchr-1.0.2/Cargo.toml b/third_party/rust/memchr-1.0.2/Cargo.toml
new file mode 100644
index 000000000000..2bb28a8eaa2f
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/Cargo.toml
@@ -0,0 +1,44 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "memchr"
+version = "1.0.2"
+authors = ["Andrew Gallant <jamslam@gmail.com>", "bluss"]
+description = "Safe interface to memchr."
+homepage = "https://github.com/BurntSushi/rust-memchr"
+documentation = "https://docs.rs/memchr/"
+readme = "README.md"
+keywords = ["memchr", "char", "scan", "strchr", "string"]
+license = "Unlicense/MIT"
+repository = "https://github.com/BurntSushi/rust-memchr"
+[profile.test]
+opt-level = 3
+
+[lib]
+name = "memchr"
+bench = false
+[dependencies.libc]
+version = "0.2.18"
+optional = true
+default-features = false
+[dev-dependencies.quickcheck]
+version = "0.4.1"
+
+[features]
+default = ["use_std", "libc"]
+use_std = ["libc", "libc/use_std"]
+[badges.appveyor]
+repository = "BurntSushi/rust-memchr"
+
+[badges.travis-ci]
+repository = "BurntSushi/rust-memchr"
diff --git a/third_party/rust/memchr-1.0.2/LICENSE-MIT b/third_party/rust/memchr-1.0.2/LICENSE-MIT
new file mode 100644
index 000000000000..3b0a5dc09c1e
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Gallant
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/rust/memchr-1.0.2/Makefile b/third_party/rust/memchr-1.0.2/Makefile
new file mode 100644
index 000000000000..9f956f4c4338
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/Makefile
@@ -0,0 +1,14 @@
+all:
+	echo Nothing to do...
+
+ctags:
+	ctags --recurse --options=ctags.rust --languages=Rust
+
+docs:
+	cargo doc
+	in-dir ./target/doc fix-perms
+	rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
+
+push:
+	git push origin master
+	git push github master
diff --git a/third_party/rust/memchr-1.0.2/README.md b/third_party/rust/memchr-1.0.2/README.md
new file mode 100644
index 000000000000..1e7548ef3203
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/README.md
@@ -0,0 +1,36 @@
+This crate provides a safe interface `libc`'s `memchr` and `memrchr`.
+This crate also provides fallback implementations when either function is
+unavailable.
+
+[![Build status](https://api.travis-ci.org/BurntSushi/rust-memchr.png)](https://travis-ci.org/BurntSushi/rust-memchr)
+[![Build status](https://ci.appveyor.com/api/projects/status/8i9484t8l4w7uql0/branch/master?svg=true)](https://ci.appveyor.com/project/BurntSushi/rust-memchr/branch/master)
+[![](http://meritbadge.herokuapp.com/memchr)](https://crates.io/crates/memchr)
+
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+
+
+### Documentation
+
+[https://docs.rs/memchr](https://docs.rs/memchr)
+
+### no_std
+
+memchr links to the standard library by default, but you can disable the
+`use_std` feature if you want to use it in a `#![no_std]` crate:
+
+```toml
+[dependencies]
+memchr = { version = "1.0", default-features = false }
+```
+
+### Performance
+
+On my system (Linux/amd64), `memchr` is about an order of magnitude faster than
+the more idiomatic `haystack.iter().position(|&b| b == needle)`:
+
+```
+test iterator          ... bench:       5,280 ns/iter (+/- 13) = 1893 MB/s
+test iterator_reversed ... bench:       5,271 ns/iter (+/- 7) = 1897 MB/s
+test libc_memchr       ... bench:         202 ns/iter (+/- 0) = 49504 MB/s
+test libc_memrchr      ... bench:         197 ns/iter (+/- 1) = 50761 MB/s
+```
diff --git a/third_party/rust/memchr-1.0.2/UNLICENSE b/third_party/rust/memchr-1.0.2/UNLICENSE
new file mode 100644
index 000000000000..68a49daad8ff
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/third_party/rust/memchr-1.0.2/appveyor.yml b/third_party/rust/memchr-1.0.2/appveyor.yml
new file mode 100644
index 000000000000..e572642c31a1
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/appveyor.yml
@@ -0,0 +1,19 @@
+environment:
+  matrix:
+  - TARGET: x86_64-pc-windows-msvc
+  - TARGET: i686-pc-windows-msvc
+  - TARGET: i686-pc-windows-gnu
+install:
+  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
+  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
+  - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
+  - SET PATH=%PATH%;C:\MinGW\bin
+  - rustc -V
+  - cargo -V
+
+build: false
+
+test_script:
+  - cargo build --verbose
+  - cargo test --verbose
+  - cargo bench --verbose
diff --git a/third_party/rust/memchr-1.0.2/benches/bench.rs b/third_party/rust/memchr-1.0.2/benches/bench.rs
new file mode 100644
index 000000000000..949b2228a5bd
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/benches/bench.rs
@@ -0,0 +1,117 @@
+#![feature(test)]
+
+extern crate memchr;
+extern crate test;
+
+use std::iter;
+
+fn bench_data() -> Vec<u8> { iter::repeat(b'z').take(10000).collect() }
+
+#[bench]
+fn iterator_memchr(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let needle = b'a';
+    b.iter(|| {
+        assert!(haystack.iter().position(|&b| b == needle).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn optimized_memchr(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let needle = b'a';
+    b.iter(|| {
+        assert!(memchr::memchr(needle, &haystack).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn iterator_memrchr(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let needle = b'a';
+    b.iter(|| {
+        assert!(haystack.iter().rposition(|&b| b == needle).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn optimized_memrchr(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let needle = b'a';
+    b.iter(|| {
+        assert!(memchr::memrchr(needle, &haystack).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn iterator_memchr2(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let (needle1, needle2) = (b'a', b'b');
+    b.iter(|| {
+        assert!(haystack.iter().position(|&b| {
+            b == needle1 || b == needle2
+        }).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn manual_memchr2(b: &mut test::Bencher) {
+    fn find_singles(
+        sparse: &[bool],
+        text: &[u8],
+    ) -> Option<(usize, usize)> {
+        for (hi, &b) in text.iter().enumerate() {
+            if sparse[b as usize] {
+                return Some((hi, hi+1));
+            }
+        }
+        None
+    }
+
+    let haystack = bench_data();
+    let mut sparse = vec![false; 256];
+    sparse[b'a' as usize] = true;
+    sparse[b'b' as usize] = true;
+    b.iter(|| {
+        assert!(find_singles(&sparse, &haystack).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn optimized_memchr2(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let (needle1, needle2) = (b'a', b'b');
+    b.iter(|| {
+        assert!(memchr::memchr2(needle1, needle2, &haystack).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn iterator_memchr3(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let (needle1, needle2, needle3) = (b'a', b'b', b'c');
+    b.iter(|| {
+        assert!(haystack.iter().position(|&b| {
+            b == needle1 || b == needle2 || b == needle3
+        }).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
+
+#[bench]
+fn optimized_memchr3(b: &mut test::Bencher) {
+    let haystack = bench_data();
+    let (needle1, needle2, needle3) = (b'a', b'b', b'c');
+    b.iter(|| {
+        assert!(memchr::memchr3(
+            needle1, needle2, needle3, &haystack).is_none());
+    });
+    b.bytes = haystack.len() as u64;
+}
diff --git a/third_party/rust/memchr-1.0.2/ctags.rust b/third_party/rust/memchr-1.0.2/ctags.rust
new file mode 100644
index 000000000000..b42edf7579a6
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/ctags.rust
@@ -0,0 +1,11 @@
+--langdef=Rust
+--langmap=Rust:.rs
+--regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/
+--regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/
+--regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/
diff --git a/third_party/rust/memchr-1.0.2/session.vim b/third_party/rust/memchr-1.0.2/session.vim
new file mode 100644
index 000000000000..213c95660bcd
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/session.vim
@@ -0,0 +1 @@
+au BufWritePost *.rs silent!make ctags > /dev/null 2>&1
diff --git a/third_party/rust/memchr-1.0.2/src/lib.rs b/third_party/rust/memchr-1.0.2/src/lib.rs
new file mode 100644
index 000000000000..7faf32353bc2
--- /dev/null
+++ b/third_party/rust/memchr-1.0.2/src/lib.rs
@@ -0,0 +1,881 @@
+/*!
+This crate defines two functions, `memchr` and `memrchr`, which expose a safe interface
+to the corresponding functions in `libc`.
+*/
+
+#![deny(missing_docs)]
+#![allow(unused_imports)]
+
+#![cfg_attr(not(feature = "use_std"), no_std)]
+
+#[cfg(all(test, not(feature = "use_std")))]
+#[macro_use]
+extern crate std;
+
+#[cfg(feature = "libc")]
+extern crate libc;
+
+#[cfg(feature = "libc")]
+use libc::c_void;
+#[cfg(feature = "libc")]
+use libc::{c_int, size_t};
+
+#[cfg(feature = "use_std")]
+use std::cmp;
+#[cfg(not(feature = "use_std"))]
+use core::cmp;
+
+const LO_U64: u64 = 0x0101010101010101;
+const HI_U64: u64 = 0x8080808080808080;
+
+// use truncation
+const LO_USIZE: usize = LO_U64 as usize;
+const HI_USIZE: usize = HI_U64 as usize;
+
+#[cfg(target_pointer_width = "32")]
+const USIZE_BYTES: usize = 4;
+#[cfg(target_pointer_width = "64")]
+const USIZE_BYTES: usize = 8;
+
+/// Return `true` if `x` contains any zero byte.
+///
+/// From *Matters Computational*, J. Arndt
+///
+/// "The idea is to subtract one from each of the bytes and then look for
+/// bytes where the borrow propagated all the way to the most significant
+/// bit."
+#[inline]
+fn contains_zero_byte(x: usize) -> bool {
+    x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
+}
+
+#[cfg(target_pointer_width = "32")]
+#[inline]
+fn repeat_byte(b: u8) -> usize {
+    let mut rep = (b as usize) << 8 | b as usize;
+    rep = rep << 16 | rep;
+    rep
+}
+
+#[cfg(target_pointer_width = "64")]
+#[inline]
+fn repeat_byte(b: u8) -> usize {
+    let mut rep = (b as usize) << 8 | b as usize;
+    rep = rep << 16 | rep;
+    rep = rep << 32 | rep;
+    rep
+}
+
+/// An iterator for memchr
+pub struct Memchr<'a> {
+    needle: u8,
+    // The haystack to iterate over
+    haystack: &'a [u8],
+    // The index
+    position: usize,
+}
+
+impl<'a> Memchr<'a> {
+    /// Creates a new iterator that yields all positions of needle in haystack.
+    pub fn new(needle: u8, haystack: &[u8]) -> Memchr {
+        Memchr {
+            needle: needle,
+            haystack: haystack,
+            position: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for Memchr<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        let search_result = memchr(self.needle, &self.haystack);
+        match search_result {
+            Some(index) => {
+                // Move our internal position
+                self.haystack = self.haystack.split_at(index + 1).1;
+                self.position = self.position + index + 1;
+                Some(self.position)
+            }
+            None => None,
+        }
+    }
+}
+
+impl<'a> DoubleEndedIterator for Memchr<'a> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        let search_result = memrchr(self.needle, &self.haystack);
+        match search_result {
+            Some(index) => {
+                // Move our internal position
+                self.haystack = self.haystack.split_at(index).0;
+                Some(self.position + index + 1)
+            }
+            None => None,
+        }
+    }
+}
+
+/// A safe interface to `memchr`.
+///
+/// Returns the index corresponding to the first occurrence of `needle` in
+/// `haystack`, or `None` if one is not found.
+///
+/// memchr reduces to super-optimized machine code at around an order of
+/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
+/// (See benchmarks.)
+///
+/// # Example
+///
+/// This shows how to find the first position of a byte in a byte string.
+///
+/// ```rust
+/// use memchr::memchr;
+///
+/// let haystack = b"the quick brown fox";
+/// assert_eq!(memchr(b'k', haystack), Some(8));
+/// ```
+#[inline(always)] // reduces constant overhead
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+    // libc memchr
+    #[cfg(all(feature = "libc",
+              any(not(target_os = "windows"),
+                  not(any(target_pointer_width = "32",
+                          target_pointer_width = "64")))))]
+    #[inline(always)] // reduces constant overhead
+    fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        use libc::memchr as libc_memchr;
+
+        let p = unsafe {
+            libc_memchr(haystack.as_ptr() as *const c_void,
+                        needle as c_int,
+                        haystack.len() as size_t)
+        };
+        if p.is_null() {
+            None
+        } else {
+            Some(p as usize - (haystack.as_ptr() as usize))
+        }
+    }
+
+    // use fallback on windows, since it's faster
+    #[cfg(all(any(not(feature = "libc"), target_os = "windows"),
+              any(target_pointer_width = "32",
+                  target_pointer_width = "64")))]
+    fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        fallback::memchr(needle, haystack)
+    }
+
+    // For the rare case of neither 32 bit nor 64-bit platform.
+    #[cfg(all(any(not(feature = "libc"), target_os = "windows"),
+              not(target_pointer_width = "32"),
+              not(target_pointer_width = "64")))]
+    fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        haystack.iter().position(|&b| b == needle)
+    }
+
+    memchr_specific(needle, haystack)
+}
+
+/// A safe interface to `memrchr`.
+///
+/// Returns the index corresponding to the last occurrence of `needle` in
+/// `haystack`, or `None` if one is not found.
+///
+/// # Example
+///
+/// This shows how to find the last position of a byte in a byte string.
+///
+/// ```rust
+/// use memchr::memrchr;
+///
+/// let haystack = b"the quick brown fox";
+/// assert_eq!(memrchr(b'o', haystack), Some(17));
+/// ```
+#[inline(always)] // reduces constant overhead
+pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+
+    #[cfg(all(feature = "libc", target_os = "linux"))]
+    #[inline(always)] // reduces constant overhead
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
+        if haystack.is_empty() {
+            return None;
+        }
+        let p = unsafe {
+            libc::memrchr(haystack.as_ptr() as *const c_void,
+                          needle as c_int,
+                          haystack.len() as size_t)
+        };
+        if p.is_null() {
+            None
+        } else {
+            Some(p as usize - (haystack.as_ptr() as usize))
+        }
+    }
+
+    #[cfg(all(not(all(feature = "libc", target_os = "linux")),
+              any(target_pointer_width = "32", target_pointer_width = "64")))]
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        fallback::memrchr(needle, haystack)
+    }
+
+    // For the rare case of neither 32 bit nor 64-bit platform.
+    #[cfg(all(not(all(feature = "libc", target_os = "linux")),
+              not(target_pointer_width = "32"),
+              not(target_pointer_width = "64")))]
+    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
+        haystack.iter().rposition(|&b| b == needle)
+    }
+
+    memrchr_specific(needle, haystack)
+}
+
+/// An iterator for Memchr2
+pub struct Memchr2<'a> {
+    needle1: u8,
+    needle2: u8,
+    // The haystack to iterate over
+    haystack: &'a [u8],
+    // The index
+    position: usize,
+}
+
+impl<'a> Memchr2<'a> {
+    /// Creates a new iterator that yields all positions of needle in haystack.
+    pub fn new(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2 {
+        Memchr2 {
+            needle1: needle1,
+            needle2: needle2,
+            haystack: haystack,
+            position: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for Memchr2<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        let search_result = memchr2(self.needle1, self.needle2, &self.haystack);
+        match search_result {
+            Some(index) => {
+                // Move our internal position
+                self.haystack = self.haystack.split_at(index + 1).1;
+                self.position = self.position + index + 1;
+                Some(self.position)
+            }
+            None => None,
+        }
+    }
+}
+
+
+/// Like `memchr`, but searches for two bytes instead of one.
+pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
+    fn slow(b1: u8, b2: u8, haystack: &[u8]) -> Option<usize> {
+        haystack.iter().position(|&b| b == b1 || b == b2)
+    }
+
+    let len = haystack.len();
+    let ptr = haystack.as_ptr();
+    let align = (ptr as usize) & (USIZE_BYTES - 1);
+    let mut i = 0;
+    if align > 0 {
+        i = cmp::min(USIZE_BYTES - align, len);
+        if let Some(found) = slow(needle1, needle2, &haystack[..i]) {
+            return Some(found);
+        }
+    }
+    let repeated_b1 = repeat_byte(needle1);
+    let repeated_b2 = repeat_byte(needle2);
+    if len >= USIZE_BYTES {
+        while i <= len - USIZE_BYTES {
+            unsafe {
+                let u = *(ptr.offset(i as isize) as *const usize);
+                let found_ub1 = contains_zero_byte(u ^ repeated_b1);
+                let found_ub2 = contains_zero_byte(u ^ repeated_b2);
+                if found_ub1 || found_ub2 {
+                    break;
+                }
+            }
+            i += USIZE_BYTES;
+        }
+    }
+    slow(needle1, needle2, &haystack[i..]).map(|pos| i + pos)
+}
+
+/// An iterator for Memchr3
+pub struct Memchr3<'a> {
+    needle1: u8,
+    needle2: u8,
+    needle3: u8,
+    // The haystack to iterate over
+    haystack: &'a [u8],
+    // The index
+    position: usize,
+}
+
+impl<'a> Memchr3<'a> {
+    /// Create a new Memchr2 that's initalized to zero with a haystack
+    pub fn new(needle1: u8, needle2: u8, needle3: u8, haystack: &[u8]) -> Memchr3 {
+        Memchr3 {
+            needle1: needle1,
+            needle2: needle2,
+            needle3: needle3,
+            haystack: haystack,
+            position: 0,
+        }
+    }
+}
+
+impl<'a> Iterator for Memchr3<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        let search_result = memchr3(self.needle1, self.needle2, self.needle3, &self.haystack);
+        match search_result {
+            Some(index) => {
+                // Move our internal position
+                self.haystack = self.haystack.split_at(index + 1).1;
+                self.position = self.position + index + 1;
+                Some(self.position)
+            }
+            None => None,
+        }
+    }
+}
+
+/// Like `memchr`, but searches for three bytes instead of one.
+pub fn memchr3(needle1: u8, needle2: u8, needle3: u8, haystack: &[u8]) -> Option<usize> {
+    fn slow(b1: u8, b2: u8, b3: u8, haystack: &[u8]) -> Option<usize> {
+        haystack.iter().position(|&b| b == b1 || b == b2 || b == b3)
+    }
+
+    let len = haystack.len();
+    let ptr = haystack.as_ptr();
+    let align = (ptr as usize) & (USIZE_BYTES - 1);
+    let mut i = 0;
+    if align > 0 {
+        i = cmp::min(USIZE_BYTES - align, len);
+        if let Some(found) = slow(needle1, needle2, needle3, &haystack[..i]) {
+            return Some(found);
+        }
+    }
+    let repeated_b1 = repeat_byte(needle1);
+    let repeated_b2 = repeat_byte(needle2);
+    let repeated_b3 = repeat_byte(needle3);
+    if len >= USIZE_BYTES {
+        while i <= len - USIZE_BYTES {
+            unsafe {
+                let u = *(ptr.offset(i as isize) as *const usize);
+                let found_ub1 = contains_zero_byte(u ^ repeated_b1);
+                let found_ub2 = contains_zero_byte(u ^ repeated_b2);
+                let found_ub3 = contains_zero_byte(u ^ repeated_b3);
+                if found_ub1 || found_ub2 || found_ub3 {
+                    break;
+                }
+            }
+            i += USIZE_BYTES;
+        }
+    }
+    slow(needle1, needle2, needle3, &haystack[i..]).map(|pos| i + pos)
+}
+
+#[allow(dead_code)]
+#[cfg(any(test, not(feature = "libc"), all(not(target_os = "linux"),
+          any(target_pointer_width = "32", target_pointer_width = "64"))))]
+mod fallback {
+    #[cfg(feature = "use_std")]
+    use std::cmp;
+    #[cfg(not(feature = "use_std"))]
+    use core::cmp;
+
+    use super::{LO_U64, HI_U64, LO_USIZE, HI_USIZE, USIZE_BYTES, contains_zero_byte, repeat_byte};
+
+    /// Return the first index matching the byte `a` in `text`.
+    pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
+        // Scan for a single byte value by reading two `usize` words at a time.
+        //
+        // Split `text` in three parts
+        // - unaligned inital part, before the first word aligned address in text
+        // - body, scan by 2 words at a time
+        // - the last remaining part, < 2 word size
+        let len = text.len();
+        let ptr = text.as_ptr();
+
+        // search up to an aligned boundary
+        let align = (ptr as usize) & (USIZE_BYTES - 1);
+        let mut offset;
+        if align > 0 {
+            offset = cmp::min(USIZE_BYTES - align, len);
+            if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
+                return Some(index);
+            }
+        } else {
+            offset = 0;
+        }
+
+        // search the body of the text
+        let repeated_x = repeat_byte(x);
+
+        if len >= 2 * USIZE_BYTES {
+            while offset <= len - 2 * USIZE_BYTES {
+                debug_assert_eq!((ptr as usize + offset) % USIZE_BYTES, 0);
+                unsafe {
+                    let u = *(ptr.offset(offset as isize) as *const usize);
+                    let v = *(ptr.offset((offset + USIZE_BYTES) as isize) as *const usize);
+
+                    // break if there is a matching byte
+                    let zu = contains_zero_byte(u ^ repeated_x);
+                    let zv = contains_zero_byte(v ^ repeated_x);
+                    if zu || zv {
+                        break;
+                    }
+                }
+                offset += USIZE_BYTES * 2;
+            }
+        }
+
+        // find the byte after the point the body loop stopped
+        text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
+    }
+
+    /// Return the last index matching the byte `a` in `text`.
+    pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
+        // Scan for a single byte value by reading two `usize` words at a time.
+        //
+        // Split `text` in three parts
+        // - unaligned tail, after the last word aligned address in text
+        // - body, scan by 2 words at a time
+        // - the first remaining bytes, < 2 word size
+        let len = text.len();
+        let ptr = text.as_ptr();
+
+        // search to an aligned boundary
+        let end_align = (ptr as usize + len) & (USIZE_BYTES - 1);
+        let mut offset;
+        if end_align > 0 {
+            offset = if end_align >= len { 0 } else { len - end_align };
+            if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
+                return Some(offset + index);
+            }
+        } else {
+            offset = len;
+        }
+
+        // search the body of the text
+        let repeated_x = repeat_byte(x);
+
+        while offset >= 2 * USIZE_BYTES {
+            debug_assert_eq!((ptr as usize + offset) % USIZE_BYTES, 0);
+            unsafe {
+                let u = *(ptr.offset(offset as isize - 2 * USIZE_BYTES as isize) as *const usize);
+                let v = *(ptr.offset(offset as isize - USIZE_BYTES as isize) as *const usize);
+
+                // break if there is a matching byte
+                let zu = contains_zero_byte(u ^ repeated_x);
+                let zv = contains_zero_byte(v ^ repeated_x);
+                if zu || zv {
+                    break;
+                }
+            }
+            offset -= 2 * USIZE_BYTES;
+        }
+
+        // find the byte before the point the body loop stopped
+        text[..offset].iter().rposition(|elt| *elt == x)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate quickcheck;
+    use std::prelude::v1::*;
+
+    use super::{memchr, memrchr, memchr2, memchr3, Memchr, Memchr2, Memchr3};
+    // Use a macro to test both native and fallback impls on all configurations
+    macro_rules! memchr_tests {
+        ($mod_name:ident, $memchr:path, $memrchr:path) => {
+            mod $mod_name {
+            use std::prelude::v1::*;
+            use super::quickcheck;
+            #[test]
+            fn matches_one() {
+                assert_eq!(Some(0), $memchr(b'a', b"a"));
+            }
+
+            #[test]
+            fn matches_begin() {
+                assert_eq!(Some(0), $memchr(b'a', b"aaaa"));
+            }
+
+            #[test]
+            fn matches_end() {
+                assert_eq!(Some(4), $memchr(b'z', b"aaaaz"));
+            }
+
+            #[test]
+            fn matches_nul() {
+                assert_eq!(Some(4), $memchr(b'\x00', b"aaaa\x00"));
+            }
+
+            #[test]
+            fn matches_past_nul() {
+                assert_eq!(Some(5), $memchr(b'z', b"aaaa\x00z"));
+            }
+
+            #[test]
+            fn no_match_empty() {
+                assert_eq!(None, $memchr(b'a', b""));
+            }
+
+            #[test]
+            fn no_match() {
+                assert_eq!(None, $memchr(b'a', b"xyz"));
+            }
+
+            #[test]
+            fn qc_never_fail() {
+                fn prop(needle: u8, haystack: Vec<u8>) -> bool {
+                    $memchr(needle, &haystack); true
+                }
+                quickcheck::quickcheck(prop as fn(u8, Vec<u8>) -> bool);
+            }
+
+            #[test]
+            fn matches_one_reversed() {
+                assert_eq!(Some(0), $memrchr(b'a', b"a"));
+            }
+
+            #[test]
+            fn matches_begin_reversed() {
+                assert_eq!(Some(3), $memrchr(b'a', b"aaaa"));
+            }
+
+            #[test]
+            fn matches_end_reversed() {
+                assert_eq!(Some(0), $memrchr(b'z', b"zaaaa"));
+            }
+
+            #[test]
+            fn matches_nul_reversed() {
+                assert_eq!(Some(4), $memrchr(b'\x00', b"aaaa\x00"));
+            }
+
+            #[test]
+            fn matches_past_nul_reversed() {
+                assert_eq!(Some(0), $memrchr(b'z', b"z\x00aaaa"));
+            }
+
+            #[test]
+            fn no_match_empty_reversed() {
+                assert_eq!(None, $memrchr(b'a', b""));
+            }
+
+            #[test]
+            fn no_match_reversed() {
+                assert_eq!(None, $memrchr(b'a', b"xyz"));
+            }
+
+            #[test]
+            fn qc_never_fail_reversed() {
+                fn prop(needle: u8, haystack: Vec<u8>) -> bool {
+                    $memrchr(needle, &haystack); true
+                }
+                quickcheck::quickcheck(prop as fn(u8, Vec<u8>) -> bool);
+            }
+
+            #[test]
+            fn qc_correct_memchr() {
+                fn prop(v: Vec<u8>, offset: u8) -> bool {
+                    // test all pointer alignments
+                    let uoffset = (offset & 0xF) as usize;
+                    let data = if uoffset <= v.len() {
+                        &v[uoffset..]
+                    } else {
+                        &v[..]
+                    };
+                    for byte in 0..256u32 {
+                        let byte = byte as u8;
+                        if $memchr(byte, &data) != data.iter().position(|elt| *elt == byte) {
+                            return false;
+                        }
+                    }
+                    true
+                }
+                quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
+            }
+
+            #[test]
+            fn qc_correct_memrchr() {
+                fn prop(v: Vec<u8>, offset: u8) -> bool {
+                    // test all pointer alignments
+                    let uoffset = (offset & 0xF) as usize;
+                    let data = if uoffset <= v.len() {
+                        &v[uoffset..]
+                    } else {
+                        &v[..]
+                    };
+                    for byte in 0..256u32 {
+                        let byte = byte as u8;
+                        if $memrchr(byte, &data) != data.iter().rposition(|elt| *elt == byte) {
+                            return false;
+                        }
+                    }
+                    true
+                }
+                quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
+            }
+            }
+        }
+    }
+
+    memchr_tests! { native, ::memchr, ::memrchr }
+    memchr_tests! { fallback, ::fallback::memchr, ::fallback::memrchr }
+
+    #[test]
+    fn memchr2_matches_one() {
+        assert_eq!(Some(0), memchr2(b'a', b'b', b"a"));
+        assert_eq!(Some(0), memchr2(b'a', b'b', b"b"));
+        assert_eq!(Some(0), memchr2(b'b', b'a', b"a"));
+        assert_eq!(Some(0), memchr2(b'b', b'a', b"b"));
+    }
+
+    #[test]
+    fn memchr2_matches_begin() {
+        assert_eq!(Some(0), memchr2(b'a', b'b', b"aaaa"));
+        assert_eq!(Some(0), memchr2(b'a', b'b', b"bbbb"));
+    }
+
+    #[test]
+    fn memchr2_matches_end() {
+        assert_eq!(Some(4), memchr2(b'z', b'y', b"aaaaz"));
+        assert_eq!(Some(4), memchr2(b'z', b'y', b"aaaay"));
+    }
+
+    #[test]
+    fn memchr2_matches_nul() {
+        assert_eq!(Some(4), memchr2(b'\x00', b'z', b"aaaa\x00"));
+        assert_eq!(Some(4), memchr2(b'z', b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn memchr2_matches_past_nul() {
+        assert_eq!(Some(5), memchr2(b'z', b'y', b"aaaa\x00z"));
+        assert_eq!(Some(5), memchr2(b'y', b'z', b"aaaa\x00z"));
+    }
+
+    #[test]
+    fn memchr2_no_match_empty() {
+        assert_eq!(None, memchr2(b'a', b'b', b""));
+        assert_eq!(None, memchr2(b'b', b'a', b""));
+    }
+
+    #[test]
+    fn memchr2_no_match() {
+        assert_eq!(None, memchr2(b'a', b'b', b"xyz"));
+    }
+
+    #[test]
+    fn qc_never_fail_memchr2() {
+        fn prop(needle1: u8, needle2: u8, haystack: Vec<u8>) -> bool {
+            memchr2(needle1, needle2, &haystack);
+            true
+        }
+        quickcheck::quickcheck(prop as fn(u8, u8, Vec<u8>) -> bool);
+    }
+
+    #[test]
+    fn memchr3_matches_one() {
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"a"));
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"b"));
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"c"));
+    }
+
+    #[test]
+    fn memchr3_matches_begin() {
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"aaaa"));
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"bbbb"));
+        assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"cccc"));
+    }
+
+    #[test]
+    fn memchr3_matches_end() {
+        assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaaz"));
+        assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaay"));
+        assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaax"));
+    }
+
+    #[test]
+    fn memchr3_matches_nul() {
+        assert_eq!(Some(4), memchr3(b'\x00', b'z', b'y', b"aaaa\x00"));
+        assert_eq!(Some(4), memchr3(b'z', b'\x00', b'y', b"aaaa\x00"));
+        assert_eq!(Some(4), memchr3(b'z', b'y', b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn memchr3_matches_past_nul() {
+        assert_eq!(Some(5), memchr3(b'z', b'y', b'x', b"aaaa\x00z"));
+        assert_eq!(Some(5), memchr3(b'y', b'z', b'x', b"aaaa\x00z"));
+        assert_eq!(Some(5), memchr3(b'y', b'x', b'z', b"aaaa\x00z"));
+    }
+
+    #[test]
+    fn memchr3_no_match_empty() {
+        assert_eq!(None, memchr3(b'a', b'b', b'c', b""));
+        assert_eq!(None, memchr3(b'b', b'a', b'c', b""));
+        assert_eq!(None, memchr3(b'c', b'b', b'a', b""));
+    }
+
+    #[test]
+    fn memchr3_no_match() {
+        assert_eq!(None, memchr3(b'a', b'b', b'c', b"xyz"));
+    }
+
+    #[test]
+    fn memchr_iter() {
+        let haystack = b"aaaabaaaab";
+        let mut memchr_iter = Memchr::new(b'b', haystack);
+        let first = memchr_iter.next();
+        let second = memchr_iter.next();
+        let third = memchr_iter.next();
+        assert_eq!(Some(5), first);
+        assert_eq!(Some(10), second);
+        assert_eq!(None, third);
+    }
+
+    #[test]
+    fn memchr2_iter() {
+        let haystack = b"ab";
+        let mut memchr_iter = Memchr2::new(b'a', b'b', haystack);
+        let first = memchr_iter.next();
+        let second = memchr_iter.next();
+        let third = memchr_iter.next();
+        assert_eq!(Some(1), first);
+        assert_eq!(Some(2), second);
+        assert_eq!(None, third);
+    }
+
+    #[test]
+    fn memchr3_iter() {
+        let haystack = b"abc";
+        let mut memchr_iter = Memchr3::new(b'a', b'b', b'c', haystack);
+        let first = memchr_iter.next();
+        let second = memchr_iter.next();
+        let third = memchr_iter.next();
+        let fourth = memchr_iter.next();
+        assert_eq!(Some(1), first);
+        assert_eq!(Some(2), second);
+        assert_eq!(Some(3), third);
+        assert_eq!(None, fourth);
+    }
+
+    #[test]
+    fn memchr_reverse_iter() {
+        let haystack = b"aaaabaaaabaaaab";
+        let mut memchr_iter = Memchr::new(b'b', haystack);
+        let first = memchr_iter.next();
+        let second = memchr_iter.next_back();
+        let third = memchr_iter.next();
+        let fourth = memchr_iter.next_back();
+
+        assert_eq!(Some(5), first);
+        assert_eq!(Some(15), second);
+        assert_eq!(Some(10), third);
+        assert_eq!(None, fourth);
+    }
+
+    #[test]
+    fn memrchr_iter(){
+        let haystack = b"aaaabaaaabaaaab";
+        let mut memchr_iter = Memchr::new(b'b', haystack);
+        let first = memchr_iter.next_back();
+        let second = memchr_iter.next_back();
+        let third = memchr_iter.next_back();
+        let fourth = memchr_iter.next_back();
+
+        assert_eq!(Some(15), first);
+        assert_eq!(Some(10), second);
+        assert_eq!(Some(5), third);
+        assert_eq!(None, fourth);
+
+    }
+
+    #[test]
+    fn qc_never_fail_memchr3() {
+        fn prop(needle1: u8, needle2: u8, needle3: u8, haystack: Vec<u8>) -> bool {
+            memchr3(needle1, needle2, needle3, &haystack);
+            true
+        }
+        quickcheck::quickcheck(prop as fn(u8, u8, u8, Vec<u8>) -> bool);
+    }
+
+    #[test]
+    fn qc_correct_memchr() {
+        fn prop(v: Vec<u8>, offset: u8) -> bool {
+            // test all pointer alignments
+            let uoffset = (offset & 0xF) as usize;
+            let data = if uoffset <= v.len() {
+                &v[uoffset..]
+            } else {
+                &v[..]
+            };
+            for byte in 0..256u32 {
+                let byte = byte as u8;
+                if memchr(byte, &data) != data.iter().position(|elt| *elt == byte) {
+                    return false;
+                }
+            }
+            true
+        }
+        quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
+    }
+
+    #[test]
+    fn qc_correct_memrchr() {
+        fn prop(v: Vec<u8>, offset: u8) -> bool {
+            // test all pointer alignments
+            let uoffset = (offset & 0xF) as usize;
+            let data = if uoffset <= v.len() {
+                &v[uoffset..]
+            } else {
+                &v[..]
+            };
+            for byte in 0..256u32 {
+                let byte = byte as u8;
+                if memrchr(byte, &data) != data.iter().rposition(|elt| *elt == byte) {
+                    return false;
+                }
+            }
+            true
+        }
+        quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
+    }
+
+    #[test]
+    fn qc_correct_memchr2() {
+        fn prop(v: Vec<u8>, offset: u8) -> bool {
+            // test all pointer alignments
+            let uoffset = (offset & 0xF) as usize;
+            let data = if uoffset <= v.len() {
+                &v[uoffset..]
+            } else {
+                &v[..]
+            };
+            for b1 in 0..256u32 {
+                for b2 in 0..256u32 {
+                    let (b1, b2) = (b1 as u8, b2 as u8);
+                    let expected = data.iter().position(|&b| b == b1 || b == b2);
+                    let got = memchr2(b1, b2, &data);
+                    if expected != got {
+                        return false;
+                    }
+                }
+            }
+            true
+        }
+        quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
+    }
+}
diff --git a/third_party/rust/memchr/.cargo-checksum.json b/third_party/rust/memchr/.cargo-checksum.json
index 872391ed2a88..cac0454e78ab 100644
--- a/third_party/rust/memchr/.cargo-checksum.json
+++ b/third_party/rust/memchr/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"7c44542bc6662b5af4f15a98b2bcf052a57190922eb280bce93688785c31e323","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"38694643a2d98dc66c1ea8583b9ee49210e8d92205835e43d9a8cc3216e680fe","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"74e385c51a2402527a61a500d66e509fea97961f15bfffab85040064e576fe31","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","appveyor.yml":"b5c1a28f805854370f24e530df912764a9520f4581b33da090f44cec0eef181c","benches/bench.rs":"87cfb76154c3c322691201c6f5649b37665ed8bf1cf303bca971309a4eef6b61","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"98c86c86fd996455d7ec94bdfdcedd3ded3b2a7016480d3474808cfe36d00a63"},"package":"148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"}
\ No newline at end of file
+{"files":{".travis.yml":"84e5793f37584e4756d8e7ec5ad3eea9a4102e04dfcb4dac7da63526b819aa8f","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"bfd1e2c6bbfca288e64009a1453fd8e9e8a2a48a38331a6795a4b90dbe7652f7","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"c6d916d541fc7ee000ee3bcddf014b241bbd6976930462f27985f12081d77faa","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","appveyor.yml":"0c9b5bcd5cefa5841433cb9101b0a5c543d900f7d462057e2c5de8f4ca57c3ce","benches/bench.rs":"87cfb76154c3c322691201c6f5649b37665ed8bf1cf303bca971309a4eef6b61","ci/script.sh":"5bc79c7b4312004b6b08941134de2ea21c295f78f29a55615e0956d2149d433c","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"ead5dca93ef500afc405121848622eff79dd7e084656e0457a5f5e0def604c5a"},"package":"a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"}
\ No newline at end of file
diff --git a/third_party/rust/memchr/.travis.yml b/third_party/rust/memchr/.travis.yml
index 9120fc1d1f4d..6c50f816055c 100644
--- a/third_party/rust/memchr/.travis.yml
+++ b/third_party/rust/memchr/.travis.yml
@@ -1,14 +1,10 @@
 language: rust
 rust:
   - 1.12.0
   - stable
   - beta
   - nightly
-script:
-  - cargo build --verbose --no-default-features
-  - cargo build --verbose
-  - cargo test --verbose
-  - cargo doc
-  - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
-      cargo bench --verbose;
-    fi
+script: ci/script.sh
+branches:
+  only:
+    - master
diff --git a/third_party/rust/memchr/Cargo.toml b/third_party/rust/memchr/Cargo.toml
index 2bb28a8eaa2f..122a0d9913c5 100644
--- a/third_party/rust/memchr/Cargo.toml
+++ b/third_party/rust/memchr/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "memchr"
-version = "1.0.2"
+version = "2.0.2"
 authors = ["Andrew Gallant <jamslam@gmail.com>", "bluss"]
 description = "Safe interface to memchr."
 homepage = "https://github.com/BurntSushi/rust-memchr"
 documentation = "https://docs.rs/memchr/"
 readme = "README.md"
 keywords = ["memchr", "char", "scan", "strchr", "string"]
 license = "Unlicense/MIT"
 repository = "https://github.com/BurntSushi/rust-memchr"
@@ -27,17 +27,18 @@ opt-level = 3
 [lib]
 name = "memchr"
 bench = false
 [dependencies.libc]
 version = "0.2.18"
 optional = true
 default-features = false
 [dev-dependencies.quickcheck]
-version = "0.4.1"
+version = "0.7"
+default-features = false
 
 [features]
 default = ["use_std", "libc"]
 use_std = ["libc", "libc/use_std"]
 [badges.appveyor]
 repository = "BurntSushi/rust-memchr"
 
 [badges.travis-ci]
diff --git a/third_party/rust/memchr/README.md b/third_party/rust/memchr/README.md
index 1e7548ef3203..8c3e19752ef2 100644
--- a/third_party/rust/memchr/README.md
+++ b/third_party/rust/memchr/README.md
@@ -15,17 +15,17 @@ Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
 
 ### no_std
 
 memchr links to the standard library by default, but you can disable the
 `use_std` feature if you want to use it in a `#![no_std]` crate:
 
 ```toml
 [dependencies]
-memchr = { version = "1.0", default-features = false }
+memchr = { version = "2", default-features = false }
 ```
 
 ### Performance
 
 On my system (Linux/amd64), `memchr` is about an order of magnitude faster than
 the more idiomatic `haystack.iter().position(|&b| b == needle)`:
 
 ```
diff --git a/third_party/rust/memchr/appveyor.yml b/third_party/rust/memchr/appveyor.yml
index e572642c31a1..8170c78f315f 100644
--- a/third_party/rust/memchr/appveyor.yml
+++ b/third_party/rust/memchr/appveyor.yml
@@ -5,15 +5,16 @@ environment:
   - TARGET: i686-pc-windows-gnu
 install:
   - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
   - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
   - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
   - SET PATH=%PATH%;C:\MinGW\bin
   - rustc -V
   - cargo -V
-
 build: false
-
 test_script:
   - cargo build --verbose
   - cargo test --verbose
   - cargo bench --verbose
+branches:
+  only:
+    - master
diff --git a/third_party/rust/memchr/ci/script.sh b/third_party/rust/memchr/ci/script.sh
new file mode 100755
index 000000000000..aebb3bd2e217
--- /dev/null
+++ b/third_party/rust/memchr/ci/script.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -ex
+
+cargo build --verbose
+cargo doc --verbose
+
+# If we're testing on an older version of Rust, then only check that we
+# can build the crate. This is because the dev dependencies might be updated
+# more frequently, and therefore might require a newer version of Rust.
+#
+# This isn't ideal. It's a compromise.
+if [ "$TRAVIS_RUST_VERSION" = "1.12.0" ]; then
+  exit
+fi
+
+cargo test --verbose
+if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  cargo bench --verbose --no-run
+fi
diff --git a/third_party/rust/memchr/src/lib.rs b/third_party/rust/memchr/src/lib.rs
index 7faf32353bc2..00fa8550730b 100644
--- a/third_party/rust/memchr/src/lib.rs
+++ b/third_party/rust/memchr/src/lib.rs
@@ -1,28 +1,33 @@
 /*!
-This crate defines two functions, `memchr` and `memrchr`, which expose a safe interface
-to the corresponding functions in `libc`.
+This crate defines two functions, `memchr` and `memrchr`, which expose a safe
+interface to the corresponding functions in `libc`.
 */
 
 #![deny(missing_docs)]
 #![allow(unused_imports)]
+#![doc(html_root_url = "https://docs.rs/memchr/2.0.0")]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
 
 #[cfg(all(test, not(feature = "use_std")))]
 #[macro_use]
 extern crate std;
 
-#[cfg(feature = "libc")]
+#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
 extern crate libc;
 
-#[cfg(feature = "libc")]
+#[macro_use]
+#[cfg(test)]
+extern crate quickcheck;
+
+#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
 use libc::c_void;
-#[cfg(feature = "libc")]
+#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
 use libc::{c_int, size_t};
 
 #[cfg(feature = "use_std")]
 use std::cmp;
 #[cfg(not(feature = "use_std"))]
 use core::cmp;
 
 const LO_U64: u64 = 0x0101010101010101;
@@ -61,16 +66,46 @@ fn repeat_byte(b: u8) -> usize {
 #[inline]
 fn repeat_byte(b: u8) -> usize {
     let mut rep = (b as usize) << 8 | b as usize;
     rep = rep << 16 | rep;
     rep = rep << 32 | rep;
     rep
 }
 
+macro_rules! iter_next {
+    // Common code for the memchr iterators:
+    // update haystack and position and produce the index
+    //
+    // self: &mut Self where Self is the iterator
+    // search_result: Option<usize> which is the result of the corresponding
+    // memchr function.
+    //
+    // Returns Option<usize> (the next iterator element)
+    ($self_:expr, $search_result:expr) => {
+        $search_result.map(move |index| {
+            // split and take the remaining back half
+            $self_.haystack = $self_.haystack.split_at(index + 1).1;
+            let found_position = $self_.position + index;
+            $self_.position = found_position + 1;
+            found_position
+        })
+    }
+}
+
+macro_rules! iter_next_back {
+    ($self_:expr, $search_result:expr) => {
+        $search_result.map(move |index| {
+            // split and take the remaining front half
+            $self_.haystack = $self_.haystack.split_at(index).0;
+            $self_.position + index
+        })
+    }
+}
+
 /// An iterator for memchr
 pub struct Memchr<'a> {
     needle: u8,
     // The haystack to iterate over
     haystack: &'a [u8],
     // The index
     position: usize,
 }
@@ -85,40 +120,27 @@ impl<'a> Memchr<'a> {
         }
     }
 }
 
 impl<'a> Iterator for Memchr<'a> {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
-        let search_result = memchr(self.needle, &self.haystack);
-        match search_result {
-            Some(index) => {
-                // Move our internal position
-                self.haystack = self.haystack.split_at(index + 1).1;
-                self.position = self.position + index + 1;
-                Some(self.position)
-            }
-            None => None,
-        }
+        iter_next!(self, memchr(self.needle, self.haystack))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.haystack.len()))
     }
 }
 
 impl<'a> DoubleEndedIterator for Memchr<'a> {
     fn next_back(&mut self) -> Option<Self::Item> {
-        let search_result = memrchr(self.needle, &self.haystack);
-        match search_result {
-            Some(index) => {
-                // Move our internal position
-                self.haystack = self.haystack.split_at(index).0;
-                Some(self.position + index + 1)
-            }
-            None => None,
-        }
+        iter_next_back!(self, memrchr(self.needle, self.haystack))
     }
 }
 
 /// A safe interface to `memchr`.
 ///
 /// Returns the index corresponding to the first occurrence of `needle` in
 /// `haystack`, or `None` if one is not found.
 ///
@@ -135,16 +157,17 @@ impl<'a> DoubleEndedIterator for Memchr<'a> {
 ///
 /// let haystack = b"the quick brown fox";
 /// assert_eq!(memchr(b'k', haystack), Some(8));
 /// ```
 #[inline(always)] // reduces constant overhead
 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
     // libc memchr
     #[cfg(all(feature = "libc",
+              not(target_arch = "wasm32"),
               any(not(target_os = "windows"),
                   not(any(target_pointer_width = "32",
                           target_pointer_width = "64")))))]
     #[inline(always)] // reduces constant overhead
     fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
         use libc::memchr as libc_memchr;
 
         let p = unsafe {
@@ -155,17 +178,18 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
         if p.is_null() {
             None
         } else {
             Some(p as usize - (haystack.as_ptr() as usize))
         }
     }
 
     // use fallback on windows, since it's faster
-    #[cfg(all(any(not(feature = "libc"), target_os = "windows"),
+    // use fallback on wasm32, since it doesn't have libc
+    #[cfg(all(any(not(feature = "libc"), target_os = "windows", target_arch = "wasm32"),
               any(target_pointer_width = "32",
                   target_pointer_width = "64")))]
     fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
         fallback::memchr(needle, haystack)
     }
 
     // For the rare case of neither 32 bit nor 64-bit platform.
     #[cfg(all(any(not(feature = "libc"), target_os = "windows"),
@@ -253,26 +277,21 @@ impl<'a> Memchr2<'a> {
         }
     }
 }
 
 impl<'a> Iterator for Memchr2<'a> {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
-        let search_result = memchr2(self.needle1, self.needle2, &self.haystack);
-        match search_result {
-            Some(index) => {
-                // Move our internal position
-                self.haystack = self.haystack.split_at(index + 1).1;
-                self.position = self.position + index + 1;
-                Some(self.position)
-            }
-            None => None,
-        }
+        iter_next!(self, memchr2(self.needle1, self.needle2, self.haystack))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.haystack.len()))
     }
 }
 
 
 /// Like `memchr`, but searches for two bytes instead of one.
 pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
     fn slow(b1: u8, b2: u8, haystack: &[u8]) -> Option<usize> {
         haystack.iter().position(|&b| b == b1 || b == b2)
@@ -313,47 +332,55 @@ pub struct Memchr3<'a> {
     needle3: u8,
     // The haystack to iterate over
     haystack: &'a [u8],
     // The index
     position: usize,
 }
 
 impl<'a> Memchr3<'a> {
-    /// Create a new Memchr2 that's initalized to zero with a haystack
-    pub fn new(needle1: u8, needle2: u8, needle3: u8, haystack: &[u8]) -> Memchr3 {
+    /// Create a new `Memchr3` that's initialized to zero with a haystack
+    pub fn new(
+        needle1: u8,
+        needle2: u8,
+        needle3: u8,
+        haystack: &[u8],
+    ) -> Memchr3 {
         Memchr3 {
             needle1: needle1,
             needle2: needle2,
             needle3: needle3,
             haystack: haystack,
             position: 0,
         }
     }
 }
 
 impl<'a> Iterator for Memchr3<'a> {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
-        let search_result = memchr3(self.needle1, self.needle2, self.needle3, &self.haystack);
-        match search_result {
-            Some(index) => {
-                // Move our internal position
-                self.haystack = self.haystack.split_at(index + 1).1;
-                self.position = self.position + index + 1;
-                Some(self.position)
-            }
-            None => None,
-        }
+        iter_next!(
+            self,
+            memchr3(self.needle1, self.needle2, self.needle3, self.haystack)
+        )
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.haystack.len()))
     }
 }
 
 /// Like `memchr`, but searches for three bytes instead of one.
-pub fn memchr3(needle1: u8, needle2: u8, needle3: u8, haystack: &[u8]) -> Option<usize> {
+pub fn memchr3(
+    needle1: u8,
+    needle2: u8,
+    needle3: u8,
+    haystack: &[u8],
+) -> Option<usize> {
     fn slow(b1: u8, b2: u8, b3: u8, haystack: &[u8]) -> Option<usize> {
         haystack.iter().position(|&b| b == b1 || b == b2 || b == b3)
     }
 
     let len = haystack.len();
     let ptr = haystack.as_ptr();
     let align = (ptr as usize) & (USIZE_BYTES - 1);
     let mut i = 0;
@@ -387,35 +414,39 @@ pub fn memchr3(needle1: u8, needle2: u8, needle3: u8, haystack: &[u8]) -> Option
 #[cfg(any(test, not(feature = "libc"), all(not(target_os = "linux"),
           any(target_pointer_width = "32", target_pointer_width = "64"))))]
 mod fallback {
     #[cfg(feature = "use_std")]
     use std::cmp;
     #[cfg(not(feature = "use_std"))]
     use core::cmp;
 
-    use super::{LO_U64, HI_U64, LO_USIZE, HI_USIZE, USIZE_BYTES, contains_zero_byte, repeat_byte};
+    use super::{
+        LO_U64, HI_U64, LO_USIZE, HI_USIZE, USIZE_BYTES,
+        contains_zero_byte, repeat_byte,
+    };
 
-    /// Return the first index matching the byte `a` in `text`.
+    /// Return the first index matching the byte `x` in `text`.
     pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
         // Scan for a single byte value by reading two `usize` words at a time.
         //
         // Split `text` in three parts
-        // - unaligned inital part, before the first word aligned address in text
+        // - unaligned initial part, before first word aligned address in text
         // - body, scan by 2 words at a time
         // - the last remaining part, < 2 word size
         let len = text.len();
         let ptr = text.as_ptr();
 
         // search up to an aligned boundary
         let align = (ptr as usize) & (USIZE_BYTES - 1);
         let mut offset;
         if align > 0 {
             offset = cmp::min(USIZE_BYTES - align, len);
-            if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
+            let pos = text[..offset].iter().position(|elt| *elt == x);
+            if let Some(index) = pos {
                 return Some(index);
             }
         } else {
             offset = 0;
         }
 
         // search the body of the text
         let repeated_x = repeat_byte(x);
@@ -437,33 +468,34 @@ mod fallback {
                 offset += USIZE_BYTES * 2;
             }
         }
 
         // find the byte after the point the body loop stopped
         text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
     }
 
-    /// Return the last index matching the byte `a` in `text`.
+    /// Return the last index matching the byte `x` in `text`.
     pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
         // Scan for a single byte value by reading two `usize` words at a time.
         //
         // Split `text` in three parts
         // - unaligned tail, after the last word aligned address in text
         // - body, scan by 2 words at a time
         // - the first remaining bytes, < 2 word size
         let len = text.len();
         let ptr = text.as_ptr();
 
         // search to an aligned boundary
         let end_align = (ptr as usize + len) & (USIZE_BYTES - 1);
         let mut offset;
         if end_align > 0 {
             offset = if end_align >= len { 0 } else { len - end_align };
-            if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
+            let pos = text[offset..].iter().rposition(|elt| *elt == x);
+            if let Some(index) = pos {
                 return Some(offset + index);
             }
         } else {
             offset = len;
         }
 
         // search the body of the text
         let repeated_x = repeat_byte(x);
@@ -486,26 +518,26 @@ mod fallback {
 
         // find the byte before the point the body loop stopped
         text[..offset].iter().rposition(|elt| *elt == x)
     }
 }
 
 #[cfg(test)]
 mod tests {
-    extern crate quickcheck;
     use std::prelude::v1::*;
+    use quickcheck;
 
     use super::{memchr, memrchr, memchr2, memchr3, Memchr, Memchr2, Memchr3};
     // Use a macro to test both native and fallback impls on all configurations
     macro_rules! memchr_tests {
         ($mod_name:ident, $memchr:path, $memrchr:path) => {
             mod $mod_name {
             use std::prelude::v1::*;
-            use super::quickcheck;
+            use quickcheck;
             #[test]
             fn matches_one() {
                 assert_eq!(Some(0), $memchr(b'a', b"a"));
             }
 
             #[test]
             fn matches_begin() {
                 assert_eq!(Some(0), $memchr(b'a', b"aaaa"));
@@ -594,17 +626,18 @@ mod tests {
                     let uoffset = (offset & 0xF) as usize;
                     let data = if uoffset <= v.len() {
                         &v[uoffset..]
                     } else {
                         &v[..]
                     };
                     for byte in 0..256u32 {
                         let byte = byte as u8;
-                        if $memchr(byte, &data) != data.iter().position(|elt| *elt == byte) {
+                        let pos = data.iter().position(|elt| *elt == byte);
+                        if $memchr(byte, &data) != pos {
                             return false;
                         }
                     }
                     true
                 }
                 quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
             }
 
@@ -615,17 +648,18 @@ mod tests {
                     let uoffset = (offset & 0xF) as usize;
                     let data = if uoffset <= v.len() {
                         &v[uoffset..]
                     } else {
                         &v[..]
                     };
                     for byte in 0..256u32 {
                         let byte = byte as u8;
-                        if $memrchr(byte, &data) != data.iter().rposition(|elt| *elt == byte) {
+                        let pos = data.iter().rposition(|elt| *elt == byte);
+                        if $memrchr(byte, &data) != pos {
                             return false;
                         }
                     }
                     true
                 }
                 quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
             }
             }
@@ -729,88 +763,137 @@ mod tests {
         assert_eq!(None, memchr3(b'c', b'b', b'a', b""));
     }
 
     #[test]
     fn memchr3_no_match() {
         assert_eq!(None, memchr3(b'a', b'b', b'c', b"xyz"));
     }
 
+    // return an iterator of the 0-based indices of haystack that match the
+    // needle
+    fn positions1<'a>(needle: u8, haystack: &'a [u8])
+        -> Box<DoubleEndedIterator<Item=usize> + 'a>
+    {
+        Box::new(haystack.iter()
+                         .enumerate()
+                         .filter(move |&(_, &elt)| elt == needle)
+                         .map(|t| t.0))
+    }
+
+    fn positions2<'a>(needle1: u8, needle2: u8, haystack: &'a [u8])
+        -> Box<DoubleEndedIterator<Item=usize> + 'a>
+    {
+        Box::new(haystack
+            .iter()
+            .enumerate()
+            .filter(move |&(_, &elt)| elt == needle1 || elt == needle2)
+            .map(|t| t.0))
+    }
+
+    fn positions3<'a>(
+        needle1: u8,
+        needle2: u8,
+        needle3: u8,
+        haystack: &'a [u8],
+    ) -> Box<DoubleEndedIterator<Item=usize> + 'a> {
+        Box::new(haystack
+            .iter()
+            .enumerate()
+            .filter(move |&(_, &elt)| {
+                elt == needle1 || elt == needle2 || elt == needle3
+            })
+            .map(|t| t.0))
+    }
+
     #[test]
     fn memchr_iter() {
         let haystack = b"aaaabaaaab";
         let mut memchr_iter = Memchr::new(b'b', haystack);
         let first = memchr_iter.next();
         let second = memchr_iter.next();
         let third = memchr_iter.next();
-        assert_eq!(Some(5), first);
-        assert_eq!(Some(10), second);
-        assert_eq!(None, third);
+
+        let mut answer_iter = positions1(b'b', haystack);
+        assert_eq!(answer_iter.next(), first);
+        assert_eq!(answer_iter.next(), second);
+        assert_eq!(answer_iter.next(), third);
     }
 
     #[test]
     fn memchr2_iter() {
-        let haystack = b"ab";
+        let haystack = b"axxb";
         let mut memchr_iter = Memchr2::new(b'a', b'b', haystack);
         let first = memchr_iter.next();
         let second = memchr_iter.next();
         let third = memchr_iter.next();
-        assert_eq!(Some(1), first);
-        assert_eq!(Some(2), second);
-        assert_eq!(None, third);
+
+        let mut answer_iter = positions2(b'a', b'b', haystack);
+        assert_eq!(answer_iter.next(), first);
+        assert_eq!(answer_iter.next(), second);
+        assert_eq!(answer_iter.next(), third);
     }
 
     #[test]
     fn memchr3_iter() {
-        let haystack = b"abc";
+        let haystack = b"axxbc";
         let mut memchr_iter = Memchr3::new(b'a', b'b', b'c', haystack);
         let first = memchr_iter.next();
         let second = memchr_iter.next();
         let third = memchr_iter.next();
         let fourth = memchr_iter.next();
-        assert_eq!(Some(1), first);
-        assert_eq!(Some(2), second);
-        assert_eq!(Some(3), third);
-        assert_eq!(None, fourth);
+
+        let mut answer_iter = positions3(b'a', b'b', b'c', haystack);
+        assert_eq!(answer_iter.next(), first);
+        assert_eq!(answer_iter.next(), second);
+        assert_eq!(answer_iter.next(), third);
+        assert_eq!(answer_iter.next(), fourth);
     }
 
     #[test]
     fn memchr_reverse_iter() {
         let haystack = b"aaaabaaaabaaaab";
         let mut memchr_iter = Memchr::new(b'b', haystack);
         let first = memchr_iter.next();
         let second = memchr_iter.next_back();
         let third = memchr_iter.next();
         let fourth = memchr_iter.next_back();
 
-        assert_eq!(Some(5), first);
-        assert_eq!(Some(15), second);
-        assert_eq!(Some(10), third);
-        assert_eq!(None, fourth);
+        let mut answer_iter = positions1(b'b', haystack);
+        assert_eq!(answer_iter.next(), first);
+        assert_eq!(answer_iter.next_back(), second);
+        assert_eq!(answer_iter.next(), third);
+        assert_eq!(answer_iter.next_back(), fourth);
     }
 
     #[test]
     fn memrchr_iter(){
         let haystack = b"aaaabaaaabaaaab";
         let mut memchr_iter = Memchr::new(b'b', haystack);
         let first = memchr_iter.next_back();
         let second = memchr_iter.next_back();
         let third = memchr_iter.next_back();
         let fourth = memchr_iter.next_back();
 
-        assert_eq!(Some(15), first);
-        assert_eq!(Some(10), second);
-        assert_eq!(Some(5), third);
-        assert_eq!(None, fourth);
+        let mut answer_iter = positions1(b'b', haystack);
+        assert_eq!(answer_iter.next_back(), first);
+        assert_eq!(answer_iter.next_back(), second);
+        assert_eq!(answer_iter.next_back(), third);
+        assert_eq!(answer_iter.next_back(), fourth);
 
     }
 
     #[test]
     fn qc_never_fail_memchr3() {
-        fn prop(needle1: u8, needle2: u8, needle3: u8, haystack: Vec<u8>) -> bool {
+        fn prop(
+            needle1: u8,
+            needle2: u8,
+            needle3: u8,
+            haystack: Vec<u8>,
+        ) -> bool {
             memchr3(needle1, needle2, needle3, &haystack);
             true
         }
         quickcheck::quickcheck(prop as fn(u8, u8, u8, Vec<u8>) -> bool);
     }
 
     #[test]
     fn qc_correct_memchr() {
@@ -819,17 +902,18 @@ mod tests {
             let uoffset = (offset & 0xF) as usize;
             let data = if uoffset <= v.len() {
                 &v[uoffset..]
             } else {
                 &v[..]
             };
             for byte in 0..256u32 {
                 let byte = byte as u8;
-                if memchr(byte, &data) != data.iter().position(|elt| *elt == byte) {
+                let pos = data.iter().position(|elt| *elt == byte);
+                if memchr(byte, &data) != pos {
                     return false;
                 }
             }
             true
         }
         quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
     }
 
@@ -840,17 +924,18 @@ mod tests {
             let uoffset = (offset & 0xF) as usize;
             let data = if uoffset <= v.len() {
                 &v[uoffset..]
             } else {
                 &v[..]
             };
             for byte in 0..256u32 {
                 let byte = byte as u8;
-                if memrchr(byte, &data) != data.iter().rposition(|elt| *elt == byte) {
+                let pos = data.iter().rposition(|elt| *elt == byte);
+                if memrchr(byte, &data) != pos {
                     return false;
                 }
             }
             true
         }
         quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
     }
 
@@ -862,20 +947,116 @@ mod tests {
             let data = if uoffset <= v.len() {
                 &v[uoffset..]
             } else {
                 &v[..]
             };
             for b1 in 0..256u32 {
                 for b2 in 0..256u32 {
                     let (b1, b2) = (b1 as u8, b2 as u8);
-                    let expected = data.iter().position(|&b| b == b1 || b == b2);
+                    let expected = data
+                        .iter()
+                        .position(|&b| b == b1 || b == b2);
                     let got = memchr2(b1, b2, &data);
                     if expected != got {
                         return false;
                     }
                 }
             }
             true
         }
         quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
     }
+
+    // take items from a DEI, taking front for each true and back for each
+    // false. Return a vector with the concatenation of the fronts and the
+    // reverse of the backs.
+    fn double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item>
+        where I: DoubleEndedIterator,
+              J: Iterator<Item=bool>,
+    {
+        let mut found_front = Vec::new();
+        let mut found_back = Vec::new();
+
+        for take_front in take_side {
+            if take_front {
+                if let Some(pos) = iter.next() {
+                    found_front.push(pos);
+                } else {
+                    break;
+                }
+            } else {
+                if let Some(pos) = iter.next_back() {
+                    found_back.push(pos);
+                } else {
+                    break;
+                }
+            };
+        }
+
+        let mut all_found = found_front;
+        all_found.extend(found_back.into_iter().rev());
+        all_found
+    }
+
+
+    quickcheck! {
+        fn qc_memchr_double_ended_iter(needle: u8, data: Vec<u8>,
+                                       take_side: Vec<bool>) -> bool
+        {
+            // make nonempty
+            let mut take_side = take_side;
+            if take_side.is_empty() { take_side.push(true) };
+
+            let iter = Memchr::new(needle, &data);
+            let all_found = double_ended_take(
+                iter, take_side.iter().cycle().cloned());
+
+            all_found.iter().cloned().eq(positions1(needle, &data))
+        }
+
+        fn qc_memchr1_iter(data: Vec<u8>) -> bool {
+            let needle = 0;
+            let answer = positions1(needle, &data);
+            answer.eq(Memchr::new(needle, &data))
+        }
+
+        fn qc_memchr1_rev_iter(data: Vec<u8>) -> bool {
+            let needle = 0;
+            let answer = positions1(needle, &data);
+            answer.rev().eq(Memchr::new(needle, &data).rev())
+        }
+
+        fn qc_memchr2_iter(data: Vec<u8>) -> bool {
+            let needle1 = 0;
+            let needle2 = 1;
+            let answer = positions2(needle1, needle2, &data);
+            answer.eq(Memchr2::new(needle1, needle2, &data))
+        }
+
+        fn qc_memchr3_iter(data: Vec<u8>) -> bool {
+            let needle1 = 0;
+            let needle2 = 1;
+            let needle3 = 2;
+            let answer = positions3(needle1, needle2, needle3, &data);
+            answer.eq(Memchr3::new(needle1, needle2, needle3, &data))
+        }
+
+        fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> bool {
+            // test that the size hint is within reasonable bounds
+            let needle = 0;
+            let mut iter = Memchr::new(needle, &data);
+            let mut real_count = data
+                .iter()
+                .filter(|&&elt| elt == needle)
+                .count();
+
+            while let Some(index) = iter.next() {
+                real_count -= 1;
+                let (lower, upper) = iter.size_hint();
+                assert!(lower <= real_count);
+                assert!(upper.unwrap() >= real_count);
+                assert!(upper.unwrap() <= data.len() - index);
+            }
+            true
+        }
+    }
 }
diff --git a/third_party/rust/proc-macro2-0.2.2/.cargo-checksum.json b/third_party/rust/proc-macro2-0.2.2/.cargo-checksum.json
new file mode 100644
index 000000000000..6d5e5011ec54
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".travis.yml":"e455a0ed5c3dd056d31f4c7be088bc94f21cab6595a23f2f015b1efc0ac2b55c","Cargo.toml":"0b700f1e7b8ba76ce4678d36b6906d38455e88f51085ea9f120d6ca63f13d5d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"adf2e822923878c2ebf4a0a782898c598fc6f57a3af905b85d57fc716c836687","src/lib.rs":"fbae25504264b185d877fb8784d4d88333ea34a7cbeddca3277dc8421f179933","src/macros.rs":"414505e520b8d705b4ce5a64ec2e82d6d1af0b88567454169486a668fbc1e9c8","src/stable.rs":"6363c4c0ef989c2ec81aa75be71c69a103d45a1de439f3f3bcb6806d8a78a172","src/strnom.rs":"1baded8543a9930798fb16092fe51e9074591902e327e0f94eb1c908a6370de9","src/unstable.rs":"110d27103e37427b3d1dcb45b6ba9dc9f5641a255766a43d5db0f4fd10a341ed","tests/test.rs":"9e75d5289abc1dc58c1df00ae051d8c3cd2c0d7830cca5ad689007c05acffe26"},"package":"d1cb7aaaa4bf022ec2b14ff2f2ba1643a22f3cee88df014a85e14b392282c61d"}
\ No newline at end of file
diff --git a/third_party/rust/proc-macro2-0.2.2/.travis.yml b/third_party/rust/proc-macro2-0.2.2/.travis.yml
new file mode 100644
index 000000000000..a524c0167e1e
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/.travis.yml
@@ -0,0 +1,31 @@
+language: rust
+sudo: false
+
+matrix:
+  include:
+    - rust: 1.15.0
+    - rust: stable
+    - rust: beta
+    - rust: nightly
+      before_script:
+        - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
+      script:
+        - cargo test
+        - cargo build --features nightly
+        - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
+        - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build --features nightly
+        - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo doc --no-deps
+      after_success:
+        - travis-cargo --only nightly doc-upload
+
+script:
+  - cargo test
+  - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
+env:
+  global:
+    - TRAVIS_CARGO_NIGHTLY_FEATURE=""
+    - secure: "NAsZghAVTAksrm4WP4I66VmD2wW0eRbwB+ZKHUQfvbgUaCRvVdp4WBbWXGU/f/yHgDFWZwljWR4iPMiBwAK8nZsQFRuLFdHrOOHqbkj639LLdT9A07s1zLMB1GfR1fDttzrGhm903pbT2yxSyqqpahGYM7TaGDYYmKYIk4XyVNA5F5Sk7RI+rCecKraoYDeUEFbjWWYtU2FkEXsELEKj0emX5reWkR+wja3QokFcRZ25+Zd2dRC0K8W5QcY2UokLzKncBMCTC5q70H616S3r/9qW67Si1njsJ7RzP0NlZQUNQ/VCvwr4LCr9w+AD9i1SZtXxuux77tWEWSJvBzUc82dDMUv/floJuF7HTulSxxQoRm+fbzpXj9mgaJNiUHXru6ZRTCRVRUSXpcAco94bVoy/jnjrTe3jgAIZK5w14zA8yLw1Jxof31DlbcWORxgF+6fnY2nKPRN2oiQ50+jm1AuGDZX59/wMiu1QlkjOBHtikHp+u+7mp3SkkM04DvuQ/tWODQQnOOtrA0EB3i5H1zeTSnUcmbJufUljWWOvF1QYII08MccqwfG1KWbpobvdu+cV2iVhkq/lNCEL3Ai101CnmSCnMz+9oK/XxYOrx2TnaD9ootOKgnk7XWxF19GZecQx6O2hHTouxvB/0KcRPGWmMWl0H88f3T/Obql8bG8="
+
+notifications:
+  email:
+    on_success: never
diff --git a/third_party/rust/proc-macro2-0.2.2/Cargo.toml b/third_party/rust/proc-macro2-0.2.2/Cargo.toml
new file mode 100644
index 000000000000..17a47c189be7
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/Cargo.toml
@@ -0,0 +1,31 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "proc-macro2"
+version = "0.2.2"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
+homepage = "https://github.com/alexcrichton/proc-macro2"
+documentation = "https://docs.rs/proc-macro2"
+readme = "README.md"
+keywords = ["macros"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/alexcrichton/proc-macro2"
+
+[lib]
+doctest = false
+[dependencies.unicode-xid]
+version = "0.1"
+
+[features]
+nightly = []
diff --git a/third_party/rust/proc-macro2-0.2.2/LICENSE-APACHE b/third_party/rust/proc-macro2-0.2.2/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/proc-macro2-0.2.2/LICENSE-MIT b/third_party/rust/proc-macro2-0.2.2/LICENSE-MIT
new file mode 100644
index 000000000000..39e0ed660215
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 Alex Crichton
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/proc-macro2-0.2.2/README.md b/third_party/rust/proc-macro2-0.2.2/README.md
new file mode 100644
index 000000000000..c0a62a3a184b
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/README.md
@@ -0,0 +1,98 @@
+# proc-macro2
+
+[![Build Status](https://api.travis-ci.org/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.org/alexcrichton/proc-macro2)
+[![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
+
+A small shim over the `proc_macro` crate in the compiler intended to multiplex
+the current stable interface (as of 2017-07-05) and the [upcoming richer
+interface][upcoming].
+
+[upcoming]: https://github.com/rust-lang/rust/pull/40939
+
+The upcoming support has features like:
+
+* Span information on tokens
+* No need to go in/out through strings
+* Structured input/output
+
+The hope is that libraries ported to `proc_macro2` will be trivial to port to
+the real `proc_macro` crate once the support on nightly is stabilize.
+
+## Usage
+
+This crate by default compiles on the stable version of the compiler. It only
+uses the stable surface area of the `proc_macro` crate upstream in the compiler
+itself. Usage is done via:
+
+```toml
+[dependencies]
+proc-macro2 = "0.2"
+```
+
+followed by
+
+```rust
+extern crate proc_macro;
+extern crate proc_macro2;
+
+#[proc_macro_derive(MyDerive)]
+pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let input: proc_macro2::TokenStream = input.into();
+
+    let output: proc_macro2::TokenStream = {
+        /* transform input */
+    };
+
+    output.into()
+}
+```
+
+If you'd like you can enable the `nightly` feature in this crate. This will
+cause it to compile against the **unstable and nightly-only** features of the
+`proc_macro` crate. This in turn requires a nightly compiler. This should help
+preserve span information, however, coming in from the compiler itself.
+
+You can enable this feature via:
+
+```toml
+[dependencies]
+proc-macro2 = { version = "0.2", features = ["nightly"] }
+```
+
+
+## Unstable Features
+
+`proc-macro2` supports exporting some methods from `proc_macro` which are
+currently highly unstable, and may not be stabilized in the first pass of
+`proc_macro` stabilizations. These features are not exported by default. Minor
+versions of `proc-macro2` may make breaking changes to them at any time.
+
+To enable these features, the `procmacro2_semver_exempt` config flag must be
+passed to rustc.
+
+```
+RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
+```
+
+Note that this must not only be done for your crate, but for any crate that
+depends on your crate. This infectious nature is intentional, as it serves as a
+reminder that you are outside of the normal semver guarantees.
+
+
+# License
+
+This project is 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 Serde by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/third_party/rust/proc-macro2-0.2.2/src/lib.rs b/third_party/rust/proc-macro2-0.2.2/src/lib.rs
new file mode 100644
index 000000000000..373174c5f79d
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/src/lib.rs
@@ -0,0 +1,337 @@
+//! A "shim crate" intended to multiplex the `proc_macro` API on to stable Rust.
+//!
+//! Procedural macros in Rust operate over the upstream
+//! `proc_macro::TokenStream` type. This type currently is quite conservative
+//! and exposed no internal implementation details. Nightly compilers, however,
+//! contain a much richer interface. This richer interface allows fine-grained
+//! inspection of the token stream which avoids stringification/re-lexing and
+//! also preserves span information.
+//!
+//! The upcoming APIs added to `proc_macro` upstream are the foundation for
+//! productive procedural macros in the ecosystem. To help prepare the ecosystem
+//! for using them this crate serves to both compile on stable and nightly and
+//! mirrors the API-to-be. The intention is that procedural macros which switch
+//! to use this crate will be trivially able to switch to the upstream
+//! `proc_macro` crate once its API stabilizes.
+//!
+//! In the meantime this crate also has a `nightly` Cargo feature which
+//! enables it to reimplement itself with the unstable API of `proc_macro`.
+//! This'll allow immediate usage of the beneficial upstream API, particularly
+//! around preserving span information.
+
+// Proc-macro2 types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/proc-macro2/0.2.2")]
+
+#![cfg_attr(feature = "nightly", feature(proc_macro))]
+
+extern crate proc_macro;
+
+#[cfg(not(feature = "nightly"))]
+extern crate unicode_xid;
+
+use std::fmt;
+use std::str::FromStr;
+use std::iter::FromIterator;
+
+#[macro_use]
+#[cfg(not(feature = "nightly"))]
+mod strnom;
+
+#[path = "stable.rs"]
+#[cfg(not(feature = "nightly"))]
+mod imp;
+#[path = "unstable.rs"]
+#[cfg(feature = "nightly")]
+mod imp;
+
+#[macro_use]
+mod macros;
+
+#[derive(Clone)]
+pub struct TokenStream(imp::TokenStream);
+
+pub struct LexError(imp::LexError);
+
+impl FromStr for TokenStream {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<TokenStream, LexError> {
+        match src.parse() {
+            Ok(e) => Ok(TokenStream(e)),
+            Err(e) => Err(LexError(e)),
+        }
+    }
+}
+
+impl From<proc_macro::TokenStream> for TokenStream {
+    fn from(inner: proc_macro::TokenStream) -> TokenStream {
+        TokenStream(inner.into())
+    }
+}
+
+impl From<TokenStream> for proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> proc_macro::TokenStream {
+        inner.0.into()
+    }
+}
+
+impl From<TokenTree> for TokenStream {
+    fn from(tree: TokenTree) -> TokenStream {
+        TokenStream(tree.into())
+    }
+}
+
+impl<T: Into<TokenStream>> FromIterator<T> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
+        TokenStream(streams.into_iter().map(|t| t.into().0).collect())
+    }
+}
+
+impl IntoIterator for TokenStream {
+    type Item = TokenTree;
+    type IntoIter = TokenTreeIter;
+
+    fn into_iter(self) -> TokenTreeIter {
+        TokenTreeIter(self.0.into_iter())
+    }
+}
+
+impl TokenStream {
+    pub fn empty() -> TokenStream {
+        TokenStream(imp::TokenStream::empty())
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+// Returned by reference, so we can't easily wrap it.
+#[cfg(procmacro2_semver_exempt)]
+pub use imp::FileName;
+
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq)]
+pub struct SourceFile(imp::SourceFile);
+
+#[cfg(procmacro2_semver_exempt)]
+impl SourceFile {
+    /// Get the path to this source file as a string.
+    pub fn path(&self) -> &FileName {
+        self.0.path()
+    }
+
+    pub fn is_real(&self) -> bool {
+        self.0.is_real()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl AsRef<FileName> for SourceFile {
+    fn as_ref(&self) -> &FileName {
+        self.0.path()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Debug for SourceFile {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+pub struct LineColumn {
+    pub line: usize,
+    pub column: usize,
+}
+
+#[derive(Copy, Clone)]
+pub struct Span(imp::Span);
+
+impl Span {
+    pub fn call_site() -> Span {
+        Span(imp::Span::call_site())
+    }
+
+    pub fn def_site() -> Span {
+        Span(imp::Span::def_site())
+    }
+
+    /// Creates a new span with the same line/column information as `self` but
+    /// that resolves symbols as though it were at `other`.
+    pub fn resolved_at(&self, other: Span) -> Span {
+        Span(self.0.resolved_at(other.0))
+    }
+
+    /// Creates a new span with the same name resolution behavior as `self` but
+    /// with the line/column information of `other`.
+    pub fn located_at(&self, other: Span) -> Span {
+        Span(self.0.located_at(other.0))
+    }
+
+    /// This method is only available when the `"nightly"` feature is enabled.
+    #[cfg(feature = "nightly")]
+    pub fn unstable(self) -> proc_macro::Span {
+        self.0.unstable()
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn source_file(&self) -> SourceFile {
+        SourceFile(self.0.source_file())
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn start(&self) -> LineColumn {
+        let imp::LineColumn{ line, column } = self.0.start();
+        LineColumn { line: line, column: column }
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn end(&self) -> LineColumn {
+        let imp::LineColumn{ line, column } = self.0.end();
+        LineColumn { line: line, column: column }
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn join(&self, other: Span) -> Option<Span> {
+        self.0.join(other.0).map(Span)
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct TokenTree {
+    pub span: Span,
+    pub kind: TokenNode,
+}
+
+impl From<TokenNode> for TokenTree {
+    fn from(kind: TokenNode) -> TokenTree {
+        TokenTree { span: Span::def_site(), kind: kind }
+    }
+}
+
+impl fmt::Display for TokenTree {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        TokenStream::from(self.clone()).fmt(f)
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum TokenNode {
+    Group(Delimiter, TokenStream),
+    Term(Term),
+    Op(char, Spacing),
+    Literal(Literal),
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Delimiter {
+    Parenthesis,
+    Brace,
+    Bracket,
+    None,
+}
+
+#[derive(Copy, Clone)]
+pub struct Term(imp::Term);
+
+impl Term {
+    pub fn intern(string: &str) -> Term {
+        Term(imp::Term::intern(string))
+    }
+
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Spacing {
+    Alone,
+    Joint,
+}
+
+#[derive(Clone)]
+pub struct Literal(imp::Literal);
+
+macro_rules! int_literals {
+    ($($kind:ident,)*) => ($(
+        pub fn $kind(n: $kind) -> Literal {
+            Literal(n.into())
+        }
+    )*)
+}
+
+impl Literal {
+    pub fn integer(s: i64) -> Literal {
+        Literal(imp::Literal::integer(s))
+    }
+
+    int_literals! {
+        u8, u16, u32, u64, usize,
+        i8, i16, i32, i64, isize,
+    }
+
+    pub fn float(f: f64) -> Literal {
+        Literal(imp::Literal::float(f))
+    }
+
+    pub fn f64(f: f64) -> Literal {
+        Literal(f.into())
+    }
+
+    pub fn f32(f: f32) -> Literal {
+        Literal(f.into())
+    }
+
+    pub fn string(string: &str) -> Literal {
+        Literal(string.into())
+    }
+
+    pub fn character(ch: char) -> Literal {
+        Literal(ch.into())
+    }
+
+    pub fn byte_string(s: &[u8]) -> Literal {
+        Literal(imp::Literal::byte_string(s))
+    }
+
+    // =======================================================================
+    // Not present upstream in proc_macro yet
+
+    pub fn byte_char(b: u8) -> Literal {
+        Literal(imp::Literal::byte_char(b))
+    }
+
+    pub fn doccomment(s: &str) -> Literal {
+        Literal(imp::Literal::doccomment(s))
+    }
+
+    pub fn raw_string(s: &str, pounds: usize) -> Literal {
+        Literal(imp::Literal::raw_string(s, pounds))
+    }
+
+    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
+        Literal(imp::Literal::raw_byte_string(s, pounds))
+    }
+}
+
+pub struct TokenTreeIter(imp::TokenTreeIter);
+
+impl Iterator for TokenTreeIter {
+    type Item = TokenTree;
+
+    fn next(&mut self) -> Option<TokenTree> {
+        self.0.next()
+    }
+}
+
+forward_fmt!(Debug for LexError);
+forward_fmt!(Debug for Literal);
+forward_fmt!(Debug for Span);
+forward_fmt!(Debug for Term);
+forward_fmt!(Debug for TokenTreeIter);
+forward_fmt!(Debug for TokenStream);
+forward_fmt!(Display for Literal);
+forward_fmt!(Display for TokenStream);
diff --git a/third_party/rust/proc-macro2/src/macros.rs b/third_party/rust/proc-macro2-0.2.2/src/macros.rs
similarity index 100%
rename from third_party/rust/proc-macro2/src/macros.rs
rename to third_party/rust/proc-macro2-0.2.2/src/macros.rs
diff --git a/third_party/rust/proc-macro2-0.2.2/src/stable.rs b/third_party/rust/proc-macro2-0.2.2/src/stable.rs
new file mode 100644
index 000000000000..ffa077a29531
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/src/stable.rs
@@ -0,0 +1,1206 @@
+use std::ascii;
+use std::borrow::Borrow;
+use std::cell::RefCell;
+#[cfg(procmacro2_semver_exempt)]
+use std::cmp;
+use std::collections::HashMap;
+use std::fmt;
+use std::iter;
+use std::marker::PhantomData;
+use std::rc::Rc;
+use std::str::FromStr;
+use std::vec;
+
+use proc_macro;
+use unicode_xid::UnicodeXID;
+use strnom::{Cursor, PResult, skip_whitespace, block_comment, whitespace, word_break};
+
+use {TokenTree, TokenNode, Delimiter, Spacing};
+
+#[derive(Clone, Debug)]
+pub struct TokenStream {
+    inner: Vec<TokenTree>,
+}
+
+#[derive(Debug)]
+pub struct LexError;
+
+impl TokenStream {
+    pub fn empty() -> TokenStream {
+        TokenStream { inner: Vec::new() }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.inner.len() == 0
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+fn get_cursor(src: &str) -> Cursor {
+    // Create a dummy file & add it to the codemap
+    CODEMAP.with(|cm| {
+        let mut cm = cm.borrow_mut();
+        let name = format!("<parsed string {}>", cm.files.len());
+        let span = cm.add_file(&name, src);
+        Cursor {
+            rest: src,
+            off: span.lo,
+        }
+    })
+}
+
+#[cfg(not(procmacro2_semver_exempt))]
+fn get_cursor(src: &str) -> Cursor {
+    Cursor {
+        rest: src,
+    }
+}
+
+impl FromStr for TokenStream {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<TokenStream, LexError> {
+        // Create a dummy file & add it to the codemap
+        let cursor = get_cursor(src);
+
+        match token_stream(cursor) {
+            Ok((input, output)) => {
+                if skip_whitespace(input).len() != 0 {
+                    Err(LexError)
+                } else {
+                    Ok(output.0)
+                }
+            }
+            Err(LexError) => Err(LexError),
+        }
+    }
+}
+
+impl fmt::Display for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut joint = false;
+        for (i, tt) in self.inner.iter().enumerate() {
+            if i != 0 && !joint {
+                write!(f, " ")?;
+            }
+            joint = false;
+            match tt.kind {
+                TokenNode::Group(delim, ref stream) => {
+                    let (start, end) = match delim {
+                        Delimiter::Parenthesis => ("(", ")"),
+                        Delimiter::Brace => ("{", "}"),
+                        Delimiter::Bracket => ("[", "]"),
+                        Delimiter::None => ("", ""),
+                    };
+                    if stream.0.inner.len() == 0 {
+                        write!(f, "{} {}", start, end)?
+                    } else {
+                        write!(f, "{} {} {}", start, stream, end)?
+                    }
+                }
+                TokenNode::Term(ref sym) => write!(f, "{}", sym.as_str())?,
+                TokenNode::Op(ch, ref op) => {
+                    write!(f, "{}", ch)?;
+                    match *op {
+                        Spacing::Alone => {}
+                        Spacing::Joint => joint = true,
+                    }
+                }
+                TokenNode::Literal(ref literal) => {
+                    write!(f, "{}", literal)?;
+                    // handle comments
+                    if (literal.0).0.starts_with("/") {
+                        write!(f, "\n")?;
+                    }
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl From<proc_macro::TokenStream> for TokenStream {
+    fn from(inner: proc_macro::TokenStream) -> TokenStream {
+        inner.to_string().parse().expect("compiler token stream parse failed")
+    }
+}
+
+impl From<TokenStream> for proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> proc_macro::TokenStream {
+        inner.to_string().parse().expect("failed to parse to compiler tokens")
+    }
+}
+
+
+impl From<TokenTree> for TokenStream {
+    fn from(tree: TokenTree) -> TokenStream {
+        TokenStream { inner: vec![tree] }
+    }
+}
+
+impl iter::FromIterator<TokenStream> for TokenStream {
+    fn from_iter<I: IntoIterator<Item=TokenStream>>(streams: I) -> Self {
+        let mut v = Vec::new();
+
+        for stream in streams.into_iter() {
+            v.extend(stream.inner);
+        }
+
+        TokenStream { inner: v }
+    }
+}
+
+pub type TokenTreeIter = vec::IntoIter<TokenTree>;
+
+impl IntoIterator for TokenStream {
+    type Item = TokenTree;
+    type IntoIter = TokenTreeIter;
+
+    fn into_iter(self) -> TokenTreeIter {
+        self.inner.into_iter()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FileName(String);
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Display for FileName {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq)]
+pub struct SourceFile {
+    name: FileName,
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl SourceFile {
+    /// Get the path to this source file as a string.
+    pub fn path(&self) -> &FileName {
+        &self.name
+    }
+
+    pub fn is_real(&self) -> bool {
+        // XXX(nika): Support real files in the future?
+        false
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl AsRef<FileName> for SourceFile {
+    fn as_ref(&self) -> &FileName {
+        self.path()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Debug for SourceFile {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SourceFile")
+            .field("path", &self.path())
+            .field("is_real", &self.is_real())
+            .finish()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct LineColumn {
+    pub line: usize,
+    pub column: usize,
+}
+
+#[cfg(procmacro2_semver_exempt)]
+thread_local! {
+    static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
+        // NOTE: We start with a single dummy file which all call_site() and
+        // def_site() spans reference.
+        files: vec![FileInfo {
+            name: "<unspecified>".to_owned(),
+            span: Span { lo: 0, hi: 0 },
+            lines: vec![0],
+        }],
+    });
+}
+
+#[cfg(procmacro2_semver_exempt)]
+struct FileInfo {
+    name: String,
+    span: Span,
+    lines: Vec<usize>,
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl FileInfo {
+    fn offset_line_column(&self, offset: usize) -> LineColumn {
+        assert!(self.span_within(Span { lo: offset as u32, hi: offset as u32 }));
+        let offset = offset - self.span.lo as usize;
+        match self.lines.binary_search(&offset) {
+            Ok(found) => LineColumn {
+                line: found + 1,
+                column: 0
+            },
+            Err(idx) => LineColumn {
+                line: idx,
+                column: offset - self.lines[idx - 1]
+            },
+        }
+    }
+
+    fn span_within(&self, span: Span) -> bool {
+        span.lo >= self.span.lo && span.hi <= self.span.hi
+    }
+}
+
+/// Computes the offsets of each line in the given source string.
+#[cfg(procmacro2_semver_exempt)]
+fn lines_offsets(s: &str) -> Vec<usize> {
+    let mut lines = vec![0];
+    let mut prev = 0;
+    while let Some(len) = s[prev..].find('\n') {
+        prev += len + 1;
+        lines.push(prev);
+    }
+    lines
+}
+
+#[cfg(procmacro2_semver_exempt)]
+struct Codemap {
+    files: Vec<FileInfo>,
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl Codemap {
+    fn next_start_pos(&self) -> u32 {
+        // Add 1 so there's always space between files.
+        //
+        // We'll always have at least 1 file, as we initialize our files list
+        // with a dummy file.
+        self.files.last().unwrap().span.hi + 1
+    }
+
+    fn add_file(&mut self, name: &str, src: &str) -> Span {
+        let lines = lines_offsets(src);
+        let lo = self.next_start_pos();
+        // XXX(nika): Shouild we bother doing a checked cast or checked add here?
+        let span = Span { lo: lo, hi: lo + (src.len() as u32) };
+
+        self.files.push(FileInfo {
+            name: name.to_owned(),
+            span: span,
+            lines: lines,
+        });
+
+        span
+    }
+
+    fn fileinfo(&self, span: Span) -> &FileInfo {
+        for file in &self.files {
+            if file.span_within(span) {
+                return file;
+            }
+        }
+        panic!("Invalid span with no related FileInfo!");
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct Span {
+    #[cfg(procmacro2_semver_exempt)]
+    lo: u32,
+    #[cfg(procmacro2_semver_exempt)]
+    hi: u32,
+}
+
+impl Span {
+    #[cfg(not(procmacro2_semver_exempt))]
+    pub fn call_site() -> Span {
+        Span {}
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn call_site() -> Span {
+        Span { lo: 0, hi: 0 }
+    }
+
+    pub fn def_site() -> Span {
+        Span::call_site()
+    }
+
+    pub fn resolved_at(&self, _other: Span) -> Span {
+        // Stable spans consist only of line/column information, so
+        // `resolved_at` and `located_at` only select which span the
+        // caller wants line/column information from.
+        *self
+    }
+
+    pub fn located_at(&self, other: Span) -> Span {
+        other
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn source_file(&self) -> SourceFile {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            SourceFile {
+                name: FileName(fi.name.clone()),
+            }
+        })
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn start(&self) -> LineColumn {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            fi.offset_line_column(self.lo as usize)
+        })
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn end(&self) -> LineColumn {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            fi.offset_line_column(self.hi as usize)
+        })
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn join(&self, other: Span) -> Option<Span> {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            // If `other` is not within the same FileInfo as us, return None.
+            if !cm.fileinfo(*self).span_within(other) {
+                return None;
+            }
+            Some(Span {
+                lo: cmp::min(self.lo, other.lo),
+                hi: cmp::max(self.hi, other.hi),
+            })
+        })
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct Term {
+    intern: usize,
+    not_send_sync: PhantomData<*const ()>,
+}
+
+thread_local!(static SYMBOLS: RefCell<Interner> = RefCell::new(Interner::new()));
+
+impl Term {
+    pub fn intern(string: &str) -> Term {
+        Term {
+            intern: SYMBOLS.with(|s| s.borrow_mut().intern(string)),
+            not_send_sync: PhantomData,
+        }
+    }
+
+    pub fn as_str(&self) -> &str {
+        SYMBOLS.with(|interner| {
+            let interner = interner.borrow();
+            let s = interner.get(self.intern);
+            unsafe {
+                &*(s as *const str)
+            }
+        })
+    }
+}
+
+impl fmt::Debug for Term {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Term").field(&self.as_str()).finish()
+    }
+}
+
+struct Interner {
+    string_to_index: HashMap<MyRc, usize>,
+    index_to_string: Vec<Rc<String>>,
+}
+
+#[derive(Hash, Eq, PartialEq)]
+struct MyRc(Rc<String>);
+
+impl Borrow<str> for MyRc {
+    fn borrow(&self) -> &str {
+        &self.0
+    }
+}
+
+impl Interner {
+    fn new() -> Interner {
+        Interner {
+            string_to_index: HashMap::new(),
+            index_to_string: Vec::new(),
+        }
+    }
+
+   fn intern(&mut self, s: &str) -> usize {
+        if let Some(&idx) = self.string_to_index.get(s) {
+            return idx
+        }
+        let s = Rc::new(s.to_string());
+        self.index_to_string.push(s.clone());
+        self.string_to_index.insert(MyRc(s), self.index_to_string.len() - 1);
+        self.index_to_string.len() - 1
+    }
+
+   fn get(&self, idx: usize) -> &str {
+       &self.index_to_string[idx]
+   }
+}
+
+#[derive(Clone, Debug)]
+pub struct Literal(String);
+
+impl Literal {
+    pub fn byte_char(byte: u8) -> Literal {
+        match byte {
+            0 => Literal(format!("b'\\0'")),
+            b'\"' => Literal(format!("b'\"'")),
+            n => {
+                let mut escaped = "b'".to_string();
+                escaped.extend(ascii::escape_default(n).map(|c| c as char));
+                escaped.push('\'');
+                Literal(escaped)
+            }
+        }
+    }
+
+    pub fn byte_string(bytes: &[u8]) -> Literal {
+        let mut escaped = "b\"".to_string();
+        for b in bytes {
+            match *b {
+                b'\0' => escaped.push_str(r"\0"),
+                b'\t' => escaped.push_str(r"\t"),
+                b'\n' => escaped.push_str(r"\n"),
+                b'\r' => escaped.push_str(r"\r"),
+                b'"' => escaped.push_str("\\\""),
+                b'\\' => escaped.push_str("\\\\"),
+                b'\x20' ... b'\x7E' => escaped.push(*b as char),
+                _ => escaped.push_str(&format!("\\x{:02X}", b)),
+            }
+        }
+        escaped.push('"');
+        Literal(escaped)
+    }
+
+    pub fn doccomment(s: &str) -> Literal {
+        Literal(s.to_string())
+    }
+
+    pub fn float(n: f64) -> Literal {
+        if !n.is_finite() {
+            panic!("Invalid float literal {}", n);
+        }
+        let mut s = n.to_string();
+        if !s.contains('.') {
+            s += ".0";
+        }
+        Literal(s)
+    }
+
+    pub fn integer(s: i64) -> Literal {
+        Literal(s.to_string())
+    }
+
+    pub fn raw_string(s: &str, pounds: usize) -> Literal {
+        let mut ret = format!("r");
+        ret.extend((0..pounds).map(|_| "#"));
+        ret.push('"');
+        ret.push_str(s);
+        ret.push('"');
+        ret.extend((0..pounds).map(|_| "#"));
+        Literal(ret)
+    }
+
+    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
+        let mut ret = format!("br");
+        ret.extend((0..pounds).map(|_| "#"));
+        ret.push('"');
+        ret.push_str(s);
+        ret.push('"');
+        ret.extend((0..pounds).map(|_| "#"));
+        Literal(ret)
+    }
+}
+
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+macro_rules! ints {
+    ($($t:ty,)*) => {$(
+        impl From<$t> for Literal {
+            fn from(t: $t) -> Literal {
+                Literal(format!(concat!("{}", stringify!($t)), t))
+            }
+        }
+    )*}
+}
+
+ints! {
+    u8, u16, u32, u64, usize,
+    i8, i16, i32, i64, isize,
+}
+
+macro_rules! floats {
+    ($($t:ty,)*) => {$(
+        impl From<$t> for Literal {
+            fn from(t: $t) -> Literal {
+                assert!(!t.is_nan());
+                assert!(!t.is_infinite());
+                Literal(format!(concat!("{}", stringify!($t)), t))
+            }
+        }
+    )*}
+}
+
+floats! {
+    f32, f64,
+}
+
+impl<'a> From<&'a str> for Literal {
+    fn from(t: &'a str) -> Literal {
+        let mut s = t.chars().flat_map(|c| c.escape_default()).collect::<String>();
+        s.push('"');
+        s.insert(0, '"');
+        Literal(s)
+    }
+}
+
+impl From<char> for Literal {
+    fn from(t: char) -> Literal {
+        Literal(format!("'{}'", t.escape_default().collect::<String>()))
+    }
+}
+
+named!(token_stream -> ::TokenStream, map!(
+    many0!(token_tree),
+    |trees| ::TokenStream(TokenStream { inner: trees })
+));
+
+#[cfg(not(procmacro2_semver_exempt))]
+fn token_tree(input: Cursor) -> PResult<TokenTree> {
+    let (input, kind) = token_kind(input)?;
+    Ok((input, TokenTree {
+        span: ::Span(Span {}),
+        kind: kind,
+    }))
+}
+
+#[cfg(procmacro2_semver_exempt)]
+fn token_tree(input: Cursor) -> PResult<TokenTree> {
+    let input = skip_whitespace(input);
+    let lo = input.off;
+    let (input, kind) = token_kind(input)?;
+    let hi = input.off;
+    Ok((input, TokenTree {
+        span: ::Span(Span {
+            lo: lo,
+            hi: hi,
+        }),
+        kind: kind,
+    }))
+}
+
+named!(token_kind -> TokenNode, alt!(
+    map!(delimited, |(d, s)| TokenNode::Group(d, s))
+    |
+    map!(literal, TokenNode::Literal) // must be before symbol
+    |
+    symbol
+    |
+    map!(op, |(op, kind)| TokenNode::Op(op, kind))
+));
+
+named!(delimited -> (Delimiter, ::TokenStream), alt!(
+    delimited!(
+        punct!("("),
+        token_stream,
+        punct!(")")
+    ) => { |ts| (Delimiter::Parenthesis, ts) }
+    |
+    delimited!(
+        punct!("["),
+        token_stream,
+        punct!("]")
+    ) => { |ts| (Delimiter::Bracket, ts) }
+    |
+    delimited!(
+        punct!("{"),
+        token_stream,
+        punct!("}")
+    ) => { |ts| (Delimiter::Brace, ts) }
+));
+
+fn symbol(mut input: Cursor) -> PResult<TokenNode> {
+    input = skip_whitespace(input);
+
+    let mut chars = input.char_indices();
+
+    let lifetime = input.starts_with("'");
+    if lifetime {
+        chars.next();
+    }
+
+    match chars.next() {
+        Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
+        _ => return Err(LexError),
+    }
+
+    let mut end = input.len();
+    for (i, ch) in chars {
+        if !UnicodeXID::is_xid_continue(ch) {
+            end = i;
+            break;
+        }
+    }
+
+    if lifetime && &input.rest[..end] != "'static" && KEYWORDS.contains(&&input.rest[1..end]) {
+        Err(LexError)
+    } else {
+        let a = &input.rest[..end];
+        if a == "_" {
+            Ok((input.advance(end), TokenNode::Op('_', Spacing::Alone)))
+        } else {
+            Ok((input.advance(end), TokenNode::Term(::Term::intern(a))))
+        }
+    }
+}
+
+// From https://github.com/rust-lang/rust/blob/master/src/libsyntax_pos/symbol.rs
+static KEYWORDS: &'static [&'static str] = &[
+    "abstract", "alignof", "as", "become", "box", "break", "const", "continue",
+    "crate", "do", "else", "enum", "extern", "false", "final", "fn", "for",
+    "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut",
+    "offsetof", "override", "priv", "proc", "pub", "pure", "ref", "return",
+    "self", "Self", "sizeof", "static", "struct", "super", "trait", "true",
+    "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while",
+    "yield",
+];
+
+fn literal(input: Cursor) -> PResult<::Literal> {
+    let input_no_ws = skip_whitespace(input);
+
+    match literal_nocapture(input_no_ws) {
+        Ok((a, ())) => {
+            let start = input.len() - input_no_ws.len();
+            let len = input_no_ws.len() - a.len();
+            let end = start + len;
+            Ok((a, ::Literal(Literal(input.rest[start..end].to_string()))))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+named!(literal_nocapture -> (), alt!(
+    string
+    |
+    byte_string
+    |
+    byte
+    |
+    character
+    |
+    float
+    |
+    int
+    |
+    doc_comment
+));
+
+named!(string -> (), alt!(
+    quoted_string
+    |
+    preceded!(
+        punct!("r"),
+        raw_string
+    ) => { |_| () }
+));
+
+named!(quoted_string -> (), delimited!(
+    punct!("\""),
+    cooked_string,
+    tag!("\"")
+));
+
+fn cooked_string(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices().peekable();
+    while let Some((byte_offset, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                return Ok((input.advance(byte_offset), ()));
+            }
+            '\r' => {
+                if let Some((_, '\n')) = chars.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            '\\' => {
+                match chars.next() {
+                    Some((_, 'x')) => {
+                        if !backslash_x_char(&mut chars) {
+                            break
+                        }
+                    }
+                    Some((_, 'n')) |
+                    Some((_, 'r')) |
+                    Some((_, 't')) |
+                    Some((_, '\\')) |
+                    Some((_, '\'')) |
+                    Some((_, '"')) |
+                    Some((_, '0')) => {}
+                    Some((_, 'u')) => {
+                        if !backslash_u(&mut chars) {
+                            break
+                        }
+                    }
+                    Some((_, '\n')) | Some((_, '\r')) => {
+                        while let Some(&(_, ch)) = chars.peek() {
+                            if ch.is_whitespace() {
+                                chars.next();
+                            } else {
+                                break;
+                            }
+                        }
+                    }
+                    _ => break,
+                }
+            }
+            _ch => {}
+        }
+    }
+    Err(LexError)
+}
+
+named!(byte_string -> (), alt!(
+    delimited!(
+        punct!("b\""),
+        cooked_byte_string,
+        tag!("\"")
+    ) => { |_| () }
+    |
+    preceded!(
+        punct!("br"),
+        raw_string
+    ) => { |_| () }
+));
+
+fn cooked_byte_string(mut input: Cursor) -> PResult<()> {
+    let mut bytes = input.bytes().enumerate();
+    'outer: while let Some((offset, b)) = bytes.next() {
+        match b {
+            b'"' => {
+                return Ok((input.advance(offset), ()));
+            }
+            b'\r' => {
+                if let Some((_, b'\n')) = bytes.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            b'\\' => {
+                match bytes.next() {
+                    Some((_, b'x')) => {
+                        if !backslash_x_byte(&mut bytes) {
+                            break
+                        }
+                    }
+                    Some((_, b'n')) |
+                    Some((_, b'r')) |
+                    Some((_, b't')) |
+                    Some((_, b'\\')) |
+                    Some((_, b'0')) |
+                    Some((_, b'\'')) |
+                    Some((_, b'"'))  => {}
+                    Some((newline, b'\n')) |
+                    Some((newline, b'\r')) => {
+                        let rest = input.advance(newline + 1);
+                        for (offset, ch) in rest.char_indices() {
+                            if !ch.is_whitespace() {
+                                input = rest.advance(offset);
+                                bytes = input.bytes().enumerate();
+                                continue 'outer;
+                            }
+                        }
+                        break;
+                    }
+                    _ => break,
+                }
+            }
+            b if b < 0x80 => {}
+            _ => break,
+        }
+    }
+    Err(LexError)
+}
+
+fn raw_string(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices();
+    let mut n = 0;
+    while let Some((byte_offset, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                n = byte_offset;
+                break;
+            }
+            '#' => {}
+            _ => return Err(LexError),
+        }
+    }
+    for (byte_offset, ch) in chars {
+        match ch {
+            '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => {
+                let rest = input.advance(byte_offset + 1 + n);
+                return Ok((rest, ()))
+            }
+            '\r' => {}
+            _ => {}
+        }
+    }
+    Err(LexError)
+}
+
+named!(byte -> (), do_parse!(
+    punct!("b") >>
+    tag!("'") >>
+    cooked_byte >>
+    tag!("'") >>
+    (())
+));
+
+fn cooked_byte(input: Cursor) -> PResult<()> {
+    let mut bytes = input.bytes().enumerate();
+    let ok = match bytes.next().map(|(_, b)| b) {
+        Some(b'\\') => {
+            match bytes.next().map(|(_, b)| b) {
+                Some(b'x') => backslash_x_byte(&mut bytes),
+                Some(b'n') |
+                Some(b'r') |
+                Some(b't') |
+                Some(b'\\') |
+                Some(b'0') |
+                Some(b'\'') |
+                Some(b'"') => true,
+                _ => false,
+            }
+        }
+        b => b.is_some(),
+    };
+    if ok {
+        match bytes.next() {
+            Some((offset, _)) => {
+                if input.chars().as_str().is_char_boundary(offset) {
+                    Ok((input.advance(offset), ()))
+                } else {
+                    Err(LexError)
+                }
+            }
+            None => Ok((input.advance(input.len()), ())),
+        }
+    } else {
+        Err(LexError)
+    }
+}
+
+named!(character -> (), do_parse!(
+    punct!("'") >>
+    cooked_char >>
+    tag!("'") >>
+    (())
+));
+
+fn cooked_char(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices();
+    let ok = match chars.next().map(|(_, ch)| ch) {
+        Some('\\') => {
+            match chars.next().map(|(_, ch)| ch) {
+                Some('x') => backslash_x_char(&mut chars),
+                Some('u') => backslash_u(&mut chars),
+                Some('n') |
+                Some('r') |
+                Some('t') |
+                Some('\\') |
+                Some('0') |
+                Some('\'') |
+                Some('"') => true,
+                _ => false,
+            }
+        }
+        ch => ch.is_some(),
+    };
+    if ok {
+        match chars.next() {
+            Some((idx, _)) => Ok((input.advance(idx), ())),
+            None => Ok((input.advance(input.len()), ())),
+        }
+    } else {
+        Err(LexError)
+    }
+}
+
+macro_rules! next_ch {
+    ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
+        match $chars.next() {
+            Some((_, ch)) => match ch {
+                $pat $(| $rest)*  => ch,
+                _ => return false,
+            },
+            None => return false
+        }
+    };
+}
+
+fn backslash_x_char<I>(chars: &mut I) -> bool
+    where I: Iterator<Item = (usize, char)>
+{
+    next_ch!(chars @ '0'...'7');
+    next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    true
+}
+
+fn backslash_x_byte<I>(chars: &mut I) -> bool
+    where I: Iterator<Item = (usize, u8)>
+{
+    next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    true
+}
+
+fn backslash_u<I>(chars: &mut I) -> bool
+    where I: Iterator<Item = (usize, char)>
+{
+    next_ch!(chars @ '{');
+    next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    loop {
+        let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '_' | '}');
+        if c == '}' {
+            return true;
+        }
+    }
+}
+
+fn float(input: Cursor) -> PResult<()> {
+    let (rest, ()) = float_digits(input)?;
+    for suffix in &["f32", "f64"] {
+        if rest.starts_with(suffix) {
+            return word_break(rest.advance(suffix.len()));
+        }
+    }
+    word_break(rest)
+}
+
+fn float_digits(input: Cursor) -> PResult<()> {
+    let mut chars = input.chars().peekable();
+    match chars.next() {
+        Some(ch) if ch >= '0' && ch <= '9' => {}
+        _ => return Err(LexError),
+    }
+
+    let mut len = 1;
+    let mut has_dot = false;
+    let mut has_exp = false;
+    while let Some(&ch) = chars.peek() {
+        match ch {
+            '0'...'9' | '_' => {
+                chars.next();
+                len += 1;
+            }
+            '.' => {
+                if has_dot {
+                    break;
+                }
+                chars.next();
+                if chars.peek()
+                       .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
+                       .unwrap_or(false) {
+                    return Err(LexError);
+                }
+                len += 1;
+                has_dot = true;
+            }
+            'e' | 'E' => {
+                chars.next();
+                len += 1;
+                has_exp = true;
+                break;
+            }
+            _ => break,
+        }
+    }
+
+    let rest = input.advance(len);
+    if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
+        return Err(LexError);
+    }
+
+    if has_exp {
+        let mut has_exp_value = false;
+        while let Some(&ch) = chars.peek() {
+            match ch {
+                '+' | '-' => {
+                    if has_exp_value {
+                        break;
+                    }
+                    chars.next();
+                    len += 1;
+                }
+                '0'...'9' => {
+                    chars.next();
+                    len += 1;
+                    has_exp_value = true;
+                }
+                '_' => {
+                    chars.next();
+                    len += 1;
+                }
+                _ => break,
+            }
+        }
+        if !has_exp_value {
+            return Err(LexError);
+        }
+    }
+
+    Ok((input.advance(len), ()))
+}
+
+fn int(input: Cursor) -> PResult<()> {
+    let (rest, ()) = digits(input)?;
+    for suffix in &[
+        "isize",
+        "i8",
+        "i16",
+        "i32",
+        "i64",
+        "i128",
+        "usize",
+        "u8",
+        "u16",
+        "u32",
+        "u64",
+        "u128",
+    ] {
+        if rest.starts_with(suffix) {
+            return word_break(rest.advance(suffix.len()));
+        }
+    }
+    word_break(rest)
+}
+
+fn digits(mut input: Cursor) -> PResult<()> {
+    let base = if input.starts_with("0x") {
+        input = input.advance(2);
+        16
+    } else if input.starts_with("0o") {
+        input = input.advance(2);
+        8
+    } else if input.starts_with("0b") {
+        input = input.advance(2);
+        2
+    } else {
+        10
+    };
+
+    let mut len = 0;
+    let mut empty = true;
+    for b in input.bytes() {
+        let digit = match b {
+            b'0'...b'9' => (b - b'0') as u64,
+            b'a'...b'f' => 10 + (b - b'a') as u64,
+            b'A'...b'F' => 10 + (b - b'A') as u64,
+            b'_' => {
+                if empty && base == 10 {
+                    return Err(LexError);
+                }
+                len += 1;
+                continue;
+            }
+            _ => break,
+        };
+        if digit >= base {
+            return Err(LexError);
+        }
+        len += 1;
+        empty = false;
+    }
+    if empty {
+        Err(LexError)
+    } else {
+        Ok((input.advance(len), ()))
+    }
+}
+
+fn op(input: Cursor) -> PResult<(char, Spacing)> {
+    let input = skip_whitespace(input);
+    match op_char(input) {
+        Ok((rest, ch)) => {
+            let kind = match op_char(rest) {
+                Ok(_) => Spacing::Joint,
+                Err(LexError) => Spacing::Alone,
+            };
+            Ok((rest, (ch, kind)))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+fn op_char(input: Cursor) -> PResult<char> {
+    let mut chars = input.chars();
+    let first = match chars.next() {
+        Some(ch) => ch,
+        None => {
+            return Err(LexError);
+        }
+    };
+    let recognized = "~!@#$%^&*-=+|;:,<.>/?";
+    if recognized.contains(first) {
+        Ok((input.advance(first.len_utf8()), first))
+    } else {
+        Err(LexError)
+    }
+}
+
+named!(doc_comment -> (), alt!(
+    do_parse!(
+        punct!("//!") >>
+        take_until!("\n") >>
+        (())
+    )
+    |
+    do_parse!(
+        option!(whitespace) >>
+        peek!(tag!("/*!")) >>
+        block_comment >>
+        (())
+    )
+    |
+    do_parse!(
+        punct!("///") >>
+        not!(tag!("/")) >>
+        take_until!("\n") >>
+        (())
+    )
+    |
+    do_parse!(
+        option!(whitespace) >>
+        peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
+        block_comment >>
+        (())
+    )
+));
diff --git a/third_party/rust/proc-macro2-0.2.2/src/strnom.rs b/third_party/rust/proc-macro2-0.2.2/src/strnom.rs
new file mode 100644
index 000000000000..33964f45bda3
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/src/strnom.rs
@@ -0,0 +1,447 @@
+//! Adapted from [`nom`](https://github.com/Geal/nom).
+
+use std::str::{Chars, CharIndices, Bytes};
+
+use unicode_xid::UnicodeXID;
+
+use imp::LexError;
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub struct Cursor<'a> {
+    pub rest: &'a str,
+    #[cfg(procmacro2_semver_exempt)]
+    pub off: u32,
+}
+
+impl<'a> Cursor<'a> {
+    #[cfg(not(procmacro2_semver_exempt))]
+    pub fn advance(&self, amt: usize) -> Cursor<'a> {
+        Cursor {
+            rest: &self.rest[amt..],
+        }
+    }
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn advance(&self, amt: usize) -> Cursor<'a> {
+        Cursor {
+            rest: &self.rest[amt..],
+            off: self.off + (amt as u32),
+        }
+    }
+
+    pub fn find(&self, p: char) -> Option<usize> {
+        self.rest.find(p)
+    }
+
+    pub fn starts_with(&self, s: &str) -> bool {
+        self.rest.starts_with(s)
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.rest.is_empty()
+    }
+
+    pub fn len(&self) -> usize {
+        self.rest.len()
+    }
+
+    pub fn as_bytes(&self) -> &'a [u8] {
+        self.rest.as_bytes()
+    }
+
+    pub fn bytes(&self) -> Bytes<'a> {
+        self.rest.bytes()
+    }
+
+    pub fn chars(&self) -> Chars<'a> {
+        self.rest.chars()
+    }
+
+    pub fn char_indices(&self) -> CharIndices<'a> {
+        self.rest.char_indices()
+    }
+}
+
+pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>;
+
+pub fn whitespace(input: Cursor) -> PResult<()> {
+    if input.is_empty() {
+        return Err(LexError);
+    }
+
+    let bytes = input.as_bytes();
+    let mut i = 0;
+    while i < bytes.len() {
+        let s = input.advance(i);
+        if bytes[i] == b'/' {
+            if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) &&
+               !s.starts_with("//!") {
+                if let Some(len) = s.find('\n') {
+                    i += len + 1;
+                    continue;
+                }
+                break;
+            } else if s.starts_with("/**/") {
+                i += 4;
+                continue
+            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) &&
+                      !s.starts_with("/*!") {
+                let (_, com) = block_comment(s)?;
+                i += com.len();
+                continue;
+            }
+        }
+        match bytes[i] {
+            b' ' | 0x09...0x0d => {
+                i += 1;
+                continue;
+            }
+            b if b <= 0x7f => {}
+            _ => {
+                let ch = s.chars().next().unwrap();
+                if is_whitespace(ch) {
+                    i += ch.len_utf8();
+                    continue;
+                }
+            }
+        }
+        return if i > 0 {
+            Ok((s, ()))
+        } else {
+            Err(LexError)
+        };
+    }
+    Ok((input.advance(input.len()), ()))
+}
+
+pub fn block_comment(input: Cursor) -> PResult<&str> {
+    if !input.starts_with("/*") {
+        return Err(LexError);
+    }
+
+    let mut depth = 0;
+    let bytes = input.as_bytes();
+    let mut i = 0;
+    let upper = bytes.len() - 1;
+    while i < upper {
+        if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+            depth += 1;
+            i += 1; // eat '*'
+        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+            depth -= 1;
+            if depth == 0 {
+                return Ok((input.advance(i + 2), &input.rest[..i + 2]));
+            }
+            i += 1; // eat '/'
+        }
+        i += 1;
+    }
+    Err(LexError)
+}
+
+pub fn skip_whitespace(input: Cursor) -> Cursor {
+    match whitespace(input) {
+        Ok((rest, _)) => rest,
+        Err(LexError) => input,
+    }
+}
+
+fn is_whitespace(ch: char) -> bool {
+    // Rust treats left-to-right mark and right-to-left mark as whitespace
+    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
+
+pub fn word_break(input: Cursor) -> PResult<()> {
+    match input.chars().next() {
+        Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError),
+        Some(_) | None => Ok((input, ())),
+    }
+}
+
+macro_rules! named {
+    ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
+        fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> {
+            $submac!(i, $($args)*)
+        }
+    };
+}
+
+macro_rules! alt {
+    ($i:expr, $e:ident | $($rest:tt)*) => {
+        alt!($i, call!($e) | $($rest)*)
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
+        match $subrule!($i, $($args)*) {
+            res @ Ok(_) => res,
+            _ => alt!($i, $($rest)*)
+        }
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
+        match $subrule!($i, $($args)*) {
+            Ok((i, o)) => Ok((i, $gen(o))),
+            Err(LexError) => alt!($i, $($rest)*)
+        }
+    };
+
+    ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
+        alt!($i, call!($e) => { $gen } | $($rest)*)
+    };
+
+    ($i:expr, $e:ident => { $gen:expr }) => {
+        alt!($i, call!($e) => { $gen })
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
+        match $subrule!($i, $($args)*) {
+            Ok((i, o)) => Ok((i, $gen(o))),
+            Err(LexError) => Err(LexError),
+        }
+    };
+
+    ($i:expr, $e:ident) => {
+        alt!($i, call!($e))
+    };
+
+    ($i:expr, $subrule:ident!( $($args:tt)*)) => {
+        $subrule!($i, $($args)*)
+    };
+}
+
+macro_rules! do_parse {
+    ($i:expr, ( $($rest:expr),* )) => {
+        Ok(($i, ( $($rest),* )))
+    };
+
+    ($i:expr, $e:ident >> $($rest:tt)*) => {
+        do_parse!($i, call!($e) >> $($rest)*)
+    };
+
+    ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, _)) => do_parse!(i, $($rest)*),
+        }
+    };
+
+    ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
+        do_parse!($i, $field: call!($e) >> $($rest)*)
+    };
+
+    ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, o)) => {
+                let $field = o;
+                do_parse!(i, $($rest)*)
+            },
+        }
+    };
+}
+
+macro_rules! peek {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            Ok((_, o)) => Ok(($i, o)),
+            Err(LexError) => Err(LexError),
+        }
+    };
+}
+
+macro_rules! call {
+    ($i:expr, $fun:expr $(, $args:expr)*) => {
+        $fun($i $(, $args)*)
+    };
+}
+
+macro_rules! option {
+    ($i:expr, $f:expr) => {
+        match $f($i) {
+            Ok((i, o)) => Ok((i, Some(o))),
+            Err(LexError) => Ok(($i, None)),
+        }
+    };
+}
+
+macro_rules! take_until {
+    ($i:expr, $substr:expr) => {{
+        if $substr.len() > $i.len() {
+            Err(LexError)
+        } else {
+            let substr_vec: Vec<char> = $substr.chars().collect();
+            let mut window: Vec<char> = vec![];
+            let mut offset = $i.len();
+            let mut parsed = false;
+            for (o, c) in $i.char_indices() {
+                window.push(c);
+                if window.len() > substr_vec.len() {
+                    window.remove(0);
+                }
+                if window == substr_vec {
+                    parsed = true;
+                    window.pop();
+                    let window_len: usize = window.iter()
+                        .map(|x| x.len_utf8())
+                        .fold(0, |x, y| x + y);
+                    offset = o - window_len;
+                    break;
+                }
+            }
+            if parsed {
+                Ok(($i.advance(offset), &$i.rest[..offset]))
+            } else {
+                Err(LexError)
+            }
+        }
+    }};
+}
+
+macro_rules! tuple {
+    ($i:expr, $($rest:tt)*) => {
+        tuple_parser!($i, (), $($rest)*)
+    };
+}
+
+/// Do not use directly. Use `tuple!`.
+macro_rules! tuple_parser {
+    ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
+        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
+    };
+
+    ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, o)) => tuple_parser!(i, (o), $($rest)*),
+        }
+    };
+
+    ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*),
+        }
+    };
+
+    ($i:expr, ($($parsed:tt),*), $e:ident) => {
+        tuple_parser!($i, ($($parsed),*), call!($e))
+    };
+
+    ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
+        $submac!($i, $($args)*)
+    };
+
+    ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, o)) => Ok((i, ($($parsed),*, o)))
+        }
+    };
+
+    ($i:expr, ($($parsed:expr),*)) => {
+        Ok(($i, ($($parsed),*)))
+    };
+}
+
+macro_rules! not {
+    ($i:expr, $submac:ident!( $($args:tt)* )) => {
+        match $submac!($i, $($args)*) {
+            Ok((_, _)) => Err(LexError),
+            Err(LexError) => Ok(($i, ())),
+        }
+    };
+}
+
+macro_rules! tag {
+    ($i:expr, $tag:expr) => {
+        if $i.starts_with($tag) {
+            Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()]))
+        } else {
+            Err(LexError)
+        }
+    };
+}
+
+macro_rules! punct {
+    ($i:expr, $punct:expr) => {
+        $crate::strnom::punct($i, $punct)
+    };
+}
+
+/// Do not use directly. Use `punct!`.
+pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> {
+    let input = skip_whitespace(input);
+    if input.starts_with(token) {
+        Ok((input.advance(token.len()), token))
+    } else {
+        Err(LexError)
+    }
+}
+
+macro_rules! preceded {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
+        match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
+            Ok((remaining, (_, o))) => Ok((remaining, o)),
+            Err(LexError) => Err(LexError),
+        }
+    };
+
+    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
+        preceded!($i, $submac!($($args)*), call!($g))
+    };
+}
+
+macro_rules! delimited {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
+        match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i1, (_, o, _))) => Ok((i1, o))
+        }
+    };
+}
+
+macro_rules! map {
+    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
+        match $submac!($i, $($args)*) {
+            Err(LexError) => Err(LexError),
+            Ok((i, o)) => Ok((i, call!(o, $g)))
+        }
+    };
+
+    ($i:expr, $f:expr, $g:expr) => {
+        map!($i, call!($f), $g)
+    };
+}
+
+macro_rules! many0 {
+    ($i:expr, $f:expr) => {{
+        let ret;
+        let mut res   = ::std::vec::Vec::new();
+        let mut input = $i;
+
+        loop {
+            if input.is_empty() {
+                ret = Ok((input, res));
+                break;
+            }
+
+            match $f(input) {
+                Err(LexError) => {
+                    ret = Ok((input, res));
+                    break;
+                }
+                Ok((i, o)) => {
+                    // loop trip must always consume (otherwise infinite loops)
+                    if i.len() == input.len() {
+                        ret = Err(LexError);
+                        break;
+                    }
+
+                    res.push(o);
+                    input = i;
+                }
+            }
+        }
+
+        ret
+    }};
+}
diff --git a/third_party/rust/proc-macro2-0.2.2/src/unstable.rs b/third_party/rust/proc-macro2-0.2.2/src/unstable.rs
new file mode 100644
index 000000000000..1a2508386291
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/src/unstable.rs
@@ -0,0 +1,406 @@
+use std::ascii;
+use std::fmt;
+use std::iter;
+use std::str::FromStr;
+
+use proc_macro;
+
+use {TokenTree, TokenNode, Delimiter, Spacing};
+
+#[derive(Clone)]
+pub struct TokenStream(proc_macro::TokenStream);
+
+pub struct LexError(proc_macro::LexError);
+
+impl TokenStream {
+    pub fn empty() -> TokenStream {
+        TokenStream(proc_macro::TokenStream::empty())
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+impl FromStr for TokenStream {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<TokenStream, LexError> {
+        Ok(TokenStream(src.parse().map_err(LexError)?))
+    }
+}
+
+impl fmt::Display for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl From<proc_macro::TokenStream> for TokenStream {
+    fn from(inner: proc_macro::TokenStream) -> TokenStream {
+        TokenStream(inner)
+    }
+}
+
+impl From<TokenStream> for proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> proc_macro::TokenStream {
+        inner.0
+    }
+}
+
+impl From<TokenTree> for TokenStream {
+    fn from(tree: TokenTree) -> TokenStream {
+        TokenStream(proc_macro::TokenTree {
+            span: (tree.span.0).0,
+            kind: match tree.kind {
+                TokenNode::Group(delim, s) => {
+                    let delim = match delim {
+                        Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
+                        Delimiter::Bracket => proc_macro::Delimiter::Bracket,
+                        Delimiter::Brace => proc_macro::Delimiter::Brace,
+                        Delimiter::None => proc_macro::Delimiter::None,
+                    };
+                    proc_macro::TokenNode::Group(delim, (s.0).0)
+                }
+                TokenNode::Op(ch, kind) => {
+                    let kind = match kind {
+                        Spacing::Joint => proc_macro::Spacing::Joint,
+                        Spacing::Alone => proc_macro::Spacing::Alone,
+                    };
+                    proc_macro::TokenNode::Op(ch, kind)
+                }
+                TokenNode::Term(s) => {
+                    proc_macro::TokenNode::Term((s.0).0)
+                }
+                TokenNode::Literal(l) => {
+                    proc_macro::TokenNode::Literal((l.0).0)
+                }
+            },
+        }.into())
+    }
+}
+
+impl iter::FromIterator<TokenStream> for TokenStream {
+    fn from_iter<I: IntoIterator<Item=TokenStream>>(streams: I) -> Self {
+        let streams = streams.into_iter().map(|s| s.0);
+        TokenStream(streams.collect::<proc_macro::TokenStream>())
+    }
+}
+
+impl fmt::Debug for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl fmt::Debug for LexError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+pub struct TokenTreeIter(proc_macro::TokenTreeIter);
+
+impl IntoIterator for TokenStream {
+    type Item = TokenTree;
+    type IntoIter = TokenTreeIter;
+
+    fn into_iter(self) -> TokenTreeIter {
+        TokenTreeIter(self.0.into_iter())
+    }
+}
+
+impl Iterator for TokenTreeIter {
+    type Item = TokenTree;
+
+    fn next(&mut self) -> Option<TokenTree> {
+        let token = match self.0.next() {
+            Some(n) => n,
+            None => return None,
+        };
+        Some(TokenTree {
+            span: ::Span(Span(token.span)),
+            kind: match token.kind {
+                proc_macro::TokenNode::Group(delim, s) => {
+                    let delim = match delim {
+                        proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
+                        proc_macro::Delimiter::Bracket => Delimiter::Bracket,
+                        proc_macro::Delimiter::Brace => Delimiter::Brace,
+                        proc_macro::Delimiter::None => Delimiter::None,
+                    };
+                    TokenNode::Group(delim, ::TokenStream(TokenStream(s)))
+                }
+                proc_macro::TokenNode::Op(ch, kind) => {
+                    let kind = match kind {
+                        proc_macro::Spacing::Joint => Spacing::Joint,
+                        proc_macro::Spacing::Alone => Spacing::Alone,
+                    };
+                    TokenNode::Op(ch, kind)
+                }
+                proc_macro::TokenNode::Term(s) => {
+                    TokenNode::Term(::Term(Term(s)))
+                }
+                proc_macro::TokenNode::Literal(l) => {
+                    TokenNode::Literal(::Literal(Literal(l)))
+                }
+            },
+        })
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl fmt::Debug for TokenTreeIter {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("TokenTreeIter").finish()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq)]
+pub struct FileName(String);
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Display for FileName {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+// NOTE: We have to generate our own filename object here because we can't wrap
+// the one provided by proc_macro.
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq)]
+pub struct SourceFile(proc_macro::SourceFile, FileName);
+
+#[cfg(procmacro2_semver_exempt)]
+impl SourceFile {
+    fn new(sf: proc_macro::SourceFile) -> Self {
+        let filename = FileName(sf.path().to_string());
+        SourceFile(sf, filename)
+    }
+
+    /// Get the path to this source file as a string.
+    pub fn path(&self) -> &FileName {
+        &self.1
+    }
+
+    pub fn is_real(&self) -> bool {
+        self.0.is_real()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl AsRef<FileName> for SourceFile {
+    fn as_ref(&self) -> &FileName {
+        self.path()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Debug for SourceFile {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+pub struct LineColumn {
+    pub line: usize,
+    pub column: usize,
+}
+
+#[derive(Copy, Clone)]
+pub struct Span(proc_macro::Span);
+
+impl From<proc_macro::Span> for ::Span {
+    fn from(proc_span: proc_macro::Span) -> ::Span {
+        ::Span(Span(proc_span))
+    }
+}
+
+impl Span {
+    pub fn call_site() -> Span {
+        Span(proc_macro::Span::call_site())
+    }
+
+    pub fn def_site() -> Span {
+        Span(proc_macro::Span::def_site())
+    }
+
+    pub fn resolved_at(&self, other: Span) -> Span {
+        Span(self.0.resolved_at(other.0))
+    }
+
+    pub fn located_at(&self, other: Span) -> Span {
+        Span(self.0.located_at(other.0))
+    }
+
+    pub fn unstable(self) -> proc_macro::Span {
+        self.0
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn source_file(&self) -> SourceFile {
+        SourceFile::new(self.0.source_file())
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn start(&self) -> LineColumn {
+        let proc_macro::LineColumn{ line, column } = self.0.start();
+        LineColumn { line, column }
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn end(&self) -> LineColumn {
+        let proc_macro::LineColumn{ line, column } = self.0.end();
+        LineColumn { line, column }
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn join(&self, other: Span) -> Option<Span> {
+        self.0.join(other.0).map(Span)
+    }
+}
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct Term(proc_macro::Term);
+
+impl Term {
+    pub fn intern(string: &str) -> Term {
+        Term(proc_macro::Term::intern(string))
+    }
+
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
+}
+
+impl fmt::Debug for Term {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[derive(Clone)]
+pub struct Literal(proc_macro::Literal);
+
+impl Literal {
+    pub fn byte_char(byte: u8) -> Literal {
+        match byte {
+            0 => Literal(to_literal("b'\\0'")),
+            b'\"' => Literal(to_literal("b'\"'")),
+            n => {
+                let mut escaped = "b'".to_string();
+                escaped.extend(ascii::escape_default(n).map(|c| c as char));
+                escaped.push('\'');
+                Literal(to_literal(&escaped))
+            }
+        }
+    }
+
+    pub fn byte_string(bytes: &[u8]) -> Literal {
+        Literal(proc_macro::Literal::byte_string(bytes))
+    }
+
+    pub fn doccomment(s: &str) -> Literal {
+        Literal(to_literal(s))
+    }
+
+    pub fn float(s: f64) -> Literal {
+        Literal(proc_macro::Literal::float(s))
+    }
+
+    pub fn integer(s: i64) -> Literal {
+        Literal(proc_macro::Literal::integer(s.into()))
+    }
+
+    pub fn raw_string(s: &str, pounds: usize) -> Literal {
+        let mut ret = format!("r");
+        ret.extend((0..pounds).map(|_| "#"));
+        ret.push('"');
+        ret.push_str(s);
+        ret.push('"');
+        ret.extend((0..pounds).map(|_| "#"));
+        Literal(to_literal(&ret))
+    }
+
+    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
+        let mut ret = format!("br");
+        ret.extend((0..pounds).map(|_| "#"));
+        ret.push('"');
+        ret.push_str(s);
+        ret.push('"');
+        ret.extend((0..pounds).map(|_| "#"));
+        Literal(to_literal(&ret))
+    }
+}
+
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl fmt::Debug for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+fn to_literal(s: &str) -> proc_macro::Literal {
+    let stream = s.parse::<proc_macro::TokenStream>().unwrap();
+    match stream.into_iter().next().unwrap().kind {
+        proc_macro::TokenNode::Literal(l) => l,
+        _ => unreachable!(),
+    }
+}
+
+macro_rules! ints {
+    ($($t:ident,)*) => {$(
+        impl From<$t> for Literal {
+            fn from(t: $t) -> Literal {
+                Literal(proc_macro::Literal::$t(t))
+            }
+        }
+    )*}
+}
+
+ints! {
+    u8, u16, u32, u64, usize,
+    i8, i16, i32, i64, isize,
+}
+
+macro_rules! floats {
+    ($($t:ident,)*) => {$(
+        impl From<$t> for Literal {
+            fn from(t: $t) -> Literal {
+                Literal(proc_macro::Literal::$t(t))
+            }
+        }
+    )*}
+}
+
+floats! {
+    f32, f64,
+}
+
+impl<'a> From<&'a str> for Literal {
+    fn from(t: &'a str) -> Literal {
+        Literal(proc_macro::Literal::string(t))
+    }
+}
+
+impl From<char> for Literal {
+    fn from(t: char) -> Literal {
+        Literal(proc_macro::Literal::character(t))
+    }
+}
diff --git a/third_party/rust/proc-macro2-0.2.2/tests/test.rs b/third_party/rust/proc-macro2-0.2.2/tests/test.rs
new file mode 100644
index 000000000000..ff9c205af9fe
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.2.2/tests/test.rs
@@ -0,0 +1,179 @@
+extern crate proc_macro2;
+
+use std::str;
+
+use proc_macro2::{Term, Literal, TokenStream};
+
+#[cfg(procmacro2_semver_exempt)]
+use proc_macro2::TokenNode;
+
+#[cfg(procmacro2_semver_exempt)]
+#[cfg(not(feature = "nightly"))]
+use proc_macro2::Span;
+
+#[test]
+fn symbols() {
+    assert_eq!(Term::intern("foo").as_str(), "foo");
+    assert_eq!(Term::intern("bar").as_str(), "bar");
+}
+
+#[test]
+fn literals() {
+    assert_eq!(Literal::string("foo").to_string(), "\"foo\"");
+    assert_eq!(Literal::string("\"").to_string(), "\"\\\"\"");
+    assert_eq!(Literal::float(10.0).to_string(), "10.0");
+}
+
+#[test]
+fn roundtrip() {
+    fn roundtrip(p: &str) {
+        println!("parse: {}", p);
+        let s = p.parse::<TokenStream>().unwrap().to_string();
+        println!("first: {}", s);
+        let s2 = s.to_string().parse::<TokenStream>().unwrap().to_string();
+        assert_eq!(s, s2);
+    }
+    roundtrip("a");
+    roundtrip("<<");
+    roundtrip("<<=");
+    roundtrip("
+        /// a
+        wut
+    ");
+    roundtrip("
+        1
+        1.0
+        1f32
+        2f64
+        1usize
+        4isize
+        4e10
+        1_000
+        1_0i32
+        8u8
+        9
+        0
+        0xffffffffffffffffffffffffffffffff
+    ");
+    roundtrip("'a");
+    roundtrip("'static");
+    roundtrip("'\\u{10__FFFF}'");
+    roundtrip("\"\\u{10_F0FF__}foo\\u{1_0_0_0__}\"");
+}
+
+#[test]
+fn fail() {
+    fn fail(p: &str) {
+        if p.parse::<TokenStream>().is_ok() {
+            panic!("should have failed to parse: {}", p);
+        }
+    }
+    fail("1x");
+    fail("1u80");
+    fail("1f320");
+    fail("' static");
+    fail("'mut");
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[test]
+fn span_test() {
+    fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) {
+        let ts = p.parse::<TokenStream>().unwrap();
+        check_spans_internal(ts, &mut lines);
+    }
+
+    fn check_spans_internal(
+        ts: TokenStream,
+        lines: &mut &[(usize, usize, usize, usize)],
+    ) {
+        for i in ts {
+            if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() {
+                *lines = rest;
+
+                let start = i.span.start();
+                assert_eq!(start.line, sline, "sline did not match for {}", i);
+                assert_eq!(start.column, scol, "scol did not match for {}", i);
+
+                let end = i.span.end();
+                assert_eq!(end.line, eline, "eline did not match for {}", i);
+                assert_eq!(end.column, ecol, "ecol did not match for {}", i);
+
+                match i.kind {
+                    TokenNode::Group(_, stream) =>
+                        check_spans_internal(stream, lines),
+                    _ => {}
+                }
+            }
+        }
+    }
+
+    check_spans("\
+/// This is a document comment
+testing 123
+{
+  testing 234
+}", &[
+    (1, 0, 1, 30),
+    (2, 0, 2, 7),
+    (2, 8, 2, 11),
+    (3, 0, 5, 1),
+    (4, 2, 4, 9),
+    (4, 10, 4, 13),
+]);
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[cfg(not(feature = "nightly"))]
+#[test]
+fn default_span() {
+    let start = Span::call_site().start();
+    assert_eq!(start.line, 1);
+    assert_eq!(start.column, 0);
+    let end = Span::call_site().end();
+    assert_eq!(end.line, 1);
+    assert_eq!(end.column, 0);
+    let source_file = Span::call_site().source_file();
+    assert_eq!(source_file.path().to_string(), "<unspecified>");
+    assert!(!source_file.is_real());
+}
+
+#[cfg(procmacro2_semver_exempt)]
+#[test]
+fn span_join() {
+    let source1 =
+        "aaa\nbbb".parse::<TokenStream>().unwrap().into_iter().collect::<Vec<_>>();
+    let source2 =
+        "ccc\nddd".parse::<TokenStream>().unwrap().into_iter().collect::<Vec<_>>();
+
+    assert!(source1[0].span.source_file() != source2[0].span.source_file());
+    assert_eq!(source1[0].span.source_file(), source1[1].span.source_file());
+
+    let joined1 = source1[0].span.join(source1[1].span);
+    let joined2 = source1[0].span.join(source2[0].span);
+    assert!(joined1.is_some());
+    assert!(joined2.is_none());
+
+    let start = joined1.unwrap().start();
+    let end = joined1.unwrap().end();
+    assert_eq!(start.line, 1);
+    assert_eq!(start.column, 0);
+    assert_eq!(end.line, 2);
+    assert_eq!(end.column, 3);
+
+    assert_eq!(joined1.unwrap().source_file(), source1[0].span.source_file());
+}
+
+#[test]
+fn no_panic() {
+    let s = str::from_utf8(b"b\'\xc2\x86  \x00\x00\x00^\"").unwrap();
+    assert!(s.parse::<proc_macro2::TokenStream>().is_err());
+}
+
+#[test]
+fn tricky_doc_commaent() {
+    let stream = "/**/".parse::<proc_macro2::TokenStream>().unwrap();
+    let tokens = stream.into_iter().collect::<Vec<_>>();
+    assert!(tokens.is_empty(), "not empty -- {:?}", tokens);
+}
+
diff --git a/third_party/rust/proc-macro2/.cargo-checksum.json b/third_party/rust/proc-macro2/.cargo-checksum.json
index 6d5e5011ec54..42c3596e0eb7 100644
--- a/third_party/rust/proc-macro2/.cargo-checksum.json
+++ b/third_party/rust/proc-macro2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"e455a0ed5c3dd056d31f4c7be088bc94f21cab6595a23f2f015b1efc0ac2b55c","Cargo.toml":"0b700f1e7b8ba76ce4678d36b6906d38455e88f51085ea9f120d6ca63f13d5d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"adf2e822923878c2ebf4a0a782898c598fc6f57a3af905b85d57fc716c836687","src/lib.rs":"fbae25504264b185d877fb8784d4d88333ea34a7cbeddca3277dc8421f179933","src/macros.rs":"414505e520b8d705b4ce5a64ec2e82d6d1af0b88567454169486a668fbc1e9c8","src/stable.rs":"6363c4c0ef989c2ec81aa75be71c69a103d45a1de439f3f3bcb6806d8a78a172","src/strnom.rs":"1baded8543a9930798fb16092fe51e9074591902e327e0f94eb1c908a6370de9","src/unstable.rs":"110d27103e37427b3d1dcb45b6ba9dc9f5641a255766a43d5db0f4fd10a341ed","tests/test.rs":"9e75d5289abc1dc58c1df00ae051d8c3cd2c0d7830cca5ad689007c05acffe26"},"package":"d1cb7aaaa4bf022ec2b14ff2f2ba1643a22f3cee88df014a85e14b392282c61d"}
\ No newline at end of file
+{"files":{".travis.yml":"872a0d195dcb1e84f28aa994f301c7139f70360bb42dee3954df5ee965efea15","Cargo.toml":"e71f764696d6998512da00a9ac309f2717d103707aeef81164f906c1588ede63","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ce05336717e1e90724491a2f54487c41c752fa2d32396639439f7c6d0f1e6776","src/lib.rs":"3280d7e0b6043d8472f418aa5c8458c97aa2b5a572f9156a251b5672828468c2","src/stable.rs":"4b5a65bd5dc174dd027b9ee951844c3765450f9d45961a8d6cd7d5f85b4c25c8","src/strnom.rs":"129fe22f0b50e5a64fca82e731c959135381c910e19f3305ef35420e0aadde08","src/unstable.rs":"b43c713ac16d9de0ba0fa1b9bebe390122b4ad60ef2fc75408f721305fdcd46b","tests/test.rs":"b06713fd8bd93ab9f0156bd25152e08f68a71b35e064c53b584f7f7dbb9b60b8"},"package":"77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"}
\ No newline at end of file
diff --git a/third_party/rust/proc-macro2/.travis.yml b/third_party/rust/proc-macro2/.travis.yml
index a524c0167e1e..78942c4061d6 100644
--- a/third_party/rust/proc-macro2/.travis.yml
+++ b/third_party/rust/proc-macro2/.travis.yml
@@ -7,16 +7,17 @@ matrix:
     - rust: stable
     - rust: beta
     - rust: nightly
       before_script:
         - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
       script:
         - cargo test
         - cargo build --features nightly
+        - cargo build --no-default-features
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build --features nightly
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo doc --no-deps
       after_success:
         - travis-cargo --only nightly doc-upload
 
 script:
   - cargo test
diff --git a/third_party/rust/proc-macro2/Cargo.toml b/third_party/rust/proc-macro2/Cargo.toml
index 17a47c189be7..95dec5e89b65 100644
--- a/third_party/rust/proc-macro2/Cargo.toml
+++ b/third_party/rust/proc-macro2/Cargo.toml
@@ -7,25 +7,27 @@
 #
 # 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 = "proc-macro2"
-version = "0.2.2"
+version = "0.3.5"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
 homepage = "https://github.com/alexcrichton/proc-macro2"
 documentation = "https://docs.rs/proc-macro2"
 readme = "README.md"
 keywords = ["macros"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/alexcrichton/proc-macro2"
 
 [lib]
 doctest = false
 [dependencies.unicode-xid]
 version = "0.1"
 
 [features]
-nightly = []
+default = ["proc-macro"]
+nightly = ["proc-macro"]
+proc-macro = []
diff --git a/third_party/rust/proc-macro2/README.md b/third_party/rust/proc-macro2/README.md
index c0a62a3a184b..6a9153f86e69 100644
--- a/third_party/rust/proc-macro2/README.md
+++ b/third_party/rust/proc-macro2/README.md
@@ -22,17 +22,17 @@ the real `proc_macro` crate once the support on nightly is stabilize.
 ## Usage
 
 This crate by default compiles on the stable version of the compiler. It only
 uses the stable surface area of the `proc_macro` crate upstream in the compiler
 itself. Usage is done via:
 
 ```toml
 [dependencies]
-proc-macro2 = "0.2"
+proc-macro2 = "0.3"
 ```
 
 followed by
 
 ```rust
 extern crate proc_macro;
 extern crate proc_macro2;
 
@@ -52,17 +52,17 @@ If you'd like you can enable the `nightly` feature in this crate. This will
 cause it to compile against the **unstable and nightly-only** features of the
 `proc_macro` crate. This in turn requires a nightly compiler. This should help
 preserve span information, however, coming in from the compiler itself.
 
 You can enable this feature via:
 
 ```toml
 [dependencies]
-proc-macro2 = { version = "0.2", features = ["nightly"] }
+proc-macro2 = { version = "0.3", features = ["nightly"] }
 ```
 
 
 ## Unstable Features
 
 `proc-macro2` supports exporting some methods from `proc_macro` which are
 currently highly unstable, and may not be stabilized in the first pass of
 `proc_macro` stabilizations. These features are not exported by default. Minor
diff --git a/third_party/rust/proc-macro2/src/lib.rs b/third_party/rust/proc-macro2/src/lib.rs
index 373174c5f79d..4db9f0384fc9 100644
--- a/third_party/rust/proc-macro2/src/lib.rs
+++ b/third_party/rust/proc-macro2/src/lib.rs
@@ -1,113 +1,135 @@
-//! A "shim crate" intended to multiplex the `proc_macro` API on to stable Rust.
+//! A "shim crate" intended to multiplex the [`proc_macro`] API on to stable
+//! Rust.
 //!
 //! Procedural macros in Rust operate over the upstream
-//! `proc_macro::TokenStream` type. This type currently is quite conservative
-//! and exposed no internal implementation details. Nightly compilers, however,
-//! contain a much richer interface. This richer interface allows fine-grained
-//! inspection of the token stream which avoids stringification/re-lexing and
-//! also preserves span information.
+//! [`proc_macro::TokenStream`][ts] type. This type currently is quite
+//! conservative and exposed no internal implementation details. Nightly
+//! compilers, however, contain a much richer interface. This richer interface
+//! allows fine-grained inspection of the token stream which avoids
+//! stringification/re-lexing and also preserves span information.
 //!
-//! The upcoming APIs added to `proc_macro` upstream are the foundation for
+//! The upcoming APIs added to [`proc_macro`] upstream are the foundation for
 //! productive procedural macros in the ecosystem. To help prepare the ecosystem
 //! for using them this crate serves to both compile on stable and nightly and
 //! mirrors the API-to-be. The intention is that procedural macros which switch
 //! to use this crate will be trivially able to switch to the upstream
 //! `proc_macro` crate once its API stabilizes.
 //!
 //! In the meantime this crate also has a `nightly` Cargo feature which
-//! enables it to reimplement itself with the unstable API of `proc_macro`.
+//! enables it to reimplement itself with the unstable API of [`proc_macro`].
 //! This'll allow immediate usage of the beneficial upstream API, particularly
 //! around preserving span information.
+//!
+//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
+//! [ts]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
 
 // Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/0.2.2")]
-
+#![doc(html_root_url = "https://docs.rs/proc-macro2/0.3.5")]
 #![cfg_attr(feature = "nightly", feature(proc_macro))]
 
+#[cfg(feature = "proc-macro")]
 extern crate proc_macro;
 
 #[cfg(not(feature = "nightly"))]
 extern crate unicode_xid;
 
 use std::fmt;
-use std::str::FromStr;
 use std::iter::FromIterator;
+use std::marker;
+use std::rc::Rc;
+use std::str::FromStr;
 
 #[macro_use]
 #[cfg(not(feature = "nightly"))]
 mod strnom;
 
 #[path = "stable.rs"]
 #[cfg(not(feature = "nightly"))]
 mod imp;
 #[path = "unstable.rs"]
 #[cfg(feature = "nightly")]
 mod imp;
 
-#[macro_use]
-mod macros;
-
 #[derive(Clone)]
-pub struct TokenStream(imp::TokenStream);
+pub struct TokenStream {
+    inner: imp::TokenStream,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+pub struct LexError {
+    inner: imp::LexError,
+    _marker: marker::PhantomData<Rc<()>>,
+}
 
-pub struct LexError(imp::LexError);
+impl TokenStream {
+    fn _new(inner: imp::TokenStream) -> TokenStream {
+        TokenStream {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
+    pub fn empty() -> TokenStream {
+        TokenStream::_new(imp::TokenStream::empty())
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.inner.is_empty()
+    }
+}
 
 impl FromStr for TokenStream {
     type Err = LexError;
 
     fn from_str(src: &str) -> Result<TokenStream, LexError> {
-        match src.parse() {
-            Ok(e) => Ok(TokenStream(e)),
-            Err(e) => Err(LexError(e)),
-        }
+        let e = src.parse().map_err(|e| LexError {
+            inner: e,
+            _marker: marker::PhantomData,
+        })?;
+        Ok(TokenStream::_new(e))
     }
 }
 
+#[cfg(feature = "proc-macro")]
 impl From<proc_macro::TokenStream> for TokenStream {
     fn from(inner: proc_macro::TokenStream) -> TokenStream {
-        TokenStream(inner.into())
+        TokenStream::_new(inner.into())
     }
 }
 
+#[cfg(feature = "proc-macro")]
 impl From<TokenStream> for proc_macro::TokenStream {
     fn from(inner: TokenStream) -> proc_macro::TokenStream {
-        inner.0.into()
+        inner.inner.into()
     }
 }
 
-impl From<TokenTree> for TokenStream {
-    fn from(tree: TokenTree) -> TokenStream {
-        TokenStream(tree.into())
+impl FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
+        TokenStream::_new(streams.into_iter().collect())
     }
 }
 
-impl<T: Into<TokenStream>> FromIterator<T> for TokenStream {
-    fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
-        TokenStream(streams.into_iter().map(|t| t.into().0).collect())
+impl fmt::Display for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
-impl IntoIterator for TokenStream {
-    type Item = TokenTree;
-    type IntoIter = TokenTreeIter;
-
-    fn into_iter(self) -> TokenTreeIter {
-        TokenTreeIter(self.0.into_iter())
+impl fmt::Debug for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
-impl TokenStream {
-    pub fn empty() -> TokenStream {
-        TokenStream(imp::TokenStream::empty())
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.0.is_empty()
+impl fmt::Debug for LexError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
 // Returned by reference, so we can't easily wrap it.
 #[cfg(procmacro2_semver_exempt)]
 pub use imp::FileName;
 
 #[cfg(procmacro2_semver_exempt)]
@@ -142,196 +164,427 @@ impl fmt::Debug for SourceFile {
 
 #[cfg(procmacro2_semver_exempt)]
 pub struct LineColumn {
     pub line: usize,
     pub column: usize,
 }
 
 #[derive(Copy, Clone)]
-pub struct Span(imp::Span);
+pub struct Span {
+    inner: imp::Span,
+    _marker: marker::PhantomData<Rc<()>>,
+}
 
 impl Span {
+    fn _new(inner: imp::Span) -> Span {
+        Span {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
     pub fn call_site() -> Span {
-        Span(imp::Span::call_site())
+        Span::_new(imp::Span::call_site())
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn def_site() -> Span {
-        Span(imp::Span::def_site())
+        Span::_new(imp::Span::def_site())
     }
 
     /// Creates a new span with the same line/column information as `self` but
     /// that resolves symbols as though it were at `other`.
+    #[cfg(procmacro2_semver_exempt)]
     pub fn resolved_at(&self, other: Span) -> Span {
-        Span(self.0.resolved_at(other.0))
+        Span::_new(self.inner.resolved_at(other.inner))
     }
 
     /// Creates a new span with the same name resolution behavior as `self` but
     /// with the line/column information of `other`.
+    #[cfg(procmacro2_semver_exempt)]
     pub fn located_at(&self, other: Span) -> Span {
-        Span(self.0.located_at(other.0))
+        Span::_new(self.inner.located_at(other.inner))
     }
 
     /// This method is only available when the `"nightly"` feature is enabled.
-    #[cfg(feature = "nightly")]
+    #[cfg(all(feature = "nightly", feature = "proc-macro"))]
     pub fn unstable(self) -> proc_macro::Span {
-        self.0.unstable()
+        self.inner.unstable()
     }
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn source_file(&self) -> SourceFile {
-        SourceFile(self.0.source_file())
+        SourceFile(self.inner.source_file())
     }
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn start(&self) -> LineColumn {
-        let imp::LineColumn{ line, column } = self.0.start();
-        LineColumn { line: line, column: column }
+        let imp::LineColumn { line, column } = self.inner.start();
+        LineColumn {
+            line: line,
+            column: column,
+        }
     }
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn end(&self) -> LineColumn {
-        let imp::LineColumn{ line, column } = self.0.end();
-        LineColumn { line: line, column: column }
+        let imp::LineColumn { line, column } = self.inner.end();
+        LineColumn {
+            line: line,
+            column: column,
+        }
     }
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn join(&self, other: Span) -> Option<Span> {
-        self.0.join(other.0).map(Span)
+        self.inner.join(other.inner).map(Span::_new)
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn eq(&self, other: &Span) -> bool {
+        self.inner.eq(&other.inner)
+    }
+}
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
 #[derive(Clone, Debug)]
-pub struct TokenTree {
-    pub span: Span,
-    pub kind: TokenNode,
+pub enum TokenTree {
+    Group(Group),
+    Term(Term),
+    Op(Op),
+    Literal(Literal),
+}
+
+impl TokenTree {
+    pub fn span(&self) -> Span {
+        match *self {
+            TokenTree::Group(ref t) => t.span(),
+            TokenTree::Term(ref t) => t.span(),
+            TokenTree::Op(ref t) => t.span(),
+            TokenTree::Literal(ref t) => t.span(),
+        }
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        match *self {
+            TokenTree::Group(ref mut t) => t.set_span(span),
+            TokenTree::Term(ref mut t) => t.set_span(span),
+            TokenTree::Op(ref mut t) => t.set_span(span),
+            TokenTree::Literal(ref mut t) => t.set_span(span),
+        }
+    }
 }
 
-impl From<TokenNode> for TokenTree {
-    fn from(kind: TokenNode) -> TokenTree {
-        TokenTree { span: Span::def_site(), kind: kind }
+impl From<Group> for TokenTree {
+    fn from(g: Group) -> TokenTree {
+        TokenTree::Group(g)
+    }
+}
+
+impl From<Term> for TokenTree {
+    fn from(g: Term) -> TokenTree {
+        TokenTree::Term(g)
+    }
+}
+
+impl From<Op> for TokenTree {
+    fn from(g: Op) -> TokenTree {
+        TokenTree::Op(g)
+    }
+}
+
+impl From<Literal> for TokenTree {
+    fn from(g: Literal) -> TokenTree {
+        TokenTree::Literal(g)
     }
 }
 
 impl fmt::Display for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        TokenStream::from(self.clone()).fmt(f)
+        match *self {
+            TokenTree::Group(ref t) => t.fmt(f),
+            TokenTree::Term(ref t) => t.fmt(f),
+            TokenTree::Op(ref t) => t.fmt(f),
+            TokenTree::Literal(ref t) => t.fmt(f),
+        }
     }
 }
 
 #[derive(Clone, Debug)]
-pub enum TokenNode {
-    Group(Delimiter, TokenStream),
-    Term(Term),
-    Op(char, Spacing),
-    Literal(Literal),
+pub struct Group {
+    delimiter: Delimiter,
+    stream: TokenStream,
+    span: Span,
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Delimiter {
     Parenthesis,
     Brace,
     Bracket,
     None,
 }
 
-#[derive(Copy, Clone)]
-pub struct Term(imp::Term);
+impl Group {
+    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
+        Group {
+            delimiter: delimiter,
+            stream: stream,
+            span: Span::call_site(),
+        }
+    }
 
-impl Term {
-    pub fn intern(string: &str) -> Term {
-        Term(imp::Term::intern(string))
+    pub fn delimiter(&self) -> Delimiter {
+        self.delimiter
     }
 
-    pub fn as_str(&self) -> &str {
-        self.0.as_str()
+    pub fn stream(&self) -> TokenStream {
+        self.stream.clone()
+    }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
     }
 }
 
+impl fmt::Display for Group {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.stream.fmt(f)
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct Op {
+    op: char,
+    spacing: Spacing,
+    span: Span,
+}
+
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Spacing {
     Alone,
     Joint,
 }
 
+impl Op {
+    pub fn new(op: char, spacing: Spacing) -> Op {
+        Op {
+            op: op,
+            spacing: spacing,
+            span: Span::call_site(),
+        }
+    }
+
+    pub fn op(&self) -> char {
+        self.op
+    }
+
+    pub fn spacing(&self) -> Spacing {
+        self.spacing
+    }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
+impl fmt::Display for Op {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.op.fmt(f)
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct Term {
+    inner: imp::Term,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+impl Term {
+    fn _new(inner: imp::Term) -> Term {
+        Term {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
+    pub fn new(string: &str, span: Span) -> Term {
+        Term::_new(imp::Term::new(string, span.inner))
+    }
+
+    pub fn as_str(&self) -> &str {
+        self.inner.as_str()
+    }
+
+    pub fn span(&self) -> Span {
+        Span::_new(self.inner.span())
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.inner.set_span(span.inner);
+    }
+}
+
+impl fmt::Display for Term {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_str().fmt(f)
+    }
+}
+
+impl fmt::Debug for Term {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
 #[derive(Clone)]
-pub struct Literal(imp::Literal);
+pub struct Literal {
+    inner: imp::Literal,
+    _marker: marker::PhantomData<Rc<()>>,
+}
 
 macro_rules! int_literals {
-    ($($kind:ident,)*) => ($(
-        pub fn $kind(n: $kind) -> Literal {
-            Literal(n.into())
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(imp::Literal::$name(n))
         }
     )*)
 }
 
 impl Literal {
-    pub fn integer(s: i64) -> Literal {
-        Literal(imp::Literal::integer(s))
+    fn _new(inner: imp::Literal) -> Literal {
+        Literal {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
     }
 
     int_literals! {
-        u8, u16, u32, u64, usize,
-        i8, i16, i32, i64, isize,
+        u8_suffixed => u8,
+        u16_suffixed => u16,
+        u32_suffixed => u32,
+        u64_suffixed => u64,
+        usize_suffixed => usize,
+        i8_suffixed => i8,
+        i16_suffixed => i16,
+        i32_suffixed => i32,
+        i64_suffixed => i64,
+        isize_suffixed => isize,
+
+        u8_unsuffixed => u8,
+        u16_unsuffixed => u16,
+        u32_unsuffixed => u32,
+        u64_unsuffixed => u64,
+        usize_unsuffixed => usize,
+        i8_unsuffixed => i8,
+        i16_unsuffixed => i16,
+        i32_unsuffixed => i32,
+        i64_unsuffixed => i64,
+        isize_unsuffixed => isize,
+    }
+
+    pub fn f64_unsuffixed(f: f64) -> Literal {
+        assert!(f.is_finite());
+        Literal::_new(imp::Literal::f64_unsuffixed(f))
     }
 
-    pub fn float(f: f64) -> Literal {
-        Literal(imp::Literal::float(f))
+    pub fn f64_suffixed(f: f64) -> Literal {
+        assert!(f.is_finite());
+        Literal::_new(imp::Literal::f64_suffixed(f))
     }
 
-    pub fn f64(f: f64) -> Literal {
-        Literal(f.into())
+    pub fn f32_unsuffixed(f: f32) -> Literal {
+        assert!(f.is_finite());
+        Literal::_new(imp::Literal::f32_unsuffixed(f))
     }
 
-    pub fn f32(f: f32) -> Literal {
-        Literal(f.into())
+    pub fn f32_suffixed(f: f32) -> Literal {
+        assert!(f.is_finite());
+        Literal::_new(imp::Literal::f32_suffixed(f))
     }
 
     pub fn string(string: &str) -> Literal {
-        Literal(string.into())
+        Literal::_new(imp::Literal::string(string))
     }
 
     pub fn character(ch: char) -> Literal {
-        Literal(ch.into())
+        Literal::_new(imp::Literal::character(ch))
     }
 
     pub fn byte_string(s: &[u8]) -> Literal {
-        Literal(imp::Literal::byte_string(s))
+        Literal::_new(imp::Literal::byte_string(s))
     }
 
-    // =======================================================================
-    // Not present upstream in proc_macro yet
-
-    pub fn byte_char(b: u8) -> Literal {
-        Literal(imp::Literal::byte_char(b))
+    pub fn span(&self) -> Span {
+        Span::_new(self.inner.span())
     }
 
-    pub fn doccomment(s: &str) -> Literal {
-        Literal(imp::Literal::doccomment(s))
+    pub fn set_span(&mut self, span: Span) {
+        self.inner.set_span(span.inner);
     }
+}
 
-    pub fn raw_string(s: &str, pounds: usize) -> Literal {
-        Literal(imp::Literal::raw_string(s, pounds))
+impl fmt::Debug for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
+}
 
-    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
-        Literal(imp::Literal::raw_byte_string(s, pounds))
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
     }
 }
 
-pub struct TokenTreeIter(imp::TokenTreeIter);
+pub mod token_stream {
+    use std::fmt;
+    use std::marker;
+    use std::rc::Rc;
 
-impl Iterator for TokenTreeIter {
-    type Item = TokenTree;
+    pub use TokenStream;
+    use TokenTree;
+    use imp;
 
-    fn next(&mut self) -> Option<TokenTree> {
-        self.0.next()
+    pub struct IntoIter {
+        inner: imp::TokenTreeIter,
+        _marker: marker::PhantomData<Rc<()>>,
+    }
+
+    impl Iterator for IntoIter {
+        type Item = TokenTree;
+
+        fn next(&mut self) -> Option<TokenTree> {
+            self.inner.next()
+        }
+    }
+
+    impl fmt::Debug for IntoIter {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            self.inner.fmt(f)
+        }
     }
-}
 
-forward_fmt!(Debug for LexError);
-forward_fmt!(Debug for Literal);
-forward_fmt!(Debug for Span);
-forward_fmt!(Debug for Term);
-forward_fmt!(Debug for TokenTreeIter);
-forward_fmt!(Debug for TokenStream);
-forward_fmt!(Display for Literal);
-forward_fmt!(Display for TokenStream);
+    impl IntoIterator for TokenStream {
+        type Item = TokenTree;
+        type IntoIter = IntoIter;
+
+        fn into_iter(self) -> IntoIter {
+            IntoIter {
+                inner: self.inner.into_iter(),
+                _marker: marker::PhantomData,
+            }
+        }
+    }
+}
diff --git a/third_party/rust/proc-macro2/src/stable.rs b/third_party/rust/proc-macro2/src/stable.rs
index ffa077a29531..abfeab36951c 100644
--- a/third_party/rust/proc-macro2/src/stable.rs
+++ b/third_party/rust/proc-macro2/src/stable.rs
@@ -1,26 +1,25 @@
-use std::ascii;
+#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
+
 use std::borrow::Borrow;
 use std::cell::RefCell;
 #[cfg(procmacro2_semver_exempt)]
 use std::cmp;
 use std::collections::HashMap;
 use std::fmt;
 use std::iter;
-use std::marker::PhantomData;
 use std::rc::Rc;
 use std::str::FromStr;
 use std::vec;
 
-use proc_macro;
+use strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult};
 use unicode_xid::UnicodeXID;
-use strnom::{Cursor, PResult, skip_whitespace, block_comment, whitespace, word_break};
 
-use {TokenTree, TokenNode, Delimiter, Spacing};
+use {Delimiter, Group, Op, Spacing, TokenTree};
 
 #[derive(Clone, Debug)]
 pub struct TokenStream {
     inner: Vec<TokenTree>,
 }
 
 #[derive(Debug)]
 pub struct LexError;
@@ -46,110 +45,109 @@ fn get_cursor(src: &str) -> Cursor {
             rest: src,
             off: span.lo,
         }
     })
 }
 
 #[cfg(not(procmacro2_semver_exempt))]
 fn get_cursor(src: &str) -> Cursor {
-    Cursor {
-        rest: src,
-    }
+    Cursor { rest: src }
 }
 
 impl FromStr for TokenStream {
     type Err = LexError;
 
     fn from_str(src: &str) -> Result<TokenStream, LexError> {
         // Create a dummy file & add it to the codemap
         let cursor = get_cursor(src);
 
         match token_stream(cursor) {
             Ok((input, output)) => {
                 if skip_whitespace(input).len() != 0 {
                     Err(LexError)
                 } else {
-                    Ok(output.0)
+                    Ok(output.inner)
                 }
             }
             Err(LexError) => Err(LexError),
         }
     }
 }
 
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut joint = false;
         for (i, tt) in self.inner.iter().enumerate() {
             if i != 0 && !joint {
                 write!(f, " ")?;
             }
             joint = false;
-            match tt.kind {
-                TokenNode::Group(delim, ref stream) => {
-                    let (start, end) = match delim {
+            match *tt {
+                TokenTree::Group(ref tt) => {
+                    let (start, end) = match tt.delimiter() {
                         Delimiter::Parenthesis => ("(", ")"),
                         Delimiter::Brace => ("{", "}"),
                         Delimiter::Bracket => ("[", "]"),
                         Delimiter::None => ("", ""),
                     };
-                    if stream.0.inner.len() == 0 {
+                    if tt.stream().inner.inner.len() == 0 {
                         write!(f, "{} {}", start, end)?
                     } else {
-                        write!(f, "{} {} {}", start, stream, end)?
+                        write!(f, "{} {} {}", start, tt.stream(), end)?
                     }
                 }
-                TokenNode::Term(ref sym) => write!(f, "{}", sym.as_str())?,
-                TokenNode::Op(ch, ref op) => {
-                    write!(f, "{}", ch)?;
-                    match *op {
+                TokenTree::Term(ref tt) => write!(f, "{}", tt.as_str())?,
+                TokenTree::Op(ref tt) => {
+                    write!(f, "{}", tt.op())?;
+                    match tt.spacing() {
                         Spacing::Alone => {}
                         Spacing::Joint => joint = true,
                     }
                 }
-                TokenNode::Literal(ref literal) => {
-                    write!(f, "{}", literal)?;
-                    // handle comments
-                    if (literal.0).0.starts_with("/") {
-                        write!(f, "\n")?;
-                    }
-                }
+                TokenTree::Literal(ref tt) => write!(f, "{}", tt)?,
             }
         }
 
         Ok(())
     }
 }
 
-impl From<proc_macro::TokenStream> for TokenStream {
-    fn from(inner: proc_macro::TokenStream) -> TokenStream {
-        inner.to_string().parse().expect("compiler token stream parse failed")
+#[cfg(feature = "proc-macro")]
+impl From<::proc_macro::TokenStream> for TokenStream {
+    fn from(inner: ::proc_macro::TokenStream) -> TokenStream {
+        inner
+            .to_string()
+            .parse()
+            .expect("compiler token stream parse failed")
     }
 }
 
-impl From<TokenStream> for proc_macro::TokenStream {
-    fn from(inner: TokenStream) -> proc_macro::TokenStream {
-        inner.to_string().parse().expect("failed to parse to compiler tokens")
+#[cfg(feature = "proc-macro")]
+impl From<TokenStream> for ::proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> ::proc_macro::TokenStream {
+        inner
+            .to_string()
+            .parse()
+            .expect("failed to parse to compiler tokens")
     }
 }
 
-
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
         TokenStream { inner: vec![tree] }
     }
 }
 
-impl iter::FromIterator<TokenStream> for TokenStream {
-    fn from_iter<I: IntoIterator<Item=TokenStream>>(streams: I) -> Self {
+impl iter::FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
         let mut v = Vec::new();
 
-        for stream in streams.into_iter() {
-            v.extend(stream.inner);
+        for token in streams.into_iter() {
+            v.push(token);
         }
 
         TokenStream { inner: v }
     }
 }
 
 pub type TokenTreeIter = vec::IntoIter<TokenTree>;
 
@@ -234,36 +232,39 @@ struct FileInfo {
     name: String,
     span: Span,
     lines: Vec<usize>,
 }
 
 #[cfg(procmacro2_semver_exempt)]
 impl FileInfo {
     fn offset_line_column(&self, offset: usize) -> LineColumn {
-        assert!(self.span_within(Span { lo: offset as u32, hi: offset as u32 }));
+        assert!(self.span_within(Span {
+            lo: offset as u32,
+            hi: offset as u32
+        }));
         let offset = offset - self.span.lo as usize;
         match self.lines.binary_search(&offset) {
             Ok(found) => LineColumn {
                 line: found + 1,
-                column: 0
+                column: 0,
             },
             Err(idx) => LineColumn {
                 line: idx,
-                column: offset - self.lines[idx - 1]
+                column: offset - self.lines[idx - 1],
             },
         }
     }
 
     fn span_within(&self, span: Span) -> bool {
         span.lo >= self.span.lo && span.hi <= self.span.hi
     }
 }
 
-/// Computes the offsets of each line in the given source string.
+/// Computesthe offsets of each line in the given source string.
 #[cfg(procmacro2_semver_exempt)]
 fn lines_offsets(s: &str) -> Vec<usize> {
     let mut lines = vec![0];
     let mut prev = 0;
     while let Some(len) = s[prev..].find('\n') {
         prev += len + 1;
         lines.push(prev);
     }
@@ -284,17 +285,20 @@ impl Codemap {
         // with a dummy file.
         self.files.last().unwrap().span.hi + 1
     }
 
     fn add_file(&mut self, name: &str, src: &str) -> Span {
         let lines = lines_offsets(src);
         let lo = self.next_start_pos();
         // XXX(nika): Shouild we bother doing a checked cast or checked add here?
-        let span = Span { lo: lo, hi: lo + (src.len() as u32) };
+        let span = Span {
+            lo: lo,
+            hi: lo + (src.len() as u32),
+        };
 
         self.files.push(FileInfo {
             name: name.to_owned(),
             span: span,
             lines: lines,
         });
 
         span
@@ -305,17 +309,17 @@ impl Codemap {
             if file.span_within(span) {
                 return file;
             }
         }
         panic!("Invalid span with no related FileInfo!");
     }
 }
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct Span {
     #[cfg(procmacro2_semver_exempt)]
     lo: u32,
     #[cfg(procmacro2_semver_exempt)]
     hi: u32,
 }
 
 impl Span {
@@ -387,38 +391,44 @@ impl Span {
             })
         })
     }
 }
 
 #[derive(Copy, Clone)]
 pub struct Term {
     intern: usize,
-    not_send_sync: PhantomData<*const ()>,
+    span: Span,
 }
 
 thread_local!(static SYMBOLS: RefCell<Interner> = RefCell::new(Interner::new()));
 
 impl Term {
-    pub fn intern(string: &str) -> Term {
+    pub fn new(string: &str, span: Span) -> Term {
         Term {
             intern: SYMBOLS.with(|s| s.borrow_mut().intern(string)),
-            not_send_sync: PhantomData,
+            span: span,
         }
     }
 
     pub fn as_str(&self) -> &str {
         SYMBOLS.with(|interner| {
             let interner = interner.borrow();
             let s = interner.get(self.intern);
-            unsafe {
-                &*(s as *const str)
-            }
+            unsafe { &*(s as *const str) }
         })
     }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
 }
 
 impl fmt::Debug for Term {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("Term").field(&self.as_str()).finish()
     }
 }
 
@@ -439,272 +449,297 @@ impl Borrow<str> for MyRc {
 impl Interner {
     fn new() -> Interner {
         Interner {
             string_to_index: HashMap::new(),
             index_to_string: Vec::new(),
         }
     }
 
-   fn intern(&mut self, s: &str) -> usize {
+    fn intern(&mut self, s: &str) -> usize {
         if let Some(&idx) = self.string_to_index.get(s) {
-            return idx
+            return idx;
         }
         let s = Rc::new(s.to_string());
         self.index_to_string.push(s.clone());
-        self.string_to_index.insert(MyRc(s), self.index_to_string.len() - 1);
+        self.string_to_index
+            .insert(MyRc(s), self.index_to_string.len() - 1);
         self.index_to_string.len() - 1
     }
 
-   fn get(&self, idx: usize) -> &str {
-       &self.index_to_string[idx]
-   }
+    fn get(&self, idx: usize) -> &str {
+        &self.index_to_string[idx]
+    }
 }
 
 #[derive(Clone, Debug)]
-pub struct Literal(String);
+pub struct Literal {
+    text: String,
+    span: Span,
+}
+
+macro_rules! suffixed_numbers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(format!(concat!("{}", stringify!($kind)), n))
+        }
+    )*)
+}
+
+macro_rules! unsuffixed_numbers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(n.to_string())
+        }
+    )*)
+}
 
 impl Literal {
-    pub fn byte_char(byte: u8) -> Literal {
-        match byte {
-            0 => Literal(format!("b'\\0'")),
-            b'\"' => Literal(format!("b'\"'")),
-            n => {
-                let mut escaped = "b'".to_string();
-                escaped.extend(ascii::escape_default(n).map(|c| c as char));
-                escaped.push('\'');
-                Literal(escaped)
-            }
+    fn _new(text: String) -> Literal {
+        Literal {
+            text: text,
+            span: Span::call_site(),
         }
     }
 
+    suffixed_numbers! {
+        u8_suffixed => u8,
+        u16_suffixed => u16,
+        u32_suffixed => u32,
+        u64_suffixed => u64,
+        usize_suffixed => usize,
+        i8_suffixed => i8,
+        i16_suffixed => i16,
+        i32_suffixed => i32,
+        i64_suffixed => i64,
+        isize_suffixed => isize,
+
+        f32_suffixed => f32,
+        f64_suffixed => f64,
+    }
+
+    unsuffixed_numbers! {
+        u8_unsuffixed => u8,
+        u16_unsuffixed => u16,
+        u32_unsuffixed => u32,
+        u64_unsuffixed => u64,
+        usize_unsuffixed => usize,
+        i8_unsuffixed => i8,
+        i16_unsuffixed => i16,
+        i32_unsuffixed => i32,
+        i64_unsuffixed => i64,
+        isize_unsuffixed => isize,
+    }
+
+    pub fn f32_unsuffixed(f: f32) -> Literal {
+        let mut s = f.to_string();
+        if !s.contains(".") {
+            s.push_str(".0");
+        }
+        Literal::_new(s)
+    }
+
+    pub fn f64_unsuffixed(f: f64) -> Literal {
+        let mut s = f.to_string();
+        if !s.contains(".") {
+            s.push_str(".0");
+        }
+        Literal::_new(s)
+    }
+
+    pub fn string(t: &str) -> Literal {
+        let mut s = t.chars()
+            .flat_map(|c| c.escape_default())
+            .collect::<String>();
+        s.push('"');
+        s.insert(0, '"');
+        Literal::_new(s)
+    }
+
+    pub fn character(t: char) -> Literal {
+        Literal::_new(format!("'{}'", t.escape_default().collect::<String>()))
+    }
+
     pub fn byte_string(bytes: &[u8]) -> Literal {
         let mut escaped = "b\"".to_string();
         for b in bytes {
             match *b {
                 b'\0' => escaped.push_str(r"\0"),
                 b'\t' => escaped.push_str(r"\t"),
                 b'\n' => escaped.push_str(r"\n"),
                 b'\r' => escaped.push_str(r"\r"),
                 b'"' => escaped.push_str("\\\""),
                 b'\\' => escaped.push_str("\\\\"),
-                b'\x20' ... b'\x7E' => escaped.push(*b as char),
+                b'\x20'...b'\x7E' => escaped.push(*b as char),
                 _ => escaped.push_str(&format!("\\x{:02X}", b)),
             }
         }
         escaped.push('"');
-        Literal(escaped)
+        Literal::_new(escaped)
     }
 
-    pub fn doccomment(s: &str) -> Literal {
-        Literal(s.to_string())
+    pub fn span(&self) -> Span {
+        self.span
     }
 
-    pub fn float(n: f64) -> Literal {
-        if !n.is_finite() {
-            panic!("Invalid float literal {}", n);
-        }
-        let mut s = n.to_string();
-        if !s.contains('.') {
-            s += ".0";
-        }
-        Literal(s)
-    }
-
-    pub fn integer(s: i64) -> Literal {
-        Literal(s.to_string())
-    }
-
-    pub fn raw_string(s: &str, pounds: usize) -> Literal {
-        let mut ret = format!("r");
-        ret.extend((0..pounds).map(|_| "#"));
-        ret.push('"');
-        ret.push_str(s);
-        ret.push('"');
-        ret.extend((0..pounds).map(|_| "#"));
-        Literal(ret)
-    }
-
-    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
-        let mut ret = format!("br");
-        ret.extend((0..pounds).map(|_| "#"));
-        ret.push('"');
-        ret.push_str(s);
-        ret.push('"');
-        ret.extend((0..pounds).map(|_| "#"));
-        Literal(ret)
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
     }
 }
 
 impl fmt::Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        self.text.fmt(f)
     }
 }
 
-macro_rules! ints {
-    ($($t:ty,)*) => {$(
-        impl From<$t> for Literal {
-            fn from(t: $t) -> Literal {
-                Literal(format!(concat!("{}", stringify!($t)), t))
-            }
+fn token_stream(mut input: Cursor) -> PResult<::TokenStream> {
+    let mut trees = Vec::new();
+    loop {
+        let input_no_ws = skip_whitespace(input);
+        if input_no_ws.rest.len() == 0 {
+            break
         }
-    )*}
-}
-
-ints! {
-    u8, u16, u32, u64, usize,
-    i8, i16, i32, i64, isize,
-}
-
-macro_rules! floats {
-    ($($t:ty,)*) => {$(
-        impl From<$t> for Literal {
-            fn from(t: $t) -> Literal {
-                assert!(!t.is_nan());
-                assert!(!t.is_infinite());
-                Literal(format!(concat!("{}", stringify!($t)), t))
-            }
+        if let Ok((a, tokens)) = doc_comment(input_no_ws) {
+            input = a;
+            trees.extend(tokens);
+            continue
         }
-    )*}
-}
-
-floats! {
-    f32, f64,
-}
 
-impl<'a> From<&'a str> for Literal {
-    fn from(t: &'a str) -> Literal {
-        let mut s = t.chars().flat_map(|c| c.escape_default()).collect::<String>();
-        s.push('"');
-        s.insert(0, '"');
-        Literal(s)
-    }
-}
-
-impl From<char> for Literal {
-    fn from(t: char) -> Literal {
-        Literal(format!("'{}'", t.escape_default().collect::<String>()))
+        let (a, tt) = match token_tree(input_no_ws) {
+            Ok(p) => p,
+            Err(_) => break,
+        };
+        trees.push(tt);
+        input = a;
     }
+    Ok((input, ::TokenStream::_new(TokenStream { inner: trees })))
 }
 
-named!(token_stream -> ::TokenStream, map!(
-    many0!(token_tree),
-    |trees| ::TokenStream(TokenStream { inner: trees })
-));
-
 #[cfg(not(procmacro2_semver_exempt))]
-fn token_tree(input: Cursor) -> PResult<TokenTree> {
-    let (input, kind) = token_kind(input)?;
-    Ok((input, TokenTree {
-        span: ::Span(Span {}),
-        kind: kind,
-    }))
+fn spanned<'a, T>(
+    input: Cursor<'a>,
+    f: fn(Cursor<'a>) -> PResult<'a, T>,
+) -> PResult<'a, (T, ::Span)> {
+    let (a, b) = f(skip_whitespace(input))?;
+    Ok((a, ((b, ::Span::_new(Span { })))))
 }
 
 #[cfg(procmacro2_semver_exempt)]
-fn token_tree(input: Cursor) -> PResult<TokenTree> {
+fn spanned<'a, T>(
+    input: Cursor<'a>,
+    f: fn(Cursor<'a>) -> PResult<'a, T>,
+) -> PResult<'a, (T, ::Span)> {
     let input = skip_whitespace(input);
     let lo = input.off;
-    let (input, kind) = token_kind(input)?;
-    let hi = input.off;
-    Ok((input, TokenTree {
-        span: ::Span(Span {
-            lo: lo,
-            hi: hi,
-        }),
-        kind: kind,
-    }))
+    let (a, b) = f(input)?;
+    let hi = a.off;
+    let span = ::Span::_new(Span { lo: lo, hi: hi });
+    Ok((a, (b, span)))
+}
+
+fn token_tree(input: Cursor) -> PResult<TokenTree> {
+    let (rest, (mut tt, span)) = spanned(input, token_kind)?;
+    tt.set_span(span);
+    Ok((rest, tt))
 }
 
-named!(token_kind -> TokenNode, alt!(
-    map!(delimited, |(d, s)| TokenNode::Group(d, s))
+named!(token_kind -> TokenTree, alt!(
+    map!(group, TokenTree::Group)
     |
-    map!(literal, TokenNode::Literal) // must be before symbol
+    map!(literal, TokenTree::Literal) // must be before symbol
     |
     symbol
     |
-    map!(op, |(op, kind)| TokenNode::Op(op, kind))
+    map!(op, TokenTree::Op)
 ));
 
-named!(delimited -> (Delimiter, ::TokenStream), alt!(
+named!(group -> Group, alt!(
     delimited!(
         punct!("("),
         token_stream,
         punct!(")")
-    ) => { |ts| (Delimiter::Parenthesis, ts) }
+    ) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
     |
     delimited!(
         punct!("["),
         token_stream,
         punct!("]")
-    ) => { |ts| (Delimiter::Bracket, ts) }
+    ) => { |ts| Group::new(Delimiter::Bracket, ts) }
     |
     delimited!(
         punct!("{"),
         token_stream,
         punct!("}")
-    ) => { |ts| (Delimiter::Brace, ts) }
+    ) => { |ts| Group::new(Delimiter::Brace, ts) }
 ));
 
-fn symbol(mut input: Cursor) -> PResult<TokenNode> {
+fn symbol(mut input: Cursor) -> PResult<TokenTree> {
     input = skip_whitespace(input);
 
     let mut chars = input.char_indices();
 
     let lifetime = input.starts_with("'");
     if lifetime {
         chars.next();
     }
 
+    let raw = !lifetime && input.starts_with("r#");
+    if raw {
+        chars.next();
+        chars.next();
+    }
+
     match chars.next() {
         Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
         _ => return Err(LexError),
     }
 
     let mut end = input.len();
     for (i, ch) in chars {
         if !UnicodeXID::is_xid_continue(ch) {
             end = i;
             break;
         }
     }
 
-    if lifetime && &input.rest[..end] != "'static" && KEYWORDS.contains(&&input.rest[1..end]) {
+    let a = &input.rest[..end];
+    if a == "r#_" || lifetime && a != "'static" && KEYWORDS.contains(&&a[1..]) {
         Err(LexError)
+    } else if a == "_" {
+        Ok((input.advance(end), Op::new('_', Spacing::Alone).into()))
     } else {
-        let a = &input.rest[..end];
-        if a == "_" {
-            Ok((input.advance(end), TokenNode::Op('_', Spacing::Alone)))
-        } else {
-            Ok((input.advance(end), TokenNode::Term(::Term::intern(a))))
-        }
+        Ok((
+            input.advance(end),
+            ::Term::new(a, ::Span::call_site()).into(),
+        ))
     }
 }
 
 // From https://github.com/rust-lang/rust/blob/master/src/libsyntax_pos/symbol.rs
 static KEYWORDS: &'static [&'static str] = &[
-    "abstract", "alignof", "as", "become", "box", "break", "const", "continue",
-    "crate", "do", "else", "enum", "extern", "false", "final", "fn", "for",
-    "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut",
-    "offsetof", "override", "priv", "proc", "pub", "pure", "ref", "return",
-    "self", "Self", "sizeof", "static", "struct", "super", "trait", "true",
-    "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while",
-    "yield",
+    "abstract", "alignof", "as", "become", "box", "break", "const", "continue", "crate", "do",
+    "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl", "in", "let", "loop",
+    "macro", "match", "mod", "move", "mut", "offsetof", "override", "priv", "proc", "pub", "pure",
+    "ref", "return", "self", "Self", "sizeof", "static", "struct", "super", "trait", "true",
+    "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
 ];
 
 fn literal(input: Cursor) -> PResult<::Literal> {
     let input_no_ws = skip_whitespace(input);
 
     match literal_nocapture(input_no_ws) {
         Ok((a, ())) => {
             let start = input.len() - input_no_ws.len();
             let len = input_no_ws.len() - a.len();
             let end = start + len;
-            Ok((a, ::Literal(Literal(input.rest[start..end].to_string()))))
+            Ok((
+                a,
+                ::Literal::_new(Literal::_new(input.rest[start..end].to_string())),
+            ))
         }
         Err(LexError) => Err(LexError),
     }
 }
 
 named!(literal_nocapture -> (), alt!(
     string
     |
@@ -712,18 +747,16 @@ named!(literal_nocapture -> (), alt!(
     |
     byte
     |
     character
     |
     float
     |
     int
-    |
-    doc_comment
 ));
 
 named!(string -> (), alt!(
     quoted_string
     |
     preceded!(
         punct!("r"),
         raw_string
@@ -745,47 +778,40 @@ fn cooked_string(input: Cursor) -> PResult<()> {
             }
             '\r' => {
                 if let Some((_, '\n')) = chars.next() {
                     // ...
                 } else {
                     break;
                 }
             }
-            '\\' => {
-                match chars.next() {
-                    Some((_, 'x')) => {
-                        if !backslash_x_char(&mut chars) {
-                            break
-                        }
+            '\\' => match chars.next() {
+                Some((_, 'x')) => {
+                    if !backslash_x_char(&mut chars) {
+                        break;
                     }
-                    Some((_, 'n')) |
-                    Some((_, 'r')) |
-                    Some((_, 't')) |
-                    Some((_, '\\')) |
-                    Some((_, '\'')) |
-                    Some((_, '"')) |
-                    Some((_, '0')) => {}
-                    Some((_, 'u')) => {
-                        if !backslash_u(&mut chars) {
-                            break
-                        }
+                }
+                Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
+                | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
+                Some((_, 'u')) => {
+                    if !backslash_u(&mut chars) {
+                        break;
                     }
-                    Some((_, '\n')) | Some((_, '\r')) => {
-                        while let Some(&(_, ch)) = chars.peek() {
-                            if ch.is_whitespace() {
-                                chars.next();
-                            } else {
-                                break;
-                            }
+                }
+                Some((_, '\n')) | Some((_, '\r')) => {
+                    while let Some(&(_, ch)) = chars.peek() {
+                        if ch.is_whitespace() {
+                            chars.next();
+                        } else {
+                            break;
                         }
                     }
-                    _ => break,
                 }
-            }
+                _ => break,
+            },
             _ch => {}
         }
     }
     Err(LexError)
 }
 
 named!(byte_string -> (), alt!(
     delimited!(
@@ -809,45 +835,37 @@ fn cooked_byte_string(mut input: Cursor) -> PResult<()> {
             }
             b'\r' => {
                 if let Some((_, b'\n')) = bytes.next() {
                     // ...
                 } else {
                     break;
                 }
             }
-            b'\\' => {
-                match bytes.next() {
-                    Some((_, b'x')) => {
-                        if !backslash_x_byte(&mut bytes) {
-                            break
-                        }
+            b'\\' => match bytes.next() {
+                Some((_, b'x')) => {
+                    if !backslash_x_byte(&mut bytes) {
+                        break;
                     }
-                    Some((_, b'n')) |
-                    Some((_, b'r')) |
-                    Some((_, b't')) |
-                    Some((_, b'\\')) |
-                    Some((_, b'0')) |
-                    Some((_, b'\'')) |
-                    Some((_, b'"'))  => {}
-                    Some((newline, b'\n')) |
-                    Some((newline, b'\r')) => {
-                        let rest = input.advance(newline + 1);
-                        for (offset, ch) in rest.char_indices() {
-                            if !ch.is_whitespace() {
-                                input = rest.advance(offset);
-                                bytes = input.bytes().enumerate();
-                                continue 'outer;
-                            }
+                }
+                Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
+                | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
+                Some((newline, b'\n')) | Some((newline, b'\r')) => {
+                    let rest = input.advance(newline + 1);
+                    for (offset, ch) in rest.char_indices() {
+                        if !ch.is_whitespace() {
+                            input = rest.advance(offset);
+                            bytes = input.bytes().enumerate();
+                            continue 'outer;
                         }
-                        break;
                     }
-                    _ => break,
+                    break;
                 }
-            }
+                _ => break,
+            },
             b if b < 0x80 => {}
             _ => break,
         }
     }
     Err(LexError)
 }
 
 fn raw_string(input: Cursor) -> PResult<()> {
@@ -862,17 +880,17 @@ fn raw_string(input: Cursor) -> PResult<()> {
             '#' => {}
             _ => return Err(LexError),
         }
     }
     for (byte_offset, ch) in chars {
         match ch {
             '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => {
                 let rest = input.advance(byte_offset + 1 + n);
-                return Ok((rest, ()))
+                return Ok((rest, ()));
             }
             '\r' => {}
             _ => {}
         }
     }
     Err(LexError)
 }
 
@@ -882,29 +900,22 @@ named!(byte -> (), do_parse!(
     cooked_byte >>
     tag!("'") >>
     (())
 ));
 
 fn cooked_byte(input: Cursor) -> PResult<()> {
     let mut bytes = input.bytes().enumerate();
     let ok = match bytes.next().map(|(_, b)| b) {
-        Some(b'\\') => {
-            match bytes.next().map(|(_, b)| b) {
-                Some(b'x') => backslash_x_byte(&mut bytes),
-                Some(b'n') |
-                Some(b'r') |
-                Some(b't') |
-                Some(b'\\') |
-                Some(b'0') |
-                Some(b'\'') |
-                Some(b'"') => true,
-                _ => false,
-            }
-        }
+        Some(b'\\') => match bytes.next().map(|(_, b)| b) {
+            Some(b'x') => backslash_x_byte(&mut bytes),
+            Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
+            | Some(b'"') => true,
+            _ => false,
+        },
         b => b.is_some(),
     };
     if ok {
         match bytes.next() {
             Some((offset, _)) => {
                 if input.chars().as_str().is_char_boundary(offset) {
                     Ok((input.advance(offset), ()))
                 } else {
@@ -923,30 +934,24 @@ named!(character -> (), do_parse!(
     cooked_char >>
     tag!("'") >>
     (())
 ));
 
 fn cooked_char(input: Cursor) -> PResult<()> {
     let mut chars = input.char_indices();
     let ok = match chars.next().map(|(_, ch)| ch) {
-        Some('\\') => {
-            match chars.next().map(|(_, ch)| ch) {
-                Some('x') => backslash_x_char(&mut chars),
-                Some('u') => backslash_u(&mut chars),
-                Some('n') |
-                Some('r') |
-                Some('t') |
-                Some('\\') |
-                Some('0') |
-                Some('\'') |
-                Some('"') => true,
-                _ => false,
+        Some('\\') => match chars.next().map(|(_, ch)| ch) {
+            Some('x') => backslash_x_char(&mut chars),
+            Some('u') => backslash_u(&mut chars),
+            Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
+                true
             }
-        }
+            _ => false,
+        },
         ch => ch.is_some(),
     };
     if ok {
         match chars.next() {
             Some((idx, _)) => Ok((input.advance(idx), ())),
             None => Ok((input.advance(input.len()), ())),
         }
     } else {
@@ -962,33 +967,36 @@ macro_rules! next_ch {
                 _ => return false,
             },
             None => return false
         }
     };
 }
 
 fn backslash_x_char<I>(chars: &mut I) -> bool
-    where I: Iterator<Item = (usize, char)>
+where
+    I: Iterator<Item = (usize, char)>,
 {
     next_ch!(chars @ '0'...'7');
     next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
     true
 }
 
 fn backslash_x_byte<I>(chars: &mut I) -> bool
-    where I: Iterator<Item = (usize, u8)>
+where
+    I: Iterator<Item = (usize, u8)>,
 {
     next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
     next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
     true
 }
 
 fn backslash_u<I>(chars: &mut I) -> bool
-    where I: Iterator<Item = (usize, char)>
+where
+    I: Iterator<Item = (usize, char)>,
 {
     next_ch!(chars @ '{');
     next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
     loop {
         let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '_' | '}');
         if c == '}' {
             return true;
         }
@@ -1021,19 +1029,21 @@ fn float_digits(input: Cursor) -> PResult<()> {
                 chars.next();
                 len += 1;
             }
             '.' => {
                 if has_dot {
                     break;
                 }
                 chars.next();
-                if chars.peek()
-                       .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
-                       .unwrap_or(false) {
+                if chars
+                    .peek()
+                    .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
+                    .unwrap_or(false)
+                {
                     return Err(LexError);
                 }
                 len += 1;
                 has_dot = true;
             }
             'e' | 'E' => {
                 chars.next();
                 len += 1;
@@ -1078,28 +1088,17 @@ fn float_digits(input: Cursor) -> PResult<()> {
     }
 
     Ok((input.advance(len), ()))
 }
 
 fn int(input: Cursor) -> PResult<()> {
     let (rest, ()) = digits(input)?;
     for suffix in &[
-        "isize",
-        "i8",
-        "i16",
-        "i32",
-        "i64",
-        "i128",
-        "usize",
-        "u8",
-        "u16",
-        "u32",
-        "u64",
-        "u128",
+        "isize", "i8", "i16", "i32", "i64", "i128", "usize", "u8", "u16", "u32", "u64", "u128"
     ] {
         if rest.starts_with(suffix) {
             return word_break(rest.advance(suffix.len()));
         }
     }
     word_break(rest)
 }
 
@@ -1141,25 +1140,25 @@ fn digits(mut input: Cursor) -> PResult<()> {
     }
     if empty {
         Err(LexError)
     } else {
         Ok((input.advance(len), ()))
     }
 }
 
-fn op(input: Cursor) -> PResult<(char, Spacing)> {
+fn op(input: Cursor) -> PResult<Op> {
     let input = skip_whitespace(input);
     match op_char(input) {
         Ok((rest, ch)) => {
             let kind = match op_char(rest) {
                 Ok(_) => Spacing::Joint,
                 Err(LexError) => Spacing::Alone,
             };
-            Ok((rest, (ch, kind)))
+            Ok((rest, Op::new(ch, kind)))
         }
         Err(LexError) => Err(LexError),
     }
 }
 
 fn op_char(input: Cursor) -> PResult<char> {
     let mut chars = input.chars();
     let first = match chars.next() {
@@ -1171,36 +1170,58 @@ fn op_char(input: Cursor) -> PResult<char> {
     let recognized = "~!@#$%^&*-=+|;:,<.>/?";
     if recognized.contains(first) {
         Ok((input.advance(first.len_utf8()), first))
     } else {
         Err(LexError)
     }
 }
 
-named!(doc_comment -> (), alt!(
+fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> {
+    let mut trees = Vec::new();
+    let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?;
+    trees.push(TokenTree::Op(Op::new('#', Spacing::Alone)));
+    if inner {
+        trees.push(Op::new('!', Spacing::Alone).into());
+    }
+    let mut stream = vec![
+        TokenTree::Term(::Term::new("doc", span)),
+        TokenTree::Op(Op::new('=', Spacing::Alone)),
+        TokenTree::Literal(::Literal::string(comment)),
+    ];
+    for tt in stream.iter_mut() {
+        tt.set_span(span);
+    }
+    trees.push(Group::new(Delimiter::Bracket, stream.into_iter().collect()).into());
+    for tt in trees.iter_mut() {
+        tt.set_span(span);
+    }
+    Ok((rest, trees))
+}
+
+named!(doc_comment_contents -> (&str, bool), alt!(
     do_parse!(
         punct!("//!") >>
-        take_until!("\n") >>
-        (())
+        s: take_until_newline_or_eof!() >>
+        ((s, true))
     )
     |
     do_parse!(
         option!(whitespace) >>
         peek!(tag!("/*!")) >>
-        block_comment >>
-        (())
+        s: block_comment >>
+        ((s, true))
     )
     |
     do_parse!(
         punct!("///") >>
         not!(tag!("/")) >>
-        take_until!("\n") >>
-        (())
+        s: take_until_newline_or_eof!() >>
+        ((s, false))
     )
     |
     do_parse!(
         option!(whitespace) >>
         peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
-        block_comment >>
-        (())
+        s: block_comment >>
+        ((s, false))
     )
 ));
diff --git a/third_party/rust/proc-macro2/src/strnom.rs b/third_party/rust/proc-macro2/src/strnom.rs
index 33964f45bda3..f5dd1456e632 100644
--- a/third_party/rust/proc-macro2/src/strnom.rs
+++ b/third_party/rust/proc-macro2/src/strnom.rs
@@ -1,11 +1,11 @@
 //! Adapted from [`nom`](https://github.com/Geal/nom).
 
-use std::str::{Chars, CharIndices, Bytes};
+use std::str::{Bytes, CharIndices, Chars};
 
 use unicode_xid::UnicodeXID;
 
 use imp::LexError;
 
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Cursor<'a> {
     pub rest: &'a str,
@@ -68,28 +68,30 @@ pub fn whitespace(input: Cursor) -> PResult<()> {
         return Err(LexError);
     }
 
     let bytes = input.as_bytes();
     let mut i = 0;
     while i < bytes.len() {
         let s = input.advance(i);
         if bytes[i] == b'/' {
-            if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) &&
-               !s.starts_with("//!") {
+            if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////"))
+                && !s.starts_with("//!")
+            {
                 if let Some(len) = s.find('\n') {
                     i += len + 1;
                     continue;
                 }
                 break;
             } else if s.starts_with("/**/") {
                 i += 4;
-                continue
-            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) &&
-                      !s.starts_with("/*!") {
+                continue;
+            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***"))
+                && !s.starts_with("/*!")
+            {
                 let (_, com) = block_comment(s)?;
                 i += com.len();
                 continue;
             }
         }
         match bytes[i] {
             b' ' | 0x09...0x0d => {
                 i += 1;
@@ -99,21 +101,17 @@ pub fn whitespace(input: Cursor) -> PResult<()> {
             _ => {
                 let ch = s.chars().next().unwrap();
                 if is_whitespace(ch) {
                     i += ch.len_utf8();
                     continue;
                 }
             }
         }
-        return if i > 0 {
-            Ok((s, ()))
-        } else {
-            Err(LexError)
-        };
+        return if i > 0 { Ok((s, ())) } else { Err(LexError) };
     }
     Ok((input.advance(input.len()), ()))
 }
 
 pub fn block_comment(input: Cursor) -> PResult<&str> {
     if !input.starts_with("/*") {
         return Err(LexError);
     }
@@ -258,44 +256,24 @@ macro_rules! option {
     ($i:expr, $f:expr) => {
         match $f($i) {
             Ok((i, o)) => Ok((i, Some(o))),
             Err(LexError) => Ok(($i, None)),
         }
     };
 }
 
-macro_rules! take_until {
-    ($i:expr, $substr:expr) => {{
-        if $substr.len() > $i.len() {
-            Err(LexError)
+macro_rules! take_until_newline_or_eof {
+    ($i:expr,) => {{
+        if $i.len() == 0 {
+            Ok(($i, ""))
         } else {
-            let substr_vec: Vec<char> = $substr.chars().collect();
-            let mut window: Vec<char> = vec![];
-            let mut offset = $i.len();
-            let mut parsed = false;
-            for (o, c) in $i.char_indices() {
-                window.push(c);
-                if window.len() > substr_vec.len() {
-                    window.remove(0);
-                }
-                if window == substr_vec {
-                    parsed = true;
-                    window.pop();
-                    let window_len: usize = window.iter()
-                        .map(|x| x.len_utf8())
-                        .fold(0, |x, y| x + y);
-                    offset = o - window_len;
-                    break;
-                }
-            }
-            if parsed {
-                Ok(($i.advance(offset), &$i.rest[..offset]))
-            } else {
-                Err(LexError)
+            match $i.find('\n') {
+                Some(i) => Ok(($i.advance(i), &$i.rest[..i])),
+                None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])),
             }
         }
     }};
 }
 
 macro_rules! tuple {
     ($i:expr, $($rest:tt)*) => {
         tuple_parser!($i, (), $($rest)*)
@@ -406,42 +384,8 @@ macro_rules! map {
             Ok((i, o)) => Ok((i, call!(o, $g)))
         }
     };
 
     ($i:expr, $f:expr, $g:expr) => {
         map!($i, call!($f), $g)
     };
 }
-
-macro_rules! many0 {
-    ($i:expr, $f:expr) => {{
-        let ret;
-        let mut res   = ::std::vec::Vec::new();
-        let mut input = $i;
-
-        loop {
-            if input.is_empty() {
-                ret = Ok((input, res));
-                break;
-            }
-
-            match $f(input) {
-                Err(LexError) => {
-                    ret = Ok((input, res));
-                    break;
-                }
-                Ok((i, o)) => {
-                    // loop trip must always consume (otherwise infinite loops)
-                    if i.len() == input.len() {
-                        ret = Err(LexError);
-                        break;
-                    }
-
-                    res.push(o);
-                    input = i;
-                }
-            }
-        }
-
-        ret
-    }};
-}
diff --git a/third_party/rust/proc-macro2/src/unstable.rs b/third_party/rust/proc-macro2/src/unstable.rs
index 1a2508386291..d913df48c94a 100644
--- a/third_party/rust/proc-macro2/src/unstable.rs
+++ b/third_party/rust/proc-macro2/src/unstable.rs
@@ -1,16 +1,17 @@
-use std::ascii;
+#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
+
 use std::fmt;
 use std::iter;
 use std::str::FromStr;
 
 use proc_macro;
 
-use {TokenTree, TokenNode, Delimiter, Spacing};
+use {Delimiter, Group, Op, Spacing, TokenTree};
 
 #[derive(Clone)]
 pub struct TokenStream(proc_macro::TokenStream);
 
 pub struct LexError(proc_macro::LexError);
 
 impl TokenStream {
     pub fn empty() -> TokenStream {
@@ -44,185 +45,181 @@ impl From<proc_macro::TokenStream> for TokenStream {
 
 impl From<TokenStream> for proc_macro::TokenStream {
     fn from(inner: TokenStream) -> proc_macro::TokenStream {
         inner.0
     }
 }
 
 impl From<TokenTree> for TokenStream {
-    fn from(tree: TokenTree) -> TokenStream {
-        TokenStream(proc_macro::TokenTree {
-            span: (tree.span.0).0,
-            kind: match tree.kind {
-                TokenNode::Group(delim, s) => {
-                    let delim = match delim {
-                        Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
-                        Delimiter::Bracket => proc_macro::Delimiter::Bracket,
-                        Delimiter::Brace => proc_macro::Delimiter::Brace,
-                        Delimiter::None => proc_macro::Delimiter::None,
-                    };
-                    proc_macro::TokenNode::Group(delim, (s.0).0)
-                }
-                TokenNode::Op(ch, kind) => {
-                    let kind = match kind {
-                        Spacing::Joint => proc_macro::Spacing::Joint,
-                        Spacing::Alone => proc_macro::Spacing::Alone,
-                    };
-                    proc_macro::TokenNode::Op(ch, kind)
-                }
-                TokenNode::Term(s) => {
-                    proc_macro::TokenNode::Term((s.0).0)
-                }
-                TokenNode::Literal(l) => {
-                    proc_macro::TokenNode::Literal((l.0).0)
-                }
-            },
-        }.into())
+    fn from(token: TokenTree) -> TokenStream {
+        let tt: proc_macro::TokenTree = match token {
+            TokenTree::Group(tt) => {
+                let delim = match tt.delimiter() {
+                    Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
+                    Delimiter::Bracket => proc_macro::Delimiter::Bracket,
+                    Delimiter::Brace => proc_macro::Delimiter::Brace,
+                    Delimiter::None => proc_macro::Delimiter::None,
+                };
+                let span = tt.span();
+                let mut group = proc_macro::Group::new(delim, tt.stream.inner.0);
+                group.set_span(span.inner.0);
+                group.into()
+            }
+            TokenTree::Op(tt) => {
+                let spacing = match tt.spacing() {
+                    Spacing::Joint => proc_macro::Spacing::Joint,
+                    Spacing::Alone => proc_macro::Spacing::Alone,
+                };
+                let mut op = proc_macro::Op::new(tt.op(), spacing);
+                op.set_span(tt.span().inner.0);
+                op.into()
+            }
+            TokenTree::Term(tt) => tt.inner.term.into(),
+            TokenTree::Literal(tt) => tt.inner.lit.into(),
+        };
+        TokenStream(tt.into())
     }
 }
 
-impl iter::FromIterator<TokenStream> for TokenStream {
-    fn from_iter<I: IntoIterator<Item=TokenStream>>(streams: I) -> Self {
-        let streams = streams.into_iter().map(|s| s.0);
+impl iter::FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
+        let streams = streams.into_iter().map(TokenStream::from)
+            .flat_map(|t| t.0);
         TokenStream(streams.collect::<proc_macro::TokenStream>())
     }
 }
 
 impl fmt::Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
 impl fmt::Debug for LexError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
-pub struct TokenTreeIter(proc_macro::TokenTreeIter);
+pub struct TokenTreeIter(proc_macro::token_stream::IntoIter);
 
 impl IntoIterator for TokenStream {
     type Item = TokenTree;
     type IntoIter = TokenTreeIter;
 
     fn into_iter(self) -> TokenTreeIter {
         TokenTreeIter(self.0.into_iter())
     }
 }
 
 impl Iterator for TokenTreeIter {
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
-        let token = match self.0.next() {
-            Some(n) => n,
-            None => return None,
-        };
-        Some(TokenTree {
-            span: ::Span(Span(token.span)),
-            kind: match token.kind {
-                proc_macro::TokenNode::Group(delim, s) => {
-                    let delim = match delim {
-                        proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
-                        proc_macro::Delimiter::Bracket => Delimiter::Bracket,
-                        proc_macro::Delimiter::Brace => Delimiter::Brace,
-                        proc_macro::Delimiter::None => Delimiter::None,
-                    };
-                    TokenNode::Group(delim, ::TokenStream(TokenStream(s)))
-                }
-                proc_macro::TokenNode::Op(ch, kind) => {
-                    let kind = match kind {
-                        proc_macro::Spacing::Joint => Spacing::Joint,
-                        proc_macro::Spacing::Alone => Spacing::Alone,
-                    };
-                    TokenNode::Op(ch, kind)
-                }
-                proc_macro::TokenNode::Term(s) => {
-                    TokenNode::Term(::Term(Term(s)))
-                }
-                proc_macro::TokenNode::Literal(l) => {
-                    TokenNode::Literal(::Literal(Literal(l)))
-                }
-            },
+        let token = self.0.next()?;
+        Some(match token {
+            proc_macro::TokenTree::Group(tt) => {
+                let delim = match tt.delimiter() {
+                    proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
+                    proc_macro::Delimiter::Bracket => Delimiter::Bracket,
+                    proc_macro::Delimiter::Brace => Delimiter::Brace,
+                    proc_macro::Delimiter::None => Delimiter::None,
+                };
+                let stream = ::TokenStream::_new(TokenStream(tt.stream()));
+                let mut g = Group::new(delim, stream);
+                g.set_span(::Span::_new(Span(tt.span())));
+                g.into()
+            }
+            proc_macro::TokenTree::Op(tt) => {
+                let spacing = match tt.spacing() {
+                    proc_macro::Spacing::Joint => Spacing::Joint,
+                    proc_macro::Spacing::Alone => Spacing::Alone,
+                };
+                let mut o = Op::new(tt.op(), spacing);
+                o.set_span(::Span::_new(Span(tt.span())));
+                o.into()
+            }
+            proc_macro::TokenTree::Term(s) => {
+                ::Term::_new(Term {
+                    term: s,
+                }).into()
+            }
+            proc_macro::TokenTree::Literal(l) => {
+                ::Literal::_new(Literal {
+                    lit: l,
+                }).into()
+            }
         })
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
 }
 
 impl fmt::Debug for TokenTreeIter {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("TokenTreeIter").finish()
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, PartialEq, Eq)]
 pub struct FileName(String);
 
-#[cfg(procmacro2_semver_exempt)]
 impl fmt::Display for FileName {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
 // NOTE: We have to generate our own filename object here because we can't wrap
 // the one provided by proc_macro.
-#[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, PartialEq, Eq)]
 pub struct SourceFile(proc_macro::SourceFile, FileName);
 
-#[cfg(procmacro2_semver_exempt)]
 impl SourceFile {
     fn new(sf: proc_macro::SourceFile) -> Self {
         let filename = FileName(sf.path().to_string());
         SourceFile(sf, filename)
     }
 
     /// Get the path to this source file as a string.
     pub fn path(&self) -> &FileName {
         &self.1
     }
 
     pub fn is_real(&self) -> bool {
         self.0.is_real()
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 impl AsRef<FileName> for SourceFile {
     fn as_ref(&self) -> &FileName {
         self.path()
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 impl fmt::Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 pub struct LineColumn {
     pub line: usize,
     pub column: usize,
 }
 
 #[derive(Copy, Clone)]
 pub struct Span(proc_macro::Span);
 
 impl From<proc_macro::Span> for ::Span {
     fn from(proc_span: proc_macro::Span) -> ::Span {
-        ::Span(Span(proc_span))
+        ::Span::_new(Span(proc_span))
     }
 }
 
 impl Span {
     pub fn call_site() -> Span {
         Span(proc_macro::Span::call_site())
     }
 
@@ -237,170 +234,166 @@ impl Span {
     pub fn located_at(&self, other: Span) -> Span {
         Span(self.0.located_at(other.0))
     }
 
     pub fn unstable(self) -> proc_macro::Span {
         self.0
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn source_file(&self) -> SourceFile {
         SourceFile::new(self.0.source_file())
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn start(&self) -> LineColumn {
-        let proc_macro::LineColumn{ line, column } = self.0.start();
+        let proc_macro::LineColumn { line, column } = self.0.start();
         LineColumn { line, column }
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn end(&self) -> LineColumn {
-        let proc_macro::LineColumn{ line, column } = self.0.end();
+        let proc_macro::LineColumn { line, column } = self.0.end();
         LineColumn { line, column }
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn join(&self, other: Span) -> Option<Span> {
         self.0.join(other.0).map(Span)
     }
+
+    pub fn eq(&self, other: &Span) -> bool {
+        self.0.eq(&other.0)
+    }
 }
 
 impl fmt::Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
 #[derive(Copy, Clone)]
-pub struct Term(proc_macro::Term);
+pub struct Term {
+    term: proc_macro::Term,
+}
 
 impl Term {
-    pub fn intern(string: &str) -> Term {
-        Term(proc_macro::Term::intern(string))
+    pub fn new(string: &str, span: Span) -> Term {
+        Term {
+            term: proc_macro::Term::new(string, span.0),
+        }
     }
 
     pub fn as_str(&self) -> &str {
-        self.0.as_str()
+        self.term.as_str()
+    }
+
+    pub fn span(&self) -> Span {
+        Span(self.term.span())
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.term.set_span(span.0);
     }
 }
 
 impl fmt::Debug for Term {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        self.term.fmt(f)
     }
 }
 
 #[derive(Clone)]
-pub struct Literal(proc_macro::Literal);
+pub struct Literal {
+    lit: proc_macro::Literal,
+}
+
+macro_rules! suffixed_numbers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(proc_macro::Literal::$name(n))
+        }
+    )*)
+}
+
+macro_rules! unsuffixed_integers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(proc_macro::Literal::$name(n))
+        }
+    )*)
+}
 
 impl Literal {
-    pub fn byte_char(byte: u8) -> Literal {
-        match byte {
-            0 => Literal(to_literal("b'\\0'")),
-            b'\"' => Literal(to_literal("b'\"'")),
-            n => {
-                let mut escaped = "b'".to_string();
-                escaped.extend(ascii::escape_default(n).map(|c| c as char));
-                escaped.push('\'');
-                Literal(to_literal(&escaped))
-            }
+    fn _new(lit: proc_macro::Literal) -> Literal {
+        Literal {
+            lit,
         }
     }
 
-    pub fn byte_string(bytes: &[u8]) -> Literal {
-        Literal(proc_macro::Literal::byte_string(bytes))
-    }
+    suffixed_numbers! {
+        u8_suffixed => u8,
+        u16_suffixed => u16,
+        u32_suffixed => u32,
+        u64_suffixed => u64,
+        usize_suffixed => usize,
+        i8_suffixed => i8,
+        i16_suffixed => i16,
+        i32_suffixed => i32,
+        i64_suffixed => i64,
+        isize_suffixed => isize,
 
-    pub fn doccomment(s: &str) -> Literal {
-        Literal(to_literal(s))
+        f32_suffixed => f32,
+        f64_suffixed => f64,
     }
 
-    pub fn float(s: f64) -> Literal {
-        Literal(proc_macro::Literal::float(s))
+    unsuffixed_integers! {
+        u8_unsuffixed => u8,
+        u16_unsuffixed => u16,
+        u32_unsuffixed => u32,
+        u64_unsuffixed => u64,
+        usize_unsuffixed => usize,
+        i8_unsuffixed => i8,
+        i16_unsuffixed => i16,
+        i32_unsuffixed => i32,
+        i64_unsuffixed => i64,
+        isize_unsuffixed => isize,
     }
 
-    pub fn integer(s: i64) -> Literal {
-        Literal(proc_macro::Literal::integer(s.into()))
+    pub fn f32_unsuffixed(f: f32) -> Literal {
+        Literal::_new(proc_macro::Literal::f32_unsuffixed(f))
     }
 
-    pub fn raw_string(s: &str, pounds: usize) -> Literal {
-        let mut ret = format!("r");
-        ret.extend((0..pounds).map(|_| "#"));
-        ret.push('"');
-        ret.push_str(s);
-        ret.push('"');
-        ret.extend((0..pounds).map(|_| "#"));
-        Literal(to_literal(&ret))
+    pub fn f64_unsuffixed(f: f64) -> Literal {
+        Literal::_new(proc_macro::Literal::f64_unsuffixed(f))
     }
 
-    pub fn raw_byte_string(s: &str, pounds: usize) -> Literal {
-        let mut ret = format!("br");
-        ret.extend((0..pounds).map(|_| "#"));
-        ret.push('"');
-        ret.push_str(s);
-        ret.push('"');
-        ret.extend((0..pounds).map(|_| "#"));
-        Literal(to_literal(&ret))
-    }
-}
 
-impl fmt::Display for Literal {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+    pub fn string(t: &str) -> Literal {
+        Literal::_new(proc_macro::Literal::string(t))
     }
-}
 
-impl fmt::Debug for Literal {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+    pub fn character(t: char) -> Literal {
+        Literal::_new(proc_macro::Literal::character(t))
     }
-}
 
-fn to_literal(s: &str) -> proc_macro::Literal {
-    let stream = s.parse::<proc_macro::TokenStream>().unwrap();
-    match stream.into_iter().next().unwrap().kind {
-        proc_macro::TokenNode::Literal(l) => l,
-        _ => unreachable!(),
+    pub fn byte_string(bytes: &[u8]) -> Literal {
+        Literal::_new(proc_macro::Literal::byte_string(bytes))
     }
-}
 
-macro_rules! ints {
-    ($($t:ident,)*) => {$(
-        impl From<$t> for Literal {
-            fn from(t: $t) -> Literal {
-                Literal(proc_macro::Literal::$t(t))
-            }
-        }
-    )*}
-}
-
-ints! {
-    u8, u16, u32, u64, usize,
-    i8, i16, i32, i64, isize,
-}
-
-macro_rules! floats {
-    ($($t:ident,)*) => {$(
-        impl From<$t> for Literal {
-            fn from(t: $t) -> Literal {
-                Literal(proc_macro::Literal::$t(t))
-            }
-        }
-    )*}
-}
+    pub fn span(&self) -> Span {
+        Span(self.lit.span())
+    }
 
-floats! {
-    f32, f64,
+    pub fn set_span(&mut self, span: Span) {
+        self.lit.set_span(span.0);
+    }
 }
 
-impl<'a> From<&'a str> for Literal {
-    fn from(t: &'a str) -> Literal {
-        Literal(proc_macro::Literal::string(t))
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.lit.fmt(f)
     }
 }
 
-impl From<char> for Literal {
-    fn from(t: char) -> Literal {
-        Literal(proc_macro::Literal::character(t))
+impl fmt::Debug for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.lit.fmt(f)
     }
 }
diff --git a/third_party/rust/proc-macro2/tests/test.rs b/third_party/rust/proc-macro2/tests/test.rs
index ff9c205af9fe..7699d53d1d8e 100644
--- a/third_party/rust/proc-macro2/tests/test.rs
+++ b/third_party/rust/proc-macro2/tests/test.rs
@@ -1,65 +1,56 @@
 extern crate proc_macro2;
 
-use std::str;
+use std::str::{self, FromStr};
 
-use proc_macro2::{Term, Literal, TokenStream};
-
-#[cfg(procmacro2_semver_exempt)]
-use proc_macro2::TokenNode;
-
-#[cfg(procmacro2_semver_exempt)]
-#[cfg(not(feature = "nightly"))]
-use proc_macro2::Span;
+use proc_macro2::{Literal, Span, Term, TokenStream, TokenTree};
 
 #[test]
 fn symbols() {
-    assert_eq!(Term::intern("foo").as_str(), "foo");
-    assert_eq!(Term::intern("bar").as_str(), "bar");
+    assert_eq!(Term::new("foo", Span::call_site()).as_str(), "foo");
+    assert_eq!(Term::new("bar", Span::call_site()).as_str(), "bar");
 }
 
 #[test]
 fn literals() {
     assert_eq!(Literal::string("foo").to_string(), "\"foo\"");
     assert_eq!(Literal::string("\"").to_string(), "\"\\\"\"");
-    assert_eq!(Literal::float(10.0).to_string(), "10.0");
+    assert_eq!(Literal::f32_unsuffixed(10.0).to_string(), "10.0");
 }
 
 #[test]
 fn roundtrip() {
     fn roundtrip(p: &str) {
         println!("parse: {}", p);
         let s = p.parse::<TokenStream>().unwrap().to_string();
         println!("first: {}", s);
         let s2 = s.to_string().parse::<TokenStream>().unwrap().to_string();
         assert_eq!(s, s2);
     }
     roundtrip("a");
     roundtrip("<<");
     roundtrip("<<=");
-    roundtrip("
-        /// a
-        wut
-    ");
-    roundtrip("
+    roundtrip(
+        "
         1
         1.0
         1f32
         2f64
         1usize
         4isize
         4e10
         1_000
         1_0i32
         8u8
         9
         0
         0xffffffffffffffffffffffffffffffff
-    ");
+    ",
+    );
     roundtrip("'a");
     roundtrip("'static");
     roundtrip("'\\u{10__FFFF}'");
     roundtrip("\"\\u{10_F0FF__}foo\\u{1_0_0_0__}\"");
 }
 
 #[test]
 fn fail() {
@@ -68,64 +59,73 @@ fn fail() {
             panic!("should have failed to parse: {}", p);
         }
     }
     fail("1x");
     fail("1u80");
     fail("1f320");
     fail("' static");
     fail("'mut");
+    fail("r#1");
+    fail("r#_");
 }
 
 #[cfg(procmacro2_semver_exempt)]
 #[test]
 fn span_test() {
+    use proc_macro2::TokenTree;
+
     fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) {
         let ts = p.parse::<TokenStream>().unwrap();
         check_spans_internal(ts, &mut lines);
     }
 
-    fn check_spans_internal(
-        ts: TokenStream,
-        lines: &mut &[(usize, usize, usize, usize)],
-    ) {
+    fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) {
         for i in ts {
             if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() {
                 *lines = rest;
 
-                let start = i.span.start();
+                let start = i.span().start();
                 assert_eq!(start.line, sline, "sline did not match for {}", i);
                 assert_eq!(start.column, scol, "scol did not match for {}", i);
 
-                let end = i.span.end();
+                let end = i.span().end();
                 assert_eq!(end.line, eline, "eline did not match for {}", i);
                 assert_eq!(end.column, ecol, "ecol did not match for {}", i);
 
-                match i.kind {
-                    TokenNode::Group(_, stream) =>
-                        check_spans_internal(stream, lines),
+                match i {
+                    TokenTree::Group(ref g) => {
+                        check_spans_internal(g.stream().clone(), lines);
+                    }
                     _ => {}
                 }
             }
         }
     }
 
-    check_spans("\
+    check_spans(
+        "\
 /// This is a document comment
 testing 123
 {
   testing 234
-}", &[
-    (1, 0, 1, 30),
-    (2, 0, 2, 7),
-    (2, 8, 2, 11),
-    (3, 0, 5, 1),
-    (4, 2, 4, 9),
-    (4, 10, 4, 13),
-]);
+}",
+        &[
+            (1, 0, 1, 30),  // #
+            (1, 0, 1, 30),  // [ ... ]
+            (1, 0, 1, 30),  // doc
+            (1, 0, 1, 30),  // =
+            (1, 0, 1, 30),  // "This is..."
+            (2, 0, 2, 7),   // testing
+            (2, 8, 2, 11),  // 123
+            (3, 0, 5, 1),   // { ... }
+            (4, 2, 4, 9),   // testing
+            (4, 10, 4, 13), // 234
+        ],
+    );
 }
 
 #[cfg(procmacro2_semver_exempt)]
 #[cfg(not(feature = "nightly"))]
 #[test]
 fn default_span() {
     let start = Span::call_site().start();
     assert_eq!(start.line, 1);
@@ -136,44 +136,100 @@ fn default_span() {
     let source_file = Span::call_site().source_file();
     assert_eq!(source_file.path().to_string(), "<unspecified>");
     assert!(!source_file.is_real());
 }
 
 #[cfg(procmacro2_semver_exempt)]
 #[test]
 fn span_join() {
-    let source1 =
-        "aaa\nbbb".parse::<TokenStream>().unwrap().into_iter().collect::<Vec<_>>();
-    let source2 =
-        "ccc\nddd".parse::<TokenStream>().unwrap().into_iter().collect::<Vec<_>>();
-
-    assert!(source1[0].span.source_file() != source2[0].span.source_file());
-    assert_eq!(source1[0].span.source_file(), source1[1].span.source_file());
-
-    let joined1 = source1[0].span.join(source1[1].span);
-    let joined2 = source1[0].span.join(source2[0].span);
+    let source1 = "aaa\nbbb"
+        .parse::<TokenStream>()
+        .unwrap()
+        .into_iter()
+        .collect::<Vec<_>>();
+    let source2 = "ccc\nddd"
+        .parse::<TokenStream>()
+        .unwrap()
+        .into_iter()
+        .collect::<Vec<_>>();
+
+    assert!(source1[0].span().source_file() != source2[0].span().source_file());
+    assert_eq!(
+        source1[0].span().source_file(),
+        source1[1].span().source_file()
+    );
+
+    let joined1 = source1[0].span().join(source1[1].span());
+    let joined2 = source1[0].span().join(source2[0].span());
     assert!(joined1.is_some());
     assert!(joined2.is_none());
 
     let start = joined1.unwrap().start();
     let end = joined1.unwrap().end();
     assert_eq!(start.line, 1);
     assert_eq!(start.column, 0);
     assert_eq!(end.line, 2);
     assert_eq!(end.column, 3);
 
-    assert_eq!(joined1.unwrap().source_file(), source1[0].span.source_file());
+    assert_eq!(
+        joined1.unwrap().source_file(),
+        source1[0].span().source_file()
+    );
 }
 
 #[test]
 fn no_panic() {
     let s = str::from_utf8(b"b\'\xc2\x86  \x00\x00\x00^\"").unwrap();
     assert!(s.parse::<proc_macro2::TokenStream>().is_err());
 }
 
 #[test]
-fn tricky_doc_commaent() {
+fn tricky_doc_comment() {
     let stream = "/**/".parse::<proc_macro2::TokenStream>().unwrap();
     let tokens = stream.into_iter().collect::<Vec<_>>();
     assert!(tokens.is_empty(), "not empty -- {:?}", tokens);
+
+    let stream = "/// doc".parse::<proc_macro2::TokenStream>().unwrap();
+    let tokens = stream.into_iter().collect::<Vec<_>>();
+    assert!(tokens.len() == 2, "not length 2 -- {:?}", tokens);
+    match tokens[0] {
+        proc_macro2::TokenTree::Op(ref tt) => assert_eq!(tt.op(), '#'),
+        _ => panic!("wrong token {:?}", tokens[0]),
+    }
+    let mut tokens = match tokens[1] {
+        proc_macro2::TokenTree::Group(ref tt) => {
+            assert_eq!(tt.delimiter(), proc_macro2::Delimiter::Bracket);
+            tt.stream().into_iter()
+        }
+        _ => panic!("wrong token {:?}", tokens[0]),
+    };
+
+    match tokens.next().unwrap() {
+        proc_macro2::TokenTree::Term(ref tt) => assert_eq!(tt.as_str(), "doc"),
+        t => panic!("wrong token {:?}", t),
+    }
+    match tokens.next().unwrap() {
+        proc_macro2::TokenTree::Op(ref tt) => assert_eq!(tt.op(), '='),
+        t => panic!("wrong token {:?}", t),
+    }
+    match tokens.next().unwrap() {
+        proc_macro2::TokenTree::Literal(ref tt) => {
+            assert_eq!(tt.to_string(), "\" doc\"");
+        }
+        t => panic!("wrong token {:?}", t),
+    }
+    assert!(tokens.next().is_none());
+
+    let stream = "//! doc".parse::<proc_macro2::TokenStream>().unwrap();
+    let tokens = stream.into_iter().collect::<Vec<_>>();
+    assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens);
 }
 
+#[test]
+fn raw_identifier() {
+    let mut tts = TokenStream::from_str("r#dyn").unwrap().into_iter();
+    match tts.next().unwrap() {
+        TokenTree::Term(raw) => assert_eq!("r#dyn", raw.as_str()),
+        wrong => panic!("wrong token {:?}", wrong),
+    }
+    assert!(tts.next().is_none());
+}
diff --git a/third_party/rust/quote-0.4.2/.cargo-checksum.json b/third_party/rust/quote-0.4.2/.cargo-checksum.json
new file mode 100644
index 000000000000..d2174ba2dcf3
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"c8e98953df6fdcc4bdf6a1b7d970c214e8f5eb0f21da327d1c0916735303cd3a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"f1812dcc3e666d6bebca97f3739058e1bd8de1a2542c9a8cb258d0a259bd59e1","src/lib.rs":"b63a044edeff7ae12d0733e0a7fe64babf9b593b624fa753639ad3f340f24031","src/to_tokens.rs":"3b7fe0934ce2d9c23d9851ec624349cfa6e9d5cd9ed31c67f25cecce50dc218f","src/tokens.rs":"963474535197c1a79bf60af570470e7a89dce43546ee3186920197fdb40bdd9b","tests/test.rs":"8db237707035f55af7c7ef82c2c3892a048411963dccd019da0148bacae8c3d2"},"package":"1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"}
\ No newline at end of file
diff --git a/third_party/rust/quote-0.4.2/Cargo.toml b/third_party/rust/quote-0.4.2/Cargo.toml
new file mode 100644
index 000000000000..a5d4b7d8f6a9
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/Cargo.toml
@@ -0,0 +1,24 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "quote"
+version = "0.4.2"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
+description = "Quasi-quoting macro quote!(...)"
+documentation = "https://docs.rs/quote/"
+keywords = ["syn"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/dtolnay/quote"
+[dependencies.proc-macro2]
+version = "0.2"
diff --git a/third_party/rust/quote-0.4.2/LICENSE-APACHE b/third_party/rust/quote-0.4.2/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/quote-0.4.2/LICENSE-MIT b/third_party/rust/quote-0.4.2/LICENSE-MIT
new file mode 100644
index 000000000000..40b8817a47be
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2016 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/quote-0.4.2/README.md b/third_party/rust/quote-0.4.2/README.md
new file mode 100644
index 000000000000..90db71948200
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/README.md
@@ -0,0 +1,135 @@
+Rust Quasi-Quoting
+==================
+
+[![Build Status](https://api.travis-ci.org/dtolnay/quote.svg?branch=master)](https://travis-ci.org/dtolnay/quote)
+[![Latest Version](https://img.shields.io/crates/v/quote.svg)](https://crates.io/crates/quote)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/quote/)
+
+This crate provides the [`quote!`] macro for turning Rust syntax tree data
+structures into tokens of source code.
+
+[`quote!`]: https://docs.rs/quote/0.4/quote/macro.quote.html
+
+Procedural macros in Rust receive a stream of tokens as input, execute arbitrary
+Rust code to determine how to manipulate those tokens, and produce a stream of
+tokens to hand back to the compiler to compile into the caller's crate.
+Quasi-quoting is a solution to one piece of that -- producing tokens to return
+to the compiler.
+
+The idea of quasi-quoting is that we write *code* that we treat as *data*.
+Within the `quote!` macro, we can write what looks like code to our text editor
+or IDE. We get all the benefits of the editor's brace matching, syntax
+highlighting, indentation, and maybe autocompletion. But rather than compiling
+that as code into the current crate, we can treat it as data, pass it around,
+mutate it, and eventually hand it back to the compiler as tokens to compile into
+the macro caller's crate.
+
+This crate is motivated by the procedural macro use case, but is a
+general-purpose Rust quasi-quoting library and is not specific to procedural
+macros.
+
+*Version requirement: Quote supports any compiler version back to Rust's very
+first support for procedural macros in Rust 1.15.0.*
+
+```toml
+[dependencies]
+quote = "0.4"
+```
+
+```rust
+#[macro_use]
+extern crate quote;
+```
+
+## Syntax
+
+The quote crate provides a [`quote!`] macro within which you can write Rust code
+that gets packaged into a [`quote::Tokens`] and can be treated as data. You
+should think of `Tokens` as representing a fragment of Rust source code. Call
+`to_string()` on a `Tokens` to get back the fragment of source code as a string,
+or call `into()` to stream them as a `TokenStream` back to the compiler in a
+procedural macro.
+
+[`quote::Tokens`]: https://docs.rs/quote/0.4/quote/struct.Tokens.html
+
+Within the `quote!` macro, interpolation is done with `#var`. Any type
+implementing the [`quote::ToTokens`] trait can be interpolated. This includes
+most Rust primitive types as well as most of the syntax tree types from [`syn`].
+
+[`quote::ToTokens`]: https://docs.rs/quote/0.4/quote/trait.ToTokens.html
+[`syn`]: https://github.com/dtolnay/syn
+
+```rust
+let tokens = quote! {
+    struct SerializeWith #generics #where_clause {
+        value: &'a #field_ty,
+        phantom: ::std::marker::PhantomData<#item_ty>,
+    }
+
+    impl #generics serde::Serialize for SerializeWith #generics #where_clause {
+        fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
+            where S: serde::Serializer
+        {
+            #path(self.value, s)
+        }
+    }
+
+    SerializeWith {
+        value: #value,
+        phantom: ::std::marker::PhantomData::<#item_ty>,
+    }
+};
+```
+
+## Repetition
+
+Repetition is done using `#(...)*` or `#(...),*` similar to `macro_rules!`. This
+iterates through the elements of any variable interpolated within the repetition
+and inserts a copy of the repetition body for each one. The variables in an
+interpolation may be anything that implements `IntoIterator`, including `Vec` or
+a pre-existing iterator.
+
+- `#(#var)*` — no separators
+- `#(#var),*` — the character before the asterisk is used as a separator
+- `#( struct #var; )*` — the repetition can contain other things
+- `#( #k => println!("{}", #v), )*` — even multiple interpolations
+
+Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latter
+does not produce a trailing comma. This matches the behavior of delimiters in
+`macro_rules!`.
+
+## Hygiene
+
+Any interpolated tokens preserve the `Span` information provided by their
+`ToTokens` implementation. Tokens that originate within a `quote!` invocation
+are spanned with [`Span::def_site()`].
+
+[`Span::def_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.def_site
+
+A different span can be provided explicitly through the [`quote_spanned!`]
+macro.
+
+[`quote_spanned!`]: https://docs.rs/quote/0.4/quote/macro.quote_spanned.html
+
+### Recursion limit
+
+The `quote!` macro relies on deep recursion so some large invocations may fail
+with "recursion limit reached" when you compile. If it fails, bump up the
+recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
+higher limit may be necessary for especially large invocations. You don't need
+this unless the compiler tells you that you need it.
+
+## 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 this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
diff --git a/third_party/rust/quote-0.4.2/src/lib.rs b/third_party/rust/quote-0.4.2/src/lib.rs
new file mode 100644
index 000000000000..7d174343feaf
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/src/lib.rs
@@ -0,0 +1,501 @@
+//! This crate provides the [`quote!`] macro for turning Rust syntax tree data
+//! structures into tokens of source code.
+//!
+//! [`quote!`]: macro.quote.html
+//!
+//! Procedural macros in Rust receive a stream of tokens as input, execute
+//! arbitrary Rust code to determine how to manipulate those tokens, and produce
+//! a stream of tokens to hand back to the compiler to compile into the caller's
+//! crate. Quasi-quoting is a solution to one piece of that -- producing tokens
+//! to return to the compiler.
+//!
+//! The idea of quasi-quoting is that we write *code* that we treat as *data*.
+//! Within the `quote!` macro, we can write what looks like code to our text
+//! editor or IDE. We get all the benefits of the editor's brace matching,
+//! syntax highlighting, indentation, and maybe autocompletion. But rather than
+//! compiling that as code into the current crate, we can treat it as data, pass
+//! it around, mutate it, and eventually hand it back to the compiler as tokens
+//! to compile into the macro caller's crate.
+//!
+//! This crate is motivated by the procedural macro use case, but is a
+//! general-purpose Rust quasi-quoting library and is not specific to procedural
+//! macros.
+//!
+//! *Version requirement: Quote supports any compiler version back to Rust's
+//! very first support for procedural macros in Rust 1.15.0.*
+//!
+//! ```toml
+//! [dependencies]
+//! quote = "0.4"
+//! ```
+//!
+//! ```
+//! #[macro_use]
+//! extern crate quote;
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! # Example
+//!
+//! The following quasi-quoted block of code is something you might find in [a]
+//! procedural macro having to do with data structure serialization. The `#var`
+//! syntax performs interpolation of runtime variables into the quoted tokens.
+//! Check out the documentation of the [`quote!`] macro for more detail about
+//! the syntax. See also the [`quote_spanned!`] macro which is important for
+//! implementing hygienic procedural macros.
+//!
+//! [a]: https://serde.rs/
+//! [`quote_spanned!`]: macro.quote_spanned.html
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate quote;
+//! #
+//! # fn main() {
+//! #     let generics = "";
+//! #     let where_clause = "";
+//! #     let field_ty = "";
+//! #     let item_ty = "";
+//! #     let path = "";
+//! #     let value = "";
+//! #
+//! let tokens = quote! {
+//!     struct SerializeWith #generics #where_clause {
+//!         value: &'a #field_ty,
+//!         phantom: ::std::marker::PhantomData<#item_ty>,
+//!     }
+//!
+//!     impl #generics serde::Serialize for SerializeWith #generics #where_clause {
+//!         fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
+//!             where S: serde::Serializer
+//!         {
+//!             #path(self.value, s)
+//!         }
+//!     }
+//!
+//!     SerializeWith {
+//!         value: #value,
+//!         phantom: ::std::marker::PhantomData::<#item_ty>,
+//!     }
+//! };
+//! #
+//! # }
+//! ```
+//!
+//! ## Recursion limit
+//!
+//! The `quote!` macro relies on deep recursion so some large invocations may
+//! fail with "recursion limit reached" when you compile. If it fails, bump up
+//! the recursion limit by adding `#![recursion_limit = "128"]` to your crate.
+//! An even higher limit may be necessary for especially large invocations.
+
+// Quote types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/quote/0.4.2")]
+
+extern crate proc_macro2;
+extern crate proc_macro;
+
+mod tokens;
+pub use tokens::Tokens;
+
+mod to_tokens;
+pub use to_tokens::ToTokens;
+
+// Not public API.
+#[doc(hidden)]
+pub mod __rt {
+    // Not public API.
+    pub use proc_macro2::*;
+
+    // Not public API.
+    pub fn parse(tokens: &mut ::Tokens, span: Span, s: &str) {
+        let s: TokenStream = s.parse().expect("invalid token stream");
+        tokens.append_all(s.into_iter().map(|mut t| {
+            t.span = span;
+            t
+        }));
+    }
+
+    // Not public API.
+    pub fn append_kind(tokens: &mut ::Tokens, span: Span, kind: TokenNode) {
+        tokens.append(TokenTree {
+            span: span,
+            kind: kind,
+        })
+    }
+}
+
+/// The whole point.
+///
+/// Performs variable interpolation against the input and produces it as
+/// [`Tokens`]. For returning tokens to the compiler in a procedural macro, use
+/// `into()` to build a `TokenStream`.
+///
+/// [`Tokens`]: struct.Tokens.html
+///
+/// # Interpolation
+///
+/// Variable interpolation is done with `#var` (similar to `$var` in
+/// `macro_rules!` macros). This grabs the `var` variable that is currently in
+/// scope and inserts it in that location in the output tokens. The variable
+/// must implement the [`ToTokens`] trait.
+///
+/// [`ToTokens`]: trait.ToTokens.html
+///
+/// Repetition is done using `#(...)*` or `#(...),*` again similar to
+/// `macro_rules!`. This iterates through the elements of any variable
+/// interpolated within the repetition and inserts a copy of the repetition body
+/// for each one. The variables in an interpolation may be anything that
+/// implements `IntoIterator`, including `Vec` or a pre-existing iterator.
+///
+/// - `#(#var)*` — no separators
+/// - `#(#var),*` — the character before the asterisk is used as a separator
+/// - `#( struct #var; )*` — the repetition can contain other tokens
+/// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
+///
+/// # Hygiene
+///
+/// Any interpolated tokens preserve the `Span` information provided by their
+/// `ToTokens` implementation. Tokens that originate within the `quote!`
+/// invocation are spanned with [`Span::def_site()`].
+///
+/// [`Span::def_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.def_site
+///
+/// A different span can be provided through the [`quote_spanned!`] macro.
+///
+/// [`quote_spanned!`]: macro.quote_spanned.html
+///
+/// # Example
+///
+/// ```
+/// extern crate proc_macro;
+///
+/// #[macro_use]
+/// extern crate quote;
+///
+/// use proc_macro::TokenStream;
+///
+/// # const IGNORE_TOKENS: &'static str = stringify! {
+/// #[proc_macro_derive(HeapSize)]
+/// # };
+/// pub fn derive_heap_size(input: TokenStream) -> TokenStream {
+///     // Parse the input and figure out what implementation to generate...
+///     # const IGNORE_TOKENS: &'static str = stringify! {
+///     let name = /* ... */;
+///     let expr = /* ... */;
+///     # };
+///     #
+///     # let name = 0;
+///     # let expr = 0;
+///
+///     let expanded = quote! {
+///         // The generated impl.
+///         impl ::heapsize::HeapSize for #name {
+///             fn heap_size_of_children(&self) -> usize {
+///                 #expr
+///             }
+///         }
+///     };
+///
+///     // Hand the output tokens back to the compiler.
+///     expanded.into()
+/// }
+/// #
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! quote {
+    ($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::def_site()=> $($tt)*));
+}
+
+/// Same as `quote!`, but applies a given span to all tokens originating within
+/// the macro invocation.
+///
+/// # Syntax
+///
+/// A span expression of type [`Span`], followed by `=>`, followed by the tokens
+/// to quote. The span expression should be brief -- use a variable for anything
+/// more than a few characters. There should be no space before the `=>` token.
+///
+/// [`Span`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate quote;
+/// # extern crate proc_macro2;
+/// #
+/// # use proc_macro2::Span;
+/// #
+/// # fn main() {
+/// # const IGNORE_TOKENS: &'static str = stringify! {
+/// let span = /* ... */;
+/// # };
+/// # let span = Span::call_site();
+/// # let init = 0;
+///
+/// // On one line, use parentheses.
+/// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));
+///
+/// // On multiple lines, place the span at the top and use braces.
+/// let tokens = quote_spanned! {span=>
+///     Box::into_raw(Box::new(#init))
+/// };
+/// # }
+/// ```
+///
+/// # Hygiene
+///
+/// Any interpolated tokens preserve the `Span` information provided by their
+/// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
+/// invocation are spanned with the given span argument.
+///
+/// # Example
+///
+/// The following procedural macro code uses `quote_spanned!` to assert that a
+/// particular Rust type implements the [`Sync`] trait so that references can be
+/// safely shared between threads.
+///
+/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate quote;
+/// # extern crate proc_macro2;
+/// #
+/// # use quote::{Tokens, ToTokens};
+/// # use proc_macro2::Span;
+/// #
+/// # struct Type;
+/// #
+/// # impl Type {
+/// #     fn span(&self) -> Span {
+/// #         Span::call_site()
+/// #     }
+/// # }
+/// #
+/// # impl ToTokens for Type {
+/// #     fn to_tokens(&self, _tokens: &mut Tokens) {}
+/// # }
+/// #
+/// # fn main() {
+/// # let ty = Type;
+/// # let def_site = Span::def_site();
+/// #
+/// let ty_span = ty.span().resolved_at(def_site);
+/// let assert_sync = quote_spanned! {ty_span=>
+///     struct _AssertSync where #ty: Sync;
+/// };
+/// # }
+/// ```
+///
+/// If the assertion fails, the user will see an error like the following. The
+/// input span of their type is hightlighted in the error.
+///
+/// ```text
+/// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
+///   --> src/main.rs:10:21
+///    |
+/// 10 |     static ref PTR: *const () = &();
+///    |                     ^^^^^^^^^ `*const ()` cannot be shared between threads safely
+/// ```
+///
+/// In this example it is important for the where-clause to be spanned with the
+/// line/column information of the user's input type so that error messages are
+/// placed appropriately by the compiler. But it is also incredibly important
+/// that `Sync` resolves at the macro definition site and not the macro call
+/// site. If we resolve `Sync` at the same span that the user's type is going to
+/// be resolved, then they could bypass our check by defining their own trait
+/// named `Sync` that is implemented for their type.
+#[macro_export]
+macro_rules! quote_spanned {
+    ($span:expr=> $($tt:tt)*) => {
+        {
+            let mut _s = $crate::Tokens::new();
+            let _span = $span;
+            quote_each_token!(_s _span $($tt)*);
+            _s
+        }
+    };
+}
+
+// Extract the names of all #metavariables and pass them to the $finish macro.
+//
+// in:   pounded_var_names!(then () a #b c #( #d )* #e)
+// out:  then!(() b d e)
+#[macro_export]
+#[doc(hidden)]
+macro_rules! pounded_var_names {
+    ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)* $first) $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
+        pounded_var_names!($finish ($($found)*) $($rest)*)
+    };
+
+    ($finish:ident ($($found:ident)*)) => {
+        $finish!(() $($found)*)
+    };
+}
+
+// in:   nested_tuples_pat!(() a b c d e)
+// out:  ((((a b) c) d) e)
+//
+// in:   nested_tuples_pat!(() a)
+// out:  a
+#[macro_export]
+#[doc(hidden)]
+macro_rules! nested_tuples_pat {
+    (()) => {
+        &()
+    };
+
+    (() $first:ident $($rest:ident)*) => {
+        nested_tuples_pat!(($first) $($rest)*)
+    };
+
+    (($pat:pat) $first:ident $($rest:ident)*) => {
+        nested_tuples_pat!((($pat, $first)) $($rest)*)
+    };
+
+    (($done:pat)) => {
+        $done
+    };
+}
+
+// in:   multi_zip_expr!(() a b c d e)
+// out:  a.into_iter().zip(b).zip(c).zip(d).zip(e)
+//
+// in:   multi_zip_iter!(() a)
+// out:  a
+#[macro_export]
+#[doc(hidden)]
+macro_rules! multi_zip_expr {
+    (()) => {
+        &[]
+    };
+
+    (() $single:ident) => {
+        $single
+    };
+
+    (() $first:ident $($rest:ident)*) => {
+        multi_zip_expr!(($first.into_iter()) $($rest)*)
+    };
+
+    (($zips:expr) $first:ident $($rest:ident)*) => {
+        multi_zip_expr!(($zips.zip($first)) $($rest)*)
+    };
+
+    (($done:expr)) => {
+        $done
+    };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_each_token {
+    ($tokens:ident $span:ident) => {};
+
+    ($tokens:ident $span:ident # ! $($rest:tt)*) => {
+        quote_each_token!($tokens $span #);
+        quote_each_token!($tokens $span !);
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
+        for pounded_var_names!(nested_tuples_pat () $($inner)*)
+        in pounded_var_names!(multi_zip_expr () $($inner)*) {
+            quote_each_token!($tokens $span $($inner)*);
+        }
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
+        for (_i, pounded_var_names!(nested_tuples_pat () $($inner)*))
+        in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
+            if _i > 0 {
+                quote_each_token!($tokens $span $sep);
+            }
+            quote_each_token!($tokens $span $($inner)*);
+        }
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
+        quote_each_token!($tokens $span #);
+        $crate::__rt::append_kind(&mut $tokens,
+            $span,
+            $crate::__rt::TokenNode::Group(
+                $crate::__rt::Delimiter::Bracket,
+                quote_spanned!($span=> $($inner)*).into()
+            ));
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident # $first:ident $($rest:tt)*) => {
+        $crate::ToTokens::to_tokens(&$first, &mut $tokens);
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident ( $($first:tt)* ) $($rest:tt)*) => {
+        $crate::__rt::append_kind(&mut $tokens,
+            $span,
+            $crate::__rt::TokenNode::Group(
+                $crate::__rt::Delimiter::Parenthesis,
+                quote_spanned!($span=> $($first)*).into()
+            ));
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident [ $($first:tt)* ] $($rest:tt)*) => {
+        $crate::__rt::append_kind(&mut $tokens,
+            $span,
+            $crate::__rt::TokenNode::Group(
+                $crate::__rt::Delimiter::Bracket,
+                quote_spanned!($span=> $($first)*).into()
+            ));
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident { $($first:tt)* } $($rest:tt)*) => {
+        $crate::__rt::append_kind(&mut $tokens,
+            $span,
+            $crate::__rt::TokenNode::Group(
+                $crate::__rt::Delimiter::Brace,
+                quote_spanned!($span=> $($first)*).into()
+            ));
+        quote_each_token!($tokens $span $($rest)*);
+    };
+
+    ($tokens:ident $span:ident $first:tt $($rest:tt)*) => {
+        // TODO: this seems slow... special case some `:tt` arguments?
+        $crate::__rt::parse(&mut $tokens, $span, stringify!($first));
+        quote_each_token!($tokens $span $($rest)*);
+    };
+}
diff --git a/third_party/rust/quote-0.4.2/src/to_tokens.rs b/third_party/rust/quote-0.4.2/src/to_tokens.rs
new file mode 100644
index 000000000000..277d0a509898
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/src/to_tokens.rs
@@ -0,0 +1,175 @@
+use super::Tokens;
+
+use std::borrow::Cow;
+
+use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};
+
+fn tt(kind: TokenNode) -> TokenTree {
+    TokenTree {
+        span: Span::def_site(),
+        kind: kind,
+    }
+}
+
+/// Types that can be interpolated inside a [`quote!`] invocation.
+///
+/// [`quote!`]: macro.quote.html
+pub trait ToTokens {
+    /// Write `self` to the given `Tokens`.
+    ///
+    /// Example implementation for a struct representing Rust paths like
+    /// `std::cmp::PartialEq`:
+    ///
+    /// ```
+    /// extern crate quote;
+    /// use quote::{Tokens, ToTokens};
+    ///
+    /// extern crate proc_macro2;
+    /// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
+    ///
+    /// pub struct Path {
+    ///     pub global: bool,
+    ///     pub segments: Vec<PathSegment>,
+    /// }
+    ///
+    /// impl ToTokens for Path {
+    ///     fn to_tokens(&self, tokens: &mut Tokens) {
+    ///         for (i, segment) in self.segments.iter().enumerate() {
+    ///             if i > 0 || self.global {
+    ///                 // Double colon `::`
+    ///                 tokens.append(TokenTree {
+    ///                     span: Span::def_site(),
+    ///                     kind: TokenNode::Op(':', Spacing::Joint),
+    ///                 });
+    ///                 tokens.append(TokenTree {
+    ///                     span: Span::def_site(),
+    ///                     kind: TokenNode::Op(':', Spacing::Alone),
+    ///                 });
+    ///             }
+    ///             segment.to_tokens(tokens);
+    ///         }
+    ///     }
+    /// }
+    /// #
+    /// # pub struct PathSegment;
+    /// #
+    /// # impl ToTokens for PathSegment {
+    /// #     fn to_tokens(&self, tokens: &mut Tokens) {
+    /// #         unimplemented!()
+    /// #     }
+    /// # }
+    /// #
+    /// # fn main() {}
+    /// ```
+    fn to_tokens(&self, tokens: &mut Tokens);
+
+    /// Convert `self` directly into a `Tokens` object.
+    ///
+    /// This method is implicitly implemented using `to_tokens`, and acts as a
+    /// convenience method for consumers of the `ToTokens` trait.
+    fn into_tokens(self) -> Tokens
+    where
+        Self: Sized,
+    {
+        let mut tokens = Tokens::new();
+        self.to_tokens(&mut tokens);
+        tokens
+    }
+}
+
+impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        (**self).to_tokens(tokens);
+    }
+}
+
+impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        (**self).to_tokens(tokens);
+    }
+}
+
+impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        (**self).to_tokens(tokens);
+    }
+}
+
+impl<T: ToTokens> ToTokens for Option<T> {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        if let Some(ref t) = *self {
+            t.to_tokens(tokens);
+        }
+    }
+}
+
+impl ToTokens for str {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(tt(TokenNode::Literal(Literal::string(self))));
+    }
+}
+
+impl ToTokens for String {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        self.as_str().to_tokens(tokens);
+    }
+}
+
+macro_rules! primitive {
+    ($($t:ident)*) => ($(
+        impl ToTokens for $t {
+            fn to_tokens(&self, tokens: &mut Tokens) {
+                tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
+            }
+        }
+    )*)
+}
+
+primitive! {
+    i8 i16 i32 i64 isize
+    u8 u16 u32 u64 usize
+    f32 f64
+}
+
+impl ToTokens for char {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
+    }
+}
+
+impl ToTokens for bool {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        let word = if *self { "true" } else { "false" };
+        tokens.append(tt(TokenNode::Term(Term::intern(word))));
+    }
+}
+
+impl ToTokens for Term {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(tt(TokenNode::Term(*self)));
+    }
+}
+
+impl ToTokens for Literal {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(tt(TokenNode::Literal(self.clone())));
+    }
+}
+
+impl ToTokens for TokenNode {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(tt(self.clone()));
+    }
+}
+
+impl ToTokens for TokenTree {
+    fn to_tokens(&self, dst: &mut Tokens) {
+        dst.append(self.clone());
+    }
+}
+
+impl ToTokens for TokenStream {
+    fn to_tokens(&self, dst: &mut Tokens) {
+        dst.append_all(self.clone().into_iter());
+    }
+}
diff --git a/third_party/rust/quote-0.4.2/src/tokens.rs b/third_party/rust/quote-0.4.2/src/tokens.rs
new file mode 100644
index 000000000000..8fa2e44318e1
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/src/tokens.rs
@@ -0,0 +1,264 @@
+use super::ToTokens;
+use std::fmt::{self, Debug, Display};
+use std::hash::{Hash, Hasher};
+
+use proc_macro;
+use proc_macro2::{TokenStream, TokenTree};
+
+/// Tokens produced by a [`quote!`] invocation.
+///
+/// [`quote!`]: macro.quote.html
+#[derive(Clone, Default)]
+pub struct Tokens {
+    tts: Vec<TokenTree>,
+}
+
+impl Tokens {
+    /// Empty tokens.
+    pub fn new() -> Self {
+        Tokens { tts: Vec::new() }
+    }
+
+    /// For use by `ToTokens` implementations.
+    ///
+    /// Appends the token specified to this list of tokens.
+    pub fn append<U>(&mut self, token: U)
+    where
+        U: Into<TokenTree>,
+    {
+        self.tts.push(token.into());
+    }
+
+    /// For use by `ToTokens` implementations.
+    ///
+    /// ```
+    /// # #[macro_use] extern crate quote;
+    /// # use quote::{Tokens, ToTokens};
+    /// # fn main() {
+    /// struct X;
+    ///
+    /// impl ToTokens for X {
+    ///     fn to_tokens(&self, tokens: &mut Tokens) {
+    ///         tokens.append_all(&[true, false]);
+    ///     }
+    /// }
+    ///
+    /// let tokens = quote!(#X);
+    /// assert_eq!(tokens.to_string(), "true false");
+    /// # }
+    /// ```
+    pub fn append_all<T, I>(&mut self, iter: I)
+    where
+        T: ToTokens,
+        I: IntoIterator<Item = T>,
+    {
+        for token in iter {
+            token.to_tokens(self);
+        }
+    }
+
+    /// For use by `ToTokens` implementations.
+    ///
+    /// Appends all of the items in the iterator `I`, separated by the tokens
+    /// `U`.
+    pub fn append_separated<T, I, U>(&mut self, iter: I, op: U)
+    where
+        T: ToTokens,
+        I: IntoIterator<Item = T>,
+        U: ToTokens,
+    {
+        for (i, token) in iter.into_iter().enumerate() {
+            if i > 0 {
+                op.to_tokens(self);
+            }
+            token.to_tokens(self);
+        }
+    }
+
+    /// For use by `ToTokens` implementations.
+    ///
+    /// Appends all tokens in the iterator `I`, appending `U` after each
+    /// element, including after the last element of the iterator.
+    pub fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
+    where
+        T: ToTokens,
+        I: IntoIterator<Item = T>,
+        U: ToTokens,
+    {
+        for token in iter {
+            token.to_tokens(self);
+            term.to_tokens(self);
+        }
+    }
+}
+
+impl ToTokens for Tokens {
+    fn to_tokens(&self, dst: &mut Tokens) {
+        dst.tts.extend(self.tts.iter().cloned());
+    }
+
+    fn into_tokens(self) -> Tokens {
+        self
+    }
+}
+
+impl From<Tokens> for TokenStream {
+    fn from(tokens: Tokens) -> TokenStream {
+        tokens.tts.into_iter().collect()
+    }
+}
+
+impl From<Tokens> for proc_macro::TokenStream {
+    fn from(tokens: Tokens) -> proc_macro::TokenStream {
+        TokenStream::from(tokens).into()
+    }
+}
+
+/// Allows a `Tokens` to be passed to `Tokens::append_all`.
+impl IntoIterator for Tokens {
+    type Item = TokenTree;
+    type IntoIter = private::IntoIter;
+
+    fn into_iter(self) -> Self::IntoIter {
+        private::into_iter(self.tts.into_iter())
+    }
+}
+
+mod private {
+    use std::vec;
+    use proc_macro2::TokenTree;
+
+    pub struct IntoIter(vec::IntoIter<TokenTree>);
+
+    pub fn into_iter(tts: vec::IntoIter<TokenTree>) -> IntoIter {
+        IntoIter(tts)
+    }
+
+    impl Iterator for IntoIter {
+        type Item = TokenTree;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            self.0.next()
+        }
+    }
+}
+
+impl Display for Tokens {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&TokenStream::from(self.clone()), formatter)
+    }
+}
+
+impl Debug for Tokens {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        struct DebugAsDisplay<'a, T: 'a>(&'a T);
+
+        impl<'a, T> Debug for DebugAsDisplay<'a, T>
+        where
+            T: Display,
+        {
+            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                Display::fmt(self.0, formatter)
+            }
+        }
+
+        formatter
+            .debug_tuple("Tokens")
+            .field(&DebugAsDisplay(self))
+            .finish()
+    }
+}
+
+fn tt_eq(a: &TokenTree, b: &TokenTree) -> bool {
+    use proc_macro2::{TokenNode, Delimiter, Spacing};
+
+    match (&a.kind, &b.kind) {
+        (&TokenNode::Group(d1, ref s1), &TokenNode::Group(d2, ref s2)) => {
+            match (d1, d2) {
+                (Delimiter::Parenthesis, Delimiter::Parenthesis)
+                | (Delimiter::Brace, Delimiter::Brace)
+                | (Delimiter::Bracket, Delimiter::Bracket)
+                | (Delimiter::None, Delimiter::None) => {}
+                _ => return false,
+            }
+
+            let s1 = s1.clone().into_iter();
+            let mut s2 = s2.clone().into_iter();
+
+            for item1 in s1 {
+                let item2 = match s2.next() {
+                    Some(item) => item,
+                    None => return false,
+                };
+                if !tt_eq(&item1, &item2) {
+                    return false;
+                }
+            }
+            s2.next().is_none()
+        }
+        (&TokenNode::Op(o1, k1), &TokenNode::Op(o2, k2)) => {
+            o1 == o2 && match (k1, k2) {
+                (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
+                _ => false,
+            }
+        }
+        (&TokenNode::Literal(ref l1), &TokenNode::Literal(ref l2)) => {
+            l1.to_string() == l2.to_string()
+        }
+        (&TokenNode::Term(ref s1), &TokenNode::Term(ref s2)) => s1.as_str() == s2.as_str(),
+        _ => false,
+    }
+}
+
+impl PartialEq for Tokens {
+    fn eq(&self, other: &Self) -> bool {
+        if self.tts.len() != other.tts.len() {
+            return false;
+        }
+
+        self.tts
+            .iter()
+            .zip(other.tts.iter())
+            .all(|(a, b)| tt_eq(a, b))
+    }
+}
+
+fn tt_hash<H: Hasher>(tt: &TokenTree, h: &mut H) {
+    use proc_macro2::{TokenNode, Delimiter, Spacing};
+
+    match tt.kind {
+        TokenNode::Group(delim, ref stream) => {
+            0u8.hash(h);
+            match delim {
+                Delimiter::Parenthesis => 0u8.hash(h),
+                Delimiter::Brace => 1u8.hash(h),
+                Delimiter::Bracket => 2u8.hash(h),
+                Delimiter::None => 3u8.hash(h),
+            }
+
+            for item in stream.clone() {
+                tt_hash(&item, h);
+            }
+            0xffu8.hash(h); // terminator w/ a variant we don't normally hash
+        }
+        TokenNode::Op(op, kind) => {
+            1u8.hash(h);
+            op.hash(h);
+            match kind {
+                Spacing::Alone => 0u8.hash(h),
+                Spacing::Joint => 1u8.hash(h),
+            }
+        }
+        TokenNode::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
+        TokenNode::Term(ref word) => (3u8, word.as_str()).hash(h),
+    }
+}
+
+impl<'a> Hash for Tokens {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        self.tts.len().hash(h);
+        for tt in &self.tts {
+            tt_hash(&tt, h);
+        }
+    }
+}
diff --git a/third_party/rust/quote-0.4.2/tests/test.rs b/third_party/rust/quote-0.4.2/tests/test.rs
new file mode 100644
index 000000000000..2a48f1f59355
--- /dev/null
+++ b/third_party/rust/quote-0.4.2/tests/test.rs
@@ -0,0 +1,292 @@
+#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]
+
+use std::borrow::Cow;
+
+extern crate proc_macro2;
+#[macro_use]
+extern crate quote;
+
+use proc_macro2::{Span, Term};
+
+struct X;
+
+impl quote::ToTokens for X {
+    fn to_tokens(&self, tokens: &mut quote::Tokens) {
+        tokens.append(proc_macro2::TokenTree {
+            kind: proc_macro2::TokenNode::Term(Term::intern("X")),
+            span: Span::def_site(),
+        });
+    }
+}
+
+#[test]
+fn test_quote_impl() {
+    let tokens = quote!(
+        impl<'a, T: ToTokens> ToTokens for &'a T {
+            fn to_tokens(&self, tokens: &mut Tokens) {
+                (**self).to_tokens(tokens)
+            }
+        }
+    );
+
+    let expected = concat!(
+        "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
+        "fn to_tokens ( & self , tokens : & mut Tokens ) { ",
+        "( * * self ) . to_tokens ( tokens ) ",
+        "} ",
+        "}"
+    );
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_substitution() {
+    let x = X;
+    let tokens = quote!(#x <#x> (#x) [#x] {#x});
+
+    let expected = "X < X > ( X ) [ X ] { X }";
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_iter() {
+    let primes = &[X, X, X, X];
+
+    assert_eq!("X X X X", quote!(#(#primes)*).to_string());
+
+    assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());
+
+    assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
+}
+
+#[test]
+fn test_advanced() {
+    let generics = quote!( <'a, T> );
+
+    let where_clause = quote!( where T: Serialize );
+
+    let field_ty = quote!(String);
+
+    let item_ty = quote!(Cow<'a, str>);
+
+    let path = quote!(SomeTrait::serialize_with);
+
+    let value = quote!(self.x);
+
+    let tokens = quote! {
+        struct SerializeWith #generics #where_clause {
+            value: &'a #field_ty,
+            phantom: ::std::marker::PhantomData<#item_ty>,
+        }
+
+        impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
+            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
+                where S: ::serde::Serializer
+            {
+                #path(self.value, s)
+            }
+        }
+
+        SerializeWith {
+            value: #value,
+            phantom: ::std::marker::PhantomData::<#item_ty>,
+        }
+    };
+
+    let expected = concat!(
+        "struct SerializeWith < 'a , T > where T : Serialize { ",
+        "value : & 'a String , ",
+        "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
+        "} ",
+        "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
+        "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
+        "where S : :: serde :: Serializer ",
+        "{ ",
+        "SomeTrait :: serialize_with ( self . value , s ) ",
+        "} ",
+        "} ",
+        "SerializeWith { ",
+        "value : self . x , ",
+        "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
+        "}"
+    );
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_integer() {
+    let ii8 = -1i8;
+    let ii16 = -1i16;
+    let ii32 = -1i32;
+    let ii64 = -1i64;
+    let iisize = -1isize;
+    let uu8 = 1u8;
+    let uu16 = 1u16;
+    let uu32 = 1u32;
+    let uu64 = 1u64;
+    let uusize = 1usize;
+
+    let tokens = quote! {
+        #ii8 #ii16 #ii32 #ii64 #iisize
+        #uu8 #uu16 #uu32 #uu64 #uusize
+    };
+    let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_floating() {
+    let e32 = 2.345f32;
+
+    let e64 = 2.345f64;
+
+    let tokens = quote! {
+        #e32
+        #e64
+    };
+    let expected = concat!("2.345f32 2.345f64");
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_char() {
+    let zero = '\0';
+    let pound = '#';
+    let quote = '"';
+    let apost = '\'';
+    let newline = '\n';
+    let heart = '\u{2764}';
+
+    let tokens = quote! {
+        #zero #pound #quote #apost #newline #heart
+    };
+    let expected = "'\\u{0}' '#' '\\\"' '\\'' '\\n' '\\u{2764}'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_str() {
+    let s = "\0 a 'b \" c";
+    let tokens = quote!(#s);
+    let expected = "\"\\u{0} a \\'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_string() {
+    let s = "\0 a 'b \" c".to_string();
+    let tokens = quote!(#s);
+    let expected = "\"\\u{0} a \\'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_ident() {
+    let foo = Term::intern("Foo");
+    let bar = Term::intern(&format!("Bar{}", 7));
+    let tokens = quote!(struct #foo; enum #bar {});
+    let expected = "struct Foo ; enum Bar7 { }";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_duplicate() {
+    let ch = 'x';
+
+    let tokens = quote!(#ch #ch);
+
+    let expected = "'x' 'x'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_fancy_repetition() {
+    let foo = vec!["a", "b"];
+    let bar = vec![true, false];
+
+    let tokens = quote! {
+        #(#foo: #bar),*
+    };
+
+    let expected = r#""a" : true , "b" : false"#;
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_nested_fancy_repetition() {
+    let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];
+
+    let tokens = quote! {
+        #(
+            #(#nested)*
+        ),*
+    };
+
+    let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_empty_repetition() {
+    let tokens = quote!(#(a b)* #(c d),*);
+    assert_eq!("", tokens.to_string());
+}
+
+#[test]
+fn test_variable_name_conflict() {
+    // The implementation of `#(...),*` uses the variable `_i` but it should be
+    // fine, if a little confusing when debugging.
+    let _i = vec!['a', 'b'];
+    let tokens = quote! { #(#_i),* };
+    let expected = "'a' , 'b'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+fn test_empty_quote() {
+    let tokens = quote!();
+    assert_eq!("", tokens.to_string());
+}
+
+#[test]
+fn test_box_str() {
+    let b = "str".to_owned().into_boxed_str();
+    let tokens = quote! { #b };
+    assert_eq!("\"str\"", tokens.to_string());
+}
+
+#[test]
+fn test_cow() {
+    let owned: Cow<Term> = Cow::Owned(Term::intern("owned"));
+
+    let ident = Term::intern("borrowed");
+    let borrowed = Cow::Borrowed(&ident);
+
+    let tokens = quote! { #owned #borrowed };
+    assert_eq!("owned borrowed", tokens.to_string());
+}
+
+#[test]
+fn test_closure() {
+    fn field_i(i: usize) -> Term {
+        Term::intern(&format!("__field{}", i))
+    }
+
+    let fields = (0usize..3)
+        .map(field_i as fn(_) -> _)
+        .map(|var| quote! { #var });
+
+    let tokens = quote! { #(#fields)* };
+    assert_eq!("__field0 __field1 __field2", tokens.to_string());
+}
+
+#[test]
+fn test_append_tokens() {
+    let mut a = quote!(a);
+    let b = quote!(b);
+    a.append_all(b);
+    assert_eq!("a b", a.to_string());
+}
diff --git a/third_party/rust/quote/.cargo-checksum.json b/third_party/rust/quote/.cargo-checksum.json
index d2174ba2dcf3..01b9be2bcadf 100644
--- a/third_party/rust/quote/.cargo-checksum.json
+++ b/third_party/rust/quote/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c8e98953df6fdcc4bdf6a1b7d970c214e8f5eb0f21da327d1c0916735303cd3a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"f1812dcc3e666d6bebca97f3739058e1bd8de1a2542c9a8cb258d0a259bd59e1","src/lib.rs":"b63a044edeff7ae12d0733e0a7fe64babf9b593b624fa753639ad3f340f24031","src/to_tokens.rs":"3b7fe0934ce2d9c23d9851ec624349cfa6e9d5cd9ed31c67f25cecce50dc218f","src/tokens.rs":"963474535197c1a79bf60af570470e7a89dce43546ee3186920197fdb40bdd9b","tests/test.rs":"8db237707035f55af7c7ef82c2c3892a048411963dccd019da0148bacae8c3d2"},"package":"1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"}
\ No newline at end of file
+{"files":{"Cargo.toml":"8078663280ca2bbda17459a3c2629b84aee2b9904a83f83b87f1bf60e096692f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"bdb5b5375e8cd37b75b4e0269b8fa9fb22776df9762c1df11ec88eb4cd2dc097","src/lib.rs":"7f72accca88679bc49cc8aedf7d96c922288e66a3d63bf1d06f5da262f02a4ad","src/to_tokens.rs":"6eb18c100701d1f9556cd21b1f2faca3316e85029345274dcfe7691e7ffa254d","src/tokens.rs":"a4939fc092d6466d5a2e75474886152e880586b12e057c0d7bf7b3f22428b2de","tests/test.rs":"35bac59a637a8dc3919df51bfa0957b6f964f408cc63c7a81a3e759ab8557f55"},"package":"9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"}
\ No newline at end of file
diff --git a/third_party/rust/quote/Cargo.toml b/third_party/rust/quote/Cargo.toml
index a5d4b7d8f6a9..d565c45bba2f 100644
--- a/third_party/rust/quote/Cargo.toml
+++ b/third_party/rust/quote/Cargo.toml
@@ -7,18 +7,24 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "quote"
-version = "0.4.2"
+version = "0.5.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
 description = "Quasi-quoting macro quote!(...)"
 documentation = "https://docs.rs/quote/"
+readme = "README.md"
 keywords = ["syn"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/dtolnay/quote"
 [dependencies.proc-macro2]
-version = "0.2"
+version = "0.3"
+default-features = false
+
+[features]
+default = ["proc-macro"]
+proc-macro = ["proc-macro2/proc-macro"]
diff --git a/third_party/rust/quote/README.md b/third_party/rust/quote/README.md
index 90db71948200..e38319cb5459 100644
--- a/third_party/rust/quote/README.md
+++ b/third_party/rust/quote/README.md
@@ -3,17 +3,17 @@ Rust Quasi-Quoting
 
 [![Build Status](https://api.travis-ci.org/dtolnay/quote.svg?branch=master)](https://travis-ci.org/dtolnay/quote)
 [![Latest Version](https://img.shields.io/crates/v/quote.svg)](https://crates.io/crates/quote)
 [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/quote/)
 
 This crate provides the [`quote!`] macro for turning Rust syntax tree data
 structures into tokens of source code.
 
-[`quote!`]: https://docs.rs/quote/0.4/quote/macro.quote.html
+[`quote!`]: https://docs.rs/quote/0.5/quote/macro.quote.html
 
 Procedural macros in Rust receive a stream of tokens as input, execute arbitrary
 Rust code to determine how to manipulate those tokens, and produce a stream of
 tokens to hand back to the compiler to compile into the caller's crate.
 Quasi-quoting is a solution to one piece of that -- producing tokens to return
 to the compiler.
 
 The idea of quasi-quoting is that we write *code* that we treat as *data*.
@@ -28,40 +28,40 @@ This crate is motivated by the procedural macro use case, but is a
 general-purpose Rust quasi-quoting library and is not specific to procedural
 macros.
 
 *Version requirement: Quote supports any compiler version back to Rust's very
 first support for procedural macros in Rust 1.15.0.*
 
 ```toml
 [dependencies]
-quote = "0.4"
+quote = "0.5"
 ```
 
 ```rust
 #[macro_use]
 extern crate quote;
 ```
 
 ## Syntax
 
 The quote crate provides a [`quote!`] macro within which you can write Rust code
 that gets packaged into a [`quote::Tokens`] and can be treated as data. You
 should think of `Tokens` as representing a fragment of Rust source code. Call
 `to_string()` on a `Tokens` to get back the fragment of source code as a string,
 or call `into()` to stream them as a `TokenStream` back to the compiler in a
 procedural macro.
 
-[`quote::Tokens`]: https://docs.rs/quote/0.4/quote/struct.Tokens.html
+[`quote::Tokens`]: https://docs.rs/quote/0.5/quote/struct.Tokens.html
 
 Within the `quote!` macro, interpolation is done with `#var`. Any type
 implementing the [`quote::ToTokens`] trait can be interpolated. This includes
 most Rust primitive types as well as most of the syntax tree types from [`syn`].
 
-[`quote::ToTokens`]: https://docs.rs/quote/0.4/quote/trait.ToTokens.html
+[`quote::ToTokens`]: https://docs.rs/quote/0.5/quote/trait.ToTokens.html
 [`syn`]: https://github.com/dtolnay/syn
 
 ```rust
 let tokens = quote! {
     struct SerializeWith #generics #where_clause {
         value: &'a #field_ty,
         phantom: ::std::marker::PhantomData<#item_ty>,
     }
@@ -104,17 +104,17 @@ Any interpolated tokens preserve the `Span` information provided by their
 `ToTokens` implementation. Tokens that originate within a `quote!` invocation
 are spanned with [`Span::def_site()`].
 
 [`Span::def_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.def_site
 
 A different span can be provided explicitly through the [`quote_spanned!`]
 macro.
 
-[`quote_spanned!`]: https://docs.rs/quote/0.4/quote/macro.quote_spanned.html
+[`quote_spanned!`]: https://docs.rs/quote/0.5/quote/macro.quote_spanned.html
 
 ### Recursion limit
 
 The `quote!` macro relies on deep recursion so some large invocations may fail
 with "recursion limit reached" when you compile. If it fails, bump up the
 recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
 higher limit may be necessary for especially large invocations. You don't need
 this unless the compiler tells you that you need it.
diff --git a/third_party/rust/quote/src/lib.rs b/third_party/rust/quote/src/lib.rs
index 7d174343feaf..492186bdb322 100644
--- a/third_party/rust/quote/src/lib.rs
+++ b/third_party/rust/quote/src/lib.rs
@@ -21,17 +21,17 @@
 //! general-purpose Rust quasi-quoting library and is not specific to procedural
 //! macros.
 //!
 //! *Version requirement: Quote supports any compiler version back to Rust's
 //! very first support for procedural macros in Rust 1.15.0.*
 //!
 //! ```toml
 //! [dependencies]
-//! quote = "0.4"
+//! quote = "0.5"
 //! ```
 //!
 //! ```
 //! #[macro_use]
 //! extern crate quote;
 //! #
 //! # fn main() {}
 //! ```
@@ -86,20 +86,21 @@
 //! ## Recursion limit
 //!
 //! The `quote!` macro relies on deep recursion so some large invocations may
 //! fail with "recursion limit reached" when you compile. If it fails, bump up
 //! the recursion limit by adding `#![recursion_limit = "128"]` to your crate.
 //! An even higher limit may be necessary for especially large invocations.
 
 // Quote types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/quote/0.4.2")]
+#![doc(html_root_url = "https://docs.rs/quote/0.5.2")]
 
-extern crate proc_macro2;
+#[cfg(feature = "proc-macro")]
 extern crate proc_macro;
+extern crate proc_macro2;
 
 mod tokens;
 pub use tokens::Tokens;
 
 mod to_tokens;
 pub use to_tokens::ToTokens;
 
 // Not public API.
@@ -107,28 +108,20 @@ pub use to_tokens::ToTokens;
 pub mod __rt {
     // Not public API.
     pub use proc_macro2::*;
 
     // Not public API.
     pub fn parse(tokens: &mut ::Tokens, span: Span, s: &str) {
         let s: TokenStream = s.parse().expect("invalid token stream");
         tokens.append_all(s.into_iter().map(|mut t| {
-            t.span = span;
+            t.set_span(span);
             t
         }));
     }
-
-    // Not public API.
-    pub fn append_kind(tokens: &mut ::Tokens, span: Span, kind: TokenNode) {
-        tokens.append(TokenTree {
-            span: span,
-            kind: kind,
-        })
-    }
 }
 
 /// The whole point.
 ///
 /// Performs variable interpolation against the input and produces it as
 /// [`Tokens`]. For returning tokens to the compiler in a procedural macro, use
 /// `into()` to build a `TokenStream`.
 ///
@@ -153,28 +146,31 @@ pub mod __rt {
 /// - `#(#var),*` — the character before the asterisk is used as a separator
 /// - `#( struct #var; )*` — the repetition can contain other tokens
 /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
 ///
 /// # Hygiene
 ///
 /// Any interpolated tokens preserve the `Span` information provided by their
 /// `ToTokens` implementation. Tokens that originate within the `quote!`
-/// invocation are spanned with [`Span::def_site()`].
+/// invocation are spanned with [`Span::call_site()`].
 ///
-/// [`Span::def_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.def_site
+/// [`Span::call_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.call_site
 ///
 /// A different span can be provided through the [`quote_spanned!`] macro.
 ///
 /// [`quote_spanned!`]: macro.quote_spanned.html
 ///
 /// # Example
 ///
 /// ```
+/// # #[cfg(feature = "proc-macro")]
 /// extern crate proc_macro;
+/// # #[cfg(not(feature = "proc-macro"))]
+/// # extern crate proc_macro2 as proc_macro;
 ///
 /// #[macro_use]
 /// extern crate quote;
 ///
 /// use proc_macro::TokenStream;
 ///
 /// # const IGNORE_TOKENS: &'static str = stringify! {
 /// #[proc_macro_derive(HeapSize)]
@@ -201,17 +197,17 @@ pub mod __rt {
 ///     // Hand the output tokens back to the compiler.
 ///     expanded.into()
 /// }
 /// #
 /// # fn main() {}
 /// ```
 #[macro_export]
 macro_rules! quote {
-    ($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::def_site()=> $($tt)*));
+    ($($tt:tt)*) => (quote_spanned!($crate::__rt::Span::call_site()=> $($tt)*));
 }
 
 /// Same as `quote!`, but applies a given span to all tokens originating within
 /// the macro invocation.
 ///
 /// # Syntax
 ///
 /// A span expression of type [`Span`], followed by `=>`, followed by the tokens
@@ -239,16 +235,22 @@ macro_rules! quote {
 ///
 /// // On multiple lines, place the span at the top and use braces.
 /// let tokens = quote_spanned! {span=>
 ///     Box::into_raw(Box::new(#init))
 /// };
 /// # }
 /// ```
 ///
+/// The lack of space before the `=>` should look jarring to Rust programmers
+/// and this is intentional. The formatting is designed to be visibly
+/// off-balance and draw the eye a particular way, due to the span expression
+/// being evaluated in the context of the procedural macro and the remaining
+/// tokens being evaluated in the generated code.
+///
 /// # Hygiene
 ///
 /// Any interpolated tokens preserve the `Span` information provided by their
 /// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
 /// invocation are spanned with the given span argument.
 ///
 /// # Example
 ///
@@ -275,19 +277,19 @@ macro_rules! quote {
 /// # }
 /// #
 /// # impl ToTokens for Type {
 /// #     fn to_tokens(&self, _tokens: &mut Tokens) {}
 /// # }
 /// #
 /// # fn main() {
 /// # let ty = Type;
-/// # let def_site = Span::def_site();
+/// # let call_site = Span::call_site();
 /// #
-/// let ty_span = ty.span().resolved_at(def_site);
+/// let ty_span = ty.span();
 /// let assert_sync = quote_spanned! {ty_span=>
 ///     struct _AssertSync where #ty: Sync;
 /// };
 /// # }
 /// ```
 ///
 /// If the assertion fails, the user will see an error like the following. The
 /// input span of their type is hightlighted in the error.
@@ -444,57 +446,65 @@ macro_rules! quote_each_token {
             }
             quote_each_token!($tokens $span $($inner)*);
         }
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
         quote_each_token!($tokens $span #);
-        $crate::__rt::append_kind(&mut $tokens,
-            $span,
-            $crate::__rt::TokenNode::Group(
+        $tokens.append({
+            let mut g = $crate::__rt::Group::new(
                 $crate::__rt::Delimiter::Bracket,
-                quote_spanned!($span=> $($inner)*).into()
-            ));
+                quote_spanned!($span=> $($inner)*).into(),
+            );
+            g.set_span($span);
+            g
+        });
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident # $first:ident $($rest:tt)*) => {
         $crate::ToTokens::to_tokens(&$first, &mut $tokens);
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident ( $($first:tt)* ) $($rest:tt)*) => {
-        $crate::__rt::append_kind(&mut $tokens,
-            $span,
-            $crate::__rt::TokenNode::Group(
+        $tokens.append({
+            let mut g = $crate::__rt::Group::new(
                 $crate::__rt::Delimiter::Parenthesis,
-                quote_spanned!($span=> $($first)*).into()
-            ));
+                quote_spanned!($span=> $($first)*).into(),
+            );
+            g.set_span($span);
+            g
+        });
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident [ $($first:tt)* ] $($rest:tt)*) => {
-        $crate::__rt::append_kind(&mut $tokens,
-            $span,
-            $crate::__rt::TokenNode::Group(
+        $tokens.append({
+            let mut g = $crate::__rt::Group::new(
                 $crate::__rt::Delimiter::Bracket,
-                quote_spanned!($span=> $($first)*).into()
-            ));
+                quote_spanned!($span=> $($first)*).into(),
+            );
+            g.set_span($span);
+            g
+        });
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident { $($first:tt)* } $($rest:tt)*) => {
-        $crate::__rt::append_kind(&mut $tokens,
-            $span,
-            $crate::__rt::TokenNode::Group(
+        $tokens.append({
+            let mut g = $crate::__rt::Group::new(
                 $crate::__rt::Delimiter::Brace,
-                quote_spanned!($span=> $($first)*).into()
-            ));
+                quote_spanned!($span=> $($first)*).into(),
+            );
+            g.set_span($span);
+            g
+        });
         quote_each_token!($tokens $span $($rest)*);
     };
 
     ($tokens:ident $span:ident $first:tt $($rest:tt)*) => {
         // TODO: this seems slow... special case some `:tt` arguments?
         $crate::__rt::parse(&mut $tokens, $span, stringify!($first));
         quote_each_token!($tokens $span $($rest)*);
     };
diff --git a/third_party/rust/quote/src/to_tokens.rs b/third_party/rust/quote/src/to_tokens.rs
index 277d0a509898..029fde5fd4d1 100644
--- a/third_party/rust/quote/src/to_tokens.rs
+++ b/third_party/rust/quote/src/to_tokens.rs
@@ -1,55 +1,42 @@
 use super::Tokens;
 
 use std::borrow::Cow;
 
-use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};
-
-fn tt(kind: TokenNode) -> TokenTree {
-    TokenTree {
-        span: Span::def_site(),
-        kind: kind,
-    }
-}
+use proc_macro2::{Group, Literal, Op, Span, Term, TokenStream, TokenTree};
 
 /// Types that can be interpolated inside a [`quote!`] invocation.
 ///
 /// [`quote!`]: macro.quote.html
 pub trait ToTokens {
     /// Write `self` to the given `Tokens`.
     ///
     /// Example implementation for a struct representing Rust paths like
     /// `std::cmp::PartialEq`:
     ///
     /// ```
     /// extern crate quote;
     /// use quote::{Tokens, ToTokens};
     ///
     /// extern crate proc_macro2;
-    /// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
+    /// use proc_macro2::{TokenTree, Spacing, Span, Op};
     ///
     /// pub struct Path {
     ///     pub global: bool,
     ///     pub segments: Vec<PathSegment>,
     /// }
     ///
     /// impl ToTokens for Path {
     ///     fn to_tokens(&self, tokens: &mut Tokens) {
     ///         for (i, segment) in self.segments.iter().enumerate() {
     ///             if i > 0 || self.global {
     ///                 // Double colon `::`
-    ///                 tokens.append(TokenTree {
-    ///                     span: Span::def_site(),
-    ///                     kind: TokenNode::Op(':', Spacing::Joint),
-    ///                 });
-    ///                 tokens.append(TokenTree {
-    ///                     span: Span::def_site(),
-    ///                     kind: TokenNode::Op(':', Spacing::Alone),
-    ///                 });
+    ///                 tokens.append(Op::new(':', Spacing::Joint));
+    ///                 tokens.append(Op::new(':', Spacing::Alone));
     ///             }
     ///             segment.to_tokens(tokens);
     ///         }
     ///     }
     /// }
     /// #
     /// # pub struct PathSegment;
     /// #
@@ -100,70 +87,87 @@ impl<T: ToTokens> ToTokens for Option<T> {
         if let Some(ref t) = *self {
             t.to_tokens(tokens);
         }
     }
 }
 
 impl ToTokens for str {
     fn to_tokens(&self, tokens: &mut Tokens) {
-        tokens.append(tt(TokenNode::Literal(Literal::string(self))));
+        tokens.append(Literal::string(self));
     }
 }
 
 impl ToTokens for String {
     fn to_tokens(&self, tokens: &mut Tokens) {
         self.as_str().to_tokens(tokens);
     }
 }
 
 macro_rules! primitive {
-    ($($t:ident)*) => ($(
+    ($($t:ident => $name:ident)*) => ($(
         impl ToTokens for $t {
             fn to_tokens(&self, tokens: &mut Tokens) {
-                tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
+                tokens.append(Literal::$name(*self));
             }
         }
     )*)
 }
 
 primitive! {
-    i8 i16 i32 i64 isize
-    u8 u16 u32 u64 usize
-    f32 f64
+    i8 => i8_suffixed
+    i16 => i16_suffixed
+    i32 => i32_suffixed
+    i64 => i64_suffixed
+    isize => isize_suffixed
+
+    u8 => u8_suffixed
+    u16 => u16_suffixed
+    u32 => u32_suffixed
+    u64 => u64_suffixed
+    usize => usize_suffixed
+
+    f32 => f32_suffixed
+    f64 => f64_suffixed
 }
 
 impl ToTokens for char {
     fn to_tokens(&self, tokens: &mut Tokens) {
-        tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
+        tokens.append(Literal::character(*self));
     }
 }
 
 impl ToTokens for bool {
     fn to_tokens(&self, tokens: &mut Tokens) {
         let word = if *self { "true" } else { "false" };
-        tokens.append(tt(TokenNode::Term(Term::intern(word))));
+        tokens.append(Term::new(word, Span::call_site()));
+    }
+}
+
+impl ToTokens for Group {
+    fn to_tokens(&self, tokens: &mut Tokens) {
+        tokens.append(self.clone());
     }
 }
 
 impl ToTokens for Term {
     fn to_tokens(&self, tokens: &mut Tokens) {
-        tokens.append(tt(TokenNode::Term(*self)));
+        tokens.append(self.clone());
     }
 }
 
-impl ToTokens for Literal {
+impl ToTokens for Op {
     fn to_tokens(&self, tokens: &mut Tokens) {
-        tokens.append(tt(TokenNode::Literal(self.clone())));
+        tokens.append(self.clone());
     }
 }
 
-impl ToTokens for TokenNode {
+impl ToTokens for Literal {
     fn to_tokens(&self, tokens: &mut Tokens) {
-        tokens.append(tt(self.clone()));
+        tokens.append(self.clone());
     }
 }
 
 impl ToTokens for TokenTree {
     fn to_tokens(&self, dst: &mut Tokens) {
         dst.append(self.clone());
     }
 }
diff --git a/third_party/rust/quote/src/tokens.rs b/third_party/rust/quote/src/tokens.rs
index 8fa2e44318e1..ff4d76809298 100644
--- a/third_party/rust/quote/src/tokens.rs
+++ b/third_party/rust/quote/src/tokens.rs
@@ -1,12 +1,13 @@
 use super::ToTokens;
 use std::fmt::{self, Debug, Display};
 use std::hash::{Hash, Hasher};
 
+#[cfg(feature = "proc-macro")]
 use proc_macro;
 use proc_macro2::{TokenStream, TokenTree};
 
 /// Tokens produced by a [`quote!`] invocation.
 ///
 /// [`quote!`]: macro.quote.html
 #[derive(Clone, Default)]
 pub struct Tokens {
@@ -103,16 +104,17 @@ impl ToTokens for Tokens {
 }
 
 impl From<Tokens> for TokenStream {
     fn from(tokens: Tokens) -> TokenStream {
         tokens.tts.into_iter().collect()
     }
 }
 
+#[cfg(feature = "proc-macro")]
 impl From<Tokens> for proc_macro::TokenStream {
     fn from(tokens: Tokens) -> proc_macro::TokenStream {
         TokenStream::from(tokens).into()
     }
 }
 
 /// Allows a `Tokens` to be passed to `Tokens::append_all`.
 impl IntoIterator for Tokens {
@@ -120,18 +122,18 @@ impl IntoIterator for Tokens {
     type IntoIter = private::IntoIter;
 
     fn into_iter(self) -> Self::IntoIter {
         private::into_iter(self.tts.into_iter())
     }
 }
 
 mod private {
-    use std::vec;
     use proc_macro2::TokenTree;
+    use std::vec;
 
     pub struct IntoIter(vec::IntoIter<TokenTree>);
 
     pub fn into_iter(tts: vec::IntoIter<TokenTree>) -> IntoIter {
         IntoIter(tts)
     }
 
     impl Iterator for IntoIter {
@@ -165,52 +167,52 @@ impl Debug for Tokens {
         formatter
             .debug_tuple("Tokens")
             .field(&DebugAsDisplay(self))
             .finish()
     }
 }
 
 fn tt_eq(a: &TokenTree, b: &TokenTree) -> bool {
-    use proc_macro2::{TokenNode, Delimiter, Spacing};
+    use proc_macro2::{Delimiter, Spacing};
 
-    match (&a.kind, &b.kind) {
-        (&TokenNode::Group(d1, ref s1), &TokenNode::Group(d2, ref s2)) => {
-            match (d1, d2) {
+    match (a, b) {
+        (&TokenTree::Group(ref s1), &TokenTree::Group(ref s2)) => {
+            match (s1.delimiter(), s2.delimiter()) {
                 (Delimiter::Parenthesis, Delimiter::Parenthesis)
                 | (Delimiter::Brace, Delimiter::Brace)
                 | (Delimiter::Bracket, Delimiter::Bracket)
                 | (Delimiter::None, Delimiter::None) => {}
                 _ => return false,
             }
 
-            let s1 = s1.clone().into_iter();
-            let mut s2 = s2.clone().into_iter();
+            let s1 = s1.stream().clone().into_iter();
+            let mut s2 = s2.stream().clone().into_iter();
 
             for item1 in s1 {
                 let item2 = match s2.next() {
                     Some(item) => item,
                     None => return false,
                 };
                 if !tt_eq(&item1, &item2) {
                     return false;
                 }
             }
             s2.next().is_none()
         }
-        (&TokenNode::Op(o1, k1), &TokenNode::Op(o2, k2)) => {
-            o1 == o2 && match (k1, k2) {
+        (&TokenTree::Op(ref o1), &TokenTree::Op(ref o2)) => {
+            o1.op() == o2.op() && match (o1.spacing(), o2.spacing()) {
                 (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
                 _ => false,
             }
         }
-        (&TokenNode::Literal(ref l1), &TokenNode::Literal(ref l2)) => {
+        (&TokenTree::Literal(ref l1), &TokenTree::Literal(ref l2)) => {
             l1.to_string() == l2.to_string()
         }
-        (&TokenNode::Term(ref s1), &TokenNode::Term(ref s2)) => s1.as_str() == s2.as_str(),
+        (&TokenTree::Term(ref s1), &TokenTree::Term(ref s2)) => s1.as_str() == s2.as_str(),
         _ => false,
     }
 }
 
 impl PartialEq for Tokens {
     fn eq(&self, other: &Self) -> bool {
         if self.tts.len() != other.tts.len() {
             return false;
@@ -219,43 +221,43 @@ impl PartialEq for Tokens {
         self.tts
             .iter()
             .zip(other.tts.iter())
             .all(|(a, b)| tt_eq(a, b))
     }
 }
 
 fn tt_hash<H: Hasher>(tt: &TokenTree, h: &mut H) {
-    use proc_macro2::{TokenNode, Delimiter, Spacing};
+    use proc_macro2::{Delimiter, Spacing};
 
-    match tt.kind {
-        TokenNode::Group(delim, ref stream) => {
+    match *tt {
+        TokenTree::Group(ref g) => {
             0u8.hash(h);
-            match delim {
+            match g.delimiter() {
                 Delimiter::Parenthesis => 0u8.hash(h),
                 Delimiter::Brace => 1u8.hash(h),
                 Delimiter::Bracket => 2u8.hash(h),
                 Delimiter::None => 3u8.hash(h),
             }
 
-            for item in stream.clone() {
+            for item in g.stream().clone() {
                 tt_hash(&item, h);
             }
             0xffu8.hash(h); // terminator w/ a variant we don't normally hash
         }
-        TokenNode::Op(op, kind) => {
+        TokenTree::Op(ref t) => {
             1u8.hash(h);
-            op.hash(h);
-            match kind {
+            t.op().hash(h);
+            match t.spacing() {
                 Spacing::Alone => 0u8.hash(h),
                 Spacing::Joint => 1u8.hash(h),
             }
         }
-        TokenNode::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
-        TokenNode::Term(ref word) => (3u8, word.as_str()).hash(h),
+        TokenTree::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
+        TokenTree::Term(ref word) => (3u8, word.as_str()).hash(h),
     }
 }
 
 impl<'a> Hash for Tokens {
     fn hash<H: Hasher>(&self, h: &mut H) {
         self.tts.len().hash(h);
         for tt in &self.tts {
             tt_hash(&tt, h);
diff --git a/third_party/rust/quote/tests/test.rs b/third_party/rust/quote/tests/test.rs
index 2a48f1f59355..df5f897e895c 100644
--- a/third_party/rust/quote/tests/test.rs
+++ b/third_party/rust/quote/tests/test.rs
@@ -7,32 +7,29 @@ extern crate proc_macro2;
 extern crate quote;
 
 use proc_macro2::{Span, Term};
 
 struct X;
 
 impl quote::ToTokens for X {
     fn to_tokens(&self, tokens: &mut quote::Tokens) {
-        tokens.append(proc_macro2::TokenTree {
-            kind: proc_macro2::TokenNode::Term(Term::intern("X")),
-            span: Span::def_site(),
-        });
+        tokens.append(Term::new("X", Span::call_site()));
     }
 }
 
 #[test]
 fn test_quote_impl() {
-    let tokens = quote!(
+    let tokens = quote! {
         impl<'a, T: ToTokens> ToTokens for &'a T {
             fn to_tokens(&self, tokens: &mut Tokens) {
                 (**self).to_tokens(tokens)
             }
         }
-    );
+    };
 
     let expected = concat!(
         "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
         "fn to_tokens ( & self , tokens : & mut Tokens ) { ",
         "( * * self ) . to_tokens ( tokens ) ",
         "} ",
         "}"
     );
@@ -180,18 +177,18 @@ fn test_string() {
     let s = "\0 a 'b \" c".to_string();
     let tokens = quote!(#s);
     let expected = "\"\\u{0} a \\'b \\\" c\"";
     assert_eq!(expected, tokens.to_string());
 }
 
 #[test]
 fn test_ident() {
-    let foo = Term::intern("Foo");
-    let bar = Term::intern(&format!("Bar{}", 7));
+    let foo = Term::new("Foo", Span::call_site());
+    let bar = Term::new(&format!("Bar{}", 7), Span::call_site());
     let tokens = quote!(struct #foo; enum #bar {});
     let expected = "struct Foo ; enum Bar7 { }";
     assert_eq!(expected, tokens.to_string());
 }
 
 #[test]
 fn test_duplicate() {
     let ch = 'x';
@@ -255,29 +252,29 @@ fn test_empty_quote() {
 fn test_box_str() {
     let b = "str".to_owned().into_boxed_str();
     let tokens = quote! { #b };
     assert_eq!("\"str\"", tokens.to_string());
 }
 
 #[test]
 fn test_cow() {
-    let owned: Cow<Term> = Cow::Owned(Term::intern("owned"));
+    let owned: Cow<Term> = Cow::Owned(Term::new("owned", Span::call_site()));
 
-    let ident = Term::intern("borrowed");
+    let ident = Term::new("borrowed", Span::call_site());
     let borrowed = Cow::Borrowed(&ident);
 
     let tokens = quote! { #owned #borrowed };
     assert_eq!("owned borrowed", tokens.to_string());
 }
 
 #[test]
 fn test_closure() {
     fn field_i(i: usize) -> Term {
-        Term::intern(&format!("__field{}", i))
+        Term::new(&format!("__field{}", i), Span::call_site())
     }
 
     let fields = (0usize..3)
         .map(field_i as fn(_) -> _)
         .map(|var| quote! { #var });
 
     let tokens = quote! { #(#fields)* };
     assert_eq!("__field0 __field1 __field2", tokens.to_string());
diff --git a/third_party/rust/regex-0.2.2/.cargo-checksum.json b/third_party/rust/regex-0.2.2/.cargo-checksum.json
new file mode 100644
index 000000000000..7397ed39ea11
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".travis.yml":"28fc87d41a27bc03d9a8c6b5f7bc1bca55444dbd0001100b85060acada1449d7","CHANGELOG.md":"1056eb04d324b46354605713b40b76bb68d29e5d6ff7ab8d67a58f24534d1860","Cargo.toml":"db32762fb82d997942d0ccebdfab132e742a3d384b2f3b10b2e1000515bd40e7","HACKING.md":"37ea34650ce307a1d561aa915ada82cc8b44153085f327aa2b342fcf8e7afc62","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"d23d6dbe3791bc0689c5a876922b8264d6d3069b577772440b8caa01867f0cb4","README.md":"e88b7b2f1982115b1bfa8dd1b305ae1315af6f426c919009d80b63007509ed1c","appveyor.yml":"6855c14a64fec423d67c1ddcc47644593ae3ad1f26e8d157cd5c395efee1efc0","ci/after_success.sh":"6c9562098234f7484e2496918386505185c43018c3f3d17f8df95a59457d8f1f","ci/run-kcov":"721a0ebfb72deb34e4b45141279eae5b4a40c22d47159e01b4e6f176ed3bbc22","ci/run-shootout-test":"be7edb66a4a65eaef6a2b7e6036b4b732effa8dcd931bf4cbd591d0ca32b8264","ci/script.sh":"7f640b7a469c2764f6c12dc84a75fa956c24bc1f611cd72f1ae3a53bacd3ee06","examples/bug347.rs":"93fde9707dd78978dffed46b08bde095a515151bc94f892c0159ac3c0060852d","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"3d36b08dd34c51d022e9b3a3dcfbc780bc9dc3d46a601256db5d4d5e2213119c","examples/shootout-regex-dna-cheat.rs":"4b5a590ec88a9ba67cc4a34621cb038a400d45e64a15a354f3e07fdaf41a935b","examples/shootout-regex-dna-replace.rs":"15677e7de356427fe2b983e918de073a7a730337b090d4ab0e815e1e66f74f73","examples/shootout-regex-dna-single-cheat.rs":"5e743b3a6ec968713ce064a289b1fbd11c302add824d1c749a2ffb546c73128e","examples/shootout-regex-dna-single.rs":"021292ec6999be33a9b8e833759bf3509dc0e6b6365fad8e3a882cf3835b0405","examples/shootout-regex-dna.rs":"b892242cea6b6b16f0511ea672c24a49909585224fb69085f0f2fca77ce30aea","examples/shootout-regex-redux-1.rs":"191f47847f5466261a308c8cdc19a3502603a208f40e4e650024dec80241b9e3","examples/shootout-regex-redux-chunked.rs":"6da0b6af66df64dfe45fb2e08532e2b3712cebcf0d3f19ff8d5f87fe712278c9","examples/shootout-regex-redux.rs":"c587bef968feb9c329f5c1896f79ec09e509885dec27091678b28a221a5d40e8","scripts/frequencies.py":"df2cac150bc4ed42d2d97762535a5f260f3fe06d9d516721f68a52671a3b7a3b","scripts/regex-match-tests.py":"f1b3ad870c893510172bd84f8328b66ee99cd7aee7715a95a858468ff3e33635","scripts/unicode.py":"4b1330e733bbc22e677e22855bf8a88ab134aae56a10fda97081320aa12a6228","src/backtrack.rs":"221e12b4afaff096f8a61bb274eade928845e194e1ec37fa75b684b18c126b1b","src/compile.rs":"4c2159961364d001e9191840a878c3c3ca0b641f2356ba2abcc3356581b7b47c","src/dfa.rs":"985b5f880814452edae862347584f2e53c08eaccae0e01ee5c5d8564dd8381ad","src/error.rs":"b4052872f9a7bc48c478fe73e145ac1acf7533140f827999808fadcba09754d3","src/exec.rs":"b696cd65cca692d4ddf55e60bcd29986c5f2fd43a2e32ffea23c0c95548915d9","src/expand.rs":"94d7fb06544639d94338fc426bd15d1883efd4e0204552c9def667b9b415ef63","src/freqs.rs":"e25871eec51d1c02c15abbc04d61dbea71fb2dbc15f370c98279687416c969de","src/input.rs":"c2710458e38398a0eba357c76c38fde42b50c22b6e39764ea68984fab3acfab7","src/lib.rs":"1652707e4c259cd39e5c45011c5c8d001f582944527af8d78637600bfe162b44","src/literals.rs":"7a2efe252c21660794bd27054e997151763c8f0ea68c2be7994e1a36f4811675","src/pattern.rs":"4e820c17a2b983050f47d3fd13282094ce9f27b75fd852fcec438d61f07f0b0b","src/pikevm.rs":"bc9d00bd5aed5463121fc98ce9390381137f842c821da48242b2f6fae1137f22","src/prog.rs":"3b3d472ced5958e140e96d367067ab53edba72804c80009a46131ec904a75f2a","src/re_builder.rs":"d14baf810f1248a030eca31475989115f6254a438acbba1eec14b59ed58d2f12","src/re_bytes.rs":"a5b7afee1460fb1957284a2483e6708f6357acc7c13288dee409b6aa0fa15b74","src/re_plugin.rs":"74999c35abc02cb7c18adb74c1d8ebd08b56141f66f174c67b7157c5c27e2a49","src/re_set.rs":"43f40dba1273b8b359d4010616be62b41f71b1d803f0c6e4b04169dc57cb6318","src/re_trait.rs":"37d791af9cc737e0a144be64ddb7104114222e5034cfc9c948078b0b2c799295","src/re_unicode.rs":"34cff9ae054084d870803f1c8d092847fe32a34c9572e67bfc524da03cbfc905","src/simd_accel/mod.rs":"a3eb2c7fcc296137cfc135da47cdfe745606e8159c3263591bebced2c09fdd54","src/simd_accel/teddy128.rs":"4b913c67f5b7105f75b02fff092c3d76895612425c3f8b3e5ded2c41aae4279c","src/simd_fallback/mod.rs":"4cb8a77e2d3e167e9bfc47cb7e4734179f743c2f727e26838864d9959275239b","src/simd_fallback/teddy128.rs":"502d3bff4c78963f343875aa00b15e3625f3ee2ba1de01f029211292a5721912","src/sparse.rs":"04e70bb0bd006f806e8c9cf19825625e907036304823bc03b6c8f2e5046a38ef","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"75a4516d636566938e896f10687fc16b3ecd8b09de0093015359eb0d11471d5d","tests/api.rs":"803faacd9ac5efc149959ff63a2132f5ca155f75a246b79807c549b464b5c497","tests/api_str.rs":"aef1388c9de8fe9044539745d1975c734e9d268ff02a2dbb1edc5b754cc56d77","tests/bytes.rs":"ae7601bf69307c541b56d85b6f77369051f55096dddfa9d81d470adb54f42a5d","tests/crazy.rs":"bf3a1c3b8620d7d4c9aa72ab5e027fec02ef4bcec45a884e89ad70e82c445a8d","tests/flags.rs":"cd3788760defc667b32adb2732b6657b289372e1051fc240dfd0e435e2835353","tests/fowler.rs":"e0b7420fa5b636301d4c11cd4dfb803ec09fa7b27be47c594d231167de1241e3","tests/macros.rs":"e0329eedbe073e9dca649e651bc869ef2e6030b4b2a2d5959033b58bfddeb858","tests/macros_bytes.rs":"647c42525b8df5151f4f4cab40f515dd2fa5a05246562f5575902e162b0af2c0","tests/macros_str.rs":"124767f6ff33766502e89050ad498d3aba21e975aefeaf64ae76b0abe13b4fdb","tests/misc.rs":"c8cc85ac916980ebd053df2444fe9b795a00f2ac42c5cd828fc3df487f689265","tests/multiline.rs":"4e872a9473bc229d955716c18c77aa3530625a8f3a28ecaefdb70b9aff0f0a8b","tests/noparse.rs":"9c5acf252655f8daba67d5aa15a98f556a8bb5de87de9ecc8e8e3b50614a65c2","tests/plugin.rs":"9a51dfcbdad4e2a19f43598d74e0dd745a862a01b4165fce387a94083e5b588f","tests/regression.rs":"28bd9e3b6df7b8b48b4c2e069f72f4f59d5e64b091ed2559bd3b0516e27f626a","tests/replace.rs":"4a65b863ad012366328062784e323f13c4bbccce89ff709196e4d84d94ef1636","tests/searcher.rs":"124c9909a1e8fcfddee8ecfae3a1fb9d76f9ddac62fda23d9b895744728a0aa8","tests/set.rs":"0cecf5d2acb3d0df2b051e0ab56a4a853bb58c0e922480f5e460b9a05a0d16af","tests/shortest_match.rs":"7ca223e0a61b1a26a1f36465ab49de021475295e18f4d6421497461af1e107be","tests/suffix_reverse.rs":"cd497c1a51246a8fc727062133470e0c6300620ad80333d20d63c0ee4224ef1c","tests/test_backtrack.rs":"b07a114b2eb7f1f17357629be9c8458e31f7952fb2c327d66d9415f08855c624","tests/test_backtrack_bytes.rs":"dd3cec3c630d6f41892c9111bee87227bf47126651b2402672c30b084fa9c28c","tests/test_backtrack_utf8bytes.rs":"b576b933d6be21f8cedb281e456441d4278350b0145a139dbccb1861639a54f9","tests/test_default.rs":"768a1fabafc7eb815bfaf55c22606dc884e1dbb88d7fc40fd561e8faaa61e6d9","tests/test_default_bytes.rs":"c0b66b63abd263f3fc7e5fcacf4a93cb7fc40c17b764edf8700ae9ba1ab950ff","tests/test_nfa.rs":"aad36ca01f3f7eb23633a1207056e9056d686be2ef6e3661fad83805fa482927","tests/test_nfa_bytes.rs":"198f7b58c5c7dd0a05f16ddb3b9b63dab29ef2a56448378ac602c5d087c01e4e","tests/test_nfa_utf8bytes.rs":"854d80114ca1bed14d4ad3f2b3bf292ff0fa44e12d7d3f2ec6dd17cbbaa82175","tests/test_plugin.rs":"84be9cabe1cf8fb208638475436b020a75e9ec3e7f885af39e5404adb6fcae03","tests/unicode.rs":"7bd3095678fa227dc722f2b5f60a072c2b1752a5ac8df234cd023ece34c80d8a","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"ae4ac0689c6b42ff7628a681d6d99a124d254f35eb1b809137859d3a8afe84fc"},"package":"1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"}
\ No newline at end of file
diff --git a/third_party/rust/regex-0.2.2/.travis.yml b/third_party/rust/regex-0.2.2/.travis.yml
new file mode 100644
index 000000000000..c3d5321e0c50
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/.travis.yml
@@ -0,0 +1,28 @@
+dist: trusty
+sudo: false
+language: rust
+rust:
+  - 1.12.0
+  - stable
+  - beta
+  - nightly
+script: ci/script.sh
+addons:
+  apt:
+    packages:
+      - libcurl4-openssl-dev
+      - libelf-dev
+      - libdw-dev
+      - binutils-dev
+      - wget
+      - clang-3.6
+      - cmake
+      - python
+      - python-virtualenv
+after_success: ci/after_success.sh
+env:
+  global:
+    secure: "GdGE0kFYiJGccVZligur7JlWRCy49eH6uWPl71mrnaaW8jLHmkva0jVb0LB9e5ol3YMaMCgrwM2pcj3Uk2C08YcGIoEKOLlDVho351KaD6XfclZ29CQTAPMz4Xut2IcB4YeuZlDrOnM26guTIOtn2NAjeQgOhpM/ErzVBgkB+wQ="
+notifications:
+  email:
+    on_success: never
diff --git a/third_party/rust/regex-0.2.2/CHANGELOG.md b/third_party/rust/regex-0.2.2/CHANGELOG.md
new file mode 100644
index 000000000000..19492b701004
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/CHANGELOG.md
@@ -0,0 +1,276 @@
+0.2.2 (2017-05-21)
+==================
+New features:
+
+* [FEATURE #341](https://github.com/rust-lang/regex/issues/341):
+  Support nested character classes and intersection operation.
+  For example, `[\p{Greek}&&\pL]` matches greek letters and
+  `[[0-9]&&[^4]]` matches every decimal digit except `4`.
+  (Much thanks to @robinst, who contributed this awesome feature.)
+
+Bug fixes:
+
+* [BUG #321](https://github.com/rust-lang/regex/issues/321):
+  Fix bug in literal extraction and UTF-8 decoding.
+* [BUG #326](https://github.com/rust-lang/regex/issues/326):
+  Add documentation tip about the `(?x)` flag.
+* [BUG #333](https://github.com/rust-lang/regex/issues/333):
+  Show additional replacement example using curly braces.
+* [BUG #334](https://github.com/rust-lang/regex/issues/334):
+  Fix bug when resolving captures after a match.
+* [BUG #338](https://github.com/rust-lang/regex/issues/338):
+  Add example that uses `Captures::get` to API documentation.
+* [BUG #353](https://github.com/rust-lang/regex/issues/353):
+  Fix RegexSet bug that caused match failure in some cases.
+* [BUG #354](https://github.com/rust-lang/regex/pull/354):
+  Fix panic in parser when `(?x)` is used.
+* [BUG #358](https://github.com/rust-lang/regex/issues/358):
+  Fix literal optimization bug with RegexSet.
+* [BUG #359](https://github.com/rust-lang/regex/issues/359):
+  Fix example code in README.
+* [BUG #365](https://github.com/rust-lang/regex/pull/365):
+  Fix bug in `rure_captures_len` in the C binding.
+* [BUG #367](https://github.com/rust-lang/regex/issues/367):
+  Fix byte class bug that caused a panic.
+
+
+0.2.1
+=====
+One major bug with `replace_all` has been fixed along with a couple of other
+touchups.
+
+* [BUG #312](https://github.com/rust-lang/regex/issues/312):
+  Fix documentation for `NoExpand` to reference correct lifetime parameter.
+* [BUG #314](https://github.com/rust-lang/regex/issues/314):
+  Fix a bug with `replace_all` when replacing a match with the empty string.
+* [BUG #316](https://github.com/rust-lang/regex/issues/316):
+  Note a missing breaking change from the `0.2.0` CHANGELOG entry.
+  (`RegexBuilder::compile` was renamed to `RegexBuilder::build`.)
+* [BUG #324](https://github.com/rust-lang/regex/issues/324):
+  Compiling `regex` should only require one version of `memchr` crate.
+
+
+0.2.0
+=====
+This is a new major release of the regex crate, and is an implementation of the
+[regex 1.0 RFC](https://github.com/rust-lang/rfcs/blob/master/text/1620-regex-1.0.md).
+We are releasing a `0.2` first, and if there are no major problems, we will
+release a `1.0` shortly. For `0.2`, the minimum *supported* Rust version is
+1.12.
+
+There are a number of **breaking changes** in `0.2`. They are split into two
+types. The first type correspond to breaking changes in regular expression
+syntax. The second type correspond to breaking changes in the API.
+
+Breaking changes for regex syntax:
+
+* POSIX character classes now require double bracketing. Previously, the regex
+  `[:upper:]` would parse as the `upper` POSIX character class. Now it parses
+  as the character class containing the characters `:upper:`. The fix to this
+  change is to use `[[:upper:]]` instead. Note that variants like
+  `[[:upper:][:blank:]]` continue to work.
+* The character `[` must always be escaped inside a character class.
+* The characters `&`, `-` and `~` must be escaped if any one of them are
+  repeated consecutively. For example, `[&]`, `[\&]`, `[\&\&]`, `[&-&]` are all
+  equivalent while `[&&]` is illegal. (The motivation for this and the prior
+  change is to provide a backwards compatible path for adding character class
+  set notation.)
+* A `bytes::Regex` now has Unicode mode enabled by default (like the main
+  `Regex` type). This means regexes compiled with `bytes::Regex::new` that
+  don't have the Unicode flag set should add `(?-u)` to recover the original
+  behavior.
+
+Breaking changes for the regex API:
+
+* `find` and `find_iter` now **return `Match` values instead of
+  `(usize, usize)`.** `Match` values have `start` and `end` methods, which
+  return the match offsets. `Match` values also have an `as_str` method,
+  which returns the text of the match itself.
+* The `Captures` type now only provides a single iterator over all capturing
+  matches, which should replace uses of `iter` and `iter_pos`. Uses of
+  `iter_named` should use the `capture_names` method on `Regex`.
+* The `at` method on the `Captures` type has been renamed to `get`, and it
+  now returns a `Match`. Similarly, the `name` method on `Captures` now returns
+  a `Match`.
+* The `replace` methods now return `Cow` values. The `Cow::Borrowed` variant
+  is returned when no replacements are made.
+* The `Replacer` trait has been completely overhauled. This should only
+  impact clients that implement this trait explicitly. Standard uses of
+  the `replace` methods should continue to work unchanged. If you implement
+  the `Replacer` trait, please consult the new documentation.
+* The `quote` free function has been renamed to `escape`.
+* The `Regex::with_size_limit` method has been removed. It is replaced by
+  `RegexBuilder::size_limit`.
+* The `RegexBuilder` type has switched from owned `self` method receivers to
+  `&mut self` method receivers. Most uses will continue to work unchanged, but
+  some code may require naming an intermediate variable to hold the builder.
+* The `compile` method on `RegexBuilder` has been renamed to `build`.
+* The free `is_match` function has been removed. It is replaced by compiling
+  a `Regex` and calling its `is_match` method.
+* The `PartialEq` and `Eq` impls on `Regex` have been dropped. If you relied
+  on these impls, the fix is to define a wrapper type around `Regex`, impl
+  `Deref` on it and provide the necessary impls.
+* The `is_empty` method on `Captures` has been removed. This always returns
+  `false`, so its use is superfluous.
+* The `Syntax` variant of the `Error` type now contains a string instead of
+  a `regex_syntax::Error`. If you were examining syntax errors more closely,
+  you'll need to explicitly use the `regex_syntax` crate to re-parse the regex.
+* The `InvalidSet` variant of the `Error` type has been removed since it is
+  no longer used.
+* Most of the iterator types have been renamed to match conventions. If you
+  were using these iterator types explicitly, please consult the documentation
+  for its new name. For example, `RegexSplits` has been renamed to `Split`.
+
+A number of bugs have been fixed:
+
+* [BUG #151](https://github.com/rust-lang/regex/issues/151):
+  The `Replacer` trait has been changed to permit the caller to control
+  allocation.
+* [BUG #165](https://github.com/rust-lang/regex/issues/165):
+  Remove the free `is_match` function.
+* [BUG #166](https://github.com/rust-lang/regex/issues/166):
+  Expose more knobs (available in `0.1`) and remove `with_size_limit`.
+* [BUG #168](https://github.com/rust-lang/regex/issues/168):
+  Iterators produced by `Captures` now have the correct lifetime parameters.
+* [BUG #175](https://github.com/rust-lang/regex/issues/175):
+  Fix a corner case in the parsing of POSIX character classes.
+* [BUG #178](https://github.com/rust-lang/regex/issues/178):
+  Drop the `PartialEq` and `Eq` impls on `Regex`.
+* [BUG #179](https://github.com/rust-lang/regex/issues/179):
+  Remove `is_empty` from `Captures` since it always returns false.
+* [BUG #276](https://github.com/rust-lang/regex/issues/276):
+  Position of named capture can now be retrieved from a `Captures`.
+* [BUG #296](https://github.com/rust-lang/regex/issues/296):
+  Remove winapi/kernel32-sys dependency on UNIX.
+* [BUG #307](https://github.com/rust-lang/regex/issues/307):
+  Fix error on emscripten.
+
+
+0.1.80
+======
+* [PR #292](https://github.com/rust-lang/regex/pull/292):
+  Fixes bug #291, which was introduced by PR #290.
+
+0.1.79
+======
+* Require regex-syntax 0.3.8.
+
+0.1.78
+======
+* [PR #290](https://github.com/rust-lang/regex/pull/290):
+  Fixes bug #289, which caused some regexes with a certain combination
+  of literals to match incorrectly.
+
+0.1.77
+======
+* [PR #281](https://github.com/rust-lang/regex/pull/281):
+  Fixes bug #280 by disabling all literal optimizations when a pattern
+  is partially anchored.
+
+0.1.76
+======
+* Tweak criteria for using the Teddy literal matcher.
+
+0.1.75
+======
+* [PR #275](https://github.com/rust-lang/regex/pull/275):
+  Improves match verification performance in the Teddy SIMD searcher.
+* [PR #278](https://github.com/rust-lang/regex/pull/278):
+  Replaces slow substring loop in the Teddy SIMD searcher with Aho-Corasick.
+* Implemented DoubleEndedIterator on regex set match iterators.
+
+0.1.74
+======
+* Release regex-syntax 0.3.5 with a minor bug fix.
+* Fix bug #272.
+* Fix bug #277.
+* [PR #270](https://github.com/rust-lang/regex/pull/270):
+  Fixes bugs #264, #268 and an unreported where the DFA cache size could be
+  drastically under estimated in some cases (leading to high unexpected memory
+  usage).
+
+0.1.73
+======
+* Release `regex-syntax 0.3.4`.
+* Bump `regex-syntax` dependency version for `regex` to `0.3.4`.
+
+0.1.72
+======
+* [PR #262](https://github.com/rust-lang/regex/pull/262):
+  Fixes a number of small bugs caught by fuzz testing (AFL).
+
+0.1.71
+======
+* [PR #236](https://github.com/rust-lang/regex/pull/236):
+  Fix a bug in how suffix literals were extracted, which could lead
+  to invalid match behavior in some cases.
+
+0.1.70
+======
+* [PR #231](https://github.com/rust-lang/regex/pull/231):
+  Add SIMD accelerated multiple pattern search.
+* [PR #228](https://github.com/rust-lang/regex/pull/228):
+  Reintroduce the reverse suffix literal optimization.
+* [PR #226](https://github.com/rust-lang/regex/pull/226):
+  Implements NFA state compression in the lazy DFA.
+* [PR #223](https://github.com/rust-lang/regex/pull/223):
+  A fully anchored RegexSet can now short-circuit.
+
+0.1.69
+======
+* [PR #216](https://github.com/rust-lang/regex/pull/216):
+  Tweak the threshold for running backtracking.
+* [PR #217](https://github.com/rust-lang/regex/pull/217):
+  Add upper limit (from the DFA) to capture search (for the NFA).
+* [PR #218](https://github.com/rust-lang/regex/pull/218):
+  Add rure, a C API.
+
+0.1.68
+======
+* [PR #210](https://github.com/rust-lang/regex/pull/210):
+  Fixed a performance bug in `bytes::Regex::replace` where `extend` was used
+  instead of `extend_from_slice`.
+* [PR #211](https://github.com/rust-lang/regex/pull/211):
+  Fixed a bug in the handling of word boundaries in the DFA.
+* [PR #213](https://github.com/rust-lang/pull/213):
+  Added RE2 and Tcl to the benchmark harness. Also added a CLI utility from
+  running regexes using any of the following regex engines: PCRE1, PCRE2,
+  Oniguruma, RE2, Tcl and of course Rust's own regexes.
+
+0.1.67
+======
+* [PR #201](https://github.com/rust-lang/regex/pull/201):
+  Fix undefined behavior in the `regex!` compiler plugin macro.
+* [PR #205](https://github.com/rust-lang/regex/pull/205):
+  More improvements to DFA performance. Competitive with RE2. See PR for
+  benchmarks.
+* [PR #209](https://github.com/rust-lang/regex/pull/209):
+  Release 0.1.66 was semver incompatible since it required a newer version
+  of Rust than previous releases. This PR fixes that. (And `0.1.66` was
+  yanked.)
+
+0.1.66
+======
+* Speculative support for Unicode word boundaries was added to the DFA. This
+  should remove the last common case that disqualified use of the DFA.
+* An optimization that scanned for suffix literals and then matched the regular
+  expression in reverse was removed because it had worst case quadratic time
+  complexity. It was replaced with a more limited optimization where, given any
+  regex of the form `re$`, it will be matched in reverse from the end of the
+  haystack.
+* [PR #202](https://github.com/rust-lang/regex/pull/202):
+  The inner loop of the DFA was heavily optimized to improve cache locality
+  and reduce the overall number of instructions run on each iteration. This
+  represents the first use of `unsafe` in `regex` (to elide bounds checks).
+* [PR #200](https://github.com/rust-lang/regex/pull/200):
+  Use of the `mempool` crate (which used thread local storage) was replaced
+  with a faster version of a similar API in @Amanieu's `thread_local` crate.
+  It should reduce contention when using a regex from multiple threads
+  simultaneously.
+* PCRE2 JIT benchmarks were added. A benchmark comparison can be found
+  [here](https://gist.github.com/anonymous/14683c01993e91689f7206a18675901b).
+  (Includes a comparison with PCRE1's JIT and Oniguruma.)
+* A bug where word boundaries weren't being matched correctly in the DFA was
+  fixed. This only affected use of `bytes::Regex`.
+* [#160](https://github.com/rust-lang/regex/issues/160):
+  `Captures` now has a `Debug` impl.
diff --git a/third_party/rust/regex-0.2.2/Cargo.toml b/third_party/rust/regex-0.2.2/Cargo.toml
new file mode 100644
index 000000000000..664f34b16d60
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/Cargo.toml
@@ -0,0 +1,94 @@
+[package]
+name = "regex"
+version = "0.2.2"  #:version
+authors = ["The Rust Project Developers"]
+license = "MIT/Apache-2.0"
+readme = "README.md"
+repository = "https://github.com/rust-lang/regex"
+documentation = "https://doc.rust-lang.org/regex"
+homepage = "https://github.com/rust-lang/regex"
+description = """
+An implementation of regular expressions for Rust. This implementation uses
+finite automata and guarantees linear time matching on all inputs.
+"""
+categories = ["text-processing"]
+
+[dependencies]
+# For very fast prefix literal matching.
+aho-corasick = "0.6.0"
+# For skipping along search text quickly when a leading byte is known.
+memchr = "1.0.0"
+# For managing regex caches quickly across multiple threads.
+thread_local = "0.3.2"
+# For parsing regular expressions.
+regex-syntax = { path = "regex-syntax", version = "0.4.1" }
+# For accelerating text search.
+simd = { version = "0.1.1", optional = true }
+# For compiling UTF-8 decoding into automata.
+utf8-ranges = "1.0.0"
+
+[dev-dependencies]
+# For examples.
+lazy_static = "0.2.2"
+# For property based tests.
+quickcheck = { version = "0.4.1", default-features = false }
+# For generating random test data.
+rand = "0.3.15"
+
+[features]
+# Enable to use the unstable pattern traits defined in std.
+pattern = []
+# Enable to use simd acceleration.
+simd-accel = ["simd"]
+
+[lib]
+# There are no benchmarks in the library code itself
+bench = false
+
+# Run the test suite on the default behavior of Regex::new.
+# This includes a mish mash of NFAs and DFAs, which are chosen automatically
+# based on the regex. We test both of the NFA implementations by forcing their
+# usage with the test definitions below. (We can't test the DFA implementations
+# in the same way since they can't be used for every regex tested.)
+[[test]]
+path = "tests/test_default.rs"
+name = "default"
+
+# The same as the default tests, but run on bytes::Regex.
+[[test]]
+path = "tests/test_default_bytes.rs"
+name = "default-bytes"
+
+# Run the test suite on the NFA algorithm over Unicode codepoints.
+[[test]]
+path = "tests/test_nfa.rs"
+name = "nfa"
+
+# Run the test suite on the NFA algorithm over bytes that match UTF-8 only.
+[[test]]
+path = "tests/test_nfa_utf8bytes.rs"
+name = "nfa-utf8bytes"
+
+# Run the test suite on the NFA algorithm over arbitrary bytes.
+[[test]]
+path = "tests/test_nfa_bytes.rs"
+name = "nfa-bytes"
+
+# Run the test suite on the backtracking engine over Unicode codepoints.
+[[test]]
+path = "tests/test_backtrack.rs"
+name = "backtrack"
+
+# Run the test suite on the backtracking engine over bytes that match UTF-8
+# only.
+[[test]]
+path = "tests/test_backtrack_utf8bytes.rs"
+name = "backtrack-utf8bytes"
+
+# Run the test suite on the backtracking engine over arbitrary bytes.
+[[test]]
+path = "tests/test_backtrack_bytes.rs"
+name = "backtrack-bytes"
+
+[profile.test]
+debug = true
diff --git a/third_party/rust/regex-0.2.2/HACKING.md b/third_party/rust/regex-0.2.2/HACKING.md
new file mode 100644
index 000000000000..28b9fcb5d7a6
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/HACKING.md
@@ -0,0 +1,315 @@
+Your friendly guide to hacking and navigating the regex library.
+
+This guide assumes familiarity with Rust and Cargo, and at least a perusal of
+the user facing documentation for this crate.
+
+If you're looking for background on the implementation in this library, then
+you can do no better than Russ Cox's article series on implementing regular
+expressions using finite automata: https://swtch.com/~rsc/regexp/
+
+
+## Architecture overview
+
+As you probably already know, this library executes regular expressions using
+finite automata. In particular, a design goal is to make searching linear
+with respect to both the regular expression and the text being searched.
+Meeting that design goal on its own is not so hard and can be done with an
+implementation of the Pike VM (similar to Thompson's construction, but supports
+capturing groups), as described in: https://swtch.com/~rsc/regexp/regexp2.html
+--- This library contains such an implementation in src/pikevm.rs.
+
+Making it fast is harder. One of the key problems with the Pike VM is that it
+can be in more than one state at any point in time, and must shuffle capture
+positions between them. The Pike VM also spends a lot of time following the
+same epsilon transitions over and over again. We can employ one trick to
+speed up the Pike VM: extract one or more literal prefixes from the regular
+expression and execute specialized code to quickly find matches of those
+prefixes in the search text. The Pike VM can then be avoided for most the
+search, and instead only executed when a prefix is found. The code to find
+prefixes is in the regex-syntax crate (in this repository). The code to search
+for literals is in src/literals.rs. When more than one literal prefix is found,
+we fall back to an Aho-Corasick DFA using the aho-corasick crate. For one
+literal, we use a variant of the Boyer-Moore algorithm. Both Aho-Corasick and
+Boyer-Moore use `memchr` when appropriate. The Boyer-Moore variant in this
+library also uses elementary frequency analysis to choose the right byte to run
+`memchr` with.
+
+Of course, detecting prefix literals can only take us so far. Not all regular
+expressions have literal prefixes. To remedy this, we try another approach
+to executing the Pike VM: backtracking, whose implementation can be found in
+src/backtrack.rs. One reason why backtracking can be faster is that it avoids
+excessive shuffling of capture groups. Of course, backtracking is susceptible
+to exponential runtimes, so we keep track of every state we've visited to make
+sure we never visit it again. This guarantees linear time execution, but we
+pay for it with the memory required to track visited states. Because of the
+memory requirement, we only use this engine on small search strings *and* small
+regular expressions.
+
+Lastly, the real workhorse of this library is the "lazy" DFA in src/dfa.rs.
+It is distinct from the Pike VM in that the DFA is explicitly represented in
+memory and is only ever in one state at a time. It is said to be "lazy" because
+the DFA is computed as text is searched, where each byte in the search text
+results in at most one new DFA state. It is made fast by caching states. DFAs
+are susceptible to exponential state blow up (where the worst case is computing
+a new state for every input byte, regardless of what's in the state cache). To
+avoid using a lot of memory, the lazy DFA uses a bounded cache. Once the cache
+is full, it is wiped and state computation starts over again. If the cache is
+wiped too frequently, then the DFA gives up and searching falls back to one of
+the aforementioned algorithms.
+
+All of the above matching engines expose precisely the same matching semantics.
+This is indeed tested. (See the section below about testing.)
+
+The following sub-sections describe the rest of the library and how each of the
+matching engines are actually used.
+
+### Parsing
+
+Regular expressions are parsed using the regex-syntax crate, which is
+maintained in this repository. The regex-syntax crate defines an abstract
+syntax and provides very detailed error messages when a parse error is
+encountered. Parsing is done in a separate crate so that others may benefit
+from its existence, and because it is relatively divorced from the rest of the
+regex library.
+
+The regex-syntax crate also provides sophisticated support for extracting
+prefix and suffix literals from regular expressions.
+
+### Compilation
+
+The compiler is in src/compile.rs. The input to the compiler is some abstract
+syntax for a regular expression and the output is a sequence of opcodes that
+matching engines use to execute a search. (One can think of matching engines as
+mini virtual machines.) The sequence of opcodes is a particular encoding of a
+non-deterministic finite automaton. In particular, the opcodes explicitly rely
+on epsilon transitions.
+
+Consider a simple regular expression like `a|b`. Its compiled form looks like
+this:
+
+    000 Save(0)
+    001 Split(2, 3)
+    002 'a' (goto: 4)
+    003 'b'
+    004 Save(1)
+    005 Match
+
+The first column is the instruction pointer and the second column is the
+instruction. Save instructions indicate that the current position in the input
+should be stored in a captured location. Split instructions represent a binary
+branch in the program (i.e., epsilon transitions). The instructions `'a'` and
+`'b'` indicate that the literal bytes `'a'` or `'b'` should match.
+
+In older versions of this library, the compilation looked like this:
+
+    000 Save(0)
+    001 Split(2, 3)
+    002 'a'
+    003 Jump(5)
+    004 'b'
+    005 Save(1)
+    006 Match
+
+In particular, empty instructions that merely served to move execution from one
+point in the program to another were removed. Instead, every instruction has a
+`goto` pointer embedded into it. This resulted in a small performance boost for
+the Pike VM, because it was one fewer epsilon transition that it had to follow.
+
+There exist more instructions and they are defined and documented in
+src/prog.rs.
+
+Compilation has several knobs and a few unfortunately complicated invariants.
+Namely, the output of compilation can be one of two types of programs: a
+program that executes on Unicode scalar values or a program that executes
+on raw bytes. In the former case, the matching engine is responsible for
+performing UTF-8 decoding and executing instructions using Unicode codepoints.
+In the latter case, the program handles UTF-8 decoding implicitly, so that the
+matching engine can execute on raw bytes. All matching engines can execute
+either Unicode or byte based programs except for the lazy DFA, which requires
+byte based programs. In general, both representations were kept because (1) the
+lazy DFA requires byte based programs so that states can be encoded in a memory
+efficient manner and (2) the Pike VM benefits greatly from inlining Unicode
+character classes into fewer instructions as it results in fewer epsilon
+transitions.
+
+N.B. UTF-8 decoding is built into the compiled program by making use of the
+utf8-ranges crate. The compiler in this library factors out common suffixes to
+reduce the size of huge character classes (e.g., `\pL`).
+
+A regrettable consequence of this split in instruction sets is we generally
+need to compile two programs; one for NFA execution and one for the lazy DFA.
+
+In fact, it is worse than that: the lazy DFA is not capable of finding the
+starting location of a match in a single scan, and must instead execute a
+backwards search after finding the end location. To execute a backwards search,
+we must have compiled the regular expression *in reverse*.
+
+This means that every compilation of a regular expression generally results in
+three distinct programs. It would be possible to lazily compile the Unicode
+program, since it is never needed if (1) the regular expression uses no word
+boundary assertions and (2) the caller never asks for sub-capture locations.
+
+### Execution
+
+At the time of writing, there are four matching engines in this library:
+
+1. The Pike VM (supports captures).
+2. Bounded backtracking (supports captures).
+3. Literal substring or multi-substring search.
+4. Lazy DFA (no support for Unicode word boundary assertions).
+
+Only the first two matching engines are capable of executing every regular
+expression program. They also happen to be the slowest, which means we need
+some logic that (1) knows various facts about the regular expression and (2)
+knows what the caller wants. Using this information, we can determine which
+engine (or engines) to use.
+
+The logic for choosing which engine to execute is in src/exec.rs and is
+documented on the Exec type. Exec values contain regular expression Programs
+(defined in src/prog.rs), which contain all the necessary tidbits for actually
+executing a regular expression on search text.
+
+For the most part, the execution logic is straight-forward and follows the
+limitations of each engine described above pretty faithfully. The hairiest
+part of src/exec.rs by far is the execution of the lazy DFA, since it requires
+a forwards and backwards search, and then falls back to either the Pike VM or
+backtracking if the caller requested capture locations.
+
+The Exec type also contains mutable scratch space for each type of matching
+engine. This scratch space is used during search (for example, for the lazy
+DFA, it contains compiled states that are reused on subsequent searches).
+
+### Programs
+
+A regular expression program is essentially a sequence of opcodes produced by
+the compiler plus various facts about the regular expression (such as whether
+it is anchored, its capture names, etc.).
+
+### The regex! macro (or why `regex::internal` exists)
+
+The `regex!` macro is defined in the `regex_macros` crate as a compiler plugin,
+which is maintained in this repository. The `regex!` macro compiles a regular
+expression at compile time into specialized Rust code.
+
+The `regex!` macro was written when this library was first conceived and
+unfortunately hasn't changed much since then. In particular, it encodes the
+entire Pike VM into stack allocated space (no heap allocation is done). When
+`regex!` was first written, this provided a substantial speed boost over
+so-called "dynamic" regexes compiled at runtime, and in particular had much
+lower overhead per match. This was because the only matching engine at the
+time was the Pike VM. The addition of other matching engines has inverted
+the relationship; the `regex!` macro is almost never faster than the dynamic
+variant. (In fact, it is typically substantially slower.)
+
+In order to build the `regex!` macro this way, it must have access to some
+internals of the regex library, which is in a distinct crate. (Compiler plugins
+must be part of a distinct crate.) Namely, it must be able to compile a regular
+expression and access its opcodes. The necessary internals are exported as part
+of the top-level `internal` module in the regex library, but is hidden from
+public documentation. In order to present a uniform API between programs build
+by the `regex!` macro and their dynamic analoges, the `Regex` type is an enum
+whose variants are hidden from public documentation.
+
+In the future, the `regex!` macro should probably work more like Ragel, but
+it's not clear how hard this is. In particular, the `regex!` macro should be
+able to support all the features of dynamic regexes, which may be hard to do
+with a Ragel-style implementation approach. (Which somewhat suggests that the
+`regex!` macro may also need to grow conditional execution logic like the
+dynamic variants, which seems rather grotesque.)
+
+
+## Testing
+
+A key aspect of any mature regex library is its test suite. A subset of the
+tests in this library come from Glenn Fowler's AT&T test suite (its online
+presence seems gone at the time of writing). The source of the test suite is
+located in src/testdata. The scripts/regex-match-tests.py takes the test suite
+in src/testdata and generates tests/matches.rs.
+
+There are also many other manually crafted tests and regression tests in
+tests/tests.rs. Some of these tests were taken from RE2.
+
+The biggest source of complexity in the tests is related to answering this
+question: how can we reuse the tests to check all of our matching engines? One
+approach would have been to encode every test into some kind of format (like
+the AT&T test suite) and code generate tests for each matching engine. The
+approach we use in this library is to create a Cargo.toml entry point for each
+matching engine we want to test. The entry points are:
+
+* `tests/test_plugin.rs` - tests the `regex!` macro
+* `tests/test_default.rs` - tests `Regex::new`
+* `tests/test_default_bytes.rs` - tests `bytes::Regex::new`
+* `tests/test_nfa.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex.
+* `tests/test_nfa_bytes.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex and use *arbitrary* byte based programs.
+* `tests/test_nfa_utf8bytes.rs` - tests `Regex::new`, forced to use the NFA
+  algorithm on every regex and use *UTF-8* byte based programs.
+* `tests/test_backtrack.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex.
+* `tests/test_backtrack_bytes.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex and use *arbitrary* byte based programs.
+* `tests/test_backtrack_utf8bytes.rs` - tests `Regex::new`, forced to use
+  backtracking on every regex and use *UTF-8* byte based programs.
+
+The lazy DFA and pure literal engines are absent from this list because
+they cannot be used on every regular expression. Instead, we rely on
+`tests/test_dynamic.rs` to test the lazy DFA and literal engines when possible.
+
+Since the tests are repeated several times, and because `cargo test` runs all
+entry points, it can take a while to compile everything. To reduce compile
+times slightly, try using `cargo test --test default`, which will only use the
+`tests/test_default.rs` entry point.
+
+N.B. To run tests for the `regex!` macro, use:
+
+    cargo test --manifest-path regex_macros/Cargo.toml
+
+
+## Benchmarking
+
+The benchmarking in this crate is made up of many micro-benchmarks. Currently,
+there are two primary sets of benchmarks: the benchmarks that were adopted
+at this library's inception (in `benches/src/misc.rs`) and a newer set of
+benchmarks meant to test various optimizations. Specifically, the latter set
+contain some analysis and are in `benches/src/sherlock.rs`. Also, the latter
+set are all executed on the same lengthy input whereas the former benchmarks
+are executed on strings of varying length.
+
+There is also a smattering of benchmarks for parsing and compilation.
+
+Benchmarks are in a separate crate so that its dependencies can be managed
+separately from the main regex crate.
+
+Benchmarking follows a similarly wonky setup as tests. There are multiple entry
+points:
+
+* `bench_rust_plugin.rs` - benchmarks the `regex!` macro
+* `bench_rust.rs` - benchmarks `Regex::new`
+* `bench_rust_bytes.rs` benchmarks `bytes::Regex::new`
+* `bench_pcre.rs` - benchmarks PCRE
+* `bench_onig.rs` - benchmarks Oniguruma
+
+The PCRE and Oniguruma benchmarks exist as a comparison point to a mature
+regular expression library. In general, this regex library compares favorably
+(there are even a few benchmarks that PCRE simply runs too slowly on or
+outright can't execute at all). I would love to add other regular expression
+library benchmarks (especially RE2).
+
+If you're hacking on one of the matching engines and just want to see
+benchmarks, then all you need to run is:
+
+    $ ./run-bench rust
+
+If you want to compare your results with older benchmarks, then try:
+
+    $ ./run-bench rust | tee old
+    $ ... make it faster
+    $ ./run-bench rust | tee new
+    $ cargo-benchcmp old new --improvements
+
+The `cargo-benchcmp` utility is available here:
+https://github.com/BurntSushi/cargo-benchcmp
+
+The `run-bench` utility can run benchmarks for PCRE and Oniguruma too. See
+`./run-bench --help`.
diff --git a/third_party/rust/regex-0.2.2/LICENSE-APACHE b/third_party/rust/regex-0.2.2/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/regex-0.2.2/LICENSE-MIT b/third_party/rust/regex-0.2.2/LICENSE-MIT
new file mode 100644
index 000000000000..39d4bdb5acd3
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/regex-0.2.2/PERFORMANCE.md b/third_party/rust/regex-0.2.2/PERFORMANCE.md
new file mode 100644
index 000000000000..6b143262d409
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/PERFORMANCE.md
@@ -0,0 +1,279 @@
+Your friendly guide to understanding the performance characteristics of this
+crate.
+
+This guide assumes some familiarity with the public API of this crate, which
+can be found here: http://doc.rust-lang.org/regex/regex/index.html
+
+## Theory vs. Practice
+
+One of the design goals of this crate is to provide worst case linear time
+behavior with respect to the text searched using finite state automata. This
+means that, *in theory*, the performance of this crate is much better than most
+regex implementations, which typically use backtracking which has worst case
+exponential time.
+
+For example, try opening a Python interpreter and typing this:
+
+    >>> import re
+    >>> re.search('(a*)*c', 'a' * 30).span()
+
+I'll wait.
+
+At some point, you'll figure out that it won't terminate any time soon. ^C it.
+
+The promise of this crate is that *this pathological behavior can't happen*.
+
+With that said, just because we have protected ourselves against worst case
+exponential behavior doesn't mean we are immune from large constant factors
+or places where the current regex engine isn't quite optimal. This guide will
+detail those cases and provide guidance on how to avoid them, among other
+bits of general advice.
+
+## Thou Shalt Not Compile Regular Expressions In A Loop
+
+**Advice**: Use `lazy_static` to amortize the cost of `Regex` compilation.
+
+Don't do it unless you really don't mind paying for it. Compiling a regular
+expression in this crate is quite expensive. It is conceivable that it may get
+faster some day, but I wouldn't hold out hope for, say, an order of magnitude
+improvement. In particular, compilation can take any where from a few dozen
+microseconds to a few dozen milliseconds. Yes, milliseconds. Unicode character
+classes, in particular, have the largest impact on compilation performance. At
+the time of writing, for example, `\pL{100}` takes around 44ms to compile. This
+is because `\pL` corresponds to every letter in Unicode and compilation must
+turn it into a proper automaton that decodes a subset of UTF-8 which
+corresponds to those letters. Compilation also spends some cycles shrinking the
+size of the automaton.
+
+This means that in order to realize efficient regex matching, one must
+*amortize the cost of compilation*. Trivially, if a call to `is_match` is
+inside a loop, then make sure your call to `Regex::new` is *outside* that loop.
+
+In many programming languages, regular expressions can be conveniently defined
+and compiled in a global scope, and code can reach out and use them as if
+they were global static variables. In Rust, there is really no concept of
+life-before-main, and therefore, one cannot utter this:
+
+    static MY_REGEX: Regex = Regex::new("...").unwrap();
+
+Unfortunately, this would seem to imply that one must pass `Regex` objects
+around to everywhere they are used, which can be especially painful depending
+on how your program is structured. Thankfully, the
+[`lazy_static`](https://crates.io/crates/lazy_static)
+crate provides an answer that works well:
+
+    #[macro_use] extern crate lazy_static;
+    extern crate regex;
+
+    use regex::Regex;
+
+    fn some_helper_function(text: &str) -> bool {
+        lazy_static! {
+            static ref MY_REGEX: Regex = Regex::new("...").unwrap();
+        }
+        MY_REGEX.is_match(text)
+    }
+
+In other words, the `lazy_static!` macro enables us to define a `Regex` *as if*
+it were a global static value. What is actually happening under the covers is
+that the code inside the macro (i.e., `Regex::new(...)`) is run on *first use*
+of `MY_REGEX` via a `Deref` impl. The implementation is admittedly magical, but
+it's self contained and everything works exactly as you expect. In particular,
+`MY_REGEX` can be used from multiple threads without wrapping it in an `Arc` or
+a `Mutex`. On that note...
+
+## Using a regex from multiple threads
+
+**Advice**: The performance impact from using a `Regex` from multiple threads
+is likely negligible. If necessary, clone the `Regex` so that each thread gets
+its own copy. Cloning a regex does not incur any additional memory overhead
+than what would be used by using a `Regex` from multiple threads
+simultaneously. *Its only cost is ergonomics.*
+
+It is supported and encouraged to define your regexes using `lazy_static!` as
+if they were global static values, and then use them to search text from
+multiple threads simultaneously.
+
+One might imagine that this is possible because a `Regex` represents a
+*compiled* program, so that any allocation or mutation is already done, and is
+therefore read-only. Unfortunately, this is not true. Each type of search
+strategy in this crate requires some kind of mutable scratch space to use
+*during search*. For example, when executing a DFA, its states are computed
+lazily and reused on subsequent searches. Those states go into that mutable
+scratch space.
+
+The mutable scratch space is an implementation detail, and in general, its
+mutation should not be observable from users of this crate. Therefore, it uses
+interior mutability. This implies that `Regex` can either only be used from one
+thread, or it must do some sort of synchronization. Either choice is
+reasonable, but this crate chooses the latter, in particular because it is
+ergonomic and makes use with `lazy_static!` straight forward.
+
+Synchronization implies *some* amount of overhead. When a `Regex` is used from
+a single thread, this overhead is negligible. When a `Regex` is used from
+multiple threads simultaneously, it is possible for the overhead of
+synchronization from contention to impact performance. The specific cases where
+contention may happen is if you are calling any of these methods repeatedly
+from multiple threads simultaneously:
+
+* shortest_match
+* is_match
+* find
+* captures
+
+In particular, every invocation of one of these methods must synchronize with
+other threads to retrieve its mutable scratch space before searching can start.
+If, however, you are using one of these methods:
+
+* find_iter
+* captures_iter
+
+Then you may not suffer from contention since the cost of synchronization is
+amortized on *construction of the iterator*. That is, the mutable scratch space
+is obtained when the iterator is created and retained throughout its lifetime.
+
+## Only ask for what you need
+
+**Advice**: Prefer in this order: `is_match`, `find`, `captures`.
+
+There are three primary search methods on a `Regex`:
+
+* is_match
+* find
+* captures
+
+In general, these are ordered from fastest to slowest.
+
+`is_match` is fastest because it doesn't actually need to find the start or the
+end of the leftmost-first match. It can quit immediately after it knows there
+is a match. For example, given the regex `a+` and the haystack, `aaaaa`, the
+search will quit after examing the first byte.
+
+In constrast, `find` must return both the start and end location of the
+leftmost-first match. It can use the DFA matcher for this, but must run it
+forwards once to find the end of the match *and then run it backwards* to find
+the start of the match. The two scans and the cost of finding the real end of
+the leftmost-first match make this more expensive than `is_match`.
+
+`captures` is the most expensive of them all because it must do what `find`
+does, and then run either the bounded backtracker or the Pike VM to fill in the
+capture group locations. Both of these are simulations of an NFA, which must
+spend a lot of time shuffling states around. The DFA limits the performance hit
+somewhat by restricting the amount of text that must be searched via an NFA
+simulation.
+
+One other method not mentioned is `shortest_match`. This method has precisely
+the same performance characteristics as `is_match`, except it will return the
+end location of when it discovered a match. For example, given the regex `a+`
+and the haystack `aaaaa`, `shortest_match` may return `1` as opposed to `5`,
+the latter of which being the correct end location of the leftmost-first match.
+
+## Literals in your regex may make it faster
+
+**Advice**: Literals can reduce the work that the regex engine needs to do. Use
+them if you can, especially as prefixes.
+
+In particular, if your regex starts with a prefix literal, the prefix is
+quickly searched before entering the (much slower) regex engine. For example,
+given the regex `foo\w+`, the literal `foo` will be searched for using
+Boyer-Moore. If there's no match, then no regex engine is ever used. Only when
+there's a match is the regex engine invoked at the location of the match, which
+effectively permits the regex engine to skip large portions of a haystack.
+If a regex is comprised entirely of literals (possibly more than one), then
+it's possible that the regex engine can be avoided entirely even when there's a
+match.
+
+When one literal is found, Boyer-Moore is used. When multiple literals are
+found, then an optimized version of Aho-Corasick is used.
+
+This optimization is in particular extended quite a bit in this crate. Here are
+a few examples of regexes that get literal prefixes detected:
+
+* `(foo|bar)` detects `foo` and `bar`
+* `(a|b)c` detects `ac` and `bc`
+* `[ab]foo[yz]` detects `afooy`, `afooz`, `bfooy` and `bfooz`
+* `a?b` detects `a` and `b`
+* `a*b` detects `a` and `b`
+* `(ab){3,6}` detects `ababab`
+
+Literals in anchored regexes can also be used for detecting non-matches very
+quickly. For example, `^foo\w+` and `\w+foo$` may be able to detect a non-match
+just by examing the first (or last) three bytes of the haystack.
+
+## Unicode word boundaries may prevent the DFA from being used
+
+**Advice**: In most cases, `\b` should work well. If not, use `(?-u:\b)`
+instead of `\b` if you care about consistent performance more than correctness.
+
+It's a sad state of the current implementation. At the moment, the DFA will try
+to interpret Unicode word boundaries as if they were ASCII word boundaries.
+If the DFA comes across any non-ASCII byte, it will quit and fall back to an
+alternative matching engine that can handle Unicode word boundaries correctly.
+The alternate matching engine is generally quite a bit slower (perhaps by an
+order of magnitude). If necessary, this can be ameliorated in two ways.
+
+The first way is to add some number of literal prefixes to your regular
+expression. Even though the DFA may not be used, specialized routines will
+still kick in to find prefix literals quickly, which limits how much work the
+NFA simulation will need to do.
+
+The second way is to give up on Unicode and use an ASCII word boundary instead.
+One can use an ASCII word boundary by disabling Unicode support. That is,
+instead of using `\b`, use `(?-u:\b)`.  Namely, given the regex `\b.+\b`, it
+can be transformed into a regex that uses the DFA with `(?-u:\b).+(?-u:\b)`. It
+is important to limit the scope of disabling the `u` flag, since it might lead
+to a syntax error if the regex could match arbitrary bytes. For example, if one
+wrote `(?-u)\b.+\b`, then a syntax error would be returned because `.` matches
+any *byte* when the Unicode flag is disabled.
+
+The second way isn't appreciably different than just using a Unicode word
+boundary in the first place, since the DFA will speculatively interpret it as
+an ASCII word boundary anyway. The key difference is that if an ASCII word
+boundary is used explicitly, then the DFA won't quit in the presence of
+non-ASCII UTF-8 bytes. This results in giving up correctness in exchange for
+more consistent performance.
+
+N.B. When using `bytes::Regex`, Unicode support is disabled by default, so one
+can simply write `\b` to get an ASCII word boundary.
+
+## Excessive counting can lead to exponential state blow up in the DFA
+
+**Advice**: Don't write regexes that cause DFA state blow up if you care about
+match performance.
+
+Wait, didn't I say that this crate guards against exponential worst cases?
+Well, it turns out that the process of converting an NFA to a DFA can lead to
+an exponential blow up in the number of states. This crate specifically guards
+against exponential blow up by doing two things:
+
+1. The DFA is computed lazily. That is, a state in the DFA only exists in
+   memory if it is visited. In particular, the lazy DFA guarantees that *at
+   most* one state is created for every byte of input. This, on its own,
+   guarantees linear time complexity.
+2. Of course, creating a new state for *every* byte of input means that search
+   will go incredibly slow because of very large constant factors. On top of
+   that, creating a state for every byte in a large haystack could result in
+   exorbitant memory usage. To ameliorate this, the DFA bounds the number of
+   states it can store. Once it reaches its limit, it flushes its cache. This
+   prevents reuse of states that it already computed. If the cache is flushed
+   too frequently, then the DFA will give up and execution will fall back to
+   one of the NFA simulations.
+
+In effect, this crate will detect exponential state blow up and fall back to
+a search routine with fixed memory requirements. This does, however, mean that
+searching will be much slower than one might expect. Regexes that rely on
+counting in particular are strong aggravators of this behavior. For example,
+matching `[01]*1[01]{20}$` against a random sequence of `0`s and `1`s.
+
+In the future, it may be possible to increase the bound that the DFA uses,
+which would allow the caller to choose how much memory they're willing to
+spend.
+
+## Resist the temptation to "optimize" regexes
+
+**Advice**: This ain't a backtracking engine.
+
+An entire book was written on how to optimize Perl-style regular expressions.
+Most of those techniques are not applicable for this library. For example,
+there is no problem with using non-greedy matching or having lots of
+alternations in your regex.
diff --git a/third_party/rust/regex-0.2.2/README.md b/third_party/rust/regex-0.2.2/README.md
new file mode 100644
index 000000000000..1384fb55420f
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/README.md
@@ -0,0 +1,240 @@
+regex
+=====
+A Rust library for parsing, compiling, and executing regular expressions. Its
+syntax is similar to Perl-style regular expressions, but lacks a few features
+like look around and backreferences. In exchange, all searches execute in
+linear time with respect to the size of the regular expression and search text.
+Much of the syntax and implementation is inspired
+by [RE2](https://github.com/google/re2).
+
+[![Build Status](https://travis-ci.org/rust-lang/regex.svg?branch=master)](https://travis-ci.org/rust-lang/regex)
+[![Build status](https://ci.appveyor.com/api/projects/status/github/rust-lang/regex?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/regex)
+[![Coverage Status](https://coveralls.io/repos/github/rust-lang/regex/badge.svg?branch=master)](https://coveralls.io/github/rust-lang/regex?branch=master)
+[![](http://meritbadge.herokuapp.com/regex)](https://crates.io/crates/regex)
+
+### Documentation
+
+[Module documentation with examples](https://doc.rust-lang.org/regex).
+The module documentation also include a comprehensive description of the syntax
+supported.
+
+Documentation with examples for the various matching functions and iterators
+can be found on the
+[`Regex` type](https://doc.rust-lang.org/regex/regex/struct.Regex.html).
+
+### Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+regex = "0.2"
+```
+
+and this to your crate root:
+
+```rust
+extern crate regex;
+```
+
+Here's a simple example that matches a date in YYYY-MM-DD format and prints the
+year, month and day:
+
+```rust
+extern crate regex;
+
+use regex::Regex;
+
+fn main() {
+    let re = Regex::new(r"(?x)
+(?P<year>\d{4})  # the year
+-
+(?P<month>\d{2}) # the month
+-
+(?P<day>\d{2})   # the day
+").unwrap();
+    let caps = re.captures("2010-03-14").unwrap();
+
+    assert_eq!("2010", &caps["year"]);
+    assert_eq!("03", &caps["month"]);
+    assert_eq!("14", &caps["day"]);
+}
+```
+
+If you have lots of dates in text that you'd like to iterate over, then it's
+easy to adapt the above example with an iterator:
+
+```rust
+extern crate regex;
+
+use regex::Regex;
+
+const TO_SEARCH: &'static str = "
+On 2010-03-14, foo happened. On 2014-10-14, bar happened.
+";
+
+fn main() {
+    let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
+
+    for caps in re.captures_iter(TO_SEARCH) {
+        // Note that all of the unwraps are actually OK for this regex
+        // because the only way for the regex to match is if all of the
+        // capture groups match. This is not true in general though!
+        println!("year: {}, month: {}, day: {}",
+                 caps.get(1).unwrap().as_str(),
+                 caps.get(2).unwrap().as_str(),
+                 caps.get(3).unwrap().as_str());
+    }
+}
+```
+
+This example outputs:
+
+```
+year: 2010, month: 03, day: 14
+year: 2014, month: 10, day: 14
+```
+
+### Usage: Avoid compiling the same regex in a loop
+
+It is an anti-pattern to compile the same regular expression in a loop since
+compilation is typically expensive. (It takes anywhere from a few microseconds
+to a few **milliseconds** depending on the size of the regex.) Not only is
+compilation itself expensive, but this also prevents optimizations that reuse
+allocations internally to the matching engines.
+
+In Rust, it can sometimes be a pain to pass regular expressions around if
+they're used from inside a helper function. Instead, we recommend using the
+[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
+regular expressions are compiled exactly once.
+
+For example:
+
+```rust
+#[macro_use] extern crate lazy_static;
+extern crate regex;
+
+use regex::Regex;
+
+fn some_helper_function(text: &str) -> bool {
+    lazy_static! {
+        static ref RE: Regex = Regex::new("...").unwrap();
+    }
+    RE.is_match(text)
+}
+```
+
+Specifically, in this example, the regex will be compiled when it is used for
+the first time. On subsequent uses, it will reuse the previous compilation.
+
+### Usage: match regular expressions on `&[u8]`
+
+The main API of this crate (`regex::Regex`) requires the caller to pass a
+`&str` for searching. In Rust, an `&str` is required to be valid UTF-8, which
+means the main API can't be used for searching arbitrary bytes.
+
+To match on arbitrary bytes, use the `regex::bytes::Regex` API. The API
+is identical to the main API, except that it takes an `&[u8]` to search
+on instead of an `&str`. By default, `.` will match any *byte* using
+`regex::bytes::Regex`, while `.` will match any *UTF-8 encoded Unicode scalar
+value* using the main API.
+
+This example shows how to find all null-terminated strings in a slice of bytes:
+
+```rust
+use regex::bytes::Regex;
+
+let re = Regex::new(r"(?P<cstr>[^\x00]+)\x00").unwrap();
+let text = b"foo\x00bar\x00baz\x00";
+
+// Extract all of the strings without the null terminator from each match.
+// The unwrap is OK here since a match requires the `cstr` capture to match.
+let cstrs: Vec<&[u8]> =
+    re.captures_iter(text)
+      .map(|c| c.name("cstr").unwrap().as_bytes())
+      .collect();
+assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
+```
+
+Notice here that the `[^\x00]+` will match any *byte* except for `NUL`. When
+using the main API, `[^\x00]+` would instead match any valid UTF-8 sequence
+except for `NUL`.
+
+### Usage: match multiple regular expressions simultaneously
+
+This demonstrates how to use a `RegexSet` to match multiple (possibly
+overlapping) regular expressions in a single scan of the search text:
+
+```rust
+use regex::RegexSet;
+
+let set = RegexSet::new(&[
+    r"\w+",
+    r"\d+",
+    r"\pL+",
+    r"foo",
+    r"bar",
+    r"barfoo",
+    r"foobar",
+]).unwrap();
+
+// Iterate over and collect all of the matches.
+let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+
+// You can also test whether a particular regex matched:
+let matches = set.matches("foobar");
+assert!(!matches.matched(5));
+assert!(matches.matched(6));
+```
+
+### Usage: `regex!` compiler plugin
+
+**WARNING**: The `regex!` compiler plugin is orders of magnitude slower than
+the normal `Regex::new(...)` usage. You should not use the compiler plugin
+unless you have a very special reason for doing so. The performance difference
+may be the temporary, but the path forward at this point isn't clear.
+
+The `regex!` compiler plugin will compile your regexes at compile time. **This
+only works with a nightly compiler.**
+
+Here is a small example:
+
+```rust
+#![feature(plugin)]
+
+#![plugin(regex_macros)]
+extern crate regex;
+
+fn main() {
+    let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
+    let caps = re.captures("2010-03-14").unwrap();
+
+    assert_eq!("2010", caps[1]);
+    assert_eq!("03", caps[2]);
+    assert_eq!("14", caps[3]);
+}
+```
+
+Notice that we never `unwrap` the result of `regex!`. This is because your
+*program* won't compile if the regex doesn't compile. (Try `regex!("(")`.)
+
+
+### Usage: a regular expression parser
+
+This repository contains a crate that provides a well tested regular expression
+parser and abstract syntax. It provides no facilities for compilation or
+execution. This may be useful if you're implementing your own regex engine or
+otherwise need to do analysis on the syntax of a regular expression. It is
+otherwise not recommended for general use.
+
+[Documentation for `regex-syntax` with
+examples](https://doc.rust-lang.org/regex/regex_syntax/index.html).
+
+# License
+
+`regex` is primarily distributed under the terms of both the MIT license and
+the Apache License (Version 2.0), with portions covered by various BSD-like
+licenses.
+
+See LICENSE-APACHE, and LICENSE-MIT for details.
diff --git a/third_party/rust/regex-0.2.2/appveyor.yml b/third_party/rust/regex-0.2.2/appveyor.yml
new file mode 100644
index 000000000000..0933ad8cc3f8
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/appveyor.yml
@@ -0,0 +1,17 @@
+environment:
+  matrix:
+  - TARGET: x86_64-pc-windows-msvc
+  - TARGET: i686-pc-windows-msvc
+  - TARGET: i686-pc-windows-gnu
+install:
+  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
+  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
+  - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
+  - SET PATH=%PATH%;C:\MinGW\bin
+  - rustc -V
+  - cargo -V
+
+build: false
+
+test_script:
+  - cargo test --verbose --jobs 4
diff --git a/third_party/rust/regex-0.2.2/ci/after_success.sh b/third_party/rust/regex-0.2.2/ci/after_success.sh
new file mode 100755
index 000000000000..2cf60f16e59f
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/ci/after_success.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# This runs only when a commit is pushed to master. It is responsible for
+# updating docs and computing coverage statistics.
+
+set -e
+
+if [ "$TRAVIS_RUST_VERSION" != "nightly" ] || [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" != "master" ]; then
+  exit 0
+fi
+
+env
+
+# Build and upload docs.
+echo '<meta http-equiv=refresh content=0;url=regex/index.html>' > target/doc/index.html
+ve=$(mktemp -d)
+virtualenv "$ve"
+"$ve"/bin/pip install --upgrade pip
+"$ve"/bin/pip install ghp-import
+"$ve"/bin/ghp-import -n target/doc
+git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
+
+# Install kcov.
+tmp=$(mktemp -d)
+pushd "$tmp"
+wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz
+tar zxf master.tar.gz
+mkdir kcov-master/build
+cd kcov-master/build
+cmake ..
+make
+make install DESTDIR="$tmp"
+popd
+PATH="$tmp/usr/local/bin:$PATH" ./ci/run-kcov --coveralls-id $TRAVIS_JOB_ID
diff --git a/third_party/rust/regex-0.2.2/ci/run-kcov b/third_party/rust/regex-0.2.2/ci/run-kcov
new file mode 100755
index 000000000000..092123775d10
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/ci/run-kcov
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+set -e
+
+tests=(
+  default
+  default_bytes
+  backtrack
+  backtrack_utf8bytes
+  backtrack_bytes
+  nfa
+  nfa_utf8bytes
+  nfa_bytes
+  regex
+)
+tmpdir=$(mktemp -d)
+with_plugin=
+coveralls_id=
+
+while true; do
+  case "$1" in
+    --with-plugin)
+      with_plugin=yes
+      shift
+      ;;
+    --coveralls-id)
+      coveralls_id="$2"
+      shift 2
+      ;;
+    *)
+      break
+      ;;
+  esac
+done
+
+if [ -n "$with_plugin" ]; then
+  cargo test --manifest-path regex_macros/Cargo.toml --no-run --verbose
+  kcov \
+    --verify \
+    --include-pattern '/regex/src/' \
+    "$tmpdir/plugin" \
+    $(ls -t ./regex_macros/target/debug/plugin-* | head -n1)
+fi
+
+cargo test --no-run --verbose --jobs 4
+for t in ${tests[@]}; do
+  kcov \
+    --verify \
+    --include-pattern '/regex/src/' \
+    "$tmpdir/$t" \
+    $(find ./target/debug -executable -wholename "./target/debug/$t-*" | head -n1)
+done
+
+if [ -n "$coveralls_id" ]; then
+  kcov --verify --coveralls-id=$coveralls_id --merge target/cov "$tmpdir"/*
+else
+  kcov --verify --merge target/cov "$tmpdir"/*
+fi
diff --git a/third_party/rust/regex-0.2.2/ci/run-shootout-test b/third_party/rust/regex-0.2.2/ci/run-shootout-test
new file mode 100755
index 000000000000..5d1dc1d52087
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/ci/run-shootout-test
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -e
+
+cargo build --example shootout-regex-dna
+diff \
+  ./examples/regexdna-output.txt \
+  <(./target/debug/examples/shootout-regex-dna < ./examples/regexdna-input.txt)
+
+cargo build --example shootout-regex-dna-single
+diff \
+  ./examples/regexdna-output.txt \
+  <(./target/debug/examples/shootout-regex-dna-single < ./examples/regexdna-input.txt)
+
+cargo build --example shootout-regex-dna-cheat
+diff \
+  ./examples/regexdna-output.txt \
+  <(./target/debug/examples/shootout-regex-dna-cheat < ./examples/regexdna-input.txt)
diff --git a/third_party/rust/regex-0.2.2/ci/script.sh b/third_party/rust/regex-0.2.2/ci/script.sh
new file mode 100755
index 000000000000..2b48aa5d7ff5
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/ci/script.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# This is the main CI script for testing the regex crate and its sub-crates.
+
+set -e
+
+# Builds the regex crate and runs tests.
+cargo build --verbose
+cargo doc --verbose
+if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  cargo build --verbose --manifest-path regex-debug/Cargo.toml
+  RUSTFLAGS="-C target-feature=+ssse3" cargo test --verbose --features 'simd-accel pattern' --jobs 4
+else
+  cargo test --verbose --jobs 4
+fi
+
+# Run a test that confirms the shootout benchmarks are correct.
+ci/run-shootout-test
+
+# Run tests on regex-syntax crate.
+cargo test --verbose --manifest-path regex-syntax/Cargo.toml
+cargo doc --verbose --manifest-path regex-syntax/Cargo.toml
+
+# Run tests on regex-capi crate.
+cargo build --verbose --manifest-path regex-capi/Cargo.toml
+(cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../target/debug ./test)
+(cd regex-capi/examples && ./compile && LD_LIBRARY_PATH=../target/debug ./iter)
+
+# Make sure benchmarks compile. Don't run them though because they take a
+# very long time.
+if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  for x in rust rust-bytes pcre1 onig; do
+    (cd bench && ./run $x --no-run)
+  done
+fi
diff --git a/third_party/rust/regex/examples/bug347.rs b/third_party/rust/regex-0.2.2/examples/bug347.rs
similarity index 100%
rename from third_party/rust/regex/examples/bug347.rs
rename to third_party/rust/regex-0.2.2/examples/bug347.rs
diff --git a/third_party/rust/regex-0.2.2/examples/regexdna-input.txt b/third_party/rust/regex-0.2.2/examples/regexdna-input.txt
new file mode 100644
index 000000000000..fb23263397d9
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/regexdna-input.txt
@@ -0,0 +1,1671 @@
+>ONE Homo sapiens alu
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
+GAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATC
+GCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGC
+GGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGG
+TCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAA
+AAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAG
+GAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACT
+CCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCC
+TGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAG
+ACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGC
+GTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGA
+ACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGA
+CAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCA
+CTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCA
+ACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCG
+CCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG
+AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTC
+CGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCG
+AGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACC
+CCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAG
+CTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAG
+CCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGG
+CCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATC
+ACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAA
+AAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGC
+TGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCC
+ACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGG
+CTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGG
+AGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATT
+AGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAA
+TCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGC
+CTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAA
+TCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAG
+CCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGT
+GGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCG
+GGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAG
+CGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG
+GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATG
+GTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGT
+AATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT
+GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCT
+CAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCG
+GGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTC
+TCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACT
+CGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAG
+ATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGG
+CGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTG
+AGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATA
+CAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGG
+CAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGC
+ACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCAC
+GCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTC
+GAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCG
+GGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCT
+TGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGG
+CGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCA
+GCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGG
+CCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGC
+GCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGG
+CGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGA
+CTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGG
+CCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAA
+ACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCC
+CAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGT
+GAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAA
+AGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGG
+ATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTAC
+TAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGA
+GGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGC
+GCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGG
+TGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC
+AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAA
+ATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGA
+GAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC
+AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTG
+TAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGAC
+CAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGT
+GGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC
+CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACA
+GAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACT
+TTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAAC
+ATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCC
+TGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAG
+GTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCG
+TCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAG
+GCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCC
+GTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCT
+ACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCC
+GAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCC
+GGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCAC
+CTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAA
+ATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTG
+AGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCAC
+TGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCT
+CACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAG
+TTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAG
+CCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATC
+GCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCT
+GGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATC
+CCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCC
+TGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGG
+CGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG
+AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCG
+AGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGG
+AGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGT
+GAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAA
+TCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGC
+AGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCA
+AAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGG
+CGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTC
+TACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCG
+GGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGAT
+CGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCG
+CGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAG
+GTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACA
+AAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCA
+GGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCAC
+TCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGC
+CTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA
+GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGG
+CGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTG
+AACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCG
+ACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGC
+ACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCC
+AACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGC
+GCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCG
+GAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACT
+CCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCC
+GAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAAC
+CCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA
+GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGA
+GCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAG
+GCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGAT
+CACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTA
+AAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGG
+CTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGC
+CACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTG
+GCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAG
+GAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAAT
+TAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGA
+ATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAG
+CCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTA
+ATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCA
+GCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG
+TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCC
+GGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGA
+GCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT
+GGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT
+GGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTG
+TAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGT
+TGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTC
+TCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGC
+GGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGT
+CTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTAC
+TCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGA
+GATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGG
+GCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCT
+GAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT
+ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAG
+GCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG
+CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCA
+CGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTT
+CGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCC
+GGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGC
+TTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGG
+GCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCC
+AGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTG
+GCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCG
+CGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAG
+GCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAG
+ACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAG
+GCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGA
+AACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATC
+CCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAG
+TGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAA
+AAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCG
+GATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTA
+CTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGG
+AGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCG
+CGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCG
+GTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGT
+CAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAA
+AATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGG
+AGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTC
+CAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCT
+GTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA
+CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG
+TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA
+CCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGAC
+AGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCAC
+TTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAA
+CATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGC
+CTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGA
+GGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCC
+GTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGA
+GGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCC
+CGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGC
+TACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGC
+CGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGC
+CGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCA
+CCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA
+AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCT
+GAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCA
+CTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGC
+TCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGA
+GTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTA
+GCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAAT
+CGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCC
+TGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAAT
+CCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGC
+CTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTG
+GCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGG
+GAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGC
+GAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG
+GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGG
+TGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTA
+ATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTG
+CAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTC
+AAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGG
+GCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCT
+CTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTC
+GGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGA
+TCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGC
+GCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGA
+GGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATAC
+AAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGC
+AGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCA
+CTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACG
+CCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCG
+AGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGG
+GCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTT
+GAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGC
+GACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAG
+CACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGC
+CAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCG
+CGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGC
+GGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGAC
+TCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGC
+CGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAA
+CCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCC
+AGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTG
+AGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG
+GAGGCTGAGGCAGGAGAATC
+>TWO IUB ambiguity codes
+cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
+tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
+NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
+cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
+gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
+HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
+tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
+tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
+acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
+tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
+gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
+accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
+RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
+tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
+cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
+ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
+actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
+YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
+KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
+aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
+aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
+gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
+tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
+tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
+ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
+ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
+BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
+aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
+tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
+cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
+aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
+tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
+aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
+gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
+ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
+taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
+ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
+gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
+gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
+tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
+tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
+taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
+cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
+aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
+cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
+ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
+attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
+ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
+attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
+tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
+aagacYRcaggattHaYgtKtaatgcVcaataMYacccatatcacgWDBtgaatcBaata
+cKcttRaRtgatgaBDacggtaattaaYtataStgVHDtDctgactcaaatKtacaatgc
+gYatBtRaDatHaactgtttatatDttttaaaKVccYcaaccNcBcgHaaVcattHctcg
+attaaatBtatgcaaaaatYMctSactHatacgaWacattacMBgHttcgaatVaaaaca
+BatatVtctgaaaaWtctRacgBMaatSgRgtgtcgactatcRtattaScctaStagKga
+DcWgtYtDDWKRgRtHatRtggtcgaHgggcgtattaMgtcagccaBggWVcWctVaaat
+tcgNaatcKWagcNaHtgaaaSaaagctcYctttRVtaaaatNtataaccKtaRgtttaM
+tgtKaBtRtNaggaSattHatatWactcagtgtactaKctatttgRYYatKatgtccgtR
+tttttatttaatatVgKtttgtatgtNtataRatWYNgtRtHggtaaKaYtKSDcatcKg
+taaYatcSRctaVtSMWtVtRWHatttagataDtVggacagVcgKWagBgatBtaaagNc
+aRtagcataBggactaacacRctKgttaatcctHgDgttKHHagttgttaatgHBtatHc
+DaagtVaBaRccctVgtgDtacRHSctaagagcggWYaBtSaKtHBtaaactYacgNKBa
+VYgtaacttagtVttcttaatgtBtatMtMtttaattaatBWccatRtttcatagVgMMt
+agctStKctaMactacDNYgKYHgaWcgaHgagattacVgtttgtRaSttaWaVgataat
+gtgtYtaStattattMtNgWtgttKaccaatagNYttattcgtatHcWtctaaaNVYKKt
+tWtggcDtcgaagtNcagatacgcattaagaccWctgcagcttggNSgaNcHggatgtVt
+catNtRaaBNcHVagagaaBtaaSggDaatWaatRccaVgggStctDaacataKttKatt
+tggacYtattcSatcttagcaatgaVBMcttDattctYaaRgatgcattttNgVHtKcYR
+aatRKctgtaaacRatVSagctgtWacBtKVatctgttttKcgtctaaDcaagtatcSat
+aWVgcKKataWaYttcccSaatgaaaacccWgcRctWatNcWtBRttYaattataaNgac
+acaatagtttVNtataNaYtaatRaVWKtBatKagtaatataDaNaaaaataMtaagaaS
+tccBcaatNgaataWtHaNactgtcDtRcYaaVaaaaaDgtttRatctatgHtgttKtga
+aNSgatactttcgagWaaatctKaaDaRttgtggKKagcDgataaattgSaacWaVtaNM
+acKtcaDaaatttctRaaVcagNacaScRBatatctRatcctaNatWgRtcDcSaWSgtt
+RtKaRtMtKaatgttBHcYaaBtgatSgaSWaScMgatNtctcctatttctYtatMatMt
+RRtSaattaMtagaaaaStcgVgRttSVaScagtgDtttatcatcatacRcatatDctta
+tcatVRtttataaHtattcYtcaaaatactttgVctagtaaYttagatagtSYacKaaac
+gaaKtaaatagataatSatatgaaatSgKtaatVtttatcctgKHaatHattagaaccgt
+YaaHactRcggSBNgtgctaaBagBttgtRttaaattYtVRaaaattgtaatVatttctc
+ttcatgBcVgtgKgaHaaatattYatagWacNctgaaMcgaattStagWaSgtaaKagtt
+ttaagaDgatKcctgtaHtcatggKttVDatcaaggtYcgccagNgtgcVttttagagat
+gctaccacggggtNttttaSHaNtatNcctcatSaaVgtactgBHtagcaYggYVKNgta
+KBcRttgaWatgaatVtagtcgattYgatgtaatttacDacSctgctaaaStttaWMagD
+aaatcaVYctccgggcgaVtaaWtStaKMgDtttcaaMtVgBaatccagNaaatcYRMBg
+gttWtaaScKttMWtYataRaDBMaDataatHBcacDaaKDactaMgagttDattaHatH
+taYatDtattDcRNStgaatattSDttggtattaaNSYacttcDMgYgBatWtaMagact
+VWttctttgYMaYaacRgHWaattgRtaagcattctMKVStatactacHVtatgatcBtV
+NataaBttYtSttacKgggWgYDtgaVtYgatDaacattYgatggtRDaVDttNactaSa
+MtgNttaacaaSaBStcDctaccacagacgcaHatMataWKYtaYattMcaMtgSttDag
+cHacgatcaHttYaKHggagttccgatYcaatgatRaVRcaagatcagtatggScctata
+ttaNtagcgacgtgKaaWaactSgagtMYtcttccaKtStaacggMtaagNttattatcg
+tctaRcactctctDtaacWYtgaYaSaagaWtNtatttRacatgNaatgttattgWDDcN
+aHcctgaaHacSgaataaRaataMHttatMtgaSDSKatatHHaNtacagtccaYatWtc
+actaactatKDacSaStcggataHgYatagKtaatKagStaNgtatactatggRHacttg
+tattatgtDVagDVaRctacMYattDgtttYgtctatggtKaRSttRccRtaaccttaga
+gRatagSaaMaacgcaNtatgaaatcaRaagataatagatactcHaaYKBctccaagaRa
+BaStNagataggcgaatgaMtagaatgtcaKttaaatgtaWcaBttaatRcggtgNcaca
+aKtttScRtWtgcatagtttWYaagBttDKgcctttatMggNttattBtctagVtacata
+aaYttacacaaRttcYtWttgHcaYYtaMgBaBatctNgcDtNttacgacDcgataaSat
+YaSttWtcctatKaatgcagHaVaacgctgcatDtgttaSataaaaYSNttatagtaNYt
+aDaaaNtggggacttaBggcHgcgtNtaaMcctggtVtaKcgNacNtatVaSWctWtgaW
+cggNaBagctctgaYataMgaagatBSttctatacttgtgtKtaattttRagtDtacata
+tatatgatNHVgBMtKtaKaNttDHaagatactHaccHtcatttaaagttVaMcNgHata
+tKtaNtgYMccttatcaaNagctggacStttcNtggcaVtattactHaSttatgNMVatt
+MMDtMactattattgWMSgtHBttStStgatatRaDaagattttctatMtaaaaaggtac
+taaVttaSacNaatactgMttgacHaHRttgMacaaaatagttaatatWKRgacDgaRta
+tatttattatcYttaWtgtBRtWatgHaaattHataagtVaDtWaVaWtgStcgtMSgaS
+RgMKtaaataVacataatgtaSaatttagtcgaaHtaKaatgcacatcggRaggSKctDc
+agtcSttcccStYtccRtctctYtcaaKcgagtaMttttcRaYDttgttatctaatcata
+NctctgctatcaMatactataggDaHaaSttMtaDtcNatataattctMcStaaBYtaNa
+gatgtaatHagagSttgWHVcttatKaYgDctcttggtgttMcRaVgSgggtagacaata
+aDtaattSaDaNaHaBctattgNtaccaaRgaVtKNtaaYggHtaKKgHcatctWtctDt
+ttctttggSDtNtaStagttataaacaattgcaBaBWggHgcaaaBtYgctaatgaaatW
+cDcttHtcMtWWattBHatcatcaaatctKMagtDNatttWaBtHaaaNgMttaaStagt
+tctctaatDtcRVaYttgttMtRtgtcaSaaYVgSWDRtaatagctcagDgcWWaaaBaa
+RaBctgVgggNgDWStNaNBKcBctaaKtttDcttBaaggBttgaccatgaaaNgttttt
+tttatctatgttataccaaDRaaSagtaVtDtcaWatBtacattaWacttaSgtattggD
+gKaaatScaattacgWcagKHaaccaYcRcaRttaDttRtttHgaHVggcttBaRgtccc
+tDatKaVtKtcRgYtaKttacgtatBtStaagcaattaagaRgBagSaattccSWYttta
+ttVaataNctgHgttaaNBgcVYgtRtcccagWNaaaacaDNaBcaaaaRVtcWMgBagM
+tttattacgDacttBtactatcattggaaatVccggttRttcatagttVYcatYaSHaHc
+ttaaagcNWaHataaaRWtctVtRYtagHtaaaYMataHYtNBctNtKaatattStgaMc
+BtRgctaKtgcScSttDgYatcVtggaaKtaagatWccHccgKYctaNNctacaWctttt
+gcRtgtVcgaKttcMRHgctaHtVaataaDtatgKDcttatBtDttggNtacttttMtga
+acRattaaNagaactcaaaBBVtcDtcgaStaDctgaaaSgttMaDtcgttcaccaaaag
+gWtcKcgSMtcDtatgtttStaaBtatagDcatYatWtaaaBacaKgcaDatgRggaaYc
+taRtccagattDaWtttggacBaVcHtHtaacDacYgtaatataMagaatgHMatcttat
+acgtatttttatattacHactgttataMgStYaattYaccaattgagtcaaattaYtgta
+tcatgMcaDcgggtcttDtKgcatgWRtataatatRacacNRBttcHtBgcRttgtgcgt
+catacMtttBctatctBaatcattMttMYgattaaVYatgDaatVagtattDacaacDMa
+tcMtHcccataagatgBggaccattVWtRtSacatgctcaaggggYtttDtaaNgNtaaB
+atggaatgtctRtaBgBtcNYatatNRtagaacMgagSaSDDSaDcctRagtVWSHtVSR
+ggaacaBVaccgtttaStagaacaMtactccagtttVctaaRaaHttNcttagcaattta
+ttaatRtaaaatctaacDaBttggSagagctacHtaaRWgattcaaBtctRtSHaNtgta
+cattVcaHaNaagtataccacaWtaRtaaVKgMYaWgttaKggKMtKcgWatcaDatYtK
+SttgtacgaccNctSaattcDcatcttcaaaDKttacHtggttHggRRaRcaWacaMtBW
+VHSHgaaMcKattgtaRWttScNattBBatYtaNRgcggaagacHSaattRtttcYgacc
+BRccMacccKgatgaacttcgDgHcaaaaaRtatatDtatYVtttttHgSHaSaatagct
+NYtaHYaVYttattNtttgaaaYtaKttWtctaNtgagaaaNctNDctaaHgttagDcRt
+tatagccBaacgcaRBtRctRtggtaMYYttWtgataatcgaataattattataVaaaaa
+ttacNRVYcaaMacNatRttcKatMctgaagactaattataaYgcKcaSYaatMNctcaa
+cgtgatttttBacNtgatDccaattattKWWcattttatatatgatBcDtaaaagttgaa
+VtaHtaHHtBtataRBgtgDtaataMttRtDgDcttattNtggtctatctaaBcatctaR
+atgNacWtaatgaagtcMNaacNgHttatactaWgcNtaStaRgttaaHacccgaYStac
+aaaatWggaYaWgaattattcMaactcBKaaaRVNcaNRDcYcgaBctKaacaaaaaSgc
+tccYBBHYaVagaatagaaaacagYtctVccaMtcgtttVatcaatttDRtgWctagtac
+RttMctgtDctttcKtWttttataaatgVttgBKtgtKWDaWagMtaaagaaattDVtag
+gttacatcatttatgtcgMHaVcttaBtVRtcgtaYgBRHatttHgaBcKaYWaatcNSc
+tagtaaaaatttacaatcactSWacgtaatgKttWattagttttNaggtctcaagtcact
+attcttctaagKggaataMgtttcataagataaaaatagattatDgcBVHWgaBKttDgc
+atRHaagcaYcRaattattatgtMatatattgHDtcaDtcaaaHctStattaatHaccga
+cNattgatatattttgtgtDtRatagSacaMtcRtcattcccgacacSattgttKaWatt
+NHcaacttccgtttSRtgtctgDcgctcaaMagVtBctBMcMcWtgtaacgactctcttR
+ggRKSttgYtYatDccagttDgaKccacgVatWcataVaaagaataMgtgataaKYaaat
+cHDaacgataYctRtcYatcgcaMgtNttaBttttgatttaRtStgcaacaaaataccVg
+aaDgtVgDcStctatatttattaaaaRKDatagaaagaKaaYYcaYSgKStctccSttac
+agtcNactttDVttagaaagMHttRaNcSaRaMgBttattggtttaRMggatggcKDgWR
+tNaataataWKKacttcKWaaagNaBttaBatMHtccattaacttccccYtcBcYRtaga
+ttaagctaaYBDttaNtgaaaccHcaRMtKtaaHMcNBttaNaNcVcgVttWNtDaBatg
+ataaVtcWKcttRggWatcattgaRagHgaattNtatttctctattaattaatgaDaaMa
+tacgttgggcHaYVaaNaDDttHtcaaHtcVVDgBVagcMacgtgttaaBRNtatRtcag
+taagaggtttaagacaVaaggttaWatctccgtVtaDtcDatttccVatgtacNtttccg
+tHttatKgScBatgtVgHtYcWagcaKtaMYaaHgtaattaSaHcgcagtWNaatNccNN
+YcacgVaagaRacttctcattcccRtgtgtaattagcSttaaStWaMtctNNcSMacatt
+ataaactaDgtatWgtagtttaagaaaattgtagtNagtcaataaatttgatMMYactaa
+tatcggBWDtVcYttcDHtVttatacYaRgaMaacaStaatcRttttVtagaDtcacWat
+ttWtgaaaagaaagNRacDtttStVatBaDNtaactatatcBSMcccaSttccggaMatg
+attaaWatKMaBaBatttgataNctgttKtVaagtcagScgaaaDggaWgtgttttKtWt
+atttHaatgtagttcactaaKMagttSYBtKtaYgaactcagagRtatagtVtatcaaaW
+YagcgNtaDagtacNSaaYDgatBgtcgataacYDtaaactacagWDcYKaagtttatta
+gcatcgagttKcatDaattgattatDtcagRtWSKtcgNtMaaaaacaMttKcaWcaaSV
+MaaaccagMVtaMaDtMaHaBgaacataBBVtaatVYaNSWcSgNtDNaaKacacBttta
+tKtgtttcaaHaMctcagtaacgtcgYtactDcgcctaNgagagcYgatattttaaattt
+ccattttacatttDaaRctattttWctttacgtDatYtttcagacgcaaVttagtaaKaa
+aRtgVtccataBggacttatttgtttaWNtgttVWtaWNVDaattgtatttBaagcBtaa
+BttaaVatcHcaVgacattccNggtcgacKttaaaRtagRtctWagaYggtgMtataatM
+tgaaRttattttgWcttNtDRRgMDKacagaaaaggaaaRStcccagtYccVattaNaaK
+StNWtgacaVtagaagcttSaaDtcacaacgDYacWDYtgtttKatcVtgcMaDaSKStV
+cgtagaaWaKaagtttcHaHgMgMtctataagBtKaaaKKcactggagRRttaagaBaaN
+atVVcgRcKSttDaactagtSttSattgttgaaRYatggttVttaataaHttccaagDtg
+atNWtaagHtgcYtaactRgcaatgMgtgtRaatRaNaacHKtagactactggaatttcg
+ccataacgMctRgatgttaccctaHgtgWaYcactcacYaattcttaBtgacttaaacct
+gYgaWatgBttcttVttcgttWttMcNYgtaaaatctYgMgaaattacNgaHgaacDVVM
+tttggtHtctaaRgtacagacgHtVtaBMNBgattagcttaRcttacaHcRctgttcaaD
+BggttKaacatgKtttYataVaNattccgMcgcgtagtRaVVaattaKaatggttRgaMc
+agtatcWBttNtHagctaatctagaaNaaacaYBctatcgcVctBtgcaaagDgttVtga
+HtactSNYtaaNccatgtgDacgaVtDcgKaRtacDcttgctaagggcagMDagggtBWR
+tttSgccttttttaacgtcHctaVtVDtagatcaNMaVtcVacatHctDWNaataRgcgt
+aVHaggtaaaaSgtttMtattDgBtctgatSgtRagagYtctSaKWaataMgattRKtaa
+catttYcgtaacacattRWtBtcggtaaatMtaaacBatttctKagtcDtttgcBtKYYB
+aKttctVttgttaDtgattttcttccacttgSaaacggaaaNDaattcYNNaWcgaaYat
+tttMgcBtcatRtgtaaagatgaWtgaccaYBHgaatagataVVtHtttVgYBtMctaMt
+cctgaDcYttgtccaaaRNtacagcMctKaaaggatttacatgtttaaWSaYaKttBtag
+DacactagctMtttNaKtctttcNcSattNacttggaacaatDagtattRtgSHaataat
+gccVgacccgatactatccctgtRctttgagaSgatcatatcgDcagWaaHSgctYYWta
+tHttggttctttatVattatcgactaagtgtagcatVgtgHMtttgtttcgttaKattcM
+atttgtttWcaaStNatgtHcaaaDtaagBaKBtRgaBgDtSagtatMtaacYaatYtVc
+KatgtgcaacVaaaatactKcRgtaYtgtNgBBNcKtcttaccttKgaRaYcaNKtactt
+tgagSBtgtRagaNgcaaaNcacagtVtttHWatgttaNatBgtttaatNgVtctgaata
+tcaRtattcttttttttRaaKcRStctcggDgKagattaMaaaKtcaHacttaataataK
+taRgDtKVBttttcgtKaggHHcatgttagHggttNctcgtatKKagVagRaaaggaaBt
+NatttVKcRttaHctaHtcaaatgtaggHccaBataNaNaggttgcWaatctgatYcaaa
+HaatWtaVgaaBttagtaagaKKtaaaKtRHatMaDBtBctagcatWtatttgWttVaaa
+ScMNattRactttgtYtttaaaagtaagtMtaMaSttMBtatgaBtttaKtgaatgagYg
+tNNacMtcNRacMMHcttWtgtRtctttaacaacattattcYaMagBaacYttMatcttK
+cRMtgMNccattaRttNatHaHNaSaaHMacacaVaatacaKaSttHatattMtVatWga
+ttttttaYctttKttHgScWaacgHtttcaVaaMgaacagNatcgttaacaaaaagtaca
+HBNaattgttKtcttVttaaBtctgctacgBgcWtttcaggacacatMgacatcccagcg
+gMgaVKaBattgacttaatgacacacaaaaaatRKaaBctacgtRaDcgtagcVBaacDS
+BHaaaaSacatatacagacRNatcttNaaVtaaaataHattagtaaaaSWccgtatWatg
+gDttaactattgcccatcttHaSgYataBttBaactattBtcHtgatcaataSttaBtat
+KSHYttWggtcYtttBttaataccRgVatStaHaKagaatNtagRMNgtcttYaaSaact
+cagDSgagaaYtMttDtMRVgWKWtgMaKtKaDttttgactatacataatcNtatNaHat
+tVagacgYgatatatttttgtStWaaatctWaMgagaRttRatacgStgattcttaagaD
+taWccaaatRcagcagaaNKagtaaDggcgccBtYtagSBMtactaaataMataBSacRM
+gDgattMMgtcHtcaYDtRaDaacggttDaggcMtttatgttaNctaattaVacgaaMMt
+aatDccSgtattgaRtWWaccaccgagtactMcgVNgctDctaMScatagcgtcaactat
+acRacgHRttgctatttaatgaattataYKttgtaagWgtYttgcHgMtaMattWaWVta
+RgcttgYgttBHtYataSccStBtgtagMgtDtggcVaaSBaatagDttgBgtctttctc
+attttaNagtHKtaMWcYactVcgcgtatMVtttRacVagDaatcttgctBBcRDgcaac
+KttgatSKtYtagBMagaRtcgBattHcBWcaactgatttaatttWDccatttatcgagS
+KaWttataHactaHMttaatHtggaHtHagaatgtKtaaRactgtttMatacgatcaagD
+gatKaDctataMggtHDtggHacctttRtatcttYattttgacttgaaSaataaatYcgB
+aaaaccgNatVBttMacHaKaataagtatKgtcaagactcttaHttcggaattgttDtct
+aaccHttttWaaatgaaatataaaWattccYDtKtaaaacggtgaggWVtctattagtga
+ctattaagtMgtttaagcatttgSgaaatatccHaaggMaaaattttcWtatKctagDtY
+tMcctagagHcactttactatacaaacattaacttaHatcVMYattYgVgtMttaaRtga
+aataaDatcaHgtHHatKcDYaatcttMtNcgatYatgSaMaNtcttKcWataScKggta
+tcttacgcttWaaagNatgMgHtctttNtaacVtgttcMaaRatccggggactcMtttaY
+MtcWRgNctgNccKatcttgYDcMgattNYaRagatHaaHgKctcataRDttacatBatc
+cattgDWttatttaWgtcggagaaaaatacaatacSNtgggtttccttacSMaagBatta
+caMaNcactMttatgaRBacYcYtcaaaWtagctSaacttWgDMHgaggatgBVgcHaDt
+ggaactttggtcNatNgtaKaBcccaNtaagttBaacagtatacDYttcctNgWgcgSMc
+acatStctHatgRcNcgtacacaatRttMggaNKKggataaaSaYcMVcMgtaMaHtgat
+tYMatYcggtcttcctHtcDccgtgRatcattgcgccgatatMaaYaataaYSggatagc
+gcBtNtaaaScaKgttBgagVagttaKagagtatVaactaSacWactSaKatWccaKaaa
+atBKgaaKtDMattttgtaaatcRctMatcaaMagMttDgVatggMaaWgttcgaWatga
+aatttgRtYtattaWHKcRgctacatKttctaccaaHttRatctaYattaaWatVNccat
+NgagtcKttKataStRaatatattcctRWatDctVagttYDgSBaatYgttttgtVaatt
+taatagcagMatRaacttBctattgtMagagattaaactaMatVtHtaaatctRgaaaaa
+aaatttWacaacaYccYDSaattMatgaccKtaBKWBattgtcaagcHKaagttMMtaat
+ttcKcMagNaaKagattggMagaggtaatttYacatcWaaDgatMgKHacMacgcVaaca
+DtaDatatYggttBcgtatgWgaSatttgtagaHYRVacaRtctHaaRtatgaactaata
+tctSSBgggaaHMWtcaagatKgagtDaSatagttgattVRatNtctMtcSaagaSHaat
+aNataataRaaRgattctttaataaagWaRHcYgcatgtWRcttgaaggaMcaataBRaa
+ccagStaaacNtttcaatataYtaatatgHaDgcStcWttaacctaRgtYaRtataKtgM
+ttttatgactaaaatttacYatcccRWtttHRtattaaatgtttatatttgttYaatMca
+RcSVaaDatcgtaYMcatgtagacatgaaattgRtcaaYaaYtRBatKacttataccaNa
+aattVaBtctggacaagKaaYaaatatWtMtatcYaaVNtcgHaactBaagKcHgtctac
+aatWtaDtSgtaHcataHtactgataNctRgttMtDcDttatHtcgtacatcccaggStt
+aBgtcacacWtccNMcNatMVaVgtccDYStatMaccDatggYaRKaaagataRatttHK
+tSaaatDgataaacttaHgttgVBtcttVttHgDacgaKatgtatatNYataactctSat
+atatattgcHRRYttStggaactHgttttYtttaWtatMcttttctatctDtagVHYgMR
+BgtHttcctaatYRttKtaagatggaVRataKDctaMtKBNtMtHNtWtttYcVtattMc
+gRaacMcctNSctcatttaaagDcaHtYccSgatgcaatYaaaaDcttcgtaWtaattct
+cgttttScttggtaatctttYgtctaactKataHacctMctcttacHtKataacacagcN
+RatgKatttttSaaatRYcgDttaMRcgaaattactMtgcgtaagcgttatBtttttaat
+taagtNacatHgttcRgacKcBBtVgatKttcgaBaatactDRgtRtgaNacWtcacYtt
+aaKcgttctHaKttaNaMgWgWaggtctRgaKgWttSttBtDcNtgtttacaaatYcDRt
+gVtgcctattcNtctaaaDMNttttNtggctgagaVctDaacVtWccaagtaacacaNct
+gaScattccDHcVBatcgatgtMtaatBgHaatDctMYgagaatgYWKcctaatNaStHa
+aaKccgHgcgtYaaYtattgtStgtgcaaRtattaKatattagaWVtcaMtBagttatta
+gNaWHcVgcaattttDcMtgtaRHVYtHtctgtaaaaHVtMKacatcgNaatttMatatg
+ttgttactagWYtaRacgataKagYNKcattataNaRtgaacKaYgcaaYYacaNccHat
+MatDcNgtHttRaWttagaaDcaaaaaatagggtKDtStaDaRtaVtHWKNtgtattVct
+SVgRgataDaRaWataBgaagaaKtaataaYgDcaStaNgtaDaaggtattHaRaWMYaY
+aWtggttHYgagVtgtgcttttcaaDKcagVcgttagacNaaWtagtaataDttctggtt
+VcatcataaagtgKaaaNaMtaBBaattaatWaattgctHaVKaSgDaaVKaHtatatat
+HatcatSBagNgHtatcHYMHgttDgtaHtBttWatcgtttaRaattgStKgSKNWKatc
+agDtctcagatttctRtYtBatBgHHtKaWtgYBgacVVWaKtacKcDttKMaKaVcggt
+gttataagaataaHaatattagtataatMHgttYgaRttagtaRtcaaVatacggtcMcg
+agtaaRttacWgactKRYataaaagSattYaWgagatYagKagatgSaagKgttaatMgg
+tataatgttWYttatgagaaacctNVataatHcccKtDctcctaatactggctHggaSag
+gRtKHaWaattcgSatMatttagaggcYtctaMcgctcataSatatgRagacNaaDagga
+VBagaYttKtacNaKgtSYtagttggaWcatcWttaatctatgaVtcgtgtMtatcaYcg
+tRccaaYgDctgcMgtgtWgacWtgataacacgcgctBtgttaKtYDtatDcatcagKaV
+MctaatcttgVcaaRgcRMtDcgattaHttcaNatgaatMtactacVgtRgatggaWttt
+actaaKatgagSaaKggtaNtactVaYtaaKRagaacccacaMtaaMtKtatBcttgtaa
+WBtMctaataaVcDaaYtcRHBtcgttNtaaHatttBNgRStVDattBatVtaagttaYa
+tVattaagaBcacggtSgtVtatttaRattgatgtaHDKgcaatattKtggcctatgaWD
+KRYcggattgRctatNgatacaatMNttctgtcRBYRaaaHctNYattcHtaWcaattct
+BtMKtVgYataatMgYtcagcttMDataVtggRtKtgaatgccNcRttcaMtRgattaac
+attRcagcctHtWMtgtDRagaKaBtgDttYaaaaKatKgatctVaaYaacWcgcatagB
+VtaNtRtYRaggBaaBtgKgttacataagagcatgtRattccacttaccatRaaatgWgD
+aMHaYVgVtaSctatcgKaatatattaDgacccYagtgtaYNaaatKcagtBRgagtcca
+tgKgaaaccBgaagBtgSttWtacgatWHaYatcgatttRaaNRgcaNaKVacaNtDgat
+tgHVaatcDaagcgtatgcNttaDataatcSataaKcaataaHWataBtttatBtcaKtK
+tatagttaDgSaYctacaRatNtaWctSaatatttYaKaKtaccWtatcRagacttaYtt
+VcKgSDcgagaagatccHtaattctSttatggtKYgtMaHagVaBRatttctgtRgtcta
+tgggtaHKgtHacHtSYacgtacacHatacKaaBaVaccaDtatcSaataaHaagagaat
+ScagactataaRttagcaaVcaHataKgDacatWccccaagcaBgagWatctaYttgaaa
+tctVNcYtttWagHcgcgcDcVaaatgttKcHtNtcaatagtgtNRaactttttcaatgg
+WgBcgDtgVgtttctacMtaaataaaRggaaacWaHttaRtNtgctaaRRtVBctYtVta
+tDcattDtgaccYatagatYRKatNYKttNgcctagtaWtgaactaMVaacctgaStttc
+tgaKVtaaVaRKDttVtVctaDNtataaaDtccccaagtWtcgatcactDgYaBcatcct
+MtVtacDaaBtYtMaKNatNtcaNacgDatYcatcgcaRatWBgaacWttKttagYtaat
+tcggttgSWttttDWctttacYtatatWtcatDtMgtBttgRtVDggttaacYtacgtac
+atgaattgaaWcttMStaDgtatattgaDtcRBcattSgaaVBRgagccaaKtttcDgcg
+aSMtatgWattaKttWtgDBMaggBBttBaatWttRtgcNtHcgttttHtKtcWtagHSt
+aacagttgatatBtaWSaWggtaataaMttaKacDaatactcBttcaatatHttcBaaSa
+aatYggtaRtatNtHcaatcaHtagVtgtattataNggaMtcttHtNagctaaaggtaga
+YctMattNaMVNtcKtactBKcaHHcBttaSagaKacataYgctaKaYgttYcgacWVtt
+WtSagcaacatcccHaccKtcttaacgaKttcacKtNtacHtatatRtaaatacactaBt
+ttgaHaRttggttWtatYagcatYDatcggagagcWBataagRtacctataRKgtBgatg
+aDatataSttagBaHtaatNtaDWcWtgtaattacagKttcNtMagtattaNgtctcgtc
+ctcttBaHaKcKccgtRcaaYagSattaagtKataDatatatagtcDtaacaWHcaKttD
+gaaRcgtgYttgtcatatNtatttttatggccHtgDtYHtWgttatYaacaattcaWtat
+NgctcaaaSttRgctaatcaaatNatcgtttaBtNNVtgttataagcaaagattBacgtD
+atttNatttaaaDcBgtaSKgacgtagataatttcHMVNttgttBtDtgtaWKaaRMcKM
+tHtaVtagataWctccNNaSWtVaHatctcMgggDgtNHtDaDttatatVWttgttattt
+aacctttcacaaggaSaDcggttttttatatVtctgVtaacaStDVaKactaMtttaSNa
+gtgaaattaNacttSKctattcctctaSagKcaVttaagNaVcttaVaaRNaHaaHttat
+gtHttgtgatMccaggtaDcgaccgtWgtWMtttaHcRtattgScctatttKtaaccaag
+tYagaHgtWcHaatgccKNRtttagtMYSgaDatctgtgaWDtccMNcgHgcaaacNDaa
+aRaStDWtcaaaaHKtaNBctagBtgtattaactaattttVctagaatggcWSatMaccc
+ttHttaSgSgtgMRcatRVKtatctgaaaccDNatYgaaVHNgatMgHRtacttaaaRta
+tStRtDtatDttYatattHggaBcttHgcgattgaKcKtttcRataMtcgaVttWacatN
+catacctRataDDatVaWNcggttgaHtgtMacVtttaBHtgagVttMaataattatgtt
+cttagtttgtgcDtSatttgBtcaacHattaaBagVWcgcaSYttMgcttacYKtVtatc
+aYaKctgBatgcgggcYcaaaaacgNtctagKBtattatctttKtaVttatagtaYtRag
+NtaYataaVtgaatatcHgcaaRataHtacacatgtaNtgtcgYatWMatttgaactacR
+ctaWtWtatacaatctBatatgYtaagtatgtgtatSttactVatcttYtaBcKgRaSgg
+RaaaaatgcagtaaaWgtaRgcgataatcBaataccgtatttttccatcNHtatWYgatH
+SaaaDHttgctgtccHtggggcctaataatttttctatattYWtcattBtgBRcVttaVM
+RSgctaatMagtYtttaaaaatBRtcBttcaaVtaacagctccSaaSttKNtHtKYcagc
+agaaaccccRtttttaaDcDtaStatccaagcgctHtatcttaDRYgatDHtWcaaaBcW
+gKWHttHataagHacgMNKttMKHccaYcatMVaacgttaKgYcaVaaBtacgcaacttt
+MctaaHaatgtBatgagaSatgtatgSRgHgWaVWgataaatatttccKagVgataattW
+aHNcYggaaatgctHtKtaDtctaaagtMaatVDVactWtSaaWaaMtaHtaSKtcBRaN
+cttStggtBttacNagcatagRgtKtgcgaacaacBcgKaatgataagatgaaaattgta
+ctgcgggtccHHWHaaNacaBttNKtKtcaaBatatgctaHNgtKcDWgtttatNgVDHg
+accaacWctKaaggHttgaRgYaatHcaBacaatgagcaaattactgtaVaaYaDtagat
+tgagNKggtggtgKtWKaatacagDRtatRaMRtgattDggtcaaYRtatttNtagaDtc
+acaaSDctDtataatcgtactaHttatacaatYaacaaHttHatHtgcgatRRttNgcat
+SVtacWWgaaggagtatVMaVaaattScDDKNcaYBYaDatHgtctatBagcaacaagaa
+tgagaaRcataaKNaRtBDatcaaacgcattttttaaBtcSgtacaRggatgtMNaattg
+gatatWtgagtattaaaVctgcaYMtatgatttttYgaHtgtcttaagWBttHttgtctt
+attDtcgtatWtataataSgctaHagcDVcNtaatcaagtaBDaWaDgtttagYctaNcc
+DtaKtaHcttaataacccaRKtacaVaatNgcWRaMgaattatgaBaaagattVYaHMDc
+aDHtcRcgYtcttaaaWaaaVKgatacRtttRRKYgaatacaWVacVcRtatMacaBtac
+tggMataaattttHggNagSctacHgtBagcgtcgtgattNtttgatSaaggMttctttc
+ttNtYNagBtaaacaaatttMgaccttacataattgYtcgacBtVMctgStgMDtagtaR
+ctHtatgttcatatVRNWataDKatWcgaaaaagttaaaagcacgHNacgtaatctttMR
+tgacttttDacctataaacgaaatatgattagaactccSYtaBctttaataacWgaaaYa
+tagatgWttcatKtNgatttttcaagHtaYgaaRaDaagtaggagcttatVtagtctttc
+attaaaatcgKtattaRttacagVaDatgcatVgattgggtctttHVtagKaaRBtaHta
+aggccccaaaaKatggtttaMWgtBtaaacttcactttKHtcgatctccctaYaBacMgt
+cttBaBaNgcgaaacaatctagtHccHtKttcRtRVttccVctttcatacYagMVtMcag
+aMaaacaataBctgYtaatRaaagattaaccatVRatHtaRagcgcaBcgDttStttttc
+VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa
+catYaRRcVRHctKtcgacKttaaVctaDaatgttMggRcWaacttttHaDaKaDaBctg
+taggcgtttaHBccatccattcNHtDaYtaataMttacggctNVaacDattgatatttta
+cVttSaattacaaRtataNDgacVtgaacataVRttttaDtcaaacataYDBtttaatBa
+DtttYDaDaMccMttNBttatatgagaaMgaNtattHccNataattcaHagtgaaggDga
+tgtatatatgYatgaStcataaBStWacgtcccataRMaaDattggttaaattcMKtctM
+acaBSactcggaatDDgatDgcWctaacaccgggaVcacWKVacggtaNatatacctMta
+tgatagtgcaKagggVaDtgtaacttggagtcKatatcgMcttRaMagcattaBRaStct
+YSggaHYtacaactMBaagDcaBDRaaacMYacaHaattagcattaaaHgcgctaaggSc
+cKtgaaKtNaBtatDDcKBSaVtgatVYaagVtctSgMctacgttaacWaaattctSgtD
+actaaStaaattgcagBBRVctaatatacctNttMcRggctttMttagacRaHcaBaacV
+KgaataHttttMgYgattcYaNRgttMgcVaaacaVVcDHaatttgKtMYgtatBtVVct
+WgVtatHtacaaHttcacgatagcagtaaNattBatatatttcVgaDagcggttMaagtc
+ScHagaaatgcYNggcgtttttMtStggtRatctacttaaatVVtBacttHNttttaRca
+aatcacagHgagagtMgatcSWaNRacagDtatactaaDKaSRtgattctccatSaaRtt
+aaYctacacNtaRtaactggatgaccYtacactttaattaattgattYgttcagDtNKtt
+agDttaaaaaaaBtttaaNaYWKMBaaaacVcBMtatWtgBatatgaacVtattMtYatM
+NYDKNcKgDttDaVtaaaatgggatttctgtaaatWtctcWgtVVagtcgRgacttcccc
+taDcacagcRcagagtgtWSatgtacatgttaaSttgtaaHcgatgggMagtgaacttat
+RtttaVcaccaWaMgtactaatSSaHtcMgaaYtatcgaaggYgggcgtgaNDtgttMNg
+aNDMtaattcgVttttaacatgVatgtWVMatatcaKgaaattcaBcctccWcttgaaWH
+tWgHtcgNWgaRgctcBgSgaattgcaaHtgattgtgNagtDttHHgBttaaWcaaWagc
+aSaHHtaaaVctRaaMagtaDaatHtDMtcVaWMtagSagcttHSattaacaaagtRacM
+tRtctgttagcMtcaBatVKtKtKacgagaSNatSactgtatatcBctgagVtYactgta
+aattaaaggcYgDHgtaacatSRDatMMccHatKgttaacgactKtgKagtcttcaaHRV
+tccttKgtSataatttacaactggatDNgaacttcaRtVaagDcaWatcBctctHYatHa
+DaaatttagYatSatccaWtttagaaatVaacBatHcatcgtacaatatcgcNYRcaata
+YaRaYtgattVttgaatgaVaactcRcaNStgtgtattMtgaggtNttBaDRcgaaaagc
+tNgBcWaWgtSaDcVtgVaatMKBtttcgtttctaaHctaaagYactgMtatBDtcStga
+ccgtSDattYaataHctgggaYYttcggttaWaatctggtRagWMaDagtaacBccacta
+cgHWMKaatgatWatcctgHcaBaSctVtcMtgtDttacctaVgatYcWaDRaaaaRtag
+atcgaMagtggaRaWctctgMgcWttaagKBRtaaDaaWtctgtaagYMttactaHtaat
+cttcataacggcacBtSgcgttNHtgtHccatgttttaaagtatcgaKtMttVcataYBB
+aKtaMVaVgtattNDSataHcagtWMtaggtaSaaKgttgBtVtttgttatcatKcgHac
+acRtctHatNVagSBgatgHtgaRaSgttRcctaacaaattDNttgacctaaYtBgaaaa
+tagttattactcttttgatgtNNtVtgtatMgtcttRttcatttgatgacacttcHSaaa
+ccaWWDtWagtaRDDVNacVaRatgttBccttaatHtgtaaacStcVNtcacaSRttcYa
+gacagaMMttttgMcNttBcgWBtactgVtaRttctccaaYHBtaaagaBattaYacgat
+ttacatctgtaaMKaRYtttttactaaVatWgctBtttDVttctggcDaHaggDaagtcg
+aWcaagtagtWttHtgKtVataStccaMcWcaagataagatcactctHatgtcYgaKcat
+cagatactaagNSStHcctRRNtattgtccttagttagMVgtatagactaactctVcaat
+MctgtttgtgttgccttatWgtaBVtttctggMcaaKgDWtcgtaaYStgSactatttHg
+atctgKagtagBtVacRaagRtMctatgggcaaaKaaaatacttcHctaRtgtDcttDat
+taggaaatttcYHaRaaBttaatggcacKtgctHVcaDcaaaVDaaaVcgMttgtNagcg
+taDWgtcgttaatDgKgagcSatatcSHtagtagttggtgtHaWtaHKtatagctgtVga
+ttaBVaatgaataagtaatVatSttaHctttKtttgtagttaccttaatcgtagtcctgB
+cgactatttVcMacHaaaggaatgDatggKtaHtgStatattaaSagctWcctccRtata
+BaDYcgttgcNaagaggatRaaaYtaWgNtSMcaatttactaacatttaaWttHtatBat
+tgtcgacaatNgattgcNgtMaaaKaBDattHacttggtRtttaYaacgVactBtaBaKt
+gBttatgVttgtVttcaatcWcNctDBaaBgaDHacBttattNtgtDtatttVSaaacag
+gatgcRatSgtaSaNtgBatagttcHBgcBBaaattaHgtDattatDaKaatBaaYaaMa
+ataaataKtttYtagtBgMatNcatgtttgaNagtgttgtgKaNaSagtttgaSMaYBca
+aaacDStagttVacaaaaactaaWttBaagtctgtgcgtMgtaattctcctacctcaNtt
+taaccaaaaVtBcacataacaccccBcWMtatVtggaatgaWtcaaWaaaaaaaaWtDta
+atatRcctDWtcctaccMtVVatKttaWaaKaaatataaagScHBagaggBaSMtaWaVt
+atattactSaaaKNaactatNatccttgaYctattcaaaVgatttYHcRagattttaSat
+aggttattcVtaaagaKgtattattKtRttNcggcRgtgtgtWYtaacHgKatKgatYta
+cYagDtWcHBDctctgRaYKaYagcactKcacSaRtBttttBHKcMtNtcBatttatttt
+tgSatVgaaagaWtcDtagDatatgMacaacRgatatatgtttgtKtNRaatatNatgYc
+aHtgHataacKtgagtagtaacYttaNccaaatHcacaacaVDtagtaYtccagcattNt
+acKtBtactaaagaBatVtKaaHBctgStgtBgtatgaSNtgDataaccctgtagcaBgt
+gatcttaDataStgaMaccaSBBgWagtacKcgattgaDgNNaaaacacagtSatBacKD
+gcgtataBKcatacactaSaatYtYcDaactHttcatRtttaatcaattataRtttgtaa
+gMcgNttcatcBtYBagtNWNMtSHcattcRctttttRWgaKacKttgggagBcgttcgc
+MaWHtaatactgtctctatttataVgtttaBScttttaBMaNaatMacactYtBMggtHa
+cMagtaRtctgcatttaHtcaaaatttgagKtgNtactBacaHtcgtatttctMaSRagc
+agttaatgtNtaaattgagagWcKtaNttagVtacgatttgaatttcgRtgtWcVatcgt
+taaDVctgtttBWgaccagaaagtcSgtVtatagaBccttttcctaaattgHtatcggRa
+ttttcaaggcYSKaagWaWtRactaaaacccBatMtttBaatYtaagaactSttcgaaSc
+aatagtattgaccaagtgttttctaacatgtttNVaatcaaagagaaaNattaaRtttta
+VaaaccgcaggNMtatattVctcaagaggaacgBgtttaacaagttcKcYaatatactaa
+ccBaaaSggttcNtattctagttRtBacgScVctcaatttaatYtaaaaaaatgSaatga
+tagaMBRatgRcMcgttgaWHtcaVYgaatYtaatctttYttatRaWtctgBtDcgatNa
+tcKaBaDgatgtaNatWKctccgatattaacattNaaacDatgBgttctgtDtaaaMggt
+gaBaSHataacgccSctaBtttaRBtcNHcDatcDcctagagtcRtaBgWttDRVHagat
+tYatgtatcWtaHtttYcattWtaaagtctNgtStggRNcgcggagSSaaagaaaatYcH
+DtcgctttaatgYcKBVSgtattRaYBaDaaatBgtatgaHtaaRaRgcaSWNtagatHa
+acttNctBtcaccatctMcatattccaSatttgcgaDagDgtatYtaaaVDtaagtttWV
+aagtagYatRttaagDcNgacKBcScagHtattatcDaDactaaaaaYgHttBcgaDttg
+gataaaKSRcBMaBcgaBSttcWtgNBatRaccgattcatttataacggHVtaattcaca
+agagVttaaRaatVVRKcgWtVgacctgDgYaaHaWtctttcacMagggatVgactagMa
+aataKaaNWagKatagNaaWtaaaatttgaattttatttgctaaVgaHatBatcaaBWcB
+gttcMatcgBaaNgttcgSNaggSaRtttgHtRtattaNttcDcatSaVttttcgaaaaa
+ttgHatctaRaggSaNatMDaaatDcacgattttagaHgHaWtYgattaatHNSttatMS
+gggNtcKtYatRggtttgtMWVtttaYtagcagBagHaYagttatatggtBacYcattaR
+SataBatMtttaaatctHcaaaSaaaagttNSaaWcWRccRtKaagtBWtcaaattSttM
+tattggaaaccttaacgttBtWatttatatWcDaatagattcctScacctaagggRaaYt
+aNaatgVtBcttaaBaacaMVaaattatStYgRcctgtactatcMcVKatttcgSgatRH
+MaaaHtagtaaHtVgcaaataatatcgKKtgccaatBNgaaWcVttgagttaKatagttc
+aggKDatDtattgaKaVcaKtaataDataataHSaHcattagttaatRVYcNaHtaRcaa
+ggtNHcgtcaaccaBaaagYtHWaaaRcKgaYaaDttgcWYtataRgaatatgtYtgcKt
+aNttWacatYHctRaDtYtattcBttttatcSataYaYgttWaRagcacHMgtttHtYtt
+YaatcggtatStttcgtRSattaaDaKMaatatactaNBaWgctacacYtgaYVgtgHta
+aaRaaRgHtagtWattataaaSDaaWtgMattatcgaaaagtaYRSaWtSgNtBgagcRY
+aMDtactaacttaWgtatctagacaagNtattHggataatYttYatcataDcgHgttBtt
+ctttVttgccgaaWtaaaacgKgtatctaaaaaNtccDtaDatBMaMggaatNKtatBaa
+atVtccRaHtaSacataHattgtttKVYattcataVaattWtcgtgMttcttKtgtctaa
+cVtatctatatBRataactcgKatStatattcatHHRttKtccaacgtgggtgRgtgaMt
+attattggctatcgtgacMtRcBDtcttgtactaatRHttttaagatcgVMDStattatY
+BtttDttgtBtNttgRcMtYtgBacHaWaBaatDKctaagtgaaactaatgRaaKgatcc
+aagNaaaatattaggWNtaagtatacttttKcgtcggSYtcttgRctataYcttatataa
+agtatattaatttataVaacacaDHatctatttttKYVatHRactttaBHccaWagtact
+BtcacgaVgcgttRtttttttSVgtSagtBaaattctgaHgactcttgMcattttagVta
+agaattHctHtcaDaaNtaacRggWatagttcgtSttgaDatcNgNagctagDgatcNtt
+KgttgtaDtctttRaaYStRatDtgMggactSttaDtagSaVtBDttgtDgccatcacaM
+attaaaMtNacaVcgSWcVaaDatcaHaatgaattaMtatccVtctBtaattgtWattat
+BRcWcaatgNNtactWYtDaKttaaatcactcagtRaaRgatggtKgcgccaaHgaggat
+StattYcaNMtcaBttacttatgagDaNtaMgaaWtgtttcttctaHtMNgttatctaWW
+atMtBtaaatagDVatgtBYtatcggcttaagacMRtaHScgatatYgRDtcattatSDa
+HggaaataNgaWSRRaaaBaatagBattaDctttgHWNttacaataaaaaaatacggttt
+gHgVtaHtWMttNtBtctagtMcgKMgHgYtataHaNagWtcaacYattaataYRgtaWK
+gaBctataaccgatttaHaNBRaRaMtccggtNgacMtctcatttgcaattcWgMactta
+caaDaaNtactWatVtttagccttMaatcagVaagtctVaaDaBtattaattaYtNaYtg
+gattaKtaKctYaMtattYgatattataatKtVgDcttatatNBtcgttgtStttttMag
+aggttaHYSttcKgtcKtDNtataagttataagSgttatDtRttattgttttSNggRtca
+aKMNatgaatattgtBWtaMacctgggYgaSgaagYataagattacgagaatBtggtRcV
+HtgYggaDgaYaKagWagctatagacgaaHgtWaNgacttHRatVaWacKYtgRVNgVcS
+gRWctacatcKSactctgWYtBggtataagcttNRttVtgRcaWaaatDMatYattaact
+ttcgaagRatSctgccttgcRKaccHtttSNVagtagHagBagttagaccaRtataBcca
+taatSHatRtcHagacBWatagcaMtacaRtgtgaaBatctKRtScttccaNaatcNgta
+atatWtcaMgactctBtWtaaNactHaaaaRctcgcatggctMcaaNtcagaaaaacaca
+gtggggWttRttagtaagaVctVMtcgaatcttcMaaaHcaHBttcgattatgtcaDagc
+YRtBtYcgacMgtDcagcgaNgttaataatagcagKYYtcgtaBtYctMaRtaRtDagaa
+aacacatgYaBttgattattcgaaNttBctSataaMataWRgaHtttccgtDgaYtatgg
+tDgHKgMtatttVtMtVagttaRatMattRagataaccctKctMtSttgaHagtcStcta
+tttccSagatgttccacgaggYNttHRacgattcDatatDcataaaatBBttatcgaHtN
+HaaatatDNaggctgaNcaaggagttBttMgRagVatBcRtaWgatgBtSgaKtcgHttt
+gaatcaaDaHttcSBgHcagtVaaSttDcagccgttNBtgttHagYtattctttRWaaVt
+SttcatatKaaRaaaNacaVtVctMtSDtDtRHRcgtaatgctcttaaatSacacaatcg
+HattcaWcttaaaatHaaatcNctWttaNMcMtaKctVtcctaagYgatgatcYaaaRac
+tctaRDaYagtaacgtDgaggaaatctcaaacatcaScttcKttNtaccatNtaNataca
+tttHaaDHgcaDatMWaaBttcRggctMaagctVYcacgatcaDttatYtaatcKatWat
+caatVYtNagatttgattgaYttttYgacttVtcKaRagaaaHVgDtaMatKYagagttN
+atWttaccNtYtcDWgSatgaRgtMatgKtcgacaagWtacttaagtcgKtgatccttNc
+ttatagMatHVggtagcgHctatagccctYttggtaattKNaacgaaYatatVctaataM
+aaaYtgVtcKaYtaataacagaatHcacVagatYWHttagaaSMaatWtYtgtaaagNaa
+acaVgaWtcacNWgataNttcaSagctMDaRttgNactaccgataMaaatgtttattDtc
+aagacgctDHYYatggttcaagccNctccttcMctttagacBtaaWtaWVHggaaaaNat
+ttaDtDtgctaaHHtMtatNtMtagtcatttgcaaaRatacagRHtatDNtgtDgaatVg
+tVNtcaaatYBMaaaagcaKgtgatgatMgWWMaHttttMgMagatDtataaattaacca
+actMtacataaattgRataatacgBtKtaataattRgtatDagDtcRDacctatRcagag
+cSHatNtcaScNtttggacNtaaggaccgtgKNttgttNcttgaaRgYgRtNtcagttBc
+ttttcHtKtgcttYaaNgYagtaaatgaatggWaMattBHtatctatSgtcYtgcHtaat
+tHgaaMtHcagaaSatggtatgccaHBtYtcNattWtgtNgctttaggtttgtWatNtgH
+tgcDttactttttttgcNtactKtWRaVcttcatagtgSNKaNccgaataaBttataata
+YtSagctttaaatSttggctaaKSaatRccgWHgagDttaaatcatgagMtcgagtVtaD
+ggaBtatttgDacataaacgtagYRagBWtgDStKDgatgaagttcattatttaKWcata
+aatWRgatataRgttRacaaNKttNtKagaaYaStaactScattattaacgatttaaatg
+DtaattagatHgaYataaactatggggatVHtgccgtNgatNYcaStRtagaccacWcaM
+tatRagHgVactYtWHtcttcatgatWgagaKggagtatgaWtDtVtNaNtcgYYgtaaa
+ctttaDtBactagtaDctatagtaatatttatatataacgHaaaRagKattSagttYtSt
+>THREE Homo sapiens frequency
+agagagacgatgaaaattaatcgtcaatacgctggcgaacactgagggggacccaatgct
+cttctcggtctaaaaaggaatgtgtcagaaattggtcagttcaaaagtagaccggatctt
+tgcggagaacaattcacggaacgtagcgttgggaaatatcctttctaccacacatcggat
+tttcgccctctcccattatttattgtgttctcacatagaattattgtttagacatccctc
+gttgtatggagagttgcccgagcgtaaaggcataatccatataccgccgggtgagtgacc
+tgaaattgtttttagttgggatttcgctatggattagcttacacgaagagattctaatgg
+tactataggataattataatgctgcgtggcgcagtacaccgttacaaacgtcgttcgcat
+atgtggctaacacggtgaaaatacctacatcgtatttgcaatttcggtcgtttcatagag
+cgcattgaattactcaaaaattatatatgttgattatttgattagactgcgtggaaagaa
+ggggtactcaagccatttgtaaaagctgcatctcgcttaagtttgagagcttacattagt
+ctatttcagtcttctaggaaatgtctgtgtgagtggttgtcgtccataggtcactggcat
+atgcgattcatgacatgctaaactaagaaagtagattactattaccggcatgcctaatgc
+gattgcactgctatgaaggtgcggacgtcgcgcccatgtagccctgataataccaatact
+tacatttggtcagcaattctgacattatacctagcacccataaatttactcagacttgag
+gacaggctcttggagtcgatcttctgtttgtatgcatgtgatcatatagatgaataagcg
+atgcgactagttagggcatagtatagatctgtgtatacagttcagctgaacgtccgcgag
+tggaagtacagctgagatctatcctaaaatgcaaccatatcgttcacacatgatatgaac
+ccagggggaaacattgagttcagttaaattggcagcgaatcccccaagaagaaggcggag
+tgacgttgaacgggcttatggtttttcagtacttcctccgtataagttgagcgaaatgta
+aacagaataatcgttgtgttaacaacattaaaatcgcggaatatgatgagaatacacagt
+gtgagcatttcacttgtaaaatatctttggtagaacttactttgctttaaatatgttaaa
+ccgatctaataatctacaaaacggtagattttgcctagcacattgcgtccttctctattc
+agatagaggcaatactcagaaggttttatccaaagcactgtgttgactaacctaagtttt
+agtctaataatcatgattgattataggtgccgtggactacatgactcgtccacaaataat
+acttagcagatcagcaattggccaagcacccgacttttatttaatggttgtgcaatagtc
+cagattcgtattcgggactctttcaaataatagtttcctggcatctaagtaagaaaagct
+cataaggaagcgatattatgacacgctcttccgccgctgttttgaaacttgagtattgct
+cgtccgaaattgagggtcacttcaaaatttactgagaagacgaagatcgactaaagttaa
+aatgctagtccacagttggtcaagttgaattcatccacgagttatatagctattttaatt
+tatagtcgagtgtacaaaaaacatccacaataagatttatcttagaataacaacccccgt
+atcatcgaaatcctccgttatggcctgactcctcgagcttatagcatttgtgctggcgct
+cttgccaggaacttgctcgcgaggtggtgacgagtgagatgatcagtttcattatgatga
+tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat
+catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc
+tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg
+caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc
+tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc
+aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag
+aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat
+ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac
+gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag
+ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt
+cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta
+gtgatacacaatactcgtgggccatgggttctcaaataaaatgtaatattgcgtcgatca
+ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt
+cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg
+taccagtttaattgccagtgggcaatcctaagcaaaatgagattctatcctaaagtttgg
+gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc
+taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt
+ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt
+aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt
+gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta
+acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct
+ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta
+tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt
+tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg
+tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa
+ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac
+aatttttgcacgagaaagtaatgcaatacaatatgatgaaagccagctaatgaaaaggga
+tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca
+gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt
+gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc
+cgattactgccctaccctaacgtctgccatctaaatatcgaacttgttatgatcaatgtg
+actacctcccaccctttccccttcatttgttccactggggataagctagcgttttcagaa
+tcaatgcaataagaatagccaattgtctcacttcatcagagctcttggcaattccaggcg
+ctacgtggttctggaatatattcatttttcaaatagtaatacgtttagtgttgctattgt
+ctacacgtttggatattacgttatgtgagcggacatcaatagttgtctaactctttagta
+agccagagatagcactcttagcgaatggataccatcttccataagtttagttaatagtcc
+gaaacaactgcttcgagcatatttgaacctccttgtaggcaaatagcctcttcaaagcaa
+tcttactaatagatagagtttgttttaagggactactagaaatgggacaatcttaatagt
+atgacctaaactgacatttaaagatatatccaggtggcaagcataaagatcattgcgcca
+cctccaccgtgggattacttatcagtcgatatcctatatgctaagtttgcgacggcagaa
+tacaaactaagctgagttgatgctaaccttacctatgataccccattggaccggttaaca
+gccctacttattccaaataaaagaacttttatgctgtagaagctattatagtgatgcctg
+gtaacttcagtatattaaaatgacacacatacgccatatagagctcctggaactttgaat
+aatgagcgaacttcgaagttgaagagcaagaaaccatatgtcacggttgcctaaagcccg
+gtaaccagacatgtgctatcattgatcattatcgaggttttcataaccttgacccattat
+cggctgtgcgcggacaagtacttaaatcactagtttcttcacctgcttatcggtaagaaa
+taaggttggcaaagaatcgcataagacggacgtagagccgcagcgttgtgcgagtccagg
+tgcatgcgcagcaataggattttaaattttgttccatttttaatttagccgtaaggatgt
+ccgtaaatgattgaaaattggattcaatctttgggcctatgctactggaacctgatcgac
+aaaatttcaaacatacgttaactccgaaagaccgtatttttgcggctagaatagtcagtc
+gcttggagccatataccttaccacttaaacgacgtgctcctgtagttgaaatataaacag
+aacacaaagactaccgatcatatcaactgaagatctttgtaactttgaggcgaagcaccc
+tcttcgagacaactaagagtaaagtaccgggcgccgcaaggagtcgattgggaccctaaa
+tcttgacgaattgctaagaggctcagagctaccactgtaatttctctagagcccataata
+aatgaacgatacatccgtaggtagcacctaagggattataatggaagccaaatgcagtta
+ataatattatatactggcgtacacgattcgacggatctctcacatagtgattcacgaccc
+ccccctttgattgacacagcgtcagcattttgcaagaacgatcttctgcatagggtgcgc
+caccgtaaggatgacgtcgaagctacaactgggtataatttaccatgcttccctgatgct
+gagtgcaatacactaagaatgagtttttaccccatatcaccagtatttgttctgttattg
+cgaagaaatggctatgctgagttggcgactaaagtcacccatcctttttattaggtaacc
+ccctcccttaaactaactgatttgctggagctgccctgcatacatatactttatcattta
+tggacgtccgtgacgcttattatccaccatagtcgatatgctacacggattcattaatgg
+atcgtaggagtttaagttatatttactaagatcggtctcggctactatcccgccttaccc
+ggcgctatttacggccatttttaatatattgacggtaattattcctatggtttcgaccgc
+acgtccttggacaagaaagaatggcaaaaaaaatgtaaaagaaaaaaaatattgagtccc
+taccatcatataaaaaatatgtgatgagtaacttgacgaaatgttagtggttattaaaga
+ctatctattacaccttttgttttctgtcgtagtatattaaagtctagaagccttacagga
+aaatcagggttatacagccgatactccgcagcatgaatcatcgaggaggtgtcctaccat
+cgcgccttgtaatcttgtctgtgtatactgtatttagaccttttatacaaagtaaatatc
+tcggctttatgtgattgggaggggcctactcaaacatgatgacttgacctaataatcact
+gtgcgggcgtcttatgactagctattccttgaaatccaccaccaaatggttaatatgtaa
+aaactttgacgatgaaacaaggtgaatgtgtagttactttgtgtaattagctgcgtcgag
+cattgcttgtaaaaccgtcaatcgcacacgttacttccataaaatttctacgaatacacc
+cttcttaaaaaaaacgtaggaattcacgagtttaacaaacgataactgtataaagtggaa
+gtccgaagaaagcagatgcccgaactactcgaagatgtttcgttttcttaaccatagggg
+cttcttaatggcccactacgcacattttgttcaagcccgagagggacatccccattacgg
+gagtattactaaaactgttccgtaatacgttcagcaagggatgaaaaaggccactgctca
+agttattgacgtgggagtattacatcggaagcctgaatcccacactatgatggtctgtac
+aggcctagggactgcgtctagacggtattaccggcttctaatcatacgatcgtgagtctt
+aacgggaagtaaggctcacacctaccccaaaccatttatctatgtaagtataaaattgtg
+cgtaagtgttcaaagtggacaataaagacgtggcaaaaacccccgcacataagccgcttt
+agatttcacaaataccaatgcggttaaaaacatccttgagtcgtacatacaccatactcg
+cgttaaacggatataacagaagataataaatccggatgtggagtcggtgtaactatagaa
+agccaagtgaaataatgcttaccagtcatttagctatacggctttcatttcatgtcaaga
+gggtggagtttgacctgtacagttgatatatcaccgatacttagaactcacctaaagcta
+aaattgctcgcagcgtgtaatccgcatattacaaacaatagatgggattcattatacata
+agacacgatgatctgctttttcaggttgcgagatgttgcctatcgtcaatcgagtcctgc
+cttacaccacttaaacaaaagtattgacagggaacctattttcgaggtattatatagtcc
+agcttgaatatcaatttgacagttaacctagtgaaaatcagtaagaggaaatacgccaca
+ttctccagtgaaattctacgggttatcgtctagtccaactatcaattataactcacgaga
+tataagtaaattctcgtacttggcctgatttttattatactttggatccttagtaaacag
+gaagggagaaaccttcaacgaaaaacactggattttgttttactctcaaagctcttatat
+gacggaaataccctgtcaagtcttaactttattactagactaatgaaatgggcttggggt
+ggccagaatcatagtacaatttagcggatacactattcggactttcctatcggctgtctg
+gttggataagtatggggactaataggctagacatacctatacttaaactatacaggcgtc
+atctatctctgcaactttggagttccctgatgttctcccgccctttgggttcacatcttc
+tataccgacacccctaataacgattagtttgtgggttagagtaaattaatacggttaata
+ttaatgtatcgttgaaaagctggtgtcgccaataaggtaaccggctaggcagagtatatg
+tcacgaagtataactaccctaatgataagctgtaggaataaaattaatgctgtctctaag
+cgaagagatatttccgactctgttttaatgacgaatctcattacttctgacttgcaaatg
+ttcaatatggcacggtttcacggcacctttgtgacgcatataatgaacttagaagattat
+aacgacggaactttatatgataatccgttacgattaaagaatctgttaaatatcataatg
+gcattcagttctagaccgtgcatcatggtaaacttactttctctgcatggcgacatacat
+ttcgctattcaaattcgcgtgtggttacacccactcgcacctttggaatattaagagaag
+atgatcagaaaatccattcgctcaatttttctgacgtacgtctaatttatcctaggagac
+aaatcgttttatgtctctcacatttttgaagaaaggttcgagagacaatactcaggtcct
+gaactgctagaagatactcggtggagcgtggcaacaatgaaaaactcgtgacataaatga
+atgatacttttccaagttcagttaagtgaatatgtttaacatacccggcttttcgatctt
+aagctgacgctggacgtgcgagtaatgtcagtctcttacatacactagtgactccaagtt
+tcgtcaaaaacgccccctcccttctcgagcccactcacgctatgtattgacgcgaacttg
+ttcgggatcagacttttcaggagttcggtcgcgtgtccctatgtgctaatatataagtta
+gatcgcattagatgctaatctgaatacttatagacgaccttcaacgagaacgggtaccac
+cttgaggctagagttaggtgtgaaacgacaggtagggacatataaaatttgagtgcggct
+ttagttaagggtttaattacctactcaaacatcacgctcgcgcccttcgtacgtaatcga
+ccatctagaggctaaggggactgtactaggtagtgattaatgatatcctagacgcacgtg
+ccttagatcttcagactctgatggtccgcgatcaccgtaattgtagtcctccaactcgat
+cactttgttggcgtcaaagaaattacgatatctaaatacttataatacaataaccaagga
+tgagaatgactcatcgcgttggagttatattgcttgaagttctatggaatgaaagcacgt
+tatctgccgtcccaatatctccagtgagctaattcattggacggtccactttgatcaatc
+cccgaggagatgttcggacactttagtctgtaacacttagcgttgagaccacgaacaatt
+gattactcagtcttgaaggtgttttccaaagttcattttaaataagactacgataggcct
+ttcctattgatataaactacccggctctgttgttcgtgtgagtcgtacttctctgtgttt
+ttctgattatagcaagattcgattcttagtgtaaacagcgatttttatttgacccgtcaa
+tgagaagcgcataggatctaagcaaaattatcaagttgtgccacaaggtaagatctttcc
+agttattgcaggtaggatgtatcccacgttgatagtatgaggtctgacgtcaactgtcta
+ggagagttgaccgcgtgcgggtacaccggatttgcatcgatgttgagaacgcagaactcc
+cactgtcgtggcggcgttcctgatatttagcaagaggcgttgataaagccctcatcatct
+agatctcgacctcatctgccctcttgctccatcattttctacacagactactttcctatc
+tacgttagtataattgctttctatcttagtatcatttagagcttctccgtcaacaggttc
+gtgctattaaagttagtacgaaagggacaacttgtagcaacgcatttaatcggttttcga
+ctacttcgcacaaaatcagataaagaagtttgtcattctattagacattgaattgcgcaa
+ttgacttgtaccacttatgatcgaacactgaatcaagactgtgattaactaaaatagaca
+agccactatatcaactaataaaaacgcccctggtggtcgaacatagttgactacaggata
+attaattggactggagccattacattctctacaatcgtatcacttcccaagtagacaact
+ttgaccttgtagtttcatgtacaaaaaaatgctttcgcaggagcacattggtagttcaat
+agtttcatgggaacctcttgagccgtcttctgtgggtgtgttcggatagtaggtactgat
+aaagtcgtgtcgctttcgatgagagggaattcaccggaaaacaccttggttaacaggata
+gtctatgtaaacttcgagacatgtttaagagttaccagcttaatccacggtgctctacta
+gtatcatcagctgtcttgcctcgcctagaaatatgcattctatcgttatcctatcaacgg
+ttgccgtactgagcagccttattgtggaagagtaatatataaatgtagtcttgtctttac
+gaagcagacgtaagtaataatgacttggaataccaaaactaaacatagtggattatcata
+ctcaagaactctccagataaataacagtttttacgatacgtcaccaatgagcttaaagat
+taggatcctcaaaactgatacaaacgctaattcatttgttattggatccagtatcagtta
+aactgaatggagtgaagattgtagaatgttgttctggcctcgcatggggtctaggtgata
+tacaatttctcatacttacacggtagtggaaatctgattctagcttcgtagctgactata
+ctcaaggaaccactgctcaaggtaggagactagttccgaccctacagtcaaagtggccga
+agcttaaactatagactagttgttaaatgctgatttcaagatatcatctatatacagttt
+ggacaattatgtgtgcgaaactaaaattcatgctattcagatggatttcacttatgcctt
+agaaacagatattgcccgagctcaatcaacagttttagccggaaacaatcgaagcatagg
+gacaatgtatcttttcctaaattgccatgtgcagatttctgagtgtcacgaagcgcataa
+tagaatcttgtgttgcctcaactcgttgaaaagtttaaaacaatcgcagcagtctttttg
+gggtctactgtgtgtttgcaaaataactgaaagaaacgcttgaacaactctgaagtagct
+cgagtactcattaaagtgtaacacattagtgaatatcggccaatgaaccaaacgcttccc
+ggtacgctatctctctcatcgggaggcgatgtgcaggttatctacgaaagcatcccttta
+cgttgagagtgtcgatgcatgaacctcattgtaacaatagcccagcaaattctcatacgt
+gcctcagggtccgggcgtactcctccatggaagggcgcgcatctagtgttataccaactc
+gctttttaactactatgctgtagttctacaggcatagtggccagtattttctaacttctc
+tggatagatgctctcactcctcatccatcacggcttcagtttacgtcttacttgcttgtt
+cagcaacggatggaggcattaagtatcttcactgttccctaaaattgctgttcaatatca
+aagtaaggacgatacagggaaagctcaagcacactcattgaatactgccccagttgcaac
+ctcacttaatctgacaaaaataatgactactctaagtgttgcggaagcagtctcttccac
+gagcttgtctgtatcacttcgtataggcatgtaactcgatagacacgaacaccgagtgag
+aaactatattcttgcttccgtgtgtgtgacaccaggtaattgatgcggatataagctgga
+gatcactcacgcccacacaaggcgctgctacctctttattccaatgtgtaagaatttgct
+aacttcatttctagaccgcagctttgcggtcataatttcacggtacggacccttgggtta
+gagacttgataacacacttcgcagtttccaccgcgcacatgttttagtggcttctaacat
+agaatttttgttgtgacataaagagtgcgtgggagacttgcccgaccgttaagccataat
+caattgaaagccccgtgagtcacatctaattggttgtactgcgcatttagctatccttta
+gctgactcgaagagattcgattcctaatataggttaattagatggctgccgcgcgaagta
+aaacgtgaaaaacgtagtgcgcagatctgcataactcgcgcttaattacttatgagtagt
+tccaagttcgctacgttatgagagagattggaattaagcaaatatgttttatggtgattt
+tgggatgagaaggactgctaagtacggctactaaacaaatttctaaaaccgccatctacc
+ttatcttggagacatttaagttgtatatgtcactagtctagcttttgtctgtgggacgcg
+ttctcggaatgagggaaatgcaagagccgattcatcaaatgcttatctaagaaagtagtg
+gactattacaccaagcacgaatgccagggaactgctttcttgctcaggacctcgcgacaa
+ggtaccccgcataagtcctagaattacatttggtcagcaatgctgacatttgaccgtgaa
+aacataattttaatcagaaggcagctcacccgcttgctctagatcttatctttgtatgaa
+tgtcagaatttactgcaatatccgttccgaatagtgagggcttagtatagttctctgtat
+acaggtcacatcaaactccccctgtcctagtacagctctgagctttaattaattgcatac
+atttccttcaatcatcagatgaaaacaccgcgaatcatgctcttctcgtatagggcaaga
+gaagcaacaaacaactagcccgactcacgttcatccgccgtatccttgttcagttcttac
+tccgtattaggtcagcgaaatctaatcagaataatcggtcgcgtatcaaaattaaaatcc
+cgcttgaggttgacaattaaaacgctgagcagttatcggctattagatagtggggtgaaa
+gtaattggctggaattatgttaaaacgtgatattaagctaaaatacgctacttgttgccg
+acctaattcagtcattcgatattcagttagagccaagaataacaagcttgtataaattga
+acggggtgcactaaacgatgtgttactctaatattcagcttggagtatacctgaaggcga
+attcatgtatcggccaataataagacgttgaagatcacaatttggactagcaaaagaagg
+tgatttatgcgtggggattgagtccactgtacgagtacggtctctggaaaattataggtt
+cagggaatataaggaagtaaagataattaccaagagatttttggtatcgctatgacccag
+aggtgttctaacgtctgttttgatccgcagaatttctgcctcaatgcatatttgacggac
+ttgaactagagcctctaaagttaaatggcgacgcaactgttcctaaacttcaattattac
+tactctttttttcctagggtattgtagaggccagtggacaaaataaatcaaatttaagat
+gtttcggacattaacatcccccgtagcatagaaatcatcagttatccaatctctcatcga
+gcttttacaatttctgctggcgctatggacagcatatgccgcgagacctccgcaagactc
+acttgatcactgtaagtatcttcattagaggttagagcctatagttaagctgctgaccta
+gtaaaattggtattttctaattttattgctcaagttaaaggttagtgaagggataatgac
+gttatttttgaacaatgggttgtattcaattttatatcacgaatggaacccttcattccc
+ggcataatactagacgacacgaacaagctccgatctatcagccaggcacgtgttaaggtt
+taattccggcaaaccaatgaagcatcaaaaggtgacctgatgcaacttagggtcacgatg
+agtttttcaggactacttattacctattaataagttaacatgagccttcataccccgtaa
+gacaatacatactccaccaattagaattctgagccatcttatctttttgtatcatcgaag
+ggtatggccgaataggttaattagttactcctaacgtctctacaggcatgcatttgacgc
+accttcgaaaatagtcaatctctcgccacacgcgtctagtatgcagcatcaaaaatatag
+tccacggtttccggattaccaaacgcggcaaagagaaacattgtatcgacggagataact
+taatacagaaggaaggggcatcttcgaatacggatgaataattctatctgtttattctga
+catcttgttttcaggttaatcttacgcattcaaatgacgcctgccccatgcgtgcgcaat
+tattttctaatattgacgagagcaatctcactccttttgggtctatttatgttttattga
+ggcacaagcctatacagaacaggtactattaaggccgtgagtgtgagactcaaaccgtgg
+aaacaaaggatgggttgttcttggtacaagttttagtgcatgtgggcaatccttaccaaa
+atcagatgctatccttaactttgggctgcatttaagatggcggttggaggcctgtgagaa
+tcctgcgtgtcatctttaatgaccgaattcatccatgtagattcagatcacacactcatt
+ccttgatgttgtctaaacaaaagttgttgtggacgcattggagggagttaagtaacaact
+tgggatcgcatacttataaaaattatatgttaaactttcacaaacgctgaagtccaaagt
+aactagcccaaacgcctcgagagtcactaggtattaatggtgtttgagttcctgtgaaat
+agtgttcgaaggtaaaatttatgtaccaaatcgaaagaacacttaataaggcttgcttgc
+acggaggtatgatgtttactgactctacaaccctaattttccagtacgtacattcattcc
+aataggttagttctcaaagtgctatacaggctcctcaattgatgatatgcttcagccgct
+ctatggatattagctcattttatttaggaagcccgcttagaggcttactatgagggaaat
+gccaaaatgtcatacttttcggtgtgtcccatatgacaccgctttacatagaatttgaat
+taaaacgcgctctcccgttcactaccatacttggtaccgtgcgcatattacatatagata
+taggatcattttttaaagctgtactaggtttgatcgacaatcttatgctatactatatga
+tgtaaccctcataatcaataccgatcgtacgatcctagcataggtggcaagcgattttat
+gccgattattgtgttaaatagtctgtgagtgtgattatcagggctacgttggtagagggg
+ttgtatagacctcgcacacattgtgacatacttaacaatatacgaaaactgatataataa
+atccccttacccaaacaccaatcccgttgaatcaactaccataacgtctcccatataaat
+tgcctacttgtttgcataaatctgaatacataacaccattgcaccttcttgtgttccaat
+cccgttaagattgccttgtcagatgatatgcaagaacaatagcatttgctagcaattatt
+aacagctcttcgaattgcctccacataacgcgggagggtatattttaatttggcaaatac
+taagtactgttggcgtcatatgctattaacggttggatattaagttatgtcagccgtaag
+caagagtgggcgaaatattttgttacccagtgagagcactcttagagtttggatacaata
+ggccatatgttgacttaagaggacgtaactacgccgtacaccattgttcaaccgacttct
+tggcaaatagaatcgtattagcaatcttaagaatagagacacgttcgtgttagggtatac
+tacaaatccgaaaatcttaagaggatcacctaaactgaaatttatacatatttcaacgtg
+gatagatttaacataattcagccacctccaacctgggagtaattttcagtagatttacta
+gatgattagtggcccaacgcacttgactatataagatctggggatcctaacctgacctat
+gagacaaaattggaaacgttaacagcccttatgtgtacaaagaaaagtaagttgttgctg
+ttcaacagatgatagtcatgacgcgtaacttcactatagtaaattgaaacaaatacgcaa
+tttagacagaatggtacggtcatgaatgacagtaattcgaagtgctagaccaacttaaaa
+taggtaaacgtgcccgaaaccccccttaacagaaagctgctatcatggtgcagtatcgac
+gtgttcagaaacttgtaacttttgagcaggtccgagcacatggaagtatatcacgtgttt
+ctgaaccggcttatccctaagatatatccgtcgcaaactttcgatttagtcccacgtaga
+gcccaagcgttgtgcgactccacgtgcatgcccagaaatacgagtttaaatttggttaca
+tggttaattttgaccgaagcatcgcactttatgattgataattggattcaatatgtcgcc
+ctatgcgaatgcaacatgatccacaatttggctataagacgtttaatccgtatcacactt
+tgtttgcggctagtatagtaacgcccgtgcaccaagagtcagtaacaattataagtactc
+cgcaggtacttcaaatataaaaactaatcaaacacgacccatatgatcatctgaagatat
+ttggaactttctcgacaaccaccctcgtactcaatacttacactaatcgacaggcacacg
+caacgtgtacagtcgcaccatattgagtcaagatttgcttagtggcgatgagcgtacacg
+cttatttctctagtcacaattagttatctacgagacatcacgagggagcaaataagcgat
+gttatggctacacataggcacgtatgaatatgatataagccagttaaacagtcgaaccat
+cgagcaaattctcatgcaccaacccacacgttgaggcacaaagagtaagctgtttgaatg
+taacttcttctgctgagcgggccccaacgtaaggatcaactagaagagaaaactcggtat
+tagtttaaatgcgtcacggagcatgagtgcatttcactaagaatgtctgtgtaaccaata
+taacatctatttgttatctgattgcctacttatggctttgcggtcgtggcgactaatgtc
+tccaatccttttgaggtcggtaccaactccctttaaattacgctgtgcaggctcatgcac
+tgcatacatatacggtagcaggtagggacctcacgcacccttattataatcaatagtagt
+tatcagtcaacgaggcaggaatgctgaggtcgaggtgttggtatattttctatgtgccgt
+ctaggcgactatcacgcattaccaggcgagatttaagccaattttgaatatagtcaacgt
+aatttttactatgggttccaccgaaacgccttgcacaactaagaatcccataaaatatcg
+atatcaaataaaagattgtgtcaataccttcatatatattttttcggttgactaacgtga
+actaaggttaggggttttgtatgtctatataggaaacagtttcttttctgtcctacttta
+gtaaagtcttcaagccttactccaaaatcacggtgattaagccgttactcagcagcatga
+ttctgcctgctcgggtcctaaaatccagccttgtaagagtcgctgtgtattagctaggga
+gacctttgttaaaaaggatatatcgcggcgggatgtgagtgcgtggcgcatactcaatct
+tcagctcgtgtcattataatatctctcccccacgcttttcactagatatgccgtgtaagc
+aaacaccttatgcttaatttcgaaaatattggtacttgaaaaaagctgtaggggtactta
+atgtctggtaggagatcaggagagaattgagtgtaaaaccgtaaagccctcacctgactt
+catgtaaatggcttagaagactccatgatttaataaatactacgaaggaaagactggatc
+taaagataactctagtaaggccaactcccttcaatgctgttgccagttataatccaagag
+ctgtccttttctgaaccatagcggcttctgaagcgaactagaagcaaagttggttctagc
+cagacagccacataccctgtacgggtgtattactaaaactggtccggtattagttcacca
+agggaggaattaggcaaaggatctaggtatgcaagtcggagtattacatccctaccctga
+atccatcaataggttcctctgtactggccttcgcaatgagtattcaaggttgtacagccg
+tataataataagatagtgactatgaacgggaagtaacccgctcaccttccccaaaacatt
+gttatatctaagtattaaagtctgccgtagtgttaatactcgaaaataaacaactggcaa
+attacaccgcacttaagccgcttttgatttatatttttccaatgcgcttttaaaaataat
+tcagtcctacatactaattaagacccttaaacggagatatcacaagttaagttttaacca
+tctcgactaggtggaactatagatacccaactcaatttatcattacctgtaatgttccta
+gaaggattgcatttcatgtcaagacggtggagtttcacagcgaaacttcagtgtgaacag
+attctgagaaatcacctaaacctattagtcagagcacccggttagaaccagttgtcaaaa
+aatagagcggttgcatgagacagaagtaacgatgagatccgttgtaacgttgagacatct
+ggcctatcgtcaatacagtcctcccttaaaaatatttttaaatactaggcaaacccaaca
+taggttagtcctatgtgatacgccacatggtatatcattttgtaacgttacctagggata
+atcaggaagtggaattacgcaaaagtagacagtgaaatgcttagggttatagtctagtcc
+aaagataaaggataaagcacgtcagagaactatattagccgaatgggaatcattgttagg
+agactgtggatcatgtctaaaaagcaacgcagaaacagtcatcgaaaaaatctcgttttt
+gtttgaatctaaaagagctttgatgaccgatagtacctgtatactagttactgtattacg
+tgtctaatgatttcggattggggtccccagaatcagacgtcattgtagacgattcaagtt
+taccaatttaatttcccagctctccttggagaactatcgccaataattgcagtcactttc
+cttttctgaaacgataaagccgtcagagttctctgcaacgttggacttacctgaggttct
+aacccactttcggttctaatagtagttaacgacacaacgaataacctttactgtggggct
+ttcacgatattttttcgcttattattaatggttacgtcataagctggtgtccaaattaag
+gttaccggcttcgcagagtagttgtatccaagtataacttccctaatcataagatcgagg
+tagaaaattaatgctgtctctaaccgaacagatatgtcccactatgtggtatggacgttg
+ctaattacttctgaagggaaattggtcattatggatacgtgtctaccatcaggtcggacg
+cagatatggttctgtcttcagttgatccaccgttctttataggataataactgacgatta
+aagattatggtaaatagattaagccaattctcttcttgtcagtgaagcatccttaactga
+cttgctctgcagcccctcatacatttagctattcaaagtaccggctcgtttcaaactctc
+ccacctttggaagaggttgtcaacttgataagtatatcatttacagcattttttcggacg
+tacctctaatgtttcattgcagaaaattagttttttctatcgcacattttgcaagtaacg
+ttagagacacaattatctgcgaatgaactgctagatctgacgaccgggagcctcgcaaat
+atcaaaaaagactgacatatatcaaggagtcgttgacaagtgctggtaagtcaattggtt
+tatctgtcccggcgtttcgatcttaagctgaccatgcacggcagagtaatgtcactctcg
+ttcttacaagtctgtctccaagggtcggcaaaaaagacccctccattctcgagcccactc
+acgatatgtagggacgacaacttgtgcggcttatgaattgtctggactgcgggcgagggt
+ccatatctccgaagttagaagggacatacctttagatgataagatcaattcttattgacg
+aaattcatccacaacggggaacaacttcaccctagacttacgtctgaaaagacacctagc
+gtcttataaaaggtcagtgccccgtttcgtaaggctggaattacctacgcaaacttaaac
+ctcgcgcccttccttacgtatcgacaagatagaggctatcgcgaatgtactacggaggca
+tgaatcatatactagaaccaagtgcctgtgatattaacaagatgatccgacgcgagcacc
+gtaattctaggcataaaactccagcaatttgggggccgaaaacaaatgacgttagctaat
+taattatatgacatgatcaaaggaggtcaatcacgcatcgagttcgacgtatattcattg
+aacttcgtgcgtttgaaagaaacttttatgaaggcaaaattgatcctgtctcctatttca
+tgcgtacctcctagttgataattccccgagcagtggttaggacacttttgtcggtatcaa
+gttccggtctcaaaacgtaaaattctgtaatctgtatggatggtctgtgaattagttaat
+ttttatgaagtcgtcgagacgcagttcctattgatttattctaaacggagatgtgcttcg
+tgggactcggaagtagatctgtgtttatgattattgctactttagatgctgactgttaac
+tccgtgttgtttttcaaccgtatatcacaaccgaattggatagaacctatagtttcaagt
+tctgccacaaggtatcatatttacagttagtgctggttgcttctttcaaacgtggtgagt
+ttgtgctatcacgtcaacggtagagctcagtggaccgagtgcgcgttcaaccctgttcca
+gagagggtgtgatagcacatataccacgctcgtcgaggcgttcatgatagtttgcaagag
+ccggtgttaaacacatattattattgttatccaactaatcggacctatgcataaagcatt
+gtctaaacagaataattgcctatatacggtagttttagtgatttatatcttagtatcagt
+tagagcttcgaactcttcaggttcctcatatttaacgttcttcgaaagcgaaaacttcta
+caaacgaatgtaagcggttttccaagtagtacctataaatcacagaaagatctgtctcag
+tatagttgaaatggtattcagctagtgacgtgtaccaattatcatagttcactcaagcaa
+gacgctcattaacgaatatagacaagacactatatcatataataaaaaagaacatggtgc
+tcgaacatagttgaattcaccatattgaaggggaatgctgacatgtaattcgctactaga
+cgatcaattccctacttgtcaaagttgaactggtacgttcttggaattaaatatgattgc
+gctggaccaaattgcgacttcttgagtttcagggcaaacgattgagccggaggatgtccg
+tctcttacctttcttgcttatgataaacgacggtccctgtacatcactgggaattctcag
+caaaaataattgggtaaatcgagactcgatgtattcggccacaaaggtgttagacgttaa
+agattattcaacggggcgataataggatcataaccggtatgcaagcgcattgaaagagcc
+atgagatccttatccgataaacgctgcacggtatgtgcagccttattgtcgatcacgaat
+ttataaatgtagtctgggctgtaagttgaagacctaagttataatgaagtgcaataccaa
+atcgattcatagtggattatcagactcaagatatctcctgataaattacagttgttaaga
+tacggataaaatgagatttaagattagcagcctctaatctgtttcaatcccgttggaatg
+tggtatgcgatcaaggttaagttaaaatcaagcctgtcttcagtcttgattcttgttctg
+ccatcgcatgcggtctacgtgagttaatatgtagcttacgttctagcttgtgctaatctg
+agtatagattcgtagaggaatattatcaagcttccacgcctcaacgtacgtgtattggtc
+acacaagacactaaaagtggaagtagcgtaaactatagtctagttgttaaatgctcagtt
+cttgttatattcgatatactcttggctaatttatgtctgagtatataaaattaatgatat
+taacttgcatttcacggatcccttagaaaaagattttgaccgagcgcattataaacggtt
+acaccgaatcaatagaagcatacccaatagctttctttgaatttattgcctgcgcaactt
+ggctgactctctagatccgaataattctatatggtcgtgacgaaactagttcattactgt
+ttaaaatgccaacatgtcttttgggccgataatggctctttgcaaaattactcaatgata
+cgattgatcaaagcggtagttgctagtggtagcatgtaagtctatcaaatgtctgattat
+ccgaaaatcttccaaaagagtccacgtaccatatctatctcatagcgacgcgaggggaac
+cttatctaactatcattccatttaccgggtgactctcgatgcaggatccgattgggataa
+attgcccagaaatggctcattcctgactaagggtaaggccgttctcagcaagggaacccc
+gcgaatctaggcttataccatctagattgttaactacttgcctgtagttctacagccata
+ctggacagttgtttctaaatgatcgggattcatgctagcactcctctgaatgcaccgcgt
+aagtttaactattacgtccgtgggcagataaggatggaggctgtatgtatcttaactgtt
+acctaatatggctggtaattatcaaagtaaggaccttaatgccatagcgctagcaatcgc
+tttgtatactgaccatgtgccaacctctcttaatctgtaaaatataatgtcttagctaac
+tgtggacgatcatgtctctgcctagagcttcgctgtatcaattcctatagccagcgtact
+agtgacacaacaacaccgtgtgagaaaagatattagtccttacgtctgtctctctacagc
+ttattgatgaggattgaacatggacatatagctccccctcaaaagcagatgctacctctt
+tattccattctcgaacatttgccgaacttaatttcgacaaacctgaggtcacgtcttaat
+ttatcggtaacgtcacgtccctttgagactggataaatatattaccaggggccaacgagc
+aattgttggaggcgcttctataatacaaggtgtcttgtcaaagaaagacggcgtgcgtct
+cgtgcaactcacttaaccaatattaatgtgaaacccccctctctcacatcttatgcggtg
+tactgccctggtacatttcctgtacaggactccaacagtgtagattcctaagatagctgt
+tggagttgcctcacgccagatcgaaaaactgaataaactagtgagctgagctgcagaaat
+accgcttaattacttatgactagttcaaagggacctacgtgatgtcagacattgcaagga
+agaaattaggtttgtgcgtcattttggctggactagcactccttacttcccctactattc
+aaatgtcgtaaacagcatgagacaggatcgtgctgacatttaaggtctattgggaacgag
+gctacctttggtcgcgcgctcgcgttctccgaatgaccgaaatgcatgagcacagtatgc
+aattgcttatagatctaaggtctggtcgttgaaaccaagcacgtaggcctgggaaatcag
+ttcttcctcagcaactacacaaaagcgtccaagcattagtacttgtagtaaatgtccgaa
+cctatgcgctcatttgaaagtcaaaaaatatttttaagcagtaggcacctaacccgattc
+ctctacttagtagctttctttgattctcagaattgactgcaatatcactgcacaattctg
+tgccattactagacttctctgtattaacgtctcatcttactaacactcgcctaggacaca
+tctgagagtgaagtatttcaatacatttactgaaatcttcagttctaaaatccccgaata
+aggctcttatcggtttggccaacacaagaaaaaaacttcttgcaccactcaccttcatac
+gcaggagcctggggaacttagtaataactatttcggcagacaaagcttataacaagttgc
+cggcgcgtataatatttaaaagaccccttgagctgctcaattaaaacgctcacctggtat
+aggctattagatagtgccgtcttagtaaggggcgggaattatcggataaactgatatttt
+gataaaataaccgacttgttcacgacataagtcactaaggagattttatctttctccaaa
+gtatatcttccttggataatttcaaagcgctgcaatttaagttctgttactagtttatgc
+tgctgggaggtgaccggaaggcgtagtaatctagaggcaaattataagaagttcatcata
+tcattttcgactacaaaaacaaggtgttgtatgccggcgcattgtgtaaactggacgagt
+accctagatggaaaattatacgttaagccaagatttcgatgtaatgataattacctacac
+atttttgctatccataggaacaagagctgttctataggctcgtggcatacgaacatttgc
+tgccgctatgaatattggaagctcttcaactacagactctattcttaattgccgtcgaaa
+atgggccgaatcggctattattaatactcggtttttccgaggggattgttgtcgacagtc
+gtaattattattaatattgatgttggtgaggtcatttaaatacaaccttgcagacaatga
+ataagggatccaatctctcatactccttttacaattgctcatgcccctatgcaaacctta
+tgccgccacacctccgcaactctctcttctgaactgtaagtagcttcattactggtttga
+gactatactgaagctgatgacattctaaaatggctattttcgaatgtgattcataatgtt
+tatcgtttgggatggcagaatcacgttatttttgatatagcccgggtattctattgtata
+gaacgtatgctacaagtcattccccgaagaagactagaagtaaacaacatgcgaccatcg
+ttaagccacgcaaggctgtagctttatttcccgataacctatcttccataaatagcggac
+agcaggatactgacgctcaacatcagtggttatggtctaatttttaacttttaataaggt
+aacttcagcaggcatacacagtaactctttaatttataatcaaattagaagtctgacact
+tcttatatttttctatcatccaacgcgatcgcccattagcttattgtgttactaataacg
+tatctaaaccaatccttttcaagctactgcctatattgtcaatatatacaaacaacagga
+tagtaggctgcttaaaaaatattgtcaaccgtgtacgctttacaatacccggaaatcaca
+aactttgtagacaacgagtgaaatttatacactacgaagggccagcgtacaagacccatg
+aattaggcgatatgtttattctgacatattggtttatccttaatctgtcgctgtaaaatg
+aagccgcccccatccctgcgaattttttttcgaagattcacgactgaaatataaatacgt
+ttggctatatttatgttggagggaggcaatagcctttactgttaaccgaagatttagcca
+gtgagtgtgacactaaaacactggaataaatgcaggcgttcttctgggtaaaaggtttag
+tcaatctcgcctataagttcatatagctctggatataattatctggcccatgcatttatc
+atggcgcttggtgccctgtgtgaagccggcctctcatattgaaggtccgaagtattccat
+gtacattaagatcactctctcattcatgcatcttggcttaacaaatctggttgtccaagc
+tttccaggcacgtatggtacaaattcggatcgaatacttataaaaatgatatgttaaact
+gtctaaaacgctcatctacaaagtaaagtgcactaaccaatagagtctcaagaccgtgta
+atgctggtgcactgaatgtgtaatacggttagaagggattagttatgttacaaatccatt
+gaaaacttaagaagcattgcgtgctcggagggtgcatcttttatcaagagactaacatta
+ttttcaacgacgtacatgctttacaatagggtacttatcaaacgccgagaaacgcgccta
+tagtgatgttatgattatgacccgatatccattggaccgaattttatgtaggttcccagc
+gtactcgcgtaatatctcggtattgccataatgtaatacttgtcggtctctcccagatga
+aaaagcgttacagagtatttcaatgaaaaacagcgcgcaacgtcaatacctttaggggta
+acggccgctgatttcatatagatatacgataagttggtatagctctactaggtggcatcc
+acaatcgttgcatttactatagctggttacaatcataatctataccgttccttacatact
+accatagcgggatagcgtttttttgccgttgattgggtttaagaggatgtcagtctcatt
+atatccgattcggtgggagagccgttgttttcaaatcgcacactttgtgacataatgtac
+aagataacaaaactgatataagatataaactgtcaatatcaccttgacacttgaatcaaa
+gtaaattaactcgcaaatataatttgactaattgggtgcagatttctcaattaataaaaa
+aatggcaccggatgggcttacaagccccttatcattcacttgtatcatgatttccaagaa
+caatagaatttgctagcaagtatgaacagagattcgaattgcatccacagtacgccggag
+cgtttattttaatgtggatatgacgatgtactgttggcggcatttgctagtaaccggtcc
+ttatttacgtagcgcacacgtaagcatgtctgggagaaatatggtggtacaatctcagag
+aaagattacagtttggtttaaataggacttatcgggtcggaagtggaacttaataagcag
+tacacaattgggcaacagacgtcttgcctattacaataggattacaatgcgttagatttc
+agacacgttcgtgtttggctattcgtcaattccctaaatagttagacgatcaactattat
+caaagtgattctttgttcatcctccattcatgtaacagatggcacactacgcataacgcc
+gaggaattttaacgagatttaagagagcagttcgggcacaacccacttgactttataaca
+gctcggcagcataaacggtaatatgtgacaaatttccaaacgttataagaacgtatgtgt
+acttagaaaactaagtggttcatgttcaacagatgtgacgcagcaagcctaacttatcta
+ttggttttgctataaaagaacaaagttacacagaatcctaagggcttgtttcacacttat
+gcctagtgcttcaccatcttaaaatagcgaaaccggcacgaatcaaaccttaaaacaatg
+cgcagatattggtgatggtgactccgggtatgataatggtaactgttgaccagcgcccac
+ctcatcgaagtatagaaagtggttaggataaggatgagaccgaacttatttccggccata
+actttagattttctacctagtacacaacatcagggcggacacgaaaccgccatcacatca
+tataccaggtttaatttgcttaatgggggaagtgtcaacgaaccttcgaactttagcagg
+catatggccattatatatggccccagagcagaatgctacagcagacaaaatttggattta
+tgtagtttaatacctatcaaacttggtgtgaccatacttgtctaacgacagtgcacaaag
+tgtaagttacaattattactactcagcagcttctgcaatgataaaatcttatcatacacg
+tcacatatgataatatctacttagggggaacgggctccacaacctacatagtactcaata
+cttacactattcgacaggcacaccaaacctgtacagtcccaaaagattgagtcaactttg
+cagtactgcagatcacagtaatagcttagttagcgagtcaaaattagttttctacgagac
+tgcacgaccgtgcaaatttccgatgtgttggctacaaatagcaacgtatgaatttgtttg
+aagccacgtaaactgtacaaccttagagataagtctcaggctactaaaaacacgttgtgg
+cactaacaggatcatggttgattcttacttattcggctgaccggcccaataagtaacctt
+caactagaacagaataatcgggagtagtttaattcagtcaaggtgcaggtctcattgtaa
+ctaacaagctctgtgtaaccaagttaaaatcgttttcttagcggattccctacttatgga
+tttgagctcgtccacaatattcgatacaagaagtttgtggtccgtaacaacgaaatttta
+attacgctgtgcagcctcatccaaggaattaatagaaggttgatggtaggctccgaacgc
+tccatgattataatcaagtggactgtgcagtaaacgaggaaggtatcctgacgtcgtggt
+gttcgtttttgttatttgtgccctatacgagtagataaaccatgaacagcacagtgtgaa
+cccatggttgattttaggctaccttatttttaatttccgttacacagaaacgaattccac
+aactaacatgccattaatttttcgatatcttataaaagatggtcgaaattcattcattta
+ttttttttcggttctcgaaagtcaactaagctgtcgcgttttgtttctctttagaggtaa
+aagtggctttgatctcctacgtttggatactagtcaaccattactccatttgatccgtga
+gtatcacctgtctaacatccagcattatgactcctcggcgaagaaaagacacacttctta
+gagtcgatgtgtattagctagggacacagttgtttaatacgatagtgagcccagggaggg
+cagtgcgtcccccagtagatttattcagctagtgtaagtataagatatctcacccacgag
+gttcaagtgatatgcagtcttagaataatacttatcctgaatttcgatattatgggtact
+tcaataatccgctagcgctactttatgtctcgttggacagcaggacacatggcagtctta
+aacactaaagacatcacctgaatgaatgtaatgggattacaagaatcaatgaggtattat
+atacgacgtaggaaactctggatatatacagtaatctagttacgccatcgcacttcattc
+ctctggaaacttagaagacatcagctgtacgtggaggaaccagacccccgtatgtagcca
+aatagaaccaaagttgcttatacaaacacacccaatgacaatggaccgctggagttcgta
+aactcggaacgtagtactgcacaaacccagcatttagcaataggagctacgtatgcaact
+cccacgtggtaataccttcaagctatcaatatataggtgcctagctaatcgcattcgcaa
+gcagtattcaagcttgtaaaccagtataataattacagaggctctatgaaacccaacttt
+ccagctaaaagtcccaattaaatggttatttcgtacttttaaagtcgcccgttctgttat
+tacgcgaattgattctactccaaaattaaacacaaattatcaaccgtttcatttatattt
+gtcaatgcagctgtttaaaataaggctctactaaattataattaagacacttattaccag
+atttctctagttaagtttgaaccagctcgactaccgcgaaagatacattcccttctctat
+ttttcagttcatctatgggtcagagaagcattgaatttattctattcaccctcgtcgttc
+acagcgaatcgtcagtgtgatcagtgtatgagaaatatcctaaaccgtttagtcagacca
+cacgcttagaacaagtggtctaaaaagactgccctggaaggagtaagaagtatacagctg
+atccggtgtatccttcagtcatctgccctatactaattacacgacgcaaggaaaaatagg
+tttattttctaggcaaacccttcataggtgactccgatgtgttacgaatcatgcttgaga
+atgtgctatcgttaccgacggataataacgatctccaatgaaccaaatgtagaatgtcta
+ttgattacccttttactattcgacttagagataggagatagaacctcagtgtactttttt
+agccgaatgggaatctttgggaggtgaatggccataaggtcgtaaatccaaccctcttaa
+agtcttccatattatatcgttgttcgtggaatcgataacagatttgttgacccatagtaa
+atgtatactagtttatgttgtaagtgtagattgttttccgattgccgtccaaactttatg
+tcgtaattgtagaccagtaaagttgaccaaggtaagtgcccagcgatcctgcgagatcga
+tcgccaatttttccagtcactgtaagtgtaggtttagataaagccgtatgagttatatca
+taagggcctcggaaagcagcttcgaaccaaagttcccttataatagtagtttaactataa
+aagtatatactggtctgtcgccctttcacgatttgttttaccggtttatgaagcgttacg
+tcattagagcggctccaatttaaggttaacggcttccatgtgtagttgtatacaaggata
+acttaaagtatctgttcagcgagctagttaagttatcctcgatagaacacaactcagagg
+tcccaagatcgggtttgcaacttgctaatttattctcaaggcaaattgggaattatcgat
+acctgtataccataaggtcgctcgatgtgatgcttatgtcttctggtgatcctaccttag
+ttagtgctgattaacggaacattaatgtttatcgttttgagatttagccaattctctgat
+tctaactcaagatgccttatctgacgtgctatgcagcccctaagtattttacattgtaat
+aggacacgctcctttaaaactcgccaaaaggtcgttgtggttctctactggttaactata
+taatttacagctttgttgagctagttcctctttggtttaagtcctcaatattagttggtt
+cgagcgataagttggctagttaccttagtcactatattagatccgaatgttatgcttcat
+ctgaagaccgccaccctccaaaatttcttttaagactcacttattgcaaggtgtaggtga
+attcggctcgtttctcaagtggtgtatctgtacacgagtttccatattttcatcaacagc
+caccgcacacttatgtcactctaggtattaaaagtcgctctacaaggggacgcaattaag
+aaacagacatgctagtcaaaaataaacatagcgaggcaccactaattcggccgcttatca
+atgggatgctctgcgcgagacgcgccagagctcagtagttagttcggacatacatttact
+tcagatgatcaattagttttctacaaatgcttactctaccccgaaaaaagtcaccagact
+cttacgtctctttagtatccttccgtcttatataaggtcagtcccccgtttcggtaccct
+ggaatttactaagaataatgaaacagcccccaaggacgtacgtttacaaatgatagacca
+gatcgcctagcttattccgacgcatgttgcatagaattgaaccaacggaatgtgagagta
+actagatgagccgaccacagcacccgtttgcgtcgcagaatacgcctgatagttcggcca
+cgaaatcatatgtcctttgagtattaagtatttgtaatgatcaatcgagctcaagcaagc
+ttacacttcctcggatattcagggaacttagtgcctttgaaagatacgttgatcaacgaa
+aaattgataatggctcatatggaatgcctacctcatagtgctgaattaacacagcactgc
+ggacctaacttttcgaggtttcaagttcacgtctcaaaacctaataggctggaatatgta
+gggatcctcggtgaatttgtgattgggtttgttgtagtactgaccaagtgaatattcttt
+ttttctaaaagcagatctgctgccgggcactacgaaggagatctctgtgtatcattattg
+cttcttgacatgatgactcttaaatcactgtgggtgtgcaaaacgatagcacaacccaat
+tcgatagtacatattgttgatacttcgcactaaaccgttcatatttaaaggttgtgctcc
+ttccttcgttaaatactggtgacttggtcctatctactattagctagacctctggggaac
+cacgcccccgtaaaacctgtgcaagagagggggtcatacatcttagacatcgcgcctcca
+ccagggaagcattgggtgattgaccaggtgtgtaacaaatatgattattcttatactaat
+attagcaaagatgcataatgatttgtattaaatgtataattgaattgataagggtctttt
+agtcagtgatagagtagtataaggtagacattagaactcttaaccggacgcagatttttc
+ggtcttagtaagccaattagtcgacaaaacaaggtaagagcggttactagtagtacctat
+aatgcactgaatcttcggtcgaagtatagttctaatgctatgcagattgtgacggcgaca
+aatgttcagacttatatcatgaaacaagctcttgtaagtattgacaaatgaaaagattga
+atatttttaaatacaaaatgcgcctacttattaggggaattaaccagattgaaggccaat
+cctcacatgtaatgagataatagacgataaatgaaattcttgtaatagttgaactgctac
+gtgatgggtattatatatgattgagatcctccaattgccgacgtcttgtcttgatgccca
+aaagattgtcaacgaggagctccctcgcgtacctgtcgtccgtatcataaacgacgcgac
+atgtacagcactccgaagtataagcaataataatgcgggtaatccagactagatcttttc
+ggactcaatgcggtttcacggtaaacatgattaataccggagagtagtcgagcttatcag
+cgatgcaagcgaattcattgtgccaggagatacgttgcagataaaaccggcaacgtatgt
+caacaagttttggcgatctcgttgtttgtattcgacgaggcgcgggaacttcaagaacta
+tcgtatattcaagtccattaccttttagtttcagactggtggagctgactaaagttatat
+catcattttgtacactggtttagttaacgataatttcagatttaacatgaccagacgata
+atcgctgtatatccagttggaatgtggtttgccagaaaggttaacttataatcaagcctc
+tcttcagtcttgattcgtcgtatcccatccattgcgctatacctcagtgtatttggagct
+gtagttataccgtgtgctaagatcagtagacatgacgagagcaatattatctaccttaca
+agcatcaacggacgtctagtcggaacaaaagactctaaaactcgaacttcaggttaatat
+actatagttctgtattcagcagttattcttatattcgatattatcttgcctattggatgt
+ctgactttagtatattaatcatagtatctgccatgtaaaggtgccagtactaaatctgtt
+tcacagtgcgaattataaacggttacaaccattaaagacaacaagaccctatagctttat
+ttgaattttgtcaatgcgcaacttggagctcgcgatacatcccaattagtctatagggtc
+gggacgattctacggcatttctggttataatgacaacatggattgtggcccgagaatcgc
+tctttcattaattaagcaatcattacagtcttataagcgctacttccgagtggtagcagg
+taactcgatataaggtcgcatgagccgaatagcttaaaaaacaggccaccgaacattgat
+agagaataccgaccacagcgcaacctttgattactttcattaaattgtacggctcactcg
+acatcaagcttaagattgcgataatgtgaactcaaatggatcagtactgaagaaccgtaa
+cccacttcgcagaaagcgtacccagagaagatacgctgttacaatatacagggtgaaatt
+attgcctgttcttcgtaaccatttcgccaaacttggttagaaatgatagccattcatgat
+agaaataagctgaatgataccagtatctttaactatgtagtcagggggaagataacgatg
+gtccatgtatgtttctgatatgtgacagtattggccgcgtaatttgctaacgaagctact
+taatgcctttgagcttcatatagatttctttaatcaaaatcggcaaaaagatagtatgag
+ctataatatatgctagtagagaactctggaccatcatctatatgaatactgattcgagcg
+tgcaattactttagcctgcgtactactgactctacaaaacactctgagataagtttgtag
+tcagtaagtcgctctctataaaccttttggatgaccattgtacagccacttatagatccc
+aataaatagcacaggagacagagtttttcaatgctcgatcatttgccgatagtattttcg
+tctaacctcagggcacctattatttgatacctaacctaacggccctttcacaatggagaa
+atatatgacatcgggacaaacacaaatggtgggtggccaggagatatgacatggtggcgt
+ctctaagaaacacggactccctctaggcaaactcacgtaaccaattttaatgtcaaacaa
+aacgctcgaaaagattttgccgtgtaatgacctggtacattgactggtcaggaatacatc
+actgtagttgccgtagtgtcctgttggtgttccatcaagacacatcgtataacgcaattt
+acgacggacatcagatcaagttatacagattatttaagtatcacgtgtgcattgggacat
+aagggatctcacacatgccttggaacatttttgctttgtgccgctttttcgctgcactac
+caatccttacttaccagtatattcaaaggtcgttaacagaatgagaaaggttagggctct
+aagttatcgtcgattgggatagacgagacatttgcgagcgccctccacggatacgaatct
+cccatatcaatgtgaactggatgctatgcagtttagttcttacgtctcctagtggtaaaa
+atcaaagtagcactcgcatagcagttattcagaacctaatacacaaaaccgtcaaacatt
+ttctaattctaggtatgggccgatcataggagctaaggtgaaactcataaatgttttgtt
+agatctagcatcctaaaaagatgcatatactgagtagctggcgtgcattctctcaattgt
+atcctttttaactgaactagtcggtcccatttcgtgactgagatctattaaccgataaga
+ttaataacactcgcattcgtatcagctcagagtgaagtttttcaataatttgactgatat
+attaacttctaaaataaccctttaagcctcggatccgtttcccaatcacatcaaaaattc
+ttattccaactatctacggattaacaacgtgcatggggatcgtagtaagaacttgttccg
+atcactttgagtatatcaagttgacggcccggttattattgaatagaaacattcacctgc
+taaattaaataccgcacatcggatacccgatttcagagggccgtcttactaagggcaggc
+tttgttcggtttaactgagatgttcattattttacagtatgcttcaactaatatgtaacg
+aaggacagtggatctgtctccatagtagatcttcagtcgtgaatttcataccgctcctat
+ttaagttcgcgttcgagttgttgatcatggcacgtgaaagcaacccctagtattctagac
+gaaaattttttctagttcatctgataatttgccaattcaaaaacaaccgctggtttcccg
+gcgcattctctaaaatggaagtcgaacctagagccattatttgtcggtaacccatgagtt
+ccttcttttcagaagttaatacactgtggtcctatacagaggaaaaacagcggttatata
+cgatcgtggcataacaacattggatcaagatagcaatttggctacctattctaattctca
+ctagattcggtattccactacaatatcggcagattaggattggatgaataatcggtgttt
+aagtccggttgcgtctccaatctcctaatttttattaatattgatcttggtgacctattg
+taaataaaaacttcaagactttgaataacggtgaaaagatagaagactcatttgaaaatg
+gatcatccacagatccaaacattagcaagacactaatccccaactagctattctgatcgc
+gatcgtgctgcagtactcctgtcacaatagtctgttcatgatctaattctttttgggctt
+tgttcgatggtgattcagaatctttatccggtcgcttccctgtagctactttgtggggat
+attgcccggggattatagggttgagatcgtttcctaaaagtatttaaaccaagtagactt
+caactaaactacatcagaacatcgtgaagacaccatacgcggtacctttatttaccgata
+acatttcttcaagaaataccggtaagcagcataatgaccctaaacagctcggggtatcgt
+cgtagttttaaattttatttaggttactgctcaaggaataaaaactaactatttaattta
+taataatattacaaggctcacactgattagatttgtctataagacttcgcgatcccccat
+taccggattgtcttaagaataaactagataaaccatgcattttctagataaggcctttag
+tctaattagatacaaaaaacacgatagttgcatccttaatttattgtgtcaaacctggaa
+ccttttaattacccgcaaatcactttatgtcgagactacctctgaaatttattatctacc
+taccgcatgaggacttgaaccatcttgtaggagttatgtttattagctaagattcgttta
+tcctgtagcggtccatgtatattcaacaagcaaaaagcactcagaattgtttttagttga
+gtcaagactgatatataaataagtttccctagttttttcgtggtgggacgatattgaatt
+gaatcttaaccgaagagtttcccactctgtcgcacaataatacacgccaatatttccagc
+cctgcttatgccttaatcggttactcaatctcccattgaagttcattttgatctgcatag
+aagtttcgggcccagccttttttctgccaccttcctccaagctctgtagacgcactctaa
+gattgatgctcacatgtattaattctacattaacataaatatataagtcatgcatcttcg
+agtaaaatatctggttctccaacatgtcctggcacgtatcgttataatgcccatacatgt
+agtattaaaatgattgggttaactggatattaagatcatcgaaattgtaaagtcaaatta
+acaatactgtctcaagaccgtgtattcctcgtgctcggaagggctattacgcttacttcc
+gttttggtatcttaatatgactttcaaaaattaagttgcagtgagtcctacctgcgtgca
+tcggttagcaagagtataaaagttgtttaaacgaactacttgctttacaataccggtcgt
+atatatcgccgtgaatccagaagattgtcttctttggattatcaaccgagatcctgtgga
+ccgatgttttgggaccttcacagaggactccaggtagagctcgcttttgcattaatctaa
+gaattgtacctctctaaaagatctaaaacagtgaatgtgtatttcatggaaaaacacaga
+gaaacgtaaattactttaggccgaaaggcacatgagttattatacatatacgagatggtg
+gtatacatcgaattcggggcatacactatagttgcattgtatttagctgctttaaataat
+atgatattaccttccttacataagacattaccggcataccctggttttcaacttgtgggg
+ctttttgacgatcgcactctcatttgatccgagtagggcggtgacccctgcttttcaaat
+acaaaaatttcgctatgaaggtaatagattacttttcgctgttatgatagaaacggtaaa
+tttaaaattgaaacttctagaaaagtaaagtaacgagaaatgattttgtgaataatgcgg
+tcatgattgcgcaagtaagaaaaaaaggcaaaaggatgcgcggaatagaaacttatcagt
+cacgggtatcttgatttcattcttcttgtcaattgccgacataggatgaaatcagattcc
+aatgcaatacacagtaacccccacccttgattgtaatgtcgatttgaagttgtacgcgtc
+gacgaagtggatagtatacgggccttttgtacggtgcgatcaactatgaatctcggcgag
+ttagatggtcgtacaatctcacacatagaggtcacttgcctgtaatgacgaattttcggc
+taggtactcgaactttattagaagtaaaaatgtgggcaaaagaaggattccattttacaa
+gacgattacaatgagttacatgtctctcaacgtagtctttccctagtagtctttgaacta
+tttaggtactccagaaaattttagcaaagggtttctgtgtgaatccgccattcatgttta
+tgatggaacaataagaataacgccctcgtatgttatcgacagtgaagtcagcagttcggc
+caaaaacatattcaatttagtacagatccccagaagttaagctaagtgctctaaaatggc
+ctaaacggttatcaaagtaggtctaattactatactaacgggtgcatcgtaataactgct
+gtcgatgcaacactatatgatagtgtcgttttgctatatatgtacaatgtgacaaagaag
+ccttagcgattcttgcaaacttaggacttcggattctcaatcttaaatgtccgaaaacgc
+aaagattcaaaaatttaatctatgagcagatatgcctgatggtgactacgcgtatgttaa
+ggctaaatgttgacaaccgcacacataatcgaactattgatagtcgggagcataaccagg
+tgaacgtactttgttcacgacatttattgacatgttctaaatacgtctcaaaatcacggc
+gcactagaaaacgcaatcaaatcattgtcctggtttaagggccgtaatgccggtagtgtc
+aaacttcatgagaactttagctggcttttggccagtatttagggaccaagagcactagcc
+ttaagctgaatattttgccatttatctactgttataactttaaaacttggtggcaccaga
+cttgtcgatacacacgcatcaatctgtaacgtaaaaggtttactaagaacaagcgtagga
+attgagtttatattatatttaaactaaaagatgatattagcttctgagggcgatagggct
+ccaaatcataaagaggaatatattattacacgattagaaacccacaacatacctcgaatc
+gcccaaaagtttgacgaaacttggcagtactccacatctcagtaatacagttgggagagt
+ctcaaatgttgttttattactcaatgaaccaccctcataatttcactgctgttccattaa
+atttgcaaacgatcatttgctttgaagaaacgtaaaatcgacaaaattacagataagtag
+atgcataataaaaaaaactgctcgctataacacgatcatcgtgcattcttacttaggagc
+atcacccgcacaataacgtaccttaaactacaacactattagaccgagtactgtaattca
+cgaaagctcaagctcgcattgtaaagaacttgctctctcgtaaaatgtgataatagtttg
+cggagaggattcaattattttccattgcacctactccactagattcgataaaagaaggtg
+gtcctcccttaaaaagaaatgttaagtaacatcggaaccataagcaaagcatgtaagtga
+accgtcatccttccctaagaaacataaaggtttttaataatgtcgactgtgaactataac
+tgcatcctttcctgacctactccggttccttgttgttatttctgaacgagaccagtagat
+aaacaatgtaaaccacagtgggtaccaatggtgcatgtgacgctaccgttgttttaagtg
+cccgtacaaacataagaagtcataatcttacttgaaattaattttgccttttattttttt
+tcaggctcgaaattaatgatttgttttttttgaccttctagttacgctaatatgcggtcg
+cctgtggtttctattgagtcctataacgggatgggatctaatacgtttggttactagtaa
+acaaggtataaatttgataccggagtatcaactgtataacatcaagctttatgactcata
+cgcgaagtaatgacacaaggctttcaggagatcgcgagtacagagccactaaggggtgta
+ttacgatagtgacaccaccgagcgcactcactccccaagtagatttatgatcctacgcta
+agtattagatatataaccaaagaggttctagtcagtgcaactcttagaataataattagc
+cggttttgcctttttaggcctaatgcaatattcagctagcccttatgtatctcgcgttcc
+acagcaccactcatggcacgcgtttaaactaatcaaatataatctatgaatgttatgcca
+gtacttgaataaatcaggttttttataagtccttgcatactctcgttatatactgttaga
+gtcttaccccatagaaattctttcatctgcaaacttagaagaattctcagctacggggag
+cataaagtccccaggatgttgacaaatacaacaaatgtggcttatacaaacactccatat
+gaaaatcgaaccctcgtggtagttttagccgaaccttgtacggataaatccctccatttt
+ccaatagcagatacctatcctactacctcgtggtattaaattaaagcttgaaatatagag
+ctgcatagcttatccaattcccaagcacgagtctaccgtcgtaaccacgatttgatttac
+agacgctagagcaaacccatctttaaacatataagtaaaaattaaagggtgagtgcgtac
+gtgtttactagcaacttcgcttattaagacaattgtttataagccataattaaaaacata
+tgttcaacaggttcattgatatttgtaattgcacaggtttttaataaggatctacgtaag
+tataatgaacaaactttttaccagagttatattctgtactttgaaaatgctcctctaccg
+ccttagagactttcaattagattttttgcagttaatctatgcgtaagtgaaccatgcaag
+ggatgcgattcaaccgcctcgtgctaaccctatcgtctgtctcataactgtaggtctaat
+ataattttcagttttcgaacacataaccctttgaaaatctgctatttaatgtctcacctg
+catgcactatcttctatactgctcagaacggctatacgtcactatgctccaagtgacgat
+ttaaacgaagcaaggaataataggtttattttagtgcaaaacaattaagtgcggactacg
+tgctctttacaataagccttgtgattgggctataggttaagtcccatattaacgatctcc
+aatgtacaaaatcgacaatcgctttgcattacccggttactagtcgaattacagatagct
+gttagatactcactctaattttggacaacaatcccaatcttggggtcgtctatcgcctga
+agctcgtaaatccttccatcttaaacgattacatattatagacttgttcggggtagagat
+atcacagttgtgcaaacattgtaaatcgatactagtttatgttggtagtctagttgcttt
+taccattccccgaaaaacttgatctactatttcgacaacagtaaacttgaactaggtaag
+tgaaaacagagaatgcctcatagtgccactatttgtccactatatgtaagtgtagcttta
+cataatccactatgactgagatcattacggcctaggaaagcagcgtagaaaaaaagggcc
+cggatattacgactgtaactataaaactagttactggtagcgcgccatgtatagatttgt
+tttaccggttgtggttgcgttaacgaatttcagccgcgaaaattgatccgttaaccagtc
+catctcgacttctataaaacgataaagtaaagttgatgttcagcctccttcttatggttg
+catcgagagtacactactcagtgggaaatagatcggggttcctacttcagattgtattat
+ctaggcaattgccgattgtgccatacctggataaaataagctacctacatgtgatgctta
+tctattatcgtcatactaccttagggtgtcctgttgaacgctacattaatctttagccgt
+ttgagatgttccaatggataggagtctaacgcatgatgaagtttaggaaggcagagcatc
+ccactaagtatgtgacagtgtatttcgaaacgagacgttataaatagaaaaaaggtcctt
+ctggttctattctgctgaactattgaatggaaagattggttgacctacgtactatttgct
+tgaagtcatcaatttgacggggtgagagacatatggtgcatactttacggactctatatt
+ttagatcagaagcttagcagtcttctctacaccccctcacgacataattgcttttaagaa
+tctatgtttgattcctctacgggaattcggatccgttcgcatgtgcggtttatctaaacc
+aggggacatatgttcagctaaagcatacgaacactttgctaactagacgtatgtatagta
+gctataaatcccgacgatatttacaaaaagaaatgagactcaaatatatacatagcgacc
+ctacacttattcgcaccctgatctaggcgatcctagcacccacacccgaaagtgagcact
+agtgtcttccgtattaaatttactgcagttgagattttagttgtctactaaggattactc
+taacccgtaataaggatcaagactcggtactagctttactatcattccctatgtgttttc
+ctaactcacaagggtacgtaccagcctatgtaattacaataatgataaagacacaaagga
+agtaactttacaaatgagtctccagttacactagcttagtccctcccatcttgctttgaa
+gtctaaatacgcaatctctgaggatatacagcagaagaacactcataacgttggagtcca
+agaattagactcatagggcccccaacatttaatatgtactgtgagtttgaaggtgttcta
+ttgttaattcctgctcttgatacatgacacgtactccgtgtttaaggcttcggactgact
+ttctttcataagttgagcaacgaaaatttcagaatcgataagttggattcactaactaat
+acggctgattgaaaactccactccggacctatatggtcgacctttatacgtaaccgatat
+aaaacttataggctggtatatcgagccttcctagcgcaatttcggatggggtttcttcta
+ctactcaacaacggaatagtctttgtttagtaaaccagagctcaggacgcccaatacgta
+ggagagcgctgtggagcatgtgtcattatggactggagcactcttaaatcactctgcgtg
+tgctaaacgatagatcataacatgtcctgagtaaattttcttgatacgtcgcaatatacc
+gttattagttaaacgttctcatccgtcatgcgtgaaatacggctgtcgtgctcagatata
+ctattagcgactcatctcgcctaacacgcacacgtataaactcggaatgactgccgctct
+tacatattagaaatacagactacaccacggaagcattgggtcattctcaaccgctgtata
+aaagatgattagtcttataataagattaccaaagaggcagaatcatgggtagtaaatcta
+ttattcaagtgattaccgtcgtgtaggcagggagtgaggacgagatggtactcaggacaa
+atattaaccggacgaagtggtttacgtcgtactttcactattagtagtaaatacaaggta
+acaccggggaatagtactaaatataatgatatctatcttcgggagaacgagtcgtctatt
+gctttgaacattctcaaggcgtaaaatgtgctgacttatagcatgatacaaccgattgtt
+acttttgtctattcaaaagattgaatagttttttatacaaaagccgcatacttatgacgg
+ctagtatacagtttcatcccctagcatcaatgctatggacagtattgaacttataggaaa
+ttcttctaatagggcaaatccgtcgtgatgcctattttttttcagtcacatcctcaaatg
+gcactagtattgtcgggatcccattaacaggctcaaccacgagctcacgcgaggacatgt
+agtccgtatctttaacgaagcgacagcgacagaactcccatggataaccaattataaggc
+ccgtaatcctctagacatcgtttaccaataaatccgctttctccgtaatcatgttgaata
+ccccagagtagtccagatgataaccgatgaaacacaagtctttctcaatgcacttacggt
+gaacttattaccgccaacgtagctcatcaaggttgcgacatctagttgtgtgtttgcgac
+gagcccagcgaacttcatcaactttcgtatattcaacgccttgtaattttactttaagac
+gcctggtgatgtagattcttagataatcagtttgttatcggctgtactttaccataattt
+cacaggtttcaggtcaagaagattatagctgtatatacagttccatgctcggtgcacaga
+aacgtgatcggataataatcaatcgcttatgtcgtctttaggcgtatccaatacatgccc
+cgataccgcagtgtatttcgacatgtaggtataccgtcgcatttgagctcgagtcaggac
+gtcagctagattagattccttaatagaatataccgacctctagtccgaactaaactatag
+ataacgccaacttcaggttaattgtctagtcgtctgtttgcagatgggattcttagatga
+gtgagtatcggccatattggttcgagcactttagtttttgatgcataggatatgcaatgt
+atagctgaaagtactttatctgtttcaaactcacattgattaaaccggtaaacctttaaa
+gactacaagaaaatattcagtgagggcaattttgtcaatcacaatcttccagctagagat
+acttcacaatttgtcttgaggctacgcaacattagacggattttcgcgttttattgaaat
+aatcgaggggcccaagagtatccatagttcattttgtaagatttctttacaggcttatta
+cagcttcttcagactcctacatgcttacgagttatatgctagcatgtgaacaatagatta
+atatacaggaaaacgtacattgagagagatgaccctacacagcgcaaccgttgagtactt
+tcattaaagggtaacgctctcgagacagcatccttaagatggccttattgtcaaatcatt
+tgcagaagtacgcaagatccctaaccaacgtagaagaatccctacaaacacatgagacgc
+ggtgaaaatagacagggtgttagtattcaatcttcggagtatcaatttcgccaatcttgg
+tgagaaagcataccctttcttcagagaaagaagatcaatcataacactatctttaacgag
+gtacgcacgcgcatcattacctgcctccatggatctttaggatagcggaaagtattggca
+gcgtattgtgatttcgttcctactttatcaatttcacattcatatacatgtcttttatca
+aaatcgccaataagataggatgagctatattagatgctagtagagttcgcgccaacatca
+tcgataggaatactcaggacagcgtgataggacttttcaatccctaatactctctataat
+tataactctctcttaagtttggaggcagtaacgcgctctatataatcagtttgctgcacc
+attcttcagcctctgatacatacaaataaattccacagcagtaagagggtttaattgaga
+catcttgggaacttaggattttactctaacatcaccgaaacgattattggataccgtacc
+taaacgaactttctcaaggcagtaatataggacatccgcaataacacaaatgctgcctcc
+ccaggagttatgtcttcctggaggctatatcttacacccactcactataggcaaactaaa
+gtttaaatgttgattgtctaaaaaaaagatagataagagttggccggcgtagcacatgcg
+aaagtgaatcgtaagctataattctctggacttgaagttctgtcctgttcctctgcaaga
+aacaaacttcctttaaagctatttacgacgcacatctcagcaagttataaacatgttgga
+agtttctagtcggaattcccaaagaacggatctatctaatgcattcctacatttttcctg
+tctgccgatggtgccatcctattcaaagaatttcttaaaagtagattaaatgggactttt
+aacaatgagtaaccttacgcctctaagggttcctcgagtgccatacaccagtcaggtccg
+agccacatacacggagaacattctaacatagcattctcaactcgatcatttgcaggttac
+ttctttcctatcctagtgctaaaaatcatacttgcaatcccatagcacggattaagaacc
+taagaaacaattcagtaaaacatgttcgaattcttggtatgggaacatcattgcagctat
+ggtctaacgcattaatgtttgggtacatcttccatcatataaacaggaagagtctgacga
+cagggagtgcttgcgatcatgtctatcattgtgaaatcaaattgtagctcacatgtcgtc
+tatgagagcgtgtatccgataagatttagaaaaatagaagtcgtataagatctcactgaa
+cttttgaatgaatgtgaagcatatatgatctgctttaataaaactttatccataggatac
+gtttccaaatcaattcaataattattagtcaaaatagataaggatgaacaacctgaaggc
+cgatcggacgtagaaagtggtcccatcactttgagttgatattgttgaaccacacgttat
+tatggttttcaaacagtctcaggatattgtatatacagataatccgataccagttgtctg
+acgcccctcttacgtaccccaccctttgtgacgtttaaagcagttgttcagtattttaaa
+ctaggcggcaactaatttggaaagaagcacagtggatatgtctaaattcttgttattcag
+gcctgaatttaatacaccgcatagttaacttcgcggtagagttgttcatcatgcctcctc
+taagctaccacttctatgatacaccaatagttgttctacggaatctgataattggccaag
+tcataaacttccgctgcgttcaacccccttgctcgaatatccaactcgaaaagacagcct
+tttggtgtccggaacaaatcagttacttcttttctgatgttaattctctgtggtcagata
+cagaccaaaaactccgcggatttaccatcctccaagaacaaatttgcatcaacatagcat
+tttggctacatattctaagtctcaatagtttaggttttcaactacattatcccaacatta
+ggattggaggaataatagctgggtaagtccccttgcgtctacaatcgactattttttatg
+aatatgcttctgccgcacctatggttattaaaaaagtcatgactttgaagaaccctgaaa
+agatagatgaatcaggtgtaatggcagcagccaaagagcatataattagcaacactctaa
+gaacattatagatatgatgatagcgatcgtcatgatgttatccggtcacaatagtagctt
+catcagctaattcgttttgccagtggtgacttgcgctggaagaatcgttatacggtccct
+tccctcttgatacggtgggggcttattcaaccgcgtggattgggttgtcatacttgcatt
+aaacgatgtaaaccatctagtagtcaactatactaaatcacaaaatagtgatcaatacat
+acccgcttcatggttttaaccatttaattgattaaagatattccgctaagaaccattatc
+tacctaaactgatcgccgtatcctagtagtttgaaatttgatgtaccgtaatgatcaacg
+aagtaaaacgttatattgtatgtagaataataggtcttggagctaaatgatgtgattggt
+agtgaagacttacccttacaactttaccggtttctcggaagaatatactagagaatcaat
+gcatgggctacataagcactttagtctaatgagataaaaaatacacgagtcttccatcat
+gaattttttgtcgaaaaactcgaacctggtaatttaaaccatatatctttatgtcgtcaa
+taactctcatatgttttatataacttcccaatcacgacttgtaactgcttgttcgactga
+gctgtttgagctatgaggccgggatccggttgagctacatctatttgctacaagaaaaat
+gaaagcacatttgttgggagttctggctacactcatagagaaataagtggcccgagtggg
+tgcggcctgcctccatattcaagtgtatcttaaaccaagtggttccaacgctcgcgctaa
+agaattaaagcctttatttcctccacggagtagcccgtaatccggttcgaaagagaccat
+tgaagttaattttcatatccagtgaagtttaggcacaagcatgtgttctgccacatgcct
+caaagcgctcttcaaccaagatatgattcatcctaacttcgatgaatgcgtctgtaacat
+aaatatagaaggaatgattcggcgagttaattttcgccttctccaacatggcatccctac
+gttcgttataaggaccatacatgtaggttttaaaggtttgcggttaatcgatatttacat
+catagaaattctatagtcaaatttacaagactctagatactcactcgttgcagccggcta
+ggaagcgctttgtaccttacttcccttttcgttgcgtaatatgaatttcatatagtaagt
+tcaaggcactcatacctccgtgaagagggtagatagactattaaagttgtttaatagtac
+gtattgatggaaatgacccgtaggagatttaccactcaatccacaagattcgctgctgtg
+cattatcaaaacagtgcatgtcgaaacatgggttgggtccttcaaacacgaatccaggta
+gagatacctttgcaattttt
diff --git a/third_party/rust/regex-0.2.2/examples/regexdna-output.txt b/third_party/rust/regex-0.2.2/examples/regexdna-output.txt
new file mode 100644
index 000000000000..d36baa5be8d2
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/regexdna-output.txt
@@ -0,0 +1,13 @@
+agggtaaa|tttaccct 0
+[cgt]gggtaaa|tttaccc[acg] 3
+a[act]ggtaaa|tttacc[agt]t 9
+ag[act]gtaaa|tttac[agt]ct 8
+agg[act]taaa|ttta[agt]cct 10
+aggg[acg]aaa|ttt[cgt]ccct 3
+agggt[cgt]aa|tt[acg]accct 4
+agggta[cgt]a|t[acg]taccct 3
+agggtaa[cgt]|[acg]ttaccct 5
+
+101745
+100000
+133640
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-bytes.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-bytes.rs
new file mode 100644
index 000000000000..ec57157c8ea4
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-bytes.rs
@@ -0,0 +1,66 @@
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex { ($re:expr) => { ::regex::bytes::Regex::new($re).unwrap() } }
+
+fn main() {
+    let mut seq = Vec::with_capacity(51 * (1 << 20));
+    io::stdin().read_to_end(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, &b""[..]).into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (regex!("B"), &b"(c|g|t)"[..]),
+        (regex!("D"), &b"(a|g|t)"[..]),
+        (regex!("H"), &b"(a|c|t)"[..]),
+        (regex!("K"), &b"(g|t)"[..]),
+        (regex!("M"), &b"(a|c)"[..]),
+        (regex!("N"), &b"(a|c|g|t)"[..]),
+        (regex!("R"), &b"(a|g)"[..]),
+        (regex!("S"), &b"(c|g)"[..]),
+        (regex!("V"), &b"(a|c|g)"[..]),
+        (regex!("W"), &b"(a|t)"[..]),
+        (regex!("Y"), &b"(c|t)"[..]),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs.into_iter() {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-cheat.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-cheat.rs
new file mode 100644
index 000000000000..a421d208537b
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-cheat.rs
@@ -0,0 +1,88 @@
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+// This technically solves the problem posed in the `regex-dna` benchmark, but
+// it cheats by combining all of the replacements into a single regex and
+// replacing them with a single linear scan. i.e., it re-implements
+// `replace_all`. As a result, this is around 25% faster. ---AG
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (b'B', "(c|g|t)"),
+        (b'D', "(a|g|t)"),
+        (b'H', "(a|c|t)"),
+        (b'K', "(g|t)"),
+        (b'M', "(a|c)"),
+        (b'N', "(a|c|g|t)"),
+        (b'R', "(a|g)"),
+        (b'S', "(c|g)"),
+        (b'V', "(a|c|g)"),
+        (b'W', "(a|t)"),
+        (b'Y', "(c|t)"),
+    ]; // combined into one regex in `replace_all`
+    let seq = replace_all(&seq, substs);
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
+
+fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
+    let mut replacements = vec![""; 256];
+    let mut alternates = vec![];
+    for (re, replacement) in substs {
+        replacements[re as usize] = replacement;
+        alternates.push((re as char).to_string());
+    }
+
+    let re = regex!(&alternates.join("|"));
+    let mut new = String::with_capacity(text.len());
+    let mut last_match = 0;
+    for m in re.find_iter(text) {
+        new.push_str(&text[last_match..m.start()]);
+        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
+        last_match = m.end();
+    }
+    new.push_str(&text[last_match..]);
+    new
+}
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-replace.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-replace.rs
new file mode 100644
index 000000000000..857d8bfcd71d
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-replace.rs
@@ -0,0 +1,19 @@
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).build().unwrap().into_regex()
+    }}
+}
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    println!("original: {}, replaced: {}", ilen, seq.len());
+}
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single-cheat.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single-cheat.rs
new file mode 100644
index 000000000000..64d210499de0
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single-cheat.rs
@@ -0,0 +1,73 @@
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    for re in variants {
+        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
+    }
+
+    let substs = vec![
+        (b'B', "(c|g|t)"),
+        (b'D', "(a|g|t)"),
+        (b'H', "(a|c|t)"),
+        (b'K', "(g|t)"),
+        (b'M', "(a|c)"),
+        (b'N', "(a|c|g|t)"),
+        (b'R', "(a|g)"),
+        (b'S', "(c|g)"),
+        (b'V', "(a|c|g)"),
+        (b'W', "(a|t)"),
+        (b'Y', "(c|t)"),
+    ]; // combined into one regex in `replace_all`
+    let seq = replace_all(&seq, substs);
+
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
+
+fn replace_all(text: &str, substs: Vec<(u8, &str)>) -> String {
+    let mut replacements = vec![""; 256];
+    let mut alternates = vec![];
+    for (re, replacement) in substs {
+        replacements[re as usize] = replacement;
+        alternates.push((re as char).to_string());
+    }
+
+    let re = regex!(&alternates.join("|"));
+    let mut new = String::with_capacity(text.len());
+    let mut last_match = 0;
+    for m in re.find_iter(text) {
+        new.push_str(&text[last_match..m.start()]);
+        new.push_str(replacements[text.as_bytes()[m.start()] as usize]);
+        last_match = m.end();
+    }
+    new.push_str(&text[last_match..]);
+    new
+}
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single.rs
new file mode 100644
index 000000000000..a84bc63c1246
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna-single.rs
@@ -0,0 +1,55 @@
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+
+macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
+
+fn main() {
+    let mut seq = String::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    for re in variants {
+        println!("{} {}", re.to_string(), re.find_iter(&seq).count());
+    }
+
+    let substs = vec![
+        (regex!("B"), "(c|g|t)"),
+        (regex!("D"), "(a|g|t)"),
+        (regex!("H"), "(a|c|t)"),
+        (regex!("K"), "(g|t)"),
+        (regex!("M"), "(a|c)"),
+        (regex!("N"), "(a|c|g|t)"),
+        (regex!("R"), "(a|g)"),
+        (regex!("S"), "(c|g)"),
+        (regex!("V"), "(a|c|g)"),
+        (regex!("W"), "(a|t)"),
+        (regex!("Y"), "(c|t)"),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs.into_iter() {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/third_party/rust/regex-0.2.2/examples/shootout-regex-dna.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna.rs
new file mode 100644
index 000000000000..ec0060d7f445
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/examples/shootout-regex-dna.rs
@@ -0,0 +1,66 @@
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
+//
+// contributed by the Rust Project Developers
+// contributed by TeXitoi
+// contributed by BurntSushi
+
+extern crate regex;
+
+use std::io::{self, Read};
+use std::sync::Arc;
+use std::thread;
+
+macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
+
+fn main() {
+    let mut seq = String::with_capacity(51 * (1 << 20));
+    io::stdin().read_to_string(&mut seq).unwrap();
+    let ilen = seq.len();
+
+    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "").into_owned();
+    let clen = seq.len();
+    let seq_arc = Arc::new(seq.clone());
+
+    let variants = vec![
+        regex!("agggtaaa|tttaccct"),
+        regex!("[cgt]gggtaaa|tttaccc[acg]"),
+        regex!("a[act]ggtaaa|tttacc[agt]t"),
+        regex!("ag[act]gtaaa|tttac[agt]ct"),
+        regex!("agg[act]taaa|ttta[agt]cct"),
+        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!("agggt[cgt]aa|tt[acg]accct"),
+        regex!("agggta[cgt]a|t[acg]taccct"),
+        regex!("agggtaa[cgt]|[acg]ttaccct"),
+    ];
+    let mut counts = vec![];
+    for variant in variants {
+        let seq = seq_arc.clone();
+        let restr = variant.to_string();
+        let future = thread::spawn(move || variant.find_iter(&seq).count());
+        counts.push((restr, future));
+    }
+
+    let substs = vec![
+        (regex!("B"), "(c|g|t)"),
+        (regex!("D"), "(a|g|t)"),
+        (regex!("H"), "(a|c|t)"),
+        (regex!("K"), "(g|t)"),
+        (regex!("M"), "(a|c)"),
+        (regex!("N"), "(a|c|g|t)"),
+        (regex!("R"), "(a|g)"),
+        (regex!("S"), "(c|g)"),
+        (regex!("V"), "(a|c|g)"),
+        (regex!("W"), "(a|t)"),
+        (regex!("Y"), "(c|t)"),
+    ];
+    let mut seq = seq;
+    for (re, replacement) in substs.into_iter() {
+        seq = re.replace_all(&seq, replacement).into_owned();
+    }
+
+    for (variant, count) in counts {
+        println!("{} {}", variant, count.join().unwrap());
+    }
+    println!("\n{}\n{}\n{}", ilen, clen, seq.len());
+}
diff --git a/third_party/rust/regex/examples/shootout-regex-redux-1.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-redux-1.rs
similarity index 100%
rename from third_party/rust/regex/examples/shootout-regex-redux-1.rs
rename to third_party/rust/regex-0.2.2/examples/shootout-regex-redux-1.rs
diff --git a/third_party/rust/regex/examples/shootout-regex-redux-chunked.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-redux-chunked.rs
similarity index 100%
rename from third_party/rust/regex/examples/shootout-regex-redux-chunked.rs
rename to third_party/rust/regex-0.2.2/examples/shootout-regex-redux-chunked.rs
diff --git a/third_party/rust/regex/examples/shootout-regex-redux.rs b/third_party/rust/regex-0.2.2/examples/shootout-regex-redux.rs
similarity index 100%
rename from third_party/rust/regex/examples/shootout-regex-redux.rs
rename to third_party/rust/regex-0.2.2/examples/shootout-regex-redux.rs
diff --git a/third_party/rust/regex-0.2.2/scripts/frequencies.py b/third_party/rust/regex-0.2.2/scripts/frequencies.py
new file mode 100755
index 000000000000..c800b0bb39e8
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/scripts/frequencies.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+# This does simple normalized frequency analysis on UTF-8 encoded text. The
+# result of the analysis is translated to a ranked list, where every byte is
+# assigned a rank. This list is written to src/freqs.rs.
+#
+# Currently, the frequencies are generated from the following corpuses:
+#
+#   * The CIA world fact book
+#   * The source code of rustc
+#   * Septuaginta
+
+from __future__ import absolute_import, division, print_function
+
+import argparse
+from collections import Counter
+import sys
+
+preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// NOTE: The following code was generated by "scripts/frequencies.py", do not
+// edit directly
+'''
+
+
+def eprint(*args, **kwargs):
+    kwargs['file'] = sys.stderr
+    print(*args, **kwargs)
+
+
+def main():
+    p = argparse.ArgumentParser()
+    p.add_argument('corpus', metavar='FILE', nargs='+')
+    args = p.parse_args()
+
+    # Get frequency counts of each byte.
+    freqs = Counter()
+    for i in range(0, 256):
+        freqs[i] = 0
+
+    eprint('reading entire corpus into memory')
+    corpus = []
+    for fpath in args.corpus:
+        corpus.append(open(fpath, 'rb').read())
+
+    eprint('computing byte frequencies')
+    for c in corpus:
+        for byte in c:
+            freqs[byte] += 1.0 / float(len(c))
+
+    eprint('writing Rust code')
+    # Get the rank of each byte. A lower rank => lower relative frequency.
+    rank = [0] * 256
+    for i, (byte, _) in enumerate(freqs.most_common()):
+        # print(byte)
+        rank[byte] = 255 - i
+
+    # Forcefully set the highest rank possible for bytes that start multi-byte
+    # UTF-8 sequences. The idea here is that a continuation byte will be more
+    # discerning in a homogenous haystack.
+    for byte in range(0xC0, 0xFF + 1):
+        rank[byte] = 255
+
+    # Now write Rust.
+    olines = ['pub const BYTE_FREQUENCIES: [u8; 256] = [']
+    for byte in range(256):
+        olines.append('    %3d, // %r' % (rank[byte], chr(byte)))
+    olines.append('];')
+
+    print(preamble)
+    print('\n'.join(olines))
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/rust/regex-0.2.2/scripts/regex-match-tests.py b/third_party/rust/regex-0.2.2/scripts/regex-match-tests.py
new file mode 100755
index 000000000000..24635e7797f9
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/scripts/regex-match-tests.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python2
+
+# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+from __future__ import absolute_import, division, print_function
+import argparse
+import datetime
+import os.path as path
+
+
+def print_tests(tests):
+    print('\n'.join([test_tostr(t) for t in tests]))
+
+
+def read_tests(f):
+    basename, _ = path.splitext(path.basename(f))
+    tests = []
+    for lineno, line in enumerate(open(f), 1):
+        fields = filter(None, map(str.strip, line.split('\t')))
+        if not (4 <= len(fields) <= 5) \
+           or 'E' not in fields[0] or fields[0][0] == '#':
+            continue
+
+        opts, pat, text, sgroups = fields[0:4]
+        groups = []  # groups as integer ranges
+        if sgroups == 'NOMATCH':
+            groups = [None]
+        elif ',' in sgroups:
+            noparen = map(lambda s: s.strip('()'), sgroups.split(')('))
+            for g in noparen:
+                s, e = map(str.strip, g.split(','))
+                if s == '?' and e == '?':
+                    groups.append(None)
+                else:
+                    groups.append((int(s), int(e)))
+        else:
+            # This skips tests that should result in an error.
+            # There aren't many, so I think we can just capture those
+            # manually. Possibly fix this in future.
+            continue
+
+        if pat == 'SAME':
+            pat = tests[-1][1]
+        if '$' in opts:
+            pat = pat.decode('string_escape')
+            text = text.decode('string_escape')
+        if 'i' in opts:
+            pat = '(?i)%s' % pat
+
+        name = '%s_%d' % (basename, lineno)
+        tests.append((name, pat, text, groups))
+    return tests
+
+
+def test_tostr(t):
+    lineno, pat, text, groups = t
+    options = map(group_tostr, groups)
+    return 'mat!(match_%s, r"%s", r"%s", %s);' \
+           % (lineno, pat, '' if text == "NULL" else text, ', '.join(options))
+
+
+def group_tostr(g):
+    if g is None:
+        return 'None'
+    else:
+        return 'Some((%d, %d))' % (g[0], g[1])
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        description='Generate match tests from an AT&T POSIX test file.')
+    aa = parser.add_argument
+    aa('files', nargs='+',
+       help='A list of dat AT&T POSIX test files. See src/testdata')
+    args = parser.parse_args()
+
+    tests = []
+    for f in args.files:
+        tests += read_tests(f)
+
+    tpl = '''// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// DO NOT EDIT. Automatically generated by 'scripts/regex-match-tests.py'
+// on {date}.
+'''
+    print(tpl.format(date=str(datetime.datetime.now())))
+
+    for f in args.files:
+        print('// Tests from %s' % path.basename(f))
+        print_tests(read_tests(f))
+        print('')
diff --git a/third_party/rust/regex/scripts/unicode.py b/third_party/rust/regex-0.2.2/scripts/unicode.py
similarity index 100%
rename from third_party/rust/regex/scripts/unicode.py
rename to third_party/rust/regex-0.2.2/scripts/unicode.py
diff --git a/third_party/rust/regex-0.2.2/src/backtrack.rs b/third_party/rust/regex-0.2.2/src/backtrack.rs
new file mode 100644
index 000000000000..78bc39e93e07
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/backtrack.rs
@@ -0,0 +1,302 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This is the backtracking matching engine. It has the same exact capability
+// as the full NFA simulation, except it is artificially restricted to small
+// regexes on small inputs because of its memory requirements.
+//
+// In particular, this is a *bounded* backtracking engine. It retains worst
+// case linear time by keeping track of the states that it has visited (using a
+// bitmap). Namely, once a state is visited, it is never visited again. Since a
+// state is keyed by `(instruction index, input index)`, we have that its time
+// complexity is `O(mn)` (i.e., linear in the size of the search text).
+//
+// The backtracking engine can beat out the NFA simulation on small
+// regexes/inputs because it doesn't have to keep track of multiple copies of
+// the capture groups. In benchmarks, the backtracking engine is roughly twice
+// as fast as the full NFA simulation. Note though that its performance doesn't
+// scale, even if you're willing to live with the memory requirements. Namely,
+// the bitset has to be zeroed on each execution, which becomes quite expensive
+// on large bitsets.
+
+use exec::ProgramCache;
+use input::{Input, InputAt};
+use prog::{Program, InstPtr};
+use re_trait::Slot;
+
+type Bits = u32;
+
+const BIT_SIZE: usize = 32;
+const MAX_SIZE_BYTES: usize = 256 * (1 << 10); // 256 KB
+
+/// Returns true iff the given regex and input should be executed by this
+/// engine with reasonable memory usage.
+pub fn should_exec(num_insts: usize, text_len: usize) -> bool {
+    // Total memory usage in bytes is determined by:
+    //
+    //   ((len(insts) * (len(input) + 1) + bits - 1) / bits) * (size_of(u32))
+    //
+    // The actual limit picked is pretty much a heuristic.
+    // See: https://github.com/rust-lang/regex/issues/215
+    let size = ((num_insts * (text_len + 1) + BIT_SIZE - 1) / BIT_SIZE) * 4;
+    size <= MAX_SIZE_BYTES
+}
+
+/// A backtracking matching engine.
+#[derive(Debug)]
+pub struct Bounded<'a, 'm, 'r, 's, I> {
+    prog: &'r Program,
+    input: I,
+    matches: &'m mut [bool],
+    slots: &'s mut [Slot],
+    m: &'a mut Cache,
+}
+
+/// Shared cached state between multiple invocations of a backtracking engine
+/// in the same thread.
+#[derive(Clone, Debug)]
+pub struct Cache {
+    jobs: Vec<Job>,
+    visited: Vec<Bits>,
+}
+
+impl Cache {
+    /// Create new empty cache for the backtracking engine.
+    pub fn new(_prog: &Program) -> Self {
+        Cache { jobs: vec![], visited: vec![] }
+    }
+}
+
+/// A job is an explicit unit of stack space in the backtracking engine.
+///
+/// The "normal" representation is a single state transition, which corresponds
+/// to an NFA state and a character in the input. However, the backtracking
+/// engine must keep track of old capture group values. We use the explicit
+/// stack to do it.
+#[derive(Clone, Copy, Debug)]
+enum Job {
+    Inst { ip: InstPtr, at: InputAt },
+    SaveRestore { slot: usize, old_pos: Option<usize> },
+}
+
+impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
+    /// Execute the backtracking matching engine.
+    ///
+    /// If there's a match, `exec` returns `true` and populates the given
+    /// captures accordingly.
+    pub fn exec(
+        prog: &'r Program,
+        cache: &ProgramCache,
+        matches: &'m mut [bool],
+        slots: &'s mut [Slot],
+        input: I,
+        start: usize,
+    ) -> bool {
+        let mut cache = cache.borrow_mut();
+        let mut cache = &mut cache.backtrack;
+        let start = input.at(start);
+        let mut b = Bounded {
+            prog: prog,
+            input: input,
+            matches: matches,
+            slots: slots,
+            m: cache,
+        };
+        b.exec_(start)
+    }
+
+    /// Clears the cache such that the backtracking engine can be executed
+    /// on some input of fixed length.
+    fn clear(&mut self) {
+        // Reset the job memory so that we start fresh.
+        self.m.jobs.clear();
+
+        // Now we need to clear the bit state set.
+        // We do this by figuring out how much space we need to keep track
+        // of the states we've visited.
+        // Then we reset all existing allocated space to 0.
+        // Finally, we request more space if we need it.
+        //
+        // This is all a little circuitous, but doing this unsafely
+        // doesn't seem to have a measurable impact on performance.
+        // (Probably because backtracking is limited to such small
+        // inputs/regexes in the first place.)
+        let visited_len =
+            (self.prog.len() * (self.input.len() + 1) + BIT_SIZE - 1)
+            /
+            BIT_SIZE;
+        self.m.visited.truncate(visited_len);
+        for v in &mut self.m.visited {
+            *v = 0;
+        }
+        if visited_len > self.m.visited.len() {
+            let len = self.m.visited.len();
+            self.m.visited.reserve_exact(visited_len - len);
+            for _ in 0..(visited_len - len) {
+                self.m.visited.push(0);
+            }
+        }
+    }
+
+    /// Start backtracking at the given position in the input, but also look
+    /// for literal prefixes.
+    fn exec_(&mut self, mut at: InputAt) -> bool {
+        self.clear();
+        // If this is an anchored regex at the beginning of the input, then
+        // we're either already done or we only need to try backtracking once.
+        if self.prog.is_anchored_start {
+            return if !at.is_start() {
+                false
+            } else {
+                self.backtrack(at)
+            };
+        }
+        let mut matched = false;
+        loop {
+            if !self.prog.prefixes.is_empty() {
+                at = match self.input.prefix_at(&self.prog.prefixes, at) {
+                    None => break,
+                    Some(at) => at,
+                };
+            }
+            matched = self.backtrack(at) || matched;
+            if matched && self.prog.matches.len() == 1 {
+                return true;
+            }
+            if at.is_end() {
+                break;
+            }
+            at = self.input.at(at.next_pos());
+        }
+        matched
+    }
+
+    /// The main backtracking loop starting at the given input position.
+    fn backtrack(&mut self, start: InputAt) -> bool {
+        // N.B. We use an explicit stack to avoid recursion.
+        // To avoid excessive pushing and popping, most transitions are handled
+        // in the `step` helper function, which only pushes to the stack when
+        // there's a capture or a branch.
+        let mut matched = false;
+        self.m.jobs.push(Job::Inst { ip: 0, at: start });
+        while let Some(job) = self.m.jobs.pop() {
+            match job {
+                Job::Inst { ip, at } => {
+                    if self.step(ip, at) {
+                        // Only quit if we're matching one regex.
+                        // If we're matching a regex set, then mush on and
+                        // try to find other matches (if we want them).
+                        if self.prog.matches.len() == 1 {
+                            return true;
+                        }
+                        matched = true;
+                    }
+                }
+                Job::SaveRestore { slot, old_pos } => {
+                    if slot < self.slots.len() {
+                        self.slots[slot] = old_pos;
+                    }
+                }
+            }
+        }
+        matched
+    }
+
+    fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
+        use prog::Inst::*;
+        loop {
+            // This loop is an optimization to avoid constantly pushing/popping
+            // from the stack. Namely, if we're pushing a job only to run it
+            // next, avoid the push and just mutate `ip` (and possibly `at`)
+            // in place.
+            match self.prog[ip] {
+                Match(slot) => {
+                    if slot < self.matches.len() {
+                        self.matches[slot] = true;
+                    }
+                    return true;
+                }
+                Save(ref inst) => {
+                    if let Some(&old_pos) = self.slots.get(inst.slot) {
+                        // If this path doesn't work out, then we save the old
+                        // capture index (if one exists) in an alternate
+                        // job. If the next path fails, then the alternate
+                        // job is popped and the old capture index is restored.
+                        self.m.jobs.push(Job::SaveRestore {
+                            slot: inst.slot,
+                            old_pos: old_pos,
+                        });
+                        self.slots[inst.slot] = Some(at.pos());
+                    }
+                    ip = inst.goto;
+                }
+                Split(ref inst) => {
+                    self.m.jobs.push(Job::Inst { ip: inst.goto2, at: at });
+                    ip = inst.goto1;
+                }
+                EmptyLook(ref inst) => {
+                    if self.input.is_empty_match(at, inst) {
+                        ip = inst.goto;
+                    } else {
+                        return false;
+                    }
+                }
+                Char(ref inst) => {
+                    if inst.c == at.char() {
+                        ip = inst.goto;
+                        at = self.input.at(at.next_pos());
+                    } else {
+                        return false;
+                    }
+                }
+                Ranges(ref inst) => {
+                    if inst.matches(at.char()) {
+                        ip = inst.goto;
+                        at = self.input.at(at.next_pos());
+                    } else {
+                        return false;
+                    }
+                }
+                Bytes(ref inst) => {
+                    if let Some(b) = at.byte() {
+                        if inst.matches(b) {
+                            ip = inst.goto;
+                            at = self.input.at(at.next_pos());
+                            continue;
+                        }
+                    }
+                    return false;
+                }
+            }
+            if self.has_visited(ip, at) {
+                return false;
+            }
+        }
+    }
+
+    fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
+        let k = ip * (self.input.len() + 1) + at.pos();
+        let k1 = k / BIT_SIZE;
+        let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
+        if self.m.visited[k1] & k2 == 0 {
+            self.m.visited[k1] |= k2;
+            false
+        } else {
+            true
+        }
+    }
+}
+
+fn usize_to_u32(n: usize) -> u32 {
+    if (n as u64) > (::std::u32::MAX as u64) {
+        panic!("BUG: {} is too big to fit into u32", n)
+    }
+    n as u32
+}
diff --git a/third_party/rust/regex-0.2.2/src/compile.rs b/third_party/rust/regex-0.2.2/src/compile.rs
new file mode 100644
index 000000000000..0acdebb1128c
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/compile.rs
@@ -0,0 +1,1102 @@
+// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+use std::iter;
+use std::result;
+use std::sync::Arc;
+
+use syntax::{
+    Expr, Repeater, CharClass, ClassRange, ByteClass, ByteRange,
+    is_word_byte,
+};
+use utf8_ranges::{Utf8Range, Utf8Sequence, Utf8Sequences};
+
+use prog::{
+    Program, Inst, InstPtr, EmptyLook,
+    InstSave, InstSplit, InstEmptyLook, InstChar, InstRanges, InstBytes,
+};
+
+use Error;
+
+type Result = result::Result<Patch, Error>;
+
+#[derive(Debug)]
+struct Patch {
+    hole: Hole,
+    entry: InstPtr,
+}
+
+/// A compiler translates a regular expression AST to a sequence of
+/// instructions. The sequence of instructions represents an NFA.
+pub struct Compiler {
+    insts: Vec<MaybeInst>,
+    compiled: Program,
+    capture_name_idx: HashMap<String, usize>,
+    num_exprs: usize,
+    size_limit: usize,
+    suffix_cache: SuffixCache,
+    utf8_seqs: Option<Utf8Sequences>,
+    byte_classes: ByteClassSet,
+}
+
+impl Compiler {
+    /// Create a new regular expression compiler.
+    ///
+    /// Various options can be set before calling `compile` on an expression.
+    pub fn new() -> Self {
+        Compiler {
+            insts: vec![],
+            compiled: Program::new(),
+            capture_name_idx: HashMap::new(),
+            num_exprs: 0,
+            size_limit: 10 * (1 << 20),
+            suffix_cache: SuffixCache::new(1000),
+            utf8_seqs: Some(Utf8Sequences::new('\x00', '\x00')),
+            byte_classes: ByteClassSet::new(),
+        }
+    }
+
+    /// The size of the resulting program is limited by size_limit. If
+    /// the program approximately exceeds the given size (in bytes), then
+    /// compilation will stop and return an error.
+    pub fn size_limit(mut self, size_limit: usize) -> Self {
+        self.size_limit = size_limit;
+        self
+    }
+
+    /// If bytes is true, then the program is compiled as a byte based
+    /// automaton, which incorporates UTF-8 decoding into the machine. If it's
+    /// false, then the automaton is Unicode scalar value based, e.g., an
+    /// engine utilizing such an automaton is resposible for UTF-8 decoding.
+    ///
+    /// The specific invariant is that when returning a byte based machine,
+    /// the neither the `Char` nor `Ranges` instructions are produced.
+    /// Conversely, when producing a Unicode scalar value machine, the `Bytes`
+    /// instruction is never produced.
+    ///
+    /// Note that `dfa(true)` implies `bytes(true)`.
+    pub fn bytes(mut self, yes: bool) -> Self {
+        self.compiled.is_bytes = yes;
+        self
+    }
+
+    /// When disabled, the program compiled may match arbitrary bytes.
+    ///
+    /// When enabled (the default), all compiled programs exclusively match
+    /// valid UTF-8 bytes.
+    pub fn only_utf8(mut self, yes: bool) -> Self {
+        self.compiled.only_utf8 = yes;
+        self
+    }
+
+    /// When set, the machine returned is suitable for use in the DFA matching
+    /// engine.
+    ///
+    /// In particular, this ensures that if the regex is not anchored in the
+    /// beginning, then a preceding `.*?` is included in the program. (The NFA
+    /// based engines handle the preceding `.*?` explicitly, which is difficult
+    /// or impossible in the DFA engine.)
+    pub fn dfa(mut self, yes: bool) -> Self {
+        self.compiled.is_dfa = yes;
+        self
+    }
+
+    /// When set, the machine returned is suitable for matching text in
+    /// reverse. In particular, all concatenations are flipped.
+    pub fn reverse(mut self, yes: bool) -> Self {
+        self.compiled.is_reverse = yes;
+        self
+    }
+
+    /// Compile a regular expression given its AST.
+    ///
+    /// The compiler is guaranteed to succeed unless the program exceeds the
+    /// specified size limit. If the size limit is exceeded, then compilation
+    /// stops and returns an error.
+    pub fn compile(
+        mut self,
+        exprs: &[Expr],
+    ) -> result::Result<Program, Error> {
+        debug_assert!(exprs.len() >= 1);
+        self.num_exprs = exprs.len();
+        if exprs.len() == 1 {
+            self.compile_one(&exprs[0])
+        } else {
+            self.compile_many(exprs)
+        }
+    }
+
+    fn compile_one(mut self, expr: &Expr) -> result::Result<Program, Error> {
+        // If we're compiling a forward DFA and we aren't anchored, then
+        // add a `.*?` before the first capture group.
+        // Other matching engines handle this by baking the logic into the
+        // matching engine itself.
+        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
+        self.compiled.is_anchored_start = expr.is_anchored_start();
+        self.compiled.is_anchored_end = expr.is_anchored_end();
+        if self.compiled.needs_dotstar() {
+            dotstar_patch = try!(self.c_dotstar());
+            self.compiled.start = dotstar_patch.entry;
+        }
+        self.compiled.captures = vec![None];
+        let patch = try!(self.c_capture(0, expr));
+        if self.compiled.needs_dotstar() {
+            self.fill(dotstar_patch.hole, patch.entry);
+        } else {
+            self.compiled.start = patch.entry;
+        }
+        self.fill_to_next(patch.hole);
+        self.compiled.matches = vec![self.insts.len()];
+        self.push_compiled(Inst::Match(0));
+        self.compile_finish()
+    }
+
+    fn compile_many(
+        mut self,
+        exprs: &[Expr],
+    ) -> result::Result<Program, Error> {
+        debug_assert!(exprs.len() > 1);
+
+        self.compiled.is_anchored_start =
+            exprs.iter().all(|e| e.is_anchored_start());
+        self.compiled.is_anchored_end =
+            exprs.iter().all(|e| e.is_anchored_end());
+        let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
+        if self.compiled.needs_dotstar() {
+            dotstar_patch = try!(self.c_dotstar());
+            self.compiled.start = dotstar_patch.entry;
+        } else {
+            self.compiled.start = 0; // first instruction is always split
+        }
+        self.fill_to_next(dotstar_patch.hole);
+
+        let mut prev_hole = Hole::None;
+        for (i, expr) in exprs[0..exprs.len() - 1].iter().enumerate() {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let Patch { hole, entry } = try!(self.c_capture(0, expr));
+            self.fill_to_next(hole);
+            self.compiled.matches.push(self.insts.len());
+            self.push_compiled(Inst::Match(i));
+            prev_hole = self.fill_split(split, Some(entry), None);
+        }
+        let i = exprs.len() - 1;
+        let Patch { hole, entry } = try!(self.c_capture(0, &exprs[i]));
+        self.fill(prev_hole, entry);
+        self.fill_to_next(hole);
+        self.compiled.matches.push(self.insts.len());
+        self.push_compiled(Inst::Match(i));
+        self.compile_finish()
+    }
+
+    fn compile_finish(mut self) -> result::Result<Program, Error> {
+        self.compiled.insts =
+            self.insts.into_iter().map(|inst| inst.unwrap()).collect();
+        self.compiled.byte_classes = self.byte_classes.byte_classes();
+        self.compiled.capture_name_idx = Arc::new(self.capture_name_idx);
+        Ok(self.compiled)
+    }
+
+    fn c(&mut self, expr: &Expr) -> Result {
+        use prog;
+        use syntax::Expr::*;
+
+        try!(self.check_size());
+        match *expr {
+            Empty => Ok(Patch { hole: Hole::None, entry: self.insts.len() }),
+            Literal { ref chars, casei } => self.c_literal(chars, casei),
+            LiteralBytes { ref bytes, casei } => self.c_bytes(bytes, casei),
+            AnyChar => self.c_class(&[ClassRange {
+                start: '\x00',
+                end: '\u{10ffff}',
+            }]),
+            AnyCharNoNL => {
+                self.c_class(&[
+                    ClassRange { start: '\x00', end: '\x09' },
+                    ClassRange { start: '\x0b', end: '\u{10ffff}' },
+                ])
+            }
+            AnyByte => {
+                self.c_class_bytes(&[ByteRange { start: 0, end: 0xFF }])
+            }
+            AnyByteNoNL => {
+                self.c_class_bytes(&[
+                    ByteRange { start: 0, end: 0x9 },
+                    ByteRange { start: 0xB, end: 0xFF },
+                ])
+            }
+            Class(ref cls) => {
+                self.c_class(cls)
+            }
+            ClassBytes(ref cls) => {
+                self.c_class_bytes(cls)
+            }
+            StartLine if self.compiled.is_reverse => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::EndLine)
+            }
+            StartLine => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::StartLine)
+            }
+            EndLine if self.compiled.is_reverse => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::StartLine)
+            }
+            EndLine => {
+                self.byte_classes.set_range(b'\n', b'\n');
+                self.c_empty_look(prog::EmptyLook::EndLine)
+            }
+            StartText if self.compiled.is_reverse => {
+                self.c_empty_look(prog::EmptyLook::EndText)
+            }
+            StartText => {
+                self.c_empty_look(prog::EmptyLook::StartText)
+            }
+            EndText if self.compiled.is_reverse => {
+                self.c_empty_look(prog::EmptyLook::StartText)
+            }
+            EndText => {
+                self.c_empty_look(prog::EmptyLook::EndText)
+            }
+            WordBoundary => {
+                self.compiled.has_unicode_word_boundary = true;
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::WordBoundary)
+            }
+            NotWordBoundary => {
+                self.compiled.has_unicode_word_boundary = true;
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::NotWordBoundary)
+            }
+            WordBoundaryAscii => {
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::WordBoundaryAscii)
+            }
+            NotWordBoundaryAscii => {
+                self.byte_classes.set_word_boundary();
+                self.c_empty_look(prog::EmptyLook::NotWordBoundaryAscii)
+            }
+            Group { ref e, i: None, name: None } => self.c(e),
+            Group { ref e, i, ref name } => {
+                // it's impossible to have a named capture without an index
+                let i = i.expect("capture index");
+                if i >= self.compiled.captures.len() {
+                    self.compiled.captures.push(name.clone());
+                    if let Some(ref name) = *name {
+                        self.capture_name_idx.insert(name.to_owned(), i);
+                    }
+                }
+                self.c_capture(2 * i, e)
+            }
+            Concat(ref es) => {
+                if self.compiled.is_reverse {
+                    self.c_concat(es.iter().rev())
+                } else {
+                    self.c_concat(es)
+                }
+            }
+            Alternate(ref es) => self.c_alternate(&**es),
+            Repeat { ref e, r, greedy } => self.c_repeat(e, r, greedy),
+        }
+    }
+
+    fn c_capture(&mut self, first_slot: usize, expr: &Expr) -> Result {
+        if self.num_exprs > 1 || self.compiled.is_dfa {
+            // Don't ever compile Save instructions for regex sets because
+            // they are never used. They are also never used in DFA programs
+            // because DFAs can't handle captures.
+            self.c(expr)
+        } else {
+            let entry = self.insts.len();
+            let hole = self.push_hole(InstHole::Save { slot: first_slot });
+            let patch = try!(self.c(expr));
+            self.fill(hole, patch.entry);
+            self.fill_to_next(patch.hole);
+            let hole = self.push_hole(InstHole::Save { slot: first_slot + 1 });
+            Ok(Patch { hole: hole, entry: entry })
+        }
+    }
+
+    fn c_dotstar(&mut self) -> Result {
+        Ok(if !self.compiled.only_utf8() {
+            try!(self.c(&Expr::Repeat {
+                e: Box::new(Expr::AnyByte),
+                r: Repeater::ZeroOrMore,
+                greedy: false,
+            }))
+        } else {
+            try!(self.c(&Expr::Repeat {
+                e: Box::new(Expr::AnyChar),
+                r: Repeater::ZeroOrMore,
+                greedy: false,
+            }))
+        })
+    }
+
+    fn c_literal(&mut self, chars: &[char], casei: bool) -> Result {
+        debug_assert!(!chars.is_empty());
+        let mut chars: Box<Iterator<Item=&char>> =
+            if self.compiled.is_reverse {
+                Box::new(chars.iter().rev())
+            } else {
+                Box::new(chars.iter())
+            };
+        let first = *chars.next().expect("non-empty literal");
+        let Patch { mut hole, entry } = try!(self.c_char(first, casei));
+        for &c in chars {
+            let p = try!(self.c_char(c, casei));
+            self.fill(hole, p.entry);
+            hole = p.hole;
+        }
+        Ok(Patch { hole: hole, entry: entry })
+    }
+
+    fn c_char(&mut self, c: char, casei: bool) -> Result {
+        if casei {
+            self.c_class(&CharClass::new(vec![
+                ClassRange { start: c, end: c },
+            ]).case_fold())
+        } else {
+            self.c_class(&[ClassRange { start: c, end: c }])
+        }
+    }
+
+    fn c_class(&mut self, ranges: &[ClassRange]) -> Result {
+        assert!(!ranges.is_empty());
+        if self.compiled.uses_bytes() {
+            CompileClass {
+                c: self,
+                ranges: ranges,
+            }.compile()
+        } else {
+            let ranges: Vec<(char, char)> =
+                ranges.iter().map(|r| (r.start, r.end)).collect();
+            let hole = if ranges.len() == 1 && ranges[0].0 == ranges[0].1 {
+                self.push_hole(InstHole::Char { c: ranges[0].0 })
+            } else {
+                self.push_hole(InstHole::Ranges { ranges: ranges })
+            };
+            Ok(Patch { hole: hole, entry: self.insts.len() - 1 })
+        }
+    }
+
+    fn c_bytes(&mut self, bytes: &[u8], casei: bool) -> Result {
+        debug_assert!(!bytes.is_empty());
+        let mut bytes: Box<Iterator<Item=&u8>> =
+            if self.compiled.is_reverse {
+                Box::new(bytes.iter().rev())
+            } else {
+                Box::new(bytes.iter())
+            };
+        let first = *bytes.next().expect("non-empty literal");
+        let Patch { mut hole, entry } = try!(self.c_byte(first, casei));
+        for &b in bytes {
+            let p = try!(self.c_byte(b, casei));
+            self.fill(hole, p.entry);
+            hole = p.hole;
+        }
+        Ok(Patch { hole: hole, entry: entry })
+    }
+
+    fn c_byte(&mut self, b: u8, casei: bool) -> Result {
+        if casei {
+            self.c_class_bytes(&ByteClass::new(vec![
+                ByteRange { start: b, end: b },
+            ]).case_fold())
+        } else {
+            self.c_class_bytes(&[ByteRange { start: b, end: b }])
+        }
+    }
+
+    fn c_class_bytes(&mut self, ranges: &[ByteRange]) -> Result {
+        debug_assert!(!ranges.is_empty());
+
+        let first_split_entry = self.insts.len();
+        let mut holes = vec![];
+        let mut prev_hole = Hole::None;
+        for r in &ranges[0..ranges.len() - 1] {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let next = self.insts.len();
+            self.byte_classes.set_range(r.start, r.end);
+            holes.push(self.push_hole(InstHole::Bytes {
+                start: r.start, end: r.end,
+            }));
+            prev_hole = self.fill_split(split, Some(next), None);
+        }
+        let next = self.insts.len();
+        let r = &ranges[ranges.len() - 1];
+        self.byte_classes.set_range(r.start, r.end);
+        holes.push(self.push_hole(InstHole::Bytes {
+            start: r.start, end: r.end,
+        }));
+        self.fill(prev_hole, next);
+        Ok(Patch { hole: Hole::Many(holes), entry: first_split_entry })
+    }
+
+    fn c_empty_look(&mut self, look: EmptyLook) -> Result {
+        let hole = self.push_hole(InstHole::EmptyLook { look: look });
+        Ok(Patch { hole: hole, entry: self.insts.len() - 1 })
+    }
+
+    fn c_concat<'a, I>(&mut self, exprs: I) -> Result
+            where I: IntoIterator<Item=&'a Expr> {
+        let mut exprs = exprs.into_iter();
+        let first = match exprs.next() {
+            Some(expr) => expr,
+            None => {
+                return Ok(Patch { hole: Hole::None, entry: self.insts.len() })
+            }
+        };
+        let Patch { mut hole, entry } = try!(self.c(first));
+        for e in exprs {
+            let p = try!(self.c(e));
+            self.fill(hole, p.entry);
+            hole = p.hole;
+        }
+        Ok(Patch { hole: hole, entry: entry })
+    }
+
+    fn c_alternate(&mut self, exprs: &[Expr]) -> Result {
+        debug_assert!(
+            exprs.len() >= 2, "alternates must have at least 2 exprs");
+
+        // Initial entry point is always the first split.
+        let first_split_entry = self.insts.len();
+
+        // Save up all of the holes from each alternate. They will all get
+        // patched to point to the same location.
+        let mut holes = vec![];
+
+        let mut prev_hole = Hole::None;
+        for e in &exprs[0..exprs.len() - 1] {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let Patch { hole, entry } = try!(self.c(e));
+            holes.push(hole);
+            prev_hole = self.fill_split(split, Some(entry), None);
+        }
+        let Patch { hole, entry } = try!(self.c(&exprs[exprs.len() - 1]));
+        holes.push(hole);
+        self.fill(prev_hole, entry);
+        Ok(Patch { hole: Hole::Many(holes), entry: first_split_entry })
+    }
+
+    fn c_repeat(
+        &mut self,
+        expr: &Expr,
+        kind: Repeater,
+        greedy: bool,
+    ) -> Result {
+        match kind {
+            Repeater::ZeroOrOne => self.c_repeat_zero_or_one(expr, greedy),
+            Repeater::ZeroOrMore => self.c_repeat_zero_or_more(expr, greedy),
+            Repeater::OneOrMore => self.c_repeat_one_or_more(expr, greedy),
+            Repeater::Range { min, max: None } => {
+                self.c_repeat_range_min_or_more(expr, greedy, min)
+            }
+            Repeater::Range { min, max: Some(max) } => {
+                self.c_repeat_range(expr, greedy, min, max)
+            }
+        }
+    }
+
+    fn c_repeat_zero_or_one(
+        &mut self,
+        expr: &Expr,
+        greedy: bool,
+    ) -> Result {
+        let split_entry = self.insts.len();
+        let split = self.push_split_hole();
+        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        let holes = vec![hole_rep, split_hole];
+        Ok(Patch { hole: Hole::Many(holes), entry: split_entry })
+    }
+
+    fn c_repeat_zero_or_more(
+        &mut self,
+        expr: &Expr,
+        greedy: bool,
+    ) -> Result {
+        let split_entry = self.insts.len();
+        let split = self.push_split_hole();
+        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+
+        self.fill(hole_rep, split_entry);
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        Ok(Patch { hole: split_hole, entry: split_entry })
+    }
+
+    fn c_repeat_one_or_more(
+        &mut self,
+        expr: &Expr,
+        greedy: bool,
+    ) -> Result {
+        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+        self.fill_to_next(hole_rep);
+        let split = self.push_split_hole();
+
+        let split_hole = if greedy {
+            self.fill_split(split, Some(entry_rep), None)
+        } else {
+            self.fill_split(split, None, Some(entry_rep))
+        };
+        Ok(Patch { hole: split_hole, entry: entry_rep })
+    }
+
+    fn c_repeat_range_min_or_more(
+        &mut self,
+        expr: &Expr,
+        greedy: bool,
+        min: u32,
+    ) -> Result {
+        let min = u32_to_usize(min);
+        let patch_concat = try!(self.c_concat(iter::repeat(expr).take(min)));
+        let patch_rep = try!(self.c_repeat_zero_or_more(expr, greedy));
+        self.fill(patch_concat.hole, patch_rep.entry);
+        Ok(Patch { hole: patch_rep.hole, entry: patch_concat.entry })
+    }
+
+    fn c_repeat_range(
+        &mut self,
+        expr: &Expr,
+        greedy: bool,
+        min: u32,
+        max: u32,
+    ) -> Result {
+        let (min, max) = (u32_to_usize(min), u32_to_usize(max));
+        let patch_concat = try!(self.c_concat(iter::repeat(expr).take(min)));
+        let initial_entry = patch_concat.entry;
+        if min == max {
+            return Ok(patch_concat);
+        }
+        // It is much simpler to compile, e.g., `a{2,5}` as:
+        //
+        //     aaa?a?a?
+        //
+        // But you end up with a sequence of instructions like this:
+        //
+        //     0: 'a'
+        //     1: 'a',
+        //     2: split(3, 4)
+        //     3: 'a'
+        //     4: split(5, 6)
+        //     5: 'a'
+        //     6: split(7, 8)
+        //     7: 'a'
+        //     8: MATCH
+        //
+        // This is *incredibly* inefficient because the splits end
+        // up forming a chain, which has to be resolved everything a
+        // transition is followed.
+        let mut holes = vec![];
+        let mut prev_hole = patch_concat.hole;
+        for _ in min..max {
+            self.fill_to_next(prev_hole);
+            let split = self.push_split_hole();
+            let Patch { hole, entry } = try!(self.c(expr));
+            prev_hole = hole;
+            if greedy {
+                holes.push(self.fill_split(split, Some(entry), None));
+            } else {
+                holes.push(self.fill_split(split, None, Some(entry)));
+            }
+        }
+        holes.push(prev_hole);
+        Ok(Patch { hole: Hole::Many(holes), entry: initial_entry })
+    }
+
+    fn fill(&mut self, hole: Hole, goto: InstPtr) {
+        match hole {
+            Hole::None => {}
+            Hole::One(pc) => {
+                self.insts[pc].fill(goto);
+            }
+            Hole::Many(holes) => {
+                for hole in holes {
+                    self.fill(hole, goto);
+                }
+            }
+        }
+    }
+
+    fn fill_to_next(&mut self, hole: Hole) {
+        let next = self.insts.len();
+        self.fill(hole, next);
+    }
+
+    fn fill_split(
+        &mut self,
+        hole: Hole,
+        goto1: Option<InstPtr>,
+        goto2: Option<InstPtr>,
+    ) -> Hole {
+        match hole {
+            Hole::None => Hole::None,
+            Hole::One(pc) => {
+                match (goto1, goto2) {
+                    (Some(goto1), Some(goto2)) => {
+                        self.insts[pc].fill_split(goto1, goto2);
+                        Hole::None
+                    }
+                    (Some(goto1), None) => {
+                        self.insts[pc].half_fill_split_goto1(goto1);
+                        Hole::One(pc)
+                    }
+                    (None, Some(goto2)) => {
+                        self.insts[pc].half_fill_split_goto2(goto2);
+                        Hole::One(pc)
+                    }
+                    (None, None) => unreachable!("at least one of the split \
+                                                  holes must be filled"),
+                }
+            }
+            Hole::Many(holes) => {
+                let mut new_holes = vec![];
+                for hole in holes {
+                    new_holes.push(self.fill_split(hole, goto1, goto2));
+                }
+                if new_holes.is_empty() {
+                    Hole::None
+                } else if new_holes.len() == 1 {
+                    new_holes.pop().unwrap()
+                } else {
+                    Hole::Many(new_holes)
+                }
+            }
+        }
+    }
+
+    fn push_compiled(&mut self, inst: Inst) {
+        self.insts.push(MaybeInst::Compiled(inst));
+    }
+
+    fn push_hole(&mut self, inst: InstHole) -> Hole {
+        let hole = self.insts.len();
+        self.insts.push(MaybeInst::Uncompiled(inst));
+        Hole::One(hole)
+    }
+
+    fn push_split_hole(&mut self) -> Hole {
+        let hole = self.insts.len();
+        self.insts.push(MaybeInst::Split);
+        Hole::One(hole)
+    }
+
+    fn check_size(&self) -> result::Result<(), Error> {
+        use std::mem::size_of;
+
+        if self.insts.len() * size_of::<Inst>() > self.size_limit {
+            Err(Error::CompiledTooBig(self.size_limit))
+        } else {
+            Ok(())
+        }
+    }
+}
+
+#[derive(Debug)]
+enum Hole {
+    None,
+    One(InstPtr),
+    Many(Vec<Hole>),
+}
+
+#[derive(Clone, Debug)]
+enum MaybeInst {
+    Compiled(Inst),
+    Uncompiled(InstHole),
+    Split,
+    Split1(InstPtr),
+    Split2(InstPtr),
+}
+
+impl MaybeInst {
+    fn fill(&mut self, goto: InstPtr) {
+        let filled = match *self {
+            MaybeInst::Uncompiled(ref inst) => inst.fill(goto),
+            MaybeInst::Split1(goto1) => {
+                Inst::Split(InstSplit { goto1: goto1, goto2: goto })
+            }
+            MaybeInst::Split2(goto2) => {
+                Inst::Split(InstSplit { goto1: goto, goto2: goto2 })
+            }
+            _ => unreachable!("not all instructions were compiled! \
+                               found uncompiled instruction: {:?}", self),
+        };
+        *self = MaybeInst::Compiled(filled);
+    }
+
+    fn fill_split(&mut self, goto1: InstPtr, goto2: InstPtr) {
+        let filled = match *self {
+            MaybeInst::Split => {
+                Inst::Split(InstSplit { goto1: goto1, goto2: goto2 })
+            }
+            _ => unreachable!("must be called on Split instruction, \
+                               instead it was called on: {:?}", self),
+        };
+        *self = MaybeInst::Compiled(filled);
+    }
+
+    fn half_fill_split_goto1(&mut self, goto1: InstPtr) {
+        let half_filled = match *self {
+            MaybeInst::Split => goto1,
+            _ => unreachable!("must be called on Split instruction, \
+                               instead it was called on: {:?}", self),
+        };
+        *self = MaybeInst::Split1(half_filled);
+    }
+
+    fn half_fill_split_goto2(&mut self, goto2: InstPtr) {
+        let half_filled = match *self {
+            MaybeInst::Split => goto2,
+            _ => unreachable!("must be called on Split instruction, \
+                               instead it was called on: {:?}", self),
+        };
+        *self = MaybeInst::Split2(half_filled);
+    }
+
+    fn unwrap(self) -> Inst {
+        match self {
+            MaybeInst::Compiled(inst) => inst,
+            _ => unreachable!("must be called on a compiled instruction, \
+                               instead it was called on: {:?}", self),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+enum InstHole {
+    Save { slot: usize },
+    EmptyLook { look: EmptyLook },
+    Char { c: char },
+    Ranges { ranges: Vec<(char, char)> },
+    Bytes { start: u8, end: u8 },
+}
+
+impl InstHole {
+    fn fill(&self, goto: InstPtr) -> Inst {
+        match *self {
+            InstHole::Save { slot } => Inst::Save(InstSave {
+                goto: goto,
+                slot: slot,
+            }),
+            InstHole::EmptyLook { look } => Inst::EmptyLook(InstEmptyLook {
+                goto: goto,
+                look: look,
+            }),
+            InstHole::Char { c } => Inst::Char(InstChar {
+                goto: goto,
+                c: c,
+            }),
+            InstHole::Ranges { ref ranges } => Inst::Ranges(InstRanges {
+                goto: goto,
+                ranges: ranges.clone(),
+            }),
+            InstHole::Bytes { start, end } => Inst::Bytes(InstBytes {
+                goto: goto,
+                start: start,
+                end: end,
+            }),
+        }
+    }
+}
+
+struct CompileClass<'a, 'b> {
+    c: &'a mut Compiler,
+    ranges: &'b [ClassRange],
+}
+
+impl<'a, 'b> CompileClass<'a, 'b> {
+    fn compile(mut self) -> Result {
+        let mut holes = vec![];
+        let mut initial_entry = None;
+        let mut last_split = Hole::None;
+        let mut utf8_seqs = self.c.utf8_seqs.take().unwrap();
+        self.c.suffix_cache.clear();
+
+        for (i, ref range) in self.ranges.iter().enumerate() {
+            let is_last_range = i + 1 == self.ranges.len();
+            utf8_seqs.reset(range.start, range.end);
+            let mut it = (&mut utf8_seqs).peekable();
+            loop {
+                let utf8_seq = match it.next() {
+                    None => break,
+                    Some(utf8_seq) => utf8_seq,
+                };
+                if is_last_range && it.peek().is_none() {
+                    let Patch { hole, entry } = try!(self.c_utf8_seq(&utf8_seq));
+                    holes.push(hole);
+                    self.c.fill(last_split, entry);
+                    last_split = Hole::None;
+                    if initial_entry.is_none() {
+                        initial_entry = Some(entry);
+                    }
+                } else {
+                    if initial_entry.is_none() {
+                        initial_entry = Some(self.c.insts.len());
+                    }
+                    self.c.fill_to_next(last_split);
+                    last_split = self.c.push_split_hole();
+                    let Patch { hole, entry } = try!(self.c_utf8_seq(&utf8_seq));
+                    holes.push(hole);
+                    last_split = self.c.fill_split(last_split, Some(entry), None);
+                }
+            }
+        }
+        self.c.utf8_seqs = Some(utf8_seqs);
+        Ok(Patch {
+            hole: Hole::Many(holes),
+            entry: initial_entry.unwrap(),
+        })
+    }
+
+    fn c_utf8_seq(&mut self, seq: &Utf8Sequence) -> Result {
+        if self.c.compiled.is_reverse {
+            self.c_utf8_seq_(seq)
+        } else {
+            self.c_utf8_seq_(seq.into_iter().rev())
+        }
+    }
+
+    fn c_utf8_seq_<'r, I>(&mut self, seq: I) -> Result
+            where I: IntoIterator<Item=&'r Utf8Range> {
+        // The initial instruction for each UTF-8 sequence should be the same.
+        let mut from_inst = ::std::usize::MAX;
+        let mut last_hole = Hole::None;
+        for byte_range in seq {
+            let key = SuffixCacheKey {
+                from_inst: from_inst,
+                start: byte_range.start,
+                end: byte_range.end,
+            };
+            {
+                let pc = self.c.insts.len();
+                if let Some(cached_pc) = self.c.suffix_cache.get(key, pc) {
+                    from_inst = cached_pc;
+                    continue;
+                }
+            }
+            self.c.byte_classes.set_range(byte_range.start, byte_range.end);
+            if from_inst == ::std::usize::MAX {
+                last_hole = self.c.push_hole(InstHole::Bytes {
+                    start: byte_range.start,
+                    end: byte_range.end,
+                });
+            } else {
+                self.c.push_compiled(Inst::Bytes(InstBytes {
+                    goto: from_inst,
+                    start: byte_range.start,
+                    end: byte_range.end,
+                }));
+            }
+            from_inst = self.c.insts.len().checked_sub(1).unwrap();
+            debug_assert!(from_inst < ::std::usize::MAX);
+        }
+        debug_assert!(from_inst < ::std::usize::MAX);
+        Ok(Patch { hole: last_hole, entry: from_inst })
+    }
+}
+
+/// SuffixCache is a simple bounded hash map for caching suffix entries in
+/// UTF-8 automata. For example, consider the Unicode range \u{0}-\u{FFFF}.
+/// The set of byte ranges looks like this:
+///
+/// [0-7F]
+/// [C2-DF][80-BF]
+/// [E0][A0-BF][80-BF]
+/// [E1-EC][80-BF][80-BF]
+/// [ED][80-9F][80-BF]
+/// [EE-EF][80-BF][80-BF]
+///
+/// Each line above translates to one alternate in the compiled regex program.
+/// However, all but one of the alternates end in the same suffix, which is
+/// a waste of an instruction. The suffix cache facilitates reusing them across
+/// alternates.
+///
+/// Note that a HashMap could be trivially used for this, but we don't need its
+/// overhead. Some small bounded space (LRU style) is more than enough.
+struct SuffixCache {
+    table: Vec<SuffixCacheEntry>,
+    // Every time the cache is cleared, we increment the version number instead
+    // of actually zeroing memory. Since we store a copy of the current version
+    // in every element, all we need to do is make sure to invalidate any stale
+    // entries upon access. This saves quite a bit of time!
+    version: usize,
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
+struct SuffixCacheEntry {
+    key: SuffixCacheKey,
+    pc: InstPtr,
+    version: usize,
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
+struct SuffixCacheKey {
+    from_inst: InstPtr,
+    start: u8,
+    end: u8,
+}
+
+impl SuffixCache {
+    fn new(size: usize) -> Self {
+        SuffixCache {
+            table: vec![SuffixCacheEntry::default(); size],
+            version: 0,
+        }
+    }
+
+    fn get(&mut self, key: SuffixCacheKey, pc: InstPtr) -> Option<InstPtr> {
+        let h = self.hash(&key);
+        let e = self.table[h];
+        if e.key == key && e.version == self.version {
+            Some(e.pc)
+        } else {
+            self.table[h] = SuffixCacheEntry {
+                key: key,
+                pc: pc,
+                version: self.version,
+            };
+            None
+        }
+    }
+
+    fn clear(&mut self) {
+        self.version += 1;
+    }
+
+    fn hash(&self, suffix: &SuffixCacheKey) -> usize {
+        // Basic FNV-1a hash as described:
+        // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
+        const FNV_PRIME: u64 = 1099511628211;
+        let mut h = 14695981039346656037;
+        h = (h ^ (suffix.from_inst as u64)).wrapping_mul(FNV_PRIME);
+        h = (h ^ (suffix.start as u64)).wrapping_mul(FNV_PRIME);
+        h = (h ^ (suffix.end as u64)).wrapping_mul(FNV_PRIME);
+        (h as usize) % self.table.len()
+    }
+}
+
+struct ByteClassSet([bool; 256]);
+
+impl ByteClassSet {
+    fn new() -> Self {
+        ByteClassSet([false; 256])
+    }
+
+    fn set_range(&mut self, start: u8, end: u8) {
+        debug_assert!(start <= end);
+        if start > 0 {
+            self.0[start as usize - 1] = true;
+        }
+        self.0[end as usize] = true;
+    }
+
+    fn set_word_boundary(&mut self) {
+        // We need to mark all ranges of bytes whose pairs result in
+        // evaluating \b differently.
+        let iswb = is_word_byte;
+        let mut b1: u16 = 0;
+        let mut b2: u16;
+        while b1 <= 255 {
+            b2 = b1 + 1;
+            while b2 <= 255 && iswb(b1 as u8) == iswb(b2 as u8) {
+                b2 += 1;
+            }
+            self.set_range(b1 as u8, (b2 - 1) as u8);
+            b1 = b2;
+        }
+    }
+
+    fn byte_classes(&self) -> Vec<u8> {
+        // N.B. If you're debugging the DFA, it's useful to simply return
+        // `(0..256).collect()`, which effectively removes the byte classes
+        // and makes the transitions easier to read.
+        // (0usize..256).map(|x| x as u8).collect()
+        let mut byte_classes = vec![0; 256];
+        let mut class = 0u8;
+        let mut i = 0;
+        loop {
+            byte_classes[i] = class as u8;
+            if i >= 255 {
+                break;
+            }
+            if self.0[i] {
+                class = class.checked_add(1).unwrap();
+            }
+            i += 1;
+        }
+        byte_classes
+    }
+}
+
+fn u32_to_usize(n: u32) -> usize {
+    if (n as u64) > (::std::usize::MAX as u64) {
+        panic!("BUG: {} is too big to be pointer sized", n)
+    }
+    n as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use super::ByteClassSet;
+
+    #[test]
+    fn byte_classes() {
+        let mut set = ByteClassSet::new();
+        set.set_range(b'a', b'z');
+        let classes = set.byte_classes();
+        assert_eq!(classes[0], 0);
+        assert_eq!(classes[1], 0);
+        assert_eq!(classes[2], 0);
+        assert_eq!(classes[b'a' as usize - 1], 0);
+        assert_eq!(classes[b'a' as usize], 1);
+        assert_eq!(classes[b'm' as usize], 1);
+        assert_eq!(classes[b'z' as usize], 1);
+        assert_eq!(classes[b'z' as usize + 1], 2);
+        assert_eq!(classes[254], 2);
+        assert_eq!(classes[255], 2);
+
+        let mut set = ByteClassSet::new();
+        set.set_range(0, 2);
+        set.set_range(4, 6);
+        let classes = set.byte_classes();
+        assert_eq!(classes[0], 0);
+        assert_eq!(classes[1], 0);
+        assert_eq!(classes[2], 0);
+        assert_eq!(classes[3], 1);
+        assert_eq!(classes[4], 2);
+        assert_eq!(classes[5], 2);
+        assert_eq!(classes[6], 2);
+        assert_eq!(classes[7], 3);
+        assert_eq!(classes[255], 3);
+    }
+
+    #[test]
+    fn full_byte_classes() {
+        let mut set = ByteClassSet::new();
+        for i in 0..256u16 {
+            set.set_range(i as u8, i as u8);
+        }
+        assert_eq!(set.byte_classes().len(), 256);
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/dfa.rs b/third_party/rust/regex-0.2.2/src/dfa.rs
new file mode 100644
index 000000000000..d3c007c35037
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/dfa.rs
@@ -0,0 +1,1879 @@
+// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+The DFA matching engine.
+
+A DFA provides faster matching because the engine is in exactly one state at
+any point in time. In the NFA, there may be multiple active states, and
+considerable CPU cycles are spent shuffling them around. In finite automata
+speak, the DFA follows epsilon transitions in the regex far less than the NFA.
+
+A DFA is a classic trade off between time and space. The NFA is slower, but
+its memory requirements are typically small and predictable. The DFA is faster,
+but given the right regex and the right input, the number of states in the
+DFA can grow exponentially. To mitigate this space problem, we do two things:
+
+1. We implement an *online* DFA. That is, the DFA is constructed from the NFA
+   during a search. When a new state is computed, it is stored in a cache so
+   that it may be reused. An important consequence of this implementation
+   is that states that are never reached for a particular input are never
+   computed. (This is impossible in an "offline" DFA which needs to compute
+   all possible states up front.)
+2. If the cache gets too big, we wipe it and continue matching.
+
+In pathological cases, a new state can be created for every byte of input.
+(e.g., The regex `(a|b)*a(a|b){20}` on a long sequence of a's and b's.)
+In this case, performance regresses to slightly slower than the full NFA
+simulation, in large part because the cache becomes useless. If the cache
+is wiped too frequently, the DFA quits and control falls back to one of the
+NFA simulations.
+
+Because of the "lazy" nature of this DFA, the inner matching loop is
+considerably more complex than one might expect out of a DFA. A number of
+tricks are employed to make it fast. Tread carefully.
+
+N.B. While this implementation is heavily commented, Russ Cox's series of
+articles on regexes is strongly recommended: https://swtch.com/~rsc/regexp/
+(As is the DFA implementation in RE2, which heavily influenced this
+implementation.)
+*/
+
+use std::collections::HashMap;
+use std::fmt;
+use std::iter::repeat;
+use std::mem;
+
+use exec::ProgramCache;
+use prog::{Inst, Program};
+use sparse::SparseSet;
+
+/// Return true if and only if the given program can be executed by a DFA.
+///
+/// Generally, a DFA is always possible. A pathological case where it is not
+/// possible is if the number of NFA states exceeds u32::MAX, in which case,
+/// this function will return false.
+///
+/// This function will also return false if the given program has any Unicode
+/// instructions (Char or Ranges) since the DFA operates on bytes only.
+pub fn can_exec(insts: &Program) -> bool {
+    use prog::Inst::*;
+    // If for some reason we manage to allocate a regex program with more
+    // than i32::MAX instructions, then we can't execute the DFA because we
+    // use 32 bit instruction pointer deltas for memory savings.
+    // If i32::MAX is the largest positive delta,
+    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
+    // and we are OK to use 32 bits.
+    if insts.len() > ::std::i32::MAX as usize {
+        return false;
+    }
+    for inst in insts {
+        match *inst {
+            Char(_) | Ranges(_) => return false,
+            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
+        }
+    }
+    true
+}
+
+/// A reusable cache of DFA states.
+///
+/// This cache is reused between multiple invocations of the same regex
+/// program. (It is not shared simultaneously between threads. If there is
+/// contention, then new caches are created.)
+#[derive(Clone, Debug)]
+pub struct Cache {
+    /// Group persistent DFA related cache state together. The sparse sets
+    /// listed below are used as scratch space while computing uncached states.
+    inner: CacheInner,
+    /// qcur and qnext are ordered sets with constant time
+    /// addition/membership/clearing-whole-set and linear time iteration. They
+    /// are used to manage the sets of NFA states in DFA states when computing
+    /// cached DFA states. In particular, the order of the NFA states matters
+    /// for leftmost-first style matching. Namely, when computing a cached
+    /// state, the set of NFA states stops growing as soon as the first Match
+    /// instruction is observed.
+    qcur: SparseSet,
+    qnext: SparseSet,
+}
+
+/// CacheInner is logically just a part of Cache, but groups together fields
+/// that aren't passed as function parameters throughout search. (This split
+/// is mostly an artifact of the borrow checker. It is happily paid.)
+#[derive(Clone, Debug)]
+struct CacheInner {
+    /// A cache of pre-compiled DFA states, keyed by the set of NFA states
+    /// and the set of empty-width flags set at the byte in the input when the
+    /// state was observed.
+    ///
+    /// A StatePtr is effectively a `*State`, but to avoid various inconvenient
+    /// things, we just pass indexes around manually. The performance impact of
+    /// this is probably an instruction or two in the inner loop. However, on
+    /// 64 bit, each StatePtr is half the size of a *State.
+    compiled: HashMap<State, StatePtr>,
+    /// The transition table.
+    ///
+    /// The transition table is laid out in row-major order, where states are
+    /// rows and the transitions for each state are columns. At a high level,
+    /// given state `s` and byte `b`, the next state can be found at index
+    /// `s * 256 + b`.
+    ///
+    /// This is, of course, a lie. A StatePtr is actually a pointer to the
+    /// *start* of a row in this table. When indexing in the DFA's inner loop,
+    /// this removes the need to multiply the StatePtr by the stride. Yes, it
+    /// matters. This reduces the number of states we can store, but: the
+    /// stride is rarely 256 since we define transitions in terms of
+    /// *equivalence classes* of bytes. Each class corresponds to a set of
+    /// bytes that never discriminate a distinct path through the DFA from each
+    /// other.
+    trans: Transitions,
+    /// Our set of states. Note that `StatePtr / num_byte_classes` indexes
+    /// this Vec rather than just a `StatePtr`.
+    states: Vec<State>,
+    /// A set of cached start states, which are limited to the number of
+    /// permutations of flags set just before the initial byte of input. (The
+    /// index into this vec is a `EmptyFlags`.)
+    ///
+    /// N.B. A start state can be "dead" (i.e., no possible match), so we
+    /// represent it with a StatePtr.
+    start_states: Vec<StatePtr>,
+    /// Stack scratch space used to follow epsilon transitions in the NFA.
+    /// (This permits us to avoid recursion.)
+    ///
+    /// The maximum stack size is the number of NFA states.
+    stack: Vec<InstPtr>,
+    /// The total number of times this cache has been flushed by the DFA
+    /// because of space constraints.
+    flush_count: u64,
+    /// The total heap size of the DFA's cache. We use this to determine when
+    /// we should flush the cache.
+    size: usize,
+}
+
+/// The transition table.
+///
+/// It is laid out in row-major order, with states as rows and byte class
+/// transitions as columns.
+///
+/// The transition table is responsible for producing valid StatePtrs. A
+/// StatePtr points to the start of a particular row in this table. When
+/// indexing to find the next state this allows us to avoid a multiplication
+/// when computing an index into the table.
+#[derive(Clone)]
+struct Transitions {
+    /// The table.
+    table: Vec<StatePtr>,
+    /// The stride.
+    num_byte_classes: usize,
+}
+
+/// Fsm encapsulates the actual execution of the DFA.
+#[derive(Debug)]
+pub struct Fsm<'a> {
+    /// prog contains the NFA instruction opcodes. DFA execution uses either
+    /// the `dfa` instructions or the `dfa_reverse` instructions from
+    /// `exec::ExecReadOnly`. (It never uses `ExecReadOnly.nfa`, which may have
+    /// Unicode opcodes that cannot be executed by the DFA.)
+    prog: &'a Program,
+    /// The start state. We record it here because the pointer may change
+    /// when the cache is wiped.
+    start: StatePtr,
+    /// The current position in the input.
+    at: usize,
+    /// Should we quit after seeing the first match? e.g., When the caller
+    /// uses `is_match` or `shortest_match`.
+    quit_after_match: bool,
+    /// The last state that matched.
+    ///
+    /// When no match has occurred, this is set to STATE_UNKNOWN.
+    ///
+    /// This is only useful when matching regex sets. The last match state
+    /// is useful because it contains all of the match instructions seen,
+    /// thereby allowing us to enumerate which regexes in the set matched.
+    last_match_si: StatePtr,
+    /// The input position of the last cache flush. We use this to determine
+    /// if we're thrashing in the cache too often. If so, the DFA quits so
+    /// that we can fall back to the NFA algorithm.
+    last_cache_flush: usize,
+    /// All cached DFA information that is persisted between searches.
+    cache: &'a mut CacheInner,
+}
+
+/// The result of running the DFA.
+///
+/// Generally, the result is either a match or not a match, but sometimes the
+/// DFA runs too slowly because the cache size is too small. In that case, it
+/// gives up with the intent of falling back to the NFA algorithm.
+///
+/// The DFA can also give up if it runs out of room to create new states, or if
+/// it sees non-ASCII bytes in the presence of a Unicode word boundary.
+#[derive(Clone, Debug)]
+pub enum Result<T> {
+    Match(T),
+    NoMatch(usize),
+    Quit,
+}
+
+impl<T> Result<T> {
+    /// Returns true if this result corresponds to a match.
+    pub fn is_match(&self) -> bool {
+        match *self {
+            Result::Match(_) => true,
+            Result::NoMatch(_) | Result::Quit => false,
+        }
+    }
+
+    /// Maps the given function onto T and returns the result.
+    ///
+    /// If this isn't a match, then this is a no-op.
+    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Result<U> {
+        match self {
+            Result::Match(t) => Result::Match(f(t)),
+            Result::NoMatch(x) => Result::NoMatch(x),
+            Result::Quit => Result::Quit,
+        }
+    }
+
+    /// Sets the non-match position.
+    ///
+    /// If this isn't a non-match, then this is a no-op.
+    fn set_non_match(self, at: usize) -> Result<T> {
+        match self {
+            Result::NoMatch(_) => Result::NoMatch(at),
+            r => r,
+        }
+    }
+}
+
+/// State is a DFA state. It contains an ordered set of NFA states (not
+/// necessarily complete) and a smattering of flags.
+///
+/// The flags are packed into the first byte of data.
+///
+/// States don't carry their transitions. Instead, transitions are stored in
+/// a single row-major table.
+///
+/// Delta encoding is used to store the instruction pointers.
+/// The first instruction pointer is stored directly starting
+/// at data[1], and each following pointer is stored as an offset
+/// to the previous one. If a delta is in the range -127..127,
+/// it is packed into a single byte; Otherwise the byte 128 (-128 as an i8)
+/// is coded as a flag, followed by 4 bytes encoding the delta.
+#[derive(Clone, Eq, Hash, PartialEq)]
+struct State{
+    data: Box<[u8]>,
+}
+
+/// InstPtr is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
+/// an NFA state).
+///
+/// Throughout this library, this is usually set to `usize`, but we force a
+/// `u32` here for the DFA to save on space.
+type InstPtr = u32;
+
+/// Adds ip to data using delta encoding with respect to prev.
+///
+/// After completion, `data` will contain `ip` and `prev` will be set to `ip`.
+fn push_inst_ptr(data: &mut Vec<u8>, prev: &mut InstPtr, ip: InstPtr) {
+    let delta = (ip as i32) - (*prev as i32);
+    write_vari32(data, delta);
+    *prev = ip;
+}
+
+struct InstPtrs<'a> {
+    base: usize,
+    data: &'a [u8],
+}
+
+impl <'a>Iterator for InstPtrs<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        if self.data.is_empty() {
+            return None;
+        }
+        let (delta, nread) = read_vari32(self.data);
+        let base = self.base as i32 + delta;
+        debug_assert!(base >= 0);
+        debug_assert!(nread > 0);
+        self.data = &self.data[nread..];
+        self.base = base as usize;
+        Some(self.base)
+    }
+}
+
+impl State {
+    fn flags(&self) -> StateFlags {
+        StateFlags(self.data[0])
+    }
+
+    fn inst_ptrs(&self) -> InstPtrs {
+        InstPtrs {
+            base: 0,
+            data: &self.data[1..],
+        }
+    }
+}
+
+/// StatePtr is a 32 bit pointer to the start of a row in the transition table.
+///
+/// It has many special values. There are two types of special values:
+/// sentinels and flags.
+///
+/// Sentinels corresponds to special states that carry some kind of
+/// significance. There are three such states: unknown, dead and quit states.
+///
+/// Unknown states are states that haven't been computed yet. They indicate
+/// that a transition should be filled in that points to either an existing
+/// cached state or a new state altogether. In general, an unknown state means
+/// "follow the NFA's epsilon transitions."
+///
+/// Dead states are states that can never lead to a match, no matter what
+/// subsequent input is observed. This means that the DFA should quit
+/// immediately and return the longest match it has found thus far.
+///
+/// Quit states are states that imply the DFA is not capable of matching the
+/// regex correctly. Currently, this is only used when a Unicode word boundary
+/// exists in the regex *and* a non-ASCII byte is observed.
+///
+/// The other type of state pointer is a state pointer with special flag bits.
+/// There are two flags: a start flag and a match flag. The lower bits of both
+/// kinds always contain a "valid" StatePtr (indicated by the STATE_MAX mask).
+///
+/// The start flag means that the state is a start state, and therefore may be
+/// subject to special prefix scanning optimizations.
+///
+/// The match flag means that the state is a match state, and therefore the
+/// current position in the input (while searching) should be recorded.
+///
+/// The above exists mostly in the service of making the inner loop fast.
+/// In particular, the inner *inner* loop looks something like this:
+///
+/// ```ignore
+/// while state <= STATE_MAX and i < len(text):
+///     state = state.next[i]
+/// ```
+///
+/// This is nice because it lets us execute a lazy DFA as if it were an
+/// entirely offline DFA (i.e., with very few instructions). The loop will
+/// quit only when we need to examine a case that needs special attention.
+type StatePtr = u32;
+
+/// An unknown state means that the state has not been computed yet, and that
+/// the only way to progress is to compute it.
+const STATE_UNKNOWN: StatePtr = 1<<31;
+
+/// A dead state means that the state has been computed and it is known that
+/// once it is entered, no future match can ever occur.
+const STATE_DEAD: StatePtr = STATE_UNKNOWN + 1;
+
+/// A quit state means that the DFA came across some input that it doesn't
+/// know how to process correctly. The DFA should quit and another matching
+/// engine should be run in its place.
+const STATE_QUIT: StatePtr = STATE_DEAD + 1;
+
+/// A start state is a state that the DFA can start in.
+///
+/// Note that start states have their lower bits set to a state pointer.
+const STATE_START: StatePtr = 1<<30;
+
+/// A match state means that the regex has successfully matched.
+///
+/// Note that match states have their lower bits set to a state pointer.
+const STATE_MATCH: StatePtr = 1<<29;
+
+/// The maximum state pointer. This is useful to mask out the "valid" state
+/// pointer from a state with the "start" or "match" bits set.
+///
+/// It doesn't make sense to use this with unknown, dead or quit state
+/// pointers, since those pointers are sentinels and never have their lower
+/// bits set to anything meaningful.
+const STATE_MAX: StatePtr = STATE_MATCH - 1;
+
+/// Byte is a u8 in spirit, but a u16 in practice so that we can represent the
+/// special EOF sentinel value.
+#[derive(Copy, Clone, Debug)]
+struct Byte(u16);
+
+/// A set of flags for zero-width assertions.
+#[derive(Clone, Copy, Eq, Debug, Default, Hash, PartialEq)]
+struct EmptyFlags {
+    start: bool,
+    end: bool,
+    start_line: bool,
+    end_line: bool,
+    word_boundary: bool,
+    not_word_boundary: bool,
+}
+
+/// A set of flags describing various configurations of a DFA state. This is
+/// represented by a `u8` so that it is compact.
+#[derive(Clone, Copy, Eq, Default, Hash, PartialEq)]
+struct StateFlags(u8);
+
+impl Cache {
+    /// Create new empty cache for the DFA engine.
+    pub fn new(prog: &Program) -> Self {
+        // We add 1 to account for the special EOF byte.
+        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
+        let starts = vec![STATE_UNKNOWN; 256];
+        let mut cache = Cache {
+            inner: CacheInner {
+                compiled: HashMap::new(),
+                trans: Transitions::new(num_byte_classes),
+                states: vec![],
+                start_states: starts,
+                stack: vec![],
+                flush_count: 0,
+                size: 0,
+            },
+            qcur: SparseSet::new(prog.insts.len()),
+            qnext: SparseSet::new(prog.insts.len()),
+        };
+        cache.inner.reset_size();
+        cache
+    }
+}
+
+impl CacheInner {
+    /// Resets the cache size to account for fixed costs, such as the program
+    /// and stack sizes.
+    fn reset_size(&mut self) {
+        self.size =
+            (self.start_states.len() * mem::size_of::<StatePtr>())
+            + (self.stack.len() * mem::size_of::<InstPtr>());
+    }
+}
+
+impl<'a> Fsm<'a> {
+    #[inline(always)] // reduces constant overhead
+    pub fn forward(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        quit_after_match: bool,
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        let mut cache = cache.borrow_mut();
+        let mut cache = &mut cache.dfa;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: quit_after_match,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags(text, at);
+        dfa.start = match dfa.start_state(
+            &mut cache.qcur,
+            empty_flags,
+            state_flags,
+        ) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return Result::NoMatch(at),
+            Some(si) => si,
+        };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    pub fn reverse(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        quit_after_match: bool,
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        let mut cache = cache.borrow_mut();
+        let mut cache = &mut cache.dfa_reverse;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: quit_after_match,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags_reverse(text, at);
+        dfa.start = match dfa.start_state(
+            &mut cache.qcur,
+            empty_flags,
+            state_flags,
+        ) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return Result::NoMatch(at),
+            Some(si) => si,
+        };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        dfa.exec_at_reverse(&mut cache.qcur, &mut cache.qnext, text)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    pub fn forward_many(
+        prog: &'a Program,
+        cache: &ProgramCache,
+        matches: &mut [bool],
+        text: &[u8],
+        at: usize,
+    ) -> Result<usize> {
+        debug_assert!(matches.len() == prog.matches.len());
+        let mut cache = cache.borrow_mut();
+        let mut cache = &mut cache.dfa;
+        let mut dfa = Fsm {
+            prog: prog,
+            start: 0, // filled in below
+            at: at,
+            quit_after_match: false,
+            last_match_si: STATE_UNKNOWN,
+            last_cache_flush: at,
+            cache: &mut cache.inner,
+        };
+        let (empty_flags, state_flags) = dfa.start_flags(text, at);
+        dfa.start = match dfa.start_state(
+            &mut cache.qcur,
+            empty_flags,
+            state_flags,
+        ) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return Result::NoMatch(at),
+            Some(si) => si,
+        };
+        debug_assert!(dfa.start != STATE_UNKNOWN);
+        let result = dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text);
+        if result.is_match() {
+            if matches.len() == 1 {
+                matches[0] = true;
+            } else {
+                debug_assert!(dfa.last_match_si != STATE_UNKNOWN);
+                debug_assert!(dfa.last_match_si != STATE_DEAD);
+                for ip in dfa.state(dfa.last_match_si).inst_ptrs() {
+                    if let Inst::Match(slot) = dfa.prog[ip] {
+                        matches[slot] = true;
+                    }
+                }
+            }
+        }
+        result
+    }
+
+    /// Executes the DFA on a forward NFA.
+    ///
+    /// {qcur,qnext} are scratch ordered sets which may be non-empty.
+    #[inline(always)] // reduces constant overhead
+    fn exec_at(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        text: &[u8],
+    ) -> Result<usize> {
+        // For the most part, the DFA is basically:
+        //
+        //   last_match = null
+        //   while current_byte != EOF:
+        //     si = current_state.next[current_byte]
+        //     if si is match
+        //       last_match = si
+        //   return last_match
+        //
+        // However, we need to deal with a few things:
+        //
+        //   1. This is an *online* DFA, so the current state's next list
+        //      may not point to anywhere yet, so we must go out and compute
+        //      them. (They are then cached into the current state's next list
+        //      to avoid re-computation.)
+        //   2. If we come across a state that is known to be dead (i.e., never
+        //      leads to a match), then we can quit early.
+        //   3. If the caller just wants to know if a match occurs, then we
+        //      can quit as soon as we know we have a match. (Full leftmost
+        //      first semantics require continuing on.)
+        //   4. If we're in the start state, then we can use a pre-computed set
+        //      of prefix literals to skip quickly along the input.
+        //   5. After the input is exhausted, we run the DFA on one symbol
+        //      that stands for EOF. This is useful for handling empty width
+        //      assertions.
+        //   6. We can't actually do state.next[byte]. Instead, we have to do
+        //      state.next[byte_classes[byte]], which permits us to keep the
+        //      'next' list very small.
+        //
+        // Since there's a bunch of extra stuff we need to consider, we do some
+        // pretty hairy tricks to get the inner loop to run as fast as
+        // possible.
+        debug_assert!(!self.prog.is_reverse);
+
+        // The last match is the currently known ending match position. It is
+        // reported as an index to the most recent byte that resulted in a
+        // transition to a match state and is always stored in capture slot `1`
+        // when searching forwards. Its maximum value is `text.len()`.
+        let mut result = Result::NoMatch(self.at);
+        let (mut prev_si, mut next_si) = (self.start, self.start);
+        let mut at = self.at;
+        while at < text.len() {
+            // This is the real inner loop. We take advantage of special bits
+            // set in the state pointer to determine whether a state is in the
+            // "common" case or not. Specifically, the common case is a
+            // non-match non-start non-dead state that has already been
+            // computed. So long as we remain in the common case, this inner
+            // loop will chew through the input.
+            //
+            // We also unroll the loop 4 times to amortize the cost of checking
+            // whether we've consumed the entire input. We are also careful
+            // to make sure that `prev_si` always represents the previous state
+            // and `next_si` always represents the next state after the loop
+            // exits, even if it isn't always true inside the loop.
+            while next_si <= STATE_MAX && at < text.len() {
+                // Argument for safety is in the definition of next_si.
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                at += 1;
+                if prev_si > STATE_MAX || at + 2 >= text.len() {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                at += 1;
+                if next_si > STATE_MAX {
+                    break;
+                }
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                at += 1;
+                if prev_si > STATE_MAX {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                at += 1;
+            }
+            if next_si & STATE_MATCH > 0 {
+                // A match state is outside of the common case because it needs
+                // special case analysis. In particular, we need to record the
+                // last position as having matched and possibly quit the DFA if
+                // we don't need to keep matching.
+                next_si &= !STATE_MATCH;
+                result = Result::Match(at - 1);
+                if self.quit_after_match {
+                    return result;
+                }
+                self.last_match_si = next_si;
+                prev_si = next_si;
+
+                // This permits short-circuiting when matching a regex set.
+                // In particular, if this DFA state contains only match states,
+                // then it's impossible to extend the set of matches since
+                // match states are final. Therefore, we can quit.
+                if self.prog.matches.len() > 1 {
+                    let state = self.state(next_si);
+                    let just_matches = state.inst_ptrs()
+                         .all(|ip| self.prog[ip].is_match());
+                    if just_matches {
+                        return result;
+                    }
+                }
+
+                // Another inner loop! If the DFA stays in this particular
+                // match state, then we can rip through all of the input
+                // very quickly, and only recording the match location once
+                // we've left this particular state.
+                let cur = at;
+                while (next_si & !STATE_MATCH) == prev_si
+                    && at + 2 < text.len() {
+                    // Argument for safety is in the definition of next_si.
+                    next_si = unsafe {
+                        self.next_si(next_si & !STATE_MATCH, text, at)
+                    };
+                    at += 1;
+                }
+                if at > cur {
+                    result = Result::Match(at - 2);
+                }
+            } else if next_si & STATE_START > 0 {
+                // A start state isn't in the common case because we may
+                // what to do quick prefix scanning. If the program doesn't
+                // have a detected prefix, then start states are actually
+                // considered common and this case is never reached.
+                debug_assert!(self.has_prefix());
+                next_si &= !STATE_START;
+                prev_si = next_si;
+                at = match self.prefix_at(text, at) {
+                    None => return Result::NoMatch(text.len()),
+                    Some(i) => i,
+                };
+            } else if next_si >= STATE_UNKNOWN {
+                if next_si == STATE_QUIT {
+                    return Result::Quit;
+                }
+                // Finally, this corresponds to the case where the transition
+                // entered a state that can never lead to a match or a state
+                // that hasn't been computed yet. The latter being the "slow"
+                // path.
+                let byte = Byte::byte(text[at - 1]);
+                // We no longer care about the special bits in the state
+                // pointer.
+                prev_si &= STATE_MAX;
+                // Record where we are. This is used to track progress for
+                // determining whether we should quit if we've flushed the
+                // cache too much.
+                self.at = at;
+                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
+                    None => return Result::Quit,
+                    Some(STATE_DEAD) => return result.set_non_match(at),
+                    Some(si) => si,
+                };
+                debug_assert!(next_si != STATE_UNKNOWN);
+                if next_si & STATE_MATCH > 0 {
+                    next_si &= !STATE_MATCH;
+                    result = Result::Match(at - 1);
+                    if self.quit_after_match {
+                        return result;
+                    }
+                    self.last_match_si = next_si;
+                }
+                prev_si = next_si;
+            } else {
+                prev_si = next_si;
+            }
+        }
+
+        // Run the DFA once more on the special EOF senitnel value.
+        // We don't care about the special bits in the state pointer any more,
+        // so get rid of them.
+        prev_si &= STATE_MAX;
+        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return result.set_non_match(text.len()),
+            Some(si) => si & !STATE_START,
+        };
+        debug_assert!(prev_si != STATE_UNKNOWN);
+        if prev_si & STATE_MATCH > 0 {
+            prev_si &= !STATE_MATCH;
+            self.last_match_si = prev_si;
+            result = Result::Match(text.len());
+        }
+        result
+    }
+
+    /// Executes the DFA on a reverse NFA.
+    #[inline(always)] // reduces constant overhead
+    fn exec_at_reverse(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        text: &[u8],
+    ) -> Result<usize> {
+        // The comments in `exec_at` above mostly apply here too. The main
+        // difference is that we move backwards over the input and we look for
+        // the longest possible match instead of the leftmost-first match.
+        //
+        // N.B. The code duplication here is regrettable. Efforts to improve
+        // it without sacrificing performance are welcome. ---AG
+        debug_assert!(self.prog.is_reverse);
+        let mut result = Result::NoMatch(self.at);
+        let (mut prev_si, mut next_si) = (self.start, self.start);
+        let mut at = self.at;
+        while at > 0 {
+            while next_si <= STATE_MAX && at > 0 {
+                // Argument for safety is in the definition of next_si.
+                at -= 1;
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                if prev_si > STATE_MAX || at <= 4 {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                at -= 1;
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+                if next_si > STATE_MAX {
+                    break;
+                }
+                at -= 1;
+                prev_si = unsafe { self.next_si(next_si, text, at) };
+                if prev_si > STATE_MAX {
+                    mem::swap(&mut prev_si, &mut next_si);
+                    break;
+                }
+                at -= 1;
+                next_si = unsafe { self.next_si(prev_si, text, at) };
+            }
+            if next_si & STATE_MATCH > 0 {
+                next_si &= !STATE_MATCH;
+                result = Result::Match(at + 1);
+                if self.quit_after_match {
+                    return result
+                }
+                self.last_match_si = next_si;
+                prev_si = next_si;
+                let cur = at;
+                while (next_si & !STATE_MATCH) == prev_si && at >= 2 {
+                    // Argument for safety is in the definition of next_si.
+                    at -= 1;
+                    next_si = unsafe {
+                        self.next_si(next_si & !STATE_MATCH, text, at)
+                    };
+                }
+                if at < cur {
+                    result = Result::Match(at + 2);
+                }
+            } else if next_si >= STATE_UNKNOWN {
+                if next_si == STATE_QUIT {
+                    return Result::Quit;
+                }
+                let byte = Byte::byte(text[at]);
+                prev_si &= STATE_MAX;
+                self.at = at;
+                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
+                    None => return Result::Quit,
+                    Some(STATE_DEAD) => return result.set_non_match(at),
+                    Some(si) => si,
+                };
+                debug_assert!(next_si != STATE_UNKNOWN);
+                if next_si & STATE_MATCH > 0 {
+                    next_si &= !STATE_MATCH;
+                    result = Result::Match(at + 1);
+                    if self.quit_after_match {
+                        return result;
+                    }
+                    self.last_match_si = next_si;
+                }
+                prev_si = next_si;
+            } else {
+                prev_si = next_si;
+            }
+        }
+
+        // Run the DFA once more on the special EOF senitnel value.
+        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
+            None => return Result::Quit,
+            Some(STATE_DEAD) => return result.set_non_match(0),
+            Some(si) => si,
+        };
+        debug_assert!(prev_si != STATE_UNKNOWN);
+        if prev_si & STATE_MATCH > 0 {
+            prev_si &= !STATE_MATCH;
+            self.last_match_si = prev_si;
+            result = Result::Match(0);
+        }
+        result
+    }
+
+    /// next_si transitions to the next state, where the transition input
+    /// corresponds to text[i].
+    ///
+    /// This elides bounds checks, and is therefore unsafe.
+    #[inline(always)]
+    unsafe fn next_si(&self, si: StatePtr, text: &[u8], i: usize) -> StatePtr {
+        // What is the argument for safety here?
+        // We have three unchecked accesses that could possibly violate safety:
+        //
+        //   1. The given byte of input (`text[i]`).
+        //   2. The class of the byte of input (`classes[text[i]]`).
+        //   3. The transition for the class (`trans[si + cls]`).
+        //
+        // (1) is only safe when calling next_si is guarded by
+        // `i < text.len()`.
+        //
+        // (2) is the easiest case to guarantee since `text[i]` is always a
+        // `u8` and `self.prog.byte_classes` always has length `u8::MAX`.
+        // (See `ByteClassSet.byte_classes` in `compile.rs`.)
+        //
+        // (3) is only safe if (1)+(2) are safe. Namely, the transitions
+        // of every state are defined to have length equal to the number of
+        // byte classes in the program. Therefore, a valid class leads to a
+        // valid transition. (All possible transitions are valid lookups, even
+        // if it points to a state that hasn't been computed yet.) (3) also
+        // relies on `si` being correct, but StatePtrs should only ever be
+        // retrieved from the transition table, which ensures they are correct.
+        debug_assert!(i < text.len());
+        let b = *text.get_unchecked(i);
+        debug_assert!((b as usize) < self.prog.byte_classes.len());
+        let cls = *self.prog.byte_classes.get_unchecked(b as usize);
+        self.cache.trans.next_unchecked(si, cls as usize)
+    }
+
+    /// Computes the next state given the current state and the current input
+    /// byte (which may be EOF).
+    ///
+    /// If STATE_DEAD is returned, then there is no valid state transition.
+    /// This implies that no permutation of future input can lead to a match
+    /// state.
+    ///
+    /// STATE_UNKNOWN can never be returned.
+    fn exec_byte(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        mut si: StatePtr,
+        b: Byte,
+    ) -> Option<StatePtr> {
+        use prog::Inst::*;
+
+        // Initialize a queue with the current DFA state's NFA states.
+        qcur.clear();
+        for ip in self.state(si).inst_ptrs() {
+            qcur.insert(ip);
+        }
+
+        // Before inspecting the current byte, we may need to also inspect
+        // whether the position immediately preceding the current byte
+        // satisfies the empty assertions found in the current state.
+        //
+        // We only need to do this step if there are any empty assertions in
+        // the current state.
+        let is_word_last = self.state(si).flags().is_word();
+        let is_word = b.is_ascii_word();
+        if self.state(si).flags().has_empty() {
+            // Compute the flags immediately preceding the current byte.
+            // This means we only care about the "end" or "end line" flags.
+            // (The "start" flags are computed immediately proceding the
+            // current byte and is handled below.)
+            let mut flags = EmptyFlags::default();
+            if b.is_eof() {
+                flags.end = true;
+                flags.end_line = true;
+            } else if b.as_byte().map_or(false, |b| b == b'\n') {
+                flags.end_line = true;
+            }
+            if is_word_last == is_word {
+                flags.not_word_boundary = true;
+            } else {
+                flags.word_boundary = true;
+            }
+            // Now follow epsilon transitions from every NFA state, but make
+            // sure we only follow transitions that satisfy our flags.
+            qnext.clear();
+            for &ip in &*qcur {
+                self.follow_epsilons(usize_to_u32(ip), qnext, flags);
+            }
+            mem::swap(qcur, qnext);
+        }
+
+        // Now we set flags for immediately after the current byte. Since start
+        // states are processed separately, and are the only states that can
+        // have the StartText flag set, we therefore only need to worry about
+        // the StartLine flag here.
+        //
+        // We do also keep track of whether this DFA state contains a NFA state
+        // that is a matching state. This is precisely how we delay the DFA
+        // matching by one byte in order to process the special EOF sentinel
+        // byte. Namely, if this DFA state containing a matching NFA state,
+        // then it is the *next* DFA state that is marked as a match.
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start_line = b.as_byte().map_or(false, |b| b == b'\n');
+        if b.is_ascii_word() {
+            state_flags.set_word();
+        }
+        // Now follow all epsilon transitions again, but only after consuming
+        // the current byte.
+        qnext.clear();
+        for &ip in &*qcur {
+            match self.prog[ip as usize] {
+                // These states never happen in a byte-based program.
+                Char(_) | Ranges(_) => unreachable!(),
+                // These states are handled when following epsilon transitions.
+                Save(_) | Split(_) | EmptyLook(_) => {}
+                Match(_) => {
+                    state_flags.set_match();
+                    if !self.continue_past_first_match() {
+                        break;
+                    } else if self.prog.matches.len() > 1
+                            && !qnext.contains(ip as usize) {
+                        // If we are continuing on to find other matches,
+                        // then keep a record of the match states we've seen.
+                        qnext.insert(ip);
+                    }
+                }
+                Bytes(ref inst) => {
+                    if b.as_byte().map_or(false, |b| inst.matches(b)) {
+                        self.follow_epsilons(
+                            inst.goto as InstPtr, qnext, empty_flags);
+                    }
+                }
+            }
+        }
+        let mut cache = true;
+        if b.is_eof() && self.prog.matches.len() > 1 {
+            // If we're processing the last byte of the input and we're
+            // matching a regex set, then make the next state contain the
+            // previous states transitions. We do this so that the main
+            // matching loop can extract all of the match instructions.
+            mem::swap(qcur, qnext);
+            // And don't cache this state because it's totally bunk.
+            cache = false;
+        }
+        // We've now built up the set of NFA states that ought to comprise the
+        // next DFA state, so try to find it in the cache, and if it doesn't
+        // exist, cache it.
+        //
+        // N.B. We pass `&mut si` here because the cache may clear itself if
+        // it has gotten too full. When that happens, the location of the
+        // current state may change.
+        let mut next = match self.cached_state(
+            qnext,
+            state_flags,
+            Some(&mut si),
+        ) {
+            None => return None,
+            Some(next) => next,
+        };
+        if (self.start & !STATE_START) == next {
+            // Start states can never be match states since all matches are
+            // delayed by one byte.
+            debug_assert!(!self.state(next).flags().is_match());
+            next = self.start_ptr(next);
+        }
+        if next <= STATE_MAX && self.state(next).flags().is_match() {
+            next = STATE_MATCH | next;
+        }
+        debug_assert!(next != STATE_UNKNOWN);
+        // And now store our state in the current state's next list.
+        if cache {
+            let cls = self.byte_class(b);
+            self.cache.trans.set_next(si, cls, next);
+        }
+        Some(next)
+    }
+
+    /// Follows the epsilon transitions starting at (and including) `ip`. The
+    /// resulting states are inserted into the ordered set `q`.
+    ///
+    /// Conditional epsilon transitions (i.e., empty width assertions) are only
+    /// followed if they are satisfied by the given flags, which should
+    /// represent the flags set at the current location in the input.
+    ///
+    /// If the current location corresponds to the empty string, then only the
+    /// end line and/or end text flags may be set. If the current location
+    /// corresponds to a real byte in the input, then only the start line
+    /// and/or start text flags may be set.
+    ///
+    /// As an exception to the above, when finding the initial state, any of
+    /// the above flags may be set:
+    ///
+    /// If matching starts at the beginning of the input, then start text and
+    /// start line should be set. If the input is empty, then end text and end
+    /// line should also be set.
+    ///
+    /// If matching starts after the beginning of the input, then only start
+    /// line should be set if the preceding byte is `\n`. End line should never
+    /// be set in this case. (Even if the proceding byte is a `\n`, it will
+    /// be handled in a subsequent DFA state.)
+    fn follow_epsilons(
+        &mut self,
+        ip: InstPtr,
+        q: &mut SparseSet,
+        flags: EmptyFlags,
+    ) {
+        use prog::Inst::*;
+        use prog::EmptyLook::*;
+
+        // We need to traverse the NFA to follow epsilon transitions, so avoid
+        // recursion with an explicit stack.
+        self.cache.stack.push(ip);
+        while let Some(ip) = self.cache.stack.pop() {
+            // Don't visit states we've already added.
+            if q.contains(ip as usize) {
+                continue;
+            }
+            q.insert(ip as usize);
+            match self.prog[ip as usize] {
+                Char(_) | Ranges(_) => unreachable!(),
+                Match(_) | Bytes(_) => {}
+                EmptyLook(ref inst) => {
+                    // Only follow empty assertion states if our flags satisfy
+                    // the assertion.
+                    match inst.look {
+                        StartLine if flags.start_line => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        EndLine if flags.end_line => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        StartText if flags.start => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        EndText if flags.end => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        WordBoundaryAscii if flags.word_boundary => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        NotWordBoundaryAscii if flags.not_word_boundary => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        WordBoundary if flags.word_boundary => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        NotWordBoundary if flags.not_word_boundary => {
+                            self.cache.stack.push(inst.goto as InstPtr);
+                        }
+                        StartLine | EndLine | StartText | EndText => {}
+                        WordBoundaryAscii | NotWordBoundaryAscii => {}
+                        WordBoundary | NotWordBoundary => {}
+                    }
+                }
+                Save(ref inst) => self.cache.stack.push(inst.goto as InstPtr),
+                Split(ref inst) => {
+                    self.cache.stack.push(inst.goto2 as InstPtr);
+                    self.cache.stack.push(inst.goto1 as InstPtr);
+                }
+            }
+        }
+    }
+
+    /// Find a previously computed state matching the given set of instructions
+    /// and is_match bool.
+    ///
+    /// The given set of instructions should represent a single state in the
+    /// NFA along with all states reachable without consuming any input.
+    ///
+    /// The is_match bool should be true if and only if the preceding DFA state
+    /// contains an NFA matching state. The cached state produced here will
+    /// then signify a match. (This enables us to delay a match by one byte,
+    /// in order to account for the EOF sentinel byte.)
+    ///
+    /// If the cache is full, then it is wiped before caching a new state.
+    ///
+    /// The current state should be specified if it exists, since it will need
+    /// to be preserved if the cache clears itself. (Start states are
+    /// always saved, so they should not be passed here.) It takes a mutable
+    /// pointer to the index because if the cache is cleared, the state's
+    /// location may change.
+    fn cached_state(
+        &mut self,
+        q: &SparseSet,
+        mut state_flags: StateFlags,
+        current_state: Option<&mut StatePtr>,
+    ) -> Option<StatePtr> {
+        // If we couldn't come up with a non-empty key to represent this state,
+        // then it is dead and can never lead to a match.
+        //
+        // Note that inst_flags represent the set of empty width assertions
+        // in q. We use this as an optimization in exec_byte to determine when
+        // we should follow epsilon transitions at the empty string preceding
+        // the current byte.
+        let key = match self.cached_state_key(q, &mut state_flags) {
+            None => return Some(STATE_DEAD),
+            Some(v) => v,
+        };
+        // In the cache? Cool. Done.
+        if let Some(&si) = self.cache.compiled.get(&key) {
+            return Some(si);
+        }
+        // If the cache has gotten too big, wipe it.
+        if self.approximate_size() > self.prog.dfa_size_limit {
+            if !self.clear_cache_and_save(current_state) {
+                // Ooops. DFA is giving up.
+                return None;
+            }
+        }
+        // Allocate room for our state and add it.
+        self.add_state(key)
+    }
+
+    /// Produces a key suitable for describing a state in the DFA cache.
+    ///
+    /// The key invariant here is that equivalent keys are produced for any two
+    /// sets of ordered NFA states (and toggling of whether the previous NFA
+    /// states contain a match state) that do not discriminate a match for any
+    /// input.
+    ///
+    /// Specifically, q should be an ordered set of NFA states and is_match
+    /// should be true if and only if the previous NFA states contained a match
+    /// state.
+    fn cached_state_key(
+        &mut self,
+        q: &SparseSet,
+        state_flags: &mut StateFlags,
+    ) -> Option<State> {
+        use prog::Inst::*;
+
+        // We need to build up enough information to recognize pre-built states
+        // in the DFA. Generally speaking, this includes every instruction
+        // except for those which are purely epsilon transitions, e.g., the
+        // Save and Split instructions.
+        //
+        // Empty width assertions are also epsilon transitions, but since they
+        // are conditional, we need to make them part of a state's key in the
+        // cache.
+
+        // Reserve 1 byte for flags.
+        let mut insts = vec![0];
+        let mut prev = 0;
+        for &ip in q {
+            let ip = usize_to_u32(ip);
+            match self.prog[ip as usize] {
+                Char(_) | Ranges(_) => unreachable!(),
+                Save(_) => {}
+                Split(_) => {}
+                Bytes(_) => push_inst_ptr(&mut insts, &mut prev, ip),
+                EmptyLook(_) => {
+                    state_flags.set_empty();
+                    push_inst_ptr(&mut insts, &mut prev, ip)
+                }
+                Match(_) => {
+                    push_inst_ptr(&mut insts, &mut prev, ip);
+                    if !self.continue_past_first_match() {
+                        break;
+                    }
+                }
+            }
+        }
+        // If we couldn't transition to any other instructions and we didn't
+        // see a match when expanding NFA states previously, then this is a
+        // dead state and no amount of additional input can transition out
+        // of this state.
+        if insts.len() == 1 && !state_flags.is_match() {
+            None
+        } else {
+            let StateFlags(f) = *state_flags;
+            insts[0] = f;
+            Some(State { data: insts.into_boxed_slice() })
+        }
+    }
+
+    /// Clears the cache, but saves and restores current_state if it is not
+    /// none.
+    ///
+    /// The current state must be provided here in case its location in the
+    /// cache changes.
+    ///
+    /// This returns false if the cache is not cleared and the DFA should
+    /// give up.
+    fn clear_cache_and_save(
+        &mut self,
+        current_state: Option<&mut StatePtr>,
+    ) -> bool {
+        if self.cache.states.is_empty() {
+            // Nothing to clear...
+            return true;
+        }
+        match current_state {
+            None => self.clear_cache(),
+            Some(si) => {
+                let cur = self.state(*si).clone();
+                if !self.clear_cache() {
+                    return false;
+                }
+                // The unwrap is OK because we just cleared the cache and
+                // therefore know that the next state pointer won't exceed
+                // STATE_MAX.
+                *si = self.restore_state(cur).unwrap();
+                true
+            }
+        }
+    }
+
+    /// Wipes the state cache, but saves and restores the current start state.
+    ///
+    /// This returns false if the cache is not cleared and the DFA should
+    /// give up.
+    fn clear_cache(&mut self) -> bool {
+        // Bail out of the DFA if we're moving too "slowly."
+        // A heuristic from RE2: assume the DFA is too slow if it is processing
+        // 10 or fewer bytes per state.
+        // Additionally, we permit the cache to be flushed a few times before
+        // caling it quits.
+        let nstates = self.cache.states.len();
+        if self.cache.flush_count >= 3
+            && self.at >= self.last_cache_flush
+            && (self.at - self.last_cache_flush) <= 10 * nstates {
+            return false;
+        }
+        // Update statistics tracking cache flushes.
+        self.last_cache_flush = self.at;
+        self.cache.flush_count += 1;
+
+        // OK, actually flush the cache.
+        let start = self.state(self.start & !STATE_START).clone();
+        let last_match = if self.last_match_si <= STATE_MAX {
+            Some(self.state(self.last_match_si).clone())
+        } else {
+            None
+        };
+        self.cache.reset_size();
+        self.cache.trans.clear();
+        self.cache.states.clear();
+        self.cache.compiled.clear();
+        for s in self.cache.start_states.iter_mut() {
+            *s = STATE_UNKNOWN;
+        }
+        // The unwraps are OK because we just cleared the cache and therefore
+        // know that the next state pointer won't exceed STATE_MAX.
+        let start_ptr = self.restore_state(start).unwrap();
+        self.start = self.start_ptr(start_ptr);
+        if let Some(last_match) = last_match {
+            self.last_match_si = self.restore_state(last_match).unwrap();
+        }
+        true
+    }
+
+    /// Restores the given state back into the cache, and returns a pointer
+    /// to it.
+    fn restore_state(&mut self, state: State) -> Option<StatePtr> {
+        // If we've already stored this state, just return a pointer to it.
+        // None will be the wiser.
+        if let Some(&si) = self.cache.compiled.get(&state) {
+            return Some(si);
+        }
+        self.add_state(state)
+    }
+
+    /// Returns the next state given the current state si and current byte
+    /// b. {qcur,qnext} are used as scratch space for storing ordered NFA
+    /// states.
+    ///
+    /// This tries to fetch the next state from the cache, but if that fails,
+    /// it computes the next state, caches it and returns a pointer to it.
+    ///
+    /// The pointer can be to a real state, or it can be STATE_DEAD.
+    /// STATE_UNKNOWN cannot be returned.
+    ///
+    /// None is returned if a new state could not be allocated (i.e., the DFA
+    /// ran out of space and thinks it's running too slowly).
+    fn next_state(
+        &mut self,
+        qcur: &mut SparseSet,
+        qnext: &mut SparseSet,
+        si: StatePtr,
+        b: Byte,
+    ) -> Option<StatePtr> {
+        if si == STATE_DEAD {
+            return Some(STATE_DEAD);
+        }
+        match self.cache.trans.next(si, self.byte_class(b)) {
+            STATE_UNKNOWN => self.exec_byte(qcur, qnext, si, b),
+            STATE_QUIT => None,
+            STATE_DEAD => Some(STATE_DEAD),
+            nsi => Some(nsi),
+        }
+    }
+
+    /// Computes and returns the start state, where searching begins at
+    /// position `at` in `text`. If the state has already been computed,
+    /// then it is pulled from the cache. If the state hasn't been cached,
+    /// then it is computed, cached and a pointer to it is returned.
+    ///
+    /// This may return STATE_DEAD but never STATE_UNKNOWN.
+    #[inline(always)] // reduces constant overhead
+    fn start_state(
+        &mut self,
+        q: &mut SparseSet,
+        empty_flags: EmptyFlags,
+        state_flags: StateFlags,
+    ) -> Option<StatePtr> {
+        // Compute an index into our cache of start states based on the set
+        // of empty/state flags set at the current position in the input. We
+        // don't use every flag since not all flags matter. For example, since
+        // matches are delayed by one byte, start states can never be match
+        // states.
+        let flagi = {
+            (((empty_flags.start as u8) << 0) |
+             ((empty_flags.end as u8) << 1) |
+             ((empty_flags.start_line as u8) << 2) |
+             ((empty_flags.end_line as u8) << 3) |
+             ((empty_flags.word_boundary as u8) << 4) |
+             ((empty_flags.not_word_boundary as u8) << 5) |
+             ((state_flags.is_word() as u8) << 6))
+            as usize
+        };
+        match self.cache.start_states[flagi] {
+            STATE_UNKNOWN => {}
+            STATE_DEAD => return Some(STATE_DEAD),
+            si => return Some(si),
+        }
+        q.clear();
+        let start = usize_to_u32(self.prog.start);
+        self.follow_epsilons(start, q, empty_flags);
+        // Start states can never be match states because we delay every match
+        // by one byte. Given an empty string and an empty match, the match
+        // won't actually occur until the DFA processes the special EOF
+        // sentinel byte.
+        let sp = match self.cached_state(q, state_flags, None) {
+            None => return None,
+            Some(sp) => self.start_ptr(sp),
+        };
+        self.cache.start_states[flagi] = sp;
+        Some(sp)
+    }
+
+    /// Computes the set of starting flags for the given position in text.
+    ///
+    /// This should only be used when executing the DFA forwards over the
+    /// input.
+    fn start_flags(&self, text: &[u8], at: usize) -> (EmptyFlags, StateFlags) {
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start = at == 0;
+        empty_flags.end = text.len() == 0;
+        empty_flags.start_line = at == 0 || text[at - 1] == b'\n';
+        empty_flags.end_line = text.len() == 0;
+
+        let is_word_last = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
+        let is_word = at < text.len() && Byte::byte(text[at]).is_ascii_word();
+        if is_word_last {
+            state_flags.set_word();
+        }
+        if is_word == is_word_last {
+            empty_flags.not_word_boundary = true;
+        } else {
+            empty_flags.word_boundary = true;
+        }
+        (empty_flags, state_flags)
+    }
+
+    /// Computes the set of starting flags for the given position in text.
+    ///
+    /// This should only be used when executing the DFA in reverse over the
+    /// input.
+    fn start_flags_reverse(
+        &self,
+        text: &[u8],
+        at: usize,
+    ) -> (EmptyFlags, StateFlags) {
+        let mut empty_flags = EmptyFlags::default();
+        let mut state_flags = StateFlags::default();
+        empty_flags.start = at == text.len();
+        empty_flags.end = text.len() == 0;
+        empty_flags.start_line = at == text.len() || text[at] == b'\n';
+        empty_flags.end_line = text.len() == 0;
+
+        let is_word_last =
+            at < text.len() && Byte::byte(text[at]).is_ascii_word();
+        let is_word = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
+        if is_word_last {
+            state_flags.set_word();
+        }
+        if is_word == is_word_last {
+            empty_flags.not_word_boundary = true;
+        } else {
+            empty_flags.word_boundary = true;
+        }
+        (empty_flags, state_flags)
+    }
+
+    /// Returns a reference to a State given a pointer to it.
+    fn state(&self, si: StatePtr) -> &State {
+        &self.cache.states[si as usize / self.num_byte_classes()]
+    }
+
+    /// Adds the given state to the DFA.
+    ///
+    /// This allocates room for transitions out of this state in
+    /// self.cache.trans. The transitions can be set with the returned
+    /// StatePtr.
+    ///
+    /// If None is returned, then the state limit was reached and the DFA
+    /// should quit.
+    fn add_state(&mut self, state: State) -> Option<StatePtr> {
+        // This will fail if the next state pointer exceeds STATE_PTR. In
+        // practice, the cache limit will prevent us from ever getting here,
+        // but maybe callers will set the cache size to something ridiculous...
+        let si = match self.cache.trans.add() {
+            None => return None,
+            Some(si) => si,
+        };
+        // If the program has a Unicode word boundary, then set any transitions
+        // for non-ASCII bytes to STATE_QUIT. If the DFA stumbles over such a
+        // transition, then it will quit and an alternative matching engine
+        // will take over.
+        if self.prog.has_unicode_word_boundary {
+            for b in 128..256 {
+                let cls = self.byte_class(Byte::byte(b as u8));
+                self.cache.trans.set_next(si, cls, STATE_QUIT);
+            }
+        }
+        // Finally, put our actual state on to our heap of states and index it
+        // so we can find it later.
+        self.cache.size +=
+            self.cache.trans.state_heap_size()
+            + (2 * state.data.len())
+            + (2 * mem::size_of::<State>())
+            + mem::size_of::<StatePtr>();
+        self.cache.states.push(state.clone());
+        self.cache.compiled.insert(state, si);
+        // Transition table and set of states and map should all be in sync.
+        debug_assert!(self.cache.states.len()
+                      == self.cache.trans.num_states());
+        debug_assert!(self.cache.states.len()
+                      == self.cache.compiled.len());
+        Some(si)
+    }
+
+    /// Quickly finds the next occurrence of any literal prefixes in the regex.
+    /// If there are no literal prefixes, then the current position is
+    /// returned. If there are literal prefixes and one could not be found,
+    /// then None is returned.
+    ///
+    /// This should only be called when the DFA is in a start state.
+    fn prefix_at(&self, text: &[u8], at: usize) -> Option<usize> {
+        self.prog.prefixes.find(&text[at..]).map(|(s, _)| at + s)
+    }
+
+    /// Returns the number of byte classes required to discriminate transitions
+    /// in each state.
+    ///
+    /// invariant: num_byte_classes() == len(State.next)
+    fn num_byte_classes(&self) -> usize {
+        // We add 1 to account for the special EOF byte.
+        (self.prog.byte_classes[255] as usize + 1) + 1
+    }
+
+    /// Given an input byte or the special EOF sentinel, return its
+    /// corresponding byte class.
+    #[inline(always)]
+    fn byte_class(&self, b: Byte) -> usize {
+        match b.as_byte() {
+            None => self.num_byte_classes() - 1,
+            Some(b) => self.u8_class(b),
+        }
+    }
+
+    /// Like byte_class, but explicitly for u8s.
+    #[inline(always)]
+    fn u8_class(&self, b: u8) -> usize {
+        self.prog.byte_classes[b as usize] as usize
+    }
+
+    /// Returns true if the DFA should continue searching past the first match.
+    ///
+    /// Leftmost first semantics in the DFA are preserved by not following NFA
+    /// transitions after the first match is seen.
+    ///
+    /// On occasion, we want to avoid leftmost first semantics to find either
+    /// the longest match (for reverse search) or all possible matches (for
+    /// regex sets).
+    fn continue_past_first_match(&self) -> bool {
+        self.prog.is_reverse || self.prog.matches.len() > 1
+    }
+
+    /// Returns true if there is a prefix we can quickly search for.
+    fn has_prefix(&self) -> bool {
+        !self.prog.is_reverse
+        && !self.prog.prefixes.is_empty()
+        && !self.prog.is_anchored_start
+    }
+
+    /// Sets the STATE_START bit in the given state pointer if and only if
+    /// we have a prefix to scan for.
+    ///
+    /// If there's no prefix, then it's a waste to treat the start state
+    /// specially.
+    fn start_ptr(&self, si: StatePtr) -> StatePtr {
+        if self.has_prefix() {
+            si | STATE_START
+        } else {
+            si
+        }
+    }
+
+    /// Approximate size returns the approximate heap space currently used by
+    /// the DFA. It is used to determine whether the DFA's state cache needs to
+    /// be wiped. Namely, it is possible that for certain regexes on certain
+    /// inputs, a new state could be created for every byte of input. (This is
+    /// bad for memory use, so we bound it with a cache.)
+    fn approximate_size(&self) -> usize {
+        self.cache.size + self.prog.approximate_size()
+    }
+}
+
+impl Transitions {
+    /// Create a new transition table.
+    ///
+    /// The number of byte classes corresponds to the stride. Every state will
+    /// have `num_byte_classes` slots for transitions.
+    fn new(num_byte_classes: usize) -> Transitions {
+        Transitions {
+            table: vec![],
+            num_byte_classes: num_byte_classes,
+        }
+    }
+
+    /// Returns the total number of states currently in this table.
+    fn num_states(&self) -> usize {
+        self.table.len() / self.num_byte_classes
+    }
+
+    /// Allocates room for one additional state and returns a pointer to it.
+    ///
+    /// If there's no more room, None is returned.
+    fn add(&mut self) -> Option<StatePtr> {
+        let si = self.table.len();
+        if si > STATE_MAX as usize {
+            return None;
+        }
+        self.table.extend(repeat(STATE_UNKNOWN).take(self.num_byte_classes));
+        Some(usize_to_u32(si))
+    }
+
+    /// Clears the table of all states.
+    fn clear(&mut self) {
+        self.table.clear();
+    }
+
+    /// Sets the transition from (si, cls) to next.
+    fn set_next(&mut self, si: StatePtr, cls: usize, next: StatePtr) {
+        self.table[si as usize + cls] = next;
+    }
+
+    /// Returns the transition corresponding to (si, cls).
+    fn next(&self, si: StatePtr, cls: usize) -> StatePtr {
+        self.table[si as usize + cls]
+    }
+
+    /// The heap size, in bytes, of a single state in the transition table.
+    fn state_heap_size(&self) -> usize {
+        self.num_byte_classes * mem::size_of::<StatePtr>()
+    }
+
+    /// Like `next`, but uses unchecked access and is therefore unsafe.
+    unsafe fn next_unchecked(&self, si: StatePtr, cls: usize) -> StatePtr {
+        debug_assert!((si as usize) < self.table.len());
+        debug_assert!(cls < self.num_byte_classes);
+        *self.table.get_unchecked(si as usize + cls)
+    }
+}
+
+impl StateFlags {
+    fn is_match(&self) -> bool {
+        self.0 & 0b0000000_1 > 0
+    }
+
+    fn set_match(&mut self) {
+        self.0 |= 0b0000000_1;
+    }
+
+    fn is_word(&self) -> bool {
+        self.0 & 0b000000_1_0 > 0
+    }
+
+    fn set_word(&mut self) {
+        self.0 |= 0b000000_1_0;
+    }
+
+    fn has_empty(&self) -> bool {
+        self.0 & 0b00000_1_00 > 0
+    }
+
+    fn set_empty(&mut self) {
+        self.0 |= 0b00000_1_00;
+    }
+}
+
+impl Byte {
+    fn byte(b: u8) -> Self { Byte(b as u16) }
+    fn eof() -> Self { Byte(256) }
+    fn is_eof(&self) -> bool { self.0 == 256 }
+
+    fn is_ascii_word(&self) -> bool {
+        let b = match self.as_byte() {
+            None => return false,
+            Some(b) => b,
+        };
+        match b {
+            b'A'...b'Z' | b'a'...b'z' | b'0'...b'9' | b'_' => true,
+            _ => false,
+        }
+    }
+
+    fn as_byte(&self) -> Option<u8> {
+        if self.is_eof() {
+            None
+        } else {
+            Some(self.0 as u8)
+        }
+    }
+}
+
+impl fmt::Debug for State {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let ips: Vec<usize> = self.inst_ptrs().collect();
+        f.debug_struct("State")
+         .field("flags", &self.flags())
+         .field("insts", &ips)
+         .finish()
+    }
+}
+
+impl fmt::Debug for Transitions {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut fmtd = f.debug_map();
+        for si in 0..self.num_states() {
+            let s = si * self.num_byte_classes;
+            let e = s + self.num_byte_classes;
+            fmtd.entry(&si.to_string(), &TransitionsRow(&self.table[s..e]));
+        }
+        fmtd.finish()
+    }
+}
+
+struct TransitionsRow<'a>(&'a [StatePtr]);
+
+impl<'a> fmt::Debug for TransitionsRow<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut fmtd = f.debug_map();
+        for (b, si) in self.0.iter().enumerate() {
+            match *si {
+                STATE_UNKNOWN => {}
+                STATE_DEAD => {
+                    fmtd.entry(&vb(b as usize), &"DEAD");
+                }
+                si => {
+                    fmtd.entry(&vb(b as usize), &si.to_string());
+                }
+            }
+        }
+        fmtd.finish()
+    }
+}
+
+impl fmt::Debug for StateFlags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("StateFlags")
+         .field("is_match", &self.is_match())
+         .field("is_word", &self.is_word())
+         .field("has_empty", &self.has_empty())
+         .finish()
+    }
+}
+
+/// Helper function for formatting a byte as a nice-to-read escaped string.
+fn vb(b: usize) -> String {
+    use std::ascii::escape_default;
+
+    if b > ::std::u8::MAX as usize {
+        "EOF".to_owned()
+    } else {
+        let escaped = escape_default(b as u8).collect::<Vec<u8>>();
+        String::from_utf8_lossy(&escaped).into_owned()
+    }
+}
+
+fn usize_to_u32(n: usize) -> u32 {
+    if (n as u64) > (::std::u32::MAX as u64) {
+        panic!("BUG: {} is too big to fit into u32", n)
+    }
+    n as u32
+}
+
+#[allow(dead_code)] // useful for debugging
+fn show_state_ptr(si: StatePtr) -> String {
+    let mut s = format!("{:?}", si & STATE_MAX);
+    if si == STATE_UNKNOWN {
+        s = format!("{} (unknown)", s);
+    }
+    if si == STATE_DEAD {
+        s = format!("{} (dead)", s);
+    }
+    if si == STATE_QUIT {
+        s = format!("{} (quit)", s);
+    }
+    if si & STATE_START > 0 {
+        s = format!("{} (start)", s);
+    }
+    if si & STATE_MATCH > 0 {
+        s = format!("{} (match)", s);
+    }
+    s
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn write_vari32(data: &mut Vec<u8>, n: i32) {
+    let mut un = (n as u32) << 1;
+    if n < 0 {
+        un = !un;
+    }
+    write_varu32(data, un)
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn read_vari32(data: &[u8]) -> (i32, usize) {
+    let (un, i) = read_varu32(data);
+    let mut n = (un >> 1) as i32;
+    if un & 1 != 0 {
+        n = !n;
+    }
+    (n, i)
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn write_varu32(data: &mut Vec<u8>, mut n: u32) {
+    while n >= 0b1000_0000 {
+        data.push((n as u8) | 0b1000_0000);
+        n >>= 7;
+    }
+    data.push(n as u8);
+}
+
+/// https://developers.google.com/protocol-buffers/docs/encoding#varints
+fn read_varu32(data: &[u8]) -> (u32, usize) {
+    let mut n: u32 = 0;
+    let mut shift: u32 = 0;
+    for (i, &b) in data.iter().enumerate() {
+        if b < 0b1000_0000 {
+            return (n | ((b as u32) << shift), i + 1);
+        }
+        n |= ((b as u32) & 0b0111_1111) << shift;
+        shift += 7;
+    }
+    (0, 0)
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate rand;
+
+    use quickcheck::{QuickCheck, StdGen, quickcheck};
+    use super::{
+        StateFlags, State, push_inst_ptr,
+        write_varu32, read_varu32, write_vari32, read_vari32,
+    };
+
+    #[test]
+    fn prop_state_encode_decode() {
+        fn p(ips: Vec<u32>, flags: u8) -> bool {
+            let mut data = vec![flags];
+            let mut prev = 0;
+            for &ip in ips.iter() {
+                push_inst_ptr(&mut data, &mut prev, ip);
+            }
+            let state = State { data: data.into_boxed_slice() };
+
+            let expected: Vec<usize> =
+                ips.into_iter().map(|ip| ip as usize).collect();
+            let got: Vec<usize> = state.inst_ptrs().collect();
+            expected == got && state.flags() == StateFlags(flags)
+        }
+        QuickCheck::new()
+            .gen(StdGen::new(self::rand::thread_rng(), 10_000))
+            .quickcheck(p as fn(Vec<u32>, u8) -> bool);
+    }
+
+    #[test]
+    fn prop_read_write_u32() {
+        fn p(n: u32) -> bool {
+            let mut buf = vec![];
+            write_varu32(&mut buf, n);
+            let (got, nread) = read_varu32(&buf);
+            nread == buf.len() && got == n
+        }
+        quickcheck(p as fn(u32) -> bool);
+    }
+
+    #[test]
+    fn prop_read_write_i32() {
+        fn p(n: i32) -> bool {
+            let mut buf = vec![];
+            write_vari32(&mut buf, n);
+            let (got, nread) = read_vari32(&buf);
+            nread == buf.len() && got == n
+        }
+        quickcheck(p as fn(i32) -> bool);
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/error.rs b/third_party/rust/regex-0.2.2/src/error.rs
new file mode 100644
index 000000000000..c95d67acddca
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/error.rs
@@ -0,0 +1,63 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+use syntax;
+
+/// An error that occurred during parsing or compiling a regular expression.
+#[derive(Debug)]
+pub enum Error {
+    /// A syntax error.
+    Syntax(String),
+    /// The compiled program exceeded the set size limit.
+    /// The argument is the size limit imposed.
+    CompiledTooBig(usize),
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl ::std::error::Error for Error {
+    fn description(&self) -> &str {
+        match *self {
+            Error::Syntax(ref err) => err,
+            Error::CompiledTooBig(_) => "compiled program too big",
+            Error::__Nonexhaustive => unreachable!(),
+        }
+    }
+
+    fn cause(&self) -> Option<&::std::error::Error> {
+        None
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Syntax(ref err) => err.fmt(f),
+            Error::CompiledTooBig(limit) => {
+                write!(f, "Compiled regex exceeds size limit of {} bytes.",
+                       limit)
+            }
+            Error::__Nonexhaustive => unreachable!(),
+        }
+    }
+}
+
+impl From<syntax::Error> for Error {
+    fn from(err: syntax::Error) -> Error {
+        Error::Syntax(err.to_string())
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/exec.rs b/third_party/rust/regex-0.2.2/src/exec.rs
new file mode 100644
index 000000000000..3192ce792876
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/exec.rs
@@ -0,0 +1,1275 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::cmp;
+use std::sync::Arc;
+
+use thread_local::CachedThreadLocal;
+use syntax::{Expr, ExprBuilder, Literals};
+
+use backtrack;
+use compile::Compiler;
+use dfa;
+use error::Error;
+use input::{ByteInput, CharInput};
+use literals::LiteralSearcher;
+use pikevm;
+use prog::Program;
+use re_builder::RegexOptions;
+use re_bytes;
+use re_set;
+use re_trait::{RegularExpression, Slot, Locations, as_slots};
+use re_unicode;
+use utf8::next_utf8;
+
+/// Exec manages the execution of a regular expression.
+///
+/// In particular, this manages the various compiled forms of a single regular
+/// expression and the choice of which matching engine to use to execute a
+/// regular expression.
+pub struct Exec {
+    /// All read only state.
+    ro: Arc<ExecReadOnly>,
+    /// Caches for the various matching engines.
+    cache: CachedThreadLocal<ProgramCache>,
+}
+
+/// ExecNoSync is like Exec, except it embeds a reference to a cache. This
+/// means it is no longer Sync, but we can now avoid the overhead of
+/// synchronization to fetch the cache.
+#[derive(Debug)]
+pub struct ExecNoSync<'c> {
+    /// All read only state.
+    ro: &'c Arc<ExecReadOnly>,
+    /// Caches for the various matching engines.
+    cache: &'c ProgramCache,
+}
+
+/// ExecNoSyncStr is like ExecNoSync, but matches on &str instead of &[u8].
+pub struct ExecNoSyncStr<'c>(ExecNoSync<'c>);
+
+/// ExecReadOnly comprises all read only state for a regex. Namely, all such
+/// state is determined at compile time and never changes during search.
+#[derive(Debug)]
+struct ExecReadOnly {
+    /// The original regular expressions given by the caller to compile.
+    res: Vec<String>,
+    /// A compiled program that is used in the NFA simulation and backtracking.
+    /// It can be byte-based or Unicode codepoint based.
+    ///
+    /// N.B. It is not possibly to make this byte-based from the public API.
+    /// It is only used for testing byte based programs in the NFA simulations.
+    nfa: Program,
+    /// A compiled byte based program for DFA execution. This is only used
+    /// if a DFA can be executed. (Currently, only word boundary assertions are
+    /// not supported.) Note that this program contains an embedded `.*?`
+    /// preceding the first capture group, unless the regex is anchored at the
+    /// beginning.
+    dfa: Program,
+    /// The same as above, except the program is reversed (and there is no
+    /// preceding `.*?`). This is used by the DFA to find the starting location
+    /// of matches.
+    dfa_reverse: Program,
+    /// A set of suffix literals extracted from the regex.
+    ///
+    /// Prefix literals are stored on the `Program`, since they are used inside
+    /// the matching engines.
+    suffixes: LiteralSearcher,
+    /// match_type encodes as much upfront knowledge about how we're going to
+    /// execute a search as possible.
+    match_type: MatchType,
+}
+
+/// Facilitates the construction of an executor by exposing various knobs
+/// to control how a regex is executed and what kinds of resources it's
+/// permitted to use.
+pub struct ExecBuilder {
+    options: RegexOptions,
+    match_type: Option<MatchType>,
+    bytes: bool,
+    only_utf8: bool,
+}
+
+/// Parsed represents a set of parsed regular expressions and their detected
+/// literals.
+struct Parsed {
+    exprs: Vec<Expr>,
+    prefixes: Literals,
+    suffixes: Literals,
+    bytes: bool,
+}
+
+impl ExecBuilder {
+    /// Create a regex execution builder.
+    ///
+    /// This uses default settings for everything except the regex itself,
+    /// which must be provided. Further knobs can be set by calling methods,
+    /// and then finally, `build` to actually create the executor.
+    pub fn new(re: &str) -> Self {
+        Self::new_many(&[re])
+    }
+
+    /// Like new, but compiles the union of the given regular expressions.
+    ///
+    /// Note that when compiling 2 or more regular expressions, capture groups
+    /// are completely unsupported. (This means both `find` and `captures`
+    /// wont work.)
+    pub fn new_many<I, S>(res: I) -> Self
+            where S: AsRef<str>, I: IntoIterator<Item=S> {
+        let mut opts = RegexOptions::default();
+        opts.pats = res.into_iter().map(|s| s.as_ref().to_owned()).collect();
+        Self::new_options(opts)
+    }
+
+    /// Create a regex execution builder.
+    pub fn new_options(opts: RegexOptions) -> Self {
+        ExecBuilder {
+            options: opts,
+            match_type: None,
+            bytes: false,
+            only_utf8: true,
+        }
+    }
+
+    /// Set the matching engine to be automatically determined.
+    ///
+    /// This is the default state and will apply whatever optimizations are
+    /// possible, such as running a DFA.
+    ///
+    /// This overrides whatever was previously set via the `nfa` or
+    /// `bounded_backtracking` methods.
+    pub fn automatic(mut self) -> Self {
+        self.match_type = None;
+        self
+    }
+
+    /// Sets the matching engine to use the NFA algorithm no matter what
+    /// optimizations are possible.
+    ///
+    /// This overrides whatever was previously set via the `automatic` or
+    /// `bounded_backtracking` methods.
+    pub fn nfa(mut self) -> Self {
+        self.match_type = Some(MatchType::Nfa(MatchNfaType::PikeVM));
+        self
+    }
+
+    /// Sets the matching engine to use a bounded backtracking engine no
+    /// matter what optimizations are possible.
+    ///
+    /// One must use this with care, since the bounded backtracking engine
+    /// uses memory proportion to `len(regex) * len(text)`.
+    ///
+    /// This overrides whatever was previously set via the `automatic` or
+    /// `nfa` methods.
+    pub fn bounded_backtracking(mut self) -> Self {
+        self.match_type = Some(MatchType::Nfa(MatchNfaType::Backtrack));
+        self
+    }
+
+    /// Compiles byte based programs for use with the NFA matching engines.
+    ///
+    /// By default, the NFA engines match on Unicode scalar values. They can
+    /// be made to use byte based programs instead. In general, the byte based
+    /// programs are slower because of a less efficient encoding of character
+    /// classes.
+    ///
+    /// Note that this does not impact DFA matching engines, which always
+    /// execute on bytes.
+    pub fn bytes(mut self, yes: bool) -> Self {
+        self.bytes = yes;
+        self
+    }
+
+    /// When disabled, the program compiled may match arbitrary bytes.
+    ///
+    /// When enabled (the default), all compiled programs exclusively match
+    /// valid UTF-8 bytes.
+    pub fn only_utf8(mut self, yes: bool) -> Self {
+        self.only_utf8 = yes;
+        self
+    }
+
+    /// Set the Unicode flag.
+    pub fn unicode(mut self, yes: bool) -> Self {
+        self.options.unicode = yes;
+        self
+    }
+
+    /// Parse the current set of patterns into their AST and extract literals.
+    fn parse(&self) -> Result<Parsed, Error> {
+        let mut exprs = Vec::with_capacity(self.options.pats.len());
+        let mut prefixes = Some(Literals::empty());
+        let mut suffixes = Some(Literals::empty());
+        let mut bytes = false;
+        let is_set = self.options.pats.len() > 1;
+        // If we're compiling a regex set and that set has any anchored
+        // expressions, then disable all literal optimizations.
+        for pat in &self.options.pats {
+            let parser =
+                ExprBuilder::new()
+                    .case_insensitive(self.options.case_insensitive)
+                    .multi_line(self.options.multi_line)
+                    .dot_matches_new_line(self.options.dot_matches_new_line)
+                    .swap_greed(self.options.swap_greed)
+                    .ignore_whitespace(self.options.ignore_whitespace)
+                    .unicode(self.options.unicode)
+                    .allow_bytes(!self.only_utf8);
+            let expr = try!(parser.parse(pat));
+            bytes = bytes || expr.has_bytes();
+
+            if !expr.is_anchored_start() && expr.has_anchored_start() {
+                // Partial anchors unfortunately make it hard to use prefixes,
+                // so disable them.
+                prefixes = None;
+            } else if is_set && expr.is_anchored_start() {
+                // Regex sets with anchors do not go well with literal
+                // optimizations.
+                prefixes = None;
+            }
+            prefixes = prefixes.and_then(|mut prefixes| {
+                if !prefixes.union_prefixes(&expr) {
+                    None
+                } else {
+                    Some(prefixes)
+                }
+            });
+
+            if !expr.is_anchored_end() && expr.has_anchored_end() {
+                // Partial anchors unfortunately make it hard to use suffixes,
+                // so disable them.
+                suffixes = None;
+            } else if is_set && expr.is_anchored_end() {
+                // Regex sets with anchors do not go well with literal
+                // optimizations.
+                prefixes = None;
+            }
+            suffixes = suffixes.and_then(|mut suffixes| {
+                if !suffixes.union_suffixes(&expr) {
+                    None
+                } else {
+                    Some(suffixes)
+                }
+            });
+            exprs.push(expr);
+        }
+        Ok(Parsed {
+            exprs: exprs,
+            prefixes: prefixes.unwrap_or(Literals::empty()),
+            suffixes: suffixes.unwrap_or(Literals::empty()),
+            bytes: bytes,
+        })
+    }
+
+    /// Build an executor that can run a regular expression.
+    pub fn build(self) -> Result<Exec, Error> {
+        // Special case when we have no patterns to compile.
+        // This can happen when compiling a regex set.
+        if self.options.pats.is_empty() {
+            let ro = Arc::new(ExecReadOnly {
+                res: vec![],
+                nfa: Program::new(),
+                dfa: Program::new(),
+                dfa_reverse: Program::new(),
+                suffixes: LiteralSearcher::empty(),
+                match_type: MatchType::Nothing,
+            });
+            return Ok(Exec { ro: ro, cache: CachedThreadLocal::new() });
+        }
+        let parsed = try!(self.parse());
+        let mut nfa = try!(
+            Compiler::new()
+                     .size_limit(self.options.size_limit)
+                     .bytes(self.bytes || parsed.bytes)
+                     .only_utf8(self.only_utf8)
+                     .compile(&parsed.exprs));
+        let mut dfa = try!(
+            Compiler::new()
+                     .size_limit(self.options.size_limit)
+                     .dfa(true)
+                     .only_utf8(self.only_utf8)
+                     .compile(&parsed.exprs));
+        let mut dfa_reverse = try!(
+            Compiler::new()
+                     .size_limit(self.options.size_limit)
+                     .dfa(true)
+                     .only_utf8(self.only_utf8)
+                     .reverse(true)
+                     .compile(&parsed.exprs));
+
+        let prefixes = parsed.prefixes.unambiguous_prefixes();
+        let suffixes = parsed.suffixes.unambiguous_suffixes();
+        nfa.prefixes = LiteralSearcher::prefixes(prefixes);
+        dfa.prefixes = nfa.prefixes.clone();
+        dfa.dfa_size_limit = self.options.dfa_size_limit;
+        dfa_reverse.dfa_size_limit = self.options.dfa_size_limit;
+
+        let mut ro = ExecReadOnly {
+            res: self.options.pats,
+            nfa: nfa,
+            dfa: dfa,
+            dfa_reverse: dfa_reverse,
+            suffixes: LiteralSearcher::suffixes(suffixes),
+            match_type: MatchType::Nothing,
+        };
+        ro.match_type = ro.choose_match_type(self.match_type);
+
+        let ro = Arc::new(ro);
+        Ok(Exec { ro: ro, cache: CachedThreadLocal::new() })
+    }
+}
+
+impl<'c> RegularExpression for ExecNoSyncStr<'c> {
+    type Text = str;
+
+    fn slots_len(&self) -> usize { self.0.slots_len() }
+
+    fn next_after_empty(&self, text: &str, i: usize) -> usize {
+        next_utf8(text.as_bytes(), i)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    fn shortest_match_at(&self, text: &str, start: usize) -> Option<usize> {
+        self.0.shortest_match_at(text.as_bytes(), start)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    fn is_match_at(&self, text: &str, start: usize) -> bool {
+        self.0.is_match_at(text.as_bytes(), start)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    fn find_at(&self, text: &str, start: usize) -> Option<(usize, usize)> {
+        self.0.find_at(text.as_bytes(), start)
+    }
+
+    #[inline(always)] // reduces constant overhead
+    fn read_captures_at(
+        &self,
+        locs: &mut Locations,
+        text: &str,
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        self.0.read_captures_at(locs, text.as_bytes(), start)
+    }
+}
+
+impl<'c> RegularExpression for ExecNoSync<'c> {
+    type Text = [u8];
+
+    /// Returns the number of capture slots in the regular expression. (There
+    /// are two slots for every capture group, corresponding to possibly empty
+    /// start and end locations of the capture.)
+    fn slots_len(&self) -> usize {
+        self.ro.nfa.captures.len() * 2
+    }
+
+    fn next_after_empty(&self, _text: &[u8], i: usize) -> usize {
+        i + 1
+    }
+
+    /// Returns the end of a match location, possibly occurring before the
+    /// end location of the correct leftmost-first match.
+    #[inline(always)] // reduces constant overhead
+    fn shortest_match_at(&self, text: &[u8], start: usize) -> Option<usize> {
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).map(|(_, e)| e)
+            }
+            MatchType::Dfa | MatchType::DfaMany => {
+                match self.shortest_dfa(text, start) {
+                    dfa::Result::Match(end) => Some(end),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            MatchType::DfaAnchoredReverse => {
+                match dfa::Fsm::reverse(
+                    &self.ro.dfa_reverse,
+                    &self.cache,
+                    true,
+                    &text[start..],
+                    text.len(),
+                ) {
+                    dfa::Result::Match(_) => Some(text.len()),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            MatchType::DfaSuffix => {
+                match self.shortest_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match(e) => Some(e),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.shortest_nfa(text, start),
+                }
+            }
+            MatchType::Nfa(ty) => self.shortest_nfa_type(ty, text, start),
+            MatchType::Nothing => None,
+        }
+    }
+
+    /// Returns true if and only if the regex matches text.
+    ///
+    /// For single regular expressions, this is equivalent to calling
+    /// shortest_match(...).is_some().
+    #[inline(always)] // reduces constant overhead
+    fn is_match_at(&self, text: &[u8], start: usize) -> bool {
+        if !self.is_anchor_end_match(text) {
+            return false;
+        }
+        // We need to do this dance because shortest_match relies on the NFA
+        // filling in captures[1], but a RegexSet has no captures. In other
+        // words, a RegexSet can't (currently) use shortest_match. ---AG
+        match self.ro.match_type {
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).is_some()
+            }
+            MatchType::Dfa | MatchType::DfaMany => {
+                match self.shortest_dfa(text, start) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            MatchType::DfaAnchoredReverse => {
+                match dfa::Fsm::reverse(
+                    &self.ro.dfa_reverse,
+                    &self.cache,
+                    true,
+                    &text[start..],
+                    text.len(),
+                ) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            MatchType::DfaSuffix => {
+                match self.shortest_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => self.match_nfa(text, start),
+                }
+            }
+            MatchType::Nfa(ty) => self.match_nfa_type(ty, text, start),
+            MatchType::Nothing => false,
+        }
+    }
+
+    /// Finds the start and end location of the leftmost-first match, starting
+    /// at the given location.
+    #[inline(always)] // reduces constant overhead
+    fn find_at(&self, text: &[u8], start: usize) -> Option<(usize, usize)> {
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start)
+            }
+            MatchType::Dfa => {
+                match self.find_dfa_forward(text, start) {
+                    dfa::Result::Match((s, e)) => Some((s, e)),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => {
+                        self.find_nfa(MatchNfaType::Auto, text, start)
+                    }
+                }
+            }
+            MatchType::DfaAnchoredReverse => {
+                match self.find_dfa_anchored_reverse(text, start) {
+                    dfa::Result::Match((s, e)) => Some((s, e)),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => {
+                        self.find_nfa(MatchNfaType::Auto, text, start)
+                    }
+                }
+            }
+            MatchType::DfaSuffix => {
+                match self.find_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match((s, e)) => Some((s, e)),
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => {
+                        self.find_nfa(MatchNfaType::Auto, text, start)
+                    }
+                }
+            }
+            MatchType::Nfa(ty) => self.find_nfa(ty, text, start),
+            MatchType::Nothing => None,
+            MatchType::DfaMany => {
+                unreachable!("BUG: RegexSet cannot be used with find")
+            }
+        }
+    }
+
+    /// Finds the start and end location of the leftmost-first match and also
+    /// fills in all matching capture groups.
+    ///
+    /// The number of capture slots given should be equal to the total number
+    /// of capture slots in the compiled program.
+    ///
+    /// Note that the first two slots always correspond to the start and end
+    /// locations of the overall match.
+    fn read_captures_at(
+        &self,
+        locs: &mut Locations,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        let slots = as_slots(locs);
+        for slot in slots.iter_mut() {
+            *slot = None;
+        }
+        // If the caller unnecessarily uses this, then we try to save them
+        // from themselves.
+        match slots.len() {
+            0 => return self.find_at(text, start),
+            2 => {
+                return self.find_at(text, start).map(|(s, e)| {
+                    slots[0] = Some(s);
+                    slots[1] = Some(e);
+                    (s, e)
+                });
+            }
+            _ => {} // fallthrough
+        }
+        if !self.is_anchor_end_match(text) {
+            return None;
+        }
+        match self.ro.match_type {
+            MatchType::Literal(ty) => {
+                self.find_literals(ty, text, start).and_then(|(s, e)| {
+                    self.captures_nfa_with_match(slots, text, s, e)
+                })
+            }
+            MatchType::Dfa => {
+                match self.find_dfa_forward(text, start) {
+                    dfa::Result::Match((s, e)) => {
+                        self.captures_nfa_with_match(slots, text, s, e)
+                    }
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
+                }
+            }
+            MatchType::DfaAnchoredReverse => {
+                match self.find_dfa_anchored_reverse(text, start) {
+                    dfa::Result::Match((s, e)) => {
+                        self.captures_nfa_with_match(slots, text, s, e)
+                    }
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
+                }
+            }
+            MatchType::DfaSuffix => {
+                match self.find_dfa_reverse_suffix(text, start) {
+                    dfa::Result::Match((s, e)) => {
+                        self.captures_nfa_with_match(slots, text, s, e)
+                    }
+                    dfa::Result::NoMatch(_) => None,
+                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
+                }
+            }
+            MatchType::Nfa(ty) => {
+                self.captures_nfa_type(ty, slots, text, start)
+            }
+            MatchType::Nothing => None,
+            MatchType::DfaMany => {
+                unreachable!("BUG: RegexSet cannot be used with captures")
+            }
+        }
+    }
+}
+
+impl<'c> ExecNoSync<'c> {
+    /// Finds the leftmost-first match using only literal search.
+    #[inline(always)] // reduces constant overhead
+    fn find_literals(
+        &self,
+        ty: MatchLiteralType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        use self::MatchLiteralType::*;
+        match ty {
+            Unanchored => {
+                let lits = &self.ro.nfa.prefixes;
+                lits.find(&text[start..])
+                    .map(|(s, e)| (start + s, start + e))
+            }
+            AnchoredStart => {
+                let lits = &self.ro.nfa.prefixes;
+                lits.find_start(&text[start..])
+                    .map(|(s, e)| (start + s, start + e))
+            }
+            AnchoredEnd => {
+                let lits = &self.ro.suffixes;
+                lits.find_end(&text[start..])
+                    .map(|(s, e)| (start + s, start + e))
+            }
+        }
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[inline(always)] // reduces constant overhead
+    fn find_dfa_forward(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+        let end = match dfa::Fsm::forward(
+            &self.ro.dfa,
+            &self.cache,
+            false,
+            text,
+            start,
+        ) {
+            NoMatch(i) => return NoMatch(i),
+            Quit => return Quit,
+            Match(end) if start == end => return Match((start, start)),
+            Match(end) => end,
+        };
+        // Now run the DFA in reverse to find the start of the match.
+        match dfa::Fsm::reverse(
+            &self.ro.dfa_reverse,
+            &self.cache,
+            false,
+            &text[start..],
+            end - start,
+        ) {
+            Match(s) => Match((start + s, end)),
+            NoMatch(i) => NoMatch(i),
+            Quit => Quit,
+        }
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA,
+    /// but assumes the regex is anchored at the end and therefore starts at
+    /// the end of the regex and matches in reverse.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[inline(always)] // reduces constant overhead
+    fn find_dfa_anchored_reverse(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+        match dfa::Fsm::reverse(
+            &self.ro.dfa_reverse,
+            &self.cache,
+            false,
+            &text[start..],
+            text.len() - start,
+        ) {
+            Match(s) => Match((start + s, text.len())),
+            NoMatch(i) => NoMatch(i),
+            Quit => Quit,
+        }
+    }
+
+    /// Finds the end of the shortest match using only the DFA.
+    #[inline(always)] // reduces constant overhead
+    fn shortest_dfa(&self, text: &[u8], start: usize) -> dfa::Result<usize> {
+        dfa::Fsm::forward(&self.ro.dfa, &self.cache, true, text, start)
+    }
+
+    /// Finds the end of the shortest match using only the DFA by scanning for
+    /// suffix literals.
+    ///
+    #[inline(always)] // reduces constant overhead
+    fn shortest_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<usize> {
+        match self.exec_dfa_reverse_suffix(text, start) {
+            None => self.shortest_dfa(text, start),
+            Some(r) => r.map(|(_, end)| end),
+        }
+    }
+
+    /// Finds the end of the shortest match using only the DFA by scanning for
+    /// suffix literals. It also reports the start of the match.
+    ///
+    /// Note that if None is returned, then the optimization gave up to avoid
+    /// worst case quadratic behavior. A forward scanning DFA should be tried
+    /// next.
+    ///
+    /// If a match is returned and the full leftmost-first match is desired,
+    /// then a forward scan starting from the beginning of the match must be
+    /// done.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[inline(always)] // reduces constant overhead
+    fn exec_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        original_start: usize,
+    ) -> Option<dfa::Result<(usize, usize)>> {
+        use dfa::Result::*;
+
+        let lcs = self.ro.suffixes.lcs();
+        debug_assert!(lcs.len() >= 1);
+        let mut start = original_start;
+        let mut end = start;
+        while end <= text.len() {
+            start = end;
+            end = end + match lcs.find(&text[end..]) {
+                None => return Some(NoMatch(text.len())),
+                Some(start) => start + lcs.len(),
+            };
+            match dfa::Fsm::reverse(
+                &self.ro.dfa_reverse,
+                &self.cache,
+                false,
+                &text[start..end],
+                end - start,
+            ) {
+                Match(0) | NoMatch(0) => return None,
+                Match(s) => return Some(Match((s + start, end))),
+                NoMatch(_) => continue,
+                Quit => return Some(Quit),
+            };
+        }
+        Some(NoMatch(text.len()))
+    }
+
+    /// Finds the leftmost-first match (start and end) using only the DFA
+    /// by scanning for suffix literals.
+    ///
+    /// If the result returned indicates that the DFA quit, then another
+    /// matching engine should be used.
+    #[inline(always)] // reduces constant overhead
+    fn find_dfa_reverse_suffix(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> dfa::Result<(usize, usize)> {
+        use dfa::Result::*;
+
+        let match_start = match self.exec_dfa_reverse_suffix(text, start) {
+            None => return self.find_dfa_forward(text, start),
+            Some(Match((start, _))) => start,
+            Some(r) => return r,
+        };
+        // At this point, we've found a match. The only way to quit now
+        // without a match is if the DFA gives up (seems unlikely).
+        //
+        // Now run the DFA forwards to find the proper end of the match.
+        // (The suffix literal match can only indicate the earliest
+        // possible end location, which may appear before the end of the
+        // leftmost-first match.)
+        match dfa::Fsm::forward(
+            &self.ro.dfa,
+            &self.cache,
+            false,
+            text,
+            match_start,
+        ) {
+            NoMatch(_) => panic!("BUG: reverse match implies forward match"),
+            Quit => Quit,
+            Match(e) => Match((match_start, e)),
+        }
+    }
+
+    /// Executes the NFA engine to return whether there is a match or not.
+    ///
+    /// Ideally, we could use shortest_nfa(...).is_some() and get the same
+    /// performance characteristics, but regex sets don't have captures, which
+    /// shortest_nfa depends on.
+    fn match_nfa(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        self.match_nfa_type(MatchNfaType::Auto, text, start)
+    }
+
+    /// Like match_nfa, but allows specification of the type of NFA engine.
+    fn match_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        self.exec_nfa(ty, &mut [false], &mut [], true, text, start)
+    }
+
+    /// Finds the shortest match using an NFA.
+    fn shortest_nfa(&self, text: &[u8], start: usize) -> Option<usize> {
+        self.shortest_nfa_type(MatchNfaType::Auto, text, start)
+    }
+
+    /// Like shortest_nfa, but allows specification of the type of NFA engine.
+    fn shortest_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<usize> {
+        let mut slots = [None, None];
+        if self.exec_nfa(ty, &mut [false], &mut slots, true, text, start) {
+            slots[1]
+        } else {
+            None
+        }
+    }
+
+    /// Like find, but executes an NFA engine.
+    fn find_nfa(
+        &self,
+        ty: MatchNfaType,
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        let mut slots = [None, None];
+        if self.exec_nfa(ty, &mut [false], &mut slots, false, text, start) {
+            match (slots[0], slots[1]) {
+                (Some(s), Some(e)) => Some((s, e)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Like find_nfa, but fills in captures and restricts the search space
+    /// using previously found match information.
+    ///
+    /// `slots` should have length equal to `2 * nfa.captures.len()`.
+    fn captures_nfa_with_match(
+        &self,
+        slots: &mut [Slot],
+        text: &[u8],
+        match_start: usize,
+        match_end: usize,
+    ) -> Option<(usize, usize)> {
+        // We can't use match_end directly, because we may need to examine one
+        // "character" after the end of a match for lookahead operators. We
+        // need to move two characters beyond the end, since some look-around
+        // operations may falsely assume a premature end of text otherwise.
+        let e = cmp::min(
+            next_utf8(text, next_utf8(text, match_end)), text.len());
+        self.captures_nfa(slots, &text[..e], match_start)
+    }
+
+    /// Like find_nfa, but fills in captures.
+    ///
+    /// `slots` should have length equal to `2 * nfa.captures.len()`.
+    fn captures_nfa(
+        &self,
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        self.captures_nfa_type(MatchNfaType::Auto, slots, text, start)
+    }
+
+    /// Like captures_nfa, but allows specification of type of NFA engine.
+    fn captures_nfa_type(
+        &self,
+        ty: MatchNfaType,
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+    ) -> Option<(usize, usize)> {
+        if self.exec_nfa(ty, &mut [false], slots, false, text, start) {
+            match (slots[0], slots[1]) {
+                (Some(s), Some(e)) => Some((s, e)),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+
+    fn exec_nfa(
+        &self,
+        mut ty: MatchNfaType,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        use self::MatchNfaType::*;
+        if let Auto = ty {
+            if backtrack::should_exec(self.ro.nfa.len(), text.len()) {
+                ty = Backtrack;
+            } else {
+                ty = PikeVM;
+            }
+        }
+        match ty {
+            Auto => unreachable!(),
+            Backtrack => self.exec_backtrack(matches, slots, text, start),
+            PikeVM => {
+                self.exec_pikevm(
+                    matches, slots, quit_after_match, text, start)
+            }
+        }
+    }
+
+    /// Always run the NFA algorithm.
+    fn exec_pikevm(
+        &self,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        if self.ro.nfa.uses_bytes() {
+            pikevm::Fsm::exec(
+                &self.ro.nfa,
+                &self.cache,
+                matches,
+                slots,
+                quit_after_match,
+                ByteInput::new(text, self.ro.nfa.only_utf8),
+                start)
+        } else {
+            pikevm::Fsm::exec(
+                &self.ro.nfa,
+                &self.cache,
+                matches,
+                slots,
+                quit_after_match,
+                CharInput::new(text),
+                start)
+        }
+    }
+
+    /// Always runs the NFA using bounded backtracking.
+    fn exec_backtrack(
+        &self,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        if self.ro.nfa.uses_bytes() {
+            backtrack::Bounded::exec(
+                &self.ro.nfa,
+                &self.cache,
+                matches,
+                slots,
+                ByteInput::new(text, self.ro.nfa.only_utf8),
+                start)
+        } else {
+            backtrack::Bounded::exec(
+                &self.ro.nfa,
+                &self.cache,
+                matches,
+                slots,
+                CharInput::new(text),
+                start)
+        }
+    }
+
+    /// Finds which regular expressions match the given text.
+    ///
+    /// `matches` should have length equal to the number of regexes being
+    /// searched.
+    ///
+    /// This is only useful when one wants to know which regexes in a set
+    /// match some text.
+    pub fn many_matches_at(
+        &self,
+        matches: &mut [bool],
+        text: &[u8],
+        start: usize,
+    ) -> bool {
+        use self::MatchType::*;
+        if !self.is_anchor_end_match(text) {
+            return false;
+        }
+        match self.ro.match_type {
+            Literal(ty) => {
+                debug_assert!(matches.len() == 1);
+                matches[0] = self.find_literals(ty, text, start).is_some();
+                matches[0]
+            }
+            Dfa | DfaAnchoredReverse | DfaSuffix | DfaMany => {
+                match dfa::Fsm::forward_many(
+                    &self.ro.dfa,
+                    &self.cache,
+                    matches,
+                    text,
+                    start,
+                ) {
+                    dfa::Result::Match(_) => true,
+                    dfa::Result::NoMatch(_) => false,
+                    dfa::Result::Quit => {
+                        self.exec_nfa(
+                            MatchNfaType::Auto,
+                            matches,
+                            &mut [],
+                            false,
+                            text,
+                            start)
+                    }
+                }
+            }
+            Nfa(ty) => self.exec_nfa(ty, matches, &mut [], false, text, start),
+            Nothing => false,
+        }
+    }
+
+    #[inline(always)] // reduces constant overhead
+    fn is_anchor_end_match(&self, text: &[u8]) -> bool {
+        // Only do this check if the haystack is big (>1MB).
+        if text.len() > (1<<20) && self.ro.nfa.is_anchored_end {
+            let lcs = self.ro.suffixes.lcs();
+            if lcs.len() >= 1 && !lcs.is_suffix(text) {
+                return false;
+            }
+        }
+        true
+    }
+
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        &self.ro.nfa.capture_name_idx
+    }
+}
+
+impl<'c> ExecNoSyncStr<'c> {
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        self.0.capture_name_idx()
+    }
+}
+
+impl Exec {
+    /// Get a searcher that isn't Sync.
+    #[inline(always)] // reduces constant overhead
+    pub fn searcher(&self) -> ExecNoSync {
+        let create = || Box::new(RefCell::new(ProgramCacheInner::new(&self.ro)));
+        ExecNoSync {
+            ro: &self.ro, // a clone is too expensive here! (and not needed)
+            cache: self.cache.get_or(create),
+        }
+    }
+
+    /// Get a searcher that isn't Sync and can match on &str.
+    #[inline(always)] // reduces constant overhead
+    pub fn searcher_str(&self) -> ExecNoSyncStr {
+        ExecNoSyncStr(self.searcher())
+    }
+
+    /// Build a Regex from this executor.
+    pub fn into_regex(self) -> re_unicode::Regex {
+        re_unicode::Regex::from(self)
+    }
+
+    /// Build a RegexSet from this executor.
+    pub fn into_regex_set(self) -> re_set::unicode::RegexSet {
+        re_set::unicode::RegexSet::from(self)
+    }
+
+    /// Build a Regex from this executor that can match arbitrary bytes.
+    pub fn into_byte_regex(self) -> re_bytes::Regex {
+        re_bytes::Regex::from(self)
+    }
+
+    /// Build a RegexSet from this executor that can match arbitrary bytes.
+    pub fn into_byte_regex_set(self) -> re_set::bytes::RegexSet {
+        re_set::bytes::RegexSet::from(self)
+    }
+
+    /// The original regular expressions given by the caller that were
+    /// compiled.
+    pub fn regex_strings(&self) -> &[String] {
+        &self.ro.res
+    }
+
+    /// Return a slice of capture names.
+    ///
+    /// Any capture that isn't named is None.
+    pub fn capture_names(&self) -> &[Option<String>] {
+        &self.ro.nfa.captures
+    }
+
+    /// Return a reference to named groups mapping (from group name to
+    /// group position).
+    pub fn capture_name_idx(&self) -> &Arc<HashMap<String, usize>> {
+        &self.ro.nfa.capture_name_idx
+    }
+}
+
+impl Clone for Exec {
+    fn clone(&self) -> Exec {
+        Exec {
+            ro: self.ro.clone(),
+            cache: CachedThreadLocal::new(),
+        }
+    }
+}
+
+impl ExecReadOnly {
+    fn choose_match_type(&self, hint: Option<MatchType>) -> MatchType {
+        use self::MatchType::*;
+        if let Some(Nfa(_)) = hint {
+            return hint.unwrap();
+        }
+        // If the NFA is empty, then we'll never match anything.
+        if self.nfa.insts.is_empty() {
+            return Nothing;
+        }
+        // If our set of prefixes is complete, then we can use it to find
+        // a match in lieu of a regex engine. This doesn't quite work well in
+        // the presence of multiple regexes, so only do it when there's one.
+        //
+        // TODO(burntsushi): Also, don't try to match literals if the regex is
+        // partially anchored. We could technically do it, but we'd need to
+        // create two sets of literals: all of them and then the subset that
+        // aren't anchored. We would then only search for all of them when at
+        // the beginning of the input and use the subset in all other cases.
+        if self.res.len() == 1 {
+            if self.nfa.prefixes.complete() {
+                return if self.nfa.is_anchored_start {
+                    Literal(MatchLiteralType::AnchoredStart)
+                } else {
+                    Literal(MatchLiteralType::Unanchored)
+                };
+            }
+            if self.suffixes.complete() {
+                return if self.nfa.is_anchored_end {
+                    Literal(MatchLiteralType::AnchoredEnd)
+                } else {
+                    // This case shouldn't happen. When the regex isn't
+                    // anchored, then complete prefixes should imply complete
+                    // suffixes.
+                    Literal(MatchLiteralType::Unanchored)
+                };
+            }
+        }
+        // If we can execute the DFA, then we totally should.
+        if dfa::can_exec(&self.dfa) {
+            // Regex sets require a slightly specialized path.
+            if self.res.len() >= 2 {
+                return DfaMany;
+            }
+            // If the regex is anchored at the end but not the start, then
+            // just match in reverse from the end of the haystack.
+            if !self.nfa.is_anchored_start && self.nfa.is_anchored_end {
+                return DfaAnchoredReverse;
+            }
+            // If there's a longish suffix literal, then it might be faster
+            // to look for that first.
+            if self.should_suffix_scan() {
+                return DfaSuffix;
+            }
+            // Fall back to your garden variety forward searching lazy DFA.
+            return Dfa;
+        }
+        // We're so totally hosed.
+        Nfa(MatchNfaType::Auto)
+    }
+
+    /// Returns true if the program is amenable to suffix scanning.
+    ///
+    /// When this is true, as a heuristic, we assume it is OK to quickly scan
+    /// for suffix literals and then do a *reverse* DFA match from any matches
+    /// produced by the literal scan. (And then followed by a forward DFA
+    /// search, since the previously found suffix literal maybe not actually be
+    /// the end of a match.)
+    ///
+    /// This is a bit of a specialized optimization, but can result in pretty
+    /// big performance wins if 1) there are no prefix literals and 2) the
+    /// suffix literals are pretty rare in the text. (1) is obviously easy to
+    /// account for but (2) is harder. As a proxy, we assume that longer
+    /// strings are generally rarer, so we only enable this optimization when
+    /// we have a meaty suffix.
+    fn should_suffix_scan(&self) -> bool {
+        if self.suffixes.is_empty() {
+            return false;
+        }
+        let lcs_len = self.suffixes.lcs().char_len();
+        lcs_len >= 3 && lcs_len > self.dfa.prefixes.lcp().char_len()
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum MatchType {
+    /// A single or multiple literal search. This is only used when the regex
+    /// can be decomposed into unambiguous literal search.
+    Literal(MatchLiteralType),
+    /// A normal DFA search.
+    Dfa,
+    /// A reverse DFA search starting from the end of a haystack.
+    DfaAnchoredReverse,
+    /// A reverse DFA search with suffix literal scanning.
+    DfaSuffix,
+    /// Use the DFA on two or more regular expressions.
+    DfaMany,
+    /// An NFA variant.
+    Nfa(MatchNfaType),
+    /// No match is ever possible, so don't ever try to search.
+    Nothing,
+}
+
+#[derive(Clone, Copy, Debug)]
+enum MatchLiteralType {
+    /// Match literals anywhere in text.
+    Unanchored,
+    /// Match literals only at the start of text.
+    AnchoredStart,
+    /// Match literals only at the end of text.
+    AnchoredEnd,
+}
+
+#[derive(Clone, Copy, Debug)]
+enum MatchNfaType {
+    /// Choose between Backtrack and PikeVM.
+    Auto,
+    /// NFA bounded backtracking.
+    ///
+    /// (This is only set by tests, since it never makes sense to always want
+    /// backtracking.)
+    Backtrack,
+    /// The Pike VM.
+    ///
+    /// (This is only set by tests, since it never makes sense to always want
+    /// the Pike VM.)
+    PikeVM,
+}
+
+/// ProgramCache maintains reusable allocations for each matching engine
+/// available to a particular program.
+pub type ProgramCache = RefCell<ProgramCacheInner>;
+
+#[derive(Clone, Debug)]
+pub struct ProgramCacheInner {
+    pub pikevm: pikevm::Cache,
+    pub backtrack: backtrack::Cache,
+    pub dfa: dfa::Cache,
+    pub dfa_reverse: dfa::Cache,
+}
+
+impl ProgramCacheInner {
+    fn new(ro: &ExecReadOnly) -> Self {
+        ProgramCacheInner {
+            pikevm: pikevm::Cache::new(&ro.nfa),
+            backtrack: backtrack::Cache::new(&ro.nfa),
+            dfa: dfa::Cache::new(&ro.dfa),
+            dfa_reverse: dfa::Cache::new(&ro.dfa_reverse),
+        }
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/expand.rs b/third_party/rust/regex-0.2.2/src/expand.rs
new file mode 100644
index 000000000000..55873f88bb96
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/expand.rs
@@ -0,0 +1,215 @@
+use std::str;
+
+use memchr::memchr;
+
+use re_bytes;
+use re_unicode;
+
+pub fn expand_str(
+    caps: &re_unicode::Captures,
+    mut replacement: &str,
+    dst: &mut String,
+) {
+    while !replacement.is_empty() {
+        match memchr(b'$', replacement.as_bytes()) {
+            None => break,
+            Some(i) => {
+                dst.push_str(&replacement[..i]);
+                replacement = &replacement[i..];
+            }
+        }
+        if replacement.as_bytes().get(1).map_or(false, |&b| b == b'$') {
+            dst.push_str("$");
+            replacement = &replacement[2..];
+            continue;
+        }
+        debug_assert!(!replacement.is_empty());
+        let cap_ref = match find_cap_ref(replacement) {
+            Some(cap_ref) => cap_ref,
+            None => {
+                dst.push_str("$");
+                replacement = &replacement[1..];
+                continue;
+            }
+        };
+        replacement = &replacement[cap_ref.end..];
+        match cap_ref.cap {
+            Ref::Number(i) => {
+                dst.push_str(
+                    caps.get(i).map(|m| m.as_str()).unwrap_or(""));
+            }
+            Ref::Named(name) => {
+                dst.push_str(
+                    caps.name(name).map(|m| m.as_str()).unwrap_or(""));
+            }
+        }
+    }
+    dst.push_str(replacement);
+}
+
+pub fn expand_bytes(
+    caps: &re_bytes::Captures,
+    mut replacement: &[u8],
+    dst: &mut Vec<u8>,
+) {
+    while !replacement.is_empty() {
+        match memchr(b'$', replacement) {
+            None => break,
+            Some(i) => {
+                dst.extend(&replacement[..i]);
+                replacement = &replacement[i..];
+            }
+        }
+        if replacement.get(1).map_or(false, |&b| b == b'$') {
+            dst.push(b'$');
+            replacement = &replacement[2..];
+            continue;
+        }
+        debug_assert!(!replacement.is_empty());
+        let cap_ref = match find_cap_ref(replacement) {
+            Some(cap_ref) => cap_ref,
+            None => {
+                dst.push(b'$');
+                replacement = &replacement[1..];
+                continue;
+            }
+        };
+        replacement = &replacement[cap_ref.end..];
+        match cap_ref.cap {
+            Ref::Number(i) => {
+                dst.extend(
+                    caps.get(i).map(|m| m.as_bytes()).unwrap_or(b""));
+            }
+            Ref::Named(name) => {
+                dst.extend(
+                    caps.name(name).map(|m| m.as_bytes()).unwrap_or(b""));
+            }
+        }
+    }
+    dst.extend(replacement);
+}
+
+/// CaptureRef represents a reference to a capture group inside some text. The
+/// reference is either a capture group name or a number.
+///
+/// It is also tagged with the position in the text immediately proceding the
+/// capture reference.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+struct CaptureRef<'a> {
+    cap: Ref<'a>,
+    end: usize,
+}
+
+/// A reference to a capture group in some text.
+///
+/// e.g., `$2`, `$foo`, `${foo}`.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+enum Ref<'a> {
+    Named(&'a str),
+    Number(usize),
+}
+
+impl<'a> From<&'a str> for Ref<'a> {
+    fn from(x: &'a str) -> Ref<'a> {
+        Ref::Named(x)
+    }
+}
+
+impl From<usize> for Ref<'static> {
+    fn from(x: usize) -> Ref<'static> {
+        Ref::Number(x)
+    }
+}
+
+/// Parses a possible reference to a capture group name in the given text,
+/// starting at the beginning of `replacement`.
+///
+/// If no such valid reference could be found, None is returned.
+fn find_cap_ref<T: ?Sized + AsRef<[u8]>>(
+    replacement: &T,
+) -> Option<CaptureRef> {
+    let mut i = 0;
+    let rep: &[u8] = replacement.as_ref();
+    if rep.len() <= 1 || rep[0] != b'$' {
+        return None;
+    }
+    let mut brace = false;
+    i += 1;
+    if rep[i] == b'{' {
+        brace = true;
+        i += 1;
+    }
+    let mut cap_end = i;
+    while rep.get(cap_end).map_or(false, is_valid_cap_letter) {
+        cap_end += 1;
+    }
+    if cap_end == i {
+        return None;
+    }
+    // We just verified that the range 0..cap_end is valid ASCII, so it must
+    // therefore be valid UTF-8. If we really cared, we could avoid this UTF-8
+    // check with either unsafe or by parsing the number straight from &[u8].
+    let cap = str::from_utf8(&rep[i..cap_end])
+                  .ok().expect("valid UTF-8 capture name");
+    if brace {
+        if !rep.get(cap_end).map_or(false, |&b| b == b'}') {
+            return None;
+        }
+        cap_end += 1;
+    }
+    Some(CaptureRef {
+        cap: match cap.parse::<u32>() {
+            Ok(i) => Ref::Number(i as usize),
+            Err(_) => Ref::Named(cap),
+        },
+        end: cap_end,
+    })
+}
+
+/// Returns true if and only if the given byte is allowed in a capture name.
+fn is_valid_cap_letter(b: &u8) -> bool {
+    match *b {
+        b'0' ... b'9' | b'a' ... b'z' | b'A' ... b'Z' | b'_' => true,
+        _ => false,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{CaptureRef, find_cap_ref};
+
+    macro_rules! find {
+        ($name:ident, $text:expr) => {
+            #[test]
+            fn $name() {
+                assert_eq!(None, find_cap_ref($text));
+            }
+        };
+        ($name:ident, $text:expr, $capref:expr) => {
+            #[test]
+            fn $name() {
+                assert_eq!(Some($capref), find_cap_ref($text));
+            }
+        };
+    }
+
+    macro_rules! c {
+        ($name_or_number:expr, $pos:expr) => {
+            CaptureRef { cap: $name_or_number.into(), end: $pos }
+        };
+    }
+
+    find!(find_cap_ref1, "$foo", c!("foo", 4));
+    find!(find_cap_ref2, "${foo}", c!("foo", 6));
+    find!(find_cap_ref3, "$0", c!(0, 2));
+    find!(find_cap_ref4, "$5", c!(5, 2));
+    find!(find_cap_ref5, "$10", c!(10, 3));
+    find!(find_cap_ref6, "$42a", c!("42a", 4));
+    find!(find_cap_ref7, "${42}a", c!(42, 5));
+    find!(find_cap_ref8, "${42");
+    find!(find_cap_ref9, "${42 ");
+    find!(find_cap_ref10, " $0 ");
+    find!(find_cap_ref11, "$");
+    find!(find_cap_ref12, " ");
+    find!(find_cap_ref13, "");
+}
diff --git a/third_party/rust/regex-0.2.2/src/freqs.rs b/third_party/rust/regex-0.2.2/src/freqs.rs
new file mode 100644
index 000000000000..92bafc199f55
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/freqs.rs
@@ -0,0 +1,271 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// NOTE: The following code was generated by "scripts/frequencies.py", do not
+// edit directly
+
+pub const BYTE_FREQUENCIES: [u8; 256] = [
+     55, // '\x00'
+     52, // '\x01'
+     51, // '\x02'
+     50, // '\x03'
+     49, // '\x04'
+     48, // '\x05'
+     47, // '\x06'
+     46, // '\x07'
+     45, // '\x08'
+    103, // '\t'
+    242, // '\n'
+     66, // '\x0b'
+     67, // '\x0c'
+    229, // '\r'
+     44, // '\x0e'
+     43, // '\x0f'
+     42, // '\x10'
+     41, // '\x11'
+     40, // '\x12'
+     39, // '\x13'
+     38, // '\x14'
+     37, // '\x15'
+     36, // '\x16'
+     35, // '\x17'
+     34, // '\x18'
+     33, // '\x19'
+     56, // '\x1a'
+     32, // '\x1b'
+     31, // '\x1c'
+     30, // '\x1d'
+     29, // '\x1e'
+     28, // '\x1f'
+    255, // ' '
+    148, // '!'
+    164, // '"'
+    149, // '#'
+    136, // '$'
+    160, // '%'
+    155, // '&'
+    173, // "'"
+    221, // '('
+    222, // ')'
+    134, // '*'
+    122, // '+'
+    232, // ','
+    202, // '-'
+    215, // '.'
+    224, // '/'
+    208, // '0'
+    220, // '1'
+    204, // '2'
+    187, // '3'
+    183, // '4'
+    179, // '5'
+    177, // '6'
+    168, // '7'
+    178, // '8'
+    200, // '9'
+    226, // ':'
+    195, // ';'
+    154, // '<'
+    184, // '='
+    174, // '>'
+    126, // '?'
+    120, // '@'
+    191, // 'A'
+    157, // 'B'
+    194, // 'C'
+    170, // 'D'
+    189, // 'E'
+    162, // 'F'
+    161, // 'G'
+    150, // 'H'
+    193, // 'I'
+    142, // 'J'
+    137, // 'K'
+    171, // 'L'
+    176, // 'M'
+    185, // 'N'
+    167, // 'O'
+    186, // 'P'
+    112, // 'Q'
+    175, // 'R'
+    192, // 'S'
+    188, // 'T'
+    156, // 'U'
+    140, // 'V'
+    143, // 'W'
+    123, // 'X'
+    133, // 'Y'
+    128, // 'Z'
+    147, // '['
+    138, // '\\'
+    146, // ']'
+    114, // '^'
+    223, // '_'
+    151, // '`'
+    249, // 'a'
+    216, // 'b'
+    238, // 'c'
+    236, // 'd'
+    253, // 'e'
+    227, // 'f'
+    218, // 'g'
+    230, // 'h'
+    247, // 'i'
+    135, // 'j'
+    180, // 'k'
+    241, // 'l'
+    233, // 'm'
+    246, // 'n'
+    244, // 'o'
+    231, // 'p'
+    139, // 'q'
+    245, // 'r'
+    243, // 's'
+    251, // 't'
+    235, // 'u'
+    201, // 'v'
+    196, // 'w'
+    240, // 'x'
+    214, // 'y'
+    152, // 'z'
+    182, // '{'
+    205, // '|'
+    181, // '}'
+    127, // '~'
+     27, // '\x7f'
+    212, // '\x80'
+    211, // '\x81'
+    210, // '\x82'
+    213, // '\x83'
+    228, // '\x84'
+    197, // '\x85'
+    169, // '\x86'
+    159, // '\x87'
+    131, // '\x88'
+    172, // '\x89'
+    105, // '\x8a'
+     80, // '\x8b'
+     98, // '\x8c'
+     96, // '\x8d'
+     97, // '\x8e'
+     81, // '\x8f'
+    207, // '\x90'
+    145, // '\x91'
+    116, // '\x92'
+    115, // '\x93'
+    144, // '\x94'
+    130, // '\x95'
+    153, // '\x96'
+    121, // '\x97'
+    107, // '\x98'
+    132, // '\x99'
+    109, // '\x9a'
+    110, // '\x9b'
+    124, // '\x9c'
+    111, // '\x9d'
+     82, // '\x9e'
+    108, // '\x9f'
+    118, // '\xa0'
+    141, // '¡'
+    113, // '¢'
+    129, // '£'
+    119, // '¤'
+    125, // '¥'
+    165, // '¦'
+    117, // '§'
+     92, // '¨'
+    106, // '©'
+     83, // 'ª'
+     72, // '«'
+     99, // '¬'
+     93, // '\xad'
+     65, // '®'
+     79, // '¯'
+    166, // '°'
+    237, // '±'
+    163, // '²'
+    199, // '³'
+    190, // '´'
+    225, // 'µ'
+    209, // '¶'
+    203, // '·'
+    198, // '¸'
+    217, // '¹'
+    219, // 'º'
+    206, // '»'
+    234, // '¼'
+    248, // '½'
+    158, // '¾'
+    239, // '¿'
+    255, // 'À'
+    255, // 'Á'
+    255, // 'Â'
+    255, // 'Ã'
+    255, // 'Ä'
+    255, // 'Å'
+    255, // 'Æ'
+    255, // 'Ç'
+    255, // 'È'
+    255, // 'É'
+    255, // 'Ê'
+    255, // 'Ë'
+    255, // 'Ì'
+    255, // 'Í'
+    255, // 'Î'
+    255, // 'Ï'
+    255, // 'Ð'
+    255, // 'Ñ'
+    255, // 'Ò'
+    255, // 'Ó'
+    255, // 'Ô'
+    255, // 'Õ'
+    255, // 'Ö'
+    255, // '×'
+    255, // 'Ø'
+    255, // 'Ù'
+    255, // 'Ú'
+    255, // 'Û'
+    255, // 'Ü'
+    255, // 'Ý'
+    255, // 'Þ'
+    255, // 'ß'
+    255, // 'à'
+    255, // 'á'
+    255, // 'â'
+    255, // 'ã'
+    255, // 'ä'
+    255, // 'å'
+    255, // 'æ'
+    255, // 'ç'
+    255, // 'è'
+    255, // 'é'
+    255, // 'ê'
+    255, // 'ë'
+    255, // 'ì'
+    255, // 'í'
+    255, // 'î'
+    255, // 'ï'
+    255, // 'ð'
+    255, // 'ñ'
+    255, // 'ò'
+    255, // 'ó'
+    255, // 'ô'
+    255, // 'õ'
+    255, // 'ö'
+    255, // '÷'
+    255, // 'ø'
+    255, // 'ù'
+    255, // 'ú'
+    255, // 'û'
+    255, // 'ü'
+    255, // 'ý'
+    255, // 'þ'
+    255, // 'ÿ'
+];
diff --git a/third_party/rust/regex-0.2.2/src/input.rs b/third_party/rust/regex-0.2.2/src/input.rs
new file mode 100644
index 000000000000..afb946342c49
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/input.rs
@@ -0,0 +1,425 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::char;
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops;
+use std::u32;
+
+use syntax;
+
+use literals::LiteralSearcher;
+use prog::InstEmptyLook;
+use utf8::{decode_utf8, decode_last_utf8};
+
+/// Represents a location in the input.
+#[derive(Clone, Copy, Debug)]
+pub struct InputAt {
+    pos: usize,
+    c: Char,
+    byte: Option<u8>,
+    len: usize,
+}
+
+impl InputAt {
+    /// Returns true iff this position is at the beginning of the input.
+    pub fn is_start(&self) -> bool {
+        self.pos == 0
+    }
+
+    /// Returns true iff this position is past the end of the input.
+    pub fn is_end(&self) -> bool {
+        self.c.is_none() && self.byte.is_none()
+    }
+
+    /// Returns the character at this position.
+    ///
+    /// If this position is just before or after the input, then an absent
+    /// character is returned.
+    pub fn char(&self) -> Char {
+        self.c
+    }
+
+    /// Returns the byte at this position.
+    pub fn byte(&self) -> Option<u8> {
+        self.byte
+    }
+
+    /// Returns the UTF-8 width of the character at this position.
+    pub fn len(&self) -> usize {
+        self.len
+    }
+
+    /// Returns the byte offset of this position.
+    pub fn pos(&self) -> usize {
+        self.pos
+    }
+
+    /// Returns the byte offset of the next position in the input.
+    pub fn next_pos(&self) -> usize {
+        self.pos + self.len
+    }
+}
+
+/// An abstraction over input used in the matching engines.
+pub trait Input {
+    /// Return an encoding of the position at byte offset `i`.
+    fn at(&self, i: usize) -> InputAt;
+
+    /// Return the Unicode character occurring next to `at`.
+    ///
+    /// If no such character could be decoded, then `Char` is absent.
+    fn next_char(&self, at: InputAt) -> Char;
+
+    /// Return the Unicode character occurring previous to `at`.
+    ///
+    /// If no such character could be decoded, then `Char` is absent.
+    fn previous_char(&self, at: InputAt) -> Char;
+
+    /// Return true if the given empty width instruction matches at the
+    /// input position given.
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool;
+
+    /// Scan the input for a matching prefix.
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt>;
+
+    /// The number of bytes in the input.
+    fn len(&self) -> usize;
+
+    /// Return the given input as a sequence of bytes.
+    fn as_bytes(&self) -> &[u8];
+}
+
+impl<'a, T: Input> Input for &'a T {
+    fn at(&self, i: usize) -> InputAt { (**self).at(i) }
+
+    fn next_char(&self, at: InputAt) -> Char { (**self).next_char(at) }
+
+    fn previous_char(&self, at: InputAt) -> Char { (**self).previous_char(at) }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        (**self).is_empty_match(at, empty)
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        (**self).prefix_at(prefixes, at)
+    }
+
+    fn len(&self) -> usize { (**self).len() }
+
+    fn as_bytes(&self) -> &[u8] { (**self).as_bytes() }
+}
+
+/// An input reader over characters.
+#[derive(Clone, Copy, Debug)]
+pub struct CharInput<'t>(&'t [u8]);
+
+impl<'t> CharInput<'t> {
+    /// Return a new character input reader for the given string.
+    pub fn new(s: &'t [u8]) -> CharInput<'t> {
+        CharInput(s)
+    }
+}
+
+impl<'t> ops::Deref for CharInput<'t> {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        self.0
+    }
+}
+
+impl<'t> Input for CharInput<'t> {
+    fn at(&self, i: usize) -> InputAt {
+        let c = decode_utf8(&self[i..]).map(|(c, _)| c).into();
+        InputAt {
+            pos: i,
+            c: c,
+            byte: None,
+            len: c.len_utf8(),
+        }
+    }
+
+    fn next_char(&self, at: InputAt) -> Char {
+        at.char()
+    }
+
+    fn previous_char(&self, at: InputAt) -> Char {
+        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
+    }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        use prog::EmptyLook::*;
+        match empty.look {
+            StartLine => {
+                let c = self.previous_char(at);
+                at.pos() == 0 || c == '\n'
+            }
+            EndLine => {
+                let c = self.next_char(at);
+                at.pos() == self.len() || c == '\n'
+            }
+            StartText => at.pos() == 0,
+            EndText => at.pos() == self.len(),
+            WordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() != c2.is_word_char()
+            }
+            NotWordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() == c2.is_word_char()
+            }
+            WordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_byte() != c2.is_word_byte()
+            }
+            NotWordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_byte() == c2.is_word_byte()
+            }
+        }
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
+    }
+
+    fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        self.0
+    }
+}
+
+/// An input reader over bytes.
+///
+/// N.B. We represent the reader with a string for now, since that gives us
+/// easy access to necessary Unicode decoding (used for word boundary look
+/// ahead/look behind).
+#[derive(Clone, Copy, Debug)]
+pub struct ByteInput<'t> {
+    text: &'t [u8],
+    only_utf8: bool,
+}
+
+impl<'t> ByteInput<'t> {
+    /// Return a new byte-based input reader for the given string.
+    pub fn new(text: &'t [u8], only_utf8: bool) -> ByteInput<'t> {
+        ByteInput {
+            text: text,
+            only_utf8: only_utf8,
+        }
+    }
+}
+
+impl<'t> ops::Deref for ByteInput<'t> {
+    type Target = [u8];
+
+    fn deref(&self) -> &[u8] {
+        self.text
+    }
+}
+
+impl<'t> Input for ByteInput<'t> {
+    fn at(&self, i: usize) -> InputAt {
+        InputAt {
+            pos: i,
+            c: None.into(),
+            byte: self.get(i).map(|&b| b),
+            len: 1,
+        }
+    }
+
+    fn next_char(&self, at: InputAt) -> Char {
+        decode_utf8(&self[at.pos()..]).map(|(c, _)| c).into()
+    }
+
+    fn previous_char(&self, at: InputAt) -> Char {
+        decode_last_utf8(&self[..at.pos()]).map(|(c, _)| c).into()
+    }
+
+    fn is_empty_match(&self, at: InputAt, empty: &InstEmptyLook) -> bool {
+        use prog::EmptyLook::*;
+        match empty.look {
+            StartLine => {
+                let c = self.previous_char(at);
+                at.pos() == 0 || c == '\n'
+            }
+            EndLine => {
+                let c = self.next_char(at);
+                at.pos() == self.len() || c == '\n'
+            }
+            StartText => at.pos() == 0,
+            EndText => at.pos() == self.len(),
+            WordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() != c2.is_word_char()
+            }
+            NotWordBoundary => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                c1.is_word_char() == c2.is_word_char()
+            }
+            WordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                if self.only_utf8 {
+                    // If we must match UTF-8, then we can't match word
+                    // boundaries at invalid UTF-8.
+                    if c1.is_none() && !at.is_start() {
+                        return false;
+                    }
+                    if c2.is_none() && !at.is_end() {
+                        return false;
+                    }
+                }
+                c1.is_word_byte() != c2.is_word_byte()
+            }
+            NotWordBoundaryAscii => {
+                let (c1, c2) = (self.previous_char(at), self.next_char(at));
+                if self.only_utf8 {
+                    // If we must match UTF-8, then we can't match word
+                    // boundaries at invalid UTF-8.
+                    if c1.is_none() && !at.is_start() {
+                        return false;
+                    }
+                    if c2.is_none() && !at.is_end() {
+                        return false;
+                    }
+                }
+                c1.is_word_byte() == c2.is_word_byte()
+            }
+        }
+    }
+
+    fn prefix_at(
+        &self,
+        prefixes: &LiteralSearcher,
+        at: InputAt,
+    ) -> Option<InputAt> {
+        prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
+    }
+
+    fn len(&self) -> usize {
+        self.text.len()
+    }
+
+    fn as_bytes(&self) -> &[u8] {
+        &self.text
+    }
+}
+
+/// An inline representation of `Option<char>`.
+///
+/// This eliminates the need to do case analysis on `Option<char>` to determine
+/// ordinality with other characters.
+///
+/// (The `Option<char>` is not related to encoding. Instead, it is used in the
+/// matching engines to represent the beginning and ending boundaries of the
+/// search text.)
+#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Char(u32);
+
+impl fmt::Debug for Char {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match char::from_u32(self.0) {
+            None => write!(f, "Empty"),
+            Some(c) => write!(f, "{:?}", c),
+        }
+    }
+}
+
+impl Char {
+    /// Returns true iff the character is absent.
+    #[inline]
+    pub fn is_none(self) -> bool { self.0 == u32::MAX }
+
+    /// Returns the length of the character's UTF-8 encoding.
+    ///
+    /// If the character is absent, then `0` is returned.
+    #[inline]
+    pub fn len_utf8(self) -> usize {
+        char::from_u32(self.0).map_or(0, |c| c.len_utf8())
+    }
+
+    /// Returns true iff the character is a word character.
+    ///
+    /// If the character is absent, then false is returned.
+    pub fn is_word_char(self) -> bool {
+        char::from_u32(self.0).map_or(false, syntax::is_word_char)
+    }
+
+    /// Returns true iff the byte is a word byte.
+    ///
+    /// If the byte is absent, then false is returned.
+    pub fn is_word_byte(self) -> bool {
+        match char::from_u32(self.0) {
+            None => false,
+            Some(c) if c <= '\u{7F}' => syntax::is_word_byte(c as u8),
+            Some(_) => false,
+        }
+    }
+
+    /// Converts the character to a real primitive `char`.
+    ///
+    /// If the character is absent, then `None` is returned.
+    pub fn as_char(self) -> Option<char> {
+        // This is only used in the `regex!` macro because it expands char
+        // classes into `match` expressions (instead of binary search).
+        char::from_u32(self.0)
+    }
+}
+
+impl From<char> for Char {
+    fn from(c: char) -> Char { Char(c as u32) }
+}
+
+impl From<Option<char>> for Char {
+    fn from(c: Option<char>) -> Char {
+        c.map_or(Char(u32::MAX), |c| c.into())
+    }
+}
+
+impl PartialEq<char> for Char {
+    #[inline]
+    fn eq(&self, other: &char) -> bool { self.0 == *other as u32 }
+}
+
+impl PartialEq<Char> for char {
+    #[inline]
+    fn eq(&self, other: &Char) -> bool { *self as u32 == other.0 }
+}
+
+impl PartialOrd<char> for Char {
+    #[inline]
+    fn partial_cmp(&self, other: &char) -> Option<Ordering> {
+        self.0.partial_cmp(&(*other as u32))
+    }
+}
+
+impl PartialOrd<Char> for char {
+    #[inline]
+    fn partial_cmp(&self, other: &Char) -> Option<Ordering> {
+        (*self as u32).partial_cmp(&other.0)
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/lib.rs b/third_party/rust/regex-0.2.2/src/lib.rs
new file mode 100644
index 000000000000..128932e620d8
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/lib.rs
@@ -0,0 +1,648 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This crate provides a library for parsing, compiling, and executing regular
+expressions. Its syntax is similar to Perl-style regular expressions, but lacks
+a few features like look around and backreferences. In exchange, all searches
+execute in linear time with respect to the size of the regular expression and
+search text.
+
+This crate's documentation provides some simple examples, describes
+[Unicode support](#unicode) and exhaustively lists the
+[supported syntax](#syntax).
+
+For more specific details on the API for regular expressions, please see the
+documentation for the [`Regex`](struct.Regex.html) type.
+
+# Usage
+
+This crate is [on crates.io](https://crates.io/crates/regex) and can be
+used by adding `regex` to your dependencies in your project's `Cargo.toml`.
+
+```toml
+[dependencies]
+regex = "0.2"
+```
+
+and this to your crate root:
+
+```rust
+extern crate regex;
+```
+
+# Example: find a date
+
+General use of regular expressions in this package involves compiling an
+expression and then using it to search, split or replace text. For example,
+to confirm that some text resembles a date:
+
+```rust
+use regex::Regex;
+let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
+assert!(re.is_match("2014-01-01"));
+```
+
+Notice the use of the `^` and `$` anchors. In this crate, every expression
+is executed with an implicit `.*?` at the beginning and end, which allows
+it to match anywhere in the text. Anchors can be used to ensure that the
+full text matches an expression.
+
+This example also demonstrates the utility of
+[raw strings](https://doc.rust-lang.org/stable/reference.html#raw-string-literals)
+in Rust, which
+are just like regular strings except they are prefixed with an `r` and do
+not process any escape sequences. For example, `"\\d"` is the same
+expression as `r"\d"`.
+
+# Example: Avoid compiling the same regex in a loop
+
+It is an anti-pattern to compile the same regular expression in a loop
+since compilation is typically expensive. (It takes anywhere from a few
+microseconds to a few **milliseconds** depending on the size of the
+regex.) Not only is compilation itself expensive, but this also prevents
+optimizations that reuse allocations internally to the matching engines.
+
+In Rust, it can sometimes be a pain to pass regular expressions around if
+they're used from inside a helper function. Instead, we recommend using the
+[`lazy_static`](https://crates.io/crates/lazy_static) crate to ensure that
+regular expressions are compiled exactly once.
+
+For example:
+
+```rust
+#[macro_use] extern crate lazy_static;
+extern crate regex;
+
+use regex::Regex;
+
+fn some_helper_function(text: &str) -> bool {
+    lazy_static! {
+        static ref RE: Regex = Regex::new("...").unwrap();
+    }
+    RE.is_match(text)
+}
+
+fn main() {}
+```
+
+Specifically, in this example, the regex will be compiled when it is used for
+the first time. On subsequent uses, it will reuse the previous compilation.
+
+# Example: iterating over capture groups
+
+This crate provides convenient iterators for matching an expression
+repeatedly against a search string to find successive non-overlapping
+matches. For example, to find all dates in a string and be able to access
+them by their component pieces:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
+let text = "2012-03-14, 2013-01-01 and 2014-07-05";
+for cap in re.captures_iter(text) {
+    println!("Month: {} Day: {} Year: {}", &cap[2], &cap[3], &cap[1]);
+}
+// Output:
+// Month: 03 Day: 14 Year: 2012
+// Month: 01 Day: 01 Year: 2013
+// Month: 07 Day: 05 Year: 2014
+# }
+```
+
+Notice that the year is in the capture group indexed at `1`. This is
+because the *entire match* is stored in the capture group at index `0`.
+
+# Example: replacement with named capture groups
+
+Building on the previous example, perhaps we'd like to rearrange the date
+formats. This can be done with text replacement. But to make the code
+clearer, we can *name*  our capture groups and use those names as variables
+in our replacement text:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
+let before = "2012-03-14, 2013-01-01 and 2014-07-05";
+let after = re.replace_all(before, "$m/$d/$y");
+assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
+# }
+```
+
+The `replace` methods are actually polymorphic in the replacement, which
+provides more flexibility than is seen here. (See the documentation for
+`Regex::replace` for more details.)
+
+Note that if your regex gets complicated, you can use the `x` flag to
+enable insigificant whitespace mode, which also lets you write comments:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?x)
+  (?P<y>\d{4}) # the year
+  -
+  (?P<m>\d{2}) # the month
+  -
+  (?P<d>\d{2}) # the day
+").unwrap();
+let before = "2012-03-14, 2013-01-01 and 2014-07-05";
+let after = re.replace_all(before, "$m/$d/$y");
+assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
+# }
+```
+
+If you wish to match against whitespace in this mode, you can still use `\s`,
+`\n`, `\t`, etc. For escaping a single space character, you can use its hex
+character code `\x20` or temporarily disable the `x` flag, e.g., `(?-x: )`.
+
+# Example: match multiple regular expressions simultaneously
+
+This demonstrates how to use a `RegexSet` to match multiple (possibly
+overlapping) regular expressions in a single scan of the search text:
+
+```rust
+use regex::RegexSet;
+
+let set = RegexSet::new(&[
+    r"\w+",
+    r"\d+",
+    r"\pL+",
+    r"foo",
+    r"bar",
+    r"barfoo",
+    r"foobar",
+]).unwrap();
+
+// Iterate over and collect all of the matches.
+let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+
+// You can also test whether a particular regex matched:
+let matches = set.matches("foobar");
+assert!(!matches.matched(5));
+assert!(matches.matched(6));
+```
+
+# Pay for what you use
+
+With respect to searching text with a regular expression, there are three
+questions that can be asked:
+
+1. Does the text match this expression?
+2. If so, where does it match?
+3. Where did the capturing groups match?
+
+Generally speaking, this crate could provide a function to answer only #3,
+which would subsume #1 and #2 automatically. However, it can be significantly
+more expensive to compute the location of capturing group matches, so it's best
+not to do it if you don't need to.
+
+Therefore, only use what you need. For example, don't use `find` if you
+only need to test if an expression matches a string. (Use `is_match`
+instead.)
+
+# Unicode
+
+This implementation executes regular expressions **only** on valid UTF-8
+while exposing match locations as byte indices into the search string.
+
+Only simple case folding is supported. Namely, when matching
+case-insensitively, the characters are first mapped using the [simple case
+folding](ftp://ftp.unicode.org/Public/UNIDATA/CaseFolding.txt) mapping
+before matching.
+
+Regular expressions themselves are **only** interpreted as a sequence of
+Unicode scalar values. This means you can use Unicode characters directly
+in your expression:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?i)Δ+").unwrap();
+let mat = re.find("ΔδΔ").unwrap();
+assert_eq!((mat.start(), mat.end()), (0, 6));
+# }
+```
+
+Most features of the regular expressions in this crate are Unicode aware. Here
+are some examples:
+
+* `.` will match any valid UTF-8 encoded Unicode scalar value except for `\n`.
+  (To also match `\n`, enable the `s` flag, e.g., `(?s:.)`.)
+* `\w`, `\d` and `\s` are Unicode aware. For example, `\s` will match all forms
+  of whitespace categorized by Unicode.
+* `\b` matches a Unicode word boundary.
+* Negated character classes like `[^a]` match all Unicode scalar values except
+  for `a`.
+* `^` and `$` are **not** Unicode aware in multi-line mode. Namely, they only
+  recognize `\n` and not any of the other forms of line terminators defined
+  by Unicode.
+
+Finally, Unicode general categories and scripts are available as character
+classes. For example, you can match a sequence of numerals, Greek or
+Cherokee letters:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"[\pN\p{Greek}\p{Cherokee}]+").unwrap();
+let mat = re.find("abcΔᎠβⅠᏴγδⅡxyz").unwrap();
+assert_eq!((mat.start(), mat.end()), (3, 23));
+# }
+```
+
+# Opt out of Unicode support
+
+The `bytes` sub-module provides a `Regex` type that can be used to match
+on `&[u8]`. By default, text is interpreted as UTF-8 just like it is with
+the main `Regex` type. However, this behavior can be disabled by turning
+off the `u` flag, even if doing so could result in matching invalid UTF-8.
+For example, when the `u` flag is disabled, `.` will match any byte instead
+of any Unicode scalar value.
+
+Disabling the `u` flag is also possible with the standard `&str`-based `Regex`
+type, but it is only allowed where the UTF-8 invariant is maintained. For
+example, `(?-u:\w)` is an ASCII-only `\w` character class and is legal in an
+`&str`-based `Regex`, but `(?-u:\xFF)` will attempt to match the raw byte
+`\xFF`, which is invalid UTF-8 and therefore is illegal in `&str`-based
+regexes.
+
+# Syntax
+
+The syntax supported in this crate is documented below.
+
+Note that the regular expression parser and abstract syntax are exposed in
+a separate crate, [`regex-syntax`](../regex_syntax/index.html).
+
+## Matching one character
+
+<pre class="rust">
+.             any character except new line (includes new line with s flag)
+\d            digit (\p{Nd})
+\D            not digit
+\pN           One-letter name Unicode character class
+\p{Greek}     Unicode character class (general category or script)
+\PN           Negated one-letter name Unicode character class
+\P{Greek}     negated Unicode character class (general category or script)
+</pre>
+
+### Character classes
+
+<pre class="rust">
+[xyz]         A character class matching either x, y or z (union).
+[^xyz]        A character class matching any character except x, y and z.
+[a-z]         A character class matching any character in range a-z.
+[[:alpha:]]   ASCII character class ([A-Za-z])
+[[:^alpha:]]  Negated ASCII character class ([^A-Za-z])
+[x[^xyz]]     Nested/grouping character class (matching any character except y and z)
+[a-y&&xyz]    Intersection (matching x or y)
+[0-9&&[^4]]   Subtraction using intersection and negation (matching 0-9 except 4)
+[\[\]]        Escaping in character classes (matching [ or ])
+</pre>
+
+Any named character class may appear inside a bracketed `[...]` character
+class. For example, `[\p{Greek}[:digit:]]` matches any Greek or ASCII
+digit. `[\p{Greek}&&\pL]` matches Greek letters.
+
+Precedence in character classes, from most binding to least:
+
+1. Ranges: `a-cd` == `[a-c]d`
+2. Union: `ab&&bc` == `[ab]&&[bc]`
+3. Intersection: `^a-z&&b` == `^[a-z&&b]`
+4. Negation
+
+## Composites
+
+<pre class="rust">
+xy    concatenation (x followed by y)
+x|y   alternation (x or y, prefer x)
+</pre>
+
+## Repetitions
+
+<pre class="rust">
+x*        zero or more of x (greedy)
+x+        one or more of x (greedy)
+x?        zero or one of x (greedy)
+x*?       zero or more of x (ungreedy/lazy)
+x+?       one or more of x (ungreedy/lazy)
+x??       zero or one of x (ungreedy/lazy)
+x{n,m}    at least n x and at most m x (greedy)
+x{n,}     at least n x (greedy)
+x{n}      exactly n x
+x{n,m}?   at least n x and at most m x (ungreedy/lazy)
+x{n,}?    at least n x (ungreedy/lazy)
+x{n}?     exactly n x
+</pre>
+
+## Empty matches
+
+<pre class="rust">
+^     the beginning of text (or start-of-line with multi-line mode)
+$     the end of text (or end-of-line with multi-line mode)
+\A    only the beginning of text (even with multi-line mode enabled)
+\z    only the end of text (even with multi-line mode enabled)
+\b    a Unicode word boundary (\w on one side and \W, \A, or \z on other)
+\B    not a Unicode word boundary
+</pre>
+
+## Grouping and flags
+
+<pre class="rust">
+(exp)          numbered capture group (indexed by opening parenthesis)
+(?P&lt;name&gt;exp)  named (also numbered) capture group (allowed chars: [_0-9a-zA-Z])
+(?:exp)        non-capturing group
+(?flags)       set flags within current group
+(?flags:exp)   set flags for exp (non-capturing)
+</pre>
+
+Flags are each a single character. For example, `(?x)` sets the flag `x`
+and `(?-x)` clears the flag `x`. Multiple flags can be set or cleared at
+the same time: `(?xy)` sets both the `x` and `y` flags and `(?x-y)` sets
+the `x` flag and clears the `y` flag.
+
+All flags are by default disabled unless stated otherwise. They are:
+
+<pre class="rust">
+i     case-insensitive
+m     multi-line mode: ^ and $ match begin/end of line
+s     allow . to match \n
+U     swap the meaning of x* and x*?
+u     Unicode support (enabled by default)
+x     ignore whitespace and allow line comments (starting with `#`)
+</pre>
+
+Here's an example that matches case-insensitively for only part of the
+expression:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?i)a+(?-i)b+").unwrap();
+let cap = re.captures("AaAaAbbBBBb").unwrap();
+assert_eq!(&cap[0], "AaAaAbb");
+# }
+```
+
+Notice that the `a+` matches either `a` or `A`, but the `b+` only matches
+`b`.
+
+Here is an example that uses an ASCII word boundary instead of a Unicode
+word boundary:
+
+```rust
+# extern crate regex; use regex::Regex;
+# fn main() {
+let re = Regex::new(r"(?-u:\b).+(?-u:\b)").unwrap();
+let cap = re.captures("$$abc$$").unwrap();
+assert_eq!(&cap[0], "abc");
+# }
+```
+
+## Escape sequences
+
+<pre class="rust">
+\*         literal *, works for any punctuation character: \.+*?()|[]{}^$
+\a         bell (\x07)
+\f         form feed (\x0C)
+\t         horizontal tab
+\n         new line
+\r         carriage return
+\v         vertical tab (\x0B)
+\123       octal character code (up to three digits)
+\x7F       hex character code (exactly two digits)
+\x{10FFFF} any hex character code corresponding to a Unicode code point
+</pre>
+
+## Perl character classes (Unicode friendly)
+
+These classes are based on the definitions provided in
+[UTS#18](http://www.unicode.org/reports/tr18/#Compatibility_Properties):
+
+<pre class="rust">
+\d     digit (\p{Nd})
+\D     not digit
+\s     whitespace (\p{White_Space})
+\S     not whitespace
+\w     word character (\p{Alphabetic} + \p{M} + \d + \p{Pc} + \p{Join_Control})
+\W     not word character
+</pre>
+
+## ASCII character classes
+
+<pre class="rust">
+[[:alnum:]]    alphanumeric ([0-9A-Za-z])
+[[:alpha:]]    alphabetic ([A-Za-z])
+[[:ascii:]]    ASCII ([\x00-\x7F])
+[[:blank:]]    blank ([\t ])
+[[:cntrl:]]    control ([\x00-\x1F\x7F])
+[[:digit:]]    digits ([0-9])
+[[:graph:]]    graphical ([!-~])
+[[:lower:]]    lower case ([a-z])
+[[:print:]]    printable ([ -~])
+[[:punct:]]    punctuation ([!-/:-@\[-`{-~])
+[[:space:]]    whitespace ([\t\n\v\f\r ])
+[[:upper:]]    upper case ([A-Z])
+[[:word:]]     word characters ([0-9A-Za-z_])
+[[:xdigit:]]   hex digit ([0-9A-Fa-f])
+</pre>
+
+# Untrusted input
+
+This crate can handle both untrusted regular expressions and untrusted
+search text.
+
+Untrusted regular expressions are handled by capping the size of a compiled
+regular expression.
+(See [`RegexBuilder::size_limit`](struct.RegexBuilder.html#method.size_limit).)
+Without this, it would be trivial for an attacker to exhaust your system's
+memory with expressions like `a{100}{100}{100}`.
+
+Untrusted search text is allowed because the matching engine(s) in this
+crate have time complexity `O(mn)` (with `m ~ regex` and `n ~ search
+text`), which means there's no way to cause exponential blow-up like with
+some other regular expression engines. (We pay for this by disallowing
+features like arbitrary look-ahead and backreferences.)
+
+When a DFA is used, pathological cases with exponential state blow up are
+avoided by constructing the DFA lazily or in an "online" manner. Therefore,
+at most one new state can be created for each byte of input. This satisfies
+our time complexity guarantees, but can lead to unbounded memory growth
+proportional to the size of the input. As a stopgap, the DFA is only
+allowed to store a fixed number of states. When the limit is reached, its
+states are wiped and continues on, possibly duplicating previous work. If
+the limit is reached too frequently, it gives up and hands control off to
+another matching engine with fixed memory requirements.
+(The DFA size limit can also be tweaked. See
+[`RegexBuilder::dfa_size_limit`](struct.RegexBuilder.html#method.dfa_size_limit).)
+*/
+
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+#![cfg_attr(feature = "pattern", feature(pattern))]
+#![cfg_attr(feature = "simd-accel", feature(cfg_target_feature))]
+
+extern crate aho_corasick;
+extern crate memchr;
+extern crate thread_local;
+#[cfg(test)] extern crate quickcheck;
+extern crate regex_syntax as syntax;
+#[cfg(feature = "simd-accel")] extern crate simd;
+extern crate utf8_ranges;
+
+pub use error::Error;
+pub use re_builder::unicode::*;
+pub use re_builder::set_unicode::*;
+pub use re_set::unicode::*;
+pub use re_trait::Locations;
+pub use re_unicode::{
+    Regex, Match, Captures,
+    CaptureNames, Matches, CaptureMatches, SubCaptureMatches,
+    Replacer, NoExpand, Split, SplitN,
+    escape,
+};
+
+/**
+Match regular expressions on arbitrary bytes.
+
+This module provides a nearly identical API to the one found in the
+top-level of this crate. There are two important differences:
+
+1. Matching is done on `&[u8]` instead of `&str`. Additionally, `Vec<u8>`
+is used where `String` would have been used.
+2. Unicode support can be disabled even when disabling it would result in
+matching invalid UTF-8 bytes.
+
+# Example: match null terminated string
+
+This shows how to find all null-terminated strings in a slice of bytes:
+
+```rust
+# use regex::bytes::Regex;
+let re = Regex::new(r"(?-u)(?P<cstr>[^\x00]+)\x00").unwrap();
+let text = b"foo\x00bar\x00baz\x00";
+
+// Extract all of the strings without the null terminator from each match.
+// The unwrap is OK here since a match requires the `cstr` capture to match.
+let cstrs: Vec<&[u8]> =
+    re.captures_iter(text)
+      .map(|c| c.name("cstr").unwrap().as_bytes())
+      .collect();
+assert_eq!(vec![&b"foo"[..], &b"bar"[..], &b"baz"[..]], cstrs);
+```
+
+# Example: selectively enable Unicode support
+
+This shows how to match an arbitrary byte pattern followed by a UTF-8 encoded
+string (e.g., to extract a title from a Matroska file):
+
+```rust
+# use std::str;
+# use regex::bytes::Regex;
+let re = Regex::new(
+    r"(?-u)\x7b\xa9(?:[\x80-\xfe]|[\x40-\xff].)(?u:(.*))"
+).unwrap();
+let text = b"\x12\xd0\x3b\x5f\x7b\xa9\x85\xe2\x98\x83\x80\x98\x54\x76\x68\x65";
+let caps = re.captures(text).unwrap();
+
+// Notice that despite the `.*` at the end, it will only match valid UTF-8
+// because Unicode mode was enabled with the `u` flag. Without the `u` flag,
+// the `.*` would match the rest of the bytes.
+let mat = caps.get(1).unwrap();
+assert_eq!((7, 10), (mat.start(), mat.end()));
+
+// If there was a match, Unicode mode guarantees that `title` is valid UTF-8.
+let title = str::from_utf8(&caps[1]).unwrap();
+assert_eq!("☃", title);
+```
+
+In general, if the Unicode flag is enabled in a capture group and that capture
+is part of the overall match, then the capture is *guaranteed* to be valid
+UTF-8.
+
+# Syntax
+
+The supported syntax is pretty much the same as the syntax for Unicode
+regular expressions with a few changes that make sense for matching arbitrary
+bytes:
+
+1. The `u` flag can be disabled even when disabling it might cause the regex to
+match invalid UTF-8. When the `u` flag is disabled, the regex is said to be in
+"ASCII compatible" mode.
+2. In ASCII compatible mode, neither Unicode scalar values nor Unicode
+character classes are allowed.
+3. In ASCII compatible mode, Perl character classes (`\w`, `\d` and `\s`)
+revert to their typical ASCII definition. `\w` maps to `[[:word:]]`, `\d` maps
+to `[[:digit:]]` and `\s` maps to `[[:space:]]`.
+4. In ASCII compatible mode, word boundaries use the ASCII compatible `\w` to
+determine whether a byte is a word byte or not.
+5. Hexadecimal notation can be used to specify arbitrary bytes instead of
+Unicode codepoints. For example, in ASCII compatible mode, `\xFF` matches the
+literal byte `\xFF`, while in Unicode mode, `\xFF` is a Unicode codepoint that
+matches its UTF-8 encoding of `\xC3\xBF`. Similarly for octal notation.
+6. `.` matches any *byte* except for `\n` instead of any Unicode scalar value.
+When the `s` flag is enabled, `.` matches any byte.
+
+# Performance
+
+In general, one should expect performance on `&[u8]` to be roughly similar to
+performance on `&str`.
+*/
+pub mod bytes {
+    pub use re_builder::bytes::*;
+    pub use re_builder::set_bytes::*;
+    pub use re_bytes::*;
+    pub use re_set::bytes::*;
+    pub use re_trait::Locations;
+}
+
+mod backtrack;
+mod utf8;
+mod compile;
+mod dfa;
+mod error;
+mod exec;
+mod expand;
+mod freqs;
+mod input;
+mod literals;
+#[cfg(feature = "pattern")]
+mod pattern;
+mod pikevm;
+mod prog;
+mod re_builder;
+mod re_bytes;
+mod re_plugin;
+mod re_set;
+mod re_trait;
+mod re_unicode;
+#[cfg(feature = "simd-accel")]
+mod simd_accel;
+#[cfg(not(feature = "simd-accel"))]
+#[path = "simd_fallback/mod.rs"]
+mod simd_accel;
+mod sparse;
+
+/// The `internal` module exists to support the `regex!` macro and other
+/// suspicious activity, such as testing different matching engines and
+/// supporting the `regex-debug` CLI utility.
+#[doc(hidden)]
+pub mod internal {
+    pub use compile::Compiler;
+    pub use exec::{Exec, ExecBuilder};
+    pub use input::{Char, Input, CharInput, InputAt};
+    pub use literals::LiteralSearcher;
+    pub use prog::{Program, Inst, EmptyLook, InstRanges};
+    pub use re_plugin::Plugin;
+    pub use re_unicode::_Regex;
+}
diff --git a/third_party/rust/regex/src/literals.rs b/third_party/rust/regex-0.2.2/src/literals.rs
similarity index 100%
rename from third_party/rust/regex/src/literals.rs
rename to third_party/rust/regex-0.2.2/src/literals.rs
diff --git a/third_party/rust/regex-0.2.2/src/pattern.rs b/third_party/rust/regex-0.2.2/src/pattern.rs
new file mode 100644
index 000000000000..37183c24e307
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/pattern.rs
@@ -0,0 +1,62 @@
+use std::str::pattern::{Pattern, Searcher, SearchStep};
+
+use re_unicode::{Regex, Matches};
+
+pub struct RegexSearcher<'r, 't> {
+    haystack: &'t str,
+    it: Matches<'r, 't>,
+    last_step_end: usize,
+    next_match: Option<(usize, usize)>,
+}
+
+impl<'r, 't> Pattern<'t> for &'r Regex {
+    type Searcher = RegexSearcher<'r, 't>;
+
+    fn into_searcher(self, haystack: &'t str) -> RegexSearcher<'r, 't> {
+        RegexSearcher {
+            haystack: haystack,
+            it: self.find_iter(haystack),
+            last_step_end: 0,
+            next_match: None,
+        }
+    }
+}
+
+unsafe impl<'r, 't> Searcher<'t> for RegexSearcher<'r, 't> {
+    #[inline]
+    fn haystack(&self) -> &'t str {
+        self.haystack
+    }
+
+    #[inline]
+    fn next(&mut self) -> SearchStep {
+        if let Some((s, e)) = self.next_match {
+            self.next_match = None;
+            self.last_step_end = e;
+            return SearchStep::Match(s, e);
+        }
+        match self.it.next() {
+            None => {
+                if self.last_step_end < self.haystack().len() {
+                    let last = self.last_step_end;
+                    self.last_step_end = self.haystack().len();
+                    SearchStep::Reject(last, self.haystack().len())
+                } else {
+                    SearchStep::Done
+                }
+            }
+            Some(m) => {
+                let (s, e) = (m.start(), m.end());
+                if s == self.last_step_end {
+                    self.last_step_end = e;
+                    SearchStep::Match(s, e)
+                } else {
+                    self.next_match = Some((s, e));
+                    let last = self.last_step_end;
+                    self.last_step_end = s;
+                    SearchStep::Reject(last, s)
+                }
+            }
+        }
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/pikevm.rs b/third_party/rust/regex-0.2.2/src/pikevm.rs
new file mode 100644
index 000000000000..b96f0e75885a
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/pikevm.rs
@@ -0,0 +1,377 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This module implements the Pike VM. That is, it guarantees linear time
+// search of a regex on any text with memory use proportional to the size of
+// the regex.
+//
+// It is equal in power to the backtracking engine in this crate, except the
+// backtracking engine is typically faster on small regexes/texts at the
+// expense of a bigger memory footprint.
+//
+// It can do more than the DFA can (specifically, record capture locations
+// and execute Unicode word boundary assertions), but at a slower speed.
+// Specifically, the Pike VM exectues a DFA implicitly by repeatedly expanding
+// epsilon transitions. That is, the Pike VM engine can be in multiple states
+// at once where as the DFA is only ever in one state at a time.
+//
+// Therefore, the Pike VM is generally treated as the fallback when the other
+// matching engines either aren't feasible to run or are insufficient.
+
+use std::mem;
+
+use exec::ProgramCache;
+use input::{Input, InputAt};
+use prog::{Program, InstPtr};
+use re_trait::Slot;
+use sparse::SparseSet;
+
+/// An NFA simulation matching engine.
+#[derive(Debug)]
+pub struct Fsm<'r, I> {
+    /// The sequence of opcodes (among other things) that is actually executed.
+    ///
+    /// The program may be byte oriented or Unicode codepoint oriented.
+    prog: &'r Program,
+    /// An explicit stack used for following epsilon transitions. (This is
+    /// borrowed from the cache.)
+    stack: &'r mut Vec<FollowEpsilon>,
+    /// The input to search.
+    input: I,
+}
+
+/// A cached allocation that can be reused on each execution.
+#[derive(Clone, Debug)]
+pub struct Cache {
+    /// A pair of ordered sets for tracking NFA states.
+    clist: Threads,
+    nlist: Threads,
+    /// An explicit stack used for following epsilon transitions.
+    stack: Vec<FollowEpsilon>,
+}
+
+/// An ordered set of NFA states and their captures.
+#[derive(Clone, Debug)]
+struct Threads {
+    /// An ordered set of opcodes (each opcode is an NFA state).
+    set: SparseSet,
+    /// Captures for every NFA state.
+    ///
+    /// It is stored in row-major order, where the columns are the capture
+    /// slots and the rows are the states.
+    caps: Vec<Slot>,
+    /// The number of capture slots stored per thread. (Every capture has
+    /// two slots.)
+    slots_per_thread: usize,
+}
+
+/// A representation of an explicit stack frame when following epsilon
+/// transitions. This is used to avoid recursion.
+#[derive(Clone, Debug)]
+enum FollowEpsilon {
+    /// Follow transitions at the given instruction pointer.
+    IP(InstPtr),
+    /// Restore the capture slot with the given position in the input.
+    Capture { slot: usize, pos: Slot },
+}
+
+impl Cache {
+    /// Create a new allocation used by the NFA machine to record execution
+    /// and captures.
+    pub fn new(_prog: &Program) -> Self {
+        Cache {
+            clist: Threads::new(),
+            nlist: Threads::new(),
+            stack: vec![],
+        }
+    }
+}
+
+impl<'r, I: Input> Fsm<'r, I> {
+    /// Execute the NFA matching engine.
+    ///
+    /// If there's a match, `exec` returns `true` and populates the given
+    /// captures accordingly.
+    pub fn exec(
+        prog: &'r Program,
+        cache: &ProgramCache,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        input: I,
+        start: usize,
+    ) -> bool {
+        let mut cache = cache.borrow_mut();
+        let mut cache = &mut cache.pikevm;
+        cache.clist.resize(prog.len(), prog.captures.len());
+        cache.nlist.resize(prog.len(), prog.captures.len());
+        let at = input.at(start);
+        Fsm {
+            prog: prog,
+            stack: &mut cache.stack,
+            input: input,
+        }.exec_(
+            &mut cache.clist,
+            &mut cache.nlist,
+            matches,
+            slots,
+            quit_after_match,
+            at,
+        )
+    }
+
+    fn exec_(
+        &mut self,
+        mut clist: &mut Threads,
+        mut nlist: &mut Threads,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        quit_after_match: bool,
+        mut at: InputAt,
+    ) -> bool {
+        let mut matched = false;
+        let mut all_matched = false;
+        clist.set.clear();
+        nlist.set.clear();
+'LOOP:  loop {
+            if clist.set.is_empty() {
+                // Three ways to bail out when our current set of threads is
+                // empty.
+                //
+                // 1. We have a match---so we're done exploring any possible
+                //    alternatives. Time to quit. (We can't do this if we're
+                //    looking for matches for multiple regexes, unless we know
+                //    they all matched.)
+                //
+                // 2. If the expression starts with a '^' we can terminate as
+                //    soon as the last thread dies.
+                if (matched && matches.len() <= 1)
+                    || all_matched
+                    || (!at.is_start() && self.prog.is_anchored_start) {
+                    break;
+                }
+
+                // 3. If there's a literal prefix for the program, try to
+                //    jump ahead quickly. If it can't be found, then we can
+                //    bail out early.
+                if !self.prog.prefixes.is_empty() {
+                    at = match self.input.prefix_at(&self.prog.prefixes, at) {
+                        None => break,
+                        Some(at) => at,
+                    };
+                }
+            }
+
+            // This simulates a preceding '.*?' for every regex by adding
+            // a state starting at the current position in the input for the
+            // beginning of the program only if we don't already have a match.
+            if clist.set.is_empty()
+                || (!self.prog.is_anchored_start && !all_matched) {
+                self.add(&mut clist, slots, 0, at);
+            }
+            // The previous call to "add" actually inspects the position just
+            // before the current character. For stepping through the machine,
+            // we can to look at the current character, so we advance the
+            // input.
+            let at_next = self.input.at(at.next_pos());
+            for i in 0..clist.set.len() {
+                let ip = clist.set[i];
+                if self.step(
+                    &mut nlist,
+                    matches,
+                    slots,
+                    clist.caps(ip),
+                    ip,
+                    at,
+                    at_next,
+                ) {
+                    matched = true;
+                    all_matched = all_matched || matches.iter().all(|&b| b);
+                    if quit_after_match {
+                        // If we only care if a match occurs (not its
+                        // position), then we can quit right now.
+                        break 'LOOP;
+                    }
+                    if self.prog.matches.len() == 1 {
+                        // We don't need to check the rest of the threads
+                        // in this set because we've matched something
+                        // ("leftmost-first"). However, we still need to check
+                        // threads in the next set to support things like
+                        // greedy matching.
+                        //
+                        // This is only true on normal regexes. For regex sets,
+                        // we need to mush on to observe other matches.
+                        break;
+                    }
+                }
+            }
+            if at.is_end() {
+                break;
+            }
+            at = at_next;
+            mem::swap(clist, nlist);
+            nlist.set.clear();
+        }
+        matched
+    }
+
+    /// Step through the input, one token (byte or codepoint) at a time.
+    ///
+    /// nlist is the set of states that will be processed on the next token
+    /// in the input.
+    ///
+    /// caps is the set of captures passed by the caller of the NFA. They are
+    /// written to only when a match state is visited.
+    ///
+    /// thread_caps is the set of captures set for the current NFA state, ip.
+    ///
+    /// at and at_next are the current and next positions in the input. at or
+    /// at_next may be EOF.
+    fn step(
+        &mut self,
+        nlist: &mut Threads,
+        matches: &mut [bool],
+        slots: &mut [Slot],
+        thread_caps: &mut [Option<usize>],
+        ip: usize,
+        at: InputAt,
+        at_next: InputAt,
+    ) -> bool {
+        use prog::Inst::*;
+        match self.prog[ip] {
+            Match(match_slot) => {
+                if match_slot < matches.len() {
+                    matches[match_slot] = true;
+                }
+                for (slot, val) in slots.iter_mut().zip(thread_caps.iter()) {
+                    *slot = *val;
+                }
+                true
+            }
+            Char(ref inst) => {
+                if inst.c == at.char() {
+                    self.add(nlist, thread_caps, inst.goto, at_next);
+                }
+                false
+            }
+            Ranges(ref inst) => {
+                if inst.matches(at.char()) {
+                    self.add(nlist, thread_caps, inst.goto, at_next);
+                }
+                false
+            }
+            Bytes(ref inst) => {
+                if let Some(b) = at.byte() {
+                    if inst.matches(b) {
+                        self.add(nlist, thread_caps, inst.goto, at_next);
+                    }
+                }
+                false
+            }
+            EmptyLook(_) | Save(_) | Split(_) => false,
+        }
+    }
+
+    /// Follows epsilon transitions and adds them for processing to nlist,
+    /// starting at and including ip.
+    fn add(
+        &mut self,
+        nlist: &mut Threads,
+        thread_caps: &mut [Option<usize>],
+        ip: usize,
+        at: InputAt,
+    ) {
+        self.stack.push(FollowEpsilon::IP(ip));
+        while let Some(frame) = self.stack.pop() {
+            match frame {
+                FollowEpsilon::IP(ip) => {
+                    self.add_step(nlist, thread_caps, ip, at);
+                }
+                FollowEpsilon::Capture { slot, pos } => {
+                    thread_caps[slot] = pos;
+                }
+            }
+        }
+    }
+
+    /// A helper function for add that avoids excessive pushing to the stack.
+    fn add_step(
+        &mut self,
+        nlist: &mut Threads,
+        thread_caps: &mut [Option<usize>],
+        mut ip: usize,
+        at: InputAt,
+    ) {
+        // Instead of pushing and popping to the stack, we mutate ip as we
+        // traverse the set of states. We only push to the stack when we
+        // absolutely need recursion (restoring captures or following a
+        // branch).
+        use prog::Inst::*;
+        loop {
+            // Don't visit states we've already added.
+            if nlist.set.contains(ip) {
+                return;
+            }
+            nlist.set.insert(ip);
+            match self.prog[ip] {
+                EmptyLook(ref inst) => {
+                    if self.input.is_empty_match(at, inst) {
+                        ip = inst.goto;
+                    }
+                }
+                Save(ref inst) => {
+                    if inst.slot < thread_caps.len() {
+                        self.stack.push(FollowEpsilon::Capture {
+                            slot: inst.slot,
+                            pos: thread_caps[inst.slot],
+                        });
+                        thread_caps[inst.slot] = Some(at.pos());
+                    }
+                    ip = inst.goto;
+                }
+                Split(ref inst) => {
+                    self.stack.push(FollowEpsilon::IP(inst.goto2));
+                    ip = inst.goto1;
+                }
+                Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
+                    let mut t = &mut nlist.caps(ip);
+                    for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
+                        *slot = *val;
+                    }
+                    return;
+                }
+            }
+        }
+    }
+}
+
+impl Threads {
+    fn new() -> Self {
+        Threads {
+            set: SparseSet::new(0),
+            caps: vec![],
+            slots_per_thread: 0,
+        }
+    }
+
+    fn resize(&mut self, num_insts: usize, ncaps: usize) {
+        if num_insts == self.set.capacity() {
+            return;
+        }
+        self.slots_per_thread = ncaps * 2;
+        self.set = SparseSet::new(num_insts);
+        self.caps = vec![None; self.slots_per_thread * num_insts];
+    }
+
+    fn caps(&mut self, pc: usize) -> &mut [Option<usize>] {
+        let i = pc * self.slots_per_thread;
+        &mut self.caps[i..i + self.slots_per_thread]
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/prog.rs b/third_party/rust/regex-0.2.2/src/prog.rs
new file mode 100644
index 000000000000..36f2aff879d9
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/prog.rs
@@ -0,0 +1,426 @@
+use std::collections::HashMap;
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops::Deref;
+use std::mem;
+use std::slice;
+use std::sync::Arc;
+
+use input::Char;
+use literals::LiteralSearcher;
+
+/// InstPtr represents the index of an instruction in a regex program.
+pub type InstPtr = usize;
+
+/// Program is a sequence of instructions and various facts about thos
+/// instructions.
+#[derive(Clone)]
+pub struct Program {
+    /// A sequence of instructions that represents an NFA.
+    pub insts: Vec<Inst>,
+    /// Pointers to each Match instruction in the sequence.
+    ///
+    /// This is always length 1 unless this program represents a regex set.
+    pub matches: Vec<InstPtr>,
+    /// The ordered sequence of all capture groups extracted from the AST.
+    /// Unnamed groups are `None`.
+    pub captures: Vec<Option<String>>,
+    /// Pointers to all named capture groups into `captures`.
+    pub capture_name_idx: Arc<HashMap<String, usize>>,
+    /// A pointer to the start instruction. This can vary depending on how
+    /// the program was compiled. For example, programs for use with the DFA
+    /// engine have a `.*?` inserted at the beginning of unanchored regular
+    /// expressions. The actual starting point of the program is after the
+    /// `.*?`.
+    pub start: InstPtr,
+    /// A set of equivalence classes for discriminating bytes in the compiled
+    /// program.
+    pub byte_classes: Vec<u8>,
+    /// When true, this program can only match valid UTF-8.
+    pub only_utf8: bool,
+    /// When true, this program uses byte range instructions instead of Unicode
+    /// range instructions.
+    pub is_bytes: bool,
+    /// When true, the program is compiled for DFA matching. For example, this
+    /// implies `is_bytes` and also inserts a preceding `.*?` for unanchored
+    /// regexes.
+    pub is_dfa: bool,
+    /// When true, the program matches text in reverse (for use only in the
+    /// DFA).
+    pub is_reverse: bool,
+    /// Whether the regex must match from the start of the input.
+    pub is_anchored_start: bool,
+    /// Whether the regex must match at the end of the input.
+    pub is_anchored_end: bool,
+    /// Whether this program contains a Unicode word boundary instruction.
+    pub has_unicode_word_boundary: bool,
+    /// A possibly empty machine for very quickly matching prefix literals.
+    pub prefixes: LiteralSearcher,
+    /// A limit on the size of the cache that the DFA is allowed to use while
+    /// matching.
+    ///
+    /// The cache limit specifies approximately how much space we're willing to
+    /// give to the state cache. Once the state cache exceeds the size, it is
+    /// wiped and all states must be re-computed.
+    ///
+    /// Note that this value does not impact correctness. It can be set to 0
+    /// and the DFA will run just fine. (It will only ever store exactly one
+    /// state in the cache, and will likely run very slowly, but it will work.)
+    ///
+    /// Also note that this limit is *per thread of execution*. That is,
+    /// if the same regex is used to search text across multiple threads
+    /// simultaneously, then the DFA cache is not shared. Instead, copies are
+    /// made.
+    pub dfa_size_limit: usize,
+}
+
+impl Program {
+    /// Creates an empty instruction sequence. Fields are given default
+    /// values.
+    pub fn new() -> Self {
+        Program {
+            insts: vec![],
+            matches: vec![],
+            captures: vec![],
+            capture_name_idx: Arc::new(HashMap::new()),
+            start: 0,
+            byte_classes: vec![0; 256],
+            only_utf8: true,
+            is_bytes: false,
+            is_dfa: false,
+            is_reverse: false,
+            is_anchored_start: false,
+            is_anchored_end: false,
+            has_unicode_word_boundary: false,
+            prefixes: LiteralSearcher::empty(),
+            dfa_size_limit: 2 * (1<<20),
+        }
+    }
+
+    /// If pc is an index to a no-op instruction (like Save), then return the
+    /// next pc that is not a no-op instruction.
+    pub fn skip(&self, mut pc: usize) -> usize {
+        loop {
+            match self[pc] {
+                Inst::Save(ref i) => pc = i.goto,
+                _ => return pc,
+            }
+        }
+    }
+
+    /// Return true if and only if an execution engine at instruction `pc` will
+    /// always lead to a match.
+    pub fn leads_to_match(&self, pc: usize) -> bool {
+        if self.matches.len() > 1 {
+            // If we have a regex set, then we have more than one ending
+            // state, so leading to one of those states is generally
+            // meaningless.
+            return false;
+        }
+        match self[self.skip(pc)] {
+            Inst::Match(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if the current configuration demands that an implicit
+    /// `.*?` be prepended to the instruction sequence.
+    pub fn needs_dotstar(&self) -> bool {
+        self.is_dfa && !self.is_reverse && !self.is_anchored_start
+    }
+
+    /// Returns true if this program uses Byte instructions instead of
+    /// Char/Range instructions.
+    pub fn uses_bytes(&self) -> bool {
+        self.is_bytes || self.is_dfa
+    }
+
+    /// Returns true if this program exclusively matches valid UTF-8 bytes.
+    ///
+    /// That is, if an invalid UTF-8 byte is seen, then no match is possible.
+    pub fn only_utf8(&self) -> bool {
+        self.only_utf8
+    }
+
+    /// Return the approximate heap usage of this instruction sequence in
+    /// bytes.
+    pub fn approximate_size(&self) -> usize {
+        // The only instruction that uses heap space is Ranges (for
+        // Unicode codepoint programs) to store non-overlapping codepoint
+        // ranges. To keep this operation constant time, we ignore them.
+        (self.len() * mem::size_of::<Inst>())
+        + (self.matches.len() * mem::size_of::<InstPtr>())
+        + (self.captures.len() * mem::size_of::<Option<String>>())
+        + (self.capture_name_idx.len() *
+           (mem::size_of::<String>() + mem::size_of::<usize>()))
+        + (self.byte_classes.len() * mem::size_of::<u8>())
+        + self.prefixes.approximate_size()
+    }
+}
+
+impl Deref for Program {
+    type Target = [Inst];
+
+    fn deref(&self) -> &Self::Target {
+        &*self.insts
+    }
+}
+
+impl fmt::Debug for Program {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::Inst::*;
+
+        fn with_goto(cur: usize, goto: usize, fmtd: String) -> String {
+            if goto == cur + 1 {
+                fmtd
+            } else {
+                format!("{} (goto: {})", fmtd, goto)
+            }
+        }
+
+        fn visible_byte(b: u8) -> String {
+            use std::ascii::escape_default;
+            let escaped = escape_default(b).collect::<Vec<u8>>();
+            String::from_utf8_lossy(&escaped).into_owned()
+        }
+
+        for (pc, inst) in self.iter().enumerate() {
+            match *inst {
+                Match(slot) => {
+                    try!(write!(f, "{:04} Match({:?})", pc, slot))
+                }
+                Save(ref inst) => {
+                    let s = format!("{:04} Save({})", pc, inst.slot);
+                    try!(write!(f, "{}", with_goto(pc, inst.goto, s)));
+                }
+                Split(ref inst) => {
+                    try!(write!(f, "{:04} Split({}, {})",
+                                pc, inst.goto1, inst.goto2));
+                }
+                EmptyLook(ref inst) => {
+                    let s = format!("{:?}", inst.look);
+                    try!(write!(f, "{:04} {}",
+                                pc, with_goto(pc, inst.goto, s)));
+                }
+                Char(ref inst) => {
+                    let s = format!("{:?}", inst.c);
+                    try!(write!(f, "{:04} {}",
+                                pc, with_goto(pc, inst.goto, s)));
+                }
+                Ranges(ref inst) => {
+                    let ranges = inst.ranges
+                        .iter()
+                        .map(|r| format!("{:?}-{:?}", r.0, r.1))
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    let s = format!("{}", ranges);
+                    try!(write!(f, "{:04} {}",
+                                pc, with_goto(pc, inst.goto, s)));
+                }
+                Bytes(ref inst) => {
+                    let s = format!(
+                        "Bytes({}, {})",
+                        visible_byte(inst.start),
+                        visible_byte(inst.end));
+                    try!(write!(f, "{:04} {}",
+                                pc, with_goto(pc, inst.goto, s)));
+                }
+            }
+            if pc == self.start {
+                try!(write!(f, " (start)"));
+            }
+            try!(write!(f, "\n"));
+        }
+        Ok(())
+    }
+}
+
+impl<'a> IntoIterator for &'a Program {
+    type Item = &'a Inst;
+    type IntoIter = slice::Iter<'a, Inst>;
+    fn into_iter(self) -> Self::IntoIter { self.iter() }
+}
+
+/// Inst is an instruction code in a Regex program.
+///
+/// Regrettably, a regex program either contains Unicode codepoint
+/// instructions (Char and Ranges) or it contains byte instructions (Bytes).
+/// A regex program can never contain both.
+///
+/// It would be worth investigating splitting this into two distinct types and
+/// then figuring out how to make the matching engines polymorphic over those
+/// types without sacrificing performance.
+///
+/// Other than the benefit of moving invariants into the type system, another
+/// benefit is the decreased size. If we remove the `Char` and `Ranges`
+/// instructions from the `Inst` enum, then its size shrinks from 40 bytes to
+/// 24 bytes. (This is because of the removal of a `Vec` in the `Ranges`
+/// variant.) Given that byte based machines are typically much bigger than
+/// their Unicode analogues (because they can decode UTF-8 directly), this ends
+/// up being a pretty significant savings.
+#[derive(Clone, Debug)]
+pub enum Inst {
+    /// Match indicates that the program has reached a match state.
+    ///
+    /// The number in the match corresponds to the Nth logical regular
+    /// expression in this program. This index is always 0 for normal regex
+    /// programs. Values greater than 0 appear when compiling regex sets, and
+    /// each match instruction gets its own unique value. The value corresponds
+    /// to the Nth regex in the set.
+    Match(usize),
+    /// Save causes the program to save the current location of the input in
+    /// the slot indicated by InstSave.
+    Save(InstSave),
+    /// Split causes the program to diverge to one of two paths in the
+    /// program, preferring goto1 in InstSplit.
+    Split(InstSplit),
+    /// EmptyLook represents a zero-width assertion in a regex program. A
+    /// zero-width assertion does not consume any of the input text.
+    EmptyLook(InstEmptyLook),
+    /// Char requires the regex program to match the character in InstChar at
+    /// the current position in the input.
+    Char(InstChar),
+    /// Ranges requires the regex program to match the character at the current
+    /// position in the input with one of the ranges specified in InstRanges.
+    Ranges(InstRanges),
+    /// Bytes is like Ranges, except it expresses a single byte range. It is
+    /// used in conjunction with Split instructions to implement multi-byte
+    /// character classes.
+    Bytes(InstBytes),
+}
+
+impl Inst {
+    /// Returns true if and only if this is a match instruction.
+    pub fn is_match(&self) -> bool {
+        match *self {
+            Inst::Match(_) => true,
+            _ => false,
+        }
+    }
+}
+
+/// Representation of the Save instruction.
+#[derive(Clone, Debug)]
+pub struct InstSave {
+    /// The next location to execute in the program.
+    pub goto: InstPtr,
+    /// The capture slot (there are two slots for every capture in a regex,
+    /// including the zeroth capture for the entire match).
+    pub slot: usize,
+}
+
+/// Representation of the Split instruction.
+#[derive(Clone, Debug)]
+pub struct InstSplit {
+    /// The first instruction to try. A match resulting from following goto1
+    /// has precedence over a match resulting from following goto2.
+    pub goto1: InstPtr,
+    /// The second instruction to try. A match resulting from following goto1
+    /// has precedence over a match resulting from following goto2.
+    pub goto2: InstPtr,
+}
+
+/// Representation of the EmptyLook instruction.
+#[derive(Clone, Debug)]
+pub struct InstEmptyLook {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The type of zero-width assertion to check.
+    pub look: EmptyLook,
+}
+
+/// The set of zero-width match instructions.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum EmptyLook {
+    /// Start of line or input.
+    StartLine,
+    /// End of line or input.
+    EndLine,
+    /// Start of input.
+    StartText,
+    /// End of input.
+    EndText,
+    /// Word character on one side and non-word character on other.
+    WordBoundary,
+    /// Word character on both sides or non-word character on both sides.
+    NotWordBoundary,
+    /// ASCII word boundary.
+    WordBoundaryAscii,
+    /// Not ASCII word boundary.
+    NotWordBoundaryAscii,
+}
+
+/// Representation of the Char instruction.
+#[derive(Clone, Debug)]
+pub struct InstChar {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The character to test.
+    pub c: char,
+}
+
+/// Representation of the Ranges instruction.
+#[derive(Clone, Debug)]
+pub struct InstRanges {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The set of Unicode scalar value ranges to test.
+    pub ranges: Vec<(char, char)>,
+}
+
+impl InstRanges {
+    /// Tests whether the given input character matches this instruction.
+    pub fn matches(&self, c: Char) -> bool {
+        // This speeds up the `match_class_unicode` benchmark by checking
+        // some common cases quickly without binary search. e.g., Matching
+        // a Unicode class on predominantly ASCII text.
+        for r in self.ranges.iter().take(4) {
+            if c < r.0 {
+                return false;
+            }
+            if c <= r.1 {
+                return true;
+            }
+        }
+        self.ranges.binary_search_by(|r| {
+            if r.1 < c {
+                Ordering::Less
+            } else if r.0 > c {
+                Ordering::Greater
+            } else {
+                Ordering::Equal
+            }
+        }).is_ok()
+    }
+
+    /// Return the number of distinct characters represented by all of the
+    /// ranges.
+    pub fn num_chars(&self) -> usize {
+        self.ranges.iter()
+            .map(|&(s, e)| 1 + (e as u32) - (s as u32))
+            .fold(0, |acc, len| acc + len)
+            as usize
+    }
+}
+
+/// Representation of the Bytes instruction.
+#[derive(Clone, Debug)]
+pub struct InstBytes {
+    /// The next location to execute in the program if this instruction
+    /// succeeds.
+    pub goto: InstPtr,
+    /// The start (inclusive) of this byte range.
+    pub start: u8,
+    /// The end (inclusive) of this byte range.
+    pub end: u8,
+}
+
+impl InstBytes {
+    /// Returns true if and only if the given byte is in this range.
+    pub fn matches(&self, byte: u8) -> bool {
+        self.start <= byte && byte <= self.end
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/re_builder.rs b/third_party/rust/regex-0.2.2/src/re_builder.rs
new file mode 100644
index 000000000000..12b251564927
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/re_builder.rs
@@ -0,0 +1,263 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// The set of user configurable options for compiling zero or more regexes.
+#[derive(Clone, Debug)]
+#[allow(missing_docs)]
+pub struct RegexOptions {
+    pub pats: Vec<String>,
+    pub size_limit: usize,
+    pub dfa_size_limit: usize,
+    pub case_insensitive: bool,
+    pub multi_line: bool,
+    pub dot_matches_new_line: bool,
+    pub swap_greed: bool,
+    pub ignore_whitespace: bool,
+    pub unicode: bool,
+}
+
+impl Default for RegexOptions {
+    fn default() -> Self {
+        RegexOptions {
+            pats: vec![],
+            size_limit: 10 * (1<<20),
+            dfa_size_limit: 2 * (1<<20),
+            case_insensitive: false,
+            multi_line: false,
+            dot_matches_new_line: false,
+            swap_greed: false,
+            ignore_whitespace: false,
+            unicode: true,
+        }
+    }
+}
+
+macro_rules! define_builder {
+    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
+        pub mod $name {
+            use error::Error;
+            use exec::ExecBuilder;
+            use super::RegexOptions;
+
+            use $regex_mod::Regex;
+
+/// A configurable builder for a regular expression.
+///
+/// A builder can be used to configure how the regex is built, for example, by
+/// setting the default flags (which can be overridden in the expression
+/// itself) or setting various limits.
+pub struct RegexBuilder(RegexOptions);
+
+impl RegexBuilder {
+    /// Create a new regular expression builder with the given pattern.
+    ///
+    /// If the pattern is invalid, then an error will be returned when
+    /// `compile` is called.
+    pub fn new(pattern: &str) -> RegexBuilder {
+        let mut builder = RegexBuilder(RegexOptions::default());
+        builder.0.pats.push(pattern.to_owned());
+        builder
+    }
+
+    /// Consume the builder and compile the regular expression.
+    ///
+    /// Note that calling `as_str` on the resulting `Regex` will produce the
+    /// pattern given to `new` verbatim. Notably, it will not incorporate any
+    /// of the flags set on this builder.
+    pub fn build(&self) -> Result<Regex, Error> {
+        ExecBuilder::new_options(self.0.clone())
+            .only_utf8($only_utf8)
+            .build()
+            .map(Regex::from)
+    }
+
+    /// Set the value for the case insensitive (`i`) flag.
+    pub fn case_insensitive(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.case_insensitive = yes;
+        self
+    }
+
+    /// Set the value for the multi-line matching (`m`) flag.
+    pub fn multi_line(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.multi_line = yes;
+        self
+    }
+
+    /// Set the value for the any character (`s`) flag, where in `.` matches
+    /// anything when `s` is set and matches anything except for new line when
+    /// it is not set (the default).
+    ///
+    /// N.B. "matches anything" means "any byte" for `regex::bytes::Regex`
+    /// expressions and means "any Unicode scalar value" for `regex::Regex`
+    /// expressions.
+    pub fn dot_matches_new_line(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.dot_matches_new_line = yes;
+        self
+    }
+
+    /// Set the value for the greedy swap (`U`) flag.
+    pub fn swap_greed(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.swap_greed = yes;
+        self
+    }
+
+    /// Set the value for the ignore whitespace (`x`) flag.
+    pub fn ignore_whitespace(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.ignore_whitespace = yes;
+        self
+    }
+
+    /// Set the value for the Unicode (`u`) flag.
+    pub fn unicode(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.unicode = yes;
+        self
+    }
+
+    /// Set the approximate size limit of the compiled regular expression.
+    ///
+    /// This roughly corresponds to the number of bytes occupied by a single
+    /// compiled program. If the program exceeds this number, then a
+    /// compilation error is returned.
+    pub fn size_limit(&mut self, limit: usize) -> &mut RegexBuilder {
+        self.0.size_limit = limit;
+        self
+    }
+
+    /// Set the approximate size of the cache used by the DFA.
+    ///
+    /// This roughly corresponds to the number of bytes that the DFA will
+    /// use while searching.
+    ///
+    /// Note that this is a *per thread* limit. There is no way to set a global
+    /// limit. In particular, if a regex is used from multiple threads
+    /// simulanteously, then each thread may use up to the number of bytes
+    /// specified here.
+    pub fn dfa_size_limit(&mut self, limit: usize) -> &mut RegexBuilder {
+        self.0.dfa_size_limit = limit;
+        self
+    }
+}
+        }
+    }
+}
+
+define_builder!(bytes, re_bytes, false);
+define_builder!(unicode, re_unicode, true);
+
+macro_rules! define_set_builder {
+    ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
+        pub mod $name {
+            use error::Error;
+            use exec::ExecBuilder;
+            use super::RegexOptions;
+
+            use re_set::$regex_mod::RegexSet;
+
+/// A configurable builder for a set of regular expressions.
+///
+/// A builder can be used to configure how the regexes are built, for example,
+/// by setting the default flags (which can be overridden in the expression
+/// itself) or setting various limits.
+pub struct RegexSetBuilder(RegexOptions);
+
+impl RegexSetBuilder {
+    /// Create a new regular expression builder with the given pattern.
+    ///
+    /// If the pattern is invalid, then an error will be returned when
+    /// `compile` is called.
+    pub fn new<I, S>(patterns: I) -> RegexSetBuilder
+            where S: AsRef<str>, I: IntoIterator<Item=S> {
+        let mut builder = RegexSetBuilder(RegexOptions::default());
+        for pat in patterns {
+            builder.0.pats.push(pat.as_ref().to_owned());
+        }
+        builder
+    }
+
+    /// Consume the builder and compile the regular expressions into a set.
+    pub fn build(&self) -> Result<RegexSet, Error> {
+        ExecBuilder::new_options(self.0.clone())
+            .only_utf8($only_utf8)
+            .build()
+            .map(RegexSet::from)
+    }
+
+    /// Set the value for the case insensitive (`i`) flag.
+    pub fn case_insensitive(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.case_insensitive = yes;
+        self
+    }
+
+    /// Set the value for the multi-line matching (`m`) flag.
+    pub fn multi_line(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.multi_line = yes;
+        self
+    }
+
+    /// Set the value for the any character (`s`) flag, where in `.` matches
+    /// anything when `s` is set and matches anything except for new line when
+    /// it is not set (the default).
+    ///
+    /// N.B. "matches anything" means "any byte" for `regex::bytes::RegexSet`
+    /// expressions and means "any Unicode scalar value" for `regex::RegexSet`
+    /// expressions.
+    pub fn dot_matches_new_line(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.dot_matches_new_line = yes;
+        self
+    }
+
+    /// Set the value for the greedy swap (`U`) flag.
+    pub fn swap_greed(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.swap_greed = yes;
+        self
+    }
+
+    /// Set the value for the ignore whitespace (`x`) flag.
+    pub fn ignore_whitespace(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.ignore_whitespace = yes;
+        self
+    }
+
+    /// Set the value for the Unicode (`u`) flag.
+    pub fn unicode(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.unicode = yes;
+        self
+    }
+
+    /// Set the approximate size limit of the compiled regular expression.
+    ///
+    /// This roughly corresponds to the number of bytes occupied by a single
+    /// compiled program. If the program exceeds this number, then a
+    /// compilation error is returned.
+    pub fn size_limit(&mut self, limit: usize) -> &mut RegexSetBuilder {
+        self.0.size_limit = limit;
+        self
+    }
+
+    /// Set the approximate size of the cache used by the DFA.
+    ///
+    /// This roughly corresponds to the number of bytes that the DFA will
+    /// use while searching.
+    ///
+    /// Note that this is a *per thread* limit. There is no way to set a global
+    /// limit. In particular, if a regex is used from multiple threads
+    /// simulanteously, then each thread may use up to the number of bytes
+    /// specified here.
+    pub fn dfa_size_limit(&mut self, limit: usize) -> &mut RegexSetBuilder {
+        self.0.dfa_size_limit = limit;
+        self
+    }
+}
+        }
+    }
+}
+
+define_set_builder!(set_bytes, bytes, false);
+define_set_builder!(set_unicode, unicode, true);
diff --git a/third_party/rust/regex-0.2.2/src/re_bytes.rs b/third_party/rust/regex-0.2.2/src/re_bytes.rs
new file mode 100644
index 000000000000..8a8550eb6509
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/re_bytes.rs
@@ -0,0 +1,1031 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt;
+use std::ops::Index;
+use std::str::FromStr;
+use std::sync::Arc;
+
+use memchr::memchr;
+
+use exec::{Exec, ExecNoSync};
+use expand::expand_bytes;
+use error::Error;
+use re_builder::bytes::RegexBuilder;
+use re_trait::{self, RegularExpression, Locations, SubCapturesPosIter};
+
+/// Match represents a single match of a regex in a haystack.
+///
+/// The lifetime parameter `'t` refers to the lifetime of the matched text.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Match<'t> {
+    text: &'t [u8],
+    start: usize,
+    end: usize,
+}
+
+impl<'t> Match<'t> {
+    /// Returns the starting byte offset of the match in the haystack.
+    #[inline]
+    pub fn start(&self) -> usize {
+        self.start
+    }
+
+    /// Returns the ending byte offset of the match in the haystack.
+    #[inline]
+    pub fn end(&self) -> usize {
+        self.end
+    }
+
+    /// Returns the matched text.
+    #[inline]
+    pub fn as_bytes(&self) -> &'t [u8] {
+        &self.text[self.start..self.end]
+    }
+
+    /// Creates a new match from the given haystack and byte offsets.
+    #[inline]
+    fn new(haystack: &'t [u8], start: usize, end: usize) -> Match<'t> {
+        Match {
+            text: haystack,
+            start: start,
+            end: end,
+        }
+    }
+}
+
+/// A compiled regular expression for matching arbitrary bytes.
+///
+/// It can be used to search, split or replace text. All searching is done with
+/// an implicit `.*?` at the beginning and end of an expression. To force an
+/// expression to match the whole string (or a prefix or a suffix), you must
+/// use an anchor like `^` or `$` (or `\A` and `\z`).
+///
+/// Like the `Regex` type in the parent module, matches with this regex return
+/// byte offsets into the search text. **Unlike** the parent `Regex` type,
+/// these byte offsets may not correspond to UTF-8 sequence boundaries since
+/// the regexes in this module can match arbitrary bytes.
+#[derive(Clone)]
+pub struct Regex(Exec);
+
+impl fmt::Display for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+impl fmt::Debug for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+/// A constructor for Regex from an Exec.
+///
+/// This is hidden because Exec isn't actually part of the public API.
+#[doc(hidden)]
+impl From<Exec> for Regex {
+    fn from(exec: Exec) -> Regex {
+        Regex(exec)
+    }
+}
+
+impl FromStr for Regex {
+    type Err = Error;
+
+    /// Attempts to parse a string into a regular expression
+    fn from_str(s: &str) -> Result<Regex, Error> {
+        Regex::new(s)
+    }
+}
+
+/// Core regular expression methods.
+impl Regex {
+    /// Compiles a regular expression. Once compiled, it can be used repeatedly
+    /// to search, split or replace text in a string.
+    ///
+    /// If an invalid expression is given, then an error is returned.
+    pub fn new(re: &str) -> Result<Regex, Error> {
+        RegexBuilder::new(re).build()
+    }
+
+    /// Returns true if and only if the regex matches the string given.
+    ///
+    /// It is recommended to use this method if all you need to do is test
+    /// a match, since the underlying matching engine may be able to do less
+    /// work.
+    ///
+    /// # Example
+    ///
+    /// Test if some text contains at least one word with exactly 13 ASCII word
+    /// bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"I categorically deny having triskaidekaphobia.";
+    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
+    /// # }
+    /// ```
+    pub fn is_match(&self, text: &[u8]) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the start and end byte range of the leftmost-first match in
+    /// `text`. If no match exists, then `None` is returned.
+    ///
+    /// Note that this should only be used if you want to discover the position
+    /// of the match. Testing the existence of a match is faster if you use
+    /// `is_match`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of the first word with exactly 13
+    /// ASCII word bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"I categorically deny having triskaidekaphobia.";
+    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
+    /// assert_eq!((mat.start(), mat.end()), (2, 15));
+    /// # }
+    /// ```
+    pub fn find<'t>(&self, text: &'t [u8]) -> Option<Match<'t>> {
+        self.find_at(text, 0)
+    }
+
+    /// Returns an iterator for each successive non-overlapping match in
+    /// `text`, returning the start and end byte indices with respect to
+    /// `text`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of every word with exactly 13 ASCII
+    /// word bytes:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"Retroactively relinquishing remunerations is reprehensible.";
+    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
+    ///     println!("{:?}", mat);
+    /// }
+    /// # }
+    /// ```
+    pub fn find_iter<'r, 't>(&'r self, text: &'t [u8]) -> Matches<'r, 't> {
+        Matches(self.0.searcher().find_iter(text))
+    }
+
+    /// Returns the capture groups corresponding to the leftmost-first
+    /// match in `text`. Capture group `0` always corresponds to the entire
+    /// match. If no match is found, then `None` is returned.
+    ///
+    /// You should only use `captures` if you need access to the location of
+    /// capturing group matches. Otherwise, `find` is faster for discovering
+    /// the location of the overall match.
+    ///
+    /// # Examples
+    ///
+    /// Say you have some text with movie names and their release years,
+    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
+    /// looking like that, while also extracting the movie name and its release
+    /// year separately.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
+    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(&caps[1], &b"Citizen Kane"[..]);
+    /// assert_eq!(&caps[2], &b"1941"[..]);
+    /// assert_eq!(&caps[0], &b"'Citizen Kane' (1941)"[..]);
+    /// // You can also access the groups by index using the Index notation.
+    /// // Note that this will panic on an invalid index.
+    /// assert_eq!(&caps[1], b"Citizen Kane");
+    /// assert_eq!(&caps[2], b"1941");
+    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
+    /// # }
+    /// ```
+    ///
+    /// Note that the full match is at capture group `0`. Each subsequent
+    /// capture group is indexed by the order of its opening `(`.
+    ///
+    /// We can make this example a bit clearer by using *named* capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(&caps["title"], &b"Citizen Kane"[..]);
+    /// assert_eq!(&caps["year"], &b"1941"[..]);
+    /// assert_eq!(&caps[0], &b"'Citizen Kane' (1941)"[..]);
+    /// // You can also access the groups by name using the Index notation.
+    /// // Note that this will panic on an invalid group name.
+    /// assert_eq!(&caps["title"], b"Citizen Kane");
+    /// assert_eq!(&caps["year"], b"1941");
+    /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
+    ///
+    /// # }
+    /// ```
+    ///
+    /// Here we name the capture groups, which we can access with the `name`
+    /// method or the `Index` notation with a `&str`. Note that the named
+    /// capture groups are still accessible with `get` or the `Index` notation
+    /// with a `usize`.
+    ///
+    /// The `0`th capture group is always unnamed, so it must always be
+    /// accessed with `at(0)` or `[0]`.
+    pub fn captures<'t>(&self, text: &'t [u8]) -> Option<Captures<'t>> {
+        let mut locs = self.locations();
+        self.read_captures_at(&mut locs, text, 0).map(|_| Captures {
+            text: text,
+            locs: locs,
+            named_groups: self.0.capture_name_idx().clone(),
+        })
+    }
+
+    /// Returns an iterator over all the non-overlapping capture groups matched
+    /// in `text`. This is operationally the same as `find_iter`, except it
+    /// yields information about capturing group matches.
+    ///
+    /// # Example
+    ///
+    /// We can use this to find all movie titles and their release years in
+    /// some text, where the movie is formatted like "'Title' (xxxx)":
+    ///
+    /// ```rust
+    /// # extern crate regex; use std::str; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = b"'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
+    /// for caps in re.captures_iter(text) {
+    ///     let title = str::from_utf8(&caps["title"]).unwrap();
+    ///     let year = str::from_utf8(&caps["year"]).unwrap();
+    ///     println!("Movie: {:?}, Released: {:?}", title, year);
+    /// }
+    /// // Output:
+    /// // Movie: Citizen Kane, Released: 1941
+    /// // Movie: The Wizard of Oz, Released: 1939
+    /// // Movie: M, Released: 1931
+    /// # }
+    /// ```
+    pub fn captures_iter<'r, 't>(
+        &'r self,
+        text: &'t [u8],
+    ) -> CaptureMatches<'r, 't> {
+        CaptureMatches(self.0.searcher().captures_iter(text))
+    }
+
+    /// Returns an iterator of substrings of `text` delimited by a match of the
+    /// regular expression. Namely, each element of the iterator corresponds to
+    /// text that *isn't* matched by the regular expression.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// To split a string delimited by arbitrary amounts of spaces or tabs:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"[ \t]+").unwrap();
+    /// let fields: Vec<&[u8]> = re.split(b"a b \t  c\td    e").collect();
+    /// assert_eq!(fields, vec![
+    ///     &b"a"[..], &b"b"[..], &b"c"[..], &b"d"[..], &b"e"[..],
+    /// ]);
+    /// # }
+    /// ```
+    pub fn split<'r, 't>(&'r self, text: &'t [u8]) -> Split<'r, 't> {
+        Split {
+            finder: self.find_iter(text),
+            last: 0,
+        }
+    }
+
+    /// Returns an iterator of at most `limit` substrings of `text` delimited
+    /// by a match of the regular expression. (A `limit` of `0` will return no
+    /// substrings.) Namely, each element of the iterator corresponds to text
+    /// that *isn't* matched by the regular expression. The remainder of the
+    /// string that is not split will be the last element in the iterator.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// Get the first two words in some text:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"\W+").unwrap();
+    /// let fields: Vec<&[u8]> = re.splitn(b"Hey! How are you?", 3).collect();
+    /// assert_eq!(fields, vec![&b"Hey"[..], &b"How"[..], &b"are you?"[..]]);
+    /// # }
+    /// ```
+    pub fn splitn<'r, 't>(
+        &'r self,
+        text: &'t [u8],
+        limit: usize,
+    ) -> SplitN<'r, 't> {
+        SplitN {
+            splits: self.split(text),
+            n: limit,
+        }
+    }
+
+    /// Replaces the leftmost-first match with the replacement provided. The
+    /// replacement can be a regular byte string (where `$N` and `$name` are
+    /// expanded to match capture groups) or a function that takes the matches'
+    /// `Captures` and returns the replaced byte string.
+    ///
+    /// If no match is found, then a copy of the byte string is returned
+    /// unchanged.
+    ///
+    /// # Replacement string syntax
+    ///
+    /// All instances of `$name` in the replacement text is replaced with the
+    /// corresponding capture group `name`.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    ///
+    /// # Examples
+    ///
+    /// Note that this function is polymorphic with respect to the replacement.
+    /// In typical usage, this can just be a normal byte string:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new("[^01]+").unwrap();
+    /// assert_eq!(re.replace(b"1078910", &b""[..]), &b"1010"[..]);
+    /// # }
+    /// ```
+    ///
+    /// But anything satisfying the `Replacer` trait will work. For example, a
+    /// closure of type `|&Captures| -> Vec<u8>` provides direct access to the
+    /// captures corresponding to a match. This allows one to access capturing
+    /// group matches easily:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # use regex::bytes::Captures; fn main() {
+    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", |caps: &Captures| {
+    ///     let mut replacement = caps[2].to_owned();
+    ///     replacement.push(b' ');
+    ///     replacement.extend(&caps[1]);
+    ///     replacement
+    /// });
+    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
+    /// # }
+    /// ```
+    ///
+    /// But this is a bit cumbersome to use all the time. Instead, a simple
+    /// syntax is supported that expands `$name` into the corresponding capture
+    /// group. Here's the last example, but using this expansion technique
+    /// with named capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", &b"$first $last"[..]);
+    /// assert_eq!(result, &b"Bruce Springsteen"[..]);
+    /// # }
+    /// ```
+    ///
+    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
+    /// would produce the same result. To write a literal `$` use `$$`.
+    ///
+    /// Sometimes the replacement string requires use of curly braces to
+    /// delineate a capture group replacement and surrounding literal text.
+    /// For example, if we wanted to join two words together with an
+    /// underscore:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
+    /// let result = re.replace(b"deep fried", &b"${first}_$second"[..]);
+    /// assert_eq!(result, &b"deep_fried"[..]);
+    /// # }
+    /// ```
+    ///
+    /// Without the curly braces, the capture group name `first_` would be
+    /// used, and since it doesn't exist, it would be replaced with the empty
+    /// string.
+    ///
+    /// Finally, sometimes you just want to replace a literal string with no
+    /// regard for capturing group expansion. This can be done by wrapping a
+    /// byte string with `NoExpand`:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// use regex::bytes::NoExpand;
+    ///
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace(b"Springsteen, Bruce", NoExpand(b"$2 $last"));
+    /// assert_eq!(result, &b"$2 $last"[..]);
+    /// # }
+    /// ```
+    pub fn replace<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        rep: R,
+    ) -> Cow<'t, [u8]> {
+        self.replacen(text, 1, rep)
+    }
+
+    /// Replaces all non-overlapping matches in `text` with the replacement
+    /// provided. This is the same as calling `replacen` with `limit` set to
+    /// `0`.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement text.
+    pub fn replace_all<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        rep: R,
+    ) -> Cow<'t, [u8]> {
+        self.replacen(text, 0, rep)
+    }
+
+    /// Replaces at most `limit` non-overlapping matches in `text` with the
+    /// replacement provided. If `limit` is 0, then all non-overlapping matches
+    /// are replaced.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement text.
+    pub fn replacen<'t, R: Replacer>(
+        &self,
+        text: &'t [u8],
+        limit: usize,
+        mut rep: R,
+    ) -> Cow<'t, [u8]> {
+        if let Some(rep) = rep.no_expansion() {
+            let mut new = Vec::with_capacity(text.len());
+            let mut last_match = 0;
+            for (i, m) in self.find_iter(text).enumerate() {
+                if limit > 0 && i >= limit {
+                    break
+                }
+                new.extend_from_slice(&text[last_match..m.start()]);
+                new.extend_from_slice(&rep);
+                last_match = m.end();
+            }
+            if last_match == 0 {
+                return Cow::Borrowed(text);
+            }
+            new.extend_from_slice(&text[last_match..]);
+            return Cow::Owned(new);
+        }
+
+        // The slower path, which we use if the replacement needs access to
+        // capture groups.
+        let mut it = self.captures_iter(text).enumerate().peekable();
+        if it.peek().is_none() {
+            return Cow::Borrowed(text);
+        }
+        let mut new = Vec::with_capacity(text.len());
+        let mut last_match = 0;
+        for (i, cap) in it {
+            if limit > 0 && i >= limit {
+                break
+            }
+            // unwrap on 0 is OK because captures only reports matches
+            let m = cap.get(0).unwrap();
+            new.extend_from_slice(&text[last_match..m.start()]);
+            rep.replace_append(&cap, &mut new);
+            last_match = m.end();
+        }
+        new.extend_from_slice(&text[last_match..]);
+        Cow::Owned(new)
+    }
+}
+
+/// Advanced or "lower level" search methods.
+impl Regex {
+    /// Returns the end location of a match in the text given.
+    ///
+    /// This method may have the same performance characteristics as
+    /// `is_match`, except it provides an end location for a match. In
+    /// particular, the location returned *may be shorter* than the proper end
+    /// of the leftmost-first match.
+    ///
+    /// # Example
+    ///
+    /// Typically, `a+` would match the entire first sequence of `a` in some
+    /// text, but `shortest_match` can give up as soon as it sees the first
+    /// `a`.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::bytes::Regex;
+    /// # fn main() {
+    /// let text = b"aaaaa";
+    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
+    /// assert_eq!(pos, Some(1));
+    /// # }
+    /// ```
+    pub fn shortest_match(&self, text: &[u8]) -> Option<usize> {
+        self.shortest_match_at(text, 0)
+    }
+
+    /// Returns the same as shortest_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn shortest_match_at(
+        &self,
+        text: &[u8],
+        start: usize,
+    ) -> Option<usize> {
+        self.0.searcher().shortest_match_at(text, start)
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn is_match_at(&self, text: &[u8], start: usize) -> bool {
+        self.shortest_match_at(text, start).is_some()
+    }
+
+    /// Returns the same as find, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn find_at<'t>(
+        &self,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0.searcher().find_at(text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// Returns the same as captures, but starts the search at the given
+    /// offset and populates the capture locations given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn read_captures_at<'t>(
+        &self,
+        locs: &mut Locations,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0.searcher().read_captures_at(locs, text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+}
+
+/// Auxiliary methods.
+impl Regex {
+    /// Returns the original string of this regex.
+    pub fn as_str(&self) -> &str {
+        &self.0.regex_strings()[0]
+    }
+
+    /// Returns an iterator over the capture names.
+    pub fn capture_names(&self) -> CaptureNames {
+        CaptureNames(self.0.capture_names().iter())
+    }
+
+    /// Returns the number of captures.
+    pub fn captures_len(&self) -> usize {
+        self.0.capture_names().len()
+    }
+
+    /// Returns an empty set of locations that can be reused in multiple calls
+    /// to `read_captures`.
+    #[doc(hidden)]
+    pub fn locations(&self) -> Locations {
+        self.0.searcher().locations()
+    }
+}
+
+/// An iterator over all non-overlapping matches for a particular string.
+///
+/// The iterator yields a tuple of integers corresponding to the start and end
+/// of the match. The indices are byte offsets. The iterator stops when no more
+/// matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched byte string.
+pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSync<'r>>);
+
+impl<'r, 't> Iterator for Matches<'r, 't> {
+    type Item = Match<'t>;
+
+    fn next(&mut self) -> Option<Match<'t>> {
+        let text = self.0.text();
+        self.0.next().map(|(s, e)| Match::new(text, s, e))
+    }
+}
+
+/// An iterator that yields all non-overlapping capture groups matching a
+/// particular regular expression.
+///
+/// The iterator stops when no more matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched byte string.
+pub struct CaptureMatches<'r, 't>(re_trait::CaptureMatches<'t, ExecNoSync<'r>>);
+
+impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
+    type Item = Captures<'t>;
+
+    fn next(&mut self) -> Option<Captures<'t>> {
+        self.0.next().map(|locs| Captures {
+            text: self.0.text(),
+            locs: locs,
+            named_groups: self.0.regex().capture_name_idx().clone(),
+        })
+    }
+}
+
+/// Yields all substrings delimited by a regular expression match.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the byte string being split.
+pub struct Split<'r, 't> {
+    finder: Matches<'r, 't>,
+    last: usize,
+}
+
+impl<'r, 't> Iterator for Split<'r, 't> {
+    type Item = &'t [u8];
+
+    fn next(&mut self) -> Option<&'t [u8]> {
+        let text = self.finder.0.text();
+        match self.finder.next() {
+            None => {
+                if self.last >= text.len() {
+                    None
+                } else {
+                    let s = &text[self.last..];
+                    self.last = text.len();
+                    Some(s)
+                }
+            }
+            Some(m) => {
+                let matched = &text[self.last..m.start()];
+                self.last = m.end();
+                Some(matched)
+            }
+        }
+    }
+}
+
+/// Yields at most `N` substrings delimited by a regular expression match.
+///
+/// The last substring will be whatever remains after splitting.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the byte string being split.
+pub struct SplitN<'r, 't> {
+    splits: Split<'r, 't>,
+    n: usize,
+}
+
+impl<'r, 't> Iterator for SplitN<'r, 't> {
+    type Item = &'t [u8];
+
+    fn next(&mut self) -> Option<&'t [u8]> {
+        if self.n == 0 {
+            return None
+        }
+        self.n -= 1;
+        if self.n == 0 {
+            let text = self.splits.finder.0.text();
+            Some(&text[self.splits.last..])
+        } else {
+            self.splits.next()
+        }
+    }
+}
+
+/// An iterator over the names of all possible captures.
+///
+/// `None` indicates an unnamed capture; the first element (capture 0, the
+/// whole matched region) is always unnamed.
+///
+/// `'r` is the lifetime of the compiled regular expression.
+pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
+
+impl<'r> Iterator for CaptureNames<'r> {
+    type Item = Option<&'r str>;
+
+    fn next(&mut self) -> Option<Option<&'r str>> {
+        self.0.next().as_ref()
+            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+/// Captures represents a group of captured byte strings for a single match.
+///
+/// The 0th capture always corresponds to the entire match. Each subsequent
+/// index corresponds to the next capture group in the regex. If a capture
+/// group is named, then the matched byte string is *also* available via the
+/// `name` method. (Note that the 0th capture is always unnamed and so must be
+/// accessed with the `get` method.)
+///
+/// Positions returned from a capture group are always byte indices.
+///
+/// `'t` is the lifetime of the matched text.
+pub struct Captures<'t> {
+    text: &'t [u8],
+    locs: Locations,
+    named_groups: Arc<HashMap<String, usize>>,
+}
+
+impl<'t> Captures<'t> {
+    /// Returns the match associated with the capture group at index `i`. If
+    /// `i` does not correspond to a capture group, or if the capture group
+    /// did not participate in the match, then `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// Get the text of the match with a default of an empty string if this
+    /// group didn't participate in the match:
+    ///
+    /// ```rust
+    /// # use regex::bytes::Regex;
+    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
+    /// let caps = re.captures(b"abc123").unwrap();
+    ///
+    /// let text1 = caps.get(1).map_or(&b""[..], |m| m.as_bytes());
+    /// let text2 = caps.get(2).map_or(&b""[..], |m| m.as_bytes());
+    /// assert_eq!(text1, &b"123"[..]);
+    /// assert_eq!(text2, &b""[..]);
+    /// ```
+    pub fn get(&self, i: usize) -> Option<Match<'t>> {
+        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
+    }
+
+    /// Returns the match for the capture group named `name`. If `name` isn't a
+    /// valid capture group or didn't match anything, then `None` is returned.
+    pub fn name(&self, name: &str) -> Option<Match<'t>> {
+        self.named_groups.get(name).and_then(|&i| self.get(i))
+    }
+
+    /// An iterator that yields all capturing matches in the order in which
+    /// they appear in the regex. If a particular capture group didn't
+    /// participate in the match, then `None` is yielded for that capture.
+    ///
+    /// The first match always corresponds to the overall match of the regex.
+    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
+        SubCaptureMatches {
+            caps: self,
+            it: self.locs.iter(),
+        }
+    }
+
+    /// Expands all instances of `$name` in `text` to the corresponding capture
+    /// group `name`, and writes them to the `dst` buffer given.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    pub fn expand(&self, replacement: &[u8], dst: &mut Vec<u8>) {
+        expand_bytes(self, replacement, dst)
+    }
+
+    /// Returns the number of captured groups.
+    ///
+    /// This is always at least `1`, since every regex has at least one capture
+    /// group that corresponds to the full match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.locs.len()
+    }
+}
+
+impl<'t> fmt::Debug for Captures<'t> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
+    }
+}
+
+struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
+
+impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn escape_bytes(bytes: &[u8]) -> String {
+            let mut s = String::new();
+            for &b in bytes {
+                s.push_str(&escape_byte(b));
+            }
+            s
+        }
+
+        fn escape_byte(byte: u8) -> String {
+            use std::ascii::escape_default;
+
+            let escaped: Vec<u8> = escape_default(byte).collect();
+            String::from_utf8_lossy(&escaped).into_owned()
+        }
+
+        // We'd like to show something nice here, even if it means an
+        // allocation to build a reverse index.
+        let slot_to_name: HashMap<&usize, &String> =
+            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
+        let mut map = f.debug_map();
+        for (slot, m) in self.0.locs.iter().enumerate() {
+            let m = m.map(|(s, e)| escape_bytes(&self.0.text[s..e]));
+            if let Some(ref name) = slot_to_name.get(&slot) {
+                map.entry(&name, &m);
+            } else {
+                map.entry(&slot, &m);
+            }
+        }
+        map.finish()
+    }
+}
+
+/// Get a group by index.
+///
+/// `'t` is the lifetime of the matched text.
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `get()` instead.
+///
+/// # Panics
+///
+/// If there is no group at the given index.
+impl<'t> Index<usize> for Captures<'t> {
+    type Output = [u8];
+
+    fn index(&self, i: usize) -> &[u8] {
+        self.get(i).map(|m| m.as_bytes())
+            .unwrap_or_else(|| panic!("no group at index '{}'", i))
+    }
+}
+
+/// Get a group by name.
+///
+/// `'t` is the lifetime of the matched text and `'i` is the lifetime
+/// of the group name (the index).
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `name` instead.
+///
+/// # Panics
+///
+/// If there is no group named by the given value.
+impl<'t, 'i> Index<&'i str> for Captures<'t> {
+    type Output = [u8];
+
+    fn index<'a>(&'a self, name: &'i str) -> &'a [u8] {
+        self.name(name).map(|m| m.as_bytes())
+            .unwrap_or_else(|| panic!("no group named '{}'", name))
+    }
+}
+
+/// An iterator that yields all capturing matches in the order in which they
+/// appear in the regex.
+///
+/// If a particular capture group didn't participate in the match, then `None`
+/// is yielded for that capture. The first match always corresponds to the
+/// overall match of the regex.
+///
+/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
+/// the lifetime `'t` corresponds to the originally matched text.
+pub struct SubCaptureMatches<'c, 't: 'c> {
+    caps: &'c Captures<'t>,
+    it: SubCapturesPosIter<'c>,
+}
+
+impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
+    type Item = Option<Match<'t>>;
+
+    fn next(&mut self) -> Option<Option<Match<'t>>> {
+        self.it.next()
+            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
+    }
+}
+
+/// Replacer describes types that can be used to replace matches in a byte
+/// string.
+///
+/// In general, users of this crate shouldn't need to implement this trait,
+/// since implementations are already provided for `&[u8]` and
+/// `FnMut(&Captures) -> Vec<u8>`, which covers most use cases.
+pub trait Replacer {
+    /// Appends text to `dst` to replace the current match.
+    ///
+    /// The current match is represented by `caps`, which is guaranteed to
+    /// have a match at capture group `0`.
+    ///
+    /// For example, a no-op replacement would be
+    /// `dst.extend(&caps[0])`.
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>);
+
+    /// Return a fixed unchanging replacement byte string.
+    ///
+    /// When doing replacements, if access to `Captures` is not needed (e.g.,
+    /// the replacement byte string does not need `$` expansion), then it can
+    /// be beneficial to avoid finding sub-captures.
+    ///
+    /// In general, this is called once for every call to `replacen`.
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        None
+    }
+}
+
+impl<'a> Replacer for &'a [u8] {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        match memchr(b'$', *self) {
+            Some(_) => None,
+            None => Some(Cow::Borrowed(*self)),
+        }
+    }
+}
+
+impl<F> Replacer for F where F: FnMut(&Captures) -> Vec<u8> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        dst.extend_from_slice(&(*self)(caps));
+    }
+}
+
+/// NoExpand indicates literal byte string replacement.
+///
+/// It can be used with `replace` and `replace_all` to do a literal byte string
+/// replacement without expanding `$name` to their corresponding capture
+/// groups. This can be both convenient (to avoid escaping `$`, for example)
+/// and performant (since capture groups don't need to be found).
+///
+/// `'t` is the lifetime of the literal text.
+pub struct NoExpand<'t>(pub &'t [u8]);
+
+impl<'t> Replacer for NoExpand<'t> {
+    fn replace_append(&mut self, _: &Captures, dst: &mut Vec<u8>) {
+        dst.extend_from_slice(self.0);
+    }
+
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        Some(Cow::Borrowed(self.0))
+    }
+}
diff --git a/third_party/rust/regex/src/re_plugin.rs b/third_party/rust/regex-0.2.2/src/re_plugin.rs
similarity index 100%
rename from third_party/rust/regex/src/re_plugin.rs
rename to third_party/rust/regex-0.2.2/src/re_plugin.rs
diff --git a/third_party/rust/regex-0.2.2/src/re_set.rs b/third_party/rust/regex-0.2.2/src/re_set.rs
new file mode 100644
index 000000000000..89a7a8082806
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/re_set.rs
@@ -0,0 +1,411 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! define_set {
+    ($name:ident, $builder_mod:ident, $text_ty:ty, $as_bytes:expr,
+     $(#[$doc_regexset_example:meta])* ) => {
+        pub mod $name {
+            use std::fmt;
+            use std::iter;
+            use std::slice;
+            use std::vec;
+
+            use error::Error;
+            use exec::Exec;
+            use re_builder::$builder_mod::RegexSetBuilder;
+            use re_trait::RegularExpression;
+
+/// Match multiple (possibly overlapping) regular expressions in a single scan.
+///
+/// A regex set corresponds to the union of two or more regular expressions.
+/// That is, a regex set will match text where at least one of its
+/// constituent regular expressions matches. A regex set as its formulated here
+/// provides a touch more power: it will also report *which* regular
+/// expressions in the set match. Indeed, this is the key difference between
+/// regex sets and a single `Regex` with many alternates, since only one
+/// alternate can match at a time.
+///
+/// For example, consider regular expressions to match email addresses and
+/// domains: `[a-z]+@[a-z]+\.(com|org|net)` and `[a-z]+\.(com|org|net)`. If a
+/// regex set is constructed from those regexes, then searching the text
+/// `foo@example.com` will report both regexes as matching. Of course, one
+/// could accomplish this by compiling each regex on its own and doing two
+/// searches over the text. The key advantage of using a regex set is that it
+/// will report the matching regexes using a *single pass through the text*.
+/// If one has hundreds or thousands of regexes to match repeatedly (like a URL
+/// router for a complex web application or a user agent matcher), then a regex
+/// set can realize huge performance gains.
+///
+/// # Example
+///
+/// This shows how the above two regexes (for matching email addresses and
+/// domains) might work:
+///
+$(#[$doc_regexset_example])*
+///
+/// Note that it would be possible to adapt the above example to using `Regex`
+/// with an expression like:
+///
+/// ```ignore
+/// (?P<email>[a-z]+@(?P<email_domain>[a-z]+[.](com|org|net)))|(?P<domain>[a-z]+[.](com|org|net))
+/// ```
+///
+/// After a match, one could then inspect the capture groups to figure out
+/// which alternates matched. The problem is that it is hard to make this
+/// approach scale when there are many regexes since the overlap between each
+/// alternate isn't always obvious to reason about.
+///
+/// # Limitations
+///
+/// Regex sets are limited to answering the following two questions:
+///
+/// 1. Does any regex in the set match?
+/// 2. If so, which regexes in the set match?
+///
+/// As with the main `Regex` type, it is cheaper to ask (1) instead of (2)
+/// since the matching engines can stop after the first match is found.
+///
+/// Other features like finding the location of successive matches or their
+/// sub-captures aren't supported. If you need this functionality, the
+/// recommended approach is to compile each regex in the set independently and
+/// selectively match them based on which regexes in the set matched.
+///
+/// # Performance
+///
+/// A `RegexSet` has the same performance characteristics as `Regex`. Namely,
+/// search takes `O(mn)` time, where `m` is proportional to the size of the
+/// regex set and `n` is proportional to the length of the search text.
+#[derive(Clone)]
+pub struct RegexSet(Exec);
+
+impl RegexSet {
+    /// Create a new regex set with the given regular expressions.
+    ///
+    /// This takes an iterator of `S`, where `S` is something that can produce
+    /// a `&str`. If any of the strings in the iterator are not valid regular
+    /// expressions, then an error is returned.
+    ///
+    /// # Example
+    ///
+    /// Create a new regex set from an iterator of strings:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
+    /// assert!(set.is_match("foo"));
+    /// ```
+    pub fn new<I, S>(exprs: I) -> Result<RegexSet, Error>
+            where S: AsRef<str>, I: IntoIterator<Item=S> {
+        RegexSetBuilder::new(exprs).build()
+    }
+
+    /// Returns true if and only if one of the regexes in this set matches
+    /// the text given.
+    ///
+    /// This method should be preferred if you only need to test whether any
+    /// of the regexes in the set should match, but don't care about *which*
+    /// regexes matched. This is because the underlying matching engine will
+    /// quit immediately after seeing the first match instead of continuing to
+    /// find all matches.
+    ///
+    /// Note that as with searches using `Regex`, the expression is unanchored
+    /// by default. That is, if the regex does not start with `^` or `\A`, or
+    /// end with `$` or `\z`, then it is permitted to match anywhere in the
+    /// text.
+    ///
+    /// # Example
+    ///
+    /// Tests whether a set matches some text:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
+    /// assert!(set.is_match("foo"));
+    /// assert!(!set.is_match("☃"));
+    /// ```
+    pub fn is_match(&self, text: $text_ty) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn is_match_at(&self, text: $text_ty, start: usize) -> bool {
+        self.0.searcher().is_match_at($as_bytes(text), start)
+    }
+
+    /// Returns the set of regular expressions that match in the given text.
+    ///
+    /// The set returned contains the index of each regular expression that
+    /// matches in the given text. The index is in correspondence with the
+    /// order of regular expressions given to `RegexSet`'s constructor.
+    ///
+    /// The set can also be used to iterate over the matched indices.
+    ///
+    /// Note that as with searches using `Regex`, the expression is unanchored
+    /// by default. That is, if the regex does not start with `^` or `\A`, or
+    /// end with `$` or `\z`, then it is permitted to match anywhere in the
+    /// text.
+    ///
+    /// # Example
+    ///
+    /// Tests which regular expressions match the given text:
+    ///
+    /// ```rust
+    /// # use regex::RegexSet;
+    /// let set = RegexSet::new(&[
+    ///     r"\w+",
+    ///     r"\d+",
+    ///     r"\pL+",
+    ///     r"foo",
+    ///     r"bar",
+    ///     r"barfoo",
+    ///     r"foobar",
+    /// ]).unwrap();
+    /// let matches: Vec<_> = set.matches("foobar").into_iter().collect();
+    /// assert_eq!(matches, vec![0, 2, 3, 4, 6]);
+    ///
+    /// // You can also test whether a particular regex matched:
+    /// let matches = set.matches("foobar");
+    /// assert!(!matches.matched(5));
+    /// assert!(matches.matched(6));
+    /// ```
+    pub fn matches(&self, text: $text_ty) -> SetMatches {
+        let mut matches = vec![false; self.0.regex_strings().len()];
+        let any = self.read_matches_at(&mut matches, text, 0);
+        SetMatches {
+            matched_any: any,
+            matches: matches,
+        }
+    }
+
+    /// Returns the same as matches, but starts the search at the given
+    /// offset and stores the matches into the slice given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    ///
+    /// `matches` must have a length that is at least the number of regexes
+    /// in this set.
+    ///
+    /// This method returns true if and only if at least one member of
+    /// `matches` is true after executing the set against `text`.
+    #[doc(hidden)]
+    pub fn read_matches_at(
+        &self,
+        matches: &mut [bool],
+        text: $text_ty,
+        start: usize,
+    ) -> bool {
+        self.0.searcher().many_matches_at(matches, $as_bytes(text), start)
+    }
+
+    /// Returns the total number of regular expressions in this set.
+    pub fn len(&self) -> usize {
+        self.0.regex_strings().len()
+    }
+}
+
+/// A set of matches returned by a regex set.
+#[derive(Clone, Debug)]
+pub struct SetMatches {
+    matched_any: bool,
+    matches: Vec<bool>,
+}
+
+impl SetMatches {
+    /// Whether this set contains any matches.
+    pub fn matched_any(&self) -> bool {
+        self.matched_any
+    }
+
+    /// Whether the regex at the given index matched.
+    ///
+    /// The index for a regex is determined by its insertion order upon the
+    /// initial construction of a `RegexSet`, starting at `0`.
+    ///
+    /// # Panics
+    ///
+    /// If `regex_index` is greater than or equal to `self.len()`.
+    pub fn matched(&self, regex_index: usize) -> bool {
+        self.matches[regex_index]
+    }
+
+    /// The total number of regexes in the set that created these matches.
+    pub fn len(&self) -> usize {
+        self.matches.len()
+    }
+
+    /// Returns an iterator over indexes in the regex that matched.
+    pub fn iter(&self) -> SetMatchesIter {
+        SetMatchesIter((&*self.matches).into_iter().enumerate())
+    }
+}
+
+impl IntoIterator for SetMatches {
+    type IntoIter = SetMatchesIntoIter;
+    type Item = usize;
+
+    fn into_iter(self) -> Self::IntoIter {
+        SetMatchesIntoIter(self.matches.into_iter().enumerate())
+    }
+}
+
+impl<'a> IntoIterator for &'a SetMatches {
+    type IntoIter = SetMatchesIter<'a>;
+    type Item = usize;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+/// An owned iterator over the set of matches from a regex set.
+pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);
+
+impl Iterator for SetMatchesIntoIter {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next() {
+                None => return None,
+                Some((_, false)) => {}
+                Some((i, true)) => return Some(i),
+            }
+        }
+    }
+}
+
+impl DoubleEndedIterator for SetMatchesIntoIter {
+    fn next_back(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next_back() {
+                None => return None,
+                Some((_, false)) => {}
+                Some((i, true)) => return Some(i),
+            }
+        }
+    }
+}
+
+/// A borrowed iterator over the set of matches from a regex set.
+///
+/// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
+#[derive(Clone)]
+pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);
+
+impl<'a> Iterator for SetMatchesIter<'a> {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next() {
+                None => return None,
+                Some((_, &false)) => {}
+                Some((i, &true)) => return Some(i),
+            }
+        }
+    }
+}
+
+impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
+    fn next_back(&mut self) -> Option<usize> {
+        loop {
+            match self.0.next_back() {
+                None => return None,
+                Some((_, &false)) => {}
+                Some((i, &true)) => return Some(i),
+            }
+        }
+    }
+}
+
+#[doc(hidden)]
+impl From<Exec> for RegexSet {
+    fn from(exec: Exec) -> Self {
+        RegexSet(exec)
+    }
+}
+
+impl fmt::Debug for RegexSet {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "RegexSet({:?})", self.0.regex_strings())
+    }
+}
+
+#[allow(dead_code)] fn as_bytes_str(text: &str) -> &[u8] { text.as_bytes() }
+#[allow(dead_code)] fn as_bytes_bytes(text: &[u8]) -> &[u8] { text }
+        }
+    }
+}
+
+define_set! {
+    unicode,
+    set_unicode,
+    &str,
+    as_bytes_str,
+/// ```rust
+/// # use regex::RegexSet;
+/// let set = RegexSet::new(&[
+///     r"[a-z]+@[a-z]+\.(com|org|net)",
+///     r"[a-z]+\.(com|org|net)",
+/// ]).unwrap();
+///
+/// // Ask whether any regexes in the set match.
+/// assert!(set.is_match("foo@example.com"));
+///
+/// // Identify which regexes in the set match.
+/// let matches: Vec<_> = set.matches("foo@example.com").into_iter().collect();
+/// assert_eq!(vec![0, 1], matches);
+///
+/// // Try again, but with text that only matches one of the regexes.
+/// let matches: Vec<_> = set.matches("example.com").into_iter().collect();
+/// assert_eq!(vec![1], matches);
+///
+/// // Try again, but with text that doesn't match any regex in the set.
+/// let matches: Vec<_> = set.matches("example").into_iter().collect();
+/// assert!(matches.is_empty());
+/// ```
+}
+
+define_set! {
+    bytes,
+    set_bytes,
+    &[u8],
+    as_bytes_bytes,
+/// ```rust
+/// # use regex::bytes::RegexSet;
+/// let set = RegexSet::new(&[
+///     r"[a-z]+@[a-z]+\.(com|org|net)",
+///     r"[a-z]+\.(com|org|net)",
+/// ]).unwrap();
+///
+/// // Ask whether any regexes in the set match.
+/// assert!(set.is_match(b"foo@example.com"));
+///
+/// // Identify which regexes in the set match.
+/// let matches: Vec<_> = set.matches(b"foo@example.com").into_iter().collect();
+/// assert_eq!(vec![0, 1], matches);
+///
+/// // Try again, but with text that only matches one of the regexes.
+/// let matches: Vec<_> = set.matches(b"example.com").into_iter().collect();
+/// assert_eq!(vec![1], matches);
+///
+/// // Try again, but with text that doesn't match any regex in the set.
+/// let matches: Vec<_> = set.matches(b"example").into_iter().collect();
+/// assert!(matches.is_empty());
+/// ```
+}
diff --git a/third_party/rust/regex-0.2.2/src/re_trait.rs b/third_party/rust/regex-0.2.2/src/re_trait.rs
new file mode 100644
index 000000000000..9f3407c98b08
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/re_trait.rs
@@ -0,0 +1,268 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Slot is a single saved capture location. Note that there are two slots for
+/// every capture in a regular expression (one slot each for the start and end
+/// of the capture).
+pub type Slot = Option<usize>;
+
+/// Locations represents the offsets of each capturing group in a regex for
+/// a single match.
+///
+/// Unlike `Captures`, a `Locations` value only stores offsets.
+#[doc(hidden)]
+pub struct Locations(Vec<Slot>);
+
+impl Locations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        let (s, e) = (i * 2, i * 2 + 1);
+        match (self.0.get(s), self.0.get(e)) {
+            (Some(&Some(s)), Some(&Some(e))) => Some((s, e)),
+            _ => None,
+        }
+    }
+
+    /// Creates an iterator of all the capture group positions in order of
+    /// appearance in the regular expression. Positions are byte indices
+    /// in terms of the original string matched.
+    pub fn iter(&self) -> SubCapturesPosIter {
+        SubCapturesPosIter { idx: 0, locs: &self }
+    }
+
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    pub fn len(&self) -> usize {
+        self.0.len() / 2
+    }
+}
+
+/// This is a hack to make Locations -> &mut [Slot] be available internally
+/// without exposing it in the public API.
+pub fn as_slots(locs: &mut Locations) -> &mut [Slot] {
+    &mut locs.0
+}
+
+/// An iterator over capture group positions for a particular match of a
+/// regular expression.
+///
+/// Positions are byte indices in terms of the original string matched.
+///
+/// `'c` is the lifetime of the captures.
+pub struct SubCapturesPosIter<'c> {
+    idx: usize,
+    locs: &'c Locations,
+}
+
+impl<'c> Iterator for SubCapturesPosIter<'c> {
+    type Item = Option<(usize, usize)>;
+
+    fn next(&mut self) -> Option<Option<(usize, usize)>> {
+        if self.idx >= self.locs.len() {
+            return None;
+        }
+        let x = match self.locs.pos(self.idx) {
+            None => Some(None),
+            Some((s, e)) => {
+                Some(Some((s, e)))
+            }
+        };
+        self.idx += 1;
+        x
+    }
+}
+
+/// RegularExpression describes types that can implement regex searching.
+///
+/// This trait is my attempt at reducing code duplication and to standardize
+/// the internal API. Specific duplication that is avoided are the `find`
+/// and `capture` iterators, which are slightly tricky.
+///
+/// It's not clear whether this trait is worth it, and it also isn't
+/// clear whether it's useful as a public trait or not. Methods like
+/// `next_after_empty` reak of bad design, but the rest of the methods seem
+/// somewhat reasonable. One particular thing this trait would expose would be
+/// the ability to start the search of a regex anywhere in a haystack, which
+/// isn't possible in the current public API.
+pub trait RegularExpression: Sized {
+    /// The type of the haystack.
+    type Text: ?Sized;
+
+    /// The number of capture slots in the compiled regular expression. This is
+    /// always two times the number of capture groups (two slots per group).
+    fn slots_len(&self) -> usize;
+
+    /// Allocates fresh space for all capturing groups in this regex.
+    fn locations(&self) -> Locations {
+        Locations(vec![None; self.slots_len()])
+    }
+
+    /// Returns the position of the next character after `i`.
+    ///
+    /// For example, a haystack with type `&[u8]` probably returns `i+1`,
+    /// whereas a haystack with type `&str` probably returns `i` plus the
+    /// length of the next UTF-8 sequence.
+    fn next_after_empty(&self, text: &Self::Text, i: usize) -> usize;
+
+    /// Returns the location of the shortest match.
+    fn shortest_match_at(
+        &self,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<usize>;
+
+    /// Returns whether the regex matches the text given.
+    fn is_match_at(
+        &self,
+        text: &Self::Text,
+        start: usize,
+    ) -> bool;
+
+    /// Returns the leftmost-first match location if one exists.
+    fn find_at(
+        &self,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<(usize, usize)>;
+
+    /// Returns the leftmost-first match location if one exists, and also
+    /// fills in any matching capture slot locations.
+    fn read_captures_at(
+        &self,
+        locs: &mut Locations,
+        text: &Self::Text,
+        start: usize,
+    ) -> Option<(usize, usize)>;
+
+    /// Returns an iterator over all non-overlapping successive leftmost-first
+    /// matches.
+    fn find_iter<'t>(
+        self,
+        text: &'t Self::Text,
+    ) -> Matches<'t, Self> {
+        Matches {
+            re: self,
+            text: text,
+            last_end: 0,
+            last_match: None,
+        }
+    }
+
+    /// Returns an iterator over all non-overlapping successive leftmost-first
+    /// matches with captures.
+    fn captures_iter<'t>(
+        self,
+        text: &'t Self::Text,
+    ) -> CaptureMatches<'t, Self> {
+        CaptureMatches(self.find_iter(text))
+    }
+}
+
+/// An iterator over all non-overlapping successive leftmost-first matches.
+pub struct Matches<'t, R> where R: RegularExpression, R::Text: 't {
+    re: R,
+    text: &'t R::Text,
+    last_end: usize,
+    last_match: Option<usize>,
+}
+
+impl<'t, R> Matches<'t, R> where R: RegularExpression, R::Text: 't {
+    /// Return the text being searched.
+    pub fn text(&self) -> &'t R::Text {
+        self.text
+    }
+
+    /// Return the underlying regex.
+    pub fn regex(&self) -> &R {
+        &self.re
+    }
+}
+
+impl<'t, R> Iterator for Matches<'t, R>
+        where R: RegularExpression, R::Text: 't + AsRef<[u8]> {
+    type Item = (usize, usize);
+
+    fn next(&mut self) -> Option<(usize, usize)> {
+        if self.last_end > self.text.as_ref().len() {
+            return None;
+        }
+        let (s, e) = match self.re.find_at(self.text, self.last_end) {
+            None => return None,
+            Some((s, e)) => (s, e),
+        };
+        if s == e {
+            // This is an empty match. To ensure we make progress, start
+            // the next search at the smallest possible starting position
+            // of the next match following this one.
+            self.last_end = self.re.next_after_empty(&self.text, e);
+            // Don't accept empty matches immediately following a match.
+            // Just move on to the next match.
+            if Some(e) == self.last_match {
+                return self.next();
+            }
+        } else {
+            self.last_end = e;
+        }
+        self.last_match = Some(e);
+        Some((s, e))
+    }
+}
+
+/// An iterator over all non-overlapping successive leftmost-first matches with
+/// captures.
+pub struct CaptureMatches<'t, R>(Matches<'t, R>)
+    where R: RegularExpression, R::Text: 't;
+
+impl<'t, R> CaptureMatches<'t, R> where R: RegularExpression, R::Text: 't {
+    /// Return the text being searched.
+    pub fn text(&self) -> &'t R::Text {
+        self.0.text()
+    }
+
+    /// Return the underlying regex.
+    pub fn regex(&self) -> &R {
+        self.0.regex()
+    }
+}
+
+impl<'t, R> Iterator for CaptureMatches<'t, R>
+        where R: RegularExpression, R::Text: 't + AsRef<[u8]> {
+    type Item = Locations;
+
+    fn next(&mut self) -> Option<Locations> {
+        if self.0.last_end > self.0.text.as_ref().len() {
+            return None
+        }
+        let mut locs = self.0.re.locations();
+        let (s, e) = match self.0.re.read_captures_at(
+            &mut locs,
+            self.0.text,
+            self.0.last_end,
+        ) {
+            None => return None,
+            Some((s, e)) => (s, e),
+        };
+        if s == e {
+            self.0.last_end = self.0.re.next_after_empty(&self.0.text, e);
+            if Some(e) == self.0.last_match {
+                return self.next();
+            }
+        } else {
+            self.0.last_end = e;
+        }
+        self.0.last_match = Some(e);
+        Some(locs)
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/src/re_unicode.rs b/third_party/rust/regex-0.2.2/src/re_unicode.rs
new file mode 100644
index 000000000000..d90be4fb1c9f
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/re_unicode.rs
@@ -0,0 +1,1237 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::fmt;
+use std::ops::Index;
+use std::str::FromStr;
+use std::sync::Arc;
+
+use memchr::memchr;
+use syntax;
+
+use error::Error;
+use exec::{Exec, ExecNoSyncStr};
+use expand::expand_str;
+use re_builder::unicode::RegexBuilder;
+use re_plugin::Plugin;
+use re_trait::{self, RegularExpression, Locations, SubCapturesPosIter};
+
+/// Escapes all regular expression meta characters in `text`.
+///
+/// The string returned may be safely used as a literal in a regular
+/// expression.
+pub fn escape(text: &str) -> String {
+    syntax::escape(text)
+}
+
+/// Match represents a single match of a regex in a haystack.
+///
+/// The lifetime parameter `'t` refers to the lifetime of the matched text.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Match<'t> {
+    text: &'t str,
+    start: usize,
+    end: usize,
+}
+
+impl<'t> Match<'t> {
+    /// Returns the starting byte offset of the match in the haystack.
+    #[inline]
+    pub fn start(&self) -> usize {
+        self.start
+    }
+
+    /// Returns the ending byte offset of the match in the haystack.
+    #[inline]
+    pub fn end(&self) -> usize {
+        self.end
+    }
+
+    /// Returns the matched text.
+    #[inline]
+    pub fn as_str(&self) -> &'t str {
+        &self.text[self.start..self.end]
+    }
+
+    /// Creates a new match from the given haystack and byte offsets.
+    #[inline]
+    fn new(haystack: &'t str, start: usize, end: usize) -> Match<'t> {
+        Match {
+            text: haystack,
+            start: start,
+            end: end,
+        }
+    }
+}
+
+/// A compiled regular expression for matching Unicode strings.
+///
+/// It is represented as either a sequence of bytecode instructions (dynamic)
+/// or as a specialized Rust function (native). It can be used to search, split
+/// or replace text. All searching is done with an implicit `.*?` at the
+/// beginning and end of an expression. To force an expression to match the
+/// whole string (or a prefix or a suffix), you must use an anchor like `^` or
+/// `$` (or `\A` and `\z`).
+///
+/// While this crate will handle Unicode strings (whether in the regular
+/// expression or in the search text), all positions returned are **byte
+/// indices**. Every byte index is guaranteed to be at a Unicode code point
+/// boundary.
+///
+/// The lifetimes `'r` and `'t` in this crate correspond to the lifetime of a
+/// compiled regular expression and text to search, respectively.
+///
+/// The only methods that allocate new strings are the string replacement
+/// methods. All other methods (searching and splitting) return borrowed
+/// pointers into the string given.
+///
+/// # Examples
+///
+/// Find the location of a US phone number:
+///
+/// ```rust
+/// # use regex::Regex;
+/// let re = Regex::new("[0-9]{3}-[0-9]{3}-[0-9]{4}").unwrap();
+/// let mat = re.find("phone: 111-222-3333").unwrap();
+/// assert_eq!((mat.start(), mat.end()), (7, 19));
+/// ```
+///
+/// # Using the `std::str::pattern` methods with `Regex`
+///
+/// > **Note**: This section requires that this crate is compiled with the
+/// > `pattern` Cargo feature enabled, which **requires nightly Rust**.
+///
+/// Since `Regex` implements `Pattern`, you can use regexes with methods
+/// defined on `&str`. For example, `is_match`, `find`, `find_iter`
+/// and `split` can be replaced with `str::contains`, `str::find`,
+/// `str::match_indices` and `str::split`.
+///
+/// Here are some examples:
+///
+/// ```rust,ignore
+/// # use regex::Regex;
+/// let re = Regex::new(r"\d+").unwrap();
+/// let haystack = "a111b222c";
+///
+/// assert!(haystack.contains(&re));
+/// assert_eq!(haystack.find(&re), Some(1));
+/// assert_eq!(haystack.match_indices(&re).collect::<Vec<_>>(),
+///            vec![(1, 4), (5, 8)]);
+/// assert_eq!(haystack.split(&re).collect::<Vec<_>>(), vec!["a", "b", "c"]);
+/// ```
+#[derive(Clone)]
+pub struct Regex(#[doc(hidden)] pub _Regex);
+
+#[derive(Clone)]
+#[doc(hidden)]
+pub enum _Regex {
+    // The representation of `Regex` is exported to support the `regex!`
+    // syntax extension. Do not rely on it.
+    //
+    // See the comments for the `internal` module in `lib.rs` for a more
+    // detailed explanation for what `regex!` requires.
+    #[doc(hidden)]
+    Dynamic(Exec),
+    #[doc(hidden)]
+    Plugin(Plugin),
+}
+
+impl fmt::Display for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
+impl fmt::Debug for Regex {
+    /// Shows the original regular expression.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+#[doc(hidden)]
+impl From<Exec> for Regex {
+    fn from(exec: Exec) -> Regex {
+        Regex(_Regex::Dynamic(exec))
+    }
+}
+
+impl FromStr for Regex {
+    type Err = Error;
+
+    /// Attempts to parse a string into a regular expression
+    fn from_str(s: &str) -> Result<Regex, Error> {
+        Regex::new(s)
+    }
+}
+
+/// Core regular expression methods.
+impl Regex {
+    /// Compiles a regular expression. Once compiled, it can be used repeatedly
+    /// to search, split or replace text in a string.
+    ///
+    /// If an invalid expression is given, then an error is returned.
+    pub fn new(re: &str) -> Result<Regex, Error> {
+        RegexBuilder::new(re).build()
+    }
+
+    /// Returns true if and only if the regex matches the string given.
+    ///
+    /// It is recommended to use this method if all you need to do is test
+    /// a match, since the underlying matching engine may be able to do less
+    /// work.
+    ///
+    /// # Example
+    ///
+    /// Test if some text contains at least one word with exactly 13
+    /// Unicode word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "I categorically deny having triskaidekaphobia.";
+    /// assert!(Regex::new(r"\b\w{13}\b").unwrap().is_match(text));
+    /// # }
+    /// ```
+    pub fn is_match(&self, text: &str) -> bool {
+        self.is_match_at(text, 0)
+    }
+
+    /// Returns the start and end byte range of the leftmost-first match in
+    /// `text`. If no match exists, then `None` is returned.
+    ///
+    /// Note that this should only be used if you want to discover the position
+    /// of the match. Testing the existence of a match is faster if you use
+    /// `is_match`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of the first word with exactly 13
+    /// Unicode word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "I categorically deny having triskaidekaphobia.";
+    /// let mat = Regex::new(r"\b\w{13}\b").unwrap().find(text).unwrap();
+    /// assert_eq!(mat.start(), 2);
+    /// assert_eq!(mat.end(), 15);
+    /// # }
+    /// ```
+    pub fn find<'t>(&self, text: &'t str) -> Option<Match<'t>> {
+        self.find_at(text, 0)
+    }
+
+    /// Returns an iterator for each successive non-overlapping match in
+    /// `text`, returning the start and end byte indices with respect to
+    /// `text`.
+    ///
+    /// # Example
+    ///
+    /// Find the start and end location of every word with exactly 13 Unicode
+    /// word characters:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "Retroactively relinquishing remunerations is reprehensible.";
+    /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
+    ///     println!("{:?}", mat);
+    /// }
+    /// # }
+    /// ```
+    pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                let it = exec.searcher_str().find_iter(text);
+                Matches(MatchesInner::Dynamic(it))
+            }
+            _Regex::Plugin(ref plug) => {
+                let it = plug.find_iter(text);
+                Matches(MatchesInner::Plugin(it))
+            }
+        }
+    }
+
+    /// Returns the capture groups corresponding to the leftmost-first
+    /// match in `text`. Capture group `0` always corresponds to the entire
+    /// match. If no match is found, then `None` is returned.
+    ///
+    /// You should only use `captures` if you need access to the location of
+    /// capturing group matches. Otherwise, `find` is faster for discovering
+    /// the location of the overall match.
+    ///
+    /// # Examples
+    ///
+    /// Say you have some text with movie names and their release years,
+    /// like "'Citizen Kane' (1941)". It'd be nice if we could search for text
+    /// looking like that, while also extracting the movie name and its release
+    /// year separately.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
+    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(caps.get(1).unwrap().as_str(), "Citizen Kane");
+    /// assert_eq!(caps.get(2).unwrap().as_str(), "1941");
+    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
+    /// // You can also access the groups by index using the Index notation.
+    /// // Note that this will panic on an invalid index.
+    /// assert_eq!(&caps[1], "Citizen Kane");
+    /// assert_eq!(&caps[2], "1941");
+    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
+    /// # }
+    /// ```
+    ///
+    /// Note that the full match is at capture group `0`. Each subsequent
+    /// capture group is indexed by the order of its opening `(`.
+    ///
+    /// We can make this example a bit clearer by using *named* capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
+    /// let caps = re.captures(text).unwrap();
+    /// assert_eq!(&caps["title"], "Citizen Kane");
+    /// assert_eq!(&caps["year"], "1941");
+    /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
+    /// // You can also access the groups by name using the Index notation.
+    /// // Note that this will panic on an invalid group name.
+    /// assert_eq!(&caps["title"], "Citizen Kane");
+    /// assert_eq!(&caps["year"], "1941");
+    /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
+    ///
+    /// # }
+    /// ```
+    ///
+    /// Here we name the capture groups, which we can access with the `name`
+    /// method or the `Index` notation with a `&str`. Note that the named
+    /// capture groups are still accessible with `get` or the `Index` notation
+    /// with a `usize`.
+    ///
+    /// The `0`th capture group is always unnamed, so it must always be
+    /// accessed with `at(0)` or `[0]`.
+    pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
+        let mut locs = self.locations();
+        self.read_captures_at(&mut locs, text, 0).map(|_| Captures {
+            text: text,
+            locs: locs,
+            named_groups: NamedGroups::from_regex(self)
+        })
+    }
+
+    /// Returns an iterator over all the non-overlapping capture groups matched
+    /// in `text`. This is operationally the same as `find_iter`, except it
+    /// yields information about capturing group matches.
+    ///
+    /// # Example
+    ///
+    /// We can use this to find all movie titles and their release years in
+    /// some text, where the movie is formatted like "'Title' (xxxx)":
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
+    ///                .unwrap();
+    /// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
+    /// for caps in re.captures_iter(text) {
+    ///     println!("Movie: {:?}, Released: {:?}",
+    ///              &caps["title"], &caps["year"]);
+    /// }
+    /// // Output:
+    /// // Movie: Citizen Kane, Released: 1941
+    /// // Movie: The Wizard of Oz, Released: 1939
+    /// // Movie: M, Released: 1931
+    /// # }
+    /// ```
+    pub fn captures_iter<'r, 't>(
+        &'r self,
+        text: &'t str,
+    ) -> CaptureMatches<'r, 't> {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                let it = exec.searcher_str().captures_iter(text);
+                CaptureMatches(CaptureMatchesInner::Dynamic(it))
+            }
+            _Regex::Plugin(ref plug) => {
+                let it = plug.captures_iter(text);
+                CaptureMatches(CaptureMatchesInner::Plugin(it))
+            }
+        }
+    }
+
+    /// Returns an iterator of substrings of `text` delimited by a match of the
+    /// regular expression. Namely, each element of the iterator corresponds to
+    /// text that *isn't* matched by the regular expression.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// To split a string delimited by arbitrary amounts of spaces or tabs:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"[ \t]+").unwrap();
+    /// let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
+    /// assert_eq!(fields, vec!["a", "b", "c", "d", "e"]);
+    /// # }
+    /// ```
+    pub fn split<'r, 't>(&'r self, text: &'t str) -> Split<'r, 't> {
+        Split {
+            finder: self.find_iter(text),
+            last: 0,
+        }
+    }
+
+    /// Returns an iterator of at most `limit` substrings of `text` delimited
+    /// by a match of the regular expression. (A `limit` of `0` will return no
+    /// substrings.) Namely, each element of the iterator corresponds to text
+    /// that *isn't* matched by the regular expression. The remainder of the
+    /// string that is not split will be the last element in the iterator.
+    ///
+    /// This method will *not* copy the text given.
+    ///
+    /// # Example
+    ///
+    /// Get the first two words in some text:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"\W+").unwrap();
+    /// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
+    /// assert_eq!(fields, vec!("Hey", "How", "are you?"));
+    /// # }
+    /// ```
+    pub fn splitn<'r, 't>(&'r self, text: &'t str, limit: usize)
+                         -> SplitN<'r, 't> {
+        SplitN {
+            splits: self.split(text),
+            n: limit,
+        }
+    }
+
+    /// Replaces the leftmost-first match with the replacement provided.
+    /// The replacement can be a regular string (where `$N` and `$name` are
+    /// expanded to match capture groups) or a function that takes the matches'
+    /// `Captures` and returns the replaced string.
+    ///
+    /// If no match is found, then a copy of the string is returned unchanged.
+    ///
+    /// # Replacement string syntax
+    ///
+    /// All instances of `$name` in the replacement text is replaced with the
+    /// corresponding capture group `name`.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    ///
+    /// # Examples
+    ///
+    /// Note that this function is polymorphic with respect to the replacement.
+    /// In typical usage, this can just be a normal string:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new("[^01]+").unwrap();
+    /// assert_eq!(re.replace("1078910", ""), "1010");
+    /// # }
+    /// ```
+    ///
+    /// But anything satisfying the `Replacer` trait will work. For example,
+    /// a closure of type `|&Captures| -> String` provides direct access to the
+    /// captures corresponding to a match. This allows one to access
+    /// capturing group matches easily:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # use regex::Captures; fn main() {
+    /// let re = Regex::new(r"([^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
+    ///     format!("{} {}", &caps[2], &caps[1])
+    /// });
+    /// assert_eq!(result, "Bruce Springsteen");
+    /// # }
+    /// ```
+    ///
+    /// But this is a bit cumbersome to use all the time. Instead, a simple
+    /// syntax is supported that expands `$name` into the corresponding capture
+    /// group. Here's the last example, but using this expansion technique
+    /// with named capture groups:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", "$first $last");
+    /// assert_eq!(result, "Bruce Springsteen");
+    /// # }
+    /// ```
+    ///
+    /// Note that using `$2` instead of `$first` or `$1` instead of `$last`
+    /// would produce the same result. To write a literal `$` use `$$`.
+    ///
+    /// Sometimes the replacement string requires use of curly braces to
+    /// delineate a capture group replacement and surrounding literal text.
+    /// For example, if we wanted to join two words together with an
+    /// underscore:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let re = Regex::new(r"(?P<first>\w+)\s+(?P<second>\w+)").unwrap();
+    /// let result = re.replace("deep fried", "${first}_$second");
+    /// assert_eq!(result, "deep_fried");
+    /// # }
+    /// ```
+    ///
+    /// Without the curly braces, the capture group name `first_` would be
+    /// used, and since it doesn't exist, it would be replaced with the empty
+    /// string.
+    ///
+    /// Finally, sometimes you just want to replace a literal string with no
+    /// regard for capturing group expansion. This can be done by wrapping a
+    /// byte string with `NoExpand`:
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// use regex::NoExpand;
+    ///
+    /// let re = Regex::new(r"(?P<last>[^,\s]+),\s+(\S+)").unwrap();
+    /// let result = re.replace("Springsteen, Bruce", NoExpand("$2 $last"));
+    /// assert_eq!(result, "$2 $last");
+    /// # }
+    /// ```
+    pub fn replace<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        rep: R,
+    ) -> Cow<'t, str> {
+        self.replacen(text, 1, rep)
+    }
+
+    /// Replaces all non-overlapping matches in `text` with the replacement
+    /// provided. This is the same as calling `replacen` with `limit` set to
+    /// `0`.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement string.
+    pub fn replace_all<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        rep: R,
+    ) -> Cow<'t, str> {
+        self.replacen(text, 0, rep)
+    }
+
+    /// Replaces at most `limit` non-overlapping matches in `text` with the
+    /// replacement provided. If `limit` is 0, then all non-overlapping matches
+    /// are replaced.
+    ///
+    /// See the documentation for `replace` for details on how to access
+    /// capturing group matches in the replacement string.
+    pub fn replacen<'t, R: Replacer>(
+        &self,
+        text: &'t str,
+        limit: usize,
+        mut rep: R,
+    ) -> Cow<'t, str> {
+        // If we know that the replacement doesn't have any capture expansions,
+        // then we can fast path. The fast path can make a tremendous
+        // difference:
+        //
+        //   1) We use `find_iter` instead of `captures_iter`. Not asking for
+        //      captures generally makes the regex engines faster.
+        //   2) We don't need to look up all of the capture groups and do
+        //      replacements inside the replacement string. We just push it
+        //      at each match and be done with it.
+        if let Some(rep) = rep.no_expansion() {
+            let mut new = String::with_capacity(text.len());
+            let mut last_match = 0;
+            for (i, m) in self.find_iter(text).enumerate() {
+                if limit > 0 && i >= limit {
+                    break
+                }
+                new.push_str(&text[last_match..m.start()]);
+                new.push_str(&rep);
+                last_match = m.end();
+            }
+            if last_match == 0 {
+                return Cow::Borrowed(text);
+            }
+            new.push_str(&text[last_match..]);
+            return Cow::Owned(new);
+        }
+
+        // The slower path, which we use if the replacement needs access to
+        // capture groups.
+        let mut it = self.captures_iter(text).enumerate().peekable();
+        if it.peek().is_none() {
+            return Cow::Borrowed(text);
+        }
+        let mut new = String::with_capacity(text.len());
+        let mut last_match = 0;
+        for (i, cap) in it {
+            if limit > 0 && i >= limit {
+                break
+            }
+            // unwrap on 0 is OK because captures only reports matches
+            let m = cap.get(0).unwrap();
+            new.push_str(&text[last_match..m.start()]);
+            rep.replace_append(&cap, &mut new);
+            last_match = m.end();
+        }
+        new.push_str(&text[last_match..]);
+        Cow::Owned(new)
+    }
+}
+
+/// Advanced or "lower level" search methods.
+impl Regex {
+    /// Returns the end location of a match in the text given.
+    ///
+    /// This method may have the same performance characteristics as
+    /// `is_match`, except it provides an end location for a match. In
+    /// particular, the location returned *may be shorter* than the proper end
+    /// of the leftmost-first match.
+    ///
+    /// # Example
+    ///
+    /// Typically, `a+` would match the entire first sequence of `a` in some
+    /// text, but `shortest_match` can give up as soon as it sees the first
+    /// `a`.
+    ///
+    /// ```rust
+    /// # extern crate regex; use regex::Regex;
+    /// # fn main() {
+    /// let text = "aaaaa";
+    /// let pos = Regex::new(r"a+").unwrap().shortest_match(text);
+    /// assert_eq!(pos, Some(1));
+    /// # }
+    /// ```
+    pub fn shortest_match(&self, text: &str) -> Option<usize> {
+        self.shortest_match_at(text, 0)
+    }
+
+    /// Returns the same as shortest_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn shortest_match_at(
+        &self,
+        text: &str,
+        start: usize,
+    ) -> Option<usize> {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                exec.searcher_str().shortest_match_at(text, start)
+            }
+            _Regex::Plugin(ref plug) => plug.shortest_match_at(text, start),
+        }
+    }
+
+    /// Returns the same as is_match, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn is_match_at(&self, text: &str, start: usize) -> bool {
+        self.shortest_match_at(text, start).is_some()
+    }
+
+    /// Returns the same as find, but starts the search at the given
+    /// offset.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn find_at<'t>(
+        &self,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                exec.searcher_str().find_at(text, start).map(|(s, e)| {
+                    Match::new(text, s, e)
+                })
+            }
+            _Regex::Plugin(ref plug) => {
+                plug.find_at(text, start).map(|(s, e)| Match::new(text, s, e))
+            }
+        }
+    }
+
+    /// Returns the same as captures, but starts the search at the given
+    /// offset and populates the capture locations given.
+    ///
+    /// The significance of the starting point is that it takes the surrounding
+    /// context into consideration. For example, the `\A` anchor can only
+    /// match when `start == 0`.
+    #[doc(hidden)]
+    pub fn read_captures_at<'t>(
+        &self,
+        locs: &mut Locations,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                exec.searcher_str().read_captures_at(locs, text, start)
+                    .map(|(s, e)| Match::new(text, s, e))
+            }
+            _Regex::Plugin(ref plug) => {
+                plug.read_captures_at(locs, text, start)
+                    .map(|(s, e)| Match::new(text, s, e))
+            }
+        }
+    }
+}
+
+/// Auxiliary methods.
+impl Regex {
+    /// Returns the original string of this regex.
+    pub fn as_str(&self) -> &str {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => &exec.regex_strings()[0],
+            _Regex::Plugin(ref plug) => &plug.original,
+        }
+    }
+
+    /// Returns an iterator over the capture names.
+    pub fn capture_names(&self) -> CaptureNames {
+        CaptureNames(match self.0 {
+            _Regex::Plugin(ref n) => _CaptureNames::Plugin(n.names.iter()),
+            _Regex::Dynamic(ref d) => {
+                _CaptureNames::Dynamic(d.capture_names().iter())
+            }
+        })
+    }
+
+    /// Returns the number of captures.
+    pub fn captures_len(&self) -> usize {
+        match self.0 {
+            _Regex::Plugin(ref n) => n.names.len(),
+            _Regex::Dynamic(ref d) => d.capture_names().len()
+        }
+    }
+
+    /// Returns an empty set of locations that can be reused in multiple calls
+    /// to `read_captures`.
+    #[doc(hidden)]
+    pub fn locations(&self) -> Locations {
+        match self.0 {
+            _Regex::Dynamic(ref exec) => {
+                exec.searcher_str().locations()
+            }
+            _Regex::Plugin(ref plug) => plug.locations(),
+        }
+    }
+}
+
+/// An iterator over the names of all possible captures.
+///
+/// `None` indicates an unnamed capture; the first element (capture 0, the
+/// whole matched region) is always unnamed.
+///
+/// `'r` is the lifetime of the compiled regular expression.
+pub struct CaptureNames<'r>(_CaptureNames<'r>);
+
+enum _CaptureNames<'r> {
+    Plugin(::std::slice::Iter<'r, Option<&'static str>>),
+    Dynamic(::std::slice::Iter<'r, Option<String>>)
+}
+
+impl<'r> Iterator for CaptureNames<'r> {
+    type Item = Option<&'r str>;
+
+    fn next(&mut self) -> Option<Option<&'r str>> {
+        match self.0 {
+            _CaptureNames::Plugin(ref mut i) => i.next().cloned(),
+            _CaptureNames::Dynamic(ref mut i) => {
+                i.next().as_ref().map(|o| o.as_ref().map(|s| s.as_ref()))
+            }
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        match self.0 {
+            _CaptureNames::Plugin(ref i)  => i.size_hint(),
+            _CaptureNames::Dynamic(ref i) => i.size_hint(),
+        }
+    }
+}
+
+/// Yields all substrings delimited by a regular expression match.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the string being split.
+pub struct Split<'r, 't> {
+    finder: Matches<'r, 't>,
+    last: usize,
+}
+
+impl<'r, 't> Iterator for Split<'r, 't> {
+    type Item = &'t str;
+
+    fn next(&mut self) -> Option<&'t str> {
+        let text = self.finder.text();
+        match self.finder.next() {
+            None => {
+                if self.last >= text.len() {
+                    None
+                } else {
+                    let s = &text[self.last..];
+                    self.last = text.len();
+                    Some(s)
+                }
+            }
+            Some(m) => {
+                let matched = &text[self.last..m.start()];
+                self.last = m.end();
+                Some(matched)
+            }
+        }
+    }
+}
+
+/// Yields at most `N` substrings delimited by a regular expression match.
+///
+/// The last substring will be whatever remains after splitting.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the string being split.
+pub struct SplitN<'r, 't> {
+    splits: Split<'r, 't>,
+    n: usize,
+}
+
+impl<'r, 't> Iterator for SplitN<'r, 't> {
+    type Item = &'t str;
+
+    fn next(&mut self) -> Option<&'t str> {
+        if self.n == 0 {
+            return None
+        }
+        self.n -= 1;
+        if self.n == 0 {
+            let text = self.splits.finder.text();
+            Some(&text[self.splits.last..])
+        } else {
+            self.splits.next()
+        }
+    }
+}
+
+enum NamedGroups {
+    Plugin(&'static [(&'static str, usize)]),
+    Dynamic(Arc<HashMap<String, usize>>),
+}
+
+impl NamedGroups {
+    fn from_regex(regex: &Regex) -> NamedGroups {
+        match regex.0 {
+            _Regex::Plugin(ref plug) => NamedGroups::Plugin(&plug.groups),
+            _Regex::Dynamic(ref exec) => {
+                NamedGroups::Dynamic(exec.capture_name_idx().clone())
+            }
+        }
+    }
+
+    fn pos(&self, name: &str) -> Option<usize> {
+        match *self {
+            NamedGroups::Plugin(groups) => {
+                groups.binary_search_by(|&(n, _)| n.cmp(name))
+                      .ok().map(|i| groups[i].1)
+            },
+            NamedGroups::Dynamic(ref groups) => {
+                groups.get(name).map(|i| *i)
+            },
+        }
+    }
+
+    fn iter<'n>(&'n self) -> NamedGroupsIter<'n> {
+        match *self {
+            NamedGroups::Plugin(g) => NamedGroupsIter::Plugin(g.iter()),
+            NamedGroups::Dynamic(ref g) => NamedGroupsIter::Dynamic(g.iter()),
+        }
+    }
+}
+
+enum NamedGroupsIter<'n> {
+    Plugin(::std::slice::Iter<'static, (&'static str, usize)>),
+    Dynamic(::std::collections::hash_map::Iter<'n, String, usize>),
+}
+
+impl<'n> Iterator for NamedGroupsIter<'n> {
+    type Item = (&'n str, usize);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            NamedGroupsIter::Plugin(ref mut it) => it.next().map(|&v| v),
+            NamedGroupsIter::Dynamic(ref mut it) => {
+                it.next().map(|(s, i)| (s.as_ref(), *i))
+            }
+        }
+    }
+}
+
+/// Captures represents a group of captured strings for a single match.
+///
+/// The 0th capture always corresponds to the entire match. Each subsequent
+/// index corresponds to the next capture group in the regex. If a capture
+/// group is named, then the matched string is *also* available via the `name`
+/// method. (Note that the 0th capture is always unnamed and so must be
+/// accessed with the `get` method.)
+///
+/// Positions returned from a capture group are always byte indices.
+///
+/// `'t` is the lifetime of the matched text.
+pub struct Captures<'t> {
+    text: &'t str,
+    locs: Locations,
+    named_groups: NamedGroups,
+}
+
+impl<'t> Captures<'t> {
+    /// Returns the match associated with the capture group at index `i`. If
+    /// `i` does not correspond to a capture group, or if the capture group
+    /// did not participate in the match, then `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// Get the text of the match with a default of an empty string if this
+    /// group didn't participate in the match:
+    ///
+    /// ```rust
+    /// # use regex::Regex;
+    /// let re = Regex::new(r"[a-z]+(?:([0-9]+)|([A-Z]+))").unwrap();
+    /// let caps = re.captures("abc123").unwrap();
+    ///
+    /// let text1 = caps.get(1).map_or("", |m| m.as_str());
+    /// let text2 = caps.get(2).map_or("", |m| m.as_str());
+    /// assert_eq!(text1, "123");
+    /// assert_eq!(text2, "");
+    /// ```
+    pub fn get(&self, i: usize) -> Option<Match<'t>> {
+        self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
+    }
+
+    /// Returns the match for the capture group named `name`. If `name` isn't a
+    /// valid capture group or didn't match anything, then `None` is returned.
+    pub fn name(&self, name: &str) -> Option<Match<'t>> {
+        self.named_groups.pos(name).and_then(|i| self.get(i))
+    }
+
+    /// An iterator that yields all capturing matches in the order in which
+    /// they appear in the regex. If a particular capture group didn't
+    /// participate in the match, then `None` is yielded for that capture.
+    ///
+    /// The first match always corresponds to the overall match of the regex.
+    pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
+        SubCaptureMatches {
+            caps: self,
+            it: self.locs.iter(),
+        }
+    }
+
+    /// Expands all instances of `$name` in `text` to the corresponding capture
+    /// group `name`, and writes them to the `dst` buffer given.
+    ///
+    /// `name` may be an integer corresponding to the index of the
+    /// capture group (counted by order of opening parenthesis where `0` is the
+    /// entire match) or it can be a name (consisting of letters, digits or
+    /// underscores) corresponding to a named capture group.
+    ///
+    /// If `name` isn't a valid capture group (whether the name doesn't exist
+    /// or isn't a valid index), then it is replaced with the empty string.
+    ///
+    /// The longest possible name is used. e.g., `$1a` looks up the capture
+    /// group named `1a` and not the capture group at index `1`. To exert more
+    /// precise control over the name, use braces, e.g., `${1}a`.
+    ///
+    /// To write a literal `$` use `$$`.
+    pub fn expand(&self, replacement: &str, dst: &mut String) {
+        expand_str(self, replacement, dst)
+    }
+
+    /// Returns the number of captured groups.
+    ///
+    /// This is always at least `1`, since every regex has at least one capture
+    /// group that corresponds to the full match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.locs.len()
+    }
+}
+
+impl<'t> fmt::Debug for Captures<'t> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("Captures").field(&CapturesDebug(self)).finish()
+    }
+}
+
+struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
+
+impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // We'd like to show something nice here, even if it means an
+        // allocation to build a reverse index.
+        let slot_to_name: HashMap<usize, &str> =
+            self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
+        let mut map = f.debug_map();
+        for (slot, m) in self.0.locs.iter().enumerate() {
+            let m = m.map(|(s, e)| &self.0.text[s..e]);
+            if let Some(ref name) = slot_to_name.get(&slot) {
+                map.entry(&name, &m);
+            } else {
+                map.entry(&slot, &m);
+            }
+        }
+        map.finish()
+    }
+}
+
+/// Get a group by index.
+///
+/// `'t` is the lifetime of the matched text.
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `get()` instead.
+///
+/// # Panics
+///
+/// If there is no group at the given index.
+impl<'t> Index<usize> for Captures<'t> {
+    type Output = str;
+
+    fn index(&self, i: usize) -> &str {
+        self.get(i).map(|m| m.as_str())
+            .unwrap_or_else(|| panic!("no group at index '{}'", i))
+    }
+}
+
+/// Get a group by name.
+///
+/// `'t` is the lifetime of the matched text and `'i` is the lifetime
+/// of the group name (the index).
+///
+/// The text can't outlive the `Captures` object if this method is
+/// used, because of how `Index` is defined (normally `a[i]` is part
+/// of `a` and can't outlive it); to do that, use `name` instead.
+///
+/// # Panics
+///
+/// If there is no group named by the given value.
+impl<'t, 'i> Index<&'i str> for Captures<'t> {
+    type Output = str;
+
+    fn index<'a>(&'a self, name: &'i str) -> &'a str {
+        self.name(name).map(|m| m.as_str())
+            .unwrap_or_else(|| panic!("no group named '{}'", name))
+    }
+}
+
+/// An iterator that yields all capturing matches in the order in which they
+/// appear in the regex.
+///
+/// If a particular capture group didn't participate in the match, then `None`
+/// is yielded for that capture. The first match always corresponds to the
+/// overall match of the regex.
+///
+/// The lifetime `'c` corresponds to the lifetime of the `Captures` value, and
+/// the lifetime `'t` corresponds to the originally matched text.
+pub struct SubCaptureMatches<'c, 't: 'c> {
+    caps: &'c Captures<'t>,
+    it: SubCapturesPosIter<'c>,
+}
+
+impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
+    type Item = Option<Match<'t>>;
+
+    fn next(&mut self) -> Option<Option<Match<'t>>> {
+        self.it.next()
+            .map(|cap| cap.map(|(s, e)| Match::new(self.caps.text, s, e)))
+    }
+}
+
+/// An iterator that yields all non-overlapping capture groups matching a
+/// particular regular expression.
+///
+/// The iterator stops when no more matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched string.
+pub struct CaptureMatches<'r, 't>(CaptureMatchesInner<'r, 't>);
+
+enum CaptureMatchesInner<'r, 't> {
+    Dynamic(re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>),
+    Plugin(re_trait::CaptureMatches<'t, Plugin>),
+}
+
+impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
+    type Item = Captures<'t>;
+
+    fn next(&mut self) -> Option<Captures<'t>> {
+        match self.0 {
+            CaptureMatchesInner::Dynamic(ref mut it) => {
+                let named = it.regex().capture_name_idx().clone();
+                it.next().map(|locs| Captures {
+                    text: it.text(),
+                    locs: locs,
+                    named_groups: NamedGroups::Dynamic(named),
+                })
+            }
+            CaptureMatchesInner::Plugin(ref mut it) => {
+                it.next().map(|locs| Captures {
+                    text: it.text(),
+                    locs: locs,
+                    named_groups: NamedGroups::Plugin(it.regex().groups),
+                })
+            }
+        }
+    }
+}
+
+/// An iterator over all non-overlapping matches for a particular string.
+///
+/// The iterator yields a `Match` value. The iterator stops when no more
+/// matches can be found.
+///
+/// `'r` is the lifetime of the compiled regular expression and `'t` is the
+/// lifetime of the matched string.
+pub struct Matches<'r, 't>(MatchesInner<'r, 't>);
+
+enum MatchesInner<'r, 't> {
+    Dynamic(re_trait::Matches<'t, ExecNoSyncStr<'r>>),
+    Plugin(re_trait::Matches<'t, Plugin>),
+}
+
+impl<'r, 't> Matches<'r, 't> {
+    fn text(&self) -> &'t str {
+        match self.0 {
+            MatchesInner::Dynamic(ref it) => it.text(),
+            MatchesInner::Plugin(ref it) => it.text(),
+        }
+    }
+}
+
+impl<'r, 't> Iterator for Matches<'r, 't> {
+    type Item = Match<'t>;
+
+    fn next(&mut self) -> Option<Match<'t>> {
+        let text = self.text();
+        match self.0 {
+            MatchesInner::Dynamic(ref mut it) => {
+                it.next().map(|(s, e)| Match::new(text, s, e))
+            }
+            MatchesInner::Plugin(ref mut it) => {
+                it.next().map(|(s, e)| Match::new(text, s, e))
+            }
+        }
+    }
+}
+
+/// Replacer describes types that can be used to replace matches in a string.
+///
+/// In general, users of this crate shouldn't need to implement this trait,
+/// since implementations are already provided for `&str` and
+/// `FnMut(&Captures) -> String`, which covers most use cases.
+pub trait Replacer {
+    /// Appends text to `dst` to replace the current match.
+    ///
+    /// The current match is represented by `caps`, which is guaranteed to
+    /// have a match at capture group `0`.
+    ///
+    /// For example, a no-op replacement would be
+    /// `dst.extend(caps.get(0).unwrap().as_str())`.
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String);
+
+    /// Return a fixed unchanging replacement string.
+    ///
+    /// When doing replacements, if access to `Captures` is not needed (e.g.,
+    /// the replacement byte string does not need `$` expansion), then it can
+    /// be beneficial to avoid finding sub-captures.
+    ///
+    /// In general, this is called once for every call to `replacen`.
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+        None
+    }
+}
+
+impl<'a> Replacer for &'a str {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        caps.expand(*self, dst);
+    }
+
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+        match memchr(b'$', self.as_bytes()) {
+            Some(_) => None,
+            None => Some(Cow::Borrowed(*self)),
+        }
+    }
+}
+
+impl<F> Replacer for F where F: FnMut(&Captures) -> String {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        dst.push_str(&(*self)(caps));
+    }
+}
+
+/// NoExpand indicates literal string replacement.
+///
+/// It can be used with `replace` and `replace_all` to do a literal string
+/// replacement without expanding `$name` to their corresponding capture
+/// groups. This can be both convenient (to avoid escaping `$`, for example)
+/// and performant (since capture groups don't need to be found).
+///
+/// `'t` is the lifetime of the literal text.
+pub struct NoExpand<'t>(pub &'t str);
+
+impl<'t> Replacer for NoExpand<'t> {
+    fn replace_append(&mut self, _: &Captures, dst: &mut String) {
+        dst.push_str(self.0);
+    }
+
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+        Some(Cow::Borrowed(self.0))
+    }
+}
diff --git a/third_party/rust/regex/src/simd_accel/mod.rs b/third_party/rust/regex-0.2.2/src/simd_accel/mod.rs
similarity index 100%
rename from third_party/rust/regex/src/simd_accel/mod.rs
rename to third_party/rust/regex-0.2.2/src/simd_accel/mod.rs
diff --git a/third_party/rust/regex/src/simd_accel/teddy128.rs b/third_party/rust/regex-0.2.2/src/simd_accel/teddy128.rs
similarity index 100%
rename from third_party/rust/regex/src/simd_accel/teddy128.rs
rename to third_party/rust/regex-0.2.2/src/simd_accel/teddy128.rs
diff --git a/third_party/rust/regex/src/simd_fallback/mod.rs b/third_party/rust/regex-0.2.2/src/simd_fallback/mod.rs
similarity index 100%
rename from third_party/rust/regex/src/simd_fallback/mod.rs
rename to third_party/rust/regex-0.2.2/src/simd_fallback/mod.rs
diff --git a/third_party/rust/regex/src/simd_fallback/teddy128.rs b/third_party/rust/regex-0.2.2/src/simd_fallback/teddy128.rs
similarity index 100%
rename from third_party/rust/regex/src/simd_fallback/teddy128.rs
rename to third_party/rust/regex-0.2.2/src/simd_fallback/teddy128.rs
diff --git a/third_party/rust/regex-0.2.2/src/sparse.rs b/third_party/rust/regex-0.2.2/src/sparse.rs
new file mode 100644
index 000000000000..34c05e7157a4
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/sparse.rs
@@ -0,0 +1,78 @@
+use std::ops::Deref;
+use std::slice;
+
+/// A sparse set used for representing ordered NFA states.
+///
+/// This supports constant time addition and membership testing. Clearing an
+/// entire set can also be done in constant time. Iteration yields elements
+/// in the order in which they were inserted.
+///
+/// The data structure is based on: http://research.swtch.com/sparse
+/// Note though that we don't actually use unitialized memory. We generally
+/// reuse allocations, so the initial allocation cost is bareable. However,
+/// its other properties listed above are extremely useful.
+#[derive(Clone, Debug)]
+pub struct SparseSet {
+    /// Dense contains the instruction pointers in the order in which they
+    /// were inserted. Accessing elements >= self.size is illegal.
+    dense: Vec<usize>,
+    /// Sparse maps instruction pointers to their location in dense.
+    ///
+    /// An instruction pointer is in the set if and only if
+    /// sparse[ip] < size && ip == dense[sparse[ip]].
+    sparse: Vec<usize>,
+    /// The number of elements in the set.
+    size: usize,
+}
+
+impl SparseSet {
+    pub fn new(size: usize) -> SparseSet {
+        SparseSet {
+            dense: vec![0; size],
+            sparse: vec![0; size],
+            size: 0,
+        }
+    }
+
+    pub fn len(&self) -> usize {
+        self.size
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.size == 0
+    }
+
+    pub fn capacity(&self) -> usize {
+        self.dense.len()
+    }
+
+    pub fn insert(&mut self, value: usize) {
+        let i = self.size;
+        self.dense[i] = value;
+        self.sparse[value] = i;
+        self.size += 1;
+    }
+
+    pub fn contains(&self, value: usize) -> bool {
+        let i = self.sparse[value];
+        i < self.size && self.dense[i] == value
+    }
+
+    pub fn clear(&mut self) {
+        self.size = 0;
+    }
+}
+
+impl Deref for SparseSet {
+    type Target = [usize];
+
+    fn deref(&self) -> &Self::Target {
+        &self.dense[0..self.size]
+    }
+}
+
+impl<'a> IntoIterator for &'a SparseSet {
+    type Item = &'a usize;
+    type IntoIter = slice::Iter<'a, usize>;
+    fn into_iter(self) -> Self::IntoIter { self.iter() }
+}
diff --git a/third_party/rust/regex-0.2.2/src/testdata/LICENSE b/third_party/rust/regex-0.2.2/src/testdata/LICENSE
new file mode 100644
index 000000000000..f47dbf4c449b
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/testdata/LICENSE
@@ -0,0 +1,19 @@
+The following license covers testregex.c and all associated test data.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following disclaimer:
+
+THIS SOFTWARE IS PROVIDED BY AT&T ``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 AT&T 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.
diff --git a/third_party/rust/regex-0.2.2/src/testdata/README b/third_party/rust/regex-0.2.2/src/testdata/README
new file mode 100644
index 000000000000..6efc2dad3377
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/testdata/README
@@ -0,0 +1,17 @@
+Test data was taken from the Go distribution, which was in turn taken from the
+testregex test suite:
+
+  http://www2.research.att.com/~astopen/testregex/testregex.html
+
+The LICENSE in this directory corresponds to the LICENSE that the data was
+released under.
+
+The tests themselves were modified for RE2/Go. A couple were modified further
+by me (Andrew Gallant) (only in repetition.dat) so that RE2/Go would pass them.
+(Yes, it seems like RE2/Go includes failing test cases.) This may or may not
+have been a bad idea, but I think being consistent with an established Regex
+library is worth something.
+
+Note that these files are read by 'scripts/regex-match-tests.py' and turned
+into Rust tests found in 'regex_macros/tests/matches.rs'.
+
diff --git a/third_party/rust/regex-0.2.2/src/testdata/basic.dat b/third_party/rust/regex-0.2.2/src/testdata/basic.dat
new file mode 100644
index 000000000000..e55efaeec062
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/testdata/basic.dat
@@ -0,0 +1,221 @@
+NOTE	all standard compliant implementations should pass these : 2002-05-31
+
+BE	abracadabra$	abracadabracadabra	(7,18)
+BE	a...b		abababbb		(2,7)
+BE	XXXXXX		..XXXXXX		(2,8)
+E	\)		()	(1,2)
+BE	a]		a]a	(0,2)
+B	}		}	(0,1)
+E	\}		}	(0,1)
+BE	\]		]	(0,1)
+B	]		]	(0,1)
+E	]		]	(0,1)
+B	{		{	(0,1)
+B	}		}	(0,1)
+BE	^a		ax	(0,1)
+BE	\^a		a^a	(1,3)
+BE	a\^		a^	(0,2)
+BE	a$		aa	(1,2)
+BE	a\$		a$	(0,2)
+BE	^$		NULL	(0,0)
+E	$^		NULL	(0,0)
+E	a($)		aa	(1,2)(2,2)
+E	a*(^a)		aa	(0,1)(0,1)
+E	(..)*(...)*		a	(0,0)
+E	(..)*(...)*		abcd	(0,4)(2,4)
+E	(ab|a)(bc|c)		abc	(0,3)(0,2)(2,3)
+E	(ab)c|abc		abc	(0,3)(0,2)
+E	a{0}b		ab			(1,2)
+E	(a*)(b?)(b+)b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	(a*)(b{0,1})(b{1,})b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	a{9876543210}	NULL	BADBR
+E	((a|a)|a)			a	(0,1)(0,1)(0,1)
+E	(a*)(a|aa)			aaaa	(0,4)(0,3)(3,4)
+E	a*(a.|aa)			aaaa	(0,4)(2,4)
+E	a(b)|c(d)|a(e)f			aef	(0,3)(?,?)(?,?)(1,2)
+E	(a|b)?.*			b	(0,1)(0,1)
+E	(a|b)c|a(b|c)			ac	(0,2)(0,1)
+E	(a|b)c|a(b|c)			ab	(0,2)(?,?)(1,2)
+E	(a|b)*c|(a|ab)*c		abc	(0,3)(1,2)
+E	(a|b)*c|(a|ab)*c		xc	(1,2)
+E	(.a|.b).*|.*(.a|.b)		xa	(0,2)(0,2)
+E	a?(ab|ba)ab			abab	(0,4)(0,2)
+E	a?(ac{0}b|ba)ab			abab	(0,4)(0,2)
+E	ab|abab				abbabab	(0,2)
+E	aba|bab|bba			baaabbbaba	(5,8)
+E	aba|bab				baaabbbaba	(6,9)
+E	(aa|aaa)*|(a|aaaaa)		aa	(0,2)(0,2)
+E	(a.|.a.)*|(a|.a...)		aa	(0,2)(0,2)
+E	ab|a				xabc	(1,3)
+E	ab|a				xxabc	(2,4)
+Ei	(Ab|cD)*			aBcD	(0,4)(2,4)
+BE	[^-]			--a		(2,3)
+BE	[a-]*			--a		(0,3)
+BE	[a-m-]*			--amoma--	(0,4)
+E	:::1:::0:|:::1:1:0:	:::0:::1:::1:::0:	(8,17)
+E	:::1:::0:|:::1:1:1:	:::0:::1:::1:::0:	(8,17)
+{E	[[:upper:]]		A		(0,1)	[[<element>]] not supported
+E	[[:lower:]]+		`az{		(1,3)
+E	[[:upper:]]+		@AZ[		(1,3)
+# No collation in Go
+#BE	[[-]]			[[-]]		(2,4)
+#BE	[[.NIL.]]	NULL	ECOLLATE
+#BE	[[=aleph=]]	NULL	ECOLLATE
+}
+BE$	\n		\n	(0,1)
+BEn$	\n		\n	(0,1)
+BE$	[^a]		\n	(0,1)
+BE$	\na		\na	(0,2)
+E	(a)(b)(c)	abc	(0,3)(0,1)(1,2)(2,3)
+BE	xxx		xxx	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 6,	(0,6)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	2/7	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 1,Feb 6	(5,11)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))	x	(0,1)(0,1)(0,1)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*	xx	(0,2)(1,2)(1,2)
+E	a?(ab|ba)*	ababababababababababababababababababababababababababababababababababababababababa	(0,81)(79,81)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabbbbaa	(18,25)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabaa	(18,22)
+E	aaac|aabc|abac|abbc|baac|babc|bbac|bbbc	baaabbbabac	(7,11)
+BE$	.*			\x01\x7f	(0,2)
+E	aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	(53,57)
+L	aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	NOMATCH
+E	a*a*a*a*a*b		aaaaaaaaab	(0,10)
+BE	^			NULL		(0,0)
+BE	$			NULL		(0,0)
+BE	^$			NULL		(0,0)
+BE	^a$			a		(0,1)
+BE	abc			abc		(0,3)
+BE	abc			xabcy		(1,4)
+BE	abc			ababc		(2,5)
+BE	ab*c			abc		(0,3)
+BE	ab*bc			abc		(0,3)
+BE	ab*bc			abbc		(0,4)
+BE	ab*bc			abbbbc		(0,6)
+E	ab+bc			abbc		(0,4)
+E	ab+bc			abbbbc		(0,6)
+E	ab?bc			abbc		(0,4)
+E	ab?bc			abc		(0,3)
+E	ab?c			abc		(0,3)
+BE	^abc$			abc		(0,3)
+BE	^abc			abcc		(0,3)
+BE	abc$			aabc		(1,4)
+BE	^			abc		(0,0)
+BE	$			abc		(3,3)
+BE	a.c			abc		(0,3)
+BE	a.c			axc		(0,3)
+BE	a.*c			axyzc		(0,5)
+BE	a[bc]d			abd		(0,3)
+BE	a[b-d]e			ace		(0,3)
+BE	a[b-d]			aac		(1,3)
+BE	a[-b]			a-		(0,2)
+BE	a[b-]			a-		(0,2)
+BE	a]			a]		(0,2)
+BE	a[]]b			a]b		(0,3)
+BE	a[^bc]d			aed		(0,3)
+BE	a[^-b]c			adc		(0,3)
+BE	a[^]b]c			adc		(0,3)
+E	ab|cd			abc		(0,2)
+E	ab|cd			abcd		(0,2)
+E	a\(b			a(b		(0,3)
+E	a\(*b			ab		(0,2)
+E	a\(*b			a((b		(0,4)
+E	((a))			abc		(0,1)(0,1)(0,1)
+E	(a)b(c)			abc		(0,3)(0,1)(2,3)
+E	a+b+c			aabbabc		(4,7)
+E	a*			aaa		(0,3)
+#E	(a*)*			-		(0,0)(0,0)
+E	(a*)*			-		(0,0)(?,?)	RE2/Go
+E	(a*)+			-		(0,0)(0,0)
+#E	(a*|b)*			-		(0,0)(0,0)
+E	(a*|b)*			-		(0,0)(?,?)	RE2/Go
+E	(a+|b)*			ab		(0,2)(1,2)
+E	(a+|b)+			ab		(0,2)(1,2)
+E	(a+|b)?			ab		(0,1)(0,1)
+BE	[^ab]*			cde		(0,3)
+#E	(^)*			-		(0,0)(0,0)
+E	(^)*			-		(0,0)(?,?)	RE2/Go
+BE	a*			NULL		(0,0)
+E	([abc])*d		abbbcd		(0,6)(4,5)
+E	([abc])*bcd		abcd		(0,4)(0,1)
+E	a|b|c|d|e		e		(0,1)
+E	(a|b|c|d|e)f		ef		(0,2)(0,1)
+#E	((a*|b))*		-		(0,0)(0,0)(0,0)
+E	((a*|b))*		-		(0,0)(?,?)(?,?)	RE2/Go
+BE	abcd*efg		abcdefg		(0,7)
+BE	ab*			xabyabbbz	(1,3)
+BE	ab*			xayabbbz	(1,2)
+E	(ab|cd)e		abcde		(2,5)(2,4)
+BE	[abhgefdc]ij		hij		(0,3)
+E	(a|b)c*d		abcd		(1,4)(1,2)
+E	(ab|ab*)bc		abc		(0,3)(0,1)
+E	a([bc]*)c*		abc		(0,3)(1,3)
+E	a([bc]*)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]+)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]*)(c+d)		abcd		(0,4)(1,2)(2,4)
+E	a[bcd]*dcdcde		adcdcde		(0,7)
+E	(ab|a)b*c		abc		(0,3)(0,2)
+E	((a)(b)c)(d)		abcd		(0,4)(0,3)(0,1)(1,2)(3,4)
+BE	[A-Za-z_][A-Za-z0-9_]*	alpha		(0,5)
+E	^a(bc+|b[eh])g|.h$	abh		(1,3)
+E	(bc+d$|ef*g.|h?i(j|k))	effgz		(0,5)(0,5)
+E	(bc+d$|ef*g.|h?i(j|k))	ij		(0,2)(0,2)(1,2)
+E	(bc+d$|ef*g.|h?i(j|k))	reffgz		(1,6)(1,6)
+E	(((((((((a)))))))))	a		(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE	multiple words		multiple words yeah	(0,14)
+E	(.*)c(.*)		abcde		(0,5)(0,2)(3,5)
+BE	abcd			abcd		(0,4)
+E	a(bc)d			abcd		(0,4)(1,3)
+E	a[-]?c		ac		(0,3)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mo'ammar Gadhafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Kaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qadhafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gadafi	(0,14)(?,?)(10,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moamar Gaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadhdhafi	(0,18)(?,?)(13,15)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Khaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafy	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muamar Kaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Quathafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gheddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Khadafy	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Qudhafi	(0,15)(?,?)(10,12)
+E	a+(b|c)*d+		aabcdd			(0,6)(3,4)
+E	^.+$			vivi			(0,4)
+E	^(.+)$			vivi			(0,4)(0,4)
+E	^([^!.]+).att.com!(.+)$	gryphon.att.com!eby	(0,19)(0,7)(16,19)
+E	^([^!]+!)?([^!]+)$	bas			(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$	bar!bas			(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$	foo!bas			(0,7)(0,4)(4,7)
+E	^.+!([^!]+!)([^!]+)$	foo!bar!bas		(0,11)(4,8)(8,11)
+E	((foo)|(bar))!bas	bar!bas			(0,7)(0,3)(?,?)(0,3)
+E	((foo)|(bar))!bas	foo!bar!bas		(4,11)(4,7)(?,?)(4,7)
+E	((foo)|(bar))!bas	foo!bas			(0,7)(0,3)(0,3)
+E	((foo)|bar)!bas		bar!bas			(0,7)(0,3)
+E	((foo)|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	((foo)|bar)!bas		foo!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		bar!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		foo!bar!bas		(4,11)(4,7)(4,7)
+E	(foo|(bar))!bas		foo!bas			(0,7)(0,3)
+E	(foo|bar)!bas		bar!bas			(0,7)(0,3)
+E	(foo|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	(foo|bar)!bas		foo!bas			(0,7)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bas		(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bar!bas		(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bar!bas	(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bas		(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bas		(0,3)(0,3)(?,?)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bar!bas		(0,7)(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bas		(0,7)(0,7)(0,4)(4,7)
+E	.*(/XXX).*			/XXX			(0,4)(0,4)
+E	.*(\\XXX).*			\XXX			(0,4)(0,4)
+E	\\XXX				\XXX			(0,4)
+E	.*(/000).*			/000			(0,4)(0,4)
+E	.*(\\000).*			\000			(0,4)(0,4)
+E	\\000				\000			(0,4)
diff --git a/third_party/rust/regex-0.2.2/src/testdata/nullsubexpr.dat b/third_party/rust/regex-0.2.2/src/testdata/nullsubexpr.dat
new file mode 100644
index 000000000000..2e18fbb91707
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/testdata/nullsubexpr.dat
@@ -0,0 +1,79 @@
+NOTE	null subexpression matches : 2002-06-06
+
+E	(a*)*		a		(0,1)(0,1)
+#E	SAME		x		(0,0)(0,0)
+E	SAME		x		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)*		a		(0,1)(0,1)
+E	SAME		x		(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)+		a		(0,1)(0,1)
+E	SAME		x		NOMATCH
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+
+E	([a]*)*		a		(0,1)(0,1)
+#E	SAME		x		(0,0)(0,0)
+E	SAME		x		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([a]*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([^b]*)*	a		(0,1)(0,1)
+#E	SAME		b		(0,0)(0,0)
+E	SAME		b		(0,0)(?,?)	RE2/Go
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaab		(0,6)(0,6)
+E	([ab]*)*	a		(0,1)(0,1)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		ababab		(0,6)(0,6)
+E	SAME		bababa		(0,6)(0,6)
+E	SAME		b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+E	SAME		aaaabcde	(0,5)(0,5)
+E	([^a]*)*	b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+#E	SAME		aaaaaa		(0,0)(0,0)
+E	SAME		aaaaaa		(0,0)(?,?)	RE2/Go
+E	([^ab]*)*	ccccxx		(0,6)(0,6)
+#E	SAME		ababab		(0,0)(0,0)
+E	SAME		ababab		(0,0)(?,?)	RE2/Go
+
+E	((z)+|a)*	zabcde		(0,2)(1,2)
+
+#{E	a+?		aaaaaa		(0,1)	no *? +? mimimal match ops
+#E	(a)		aaa		(0,1)(0,1)
+#E	(a*?)		aaa		(0,0)(0,0)
+#E	(a)*?		aaa		(0,0)
+#E	(a*?)*?		aaa		(0,0)
+#}
+
+B	\(a*\)*\(x\)		x	(0,1)(0,0)(0,1)
+B	\(a*\)*\(x\)		ax	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)		axa	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)\(\1\)	x	(0,1)(0,0)(0,1)(1,1)
+B	\(a*\)*\(x\)\(\1\)	ax	(0,2)(1,1)(1,2)(2,2)
+B	\(a*\)*\(x\)\(\1\)	axa	(0,3)(0,1)(1,2)(2,3)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axax	(0,4)(0,1)(1,2)(2,3)(3,4)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axxa	(0,3)(1,1)(1,2)(2,2)(2,3)
+
+#E	(a*)*(x)		x	(0,1)(0,0)(0,1)
+E	(a*)*(x)		x	(0,1)(?,?)(0,1)	RE2/Go
+E	(a*)*(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)*(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*)+(x)		x	(0,1)(0,0)(0,1)
+E	(a*)+(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)+(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*){2}(x)		x	(0,1)(0,0)(0,1)
+E	(a*){2}(x)		ax	(0,2)(1,1)(1,2)
+E	(a*){2}(x)		axa	(0,2)(1,1)(1,2)
diff --git a/third_party/rust/regex-0.2.2/src/testdata/repetition.dat b/third_party/rust/regex-0.2.2/src/testdata/repetition.dat
new file mode 100644
index 000000000000..3bb212118000
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/testdata/repetition.dat
@@ -0,0 +1,163 @@
+NOTE	implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+#	NOMATCH
+#	(0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+#	(0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E	((..)|(.))				NULL		NOMATCH
+E	((..)|(.))((..)|(.))			NULL		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		NULL		NOMATCH
+
+E	((..)|(.)){1}				NULL		NOMATCH
+E	((..)|(.)){2}				NULL		NOMATCH
+E	((..)|(.)){3}				NULL		NOMATCH
+
+E	((..)|(.))*				NULL		(0,0)
+
+E	((..)|(.))				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.))((..)|(.))			a		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		a		NOMATCH
+
+E	((..)|(.)){1}				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.)){2}				a		NOMATCH
+E	((..)|(.)){3}				a		NOMATCH
+
+E	((..)|(.))*				a		(0,1)(0,1)(?,?)(0,1)
+
+E	((..)|(.))				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aa		(0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E	((..)|(.))((..)|(.))((..)|(.))		aa		NOMATCH
+
+E	((..)|(.)){1}				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aa		(0,2)(1,2)(?,?)(1,2)
+E	((..)|(.)){3}				aa		NOMATCH
+
+E	((..)|(.))*				aa		(0,2)(0,2)(0,2)(?,?)
+
+E	((..)|(.))				aaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaa		(0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E	((..)|(.))((..)|(.))((..)|(.))		aaa		(0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E	((..)|(.)){1}				aaa		(0,2)(0,2)(0,2)(?,?)
+#E	((..)|(.)){2}				aaa		(0,3)(2,3)(?,?)(2,3)
+E	((..)|(.)){2}				aaa		(0,3)(2,3)(0,2)(2,3)	RE2/Go
+E	((..)|(.)){3}				aaa		(0,3)(2,3)(?,?)(2,3)
+
+#E	((..)|(.))*				aaa		(0,3)(2,3)(?,?)(2,3)
+E	((..)|(.))*				aaa		(0,3)(2,3)(0,2)(2,3)	RE2/Go
+
+E	((..)|(.))				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaa		(0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E	((..)|(.)){1}				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaa		(0,4)(2,4)(2,4)(?,?)
+#E	((..)|(.)){3}				aaaa		(0,4)(3,4)(?,?)(3,4)
+E	((..)|(.)){3}				aaaa		(0,4)(3,4)(0,2)(3,4)	RE2/Go
+
+E	((..)|(.))*				aaaa		(0,4)(2,4)(2,4)(?,?)
+
+E	((..)|(.))				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaa		(0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E	((..)|(.)){1}				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaa		(0,4)(2,4)(2,4)(?,?)
+#E	((..)|(.)){3}				aaaaa		(0,5)(4,5)(?,?)(4,5)
+E	((..)|(.)){3}				aaaaa		(0,5)(4,5)(2,4)(4,5)	RE2/Go
+
+#E	((..)|(.))*				aaaaa		(0,5)(4,5)(?,?)(4,5)
+E	((..)|(.))*				aaaaa		(0,5)(4,5)(2,4)(4,5)	RE2/Go
+
+E	((..)|(.))				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaaa		(0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E	((..)|(.)){1}				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaaa		(0,4)(2,4)(2,4)(?,?)
+E	((..)|(.)){3}				aaaaaa		(0,6)(4,6)(4,6)(?,?)
+
+E	((..)|(.))*				aaaaaa		(0,6)(4,6)(4,6)(?,?)
+
+NOTE	additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree. 
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E	X(.?){0,}Y	X1234567Y	(0,9)(7,8)
+:HA#101:E	X(.?){1,}Y	X1234567Y	(0,9)(7,8)
+:HA#102:E	X(.?){2,}Y	X1234567Y	(0,9)(7,8)
+:HA#103:E	X(.?){3,}Y	X1234567Y	(0,9)(7,8)
+:HA#104:E	X(.?){4,}Y	X1234567Y	(0,9)(7,8)
+:HA#105:E	X(.?){5,}Y	X1234567Y	(0,9)(7,8)
+:HA#106:E	X(.?){6,}Y	X1234567Y	(0,9)(7,8)
+:HA#107:E	X(.?){7,}Y	X1234567Y	(0,9)(7,8)
+:HA#108:E	X(.?){8,}Y	X1234567Y	(0,9)(8,8)
+#:HA#110:E	X(.?){0,8}Y	X1234567Y	(0,9)(7,8)
+:HA#110:E	X(.?){0,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#111:E	X(.?){1,8}Y	X1234567Y	(0,9)(7,8)
+:HA#111:E	X(.?){1,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#112:E	X(.?){2,8}Y	X1234567Y	(0,9)(7,8)
+:HA#112:E	X(.?){2,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#113:E	X(.?){3,8}Y	X1234567Y	(0,9)(7,8)
+:HA#113:E	X(.?){3,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#114:E	X(.?){4,8}Y	X1234567Y	(0,9)(7,8)
+:HA#114:E	X(.?){4,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#115:E	X(.?){5,8}Y	X1234567Y	(0,9)(7,8)
+:HA#115:E	X(.?){5,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#116:E	X(.?){6,8}Y	X1234567Y	(0,9)(7,8)
+:HA#116:E	X(.?){6,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+#:HA#117:E	X(.?){7,8}Y	X1234567Y	(0,9)(7,8)
+:HA#117:E	X(.?){7,8}Y	X1234567Y	(0,9)(8,8)	RE2/Go
+:HA#118:E	X(.?){8,8}Y	X1234567Y	(0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation).  The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E	(a|ab|c|bcd){0,}(d*)	ababcd	(0,1)(0,1)(1,1)
+:HA#261:E	(a|ab|c|bcd){1,}(d*)	ababcd	(0,1)(0,1)(1,1)
+:HA#262:E	(a|ab|c|bcd){2,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#263:E	(a|ab|c|bcd){3,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#264:E	(a|ab|c|bcd){4,}(d*)	ababcd	NOMATCH
+:HA#265:E	(a|ab|c|bcd){0,10}(d*)	ababcd	(0,1)(0,1)(1,1)
+:HA#266:E	(a|ab|c|bcd){1,10}(d*)	ababcd	(0,1)(0,1)(1,1)
+:HA#267:E	(a|ab|c|bcd){2,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#268:E	(a|ab|c|bcd){3,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#269:E	(a|ab|c|bcd){4,10}(d*)	ababcd	NOMATCH
+:HA#270:E	(a|ab|c|bcd)*(d*)	ababcd	(0,1)(0,1)(1,1)
+:HA#271:E	(a|ab|c|bcd)+(d*)	ababcd	(0,1)(0,1)(1,1)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+#:HA#280:E	(ab|a|c|bcd){0,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#280:E	(ab|a|c|bcd){0,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#281:E	(ab|a|c|bcd){1,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#281:E	(ab|a|c|bcd){1,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#282:E	(ab|a|c|bcd){2,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#282:E	(ab|a|c|bcd){2,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#283:E	(ab|a|c|bcd){3,}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#283:E	(ab|a|c|bcd){3,}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+:HA#284:E	(ab|a|c|bcd){4,}(d*)	ababcd	NOMATCH
+#:HA#285:E	(ab|a|c|bcd){0,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#285:E	(ab|a|c|bcd){0,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#286:E	(ab|a|c|bcd){1,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#286:E	(ab|a|c|bcd){1,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#287:E	(ab|a|c|bcd){2,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#287:E	(ab|a|c|bcd){2,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#288:E	(ab|a|c|bcd){3,10}(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#288:E	(ab|a|c|bcd){3,10}(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+:HA#289:E	(ab|a|c|bcd){4,10}(d*)	ababcd	NOMATCH
+#:HA#290:E	(ab|a|c|bcd)*(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#290:E	(ab|a|c|bcd)*(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
+#:HA#291:E	(ab|a|c|bcd)+(d*)	ababcd	(0,6)(3,6)(6,6)
+:HA#291:E	(ab|a|c|bcd)+(d*)	ababcd	(0,6)(4,5)(5,6)	RE2/Go
diff --git a/third_party/rust/regex-0.2.2/src/utf8.rs b/third_party/rust/regex-0.2.2/src/utf8.rs
new file mode 100644
index 000000000000..8f6ec1a02263
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/src/utf8.rs
@@ -0,0 +1,290 @@
+/// A few elementary UTF-8 encoding and decoding functions used by the matching
+/// engines.
+///
+/// In an ideal world, the matching engines operate on `&str` and we can just
+/// lean on the standard library for all our UTF-8 needs. However, to support
+/// byte based regexes (that can match on arbitrary bytes which may contain
+/// UTF-8), we need to be capable of searching and decoding UTF-8 on a `&[u8]`.
+/// The standard library doesn't really recognize this use case, so we have
+/// to build it out ourselves.
+///
+/// Should this be factored out into a separate crate? It seems independently
+/// useful. There are other crates that already exist (e.g., `utf-8`) that have
+/// overlapping use cases. Not sure what to do.
+
+use std::char;
+
+const TAG_CONT: u8 = 0b1000_0000;
+const TAG_TWO: u8 = 0b1100_0000;
+const TAG_THREE: u8 = 0b1110_0000;
+const TAG_FOUR: u8 = 0b1111_0000;
+
+/// Returns the smallest possible index of the next valid UTF-8 sequence
+/// starting after `i`.
+pub fn next_utf8(text: &[u8], i: usize) -> usize {
+    let b = match text.get(i) {
+        None => return i + 1,
+        Some(&b) => b,
+    };
+    let inc = if b <= 0x7F {
+        1
+    } else if b <= 0b110_11111 {
+        2
+    } else if b <= 0b1110_1111 {
+        3
+    } else {
+        4
+    };
+    i + inc
+}
+
+/// Encode the given Unicode character to `dst` as a single UTF-8 sequence.
+///
+/// If `dst` is not long enough, then `None` is returned. Otherwise, the number
+/// of bytes written is returned.
+#[allow(dead_code)]
+#[inline]
+pub fn encode_utf8(character: char, dst: &mut [u8]) -> Option<usize> {
+    let code = character as u32;
+    if code <= 0x7F && !dst.is_empty() {
+        dst[0] = code as u8;
+        Some(1)
+    } else if code <= 0x7FF && dst.len() >= 2 {
+        dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO;
+        dst[1] = (code & 0x3F) as u8 | TAG_CONT;
+        Some(2)
+    } else if code <= 0xFFFF && dst.len() >= 3  {
+        dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE;
+        dst[1] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+        dst[2] = (code & 0x3F) as u8 | TAG_CONT;
+        Some(3)
+    } else if dst.len() >= 4 {
+        dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR;
+        dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+        dst[2] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+        dst[3] = (code & 0x3F) as u8 | TAG_CONT;
+        Some(4)
+    } else {
+        None
+    }
+}
+
+/// Decode a single UTF-8 sequence into a single Unicode codepoint from `src`.
+///
+/// If no valid UTF-8 sequence could be found, then `None` is returned.
+/// Otherwise, the decoded codepoint and the number of bytes read is returned.
+/// The number of bytes read (for a valid UTF-8 sequence) is guaranteed to be
+/// 1, 2, 3 or 4.
+///
+/// Note that a UTF-8 sequence is invalid if it is incorrect UTF-8, encodes a
+/// codepoint that is out of range (surrogate codepoints are out of range) or
+/// is not the shortest possible UTF-8 sequence for that codepoint.
+#[inline]
+pub fn decode_utf8(src: &[u8]) -> Option<(char, usize)> {
+    let b0 = match src.get(0) {
+        None => return None,
+        Some(&b) if b <= 0x7F => return Some((b as char, 1)),
+        Some(&b) => b,
+    };
+    match b0 {
+        0b110_00000 ... 0b110_11111 => {
+            if src.len() < 2 {
+                return None;
+            }
+            let b1 = src[1];
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_TWO) as u32) << 6
+                     | ((b1 & !TAG_CONT) as u32);
+            match cp {
+                0x80 ... 0x7FF => char::from_u32(cp).map(|cp| (cp, 2)),
+                _ => None,
+            }
+        }
+        0b1110_0000 ... 0b1110_1111 => {
+            if src.len() < 3 {
+                return None;
+            }
+            let (b1, b2) = (src[1], src[2]);
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b2 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_THREE) as u32) << 12
+                     | ((b1 & !TAG_CONT) as u32) << 6
+                     | ((b2 & !TAG_CONT) as u32);
+            match cp {
+                // char::from_u32 will disallow surrogate codepoints.
+                0x800 ... 0xFFFF => char::from_u32(cp).map(|cp| (cp, 3)),
+                _ => None,
+            }
+        }
+        0b11110_000 ... 0b11110_111 => {
+            if src.len() < 4 {
+                return None;
+            }
+            let (b1, b2, b3) = (src[1], src[2], src[3]);
+            if 0b11_000000 & b1 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b2 != TAG_CONT {
+                return None;
+            }
+            if 0b11_000000 & b3 != TAG_CONT {
+                return None;
+            }
+            let cp = ((b0 & !TAG_FOUR) as u32) << 18
+                     | ((b1 & !TAG_CONT) as u32) << 12
+                     | ((b2 & !TAG_CONT) as u32) << 6
+                     | ((b3 & !TAG_CONT) as u32);
+            match cp {
+                0x10000 ... 0x10FFFF => char::from_u32(cp).map(|cp| (cp, 4)),
+                _ => None,
+            }
+        }
+        _ => None,
+    }
+}
+
+/// Like decode_utf8, but decodes the last UTF-8 sequence in `src` instead of
+/// the first.
+pub fn decode_last_utf8(src: &[u8]) -> Option<(char, usize)> {
+    if src.is_empty() {
+        return None;
+    }
+    let mut start = src.len() - 1;
+    if src[start] <= 0x7F {
+        return Some((src[start] as char, 1));
+    }
+    while start > src.len().saturating_sub(4) {
+        start -= 1;
+        if is_start_byte(src[start]) {
+            break;
+        }
+    }
+    match decode_utf8(&src[start..]) {
+        None => None,
+        Some((_, n)) if n < src.len() - start => None,
+        Some((cp, n)) => Some((cp, n)),
+    }
+}
+
+fn is_start_byte(b: u8) -> bool {
+    b & 0b11_000000 != 0b1_0000000
+}
+
+#[cfg(test)]
+mod tests {
+    use std::str;
+
+    use quickcheck::quickcheck;
+
+    use super::{
+        TAG_CONT, TAG_TWO, TAG_THREE, TAG_FOUR,
+        decode_utf8, decode_last_utf8, encode_utf8,
+    };
+
+    #[test]
+    fn prop_roundtrip() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let encoded_len = encode_utf8(given_cp, &mut tmp).unwrap();
+            let (got_cp, got_len) = decode_utf8(&tmp[..encoded_len]).unwrap();
+            encoded_len == got_len && given_cp == got_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_roundtrip_last() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let encoded_len = encode_utf8(given_cp, &mut tmp).unwrap();
+            let (got_cp, got_len) =
+                decode_last_utf8(&tmp[..encoded_len]).unwrap();
+            encoded_len == got_len && given_cp == got_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_encode_matches_std() {
+        fn p(cp: char) -> bool {
+            let mut got = [0; 4];
+            let n = encode_utf8(cp, &mut got).unwrap();
+            let expected = cp.to_string();
+            &got[..n] == expected.as_bytes()
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_decode_matches_std() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let n = encode_utf8(given_cp, &mut tmp).unwrap();
+            let (got_cp, _) = decode_utf8(&tmp[..n]).unwrap();
+            let expected_cp =
+                str::from_utf8(&tmp[..n]).unwrap().chars().next().unwrap();
+            got_cp == expected_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn prop_decode_last_matches_std() {
+        fn p(given_cp: char) -> bool {
+            let mut tmp = [0; 4];
+            let n = encode_utf8(given_cp, &mut tmp).unwrap();
+            let (got_cp, _) = decode_last_utf8(&tmp[..n]).unwrap();
+            let expected_cp =
+                str::from_utf8(&tmp[..n]).unwrap()
+                    .chars().rev().next().unwrap();
+            got_cp == expected_cp
+        }
+        quickcheck(p as fn(char) -> bool)
+    }
+
+    #[test]
+    fn reject_invalid() {
+        // Invalid start byte
+        assert_eq!(decode_utf8(&[0xFF]), None);
+        // Surrogate pair
+        assert_eq!(decode_utf8(&[0xED, 0xA0, 0x81]), None);
+        // Invalid continuation byte.
+        assert_eq!(decode_utf8(&[0xD4, 0xC2]), None);
+        // Bad lengths
+        assert_eq!(decode_utf8(&[0xC3]), None); // 2 bytes
+        assert_eq!(decode_utf8(&[0xEF, 0xBF]), None); // 3 bytes
+        assert_eq!(decode_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
+        // Not a minimal UTF-8 sequence
+        assert_eq!(decode_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
+        assert_eq!(decode_utf8(&[TAG_THREE, TAG_CONT, TAG_CONT | b'a']), None);
+        assert_eq!(decode_utf8(&[
+            TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',
+        ]), None);
+    }
+
+    #[test]
+    fn reject_invalid_last() {
+        // Invalid start byte
+        assert_eq!(decode_last_utf8(&[0xFF]), None);
+        // Surrogate pair
+        assert_eq!(decode_last_utf8(&[0xED, 0xA0, 0x81]), None);
+        // Bad lengths
+        assert_eq!(decode_last_utf8(&[0xC3]), None); // 2 bytes
+        assert_eq!(decode_last_utf8(&[0xEF, 0xBF]), None); // 3 bytes
+        assert_eq!(decode_last_utf8(&[0xF4, 0x8F, 0xBF]), None); // 4 bytes
+        // Not a minimal UTF-8 sequence
+        assert_eq!(decode_last_utf8(&[TAG_TWO, TAG_CONT | b'a']), None);
+        assert_eq!(decode_last_utf8(&[
+            TAG_THREE, TAG_CONT, TAG_CONT | b'a',
+        ]), None);
+        assert_eq!(decode_last_utf8(&[
+            TAG_FOUR, TAG_CONT, TAG_CONT, TAG_CONT | b'a',
+        ]), None);
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/tests/api.rs b/third_party/rust/regex-0.2.2/tests/api.rs
new file mode 100644
index 000000000000..e17afa9332f4
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/api.rs
@@ -0,0 +1,182 @@
+#[test]
+fn empty_regex_empty_match() {
+    let re = regex!("");
+    assert_eq!(vec![(0, 0)], findall!(re, ""));
+}
+
+#[test]
+fn empty_regex_nonempty_match() {
+    let re = regex!("");
+    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
+}
+
+#[test]
+fn one_zero_length_match() {
+    let re = regex!(r"\d*");
+    assert_eq!(vec![(0, 0), (1, 2), (3, 4)], findall!(re, "a1b2"));
+}
+
+#[test]
+fn many_zero_length_match() {
+    let re = regex!(r"\d*");
+    assert_eq!(vec![(0, 0), (1, 2), (3, 3), (4, 4), (5, 6)],
+               findall!(re, "a1bbb2"));
+}
+
+#[test]
+fn many_sequential_zero_length_match() {
+    let re = regex!(r"\d?");
+    assert_eq!(vec![(0, 0), (1, 2), (2, 3), (4, 5), (6, 6)],
+               findall!(re, "a12b3c"));
+}
+
+#[test]
+fn quoted_bracket_set() {
+    let re = regex!(r"([\x{5b}\x{5d}])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+    let re = regex!(r"([\[\]])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn first_range_starts_with_left_bracket() {
+    let re = regex!(r"([\[-z])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn range_ends_with_escape() {
+    let re = regex!(r"([\[-\x{5d}])");
+    assert_eq!(vec![(0, 1), (1, 2)], findall!(re, "[]"));
+}
+
+#[test]
+fn empty_match_find_iter() {
+    let re = regex!(r".*?");
+    assert_eq!(vec![(0, 0), (1, 1), (2, 2), (3, 3)], findall!(re, "abc"));
+}
+
+#[test]
+fn empty_match_captures_iter() {
+    let re = regex!(r".*?");
+    let ms: Vec<_> = re.captures_iter(text!("abc"))
+                       .map(|c| c.get(0).unwrap())
+                       .map(|m| (m.start(), m.end()))
+                       .collect();
+    assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
+}
+
+#[test]
+fn capture_names() {
+    let re = regex!(r"(.)(?P<a>.)");
+    assert_eq!(3, re.captures_len());
+    assert_eq!((3, Some(3)), re.capture_names().size_hint());
+    assert_eq!(vec![None, None, Some("a")],
+               re.capture_names().collect::<Vec<_>>());
+}
+
+#[test]
+fn regex_string() {
+    assert_eq!(r"[a-zA-Z0-9]+", regex!(r"[a-zA-Z0-9]+").as_str());
+    assert_eq!(r"[a-zA-Z0-9]+", &format!("{}", regex!(r"[a-zA-Z0-9]+")));
+    assert_eq!(r"[a-zA-Z0-9]+", &format!("{:?}", regex!(r"[a-zA-Z0-9]+")));
+}
+
+#[test]
+fn capture_index() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    assert_eq!(&cap[0], t!("abc"));
+    assert_eq!(&cap[1], t!("abc"));
+    assert_eq!(&cap["name"], t!("abc"));
+}
+
+#[test]
+#[should_panic]
+#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
+fn capture_index_panic_usize() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    let _ = cap[2];
+}
+
+#[test]
+#[should_panic]
+#[cfg_attr(all(target_env = "msvc", target_pointer_width = "32"), ignore)]
+fn capture_index_panic_name() {
+    let re = regex!(r"^(?P<name>.+)$");
+    let cap = re.captures(t!("abc")).unwrap();
+    let _ = cap["bad name"];
+}
+
+#[test]
+fn capture_index_lifetime() {
+    // This is a test of whether the types on `caps["..."]` are general
+    // enough. If not, this will fail to typecheck.
+    fn inner(s: &str) -> usize {
+        let re = regex!(r"(?P<number>\d+)");
+        let caps = re.captures(t!(s)).unwrap();
+        caps["number"].len()
+    }
+    assert_eq!(3, inner("123"));
+}
+
+#[test]
+fn capture_misc() {
+    let re = regex!(r"(.)(?P<a>a)?(.)(?P<b>.)");
+    let cap = re.captures(t!("abc")).unwrap();
+
+    assert_eq!(5, cap.len());
+
+    assert_eq!((0, 3), { let m = cap.get(0).unwrap(); (m.start(), m.end()) });
+    assert_eq!(None, cap.get(2));
+    assert_eq!((2, 3), { let m = cap.get(4).unwrap(); (m.start(), m.end()) });
+
+    assert_eq!(t!("abc"), match_text!(cap.get(0).unwrap()));
+    assert_eq!(None, cap.get(2));
+    assert_eq!(t!("c"), match_text!(cap.get(4).unwrap()));
+
+    assert_eq!(None, cap.name("a"));
+    assert_eq!(t!("c"), match_text!(cap.name("b").unwrap()));
+}
+
+#[test]
+fn sub_capture_matches() {
+    let re = regex!(r"([a-z])(([a-z])|([0-9]))");
+    let cap = re.captures(t!("a5")).unwrap();
+    let subs: Vec<_> = cap.iter().collect();
+
+    assert_eq!(5, subs.len());
+    assert!(subs[0].is_some());
+    assert!(subs[1].is_some());
+    assert!(subs[2].is_some());
+    assert!(subs[3].is_none());
+    assert!(subs[4].is_some());
+
+    assert_eq!(t!("a5"), match_text!(subs[0].unwrap()));
+    assert_eq!(t!("a"), match_text!(subs[1].unwrap()));
+    assert_eq!(t!("5"), match_text!(subs[2].unwrap()));
+    assert_eq!(t!("5"), match_text!(subs[4].unwrap()));
+}
+
+expand!(expand1, r"(?P<foo>\w+)", "abc", "$foo", "abc");
+expand!(expand2, r"(?P<foo>\w+)", "abc", "$0", "abc");
+expand!(expand3, r"(?P<foo>\w+)", "abc", "$1", "abc");
+expand!(expand4, r"(?P<foo>\w+)", "abc", "$$1", "$1");
+expand!(expand5, r"(?P<foo>\w+)", "abc", "$$foo", "$foo");
+expand!(expand6, r"(?P<a>\w+)\s+(?P<b>\d+)",
+        "abc 123", "$b$a", "123abc");
+expand!(expand7, r"(?P<a>\w+)\s+(?P<b>\d+)",
+        "abc 123", "z$bz$az", "z");
+expand!(expand8, r"(?P<a>\w+)\s+(?P<b>\d+)",
+        "abc 123", ".$b.$a.", ".123.abc.");
+expand!(expand9, r"(?P<a>\w+)\s+(?P<b>\d+)",
+        "abc 123", " $b $a ", " 123 abc ");
+expand!(expand10, r"(?P<a>\w+)\s+(?P<b>\d+)",
+        "abc 123", "$bz$az", "");
+
+split!(split1, r"\s+", "a b\nc\td\n\t e",
+       &[t!("a"), t!("b"), t!("c"), t!("d"), t!("e")]);
+split!(split2, r"\b", "a b c",
+       &[t!(""), t!("a"), t!(" "), t!("b"), t!(" "), t!("c")]);
+split!(split3, r"a$", "a", &[t!("")]);
diff --git a/third_party/rust/regex-0.2.2/tests/api_str.rs b/third_party/rust/regex-0.2.2/tests/api_str.rs
new file mode 100644
index 000000000000..5bdca8426a8b
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/api_str.rs
@@ -0,0 +1,22 @@
+// These tests don't really make sense with the bytes API, so we only test them
+// on the Unicode API.
+
+#[test]
+fn empty_match_unicode_find_iter() {
+    // Tests that we still yield byte ranges at valid UTF-8 sequence boundaries
+    // even when we're susceptible to empty width matches.
+    let re = regex!(r".*?");
+    assert_eq!(vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)],
+               findall!(re, "Ⅰ1Ⅱ2"));
+}
+
+#[test]
+fn empty_match_unicode_captures_iter() {
+    // Same as empty_match_unicode_find_iter, but tests capture iteration.
+    let re = regex!(r".*?");
+    let ms: Vec<_> = re.captures_iter(text!("Ⅰ1Ⅱ2"))
+                       .map(|c| c.get(0).unwrap())
+                       .map(|m| (m.start(), m.end()))
+                       .collect();
+    assert_eq!(vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)], ms);
+}
diff --git a/third_party/rust/regex-0.2.2/tests/bytes.rs b/third_party/rust/regex-0.2.2/tests/bytes.rs
new file mode 100644
index 000000000000..9d472aa518d7
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/bytes.rs
@@ -0,0 +1,62 @@
+// These are tests specifically crafted for regexes that can match arbitrary
+// bytes.
+
+// A silly wrapper to make it possible to write and match raw bytes.
+struct R<'a>(&'a [u8]);
+impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { &self.0 } }
+
+mat!(word_boundary, r"(?-u) \b", " δ", None);
+mat!(word_boundary_unicode, r" \b", " δ", Some((0, 1)));
+mat!(word_not_boundary, r"(?-u) \B", " δ", Some((0, 1)));
+mat!(word_not_boundary_unicode, r" \B", " δ", None);
+
+mat!(perl_w_ascii, r"(?-u)\w+", "aδ", Some((0, 1)));
+mat!(perl_w_unicode, r"\w+", "aδ", Some((0, 3)));
+mat!(perl_d_ascii, r"(?-u)\d+", "1२३9", Some((0, 1)));
+mat!(perl_d_unicode, r"\d+", "1२३9", Some((0, 8)));
+mat!(perl_s_ascii, r"(?-u)\s+", " \u{1680}", Some((0, 1)));
+mat!(perl_s_unicode, r"\s+", " \u{1680}", Some((0, 4)));
+
+// The first `(.+)` matches two Unicode codepoints, but can't match the 5th
+// byte, which isn't valid UTF-8. The second (byte based) `(.+)` takes over and
+// matches.
+mat!(mixed1, r"(.+)(?-u)(.+)", R(b"\xCE\x93\xCE\x94\xFF"),
+     Some((0, 5)), Some((0, 4)), Some((4, 5)));
+
+mat!(case_ascii_one, r"(?i-u)a", "A", Some((0, 1)));
+mat!(case_ascii_class, r"(?i-u)[a-z]+", "AaAaA", Some((0, 5)));
+mat!(case_unicode, r"(?i)[a-z]+", "aA\u{212A}aA", Some((0, 7)));
+mat!(case_not_unicode, r"(?i-u)[a-z]+", "aA\u{212A}aA", Some((0, 2)));
+
+mat!(negate_unicode, r"[^a]", "δ", Some((0, 2)));
+mat!(negate_not_unicode, r"(?-u)[^a]", "δ", Some((0, 1)));
+
+// This doesn't match in a normal Unicode regex because the implicit preceding
+// `.*?` is Unicode aware.
+mat!(dotstar_prefix_not_unicode1, r"(?-u)a", R(b"\xFFa"), Some((1, 2)));
+mat!(dotstar_prefix_not_unicode2, r"a", R(b"\xFFa"), Some((1, 2)));
+
+// Have fun with null bytes.
+mat!(null_bytes, r"(?-u)(?P<cstr>[^\x00]+)\x00",
+     R(b"foo\x00"), Some((0, 4)), Some((0, 3)));
+
+// Test that lookahead operators work properly in the face of invalid UTF-8.
+// See: https://github.com/rust-lang/regex/issues/277
+matiter!(invalidutf8_anchor1,
+         r"(?-u)\xcc?^",
+         R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+         (0, 0));
+matiter!(invalidutf8_anchor2,
+         r"(?-u)^\xf7|4\xff\d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########[] d\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a##########\[] #####\x80\S7|$",
+         R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+         (22, 22));
+matiter!(invalidutf8_anchor3,
+         r"(?-u)^|ddp\xff\xffdddddlQd@\x80",
+         R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
+         (0, 0));
+
+// See https://github.com/rust-lang/regex/issues/303
+#[test]
+fn negated_full_byte_range() {
+     assert!(::regex::bytes::Regex::new(r#"(?-u)[^\x00-\xff]"#).is_err());
+}
diff --git a/third_party/rust/regex-0.2.2/tests/crazy.rs b/third_party/rust/regex-0.2.2/tests/crazy.rs
new file mode 100644
index 000000000000..ade839ade134
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/crazy.rs
@@ -0,0 +1,78 @@
+mat!(ascii_literal, r"a", "a", Some((0, 1)));
+
+// Some crazy expressions from regular-expressions.info.
+mat!(match_ranges,
+     r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
+     "num: 255", Some((5, 8)));
+mat!(match_ranges_not,
+     r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
+     "num: 256", None);
+mat!(match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3)));
+mat!(match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3)));
+mat!(match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4)));
+mat!(match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None);
+mat!(match_email, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+     "mine is jam.slam@gmail.com ", Some((8, 26)));
+mat!(match_email_not, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+     "mine is jam.slam@gmail ", None);
+mat!(match_email_big, r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
+     "mine is jam.slam@gmail.com ", Some((8, 26)));
+mat!(match_date1,
+     r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+     "1900-01-01", Some((0, 10)));
+mat!(match_date2,
+     r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+     "1900-00-01", None);
+mat!(match_date3,
+     r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
+     "1900-13-01", None);
+
+// Do some crazy dancing with the start/end assertions.
+matiter!(match_start_end_empty, r"^$", "", (0, 0));
+matiter!(match_start_end_empty_many_1, r"^$^$^$", "", (0, 0));
+matiter!(match_start_end_empty_many_2, r"^^^$$$", "", (0, 0));
+matiter!(match_start_end_empty_rev, r"$^", "", (0, 0));
+matiter!(match_start_end_empty_rep, r"(?:^$)*", "a\nb\nc",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+matiter!(match_start_end_empty_rep_rev, r"(?:$^)*", "a\nb\nc",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+
+// Test negated character classes.
+mat!(negclass_letters, r"[^ac]", "acx", Some((2, 3)));
+mat!(negclass_letter_comma, r"[^a,]", "a,x", Some((2, 3)));
+mat!(negclass_letter_space, r"[^a\s]", "a x", Some((2, 3)));
+mat!(negclass_comma, r"[^,]", ",,x", Some((2, 3)));
+mat!(negclass_space, r"[^\s]", " a", Some((1, 2)));
+mat!(negclass_space_comma, r"[^,\s]", ", a", Some((2, 3)));
+mat!(negclass_comma_space, r"[^\s,]", " ,a", Some((2, 3)));
+mat!(negclass_ascii, r"[^[:alpha:]Z]", "A1", Some((1, 2)));
+
+// Test that the DFA can handle pathological cases.
+// (This should result in the DFA's cache being flushed too frequently, which
+// should cause it to quit and fall back to the NFA algorithm.)
+#[test]
+fn dfa_handles_pathological_case() {
+    fn ones_and_zeroes(count: usize) -> String {
+        use rand::{Rng, thread_rng};
+
+        let mut rng = thread_rng();
+        let mut s = String::new();
+        for _ in 0..count {
+            if rng.gen() {
+                s.push('1');
+            } else {
+                s.push('0');
+            }
+        }
+        s
+    }
+
+    let re = regex!(r"[01]*1[01]{20}$");
+    let text = {
+        let mut pieces = ones_and_zeroes(100_000);
+        pieces.push('1');
+        pieces.push_str(&ones_and_zeroes(20));
+        pieces
+    };
+    assert!(re.is_match(text!(&*text)));
+}
diff --git a/third_party/rust/regex-0.2.2/tests/flags.rs b/third_party/rust/regex-0.2.2/tests/flags.rs
new file mode 100644
index 000000000000..0c9b36c91c8e
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/flags.rs
@@ -0,0 +1,11 @@
+mat!(match_flag_case, "(?i)abc", "ABC", Some((0, 3)));
+mat!(match_flag_weird_case, "(?i)a(?-i)bc", "Abc", Some((0, 3)));
+mat!(match_flag_weird_case_not, "(?i)a(?-i)bc", "ABC", None);
+mat!(match_flag_case_dotnl, "(?is)a.", "A\n", Some((0, 2)));
+mat!(match_flag_case_dotnl_toggle, "(?is)a.(?-is)a.", "A\nab", Some((0, 4)));
+mat!(match_flag_case_dotnl_toggle_not, "(?is)a.(?-is)a.", "A\na\n", None);
+mat!(match_flag_case_dotnl_toggle_ok, "(?is)a.(?-is:a.)?", "A\na\n", Some((0, 2)));
+mat!(match_flag_multi, "(?m)(?:^\\d+$\n?)+", "123\n456\n789", Some((0, 11)));
+mat!(match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1)));
+mat!(match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2)));
+mat!(match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2)));
diff --git a/third_party/rust/regex-0.2.2/tests/fowler.rs b/third_party/rust/regex-0.2.2/tests/fowler.rs
new file mode 100644
index 000000000000..a4d1a5bdfbc0
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/fowler.rs
@@ -0,0 +1,371 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// DO NOT EDIT. Automatically generated by 'scripts/regex-match-tests.py'
+// on 2015-02-28 11:00:00.161706.
+
+// Tests from basic.dat
+mat!(match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18)));
+mat!(match_basic_4, r"a...b", r"abababbb", Some((2, 7)));
+mat!(match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8)));
+mat!(match_basic_6, r"\)", r"()", Some((1, 2)));
+mat!(match_basic_7, r"a]", r"a]a", Some((0, 2)));
+mat!(match_basic_9, r"\}", r"}", Some((0, 1)));
+mat!(match_basic_10, r"\]", r"]", Some((0, 1)));
+mat!(match_basic_12, r"]", r"]", Some((0, 1)));
+mat!(match_basic_15, r"^a", r"ax", Some((0, 1)));
+mat!(match_basic_16, r"\^a", r"a^a", Some((1, 3)));
+mat!(match_basic_17, r"a\^", r"a^", Some((0, 2)));
+mat!(match_basic_18, r"a$", r"aa", Some((1, 2)));
+mat!(match_basic_19, r"a\$", r"a$", Some((0, 2)));
+mat!(match_basic_20, r"^$", r"", Some((0, 0)));
+mat!(match_basic_21, r"$^", r"", Some((0, 0)));
+mat!(match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2)));
+mat!(match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_24, r"(..)*(...)*", r"a", Some((0, 0)));
+mat!(match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4)));
+mat!(match_basic_26, r"(ab|a)(bc|c)", r"abc", Some((0, 3)), Some((0, 2)), Some((2, 3)));
+mat!(match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2)));
+mat!(match_basic_28, r"a{0}b", r"ab", Some((1, 2)));
+mat!(match_basic_29, r"(a*)(b?)(b+)b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7)));
+mat!(match_basic_30, r"(a*)(b{0,1})(b{1,})b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7)));
+mat!(match_basic_32, r"((a|a)|a)", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)));
+mat!(match_basic_33, r"(a*)(a|aa)", r"aaaa", Some((0, 4)), Some((0, 3)), Some((3, 4)));
+mat!(match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4)));
+mat!(match_basic_35, r"a(b)|c(d)|a(e)f", r"aef", Some((0, 3)), None, None, Some((1, 2)));
+mat!(match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1)));
+mat!(match_basic_38, r"(a|b)c|a(b|c)", r"ab", Some((0, 2)), None, Some((1, 2)));
+mat!(match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2)));
+mat!(match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2)));
+mat!(match_basic_41, r"(.a|.b).*|.*(.a|.b)", r"xa", Some((0, 2)), Some((0, 2)));
+mat!(match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
+mat!(match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2)));
+mat!(match_basic_44, r"ab|abab", r"abbabab", Some((0, 2)));
+mat!(match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8)));
+mat!(match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9)));
+mat!(match_basic_47, r"(aa|aaa)*|(a|aaaaa)", r"aa", Some((0, 2)), Some((0, 2)));
+mat!(match_basic_48, r"(a.|.a.)*|(a|.a...)", r"aa", Some((0, 2)), Some((0, 2)));
+mat!(match_basic_49, r"ab|a", r"xabc", Some((1, 3)));
+mat!(match_basic_50, r"ab|a", r"xxabc", Some((2, 4)));
+mat!(match_basic_51, r"(?i)(Ab|cD)*", r"aBcD", Some((0, 4)), Some((2, 4)));
+mat!(match_basic_52, r"[^-]", r"--a", Some((2, 3)));
+mat!(match_basic_53, r"[a-]*", r"--a", Some((0, 3)));
+mat!(match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4)));
+mat!(match_basic_55, r":::1:::0:|:::1:1:0:", r":::0:::1:::1:::0:", Some((8, 17)));
+mat!(match_basic_56, r":::1:::0:|:::1:1:1:", r":::0:::1:::1:::0:", Some((8, 17)));
+mat!(match_basic_57, r"[[:upper:]]", r"A", Some((0, 1)));
+mat!(match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3)));
+mat!(match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3)));
+mat!(match_basic_65, r"
+", r"
+", Some((0, 1)));
+mat!(match_basic_66, r"
+", r"
+", Some((0, 1)));
+mat!(match_basic_67, r"[^a]", r"
+", Some((0, 1)));
+mat!(match_basic_68, r"
+a", r"
+a", Some((0, 2)));
+mat!(match_basic_69, r"(a)(b)(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((2, 3)));
+mat!(match_basic_70, r"xxx", r"xxx", Some((0, 3)));
+mat!(match_basic_71, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 6,", Some((0, 6)));
+mat!(match_basic_72, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"2/7", Some((0, 3)));
+mat!(match_basic_73, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 1,Feb 6", Some((5, 11)));
+mat!(match_basic_74, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))", r"x", Some((0, 1)), Some((0, 1)), Some((0, 1)));
+mat!(match_basic_75, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*", r"xx", Some((0, 2)), Some((1, 2)), Some((1, 2)));
+mat!(match_basic_76, r"a?(ab|ba)*", r"ababababababababababababababababababababababababababababababababababababababababa", Some((0, 81)), Some((79, 81)));
+mat!(match_basic_77, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabbbbaa", Some((18, 25)));
+mat!(match_basic_78, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabaa", Some((18, 22)));
+mat!(match_basic_79, r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc", r"baaabbbabac", Some((7, 11)));
+mat!(match_basic_80, r".*", r"", Some((0, 2)));
+mat!(match_basic_81, r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll", r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa", Some((53, 57)));
+mat!(match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10)));
+mat!(match_basic_84, r"^", r"", Some((0, 0)));
+mat!(match_basic_85, r"$", r"", Some((0, 0)));
+mat!(match_basic_86, r"^$", r"", Some((0, 0)));
+mat!(match_basic_87, r"^a$", r"a", Some((0, 1)));
+mat!(match_basic_88, r"abc", r"abc", Some((0, 3)));
+mat!(match_basic_89, r"abc", r"xabcy", Some((1, 4)));
+mat!(match_basic_90, r"abc", r"ababc", Some((2, 5)));
+mat!(match_basic_91, r"ab*c", r"abc", Some((0, 3)));
+mat!(match_basic_92, r"ab*bc", r"abc", Some((0, 3)));
+mat!(match_basic_93, r"ab*bc", r"abbc", Some((0, 4)));
+mat!(match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6)));
+mat!(match_basic_95, r"ab+bc", r"abbc", Some((0, 4)));
+mat!(match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6)));
+mat!(match_basic_97, r"ab?bc", r"abbc", Some((0, 4)));
+mat!(match_basic_98, r"ab?bc", r"abc", Some((0, 3)));
+mat!(match_basic_99, r"ab?c", r"abc", Some((0, 3)));
+mat!(match_basic_100, r"^abc$", r"abc", Some((0, 3)));
+mat!(match_basic_101, r"^abc", r"abcc", Some((0, 3)));
+mat!(match_basic_102, r"abc$", r"aabc", Some((1, 4)));
+mat!(match_basic_103, r"^", r"abc", Some((0, 0)));
+mat!(match_basic_104, r"$", r"abc", Some((3, 3)));
+mat!(match_basic_105, r"a.c", r"abc", Some((0, 3)));
+mat!(match_basic_106, r"a.c", r"axc", Some((0, 3)));
+mat!(match_basic_107, r"a.*c", r"axyzc", Some((0, 5)));
+mat!(match_basic_108, r"a[bc]d", r"abd", Some((0, 3)));
+mat!(match_basic_109, r"a[b-d]e", r"ace", Some((0, 3)));
+mat!(match_basic_110, r"a[b-d]", r"aac", Some((1, 3)));
+mat!(match_basic_111, r"a[-b]", r"a-", Some((0, 2)));
+mat!(match_basic_112, r"a[b-]", r"a-", Some((0, 2)));
+mat!(match_basic_113, r"a]", r"a]", Some((0, 2)));
+mat!(match_basic_114, r"a[]]b", r"a]b", Some((0, 3)));
+mat!(match_basic_115, r"a[^bc]d", r"aed", Some((0, 3)));
+mat!(match_basic_116, r"a[^-b]c", r"adc", Some((0, 3)));
+mat!(match_basic_117, r"a[^]b]c", r"adc", Some((0, 3)));
+mat!(match_basic_118, r"ab|cd", r"abc", Some((0, 2)));
+mat!(match_basic_119, r"ab|cd", r"abcd", Some((0, 2)));
+mat!(match_basic_120, r"a\(b", r"a(b", Some((0, 3)));
+mat!(match_basic_121, r"a\(*b", r"ab", Some((0, 2)));
+mat!(match_basic_122, r"a\(*b", r"a((b", Some((0, 4)));
+mat!(match_basic_123, r"((a))", r"abc", Some((0, 1)), Some((0, 1)), Some((0, 1)));
+mat!(match_basic_124, r"(a)b(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((2, 3)));
+mat!(match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7)));
+mat!(match_basic_126, r"a*", r"aaa", Some((0, 3)));
+mat!(match_basic_128, r"(a*)*", r"-", Some((0, 0)), None);
+mat!(match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0)));
+mat!(match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None);
+mat!(match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2)));
+mat!(match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2)));
+mat!(match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1)));
+mat!(match_basic_135, r"[^ab]*", r"cde", Some((0, 3)));
+mat!(match_basic_137, r"(^)*", r"-", Some((0, 0)), None);
+mat!(match_basic_138, r"a*", r"", Some((0, 0)));
+mat!(match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5)));
+mat!(match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1)));
+mat!(match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1)));
+mat!(match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1)));
+mat!(match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None);
+mat!(match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7)));
+mat!(match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3)));
+mat!(match_basic_147, r"ab*", r"xayabbbz", Some((1, 2)));
+mat!(match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4)));
+mat!(match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3)));
+mat!(match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2)));
+mat!(match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1)));
+mat!(match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3)));
+mat!(match_basic_153, r"a([bc]*)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4)));
+mat!(match_basic_154, r"a([bc]+)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4)));
+mat!(match_basic_155, r"a([bc]*)(c+d)", r"abcd", Some((0, 4)), Some((1, 2)), Some((2, 4)));
+mat!(match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7)));
+mat!(match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2)));
+mat!(match_basic_158, r"((a)(b)c)(d)", r"abcd", Some((0, 4)), Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((3, 4)));
+mat!(match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5)));
+mat!(match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3)));
+mat!(match_basic_161, r"(bc+d$|ef*g.|h?i(j|k))", r"effgz", Some((0, 5)), Some((0, 5)));
+mat!(match_basic_162, r"(bc+d$|ef*g.|h?i(j|k))", r"ij", Some((0, 2)), Some((0, 2)), Some((1, 2)));
+mat!(match_basic_163, r"(bc+d$|ef*g.|h?i(j|k))", r"reffgz", Some((1, 6)), Some((1, 6)));
+mat!(match_basic_164, r"(((((((((a)))))))))", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)));
+mat!(match_basic_165, r"multiple words", r"multiple words yeah", Some((0, 14)));
+mat!(match_basic_166, r"(.*)c(.*)", r"abcde", Some((0, 5)), Some((0, 2)), Some((3, 5)));
+mat!(match_basic_167, r"abcd", r"abcd", Some((0, 4)));
+mat!(match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3)));
+mat!(match_basic_169, r"a[-]?c", r"ac", Some((0, 3)));
+mat!(match_basic_170, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qaddafi", Some((0, 15)), None, Some((10, 12)));
+mat!(match_basic_171, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mo'ammar Gadhafi", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_172, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Kaddafi", Some((0, 15)), None, Some((10, 12)));
+mat!(match_basic_173, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qadhafi", Some((0, 15)), None, Some((10, 12)));
+mat!(match_basic_174, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gadafi", Some((0, 14)), None, Some((10, 11)));
+mat!(match_basic_175, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadafi", Some((0, 15)), None, Some((11, 12)));
+mat!(match_basic_176, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moamar Gaddafi", Some((0, 14)), None, Some((9, 11)));
+mat!(match_basic_177, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadhdhafi", Some((0, 18)), None, Some((13, 15)));
+mat!(match_basic_178, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Khaddafi", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_179, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafy", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_180, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghadafi", Some((0, 15)), None, Some((11, 12)));
+mat!(match_basic_181, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafi", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_182, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muamar Kaddafi", Some((0, 14)), None, Some((9, 11)));
+mat!(match_basic_183, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Quathafi", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_184, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gheddafi", Some((0, 16)), None, Some((11, 13)));
+mat!(match_basic_185, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Khadafy", Some((0, 15)), None, Some((11, 12)));
+mat!(match_basic_186, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Qudhafi", Some((0, 15)), None, Some((10, 12)));
+mat!(match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4)));
+mat!(match_basic_188, r"^.+$", r"vivi", Some((0, 4)));
+mat!(match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_190, r"^([^!.]+).att.com!(.+)$", r"gryphon.att.com!eby", Some((0, 19)), Some((0, 7)), Some((16, 19)));
+mat!(match_basic_191, r"^([^!]+!)?([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3)));
+mat!(match_basic_192, r"^([^!]+!)?([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_193, r"^([^!]+!)?([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_194, r"^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), Some((4, 8)), Some((8, 11)));
+mat!(match_basic_195, r"((foo)|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), None, Some((0, 3)));
+mat!(match_basic_196, r"((foo)|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), None, Some((4, 7)));
+mat!(match_basic_197, r"((foo)|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)));
+mat!(match_basic_198, r"((foo)|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3)));
+mat!(match_basic_199, r"((foo)|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)));
+mat!(match_basic_200, r"((foo)|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)));
+mat!(match_basic_201, r"(foo|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)));
+mat!(match_basic_202, r"(foo|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), Some((4, 7)));
+mat!(match_basic_203, r"(foo|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)));
+mat!(match_basic_204, r"(foo|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3)));
+mat!(match_basic_205, r"(foo|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)));
+mat!(match_basic_206, r"(foo|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)));
+mat!(match_basic_207, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)));
+mat!(match_basic_208, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3)));
+mat!(match_basic_209, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_210, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)));
+mat!(match_basic_211, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_212, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bas", Some((0, 3)), Some((0, 3)), None, Some((0, 3)));
+mat!(match_basic_213, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bar!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_214, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)));
+mat!(match_basic_215, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7)));
+mat!(match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_218, r"\\XXX", r"\XXX", Some((0, 4)));
+mat!(match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4)));
+mat!(match_basic_221, r"\\000", r"\000", Some((0, 4)));
+
+// Tests from nullsubexpr.dat
+mat!(match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None);
+mat!(match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0)));
+mat!(match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0)));
+mat!(match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_17, r"(a+)+", r"x", None);
+mat!(match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None);
+mat!(match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0)));
+mat!(match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None);
+mat!(match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_34, r"([^b]*)*", r"aaaaaab", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_41, r"([ab]*)*", r"aaaabcde", Some((0, 5)), Some((0, 5)));
+mat!(match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1)));
+mat!(match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None);
+mat!(match_nullsubexpr_46, r"([^ab]*)*", r"ccccxx", Some((0, 6)), Some((0, 6)));
+mat!(match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None);
+mat!(match_nullsubexpr_50, r"((z)+|a)*", r"zabcde", Some((0, 2)), Some((1, 2)));
+mat!(match_nullsubexpr_69, r"(a*)*(x)", r"x", Some((0, 1)), None, Some((0, 1)));
+mat!(match_nullsubexpr_70, r"(a*)*(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2)));
+mat!(match_nullsubexpr_71, r"(a*)*(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2)));
+mat!(match_nullsubexpr_73, r"(a*)+(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1)));
+mat!(match_nullsubexpr_74, r"(a*)+(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2)));
+mat!(match_nullsubexpr_75, r"(a*)+(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2)));
+mat!(match_nullsubexpr_77, r"(a*){2}(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1)));
+mat!(match_nullsubexpr_78, r"(a*){2}(x)", r"ax", Some((0, 2)), Some((1, 1)), Some((1, 2)));
+mat!(match_nullsubexpr_79, r"(a*){2}(x)", r"axa", Some((0, 2)), Some((1, 1)), Some((1, 2)));
+
+// Tests from repetition.dat
+mat!(match_repetition_10, r"((..)|(.))", r"", None);
+mat!(match_repetition_11, r"((..)|(.))((..)|(.))", r"", None);
+mat!(match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None);
+mat!(match_repetition_14, r"((..)|(.)){1}", r"", None);
+mat!(match_repetition_15, r"((..)|(.)){2}", r"", None);
+mat!(match_repetition_16, r"((..)|(.)){3}", r"", None);
+mat!(match_repetition_18, r"((..)|(.))*", r"", Some((0, 0)));
+mat!(match_repetition_20, r"((..)|(.))", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)));
+mat!(match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None);
+mat!(match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None);
+mat!(match_repetition_24, r"((..)|(.)){1}", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)));
+mat!(match_repetition_25, r"((..)|(.)){2}", r"a", None);
+mat!(match_repetition_26, r"((..)|(.)){3}", r"a", None);
+mat!(match_repetition_28, r"((..)|(.))*", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)));
+mat!(match_repetition_30, r"((..)|(.))", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_31, r"((..)|(.))((..)|(.))", r"aa", Some((0, 2)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)));
+mat!(match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None);
+mat!(match_repetition_34, r"((..)|(.)){1}", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_35, r"((..)|(.)){2}", r"aa", Some((0, 2)), Some((1, 2)), None, Some((1, 2)));
+mat!(match_repetition_36, r"((..)|(.)){3}", r"aa", None);
+mat!(match_repetition_38, r"((..)|(.))*", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_40, r"((..)|(.))", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_41, r"((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)));
+mat!(match_repetition_42, r"((..)|(.))((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)), Some((2, 3)), None, Some((2, 3)));
+mat!(match_repetition_44, r"((..)|(.)){1}", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_46, r"((..)|(.)){2}", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3)));
+mat!(match_repetition_47, r"((..)|(.)){3}", r"aaa", Some((0, 3)), Some((2, 3)), None, Some((2, 3)));
+mat!(match_repetition_50, r"((..)|(.))*", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3)));
+mat!(match_repetition_52, r"((..)|(.))", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_53, r"((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_54, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)), Some((3, 4)), None, Some((3, 4)));
+mat!(match_repetition_56, r"((..)|(.)){1}", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_57, r"((..)|(.)){2}", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_59, r"((..)|(.)){3}", r"aaaa", Some((0, 4)), Some((3, 4)), Some((0, 2)), Some((3, 4)));
+mat!(match_repetition_61, r"((..)|(.))*", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_63, r"((..)|(.))", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_64, r"((..)|(.))((..)|(.))", r"aaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_65, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaa", Some((0, 5)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 5)), None, Some((4, 5)));
+mat!(match_repetition_67, r"((..)|(.)){1}", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_68, r"((..)|(.)){2}", r"aaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_70, r"((..)|(.)){3}", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5)));
+mat!(match_repetition_73, r"((..)|(.))*", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5)));
+mat!(match_repetition_75, r"((..)|(.))", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_76, r"((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_77, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 6)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 6)), Some((4, 6)), None);
+mat!(match_repetition_79, r"((..)|(.)){1}", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None);
+mat!(match_repetition_80, r"((..)|(.)){2}", r"aaaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None);
+mat!(match_repetition_81, r"((..)|(.)){3}", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None);
+mat!(match_repetition_83, r"((..)|(.))*", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None);
+mat!(match_repetition_90, r"X(.?){0,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_91, r"X(.?){1,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_92, r"X(.?){2,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_93, r"X(.?){3,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_94, r"X(.?){4,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_95, r"X(.?){5,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_96, r"X(.?){6,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_97, r"X(.?){7,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)));
+mat!(match_repetition_98, r"X(.?){8,}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_100, r"X(.?){0,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_102, r"X(.?){1,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_104, r"X(.?){2,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_106, r"X(.?){3,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_108, r"X(.?){4,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_110, r"X(.?){5,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_112, r"X(.?){6,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_114, r"X(.?){7,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_115, r"X(.?){8,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)));
+mat!(match_repetition_126, r"(a|ab|c|bcd){0,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_127, r"(a|ab|c|bcd){1,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_128, r"(a|ab|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)));
+mat!(match_repetition_129, r"(a|ab|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)));
+mat!(match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None);
+mat!(match_repetition_131, r"(a|ab|c|bcd){0,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_132, r"(a|ab|c|bcd){1,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_133, r"(a|ab|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)));
+mat!(match_repetition_134, r"(a|ab|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)));
+mat!(match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None);
+mat!(match_repetition_136, r"(a|ab|c|bcd)*(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_137, r"(a|ab|c|bcd)+(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)));
+mat!(match_repetition_143, r"(ab|a|c|bcd){0,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_145, r"(ab|a|c|bcd){1,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_147, r"(ab|a|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_149, r"(ab|a|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None);
+mat!(match_repetition_152, r"(ab|a|c|bcd){0,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_154, r"(ab|a|c|bcd){1,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_156, r"(ab|a|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_158, r"(ab|a|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None);
+mat!(match_repetition_161, r"(ab|a|c|bcd)*(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+mat!(match_repetition_163, r"(ab|a|c|bcd)+(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)));
+
diff --git a/third_party/rust/regex-0.2.2/tests/macros.rs b/third_party/rust/regex-0.2.2/tests/macros.rs
new file mode 100644
index 000000000000..2cd1463b4e27
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/macros.rs
@@ -0,0 +1,149 @@
+// Convenience macros.
+
+macro_rules! findall {
+    ($re:expr, $text:expr) => {{
+        $re.find_iter(text!($text))
+           .map(|m| (m.start(), m.end())).collect::<Vec<_>>()
+    }}
+}
+
+// Macros for automatically producing tests.
+
+macro_rules! ismatch {
+    ($name:ident, $re:expr, $text:expr, $ismatch:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            assert!($ismatch == re.is_match(text!($text)));
+        }
+    };
+}
+
+macro_rules! mat(
+    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<Option<_>> = vec![$($loc)+];
+            let r = regex!($re);
+            let got: Vec<Option<_>> = match r.captures(text) {
+                Some(c) => {
+                    assert!(r.is_match(text));
+                    assert!(r.shortest_match(text).is_some());
+                    r.capture_names()
+                     .enumerate()
+                     .map(|(i, _)| c.get(i).map(|m| (m.start(), m.end())))
+                     .collect()
+                }
+                None => vec![None],
+            };
+            // The test set sometimes leave out capture groups, so truncate
+            // actual capture groups to match test set.
+            let mut sgot = &got[..];
+            if sgot.len() > expected.len() {
+                sgot = &sgot[0..expected.len()]
+            }
+            if expected != sgot {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, sgot);
+            }
+        }
+    );
+);
+
+macro_rules! matiter(
+    ($name:ident, $re:expr, $text:expr) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<(usize, usize)> = vec![];
+            let r = regex!($re);
+            let got: Vec<_> =
+                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
+            if expected != got {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, got);
+            }
+            let captures_got: Vec<_> =
+                r.captures_iter(text)
+                 .map(|c| c.get(0).unwrap())
+                 .map(|m| (m.start(), m.end()))
+                 .collect();
+            if captures_got != got {
+                panic!("For RE '{}' against '{:?}', \
+                        got '{:?}' using find_iter but got '{:?}' \
+                        using captures_iter",
+                       $re, text, got, captures_got);
+            }
+        }
+    );
+    ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let expected: Vec<_> = vec![$($loc)+];
+            let r = regex!($re);
+            let got: Vec<_> =
+                r.find_iter(text).map(|m| (m.start(), m.end())).collect();
+            if expected != got {
+                panic!("For RE '{}' against '{:?}', \
+                        expected '{:?}' but got '{:?}'",
+                       $re, text, expected, got);
+            }
+            let captures_got: Vec<_> =
+                r.captures_iter(text)
+                 .map(|c| c.get(0).unwrap())
+                 .map(|m| (m.start(), m.end()))
+                 .collect();
+            if captures_got != got {
+                panic!("For RE '{}' against '{:?}', \
+                        got '{:?}' using find_iter but got '{:?}' \
+                        using captures_iter",
+                       $re, text, got, captures_got);
+            }
+        }
+    );
+);
+
+macro_rules! matset {
+    ($name:ident, $res:expr, $text:expr, $($match_index:expr),*) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let set = regex_set!($res);
+            assert!(set.is_match(text));
+            let expected = vec![$($match_index),*];
+            let matches = set.matches(text);
+            assert!(matches.matched_any());
+            let got: Vec<_> = matches.into_iter().collect();
+            assert_eq!(expected, got);
+        }
+    }
+}
+
+macro_rules! nomatset {
+    ($name:ident, $res:expr, $text:expr) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let set = regex_set!($res);
+            assert!(!set.is_match(text));
+            let matches = set.matches(text);
+            assert!(!matches.matched_any());
+            assert_eq!(0, matches.into_iter().count());
+        }
+    }
+}
+
+macro_rules! split {
+    ($name:ident, $re:expr, $text:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let splitted: Vec<_> = re.split(t!($text)).collect();
+            assert_eq!($expected, &*splitted);
+        }
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/tests/macros_bytes.rs b/third_party/rust/regex-0.2.2/tests/macros_bytes.rs
new file mode 100644
index 000000000000..4a382c78dd9f
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/macros_bytes.rs
@@ -0,0 +1,41 @@
+// Macros for use in writing tests generic over &str/&[u8].
+macro_rules! text { ($text:expr) => { $text.as_bytes() } }
+macro_rules! t { ($re:expr) => { text!($re) } }
+macro_rules! match_text { ($text:expr) => { $text.as_bytes() } }
+
+macro_rules! bytes { ($text:expr) => { $text } }
+macro_rules! b { ($text:expr) => { bytes!($text) } }
+
+// macro_rules! u { ($re:expr) => { concat!("(?u)", $re) } }
+
+macro_rules! no_expand {
+    ($text:expr) => {{
+        use regex::bytes::NoExpand;
+        NoExpand(text!($text))
+    }}
+}
+
+macro_rules! show {
+    ($text:expr) => {{
+        use std::ascii::escape_default;
+        let mut s = vec![];
+        for &b in bytes!($text) {
+            s.extend(escape_default(b));
+        }
+        String::from_utf8(s).unwrap()
+    }}
+}
+
+macro_rules! expand {
+    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let cap = re.captures(t!($text)).unwrap();
+
+            let mut got = vec![];
+            cap.expand(t!($expand), &mut got);
+            assert_eq!(show!(t!($expected)), show!(&*got));
+        }
+    }
+}
diff --git a/third_party/rust/regex-0.2.2/tests/macros_str.rs b/third_party/rust/regex-0.2.2/tests/macros_str.rs
new file mode 100644
index 000000000000..e5b0e219daa9
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/macros_str.rs
@@ -0,0 +1,40 @@
+// Macros for use in writing tests generic over &str/&[u8].
+macro_rules! text { ($text:expr) => { $text } }
+macro_rules! t { ($text:expr) => { text!($text) } }
+macro_rules! match_text { ($text:expr) => { $text.as_str() } }
+
+macro_rules! bytes { ($text:expr) => { $text.as_bytes() } }
+macro_rules! b { ($text:expr) => { bytes!($text) } }
+
+// macro_rules! u { ($re:expr) => { $re } }
+
+macro_rules! no_expand {
+    ($text:expr) => {{
+        use regex::NoExpand;
+        NoExpand(text!($text))
+    }}
+}
+
+macro_rules! show { ($text:expr) => { $text } }
+
+// N.B. The expansion API for &str and &[u8] APIs differs slightly for now,
+// but they should be unified in 1.0. Then we can move this macro back into
+// tests/api.rs where it is used. ---AG
+macro_rules! expand {
+    ($name:ident, $re:expr, $text:expr, $expand:expr, $expected:expr) => {
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            let cap = re.captures(t!($text)).unwrap();
+
+            let mut got = String::new();
+            cap.expand(t!($expand), &mut got);
+            assert_eq!(show!(t!($expected)), show!(&*got));
+        }
+    }
+}
+
+#[cfg(feature = "pattern")]
+macro_rules! searcher_expr { ($e:expr) => ($e) }
+#[cfg(not(feature = "pattern"))]
+macro_rules! searcher_expr { ($e:expr) => ({}) }
diff --git a/third_party/rust/regex-0.2.2/tests/misc.rs b/third_party/rust/regex-0.2.2/tests/misc.rs
new file mode 100644
index 000000000000..dfe28c9707c8
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/misc.rs
@@ -0,0 +1,14 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mat!(prefix_literal_match, r"^abc", r"abc", Some((0, 3)));
+mat!(prefix_literal_nomatch, r"^abc", r"zabc", None);
+mat!(one_literal_edge, r"abc", r"xxxxxab", None);
+matiter!(terminates, r"a$", r"a", (0, 1));
diff --git a/third_party/rust/regex-0.2.2/tests/multiline.rs b/third_party/rust/regex-0.2.2/tests/multiline.rs
new file mode 100644
index 000000000000..191504aa75c8
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/multiline.rs
@@ -0,0 +1,49 @@
+matiter!(match_multi_1, r"(?m)^[a-z]+$", "abc\ndef\nxyz",
+         (0, 3), (4, 7), (8, 11));
+matiter!(match_multi_2, r"(?m)^$", "abc\ndef\nxyz");
+matiter!(match_multi_3, r"(?m)^", "abc\ndef\nxyz",
+         (0, 0), (4, 4), (8, 8));
+matiter!(match_multi_4, r"(?m)$", "abc\ndef\nxyz",
+         (3, 3), (7, 7), (11, 11));
+matiter!(match_multi_5, r"(?m)^[a-z]", "abc\ndef\nxyz",
+         (0, 1), (4, 5), (8, 9));
+matiter!(match_multi_6, r"(?m)[a-z]^", "abc\ndef\nxyz");
+matiter!(match_multi_7, r"(?m)[a-z]$", "abc\ndef\nxyz",
+         (2, 3), (6, 7), (10, 11));
+matiter!(match_multi_8, r"(?m)$[a-z]", "abc\ndef\nxyz");
+matiter!(match_multi_9, r"(?m)^$", "", (0, 0));
+
+matiter!(match_multi_rep_1, r"(?m)(?:^$)*", "a\nb\nc",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+matiter!(match_multi_rep_2, r"(?m)(?:^|a)+", "a\naaa\n",
+         (0, 0), (2, 2), (3, 5), (6, 6));
+matiter!(match_multi_rep_3, r"(?m)(?:^|a)*", "a\naaa\n",
+         (0, 1), (2, 5), (6, 6));
+matiter!(match_multi_rep_4, r"(?m)(?:^[a-z])+", "abc\ndef\nxyz",
+         (0, 1), (4, 5), (8, 9));
+matiter!(match_multi_rep_5, r"(?m)(?:^[a-z]{3}\n?)+", "abc\ndef\nxyz",
+         (0, 11));
+matiter!(match_multi_rep_6, r"(?m)(?:^[a-z]{3}\n?)*", "abc\ndef\nxyz",
+         (0, 11));
+matiter!(match_multi_rep_7, r"(?m)(?:\n?[a-z]{3}$)+", "abc\ndef\nxyz",
+         (0, 11));
+matiter!(match_multi_rep_8, r"(?m)(?:\n?[a-z]{3}$)*", "abc\ndef\nxyz",
+         (0, 11));
+matiter!(match_multi_rep_9, r"(?m)^*", "\naa\n",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4));
+matiter!(match_multi_rep_10, r"(?m)^+", "\naa\n",
+         (0, 0), (1, 1), (4, 4));
+matiter!(match_multi_rep_11, r"(?m)$*", "\naa\n",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4));
+matiter!(match_multi_rep_12, r"(?m)$+", "\naa\n",
+         (0, 0), (3, 3), (4, 4));
+matiter!(match_multi_rep_13, r"(?m)(?:$\n)+", "\n\naaa\n\n",
+         (0, 2), (5, 7));
+matiter!(match_multi_rep_14, r"(?m)(?:$\n)*", "\n\naaa\n\n",
+         (0, 2), (3, 3), (4, 4), (5, 7));
+matiter!(match_multi_rep_15, r"(?m)(?:$\n^)+", "\n\naaa\n\n",
+         (0, 2), (5, 7));
+matiter!(match_multi_rep_16, r"(?m)(?:^|$)+", "\n\naaa\n\n",
+         (0, 0), (1, 1), (2, 2), (5, 5), (6, 6), (7, 7));
+matiter!(match_multi_rep_17, r"(?m)(?:$\n)*", "\n\naaa\n\n",
+         (0, 2), (3, 3), (4, 4), (5, 7));
diff --git a/third_party/rust/regex-0.2.2/tests/noparse.rs b/third_party/rust/regex-0.2.2/tests/noparse.rs
new file mode 100644
index 000000000000..ce2d369e2065
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/noparse.rs
@@ -0,0 +1,48 @@
+macro_rules! noparse(
+    ($name:ident, $re:expr) => (
+        #[test]
+        fn $name() {
+            let re = $re;
+            match regex_new!(re) {
+                Err(_) => {},
+                Ok(_) => panic!("Regex '{}' should cause a parse error.", re),
+            }
+        }
+    );
+);
+
+noparse!(fail_double_repeat, "a**");
+noparse!(fail_no_repeat_arg, "*");
+noparse!(fail_incomplete_escape, "\\");
+noparse!(fail_class_incomplete, "[A-");
+noparse!(fail_class_not_closed, "[A");
+noparse!(fail_class_no_begin, r"[\A]");
+noparse!(fail_class_no_end, r"[\z]");
+noparse!(fail_class_no_boundary, r"[\b]");
+noparse!(fail_open_paren, "(");
+noparse!(fail_close_paren, ")");
+noparse!(fail_invalid_range, "[a-Z]");
+noparse!(fail_empty_capture_name, "(?P<>a)");
+noparse!(fail_empty_capture_exp, "(?P<name>)");
+noparse!(fail_bad_capture_name, "(?P<na-me>)");
+noparse!(fail_bad_flag, "(?a)a");
+noparse!(fail_empty_alt_before, "|a");
+noparse!(fail_empty_alt_after, "a|");
+noparse!(fail_too_big, "a{10000000}");
+noparse!(fail_counted_no_close, "a{1001");
+noparse!(fail_unfinished_cap, "(?");
+noparse!(fail_unfinished_escape, "\\");
+noparse!(fail_octal_digit, r"\8");
+noparse!(fail_hex_digit, r"\xG0");
+noparse!(fail_hex_short, r"\xF");
+noparse!(fail_hex_long_digits, r"\x{fffg}");
+noparse!(fail_flag_bad, "(?a)");
+noparse!(fail_flag_empty, "(?)");
+noparse!(fail_double_neg, "(?-i-i)");
+noparse!(fail_neg_empty, "(?i-)");
+noparse!(fail_empty_group, "()");
+noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)");
+noparse!(fail_range_end_no_class, "[a-[:lower:]]");
+noparse!(fail_range_end_no_begin, r"[a-\A]");
+noparse!(fail_range_end_no_end, r"[a-\z]");
+noparse!(fail_range_end_no_boundary, r"[a-\b]");
diff --git a/third_party/rust/regex/tests/plugin.rs b/third_party/rust/regex-0.2.2/tests/plugin.rs
similarity index 100%
rename from third_party/rust/regex/tests/plugin.rs
rename to third_party/rust/regex-0.2.2/tests/plugin.rs
diff --git a/third_party/rust/regex-0.2.2/tests/regression.rs b/third_party/rust/regex-0.2.2/tests/regression.rs
new file mode 100644
index 000000000000..7a30b1527f12
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/regression.rs
@@ -0,0 +1,92 @@
+// See: https://github.com/rust-lang/regex/issues/48
+#[test]
+fn invalid_regexes_no_crash() {
+    assert!(regex_new!("(*)").is_err());
+    assert!(regex_new!("(?:?)").is_err());
+    assert!(regex_new!("(?)").is_err());
+    assert!(regex_new!("*").is_err());
+}
+
+// See: https://github.com/rust-lang/regex/issues/98
+#[test]
+fn regression_many_repeat_stack_overflow() {
+    let re = regex!("^.{1,2500}");
+    assert_eq!(vec![(0, 1)], findall!(re, "a"));
+}
+
+// See: https://github.com/rust-lang/regex/issues/75
+mat!(regression_unsorted_binary_search_1, r"(?i)[a_]+", "A_", Some((0, 2)));
+mat!(regression_unsorted_binary_search_2, r"(?i)[A_]+", "a_", Some((0, 2)));
+
+// See: https://github.com/rust-lang/regex/issues/99
+mat!(regression_negated_char_class_1, r"(?i)[^x]", "x", None);
+mat!(regression_negated_char_class_2, r"(?i)[^x]", "X", None);
+
+// See: https://github.com/rust-lang/regex/issues/101
+mat!(regression_ascii_word_underscore, r"[[:word:]]", "_", Some((0, 1)));
+
+// See: https://github.com/rust-lang/regex/issues/129
+#[test]
+fn regression_captures_rep() {
+    let re = regex!(r"([a-f]){2}(?P<foo>[x-z])");
+    let caps = re.captures(text!("abx")).unwrap();
+    assert_eq!(match_text!(caps.name("foo").unwrap()), text!("x"));
+}
+
+// See: https://github.com/rust-lang/regex/issues/153
+mat!(regression_alt_in_alt1, r"ab?|$", "az", Some((0, 1)));
+mat!(regression_alt_in_alt2, r"^(.*?)(\n|\r\n?|$)", "ab\rcd", Some((0, 3)));
+
+// See: https://github.com/rust-lang/regex/issues/169
+mat!(regression_leftmost_first_prefix, r"z*azb", "azb", Some((0, 3)));
+
+// See: https://github.com/rust-lang/regex/issues/76
+mat!(uni_case_lower_nocase_flag, r"(?i)\p{Ll}+", "ΛΘΓΔα", Some((0, 10)));
+
+// See: https://github.com/rust-lang/regex/issues/191
+mat!(many_alternates, r"1|2|3|4|5|6|7|8|9|10|int", "int", Some((0, 3)));
+
+// burntsushi was bad and didn't create an issue for this bug.
+mat!(anchored_prefix1, r"^a\S", "a ", None);
+mat!(anchored_prefix2, r"^a\S", "foo boo a ", None);
+mat!(anchored_prefix3, r"^-[a-z]", "r-f", None);
+
+// See: https://github.com/rust-lang/regex/issues/204
+split!(split_on_word_boundary, r"\b", r"Should this (work?)",
+       &[t!(""), t!("Should"), t!(" "), t!("this"),
+         t!(" ("), t!("work"), t!("?)")]);
+matiter!(word_boundary_dfa, r"\b", "a b c",
+         (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+
+// See: https://github.com/rust-lang/regex/issues/268
+matiter!(partial_anchor, r"^a|b", "ba", (0, 1));
+
+// See: https://github.com/rust-lang/regex/issues/264
+mat!(ascii_boundary_no_capture, r"(?-u)\B", "\u{28f3e}", Some((0, 0)));
+mat!(ascii_boundary_capture, r"(?-u)(\B)", "\u{28f3e}", Some((0, 0)));
+
+// See: https://github.com/rust-lang/regex/issues/280
+ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
+ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);
+
+// See: https://github.com/rust-lang/regex/issues/289
+mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));
+
+// See: https://github.com/rust-lang/regex/issues/291
+mat!(lits_unambiguous2, r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
+     "CIMG2341", Some((0, 8)), Some((0, 4)), None, Some((0, 4)), Some((4, 8)));
+
+// See: https://github.com/rust-lang/regex/issues/271
+mat!(end_not_wb, r"$(?-u:\B)", "\u{5c124}\u{b576c}", Some((8, 8)));
+mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
+mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
+mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
+mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));
+
+// See: https://github.com/rust-lang/regex/issues/321
+ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
+ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);
+
+// See: https://github.com/rust-lang/regex/issues/334
+mat!(captures_after_dfa_premature_end, r"a(b*(X|$))?", "abcbX",
+     Some((0, 1)), None, None);
diff --git a/third_party/rust/regex-0.2.2/tests/replace.rs b/third_party/rust/regex-0.2.2/tests/replace.rs
new file mode 100644
index 000000000000..22eb0c5e5791
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/replace.rs
@@ -0,0 +1,38 @@
+macro_rules! replace(
+    ($name:ident, $which:ident, $re:expr,
+     $search:expr, $replace:expr, $result:expr) => (
+        #[test]
+        fn $name() {
+            let re = regex!($re);
+            assert_eq!(re.$which(text!($search), $replace), text!($result));
+        }
+    );
+);
+
+replace!(first, replace, r"\d", "age: 26", t!("Z"), "age: Z6");
+replace!(plus, replace, r"\d+", "age: 26", t!("Z"), "age: Z");
+replace!(all, replace_all, r"\d", "age: 26", t!("Z"), "age: ZZ");
+replace!(groups, replace, r"(\S+)\s+(\S+)", "w1 w2", t!("$2 $1"), "w2 w1");
+replace!(double_dollar, replace,
+         r"(\S+)\s+(\S+)", "w1 w2", t!("$2 $$1"), "w2 $1");
+// replace!(adjacent_index, replace,
+         // r"([^aeiouy])ies$", "skies", t!("$1y"), "sky");
+replace!(named, replace_all,
+         r"(?P<first>\S+)\s+(?P<last>\S+)(?P<space>\s*)",
+         "w1 w2 w3 w4", t!("$last $first$space"), "w2 w1 w4 w3");
+replace!(trim, replace_all, "^[ \t]+|[ \t]+$", " \t  trim me\t   \t",
+         t!(""), "trim me");
+replace!(number_hypen, replace, r"(.)(.)", "ab", t!("$1-$2"), "a-b");
+// replace!(number_underscore, replace, r"(.)(.)", "ab", t!("$1_$2"), "a_b");
+replace!(simple_expand, replace_all, r"(\w) (\w)", "a b", t!("$2 $1"), "b a");
+replace!(literal_dollar1, replace_all,
+         r"(\w+) (\w+)", "a b", t!("$$1"), "$1");
+replace!(literal_dollar2, replace_all,
+         r"(\w+) (\w+)", "a b", t!("$2 $$c $1"), "b $c a");
+replace!(no_expand1, replace,
+         r"(\S+)\s+(\S+)", "w1 w2", no_expand!("$2 $1"), "$2 $1");
+replace!(no_expand2, replace,
+         r"(\S+)\s+(\S+)", "w1 w2", no_expand!("$$1"), "$$1");
+
+// See https://github.com/rust-lang/regex/issues/314
+replace!(match_at_start_replace_with_empty, replace_all, r"foo", "foobar", t!(""), "bar");
diff --git a/third_party/rust/regex-0.2.2/tests/searcher.rs b/third_party/rust/regex-0.2.2/tests/searcher.rs
new file mode 100644
index 000000000000..073fa5f96cca
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/searcher.rs
@@ -0,0 +1,66 @@
+macro_rules! searcher {
+    ($name:ident, $re:expr, $haystack:expr) => (
+        searcher!($name, $re, $haystack, vec vec![]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, $($steps:expr,)*) => (
+        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, $($steps:expr),*) => (
+        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
+    );
+    ($name:ident, $re:expr, $haystack:expr, vec $expect_steps:expr) => (
+        #[test]
+        #[allow(unused_imports)]
+        fn $name() {
+            searcher_expr! {{
+                use std::str::pattern::{Pattern, Searcher};
+                use std::str::pattern::SearchStep::{Match, Reject, Done};
+                let re = regex!($re);
+                let mut se = re.into_searcher($haystack);
+                let mut got_steps = vec![];
+                loop {
+                    match se.next() {
+                        Done => break,
+                        step => { got_steps.push(step); }
+                    }
+                }
+                assert_eq!(got_steps, $expect_steps);
+            }}
+        }
+    );
+}
+
+searcher!(searcher_empty_regex_empty_haystack, r"", "", Match(0, 0));
+searcher!(searcher_empty_regex, r"", "ab",
+          Match(0, 0), Reject(0, 1), Match(1, 1), Reject(1, 2), Match(2, 2));
+searcher!(searcher_empty_haystack, r"\d", "");
+searcher!(searcher_one_match, r"\d", "5",
+          Match(0, 1));
+searcher!(searcher_no_match, r"\d", "a",
+          Reject(0, 1));
+searcher!(searcher_two_adjacent_matches, r"\d", "56",
+          Match(0, 1), Match(1, 2));
+searcher!(searcher_two_non_adjacent_matches, r"\d", "5a6",
+          Match(0, 1), Reject(1, 2), Match(2, 3));
+searcher!(searcher_reject_first, r"\d", "a6",
+          Reject(0, 1), Match(1, 2));
+searcher!(searcher_one_zero_length_matches, r"\d*", "a1b2",
+          Match(0, 0),  // ^
+          Reject(0, 1), // a
+          Match(1, 2),  // a1
+          Reject(2, 3), // a1b
+          Match(3, 4),  // a1b2
+);
+searcher!(searcher_many_zero_length_matches, r"\d*", "a1bbb2",
+          Match(0, 0),  // ^
+          Reject(0, 1), // a
+          Match(1, 2),  // a1
+          Reject(2, 3), // a1b
+          Match(3, 3),  // a1bb
+          Reject(3, 4), // a1bb
+          Match(4, 4),  // a1bbb
+          Reject(4, 5), // a1bbb
+          Match(5, 6),  // a1bbba
+);
+searcher!(searcher_unicode, r".+?", "Ⅰ1Ⅱ2",
+          Match(0, 3), Match(3, 4), Match(4, 7), Match(7, 8));
diff --git a/third_party/rust/regex-0.2.2/tests/set.rs b/third_party/rust/regex-0.2.2/tests/set.rs
new file mode 100644
index 000000000000..d9842ace6a10
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/set.rs
@@ -0,0 +1,32 @@
+matset!(set1, &["a", "a"], "a", 0, 1);
+matset!(set2, &["a", "a"], "ba", 0, 1);
+matset!(set3, &["a", "b"], "a", 0);
+matset!(set4, &["a", "b"], "b", 1);
+matset!(set5, &["a|b", "b|a"], "b", 0, 1);
+matset!(set6, &["foo", "oo"], "foo", 0, 1);
+matset!(set7, &["^foo", "bar$"], "foo", 0);
+matset!(set8, &["^foo", "bar$"], "foo bar", 0, 1);
+matset!(set9, &["^foo", "bar$"], "bar", 1);
+matset!(set10, &[r"[a-z]+$", "foo"], "01234 foo", 0, 1);
+matset!(set11, &[r"[a-z]+$", "foo"], "foo 01234", 1);
+matset!(set12, &[r".*?", "a"], "zzzzzza", 0, 1);
+matset!(set13, &[r".*", "a"], "zzzzzza", 0, 1);
+matset!(set14, &[r".*", "a"], "zzzzzz", 0);
+matset!(set15, &[r"\ba\b"], "hello a bye", 0);
+matset!(set16, &["a"], "a", 0);
+matset!(set17, &[".*a"], "a", 0);
+matset!(set18, &["a", "β"], "β", 1);
+
+nomatset!(nset1, &["a", "a"], "b");
+nomatset!(nset2, &["^foo", "bar$"], "bar foo");
+nomatset!(nset3, { let xs: &[&str] = &[]; xs }, "a");
+nomatset!(nset4, &[r"^rooted$", r"\.log$"], "notrooted");
+
+// See: https://github.com/rust-lang/regex/issues/187
+#[test]
+fn regression_subsequent_matches() {
+    let set = regex_set!(&["ab", "b"]);
+    let text = text!("ba");
+    assert!(set.matches(text).matched(1));
+    assert!(set.matches(text).matched(1));
+}
diff --git a/third_party/rust/regex-0.2.2/tests/shortest_match.rs b/third_party/rust/regex-0.2.2/tests/shortest_match.rs
new file mode 100644
index 000000000000..c964ab913181
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/shortest_match.rs
@@ -0,0 +1,14 @@
+macro_rules! shortmat {
+    ($name:ident, $re:expr, $text:expr, $shortest_match:expr) => {
+        #[test]
+        fn $name() {
+            let text = text!($text);
+            let re = regex!($re);
+            assert_eq!($shortest_match, re.shortest_match(text));
+        }
+    }
+}
+
+shortmat!(t01, r"a+", r"aa", Some(1));
+// Test that the reverse suffix optimization gets it right.
+shortmat!(t02, r".*(?:abcd)+", r"abcdabcd", Some(4));
diff --git a/third_party/rust/regex-0.2.2/tests/suffix_reverse.rs b/third_party/rust/regex-0.2.2/tests/suffix_reverse.rs
new file mode 100644
index 000000000000..f2993553f972
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/suffix_reverse.rs
@@ -0,0 +1,16 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mat!(t01, r".*abcd", r"abcd", Some((0, 4)));
+mat!(t02, r".*(?:abcd)+", r"abcd", Some((0, 4)));
+mat!(t03, r".*(?:abcd)+", r"abcdabcd", Some((0, 8)));
+mat!(t04, r".*(?:abcd)+", r"abcdxabcd", Some((0, 9)));
+mat!(t05, r".*x(?:abcd)+", r"abcdxabcd", Some((0, 9)));
+mat!(t06, r"[^abcd]*x(?:abcd)+", r"abcdxabcd", Some((4, 9)));
diff --git a/third_party/rust/regex-0.2.2/tests/test_backtrack.rs b/third_party/rust/regex-0.2.2/tests/test_backtrack.rs
new file mode 100644
index 000000000000..5516c840e732
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_backtrack.rs
@@ -0,0 +1,64 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking().build().map(|e| e.into_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .build()
+            .map(|e| e.into_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_unicode;
diff --git a/third_party/rust/regex-0.2.2/tests/test_backtrack_bytes.rs b/third_party/rust/regex-0.2.2/tests/test_backtrack_bytes.rs
new file mode 100644
index 000000000000..4ea60e7d0f6e
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_backtrack_bytes.rs
@@ -0,0 +1,65 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_ascii;
diff --git a/third_party/rust/regex-0.2.2/tests/test_backtrack_utf8bytes.rs b/third_party/rust/regex-0.2.2/tests/test_backtrack_utf8bytes.rs
new file mode 100644
index 000000000000..a170d19324fe
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_backtrack_utf8bytes.rs
@@ -0,0 +1,65 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .bounded_backtracking().bytes(true).build().map(|e| e.into_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .bounded_backtracking()
+            .bytes(true)
+            .build()
+            .map(|e| e.into_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_unicode;
diff --git a/third_party/rust/regex-0.2.2/tests/test_default.rs b/third_party/rust/regex-0.2.2/tests/test_default.rs
new file mode 100644
index 000000000000..e6cf92fa2e66
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_default.rs
@@ -0,0 +1,77 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+// Due to macro scoping rules, this definition only applies for the modules
+// defined below. Effectively, it allows us to use the same tests for both
+// native and dynamic regexes.
+//
+// This is also used to test the various matching engines. This one exercises
+// the normal code path which automatically chooses the engine based on the
+// regex and the input. Other dynamic tests explicitly set the engine to use.
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::Regex;
+        Regex::new($re)
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::RegexSet;
+        RegexSet::new($re)
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod misc;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod shortest_match;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_unicode;
+
+#[test]
+fn disallow_non_utf8() {
+    assert!(regex::Regex::new(r"(?-u)\xFF").is_err());
+    assert!(regex::Regex::new(r"(?-u).").is_err());
+    assert!(regex::Regex::new(r"(?-u)[\xFF]").is_err());
+    assert!(regex::Regex::new(r"(?-u)☃").is_err());
+}
diff --git a/third_party/rust/regex-0.2.2/tests/test_default_bytes.rs b/third_party/rust/regex-0.2.2/tests/test_default_bytes.rs
new file mode 100644
index 000000000000..b049b3d2aaf5
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_default_bytes.rs
@@ -0,0 +1,73 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::bytes::Regex;
+        Regex::new($re)
+    }}
+}
+
+macro_rules! regex_set_new {
+    ($res:expr) => {{
+        use regex::bytes::RegexSet;
+        RegexSet::new($res)
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+// A silly wrapper to make it possible to write and match raw bytes.
+struct R<'a>(&'a [u8]);
+impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { &self.0 } }
+
+// See: https://github.com/rust-lang/regex/issues/321
+//
+// These tests are here because they do not have the same behavior in every
+// regex engine.
+mat!(invalid_utf8_nfa1, r".", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), Some((2, 3)));
+mat!(invalid_utf8_nfa2, r"${2}ä", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), None);
+mat!(invalid_utf8_nfa3, r".", R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
+     Some((1, 3)));
+mat!(invalid_utf8_nfa4, r"${2}ä", R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
+     None);
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod shortest_match;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_ascii;
diff --git a/third_party/rust/regex-0.2.2/tests/test_nfa.rs b/third_party/rust/regex-0.2.2/tests/test_nfa.rs
new file mode 100644
index 000000000000..8a831c47d3d3
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_nfa.rs
@@ -0,0 +1,60 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).nfa().build().map(|e| e.into_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re).nfa().build().map(|e| e.into_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_unicode;
diff --git a/third_party/rust/regex-0.2.2/tests/test_nfa_bytes.rs b/third_party/rust/regex-0.2.2/tests/test_nfa_bytes.rs
new file mode 100644
index 000000000000..f376cefe1f48
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_nfa_bytes.rs
@@ -0,0 +1,65 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re)
+            .nfa()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .nfa()
+            .only_utf8(false)
+            .build()
+            .map(|e| e.into_byte_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_bytes.rs");
+include!("macros.rs");
+
+mod api;
+mod bytes;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_ascii;
diff --git a/third_party/rust/regex-0.2.2/tests/test_nfa_utf8bytes.rs b/third_party/rust/regex-0.2.2/tests/test_nfa_utf8bytes.rs
new file mode 100644
index 000000000000..5d13685aab00
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/test_nfa_utf8bytes.rs
@@ -0,0 +1,61 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(feature = "pattern", feature(pattern))]
+
+extern crate rand;
+extern crate regex;
+
+macro_rules! regex_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new($re).nfa().bytes(true).build().map(|e| e.into_regex())
+    }}
+}
+
+macro_rules! regex {
+    ($re:expr) => {
+        regex_new!($re).unwrap()
+    }
+}
+
+macro_rules! regex_set_new {
+    ($re:expr) => {{
+        use regex::internal::ExecBuilder;
+        ExecBuilder::new_many($re)
+            .nfa().bytes(true).build().map(|e| e.into_regex_set())
+    }}
+}
+
+macro_rules! regex_set {
+    ($res:expr) => {
+        regex_set_new!($res).unwrap()
+    }
+}
+
+// Must come before other module definitions.
+include!("macros_str.rs");
+include!("macros.rs");
+
+mod api;
+mod api_str;
+mod crazy;
+mod flags;
+mod fowler;
+mod multiline;
+mod noparse;
+mod regression;
+mod replace;
+mod searcher;
+mod set;
+mod suffix_reverse;
+mod unicode;
+mod word_boundary;
+mod word_boundary_unicode;
diff --git a/third_party/rust/regex/tests/test_plugin.rs b/third_party/rust/regex-0.2.2/tests/test_plugin.rs
similarity index 100%
rename from third_party/rust/regex/tests/test_plugin.rs
rename to third_party/rust/regex-0.2.2/tests/test_plugin.rs
diff --git a/third_party/rust/regex-0.2.2/tests/unicode.rs b/third_party/rust/regex-0.2.2/tests/unicode.rs
new file mode 100644
index 000000000000..48e9a95aaf41
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/unicode.rs
@@ -0,0 +1,31 @@
+mat!(uni_literal, r"☃", "☃", Some((0, 3)));
+mat!(uni_literal_plus, r"☃+", "☃", Some((0, 3)));
+mat!(uni_literal_casei_plus, r"(?i)☃+", "☃", Some((0, 3)));
+mat!(uni_class_plus, r"[☃Ⅰ]+", "☃", Some((0, 3)));
+mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)));
+mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)));
+mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)));
+mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)));
+mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)));
+mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)));
+mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)));
+mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)));
+mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)));
+mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)));
+
+// Test the Unicode friendliness of Perl character classes.
+mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)));
+mat!(uni_perl_w_not, r"\w+", "⥡", None);
+mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)));
+mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)));
+mat!(uni_perl_d_not, r"\d+", "Ⅱ", None);
+mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)));
+mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
+mat!(uni_perl_s_not, r"\s+", "☃", None);
+mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));
+
+// And do the same for word boundaries.
+mat!(uni_boundary_none, r"\d\b", "6δ", None);
+mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
+mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
+mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);
diff --git a/third_party/rust/regex-0.2.2/tests/word_boundary.rs b/third_party/rust/regex-0.2.2/tests/word_boundary.rs
new file mode 100644
index 000000000000..7fe97a297488
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/word_boundary.rs
@@ -0,0 +1,89 @@
+// Many of these are cribbed from RE2's test suite.
+
+matiter!(wb1, r"\b", "");
+matiter!(wb2, r"\b", "a", (0, 0), (1, 1));
+matiter!(wb3, r"\b", "ab", (0, 0), (2, 2));
+matiter!(wb4, r"^\b", "ab", (0, 0));
+matiter!(wb5, r"\b$", "ab", (2, 2));
+matiter!(wb6, r"^\b$", "ab");
+matiter!(wb7, r"\bbar\b", "nobar bar foo bar", (6, 9), (14, 17));
+matiter!(wb8, r"a\b", "faoa x", (3, 4));
+matiter!(wb9, r"\bbar", "bar x", (0, 3));
+matiter!(wb10, r"\bbar", "foo\nbar x", (4, 7));
+matiter!(wb11, r"bar\b", "foobar", (3, 6));
+matiter!(wb12, r"bar\b", "foobar\nxxx", (3, 6));
+matiter!(wb13, r"(foo|bar|[A-Z])\b", "foo", (0, 3));
+matiter!(wb14, r"(foo|bar|[A-Z])\b", "foo\n", (0, 3));
+matiter!(wb15, r"\b(foo|bar|[A-Z])", "foo", (0, 3));
+matiter!(wb16, r"\b(foo|bar|[A-Z])\b", "X", (0, 1));
+matiter!(wb17, r"\b(foo|bar|[A-Z])\b", "XY");
+matiter!(wb18, r"\b(foo|bar|[A-Z])\b", "bar", (0, 3));
+matiter!(wb19, r"\b(foo|bar|[A-Z])\b", "foo", (0, 3));
+matiter!(wb20, r"\b(foo|bar|[A-Z])\b", "foo\n", (0, 3));
+matiter!(wb21, r"\b(foo|bar|[A-Z])\b", "ffoo bbar N x", (10, 11));
+matiter!(wb22, r"\b(fo|foo)\b", "fo", (0, 2));
+matiter!(wb23, r"\b(fo|foo)\b", "foo", (0, 3));
+matiter!(wb24, r"\b\b", "");
+matiter!(wb25, r"\b\b", "a", (0, 0), (1, 1));
+matiter!(wb26, r"\b$", "");
+matiter!(wb27, r"\b$", "x", (1, 1));
+matiter!(wb28, r"\b$", "y x", (3, 3));
+matiter!(wb29, r"\b.$", "x", (0, 1));
+matiter!(wb30, r"^\b(fo|foo)\b", "fo", (0, 2));
+matiter!(wb31, r"^\b(fo|foo)\b", "foo", (0, 3));
+matiter!(wb32, r"^\b$", "");
+matiter!(wb33, r"^\b$", "x");
+matiter!(wb34, r"^\b.$", "x", (0, 1));
+matiter!(wb35, r"^\b.\b$", "x", (0, 1));
+matiter!(wb36, r"^^^^^\b$$$$$", "");
+matiter!(wb37, r"^^^^^\b.$$$$$", "x", (0, 1));
+matiter!(wb38, r"^^^^^\b$$$$$", "x");
+matiter!(wb39, r"^^^^^\b\b\b.\b\b\b$$$$$", "x", (0, 1));
+matiter!(wb40, r"\b.+\b", "$$abc$$", (2, 5));
+matiter!(wb41, r"\b", "a b c", (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
+
+matiter!(nb1, r"\Bfoo\B", "n foo xfoox that", (7, 10));
+matiter!(nb2, r"a\B", "faoa x", (1, 2));
+matiter!(nb3, r"\Bbar", "bar x");
+matiter!(nb4, r"\Bbar", "foo\nbar x");
+matiter!(nb5, r"bar\B", "foobar");
+matiter!(nb6, r"bar\B", "foobar\nxxx");
+matiter!(nb7, r"(foo|bar|[A-Z])\B", "foox", (0, 3));
+matiter!(nb8, r"(foo|bar|[A-Z])\B", "foo\n");
+matiter!(nb9, r"\B", "", (0, 0));
+matiter!(nb10, r"\B", "x");
+matiter!(nb11, r"\B(foo|bar|[A-Z])", "foo");
+matiter!(nb12, r"\B(foo|bar|[A-Z])\B", "xXy", (1, 2));
+matiter!(nb13, r"\B(foo|bar|[A-Z])\B", "XY");
+matiter!(nb14, r"\B(foo|bar|[A-Z])\B", "XYZ", (1, 2));
+matiter!(nb15, r"\B(foo|bar|[A-Z])\B", "abara", (1, 4));
+matiter!(nb16, r"\B(foo|bar|[A-Z])\B", "xfoo_", (1, 4));
+matiter!(nb17, r"\B(foo|bar|[A-Z])\B", "xfoo\n");
+matiter!(nb18, r"\B(foo|bar|[A-Z])\B", "foo bar vNX", (9, 10));
+matiter!(nb19, r"\B(fo|foo)\B", "xfoo", (1, 3));
+matiter!(nb20, r"\B(foo|fo)\B", "xfooo", (1, 4));
+matiter!(nb21, r"\B\B", "", (0, 0));
+matiter!(nb22, r"\B\B", "x");
+matiter!(nb23, r"\B$", "", (0, 0));
+matiter!(nb24, r"\B$", "x");
+matiter!(nb25, r"\B$", "y x");
+matiter!(nb26, r"\B.$", "x");
+matiter!(nb27, r"^\B(fo|foo)\B", "fo");
+matiter!(nb28, r"^\B(fo|foo)\B", "foo");
+matiter!(nb29, r"^\B", "", (0, 0));
+matiter!(nb30, r"^\B", "x");
+matiter!(nb31, r"^\B\B", "", (0, 0));
+matiter!(nb32, r"^\B\B", "x");
+matiter!(nb33, r"^\B$", "", (0, 0));
+matiter!(nb34, r"^\B$", "x");
+matiter!(nb35, r"^\B.$", "x");
+matiter!(nb36, r"^\B.\B$", "x");
+matiter!(nb37, r"^^^^^\B$$$$$", "", (0, 0));
+matiter!(nb38, r"^^^^^\B.$$$$$", "x");
+matiter!(nb39, r"^^^^^\B$$$$$", "x");
+
+// These work for both Unicode and ASCII because all matches are reported as
+// byte offsets, and « and » do not correspond to word boundaries at either
+// the character or byte level.
+matiter!(unicode1, r"\bx\b", "«x", (2, 3));
+matiter!(unicode2, r"\bx\b", "x»", (0, 1));
diff --git a/third_party/rust/regex-0.2.2/tests/word_boundary_ascii.rs b/third_party/rust/regex-0.2.2/tests/word_boundary_ascii.rs
new file mode 100644
index 000000000000..5a3cf1166cf5
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/word_boundary_ascii.rs
@@ -0,0 +1,9 @@
+// ASCII word boundaries are completely oblivious to Unicode characters.
+// For Unicode word boundaries, the tests are precisely inverted.
+matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
+matiter!(ascii2, r"(?-u:\B)x(?-u:\B)", "áxβ");
+matiter!(ascii3, r"(?-u:\B)", "0\u{7EF5E}", (2, 2), (3, 3), (4, 4), (5, 5));
+
+// We still get Unicode word boundaries by default in byte regexes.
+matiter!(unicode1, r"\bx\b", "áxβ");
+matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
diff --git a/third_party/rust/regex-0.2.2/tests/word_boundary_unicode.rs b/third_party/rust/regex-0.2.2/tests/word_boundary_unicode.rs
new file mode 100644
index 000000000000..43612a91ac68
--- /dev/null
+++ b/third_party/rust/regex-0.2.2/tests/word_boundary_unicode.rs
@@ -0,0 +1,8 @@
+// Unicode word boundaries know about Unicode characters.
+// For ASCII word boundaries, the tests are precisely inverted.
+matiter!(unicode1, r"\bx\b", "áxβ");
+matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
+
+matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
+matiter!(ascii2, r"(?-u:\B)x(?-u:\B)", "áxβ");
+matiter!(ascii3, r"(?-u:\B)", "0\u{7EF5E}", (5, 5));
diff --git a/third_party/rust/regex-syntax-0.4.1/.cargo-checksum.json b/third_party/rust/regex-syntax-0.4.1/.cargo-checksum.json
new file mode 100644
index 000000000000..df93a3670e12
--- /dev/null
+++ b/third_party/rust/regex-syntax-0.4.1/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"264a95f5e516e60aecbe9f8a5f1c551bf71debb7249cf4bc3c102d68b9bb0dde","src/lib.rs":"e8eb3529e5bf62913439605d478b7385e43e5ef8ebb6c4800630a16f8ab3cb26","src/literals.rs":"4e7d4afa303ffe241bd17621728a1e0c018386f4f77b4d8f0f4403f74650bc6a","src/parser.rs":"975f570f86914c8bc8a132f5ced11484fa912ed0f7071f2bd2764600b611ec46","src/properties.rs":"ba19030e905d133039eb97b167dc82b4a9f78dd88c3b79b381ec7e5fbc6f6a8c","src/unicode.rs":"5bbab13485910b55a56e8f8437786e820f409902e96d07ba2018c28cecb033fc"},"package":"ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"}
\ No newline at end of file
diff --git a/third_party/rust/regex-syntax-0.4.1/Cargo.toml b/third_party/rust/regex-syntax-0.4.1/Cargo.toml
new file mode 100644
index 000000000000..c6295395b861
--- /dev/null
+++ b/third_party/rust/regex-syntax-0.4.1/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "regex-syntax"
+version = "0.4.1"  #:version
+authors = ["The Rust Project Developers"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/regex"
+documentation = "http://doc.rust-lang.org/regex/regex_syntax/index.html"
+homepage = "https://github.com/rust-lang/regex"
+description = "A regular expression parser."
+
+[dev-dependencies]
+quickcheck = { version = "0.4.1", default-features = false }
+rand = "0.3.15"
diff --git a/third_party/rust/regex-syntax-0.4.1/src/lib.rs b/third_party/rust/regex-syntax-0.4.1/src/lib.rs
new file mode 100644
index 000000000000..83260d7e0368
--- /dev/null
+++ b/third_party/rust/regex-syntax-0.4.1/src/lib.rs
@@ -0,0 +1,2214 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This crate provides a regular expression parser and an abstract syntax for
+regular expressions. The abstract syntax is defined by the `Expr` type. The
+concrete syntax is enumerated in the
+[`regex`](../regex/index.html#syntax)
+crate documentation.
+
+Note that since this crate is first and foremost an implementation detail for
+the `regex` crate, it may experience more frequent breaking changes. It is
+exposed as a separate crate so that others may use it to do analysis on regular
+expressions or even build their own matching engine.
+
+# Example: parsing an expression
+
+Parsing a regular expression can be done with the `Expr::parse` function.
+
+```rust
+use regex_syntax::Expr;
+
+assert_eq!(Expr::parse(r"ab|yz").unwrap(), Expr::Alternate(vec![
+    Expr::Literal { chars: vec!['a', 'b'], casei: false },
+    Expr::Literal { chars: vec!['y', 'z'], casei: false },
+]));
+```
+
+# Example: inspecting an error
+
+The parser in this crate provides very detailed error values. For example,
+if an invalid character class range is given:
+
+```rust
+use regex_syntax::{Expr, ErrorKind};
+
+let err = Expr::parse(r"[z-a]").unwrap_err();
+assert_eq!(err.position(), 4);
+assert_eq!(err.kind(), &ErrorKind::InvalidClassRange {
+    start: 'z',
+    end: 'a',
+});
+```
+
+Or unbalanced parentheses:
+
+```rust
+use regex_syntax::{Expr, ErrorKind};
+
+let err = Expr::parse(r"ab(cd").unwrap_err();
+assert_eq!(err.position(), 2);
+assert_eq!(err.kind(), &ErrorKind::UnclosedParen);
+```
+*/
+
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+
+#[cfg(test)] extern crate quickcheck;
+#[cfg(test)] extern crate rand;
+
+mod literals;
+mod parser;
+mod unicode;
+
+use std::ascii;
+use std::char;
+use std::cmp::{Ordering, max, min};
+use std::fmt;
+use std::iter::IntoIterator;
+use std::ops::Deref;
+use std::result;
+use std::slice;
+use std::u8;
+use std::vec;
+
+use unicode::case_folding;
+
+use self::Expr::*;
+use self::Repeater::*;
+
+use parser::{Flags, Parser};
+
+pub use literals::{Literals, Lit};
+
+/// A regular expression abstract syntax tree.
+///
+/// An `Expr` represents the abstract syntax of a regular expression.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum Expr {
+    /// An empty regex (which never matches any text).
+    Empty,
+    /// A sequence of one or more literal characters to be matched.
+    Literal {
+        /// The characters.
+        chars: Vec<char>,
+        /// Whether to match case insensitively.
+        casei: bool,
+    },
+    /// A sequence of one or more literal bytes to be matched.
+    LiteralBytes {
+        /// The bytes.
+        bytes: Vec<u8>,
+        /// Whether to match case insensitively.
+        ///
+        /// The interpretation of "case insensitive" in this context is
+        /// ambiguous since `bytes` can be arbitrary. However, a good heuristic
+        /// is to assume that the bytes are ASCII-compatible and do simple
+        /// ASCII case folding.
+        casei: bool,
+    },
+    /// Match any character.
+    AnyChar,
+    /// Match any character, excluding new line (`0xA`).
+    AnyCharNoNL,
+    /// Match any byte.
+    AnyByte,
+    /// Match any byte, excluding new line (`0xA`).
+    AnyByteNoNL,
+    /// A character class.
+    Class(CharClass),
+    /// A character class with byte ranges only.
+    ClassBytes(ByteClass),
+    /// Match the start of a line or beginning of input.
+    StartLine,
+    /// Match the end of a line or end of input.
+    EndLine,
+    /// Match the beginning of input.
+    StartText,
+    /// Match the end of input.
+    EndText,
+    /// Match a word boundary (word character on one side and a non-word
+    /// character on the other).
+    WordBoundary,
+    /// Match a position that is not a word boundary (word or non-word
+    /// characters on both sides).
+    NotWordBoundary,
+    /// Match an ASCII word boundary.
+    WordBoundaryAscii,
+    /// Match a position that is not an ASCII word boundary.
+    NotWordBoundaryAscii,
+    /// A group, possibly non-capturing.
+    Group {
+        /// The expression inside the group.
+        e: Box<Expr>,
+        /// The capture index (starting at `1`) only for capturing groups.
+        i: Option<usize>,
+        /// The capture name, only for capturing named groups.
+        name: Option<String>,
+    },
+    /// A repeat operator (`?`, `*`, `+` or `{m,n}`).
+    Repeat {
+        /// The expression to be repeated. Limited to literals, `.`, classes
+        /// or grouped expressions.
+        e: Box<Expr>,
+        /// The type of repeat operator used.
+        r: Repeater,
+        /// Whether the repeat is greedy (match the most) or not (match the
+        /// least).
+        greedy: bool,
+    },
+    /// A concatenation of expressions. Must be matched one after the other.
+    ///
+    /// N.B. A concat expression can only appear at the top-level or
+    /// immediately inside a group expression.
+    Concat(Vec<Expr>),
+    /// An alternation of expressions. Only one must match.
+    ///
+    /// N.B. An alternate expression can only appear at the top-level or
+    /// immediately inside a group expression.
+    Alternate(Vec<Expr>),
+}
+
+type CaptureIndex = Option<usize>;
+
+type CaptureName = Option<String>;
+
+/// The type of a repeat operator expression.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Repeater {
+    /// Match zero or one (`?`).
+    ZeroOrOne,
+    /// Match zero or more (`*`).
+    ZeroOrMore,
+    /// Match one or more (`+`).
+    OneOrMore,
+    /// Match for at least `min` and at most `max` (`{m,n}`).
+    ///
+    /// When `max` is `None`, there is no upper bound on the number of matches.
+    Range {
+        /// Lower bound on the number of matches.
+        min: u32,
+        /// Optional upper bound on the number of matches.
+        max: Option<u32>,
+    },
+}
+
+impl Repeater {
+    /// Returns true if and only if this repetition can match the empty string.
+    fn matches_empty(&self) -> bool {
+        use self::Repeater::*;
+        match *self {
+            ZeroOrOne => true,
+            ZeroOrMore => true,
+            OneOrMore => false,
+            Range { min, .. } => min == 0,
+        }
+    }
+}
+
+/// A character class.
+///
+/// A character class has a canonical format that the parser guarantees. Its
+/// canonical format is defined by the following invariants:
+///
+/// 1. Given any Unicode scalar value, it is matched by *at most* one character
+///    range in a canonical character class.
+/// 2. Every adjacent character range is separated by at least one Unicode
+///    scalar value.
+/// 3. Given any pair of character ranges `r1` and `r2`, if
+///    `r1.end < r2.start`, then `r1` comes before `r2` in a canonical
+///    character class.
+///
+/// In sum, any `CharClass` produced by this crate's parser is a sorted
+/// sequence of non-overlapping ranges. This makes it possible to test whether
+/// a character is matched by a class with a binary search.
+///
+/// If the case insensitive flag was set when parsing a character class, then
+/// simple case folding is done automatically. For example, `(?i)[a-c]` is
+/// automatically translated to `[a-cA-C]`.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct CharClass {
+    ranges: Vec<ClassRange>,
+}
+
+/// A single inclusive range in a character class.
+///
+/// Since range boundaries are defined by Unicode scalar values, the boundaries
+/// can never be in the open interval `(0xD7FF, 0xE000)`. However, a range may
+/// *cover* codepoints that are not scalar values.
+///
+/// Note that this has a few convenient impls on `PartialEq` and `PartialOrd`
+/// for testing whether a character is contained inside a given range.
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
+pub struct ClassRange {
+    /// The start character of the range.
+    ///
+    /// This must be less than or equal to `end`.
+    pub start: char,
+
+    /// The end character of the range.
+    ///
+    /// This must be greater than or equal to `start`.
+    pub end: char,
+}
+
+/// A byte class for byte ranges only.
+///
+/// A byte class has a canonical format that the parser guarantees. Its
+/// canonical format is defined by the following invariants:
+///
+/// 1. Given any byte, it is matched by *at most* one byte range in a canonical
+///    character class.
+/// 2. Every adjacent byte range is separated by at least one byte.
+/// 3. Given any pair of byte ranges `r1` and `r2`, if
+///    `r1.end < r2.start`, then `r1` comes before `r2` in a canonical
+///    character class.
+///
+/// In sum, any `ByteClass` produced by this crate's parser is a sorted
+/// sequence of non-overlapping ranges. This makes it possible to test whether
+/// a byte is matched by a class with a binary search.
+///
+/// If the case insensitive flag was set when parsing a character class,
+/// then simple ASCII-only case folding is done automatically. For example,
+/// `(?i)[a-c]` is automatically translated to `[a-cA-C]`.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ByteClass {
+    ranges: Vec<ByteRange>,
+}
+
+/// A single inclusive range in a byte class.
+///
+/// Note that this has a few convenient impls on `PartialEq` and `PartialOrd`
+/// for testing whether a byte is contained inside a given range.
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
+pub struct ByteRange {
+    /// The start byte of the range.
+    ///
+    /// This must be less than or equal to `end`.
+    pub start: u8,
+
+    /// The end byte of the range.
+    ///
+    /// This must be greater than or equal to `end`.
+    pub end: u8,
+}
+
+/// A builder for configuring regular expression parsing.
+///
+/// This allows setting the default values of flags and other options, such
+/// as the maximum nesting depth.
+#[derive(Clone, Debug)]
+pub struct ExprBuilder {
+    flags: Flags,
+    nest_limit: usize,
+}
+
+impl ExprBuilder {
+    /// Create a new builder for configuring expression parsing.
+    ///
+    /// Note that all flags are disabled by default.
+    pub fn new() -> ExprBuilder {
+        ExprBuilder {
+            flags: Flags::default(),
+            nest_limit: 200,
+        }
+    }
+
+    /// Set the default value for the case insensitive (`i`) flag.
+    pub fn case_insensitive(mut self, yes: bool) -> ExprBuilder {
+        self.flags.casei = yes;
+        self
+    }
+
+    /// Set the default value for the multi-line matching (`m`) flag.
+    pub fn multi_line(mut self, yes: bool) -> ExprBuilder {
+        self.flags.multi = yes;
+        self
+    }
+
+    /// Set the default value for the any character (`s`) flag.
+    pub fn dot_matches_new_line(mut self, yes: bool) -> ExprBuilder {
+        self.flags.dotnl = yes;
+        self
+    }
+
+    /// Set the default value for the greedy swap (`U`) flag.
+    pub fn swap_greed(mut self, yes: bool) -> ExprBuilder {
+        self.flags.swap_greed = yes;
+        self
+    }
+
+    /// Set the default value for the ignore whitespace (`x`) flag.
+    pub fn ignore_whitespace(mut self, yes: bool) -> ExprBuilder {
+        self.flags.ignore_space = yes;
+        self
+    }
+
+    /// Set the default value for the Unicode (`u`) flag.
+    ///
+    /// If `yes` is false, then `allow_bytes` is set to true.
+    pub fn unicode(mut self, yes: bool) -> ExprBuilder {
+        self.flags.unicode = yes;
+        if !yes {
+            self.allow_bytes(true)
+        } else {
+            self
+        }
+    }
+
+    /// Whether the parser allows matching arbitrary bytes or not.
+    ///
+    /// When the `u` flag is disabled (either with this builder or in the
+    /// expression itself), the parser switches to interpreting the expression
+    /// as matching arbitrary bytes instead of Unicode codepoints. For example,
+    /// the expression `(?u:\xFF)` matches the *codepoint* `\xFF`, which
+    /// corresponds to the UTF-8 byte sequence `\xCE\xBF`. Conversely,
+    /// `(?-u:\xFF)` matches the *byte* `\xFF`, which is not valid UTF-8.
+    ///
+    /// When `allow_bytes` is disabled (the default), an expression like
+    /// `(?-u:\xFF)` will cause the parser to return an error, since it would
+    /// otherwise match invalid UTF-8. When enabled, it will be allowed.
+    pub fn allow_bytes(mut self, yes: bool) -> ExprBuilder {
+        self.flags.allow_bytes = yes;
+        self
+    }
+
+    /// Set the nesting limit for regular expression parsing.
+    ///
+    /// Regular expressions that nest more than this limit will result in a
+    /// `StackExhausted` error.
+    pub fn nest_limit(mut self, limit: usize) -> ExprBuilder {
+        self.nest_limit = limit;
+        self
+    }
+
+    /// Parse a string as a regular expression using the current configuraiton.
+    pub fn parse(self, s: &str) -> Result<Expr> {
+        Parser::parse(s, self.flags).and_then(|e| e.simplify(self.nest_limit))
+    }
+}
+
+impl Expr {
+    /// Parses a string in a regular expression syntax tree.
+    ///
+    /// This is a convenience method for parsing an expression using the
+    /// default configuration. To tweak parsing options (such as which flags
+    /// are enabled by default), use the `ExprBuilder` type.
+    pub fn parse(s: &str) -> Result<Expr> {
+        ExprBuilder::new().parse(s)
+    }
+
+    /// Returns true iff the expression can be repeated by a quantifier.
+    fn can_repeat(&self) -> bool {
+        match *self {
+            Literal{..} | LiteralBytes{..}
+            | AnyChar | AnyCharNoNL | AnyByte | AnyByteNoNL
+            | Class(_) | ClassBytes(_)
+            | StartLine | EndLine | StartText | EndText
+            | WordBoundary | NotWordBoundary
+            | WordBoundaryAscii | NotWordBoundaryAscii
+            | Group{..}
+            => true,
+            _ => false,
+        }
+    }
+
+    fn simplify(self, nest_limit: usize) -> Result<Expr> {
+        fn combine_literals(es: &mut Vec<Expr>, e: Expr) {
+            match (es.pop(), e) {
+                (None, e) => es.push(e),
+                (Some(Literal { chars: mut chars1, casei: casei1 }),
+                      Literal { chars: chars2, casei: casei2 }) => {
+                    if casei1 == casei2 {
+                        chars1.extend(chars2);
+                        es.push(Literal { chars: chars1, casei: casei1 });
+                    } else {
+                        es.push(Literal { chars: chars1, casei: casei1 });
+                        es.push(Literal { chars: chars2, casei: casei2 });
+                    }
+                }
+                (Some(LiteralBytes { bytes: mut bytes1, casei: casei1 }),
+                      LiteralBytes { bytes: bytes2, casei: casei2 }) => {
+                    if casei1 == casei2 {
+                        bytes1.extend(bytes2);
+                        es.push(LiteralBytes { bytes: bytes1, casei: casei1 });
+                    } else {
+                        es.push(LiteralBytes { bytes: bytes1, casei: casei1 });
+                        es.push(LiteralBytes { bytes: bytes2, casei: casei2 });
+                    }
+                }
+                (Some(e1), e2) => {
+                    es.push(e1);
+                    es.push(e2);
+                }
+            }
+        }
+        fn simp(expr: Expr, recurse: usize, limit: usize) -> Result<Expr> {
+            if recurse > limit {
+                return Err(Error {
+                    pos: 0,
+                    surround: "".to_owned(),
+                    kind: ErrorKind::StackExhausted,
+                });
+            }
+            let simplify = |e| simp(e, recurse + 1, limit);
+            Ok(match expr {
+                Repeat { e, r, greedy } => Repeat {
+                    e: Box::new(try!(simplify(*e))),
+                    r: r,
+                    greedy: greedy,
+                },
+                Group { e, i, name } => {
+                    let e = try!(simplify(*e));
+                    if i.is_none() && name.is_none() && e.can_repeat() {
+                        e
+                    } else {
+                        Group { e: Box::new(e), i: i, name: name }
+                    }
+                }
+                Concat(es) => {
+                    let mut new_es = Vec::with_capacity(es.len());
+                    for e in es {
+                        combine_literals(&mut new_es, try!(simplify(e)));
+                    }
+                    if new_es.len() == 1 {
+                        new_es.pop().unwrap()
+                    } else {
+                        Concat(new_es)
+                    }
+                }
+                Alternate(es) => {
+                    let mut new_es = Vec::with_capacity(es.len());
+                    for e in es {
+                        new_es.push(try!(simplify(e)));
+                    }
+                    Alternate(new_es)
+                }
+                e => e,
+            })
+        }
+        simp(self, 0, nest_limit)
+    }
+
+    /// Returns a set of literal prefixes extracted from this expression.
+    pub fn prefixes(&self) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_prefixes(self);
+        lits
+    }
+
+    /// Returns a set of literal suffixes extracted from this expression.
+    pub fn suffixes(&self) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_suffixes(self);
+        lits
+    }
+
+    /// Returns true if and only if the expression is required to match from
+    /// the beginning of text.
+    pub fn is_anchored_start(&self) -> bool {
+        match *self {
+            Repeat { ref e, r, .. } => {
+                !r.matches_empty() && e.is_anchored_start()
+            }
+            Group { ref e, .. } => e.is_anchored_start(),
+            Concat(ref es) => es[0].is_anchored_start(),
+            Alternate(ref es) => es.iter().all(|e| e.is_anchored_start()),
+            StartText => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if the expression has at least one matchable
+    /// sub-expression that must match the beginning of text.
+    pub fn has_anchored_start(&self) -> bool {
+        match *self {
+            Repeat { ref e, r, .. } => {
+                !r.matches_empty() && e.has_anchored_start()
+            }
+            Group { ref e, .. } => e.has_anchored_start(),
+            Concat(ref es) => es[0].has_anchored_start(),
+            Alternate(ref es) => es.iter().any(|e| e.has_anchored_start()),
+            StartText => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if the expression is required to match at the
+    /// end of the text.
+    pub fn is_anchored_end(&self) -> bool {
+        match *self {
+            Repeat { ref e, r, .. } => {
+                !r.matches_empty() && e.is_anchored_end()
+            }
+            Group { ref e, .. } => e.is_anchored_end(),
+            Concat(ref es) => es[es.len() - 1].is_anchored_end(),
+            Alternate(ref es) => es.iter().all(|e| e.is_anchored_end()),
+            EndText => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if the expression has at least one matchable
+    /// sub-expression that must match the beginning of text.
+    pub fn has_anchored_end(&self) -> bool {
+        match *self {
+            Repeat { ref e, r, .. } => {
+                !r.matches_empty() && e.has_anchored_end()
+            }
+            Group { ref e, .. } => e.has_anchored_end(),
+            Concat(ref es) => es[es.len() - 1].has_anchored_end(),
+            Alternate(ref es) => es.iter().any(|e| e.has_anchored_end()),
+            EndText => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if the expression contains sub-expressions
+    /// that can match arbitrary bytes.
+    pub fn has_bytes(&self) -> bool {
+        match *self {
+            Repeat { ref e, .. } => e.has_bytes(),
+            Group { ref e, .. } => e.has_bytes(),
+            Concat(ref es) => es.iter().any(|e| e.has_bytes()),
+            Alternate(ref es) => es.iter().any(|e| e.has_bytes()),
+            LiteralBytes{..} => true,
+            AnyByte | AnyByteNoNL => true,
+            ClassBytes(_) => true,
+            WordBoundaryAscii | NotWordBoundaryAscii => true,
+            _ => false,
+        }
+    }
+}
+
+impl Deref for CharClass {
+    type Target = Vec<ClassRange>;
+    fn deref(&self) -> &Vec<ClassRange> { &self.ranges }
+}
+
+impl IntoIterator for CharClass {
+    type Item = ClassRange;
+    type IntoIter = vec::IntoIter<ClassRange>;
+    fn into_iter(self) -> vec::IntoIter<ClassRange> { self.ranges.into_iter() }
+}
+
+impl<'a> IntoIterator for &'a CharClass {
+    type Item = &'a ClassRange;
+    type IntoIter = slice::Iter<'a, ClassRange>;
+    fn into_iter(self) -> slice::Iter<'a, ClassRange> { self.iter() }
+}
+
+impl CharClass {
+    /// Create a new class from an existing set of ranges.
+    pub fn new(ranges: Vec<ClassRange>) -> CharClass {
+        CharClass { ranges: ranges }
+    }
+
+    /// Create an empty class.
+    fn empty() -> CharClass {
+        CharClass::new(Vec::new())
+    }
+
+    /// Returns true if `c` is matched by this character class.
+    pub fn matches(&self, c: char) -> bool {
+        self.binary_search_by(|range| c.partial_cmp(range).unwrap()).is_ok()
+    }
+
+    /// Removes the given character from the class if it exists.
+    ///
+    /// Note that this takes `O(n)` time in the number of ranges.
+    pub fn remove(&mut self, c: char) {
+        let mut i = match self.binary_search_by(|r| c.partial_cmp(r).unwrap()) {
+            Ok(i) => i,
+            Err(_) => return,
+        };
+        let mut r = self.ranges.remove(i);
+        if r.start == c {
+            r.start = inc_char(c);
+            if r.start > r.end || c == char::MAX {
+                return;
+            }
+            self.ranges.insert(i, r);
+        } else if r.end == c {
+            r.end = dec_char(c);
+            if r.end < r.start || c == '\x00' {
+                return;
+            }
+            self.ranges.insert(0, r);
+        } else {
+            let (mut r1, mut r2) = (r.clone(), r.clone());
+            r1.end = dec_char(c);
+            if r1.start <= r1.end {
+                self.ranges.insert(i, r1);
+                i += 1;
+            }
+            r2.start = inc_char(c);
+            if r2.start <= r2.end {
+                self.ranges.insert(i, r2);
+            }
+        }
+    }
+
+    /// Create a new empty class from this one.
+    fn to_empty(&self) -> CharClass {
+        CharClass { ranges: Vec::with_capacity(self.len()) }
+    }
+
+    /// Create a byte class from this character class.
+    ///
+    /// Codepoints above 0xFF are removed.
+    fn to_byte_class(self) -> ByteClass {
+        ByteClass::new(
+            self.ranges.into_iter()
+                       .filter_map(|r| r.to_byte_range())
+                       .collect()).canonicalize()
+    }
+
+    /// Merge two classes and canonicalize them.
+    #[cfg(test)]
+    fn merge(mut self, other: CharClass) -> CharClass {
+        self.ranges.extend(other);
+        self.canonicalize()
+    }
+
+    /// Canonicalize any sequence of ranges.
+    ///
+    /// This is responsible for enforcing the canonical format invariants
+    /// as described on the docs for the `CharClass` type.
+    fn canonicalize(mut self) -> CharClass {
+        // TODO: Save some cycles here by checking if already canonicalized.
+        self.ranges.sort();
+        let mut ordered = self.to_empty(); // TODO: Do this in place?
+        for candidate in self {
+            // If the candidate overlaps with an existing range, then it must
+            // be the most recent range added because we process the candidates
+            // in order.
+            if let Some(or) = ordered.ranges.last_mut() {
+                if or.overlapping(candidate) {
+                    *or = or.merge(candidate);
+                    continue;
+                }
+            }
+            ordered.ranges.push(candidate);
+        }
+        ordered
+    }
+
+    /// Calculate the intersection of two canonical character classes.
+    ///
+    /// The returned intersection is canonical.
+    fn intersection(&self, other: &CharClass) -> CharClass {
+        if self.ranges.is_empty() || other.ranges.is_empty() {
+            return CharClass::empty();
+        }
+
+        let mut intersection = CharClass::empty();
+
+        let mut iter_a = self.ranges.iter();
+        let mut iter_b = other.ranges.iter();
+        let mut a = iter_a.next().unwrap();
+        let mut b = iter_b.next().unwrap();
+        loop {
+            if let Some(i) = a.intersection(&b) {
+                intersection.ranges.push(i);
+            }
+
+            // If the range with the smaller end didn't match this time,
+            // it won't ever match, so move on to the next one.
+            let (iter, item) = if a.end < b.end {
+                (&mut iter_a, &mut a)
+            } else {
+                (&mut iter_b, &mut b)
+            };
+            match iter.next() {
+                Some(v) => *item = v,
+                None => break, // no more ranges to check, done
+            }
+        }
+
+        intersection.canonicalize()
+    }
+
+    /// Negates the character class.
+    ///
+    /// For all `c` where `c` is a Unicode scalar value, `c` matches `self`
+    /// if and only if `c` does not match `self.negate()`.
+    pub fn negate(mut self) -> CharClass {
+        fn range(s: char, e: char) -> ClassRange { ClassRange::new(s, e) }
+
+        if self.is_empty() {
+            // Inverting an empty range yields all of Unicode.
+            return CharClass {
+                ranges: vec![ClassRange { start: '\x00', end: '\u{10ffff}' }],
+            };
+        }
+        self = self.canonicalize();
+        let mut inv = self.to_empty();
+        if self[0].start > '\x00' {
+            inv.ranges.push(range('\x00', dec_char(self[0].start)));
+        }
+        for win in self.windows(2) {
+            inv.ranges.push(range(inc_char(win[0].end),
+                                  dec_char(win[1].start)));
+        }
+        if self[self.len() - 1].end < char::MAX {
+            inv.ranges.push(range(inc_char(self[self.len() - 1].end),
+                                  char::MAX));
+        }
+        inv
+    }
+
+    /// Apply case folding to this character class.
+    ///
+    /// N.B. Applying case folding to a negated character class probably
+    /// won't produce the expected result. e.g., `(?i)[^x]` really should
+    /// match any character sans `x` and `X`, but if `[^x]` is negated
+    /// before being case folded, you'll end up matching any character.
+    pub fn case_fold(self) -> CharClass {
+        let mut folded = self.to_empty();
+        for r in self {
+            // Applying case folding to a range is expensive because *every*
+            // character needs to be examined. Thus, we avoid that drudgery
+            // if no character in the current range is in our case folding
+            // table.
+            if r.needs_case_folding() {
+                folded.ranges.extend(r.case_fold());
+            }
+            folded.ranges.push(r);
+        }
+        folded.canonicalize()
+    }
+
+    /// Returns the number of characters that match this class.
+    fn num_chars(&self) -> usize {
+        self.ranges.iter()
+            .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+            .fold(0, |acc, len| acc + len)
+            as usize
+    }
+}
+
+impl ClassRange {
+    /// Create a new class range.
+    ///
+    /// If `end < start`, then the two values are swapped so that
+    /// the invariant `start <= end` is preserved.
+    fn new(start: char, end: char) -> ClassRange {
+        if start <= end {
+            ClassRange { start: start, end: end }
+        } else {
+            ClassRange { start: end, end: start }
+        }
+    }
+
+    /// Translate this to a byte class.
+    ///
+    /// If the start codepoint exceeds 0xFF, then this returns `None`.
+    ///
+    /// If the end codepoint exceeds 0xFF, then it is set to 0xFF.
+    fn to_byte_range(self) -> Option<ByteRange> {
+        if self.start > '\u{FF}' {
+            None
+        } else {
+            let s = self.start as u8;
+            let e = min('\u{FF}', self.end) as u8;
+            Some(ByteRange::new(s, e))
+        }
+    }
+
+    /// Create a range of one character.
+    fn one(c: char) -> ClassRange {
+        ClassRange { start: c, end: c }
+    }
+
+    /// Returns true if and only if the two ranges are overlapping. Note that
+    /// since ranges are inclusive, `a-c` and `d-f` are overlapping!
+    fn overlapping(self, other: ClassRange) -> bool {
+        max(self.start, other.start) <= inc_char(min(self.end, other.end))
+    }
+
+    /// Returns the intersection of the two ranges if they have common
+    /// characters, `None` otherwise.
+    fn intersection(&self, other: &ClassRange) -> Option<ClassRange> {
+        let start = max(self.start, other.start);
+        let end = min(self.end, other.end);
+        if start <= end {
+            Some(ClassRange::new(start, end))
+        } else {
+            None
+        }
+    }
+
+    /// Creates a new range representing the union of `self` and `other.
+    fn merge(self, other: ClassRange) -> ClassRange {
+        ClassRange {
+            start: min(self.start, other.start),
+            end: max(self.end, other.end),
+        }
+    }
+
+    /// Returns true if and only if this range contains a character that is
+    /// in the case folding table.
+    fn needs_case_folding(self) -> bool {
+        case_folding::C_plus_S_both_table
+        .binary_search_by(|&(c, _)| self.partial_cmp(&c).unwrap()).is_ok()
+    }
+
+    /// Apply case folding to this range.
+    ///
+    /// Since case folding might add characters such that the range is no
+    /// longer contiguous, this returns multiple class ranges. They are in
+    /// canonical order.
+    fn case_fold(self) -> Vec<ClassRange> {
+        let table = &case_folding::C_plus_S_both_table;
+        let (s, e) = (self.start as u32, self.end as u32 + 1);
+        let mut start = self.start;
+        let mut end = start;
+        let mut next_case_fold = '\x00';
+        let mut ranges = Vec::with_capacity(10);
+        for mut c in (s..e).filter_map(char::from_u32) {
+            if c >= next_case_fold {
+                c = match simple_case_fold_both_result(c) {
+                    Ok(i) => {
+                        for &(c1, c2) in &table[i..] {
+                            if c1 != c {
+                                break;
+                            }
+                            if c2 != inc_char(end) {
+                                ranges.push(ClassRange::new(start, end));
+                                start = c2;
+                            }
+                            end = c2;
+                        }
+                        continue;
+                    }
+                    Err(i) => {
+                        if i < table.len() {
+                            next_case_fold = table[i].0;
+                        } else {
+                            next_case_fold = '\u{10FFFF}';
+                        }
+                        c
+                    }
+                };
+            }
+            // The fast path. We know this character doesn't have an entry
+            // in the case folding table.
+            if c != inc_char(end) {
+                ranges.push(ClassRange::new(start, end));
+                start = c;
+            }
+            end = c;
+        }
+        ranges.push(ClassRange::new(start, end));
+        ranges
+    }
+}
+
+impl PartialEq<char> for ClassRange {
+    #[inline]
+    fn eq(&self, other: &char) -> bool {
+        self.start <= *other && *other <= self.end
+    }
+}
+
+impl PartialEq<ClassRange> for char {
+    #[inline]
+    fn eq(&self, other: &ClassRange) -> bool {
+        other.eq(self)
+    }
+}
+
+impl PartialOrd<char> for ClassRange {
+    #[inline]
+    fn partial_cmp(&self, other: &char) -> Option<Ordering> {
+        Some(if self == other {
+            Ordering::Equal
+        } else if *other > self.end {
+            Ordering::Greater
+        } else {
+            Ordering::Less
+        })
+    }
+}
+
+impl PartialOrd<ClassRange> for char {
+    #[inline]
+    fn partial_cmp(&self, other: &ClassRange) -> Option<Ordering> {
+        other.partial_cmp(self).map(|o| o.reverse())
+    }
+}
+
+impl ByteClass {
+    /// Create a new class from an existing set of ranges.
+    pub fn new(ranges: Vec<ByteRange>) -> ByteClass {
+        ByteClass { ranges: ranges }
+    }
+
+    /// Returns true if `b` is matched by this byte class.
+    pub fn matches(&self, b: u8) -> bool {
+        self.binary_search_by(|range| b.partial_cmp(range).unwrap()).is_ok()
+    }
+
+    /// Removes the given byte from the class if it exists.
+    ///
+    /// Note that this takes `O(n)` time in the number of ranges.
+    pub fn remove(&mut self, b: u8) {
+        let mut i = match self.binary_search_by(|r| b.partial_cmp(r).unwrap()) {
+            Ok(i) => i,
+            Err(_) => return,
+        };
+        let mut r = self.ranges.remove(i);
+        if r.start == b {
+            r.start = b.saturating_add(1);
+            if r.start > r.end || b == u8::MAX {
+                return;
+            }
+            self.ranges.insert(i, r);
+        } else if r.end == b {
+            r.end = b.saturating_sub(1);
+            if r.end < r.start || b == b'\x00' {
+                return;
+            }
+            self.ranges.insert(0, r);
+        } else {
+            let (mut r1, mut r2) = (r.clone(), r.clone());
+            r1.end = b.saturating_sub(1);
+            if r1.start <= r1.end {
+                self.ranges.insert(i, r1);
+                i += 1;
+            }
+            r2.start = b.saturating_add(1);
+            if r2.start <= r2.end {
+                self.ranges.insert(i, r2);
+            }
+        }
+    }
+
+    /// Create a new empty class from this one.
+    fn to_empty(&self) -> ByteClass {
+        ByteClass { ranges: Vec::with_capacity(self.len()) }
+    }
+
+    /// Canonicalze any sequence of ranges.
+    ///
+    /// This is responsible for enforcing the canonical format invariants
+    /// as described on the docs for the `ByteClass` type.
+    fn canonicalize(mut self) -> ByteClass {
+        // TODO: Save some cycles here by checking if already canonicalized.
+        self.ranges.sort();
+        let mut ordered = self.to_empty(); // TODO: Do this in place?
+        for candidate in self {
+            // If the candidate overlaps with an existing range, then it must
+            // be the most recent range added because we process the candidates
+            // in order.
+            if let Some(or) = ordered.ranges.last_mut() {
+                if or.overlapping(candidate) {
+                    *or = or.merge(candidate);
+                    continue;
+                }
+            }
+            ordered.ranges.push(candidate);
+        }
+        ordered
+    }
+
+    /// Negates the byte class.
+    ///
+    /// For all `b` where `b` is a byte, `b` matches `self` if and only if `b`
+    /// does not match `self.negate()`.
+    pub fn negate(mut self) -> ByteClass {
+        fn range(s: u8, e: u8) -> ByteRange { ByteRange::new(s, e) }
+
+        if self.is_empty() {
+            // Inverting an empty range yields all bytes.
+            return ByteClass {
+                ranges: vec![ByteRange { start: b'\x00', end: b'\xff' }],
+            };
+        }
+        self = self.canonicalize();
+        let mut inv = self.to_empty();
+        if self[0].start > b'\x00' {
+            inv.ranges.push(range(b'\x00', self[0].start.saturating_sub(1)));
+        }
+        for win in self.windows(2) {
+            inv.ranges.push(range(win[0].end.saturating_add(1),
+                                  win[1].start.saturating_sub(1)));
+        }
+        if self[self.len() - 1].end < u8::MAX {
+            inv.ranges.push(range(self[self.len() - 1].end.saturating_add(1),
+                                  u8::MAX));
+        }
+        inv
+    }
+
+    /// Apply case folding to this byte class.
+    ///
+    /// This assumes that the bytes in the ranges are ASCII compatible.
+    ///
+    /// N.B. Applying case folding to a negated character class probably
+    /// won't produce the expected result. e.g., `(?i)[^x]` really should
+    /// match any character sans `x` and `X`, but if `[^x]` is negated
+    /// before being case folded, you'll end up matching any character.
+    pub fn case_fold(self) -> ByteClass {
+        let mut folded = self.to_empty();
+        for r in self {
+            folded.ranges.extend(r.case_fold());
+        }
+        folded.canonicalize()
+    }
+
+    /// Returns the number of bytes that match this class.
+    fn num_bytes(&self) -> usize {
+        self.ranges.iter()
+            .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+            .fold(0, |acc, len| acc + len)
+            as usize
+    }
+}
+
+impl ByteRange {
+    /// Create a new class range.
+    ///
+    /// If `end < start`, then the two values are swapped so that
+    /// the invariant `start <= end` is preserved.
+    fn new(start: u8, end: u8) -> ByteRange {
+        if start <= end {
+            ByteRange { start: start, end: end }
+        } else {
+            ByteRange { start: end, end: start }
+        }
+    }
+
+    /// Returns true if and only if the two ranges are overlapping. Note that
+    /// since ranges are inclusive, `a-c` and `d-f` are overlapping!
+    fn overlapping(self, other: ByteRange) -> bool {
+        max(self.start, other.start)
+        <= min(self.end, other.end).saturating_add(1)
+    }
+
+    /// Returns true if and only if the intersection of self and other is non
+    /// empty.
+    fn is_intersect_empty(self, other: ByteRange) -> bool {
+        max(self.start, other.start) > min(self.end, other.end)
+    }
+
+    /// Creates a new range representing the union of `self` and `other.
+    fn merge(self, other: ByteRange) -> ByteRange {
+        ByteRange {
+            start: min(self.start, other.start),
+            end: max(self.end, other.end),
+        }
+    }
+
+    /// Apply case folding to this range.
+    ///
+    /// Since case folding might add bytes such that the range is no
+    /// longer contiguous, this returns multiple byte ranges.
+    ///
+    /// This assumes that the bytes in this range are ASCII compatible.
+    fn case_fold(self) -> Vec<ByteRange> {
+        // So much easier than Unicode case folding!
+        let mut ranges = vec![self];
+        if !ByteRange::new(b'a', b'z').is_intersect_empty(self) {
+            let lower = max(self.start, b'a');
+            let upper = min(self.end, b'z');
+            ranges.push(ByteRange::new(lower - 32, upper - 32));
+        }
+        if !ByteRange::new(b'A', b'Z').is_intersect_empty(self) {
+            let lower = max(self.start, b'A');
+            let upper = min(self.end, b'Z');
+            ranges.push(ByteRange::new(lower + 32, upper + 32));
+        }
+        ranges
+    }
+}
+
+impl Deref for ByteClass {
+    type Target = Vec<ByteRange>;
+    fn deref(&self) -> &Vec<ByteRange> { &self.ranges }
+}
+
+impl IntoIterator for ByteClass {
+    type Item = ByteRange;
+    type IntoIter = vec::IntoIter<ByteRange>;
+    fn into_iter(self) -> vec::IntoIter<ByteRange> { self.ranges.into_iter() }
+}
+
+impl<'a> IntoIterator for &'a ByteClass {
+    type Item = &'a ByteRange;
+    type IntoIter = slice::Iter<'a, ByteRange>;
+    fn into_iter(self) -> slice::Iter<'a, ByteRange> { self.iter() }
+}
+
+impl PartialEq<u8> for ByteRange {
+    #[inline]
+    fn eq(&self, other: &u8) -> bool {
+        self.start <= *other && *other <= self.end
+    }
+}
+
+impl PartialEq<ByteRange> for u8 {
+    #[inline]
+    fn eq(&self, other: &ByteRange) -> bool {
+        other.eq(self)
+    }
+}
+
+impl PartialOrd<u8> for ByteRange {
+    #[inline]
+    fn partial_cmp(&self, other: &u8) -> Option<Ordering> {
+        Some(if self == other {
+            Ordering::Equal
+        } else if *other > self.end {
+            Ordering::Greater
+        } else {
+            Ordering::Less
+        })
+    }
+}
+
+impl PartialOrd<ByteRange> for u8 {
+    #[inline]
+    fn partial_cmp(&self, other: &ByteRange) -> Option<Ordering> {
+        other.partial_cmp(self).map(|o| o.reverse())
+    }
+}
+
+/// This implementation of `Display` will write a regular expression from the
+/// syntax tree. It does not write the original string parsed.
+impl fmt::Display for Expr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Empty => write!(f, ""),
+            Literal { ref chars, casei } => {
+                if casei {
+                    try!(write!(f, "(?iu:"));
+                } else {
+                    try!(write!(f, "(?u:"));
+                }
+                for &c in chars {
+                    try!(write!(f, "{}", quote_char(c)));
+                }
+                try!(write!(f, ")"));
+                Ok(())
+            }
+            LiteralBytes { ref bytes, casei } => {
+                if casei {
+                    try!(write!(f, "(?i-u:"));
+                } else {
+                    try!(write!(f, "(?-u:"));
+                }
+                for &b in bytes {
+                    try!(write!(f, "{}", quote_byte(b)));
+                }
+                try!(write!(f, ")"));
+                Ok(())
+            }
+            AnyChar => write!(f, "(?su:.)"),
+            AnyCharNoNL => write!(f, "(?u:.)"),
+            AnyByte => write!(f, "(?s-u:.)"),
+            AnyByteNoNL => write!(f, "(?-u:.)"),
+            Class(ref cls) => write!(f, "{}", cls),
+            ClassBytes(ref cls) => write!(f, "{}", cls),
+            StartLine => write!(f, "(?m:^)"),
+            EndLine => write!(f, "(?m:$)"),
+            StartText => write!(f, r"^"),
+            EndText => write!(f, r"$"),
+            WordBoundary => write!(f, r"(?u:\b)"),
+            NotWordBoundary => write!(f, r"(?u:\B)"),
+            WordBoundaryAscii => write!(f, r"(?-u:\b)"),
+            NotWordBoundaryAscii => write!(f, r"(?-u:\B)"),
+            Group { ref e, i: None, name: None } => write!(f, "(?:{})", e),
+            Group { ref e, name: None, .. } => write!(f, "({})", e),
+            Group { ref e, name: Some(ref n), .. } => {
+                write!(f, "(?P<{}>{})", n, e)
+            }
+            Repeat { ref e, r, greedy } => {
+                match &**e {
+                    &Literal { ref chars, .. } if chars.len() > 1 => {
+                        try!(write!(f, "(?:{}){}", e, r))
+                    }
+                    _ => try!(write!(f, "{}{}", e, r)),
+                }
+                if !greedy { try!(write!(f, "?")); }
+                Ok(())
+            }
+            Concat(ref es) => {
+                for e in es {
+                    try!(write!(f, "{}", e));
+                }
+                Ok(())
+            }
+            Alternate(ref es) => {
+                for (i, e) in es.iter().enumerate() {
+                    if i > 0 { try!(write!(f, "|")); }
+                    try!(write!(f, "{}", e));
+                }
+                Ok(())
+            }
+        }
+    }
+}
+
+impl fmt::Display for Repeater {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ZeroOrOne => write!(f, "?"),
+            ZeroOrMore => write!(f, "*"),
+            OneOrMore => write!(f, "+"),
+            Range { min: s, max: None } => write!(f, "{{{},}}", s),
+            Range { min: s, max: Some(e) } if s == e => write!(f, "{{{}}}", s),
+            Range { min: s, max: Some(e) } => write!(f, "{{{}, {}}}", s, e),
+        }
+    }
+}
+
+impl fmt::Display for CharClass {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "(?u:["));
+        for range in self.iter() {
+            if range.start == '-' || range.end == '-' {
+                try!(write!(f, "-"));
+                break;
+            }
+        }
+        for range in self.iter() {
+            let mut range = *range;
+            if range.start == '-' {
+                range.start = ((range.start as u8) + 1) as char;
+            }
+            if range.end == '-' {
+                range.end = ((range.end as u8) - 1) as char;
+            }
+            if range.start > range.end {
+                continue;
+            }
+            try!(write!(f, "{}", range));
+        }
+        try!(write!(f, "])"));
+        Ok(())
+    }
+}
+
+impl fmt::Display for ClassRange {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}-{}", quote_char(self.start), quote_char(self.end))
+    }
+}
+
+impl fmt::Display for ByteClass {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "(?-u:["));
+        for range in self.iter() {
+            if range.start == b'-' || range.end == b'-' {
+                try!(write!(f, "-"));
+                break;
+            }
+        }
+        for range in self.iter() {
+            let mut range = *range;
+            if range.start == b'-' {
+                range.start += 1;
+            }
+            if range.end == b'-' {
+                range.start -= 1;
+            }
+            if range.start > range.end {
+                continue;
+            }
+            try!(write!(f, "{}", range));
+        }
+        try!(write!(f, "])"));
+        Ok(())
+    }
+}
+
+impl fmt::Display for ByteRange {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}-{}", quote_byte(self.start), quote_byte(self.end))
+    }
+}
+
+/// An alias for computations that can return a `Error`.
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+/// A parse error.
+///
+/// This includes details about the specific type of error and a rough
+/// approximation of where it occurred.
+#[derive(Clone, Debug, PartialEq)]
+pub struct Error {
+    pos: usize,
+    surround: String,
+    kind: ErrorKind,
+}
+
+/// The specific type of parse error that can occur.
+#[derive(Clone, Debug, PartialEq)]
+pub enum ErrorKind {
+    /// A negation symbol is used twice in flag settings.
+    /// e.g., `(?-i-s)`.
+    DoubleFlagNegation,
+    /// The same capture name was used more than once.
+    /// e.g., `(?P<a>.)(?P<a>.)`.
+    DuplicateCaptureName(String),
+    /// An alternate is empty. e.g., `(|a)`.
+    EmptyAlternate,
+    /// A capture group name is empty. e.g., `(?P<>a)`.
+    EmptyCaptureName,
+    /// A negation symbol was not proceded by any flags. e.g., `(?i-)`.
+    EmptyFlagNegation,
+    /// A group is empty. e.g., `()`.
+    EmptyGroup,
+    /// An invalid number was used in a counted repetition. e.g., `a{b}`.
+    InvalidBase10(String),
+    /// An invalid hexadecimal number was used in an escape sequence.
+    /// e.g., `\xAG`.
+    InvalidBase16(String),
+    /// An invalid capture name was used. e.g., `(?P<0a>b)`.
+    InvalidCaptureName(String),
+    /// An invalid class range was givien. Specifically, when the start of the
+    /// range is greater than the end. e.g., `[z-a]`.
+    InvalidClassRange {
+        /// The first character specified in the range.
+        start: char,
+        /// The second character specified in the range.
+        end: char,
+    },
+    /// An escape sequence was used in a character class where it is not
+    /// allowed. e.g., `[a-\pN]` or `[\A]`.
+    InvalidClassEscape(Expr),
+    /// An invalid counted repetition min/max was given. e.g., `a{2,1}`.
+    InvalidRepeatRange {
+        /// The first number specified in the repetition.
+        min: u32,
+        /// The second number specified in the repetition.
+        max: u32,
+    },
+    /// An invalid Unicode scalar value was used in a long hexadecimal
+    /// sequence. e.g., `\x{D800}`.
+    InvalidScalarValue(u32),
+    /// An empty counted repetition operator. e.g., `a{}`.
+    MissingBase10,
+    /// A repetition operator was not applied to an expression. e.g., `*`.
+    RepeaterExpectsExpr,
+    /// A repetition operator was applied to an expression that cannot be
+    /// repeated. e.g., `a+*` or `a|*`.
+    RepeaterUnexpectedExpr(Expr),
+    /// A capture group name that is never closed. e.g., `(?P<a`.
+    UnclosedCaptureName(String),
+    /// An unclosed hexadecimal literal. e.g., `\x{a`.
+    UnclosedHex,
+    /// An unclosed parenthesis. e.g., `(a`.
+    UnclosedParen,
+    /// An unclosed counted repetition operator. e.g., `a{2`.
+    UnclosedRepeat,
+    /// An unclosed named Unicode class. e.g., `\p{Yi`.
+    UnclosedUnicodeName,
+    /// Saw end of regex before class was closed. e.g., `[a`.
+    UnexpectedClassEof,
+    /// Saw end of regex before escape sequence was closed. e.g., `\`.
+    UnexpectedEscapeEof,
+    /// Saw end of regex before flags were closed. e.g., `(?i`.
+    UnexpectedFlagEof,
+    /// Saw end of regex before two hexadecimal digits were seen. e.g., `\xA`.
+    UnexpectedTwoDigitHexEof,
+    /// Unopened parenthesis. e.g., `)`.
+    UnopenedParen,
+    /// Unrecognized escape sequence. e.g., `\q`.
+    UnrecognizedEscape(char),
+    /// Unrecognized flag. e.g., `(?a)`.
+    UnrecognizedFlag(char),
+    /// Unrecognized named Unicode class. e.g., `\p{Foo}`.
+    UnrecognizedUnicodeClass(String),
+    /// Indicates that the regex uses too much nesting.
+    ///
+    /// (N.B. This error exists because traversing the Expr is recursive and
+    /// an explicit heap allocated stack is not (yet?) used. Regardless, some
+    /// sort of limit must be applied to avoid unbounded memory growth.
+    StackExhausted,
+    /// A disallowed flag was found (e.g., `u`).
+    FlagNotAllowed(char),
+    /// A Unicode class was used when the Unicode (`u`) flag was disabled.
+    UnicodeNotAllowed,
+    /// InvalidUtf8 indicates that the expression may match non-UTF-8 bytes.
+    /// This never returned if the parser is permitted to allow expressions
+    /// that match arbitrary bytes.
+    InvalidUtf8,
+    /// A character class was constructed such that it is empty.
+    /// e.g., `[^\d\D]`.
+    EmptyClass,
+    /// Indicates that unsupported notation was used in a character class.
+    ///
+    /// The char in this error corresponds to the illegal character.
+    ///
+    /// The intent of this error is to carve a path to support set notation
+    /// as described in UTS#18 RL1.3. We do this by rejecting regexes that
+    /// would use the notation.
+    ///
+    /// The work around for end users is to escape the character included in
+    /// this error message.
+    UnsupportedClassChar(char),
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl Error {
+    /// Returns an approximate *character* offset at which the error occurred.
+    ///
+    /// The character offset may be equal to the number of characters in the
+    /// string, in which case it should be interpreted as pointing to the end
+    /// of the regex.
+    pub fn position(&self) -> usize {
+        self.pos
+    }
+
+    /// Returns the type of the regex parse error.
+    pub fn kind(&self) -> &ErrorKind {
+        &self.kind
+    }
+}
+
+impl ErrorKind {
+    fn description(&self) -> &str {
+        use ErrorKind::*;
+        match *self {
+            DoubleFlagNegation => "double flag negation",
+            DuplicateCaptureName(_) => "duplicate capture name",
+            EmptyAlternate => "empty alternate",
+            EmptyCaptureName => "empty capture name",
+            EmptyFlagNegation => "flag negation without any flags",
+            EmptyGroup => "empty group (e.g., '()')",
+            InvalidBase10(_) => "invalid base 10 number",
+            InvalidBase16(_) => "invalid base 16 number",
+            InvalidCaptureName(_) => "invalid capture name",
+            InvalidClassRange{..} => "invalid character class range",
+            InvalidClassEscape(_) => "invalid escape sequence in class",
+            InvalidRepeatRange{..} => "invalid counted repetition range",
+            InvalidScalarValue(_) => "invalid Unicode scalar value",
+            MissingBase10 => "missing count in repetition operator",
+            RepeaterExpectsExpr => "repetition operator missing expression",
+            RepeaterUnexpectedExpr(_) => "expression cannot be repeated",
+            UnclosedCaptureName(_) => "unclosed capture group name",
+            UnclosedHex => "unclosed hexadecimal literal",
+            UnclosedParen => "unclosed parenthesis",
+            UnclosedRepeat => "unclosed counted repetition operator",
+            UnclosedUnicodeName => "unclosed Unicode class literal",
+            UnexpectedClassEof => "unexpected EOF in character class",
+            UnexpectedEscapeEof => "unexpected EOF in escape sequence",
+            UnexpectedFlagEof => "unexpected EOF in flags",
+            UnexpectedTwoDigitHexEof => "unexpected EOF in hex literal",
+            UnopenedParen => "unopened parenthesis",
+            UnrecognizedEscape(_) => "unrecognized escape sequence",
+            UnrecognizedFlag(_) => "unrecognized flag",
+            UnrecognizedUnicodeClass(_) => "unrecognized Unicode class name",
+            StackExhausted => "stack exhausted, too much nesting",
+            FlagNotAllowed(_) => "flag not allowed",
+            UnicodeNotAllowed => "Unicode features not allowed",
+            InvalidUtf8 => "matching arbitrary bytes is not allowed",
+            EmptyClass => "empty character class",
+            UnsupportedClassChar(_) => "unsupported class notation",
+            __Nonexhaustive => unreachable!(),
+        }
+    }
+}
+
+impl ::std::error::Error for Error {
+    fn description(&self) -> &str {
+        self.kind.description()
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let ErrorKind::StackExhausted = self.kind {
+            write!(f, "Error parsing regex: {}", self.kind)
+        } else {
+            write!(
+                f, "Error parsing regex near '{}' at character offset {}: {}",
+                self.surround, self.pos, self.kind)
+        }
+    }
+}
+
+impl fmt::Display for ErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use ErrorKind::*;
+        match *self {
+            DoubleFlagNegation =>
+                write!(f, "Only one negation symbol is allowed in flags."),
+            DuplicateCaptureName(ref s) =>
+                write!(f, "Capture name '{}' is used more than once.", s),
+            EmptyAlternate =>
+                write!(f, "Alternations cannot be empty."),
+            EmptyCaptureName =>
+                write!(f, "Capture names cannot be empty."),
+            EmptyFlagNegation =>
+                write!(f, "Flag negation requires setting at least one flag."),
+            EmptyGroup =>
+                write!(f, "Empty regex groups (e.g., '()') are not allowed."),
+            InvalidBase10(ref s) =>
+                write!(f, "Not a valid base 10 number: '{}'", s),
+            InvalidBase16(ref s) =>
+                write!(f, "Not a valid base 16 number: '{}'", s),
+            InvalidCaptureName(ref s) =>
+                write!(f, "Invalid capture name: '{}'. Capture names must \
+                           consist of [_a-zA-Z0-9] and are not allowed to \
+                           start with with a number.", s),
+            InvalidClassRange { start, end } =>
+                write!(f, "Invalid character class range '{}-{}'. \
+                           Character class ranges must start with the smaller \
+                           character, but {} > {}", start, end, start, end),
+            InvalidClassEscape(ref e) =>
+                write!(f, "Invalid escape sequence in character \
+                           class: '{}'.", e),
+            InvalidRepeatRange { min, max } =>
+                write!(f, "Invalid counted repetition range: {{{}, {}}}. \
+                           Counted repetition ranges must start with the \
+                           minimum, but {} > {}", min, max, min, max),
+            InvalidScalarValue(c) =>
+                write!(f, "Number does not correspond to a Unicode scalar \
+                           value: '{}'.", c),
+            MissingBase10 =>
+                write!(f, "Missing maximum in counted
+repetition operator."),
+            RepeaterExpectsExpr =>
+                write!(f, "Missing expression for repetition operator."),
+            RepeaterUnexpectedExpr(ref e) =>
+                write!(f, "Invalid application of repetition operator to: \
+                          '{}'.", e),
+            UnclosedCaptureName(ref s) =>
+                write!(f, "Capture name group for '{}' is not closed. \
+                           (Missing a '>'.)", s),
+            UnclosedHex =>
+                write!(f, "Unclosed hexadecimal literal (missing a '}}')."),
+            UnclosedParen =>
+                write!(f, "Unclosed parenthesis."),
+            UnclosedRepeat =>
+                write!(f, "Unclosed counted repetition (missing a '}}')."),
+            UnclosedUnicodeName =>
+                write!(f, "Unclosed Unicode literal (missing a '}}')."),
+            UnexpectedClassEof =>
+                write!(f, "Character class was not closed before the end of \
+                           the regex (missing a ']')."),
+            UnexpectedEscapeEof =>
+                write!(f, "Started an escape sequence that didn't finish \
+                           before the end of the regex."),
+            UnexpectedFlagEof =>
+                write!(f, "Inline flag settings was not closed before the end \
+                           of the regex (missing a ')' or ':')."),
+            UnexpectedTwoDigitHexEof =>
+                write!(f, "Unexpected end of two digit hexadecimal literal."),
+            UnopenedParen =>
+                write!(f, "Unopened parenthesis."),
+            UnrecognizedEscape(c) =>
+                write!(f, "Unrecognized escape sequence: '\\{}'.", c),
+            UnrecognizedFlag(c) =>
+                write!(f, "Unrecognized flag: '{}'. \
+                           (Allowed flags: i, m, s, U, u, x.)", c),
+            UnrecognizedUnicodeClass(ref s) =>
+                write!(f, "Unrecognized Unicode class name: '{}'.", s),
+            StackExhausted =>
+                write!(f, "Exhausted space required to parse regex with too \
+                           much nesting."),
+            FlagNotAllowed(flag) =>
+                write!(f, "Use of the flag '{}' is not allowed.", flag),
+            UnicodeNotAllowed =>
+                write!(f, "Unicode features are not allowed when the Unicode \
+                           (u) flag is not set."),
+            InvalidUtf8 =>
+                write!(f, "Matching arbitrary bytes is not allowed."),
+            EmptyClass =>
+                write!(f, "Empty character classes are not allowed."),
+            UnsupportedClassChar(c) =>
+                write!(f, "Use of unescaped '{}' in character class is \
+                           not allowed.", c),
+            __Nonexhaustive => unreachable!(),
+        }
+    }
+}
+
+/// The result of binary search on the simple case folding table.
+///
+/// Note that this binary search is done on the "both" table, such that
+/// the index returned corresponds to the *first* location of `c1` in the
+/// table. The table can then be scanned linearly starting from the position
+/// returned to find other case mappings for `c1`.
+fn simple_case_fold_both_result(c1: char) -> result::Result<usize, usize> {
+    let table = &case_folding::C_plus_S_both_table;
+    let i = binary_search(table, |&(c2, _)| c1 <= c2);
+    if i >= table.len() || table[i].0 != c1 {
+        Err(i)
+    } else {
+        Ok(i)
+    }
+}
+
+/// Binary search to find first element such that `pred(T) == true`.
+///
+/// Assumes that if `pred(xs[i]) == true` then `pred(xs[i+1]) == true`.
+///
+/// If all elements yield `pred(T) == false`, then `xs.len()` is returned.
+fn binary_search<T, F>(xs: &[T], mut pred: F) -> usize
+        where F: FnMut(&T) -> bool {
+    let (mut left, mut right) = (0, xs.len());
+    while left < right {
+        let mid = (left + right) / 2;
+        if pred(&xs[mid]) {
+            right = mid;
+        } else {
+            left = mid + 1;
+        }
+    }
+    left
+}
+
+/// Escapes all regular expression meta characters in `text`.
+///
+/// The string returned may be safely used as a literal in a regular
+/// expression.
+pub fn escape(text: &str) -> String {
+    let mut quoted = String::with_capacity(text.len());
+    for c in text.chars() {
+        if parser::is_punct(c) {
+            quoted.push('\\');
+        }
+        quoted.push(c);
+    }
+    quoted
+}
+
+fn quote_char(c: char) -> String {
+    let mut s = String::new();
+    if parser::is_punct(c) {
+        s.push('\\');
+    }
+    s.push(c);
+    s
+}
+
+fn quote_byte(b: u8) -> String {
+    if parser::is_punct(b as char) || b == b'\'' || b == b'"' {
+        quote_char(b as char)
+    } else {
+        let escaped: Vec<u8> = ascii::escape_default(b).collect();
+        String::from_utf8(escaped).unwrap()
+    }
+}
+
+fn inc_char(c: char) -> char {
+    match c {
+        char::MAX => char::MAX,
+        '\u{D7FF}' => '\u{E000}',
+        c => char::from_u32(c as u32 + 1).unwrap(),
+    }
+}
+
+fn dec_char(c: char) -> char {
+    match c {
+        '\x00' => '\x00',
+        '\u{E000}' => '\u{D7FF}',
+        c => char::from_u32(c as u32 - 1).unwrap(),
+    }
+}
+
+/// Returns true if and only if `c` is a word character.
+#[doc(hidden)]
+pub fn is_word_char(c: char) -> bool {
+    match c {
+        '_' | '0' ... '9' | 'a' ... 'z' | 'A' ... 'Z'  => true,
+        _ => ::unicode::regex::PERLW.binary_search_by(|&(start, end)| {
+            if c >= start && c <= end {
+                Ordering::Equal
+            } else if start > c {
+                Ordering::Greater
+            } else {
+                Ordering::Less
+            }
+        }).is_ok(),
+    }
+}
+
+/// Returns true if and only if `c` is an ASCII word byte.
+#[doc(hidden)]
+pub fn is_word_byte(b: u8) -> bool {
+    match b {
+        b'_' | b'0' ... b'9' | b'a' ... b'z' | b'A' ... b'Z'  => true,
+        _ => false,
+    }
+}
+
+#[cfg(test)]
+mod properties;
+
+#[cfg(test)]
+mod tests {
+    use {CharClass, ClassRange, ByteClass, ByteRange, Expr};
+
+    fn class(ranges: &[(char, char)]) -> CharClass {
+        let ranges = ranges.iter().cloned()
+                           .map(|(c1, c2)| ClassRange::new(c1, c2)).collect();
+        CharClass::new(ranges)
+    }
+
+    fn bclass(ranges: &[(u8, u8)]) -> ByteClass {
+        let ranges = ranges.iter().cloned()
+                           .map(|(c1, c2)| ByteRange::new(c1, c2)).collect();
+        ByteClass::new(ranges)
+    }
+
+    fn e(re: &str) -> Expr { Expr::parse(re).unwrap() }
+
+    #[test]
+    fn stack_exhaustion() {
+        use std::iter::repeat;
+
+        let open: String = repeat('(').take(200).collect();
+        let close: String = repeat(')').take(200).collect();
+        assert!(Expr::parse(&format!("{}a{}", open, close)).is_ok());
+
+        let open: String = repeat('(').take(200 + 1).collect();
+        let close: String = repeat(')').take(200 + 1).collect();
+        assert!(Expr::parse(&format!("{}a{}", open, close)).is_err());
+    }
+
+    #[test]
+    fn anchored_start() {
+        assert!(e("^a").is_anchored_start());
+        assert!(e("(^a)").is_anchored_start());
+        assert!(e("^a|^b").is_anchored_start());
+        assert!(e("(^a)|(^b)").is_anchored_start());
+        assert!(e("(^(a|b))").is_anchored_start());
+
+        assert!(!e("^a|b").is_anchored_start());
+        assert!(!e("a|^b").is_anchored_start());
+    }
+
+    #[test]
+    fn anchored_end() {
+        assert!(e("a$").is_anchored_end());
+        assert!(e("(a$)").is_anchored_end());
+        assert!(e("a$|b$").is_anchored_end());
+        assert!(e("(a$)|(b$)").is_anchored_end());
+        assert!(e("((a|b)$)").is_anchored_end());
+
+        assert!(!e("a$|b").is_anchored_end());
+        assert!(!e("a|b$").is_anchored_end());
+    }
+
+    #[test]
+    fn class_canon_no_change() {
+        let cls = class(&[('a', 'c'), ('x', 'z')]);
+        assert_eq!(cls.clone().canonicalize(), cls);
+    }
+
+    #[test]
+    fn class_canon_unordered() {
+        let cls = class(&[('x', 'z'), ('a', 'c')]);
+        assert_eq!(cls.canonicalize(), class(&[
+            ('a', 'c'), ('x', 'z'),
+        ]));
+    }
+
+    #[test]
+    fn class_canon_overlap() {
+        let cls = class(&[('x', 'z'), ('w', 'y')]);
+        assert_eq!(cls.canonicalize(), class(&[
+            ('w', 'z'),
+        ]));
+    }
+
+    #[test]
+    fn class_canon_overlap_many() {
+        let cls = class(&[
+            ('c', 'f'), ('a', 'g'), ('d', 'j'), ('a', 'c'),
+            ('m', 'p'), ('l', 's'),
+        ]);
+        assert_eq!(cls.clone().canonicalize(), class(&[
+            ('a', 'j'), ('l', 's'),
+        ]));
+    }
+
+    #[test]
+    fn class_canon_overlap_boundary() {
+        let cls = class(&[('x', 'z'), ('u', 'w')]);
+        assert_eq!(cls.canonicalize(), class(&[
+            ('u', 'z'),
+        ]));
+    }
+
+    #[test]
+    fn class_canon_extreme_edge_case() {
+        let cls = class(&[('\x00', '\u{10FFFF}'), ('\x00', '\u{10FFFF}')]);
+        assert_eq!(cls.canonicalize(), class(&[
+            ('\x00', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_canon_singles() {
+        let cls = class(&[('a', 'a'), ('b', 'b')]);
+        assert_eq!(cls.canonicalize(), class(&[('a', 'b')]));
+    }
+
+    #[test]
+    fn class_negate_single() {
+        let cls = class(&[('a', 'a')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\x60'), ('\x62', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_singles() {
+        let cls = class(&[('a', 'a'), ('b', 'b')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\x60'), ('\x63', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_multiples() {
+        let cls = class(&[('a', 'c'), ('x', 'z')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\x60'), ('\x64', '\x77'), ('\x7b', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_min_scalar() {
+        let cls = class(&[('\x00', 'a')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x62', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_max_scalar() {
+        let cls = class(&[('a', '\u{10FFFF}')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\x60'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_everything() {
+        let cls = class(&[('\x00', '\u{10FFFF}')]);
+        assert_eq!(cls.negate(), class(&[]));
+    }
+
+    #[test]
+    fn class_negate_everything_sans_one() {
+        let cls = class(&[
+            ('\x00', '\u{10FFFD}'), ('\u{10FFFF}', '\u{10FFFF}')
+        ]);
+        assert_eq!(cls.negate(), class(&[
+            ('\u{10FFFE}', '\u{10FFFE}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_surrogates_min() {
+        let cls = class(&[('\x00', '\u{D7FF}')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\u{E000}', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_surrogates_min_edge() {
+        let cls = class(&[('\x00', '\u{D7FE}')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\u{D7FF}', '\u{10FFFF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_surrogates_max() {
+        let cls = class(&[('\u{E000}', '\u{10FFFF}')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\u{D7FF}'),
+        ]));
+    }
+
+    #[test]
+    fn class_negate_surrogates_max_edge() {
+        let cls = class(&[('\u{E001}', '\u{10FFFF}')]);
+        assert_eq!(cls.negate(), class(&[
+            ('\x00', '\u{E000}'),
+        ]));
+    }
+
+    #[test]
+    fn class_intersection_empty() {
+        let cls1 = class(&[]);
+        let cls2 = class(&[('a', 'a')]);
+        assert_intersection(cls1, cls2, class(&[]));
+    }
+
+    #[test]
+    fn class_intersection_single_equal() {
+        let cls1 = class(&[('a', 'a')]);
+        let cls2 = class(&[('a', 'a')]);
+        assert_intersection(cls1, cls2, class(&[('a', 'a')]));
+    }
+
+    #[test]
+    fn class_intersection_single_unequal() {
+        let cls1 = class(&[('a', 'a')]);
+        let cls2 = class(&[('b', 'b')]);
+        assert_intersection(cls1, cls2, class(&[]));
+    }
+
+    #[test]
+    fn class_intersection_single_in_other() {
+        let cls1 = class(&[('a', 'a')]);
+        let cls2 = class(&[('a', 'c')]);
+        assert_intersection(cls1, cls2, class(&[('a', 'a')]));
+    }
+
+    #[test]
+    fn class_intersection_range_in_other() {
+        let cls1 = class(&[('a', 'b')]);
+        let cls2 = class(&[('a', 'c')]);
+        assert_intersection(cls1, cls2, class(&[('a', 'b')]));
+    }
+
+    #[test]
+    fn class_intersection_range_intersection() {
+        let cls1 = class(&[('a', 'b')]);
+        let cls2 = class(&[('b', 'c')]);
+        assert_intersection(cls1, cls2, class(&[('b', 'b')]));
+    }
+
+    #[test]
+    fn class_intersection_only_adjacent() {
+        let cls1 = class(&[('a', 'b')]);
+        let cls2 = class(&[('c', 'd')]);
+        assert_intersection(cls1, cls2, class(&[]));
+    }
+
+    #[test]
+    fn class_intersection_range_subset() {
+        let cls1 = class(&[('b', 'c')]);
+        let cls2 = class(&[('a', 'd')]);
+        assert_intersection(cls1, cls2, class(&[('b', 'c')]));
+    }
+
+    #[test]
+    fn class_intersection_many_ranges_in_one_big() {
+        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = class(&[('a', 'h')]);
+        assert_intersection(cls1, cls2, class(&[
+            ('a', 'b'), ('d', 'e'), ('g', 'h')
+        ]));
+    }
+
+    #[test]
+    fn class_intersection_many_ranges_same() {
+        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        assert_intersection(cls1, cls2, class(&[
+            ('a', 'b'), ('d', 'e'), ('g', 'h')
+        ]));
+    }
+
+    #[test]
+    fn class_intersection_multiple_non_intersecting() {
+        let cls1 = class(&[('a', 'b'), ('g', 'h')]);
+        let cls2 = class(&[('d', 'e'), ('k', 'l')]);
+        assert_intersection(cls1, cls2, class(&[]));
+    }
+
+    #[test]
+    fn class_intersection_non_intersecting_then_intersecting() {
+        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = class(&[('h', 'h')]);
+        assert_intersection(cls1, cls2, class(&[('h', 'h')]));
+    }
+
+    #[test]
+    fn class_intersection_adjacent_alternating() {
+        let cls1 = class(&[('a', 'b'), ('e', 'f'), ('i', 'j')]);
+        let cls2 = class(&[('c', 'd'), ('g', 'h'), ('k', 'l')]);
+        assert_intersection(cls1, cls2, class(&[]));
+    }
+
+    #[test]
+    fn class_intersection_overlapping_alternating() {
+        let cls1 = class(&[('a', 'b'), ('c', 'd'), ('e', 'f')]);
+        let cls2 = class(&[('b', 'c'), ('d', 'e'), ('f', 'g')]);
+        assert_intersection(cls1, cls2, class(&[('b', 'f')]));
+    }
+
+    #[test]
+    fn class_canon_overlap_many_case_fold() {
+        let cls = class(&[
+            ('C', 'F'), ('A', 'G'), ('D', 'J'), ('A', 'C'),
+            ('M', 'P'), ('L', 'S'), ('c', 'f'),
+        ]);
+        assert_eq!(cls.case_fold(), class(&[
+            ('A', 'J'), ('L', 'S'),
+            ('a', 'j'), ('l', 's'),
+            ('\u{17F}', '\u{17F}'),
+        ]));
+
+        let cls = bclass(&[
+            (b'C', b'F'), (b'A', b'G'), (b'D', b'J'), (b'A', b'C'),
+            (b'M', b'P'), (b'L', b'S'), (b'c', b'f'),
+        ]);
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'A', b'J'), (b'L', b'S'),
+            (b'a', b'j'), (b'l', b's'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_az() {
+        let cls = class(&[('A', 'Z')]);
+        assert_eq!(cls.case_fold(), class(&[
+            ('A', 'Z'), ('a', 'z'),
+            ('\u{17F}', '\u{17F}'),
+            ('\u{212A}', '\u{212A}'),
+        ]));
+        let cls = class(&[('a', 'z')]);
+        assert_eq!(cls.case_fold(), class(&[
+            ('A', 'Z'), ('a', 'z'),
+            ('\u{17F}', '\u{17F}'),
+            ('\u{212A}', '\u{212A}'),
+        ]));
+
+        let cls = bclass(&[(b'A', b'Z')]);
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'A', b'Z'), (b'a', b'z'),
+        ]));
+        let cls = bclass(&[(b'a', b'z')]);
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'A', b'Z'), (b'a', b'z'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_a_underscore() {
+        let cls = class(&[('A', 'A'), ('_', '_')]);
+        assert_eq!(cls.clone().canonicalize(), class(&[
+            ('A', 'A'), ('_', '_'),
+        ]));
+        assert_eq!(cls.case_fold(), class(&[
+            ('A', 'A'), ('_', '_'), ('a', 'a'),
+        ]));
+
+        let cls = bclass(&[(b'A', b'A'), (b'_', b'_')]);
+        assert_eq!(cls.clone().canonicalize(), bclass(&[
+            (b'A', b'A'), (b'_', b'_'),
+        ]));
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'A', b'A'), (b'_', b'_'), (b'a', b'a'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_a_equals() {
+        let cls = class(&[('A', 'A'), ('=', '=')]);
+        assert_eq!(cls.clone().canonicalize(), class(&[
+            ('=', '='), ('A', 'A'),
+        ]));
+        assert_eq!(cls.case_fold(), class(&[
+            ('=', '='), ('A', 'A'), ('a', 'a'),
+        ]));
+
+        let cls = bclass(&[(b'A', b'A'), (b'=', b'=')]);
+        assert_eq!(cls.clone().canonicalize(), bclass(&[
+            (b'=', b'='), (b'A', b'A'),
+        ]));
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'=', b'='), (b'A', b'A'), (b'a', b'a'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_no_folding_needed() {
+        let cls = class(&[('\x00', '\x10')]);
+        assert_eq!(cls.case_fold(), class(&[
+            ('\x00', '\x10'),
+        ]));
+
+        let cls = bclass(&[(b'\x00', b'\x10')]);
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'\x00', b'\x10'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_negated() {
+        let cls = class(&[('x', 'x')]);
+        assert_eq!(cls.clone().case_fold(), class(&[
+            ('X', 'X'), ('x', 'x'),
+        ]));
+        assert_eq!(cls.case_fold().negate(), class(&[
+            ('\x00', 'W'), ('Y', 'w'), ('y', '\u{10FFFF}'),
+        ]));
+
+        let cls = bclass(&[(b'x', b'x')]);
+        assert_eq!(cls.clone().case_fold(), bclass(&[
+            (b'X', b'X'), (b'x', b'x'),
+        ]));
+        assert_eq!(cls.case_fold().negate(), bclass(&[
+            (b'\x00', b'W'), (b'Y', b'w'), (b'y', b'\xff'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_single_to_multiple() {
+        let cls = class(&[('k', 'k')]);
+        assert_eq!(cls.case_fold(), class(&[
+            ('K', 'K'), ('k', 'k'), ('\u{212A}', '\u{212A}'),
+        ]));
+
+        let cls = bclass(&[(b'k', b'k')]);
+        assert_eq!(cls.case_fold(), bclass(&[
+            (b'K', b'K'), (b'k', b'k'),
+        ]));
+    }
+
+    #[test]
+    fn class_fold_at() {
+        let cls = class(&[('@', '@')]);
+        assert_eq!(cls.clone().canonicalize(), class(&[('@', '@')]));
+        assert_eq!(cls.case_fold(), class(&[('@', '@')]));
+
+        let cls = bclass(&[(b'@', b'@')]);
+        assert_eq!(cls.clone().canonicalize(), bclass(&[(b'@', b'@')]));
+        assert_eq!(cls.case_fold(), bclass(&[(b'@', b'@')]));
+    }
+
+    #[test]
+    fn roundtrip_class_hypen() {
+        let expr = e("[-./]");
+        assert_eq!("(?u:[-\\.-/])", expr.to_string());
+
+        let expr = e("(?-u)[-./]");
+        assert_eq!("(?-u:[-\\.-/])", expr.to_string());
+    }
+
+    fn assert_intersection(cls1: CharClass, cls2: CharClass, expected: CharClass) {
+        // intersection operation should be commutative
+        assert_eq!(cls1.intersection(&cls2), expected);
+        assert_eq!(cls2.intersection(&cls1), expected);
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/literals.rs b/third_party/rust/regex-syntax-0.4.1/src/literals.rs
similarity index 100%
rename from third_party/rust/regex-syntax/src/literals.rs
rename to third_party/rust/regex-syntax-0.4.1/src/literals.rs
diff --git a/third_party/rust/regex-syntax-0.4.1/src/parser.rs b/third_party/rust/regex-syntax-0.4.1/src/parser.rs
new file mode 100644
index 000000000000..62ab76fb4f6b
--- /dev/null
+++ b/third_party/rust/regex-syntax-0.4.1/src/parser.rs
@@ -0,0 +1,3311 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp::{max, min};
+use std::u8;
+
+use unicode::regex::UNICODE_CLASSES;
+
+use {
+    Expr, Repeater, CharClass, ClassRange,
+    CaptureIndex, CaptureName,
+    Error, ErrorKind, Result,
+};
+
+/// Parser state.
+///
+/// Keeps the entire input in memory and maintains a cursor (char offset).
+///
+/// It also keeps an expression stack, which is responsible for managing
+/// grouped expressions and flag state.
+#[derive(Debug)]
+pub struct Parser {
+    chars: Vec<char>,
+    chari: usize,
+    stack: Vec<Build>,
+    caps: usize,
+    names: Vec<String>, // to check for duplicates
+    flags: Flags,
+}
+
+/// Flag state used in the parser.
+#[derive(Clone, Copy, Debug)]
+pub struct Flags {
+    /// i
+    pub casei: bool,
+    /// m
+    pub multi: bool,
+    /// s
+    pub dotnl: bool,
+    /// U
+    pub swap_greed: bool,
+    /// x
+    pub ignore_space: bool,
+    /// u
+    pub unicode: bool,
+    /// Not actually a flag, but when disabled, every regex that may not match
+    /// UTF-8 exclusively will cause the parser to return an error.
+    pub allow_bytes: bool,
+}
+
+impl Default for Flags {
+    fn default() -> Self {
+        Flags {
+            casei: false,
+            multi: false,
+            dotnl: false,
+            swap_greed: false,
+            ignore_space: false,
+            unicode: true,
+            allow_bytes: false,
+        }
+    }
+}
+
+/// An ephemeral type for representing the expression stack.
+///
+/// Everything on the stack is either a regular expression or a marker
+/// indicating the opening of a group (possibly non-capturing). The opening
+/// of a group copies the current flag state, which is reset on the parser
+/// state once the group closes.
+#[derive(Debug)]
+enum Build {
+    Expr(Expr),
+    LeftParen {
+        i: CaptureIndex,
+        name: CaptureName,
+        chari: usize,
+        old_flags: Flags,
+    },
+}
+
+/// A type for representing the elements of a bracket stack used for parsing
+/// character classes.
+///
+/// This is for parsing nested character classes without recursion.
+#[derive(Debug)]
+enum Bracket {
+    /// The opening of a character class (possibly negated)
+    LeftBracket {
+        negated: bool,
+    },
+    /// A set of characters within a character class, e.g., `a-z`
+    Set(CharClass),
+    /// An intersection operator (`&&`)
+    Intersection,
+}
+
+// Primary expression parsing routines.
+impl Parser {
+    pub fn parse(s: &str, flags: Flags) -> Result<Expr> {
+        Parser {
+            chars: s.chars().collect(),
+            chari: 0,
+            stack: vec![],
+            caps: 0,
+            names: vec![],
+            flags: flags,
+        }.parse_expr()
+    }
+
+    // Top-level expression parser.
+    //
+    // Starts at the beginning of the input and consumes until either the end
+    // of input or an error.
+    fn parse_expr(mut self) -> Result<Expr> {
+        loop {
+            self.ignore_space();
+            if self.eof() {
+                break;
+            }
+            let build_expr = match self.cur() {
+                '\\' => try!(self.parse_escape()),
+                '|' => { let e = try!(self.alternate()); self.bump(); e }
+                '?' => try!(self.parse_simple_repeat(Repeater::ZeroOrOne)),
+                '*' => try!(self.parse_simple_repeat(Repeater::ZeroOrMore)),
+                '+' => try!(self.parse_simple_repeat(Repeater::OneOrMore)),
+                '{' => try!(self.parse_counted_repeat()),
+                '[' => try!(self.parse_class()),
+                '^' => {
+                    if self.flags.multi {
+                        self.parse_one(Expr::StartLine)
+                    } else {
+                        self.parse_one(Expr::StartText)
+                    }
+                }
+                '$' => {
+                    if self.flags.multi {
+                        self.parse_one(Expr::EndLine)
+                    } else {
+                        self.parse_one(Expr::EndText)
+                    }
+                }
+                '.' => {
+                    if self.flags.dotnl {
+                        if self.flags.unicode {
+                            self.parse_one(Expr::AnyChar)
+                        } else {
+                            if !self.flags.allow_bytes {
+                                return Err(self.err(ErrorKind::InvalidUtf8));
+                            }
+                            self.parse_one(Expr::AnyByte)
+                        }
+                    } else {
+                        if self.flags.unicode {
+                            self.parse_one(Expr::AnyCharNoNL)
+                        } else {
+                            if !self.flags.allow_bytes {
+                                return Err(self.err(ErrorKind::InvalidUtf8));
+                            }
+                            self.parse_one(Expr::AnyByteNoNL)
+                        }
+                    }
+                }
+                '(' => try!(self.parse_group()),
+                ')' => {
+                    let (old_flags, e) = try!(self.close_paren());
+                    self.bump();
+                    self.flags = old_flags;
+                    e
+                }
+                _ => {
+                    let c = self.bump();
+                    try!(self.lit(c))
+                }
+            };
+            if !build_expr.is_empty() {
+                self.stack.push(build_expr);
+            }
+        }
+        self.finish_concat()
+    }
+
+    // Parses an escape sequence, e.g., \Ax
+    //
+    // Start: `\`
+    // End:   `x`
+    fn parse_escape(&mut self) -> Result<Build> {
+        self.bump();
+        if self.eof() {
+            return Err(self.err(ErrorKind::UnexpectedEscapeEof));
+        }
+        let c = self.cur();
+        if is_punct(c) || (self.flags.ignore_space && c.is_whitespace()) {
+            let c = self.bump();
+            return Ok(try!(self.lit(c)));
+        }
+        match c {
+            'a' => { self.bump(); Ok(try!(self.lit('\x07'))) }
+            'f' => { self.bump(); Ok(try!(self.lit('\x0C'))) }
+            't' => { self.bump(); Ok(try!(self.lit('\t'))) }
+            'n' => { self.bump(); Ok(try!(self.lit('\n'))) }
+            'r' => { self.bump(); Ok(try!(self.lit('\r'))) }
+            'v' => { self.bump(); Ok(try!(self.lit('\x0B'))) }
+            'A' => { self.bump(); Ok(Build::Expr(Expr::StartText)) }
+            'z' => { self.bump(); Ok(Build::Expr(Expr::EndText)) }
+            'b' => {
+                self.bump();
+                Ok(Build::Expr(if self.flags.unicode {
+                    Expr::WordBoundary
+                } else {
+                    Expr::WordBoundaryAscii
+                }))
+            }
+            'B' => {
+                self.bump();
+                Ok(Build::Expr(if self.flags.unicode {
+                    Expr::NotWordBoundary
+                } else {
+                    Expr::NotWordBoundaryAscii
+                }))
+            }
+            '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7' => self.parse_octal(),
+            'x' => { self.bump(); self.parse_hex() }
+            'p'|'P' => {
+                self.bump();
+                self.parse_unicode_class(c == 'P')
+                    .map(|cls| Build::Expr(Expr::Class(cls)))
+            }
+            'd'|'s'|'w'|'D'|'S'|'W' => {
+                self.bump();
+                Ok(Build::Expr(Expr::Class(self.parse_perl_class(c))))
+            }
+            c => Err(self.err(ErrorKind::UnrecognizedEscape(c))),
+        }
+    }
+
+    // Parses a group, e.g., `(abc)`.
+    //
+    // Start: `(`
+    // End:   `a`
+    //
+    // A more interesting example, `(?P<foo>abc)`.
+    //
+    // Start: `(`
+    // End:   `a`
+    fn parse_group(&mut self) -> Result<Build> {
+        let chari = self.chari;
+        let mut name: CaptureName = None;
+        self.bump();
+        self.ignore_space();
+        if self.bump_if("?P<") {
+            let n = try!(self.parse_group_name());
+            if self.names.iter().any(|n2| n2 == &n) {
+                return Err(self.err(ErrorKind::DuplicateCaptureName(n)));
+            }
+            self.names.push(n.clone());
+            name = Some(n);
+        } else if self.bump_if("?") {
+            // This can never be capturing. It's either setting flags for
+            // the current group, or it's opening a non-capturing group or
+            // it's opening a group with a specific set of flags (which is
+            // also non-capturing).
+            // Anything else is an error.
+            return self.parse_group_flags(chari);
+        }
+        self.caps = checkadd(self.caps, 1);
+        Ok(Build::LeftParen {
+            i: Some(self.caps),
+            name: name,
+            chari: chari,
+            old_flags: self.flags, // no flags changed if we're here
+        })
+    }
+
+    // Parses flags (inline or grouped), e.g., `(?s-i:abc)`.
+    //
+    // Start: `s`
+    // End:   `a`
+    //
+    // Another example, `(?s-i)a`.
+    //
+    // Start: `s`
+    // End:   `a`
+    fn parse_group_flags(&mut self, opening_chari: usize) -> Result<Build> {
+        let old_flags = self.flags;
+        let mut sign = true;
+        let mut saw_flag = false;
+        loop {
+            if self.eof() {
+                // e.g., (?i
+                return Err(self.err(ErrorKind::UnexpectedFlagEof));
+            }
+            match self.cur() {
+                'i' => { self.flags.casei = sign; saw_flag = true }
+                'm' => { self.flags.multi = sign; saw_flag = true }
+                's' => { self.flags.dotnl = sign; saw_flag = true }
+                'U' => { self.flags.swap_greed = sign; saw_flag = true }
+                'x' => { self.flags.ignore_space = sign; saw_flag = true }
+                'u' => { self.flags.unicode = sign; saw_flag = true }
+                '-' => {
+                    if !sign {
+                        // e.g., (?-i-s)
+                        return Err(self.err(ErrorKind::DoubleFlagNegation));
+                    }
+                    sign = false;
+                    saw_flag = false;
+                }
+                ')' => {
+                    if !saw_flag {
+                        // e.g., (?)
+                        return Err(self.err(ErrorKind::EmptyFlagNegation));
+                    }
+                    // At this point, we're just changing the flags inside
+                    // the current group, which means the old flags have
+                    // been saved elsewhere. Our modifications in place are
+                    // okey dokey!
+                    //
+                    // This particular flag expression only has a stateful
+                    // impact on a regex's AST, so nothing gets explicitly
+                    // added.
+                    self.bump();
+                    return Ok(Build::Expr(Expr::Empty));
+                }
+                ':' => {
+                    if !sign && !saw_flag {
+                        // e.g., (?i-:a)
+                        // Note that if there's no negation, it's OK not
+                        // to see flag, because you end up with a regular
+                        // non-capturing group: `(?:a)`.
+                        return Err(self.err(ErrorKind::EmptyFlagNegation));
+                    }
+                    self.bump();
+                    return Ok(Build::LeftParen {
+                        i: None,
+                        name: None,
+                        chari: opening_chari,
+                        old_flags: old_flags,
+                    });
+                }
+                // e.g., (?z:a)
+                c => return Err(self.err(ErrorKind::UnrecognizedFlag(c))),
+            }
+            self.bump();
+        }
+    }
+
+    // Parses a group name, e.g., `foo` in `(?P<foo>abc)`.
+    //
+    // Start: `f`
+    // End:   `a`
+    fn parse_group_name(&mut self) -> Result<String> {
+        let mut name = String::new();
+        while !self.eof() && !self.peek_is('>') {
+            name.push(self.bump());
+        }
+        if self.eof() {
+            // e.g., (?P<a
+            return Err(self.err(ErrorKind::UnclosedCaptureName(name)));
+        }
+        let all_valid = name.chars().all(is_valid_capture_char);
+        match name.chars().next() {
+            // e.g., (?P<>a)
+            None => Err(self.err(ErrorKind::EmptyCaptureName)),
+            Some(c) if (c >= '0' && c <= '9') || !all_valid => {
+                // e.g., (?P<a#>x)
+                // e.g., (?P<1a>x)
+                Err(self.err(ErrorKind::InvalidCaptureName(name)))
+            }
+            _ => {
+                self.bump(); // for `>`
+                Ok(name)
+            }
+        }
+    }
+
+    // Parses a counted repeition operator, e.g., `a{2,4}?z`.
+    //
+    // Start: `{`
+    // End:   `z`
+    fn parse_counted_repeat(&mut self) -> Result<Build> {
+        let e = try!(self.pop(ErrorKind::RepeaterExpectsExpr)); // e.g., ({5}
+        if !e.can_repeat() {
+            // e.g., a*{5}
+            return Err(self.err(ErrorKind::RepeaterUnexpectedExpr(e)));
+        }
+        self.bump();
+        self.ignore_space();
+        let min = try!(self.parse_decimal());
+        let mut max_opt = Some(min);
+        self.ignore_space();
+        if self.bump_if(',') {
+            self.ignore_space();
+            if self.peek_is('}') {
+                max_opt = None;
+            } else {
+                let max = try!(self.parse_decimal());
+                if min > max {
+                    // e.g., a{2,1}
+                    return Err(self.err(ErrorKind::InvalidRepeatRange {
+                        min: min,
+                        max: max,
+                    }));
+                }
+                max_opt = Some(max);
+            }
+        }
+        self.ignore_space();
+        if !self.bump_if('}') {
+            Err(self.err(ErrorKind::UnclosedRepeat))
+        } else {
+            Ok(Build::Expr(Expr::Repeat {
+                e: Box::new(e),
+                r: Repeater::Range { min: min, max: max_opt },
+                greedy: !self.bump_if('?') ^ self.flags.swap_greed,
+            }))
+        }
+    }
+
+    // Parses a simple repetition operator, e.g., `a+?z`.
+    //
+    // Start: `+`
+    // End:   `z`
+    //
+    // N.B. "simple" in this context means "not min/max repetition",
+    // e.g., `a{1,2}`.
+    fn parse_simple_repeat(&mut self, rep: Repeater) -> Result<Build> {
+        let e = try!(self.pop(ErrorKind::RepeaterExpectsExpr)); // e.g., (*
+        if !e.can_repeat() {
+            // e.g., a**
+            return Err(self.err(ErrorKind::RepeaterUnexpectedExpr(e)));
+        }
+        self.bump();
+        Ok(Build::Expr(Expr::Repeat {
+            e: Box::new(e),
+            r: rep,
+            greedy: !self.bump_if('?') ^ self.flags.swap_greed,
+        }))
+    }
+
+    // Parses a decimal number until the given character, e.g., `a{123,456}`.
+    //
+    // Start: `1`
+    // End:   `,` (where `until == ','`)
+    fn parse_decimal(&mut self) -> Result<u32> {
+        match self.bump_get(|c| is_ascii_word(c) || c.is_whitespace()) {
+            // e.g., a{}
+            None => Err(self.err(ErrorKind::MissingBase10)),
+            Some(n) => {
+                // e.g., a{xyz
+                // e.g., a{9999999999}
+                let n = n.trim();
+                u32::from_str_radix(n, 10)
+                    .map_err(|_| self.err(ErrorKind::InvalidBase10(n.into())))
+            }
+        }
+    }
+
+    // Parses an octal number, up to 3 digits, e.g., `a\123b`
+    //
+    // Start: `1`
+    // End:   `b`
+    fn parse_octal(&mut self) -> Result<Build> {
+        use std::char;
+        let mut i = 0; // counter for limiting octal to 3 digits.
+        let n = self.bump_get(|c| { i += 1; i <= 3 && c >= '0' && c <= '7' })
+                    .expect("octal string"); // guaranteed at least 1 digit
+        // I think both of the following unwraps are impossible to fail.
+        // We limit it to a three digit octal number, which maxes out at
+        // `0777` or `511` in decimal. Since all digits are in `0...7`, we'll
+        // always have a valid `u32` number. Moreover, since all numbers in
+        // the range `0...511` are valid Unicode scalar values, it will always
+        // be a valid `char`.
+        //
+        // Hence, we `unwrap` with reckless abandon.
+        let n = u32::from_str_radix(&n, 8).ok().expect("valid octal number");
+        if !self.flags.unicode {
+            return Ok(try!(self.u32_to_one_byte(n)));
+        }
+        let c = char::from_u32(n).expect("Unicode scalar value");
+        Ok(try!(self.lit(c)))
+    }
+
+    // Parses a hex number, e.g., `a\x5ab`.
+    //
+    // Start: `5`
+    // End:   `b`
+    //
+    // And also, `a\x{2603}b`.
+    //
+    // Start: `{`
+    // End:   `b`
+    fn parse_hex(&mut self) -> Result<Build> {
+        self.ignore_space();
+        if self.bump_if('{') {
+            self.parse_hex_many_digits()
+        } else {
+            self.parse_hex_two_digits()
+        }
+    }
+
+    // Parses a many-digit hex number, e.g., `a\x{2603}b`.
+    //
+    // Start: `2`
+    // End:   `b`
+    fn parse_hex_many_digits(&mut self) -> Result<Build> {
+        use std::char;
+
+        self.ignore_space();
+        let s = self.bump_get(is_ascii_word).unwrap_or("".into());
+        let n = try!(u32::from_str_radix(&s, 16)
+                         .map_err(|_| self.err(ErrorKind::InvalidBase16(s))));
+        self.ignore_space();
+        if !self.bump_if('}') {
+            // e.g., a\x{d
+            return Err(self.err(ErrorKind::UnclosedHex));
+        }
+        if !self.flags.unicode {
+            return Ok(try!(self.u32_to_one_byte(n)));
+        }
+        let c = try!(char::from_u32(n)
+                          .ok_or(self.err(ErrorKind::InvalidScalarValue(n))));
+        Ok(try!(self.lit(c)))
+    }
+
+    // Parses a two-digit hex number, e.g., `a\x5ab`.
+    //
+    // Start: `5`
+    // End:   `b`
+    fn parse_hex_two_digits(&mut self) -> Result<Build> {
+        use std::char;
+
+        let mut i = 0;
+        let s = self.bump_get(|_| { i += 1; i <= 2 }).unwrap_or("".into());
+        if s.len() < 2 {
+            // e.g., a\x
+            // e.g., a\xf
+            return Err(self.err(ErrorKind::UnexpectedTwoDigitHexEof));
+        }
+        let n = try!(u32::from_str_radix(&s, 16)
+                         .map_err(|_| self.err(ErrorKind::InvalidBase16(s))));
+        if !self.flags.unicode {
+            return Ok(try!(self.u32_to_one_byte(n)));
+        }
+        let c = char::from_u32(n).expect("Unicode scalar value");
+        Ok(try!(self.lit(c)))
+    }
+
+    // Parses a character class, e.g., `[^a-zA-Z0-9]+`.
+    //
+    // If the Unicode flag is enabled, the class is returned as a `CharClass`,
+    // otherwise it is converted to a `ByteClass`.
+    //
+    // Start: `[`
+    // End:   `+`
+    fn parse_class(&mut self) -> Result<Build> {
+        let class = try!(self.parse_class_as_chars());
+        Ok(Build::Expr(if self.flags.unicode {
+            Expr::Class(class)
+        } else {
+            let byte_class = class.to_byte_class();
+
+            // If `class` was only non-empty due to multibyte characters, the
+            // corresponding byte class will now be empty.
+            //
+            // See https://github.com/rust-lang/regex/issues/303
+            if byte_class.is_empty() {
+                // e.g., (?-u)[^\x00-\xFF]
+                return Err(self.err(ErrorKind::EmptyClass));
+            }
+
+            Expr::ClassBytes(byte_class)
+        }))
+    }
+
+    // Parses a character class as a `CharClass`, e.g., `[^a-zA-Z0-9]+`.
+    //
+    // Start: `[`
+    // End:   `+`
+    fn parse_class_as_chars(&mut self) -> Result<CharClass> {
+        let mut bracket_stack = vec![];
+        bracket_stack.extend(self.parse_open_bracket());
+        loop {
+            self.ignore_space();
+            if self.eof() {
+                // e.g., [a
+                return Err(self.err(ErrorKind::UnexpectedClassEof));
+            }
+            match self.cur() {
+                '[' => {
+                    if let Some(class) = self.maybe_parse_ascii() {
+                        // e.g. `[:alnum:]`
+                        bracket_stack.push(Bracket::Set(class));
+                    } else {
+                        // nested set, e.g. `[c-d]` in `[a-b[c-d]]`
+                        bracket_stack.extend(self.parse_open_bracket());
+                    }
+                }
+                ']' => {
+                    self.bump();
+                    let class = try!(self.close_bracket(&mut bracket_stack));
+                    if bracket_stack.is_empty() {
+                        // That was the outermost class, so stop now
+                        return Ok(class);
+                    }
+                    bracket_stack.push(Bracket::Set(class));
+                }
+                '\\' => {
+                    let class = try!(self.parse_class_escape());
+                    bracket_stack.push(Bracket::Set(class));
+                }
+                '&' if self.peek_is("&&") => {
+                    self.bump();
+                    self.bump();
+                    bracket_stack.push(Bracket::Intersection);
+                }
+                start => {
+                    if !self.flags.unicode {
+                        let _ = try!(self.codepoint_to_one_byte(start));
+                    }
+                    self.bump();
+                    match start {
+                        '~'|'-' => {
+                            // Only report an error if we see ~~ or --.
+                            if self.peek_is(start) {
+                                return Err(self.err(
+                                    ErrorKind::UnsupportedClassChar(start)));
+                            }
+                        }
+                        _ => {}
+                    }
+                    let class = try!(self.parse_class_range(start));
+                    bracket_stack.push(Bracket::Set(class));
+                }
+            }
+        }
+    }
+
+    // Parses the start of a character class or a nested character class.
+    // That includes negation using `^` and unescaped `-` and `]` allowed at
+    // the start of the class.
+    //
+    // e.g., `[^a]` or `[-a]` or `[]a]`
+    //
+    // Start: `[`
+    // End:   `a`
+    fn parse_open_bracket(&mut self) -> Vec<Bracket> {
+        self.bump();
+        self.ignore_space();
+        let negated = self.bump_if('^');
+        self.ignore_space();
+
+        let mut class = CharClass::empty();
+        while self.bump_if('-') {
+            class.ranges.push(ClassRange::one('-'));
+            self.ignore_space();
+        }
+        if class.is_empty() {
+            if self.bump_if(']') {
+                class.ranges.push(ClassRange::one(']'));
+                self.ignore_space();
+            }
+        }
+
+        let bracket = Bracket::LeftBracket { negated: negated };
+        if class.is_empty() {
+            vec![bracket]
+        } else {
+            vec![bracket, Bracket::Set(class)]
+        }
+    }
+
+    // Parses an escape in a character class.
+    //
+    // This is a helper for `parse_class`. Instead of returning an `Ok` value,
+    // it either mutates the char class or returns an error.
+    //
+    // e.g., `\wx`
+    //
+    // Start: `\`
+    // End:   `x`
+    fn parse_class_escape(&mut self) -> Result<CharClass> {
+        match try!(self.parse_escape()) {
+            Build::Expr(Expr::Class(class)) => {
+                Ok(class)
+            }
+            Build::Expr(Expr::ClassBytes(class2)) => {
+                let mut class = CharClass::empty();
+                for byte_range in class2 {
+                    let s = byte_range.start as char;
+                    let e = byte_range.end as char;
+                    class.ranges.push(ClassRange::new(s, e));
+                }
+                Ok(class)
+            }
+            Build::Expr(Expr::Literal { chars, .. }) => {
+                self.parse_class_range(chars[0])
+            }
+            Build::Expr(Expr::LiteralBytes { bytes, .. }) => {
+                let start = bytes[0] as char;
+                self.parse_class_range(start)
+            }
+            Build::Expr(e) => {
+                let err = ErrorKind::InvalidClassEscape(e);
+                Err(self.err(err))
+            }
+            // Because `parse_escape` can never return `LeftParen`.
+            _ => unreachable!(),
+        }
+    }
+
+    // Parses a single range in a character class.
+    //
+    // e.g., `[a-z]`
+    //
+    // Start: `-` (with start == `a`)
+    // End:   `]`
+    fn parse_class_range(&mut self, start: char) -> Result<CharClass> {
+        self.ignore_space();
+        if !self.bump_if('-') {
+            // Not a range, so just return a singleton range.
+            return Ok(CharClass::new(vec![ClassRange::one(start)]));
+        }
+        self.ignore_space();
+        if self.eof() {
+            // e.g., [a-
+            return Err(self.err(ErrorKind::UnexpectedClassEof));
+        }
+        if self.peek_is(']') {
+            // This is the end of the class, so we permit use of `-` as a
+            // regular char (just like we do in the beginning).
+            return Ok(CharClass::new(vec![ClassRange::one(start), ClassRange::one('-')]));
+        }
+
+        // We have a real range. Just need to check to parse literal and
+        // make sure it's a valid range.
+        let end = match self.cur() {
+            '\\' => match try!(self.parse_escape()) {
+                Build::Expr(Expr::Literal { chars, .. }) => {
+                    chars[0]
+                }
+                Build::Expr(Expr::LiteralBytes { bytes, .. }) => {
+                    bytes[0] as char
+                }
+                Build::Expr(e) => {
+                    return Err(self.err(ErrorKind::InvalidClassEscape(e)));
+                }
+                // Because `parse_escape` can never return `LeftParen`.
+                _ => unreachable!(),
+            },
+            c => {
+                self.bump();
+                if c == '-' {
+                    return Err(self.err(ErrorKind::UnsupportedClassChar('-')));
+                }
+                if !self.flags.unicode {
+                    let _ = try!(self.codepoint_to_one_byte(c));
+                }
+                c
+            }
+        };
+        if end < start {
+            // e.g., [z-a]
+            return Err(self.err(ErrorKind::InvalidClassRange {
+                start: start,
+                end: end,
+            }));
+        }
+        Ok(CharClass::new(vec![ClassRange::new(start, end)]))
+    }
+
+    // Parses an ASCII class, e.g., `[:alnum:]+`.
+    //
+    // Start: `[`
+    // End:   `+`
+    //
+    // Also supports negation, e.g., `[:^alnum:]`.
+    //
+    // This parsing routine is distinct from the others in that it doesn't
+    // actually report any errors. Namely, if it fails, then the parser should
+    // fall back to parsing a regular class.
+    //
+    // This method will only make progress in the parser if it succeeds.
+    // Otherwise, the input remains where it started.
+    fn maybe_parse_ascii(&mut self) -> Option<CharClass> {
+        fn parse(p: &mut Parser) -> Option<CharClass> {
+            p.bump(); // the `[`
+            if !p.bump_if(':') { return None; }
+            let negate = p.bump_if('^');
+            let name = match p.bump_get(|c| c != ':') {
+                None => return None,
+                Some(name) => name,
+            };
+            if !p.bump_if(":]") { return None; }
+            ascii_class(&name).map(|cls| p.class_transform(negate, cls))
+        }
+        let start = self.chari;
+        match parse(self) {
+            None => { self.chari = start; None }
+            result => result,
+        }
+    }
+
+    // Parses a Uncode class name, e.g., `a\pLb`.
+    //
+    // Start: `L`
+    // End:   `b`
+    //
+    // And also, `a\p{Greek}b`.
+    //
+    // Start: `{`
+    // End:   `b`
+    //
+    // `negate` is true when the class name is used with `\P`.
+    fn parse_unicode_class(&mut self, neg: bool) -> Result<CharClass> {
+        self.ignore_space();
+        let name =
+            if self.bump_if('{') {
+                self.ignore_space();
+                let n = self.bump_get(is_ascii_word).unwrap_or("".into());
+                self.ignore_space();
+                if n.is_empty() || !self.bump_if('}') {
+                    // e.g., \p{Greek
+                    return Err(self.err(ErrorKind::UnclosedUnicodeName));
+                }
+                n
+            } else {
+                if self.eof() {
+                    // e.g., \p
+                    return Err(self.err(ErrorKind::UnexpectedEscapeEof));
+                }
+                self.bump().to_string()
+            };
+        match unicode_class(&name) {
+            None => Err(self.err(ErrorKind::UnrecognizedUnicodeClass(name))),
+            Some(cls) => {
+                if self.flags.unicode {
+                    Ok(self.class_transform(neg, cls))
+                } else {
+                    Err(self.err(ErrorKind::UnicodeNotAllowed))
+                }
+            }
+        }
+    }
+
+    // Parses a perl character class with Unicode support.
+    //
+    // `name` must be one of d, s, w, D, S, W. If not, this function panics.
+    //
+    // No parser state is changed.
+    fn parse_perl_class(&mut self, name: char) -> CharClass {
+        use unicode::regex::{PERLD, PERLS, PERLW};
+        let (cls, negate) = match (self.flags.unicode, name) {
+            (true, 'd') => (raw_class_to_expr(PERLD), false),
+            (true, 'D') => (raw_class_to_expr(PERLD), true),
+            (true, 's') => (raw_class_to_expr(PERLS), false),
+            (true, 'S') => (raw_class_to_expr(PERLS), true),
+            (true, 'w') => (raw_class_to_expr(PERLW), false),
+            (true, 'W') => (raw_class_to_expr(PERLW), true),
+            (false, 'd') => (ascii_class("digit").unwrap(), false),
+            (false, 'D') => (ascii_class("digit").unwrap(), true),
+            (false, 's') => (ascii_class("space").unwrap(), false),
+            (false, 'S') => (ascii_class("space").unwrap(), true),
+            (false, 'w') => (ascii_class("word").unwrap(), false),
+            (false, 'W') => (ascii_class("word").unwrap(), true),
+            _ => unreachable!(),
+        };
+        self.class_transform(negate, cls)
+    }
+
+    // Always bump to the next input and return the given expression as a
+    // `Build`.
+    //
+    // This is mostly for convenience when the surrounding context implies
+    // that the next character corresponds to the given expression.
+    fn parse_one(&mut self, e: Expr) -> Build {
+        self.bump();
+        Build::Expr(e)
+    }
+}
+
+// Auxiliary helper methods.
+impl Parser {
+    fn chars(&self) -> Chars {
+        Chars::new(&self.chars[self.chari..])
+    }
+
+    fn ignore_space(&mut self) {
+        if !self.flags.ignore_space {
+            return;
+        }
+        while !self.eof() {
+            match self.cur() {
+                '#' => {
+                    self.bump();
+                    while !self.eof() {
+                        match self.bump() {
+                            '\n' => break,
+                            _ => continue,
+                        }
+                    }
+                },
+                c => if !c.is_whitespace() {
+                    return;
+                } else {
+                    self.bump();
+                }
+            }
+        }
+    }
+
+    fn bump(&mut self) -> char {
+        let c = self.cur();
+        self.chari = checkadd(self.chari, self.chars().next_count());
+        c
+    }
+
+    fn cur(&self) -> char { self.chars().next().unwrap() }
+
+    fn eof(&self) -> bool { self.chars().next().is_none() }
+
+    fn bump_get<B: Bumpable>(&mut self, s: B) -> Option<String> {
+        let n = s.match_end(self);
+        if n == 0 {
+            None
+        } else {
+            let end = checkadd(self.chari, n);
+            let s = self.chars[self.chari..end]
+                        .iter().cloned().collect::<String>();
+            self.chari = end;
+            Some(s)
+        }
+    }
+
+    fn bump_if<B: Bumpable>(&mut self, s: B) -> bool {
+        let n = s.match_end(self);
+        if n == 0 {
+            false
+        } else {
+            self.chari = checkadd(self.chari, n);
+            true
+        }
+    }
+
+    fn peek_is<B: Bumpable>(&self, s: B) -> bool {
+        s.match_end(self) > 0
+    }
+
+    fn err(&self, kind: ErrorKind) -> Error {
+        self.errat(self.chari, kind)
+    }
+
+    fn errat(&self, pos: usize, kind: ErrorKind) -> Error {
+        Error { pos: pos, surround: self.windowat(pos), kind: kind }
+    }
+
+    fn windowat(&self, pos: usize) -> String {
+        let s = max(5, pos) - 5;
+        let e = min(self.chars.len(), checkadd(pos, 5));
+        self.chars[s..e].iter().cloned().collect()
+    }
+
+    fn pop(&mut self, expected: ErrorKind) -> Result<Expr> {
+        match self.stack.pop() {
+            None | Some(Build::LeftParen{..}) => Err(self.err(expected)),
+            Some(Build::Expr(e)) => Ok(e),
+        }
+    }
+
+    // If the current context calls for case insensitivity, then apply
+    // case folding. Similarly, if `negate` is `true`, then negate the
+    // class. (Negation always proceeds case folding.)
+    fn class_transform(&self, negate: bool, mut cls: CharClass) -> CharClass {
+        if self.flags.casei {
+            cls = cls.case_fold();
+        }
+        if negate {
+            cls = cls.negate();
+        }
+        cls
+    }
+
+    // Translates a Unicode codepoint into a single UTF-8 byte, and returns an
+    // error if it's not possible.
+    //
+    // This will panic if self.flags.unicode == true.
+    fn codepoint_to_one_byte(&self, c: char) -> Result<u8> {
+        assert!(!self.flags.unicode);
+        let bytes = c.to_string().as_bytes().to_owned();
+        if bytes.len() > 1 {
+            return Err(self.err(ErrorKind::UnicodeNotAllowed));
+        }
+        Ok(bytes[0])
+    }
+
+    // Creates a new byte literal from a single byte.
+    //
+    // If the given number can't fit into a single byte, then it is assumed
+    // to be a Unicode codepoint and an error is returned.
+    //
+    // This should only be called when the bytes flag is enabled.
+    fn u32_to_one_byte(&self, b: u32) -> Result<Build> {
+        assert!(!self.flags.unicode);
+        if b > u8::MAX as u32 {
+            Err(self.err(ErrorKind::UnicodeNotAllowed))
+        } else if !self.flags.allow_bytes && b > 0x7F {
+            Err(self.err(ErrorKind::InvalidUtf8))
+        } else {
+            Ok(Build::Expr(Expr::LiteralBytes {
+                bytes: vec![b as u8],
+                casei: self.flags.casei,
+            }))
+        }
+    }
+
+    // Creates a new literal expr from a Unicode codepoint.
+    //
+    // Creates a byte literal if the `bytes` flag is set.
+    fn lit(&self, c: char) -> Result<Build> {
+        Ok(Build::Expr(if self.flags.unicode {
+            Expr::Literal {
+                chars: vec![c],
+                casei: self.flags.casei,
+            }
+        } else {
+            Expr::LiteralBytes {
+                bytes: vec![try!(self.codepoint_to_one_byte(c))],
+                casei: self.flags.casei,
+            }
+        }))
+    }
+}
+
+struct Chars<'a> {
+    chars: &'a [char],
+    cur: usize,
+}
+
+impl<'a> Iterator for Chars<'a> {
+    type Item = char;
+    fn next(&mut self) -> Option<char> {
+        let x = self.c();
+        self.advance();
+        return x;
+    }
+}
+
+impl<'a> Chars<'a> {
+    fn new(chars: &[char]) -> Chars {
+        Chars {
+            chars: chars,
+            cur: 0,
+        }
+    }
+
+    fn c(&self) -> Option<char> {
+        self.chars.get(self.cur).map(|&c| c)
+    }
+
+    fn advance(&mut self) {
+        self.cur = checkadd(self.cur, 1);
+    }
+
+    fn next_count(&mut self) -> usize {
+        self.next();
+        self.cur
+    }
+}
+
+// Auxiliary methods for manipulating the expression stack.
+impl Parser {
+    // Called whenever an alternate (`|`) is found.
+    //
+    // This pops the expression stack until:
+    //
+    //  1. The stack is empty. Pushes an alternation with one arm.
+    //  2. An opening parenthesis is found. Leave the parenthesis
+    //     on the stack and push an alternation with one arm.
+    //  3. An alternate (`|`) is found. Pop the existing alternation,
+    //     add an arm and push the modified alternation.
+    //
+    // Each "arm" in the above corresponds to the concatenation of all
+    // popped expressions.
+    //
+    // In the first two cases, the stack is left in an invalid state
+    // because an alternation with one arm is not allowed. This
+    // particular state will be detected by `finish_concat` and an
+    // error will be reported.
+    //
+    // In none of the cases is an empty arm allowed. If an empty arm
+    // is found, an error is reported.
+    fn alternate(&mut self) -> Result<Build> {
+        let mut concat = vec![];
+        let alts = |es| Ok(Build::Expr(Expr::Alternate(es)));
+        loop {
+            match self.stack.pop() {
+                None => {
+                    if concat.is_empty() {
+                        // e.g., |a
+                        return Err(self.err(ErrorKind::EmptyAlternate));
+                    }
+                    return alts(vec![rev_concat(concat)]);
+                }
+                Some(e @ Build::LeftParen{..}) => {
+                    if concat.is_empty() {
+                        // e.g., (|a)
+                        return Err(self.err(ErrorKind::EmptyAlternate));
+                    }
+                    self.stack.push(e);
+                    return alts(vec![rev_concat(concat)]);
+                }
+                Some(Build::Expr(Expr::Alternate(mut es))) => {
+                    if concat.is_empty() {
+                        // e.g., a||
+                        return Err(self.err(ErrorKind::EmptyAlternate));
+                    }
+                    es.push(rev_concat(concat));
+                    return alts(es);
+                }
+                Some(Build::Expr(e)) => { concat.push(e); }
+            }
+        }
+    }
+
+    // Called whenever a closing parenthesis (`)`) is found.
+    //
+    // This pops the expression stack until:
+    //
+    //  1. The stack is empty. An error is reported because this
+    //     indicates an unopened parenthesis.
+    //  2. An opening parenthesis is found. Pop the opening parenthesis
+    //     and push a `Group` expression.
+    //  3. An alternate (`|`) is found. Pop the existing alternation
+    //     and an arm to it in place. Pop one more item from the stack.
+    //     If the stack was empty, then report an unopened parenthesis
+    //     error, otherwise assume it is an opening parenthesis and
+    //     push a `Group` expression with the popped alternation.
+    //     (We can assume this is an opening parenthesis because an
+    //     alternation either corresponds to the entire Regex or it
+    //     corresponds to an entire group. This is guaranteed by the
+    //     `alternate` method.)
+    //
+    // Each "arm" in the above corresponds to the concatenation of all
+    // popped expressions.
+    //
+    // Empty arms nor empty groups are allowed.
+    fn close_paren(&mut self) -> Result<(Flags, Build)> {
+        let mut concat = vec![];
+        loop {
+            match self.stack.pop() {
+                // e.g., )
+                None => return Err(self.err(ErrorKind::UnopenedParen)),
+                Some(Build::LeftParen { i, name, old_flags, .. }) => {
+                    if concat.is_empty() {
+                        // e.g., ()
+                        return Err(self.err(ErrorKind::EmptyGroup));
+                    }
+                    return Ok((old_flags, Build::Expr(Expr::Group {
+                        e: Box::new(rev_concat(concat)),
+                        i: i,
+                        name: name,
+                    })));
+                }
+                Some(Build::Expr(Expr::Alternate(mut es))) => {
+                    if concat.is_empty() {
+                        // e.g., (a|)
+                        return Err(self.err(ErrorKind::EmptyAlternate));
+                    }
+                    es.push(rev_concat(concat));
+                    match self.stack.pop() {
+                        // e.g., a|b)
+                        None => return Err(self.err(ErrorKind::UnopenedParen)),
+                        Some(Build::Expr(_)) => unreachable!(),
+                        Some(Build::LeftParen { i, name, old_flags, .. }) => {
+                            return Ok((old_flags, Build::Expr(Expr::Group {
+                                e: Box::new(Expr::Alternate(es)),
+                                i: i,
+                                name: name,
+                            })));
+                        }
+                    }
+                }
+                Some(Build::Expr(e)) => { concat.push(e); }
+            }
+        }
+    }
+
+    // Called only when the parser reaches the end of input.
+    //
+    // This pops the expression stack until:
+    //
+    //  1. The stack is empty. Return concatenation of popped
+    //     expressions. This concatenation may be empty!
+    //  2. An alternation is found. Pop the alternation and push
+    //     a new arm. Return the alternation as the entire Regex.
+    //     After this, the stack must be empty, or else there is
+    //     an unclosed paren.
+    //
+    // If an opening parenthesis is popped, then an error is
+    // returned since it indicates an unclosed parenthesis.
+    fn finish_concat(&mut self) -> Result<Expr> {
+        let mut concat = vec![];
+        loop {
+            match self.stack.pop() {
+                None => { return Ok(rev_concat(concat)); }
+                Some(Build::LeftParen{ chari, ..}) => {
+                    // e.g., a(b
+                    return Err(self.errat(chari, ErrorKind::UnclosedParen));
+                }
+                Some(Build::Expr(Expr::Alternate(mut es))) => {
+                    if concat.is_empty() {
+                        // e.g., a|
+                        return Err(self.err(ErrorKind::EmptyAlternate));
+                    }
+                    es.push(rev_concat(concat));
+                    // Make sure there are no opening parens remaining.
+                    match self.stack.pop() {
+                        None => return Ok(Expr::Alternate(es)),
+                        Some(Build::LeftParen{ chari, ..}) => {
+                            // e.g., (a|b
+                            return Err(self.errat(
+                                chari, ErrorKind::UnclosedParen));
+                        }
+                        e => unreachable!("{:?}", e),
+                    }
+                }
+                Some(Build::Expr(e)) => { concat.push(e); }
+            }
+        }
+    }
+}
+
+// Methods for working with the bracket stack used for character class parsing.
+impl Parser {
+
+    // After parsing a closing bracket `]`, process elements of the bracket
+    // stack until finding the corresponding opening bracket `[`, and return
+    // the combined character class. E.g. with `[^b-f&&ab-c]`:
+    //
+    // 1. Adjacent sets are merged into a single union: `ab-c` -> `a-c`
+    // 2. Unions separated by `&&` are intersected: `b-f` and `a-c` -> `b-c`
+    // 3. Negation is applied if necessary: `b-c` -> negation of `b-c`
+    fn close_bracket(&self, stack: &mut Vec<Bracket>) -> Result<CharClass> {
+        let mut union = CharClass::empty();
+        let mut intersect = vec![];
+        loop {
+            match stack.pop() {
+                Some(Bracket::Set(class)) => {
+                    union.ranges.extend(class);
+                }
+                Some(Bracket::Intersection) => {
+                    let class = self.class_union_transform(union);
+                    intersect.push(class);
+                    union = CharClass::empty();
+                }
+                Some(Bracket::LeftBracket { negated }) => {
+                    let mut class = self.class_union_transform(union);
+                    for c in intersect {
+                        class = class.intersection(&c);
+                    }
+                    // negate after combining all sets (`^` has lower precedence than `&&`)
+                    if negated {
+                        class = class.negate();
+                    }
+                    if class.is_empty() {
+                        // e.g., [^\d\D]
+                        return Err(self.err(ErrorKind::EmptyClass));
+                    }
+                    return Ok(class);
+                }
+                // The first element on the stack is a `LeftBracket`
+                None => unreachable!()
+            }
+        }
+    }
+
+    // Apply case folding if requested on the union character class, and
+    // return a canonicalized class.
+    fn class_union_transform(&self, class: CharClass) -> CharClass {
+        if self.flags.casei {
+            // Case folding canonicalizes too
+            class.case_fold()
+        } else {
+            class.canonicalize()
+        }
+    }
+}
+
+impl Build {
+    fn is_empty(&self) -> bool {
+        match *self {
+            Build::Expr(Expr::Empty) => true,
+            _ => false,
+        }
+    }
+}
+
+// Make it ergonomic to conditionally bump the parser.
+// i.e., `bump_if('a')` or `bump_if("abc")`.
+trait Bumpable {
+    fn match_end(self, p: &Parser) -> usize;
+}
+
+impl Bumpable for char {
+    fn match_end(self, p: &Parser) -> usize {
+        let mut chars = p.chars();
+        if chars.next().map(|c| c == self).unwrap_or(false) {
+            chars.cur
+        } else {
+            0
+        }
+    }
+}
+
+impl<'a> Bumpable for &'a str {
+    fn match_end(self, p: &Parser) -> usize {
+        let mut search = self.chars();
+        let mut rest = p.chars();
+        let mut count = 0;
+        loop {
+            match (rest.next(), search.next()) {
+                (Some(c1), Some(c2)) if c1 == c2 => count = rest.cur,
+                (_, None) => return count,
+                _ => return 0,
+            }
+        }
+    }
+}
+
+impl<F: FnMut(char) -> bool> Bumpable for F {
+    fn match_end(mut self, p: &Parser) -> usize {
+        let mut chars = p.chars();
+        let mut count = 0;
+        while let Some(c) = chars.next() {
+            if !self(c) {
+                break
+            }
+            count = chars.cur;
+        }
+        count
+    }
+}
+
+// Turn a sequence of expressions into a concatenation.
+// This only uses `Concat` if there are 2 or more expressions.
+fn rev_concat(mut exprs: Vec<Expr>) -> Expr {
+    if exprs.len() == 0 {
+        Expr::Empty
+    } else if exprs.len() == 1 {
+        exprs.pop().unwrap()
+    } else {
+        exprs.reverse();
+        Expr::Concat(exprs)
+    }
+}
+
+// Returns true if and only if the given character is allowed in a capture
+// name. Note that the first char of a capture name must not be numeric.
+fn is_valid_capture_char(c: char) -> bool {
+    c == '_' || (c >= '0' && c <= '9')
+    || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+fn is_ascii_word(c: char) -> bool {
+    match c {
+        'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => true,
+        _ => false,
+    }
+}
+
+/// Returns true if the give character has significance in a regex.
+pub fn is_punct(c: char) -> bool {
+    match c {
+        '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' |
+        '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~' => true,
+        _ => false,
+    }
+}
+
+fn checkadd(x: usize, y: usize) -> usize {
+    x.checked_add(y).expect("regex length overflow")
+}
+
+fn unicode_class(name: &str) -> Option<CharClass> {
+    UNICODE_CLASSES.binary_search_by(|&(s, _)| s.cmp(name)).ok().map(|i| {
+        raw_class_to_expr(UNICODE_CLASSES[i].1)
+    })
+}
+
+fn ascii_class(name: &str) -> Option<CharClass> {
+    ASCII_CLASSES.binary_search_by(|&(s, _)| s.cmp(name)).ok().map(|i| {
+        raw_class_to_expr(ASCII_CLASSES[i].1)
+    })
+}
+
+fn raw_class_to_expr(raw: &[(char, char)]) -> CharClass {
+    let range = |&(s, e)| ClassRange { start: s, end: e };
+    CharClass::new(raw.iter().map(range).collect())
+}
+
+type Class = &'static [(char, char)];
+type NamedClasses = &'static [(&'static str, Class)];
+
+const ASCII_CLASSES: NamedClasses = &[
+    // Classes must be in alphabetical order so that bsearch works.
+    // [:alnum:]      alphanumeric (== [0-9A-Za-z])
+    // [:alpha:]      alphabetic (== [A-Za-z])
+    // [:ascii:]      ASCII (== [\x00-\x7F])
+    // [:blank:]      blank (== [\t ])
+    // [:cntrl:]      control (== [\x00-\x1F\x7F])
+    // [:digit:]      digits (== [0-9])
+    // [:graph:]      graphical (== [!-~])
+    // [:lower:]      lower case (== [a-z])
+    // [:print:]      printable (== [ -~] == [ [:graph:]])
+    // [:punct:]      punctuation (== [!-/:-@[-`{-~])
+    // [:space:]      whitespace (== [\t\n\v\f\r ])
+    // [:upper:]      upper case (== [A-Z])
+    // [:word:]       word characters (== [0-9A-Za-z_])
+    // [:xdigit:]     hex digit (== [0-9A-Fa-f])
+    // Taken from: http://golang.org/pkg/regex/syntax/
+    ("alnum", &ALNUM),
+    ("alpha", &ALPHA),
+    ("ascii", &ASCII),
+    ("blank", &BLANK),
+    ("cntrl", &CNTRL),
+    ("digit", &DIGIT),
+    ("graph", &GRAPH),
+    ("lower", &LOWER),
+    ("print", &PRINT),
+    ("punct", &PUNCT),
+    ("space", &SPACE),
+    ("upper", &UPPER),
+    ("word", &WORD),
+    ("xdigit", &XDIGIT),
+];
+
+const ALNUM: Class = &[('0', '9'), ('A', 'Z'), ('a', 'z')];
+const ALPHA: Class = &[('A', 'Z'), ('a', 'z')];
+const ASCII: Class = &[('\x00', '\x7F')];
+const BLANK: Class = &[(' ', ' '), ('\t', '\t')];
+const CNTRL: Class = &[('\x00', '\x1F'), ('\x7F', '\x7F')];
+const DIGIT: Class = &[('0', '9')];
+const GRAPH: Class = &[('!', '~')];
+const LOWER: Class = &[('a', 'z')];
+const PRINT: Class = &[(' ', '~')];
+const PUNCT: Class = &[('!', '/'), (':', '@'), ('[', '`'), ('{', '~')];
+const SPACE: Class = &[('\t', '\t'), ('\n', '\n'), ('\x0B', '\x0B'),
+                       ('\x0C', '\x0C'), ('\r', '\r'), (' ', ' ')];
+const UPPER: Class = &[('A', 'Z')];
+const WORD: Class = &[('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z')];
+const XDIGIT: Class = &[('0', '9'), ('A', 'F'), ('a', 'f')];
+
+#[cfg(test)]
+mod tests {
+    use {
+        CharClass, ClassRange, ByteClass, ByteRange,
+        Expr, Repeater,
+        ErrorKind,
+    };
+    use unicode::regex::{PERLD, PERLS, PERLW};
+    use super::{LOWER, UPPER, WORD, Flags, Parser, ascii_class};
+
+    static YI: &'static [(char, char)] = &[
+        ('\u{a000}', '\u{a48c}'), ('\u{a490}', '\u{a4c6}'),
+    ];
+
+    fn p(s: &str) -> Expr { Parser::parse(s, Flags::default()).unwrap() }
+    fn pf(s: &str, flags: Flags) -> Expr { Parser::parse(s, flags).unwrap() }
+    fn lit(c: char) -> Expr { Expr::Literal { chars: vec![c], casei: false } }
+    fn liti(c: char) -> Expr { Expr::Literal { chars: vec![c], casei: true } }
+    fn b<T>(v: T) -> Box<T> { Box::new(v) }
+    fn c(es: &[Expr]) -> Expr { Expr::Concat(es.to_vec()) }
+
+    fn pb(s: &str) -> Expr {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        Parser::parse(s, flags).unwrap()
+    }
+
+    fn blit(b: u8) -> Expr {
+        Expr::LiteralBytes {
+            bytes: vec![b],
+            casei: false,
+        }
+    }
+
+    fn bliti(b: u8) -> Expr {
+        Expr::LiteralBytes {
+            bytes: vec![b],
+            casei: true,
+        }
+    }
+
+    fn class(ranges: &[(char, char)]) -> CharClass {
+        let ranges = ranges.iter().cloned()
+                           .map(|(c1, c2)| ClassRange::new(c1, c2)).collect();
+        CharClass::new(ranges)
+    }
+
+    fn classes(classes: &[&[(char, char)]]) -> CharClass {
+        let mut cls = CharClass::empty();
+        for &ranges in classes {
+            cls.ranges.extend(class(ranges));
+        }
+        cls.canonicalize()
+    }
+
+    fn bclass(ranges: &[(u8, u8)]) -> ByteClass {
+        let ranges = ranges.iter().cloned()
+                           .map(|(c1, c2)| ByteRange::new(c1, c2)).collect();
+        ByteClass::new(ranges)
+    }
+
+    fn asciid() -> CharClass {
+        ascii_class("digit").unwrap()
+    }
+
+    fn asciis() -> CharClass {
+        ascii_class("space").unwrap()
+    }
+
+    fn asciiw() -> CharClass {
+        ascii_class("word").unwrap()
+    }
+
+    fn asciid_bytes() -> ByteClass {
+        asciid().to_byte_class()
+    }
+
+    fn asciis_bytes() -> ByteClass {
+        asciis().to_byte_class()
+    }
+
+    fn asciiw_bytes() -> ByteClass {
+        asciiw().to_byte_class()
+    }
+
+    #[test]
+    fn empty() {
+        assert_eq!(p(""), Expr::Empty);
+    }
+
+    #[test]
+    fn literal() {
+        assert_eq!(p("a"), lit('a'));
+        assert_eq!(pb("(?-u)a"), blit(b'a'));
+    }
+
+    #[test]
+    fn literal_string() {
+        assert_eq!(p("ab"), Expr::Concat(vec![lit('a'), lit('b')]));
+        assert_eq!(pb("(?-u)ab"), Expr::Concat(vec![blit(b'a'), blit(b'b')]));
+    }
+
+    #[test]
+    fn start_literal() {
+        assert_eq!(p("^a"), Expr::Concat(vec![
+            Expr::StartText,
+            Expr::Literal { chars: vec!['a'], casei: false },
+        ]));
+    }
+
+    #[test]
+    fn repeat_zero_or_one_greedy() {
+        assert_eq!(p("a?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrOne,
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_zero_or_one_greedy_concat() {
+        assert_eq!(p("ab?"), Expr::Concat(vec![
+            lit('a'),
+            Expr::Repeat {
+                e: b(lit('b')),
+                r: Repeater::ZeroOrOne,
+                greedy: true,
+            },
+        ]));
+    }
+
+    #[test]
+    fn repeat_zero_or_one_nongreedy() {
+        assert_eq!(p("a??"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrOne,
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_one_or_more_greedy() {
+        assert_eq!(p("a+"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::OneOrMore,
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_one_or_more_nongreedy() {
+        assert_eq!(p("a+?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::OneOrMore,
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_zero_or_more_greedy() {
+        assert_eq!(p("a*"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrMore,
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_zero_or_more_nongreedy() {
+        assert_eq!(p("a*?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrMore,
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_exact() {
+        assert_eq!(p("a{5}"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(5) },
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_min() {
+        assert_eq!(p("a{5,}"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: None },
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_min_max() {
+        assert_eq!(p("a{5,10}"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(10) },
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_exact_nongreedy() {
+        assert_eq!(p("a{5}?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(5) },
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_min_nongreedy() {
+        assert_eq!(p("a{5,}?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: None },
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_min_max_nongreedy() {
+        assert_eq!(p("a{5,10}?"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(10) },
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn repeat_counted_whitespace() {
+        assert_eq!(p("a{ 5   }"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(5) },
+            greedy: true,
+        });
+        assert_eq!(p("a{ 5 , 10 }"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(10) },
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn group_literal() {
+        assert_eq!(p("(a)"), Expr::Group {
+            e: b(lit('a')),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn group_literal_concat() {
+        assert_eq!(p("(ab)"), Expr::Group {
+            e: b(c(&[lit('a'), lit('b')])),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn alt_two() {
+        assert_eq!(p("a|b"), Expr::Alternate(vec![lit('a'), lit('b')]));
+    }
+
+    #[test]
+    fn alt_many() {
+        assert_eq!(p("a|b|c"), Expr::Alternate(vec![
+            lit('a'), lit('b'), lit('c'),
+        ]));
+    }
+
+    #[test]
+    fn alt_many_concat() {
+        assert_eq!(p("ab|bc|cd"), Expr::Alternate(vec![
+            c(&[lit('a'), lit('b')]),
+            c(&[lit('b'), lit('c')]),
+            c(&[lit('c'), lit('d')]),
+        ]));
+    }
+
+    #[test]
+    fn alt_group_two() {
+        assert_eq!(p("(a|b)"), Expr::Group {
+            e: b(Expr::Alternate(vec![lit('a'), lit('b')])),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn alt_group_many() {
+        assert_eq!(p("(a|b|c)"), Expr::Group {
+            e: b(Expr::Alternate(vec![lit('a'), lit('b'), lit('c')])),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn alt_group_many_concat() {
+        assert_eq!(p("(ab|bc|cd)"), Expr::Group {
+            e: b(Expr::Alternate(vec![
+                c(&[lit('a'), lit('b')]),
+                c(&[lit('b'), lit('c')]),
+                c(&[lit('c'), lit('d')]),
+            ])),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn alt_group_nested() {
+        assert_eq!(p("(ab|(bc|(cd)))"), Expr::Group {
+            e: b(Expr::Alternate(vec![
+                c(&[lit('a'), lit('b')]),
+                Expr::Group {
+                    e: b(Expr::Alternate(vec![
+                        c(&[lit('b'), lit('c')]),
+                        Expr::Group {
+                            e: b(c(&[lit('c'), lit('d')])),
+                            i: Some(3),
+                            name: None,
+                        }
+                    ])),
+                    i: Some(2),
+                    name: None,
+                },
+            ])),
+            i: Some(1),
+            name: None,
+        });
+    }
+
+    #[test]
+    fn group_name() {
+        assert_eq!(p("(?P<foo>a)"), Expr::Group {
+            e: b(lit('a')),
+            i: Some(1),
+            name: Some("foo".into()),
+        });
+    }
+
+    #[test]
+    fn group_no_capture() {
+        assert_eq!(p("(?:a)"), Expr::Group {
+            e: b(lit('a')),
+            i: None,
+            name: None,
+        });
+    }
+
+    #[test]
+    fn group_flags() {
+        assert_eq!(p("(?i:a)"), Expr::Group {
+            e: b(liti('a')),
+            i: None,
+            name: None,
+        });
+        assert_eq!(pb("(?i-u:a)"), Expr::Group {
+            e: b(bliti(b'a')),
+            i: None,
+            name: None,
+        });
+    }
+
+    #[test]
+    fn group_flags_returned() {
+        assert_eq!(p("(?i:a)a"), c(&[
+            Expr::Group {
+                e: b(liti('a')),
+                i: None,
+                name: None,
+            },
+            lit('a'),
+        ]));
+        assert_eq!(pb("(?i-u:a)a"), c(&[
+            Expr::Group {
+                e: b(bliti(b'a')),
+                i: None,
+                name: None,
+            },
+            lit('a'),
+        ]));
+    }
+
+    #[test]
+    fn group_flags_retained() {
+        assert_eq!(p("(?i)(?-i:a)a"), c(&[
+            Expr::Group {
+                e: b(lit('a')),
+                i: None,
+                name: None,
+            },
+            liti('a'),
+        ]));
+        assert_eq!(pb("(?i-u)(?u-i:a)a"), c(&[
+            Expr::Group {
+                e: b(lit('a')),
+                i: None,
+                name: None,
+            },
+            bliti(b'a'),
+        ]));
+    }
+
+    #[test]
+    fn flags_inline() {
+        assert_eq!(p("(?i)a"), liti('a'));
+    }
+
+    #[test]
+    fn flags_inline_multiple() {
+        assert_eq!(p("(?is)a."), c(&[liti('a'), Expr::AnyChar]));
+    }
+
+    #[test]
+    fn flags_inline_multiline() {
+        assert_eq!(p("(?m)^(?-m)$"), c(&[Expr::StartLine, Expr::EndText]));
+    }
+
+    #[test]
+    fn flags_inline_swap_greed() {
+        assert_eq!(p("(?U)a*a*?(?i-U)a*a*?"), c(&[
+            Expr::Repeat {
+                e: b(lit('a')),
+                r: Repeater::ZeroOrMore,
+                greedy: false,
+            },
+            Expr::Repeat {
+                e: b(lit('a')),
+                r: Repeater::ZeroOrMore,
+                greedy: true,
+            },
+            Expr::Repeat {
+                e: b(liti('a')),
+                r: Repeater::ZeroOrMore,
+                greedy: true,
+            },
+            Expr::Repeat {
+                e: b(liti('a')),
+                r: Repeater::ZeroOrMore,
+                greedy: false,
+            },
+        ]));
+    }
+
+    #[test]
+    fn flags_inline_multiple_negate_one() {
+        assert_eq!(p("(?is)a.(?i-s)a."), c(&[
+            liti('a'), Expr::AnyChar, liti('a'), Expr::AnyCharNoNL,
+        ]));
+    }
+
+    #[test]
+    fn any_byte() {
+        assert_eq!(
+            pb("(?-u).(?u)."), c(&[Expr::AnyByteNoNL, Expr::AnyCharNoNL]));
+        assert_eq!(
+            pb("(?s)(?-u).(?u)."), c(&[Expr::AnyByte, Expr::AnyChar]));
+    }
+
+    #[test]
+    fn flags_inline_negate() {
+        assert_eq!(p("(?i)a(?-i)a"), c(&[liti('a'), lit('a')]));
+    }
+
+    #[test]
+    fn flags_group_inline() {
+        assert_eq!(p("(a(?i)a)a"), c(&[
+            Expr::Group {
+                e: b(c(&[lit('a'), liti('a')])),
+                i: Some(1),
+                name: None,
+            },
+            lit('a'),
+        ]));
+    }
+
+    #[test]
+    fn flags_group_inline_retain() {
+        assert_eq!(p("(?i)((?-i)a)a"), c(&[
+            Expr::Group {
+                e: b(lit('a')),
+                i: Some(1),
+                name: None,
+            },
+            liti('a'),
+        ]));
+    }
+
+    #[test]
+    fn flags_default_casei() {
+        let flags = Flags { casei: true, .. Flags::default() };
+        assert_eq!(pf("a", flags), liti('a'));
+    }
+
+    #[test]
+    fn flags_default_multi() {
+        let flags = Flags { multi: true, .. Flags::default() };
+        assert_eq!(pf("^", flags), Expr::StartLine);
+    }
+
+    #[test]
+    fn flags_default_dotnl() {
+        let flags = Flags { dotnl: true, .. Flags::default() };
+        assert_eq!(pf(".", flags), Expr::AnyChar);
+    }
+
+    #[test]
+    fn flags_default_swap_greed() {
+        let flags = Flags { swap_greed: true, .. Flags::default() };
+        assert_eq!(pf("a+", flags), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::OneOrMore,
+            greedy: false,
+        });
+    }
+
+    #[test]
+    fn flags_default_ignore_space() {
+        let flags = Flags { ignore_space: true, .. Flags::default() };
+        assert_eq!(pf(" a ", flags), lit('a'));
+    }
+
+    #[test]
+    fn escape_simple() {
+        assert_eq!(p(r"\a\f\t\n\r\v"), c(&[
+            lit('\x07'), lit('\x0C'), lit('\t'),
+            lit('\n'), lit('\r'), lit('\x0B'),
+        ]));
+    }
+
+    #[test]
+    fn escape_boundaries() {
+        assert_eq!(p(r"\A\z\b\B"), c(&[
+            Expr::StartText, Expr::EndText,
+            Expr::WordBoundary, Expr::NotWordBoundary,
+        ]));
+        assert_eq!(pb(r"(?-u)\b\B"), c(&[
+            Expr::WordBoundaryAscii, Expr::NotWordBoundaryAscii,
+        ]));
+    }
+
+    #[test]
+    fn escape_punctuation() {
+        assert_eq!(p(r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#"), c(&[
+            lit('\\'), lit('.'), lit('+'), lit('*'), lit('?'),
+            lit('('), lit(')'), lit('|'), lit('['), lit(']'),
+            lit('{'), lit('}'), lit('^'), lit('$'), lit('#'),
+        ]));
+    }
+
+    #[test]
+    fn escape_octal() {
+        assert_eq!(p(r"\123"), lit('S'));
+        assert_eq!(p(r"\1234"), c(&[lit('S'), lit('4')]));
+
+        assert_eq!(pb(r"(?-u)\377"), blit(0xFF));
+    }
+
+    #[test]
+    fn escape_hex2() {
+        assert_eq!(p(r"\x53"), lit('S'));
+        assert_eq!(p(r"\x534"), c(&[lit('S'), lit('4')]));
+
+        assert_eq!(pb(r"(?-u)\xff"), blit(0xFF));
+        assert_eq!(pb(r"(?-u)\x00"), blit(0x0));
+        assert_eq!(pb(r"(?-u)[\x00]"),
+                   Expr::ClassBytes(bclass(&[(b'\x00', b'\x00')])));
+        assert_eq!(pb(r"(?-u)[^\x00]"),
+                   Expr::ClassBytes(bclass(&[(b'\x01', b'\xFF')])));
+    }
+
+    #[test]
+    fn escape_hex() {
+        assert_eq!(p(r"\x{53}"), lit('S'));
+        assert_eq!(p(r"\x{53}4"), c(&[lit('S'), lit('4')]));
+        assert_eq!(p(r"\x{2603}"), lit('\u{2603}'));
+
+        assert_eq!(pb(r"(?-u)\x{00FF}"), blit(0xFF));
+    }
+
+    #[test]
+    fn escape_unicode_name() {
+        assert_eq!(p(r"\p{Yi}"), Expr::Class(class(YI)));
+    }
+
+    #[test]
+    fn escape_unicode_letter() {
+        assert_eq!(p(r"\pZ"), Expr::Class(class(&[
+            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
+            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
+            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+        ])));
+    }
+
+    #[test]
+    fn escape_unicode_name_case_fold() {
+        assert_eq!(p(r"(?i)\p{Yi}"), Expr::Class(class(YI).case_fold()));
+    }
+
+    #[test]
+    fn escape_unicode_letter_case_fold() {
+        assert_eq!(p(r"(?i)\pZ"), Expr::Class(class(&[
+            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
+            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
+            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+        ]).case_fold()));
+    }
+
+    #[test]
+    fn escape_unicode_name_negate() {
+        assert_eq!(p(r"\P{Yi}"), Expr::Class(class(YI).negate()));
+    }
+
+    #[test]
+    fn escape_unicode_letter_negate() {
+        assert_eq!(p(r"\PZ"), Expr::Class(class(&[
+            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
+            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
+            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+        ]).negate()));
+    }
+
+    #[test]
+    fn escape_unicode_name_negate_case_fold() {
+        assert_eq!(p(r"(?i)\P{Yi}"),
+                   Expr::Class(class(YI).negate().case_fold()));
+    }
+
+    #[test]
+    fn escape_unicode_letter_negate_case_fold() {
+        assert_eq!(p(r"(?i)\PZ"), Expr::Class(class(&[
+            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
+            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
+            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+        ]).negate().case_fold()));
+    }
+
+    #[test]
+    fn escape_perl_d() {
+        assert_eq!(p(r"\d"), Expr::Class(class(PERLD)));
+        assert_eq!(pb(r"(?-u)\d"), Expr::Class(asciid()));
+    }
+
+    #[test]
+    fn escape_perl_s() {
+        assert_eq!(p(r"\s"), Expr::Class(class(PERLS)));
+        assert_eq!(pb(r"(?-u)\s"), Expr::Class(asciis()));
+    }
+
+    #[test]
+    fn escape_perl_w() {
+        assert_eq!(p(r"\w"), Expr::Class(class(PERLW)));
+        assert_eq!(pb(r"(?-u)\w"), Expr::Class(asciiw()));
+    }
+
+    #[test]
+    fn escape_perl_d_negate() {
+        assert_eq!(p(r"\D"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(pb(r"(?-u)\D"), Expr::Class(asciid().negate()));
+    }
+
+    #[test]
+    fn escape_perl_s_negate() {
+        assert_eq!(p(r"\S"), Expr::Class(class(PERLS).negate()));
+        assert_eq!(pb(r"(?-u)\S"), Expr::Class(asciis().negate()));
+    }
+
+    #[test]
+    fn escape_perl_w_negate() {
+        assert_eq!(p(r"\W"), Expr::Class(class(PERLW).negate()));
+        assert_eq!(pb(r"(?-u)\W"), Expr::Class(asciiw().negate()));
+    }
+
+    #[test]
+    fn escape_perl_d_case_fold() {
+        assert_eq!(p(r"(?i)\d"), Expr::Class(class(PERLD).case_fold()));
+        assert_eq!(pb(r"(?i-u)\d"), Expr::Class(asciid().case_fold()));
+    }
+
+    #[test]
+    fn escape_perl_s_case_fold() {
+        assert_eq!(p(r"(?i)\s"), Expr::Class(class(PERLS).case_fold()));
+        assert_eq!(pb(r"(?i-u)\s"), Expr::Class(asciis().case_fold()));
+    }
+
+    #[test]
+    fn escape_perl_w_case_fold() {
+        assert_eq!(p(r"(?i)\w"), Expr::Class(class(PERLW).case_fold()));
+        assert_eq!(pb(r"(?i-u)\w"), Expr::Class(asciiw().case_fold()));
+    }
+
+    #[test]
+    fn escape_perl_d_case_fold_negate() {
+        assert_eq!(p(r"(?i)\D"),
+                   Expr::Class(class(PERLD).case_fold().negate()));
+        let bytes = asciid().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)\D"), Expr::Class(bytes));
+    }
+
+    #[test]
+    fn escape_perl_s_case_fold_negate() {
+        assert_eq!(p(r"(?i)\S"),
+                   Expr::Class(class(PERLS).case_fold().negate()));
+        let bytes = asciis().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)\S"), Expr::Class(bytes));
+    }
+
+    #[test]
+    fn escape_perl_w_case_fold_negate() {
+        assert_eq!(p(r"(?i)\W"),
+                   Expr::Class(class(PERLW).case_fold().negate()));
+        let bytes = asciiw().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)\W"), Expr::Class(bytes));
+    }
+
+    #[test]
+    fn class_singleton() {
+        assert_eq!(p(r"[a]"), Expr::Class(class(&[('a', 'a')])));
+        assert_eq!(p(r"[\x00]"), Expr::Class(class(&[('\x00', '\x00')])));
+        assert_eq!(p(r"[\n]"), Expr::Class(class(&[('\n', '\n')])));
+        assert_eq!(p("[\n]"), Expr::Class(class(&[('\n', '\n')])));
+
+        assert_eq!(pb(r"(?-u)[a]"), Expr::ClassBytes(bclass(&[(b'a', b'a')])));
+        assert_eq!(pb(r"(?-u)[\x00]"), Expr::ClassBytes(bclass(&[(0, 0)])));
+        assert_eq!(pb(r"(?-u)[\xFF]"),
+                   Expr::ClassBytes(bclass(&[(0xFF, 0xFF)])));
+        assert_eq!(pb("(?-u)[\n]"),
+                   Expr::ClassBytes(bclass(&[(b'\n', b'\n')])));
+        assert_eq!(pb(r"(?-u)[\n]"),
+                   Expr::ClassBytes(bclass(&[(b'\n', b'\n')])));
+    }
+
+    #[test]
+    fn class_singleton_negate() {
+        assert_eq!(p(r"[^a]"), Expr::Class(class(&[
+            ('\x00', '\x60'), ('\x62', '\u{10FFFF}'),
+        ])));
+        assert_eq!(p(r"[^\x00]"), Expr::Class(class(&[
+            ('\x01', '\u{10FFFF}'),
+        ])));
+        assert_eq!(p(r"[^\n]"), Expr::Class(class(&[
+            ('\x00', '\x09'), ('\x0b', '\u{10FFFF}'),
+        ])));
+        assert_eq!(p("[^\n]"), Expr::Class(class(&[
+            ('\x00', '\x09'), ('\x0b', '\u{10FFFF}'),
+        ])));
+
+        assert_eq!(pb(r"(?-u)[^a]"), Expr::ClassBytes(bclass(&[
+            (0x00, 0x60), (0x62, 0xFF),
+        ])));
+        assert_eq!(pb(r"(?-u)[^\x00]"), Expr::ClassBytes(bclass(&[
+            (0x01, 0xFF),
+        ])));
+        assert_eq!(pb(r"(?-u)[^\n]"), Expr::ClassBytes(bclass(&[
+            (0x00, 0x09), (0x0B, 0xFF),
+        ])));
+        assert_eq!(pb("(?-u)[^\n]"), Expr::ClassBytes(bclass(&[
+            (0x00, 0x09), (0x0B, 0xFF),
+        ])));
+    }
+
+    #[test]
+    fn class_singleton_class() {
+        assert_eq!(p(r"[\d]"), Expr::Class(class(PERLD)));
+        assert_eq!(p(r"[\p{Yi}]"), Expr::Class(class(YI)));
+
+        let bytes = class(PERLD).to_byte_class();
+        assert_eq!(pb(r"(?-u)[\d]"), Expr::ClassBytes(bytes));
+    }
+
+    #[test]
+    fn class_singleton_class_negate() {
+        assert_eq!(p(r"[^\d]"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(p(r"[^\w]"), Expr::Class(class(PERLW).negate()));
+        assert_eq!(p(r"[^\s]"), Expr::Class(class(PERLS).negate()));
+
+        let bytes = asciid_bytes().negate();
+        assert_eq!(pb(r"(?-u)[^\d]"), Expr::ClassBytes(bytes));
+        let bytes = asciiw_bytes().negate();
+        assert_eq!(pb(r"(?-u)[^\w]"), Expr::ClassBytes(bytes));
+        let bytes = asciis_bytes().negate();
+        assert_eq!(pb(r"(?-u)[^\s]"), Expr::ClassBytes(bytes));
+    }
+
+    #[test]
+    fn class_singleton_class_negate_negate() {
+        assert_eq!(p(r"[^\D]"), Expr::Class(class(PERLD)));
+        assert_eq!(p(r"[^\W]"), Expr::Class(class(PERLW)));
+        assert_eq!(p(r"[^\S]"), Expr::Class(class(PERLS)));
+
+        assert_eq!(pb(r"(?-u)[^\D]"), Expr::ClassBytes(asciid_bytes()));
+        assert_eq!(pb(r"(?-u)[^\W]"), Expr::ClassBytes(asciiw_bytes()));
+        assert_eq!(pb(r"(?-u)[^\S]"), Expr::ClassBytes(asciis_bytes()));
+    }
+
+    #[test]
+    fn class_singleton_class_casei() {
+        assert_eq!(p(r"(?i)[\d]"), Expr::Class(class(PERLD).case_fold()));
+        assert_eq!(p(r"(?i)[\p{Yi}]"), Expr::Class(class(YI).case_fold()));
+
+        assert_eq!(pb(r"(?i-u)[\d]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold()));
+    }
+
+    #[test]
+    fn class_singleton_class_negate_casei() {
+        assert_eq!(p(r"(?i)[^\d]"),
+                   Expr::Class(class(PERLD).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^\w]"),
+                   Expr::Class(class(PERLW).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^\s]"),
+                   Expr::Class(class(PERLS).case_fold().negate()));
+
+        let bytes = asciid_bytes().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)[^\d]"), Expr::ClassBytes(bytes));
+        let bytes = asciiw_bytes().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)[^\w]"), Expr::ClassBytes(bytes));
+        let bytes = asciis_bytes().case_fold().negate();
+        assert_eq!(pb(r"(?i-u)[^\s]"), Expr::ClassBytes(bytes));
+    }
+
+    #[test]
+    fn class_singleton_class_negate_negate_casei() {
+        assert_eq!(p(r"(?i)[^\D]"), Expr::Class(class(PERLD).case_fold()));
+        assert_eq!(p(r"(?i)[^\W]"), Expr::Class(class(PERLW).case_fold()));
+        assert_eq!(p(r"(?i)[^\S]"), Expr::Class(class(PERLS).case_fold()));
+
+        assert_eq!(pb(r"(?i-u)[^\D]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold()));
+        assert_eq!(pb(r"(?i-u)[^\W]"),
+                   Expr::ClassBytes(asciiw_bytes().case_fold()));
+        assert_eq!(pb(r"(?i-u)[^\S]"),
+                   Expr::ClassBytes(asciis_bytes().case_fold()));
+    }
+
+    #[test]
+    fn class_multiple_class() {
+        assert_eq!(p(r"[\d\p{Yi}]"), Expr::Class(classes(&[
+            PERLD, YI,
+        ])));
+    }
+
+    #[test]
+    fn class_multiple_class_negate() {
+        assert_eq!(p(r"[^\d\p{Yi}]"), Expr::Class(classes(&[
+            PERLD, YI,
+        ]).negate()));
+    }
+
+    #[test]
+    fn class_multiple_class_negate_negate() {
+        let nperlw = class(PERLW).negate();
+        let nyi = class(YI).negate();
+        let cls = CharClass::empty().merge(nperlw).merge(nyi);
+        assert_eq!(p(r"[^\W\P{Yi}]"), Expr::Class(cls.negate()));
+    }
+
+    #[test]
+    fn class_multiple_class_casei() {
+        assert_eq!(p(r"(?i)[\d\p{Yi}]"), Expr::Class(classes(&[
+            PERLD, YI,
+        ]).case_fold()));
+    }
+
+    #[test]
+    fn class_multiple_class_negate_casei() {
+        assert_eq!(p(r"(?i)[^\d\p{Yi}]"), Expr::Class(classes(&[
+            PERLD, YI,
+        ]).case_fold().negate()));
+    }
+
+    #[test]
+    fn class_multiple_class_negate_negate_casei() {
+        let nperlw = class(PERLW).negate();
+        let nyi = class(YI).negate();
+        let class = CharClass::empty().merge(nperlw).merge(nyi);
+        assert_eq!(p(r"(?i)[^\W\P{Yi}]"),
+                   Expr::Class(class.case_fold().negate()));
+    }
+
+    #[test]
+    fn class_class_hypen() {
+        assert_eq!(p(r"[\p{Yi}-]"), Expr::Class(classes(&[
+            &[('-', '-')], YI,
+        ])));
+        assert_eq!(p(r"[\p{Yi}-a]"), Expr::Class(classes(&[
+            &[('-', '-')], &[('a', 'a')], YI,
+        ])));
+    }
+
+    #[test]
+    fn class_brackets() {
+        assert_eq!(p(r"[]]"), Expr::Class(class(&[(']', ']')])));
+        assert_eq!(p(r"[]\[]"), Expr::Class(class(&[('[', '['), (']', ']')])));
+        assert_eq!(p(r"[\[]]"), Expr::Concat(vec![
+            Expr::Class(class(&[('[', '[')])),
+            lit(']'),
+        ]));
+    }
+
+    #[test]
+    fn class_brackets_hypen() {
+        assert_eq!(p("[]-]"), Expr::Class(class(&[('-', '-'), (']', ']')])));
+        assert_eq!(p("[-]]"), Expr::Concat(vec![
+            Expr::Class(class(&[('-', '-')])),
+            lit(']'),
+        ]));
+    }
+
+    #[test]
+    fn class_nested_class_union() {
+        assert_eq!(p(r"[c[a-b]]"), Expr::Class(class(&[('a', 'c')])));
+        assert_eq!(p(r"[[a-b]]"), Expr::Class(class(&[('a', 'b')])));
+        assert_eq!(p(r"[[c][a-b]]"), Expr::Class(class(&[('a', 'c')])));
+
+        assert_eq!(pb(r"(?-u)[c[a-b]]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'c')])));
+        assert_eq!(pb(r"(?-u)[[a-b]]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'b')])));
+        assert_eq!(pb(r"(?-u)[[c][a-b]]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'c')])));
+    }
+
+    #[test]
+    fn class_nested_class_union_casei() {
+        assert_eq!(p(r"(?i)[c[a-b]]"),
+                   Expr::Class(class(&[('a', 'c')]).case_fold()));
+        assert_eq!(p(r"(?i)[[a-b]]"),
+                   Expr::Class(class(&[('a', 'b')]).case_fold()));
+        assert_eq!(p(r"(?i)[[c][a-b]]"),
+                   Expr::Class(class(&[('a', 'c')]).case_fold()));
+
+        assert_eq!(pb(r"(?i-u)[[\d]]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold()));
+    }
+
+    #[test]
+    fn class_nested_class_negate() {
+        assert_eq!(p(r"[^[\d]]"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(p(r"[[^\d]]"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(p(r"[^[^\d]]"), Expr::Class(class(PERLD)));
+        assert_eq!(p(r"[^[\w]]"), Expr::Class(class(PERLW).negate()));
+        assert_eq!(p(r"[[^\w]]"), Expr::Class(class(PERLW).negate()));
+        assert_eq!(p(r"[^[^\w]]"), Expr::Class(class(PERLW)));
+        assert_eq!(p(r"[a-b[^c]]"),
+                   Expr::Class(class(&[('\u{0}', 'b'), ('d', '\u{10FFFF}')])));
+
+        assert_eq!(pb(r"(?-u)[^[\d]]"),
+                   Expr::ClassBytes(asciid_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[[^\d]]"),
+                   Expr::ClassBytes(asciid_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[^[^\d]]"),
+                   Expr::ClassBytes(asciid_bytes()));
+        assert_eq!(pb(r"(?-u)[^[\w]]"),
+                   Expr::ClassBytes(asciiw_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[[^\w]]"),
+                   Expr::ClassBytes(asciiw_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[^[^\w]]"),
+                   Expr::ClassBytes(asciiw_bytes()));
+        assert_eq!(pb(r"(?-u)[a-b[^c]]"),
+                   Expr::ClassBytes(bclass(&[(b'\x00', b'b'), (b'd', b'\xFF')])))
+    }
+
+    #[test]
+    fn class_nested_class_negate_casei() {
+        assert_eq!(p(r"(?i)[^[\d]]"),
+                   Expr::Class(class(PERLD).case_fold().negate()));
+        assert_eq!(p(r"(?i)[[^\d]]"),
+                   Expr::Class(class(PERLD).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^[^\d]]"),
+                   Expr::Class(class(PERLD).case_fold()));
+        assert_eq!(p(r"(?i)[^[\w]]"),
+                   Expr::Class(class(PERLW).case_fold().negate()));
+        assert_eq!(p(r"(?i)[[^\w]]"),
+                   Expr::Class(class(PERLW).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^[^\w]]"),
+                   Expr::Class(class(PERLW).case_fold()));
+        let mut cls = CharClass::empty().negate();
+        cls.remove('c');
+        cls.remove('C');
+        assert_eq!(p(r"(?i)[a-b[^c]]"), Expr::Class(cls));
+
+        assert_eq!(pb(r"(?i-u)[^[\d]]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[[^\d]]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[^[^\d]]"),
+                   Expr::ClassBytes(asciid_bytes().case_fold()));
+        assert_eq!(pb(r"(?i-u)[^[\w]]"),
+                   Expr::ClassBytes(asciiw_bytes().case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[[^\w]]"),
+                   Expr::ClassBytes(asciiw_bytes().case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[^[^\w]]"),
+                   Expr::ClassBytes(asciiw_bytes().case_fold()));
+        let mut bytes = ByteClass::new(vec![]).negate();
+        bytes.remove(b'c');
+        bytes.remove(b'C');
+        assert_eq!(pb(r"(?i-u)[a-b[^c]]"), Expr::ClassBytes(bytes));
+    }
+
+    #[test]
+    fn class_nested_class_brackets_hyphen() {
+        // This is confusing, but `]` is allowed if first character within a class
+        // It parses as a nested class with the `]` and `-` characters
+        assert_eq!(p(r"[[]-]]"), Expr::Class(class(&[('-', '-'), (']', ']')])));
+        assert_eq!(p(r"[[\[]]"), Expr::Class(class(&[('[', '[')])));
+        assert_eq!(p(r"[[\]]]"), Expr::Class(class(&[(']', ']')])));
+    }
+
+    #[test]
+    fn class_nested_class_deep_nesting() {
+        // Makes sure that implementation can handle deep nesting.
+        // With recursive parsing, this regex would blow the stack size.
+        use std::iter::repeat;
+        let nesting = 10_000;
+        let open: String = repeat("[").take(nesting).collect();
+        let close: String = repeat("]").take(nesting).collect();
+        let s  = format!("{}a{}", open, close);
+        assert_eq!(p(&s), Expr::Class(class(&[('a', 'a')])));
+    }
+
+    #[test]
+    fn class_intersection_ranges() {
+        assert_eq!(p(r"[abc&&b-c]"), Expr::Class(class(&[('b', 'c')])));
+        assert_eq!(p(r"[abc&&[b-c]]"), Expr::Class(class(&[('b', 'c')])));
+        assert_eq!(p(r"[[abc]&&[b-c]]"), Expr::Class(class(&[('b', 'c')])));
+        assert_eq!(p(r"[a-z&&b-y&&c-x]"), Expr::Class(class(&[('c', 'x')])));
+        assert_eq!(p(r"[c-da-b&&a-d]"), Expr::Class(class(&[('a', 'd')])));
+        assert_eq!(p(r"[a-d&&c-da-b]"), Expr::Class(class(&[('a', 'd')])));
+
+        assert_eq!(pb(r"(?-u)[abc&&b-c]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
+        assert_eq!(pb(r"(?-u)[abc&&[b-c]]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
+        assert_eq!(pb(r"(?-u)[[abc]&&[b-c]]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
+        assert_eq!(pb(r"(?-u)[a-z&&b-y&&c-x]"),
+                   Expr::ClassBytes(bclass(&[(b'c', b'x')])));
+        assert_eq!(pb(r"(?-u)[c-da-b&&a-d]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'd')])));
+    }
+
+    #[test]
+    fn class_intersection_ranges_casei() {
+        assert_eq!(p(r"(?i)[abc&&b-c]"),
+                   Expr::Class(class(&[('b', 'c')]).case_fold()));
+        assert_eq!(p(r"(?i)[abc&&[b-c]]"),
+                   Expr::Class(class(&[('b', 'c')]).case_fold()));
+        assert_eq!(p(r"(?i)[[abc]&&[b-c]]"),
+                   Expr::Class(class(&[('b', 'c')]).case_fold()));
+        assert_eq!(p(r"(?i)[a-z&&b-y&&c-x]"),
+                   Expr::Class(class(&[('c', 'x')]).case_fold()));
+        assert_eq!(p(r"(?i)[c-da-b&&a-d]"),
+                   Expr::Class(class(&[('a', 'd')]).case_fold()));
+
+        assert_eq!(pb(r"(?i-u)[abc&&b-c]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
+        assert_eq!(pb(r"(?i-u)[abc&&[b-c]]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
+        assert_eq!(pb(r"(?i-u)[[abc]&&[b-c]]"),
+                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
+        assert_eq!(pb(r"(?i-u)[a-z&&b-y&&c-x]"),
+                   Expr::ClassBytes(bclass(&[(b'c', b'x')]).case_fold()));
+        assert_eq!(pb(r"(?i-u)[c-da-b&&a-d]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'd')]).case_fold()));
+    }
+
+    #[test]
+    fn class_intersection_classes() {
+        assert_eq!(p(r"[\w&&\d]"), Expr::Class(class(PERLD)));
+        assert_eq!(p(r"[\w&&[[:ascii:]]]"), Expr::Class(asciiw()));
+        assert_eq!(p(r"[\x00-\xFF&&\pZ]"),
+                   Expr::Class(class(&[('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}')])));
+
+        assert_eq!(pb(r"(?-u)[\w&&\d]"), Expr::ClassBytes(asciid_bytes()));
+        assert_eq!(pb(r"(?-u)[\w&&[[:ascii:]]]"), Expr::ClassBytes(asciiw_bytes()));
+    }
+
+    #[test]
+    fn class_intersection_classes_casei() {
+        assert_eq!(p(r"(?i)[\w&&\d]"), Expr::Class(class(PERLD).case_fold()));
+        assert_eq!(p(r"(?i)[\w&&[[:ascii:]]]"), Expr::Class(asciiw().case_fold()));
+        assert_eq!(p(r"(?i)[\x00-\xFF&&\pZ]"),
+                   Expr::Class(class(&[('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}')])));
+
+        assert_eq!(pb(r"(?i-u)[\w&&\d]"), Expr::ClassBytes(asciid_bytes().case_fold()));
+        assert_eq!(pb(r"(?i-u)[\w&&[[:ascii:]]]"), Expr::ClassBytes(asciiw_bytes().case_fold()));
+    }
+
+    #[test]
+    fn class_intersection_negate() {
+        assert_eq!(p(r"[^\w&&\d]"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(p(r"[^[\w&&\d]]"), Expr::Class(class(PERLD).negate()));
+        assert_eq!(p(r"[^[^\w&&\d]]"), Expr::Class(class(PERLD)));
+        assert_eq!(p(r"[\w&&[^\d]]"),
+                   Expr::Class(class(PERLW).intersection(&class(PERLD).negate())));
+        assert_eq!(p(r"[[^\w]&&[^\d]]"),
+                   Expr::Class(class(PERLW).negate()));
+
+        assert_eq!(pb(r"(?-u)[^\w&&\d]"),
+                   Expr::ClassBytes(asciid_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[^[\w&&\d]]"),
+                   Expr::ClassBytes(asciid_bytes().negate()));
+        assert_eq!(pb(r"(?-u)[^[^\w&&\d]]"),
+                   Expr::ClassBytes(asciid_bytes()));
+        assert_eq!(pb(r"(?-u)[\w&&[^\d]]"),
+                   Expr::ClassBytes(asciiw().intersection(&asciid().negate()).to_byte_class()));
+        assert_eq!(pb(r"(?-u)[[^\w]&&[^\d]]"),
+                   Expr::ClassBytes(asciiw_bytes().negate()));
+    }
+
+    #[test]
+    fn class_intersection_negate_casei() {
+        assert_eq!(p(r"(?i)[^\w&&a-z]"),
+                   Expr::Class(class(&[('a', 'z')]).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^[\w&&a-z]]"),
+                   Expr::Class(class(&[('a', 'z')]).case_fold().negate()));
+        assert_eq!(p(r"(?i)[^[^\w&&a-z]]"),
+                   Expr::Class(class(&[('a', 'z')]).case_fold()));
+        assert_eq!(p(r"(?i)[\w&&[^a-z]]"),
+                   Expr::Class(
+                       class(PERLW).intersection(&class(&[('a', 'z')])
+                       .case_fold().negate())));
+        assert_eq!(p(r"(?i)[[^\w]&&[^a-z]]"),
+                   Expr::Class(class(PERLW).negate()));
+
+        assert_eq!(pb(r"(?i-u)[^\w&&a-z]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[^[\w&&a-z]]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold().negate()));
+        assert_eq!(pb(r"(?i-u)[^[^\w&&a-z]]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold()));
+        assert_eq!(pb(r"(?i-u)[\w&&[^a-z]]"),
+                   Expr::ClassBytes(bclass(&[(b'0', b'9'), (b'_', b'_')])));
+        assert_eq!(pb(r"(?i-u)[[^\w]&&[^a-z]]"),
+                   Expr::ClassBytes(asciiw_bytes().negate()));
+    }
+
+    #[test]
+    fn class_intersection_caret() {
+        // In `[a^]`, `^` does not need to be escaped, so it makes sense that
+        // `^` is also allowed to be unescaped after `&&`.
+        assert_eq!(p(r"[\^&&^]"), Expr::Class(class(&[('^', '^')])));
+    }
+
+    #[test]
+    fn class_intersection_brackets_hyphen() {
+        // `]` needs to be escaped after `&&` because it is not at the start of the class.
+        assert_eq!(p(r"[]&&\]]"), Expr::Class(class(&[(']', ']')])));
+
+        assert_eq!(p(r"[-&&-]"), Expr::Class(class(&[('-', '-')])));
+    }
+
+    #[test]
+    fn class_intersection_ampersand() {
+        // Unescaped `&` after `&&`
+        assert_eq!(p(r"[\&&&&]"), Expr::Class(class(&[('&', '&')])));
+        assert_eq!(p(r"[\&&&\&]"), Expr::Class(class(&[('&', '&')])));
+    }
+
+    #[test]
+    fn class_intersection_precedence() {
+        assert_eq!(p(r"[a-w&&[^c-g]z]"), Expr::Class(class(&[('a', 'b'), ('h', 'w')])));
+    }
+
+    #[test]
+    fn class_special_escaped_set_chars() {
+        // These tests ensure that some special characters require escaping
+        // for use in character classes. The intention is to use these
+        // characters to implement sets as described in UTS#18 RL1.3. Once
+        // that's done, these tests should be removed and replaced with others.
+        assert_eq!(p(r"[\[]"), Expr::Class(class(&[('[', '[')])));
+        assert_eq!(p(r"[&]"), Expr::Class(class(&[('&', '&')])));
+        assert_eq!(p(r"[\&]"), Expr::Class(class(&[('&', '&')])));
+        assert_eq!(p(r"[\&\&]"), Expr::Class(class(&[('&', '&')])));
+        assert_eq!(p(r"[\x00-&]"), Expr::Class(class(&[('\u{0}', '&')])));
+        assert_eq!(p(r"[&-\xFF]"), Expr::Class(class(&[('&', '\u{FF}')])));
+
+        assert_eq!(p(r"[~]"), Expr::Class(class(&[('~', '~')])));
+        assert_eq!(p(r"[\~]"), Expr::Class(class(&[('~', '~')])));
+        assert_eq!(p(r"[\~\~]"), Expr::Class(class(&[('~', '~')])));
+        assert_eq!(p(r"[\x00-~]"), Expr::Class(class(&[('\u{0}', '~')])));
+        assert_eq!(p(r"[~-\xFF]"), Expr::Class(class(&[('~', '\u{FF}')])));
+
+        assert_eq!(p(r"[+-\-]"), Expr::Class(class(&[('+', '-')])));
+        assert_eq!(p(r"[a-a\--\xFF]"), Expr::Class(class(&[
+            ('-', '\u{FF}'),
+        ])));
+    }
+
+    #[test]
+    fn class_overlapping() {
+        assert_eq!(p("[a-fd-h]"), Expr::Class(class(&[('a', 'h')])));
+        assert_eq!(p("[a-fg-m]"), Expr::Class(class(&[('a', 'm')])));
+
+        assert_eq!(pb("(?-u)[a-fd-h]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'h')])));
+        assert_eq!(pb("(?-u)[a-fg-m]"),
+                   Expr::ClassBytes(bclass(&[(b'a', b'm')])));
+    }
+
+    #[test]
+    fn ascii_classes() {
+        assert_eq!(p("[:blank:]"), Expr::Class(class(&[
+            (':', ':'), ('a', 'b'), ('k', 'l'), ('n', 'n'),
+        ])));
+        assert_eq!(p("[[:upper:]]"), Expr::Class(class(UPPER)));
+
+        assert_eq!(pb("(?-u)[[:upper:]]"),
+                   Expr::ClassBytes(class(UPPER).to_byte_class()));
+    }
+
+    #[test]
+    fn ascii_classes_not() {
+        assert_eq!(p("[:abc:]"),
+                   Expr::Class(class(&[(':', ':'), ('a', 'c')])));
+        assert_eq!(pb("(?-u)[:abc:]"),
+                   Expr::ClassBytes(bclass(&[(b':', b':'), (b'a', b'c')])));
+    }
+
+    #[test]
+    fn ascii_classes_multiple() {
+        assert_eq!(p("[[:lower:][:upper:]]"),
+                   Expr::Class(classes(&[UPPER, LOWER])));
+
+        assert_eq!(pb("(?-u)[[:lower:][:upper:]]"),
+                   Expr::ClassBytes(classes(&[UPPER, LOWER]).to_byte_class()));
+    }
+
+    #[test]
+    fn ascii_classes_negate() {
+        assert_eq!(p("[[:^upper:]]"), Expr::Class(class(UPPER).negate()));
+        assert_eq!(p("[^[:^upper:]]"), Expr::Class(class(UPPER)));
+
+        assert_eq!(pb("(?-u)[[:^upper:]]"),
+                   Expr::ClassBytes(class(UPPER).to_byte_class().negate()));
+        assert_eq!(pb("(?-u)[^[:^upper:]]"),
+                   Expr::ClassBytes(class(UPPER).to_byte_class()));
+    }
+
+    #[test]
+    fn ascii_classes_negate_multiple() {
+        let (nlower, nword) = (class(LOWER).negate(), class(WORD).negate());
+        let cls = CharClass::empty().merge(nlower).merge(nword);
+        assert_eq!(p("[[:^lower:][:^word:]]"), Expr::Class(cls.clone()));
+        assert_eq!(p("[^[:^lower:][:^word:]]"), Expr::Class(cls.negate()));
+    }
+
+    #[test]
+    fn ascii_classes_case_fold() {
+        assert_eq!(p("(?i)[[:upper:]]"),
+                   Expr::Class(class(UPPER).case_fold()));
+
+        assert_eq!(pb("(?i-u)[[:upper:]]"),
+                   Expr::ClassBytes(class(UPPER).to_byte_class().case_fold()));
+    }
+
+    #[test]
+    fn ascii_classes_negate_case_fold() {
+        assert_eq!(p("(?i)[[:^upper:]]"),
+                   Expr::Class(class(UPPER).case_fold().negate()));
+        assert_eq!(p("(?i)[^[:^upper:]]"),
+                   Expr::Class(class(UPPER).case_fold()));
+
+        assert_eq!(pb("(?i-u)[[:^upper:]]"),
+                   Expr::ClassBytes(
+                       class(UPPER).to_byte_class().case_fold().negate()));
+        assert_eq!(pb("(?i-u)[^[:^upper:]]"),
+                   Expr::ClassBytes(class(UPPER).to_byte_class().case_fold()));
+    }
+
+    #[test]
+    fn single_class_negate_case_fold() {
+        assert_eq!(p("(?i)[^x]"),
+                   Expr::Class(class(&[('x', 'x')]).case_fold().negate()));
+
+        assert_eq!(pb("(?i-u)[^x]"),
+                   Expr::ClassBytes(
+                       class(&[('x', 'x')])
+                       .to_byte_class().case_fold().negate()));
+    }
+
+    #[test]
+    fn ignore_space_empty() {
+        assert_eq!(p("(?x) "), Expr::Empty);
+    }
+
+    #[test]
+    fn ignore_space_literal() {
+        assert_eq!(p("(?x) a b c"), Expr::Concat(vec![
+            lit('a'), lit('b'), lit('c'),
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_literal_off() {
+        assert_eq!(p("(?x) a b c(?-x) a"), Expr::Concat(vec![
+            lit('a'), lit('b'), lit('c'), lit(' '), lit('a'),
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_class() {
+        assert_eq!(p("(?x)[a
+        - z
+]"), Expr::Class(class(&[('a', 'z')])));
+        assert_eq!(p("(?x)[  ^   a
+        - z
+]"), Expr::Class(class(&[('a', 'z')]).negate()));
+    }
+
+    #[test]
+    fn ignore_space_escape_octal() {
+        assert_eq!(p(r"(?x)\12 3"), Expr::Concat(vec![
+            lit('\n'),
+            lit('3'),
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_escape_hex() {
+        assert_eq!(p(r"(?x)\x { 53 }"), lit('S'));
+        assert_eq!(p(r"(?x)\x # comment
+{ # comment
+    53 # comment
+} # comment"), lit('S'));
+    }
+
+    #[test]
+    fn ignore_space_escape_hex2() {
+        assert_eq!(p(r"(?x)\x 53"), lit('S'));
+        assert_eq!(p(r"(?x)\x # comment
+        53 # comment"), lit('S'));
+    }
+
+    #[test]
+    fn ignore_space_escape_unicode_name() {
+        assert_eq!(p(r"(?x)\p # comment
+{ # comment
+    Yi # comment
+} # comment"), Expr::Class(class(YI)));
+    }
+
+    #[test]
+    fn ignore_space_repeat_counted() {
+        assert_eq!(p("(?x)a # comment
+{ # comment
+    5 # comment
+    , # comment
+    10 # comment
+}"), Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::Range { min: 5, max: Some(10) },
+            greedy: true,
+        });
+    }
+
+    #[test]
+    fn ignore_space_comments() {
+        assert_eq!(p(r"(?x)(?P<foo>
+    a # comment 1
+)(?P<bar>
+    z # comment 2
+)"), Expr::Concat(vec![
+        Expr::Group {
+            e: Box::new(lit('a')),
+            i: Some(1),
+            name: Some("foo".into()),
+        },
+        Expr::Group {
+            e: Box::new(lit('z')),
+            i: Some(2),
+            name: Some("bar".into()),
+        },
+    ]));
+    }
+
+    #[test]
+    fn ignore_space_comments_re_enable() {
+        assert_eq!(p(r"(?x)a # hi
+(?-x:#) # sweet"), Expr::Concat(vec![
+            lit('a'),
+            Expr::Group {
+                e: Box::new(lit('#')),
+                i: None,
+                name: None,
+            },
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_escape_punctuation() {
+        assert_eq!(p(r"(?x)\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#"), c(&[
+            lit('\\'), lit('.'), lit('+'), lit('*'), lit('?'),
+            lit('('), lit(')'), lit('|'), lit('['), lit(']'),
+            lit('{'), lit('}'), lit('^'), lit('$'), lit('#'),
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_escape_hash() {
+        assert_eq!(p(r"(?x)a\# # hi there"), Expr::Concat(vec![
+            lit('a'),
+            lit('#'),
+        ]));
+    }
+
+    #[test]
+    fn ignore_space_escape_space() {
+        assert_eq!(p(r"(?x)a\  # hi there"), Expr::Concat(vec![
+            lit('a'),
+            lit(' '),
+        ]));
+    }
+
+    // Test every single possible error case.
+
+    macro_rules! test_err {
+        ($re:expr, $pos:expr, $kind:expr) => {
+            test_err!($re, $pos, $kind, Flags::default());
+        };
+        ($re:expr, $pos:expr, $kind:expr, $flags:expr) => {{
+            let err = Parser::parse($re, $flags).unwrap_err();
+            assert_eq!($pos, err.pos);
+            assert_eq!($kind, err.kind);
+            assert!($re.contains(&err.surround));
+        }}
+    }
+
+    #[test]
+    fn invalid_utf8_not_allowed() {
+        // let flags = Flags { unicode: false, .. Flags::default() };
+        test_err!(r"(?-u)\xFF", 9, ErrorKind::InvalidUtf8);
+        test_err!(r"(?-u).", 5, ErrorKind::InvalidUtf8);
+        test_err!(r"(?-u)(?s).", 9, ErrorKind::InvalidUtf8);
+        test_err!(r"(?-u)[\x00-\x80]", 15, ErrorKind::InvalidUtf8);
+        test_err!(r"(?-u)\222", 9, ErrorKind::InvalidUtf8);
+        test_err!(r"(?-u)\x{0080}", 13, ErrorKind::InvalidUtf8);
+    }
+
+    #[test]
+    fn unicode_char_not_allowed() {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!("☃(?-u:☃)", 7, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn unicode_class_not_allowed() {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"☃(?-u:\pL)", 9, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn unicode_class_literal_not_allowed() {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"(?-u)[☃]", 6, ErrorKind::UnicodeNotAllowed, flags);
+        test_err!(r"(?-u)[☃-☃]", 6, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn unicode_hex_not_allowed() {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"(?-u)\x{FFFF}", 13, ErrorKind::UnicodeNotAllowed, flags);
+        test_err!(r"(?-u)\x{100}", 12, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn unicode_octal_not_allowed() {
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"(?-u)\400", 9, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn error_repeat_no_expr_simple() {
+        test_err!("(*", 1, ErrorKind::RepeaterExpectsExpr);
+    }
+
+    #[test]
+    fn error_repeat_no_expr_counted() {
+        test_err!("({5}", 1, ErrorKind::RepeaterExpectsExpr);
+    }
+
+    #[test]
+    fn error_repeat_beginning_counted() {
+        test_err!("{5}", 0, ErrorKind::RepeaterExpectsExpr);
+    }
+
+    #[test]
+    fn error_repeat_illegal_exprs_simple() {
+        test_err!("a**", 2, ErrorKind::RepeaterUnexpectedExpr(Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrMore,
+            greedy: true,
+        }));
+        test_err!("a|*", 2,
+            ErrorKind::RepeaterUnexpectedExpr(Expr::Alternate(vec![lit('a')]))
+        );
+    }
+
+    #[test]
+    fn error_repeat_illegal_exprs_counted() {
+        test_err!("a*{5}", 2, ErrorKind::RepeaterUnexpectedExpr(Expr::Repeat {
+            e: b(lit('a')),
+            r: Repeater::ZeroOrMore,
+            greedy: true,
+        }));
+        test_err!("a|{5}", 2,
+            ErrorKind::RepeaterUnexpectedExpr(Expr::Alternate(vec![lit('a')]))
+        );
+    }
+
+    #[test]
+    fn error_repeat_empty_number() {
+        test_err!("a{}", 2, ErrorKind::MissingBase10);
+    }
+
+    #[test]
+    fn error_repeat_eof() {
+        test_err!("a{5", 3, ErrorKind::UnclosedRepeat);
+    }
+
+    #[test]
+    fn error_repeat_empty_number_eof() {
+        test_err!("a{xyz", 5, ErrorKind::InvalidBase10("xyz".into()));
+        test_err!("a{12,xyz", 8, ErrorKind::InvalidBase10("xyz".into()));
+    }
+
+    #[test]
+    fn error_repeat_invalid_number() {
+        test_err!("a{9999999999}", 12,
+                  ErrorKind::InvalidBase10("9999999999".into()));
+        test_err!("a{1,9999999999}", 14,
+                  ErrorKind::InvalidBase10("9999999999".into()));
+    }
+
+    #[test]
+    fn error_repeat_invalid_number_extra() {
+        test_err!("a{12x}", 5, ErrorKind::InvalidBase10("12x".into()));
+        test_err!("a{1,12x}", 7, ErrorKind::InvalidBase10("12x".into()));
+    }
+
+    #[test]
+    fn error_repeat_invalid_range() {
+        test_err!("a{2,1}", 5,
+                  ErrorKind::InvalidRepeatRange { min: 2, max: 1 });
+    }
+
+    #[test]
+    fn error_alternate_empty() {
+        test_err!("|a", 0, ErrorKind::EmptyAlternate);
+    }
+
+    #[test]
+    fn error_alternate_empty_with_group() {
+        test_err!("(|a)", 1, ErrorKind::EmptyAlternate);
+    }
+
+    #[test]
+    fn error_alternate_empty_with_alternate() {
+        test_err!("a||", 2, ErrorKind::EmptyAlternate);
+    }
+
+    #[test]
+    fn error_close_paren_unopened_empty() {
+        test_err!(")", 0, ErrorKind::UnopenedParen);
+    }
+
+    #[test]
+    fn error_close_paren_unopened() {
+        test_err!("ab)", 2, ErrorKind::UnopenedParen);
+    }
+
+    #[test]
+    fn error_close_paren_unopened_with_alt() {
+        test_err!("a|b)", 3, ErrorKind::UnopenedParen);
+    }
+
+    #[test]
+    fn error_close_paren_unclosed_with_alt() {
+        test_err!("(a|b", 0, ErrorKind::UnclosedParen);
+    }
+
+    #[test]
+    fn error_close_paren_empty_alt() {
+        test_err!("(a|)", 3, ErrorKind::EmptyAlternate);
+    }
+
+    #[test]
+    fn error_close_paren_empty_group() {
+        test_err!("()", 1, ErrorKind::EmptyGroup);
+    }
+
+    #[test]
+    fn error_close_paren_empty_group_with_name() {
+        test_err!("(?P<foo>)", 8, ErrorKind::EmptyGroup);
+    }
+
+    #[test]
+    fn error_finish_concat_unclosed() {
+        test_err!("ab(xy", 2, ErrorKind::UnclosedParen);
+    }
+
+    #[test]
+    fn error_finish_concat_empty_alt() {
+        test_err!("a|", 2, ErrorKind::EmptyAlternate);
+    }
+
+    #[test]
+    fn error_group_name_invalid() {
+        test_err!("(?P<a#>x)", 6, ErrorKind::InvalidCaptureName("a#".into()));
+    }
+
+    #[test]
+    fn error_group_name_invalid_leading() {
+        test_err!("(?P<1a>a)", 6, ErrorKind::InvalidCaptureName("1a".into()));
+    }
+
+    #[test]
+    fn error_group_name_unexpected_eof() {
+        test_err!("(?P<a", 5, ErrorKind::UnclosedCaptureName("a".into()));
+    }
+
+    #[test]
+    fn error_group_name_empty() {
+        test_err!("(?P<>a)", 4, ErrorKind::EmptyCaptureName);
+    }
+
+    #[test]
+    fn error_group_opts_unrecognized_flag() {
+        test_err!("(?z:a)", 2, ErrorKind::UnrecognizedFlag('z'));
+    }
+
+    #[test]
+    fn error_group_opts_unexpected_eof() {
+        test_err!("(?i", 3, ErrorKind::UnexpectedFlagEof);
+    }
+
+    #[test]
+    fn error_group_opts_double_negation() {
+        test_err!("(?-i-s:a)", 4, ErrorKind::DoubleFlagNegation);
+    }
+
+    #[test]
+    fn error_group_opts_empty_negation() {
+        test_err!("(?i-:a)", 4, ErrorKind::EmptyFlagNegation);
+    }
+
+    #[test]
+    fn error_group_opts_empty() {
+        test_err!("(?)", 2, ErrorKind::EmptyFlagNegation);
+    }
+
+    #[test]
+    fn error_escape_unexpected_eof() {
+        test_err!(r"\", 1, ErrorKind::UnexpectedEscapeEof);
+    }
+
+    #[test]
+    fn error_escape_unrecognized() {
+        test_err!(r"\m", 1, ErrorKind::UnrecognizedEscape('m'));
+    }
+
+    #[test]
+    fn error_escape_hex2_eof0() {
+        test_err!(r"\x", 2, ErrorKind::UnexpectedTwoDigitHexEof);
+    }
+
+    #[test]
+    fn error_escape_hex2_eof1() {
+        test_err!(r"\xA", 3, ErrorKind::UnexpectedTwoDigitHexEof);
+    }
+
+    #[test]
+    fn error_escape_hex2_invalid() {
+        test_err!(r"\xAG", 4, ErrorKind::InvalidBase16("AG".into()));
+    }
+
+    #[test]
+    fn error_escape_hex_eof0() {
+        test_err!(r"\x{", 3, ErrorKind::InvalidBase16("".into()));
+    }
+
+    #[test]
+    fn error_escape_hex_eof1() {
+        test_err!(r"\x{A", 4, ErrorKind::UnclosedHex);
+    }
+
+    #[test]
+    fn error_escape_hex_invalid() {
+        test_err!(r"\x{AG}", 5, ErrorKind::InvalidBase16("AG".into()));
+    }
+
+    #[test]
+    fn error_escape_hex_invalid_scalar_value_surrogate() {
+        test_err!(r"\x{D800}", 8, ErrorKind::InvalidScalarValue(0xD800));
+    }
+
+    #[test]
+    fn error_escape_hex_invalid_scalar_value_high() {
+        test_err!(r"\x{110000}", 10, ErrorKind::InvalidScalarValue(0x110000));
+    }
+
+    #[test]
+    fn error_escape_hex_invalid_u32() {
+        test_err!(r"\x{9999999999}", 13,
+                  ErrorKind::InvalidBase16("9999999999".into()));
+    }
+
+    #[test]
+    fn error_unicode_unclosed() {
+        test_err!(r"\p{", 3, ErrorKind::UnclosedUnicodeName);
+        test_err!(r"\p{Greek", 8, ErrorKind::UnclosedUnicodeName);
+    }
+
+    #[test]
+    fn error_unicode_no_letter() {
+        test_err!(r"\p", 2, ErrorKind::UnexpectedEscapeEof);
+    }
+
+    #[test]
+    fn error_unicode_unknown_letter() {
+        test_err!(r"\pA", 3, ErrorKind::UnrecognizedUnicodeClass("A".into()));
+    }
+
+    #[test]
+    fn error_unicode_unknown_name() {
+        test_err!(r"\p{Yii}", 7,
+                  ErrorKind::UnrecognizedUnicodeClass("Yii".into()));
+    }
+
+    #[test]
+    fn error_class_eof_empty() {
+        test_err!("[", 1, ErrorKind::UnexpectedClassEof);
+        test_err!("[^", 2, ErrorKind::UnexpectedClassEof);
+    }
+
+    #[test]
+    fn error_class_eof_non_empty() {
+        test_err!("[a", 2, ErrorKind::UnexpectedClassEof);
+        test_err!("[^a", 3, ErrorKind::UnexpectedClassEof);
+    }
+
+    #[test]
+    fn error_class_eof_range() {
+        test_err!("[a-", 3, ErrorKind::UnexpectedClassEof);
+        test_err!("[^a-", 4, ErrorKind::UnexpectedClassEof);
+        test_err!("[---", 4, ErrorKind::UnexpectedClassEof);
+    }
+
+    #[test]
+    fn error_class_invalid_escape() {
+        test_err!(r"[\pA]", 4,
+                  ErrorKind::UnrecognizedUnicodeClass("A".into()));
+    }
+
+    #[test]
+    fn error_class_valid_escape_not_allowed() {
+        test_err!(r"[\A]", 3, ErrorKind::InvalidClassEscape(Expr::StartText));
+    }
+
+    #[test]
+    fn error_class_range_valid_escape_not_allowed() {
+        test_err!(r"[a-\d]", 5,
+                  ErrorKind::InvalidClassEscape(Expr::Class(class(PERLD))));
+        test_err!(r"[a-\A]", 5,
+                  ErrorKind::InvalidClassEscape(Expr::StartText));
+        test_err!(r"[\A-a]", 3,
+                  ErrorKind::InvalidClassEscape(Expr::StartText));
+    }
+
+    #[test]
+    fn error_class_invalid_range() {
+        test_err!("[z-a]", 4, ErrorKind::InvalidClassRange {
+            start: 'z',
+            end: 'a',
+        });
+    }
+
+    #[test]
+    fn error_class_empty_range() {
+        test_err!("[]", 2, ErrorKind::UnexpectedClassEof);
+        test_err!("[^]", 3, ErrorKind::UnexpectedClassEof);
+        test_err!(r"[^\d\D]", 7, ErrorKind::EmptyClass);
+
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"(?-u)[^\x00-\xFF]", 17, ErrorKind::EmptyClass, flags);
+    }
+
+    #[test]
+    fn error_class_unsupported_char() {
+        // These tests ensure that some unescaped special characters are
+        // rejected in character classes. The intention is to use these
+        // characters to implement sets as described in UTS#18 RL1.3. Once
+        // that's done, these tests should be removed and replaced with others.
+        test_err!("[~~]", 2, ErrorKind::UnsupportedClassChar('~'));
+        test_err!("[+--]", 4, ErrorKind::UnsupportedClassChar('-'));
+        test_err!(r"[a-a--\xFF]", 5, ErrorKind::UnsupportedClassChar('-'));
+        test_err!(r"[a&&~~]", 5, ErrorKind::UnsupportedClassChar('~'));
+        test_err!(r"[a&&--]", 5, ErrorKind::UnsupportedClassChar('-'));
+    }
+
+    #[test]
+    fn error_class_nested_class() {
+        test_err!(r"[[]]", 4, ErrorKind::UnexpectedClassEof);
+        test_err!(r"[[][]]", 6, ErrorKind::UnexpectedClassEof);
+        test_err!(r"[[^\d\D]]", 8, ErrorKind::EmptyClass);
+        test_err!(r"[[]", 3, ErrorKind::UnexpectedClassEof);
+        test_err!(r"[[^]", 4, ErrorKind::UnexpectedClassEof);
+    }
+
+    #[test]
+    fn error_class_intersection() {
+        test_err!(r"[&&]", 4, ErrorKind::EmptyClass);
+        test_err!(r"[a&&]", 5, ErrorKind::EmptyClass);
+        test_err!(r"[&&&&]", 6, ErrorKind::EmptyClass);
+        // `]` after `&&` is not the same as in (`[]]`), because it's also not
+        // allowed unescaped in `[a]]`.
+        test_err!(r"[]&&]]", 5, ErrorKind::EmptyClass);
+
+        let flags = Flags { allow_bytes: true, .. Flags::default() };
+        test_err!(r"(?-u)[a&&\pZ]", 12, ErrorKind::UnicodeNotAllowed, flags);
+    }
+
+    #[test]
+    fn error_duplicate_capture_name() {
+        test_err!("(?P<a>.)(?P<a>.)", 14,
+                  ErrorKind::DuplicateCaptureName("a".into()));
+    }
+
+    #[test]
+    fn error_ignore_space_escape_hex() {
+        test_err!(r"(?x)\x{ 5 3 }", 10, ErrorKind::UnclosedHex);
+    }
+
+    #[test]
+    fn error_ignore_space_escape_hex2() {
+        test_err!(r"(?x)\x 5 3", 9, ErrorKind::InvalidBase16("5 ".into()));
+    }
+
+    #[test]
+    fn error_ignore_space_escape_unicode_name() {
+        test_err!(r"(?x)\p{Y i}", 9, ErrorKind::UnclosedUnicodeName);
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/properties.rs b/third_party/rust/regex-syntax-0.4.1/src/properties.rs
similarity index 100%
rename from third_party/rust/regex-syntax/src/properties.rs
rename to third_party/rust/regex-syntax-0.4.1/src/properties.rs
diff --git a/third_party/rust/regex-syntax-0.4.1/src/unicode.rs b/third_party/rust/regex-syntax-0.4.1/src/unicode.rs
new file mode 100644
index 000000000000..3132f63bd4e1
--- /dev/null
+++ b/third_party/rust/regex-syntax-0.4.1/src/unicode.rs
@@ -0,0 +1,5715 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// NOTE: The following code was generated by "scripts/unicode.py", do not edit
+// directly
+
+#![allow(warnings)]
+pub mod general_category {
+    pub const C_table: &'static [(char, char)] = &[
+        ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}'), ('\u{ad}', '\u{ad}'),
+        ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
+        ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
+        ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'),
+        ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'), ('\u{5c8}', '\u{5cf}'),
+        ('\u{5eb}', '\u{5ef}'), ('\u{5f5}', '\u{605}'), ('\u{61c}', '\u{61d}'),
+        ('\u{6dd}', '\u{6dd}'), ('\u{70e}', '\u{70f}'), ('\u{74b}', '\u{74c}'),
+        ('\u{7b2}', '\u{7bf}'), ('\u{7fb}', '\u{7ff}'), ('\u{82e}', '\u{82f}'),
+        ('\u{83f}', '\u{83f}'), ('\u{85c}', '\u{85d}'), ('\u{85f}', '\u{89f}'),
+        ('\u{8b5}', '\u{8e2}'), ('\u{984}', '\u{984}'), ('\u{98d}', '\u{98e}'),
+        ('\u{991}', '\u{992}'), ('\u{9a9}', '\u{9a9}'), ('\u{9b1}', '\u{9b1}'),
+        ('\u{9b3}', '\u{9b5}'), ('\u{9ba}', '\u{9bb}'), ('\u{9c5}', '\u{9c6}'),
+        ('\u{9c9}', '\u{9ca}'), ('\u{9cf}', '\u{9d6}'), ('\u{9d8}', '\u{9db}'),
+        ('\u{9de}', '\u{9de}'), ('\u{9e4}', '\u{9e5}'), ('\u{9fc}', '\u{a00}'),
+        ('\u{a04}', '\u{a04}'), ('\u{a0b}', '\u{a0e}'), ('\u{a11}', '\u{a12}'),
+        ('\u{a29}', '\u{a29}'), ('\u{a31}', '\u{a31}'), ('\u{a34}', '\u{a34}'),
+        ('\u{a37}', '\u{a37}'), ('\u{a3a}', '\u{a3b}'), ('\u{a3d}', '\u{a3d}'),
+        ('\u{a43}', '\u{a46}'), ('\u{a49}', '\u{a4a}'), ('\u{a4e}', '\u{a50}'),
+        ('\u{a52}', '\u{a58}'), ('\u{a5d}', '\u{a5d}'), ('\u{a5f}', '\u{a65}'),
+        ('\u{a76}', '\u{a80}'), ('\u{a84}', '\u{a84}'), ('\u{a8e}', '\u{a8e}'),
+        ('\u{a92}', '\u{a92}'), ('\u{aa9}', '\u{aa9}'), ('\u{ab1}', '\u{ab1}'),
+        ('\u{ab4}', '\u{ab4}'), ('\u{aba}', '\u{abb}'), ('\u{ac6}', '\u{ac6}'),
+        ('\u{aca}', '\u{aca}'), ('\u{ace}', '\u{acf}'), ('\u{ad1}', '\u{adf}'),
+        ('\u{ae4}', '\u{ae5}'), ('\u{af2}', '\u{af8}'), ('\u{afa}', '\u{b00}'),
+        ('\u{b04}', '\u{b04}'), ('\u{b0d}', '\u{b0e}'), ('\u{b11}', '\u{b12}'),
+        ('\u{b29}', '\u{b29}'), ('\u{b31}', '\u{b31}'), ('\u{b34}', '\u{b34}'),
+        ('\u{b3a}', '\u{b3b}'), ('\u{b45}', '\u{b46}'), ('\u{b49}', '\u{b4a}'),
+        ('\u{b4e}', '\u{b55}'), ('\u{b58}', '\u{b5b}'), ('\u{b5e}', '\u{b5e}'),
+        ('\u{b64}', '\u{b65}'), ('\u{b78}', '\u{b81}'), ('\u{b84}', '\u{b84}'),
+        ('\u{b8b}', '\u{b8d}'), ('\u{b91}', '\u{b91}'), ('\u{b96}', '\u{b98}'),
+        ('\u{b9b}', '\u{b9b}'), ('\u{b9d}', '\u{b9d}'), ('\u{ba0}', '\u{ba2}'),
+        ('\u{ba5}', '\u{ba7}'), ('\u{bab}', '\u{bad}'), ('\u{bba}', '\u{bbd}'),
+        ('\u{bc3}', '\u{bc5}'), ('\u{bc9}', '\u{bc9}'), ('\u{bce}', '\u{bcf}'),
+        ('\u{bd1}', '\u{bd6}'), ('\u{bd8}', '\u{be5}'), ('\u{bfb}', '\u{bff}'),
+        ('\u{c04}', '\u{c04}'), ('\u{c0d}', '\u{c0d}'), ('\u{c11}', '\u{c11}'),
+        ('\u{c29}', '\u{c29}'), ('\u{c3a}', '\u{c3c}'), ('\u{c45}', '\u{c45}'),
+        ('\u{c49}', '\u{c49}'), ('\u{c4e}', '\u{c54}'), ('\u{c57}', '\u{c57}'),
+        ('\u{c5b}', '\u{c5f}'), ('\u{c64}', '\u{c65}'), ('\u{c70}', '\u{c77}'),
+        ('\u{c80}', '\u{c80}'), ('\u{c84}', '\u{c84}'), ('\u{c8d}', '\u{c8d}'),
+        ('\u{c91}', '\u{c91}'), ('\u{ca9}', '\u{ca9}'), ('\u{cb4}', '\u{cb4}'),
+        ('\u{cba}', '\u{cbb}'), ('\u{cc5}', '\u{cc5}'), ('\u{cc9}', '\u{cc9}'),
+        ('\u{cce}', '\u{cd4}'), ('\u{cd7}', '\u{cdd}'), ('\u{cdf}', '\u{cdf}'),
+        ('\u{ce4}', '\u{ce5}'), ('\u{cf0}', '\u{cf0}'), ('\u{cf3}', '\u{d00}'),
+        ('\u{d04}', '\u{d04}'), ('\u{d0d}', '\u{d0d}'), ('\u{d11}', '\u{d11}'),
+        ('\u{d3b}', '\u{d3c}'), ('\u{d45}', '\u{d45}'), ('\u{d49}', '\u{d49}'),
+        ('\u{d4f}', '\u{d56}'), ('\u{d58}', '\u{d5e}'), ('\u{d64}', '\u{d65}'),
+        ('\u{d76}', '\u{d78}'), ('\u{d80}', '\u{d81}'), ('\u{d84}', '\u{d84}'),
+        ('\u{d97}', '\u{d99}'), ('\u{db2}', '\u{db2}'), ('\u{dbc}', '\u{dbc}'),
+        ('\u{dbe}', '\u{dbf}'), ('\u{dc7}', '\u{dc9}'), ('\u{dcb}', '\u{dce}'),
+        ('\u{dd5}', '\u{dd5}'), ('\u{dd7}', '\u{dd7}'), ('\u{de0}', '\u{de5}'),
+        ('\u{df0}', '\u{df1}'), ('\u{df5}', '\u{e00}'), ('\u{e3b}', '\u{e3e}'),
+        ('\u{e5c}', '\u{e80}'), ('\u{e83}', '\u{e83}'), ('\u{e85}', '\u{e86}'),
+        ('\u{e89}', '\u{e89}'), ('\u{e8b}', '\u{e8c}'), ('\u{e8e}', '\u{e93}'),
+        ('\u{e98}', '\u{e98}'), ('\u{ea0}', '\u{ea0}'), ('\u{ea4}', '\u{ea4}'),
+        ('\u{ea6}', '\u{ea6}'), ('\u{ea8}', '\u{ea9}'), ('\u{eac}', '\u{eac}'),
+        ('\u{eba}', '\u{eba}'), ('\u{ebe}', '\u{ebf}'), ('\u{ec5}', '\u{ec5}'),
+        ('\u{ec7}', '\u{ec7}'), ('\u{ece}', '\u{ecf}'), ('\u{eda}', '\u{edb}'),
+        ('\u{ee0}', '\u{eff}'), ('\u{f48}', '\u{f48}'), ('\u{f6d}', '\u{f70}'),
+        ('\u{f98}', '\u{f98}'), ('\u{fbd}', '\u{fbd}'), ('\u{fcd}', '\u{fcd}'),
+        ('\u{fdb}', '\u{fff}'), ('\u{10c6}', '\u{10c6}'), ('\u{10c8}',
+        '\u{10cc}'), ('\u{10ce}', '\u{10cf}'), ('\u{1249}', '\u{1249}'),
+        ('\u{124e}', '\u{124f}'), ('\u{1257}', '\u{1257}'), ('\u{1259}',
+        '\u{1259}'), ('\u{125e}', '\u{125f}'), ('\u{1289}', '\u{1289}'),
+        ('\u{128e}', '\u{128f}'), ('\u{12b1}', '\u{12b1}'), ('\u{12b6}',
+        '\u{12b7}'), ('\u{12bf}', '\u{12bf}'), ('\u{12c1}', '\u{12c1}'),
+        ('\u{12c6}', '\u{12c7}'), ('\u{12d7}', '\u{12d7}'), ('\u{1311}',
+        '\u{1311}'), ('\u{1316}', '\u{1317}'), ('\u{135b}', '\u{135c}'),
+        ('\u{137d}', '\u{137f}'), ('\u{139a}', '\u{139f}'), ('\u{13f6}',
+        '\u{13f7}'), ('\u{13fe}', '\u{13ff}'), ('\u{169d}', '\u{169f}'),
+        ('\u{16f9}', '\u{16ff}'), ('\u{170d}', '\u{170d}'), ('\u{1715}',
+        '\u{171f}'), ('\u{1737}', '\u{173f}'), ('\u{1754}', '\u{175f}'),
+        ('\u{176d}', '\u{176d}'), ('\u{1771}', '\u{1771}'), ('\u{1774}',
+        '\u{177f}'), ('\u{17de}', '\u{17df}'), ('\u{17ea}', '\u{17ef}'),
+        ('\u{17fa}', '\u{17ff}'), ('\u{180e}', '\u{180f}'), ('\u{181a}',
+        '\u{181f}'), ('\u{1878}', '\u{187f}'), ('\u{18ab}', '\u{18af}'),
+        ('\u{18f6}', '\u{18ff}'), ('\u{191f}', '\u{191f}'), ('\u{192c}',
+        '\u{192f}'), ('\u{193c}', '\u{193f}'), ('\u{1941}', '\u{1943}'),
+        ('\u{196e}', '\u{196f}'), ('\u{1975}', '\u{197f}'), ('\u{19ac}',
+        '\u{19af}'), ('\u{19ca}', '\u{19cf}'), ('\u{19db}', '\u{19dd}'),
+        ('\u{1a1c}', '\u{1a1d}'), ('\u{1a5f}', '\u{1a5f}'), ('\u{1a7d}',
+        '\u{1a7e}'), ('\u{1a8a}', '\u{1a8f}'), ('\u{1a9a}', '\u{1a9f}'),
+        ('\u{1aae}', '\u{1aaf}'), ('\u{1abf}', '\u{1aff}'), ('\u{1b4c}',
+        '\u{1b4f}'), ('\u{1b7d}', '\u{1b7f}'), ('\u{1bf4}', '\u{1bfb}'),
+        ('\u{1c38}', '\u{1c3a}'), ('\u{1c4a}', '\u{1c4c}'), ('\u{1c80}',
+        '\u{1cbf}'), ('\u{1cc8}', '\u{1ccf}'), ('\u{1cf7}', '\u{1cf7}'),
+        ('\u{1cfa}', '\u{1cff}'), ('\u{1df6}', '\u{1dfb}'), ('\u{1f16}',
+        '\u{1f17}'), ('\u{1f1e}', '\u{1f1f}'), ('\u{1f46}', '\u{1f47}'),
+        ('\u{1f4e}', '\u{1f4f}'), ('\u{1f58}', '\u{1f58}'), ('\u{1f5a}',
+        '\u{1f5a}'), ('\u{1f5c}', '\u{1f5c}'), ('\u{1f5e}', '\u{1f5e}'),
+        ('\u{1f7e}', '\u{1f7f}'), ('\u{1fb5}', '\u{1fb5}'), ('\u{1fc5}',
+        '\u{1fc5}'), ('\u{1fd4}', '\u{1fd5}'), ('\u{1fdc}', '\u{1fdc}'),
+        ('\u{1ff0}', '\u{1ff1}'), ('\u{1ff5}', '\u{1ff5}'), ('\u{1fff}',
+        '\u{1fff}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
+        ('\u{2060}', '\u{206f}'), ('\u{2072}', '\u{2073}'), ('\u{208f}',
+        '\u{208f}'), ('\u{209d}', '\u{209f}'), ('\u{20bf}', '\u{20cf}'),
+        ('\u{20f1}', '\u{20ff}'), ('\u{218c}', '\u{218f}'), ('\u{23fb}',
+        '\u{23ff}'), ('\u{2427}', '\u{243f}'), ('\u{244b}', '\u{245f}'),
+        ('\u{2b74}', '\u{2b75}'), ('\u{2b96}', '\u{2b97}'), ('\u{2bba}',
+        '\u{2bbc}'), ('\u{2bc9}', '\u{2bc9}'), ('\u{2bd2}', '\u{2beb}'),
+        ('\u{2bf0}', '\u{2bff}'), ('\u{2c2f}', '\u{2c2f}'), ('\u{2c5f}',
+        '\u{2c5f}'), ('\u{2cf4}', '\u{2cf8}'), ('\u{2d26}', '\u{2d26}'),
+        ('\u{2d28}', '\u{2d2c}'), ('\u{2d2e}', '\u{2d2f}'), ('\u{2d68}',
+        '\u{2d6e}'), ('\u{2d71}', '\u{2d7e}'), ('\u{2d97}', '\u{2d9f}'),
+        ('\u{2da7}', '\u{2da7}'), ('\u{2daf}', '\u{2daf}'), ('\u{2db7}',
+        '\u{2db7}'), ('\u{2dbf}', '\u{2dbf}'), ('\u{2dc7}', '\u{2dc7}'),
+        ('\u{2dcf}', '\u{2dcf}'), ('\u{2dd7}', '\u{2dd7}'), ('\u{2ddf}',
+        '\u{2ddf}'), ('\u{2e43}', '\u{2e7f}'), ('\u{2e9a}', '\u{2e9a}'),
+        ('\u{2ef4}', '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}',
+        '\u{2fff}'), ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'),
+        ('\u{3100}', '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}',
+        '\u{318f}'), ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'),
+        ('\u{321f}', '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{4db6}',
+        '\u{4dbf}'), ('\u{9fd6}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'),
+        ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a6f8}',
+        '\u{a6ff}'), ('\u{a7ae}', '\u{a7af}'), ('\u{a7b8}', '\u{a7f6}'),
+        ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}',
+        '\u{a87f}'), ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'),
+        ('\u{a8fe}', '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}',
+        '\u{a97f}'), ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'),
+        ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}',
+        '\u{aa4f}'), ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'),
+        ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}',
+        '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'),
+        ('\u{ab2f}', '\u{ab2f}'), ('\u{ab66}', '\u{ab6f}'), ('\u{abee}',
+        '\u{abef}'), ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'),
+        ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{e000}',
+        '\u{f8ff}'), ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', '\u{faff}'),
+        ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}',
+        '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'),
+        ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', '\u{fb45}'), ('\u{fbc2}',
+        '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'),
+        ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}',
+        '\u{fe1f}'), ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'),
+        ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}', '\u{fe75}'), ('\u{fefd}',
+        '\u{ff00}'), ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'),
+        ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}',
+        '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fffb}'),
+        ('\u{fffe}', '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}',
+        '\u{10027}'), ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'),
+        ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', '\u{1007f}'), ('\u{100fb}',
+        '\u{100ff}'), ('\u{10103}', '\u{10106}'), ('\u{10134}', '\u{10136}'),
+        ('\u{1018d}', '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), ('\u{101a1}',
+        '\u{101cf}'), ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'),
+        ('\u{102d1}', '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}',
+        '\u{1032f}'), ('\u{1034b}', '\u{1034f}'), ('\u{1037b}', '\u{1037f}'),
+        ('\u{1039e}', '\u{1039e}'), ('\u{103c4}', '\u{103c7}'), ('\u{103d6}',
+        '\u{103ff}'), ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104ff}'),
+        ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'), ('\u{10570}',
+        '\u{105ff}'), ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'),
+        ('\u{10768}', '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}',
+        '\u{10809}'), ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'),
+        ('\u{1083d}', '\u{1083e}'), ('\u{10856}', '\u{10856}'), ('\u{1089f}',
+        '\u{108a6}'), ('\u{108b0}', '\u{108df}'), ('\u{108f3}', '\u{108f3}'),
+        ('\u{108f6}', '\u{108fa}'), ('\u{1091c}', '\u{1091e}'), ('\u{1093a}',
+        '\u{1093e}'), ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'),
+        ('\u{109d0}', '\u{109d1}'), ('\u{10a04}', '\u{10a04}'), ('\u{10a07}',
+        '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'),
+        ('\u{10a34}', '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}',
+        '\u{10a4f}'), ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'),
+        ('\u{10ae7}', '\u{10aea}'), ('\u{10af7}', '\u{10aff}'), ('\u{10b36}',
+        '\u{10b38}'), ('\u{10b56}', '\u{10b57}'), ('\u{10b73}', '\u{10b77}'),
+        ('\u{10b92}', '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}',
+        '\u{10bff}'), ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'),
+        ('\u{10cf3}', '\u{10cf9}'), ('\u{10d00}', '\u{10e5f}'), ('\u{10e7f}',
+        '\u{10fff}'), ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'),
+        ('\u{110bd}', '\u{110bd}'), ('\u{110c2}', '\u{110cf}'), ('\u{110e9}',
+        '\u{110ef}'), ('\u{110fa}', '\u{110ff}'), ('\u{11135}', '\u{11135}'),
+        ('\u{11144}', '\u{1114f}'), ('\u{11177}', '\u{1117f}'), ('\u{111ce}',
+        '\u{111cf}'), ('\u{111e0}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'),
+        ('\u{11212}', '\u{11212}'), ('\u{1123e}', '\u{1127f}'), ('\u{11287}',
+        '\u{11287}'), ('\u{11289}', '\u{11289}'), ('\u{1128e}', '\u{1128e}'),
+        ('\u{1129e}', '\u{1129e}'), ('\u{112aa}', '\u{112af}'), ('\u{112eb}',
+        '\u{112ef}'), ('\u{112fa}', '\u{112ff}'), ('\u{11304}', '\u{11304}'),
+        ('\u{1130d}', '\u{1130e}'), ('\u{11311}', '\u{11312}'), ('\u{11329}',
+        '\u{11329}'), ('\u{11331}', '\u{11331}'), ('\u{11334}', '\u{11334}'),
+        ('\u{1133a}', '\u{1133b}'), ('\u{11345}', '\u{11346}'), ('\u{11349}',
+        '\u{1134a}'), ('\u{1134e}', '\u{1134f}'), ('\u{11351}', '\u{11356}'),
+        ('\u{11358}', '\u{1135c}'), ('\u{11364}', '\u{11365}'), ('\u{1136d}',
+        '\u{1136f}'), ('\u{11375}', '\u{1147f}'), ('\u{114c8}', '\u{114cf}'),
+        ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'), ('\u{115de}',
+        '\u{115ff}'), ('\u{11645}', '\u{1164f}'), ('\u{1165a}', '\u{1167f}'),
+        ('\u{116b8}', '\u{116bf}'), ('\u{116ca}', '\u{116ff}'), ('\u{1171a}',
+        '\u{1171c}'), ('\u{1172c}', '\u{1172f}'), ('\u{11740}', '\u{1189f}'),
+        ('\u{118f3}', '\u{118fe}'), ('\u{11900}', '\u{11abf}'), ('\u{11af9}',
+        '\u{11fff}'), ('\u{1239a}', '\u{123ff}'), ('\u{1246f}', '\u{1246f}'),
+        ('\u{12475}', '\u{1247f}'), ('\u{12544}', '\u{12fff}'), ('\u{1342f}',
+        '\u{143ff}'), ('\u{14647}', '\u{167ff}'), ('\u{16a39}', '\u{16a3f}'),
+        ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'), ('\u{16a70}',
+        '\u{16acf}'), ('\u{16aee}', '\u{16aef}'), ('\u{16af6}', '\u{16aff}'),
+        ('\u{16b46}', '\u{16b4f}'), ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}',
+        '\u{16b62}'), ('\u{16b78}', '\u{16b7c}'), ('\u{16b90}', '\u{16eff}'),
+        ('\u{16f45}', '\u{16f4f}'), ('\u{16f7f}', '\u{16f8e}'), ('\u{16fa0}',
+        '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'), ('\u{1bc6b}', '\u{1bc6f}'),
+        ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'), ('\u{1bc9a}',
+        '\u{1bc9b}'), ('\u{1bca0}', '\u{1cfff}'), ('\u{1d0f6}', '\u{1d0ff}'),
+        ('\u{1d127}', '\u{1d128}'), ('\u{1d173}', '\u{1d17a}'), ('\u{1d1e9}',
+        '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), ('\u{1d357}', '\u{1d35f}'),
+        ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}',
+        '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'),
+        ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}',
+        '\u{1d4ba}'), ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'),
+        ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}',
+        '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', '\u{1d53a}'),
+        ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), ('\u{1d547}',
+        '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'),
+        ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1da8c}', '\u{1da9a}'), ('\u{1daa0}',
+        '\u{1daa0}'), ('\u{1dab0}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'),
+        ('\u{1e8d7}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}',
+        '\u{1ee20}'), ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'),
+        ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}',
+        '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', '\u{1ee41}'),
+        ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}',
+        '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'),
+        ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}',
+        '\u{1ee58}'), ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'),
+        ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}',
+        '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', '\u{1ee6b}'),
+        ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}',
+        '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'),
+        ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}',
+        '\u{1eeaa}'), ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'),
+        ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}',
+        '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', '\u{1f0d0}'),
+        ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), ('\u{1f12f}',
+        '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'),
+        ('\u{1f203}', '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}',
+        '\u{1f24f}'), ('\u{1f252}', '\u{1f2ff}'), ('\u{1f57a}', '\u{1f57a}'),
+        ('\u{1f5a4}', '\u{1f5a4}'), ('\u{1f6d1}', '\u{1f6df}'), ('\u{1f6ed}',
+        '\u{1f6ef}'), ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'),
+        ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}',
+        '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', '\u{1f88f}'),
+        ('\u{1f8ae}', '\u{1f90f}'), ('\u{1f919}', '\u{1f97f}'), ('\u{1f985}',
+        '\u{1f9bf}'), ('\u{1f9c1}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'),
+        ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2b81f}'), ('\u{2cea2}',
+        '\u{2f7ff}'), ('\u{2fa1e}', '\u{e00ff}'), ('\u{e01f0}', '\u{10ffff}')
+    ];
+
+    pub const Cc_table: &'static [(char, char)] = &[
+        ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}')
+    ];
+
+    pub const Cf_table: &'static [(char, char)] = &[
+        ('\u{ad}', '\u{ad}'), ('\u{600}', '\u{605}'), ('\u{61c}', '\u{61c}'),
+        ('\u{6dd}', '\u{6dd}'), ('\u{70f}', '\u{70f}'), ('\u{180e}',
+        '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
+        ('\u{2060}', '\u{2064}'), ('\u{2066}', '\u{206f}'), ('\u{feff}',
+        '\u{feff}'), ('\u{fff9}', '\u{fffb}'), ('\u{110bd}', '\u{110bd}'),
+        ('\u{1bca0}', '\u{1bca3}'), ('\u{1d173}', '\u{1d17a}'), ('\u{e0001}',
+        '\u{e0001}'), ('\u{e0020}', '\u{e007f}')
+    ];
+
+    pub const Cn_table: &'static [(char, char)] = &[
+        ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
+        ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
+        ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'),
+        ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'), ('\u{5c8}', '\u{5cf}'),
+        ('\u{5eb}', '\u{5ef}'), ('\u{5f5}', '\u{5ff}'), ('\u{61d}', '\u{61d}'),
+        ('\u{70e}', '\u{70e}'), ('\u{74b}', '\u{74c}'), ('\u{7b2}', '\u{7bf}'),
+        ('\u{7fb}', '\u{7ff}'), ('\u{82e}', '\u{82f}'), ('\u{83f}', '\u{83f}'),
+        ('\u{85c}', '\u{85d}'), ('\u{85f}', '\u{89f}'), ('\u{8b5}', '\u{8e2}'),
+        ('\u{984}', '\u{984}'), ('\u{98d}', '\u{98e}'), ('\u{991}', '\u{992}'),
+        ('\u{9a9}', '\u{9a9}'), ('\u{9b1}', '\u{9b1}'), ('\u{9b3}', '\u{9b5}'),
+        ('\u{9ba}', '\u{9bb}'), ('\u{9c5}', '\u{9c6}'), ('\u{9c9}', '\u{9ca}'),
+        ('\u{9cf}', '\u{9d6}'), ('\u{9d8}', '\u{9db}'), ('\u{9de}', '\u{9de}'),
+        ('\u{9e4}', '\u{9e5}'), ('\u{9fc}', '\u{a00}'), ('\u{a04}', '\u{a04}'),
+        ('\u{a0b}', '\u{a0e}'), ('\u{a11}', '\u{a12}'), ('\u{a29}', '\u{a29}'),
+        ('\u{a31}', '\u{a31}'), ('\u{a34}', '\u{a34}'), ('\u{a37}', '\u{a37}'),
+        ('\u{a3a}', '\u{a3b}'), ('\u{a3d}', '\u{a3d}'), ('\u{a43}', '\u{a46}'),
+        ('\u{a49}', '\u{a4a}'), ('\u{a4e}', '\u{a50}'), ('\u{a52}', '\u{a58}'),
+        ('\u{a5d}', '\u{a5d}'), ('\u{a5f}', '\u{a65}'), ('\u{a76}', '\u{a80}'),
+        ('\u{a84}', '\u{a84}'), ('\u{a8e}', '\u{a8e}'), ('\u{a92}', '\u{a92}'),
+        ('\u{aa9}', '\u{aa9}'), ('\u{ab1}', '\u{ab1}'), ('\u{ab4}', '\u{ab4}'),
+        ('\u{aba}', '\u{abb}'), ('\u{ac6}', '\u{ac6}'), ('\u{aca}', '\u{aca}'),
+        ('\u{ace}', '\u{acf}'), ('\u{ad1}', '\u{adf}'), ('\u{ae4}', '\u{ae5}'),
+        ('\u{af2}', '\u{af8}'), ('\u{afa}', '\u{b00}'), ('\u{b04}', '\u{b04}'),
+        ('\u{b0d}', '\u{b0e}'), ('\u{b11}', '\u{b12}'), ('\u{b29}', '\u{b29}'),
+        ('\u{b31}', '\u{b31}'), ('\u{b34}', '\u{b34}'), ('\u{b3a}', '\u{b3b}'),
+        ('\u{b45}', '\u{b46}'), ('\u{b49}', '\u{b4a}'), ('\u{b4e}', '\u{b55}'),
+        ('\u{b58}', '\u{b5b}'), ('\u{b5e}', '\u{b5e}'), ('\u{b64}', '\u{b65}'),
+        ('\u{b78}', '\u{b81}'), ('\u{b84}', '\u{b84}'), ('\u{b8b}', '\u{b8d}'),
+        ('\u{b91}', '\u{b91}'), ('\u{b96}', '\u{b98}'), ('\u{b9b}', '\u{b9b}'),
+        ('\u{b9d}', '\u{b9d}'), ('\u{ba0}', '\u{ba2}'), ('\u{ba5}', '\u{ba7}'),
+        ('\u{bab}', '\u{bad}'), ('\u{bba}', '\u{bbd}'), ('\u{bc3}', '\u{bc5}'),
+        ('\u{bc9}', '\u{bc9}'), ('\u{bce}', '\u{bcf}'), ('\u{bd1}', '\u{bd6}'),
+        ('\u{bd8}', '\u{be5}'), ('\u{bfb}', '\u{bff}'), ('\u{c04}', '\u{c04}'),
+        ('\u{c0d}', '\u{c0d}'), ('\u{c11}', '\u{c11}'), ('\u{c29}', '\u{c29}'),
+        ('\u{c3a}', '\u{c3c}'), ('\u{c45}', '\u{c45}'), ('\u{c49}', '\u{c49}'),
+        ('\u{c4e}', '\u{c54}'), ('\u{c57}', '\u{c57}'), ('\u{c5b}', '\u{c5f}'),
+        ('\u{c64}', '\u{c65}'), ('\u{c70}', '\u{c77}'), ('\u{c80}', '\u{c80}'),
+        ('\u{c84}', '\u{c84}'), ('\u{c8d}', '\u{c8d}'), ('\u{c91}', '\u{c91}'),
+        ('\u{ca9}', '\u{ca9}'), ('\u{cb4}', '\u{cb4}'), ('\u{cba}', '\u{cbb}'),
+        ('\u{cc5}', '\u{cc5}'), ('\u{cc9}', '\u{cc9}'), ('\u{cce}', '\u{cd4}'),
+        ('\u{cd7}', '\u{cdd}'), ('\u{cdf}', '\u{cdf}'), ('\u{ce4}', '\u{ce5}'),
+        ('\u{cf0}', '\u{cf0}'), ('\u{cf3}', '\u{d00}'), ('\u{d04}', '\u{d04}'),
+        ('\u{d0d}', '\u{d0d}'), ('\u{d11}', '\u{d11}'), ('\u{d3b}', '\u{d3c}'),
+        ('\u{d45}', '\u{d45}'), ('\u{d49}', '\u{d49}'), ('\u{d4f}', '\u{d56}'),
+        ('\u{d58}', '\u{d5e}'), ('\u{d64}', '\u{d65}'), ('\u{d76}', '\u{d78}'),
+        ('\u{d80}', '\u{d81}'), ('\u{d84}', '\u{d84}'), ('\u{d97}', '\u{d99}'),
+        ('\u{db2}', '\u{db2}'), ('\u{dbc}', '\u{dbc}'), ('\u{dbe}', '\u{dbf}'),
+        ('\u{dc7}', '\u{dc9}'), ('\u{dcb}', '\u{dce}'), ('\u{dd5}', '\u{dd5}'),
+        ('\u{dd7}', '\u{dd7}'), ('\u{de0}', '\u{de5}'), ('\u{df0}', '\u{df1}'),
+        ('\u{df5}', '\u{e00}'), ('\u{e3b}', '\u{e3e}'), ('\u{e5c}', '\u{e80}'),
+        ('\u{e83}', '\u{e83}'), ('\u{e85}', '\u{e86}'), ('\u{e89}', '\u{e89}'),
+        ('\u{e8b}', '\u{e8c}'), ('\u{e8e}', '\u{e93}'), ('\u{e98}', '\u{e98}'),
+        ('\u{ea0}', '\u{ea0}'), ('\u{ea4}', '\u{ea4}'), ('\u{ea6}', '\u{ea6}'),
+        ('\u{ea8}', '\u{ea9}'), ('\u{eac}', '\u{eac}'), ('\u{eba}', '\u{eba}'),
+        ('\u{ebe}', '\u{ebf}'), ('\u{ec5}', '\u{ec5}'), ('\u{ec7}', '\u{ec7}'),
+        ('\u{ece}', '\u{ecf}'), ('\u{eda}', '\u{edb}'), ('\u{ee0}', '\u{eff}'),
+        ('\u{f48}', '\u{f48}'), ('\u{f6d}', '\u{f70}'), ('\u{f98}', '\u{f98}'),
+        ('\u{fbd}', '\u{fbd}'), ('\u{fcd}', '\u{fcd}'), ('\u{fdb}', '\u{fff}'),
+        ('\u{10c6}', '\u{10c6}'), ('\u{10c8}', '\u{10cc}'), ('\u{10ce}',
+        '\u{10cf}'), ('\u{1249}', '\u{1249}'), ('\u{124e}', '\u{124f}'),
+        ('\u{1257}', '\u{1257}'), ('\u{1259}', '\u{1259}'), ('\u{125e}',
+        '\u{125f}'), ('\u{1289}', '\u{1289}'), ('\u{128e}', '\u{128f}'),
+        ('\u{12b1}', '\u{12b1}'), ('\u{12b6}', '\u{12b7}'), ('\u{12bf}',
+        '\u{12bf}'), ('\u{12c1}', '\u{12c1}'), ('\u{12c6}', '\u{12c7}'),
+        ('\u{12d7}', '\u{12d7}'), ('\u{1311}', '\u{1311}'), ('\u{1316}',
+        '\u{1317}'), ('\u{135b}', '\u{135c}'), ('\u{137d}', '\u{137f}'),
+        ('\u{139a}', '\u{139f}'), ('\u{13f6}', '\u{13f7}'), ('\u{13fe}',
+        '\u{13ff}'), ('\u{169d}', '\u{169f}'), ('\u{16f9}', '\u{16ff}'),
+        ('\u{170d}', '\u{170d}'), ('\u{1715}', '\u{171f}'), ('\u{1737}',
+        '\u{173f}'), ('\u{1754}', '\u{175f}'), ('\u{176d}', '\u{176d}'),
+        ('\u{1771}', '\u{1771}'), ('\u{1774}', '\u{177f}'), ('\u{17de}',
+        '\u{17df}'), ('\u{17ea}', '\u{17ef}'), ('\u{17fa}', '\u{17ff}'),
+        ('\u{180f}', '\u{180f}'), ('\u{181a}', '\u{181f}'), ('\u{1878}',
+        '\u{187f}'), ('\u{18ab}', '\u{18af}'), ('\u{18f6}', '\u{18ff}'),
+        ('\u{191f}', '\u{191f}'), ('\u{192c}', '\u{192f}'), ('\u{193c}',
+        '\u{193f}'), ('\u{1941}', '\u{1943}'), ('\u{196e}', '\u{196f}'),
+        ('\u{1975}', '\u{197f}'), ('\u{19ac}', '\u{19af}'), ('\u{19ca}',
+        '\u{19cf}'), ('\u{19db}', '\u{19dd}'), ('\u{1a1c}', '\u{1a1d}'),
+        ('\u{1a5f}', '\u{1a5f}'), ('\u{1a7d}', '\u{1a7e}'), ('\u{1a8a}',
+        '\u{1a8f}'), ('\u{1a9a}', '\u{1a9f}'), ('\u{1aae}', '\u{1aaf}'),
+        ('\u{1abf}', '\u{1aff}'), ('\u{1b4c}', '\u{1b4f}'), ('\u{1b7d}',
+        '\u{1b7f}'), ('\u{1bf4}', '\u{1bfb}'), ('\u{1c38}', '\u{1c3a}'),
+        ('\u{1c4a}', '\u{1c4c}'), ('\u{1c80}', '\u{1cbf}'), ('\u{1cc8}',
+        '\u{1ccf}'), ('\u{1cf7}', '\u{1cf7}'), ('\u{1cfa}', '\u{1cff}'),
+        ('\u{1df6}', '\u{1dfb}'), ('\u{1f16}', '\u{1f17}'), ('\u{1f1e}',
+        '\u{1f1f}'), ('\u{1f46}', '\u{1f47}'), ('\u{1f4e}', '\u{1f4f}'),
+        ('\u{1f58}', '\u{1f58}'), ('\u{1f5a}', '\u{1f5a}'), ('\u{1f5c}',
+        '\u{1f5c}'), ('\u{1f5e}', '\u{1f5e}'), ('\u{1f7e}', '\u{1f7f}'),
+        ('\u{1fb5}', '\u{1fb5}'), ('\u{1fc5}', '\u{1fc5}'), ('\u{1fd4}',
+        '\u{1fd5}'), ('\u{1fdc}', '\u{1fdc}'), ('\u{1ff0}', '\u{1ff1}'),
+        ('\u{1ff5}', '\u{1ff5}'), ('\u{1fff}', '\u{1fff}'), ('\u{2065}',
+        '\u{2065}'), ('\u{2072}', '\u{2073}'), ('\u{208f}', '\u{208f}'),
+        ('\u{209d}', '\u{209f}'), ('\u{20bf}', '\u{20cf}'), ('\u{20f1}',
+        '\u{20ff}'), ('\u{218c}', '\u{218f}'), ('\u{23fb}', '\u{23ff}'),
+        ('\u{2427}', '\u{243f}'), ('\u{244b}', '\u{245f}'), ('\u{2b74}',
+        '\u{2b75}'), ('\u{2b96}', '\u{2b97}'), ('\u{2bba}', '\u{2bbc}'),
+        ('\u{2bc9}', '\u{2bc9}'), ('\u{2bd2}', '\u{2beb}'), ('\u{2bf0}',
+        '\u{2bff}'), ('\u{2c2f}', '\u{2c2f}'), ('\u{2c5f}', '\u{2c5f}'),
+        ('\u{2cf4}', '\u{2cf8}'), ('\u{2d26}', '\u{2d26}'), ('\u{2d28}',
+        '\u{2d2c}'), ('\u{2d2e}', '\u{2d2f}'), ('\u{2d68}', '\u{2d6e}'),
+        ('\u{2d71}', '\u{2d7e}'), ('\u{2d97}', '\u{2d9f}'), ('\u{2da7}',
+        '\u{2da7}'), ('\u{2daf}', '\u{2daf}'), ('\u{2db7}', '\u{2db7}'),
+        ('\u{2dbf}', '\u{2dbf}'), ('\u{2dc7}', '\u{2dc7}'), ('\u{2dcf}',
+        '\u{2dcf}'), ('\u{2dd7}', '\u{2dd7}'), ('\u{2ddf}', '\u{2ddf}'),
+        ('\u{2e43}', '\u{2e7f}'), ('\u{2e9a}', '\u{2e9a}'), ('\u{2ef4}',
+        '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}', '\u{2fff}'),
+        ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'), ('\u{3100}',
+        '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}', '\u{318f}'),
+        ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'), ('\u{321f}',
+        '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{4db6}', '\u{4dbf}'),
+        ('\u{9fd6}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'), ('\u{a4c7}',
+        '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a6f8}', '\u{a6ff}'),
+        ('\u{a7ae}', '\u{a7af}'), ('\u{a7b8}', '\u{a7f6}'), ('\u{a82c}',
+        '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'),
+        ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'), ('\u{a8fe}',
+        '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}', '\u{a97f}'),
+        ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), ('\u{a9ff}',
+        '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'),
+        ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), ('\u{aaf7}',
+        '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}', '\u{ab10}'),
+        ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}',
+        '\u{ab2f}'), ('\u{ab66}', '\u{ab6f}'), ('\u{abee}', '\u{abef}'),
+        ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}',
+        '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{fa6e}', '\u{fa6f}'),
+        ('\u{fada}', '\u{faff}'), ('\u{fb07}', '\u{fb12}'), ('\u{fb18}',
+        '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'),
+        ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), ('\u{fb45}',
+        '\u{fb45}'), ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'),
+        ('\u{fd90}', '\u{fd91}'), ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}',
+        '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), ('\u{fe53}', '\u{fe53}'),
+        ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}',
+        '\u{fe75}'), ('\u{fefd}', '\u{fefe}'), ('\u{ff00}', '\u{ff00}'),
+        ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), ('\u{ffd0}',
+        '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}', '\u{ffdf}'),
+        ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fff8}'), ('\u{fffe}',
+        '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'),
+        ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'), ('\u{1004e}',
+        '\u{1004f}'), ('\u{1005e}', '\u{1007f}'), ('\u{100fb}', '\u{100ff}'),
+        ('\u{10103}', '\u{10106}'), ('\u{10134}', '\u{10136}'), ('\u{1018d}',
+        '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), ('\u{101a1}', '\u{101cf}'),
+        ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'), ('\u{102d1}',
+        '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}', '\u{1032f}'),
+        ('\u{1034b}', '\u{1034f}'), ('\u{1037b}', '\u{1037f}'), ('\u{1039e}',
+        '\u{1039e}'), ('\u{103c4}', '\u{103c7}'), ('\u{103d6}', '\u{103ff}'),
+        ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104ff}'), ('\u{10528}',
+        '\u{1052f}'), ('\u{10564}', '\u{1056e}'), ('\u{10570}', '\u{105ff}'),
+        ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'), ('\u{10768}',
+        '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'),
+        ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'), ('\u{1083d}',
+        '\u{1083e}'), ('\u{10856}', '\u{10856}'), ('\u{1089f}', '\u{108a6}'),
+        ('\u{108b0}', '\u{108df}'), ('\u{108f3}', '\u{108f3}'), ('\u{108f6}',
+        '\u{108fa}'), ('\u{1091c}', '\u{1091e}'), ('\u{1093a}', '\u{1093e}'),
+        ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'), ('\u{109d0}',
+        '\u{109d1}'), ('\u{10a04}', '\u{10a04}'), ('\u{10a07}', '\u{10a0b}'),
+        ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'), ('\u{10a34}',
+        '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}', '\u{10a4f}'),
+        ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'), ('\u{10ae7}',
+        '\u{10aea}'), ('\u{10af7}', '\u{10aff}'), ('\u{10b36}', '\u{10b38}'),
+        ('\u{10b56}', '\u{10b57}'), ('\u{10b73}', '\u{10b77}'), ('\u{10b92}',
+        '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}', '\u{10bff}'),
+        ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'), ('\u{10cf3}',
+        '\u{10cf9}'), ('\u{10d00}', '\u{10e5f}'), ('\u{10e7f}', '\u{10fff}'),
+        ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'), ('\u{110c2}',
+        '\u{110cf}'), ('\u{110e9}', '\u{110ef}'), ('\u{110fa}', '\u{110ff}'),
+        ('\u{11135}', '\u{11135}'), ('\u{11144}', '\u{1114f}'), ('\u{11177}',
+        '\u{1117f}'), ('\u{111ce}', '\u{111cf}'), ('\u{111e0}', '\u{111e0}'),
+        ('\u{111f5}', '\u{111ff}'), ('\u{11212}', '\u{11212}'), ('\u{1123e}',
+        '\u{1127f}'), ('\u{11287}', '\u{11287}'), ('\u{11289}', '\u{11289}'),
+        ('\u{1128e}', '\u{1128e}'), ('\u{1129e}', '\u{1129e}'), ('\u{112aa}',
+        '\u{112af}'), ('\u{112eb}', '\u{112ef}'), ('\u{112fa}', '\u{112ff}'),
+        ('\u{11304}', '\u{11304}'), ('\u{1130d}', '\u{1130e}'), ('\u{11311}',
+        '\u{11312}'), ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'),
+        ('\u{11334}', '\u{11334}'), ('\u{1133a}', '\u{1133b}'), ('\u{11345}',
+        '\u{11346}'), ('\u{11349}', '\u{1134a}'), ('\u{1134e}', '\u{1134f}'),
+        ('\u{11351}', '\u{11356}'), ('\u{11358}', '\u{1135c}'), ('\u{11364}',
+        '\u{11365}'), ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{1147f}'),
+        ('\u{114c8}', '\u{114cf}'), ('\u{114da}', '\u{1157f}'), ('\u{115b6}',
+        '\u{115b7}'), ('\u{115de}', '\u{115ff}'), ('\u{11645}', '\u{1164f}'),
+        ('\u{1165a}', '\u{1167f}'), ('\u{116b8}', '\u{116bf}'), ('\u{116ca}',
+        '\u{116ff}'), ('\u{1171a}', '\u{1171c}'), ('\u{1172c}', '\u{1172f}'),
+        ('\u{11740}', '\u{1189f}'), ('\u{118f3}', '\u{118fe}'), ('\u{11900}',
+        '\u{11abf}'), ('\u{11af9}', '\u{11fff}'), ('\u{1239a}', '\u{123ff}'),
+        ('\u{1246f}', '\u{1246f}'), ('\u{12475}', '\u{1247f}'), ('\u{12544}',
+        '\u{12fff}'), ('\u{1342f}', '\u{143ff}'), ('\u{14647}', '\u{167ff}'),
+        ('\u{16a39}', '\u{16a3f}'), ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}',
+        '\u{16a6d}'), ('\u{16a70}', '\u{16acf}'), ('\u{16aee}', '\u{16aef}'),
+        ('\u{16af6}', '\u{16aff}'), ('\u{16b46}', '\u{16b4f}'), ('\u{16b5a}',
+        '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'), ('\u{16b78}', '\u{16b7c}'),
+        ('\u{16b90}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'), ('\u{16f7f}',
+        '\u{16f8e}'), ('\u{16fa0}', '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'),
+        ('\u{1bc6b}', '\u{1bc6f}'), ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}',
+        '\u{1bc8f}'), ('\u{1bc9a}', '\u{1bc9b}'), ('\u{1bca4}', '\u{1cfff}'),
+        ('\u{1d0f6}', '\u{1d0ff}'), ('\u{1d127}', '\u{1d128}'), ('\u{1d1e9}',
+        '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), ('\u{1d357}', '\u{1d35f}'),
+        ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}',
+        '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'),
+        ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}',
+        '\u{1d4ba}'), ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'),
+        ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}',
+        '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', '\u{1d53a}'),
+        ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), ('\u{1d547}',
+        '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'),
+        ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1da8c}', '\u{1da9a}'), ('\u{1daa0}',
+        '\u{1daa0}'), ('\u{1dab0}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'),
+        ('\u{1e8d7}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}',
+        '\u{1ee20}'), ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'),
+        ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}',
+        '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', '\u{1ee41}'),
+        ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}',
+        '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'),
+        ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}',
+        '\u{1ee58}'), ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'),
+        ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}',
+        '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', '\u{1ee6b}'),
+        ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}',
+        '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'),
+        ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}',
+        '\u{1eeaa}'), ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'),
+        ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}',
+        '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', '\u{1f0d0}'),
+        ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), ('\u{1f12f}',
+        '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'),
+        ('\u{1f203}', '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}',
+        '\u{1f24f}'), ('\u{1f252}', '\u{1f2ff}'), ('\u{1f57a}', '\u{1f57a}'),
+        ('\u{1f5a4}', '\u{1f5a4}'), ('\u{1f6d1}', '\u{1f6df}'), ('\u{1f6ed}',
+        '\u{1f6ef}'), ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'),
+        ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}',
+        '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', '\u{1f88f}'),
+        ('\u{1f8ae}', '\u{1f90f}'), ('\u{1f919}', '\u{1f97f}'), ('\u{1f985}',
+        '\u{1f9bf}'), ('\u{1f9c1}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'),
+        ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2b81f}'), ('\u{2cea2}',
+        '\u{2f7ff}'), ('\u{2fa1e}', '\u{e0000}'), ('\u{e0002}', '\u{e001f}'),
+        ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{effff}'), ('\u{ffffe}',
+        '\u{fffff}'), ('\u{10fffe}', '\u{10ffff}')
+    ];
+
+    pub const Co_table: &'static [(char, char)] = &[
+        ('\u{e000}', '\u{f8ff}'), ('\u{f0000}', '\u{ffffd}'), ('\u{100000}',
+        '\u{10fffd}')
+    ];
+
+    pub const L_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
+        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
+        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
+        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
+        ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
+        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
+        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
+        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{5d0}', '\u{5ea}'),
+        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'), ('\u{66e}', '\u{66f}'),
+        ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}', '\u{6e6}'),
+        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
+        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
+        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'),
+        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'),
+        ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'), ('\u{840}', '\u{858}'),
+        ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'), ('\u{93d}', '\u{93d}'),
+        ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}', '\u{980}'),
+        ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
+        ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'),
+        ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'),
+        ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'),
+        ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'),
+        ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'),
+        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}', '\u{a74}'),
+        ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
+        ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
+        ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'),
+        ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
+        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
+        ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'), ('\u{b5c}', '\u{b5d}'),
+        ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}', '\u{b83}'),
+        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
+        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
+        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
+        ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
+        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c3d}'),
+        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'), ('\u{c85}', '\u{c8c}'),
+        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
+        ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'),
+        ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'),
+        ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'),
+        ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'),
+        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
+        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{e01}', '\u{e30}'),
+        ('\u{e32}', '\u{e33}'), ('\u{e40}', '\u{e46}'), ('\u{e81}', '\u{e82}'),
+        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
+        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
+        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
+        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb3}'),
+        ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
+        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
+        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
+        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
+        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
+        ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
+        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'),
+        ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
+        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
+        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
+        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
+        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
+        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
+        ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
+        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
+        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
+        '\u{16ea}'), ('\u{16f1}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
+        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
+        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
+        ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}',
+        '\u{17dc}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
+        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
+        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
+        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
+        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'),
+        ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}',
+        '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
+        ('\u{1c00}', '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}',
+        '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'),
+        ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}',
+        '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'),
+        ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
+        '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'),
+        ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}',
+        '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'),
+        ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
+        '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
+        ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
+        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'),
+        ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}',
+        '\u{2115}'), ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'),
+        ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}',
+        '\u{212d}'), ('\u{212f}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
+        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2183}',
+        '\u{2184}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'),
+        ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}',
+        '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'),
+        ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}',
+        '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
+        ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
+        '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'),
+        ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{2e2f}',
+        '\u{2e2f}'), ('\u{3005}', '\u{3006}'), ('\u{3031}', '\u{3035}'),
+        ('\u{303b}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}',
+        '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'),
+        ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}',
+        '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'),
+        ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}',
+        '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'),
+        ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), ('\u{a67f}',
+        '\u{a69d}'), ('\u{a6a0}', '\u{a6e5}'), ('\u{a717}', '\u{a71f}'),
+        ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}',
+        '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
+        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}',
+        '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'),
+        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
+        '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'),
+        ('\u{a984}', '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}',
+        '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'),
+        ('\u{aa00}', '\u{aa28}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa44}',
+        '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
+        ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}',
+        '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'),
+        ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}',
+        '\u{aaea}'), ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'),
+        ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}',
+        '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'),
+        ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abe2}'), ('\u{ac00}',
+        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
+        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
+        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb1d}'),
+        ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}',
+        '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'),
+        ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}',
+        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
+        ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}',
+        '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
+        ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
+        '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'),
+        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
+        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
+        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10280}',
+        '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'),
+        ('\u{10330}', '\u{10340}'), ('\u{10342}', '\u{10349}'), ('\u{10350}',
+        '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'),
+        ('\u{103c8}', '\u{103cf}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}',
+        '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'),
+        ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}',
+        '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'),
+        ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}',
+        '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'),
+        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
+        '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'),
+        ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}',
+        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
+        ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}',
+        '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'),
+        ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}',
+        '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'),
+        ('\u{10cc0}', '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}',
+        '\u{110af}'), ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'),
+        ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}',
+        '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'),
+        ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
+        '\u{1122b}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'),
+        ('\u{1128a}', '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}',
+        '\u{112a8}'), ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'),
+        ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}',
+        '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'),
+        ('\u{1133d}', '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}',
+        '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'),
+        ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}',
+        '\u{115db}'), ('\u{11600}', '\u{1162f}'), ('\u{11644}', '\u{11644}'),
+        ('\u{11680}', '\u{116aa}'), ('\u{11700}', '\u{11719}'), ('\u{118a0}',
+        '\u{118df}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'),
+        ('\u{12000}', '\u{12399}'), ('\u{12480}', '\u{12543}'), ('\u{13000}',
+        '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'),
+        ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}',
+        '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'),
+        ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}',
+        '\u{16f50}'), ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'),
+        ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}',
+        '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}', '\u{1d454}'),
+        ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}',
+        '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'),
+        ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
+        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'),
+        ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}',
+        '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
+        ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}',
+        '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'),
+        ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}',
+        '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'),
+        ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}',
+        '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}', '\u{1e8c4}'),
+        ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}',
+        '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'),
+        ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}',
+        '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'),
+        ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}',
+        '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'),
+        ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}',
+        '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'),
+        ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}',
+        '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'),
+        ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}',
+        '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'),
+        ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}',
+        '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'),
+        ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}',
+        '\u{2fa1d}')
+    ];
+
+    pub const LC_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'),
+        ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'),
+        ('\u{1bc}', '\u{1bf}'), ('\u{1c4}', '\u{293}'), ('\u{295}', '\u{2af}'),
+        ('\u{370}', '\u{373}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
+        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
+        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
+        ('\u{561}', '\u{587}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
+        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{13a0}', '\u{13f5}'),
+        ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', '\u{1d2b}'), ('\u{1d6b}',
+        '\u{1d77}'), ('\u{1d79}', '\u{1d9a}'), ('\u{1e00}', '\u{1f15}'),
+        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
+        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
+        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
+        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
+        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
+        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
+        '\u{1ffc}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'),
+        ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2119}',
+        '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'),
+        ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}',
+        '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
+        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2183}',
+        '\u{2184}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'),
+        ('\u{2c60}', '\u{2c7b}'), ('\u{2c7e}', '\u{2ce4}'), ('\u{2ceb}',
+        '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'),
+        ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{a640}',
+        '\u{a66d}'), ('\u{a680}', '\u{a69b}'), ('\u{a722}', '\u{a76f}'),
+        ('\u{a771}', '\u{a787}'), ('\u{a78b}', '\u{a78e}'), ('\u{a790}',
+        '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7fa}', '\u{a7fa}'),
+        ('\u{ab30}', '\u{ab5a}'), ('\u{ab60}', '\u{ab65}'), ('\u{ab70}',
+        '\u{abbf}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'),
+        ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10400}',
+        '\u{1044f}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'),
+        ('\u{118a0}', '\u{118df}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}',
+        '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
+        ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}',
+        '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'),
+        ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}',
+        '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'),
+        ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}',
+        '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'),
+        ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}',
+        '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'),
+        ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}',
+        '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'),
+        ('\u{1d7c4}', '\u{1d7cb}')
+    ];
+
+    pub const Ll_table: &'static [(char, char)] = &[
+        ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'), ('\u{df}', '\u{f6}'),
+        ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'),
+        ('\u{105}', '\u{105}'), ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'),
+        ('\u{10b}', '\u{10b}'), ('\u{10d}', '\u{10d}'), ('\u{10f}', '\u{10f}'),
+        ('\u{111}', '\u{111}'), ('\u{113}', '\u{113}'), ('\u{115}', '\u{115}'),
+        ('\u{117}', '\u{117}'), ('\u{119}', '\u{119}'), ('\u{11b}', '\u{11b}'),
+        ('\u{11d}', '\u{11d}'), ('\u{11f}', '\u{11f}'), ('\u{121}', '\u{121}'),
+        ('\u{123}', '\u{123}'), ('\u{125}', '\u{125}'), ('\u{127}', '\u{127}'),
+        ('\u{129}', '\u{129}'), ('\u{12b}', '\u{12b}'), ('\u{12d}', '\u{12d}'),
+        ('\u{12f}', '\u{12f}'), ('\u{131}', '\u{131}'), ('\u{133}', '\u{133}'),
+        ('\u{135}', '\u{135}'), ('\u{137}', '\u{138}'), ('\u{13a}', '\u{13a}'),
+        ('\u{13c}', '\u{13c}'), ('\u{13e}', '\u{13e}'), ('\u{140}', '\u{140}'),
+        ('\u{142}', '\u{142}'), ('\u{144}', '\u{144}'), ('\u{146}', '\u{146}'),
+        ('\u{148}', '\u{149}'), ('\u{14b}', '\u{14b}'), ('\u{14d}', '\u{14d}'),
+        ('\u{14f}', '\u{14f}'), ('\u{151}', '\u{151}'), ('\u{153}', '\u{153}'),
+        ('\u{155}', '\u{155}'), ('\u{157}', '\u{157}'), ('\u{159}', '\u{159}'),
+        ('\u{15b}', '\u{15b}'), ('\u{15d}', '\u{15d}'), ('\u{15f}', '\u{15f}'),
+        ('\u{161}', '\u{161}'), ('\u{163}', '\u{163}'), ('\u{165}', '\u{165}'),
+        ('\u{167}', '\u{167}'), ('\u{169}', '\u{169}'), ('\u{16b}', '\u{16b}'),
+        ('\u{16d}', '\u{16d}'), ('\u{16f}', '\u{16f}'), ('\u{171}', '\u{171}'),
+        ('\u{173}', '\u{173}'), ('\u{175}', '\u{175}'), ('\u{177}', '\u{177}'),
+        ('\u{17a}', '\u{17a}'), ('\u{17c}', '\u{17c}'), ('\u{17e}', '\u{180}'),
+        ('\u{183}', '\u{183}'), ('\u{185}', '\u{185}'), ('\u{188}', '\u{188}'),
+        ('\u{18c}', '\u{18d}'), ('\u{192}', '\u{192}'), ('\u{195}', '\u{195}'),
+        ('\u{199}', '\u{19b}'), ('\u{19e}', '\u{19e}'), ('\u{1a1}', '\u{1a1}'),
+        ('\u{1a3}', '\u{1a3}'), ('\u{1a5}', '\u{1a5}'), ('\u{1a8}', '\u{1a8}'),
+        ('\u{1aa}', '\u{1ab}'), ('\u{1ad}', '\u{1ad}'), ('\u{1b0}', '\u{1b0}'),
+        ('\u{1b4}', '\u{1b4}'), ('\u{1b6}', '\u{1b6}'), ('\u{1b9}', '\u{1ba}'),
+        ('\u{1bd}', '\u{1bf}'), ('\u{1c6}', '\u{1c6}'), ('\u{1c9}', '\u{1c9}'),
+        ('\u{1cc}', '\u{1cc}'), ('\u{1ce}', '\u{1ce}'), ('\u{1d0}', '\u{1d0}'),
+        ('\u{1d2}', '\u{1d2}'), ('\u{1d4}', '\u{1d4}'), ('\u{1d6}', '\u{1d6}'),
+        ('\u{1d8}', '\u{1d8}'), ('\u{1da}', '\u{1da}'), ('\u{1dc}', '\u{1dd}'),
+        ('\u{1df}', '\u{1df}'), ('\u{1e1}', '\u{1e1}'), ('\u{1e3}', '\u{1e3}'),
+        ('\u{1e5}', '\u{1e5}'), ('\u{1e7}', '\u{1e7}'), ('\u{1e9}', '\u{1e9}'),
+        ('\u{1eb}', '\u{1eb}'), ('\u{1ed}', '\u{1ed}'), ('\u{1ef}', '\u{1f0}'),
+        ('\u{1f3}', '\u{1f3}'), ('\u{1f5}', '\u{1f5}'), ('\u{1f9}', '\u{1f9}'),
+        ('\u{1fb}', '\u{1fb}'), ('\u{1fd}', '\u{1fd}'), ('\u{1ff}', '\u{1ff}'),
+        ('\u{201}', '\u{201}'), ('\u{203}', '\u{203}'), ('\u{205}', '\u{205}'),
+        ('\u{207}', '\u{207}'), ('\u{209}', '\u{209}'), ('\u{20b}', '\u{20b}'),
+        ('\u{20d}', '\u{20d}'), ('\u{20f}', '\u{20f}'), ('\u{211}', '\u{211}'),
+        ('\u{213}', '\u{213}'), ('\u{215}', '\u{215}'), ('\u{217}', '\u{217}'),
+        ('\u{219}', '\u{219}'), ('\u{21b}', '\u{21b}'), ('\u{21d}', '\u{21d}'),
+        ('\u{21f}', '\u{21f}'), ('\u{221}', '\u{221}'), ('\u{223}', '\u{223}'),
+        ('\u{225}', '\u{225}'), ('\u{227}', '\u{227}'), ('\u{229}', '\u{229}'),
+        ('\u{22b}', '\u{22b}'), ('\u{22d}', '\u{22d}'), ('\u{22f}', '\u{22f}'),
+        ('\u{231}', '\u{231}'), ('\u{233}', '\u{239}'), ('\u{23c}', '\u{23c}'),
+        ('\u{23f}', '\u{240}'), ('\u{242}', '\u{242}'), ('\u{247}', '\u{247}'),
+        ('\u{249}', '\u{249}'), ('\u{24b}', '\u{24b}'), ('\u{24d}', '\u{24d}'),
+        ('\u{24f}', '\u{293}'), ('\u{295}', '\u{2af}'), ('\u{371}', '\u{371}'),
+        ('\u{373}', '\u{373}'), ('\u{377}', '\u{377}'), ('\u{37b}', '\u{37d}'),
+        ('\u{390}', '\u{390}'), ('\u{3ac}', '\u{3ce}'), ('\u{3d0}', '\u{3d1}'),
+        ('\u{3d5}', '\u{3d7}'), ('\u{3d9}', '\u{3d9}'), ('\u{3db}', '\u{3db}'),
+        ('\u{3dd}', '\u{3dd}'), ('\u{3df}', '\u{3df}'), ('\u{3e1}', '\u{3e1}'),
+        ('\u{3e3}', '\u{3e3}'), ('\u{3e5}', '\u{3e5}'), ('\u{3e7}', '\u{3e7}'),
+        ('\u{3e9}', '\u{3e9}'), ('\u{3eb}', '\u{3eb}'), ('\u{3ed}', '\u{3ed}'),
+        ('\u{3ef}', '\u{3f3}'), ('\u{3f5}', '\u{3f5}'), ('\u{3f8}', '\u{3f8}'),
+        ('\u{3fb}', '\u{3fc}'), ('\u{430}', '\u{45f}'), ('\u{461}', '\u{461}'),
+        ('\u{463}', '\u{463}'), ('\u{465}', '\u{465}'), ('\u{467}', '\u{467}'),
+        ('\u{469}', '\u{469}'), ('\u{46b}', '\u{46b}'), ('\u{46d}', '\u{46d}'),
+        ('\u{46f}', '\u{46f}'), ('\u{471}', '\u{471}'), ('\u{473}', '\u{473}'),
+        ('\u{475}', '\u{475}'), ('\u{477}', '\u{477}'), ('\u{479}', '\u{479}'),
+        ('\u{47b}', '\u{47b}'), ('\u{47d}', '\u{47d}'), ('\u{47f}', '\u{47f}'),
+        ('\u{481}', '\u{481}'), ('\u{48b}', '\u{48b}'), ('\u{48d}', '\u{48d}'),
+        ('\u{48f}', '\u{48f}'), ('\u{491}', '\u{491}'), ('\u{493}', '\u{493}'),
+        ('\u{495}', '\u{495}'), ('\u{497}', '\u{497}'), ('\u{499}', '\u{499}'),
+        ('\u{49b}', '\u{49b}'), ('\u{49d}', '\u{49d}'), ('\u{49f}', '\u{49f}'),
+        ('\u{4a1}', '\u{4a1}'), ('\u{4a3}', '\u{4a3}'), ('\u{4a5}', '\u{4a5}'),
+        ('\u{4a7}', '\u{4a7}'), ('\u{4a9}', '\u{4a9}'), ('\u{4ab}', '\u{4ab}'),
+        ('\u{4ad}', '\u{4ad}'), ('\u{4af}', '\u{4af}'), ('\u{4b1}', '\u{4b1}'),
+        ('\u{4b3}', '\u{4b3}'), ('\u{4b5}', '\u{4b5}'), ('\u{4b7}', '\u{4b7}'),
+        ('\u{4b9}', '\u{4b9}'), ('\u{4bb}', '\u{4bb}'), ('\u{4bd}', '\u{4bd}'),
+        ('\u{4bf}', '\u{4bf}'), ('\u{4c2}', '\u{4c2}'), ('\u{4c4}', '\u{4c4}'),
+        ('\u{4c6}', '\u{4c6}'), ('\u{4c8}', '\u{4c8}'), ('\u{4ca}', '\u{4ca}'),
+        ('\u{4cc}', '\u{4cc}'), ('\u{4ce}', '\u{4cf}'), ('\u{4d1}', '\u{4d1}'),
+        ('\u{4d3}', '\u{4d3}'), ('\u{4d5}', '\u{4d5}'), ('\u{4d7}', '\u{4d7}'),
+        ('\u{4d9}', '\u{4d9}'), ('\u{4db}', '\u{4db}'), ('\u{4dd}', '\u{4dd}'),
+        ('\u{4df}', '\u{4df}'), ('\u{4e1}', '\u{4e1}'), ('\u{4e3}', '\u{4e3}'),
+        ('\u{4e5}', '\u{4e5}'), ('\u{4e7}', '\u{4e7}'), ('\u{4e9}', '\u{4e9}'),
+        ('\u{4eb}', '\u{4eb}'), ('\u{4ed}', '\u{4ed}'), ('\u{4ef}', '\u{4ef}'),
+        ('\u{4f1}', '\u{4f1}'), ('\u{4f3}', '\u{4f3}'), ('\u{4f5}', '\u{4f5}'),
+        ('\u{4f7}', '\u{4f7}'), ('\u{4f9}', '\u{4f9}'), ('\u{4fb}', '\u{4fb}'),
+        ('\u{4fd}', '\u{4fd}'), ('\u{4ff}', '\u{4ff}'), ('\u{501}', '\u{501}'),
+        ('\u{503}', '\u{503}'), ('\u{505}', '\u{505}'), ('\u{507}', '\u{507}'),
+        ('\u{509}', '\u{509}'), ('\u{50b}', '\u{50b}'), ('\u{50d}', '\u{50d}'),
+        ('\u{50f}', '\u{50f}'), ('\u{511}', '\u{511}'), ('\u{513}', '\u{513}'),
+        ('\u{515}', '\u{515}'), ('\u{517}', '\u{517}'), ('\u{519}', '\u{519}'),
+        ('\u{51b}', '\u{51b}'), ('\u{51d}', '\u{51d}'), ('\u{51f}', '\u{51f}'),
+        ('\u{521}', '\u{521}'), ('\u{523}', '\u{523}'), ('\u{525}', '\u{525}'),
+        ('\u{527}', '\u{527}'), ('\u{529}', '\u{529}'), ('\u{52b}', '\u{52b}'),
+        ('\u{52d}', '\u{52d}'), ('\u{52f}', '\u{52f}'), ('\u{561}', '\u{587}'),
+        ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', '\u{1d2b}'), ('\u{1d6b}',
+        '\u{1d77}'), ('\u{1d79}', '\u{1d9a}'), ('\u{1e01}', '\u{1e01}'),
+        ('\u{1e03}', '\u{1e03}'), ('\u{1e05}', '\u{1e05}'), ('\u{1e07}',
+        '\u{1e07}'), ('\u{1e09}', '\u{1e09}'), ('\u{1e0b}', '\u{1e0b}'),
+        ('\u{1e0d}', '\u{1e0d}'), ('\u{1e0f}', '\u{1e0f}'), ('\u{1e11}',
+        '\u{1e11}'), ('\u{1e13}', '\u{1e13}'), ('\u{1e15}', '\u{1e15}'),
+        ('\u{1e17}', '\u{1e17}'), ('\u{1e19}', '\u{1e19}'), ('\u{1e1b}',
+        '\u{1e1b}'), ('\u{1e1d}', '\u{1e1d}'), ('\u{1e1f}', '\u{1e1f}'),
+        ('\u{1e21}', '\u{1e21}'), ('\u{1e23}', '\u{1e23}'), ('\u{1e25}',
+        '\u{1e25}'), ('\u{1e27}', '\u{1e27}'), ('\u{1e29}', '\u{1e29}'),
+        ('\u{1e2b}', '\u{1e2b}'), ('\u{1e2d}', '\u{1e2d}'), ('\u{1e2f}',
+        '\u{1e2f}'), ('\u{1e31}', '\u{1e31}'), ('\u{1e33}', '\u{1e33}'),
+        ('\u{1e35}', '\u{1e35}'), ('\u{1e37}', '\u{1e37}'), ('\u{1e39}',
+        '\u{1e39}'), ('\u{1e3b}', '\u{1e3b}'), ('\u{1e3d}', '\u{1e3d}'),
+        ('\u{1e3f}', '\u{1e3f}'), ('\u{1e41}', '\u{1e41}'), ('\u{1e43}',
+        '\u{1e43}'), ('\u{1e45}', '\u{1e45}'), ('\u{1e47}', '\u{1e47}'),
+        ('\u{1e49}', '\u{1e49}'), ('\u{1e4b}', '\u{1e4b}'), ('\u{1e4d}',
+        '\u{1e4d}'), ('\u{1e4f}', '\u{1e4f}'), ('\u{1e51}', '\u{1e51}'),
+        ('\u{1e53}', '\u{1e53}'), ('\u{1e55}', '\u{1e55}'), ('\u{1e57}',
+        '\u{1e57}'), ('\u{1e59}', '\u{1e59}'), ('\u{1e5b}', '\u{1e5b}'),
+        ('\u{1e5d}', '\u{1e5d}'), ('\u{1e5f}', '\u{1e5f}'), ('\u{1e61}',
+        '\u{1e61}'), ('\u{1e63}', '\u{1e63}'), ('\u{1e65}', '\u{1e65}'),
+        ('\u{1e67}', '\u{1e67}'), ('\u{1e69}', '\u{1e69}'), ('\u{1e6b}',
+        '\u{1e6b}'), ('\u{1e6d}', '\u{1e6d}'), ('\u{1e6f}', '\u{1e6f}'),
+        ('\u{1e71}', '\u{1e71}'), ('\u{1e73}', '\u{1e73}'), ('\u{1e75}',
+        '\u{1e75}'), ('\u{1e77}', '\u{1e77}'), ('\u{1e79}', '\u{1e79}'),
+        ('\u{1e7b}', '\u{1e7b}'), ('\u{1e7d}', '\u{1e7d}'), ('\u{1e7f}',
+        '\u{1e7f}'), ('\u{1e81}', '\u{1e81}'), ('\u{1e83}', '\u{1e83}'),
+        ('\u{1e85}', '\u{1e85}'), ('\u{1e87}', '\u{1e87}'), ('\u{1e89}',
+        '\u{1e89}'), ('\u{1e8b}', '\u{1e8b}'), ('\u{1e8d}', '\u{1e8d}'),
+        ('\u{1e8f}', '\u{1e8f}'), ('\u{1e91}', '\u{1e91}'), ('\u{1e93}',
+        '\u{1e93}'), ('\u{1e95}', '\u{1e9d}'), ('\u{1e9f}', '\u{1e9f}'),
+        ('\u{1ea1}', '\u{1ea1}'), ('\u{1ea3}', '\u{1ea3}'), ('\u{1ea5}',
+        '\u{1ea5}'), ('\u{1ea7}', '\u{1ea7}'), ('\u{1ea9}', '\u{1ea9}'),
+        ('\u{1eab}', '\u{1eab}'), ('\u{1ead}', '\u{1ead}'), ('\u{1eaf}',
+        '\u{1eaf}'), ('\u{1eb1}', '\u{1eb1}'), ('\u{1eb3}', '\u{1eb3}'),
+        ('\u{1eb5}', '\u{1eb5}'), ('\u{1eb7}', '\u{1eb7}'), ('\u{1eb9}',
+        '\u{1eb9}'), ('\u{1ebb}', '\u{1ebb}'), ('\u{1ebd}', '\u{1ebd}'),
+        ('\u{1ebf}', '\u{1ebf}'), ('\u{1ec1}', '\u{1ec1}'), ('\u{1ec3}',
+        '\u{1ec3}'), ('\u{1ec5}', '\u{1ec5}'), ('\u{1ec7}', '\u{1ec7}'),
+        ('\u{1ec9}', '\u{1ec9}'), ('\u{1ecb}', '\u{1ecb}'), ('\u{1ecd}',
+        '\u{1ecd}'), ('\u{1ecf}', '\u{1ecf}'), ('\u{1ed1}', '\u{1ed1}'),
+        ('\u{1ed3}', '\u{1ed3}'), ('\u{1ed5}', '\u{1ed5}'), ('\u{1ed7}',
+        '\u{1ed7}'), ('\u{1ed9}', '\u{1ed9}'), ('\u{1edb}', '\u{1edb}'),
+        ('\u{1edd}', '\u{1edd}'), ('\u{1edf}', '\u{1edf}'), ('\u{1ee1}',
+        '\u{1ee1}'), ('\u{1ee3}', '\u{1ee3}'), ('\u{1ee5}', '\u{1ee5}'),
+        ('\u{1ee7}', '\u{1ee7}'), ('\u{1ee9}', '\u{1ee9}'), ('\u{1eeb}',
+        '\u{1eeb}'), ('\u{1eed}', '\u{1eed}'), ('\u{1eef}', '\u{1eef}'),
+        ('\u{1ef1}', '\u{1ef1}'), ('\u{1ef3}', '\u{1ef3}'), ('\u{1ef5}',
+        '\u{1ef5}'), ('\u{1ef7}', '\u{1ef7}'), ('\u{1ef9}', '\u{1ef9}'),
+        ('\u{1efb}', '\u{1efb}'), ('\u{1efd}', '\u{1efd}'), ('\u{1eff}',
+        '\u{1f07}'), ('\u{1f10}', '\u{1f15}'), ('\u{1f20}', '\u{1f27}'),
+        ('\u{1f30}', '\u{1f37}'), ('\u{1f40}', '\u{1f45}'), ('\u{1f50}',
+        '\u{1f57}'), ('\u{1f60}', '\u{1f67}'), ('\u{1f70}', '\u{1f7d}'),
+        ('\u{1f80}', '\u{1f87}'), ('\u{1f90}', '\u{1f97}'), ('\u{1fa0}',
+        '\u{1fa7}'), ('\u{1fb0}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fb7}'),
+        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fc7}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fd7}'),
+        ('\u{1fe0}', '\u{1fe7}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
+        '\u{1ff7}'), ('\u{210a}', '\u{210a}'), ('\u{210e}', '\u{210f}'),
+        ('\u{2113}', '\u{2113}'), ('\u{212f}', '\u{212f}'), ('\u{2134}',
+        '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213d}'),
+        ('\u{2146}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2184}',
+        '\u{2184}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c61}', '\u{2c61}'),
+        ('\u{2c65}', '\u{2c66}'), ('\u{2c68}', '\u{2c68}'), ('\u{2c6a}',
+        '\u{2c6a}'), ('\u{2c6c}', '\u{2c6c}'), ('\u{2c71}', '\u{2c71}'),
+        ('\u{2c73}', '\u{2c74}'), ('\u{2c76}', '\u{2c7b}'), ('\u{2c81}',
+        '\u{2c81}'), ('\u{2c83}', '\u{2c83}'), ('\u{2c85}', '\u{2c85}'),
+        ('\u{2c87}', '\u{2c87}'), ('\u{2c89}', '\u{2c89}'), ('\u{2c8b}',
+        '\u{2c8b}'), ('\u{2c8d}', '\u{2c8d}'), ('\u{2c8f}', '\u{2c8f}'),
+        ('\u{2c91}', '\u{2c91}'), ('\u{2c93}', '\u{2c93}'), ('\u{2c95}',
+        '\u{2c95}'), ('\u{2c97}', '\u{2c97}'), ('\u{2c99}', '\u{2c99}'),
+        ('\u{2c9b}', '\u{2c9b}'), ('\u{2c9d}', '\u{2c9d}'), ('\u{2c9f}',
+        '\u{2c9f}'), ('\u{2ca1}', '\u{2ca1}'), ('\u{2ca3}', '\u{2ca3}'),
+        ('\u{2ca5}', '\u{2ca5}'), ('\u{2ca7}', '\u{2ca7}'), ('\u{2ca9}',
+        '\u{2ca9}'), ('\u{2cab}', '\u{2cab}'), ('\u{2cad}', '\u{2cad}'),
+        ('\u{2caf}', '\u{2caf}'), ('\u{2cb1}', '\u{2cb1}'), ('\u{2cb3}',
+        '\u{2cb3}'), ('\u{2cb5}', '\u{2cb5}'), ('\u{2cb7}', '\u{2cb7}'),
+        ('\u{2cb9}', '\u{2cb9}'), ('\u{2cbb}', '\u{2cbb}'), ('\u{2cbd}',
+        '\u{2cbd}'), ('\u{2cbf}', '\u{2cbf}'), ('\u{2cc1}', '\u{2cc1}'),
+        ('\u{2cc3}', '\u{2cc3}'), ('\u{2cc5}', '\u{2cc5}'), ('\u{2cc7}',
+        '\u{2cc7}'), ('\u{2cc9}', '\u{2cc9}'), ('\u{2ccb}', '\u{2ccb}'),
+        ('\u{2ccd}', '\u{2ccd}'), ('\u{2ccf}', '\u{2ccf}'), ('\u{2cd1}',
+        '\u{2cd1}'), ('\u{2cd3}', '\u{2cd3}'), ('\u{2cd5}', '\u{2cd5}'),
+        ('\u{2cd7}', '\u{2cd7}'), ('\u{2cd9}', '\u{2cd9}'), ('\u{2cdb}',
+        '\u{2cdb}'), ('\u{2cdd}', '\u{2cdd}'), ('\u{2cdf}', '\u{2cdf}'),
+        ('\u{2ce1}', '\u{2ce1}'), ('\u{2ce3}', '\u{2ce4}'), ('\u{2cec}',
+        '\u{2cec}'), ('\u{2cee}', '\u{2cee}'), ('\u{2cf3}', '\u{2cf3}'),
+        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
+        '\u{2d2d}'), ('\u{a641}', '\u{a641}'), ('\u{a643}', '\u{a643}'),
+        ('\u{a645}', '\u{a645}'), ('\u{a647}', '\u{a647}'), ('\u{a649}',
+        '\u{a649}'), ('\u{a64b}', '\u{a64b}'), ('\u{a64d}', '\u{a64d}'),
+        ('\u{a64f}', '\u{a64f}'), ('\u{a651}', '\u{a651}'), ('\u{a653}',
+        '\u{a653}'), ('\u{a655}', '\u{a655}'), ('\u{a657}', '\u{a657}'),
+        ('\u{a659}', '\u{a659}'), ('\u{a65b}', '\u{a65b}'), ('\u{a65d}',
+        '\u{a65d}'), ('\u{a65f}', '\u{a65f}'), ('\u{a661}', '\u{a661}'),
+        ('\u{a663}', '\u{a663}'), ('\u{a665}', '\u{a665}'), ('\u{a667}',
+        '\u{a667}'), ('\u{a669}', '\u{a669}'), ('\u{a66b}', '\u{a66b}'),
+        ('\u{a66d}', '\u{a66d}'), ('\u{a681}', '\u{a681}'), ('\u{a683}',
+        '\u{a683}'), ('\u{a685}', '\u{a685}'), ('\u{a687}', '\u{a687}'),
+        ('\u{a689}', '\u{a689}'), ('\u{a68b}', '\u{a68b}'), ('\u{a68d}',
+        '\u{a68d}'), ('\u{a68f}', '\u{a68f}'), ('\u{a691}', '\u{a691}'),
+        ('\u{a693}', '\u{a693}'), ('\u{a695}', '\u{a695}'), ('\u{a697}',
+        '\u{a697}'), ('\u{a699}', '\u{a699}'), ('\u{a69b}', '\u{a69b}'),
+        ('\u{a723}', '\u{a723}'), ('\u{a725}', '\u{a725}'), ('\u{a727}',
+        '\u{a727}'), ('\u{a729}', '\u{a729}'), ('\u{a72b}', '\u{a72b}'),
+        ('\u{a72d}', '\u{a72d}'), ('\u{a72f}', '\u{a731}'), ('\u{a733}',
+        '\u{a733}'), ('\u{a735}', '\u{a735}'), ('\u{a737}', '\u{a737}'),
+        ('\u{a739}', '\u{a739}'), ('\u{a73b}', '\u{a73b}'), ('\u{a73d}',
+        '\u{a73d}'), ('\u{a73f}', '\u{a73f}'), ('\u{a741}', '\u{a741}'),
+        ('\u{a743}', '\u{a743}'), ('\u{a745}', '\u{a745}'), ('\u{a747}',
+        '\u{a747}'), ('\u{a749}', '\u{a749}'), ('\u{a74b}', '\u{a74b}'),
+        ('\u{a74d}', '\u{a74d}'), ('\u{a74f}', '\u{a74f}'), ('\u{a751}',
+        '\u{a751}'), ('\u{a753}', '\u{a753}'), ('\u{a755}', '\u{a755}'),
+        ('\u{a757}', '\u{a757}'), ('\u{a759}', '\u{a759}'), ('\u{a75b}',
+        '\u{a75b}'), ('\u{a75d}', '\u{a75d}'), ('\u{a75f}', '\u{a75f}'),
+        ('\u{a761}', '\u{a761}'), ('\u{a763}', '\u{a763}'), ('\u{a765}',
+        '\u{a765}'), ('\u{a767}', '\u{a767}'), ('\u{a769}', '\u{a769}'),
+        ('\u{a76b}', '\u{a76b}'), ('\u{a76d}', '\u{a76d}'), ('\u{a76f}',
+        '\u{a76f}'), ('\u{a771}', '\u{a778}'), ('\u{a77a}', '\u{a77a}'),
+        ('\u{a77c}', '\u{a77c}'), ('\u{a77f}', '\u{a77f}'), ('\u{a781}',
+        '\u{a781}'), ('\u{a783}', '\u{a783}'), ('\u{a785}', '\u{a785}'),
+        ('\u{a787}', '\u{a787}'), ('\u{a78c}', '\u{a78c}'), ('\u{a78e}',
+        '\u{a78e}'), ('\u{a791}', '\u{a791}'), ('\u{a793}', '\u{a795}'),
+        ('\u{a797}', '\u{a797}'), ('\u{a799}', '\u{a799}'), ('\u{a79b}',
+        '\u{a79b}'), ('\u{a79d}', '\u{a79d}'), ('\u{a79f}', '\u{a79f}'),
+        ('\u{a7a1}', '\u{a7a1}'), ('\u{a7a3}', '\u{a7a3}'), ('\u{a7a5}',
+        '\u{a7a5}'), ('\u{a7a7}', '\u{a7a7}'), ('\u{a7a9}', '\u{a7a9}'),
+        ('\u{a7b5}', '\u{a7b5}'), ('\u{a7b7}', '\u{a7b7}'), ('\u{a7fa}',
+        '\u{a7fa}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab60}', '\u{ab65}'),
+        ('\u{ab70}', '\u{abbf}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}',
+        '\u{fb17}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10428}', '\u{1044f}'),
+        ('\u{10cc0}', '\u{10cf2}'), ('\u{118c0}', '\u{118df}'), ('\u{1d41a}',
+        '\u{1d433}'), ('\u{1d44e}', '\u{1d454}'), ('\u{1d456}', '\u{1d467}'),
+        ('\u{1d482}', '\u{1d49b}'), ('\u{1d4b6}', '\u{1d4b9}'), ('\u{1d4bb}',
+        '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d4cf}'),
+        ('\u{1d4ea}', '\u{1d503}'), ('\u{1d51e}', '\u{1d537}'), ('\u{1d552}',
+        '\u{1d56b}'), ('\u{1d586}', '\u{1d59f}'), ('\u{1d5ba}', '\u{1d5d3}'),
+        ('\u{1d5ee}', '\u{1d607}'), ('\u{1d622}', '\u{1d63b}'), ('\u{1d656}',
+        '\u{1d66f}'), ('\u{1d68a}', '\u{1d6a5}'), ('\u{1d6c2}', '\u{1d6da}'),
+        ('\u{1d6dc}', '\u{1d6e1}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}',
+        '\u{1d71b}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d755}'),
+        ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d78f}'), ('\u{1d7aa}',
+        '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7c9}'), ('\u{1d7cb}', '\u{1d7cb}')
+    ];
+
+    pub const Lm_table: &'static [(char, char)] = &[
+        ('\u{2b0}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'),
+        ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{374}', '\u{374}'),
+        ('\u{37a}', '\u{37a}'), ('\u{559}', '\u{559}'), ('\u{640}', '\u{640}'),
+        ('\u{6e5}', '\u{6e6}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
+        ('\u{81a}', '\u{81a}'), ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'),
+        ('\u{971}', '\u{971}'), ('\u{e46}', '\u{e46}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{10fc}', '\u{10fc}'), ('\u{17d7}', '\u{17d7}'), ('\u{1843}',
+        '\u{1843}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1c78}', '\u{1c7d}'),
+        ('\u{1d2c}', '\u{1d6a}'), ('\u{1d78}', '\u{1d78}'), ('\u{1d9b}',
+        '\u{1dbf}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
+        ('\u{2090}', '\u{209c}'), ('\u{2c7c}', '\u{2c7d}'), ('\u{2d6f}',
+        '\u{2d6f}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}', '\u{3005}'),
+        ('\u{3031}', '\u{3035}'), ('\u{303b}', '\u{303b}'), ('\u{309d}',
+        '\u{309e}'), ('\u{30fc}', '\u{30fe}'), ('\u{a015}', '\u{a015}'),
+        ('\u{a4f8}', '\u{a4fd}'), ('\u{a60c}', '\u{a60c}'), ('\u{a67f}',
+        '\u{a67f}'), ('\u{a69c}', '\u{a69d}'), ('\u{a717}', '\u{a71f}'),
+        ('\u{a770}', '\u{a770}'), ('\u{a788}', '\u{a788}'), ('\u{a7f8}',
+        '\u{a7f9}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e6}', '\u{a9e6}'),
+        ('\u{aa70}', '\u{aa70}'), ('\u{aadd}', '\u{aadd}'), ('\u{aaf3}',
+        '\u{aaf4}'), ('\u{ab5c}', '\u{ab5f}'), ('\u{ff70}', '\u{ff70}'),
+        ('\u{ff9e}', '\u{ff9f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16f93}',
+        '\u{16f9f}')
+    ];
+
+    pub const Lo_table: &'static [(char, char)] = &[
+        ('\u{aa}', '\u{aa}'), ('\u{ba}', '\u{ba}'), ('\u{1bb}', '\u{1bb}'),
+        ('\u{1c0}', '\u{1c3}'), ('\u{294}', '\u{294}'), ('\u{5d0}', '\u{5ea}'),
+        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'),
+        ('\u{66e}', '\u{66f}'), ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'),
+        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
+        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
+        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{800}', '\u{815}'),
+        ('\u{840}', '\u{858}'), ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'),
+        ('\u{93d}', '\u{93d}'), ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'),
+        ('\u{972}', '\u{980}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
+        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
+        ('\u{9b6}', '\u{9b9}'), ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'),
+        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'),
+        ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'),
+        ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'),
+        ('\u{a38}', '\u{a39}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
+        ('\u{a72}', '\u{a74}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
+        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
+        ('\u{ab5}', '\u{ab9}'), ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'),
+        ('\u{ae0}', '\u{ae1}'), ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'),
+        ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'),
+        ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'),
+        ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'),
+        ('\u{b83}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
+        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
+        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
+        ('\u{bae}', '\u{bb9}'), ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'),
+        ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'),
+        ('\u{c3d}', '\u{c3d}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'),
+        ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'),
+        ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'),
+        ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'),
+        ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'),
+        ('\u{d3d}', '\u{d3d}'), ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'),
+        ('\u{d7a}', '\u{d7f}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'),
+        ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'),
+        ('\u{e01}', '\u{e30}'), ('\u{e32}', '\u{e33}'), ('\u{e40}', '\u{e45}'),
+        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
+        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
+        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
+        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'),
+        ('\u{eb2}', '\u{eb3}'), ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'),
+        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
+        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
+        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
+        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
+        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
+        ('\u{108e}', '\u{108e}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fd}',
+        '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'),
+        ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}',
+        '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'),
+        ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
+        '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'),
+        ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}',
+        '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{1401}', '\u{166c}'),
+        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
+        '\u{16ea}'), ('\u{16f1}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
+        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
+        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
+        ('\u{1780}', '\u{17b3}'), ('\u{17dc}', '\u{17dc}'), ('\u{1820}',
+        '\u{1842}'), ('\u{1844}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
+        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
+        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
+        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
+        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1b05}', '\u{1b33}'),
+        ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}', '\u{1ba0}'), ('\u{1bae}',
+        '\u{1baf}'), ('\u{1bba}', '\u{1be5}'), ('\u{1c00}', '\u{1c23}'),
+        ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}', '\u{1c77}'), ('\u{1ce9}',
+        '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'), ('\u{1cf5}', '\u{1cf6}'),
+        ('\u{2135}', '\u{2138}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d80}',
+        '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'),
+        ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
+        '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
+        ('\u{2dd8}', '\u{2dde}'), ('\u{3006}', '\u{3006}'), ('\u{303c}',
+        '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309f}', '\u{309f}'),
+        ('\u{30a1}', '\u{30fa}'), ('\u{30ff}', '\u{30ff}'), ('\u{3105}',
+        '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'),
+        ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}',
+        '\u{9fd5}'), ('\u{a000}', '\u{a014}'), ('\u{a016}', '\u{a48c}'),
+        ('\u{a4d0}', '\u{a4f7}'), ('\u{a500}', '\u{a60b}'), ('\u{a610}',
+        '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a66e}', '\u{a66e}'),
+        ('\u{a6a0}', '\u{a6e5}'), ('\u{a78f}', '\u{a78f}'), ('\u{a7f7}',
+        '\u{a7f7}'), ('\u{a7fb}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
+        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}',
+        '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'),
+        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
+        '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'),
+        ('\u{a984}', '\u{a9b2}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e7}',
+        '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'),
+        ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}',
+        '\u{aa6f}'), ('\u{aa71}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
+        ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}',
+        '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'),
+        ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadc}'), ('\u{aae0}',
+        '\u{aaea}'), ('\u{aaf2}', '\u{aaf2}'), ('\u{ab01}', '\u{ab06}'),
+        ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}',
+        '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{abc0}', '\u{abe2}'),
+        ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}',
+        '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'),
+        ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}',
+        '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'),
+        ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}',
+        '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'),
+        ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}',
+        '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff66}', '\u{ff6f}'),
+        ('\u{ff71}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}',
+        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
+        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
+        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
+        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
+        '\u{100fa}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'),
+        ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{10340}'), ('\u{10342}',
+        '\u{10349}'), ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'),
+        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{10450}',
+        '\u{1049d}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', '\u{10563}'),
+        ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}',
+        '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'),
+        ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}',
+        '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'),
+        ('\u{10880}', '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}',
+        '\u{108f5}'), ('\u{10900}', '\u{10915}'), ('\u{10920}', '\u{10939}'),
+        ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'), ('\u{10a00}',
+        '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'),
+        ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}',
+        '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'),
+        ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}',
+        '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'),
+        ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'), ('\u{110d0}',
+        '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', '\u{11172}'),
+        ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}',
+        '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'),
+        ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'), ('\u{11280}',
+        '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
+        ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}',
+        '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'),
+        ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}',
+        '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{1133d}'),
+        ('\u{11350}', '\u{11350}'), ('\u{1135d}', '\u{11361}'), ('\u{11480}',
+        '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'),
+        ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'), ('\u{11600}',
+        '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'),
+        ('\u{11700}', '\u{11719}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}',
+        '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12480}', '\u{12543}'),
+        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
+        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'),
+        ('\u{16b00}', '\u{16b2f}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
+        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'),
+        ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}',
+        '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'),
+        ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}',
+        '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'),
+        ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}',
+        '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
+        ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
+        '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'),
+        ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}',
+        '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'),
+        ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}',
+        '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
+        ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
+        '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'),
+        ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}',
+        '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'),
+        ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}',
+        '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}')
+    ];
+
+    pub const Lt_table: &'static [(char, char)] = &[
+        ('\u{1c5}', '\u{1c5}'), ('\u{1c8}', '\u{1c8}'), ('\u{1cb}', '\u{1cb}'),
+        ('\u{1f2}', '\u{1f2}'), ('\u{1f88}', '\u{1f8f}'), ('\u{1f98}',
+        '\u{1f9f}'), ('\u{1fa8}', '\u{1faf}'), ('\u{1fbc}', '\u{1fbc}'),
+        ('\u{1fcc}', '\u{1fcc}'), ('\u{1ffc}', '\u{1ffc}')
+    ];
+
+    pub const Lu_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'),
+        ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'),
+        ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'),
+        ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), ('\u{110}', '\u{110}'),
+        ('\u{112}', '\u{112}'), ('\u{114}', '\u{114}'), ('\u{116}', '\u{116}'),
+        ('\u{118}', '\u{118}'), ('\u{11a}', '\u{11a}'), ('\u{11c}', '\u{11c}'),
+        ('\u{11e}', '\u{11e}'), ('\u{120}', '\u{120}'), ('\u{122}', '\u{122}'),
+        ('\u{124}', '\u{124}'), ('\u{126}', '\u{126}'), ('\u{128}', '\u{128}'),
+        ('\u{12a}', '\u{12a}'), ('\u{12c}', '\u{12c}'), ('\u{12e}', '\u{12e}'),
+        ('\u{130}', '\u{130}'), ('\u{132}', '\u{132}'), ('\u{134}', '\u{134}'),
+        ('\u{136}', '\u{136}'), ('\u{139}', '\u{139}'), ('\u{13b}', '\u{13b}'),
+        ('\u{13d}', '\u{13d}'), ('\u{13f}', '\u{13f}'), ('\u{141}', '\u{141}'),
+        ('\u{143}', '\u{143}'), ('\u{145}', '\u{145}'), ('\u{147}', '\u{147}'),
+        ('\u{14a}', '\u{14a}'), ('\u{14c}', '\u{14c}'), ('\u{14e}', '\u{14e}'),
+        ('\u{150}', '\u{150}'), ('\u{152}', '\u{152}'), ('\u{154}', '\u{154}'),
+        ('\u{156}', '\u{156}'), ('\u{158}', '\u{158}'), ('\u{15a}', '\u{15a}'),
+        ('\u{15c}', '\u{15c}'), ('\u{15e}', '\u{15e}'), ('\u{160}', '\u{160}'),
+        ('\u{162}', '\u{162}'), ('\u{164}', '\u{164}'), ('\u{166}', '\u{166}'),
+        ('\u{168}', '\u{168}'), ('\u{16a}', '\u{16a}'), ('\u{16c}', '\u{16c}'),
+        ('\u{16e}', '\u{16e}'), ('\u{170}', '\u{170}'), ('\u{172}', '\u{172}'),
+        ('\u{174}', '\u{174}'), ('\u{176}', '\u{176}'), ('\u{178}', '\u{179}'),
+        ('\u{17b}', '\u{17b}'), ('\u{17d}', '\u{17d}'), ('\u{181}', '\u{182}'),
+        ('\u{184}', '\u{184}'), ('\u{186}', '\u{187}'), ('\u{189}', '\u{18b}'),
+        ('\u{18e}', '\u{191}'), ('\u{193}', '\u{194}'), ('\u{196}', '\u{198}'),
+        ('\u{19c}', '\u{19d}'), ('\u{19f}', '\u{1a0}'), ('\u{1a2}', '\u{1a2}'),
+        ('\u{1a4}', '\u{1a4}'), ('\u{1a6}', '\u{1a7}'), ('\u{1a9}', '\u{1a9}'),
+        ('\u{1ac}', '\u{1ac}'), ('\u{1ae}', '\u{1af}'), ('\u{1b1}', '\u{1b3}'),
+        ('\u{1b5}', '\u{1b5}'), ('\u{1b7}', '\u{1b8}'), ('\u{1bc}', '\u{1bc}'),
+        ('\u{1c4}', '\u{1c4}'), ('\u{1c7}', '\u{1c7}'), ('\u{1ca}', '\u{1ca}'),
+        ('\u{1cd}', '\u{1cd}'), ('\u{1cf}', '\u{1cf}'), ('\u{1d1}', '\u{1d1}'),
+        ('\u{1d3}', '\u{1d3}'), ('\u{1d5}', '\u{1d5}'), ('\u{1d7}', '\u{1d7}'),
+        ('\u{1d9}', '\u{1d9}'), ('\u{1db}', '\u{1db}'), ('\u{1de}', '\u{1de}'),
+        ('\u{1e0}', '\u{1e0}'), ('\u{1e2}', '\u{1e2}'), ('\u{1e4}', '\u{1e4}'),
+        ('\u{1e6}', '\u{1e6}'), ('\u{1e8}', '\u{1e8}'), ('\u{1ea}', '\u{1ea}'),
+        ('\u{1ec}', '\u{1ec}'), ('\u{1ee}', '\u{1ee}'), ('\u{1f1}', '\u{1f1}'),
+        ('\u{1f4}', '\u{1f4}'), ('\u{1f6}', '\u{1f8}'), ('\u{1fa}', '\u{1fa}'),
+        ('\u{1fc}', '\u{1fc}'), ('\u{1fe}', '\u{1fe}'), ('\u{200}', '\u{200}'),
+        ('\u{202}', '\u{202}'), ('\u{204}', '\u{204}'), ('\u{206}', '\u{206}'),
+        ('\u{208}', '\u{208}'), ('\u{20a}', '\u{20a}'), ('\u{20c}', '\u{20c}'),
+        ('\u{20e}', '\u{20e}'), ('\u{210}', '\u{210}'), ('\u{212}', '\u{212}'),
+        ('\u{214}', '\u{214}'), ('\u{216}', '\u{216}'), ('\u{218}', '\u{218}'),
+        ('\u{21a}', '\u{21a}'), ('\u{21c}', '\u{21c}'), ('\u{21e}', '\u{21e}'),
+        ('\u{220}', '\u{220}'), ('\u{222}', '\u{222}'), ('\u{224}', '\u{224}'),
+        ('\u{226}', '\u{226}'), ('\u{228}', '\u{228}'), ('\u{22a}', '\u{22a}'),
+        ('\u{22c}', '\u{22c}'), ('\u{22e}', '\u{22e}'), ('\u{230}', '\u{230}'),
+        ('\u{232}', '\u{232}'), ('\u{23a}', '\u{23b}'), ('\u{23d}', '\u{23e}'),
+        ('\u{241}', '\u{241}'), ('\u{243}', '\u{246}'), ('\u{248}', '\u{248}'),
+        ('\u{24a}', '\u{24a}'), ('\u{24c}', '\u{24c}'), ('\u{24e}', '\u{24e}'),
+        ('\u{370}', '\u{370}'), ('\u{372}', '\u{372}'), ('\u{376}', '\u{376}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
+        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{38f}'), ('\u{391}', '\u{3a1}'),
+        ('\u{3a3}', '\u{3ab}'), ('\u{3cf}', '\u{3cf}'), ('\u{3d2}', '\u{3d4}'),
+        ('\u{3d8}', '\u{3d8}'), ('\u{3da}', '\u{3da}'), ('\u{3dc}', '\u{3dc}'),
+        ('\u{3de}', '\u{3de}'), ('\u{3e0}', '\u{3e0}'), ('\u{3e2}', '\u{3e2}'),
+        ('\u{3e4}', '\u{3e4}'), ('\u{3e6}', '\u{3e6}'), ('\u{3e8}', '\u{3e8}'),
+        ('\u{3ea}', '\u{3ea}'), ('\u{3ec}', '\u{3ec}'), ('\u{3ee}', '\u{3ee}'),
+        ('\u{3f4}', '\u{3f4}'), ('\u{3f7}', '\u{3f7}'), ('\u{3f9}', '\u{3fa}'),
+        ('\u{3fd}', '\u{42f}'), ('\u{460}', '\u{460}'), ('\u{462}', '\u{462}'),
+        ('\u{464}', '\u{464}'), ('\u{466}', '\u{466}'), ('\u{468}', '\u{468}'),
+        ('\u{46a}', '\u{46a}'), ('\u{46c}', '\u{46c}'), ('\u{46e}', '\u{46e}'),
+        ('\u{470}', '\u{470}'), ('\u{472}', '\u{472}'), ('\u{474}', '\u{474}'),
+        ('\u{476}', '\u{476}'), ('\u{478}', '\u{478}'), ('\u{47a}', '\u{47a}'),
+        ('\u{47c}', '\u{47c}'), ('\u{47e}', '\u{47e}'), ('\u{480}', '\u{480}'),
+        ('\u{48a}', '\u{48a}'), ('\u{48c}', '\u{48c}'), ('\u{48e}', '\u{48e}'),
+        ('\u{490}', '\u{490}'), ('\u{492}', '\u{492}'), ('\u{494}', '\u{494}'),
+        ('\u{496}', '\u{496}'), ('\u{498}', '\u{498}'), ('\u{49a}', '\u{49a}'),
+        ('\u{49c}', '\u{49c}'), ('\u{49e}', '\u{49e}'), ('\u{4a0}', '\u{4a0}'),
+        ('\u{4a2}', '\u{4a2}'), ('\u{4a4}', '\u{4a4}'), ('\u{4a6}', '\u{4a6}'),
+        ('\u{4a8}', '\u{4a8}'), ('\u{4aa}', '\u{4aa}'), ('\u{4ac}', '\u{4ac}'),
+        ('\u{4ae}', '\u{4ae}'), ('\u{4b0}', '\u{4b0}'), ('\u{4b2}', '\u{4b2}'),
+        ('\u{4b4}', '\u{4b4}'), ('\u{4b6}', '\u{4b6}'), ('\u{4b8}', '\u{4b8}'),
+        ('\u{4ba}', '\u{4ba}'), ('\u{4bc}', '\u{4bc}'), ('\u{4be}', '\u{4be}'),
+        ('\u{4c0}', '\u{4c1}'), ('\u{4c3}', '\u{4c3}'), ('\u{4c5}', '\u{4c5}'),
+        ('\u{4c7}', '\u{4c7}'), ('\u{4c9}', '\u{4c9}'), ('\u{4cb}', '\u{4cb}'),
+        ('\u{4cd}', '\u{4cd}'), ('\u{4d0}', '\u{4d0}'), ('\u{4d2}', '\u{4d2}'),
+        ('\u{4d4}', '\u{4d4}'), ('\u{4d6}', '\u{4d6}'), ('\u{4d8}', '\u{4d8}'),
+        ('\u{4da}', '\u{4da}'), ('\u{4dc}', '\u{4dc}'), ('\u{4de}', '\u{4de}'),
+        ('\u{4e0}', '\u{4e0}'), ('\u{4e2}', '\u{4e2}'), ('\u{4e4}', '\u{4e4}'),
+        ('\u{4e6}', '\u{4e6}'), ('\u{4e8}', '\u{4e8}'), ('\u{4ea}', '\u{4ea}'),
+        ('\u{4ec}', '\u{4ec}'), ('\u{4ee}', '\u{4ee}'), ('\u{4f0}', '\u{4f0}'),
+        ('\u{4f2}', '\u{4f2}'), ('\u{4f4}', '\u{4f4}'), ('\u{4f6}', '\u{4f6}'),
+        ('\u{4f8}', '\u{4f8}'), ('\u{4fa}', '\u{4fa}'), ('\u{4fc}', '\u{4fc}'),
+        ('\u{4fe}', '\u{4fe}'), ('\u{500}', '\u{500}'), ('\u{502}', '\u{502}'),
+        ('\u{504}', '\u{504}'), ('\u{506}', '\u{506}'), ('\u{508}', '\u{508}'),
+        ('\u{50a}', '\u{50a}'), ('\u{50c}', '\u{50c}'), ('\u{50e}', '\u{50e}'),
+        ('\u{510}', '\u{510}'), ('\u{512}', '\u{512}'), ('\u{514}', '\u{514}'),
+        ('\u{516}', '\u{516}'), ('\u{518}', '\u{518}'), ('\u{51a}', '\u{51a}'),
+        ('\u{51c}', '\u{51c}'), ('\u{51e}', '\u{51e}'), ('\u{520}', '\u{520}'),
+        ('\u{522}', '\u{522}'), ('\u{524}', '\u{524}'), ('\u{526}', '\u{526}'),
+        ('\u{528}', '\u{528}'), ('\u{52a}', '\u{52a}'), ('\u{52c}', '\u{52c}'),
+        ('\u{52e}', '\u{52e}'), ('\u{531}', '\u{556}'), ('\u{10a0}',
+        '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'),
+        ('\u{13a0}', '\u{13f5}'), ('\u{1e00}', '\u{1e00}'), ('\u{1e02}',
+        '\u{1e02}'), ('\u{1e04}', '\u{1e04}'), ('\u{1e06}', '\u{1e06}'),
+        ('\u{1e08}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0a}'), ('\u{1e0c}',
+        '\u{1e0c}'), ('\u{1e0e}', '\u{1e0e}'), ('\u{1e10}', '\u{1e10}'),
+        ('\u{1e12}', '\u{1e12}'), ('\u{1e14}', '\u{1e14}'), ('\u{1e16}',
+        '\u{1e16}'), ('\u{1e18}', '\u{1e18}'), ('\u{1e1a}', '\u{1e1a}'),
+        ('\u{1e1c}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1e}'), ('\u{1e20}',
+        '\u{1e20}'), ('\u{1e22}', '\u{1e22}'), ('\u{1e24}', '\u{1e24}'),
+        ('\u{1e26}', '\u{1e26}'), ('\u{1e28}', '\u{1e28}'), ('\u{1e2a}',
+        '\u{1e2a}'), ('\u{1e2c}', '\u{1e2c}'), ('\u{1e2e}', '\u{1e2e}'),
+        ('\u{1e30}', '\u{1e30}'), ('\u{1e32}', '\u{1e32}'), ('\u{1e34}',
+        '\u{1e34}'), ('\u{1e36}', '\u{1e36}'), ('\u{1e38}', '\u{1e38}'),
+        ('\u{1e3a}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3c}'), ('\u{1e3e}',
+        '\u{1e3e}'), ('\u{1e40}', '\u{1e40}'), ('\u{1e42}', '\u{1e42}'),
+        ('\u{1e44}', '\u{1e44}'), ('\u{1e46}', '\u{1e46}'), ('\u{1e48}',
+        '\u{1e48}'), ('\u{1e4a}', '\u{1e4a}'), ('\u{1e4c}', '\u{1e4c}'),
+        ('\u{1e4e}', '\u{1e4e}'), ('\u{1e50}', '\u{1e50}'), ('\u{1e52}',
+        '\u{1e52}'), ('\u{1e54}', '\u{1e54}'), ('\u{1e56}', '\u{1e56}'),
+        ('\u{1e58}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5a}'), ('\u{1e5c}',
+        '\u{1e5c}'), ('\u{1e5e}', '\u{1e5e}'), ('\u{1e60}', '\u{1e60}'),
+        ('\u{1e62}', '\u{1e62}'), ('\u{1e64}', '\u{1e64}'), ('\u{1e66}',
+        '\u{1e66}'), ('\u{1e68}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6a}'),
+        ('\u{1e6c}', '\u{1e6c}'), ('\u{1e6e}', '\u{1e6e}'), ('\u{1e70}',
+        '\u{1e70}'), ('\u{1e72}', '\u{1e72}'), ('\u{1e74}', '\u{1e74}'),
+        ('\u{1e76}', '\u{1e76}'), ('\u{1e78}', '\u{1e78}'), ('\u{1e7a}',
+        '\u{1e7a}'), ('\u{1e7c}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7e}'),
+        ('\u{1e80}', '\u{1e80}'), ('\u{1e82}', '\u{1e82}'), ('\u{1e84}',
+        '\u{1e84}'), ('\u{1e86}', '\u{1e86}'), ('\u{1e88}', '\u{1e88}'),
+        ('\u{1e8a}', '\u{1e8a}'), ('\u{1e8c}', '\u{1e8c}'), ('\u{1e8e}',
+        '\u{1e8e}'), ('\u{1e90}', '\u{1e90}'), ('\u{1e92}', '\u{1e92}'),
+        ('\u{1e94}', '\u{1e94}'), ('\u{1e9e}', '\u{1e9e}'), ('\u{1ea0}',
+        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea2}'), ('\u{1ea4}', '\u{1ea4}'),
+        ('\u{1ea6}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea8}'), ('\u{1eaa}',
+        '\u{1eaa}'), ('\u{1eac}', '\u{1eac}'), ('\u{1eae}', '\u{1eae}'),
+        ('\u{1eb0}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb2}'), ('\u{1eb4}',
+        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb6}'), ('\u{1eb8}', '\u{1eb8}'),
+        ('\u{1eba}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebc}'), ('\u{1ebe}',
+        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec0}'), ('\u{1ec2}', '\u{1ec2}'),
+        ('\u{1ec4}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec6}'), ('\u{1ec8}',
+        '\u{1ec8}'), ('\u{1eca}', '\u{1eca}'), ('\u{1ecc}', '\u{1ecc}'),
+        ('\u{1ece}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed0}'), ('\u{1ed2}',
+        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed4}'), ('\u{1ed6}', '\u{1ed6}'),
+        ('\u{1ed8}', '\u{1ed8}'), ('\u{1eda}', '\u{1eda}'), ('\u{1edc}',
+        '\u{1edc}'), ('\u{1ede}', '\u{1ede}'), ('\u{1ee0}', '\u{1ee0}'),
+        ('\u{1ee2}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee4}'), ('\u{1ee6}',
+        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee8}'), ('\u{1eea}', '\u{1eea}'),
+        ('\u{1eec}', '\u{1eec}'), ('\u{1eee}', '\u{1eee}'), ('\u{1ef0}',
+        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef2}'), ('\u{1ef4}', '\u{1ef4}'),
+        ('\u{1ef6}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef8}'), ('\u{1efa}',
+        '\u{1efa}'), ('\u{1efc}', '\u{1efc}'), ('\u{1efe}', '\u{1efe}'),
+        ('\u{1f08}', '\u{1f0f}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f28}',
+        '\u{1f2f}'), ('\u{1f38}', '\u{1f3f}'), ('\u{1f48}', '\u{1f4d}'),
+        ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
+        '\u{1f5d}'), ('\u{1f5f}', '\u{1f5f}'), ('\u{1f68}', '\u{1f6f}'),
+        ('\u{1fb8}', '\u{1fbb}'), ('\u{1fc8}', '\u{1fcb}'), ('\u{1fd8}',
+        '\u{1fdb}'), ('\u{1fe8}', '\u{1fec}'), ('\u{1ff8}', '\u{1ffb}'),
+        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210b}',
+        '\u{210d}'), ('\u{2110}', '\u{2112}'), ('\u{2115}', '\u{2115}'),
+        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
+        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
+        ('\u{2130}', '\u{2133}'), ('\u{213e}', '\u{213f}'), ('\u{2145}',
+        '\u{2145}'), ('\u{2183}', '\u{2183}'), ('\u{2c00}', '\u{2c2e}'),
+        ('\u{2c60}', '\u{2c60}'), ('\u{2c62}', '\u{2c64}'), ('\u{2c67}',
+        '\u{2c67}'), ('\u{2c69}', '\u{2c69}'), ('\u{2c6b}', '\u{2c6b}'),
+        ('\u{2c6d}', '\u{2c70}'), ('\u{2c72}', '\u{2c72}'), ('\u{2c75}',
+        '\u{2c75}'), ('\u{2c7e}', '\u{2c80}'), ('\u{2c82}', '\u{2c82}'),
+        ('\u{2c84}', '\u{2c84}'), ('\u{2c86}', '\u{2c86}'), ('\u{2c88}',
+        '\u{2c88}'), ('\u{2c8a}', '\u{2c8a}'), ('\u{2c8c}', '\u{2c8c}'),
+        ('\u{2c8e}', '\u{2c8e}'), ('\u{2c90}', '\u{2c90}'), ('\u{2c92}',
+        '\u{2c92}'), ('\u{2c94}', '\u{2c94}'), ('\u{2c96}', '\u{2c96}'),
+        ('\u{2c98}', '\u{2c98}'), ('\u{2c9a}', '\u{2c9a}'), ('\u{2c9c}',
+        '\u{2c9c}'), ('\u{2c9e}', '\u{2c9e}'), ('\u{2ca0}', '\u{2ca0}'),
+        ('\u{2ca2}', '\u{2ca2}'), ('\u{2ca4}', '\u{2ca4}'), ('\u{2ca6}',
+        '\u{2ca6}'), ('\u{2ca8}', '\u{2ca8}'), ('\u{2caa}', '\u{2caa}'),
+        ('\u{2cac}', '\u{2cac}'), ('\u{2cae}', '\u{2cae}'), ('\u{2cb0}',
+        '\u{2cb0}'), ('\u{2cb2}', '\u{2cb2}'), ('\u{2cb4}', '\u{2cb4}'),
+        ('\u{2cb6}', '\u{2cb6}'), ('\u{2cb8}', '\u{2cb8}'), ('\u{2cba}',
+        '\u{2cba}'), ('\u{2cbc}', '\u{2cbc}'), ('\u{2cbe}', '\u{2cbe}'),
+        ('\u{2cc0}', '\u{2cc0}'), ('\u{2cc2}', '\u{2cc2}'), ('\u{2cc4}',
+        '\u{2cc4}'), ('\u{2cc6}', '\u{2cc6}'), ('\u{2cc8}', '\u{2cc8}'),
+        ('\u{2cca}', '\u{2cca}'), ('\u{2ccc}', '\u{2ccc}'), ('\u{2cce}',
+        '\u{2cce}'), ('\u{2cd0}', '\u{2cd0}'), ('\u{2cd2}', '\u{2cd2}'),
+        ('\u{2cd4}', '\u{2cd4}'), ('\u{2cd6}', '\u{2cd6}'), ('\u{2cd8}',
+        '\u{2cd8}'), ('\u{2cda}', '\u{2cda}'), ('\u{2cdc}', '\u{2cdc}'),
+        ('\u{2cde}', '\u{2cde}'), ('\u{2ce0}', '\u{2ce0}'), ('\u{2ce2}',
+        '\u{2ce2}'), ('\u{2ceb}', '\u{2ceb}'), ('\u{2ced}', '\u{2ced}'),
+        ('\u{2cf2}', '\u{2cf2}'), ('\u{a640}', '\u{a640}'), ('\u{a642}',
+        '\u{a642}'), ('\u{a644}', '\u{a644}'), ('\u{a646}', '\u{a646}'),
+        ('\u{a648}', '\u{a648}'), ('\u{a64a}', '\u{a64a}'), ('\u{a64c}',
+        '\u{a64c}'), ('\u{a64e}', '\u{a64e}'), ('\u{a650}', '\u{a650}'),
+        ('\u{a652}', '\u{a652}'), ('\u{a654}', '\u{a654}'), ('\u{a656}',
+        '\u{a656}'), ('\u{a658}', '\u{a658}'), ('\u{a65a}', '\u{a65a}'),
+        ('\u{a65c}', '\u{a65c}'), ('\u{a65e}', '\u{a65e}'), ('\u{a660}',
+        '\u{a660}'), ('\u{a662}', '\u{a662}'), ('\u{a664}', '\u{a664}'),
+        ('\u{a666}', '\u{a666}'), ('\u{a668}', '\u{a668}'), ('\u{a66a}',
+        '\u{a66a}'), ('\u{a66c}', '\u{a66c}'), ('\u{a680}', '\u{a680}'),
+        ('\u{a682}', '\u{a682}'), ('\u{a684}', '\u{a684}'), ('\u{a686}',
+        '\u{a686}'), ('\u{a688}', '\u{a688}'), ('\u{a68a}', '\u{a68a}'),
+        ('\u{a68c}', '\u{a68c}'), ('\u{a68e}', '\u{a68e}'), ('\u{a690}',
+        '\u{a690}'), ('\u{a692}', '\u{a692}'), ('\u{a694}', '\u{a694}'),
+        ('\u{a696}', '\u{a696}'), ('\u{a698}', '\u{a698}'), ('\u{a69a}',
+        '\u{a69a}'), ('\u{a722}', '\u{a722}'), ('\u{a724}', '\u{a724}'),
+        ('\u{a726}', '\u{a726}'), ('\u{a728}', '\u{a728}'), ('\u{a72a}',
+        '\u{a72a}'), ('\u{a72c}', '\u{a72c}'), ('\u{a72e}', '\u{a72e}'),
+        ('\u{a732}', '\u{a732}'), ('\u{a734}', '\u{a734}'), ('\u{a736}',
+        '\u{a736}'), ('\u{a738}', '\u{a738}'), ('\u{a73a}', '\u{a73a}'),
+        ('\u{a73c}', '\u{a73c}'), ('\u{a73e}', '\u{a73e}'), ('\u{a740}',
+        '\u{a740}'), ('\u{a742}', '\u{a742}'), ('\u{a744}', '\u{a744}'),
+        ('\u{a746}', '\u{a746}'), ('\u{a748}', '\u{a748}'), ('\u{a74a}',
+        '\u{a74a}'), ('\u{a74c}', '\u{a74c}'), ('\u{a74e}', '\u{a74e}'),
+        ('\u{a750}', '\u{a750}'), ('\u{a752}', '\u{a752}'), ('\u{a754}',
+        '\u{a754}'), ('\u{a756}', '\u{a756}'), ('\u{a758}', '\u{a758}'),
+        ('\u{a75a}', '\u{a75a}'), ('\u{a75c}', '\u{a75c}'), ('\u{a75e}',
+        '\u{a75e}'), ('\u{a760}', '\u{a760}'), ('\u{a762}', '\u{a762}'),
+        ('\u{a764}', '\u{a764}'), ('\u{a766}', '\u{a766}'), ('\u{a768}',
+        '\u{a768}'), ('\u{a76a}', '\u{a76a}'), ('\u{a76c}', '\u{a76c}'),
+        ('\u{a76e}', '\u{a76e}'), ('\u{a779}', '\u{a779}'), ('\u{a77b}',
+        '\u{a77b}'), ('\u{a77d}', '\u{a77e}'), ('\u{a780}', '\u{a780}'),
+        ('\u{a782}', '\u{a782}'), ('\u{a784}', '\u{a784}'), ('\u{a786}',
+        '\u{a786}'), ('\u{a78b}', '\u{a78b}'), ('\u{a78d}', '\u{a78d}'),
+        ('\u{a790}', '\u{a790}'), ('\u{a792}', '\u{a792}'), ('\u{a796}',
+        '\u{a796}'), ('\u{a798}', '\u{a798}'), ('\u{a79a}', '\u{a79a}'),
+        ('\u{a79c}', '\u{a79c}'), ('\u{a79e}', '\u{a79e}'), ('\u{a7a0}',
+        '\u{a7a0}'), ('\u{a7a2}', '\u{a7a2}'), ('\u{a7a4}', '\u{a7a4}'),
+        ('\u{a7a6}', '\u{a7a6}'), ('\u{a7a8}', '\u{a7a8}'), ('\u{a7aa}',
+        '\u{a7ad}'), ('\u{a7b0}', '\u{a7b4}'), ('\u{a7b6}', '\u{a7b6}'),
+        ('\u{ff21}', '\u{ff3a}'), ('\u{10400}', '\u{10427}'), ('\u{10c80}',
+        '\u{10cb2}'), ('\u{118a0}', '\u{118bf}'), ('\u{1d400}', '\u{1d419}'),
+        ('\u{1d434}', '\u{1d44d}'), ('\u{1d468}', '\u{1d481}'), ('\u{1d49c}',
+        '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
+        ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}',
+        '\u{1d4b5}'), ('\u{1d4d0}', '\u{1d4e9}'), ('\u{1d504}', '\u{1d505}'),
+        ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}',
+        '\u{1d51c}'), ('\u{1d538}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'),
+        ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}',
+        '\u{1d550}'), ('\u{1d56c}', '\u{1d585}'), ('\u{1d5a0}', '\u{1d5b9}'),
+        ('\u{1d5d4}', '\u{1d5ed}'), ('\u{1d608}', '\u{1d621}'), ('\u{1d63c}',
+        '\u{1d655}'), ('\u{1d670}', '\u{1d689}'), ('\u{1d6a8}', '\u{1d6c0}'),
+        ('\u{1d6e2}', '\u{1d6fa}'), ('\u{1d71c}', '\u{1d734}'), ('\u{1d756}',
+        '\u{1d76e}'), ('\u{1d790}', '\u{1d7a8}'), ('\u{1d7ca}', '\u{1d7ca}')
+    ];
+
+    pub const M_table: &'static [(char, char)] = &[
+        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'),
+        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
+        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
+        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
+        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
+        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
+        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
+        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{903}'),
+        ('\u{93a}', '\u{93c}'), ('\u{93e}', '\u{94f}'), ('\u{951}', '\u{957}'),
+        ('\u{962}', '\u{963}'), ('\u{981}', '\u{983}'), ('\u{9bc}', '\u{9bc}'),
+        ('\u{9be}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cd}'),
+        ('\u{9d7}', '\u{9d7}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a03}'),
+        ('\u{a3c}', '\u{a3c}'), ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'),
+        ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'),
+        ('\u{a75}', '\u{a75}'), ('\u{a81}', '\u{a83}'), ('\u{abc}', '\u{abc}'),
+        ('\u{abe}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'),
+        ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b03}'), ('\u{b3c}', '\u{b3c}'),
+        ('\u{b3e}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'),
+        ('\u{b56}', '\u{b57}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'),
+        ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
+        ('\u{bd7}', '\u{bd7}'), ('\u{c00}', '\u{c03}'), ('\u{c3e}', '\u{c44}'),
+        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
+        ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c83}'), ('\u{cbc}', '\u{cbc}'),
+        ('\u{cbe}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
+        ('\u{cd5}', '\u{cd6}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d03}'),
+        ('\u{d3e}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4d}'),
+        ('\u{d57}', '\u{d57}'), ('\u{d62}', '\u{d63}'), ('\u{d82}', '\u{d83}'),
+        ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+        ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{e31}', '\u{e31}'),
+        ('\u{e34}', '\u{e3a}'), ('\u{e47}', '\u{e4e}'), ('\u{eb1}', '\u{eb1}'),
+        ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'), ('\u{ec8}', '\u{ecd}'),
+        ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'),
+        ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f3f}'), ('\u{f71}', '\u{f84}'),
+        ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'),
+        ('\u{fc6}', '\u{fc6}'), ('\u{102b}', '\u{103e}'), ('\u{1056}',
+        '\u{1059}'), ('\u{105e}', '\u{1060}'), ('\u{1062}', '\u{1064}'),
+        ('\u{1067}', '\u{106d}'), ('\u{1071}', '\u{1074}'), ('\u{1082}',
+        '\u{108d}'), ('\u{108f}', '\u{108f}'), ('\u{109a}', '\u{109d}'),
+        ('\u{135d}', '\u{135f}'), ('\u{1712}', '\u{1714}'), ('\u{1732}',
+        '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}', '\u{1773}'),
+        ('\u{17b4}', '\u{17d3}'), ('\u{17dd}', '\u{17dd}'), ('\u{180b}',
+        '\u{180d}'), ('\u{18a9}', '\u{18a9}'), ('\u{1920}', '\u{192b}'),
+        ('\u{1930}', '\u{193b}'), ('\u{1a17}', '\u{1a1b}'), ('\u{1a55}',
+        '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a7f}'),
+        ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}', '\u{1b04}'), ('\u{1b34}',
+        '\u{1b44}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1b82}'),
+        ('\u{1ba1}', '\u{1bad}'), ('\u{1be6}', '\u{1bf3}'), ('\u{1c24}',
+        '\u{1c37}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce8}'),
+        ('\u{1ced}', '\u{1ced}'), ('\u{1cf2}', '\u{1cf4}'), ('\u{1cf8}',
+        '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'), ('\u{1dfc}', '\u{1dff}'),
+        ('\u{20d0}', '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}',
+        '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302f}'),
+        ('\u{3099}', '\u{309a}'), ('\u{a66f}', '\u{a672}'), ('\u{a674}',
+        '\u{a67d}'), ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'),
+        ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}',
+        '\u{a80b}'), ('\u{a823}', '\u{a827}'), ('\u{a880}', '\u{a881}'),
+        ('\u{a8b4}', '\u{a8c4}'), ('\u{a8e0}', '\u{a8f1}'), ('\u{a926}',
+        '\u{a92d}'), ('\u{a947}', '\u{a953}'), ('\u{a980}', '\u{a983}'),
+        ('\u{a9b3}', '\u{a9c0}'), ('\u{a9e5}', '\u{a9e5}'), ('\u{aa29}',
+        '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4d}'),
+        ('\u{aa7b}', '\u{aa7d}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}',
+        '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'),
+        ('\u{aac1}', '\u{aac1}'), ('\u{aaeb}', '\u{aaef}'), ('\u{aaf5}',
+        '\u{aaf6}'), ('\u{abe3}', '\u{abea}'), ('\u{abec}', '\u{abed}'),
+        ('\u{fb1e}', '\u{fb1e}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}',
+        '\u{fe2f}'), ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', '\u{102e0}'),
+        ('\u{10376}', '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}',
+        '\u{10a06}'), ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'),
+        ('\u{10a3f}', '\u{10a3f}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{11000}',
+        '\u{11002}'), ('\u{11038}', '\u{11046}'), ('\u{1107f}', '\u{11082}'),
+        ('\u{110b0}', '\u{110ba}'), ('\u{11100}', '\u{11102}'), ('\u{11127}',
+        '\u{11134}'), ('\u{11173}', '\u{11173}'), ('\u{11180}', '\u{11182}'),
+        ('\u{111b3}', '\u{111c0}'), ('\u{111ca}', '\u{111cc}'), ('\u{1122c}',
+        '\u{11237}'), ('\u{112df}', '\u{112ea}'), ('\u{11300}', '\u{11303}'),
+        ('\u{1133c}', '\u{1133c}'), ('\u{1133e}', '\u{11344}'), ('\u{11347}',
+        '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11357}', '\u{11357}'),
+        ('\u{11362}', '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
+        '\u{11374}'), ('\u{114b0}', '\u{114c3}'), ('\u{115af}', '\u{115b5}'),
+        ('\u{115b8}', '\u{115c0}'), ('\u{115dc}', '\u{115dd}'), ('\u{11630}',
+        '\u{11640}'), ('\u{116ab}', '\u{116b7}'), ('\u{1171d}', '\u{1172b}'),
+        ('\u{16af0}', '\u{16af4}'), ('\u{16b30}', '\u{16b36}'), ('\u{16f51}',
+        '\u{16f7e}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}', '\u{1bc9e}'),
+        ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}',
+        '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'),
+        ('\u{1d242}', '\u{1d244}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}',
+        '\u{1da6c}'), ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'),
+        ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}',
+        '\u{1e8d6}'), ('\u{e0100}', '\u{e01ef}')
+    ];
+
+    pub const Mc_table: &'static [(char, char)] = &[
+        ('\u{903}', '\u{903}'), ('\u{93b}', '\u{93b}'), ('\u{93e}', '\u{940}'),
+        ('\u{949}', '\u{94c}'), ('\u{94e}', '\u{94f}'), ('\u{982}', '\u{983}'),
+        ('\u{9be}', '\u{9c0}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cc}'),
+        ('\u{9d7}', '\u{9d7}'), ('\u{a03}', '\u{a03}'), ('\u{a3e}', '\u{a40}'),
+        ('\u{a83}', '\u{a83}'), ('\u{abe}', '\u{ac0}'), ('\u{ac9}', '\u{ac9}'),
+        ('\u{acb}', '\u{acc}'), ('\u{b02}', '\u{b03}'), ('\u{b3e}', '\u{b3e}'),
+        ('\u{b40}', '\u{b40}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4c}'),
+        ('\u{b57}', '\u{b57}'), ('\u{bbe}', '\u{bbf}'), ('\u{bc1}', '\u{bc2}'),
+        ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcc}'), ('\u{bd7}', '\u{bd7}'),
+        ('\u{c01}', '\u{c03}'), ('\u{c41}', '\u{c44}'), ('\u{c82}', '\u{c83}'),
+        ('\u{cbe}', '\u{cbe}'), ('\u{cc0}', '\u{cc4}'), ('\u{cc7}', '\u{cc8}'),
+        ('\u{cca}', '\u{ccb}'), ('\u{cd5}', '\u{cd6}'), ('\u{d02}', '\u{d03}'),
+        ('\u{d3e}', '\u{d40}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4c}'),
+        ('\u{d57}', '\u{d57}'), ('\u{d82}', '\u{d83}'), ('\u{dcf}', '\u{dd1}'),
+        ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{f3e}', '\u{f3f}'),
+        ('\u{f7f}', '\u{f7f}'), ('\u{102b}', '\u{102c}'), ('\u{1031}',
+        '\u{1031}'), ('\u{1038}', '\u{1038}'), ('\u{103b}', '\u{103c}'),
+        ('\u{1056}', '\u{1057}'), ('\u{1062}', '\u{1064}'), ('\u{1067}',
+        '\u{106d}'), ('\u{1083}', '\u{1084}'), ('\u{1087}', '\u{108c}'),
+        ('\u{108f}', '\u{108f}'), ('\u{109a}', '\u{109c}'), ('\u{17b6}',
+        '\u{17b6}'), ('\u{17be}', '\u{17c5}'), ('\u{17c7}', '\u{17c8}'),
+        ('\u{1923}', '\u{1926}'), ('\u{1929}', '\u{192b}'), ('\u{1930}',
+        '\u{1931}'), ('\u{1933}', '\u{1938}'), ('\u{1a19}', '\u{1a1a}'),
+        ('\u{1a55}', '\u{1a55}'), ('\u{1a57}', '\u{1a57}'), ('\u{1a61}',
+        '\u{1a61}'), ('\u{1a63}', '\u{1a64}'), ('\u{1a6d}', '\u{1a72}'),
+        ('\u{1b04}', '\u{1b04}'), ('\u{1b35}', '\u{1b35}'), ('\u{1b3b}',
+        '\u{1b3b}'), ('\u{1b3d}', '\u{1b41}'), ('\u{1b43}', '\u{1b44}'),
+        ('\u{1b82}', '\u{1b82}'), ('\u{1ba1}', '\u{1ba1}'), ('\u{1ba6}',
+        '\u{1ba7}'), ('\u{1baa}', '\u{1baa}'), ('\u{1be7}', '\u{1be7}'),
+        ('\u{1bea}', '\u{1bec}'), ('\u{1bee}', '\u{1bee}'), ('\u{1bf2}',
+        '\u{1bf3}'), ('\u{1c24}', '\u{1c2b}'), ('\u{1c34}', '\u{1c35}'),
+        ('\u{1ce1}', '\u{1ce1}'), ('\u{1cf2}', '\u{1cf3}'), ('\u{302e}',
+        '\u{302f}'), ('\u{a823}', '\u{a824}'), ('\u{a827}', '\u{a827}'),
+        ('\u{a880}', '\u{a881}'), ('\u{a8b4}', '\u{a8c3}'), ('\u{a952}',
+        '\u{a953}'), ('\u{a983}', '\u{a983}'), ('\u{a9b4}', '\u{a9b5}'),
+        ('\u{a9ba}', '\u{a9bb}'), ('\u{a9bd}', '\u{a9c0}'), ('\u{aa2f}',
+        '\u{aa30}'), ('\u{aa33}', '\u{aa34}'), ('\u{aa4d}', '\u{aa4d}'),
+        ('\u{aa7b}', '\u{aa7b}'), ('\u{aa7d}', '\u{aa7d}'), ('\u{aaeb}',
+        '\u{aaeb}'), ('\u{aaee}', '\u{aaef}'), ('\u{aaf5}', '\u{aaf5}'),
+        ('\u{abe3}', '\u{abe4}'), ('\u{abe6}', '\u{abe7}'), ('\u{abe9}',
+        '\u{abea}'), ('\u{abec}', '\u{abec}'), ('\u{11000}', '\u{11000}'),
+        ('\u{11002}', '\u{11002}'), ('\u{11082}', '\u{11082}'), ('\u{110b0}',
+        '\u{110b2}'), ('\u{110b7}', '\u{110b8}'), ('\u{1112c}', '\u{1112c}'),
+        ('\u{11182}', '\u{11182}'), ('\u{111b3}', '\u{111b5}'), ('\u{111bf}',
+        '\u{111c0}'), ('\u{1122c}', '\u{1122e}'), ('\u{11232}', '\u{11233}'),
+        ('\u{11235}', '\u{11235}'), ('\u{112e0}', '\u{112e2}'), ('\u{11302}',
+        '\u{11303}'), ('\u{1133e}', '\u{1133f}'), ('\u{11341}', '\u{11344}'),
+        ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11357}',
+        '\u{11357}'), ('\u{11362}', '\u{11363}'), ('\u{114b0}', '\u{114b2}'),
+        ('\u{114b9}', '\u{114b9}'), ('\u{114bb}', '\u{114be}'), ('\u{114c1}',
+        '\u{114c1}'), ('\u{115af}', '\u{115b1}'), ('\u{115b8}', '\u{115bb}'),
+        ('\u{115be}', '\u{115be}'), ('\u{11630}', '\u{11632}'), ('\u{1163b}',
+        '\u{1163c}'), ('\u{1163e}', '\u{1163e}'), ('\u{116ac}', '\u{116ac}'),
+        ('\u{116ae}', '\u{116af}'), ('\u{116b6}', '\u{116b6}'), ('\u{11720}',
+        '\u{11721}'), ('\u{11726}', '\u{11726}'), ('\u{16f51}', '\u{16f7e}'),
+        ('\u{1d165}', '\u{1d166}'), ('\u{1d16d}', '\u{1d172}')
+    ];
+
+    pub const Me_table: &'static [(char, char)] = &[
+        ('\u{488}', '\u{489}'), ('\u{1abe}', '\u{1abe}'), ('\u{20dd}',
+        '\u{20e0}'), ('\u{20e2}', '\u{20e4}'), ('\u{a670}', '\u{a672}')
+    ];
+
+    pub const Mn_table: &'static [(char, char)] = &[
+        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{487}'), ('\u{591}', '\u{5bd}'),
+        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
+        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
+        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
+        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
+        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
+        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
+        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{902}'),
+        ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}', '\u{948}'),
+        ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'),
+        ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9c1}', '\u{9c4}'),
+        ('\u{9cd}', '\u{9cd}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'),
+        ('\u{a3c}', '\u{a3c}'), ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'),
+        ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'),
+        ('\u{a75}', '\u{a75}'), ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'),
+        ('\u{ac1}', '\u{ac5}'), ('\u{ac7}', '\u{ac8}'), ('\u{acd}', '\u{acd}'),
+        ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b01}'), ('\u{b3c}', '\u{b3c}'),
+        ('\u{b3f}', '\u{b3f}'), ('\u{b41}', '\u{b44}'), ('\u{b4d}', '\u{b4d}'),
+        ('\u{b56}', '\u{b56}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'),
+        ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{c00}', '\u{c00}'),
+        ('\u{c3e}', '\u{c40}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'),
+        ('\u{c55}', '\u{c56}'), ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c81}'),
+        ('\u{cbc}', '\u{cbc}'), ('\u{cbf}', '\u{cbf}'), ('\u{cc6}', '\u{cc6}'),
+        ('\u{ccc}', '\u{ccd}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d01}'),
+        ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'), ('\u{d62}', '\u{d63}'),
+        ('\u{dca}', '\u{dca}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+        ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'), ('\u{e47}', '\u{e4e}'),
+        ('\u{eb1}', '\u{eb1}'), ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'),
+        ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'),
+        ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f71}', '\u{f7e}'),
+        ('\u{f80}', '\u{f84}'), ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'),
+        ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{102d}',
+        '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}', '\u{103a}'),
+        ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'), ('\u{105e}',
+        '\u{1060}'), ('\u{1071}', '\u{1074}'), ('\u{1082}', '\u{1082}'),
+        ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'), ('\u{109d}',
+        '\u{109d}'), ('\u{135d}', '\u{135f}'), ('\u{1712}', '\u{1714}'),
+        ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}',
+        '\u{1773}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b7}', '\u{17bd}'),
+        ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', '\u{17d3}'), ('\u{17dd}',
+        '\u{17dd}'), ('\u{180b}', '\u{180d}'), ('\u{18a9}', '\u{18a9}'),
+        ('\u{1920}', '\u{1922}'), ('\u{1927}', '\u{1928}'), ('\u{1932}',
+        '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}', '\u{1a18}'),
+        ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'), ('\u{1a58}',
+        '\u{1a5e}'), ('\u{1a60}', '\u{1a60}'), ('\u{1a62}', '\u{1a62}'),
+        ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'), ('\u{1a7f}',
+        '\u{1a7f}'), ('\u{1ab0}', '\u{1abd}'), ('\u{1b00}', '\u{1b03}'),
+        ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'), ('\u{1b3c}',
+        '\u{1b3c}'), ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}', '\u{1b73}'),
+        ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', '\u{1ba5}'), ('\u{1ba8}',
+        '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}', '\u{1be6}'),
+        ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bef}',
+        '\u{1bf1}'), ('\u{1c2c}', '\u{1c33}'), ('\u{1c36}', '\u{1c37}'),
+        ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}',
+        '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}', '\u{1cf4}'),
+        ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'), ('\u{1dfc}',
+        '\u{1dff}'), ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'),
+        ('\u{20e5}', '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}',
+        '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302d}'),
+        ('\u{3099}', '\u{309a}'), ('\u{a66f}', '\u{a66f}'), ('\u{a674}',
+        '\u{a67d}'), ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'),
+        ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}',
+        '\u{a80b}'), ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'),
+        ('\u{a8e0}', '\u{a8f1}'), ('\u{a926}', '\u{a92d}'), ('\u{a947}',
+        '\u{a951}'), ('\u{a980}', '\u{a982}'), ('\u{a9b3}', '\u{a9b3}'),
+        ('\u{a9b6}', '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9e5}',
+        '\u{a9e5}'), ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'),
+        ('\u{aa35}', '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}',
+        '\u{aa4c}'), ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'),
+        ('\u{aab2}', '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}',
+        '\u{aabf}'), ('\u{aac1}', '\u{aac1}'), ('\u{aaec}', '\u{aaed}'),
+        ('\u{aaf6}', '\u{aaf6}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}',
+        '\u{abe8}'), ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'),
+        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{101fd}',
+        '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}', '\u{1037a}'),
+        ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
+        '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'),
+        ('\u{10ae5}', '\u{10ae6}'), ('\u{11001}', '\u{11001}'), ('\u{11038}',
+        '\u{11046}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}', '\u{110b6}'),
+        ('\u{110b9}', '\u{110ba}'), ('\u{11100}', '\u{11102}'), ('\u{11127}',
+        '\u{1112b}'), ('\u{1112d}', '\u{11134}'), ('\u{11173}', '\u{11173}'),
+        ('\u{11180}', '\u{11181}'), ('\u{111b6}', '\u{111be}'), ('\u{111ca}',
+        '\u{111cc}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}', '\u{11234}'),
+        ('\u{11236}', '\u{11237}'), ('\u{112df}', '\u{112df}'), ('\u{112e3}',
+        '\u{112ea}'), ('\u{11300}', '\u{11301}'), ('\u{1133c}', '\u{1133c}'),
+        ('\u{11340}', '\u{11340}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
+        '\u{11374}'), ('\u{114b3}', '\u{114b8}'), ('\u{114ba}', '\u{114ba}'),
+        ('\u{114bf}', '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115b2}',
+        '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}', '\u{115c0}'),
+        ('\u{115dc}', '\u{115dd}'), ('\u{11633}', '\u{1163a}'), ('\u{1163d}',
+        '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}', '\u{116ab}'),
+        ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', '\u{116b5}'), ('\u{116b7}',
+        '\u{116b7}'), ('\u{1171d}', '\u{1171f}'), ('\u{11722}', '\u{11725}'),
+        ('\u{11727}', '\u{1172b}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b30}',
+        '\u{16b36}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}', '\u{1bc9e}'),
+        ('\u{1d167}', '\u{1d169}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}',
+        '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'),
+        ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}',
+        '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'),
+        ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{e0100}',
+        '\u{e01ef}')
+    ];
+
+    pub const N_table: &'static [(char, char)] = &[
+        ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'),
+        ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'),
+        ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'),
+        ('\u{be6}', '\u{bef}'), ('\u{c66}', '\u{c6f}'), ('\u{ce6}', '\u{cef}'),
+        ('\u{d66}', '\u{d6f}'), ('\u{de6}', '\u{def}'), ('\u{e50}', '\u{e59}'),
+        ('\u{ed0}', '\u{ed9}'), ('\u{f20}', '\u{f29}'), ('\u{1040}',
+        '\u{1049}'), ('\u{1090}', '\u{1099}'), ('\u{16ee}', '\u{16f0}'),
+        ('\u{17e0}', '\u{17e9}'), ('\u{1810}', '\u{1819}'), ('\u{1946}',
+        '\u{194f}'), ('\u{19d0}', '\u{19d9}'), ('\u{1a80}', '\u{1a89}'),
+        ('\u{1a90}', '\u{1a99}'), ('\u{1b50}', '\u{1b59}'), ('\u{1bb0}',
+        '\u{1bb9}'), ('\u{1c40}', '\u{1c49}'), ('\u{1c50}', '\u{1c59}'),
+        ('\u{2160}', '\u{2182}'), ('\u{2185}', '\u{2188}'), ('\u{3007}',
+        '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303a}'),
+        ('\u{a620}', '\u{a629}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{a8d0}',
+        '\u{a8d9}'), ('\u{a900}', '\u{a909}'), ('\u{a9d0}', '\u{a9d9}'),
+        ('\u{a9f0}', '\u{a9f9}'), ('\u{aa50}', '\u{aa59}'), ('\u{abf0}',
+        '\u{abf9}'), ('\u{ff10}', '\u{ff19}'), ('\u{10140}', '\u{10174}'),
+        ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'), ('\u{103d1}',
+        '\u{103d5}'), ('\u{104a0}', '\u{104a9}'), ('\u{11066}', '\u{1106f}'),
+        ('\u{110f0}', '\u{110f9}'), ('\u{11136}', '\u{1113f}'), ('\u{111d0}',
+        '\u{111d9}'), ('\u{112f0}', '\u{112f9}'), ('\u{114d0}', '\u{114d9}'),
+        ('\u{11650}', '\u{11659}'), ('\u{116c0}', '\u{116c9}'), ('\u{11730}',
+        '\u{11739}'), ('\u{118e0}', '\u{118e9}'), ('\u{12400}', '\u{1246e}'),
+        ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'), ('\u{1d7ce}',
+        '\u{1d7ff}')
+    ];
+
+    pub const Nd_table: &'static [(char, char)] = &[
+        ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'),
+        ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'),
+        ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'),
+        ('\u{be6}', '\u{bef}'), ('\u{c66}', '\u{c6f}'), ('\u{ce6}', '\u{cef}'),
+        ('\u{d66}', '\u{d6f}'), ('\u{de6}', '\u{def}'), ('\u{e50}', '\u{e59}'),
+        ('\u{ed0}', '\u{ed9}'), ('\u{f20}', '\u{f29}'), ('\u{1040}',
+        '\u{1049}'), ('\u{1090}', '\u{1099}'), ('\u{17e0}', '\u{17e9}'),
+        ('\u{1810}', '\u{1819}'), ('\u{1946}', '\u{194f}'), ('\u{19d0}',
+        '\u{19d9}'), ('\u{1a80}', '\u{1a89}'), ('\u{1a90}', '\u{1a99}'),
+        ('\u{1b50}', '\u{1b59}'), ('\u{1bb0}', '\u{1bb9}'), ('\u{1c40}',
+        '\u{1c49}'), ('\u{1c50}', '\u{1c59}'), ('\u{a620}', '\u{a629}'),
+        ('\u{a8d0}', '\u{a8d9}'), ('\u{a900}', '\u{a909}'), ('\u{a9d0}',
+        '\u{a9d9}'), ('\u{a9f0}', '\u{a9f9}'), ('\u{aa50}', '\u{aa59}'),
+        ('\u{abf0}', '\u{abf9}'), ('\u{ff10}', '\u{ff19}'), ('\u{104a0}',
+        '\u{104a9}'), ('\u{11066}', '\u{1106f}'), ('\u{110f0}', '\u{110f9}'),
+        ('\u{11136}', '\u{1113f}'), ('\u{111d0}', '\u{111d9}'), ('\u{112f0}',
+        '\u{112f9}'), ('\u{114d0}', '\u{114d9}'), ('\u{11650}', '\u{11659}'),
+        ('\u{116c0}', '\u{116c9}'), ('\u{11730}', '\u{11739}'), ('\u{118e0}',
+        '\u{118e9}'), ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'),
+        ('\u{1d7ce}', '\u{1d7ff}')
+    ];
+
+    pub const Nl_table: &'static [(char, char)] = &[
+        ('\u{16ee}', '\u{16f0}'), ('\u{2160}', '\u{2182}'), ('\u{2185}',
+        '\u{2188}'), ('\u{3007}', '\u{3007}'), ('\u{3021}', '\u{3029}'),
+        ('\u{3038}', '\u{303a}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{10140}',
+        '\u{10174}'), ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'),
+        ('\u{103d1}', '\u{103d5}'), ('\u{12400}', '\u{1246e}')
+    ];
+
+    pub const No_table: &'static [(char, char)] = &[
+        ('\u{b2}', '\u{b3}'), ('\u{b9}', '\u{b9}'), ('\u{bc}', '\u{be}'),
+        ('\u{9f4}', '\u{9f9}'), ('\u{b72}', '\u{b77}'), ('\u{bf0}', '\u{bf2}'),
+        ('\u{c78}', '\u{c7e}'), ('\u{d70}', '\u{d75}'), ('\u{f2a}', '\u{f33}'),
+        ('\u{1369}', '\u{137c}'), ('\u{17f0}', '\u{17f9}'), ('\u{19da}',
+        '\u{19da}'), ('\u{2070}', '\u{2070}'), ('\u{2074}', '\u{2079}'),
+        ('\u{2080}', '\u{2089}'), ('\u{2150}', '\u{215f}'), ('\u{2189}',
+        '\u{2189}'), ('\u{2460}', '\u{249b}'), ('\u{24ea}', '\u{24ff}'),
+        ('\u{2776}', '\u{2793}'), ('\u{2cfd}', '\u{2cfd}'), ('\u{3192}',
+        '\u{3195}'), ('\u{3220}', '\u{3229}'), ('\u{3248}', '\u{324f}'),
+        ('\u{3251}', '\u{325f}'), ('\u{3280}', '\u{3289}'), ('\u{32b1}',
+        '\u{32bf}'), ('\u{a830}', '\u{a835}'), ('\u{10107}', '\u{10133}'),
+        ('\u{10175}', '\u{10178}'), ('\u{1018a}', '\u{1018b}'), ('\u{102e1}',
+        '\u{102fb}'), ('\u{10320}', '\u{10323}'), ('\u{10858}', '\u{1085f}'),
+        ('\u{10879}', '\u{1087f}'), ('\u{108a7}', '\u{108af}'), ('\u{108fb}',
+        '\u{108ff}'), ('\u{10916}', '\u{1091b}'), ('\u{109bc}', '\u{109bd}'),
+        ('\u{109c0}', '\u{109cf}'), ('\u{109d2}', '\u{109ff}'), ('\u{10a40}',
+        '\u{10a47}'), ('\u{10a7d}', '\u{10a7e}'), ('\u{10a9d}', '\u{10a9f}'),
+        ('\u{10aeb}', '\u{10aef}'), ('\u{10b58}', '\u{10b5f}'), ('\u{10b78}',
+        '\u{10b7f}'), ('\u{10ba9}', '\u{10baf}'), ('\u{10cfa}', '\u{10cff}'),
+        ('\u{10e60}', '\u{10e7e}'), ('\u{11052}', '\u{11065}'), ('\u{111e1}',
+        '\u{111f4}'), ('\u{1173a}', '\u{1173b}'), ('\u{118ea}', '\u{118f2}'),
+        ('\u{16b5b}', '\u{16b61}'), ('\u{1d360}', '\u{1d371}'), ('\u{1e8c7}',
+        '\u{1e8cf}'), ('\u{1f100}', '\u{1f10c}')
+    ];
+
+    pub const P_table: &'static [(char, char)] = &[
+        ('\u{21}', '\u{23}'), ('\u{25}', '\u{2a}'), ('\u{2c}', '\u{2f}'),
+        ('\u{3a}', '\u{3b}'), ('\u{3f}', '\u{40}'), ('\u{5b}', '\u{5d}'),
+        ('\u{5f}', '\u{5f}'), ('\u{7b}', '\u{7b}'), ('\u{7d}', '\u{7d}'),
+        ('\u{a1}', '\u{a1}'), ('\u{a7}', '\u{a7}'), ('\u{ab}', '\u{ab}'),
+        ('\u{b6}', '\u{b7}'), ('\u{bb}', '\u{bb}'), ('\u{bf}', '\u{bf}'),
+        ('\u{37e}', '\u{37e}'), ('\u{387}', '\u{387}'), ('\u{55a}', '\u{55f}'),
+        ('\u{589}', '\u{58a}'), ('\u{5be}', '\u{5be}'), ('\u{5c0}', '\u{5c0}'),
+        ('\u{5c3}', '\u{5c3}'), ('\u{5c6}', '\u{5c6}'), ('\u{5f3}', '\u{5f4}'),
+        ('\u{609}', '\u{60a}'), ('\u{60c}', '\u{60d}'), ('\u{61b}', '\u{61b}'),
+        ('\u{61e}', '\u{61f}'), ('\u{66a}', '\u{66d}'), ('\u{6d4}', '\u{6d4}'),
+        ('\u{700}', '\u{70d}'), ('\u{7f7}', '\u{7f9}'), ('\u{830}', '\u{83e}'),
+        ('\u{85e}', '\u{85e}'), ('\u{964}', '\u{965}'), ('\u{970}', '\u{970}'),
+        ('\u{af0}', '\u{af0}'), ('\u{df4}', '\u{df4}'), ('\u{e4f}', '\u{e4f}'),
+        ('\u{e5a}', '\u{e5b}'), ('\u{f04}', '\u{f12}'), ('\u{f14}', '\u{f14}'),
+        ('\u{f3a}', '\u{f3d}'), ('\u{f85}', '\u{f85}'), ('\u{fd0}', '\u{fd4}'),
+        ('\u{fd9}', '\u{fda}'), ('\u{104a}', '\u{104f}'), ('\u{10fb}',
+        '\u{10fb}'), ('\u{1360}', '\u{1368}'), ('\u{1400}', '\u{1400}'),
+        ('\u{166d}', '\u{166e}'), ('\u{169b}', '\u{169c}'), ('\u{16eb}',
+        '\u{16ed}'), ('\u{1735}', '\u{1736}'), ('\u{17d4}', '\u{17d6}'),
+        ('\u{17d8}', '\u{17da}'), ('\u{1800}', '\u{180a}'), ('\u{1944}',
+        '\u{1945}'), ('\u{1a1e}', '\u{1a1f}'), ('\u{1aa0}', '\u{1aa6}'),
+        ('\u{1aa8}', '\u{1aad}'), ('\u{1b5a}', '\u{1b60}'), ('\u{1bfc}',
+        '\u{1bff}'), ('\u{1c3b}', '\u{1c3f}'), ('\u{1c7e}', '\u{1c7f}'),
+        ('\u{1cc0}', '\u{1cc7}'), ('\u{1cd3}', '\u{1cd3}'), ('\u{2010}',
+        '\u{2027}'), ('\u{2030}', '\u{2043}'), ('\u{2045}', '\u{2051}'),
+        ('\u{2053}', '\u{205e}'), ('\u{207d}', '\u{207e}'), ('\u{208d}',
+        '\u{208e}'), ('\u{2308}', '\u{230b}'), ('\u{2329}', '\u{232a}'),
+        ('\u{2768}', '\u{2775}'), ('\u{27c5}', '\u{27c6}'), ('\u{27e6}',
+        '\u{27ef}'), ('\u{2983}', '\u{2998}'), ('\u{29d8}', '\u{29db}'),
+        ('\u{29fc}', '\u{29fd}'), ('\u{2cf9}', '\u{2cfc}'), ('\u{2cfe}',
+        '\u{2cff}'), ('\u{2d70}', '\u{2d70}'), ('\u{2e00}', '\u{2e2e}'),
+        ('\u{2e30}', '\u{2e42}'), ('\u{3001}', '\u{3003}'), ('\u{3008}',
+        '\u{3011}'), ('\u{3014}', '\u{301f}'), ('\u{3030}', '\u{3030}'),
+        ('\u{303d}', '\u{303d}'), ('\u{30a0}', '\u{30a0}'), ('\u{30fb}',
+        '\u{30fb}'), ('\u{a4fe}', '\u{a4ff}'), ('\u{a60d}', '\u{a60f}'),
+        ('\u{a673}', '\u{a673}'), ('\u{a67e}', '\u{a67e}'), ('\u{a6f2}',
+        '\u{a6f7}'), ('\u{a874}', '\u{a877}'), ('\u{a8ce}', '\u{a8cf}'),
+        ('\u{a8f8}', '\u{a8fa}'), ('\u{a8fc}', '\u{a8fc}'), ('\u{a92e}',
+        '\u{a92f}'), ('\u{a95f}', '\u{a95f}'), ('\u{a9c1}', '\u{a9cd}'),
+        ('\u{a9de}', '\u{a9df}'), ('\u{aa5c}', '\u{aa5f}'), ('\u{aade}',
+        '\u{aadf}'), ('\u{aaf0}', '\u{aaf1}'), ('\u{abeb}', '\u{abeb}'),
+        ('\u{fd3e}', '\u{fd3f}'), ('\u{fe10}', '\u{fe19}'), ('\u{fe30}',
+        '\u{fe52}'), ('\u{fe54}', '\u{fe61}'), ('\u{fe63}', '\u{fe63}'),
+        ('\u{fe68}', '\u{fe68}'), ('\u{fe6a}', '\u{fe6b}'), ('\u{ff01}',
+        '\u{ff03}'), ('\u{ff05}', '\u{ff0a}'), ('\u{ff0c}', '\u{ff0f}'),
+        ('\u{ff1a}', '\u{ff1b}'), ('\u{ff1f}', '\u{ff20}'), ('\u{ff3b}',
+        '\u{ff3d}'), ('\u{ff3f}', '\u{ff3f}'), ('\u{ff5b}', '\u{ff5b}'),
+        ('\u{ff5d}', '\u{ff5d}'), ('\u{ff5f}', '\u{ff65}'), ('\u{10100}',
+        '\u{10102}'), ('\u{1039f}', '\u{1039f}'), ('\u{103d0}', '\u{103d0}'),
+        ('\u{1056f}', '\u{1056f}'), ('\u{10857}', '\u{10857}'), ('\u{1091f}',
+        '\u{1091f}'), ('\u{1093f}', '\u{1093f}'), ('\u{10a50}', '\u{10a58}'),
+        ('\u{10a7f}', '\u{10a7f}'), ('\u{10af0}', '\u{10af6}'), ('\u{10b39}',
+        '\u{10b3f}'), ('\u{10b99}', '\u{10b9c}'), ('\u{11047}', '\u{1104d}'),
+        ('\u{110bb}', '\u{110bc}'), ('\u{110be}', '\u{110c1}'), ('\u{11140}',
+        '\u{11143}'), ('\u{11174}', '\u{11175}'), ('\u{111c5}', '\u{111c9}'),
+        ('\u{111cd}', '\u{111cd}'), ('\u{111db}', '\u{111db}'), ('\u{111dd}',
+        '\u{111df}'), ('\u{11238}', '\u{1123d}'), ('\u{112a9}', '\u{112a9}'),
+        ('\u{114c6}', '\u{114c6}'), ('\u{115c1}', '\u{115d7}'), ('\u{11641}',
+        '\u{11643}'), ('\u{1173c}', '\u{1173e}'), ('\u{12470}', '\u{12474}'),
+        ('\u{16a6e}', '\u{16a6f}'), ('\u{16af5}', '\u{16af5}'), ('\u{16b37}',
+        '\u{16b3b}'), ('\u{16b44}', '\u{16b44}'), ('\u{1bc9f}', '\u{1bc9f}'),
+        ('\u{1da87}', '\u{1da8b}')
+    ];
+
+    pub const Pc_table: &'static [(char, char)] = &[
+        ('\u{5f}', '\u{5f}'), ('\u{203f}', '\u{2040}'), ('\u{2054}',
+        '\u{2054}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'),
+        ('\u{ff3f}', '\u{ff3f}')
+    ];
+
+    pub const Pd_table: &'static [(char, char)] = &[
+        ('\u{2d}', '\u{2d}'), ('\u{58a}', '\u{58a}'), ('\u{5be}', '\u{5be}'),
+        ('\u{1400}', '\u{1400}'), ('\u{1806}', '\u{1806}'), ('\u{2010}',
+        '\u{2015}'), ('\u{2e17}', '\u{2e17}'), ('\u{2e1a}', '\u{2e1a}'),
+        ('\u{2e3a}', '\u{2e3b}'), ('\u{2e40}', '\u{2e40}'), ('\u{301c}',
+        '\u{301c}'), ('\u{3030}', '\u{3030}'), ('\u{30a0}', '\u{30a0}'),
+        ('\u{fe31}', '\u{fe32}'), ('\u{fe58}', '\u{fe58}'), ('\u{fe63}',
+        '\u{fe63}'), ('\u{ff0d}', '\u{ff0d}')
+    ];
+
+    pub const Pe_table: &'static [(char, char)] = &[
+        ('\u{29}', '\u{29}'), ('\u{5d}', '\u{5d}'), ('\u{7d}', '\u{7d}'),
+        ('\u{f3b}', '\u{f3b}'), ('\u{f3d}', '\u{f3d}'), ('\u{169c}',
+        '\u{169c}'), ('\u{2046}', '\u{2046}'), ('\u{207e}', '\u{207e}'),
+        ('\u{208e}', '\u{208e}'), ('\u{2309}', '\u{2309}'), ('\u{230b}',
+        '\u{230b}'), ('\u{232a}', '\u{232a}'), ('\u{2769}', '\u{2769}'),
+        ('\u{276b}', '\u{276b}'), ('\u{276d}', '\u{276d}'), ('\u{276f}',
+        '\u{276f}'), ('\u{2771}', '\u{2771}'), ('\u{2773}', '\u{2773}'),
+        ('\u{2775}', '\u{2775}'), ('\u{27c6}', '\u{27c6}'), ('\u{27e7}',
+        '\u{27e7}'), ('\u{27e9}', '\u{27e9}'), ('\u{27eb}', '\u{27eb}'),
+        ('\u{27ed}', '\u{27ed}'), ('\u{27ef}', '\u{27ef}'), ('\u{2984}',
+        '\u{2984}'), ('\u{2986}', '\u{2986}'), ('\u{2988}', '\u{2988}'),
+        ('\u{298a}', '\u{298a}'), ('\u{298c}', '\u{298c}'), ('\u{298e}',
+        '\u{298e}'), ('\u{2990}', '\u{2990}'), ('\u{2992}', '\u{2992}'),
+        ('\u{2994}', '\u{2994}'), ('\u{2996}', '\u{2996}'), ('\u{2998}',
+        '\u{2998}'), ('\u{29d9}', '\u{29d9}'), ('\u{29db}', '\u{29db}'),
+        ('\u{29fd}', '\u{29fd}'), ('\u{2e23}', '\u{2e23}'), ('\u{2e25}',
+        '\u{2e25}'), ('\u{2e27}', '\u{2e27}'), ('\u{2e29}', '\u{2e29}'),
+        ('\u{3009}', '\u{3009}'), ('\u{300b}', '\u{300b}'), ('\u{300d}',
+        '\u{300d}'), ('\u{300f}', '\u{300f}'), ('\u{3011}', '\u{3011}'),
+        ('\u{3015}', '\u{3015}'), ('\u{3017}', '\u{3017}'), ('\u{3019}',
+        '\u{3019}'), ('\u{301b}', '\u{301b}'), ('\u{301e}', '\u{301f}'),
+        ('\u{fd3e}', '\u{fd3e}'), ('\u{fe18}', '\u{fe18}'), ('\u{fe36}',
+        '\u{fe36}'), ('\u{fe38}', '\u{fe38}'), ('\u{fe3a}', '\u{fe3a}'),
+        ('\u{fe3c}', '\u{fe3c}'), ('\u{fe3e}', '\u{fe3e}'), ('\u{fe40}',
+        '\u{fe40}'), ('\u{fe42}', '\u{fe42}'), ('\u{fe44}', '\u{fe44}'),
+        ('\u{fe48}', '\u{fe48}'), ('\u{fe5a}', '\u{fe5a}'), ('\u{fe5c}',
+        '\u{fe5c}'), ('\u{fe5e}', '\u{fe5e}'), ('\u{ff09}', '\u{ff09}'),
+        ('\u{ff3d}', '\u{ff3d}'), ('\u{ff5d}', '\u{ff5d}'), ('\u{ff60}',
+        '\u{ff60}'), ('\u{ff63}', '\u{ff63}')
+    ];
+
+    pub const Pf_table: &'static [(char, char)] = &[
+        ('\u{bb}', '\u{bb}'), ('\u{2019}', '\u{2019}'), ('\u{201d}',
+        '\u{201d}'), ('\u{203a}', '\u{203a}'), ('\u{2e03}', '\u{2e03}'),
+        ('\u{2e05}', '\u{2e05}'), ('\u{2e0a}', '\u{2e0a}'), ('\u{2e0d}',
+        '\u{2e0d}'), ('\u{2e1d}', '\u{2e1d}'), ('\u{2e21}', '\u{2e21}')
+    ];
+
+    pub const Pi_table: &'static [(char, char)] = &[
+        ('\u{ab}', '\u{ab}'), ('\u{2018}', '\u{2018}'), ('\u{201b}',
+        '\u{201c}'), ('\u{201f}', '\u{201f}'), ('\u{2039}', '\u{2039}'),
+        ('\u{2e02}', '\u{2e02}'), ('\u{2e04}', '\u{2e04}'), ('\u{2e09}',
+        '\u{2e09}'), ('\u{2e0c}', '\u{2e0c}'), ('\u{2e1c}', '\u{2e1c}'),
+        ('\u{2e20}', '\u{2e20}')
+    ];
+
+    pub const Po_table: &'static [(char, char)] = &[
+        ('\u{21}', '\u{23}'), ('\u{25}', '\u{27}'), ('\u{2a}', '\u{2a}'),
+        ('\u{2c}', '\u{2c}'), ('\u{2e}', '\u{2f}'), ('\u{3a}', '\u{3b}'),
+        ('\u{3f}', '\u{40}'), ('\u{5c}', '\u{5c}'), ('\u{a1}', '\u{a1}'),
+        ('\u{a7}', '\u{a7}'), ('\u{b6}', '\u{b7}'), ('\u{bf}', '\u{bf}'),
+        ('\u{37e}', '\u{37e}'), ('\u{387}', '\u{387}'), ('\u{55a}', '\u{55f}'),
+        ('\u{589}', '\u{589}'), ('\u{5c0}', '\u{5c0}'), ('\u{5c3}', '\u{5c3}'),
+        ('\u{5c6}', '\u{5c6}'), ('\u{5f3}', '\u{5f4}'), ('\u{609}', '\u{60a}'),
+        ('\u{60c}', '\u{60d}'), ('\u{61b}', '\u{61b}'), ('\u{61e}', '\u{61f}'),
+        ('\u{66a}', '\u{66d}'), ('\u{6d4}', '\u{6d4}'), ('\u{700}', '\u{70d}'),
+        ('\u{7f7}', '\u{7f9}'), ('\u{830}', '\u{83e}'), ('\u{85e}', '\u{85e}'),
+        ('\u{964}', '\u{965}'), ('\u{970}', '\u{970}'), ('\u{af0}', '\u{af0}'),
+        ('\u{df4}', '\u{df4}'), ('\u{e4f}', '\u{e4f}'), ('\u{e5a}', '\u{e5b}'),
+        ('\u{f04}', '\u{f12}'), ('\u{f14}', '\u{f14}'), ('\u{f85}', '\u{f85}'),
+        ('\u{fd0}', '\u{fd4}'), ('\u{fd9}', '\u{fda}'), ('\u{104a}',
+        '\u{104f}'), ('\u{10fb}', '\u{10fb}'), ('\u{1360}', '\u{1368}'),
+        ('\u{166d}', '\u{166e}'), ('\u{16eb}', '\u{16ed}'), ('\u{1735}',
+        '\u{1736}'), ('\u{17d4}', '\u{17d6}'), ('\u{17d8}', '\u{17da}'),
+        ('\u{1800}', '\u{1805}'), ('\u{1807}', '\u{180a}'), ('\u{1944}',
+        '\u{1945}'), ('\u{1a1e}', '\u{1a1f}'), ('\u{1aa0}', '\u{1aa6}'),
+        ('\u{1aa8}', '\u{1aad}'), ('\u{1b5a}', '\u{1b60}'), ('\u{1bfc}',
+        '\u{1bff}'), ('\u{1c3b}', '\u{1c3f}'), ('\u{1c7e}', '\u{1c7f}'),
+        ('\u{1cc0}', '\u{1cc7}'), ('\u{1cd3}', '\u{1cd3}'), ('\u{2016}',
+        '\u{2017}'), ('\u{2020}', '\u{2027}'), ('\u{2030}', '\u{2038}'),
+        ('\u{203b}', '\u{203e}'), ('\u{2041}', '\u{2043}'), ('\u{2047}',
+        '\u{2051}'), ('\u{2053}', '\u{2053}'), ('\u{2055}', '\u{205e}'),
+        ('\u{2cf9}', '\u{2cfc}'), ('\u{2cfe}', '\u{2cff}'), ('\u{2d70}',
+        '\u{2d70}'), ('\u{2e00}', '\u{2e01}'), ('\u{2e06}', '\u{2e08}'),
+        ('\u{2e0b}', '\u{2e0b}'), ('\u{2e0e}', '\u{2e16}'), ('\u{2e18}',
+        '\u{2e19}'), ('\u{2e1b}', '\u{2e1b}'), ('\u{2e1e}', '\u{2e1f}'),
+        ('\u{2e2a}', '\u{2e2e}'), ('\u{2e30}', '\u{2e39}'), ('\u{2e3c}',
+        '\u{2e3f}'), ('\u{2e41}', '\u{2e41}'), ('\u{3001}', '\u{3003}'),
+        ('\u{303d}', '\u{303d}'), ('\u{30fb}', '\u{30fb}'), ('\u{a4fe}',
+        '\u{a4ff}'), ('\u{a60d}', '\u{a60f}'), ('\u{a673}', '\u{a673}'),
+        ('\u{a67e}', '\u{a67e}'), ('\u{a6f2}', '\u{a6f7}'), ('\u{a874}',
+        '\u{a877}'), ('\u{a8ce}', '\u{a8cf}'), ('\u{a8f8}', '\u{a8fa}'),
+        ('\u{a8fc}', '\u{a8fc}'), ('\u{a92e}', '\u{a92f}'), ('\u{a95f}',
+        '\u{a95f}'), ('\u{a9c1}', '\u{a9cd}'), ('\u{a9de}', '\u{a9df}'),
+        ('\u{aa5c}', '\u{aa5f}'), ('\u{aade}', '\u{aadf}'), ('\u{aaf0}',
+        '\u{aaf1}'), ('\u{abeb}', '\u{abeb}'), ('\u{fe10}', '\u{fe16}'),
+        ('\u{fe19}', '\u{fe19}'), ('\u{fe30}', '\u{fe30}'), ('\u{fe45}',
+        '\u{fe46}'), ('\u{fe49}', '\u{fe4c}'), ('\u{fe50}', '\u{fe52}'),
+        ('\u{fe54}', '\u{fe57}'), ('\u{fe5f}', '\u{fe61}'), ('\u{fe68}',
+        '\u{fe68}'), ('\u{fe6a}', '\u{fe6b}'), ('\u{ff01}', '\u{ff03}'),
+        ('\u{ff05}', '\u{ff07}'), ('\u{ff0a}', '\u{ff0a}'), ('\u{ff0c}',
+        '\u{ff0c}'), ('\u{ff0e}', '\u{ff0f}'), ('\u{ff1a}', '\u{ff1b}'),
+        ('\u{ff1f}', '\u{ff20}'), ('\u{ff3c}', '\u{ff3c}'), ('\u{ff61}',
+        '\u{ff61}'), ('\u{ff64}', '\u{ff65}'), ('\u{10100}', '\u{10102}'),
+        ('\u{1039f}', '\u{1039f}'), ('\u{103d0}', '\u{103d0}'), ('\u{1056f}',
+        '\u{1056f}'), ('\u{10857}', '\u{10857}'), ('\u{1091f}', '\u{1091f}'),
+        ('\u{1093f}', '\u{1093f}'), ('\u{10a50}', '\u{10a58}'), ('\u{10a7f}',
+        '\u{10a7f}'), ('\u{10af0}', '\u{10af6}'), ('\u{10b39}', '\u{10b3f}'),
+        ('\u{10b99}', '\u{10b9c}'), ('\u{11047}', '\u{1104d}'), ('\u{110bb}',
+        '\u{110bc}'), ('\u{110be}', '\u{110c1}'), ('\u{11140}', '\u{11143}'),
+        ('\u{11174}', '\u{11175}'), ('\u{111c5}', '\u{111c9}'), ('\u{111cd}',
+        '\u{111cd}'), ('\u{111db}', '\u{111db}'), ('\u{111dd}', '\u{111df}'),
+        ('\u{11238}', '\u{1123d}'), ('\u{112a9}', '\u{112a9}'), ('\u{114c6}',
+        '\u{114c6}'), ('\u{115c1}', '\u{115d7}'), ('\u{11641}', '\u{11643}'),
+        ('\u{1173c}', '\u{1173e}'), ('\u{12470}', '\u{12474}'), ('\u{16a6e}',
+        '\u{16a6f}'), ('\u{16af5}', '\u{16af5}'), ('\u{16b37}', '\u{16b3b}'),
+        ('\u{16b44}', '\u{16b44}'), ('\u{1bc9f}', '\u{1bc9f}'), ('\u{1da87}',
+        '\u{1da8b}')
+    ];
+
+    pub const Ps_table: &'static [(char, char)] = &[
+        ('\u{28}', '\u{28}'), ('\u{5b}', '\u{5b}'), ('\u{7b}', '\u{7b}'),
+        ('\u{f3a}', '\u{f3a}'), ('\u{f3c}', '\u{f3c}'), ('\u{169b}',
+        '\u{169b}'), ('\u{201a}', '\u{201a}'), ('\u{201e}', '\u{201e}'),
+        ('\u{2045}', '\u{2045}'), ('\u{207d}', '\u{207d}'), ('\u{208d}',
+        '\u{208d}'), ('\u{2308}', '\u{2308}'), ('\u{230a}', '\u{230a}'),
+        ('\u{2329}', '\u{2329}'), ('\u{2768}', '\u{2768}'), ('\u{276a}',
+        '\u{276a}'), ('\u{276c}', '\u{276c}'), ('\u{276e}', '\u{276e}'),
+        ('\u{2770}', '\u{2770}'), ('\u{2772}', '\u{2772}'), ('\u{2774}',
+        '\u{2774}'), ('\u{27c5}', '\u{27c5}'), ('\u{27e6}', '\u{27e6}'),
+        ('\u{27e8}', '\u{27e8}'), ('\u{27ea}', '\u{27ea}'), ('\u{27ec}',
+        '\u{27ec}'), ('\u{27ee}', '\u{27ee}'), ('\u{2983}', '\u{2983}'),
+        ('\u{2985}', '\u{2985}'), ('\u{2987}', '\u{2987}'), ('\u{2989}',
+        '\u{2989}'), ('\u{298b}', '\u{298b}'), ('\u{298d}', '\u{298d}'),
+        ('\u{298f}', '\u{298f}'), ('\u{2991}', '\u{2991}'), ('\u{2993}',
+        '\u{2993}'), ('\u{2995}', '\u{2995}'), ('\u{2997}', '\u{2997}'),
+        ('\u{29d8}', '\u{29d8}'), ('\u{29da}', '\u{29da}'), ('\u{29fc}',
+        '\u{29fc}'), ('\u{2e22}', '\u{2e22}'), ('\u{2e24}', '\u{2e24}'),
+        ('\u{2e26}', '\u{2e26}'), ('\u{2e28}', '\u{2e28}'), ('\u{2e42}',
+        '\u{2e42}'), ('\u{3008}', '\u{3008}'), ('\u{300a}', '\u{300a}'),
+        ('\u{300c}', '\u{300c}'), ('\u{300e}', '\u{300e}'), ('\u{3010}',
+        '\u{3010}'), ('\u{3014}', '\u{3014}'), ('\u{3016}', '\u{3016}'),
+        ('\u{3018}', '\u{3018}'), ('\u{301a}', '\u{301a}'), ('\u{301d}',
+        '\u{301d}'), ('\u{fd3f}', '\u{fd3f}'), ('\u{fe17}', '\u{fe17}'),
+        ('\u{fe35}', '\u{fe35}'), ('\u{fe37}', '\u{fe37}'), ('\u{fe39}',
+        '\u{fe39}'), ('\u{fe3b}', '\u{fe3b}'), ('\u{fe3d}', '\u{fe3d}'),
+        ('\u{fe3f}', '\u{fe3f}'), ('\u{fe41}', '\u{fe41}'), ('\u{fe43}',
+        '\u{fe43}'), ('\u{fe47}', '\u{fe47}'), ('\u{fe59}', '\u{fe59}'),
+        ('\u{fe5b}', '\u{fe5b}'), ('\u{fe5d}', '\u{fe5d}'), ('\u{ff08}',
+        '\u{ff08}'), ('\u{ff3b}', '\u{ff3b}'), ('\u{ff5b}', '\u{ff5b}'),
+        ('\u{ff5f}', '\u{ff5f}'), ('\u{ff62}', '\u{ff62}')
+    ];
+
+    pub const S_table: &'static [(char, char)] = &[
+        ('\u{24}', '\u{24}'), ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'),
+        ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{7c}', '\u{7c}'),
+        ('\u{7e}', '\u{7e}'), ('\u{a2}', '\u{a6}'), ('\u{a8}', '\u{a9}'),
+        ('\u{ac}', '\u{ac}'), ('\u{ae}', '\u{b1}'), ('\u{b4}', '\u{b4}'),
+        ('\u{b8}', '\u{b8}'), ('\u{d7}', '\u{d7}'), ('\u{f7}', '\u{f7}'),
+        ('\u{2c2}', '\u{2c5}'), ('\u{2d2}', '\u{2df}'), ('\u{2e5}', '\u{2eb}'),
+        ('\u{2ed}', '\u{2ed}'), ('\u{2ef}', '\u{2ff}'), ('\u{375}', '\u{375}'),
+        ('\u{384}', '\u{385}'), ('\u{3f6}', '\u{3f6}'), ('\u{482}', '\u{482}'),
+        ('\u{58d}', '\u{58f}'), ('\u{606}', '\u{608}'), ('\u{60b}', '\u{60b}'),
+        ('\u{60e}', '\u{60f}'), ('\u{6de}', '\u{6de}'), ('\u{6e9}', '\u{6e9}'),
+        ('\u{6fd}', '\u{6fe}'), ('\u{7f6}', '\u{7f6}'), ('\u{9f2}', '\u{9f3}'),
+        ('\u{9fa}', '\u{9fb}'), ('\u{af1}', '\u{af1}'), ('\u{b70}', '\u{b70}'),
+        ('\u{bf3}', '\u{bfa}'), ('\u{c7f}', '\u{c7f}'), ('\u{d79}', '\u{d79}'),
+        ('\u{e3f}', '\u{e3f}'), ('\u{f01}', '\u{f03}'), ('\u{f13}', '\u{f13}'),
+        ('\u{f15}', '\u{f17}'), ('\u{f1a}', '\u{f1f}'), ('\u{f34}', '\u{f34}'),
+        ('\u{f36}', '\u{f36}'), ('\u{f38}', '\u{f38}'), ('\u{fbe}', '\u{fc5}'),
+        ('\u{fc7}', '\u{fcc}'), ('\u{fce}', '\u{fcf}'), ('\u{fd5}', '\u{fd8}'),
+        ('\u{109e}', '\u{109f}'), ('\u{1390}', '\u{1399}'), ('\u{17db}',
+        '\u{17db}'), ('\u{1940}', '\u{1940}'), ('\u{19de}', '\u{19ff}'),
+        ('\u{1b61}', '\u{1b6a}'), ('\u{1b74}', '\u{1b7c}'), ('\u{1fbd}',
+        '\u{1fbd}'), ('\u{1fbf}', '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'),
+        ('\u{1fdd}', '\u{1fdf}'), ('\u{1fed}', '\u{1fef}'), ('\u{1ffd}',
+        '\u{1ffe}'), ('\u{2044}', '\u{2044}'), ('\u{2052}', '\u{2052}'),
+        ('\u{207a}', '\u{207c}'), ('\u{208a}', '\u{208c}'), ('\u{20a0}',
+        '\u{20be}'), ('\u{2100}', '\u{2101}'), ('\u{2103}', '\u{2106}'),
+        ('\u{2108}', '\u{2109}'), ('\u{2114}', '\u{2114}'), ('\u{2116}',
+        '\u{2118}'), ('\u{211e}', '\u{2123}'), ('\u{2125}', '\u{2125}'),
+        ('\u{2127}', '\u{2127}'), ('\u{2129}', '\u{2129}'), ('\u{212e}',
+        '\u{212e}'), ('\u{213a}', '\u{213b}'), ('\u{2140}', '\u{2144}'),
+        ('\u{214a}', '\u{214d}'), ('\u{214f}', '\u{214f}'), ('\u{218a}',
+        '\u{218b}'), ('\u{2190}', '\u{2307}'), ('\u{230c}', '\u{2328}'),
+        ('\u{232b}', '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}',
+        '\u{244a}'), ('\u{249c}', '\u{24e9}'), ('\u{2500}', '\u{2767}'),
+        ('\u{2794}', '\u{27c4}'), ('\u{27c7}', '\u{27e5}'), ('\u{27f0}',
+        '\u{2982}'), ('\u{2999}', '\u{29d7}'), ('\u{29dc}', '\u{29fb}'),
+        ('\u{29fe}', '\u{2b73}'), ('\u{2b76}', '\u{2b95}'), ('\u{2b98}',
+        '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'), ('\u{2bca}', '\u{2bd1}'),
+        ('\u{2bec}', '\u{2bef}'), ('\u{2ce5}', '\u{2cea}'), ('\u{2e80}',
+        '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}', '\u{2fd5}'),
+        ('\u{2ff0}', '\u{2ffb}'), ('\u{3004}', '\u{3004}'), ('\u{3012}',
+        '\u{3013}'), ('\u{3020}', '\u{3020}'), ('\u{3036}', '\u{3037}'),
+        ('\u{303e}', '\u{303f}'), ('\u{309b}', '\u{309c}'), ('\u{3190}',
+        '\u{3191}'), ('\u{3196}', '\u{319f}'), ('\u{31c0}', '\u{31e3}'),
+        ('\u{3200}', '\u{321e}'), ('\u{322a}', '\u{3247}'), ('\u{3250}',
+        '\u{3250}'), ('\u{3260}', '\u{327f}'), ('\u{328a}', '\u{32b0}'),
+        ('\u{32c0}', '\u{32fe}'), ('\u{3300}', '\u{33ff}'), ('\u{4dc0}',
+        '\u{4dff}'), ('\u{a490}', '\u{a4c6}'), ('\u{a700}', '\u{a716}'),
+        ('\u{a720}', '\u{a721}'), ('\u{a789}', '\u{a78a}'), ('\u{a828}',
+        '\u{a82b}'), ('\u{a836}', '\u{a839}'), ('\u{aa77}', '\u{aa79}'),
+        ('\u{ab5b}', '\u{ab5b}'), ('\u{fb29}', '\u{fb29}'), ('\u{fbb2}',
+        '\u{fbc1}'), ('\u{fdfc}', '\u{fdfd}'), ('\u{fe62}', '\u{fe62}'),
+        ('\u{fe64}', '\u{fe66}'), ('\u{fe69}', '\u{fe69}'), ('\u{ff04}',
+        '\u{ff04}'), ('\u{ff0b}', '\u{ff0b}'), ('\u{ff1c}', '\u{ff1e}'),
+        ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'), ('\u{ff5c}',
+        '\u{ff5c}'), ('\u{ff5e}', '\u{ff5e}'), ('\u{ffe0}', '\u{ffe6}'),
+        ('\u{ffe8}', '\u{ffee}'), ('\u{fffc}', '\u{fffd}'), ('\u{10137}',
+        '\u{1013f}'), ('\u{10179}', '\u{10189}'), ('\u{1018c}', '\u{1018c}'),
+        ('\u{10190}', '\u{1019b}'), ('\u{101a0}', '\u{101a0}'), ('\u{101d0}',
+        '\u{101fc}'), ('\u{10877}', '\u{10878}'), ('\u{10ac8}', '\u{10ac8}'),
+        ('\u{1173f}', '\u{1173f}'), ('\u{16b3c}', '\u{16b3f}'), ('\u{16b45}',
+        '\u{16b45}'), ('\u{1bc9c}', '\u{1bc9c}'), ('\u{1d000}', '\u{1d0f5}'),
+        ('\u{1d100}', '\u{1d126}'), ('\u{1d129}', '\u{1d164}'), ('\u{1d16a}',
+        '\u{1d16c}'), ('\u{1d183}', '\u{1d184}'), ('\u{1d18c}', '\u{1d1a9}'),
+        ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d200}', '\u{1d241}'), ('\u{1d245}',
+        '\u{1d245}'), ('\u{1d300}', '\u{1d356}'), ('\u{1d6c1}', '\u{1d6c1}'),
+        ('\u{1d6db}', '\u{1d6db}'), ('\u{1d6fb}', '\u{1d6fb}'), ('\u{1d715}',
+        '\u{1d715}'), ('\u{1d735}', '\u{1d735}'), ('\u{1d74f}', '\u{1d74f}'),
+        ('\u{1d76f}', '\u{1d76f}'), ('\u{1d789}', '\u{1d789}'), ('\u{1d7a9}',
+        '\u{1d7a9}'), ('\u{1d7c3}', '\u{1d7c3}'), ('\u{1d800}', '\u{1d9ff}'),
+        ('\u{1da37}', '\u{1da3a}'), ('\u{1da6d}', '\u{1da74}'), ('\u{1da76}',
+        '\u{1da83}'), ('\u{1da85}', '\u{1da86}'), ('\u{1eef0}', '\u{1eef1}'),
+        ('\u{1f000}', '\u{1f02b}'), ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}',
+        '\u{1f0ae}'), ('\u{1f0b1}', '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'),
+        ('\u{1f0d1}', '\u{1f0f5}'), ('\u{1f110}', '\u{1f12e}'), ('\u{1f130}',
+        '\u{1f16b}'), ('\u{1f170}', '\u{1f19a}'), ('\u{1f1e6}', '\u{1f202}'),
+        ('\u{1f210}', '\u{1f23a}'), ('\u{1f240}', '\u{1f248}'), ('\u{1f250}',
+        '\u{1f251}'), ('\u{1f300}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'),
+        ('\u{1f5a5}', '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}',
+        '\u{1f6f3}'), ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'),
+        ('\u{1f800}', '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}',
+        '\u{1f859}'), ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'),
+        ('\u{1f910}', '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}',
+        '\u{1f9c0}')
+    ];
+
+    pub const Sc_table: &'static [(char, char)] = &[
+        ('\u{24}', '\u{24}'), ('\u{a2}', '\u{a5}'), ('\u{58f}', '\u{58f}'),
+        ('\u{60b}', '\u{60b}'), ('\u{9f2}', '\u{9f3}'), ('\u{9fb}', '\u{9fb}'),
+        ('\u{af1}', '\u{af1}'), ('\u{bf9}', '\u{bf9}'), ('\u{e3f}', '\u{e3f}'),
+        ('\u{17db}', '\u{17db}'), ('\u{20a0}', '\u{20be}'), ('\u{a838}',
+        '\u{a838}'), ('\u{fdfc}', '\u{fdfc}'), ('\u{fe69}', '\u{fe69}'),
+        ('\u{ff04}', '\u{ff04}'), ('\u{ffe0}', '\u{ffe1}'), ('\u{ffe5}',
+        '\u{ffe6}')
+    ];
+
+    pub const Sk_table: &'static [(char, char)] = &[
+        ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{a8}', '\u{a8}'),
+        ('\u{af}', '\u{af}'), ('\u{b4}', '\u{b4}'), ('\u{b8}', '\u{b8}'),
+        ('\u{2c2}', '\u{2c5}'), ('\u{2d2}', '\u{2df}'), ('\u{2e5}', '\u{2eb}'),
+        ('\u{2ed}', '\u{2ed}'), ('\u{2ef}', '\u{2ff}'), ('\u{375}', '\u{375}'),
+        ('\u{384}', '\u{385}'), ('\u{1fbd}', '\u{1fbd}'), ('\u{1fbf}',
+        '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'), ('\u{1fdd}', '\u{1fdf}'),
+        ('\u{1fed}', '\u{1fef}'), ('\u{1ffd}', '\u{1ffe}'), ('\u{309b}',
+        '\u{309c}'), ('\u{a700}', '\u{a716}'), ('\u{a720}', '\u{a721}'),
+        ('\u{a789}', '\u{a78a}'), ('\u{ab5b}', '\u{ab5b}'), ('\u{fbb2}',
+        '\u{fbc1}'), ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'),
+        ('\u{ffe3}', '\u{ffe3}'), ('\u{1f3fb}', '\u{1f3ff}')
+    ];
+
+    pub const Sm_table: &'static [(char, char)] = &[
+        ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'), ('\u{7c}', '\u{7c}'),
+        ('\u{7e}', '\u{7e}'), ('\u{ac}', '\u{ac}'), ('\u{b1}', '\u{b1}'),
+        ('\u{d7}', '\u{d7}'), ('\u{f7}', '\u{f7}'), ('\u{3f6}', '\u{3f6}'),
+        ('\u{606}', '\u{608}'), ('\u{2044}', '\u{2044}'), ('\u{2052}',
+        '\u{2052}'), ('\u{207a}', '\u{207c}'), ('\u{208a}', '\u{208c}'),
+        ('\u{2118}', '\u{2118}'), ('\u{2140}', '\u{2144}'), ('\u{214b}',
+        '\u{214b}'), ('\u{2190}', '\u{2194}'), ('\u{219a}', '\u{219b}'),
+        ('\u{21a0}', '\u{21a0}'), ('\u{21a3}', '\u{21a3}'), ('\u{21a6}',
+        '\u{21a6}'), ('\u{21ae}', '\u{21ae}'), ('\u{21ce}', '\u{21cf}'),
+        ('\u{21d2}', '\u{21d2}'), ('\u{21d4}', '\u{21d4}'), ('\u{21f4}',
+        '\u{22ff}'), ('\u{2320}', '\u{2321}'), ('\u{237c}', '\u{237c}'),
+        ('\u{239b}', '\u{23b3}'), ('\u{23dc}', '\u{23e1}'), ('\u{25b7}',
+        '\u{25b7}'), ('\u{25c1}', '\u{25c1}'), ('\u{25f8}', '\u{25ff}'),
+        ('\u{266f}', '\u{266f}'), ('\u{27c0}', '\u{27c4}'), ('\u{27c7}',
+        '\u{27e5}'), ('\u{27f0}', '\u{27ff}'), ('\u{2900}', '\u{2982}'),
+        ('\u{2999}', '\u{29d7}'), ('\u{29dc}', '\u{29fb}'), ('\u{29fe}',
+        '\u{2aff}'), ('\u{2b30}', '\u{2b44}'), ('\u{2b47}', '\u{2b4c}'),
+        ('\u{fb29}', '\u{fb29}'), ('\u{fe62}', '\u{fe62}'), ('\u{fe64}',
+        '\u{fe66}'), ('\u{ff0b}', '\u{ff0b}'), ('\u{ff1c}', '\u{ff1e}'),
+        ('\u{ff5c}', '\u{ff5c}'), ('\u{ff5e}', '\u{ff5e}'), ('\u{ffe2}',
+        '\u{ffe2}'), ('\u{ffe9}', '\u{ffec}'), ('\u{1d6c1}', '\u{1d6c1}'),
+        ('\u{1d6db}', '\u{1d6db}'), ('\u{1d6fb}', '\u{1d6fb}'), ('\u{1d715}',
+        '\u{1d715}'), ('\u{1d735}', '\u{1d735}'), ('\u{1d74f}', '\u{1d74f}'),
+        ('\u{1d76f}', '\u{1d76f}'), ('\u{1d789}', '\u{1d789}'), ('\u{1d7a9}',
+        '\u{1d7a9}'), ('\u{1d7c3}', '\u{1d7c3}'), ('\u{1eef0}', '\u{1eef1}')
+    ];
+
+    pub const So_table: &'static [(char, char)] = &[
+        ('\u{a6}', '\u{a6}'), ('\u{a9}', '\u{a9}'), ('\u{ae}', '\u{ae}'),
+        ('\u{b0}', '\u{b0}'), ('\u{482}', '\u{482}'), ('\u{58d}', '\u{58e}'),
+        ('\u{60e}', '\u{60f}'), ('\u{6de}', '\u{6de}'), ('\u{6e9}', '\u{6e9}'),
+        ('\u{6fd}', '\u{6fe}'), ('\u{7f6}', '\u{7f6}'), ('\u{9fa}', '\u{9fa}'),
+        ('\u{b70}', '\u{b70}'), ('\u{bf3}', '\u{bf8}'), ('\u{bfa}', '\u{bfa}'),
+        ('\u{c7f}', '\u{c7f}'), ('\u{d79}', '\u{d79}'), ('\u{f01}', '\u{f03}'),
+        ('\u{f13}', '\u{f13}'), ('\u{f15}', '\u{f17}'), ('\u{f1a}', '\u{f1f}'),
+        ('\u{f34}', '\u{f34}'), ('\u{f36}', '\u{f36}'), ('\u{f38}', '\u{f38}'),
+        ('\u{fbe}', '\u{fc5}'), ('\u{fc7}', '\u{fcc}'), ('\u{fce}', '\u{fcf}'),
+        ('\u{fd5}', '\u{fd8}'), ('\u{109e}', '\u{109f}'), ('\u{1390}',
+        '\u{1399}'), ('\u{1940}', '\u{1940}'), ('\u{19de}', '\u{19ff}'),
+        ('\u{1b61}', '\u{1b6a}'), ('\u{1b74}', '\u{1b7c}'), ('\u{2100}',
+        '\u{2101}'), ('\u{2103}', '\u{2106}'), ('\u{2108}', '\u{2109}'),
+        ('\u{2114}', '\u{2114}'), ('\u{2116}', '\u{2117}'), ('\u{211e}',
+        '\u{2123}'), ('\u{2125}', '\u{2125}'), ('\u{2127}', '\u{2127}'),
+        ('\u{2129}', '\u{2129}'), ('\u{212e}', '\u{212e}'), ('\u{213a}',
+        '\u{213b}'), ('\u{214a}', '\u{214a}'), ('\u{214c}', '\u{214d}'),
+        ('\u{214f}', '\u{214f}'), ('\u{218a}', '\u{218b}'), ('\u{2195}',
+        '\u{2199}'), ('\u{219c}', '\u{219f}'), ('\u{21a1}', '\u{21a2}'),
+        ('\u{21a4}', '\u{21a5}'), ('\u{21a7}', '\u{21ad}'), ('\u{21af}',
+        '\u{21cd}'), ('\u{21d0}', '\u{21d1}'), ('\u{21d3}', '\u{21d3}'),
+        ('\u{21d5}', '\u{21f3}'), ('\u{2300}', '\u{2307}'), ('\u{230c}',
+        '\u{231f}'), ('\u{2322}', '\u{2328}'), ('\u{232b}', '\u{237b}'),
+        ('\u{237d}', '\u{239a}'), ('\u{23b4}', '\u{23db}'), ('\u{23e2}',
+        '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}', '\u{244a}'),
+        ('\u{249c}', '\u{24e9}'), ('\u{2500}', '\u{25b6}'), ('\u{25b8}',
+        '\u{25c0}'), ('\u{25c2}', '\u{25f7}'), ('\u{2600}', '\u{266e}'),
+        ('\u{2670}', '\u{2767}'), ('\u{2794}', '\u{27bf}'), ('\u{2800}',
+        '\u{28ff}'), ('\u{2b00}', '\u{2b2f}'), ('\u{2b45}', '\u{2b46}'),
+        ('\u{2b4d}', '\u{2b73}'), ('\u{2b76}', '\u{2b95}'), ('\u{2b98}',
+        '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'), ('\u{2bca}', '\u{2bd1}'),
+        ('\u{2bec}', '\u{2bef}'), ('\u{2ce5}', '\u{2cea}'), ('\u{2e80}',
+        '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}', '\u{2fd5}'),
+        ('\u{2ff0}', '\u{2ffb}'), ('\u{3004}', '\u{3004}'), ('\u{3012}',
+        '\u{3013}'), ('\u{3020}', '\u{3020}'), ('\u{3036}', '\u{3037}'),
+        ('\u{303e}', '\u{303f}'), ('\u{3190}', '\u{3191}'), ('\u{3196}',
+        '\u{319f}'), ('\u{31c0}', '\u{31e3}'), ('\u{3200}', '\u{321e}'),
+        ('\u{322a}', '\u{3247}'), ('\u{3250}', '\u{3250}'), ('\u{3260}',
+        '\u{327f}'), ('\u{328a}', '\u{32b0}'), ('\u{32c0}', '\u{32fe}'),
+        ('\u{3300}', '\u{33ff}'), ('\u{4dc0}', '\u{4dff}'), ('\u{a490}',
+        '\u{a4c6}'), ('\u{a828}', '\u{a82b}'), ('\u{a836}', '\u{a837}'),
+        ('\u{a839}', '\u{a839}'), ('\u{aa77}', '\u{aa79}'), ('\u{fdfd}',
+        '\u{fdfd}'), ('\u{ffe4}', '\u{ffe4}'), ('\u{ffe8}', '\u{ffe8}'),
+        ('\u{ffed}', '\u{ffee}'), ('\u{fffc}', '\u{fffd}'), ('\u{10137}',
+        '\u{1013f}'), ('\u{10179}', '\u{10189}'), ('\u{1018c}', '\u{1018c}'),
+        ('\u{10190}', '\u{1019b}'), ('\u{101a0}', '\u{101a0}'), ('\u{101d0}',
+        '\u{101fc}'), ('\u{10877}', '\u{10878}'), ('\u{10ac8}', '\u{10ac8}'),
+        ('\u{1173f}', '\u{1173f}'), ('\u{16b3c}', '\u{16b3f}'), ('\u{16b45}',
+        '\u{16b45}'), ('\u{1bc9c}', '\u{1bc9c}'), ('\u{1d000}', '\u{1d0f5}'),
+        ('\u{1d100}', '\u{1d126}'), ('\u{1d129}', '\u{1d164}'), ('\u{1d16a}',
+        '\u{1d16c}'), ('\u{1d183}', '\u{1d184}'), ('\u{1d18c}', '\u{1d1a9}'),
+        ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d200}', '\u{1d241}'), ('\u{1d245}',
+        '\u{1d245}'), ('\u{1d300}', '\u{1d356}'), ('\u{1d800}', '\u{1d9ff}'),
+        ('\u{1da37}', '\u{1da3a}'), ('\u{1da6d}', '\u{1da74}'), ('\u{1da76}',
+        '\u{1da83}'), ('\u{1da85}', '\u{1da86}'), ('\u{1f000}', '\u{1f02b}'),
+        ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}', '\u{1f0ae}'), ('\u{1f0b1}',
+        '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'), ('\u{1f0d1}', '\u{1f0f5}'),
+        ('\u{1f110}', '\u{1f12e}'), ('\u{1f130}', '\u{1f16b}'), ('\u{1f170}',
+        '\u{1f19a}'), ('\u{1f1e6}', '\u{1f202}'), ('\u{1f210}', '\u{1f23a}'),
+        ('\u{1f240}', '\u{1f248}'), ('\u{1f250}', '\u{1f251}'), ('\u{1f300}',
+        '\u{1f3fa}'), ('\u{1f400}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'),
+        ('\u{1f5a5}', '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}',
+        '\u{1f6f3}'), ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'),
+        ('\u{1f800}', '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}',
+        '\u{1f859}'), ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'),
+        ('\u{1f910}', '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}',
+        '\u{1f9c0}')
+    ];
+
+    pub const Z_table: &'static [(char, char)] = &[
+        ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
+        ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}',
+        '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}')
+    ];
+
+    pub const Zl_table: &'static [(char, char)] = &[
+        ('\u{2028}', '\u{2028}')
+    ];
+
+    pub const Zp_table: &'static [(char, char)] = &[
+        ('\u{2029}', '\u{2029}')
+    ];
+
+    pub const Zs_table: &'static [(char, char)] = &[
+        ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
+        ('\u{2000}', '\u{200a}'), ('\u{202f}', '\u{202f}'), ('\u{205f}',
+        '\u{205f}'), ('\u{3000}', '\u{3000}')
+    ];
+
+}
+
+pub mod derived_property {
+    pub const Alphabetic_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
+        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
+        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
+        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
+        ('\u{345}', '\u{345}'), ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'),
+        ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'),
+        ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'),
+        ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'),
+        ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'),
+        ('\u{5b0}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'),
+        ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'),
+        ('\u{5f0}', '\u{5f2}'), ('\u{610}', '\u{61a}'), ('\u{620}', '\u{657}'),
+        ('\u{659}', '\u{65f}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'),
+        ('\u{6e1}', '\u{6e8}'), ('\u{6ed}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'),
+        ('\u{6ff}', '\u{6ff}'), ('\u{710}', '\u{73f}'), ('\u{74d}', '\u{7b1}'),
+        ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
+        ('\u{800}', '\u{817}'), ('\u{81a}', '\u{82c}'), ('\u{840}', '\u{858}'),
+        ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{8e9}'), ('\u{8f0}', '\u{93b}'),
+        ('\u{93d}', '\u{94c}'), ('\u{94e}', '\u{950}'), ('\u{955}', '\u{963}'),
+        ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
+        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
+        ('\u{9b6}', '\u{9b9}'), ('\u{9bd}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
+        ('\u{9cb}', '\u{9cc}'), ('\u{9ce}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'),
+        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e3}'), ('\u{9f0}', '\u{9f1}'),
+        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
+        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
+        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3e}', '\u{a42}'),
+        ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4c}'), ('\u{a51}', '\u{a51}'),
+        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a70}', '\u{a75}'),
+        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
+        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
+        ('\u{ab5}', '\u{ab9}'), ('\u{abd}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
+        ('\u{acb}', '\u{acc}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
+        ('\u{af9}', '\u{af9}'), ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'),
+        ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'),
+        ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b44}'),
+        ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4c}'), ('\u{b56}', '\u{b57}'),
+        ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'), ('\u{b71}', '\u{b71}'),
+        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
+        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
+        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
+        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
+        ('\u{bca}', '\u{bcc}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
+        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
+        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
+        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4c}'), ('\u{c55}', '\u{c56}'),
+        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c81}', '\u{c83}'),
+        ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'),
+        ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cc4}'),
+        ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccc}'), ('\u{cd5}', '\u{cd6}'),
+        ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{cf1}', '\u{cf2}'),
+        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
+        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
+        ('\u{d4a}', '\u{d4c}'), ('\u{d4e}', '\u{d4e}'), ('\u{d57}', '\u{d57}'),
+        ('\u{d5f}', '\u{d63}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'),
+        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
+        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dcf}', '\u{dd4}'),
+        ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'),
+        ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e46}'), ('\u{e4d}', '\u{e4d}'),
+        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
+        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
+        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
+        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'),
+        ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{ecd}', '\u{ecd}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
+        ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f81}'),
+        ('\u{f88}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{1000}',
+        '\u{1036}'), ('\u{1038}', '\u{1038}'), ('\u{103b}', '\u{103f}'),
+        ('\u{1050}', '\u{1062}'), ('\u{1065}', '\u{1068}'), ('\u{106e}',
+        '\u{1086}'), ('\u{108e}', '\u{108e}'), ('\u{109c}', '\u{109d}'),
+        ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}',
+        '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{1248}'),
+        ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}',
+        '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'),
+        ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}',
+        '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'),
+        ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}',
+        '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'),
+        ('\u{135f}', '\u{135f}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
+        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
+        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
+        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
+        ('\u{170e}', '\u{1713}'), ('\u{1720}', '\u{1733}'), ('\u{1740}',
+        '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
+        ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17b3}'), ('\u{17b6}',
+        '\u{17c8}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'),
+        ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}',
+        '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'),
+        ('\u{1930}', '\u{1938}'), ('\u{1950}', '\u{196d}'), ('\u{1970}',
+        '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'),
+        ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'), ('\u{1a61}',
+        '\u{1a74}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1b00}', '\u{1b33}'),
+        ('\u{1b35}', '\u{1b43}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b80}',
+        '\u{1ba9}'), ('\u{1bac}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
+        ('\u{1be7}', '\u{1bf1}'), ('\u{1c00}', '\u{1c35}'), ('\u{1c4d}',
+        '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'),
+        ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}',
+        '\u{1dbf}'), ('\u{1de7}', '\u{1df4}'), ('\u{1e00}', '\u{1f15}'),
+        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
+        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
+        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
+        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
+        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
+        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
+        '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
+        ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}',
+        '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'),
+        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
+        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
+        ('\u{212f}', '\u{2139}'), ('\u{213c}', '\u{213f}'), ('\u{2145}',
+        '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'),
+        ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}',
+        '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'),
+        ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}',
+        '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'),
+        ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}',
+        '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'),
+        ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}',
+        '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'),
+        ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}',
+        '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3031}', '\u{3035}'),
+        ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}',
+        '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'),
+        ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}',
+        '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'),
+        ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}',
+        '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'),
+        ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), ('\u{a674}',
+        '\u{a67b}'), ('\u{a67f}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'),
+        ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}',
+        '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
+        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a827}'), ('\u{a840}',
+        '\u{a873}'), ('\u{a880}', '\u{a8c3}'), ('\u{a8f2}', '\u{a8f7}'),
+        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
+        '\u{a92a}'), ('\u{a930}', '\u{a952}'), ('\u{a960}', '\u{a97c}'),
+        ('\u{a980}', '\u{a9b2}'), ('\u{a9b4}', '\u{a9bf}'), ('\u{a9cf}',
+        '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'),
+        ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'), ('\u{aa40}',
+        '\u{aa4d}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
+        ('\u{aa7e}', '\u{aabe}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}',
+        '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaef}'),
+        ('\u{aaf2}', '\u{aaf5}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}',
+        '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'),
+        ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}',
+        '\u{ab65}'), ('\u{ab70}', '\u{abea}'), ('\u{ac00}', '\u{d7a3}'),
+        ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}',
+        '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'),
+        ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}',
+        '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'),
+        ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}',
+        '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'),
+        ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}',
+        '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'),
+        ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}',
+        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
+        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
+        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
+        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
+        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'),
+        ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}',
+        '\u{1034a}'), ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'),
+        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}',
+        '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'),
+        ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
+        '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'),
+        ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}',
+        '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'),
+        ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}',
+        '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'),
+        ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
+        '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'),
+        ('\u{10a0c}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}',
+        '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'),
+        ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}',
+        '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'),
+        ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}',
+        '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{11000}', '\u{11045}'),
+        ('\u{11082}', '\u{110b8}'), ('\u{110d0}', '\u{110e8}'), ('\u{11100}',
+        '\u{11132}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'),
+        ('\u{11180}', '\u{111bf}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}',
+        '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'),
+        ('\u{11213}', '\u{11234}'), ('\u{11237}', '\u{11237}'), ('\u{11280}',
+        '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
+        ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}',
+        '\u{112e8}'), ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'),
+        ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}',
+        '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'),
+        ('\u{1133d}', '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}',
+        '\u{1134c}'), ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'),
+        ('\u{1135d}', '\u{11363}'), ('\u{11480}', '\u{114c1}'), ('\u{114c4}',
+        '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115b5}'),
+        ('\u{115b8}', '\u{115be}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}',
+        '\u{1163e}'), ('\u{11640}', '\u{11640}'), ('\u{11644}', '\u{11644}'),
+        ('\u{11680}', '\u{116b5}'), ('\u{11700}', '\u{11719}'), ('\u{1171d}',
+        '\u{1172a}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'),
+        ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}',
+        '\u{1246e}'), ('\u{12480}', '\u{12543}'), ('\u{13000}', '\u{1342e}'),
+        ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}',
+        '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}', '\u{16b36}'),
+        ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
+        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'),
+        ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}',
+        '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'),
+        ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9e}', '\u{1bc9e}'), ('\u{1d400}',
+        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
+        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
+        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
+        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
+        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
+        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
+        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
+        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
+        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
+        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
+        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
+        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}',
+        '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
+        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
+        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
+        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
+        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
+        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
+        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
+        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
+        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
+        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
+        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
+        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
+        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
+        ('\u{1eeab}', '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'), ('\u{1f150}',
+        '\u{1f169}'), ('\u{1f170}', '\u{1f189}'), ('\u{20000}', '\u{2a6d6}'),
+        ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}',
+        '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}')
+    ];
+
+    pub const Default_Ignorable_Code_Point_table: &'static [(char, char)] = &[
+        ('\u{ad}', '\u{ad}'), ('\u{34f}', '\u{34f}'), ('\u{61c}', '\u{61c}'),
+        ('\u{115f}', '\u{1160}'), ('\u{17b4}', '\u{17b5}'), ('\u{180b}',
+        '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
+        ('\u{2060}', '\u{206f}'), ('\u{3164}', '\u{3164}'), ('\u{fe00}',
+        '\u{fe0f}'), ('\u{feff}', '\u{feff}'), ('\u{ffa0}', '\u{ffa0}'),
+        ('\u{fff0}', '\u{fff8}'), ('\u{1bca0}', '\u{1bca3}'), ('\u{1d173}',
+        '\u{1d17a}'), ('\u{e0000}', '\u{e0fff}')
+    ];
+
+    pub const Grapheme_Extend_table: &'static [(char, char)] = &[
+        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'),
+        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
+        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
+        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
+        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
+        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
+        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
+        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{902}'),
+        ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}', '\u{948}'),
+        ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'),
+        ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9be}', '\u{9be}'),
+        ('\u{9c1}', '\u{9c4}'), ('\u{9cd}', '\u{9cd}'), ('\u{9d7}', '\u{9d7}'),
+        ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'), ('\u{a3c}', '\u{a3c}'),
+        ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
+        ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'), ('\u{a75}', '\u{a75}'),
+        ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'), ('\u{ac1}', '\u{ac5}'),
+        ('\u{ac7}', '\u{ac8}'), ('\u{acd}', '\u{acd}'), ('\u{ae2}', '\u{ae3}'),
+        ('\u{b01}', '\u{b01}'), ('\u{b3c}', '\u{b3c}'), ('\u{b3e}', '\u{b3f}'),
+        ('\u{b41}', '\u{b44}'), ('\u{b4d}', '\u{b4d}'), ('\u{b56}', '\u{b57}'),
+        ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'), ('\u{bbe}', '\u{bbe}'),
+        ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{bd7}', '\u{bd7}'),
+        ('\u{c00}', '\u{c00}'), ('\u{c3e}', '\u{c40}'), ('\u{c46}', '\u{c48}'),
+        ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'), ('\u{c62}', '\u{c63}'),
+        ('\u{c81}', '\u{c81}'), ('\u{cbc}', '\u{cbc}'), ('\u{cbf}', '\u{cbf}'),
+        ('\u{cc2}', '\u{cc2}'), ('\u{cc6}', '\u{cc6}'), ('\u{ccc}', '\u{ccd}'),
+        ('\u{cd5}', '\u{cd6}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d01}'),
+        ('\u{d3e}', '\u{d3e}'), ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'),
+        ('\u{d57}', '\u{d57}'), ('\u{d62}', '\u{d63}'), ('\u{dca}', '\u{dca}'),
+        ('\u{dcf}', '\u{dcf}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+        ('\u{ddf}', '\u{ddf}'), ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'),
+        ('\u{e47}', '\u{e4e}'), ('\u{eb1}', '\u{eb1}'), ('\u{eb4}', '\u{eb9}'),
+        ('\u{ebb}', '\u{ebc}'), ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'),
+        ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'),
+        ('\u{f71}', '\u{f7e}'), ('\u{f80}', '\u{f84}'), ('\u{f86}', '\u{f87}'),
+        ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'),
+        ('\u{102d}', '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}',
+        '\u{103a}'), ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'),
+        ('\u{105e}', '\u{1060}'), ('\u{1071}', '\u{1074}'), ('\u{1082}',
+        '\u{1082}'), ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'),
+        ('\u{109d}', '\u{109d}'), ('\u{135d}', '\u{135f}'), ('\u{1712}',
+        '\u{1714}'), ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'),
+        ('\u{1772}', '\u{1773}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b7}',
+        '\u{17bd}'), ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', '\u{17d3}'),
+        ('\u{17dd}', '\u{17dd}'), ('\u{180b}', '\u{180d}'), ('\u{18a9}',
+        '\u{18a9}'), ('\u{1920}', '\u{1922}'), ('\u{1927}', '\u{1928}'),
+        ('\u{1932}', '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}',
+        '\u{1a18}'), ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'),
+        ('\u{1a58}', '\u{1a5e}'), ('\u{1a60}', '\u{1a60}'), ('\u{1a62}',
+        '\u{1a62}'), ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'),
+        ('\u{1a7f}', '\u{1a7f}'), ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}',
+        '\u{1b03}'), ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'),
+        ('\u{1b3c}', '\u{1b3c}'), ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}',
+        '\u{1b73}'), ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', '\u{1ba5}'),
+        ('\u{1ba8}', '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}',
+        '\u{1be6}'), ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'),
+        ('\u{1bef}', '\u{1bf1}'), ('\u{1c2c}', '\u{1c33}'), ('\u{1c36}',
+        '\u{1c37}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'),
+        ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}',
+        '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'),
+        ('\u{1dfc}', '\u{1dff}'), ('\u{200c}', '\u{200d}'), ('\u{20d0}',
+        '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}', '\u{2d7f}'),
+        ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302f}'), ('\u{3099}',
+        '\u{309a}'), ('\u{a66f}', '\u{a672}'), ('\u{a674}', '\u{a67d}'),
+        ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'), ('\u{a802}',
+        '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}', '\u{a80b}'),
+        ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'), ('\u{a8e0}',
+        '\u{a8f1}'), ('\u{a926}', '\u{a92d}'), ('\u{a947}', '\u{a951}'),
+        ('\u{a980}', '\u{a982}'), ('\u{a9b3}', '\u{a9b3}'), ('\u{a9b6}',
+        '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9e5}', '\u{a9e5}'),
+        ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'), ('\u{aa35}',
+        '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4c}'),
+        ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}',
+        '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'),
+        ('\u{aac1}', '\u{aac1}'), ('\u{aaec}', '\u{aaed}'), ('\u{aaf6}',
+        '\u{aaf6}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}', '\u{abe8}'),
+        ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'), ('\u{fe00}',
+        '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{ff9e}', '\u{ff9f}'),
+        ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}',
+        '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'),
+        ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}',
+        '\u{10a3f}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{11001}', '\u{11001}'),
+        ('\u{11038}', '\u{11046}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}',
+        '\u{110b6}'), ('\u{110b9}', '\u{110ba}'), ('\u{11100}', '\u{11102}'),
+        ('\u{11127}', '\u{1112b}'), ('\u{1112d}', '\u{11134}'), ('\u{11173}',
+        '\u{11173}'), ('\u{11180}', '\u{11181}'), ('\u{111b6}', '\u{111be}'),
+        ('\u{111ca}', '\u{111cc}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}',
+        '\u{11234}'), ('\u{11236}', '\u{11237}'), ('\u{112df}', '\u{112df}'),
+        ('\u{112e3}', '\u{112ea}'), ('\u{11300}', '\u{11301}'), ('\u{1133c}',
+        '\u{1133c}'), ('\u{1133e}', '\u{1133e}'), ('\u{11340}', '\u{11340}'),
+        ('\u{11357}', '\u{11357}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
+        '\u{11374}'), ('\u{114b0}', '\u{114b0}'), ('\u{114b3}', '\u{114b8}'),
+        ('\u{114ba}', '\u{114ba}'), ('\u{114bd}', '\u{114bd}'), ('\u{114bf}',
+        '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115af}', '\u{115af}'),
+        ('\u{115b2}', '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}',
+        '\u{115c0}'), ('\u{115dc}', '\u{115dd}'), ('\u{11633}', '\u{1163a}'),
+        ('\u{1163d}', '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}',
+        '\u{116ab}'), ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', '\u{116b5}'),
+        ('\u{116b7}', '\u{116b7}'), ('\u{1171d}', '\u{1171f}'), ('\u{11722}',
+        '\u{11725}'), ('\u{11727}', '\u{1172b}'), ('\u{16af0}', '\u{16af4}'),
+        ('\u{16b30}', '\u{16b36}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}',
+        '\u{1bc9e}'), ('\u{1d165}', '\u{1d165}'), ('\u{1d167}', '\u{1d169}'),
+        ('\u{1d16e}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}',
+        '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'),
+        ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}',
+        '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'),
+        ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{e0100}',
+        '\u{e01ef}')
+    ];
+
+    pub const Lowercase_table: &'static [(char, char)] = &[
+        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
+        ('\u{ba}', '\u{ba}'), ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'),
+        ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'), ('\u{105}', '\u{105}'),
+        ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'), ('\u{10b}', '\u{10b}'),
+        ('\u{10d}', '\u{10d}'), ('\u{10f}', '\u{10f}'), ('\u{111}', '\u{111}'),
+        ('\u{113}', '\u{113}'), ('\u{115}', '\u{115}'), ('\u{117}', '\u{117}'),
+        ('\u{119}', '\u{119}'), ('\u{11b}', '\u{11b}'), ('\u{11d}', '\u{11d}'),
+        ('\u{11f}', '\u{11f}'), ('\u{121}', '\u{121}'), ('\u{123}', '\u{123}'),
+        ('\u{125}', '\u{125}'), ('\u{127}', '\u{127}'), ('\u{129}', '\u{129}'),
+        ('\u{12b}', '\u{12b}'), ('\u{12d}', '\u{12d}'), ('\u{12f}', '\u{12f}'),
+        ('\u{131}', '\u{131}'), ('\u{133}', '\u{133}'), ('\u{135}', '\u{135}'),
+        ('\u{137}', '\u{138}'), ('\u{13a}', '\u{13a}'), ('\u{13c}', '\u{13c}'),
+        ('\u{13e}', '\u{13e}'), ('\u{140}', '\u{140}'), ('\u{142}', '\u{142}'),
+        ('\u{144}', '\u{144}'), ('\u{146}', '\u{146}'), ('\u{148}', '\u{149}'),
+        ('\u{14b}', '\u{14b}'), ('\u{14d}', '\u{14d}'), ('\u{14f}', '\u{14f}'),
+        ('\u{151}', '\u{151}'), ('\u{153}', '\u{153}'), ('\u{155}', '\u{155}'),
+        ('\u{157}', '\u{157}'), ('\u{159}', '\u{159}'), ('\u{15b}', '\u{15b}'),
+        ('\u{15d}', '\u{15d}'), ('\u{15f}', '\u{15f}'), ('\u{161}', '\u{161}'),
+        ('\u{163}', '\u{163}'), ('\u{165}', '\u{165}'), ('\u{167}', '\u{167}'),
+        ('\u{169}', '\u{169}'), ('\u{16b}', '\u{16b}'), ('\u{16d}', '\u{16d}'),
+        ('\u{16f}', '\u{16f}'), ('\u{171}', '\u{171}'), ('\u{173}', '\u{173}'),
+        ('\u{175}', '\u{175}'), ('\u{177}', '\u{177}'), ('\u{17a}', '\u{17a}'),
+        ('\u{17c}', '\u{17c}'), ('\u{17e}', '\u{180}'), ('\u{183}', '\u{183}'),
+        ('\u{185}', '\u{185}'), ('\u{188}', '\u{188}'), ('\u{18c}', '\u{18d}'),
+        ('\u{192}', '\u{192}'), ('\u{195}', '\u{195}'), ('\u{199}', '\u{19b}'),
+        ('\u{19e}', '\u{19e}'), ('\u{1a1}', '\u{1a1}'), ('\u{1a3}', '\u{1a3}'),
+        ('\u{1a5}', '\u{1a5}'), ('\u{1a8}', '\u{1a8}'), ('\u{1aa}', '\u{1ab}'),
+        ('\u{1ad}', '\u{1ad}'), ('\u{1b0}', '\u{1b0}'), ('\u{1b4}', '\u{1b4}'),
+        ('\u{1b6}', '\u{1b6}'), ('\u{1b9}', '\u{1ba}'), ('\u{1bd}', '\u{1bf}'),
+        ('\u{1c6}', '\u{1c6}'), ('\u{1c9}', '\u{1c9}'), ('\u{1cc}', '\u{1cc}'),
+        ('\u{1ce}', '\u{1ce}'), ('\u{1d0}', '\u{1d0}'), ('\u{1d2}', '\u{1d2}'),
+        ('\u{1d4}', '\u{1d4}'), ('\u{1d6}', '\u{1d6}'), ('\u{1d8}', '\u{1d8}'),
+        ('\u{1da}', '\u{1da}'), ('\u{1dc}', '\u{1dd}'), ('\u{1df}', '\u{1df}'),
+        ('\u{1e1}', '\u{1e1}'), ('\u{1e3}', '\u{1e3}'), ('\u{1e5}', '\u{1e5}'),
+        ('\u{1e7}', '\u{1e7}'), ('\u{1e9}', '\u{1e9}'), ('\u{1eb}', '\u{1eb}'),
+        ('\u{1ed}', '\u{1ed}'), ('\u{1ef}', '\u{1f0}'), ('\u{1f3}', '\u{1f3}'),
+        ('\u{1f5}', '\u{1f5}'), ('\u{1f9}', '\u{1f9}'), ('\u{1fb}', '\u{1fb}'),
+        ('\u{1fd}', '\u{1fd}'), ('\u{1ff}', '\u{1ff}'), ('\u{201}', '\u{201}'),
+        ('\u{203}', '\u{203}'), ('\u{205}', '\u{205}'), ('\u{207}', '\u{207}'),
+        ('\u{209}', '\u{209}'), ('\u{20b}', '\u{20b}'), ('\u{20d}', '\u{20d}'),
+        ('\u{20f}', '\u{20f}'), ('\u{211}', '\u{211}'), ('\u{213}', '\u{213}'),
+        ('\u{215}', '\u{215}'), ('\u{217}', '\u{217}'), ('\u{219}', '\u{219}'),
+        ('\u{21b}', '\u{21b}'), ('\u{21d}', '\u{21d}'), ('\u{21f}', '\u{21f}'),
+        ('\u{221}', '\u{221}'), ('\u{223}', '\u{223}'), ('\u{225}', '\u{225}'),
+        ('\u{227}', '\u{227}'), ('\u{229}', '\u{229}'), ('\u{22b}', '\u{22b}'),
+        ('\u{22d}', '\u{22d}'), ('\u{22f}', '\u{22f}'), ('\u{231}', '\u{231}'),
+        ('\u{233}', '\u{239}'), ('\u{23c}', '\u{23c}'), ('\u{23f}', '\u{240}'),
+        ('\u{242}', '\u{242}'), ('\u{247}', '\u{247}'), ('\u{249}', '\u{249}'),
+        ('\u{24b}', '\u{24b}'), ('\u{24d}', '\u{24d}'), ('\u{24f}', '\u{293}'),
+        ('\u{295}', '\u{2b8}'), ('\u{2c0}', '\u{2c1}'), ('\u{2e0}', '\u{2e4}'),
+        ('\u{345}', '\u{345}'), ('\u{371}', '\u{371}'), ('\u{373}', '\u{373}'),
+        ('\u{377}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{390}', '\u{390}'),
+        ('\u{3ac}', '\u{3ce}'), ('\u{3d0}', '\u{3d1}'), ('\u{3d5}', '\u{3d7}'),
+        ('\u{3d9}', '\u{3d9}'), ('\u{3db}', '\u{3db}'), ('\u{3dd}', '\u{3dd}'),
+        ('\u{3df}', '\u{3df}'), ('\u{3e1}', '\u{3e1}'), ('\u{3e3}', '\u{3e3}'),
+        ('\u{3e5}', '\u{3e5}'), ('\u{3e7}', '\u{3e7}'), ('\u{3e9}', '\u{3e9}'),
+        ('\u{3eb}', '\u{3eb}'), ('\u{3ed}', '\u{3ed}'), ('\u{3ef}', '\u{3f3}'),
+        ('\u{3f5}', '\u{3f5}'), ('\u{3f8}', '\u{3f8}'), ('\u{3fb}', '\u{3fc}'),
+        ('\u{430}', '\u{45f}'), ('\u{461}', '\u{461}'), ('\u{463}', '\u{463}'),
+        ('\u{465}', '\u{465}'), ('\u{467}', '\u{467}'), ('\u{469}', '\u{469}'),
+        ('\u{46b}', '\u{46b}'), ('\u{46d}', '\u{46d}'), ('\u{46f}', '\u{46f}'),
+        ('\u{471}', '\u{471}'), ('\u{473}', '\u{473}'), ('\u{475}', '\u{475}'),
+        ('\u{477}', '\u{477}'), ('\u{479}', '\u{479}'), ('\u{47b}', '\u{47b}'),
+        ('\u{47d}', '\u{47d}'), ('\u{47f}', '\u{47f}'), ('\u{481}', '\u{481}'),
+        ('\u{48b}', '\u{48b}'), ('\u{48d}', '\u{48d}'), ('\u{48f}', '\u{48f}'),
+        ('\u{491}', '\u{491}'), ('\u{493}', '\u{493}'), ('\u{495}', '\u{495}'),
+        ('\u{497}', '\u{497}'), ('\u{499}', '\u{499}'), ('\u{49b}', '\u{49b}'),
+        ('\u{49d}', '\u{49d}'), ('\u{49f}', '\u{49f}'), ('\u{4a1}', '\u{4a1}'),
+        ('\u{4a3}', '\u{4a3}'), ('\u{4a5}', '\u{4a5}'), ('\u{4a7}', '\u{4a7}'),
+        ('\u{4a9}', '\u{4a9}'), ('\u{4ab}', '\u{4ab}'), ('\u{4ad}', '\u{4ad}'),
+        ('\u{4af}', '\u{4af}'), ('\u{4b1}', '\u{4b1}'), ('\u{4b3}', '\u{4b3}'),
+        ('\u{4b5}', '\u{4b5}'), ('\u{4b7}', '\u{4b7}'), ('\u{4b9}', '\u{4b9}'),
+        ('\u{4bb}', '\u{4bb}'), ('\u{4bd}', '\u{4bd}'), ('\u{4bf}', '\u{4bf}'),
+        ('\u{4c2}', '\u{4c2}'), ('\u{4c4}', '\u{4c4}'), ('\u{4c6}', '\u{4c6}'),
+        ('\u{4c8}', '\u{4c8}'), ('\u{4ca}', '\u{4ca}'), ('\u{4cc}', '\u{4cc}'),
+        ('\u{4ce}', '\u{4cf}'), ('\u{4d1}', '\u{4d1}'), ('\u{4d3}', '\u{4d3}'),
+        ('\u{4d5}', '\u{4d5}'), ('\u{4d7}', '\u{4d7}'), ('\u{4d9}', '\u{4d9}'),
+        ('\u{4db}', '\u{4db}'), ('\u{4dd}', '\u{4dd}'), ('\u{4df}', '\u{4df}'),
+        ('\u{4e1}', '\u{4e1}'), ('\u{4e3}', '\u{4e3}'), ('\u{4e5}', '\u{4e5}'),
+        ('\u{4e7}', '\u{4e7}'), ('\u{4e9}', '\u{4e9}'), ('\u{4eb}', '\u{4eb}'),
+        ('\u{4ed}', '\u{4ed}'), ('\u{4ef}', '\u{4ef}'), ('\u{4f1}', '\u{4f1}'),
+        ('\u{4f3}', '\u{4f3}'), ('\u{4f5}', '\u{4f5}'), ('\u{4f7}', '\u{4f7}'),
+        ('\u{4f9}', '\u{4f9}'), ('\u{4fb}', '\u{4fb}'), ('\u{4fd}', '\u{4fd}'),
+        ('\u{4ff}', '\u{4ff}'), ('\u{501}', '\u{501}'), ('\u{503}', '\u{503}'),
+        ('\u{505}', '\u{505}'), ('\u{507}', '\u{507}'), ('\u{509}', '\u{509}'),
+        ('\u{50b}', '\u{50b}'), ('\u{50d}', '\u{50d}'), ('\u{50f}', '\u{50f}'),
+        ('\u{511}', '\u{511}'), ('\u{513}', '\u{513}'), ('\u{515}', '\u{515}'),
+        ('\u{517}', '\u{517}'), ('\u{519}', '\u{519}'), ('\u{51b}', '\u{51b}'),
+        ('\u{51d}', '\u{51d}'), ('\u{51f}', '\u{51f}'), ('\u{521}', '\u{521}'),
+        ('\u{523}', '\u{523}'), ('\u{525}', '\u{525}'), ('\u{527}', '\u{527}'),
+        ('\u{529}', '\u{529}'), ('\u{52b}', '\u{52b}'), ('\u{52d}', '\u{52d}'),
+        ('\u{52f}', '\u{52f}'), ('\u{561}', '\u{587}'), ('\u{13f8}',
+        '\u{13fd}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e01}', '\u{1e01}'),
+        ('\u{1e03}', '\u{1e03}'), ('\u{1e05}', '\u{1e05}'), ('\u{1e07}',
+        '\u{1e07}'), ('\u{1e09}', '\u{1e09}'), ('\u{1e0b}', '\u{1e0b}'),
+        ('\u{1e0d}', '\u{1e0d}'), ('\u{1e0f}', '\u{1e0f}'), ('\u{1e11}',
+        '\u{1e11}'), ('\u{1e13}', '\u{1e13}'), ('\u{1e15}', '\u{1e15}'),
+        ('\u{1e17}', '\u{1e17}'), ('\u{1e19}', '\u{1e19}'), ('\u{1e1b}',
+        '\u{1e1b}'), ('\u{1e1d}', '\u{1e1d}'), ('\u{1e1f}', '\u{1e1f}'),
+        ('\u{1e21}', '\u{1e21}'), ('\u{1e23}', '\u{1e23}'), ('\u{1e25}',
+        '\u{1e25}'), ('\u{1e27}', '\u{1e27}'), ('\u{1e29}', '\u{1e29}'),
+        ('\u{1e2b}', '\u{1e2b}'), ('\u{1e2d}', '\u{1e2d}'), ('\u{1e2f}',
+        '\u{1e2f}'), ('\u{1e31}', '\u{1e31}'), ('\u{1e33}', '\u{1e33}'),
+        ('\u{1e35}', '\u{1e35}'), ('\u{1e37}', '\u{1e37}'), ('\u{1e39}',
+        '\u{1e39}'), ('\u{1e3b}', '\u{1e3b}'), ('\u{1e3d}', '\u{1e3d}'),
+        ('\u{1e3f}', '\u{1e3f}'), ('\u{1e41}', '\u{1e41}'), ('\u{1e43}',
+        '\u{1e43}'), ('\u{1e45}', '\u{1e45}'), ('\u{1e47}', '\u{1e47}'),
+        ('\u{1e49}', '\u{1e49}'), ('\u{1e4b}', '\u{1e4b}'), ('\u{1e4d}',
+        '\u{1e4d}'), ('\u{1e4f}', '\u{1e4f}'), ('\u{1e51}', '\u{1e51}'),
+        ('\u{1e53}', '\u{1e53}'), ('\u{1e55}', '\u{1e55}'), ('\u{1e57}',
+        '\u{1e57}'), ('\u{1e59}', '\u{1e59}'), ('\u{1e5b}', '\u{1e5b}'),
+        ('\u{1e5d}', '\u{1e5d}'), ('\u{1e5f}', '\u{1e5f}'), ('\u{1e61}',
+        '\u{1e61}'), ('\u{1e63}', '\u{1e63}'), ('\u{1e65}', '\u{1e65}'),
+        ('\u{1e67}', '\u{1e67}'), ('\u{1e69}', '\u{1e69}'), ('\u{1e6b}',
+        '\u{1e6b}'), ('\u{1e6d}', '\u{1e6d}'), ('\u{1e6f}', '\u{1e6f}'),
+        ('\u{1e71}', '\u{1e71}'), ('\u{1e73}', '\u{1e73}'), ('\u{1e75}',
+        '\u{1e75}'), ('\u{1e77}', '\u{1e77}'), ('\u{1e79}', '\u{1e79}'),
+        ('\u{1e7b}', '\u{1e7b}'), ('\u{1e7d}', '\u{1e7d}'), ('\u{1e7f}',
+        '\u{1e7f}'), ('\u{1e81}', '\u{1e81}'), ('\u{1e83}', '\u{1e83}'),
+        ('\u{1e85}', '\u{1e85}'), ('\u{1e87}', '\u{1e87}'), ('\u{1e89}',
+        '\u{1e89}'), ('\u{1e8b}', '\u{1e8b}'), ('\u{1e8d}', '\u{1e8d}'),
+        ('\u{1e8f}', '\u{1e8f}'), ('\u{1e91}', '\u{1e91}'), ('\u{1e93}',
+        '\u{1e93}'), ('\u{1e95}', '\u{1e9d}'), ('\u{1e9f}', '\u{1e9f}'),
+        ('\u{1ea1}', '\u{1ea1}'), ('\u{1ea3}', '\u{1ea3}'), ('\u{1ea5}',
+        '\u{1ea5}'), ('\u{1ea7}', '\u{1ea7}'), ('\u{1ea9}', '\u{1ea9}'),
+        ('\u{1eab}', '\u{1eab}'), ('\u{1ead}', '\u{1ead}'), ('\u{1eaf}',
+        '\u{1eaf}'), ('\u{1eb1}', '\u{1eb1}'), ('\u{1eb3}', '\u{1eb3}'),
+        ('\u{1eb5}', '\u{1eb5}'), ('\u{1eb7}', '\u{1eb7}'), ('\u{1eb9}',
+        '\u{1eb9}'), ('\u{1ebb}', '\u{1ebb}'), ('\u{1ebd}', '\u{1ebd}'),
+        ('\u{1ebf}', '\u{1ebf}'), ('\u{1ec1}', '\u{1ec1}'), ('\u{1ec3}',
+        '\u{1ec3}'), ('\u{1ec5}', '\u{1ec5}'), ('\u{1ec7}', '\u{1ec7}'),
+        ('\u{1ec9}', '\u{1ec9}'), ('\u{1ecb}', '\u{1ecb}'), ('\u{1ecd}',
+        '\u{1ecd}'), ('\u{1ecf}', '\u{1ecf}'), ('\u{1ed1}', '\u{1ed1}'),
+        ('\u{1ed3}', '\u{1ed3}'), ('\u{1ed5}', '\u{1ed5}'), ('\u{1ed7}',
+        '\u{1ed7}'), ('\u{1ed9}', '\u{1ed9}'), ('\u{1edb}', '\u{1edb}'),
+        ('\u{1edd}', '\u{1edd}'), ('\u{1edf}', '\u{1edf}'), ('\u{1ee1}',
+        '\u{1ee1}'), ('\u{1ee3}', '\u{1ee3}'), ('\u{1ee5}', '\u{1ee5}'),
+        ('\u{1ee7}', '\u{1ee7}'), ('\u{1ee9}', '\u{1ee9}'), ('\u{1eeb}',
+        '\u{1eeb}'), ('\u{1eed}', '\u{1eed}'), ('\u{1eef}', '\u{1eef}'),
+        ('\u{1ef1}', '\u{1ef1}'), ('\u{1ef3}', '\u{1ef3}'), ('\u{1ef5}',
+        '\u{1ef5}'), ('\u{1ef7}', '\u{1ef7}'), ('\u{1ef9}', '\u{1ef9}'),
+        ('\u{1efb}', '\u{1efb}'), ('\u{1efd}', '\u{1efd}'), ('\u{1eff}',
+        '\u{1f07}'), ('\u{1f10}', '\u{1f15}'), ('\u{1f20}', '\u{1f27}'),
+        ('\u{1f30}', '\u{1f37}'), ('\u{1f40}', '\u{1f45}'), ('\u{1f50}',
+        '\u{1f57}'), ('\u{1f60}', '\u{1f67}'), ('\u{1f70}', '\u{1f7d}'),
+        ('\u{1f80}', '\u{1f87}'), ('\u{1f90}', '\u{1f97}'), ('\u{1fa0}',
+        '\u{1fa7}'), ('\u{1fb0}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fb7}'),
+        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fc7}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fd7}'),
+        ('\u{1fe0}', '\u{1fe7}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
+        '\u{1ff7}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
+        ('\u{2090}', '\u{209c}'), ('\u{210a}', '\u{210a}'), ('\u{210e}',
+        '\u{210f}'), ('\u{2113}', '\u{2113}'), ('\u{212f}', '\u{212f}'),
+        ('\u{2134}', '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}',
+        '\u{213d}'), ('\u{2146}', '\u{2149}'), ('\u{214e}', '\u{214e}'),
+        ('\u{2170}', '\u{217f}'), ('\u{2184}', '\u{2184}'), ('\u{24d0}',
+        '\u{24e9}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c61}', '\u{2c61}'),
+        ('\u{2c65}', '\u{2c66}'), ('\u{2c68}', '\u{2c68}'), ('\u{2c6a}',
+        '\u{2c6a}'), ('\u{2c6c}', '\u{2c6c}'), ('\u{2c71}', '\u{2c71}'),
+        ('\u{2c73}', '\u{2c74}'), ('\u{2c76}', '\u{2c7d}'), ('\u{2c81}',
+        '\u{2c81}'), ('\u{2c83}', '\u{2c83}'), ('\u{2c85}', '\u{2c85}'),
+        ('\u{2c87}', '\u{2c87}'), ('\u{2c89}', '\u{2c89}'), ('\u{2c8b}',
+        '\u{2c8b}'), ('\u{2c8d}', '\u{2c8d}'), ('\u{2c8f}', '\u{2c8f}'),
+        ('\u{2c91}', '\u{2c91}'), ('\u{2c93}', '\u{2c93}'), ('\u{2c95}',
+        '\u{2c95}'), ('\u{2c97}', '\u{2c97}'), ('\u{2c99}', '\u{2c99}'),
+        ('\u{2c9b}', '\u{2c9b}'), ('\u{2c9d}', '\u{2c9d}'), ('\u{2c9f}',
+        '\u{2c9f}'), ('\u{2ca1}', '\u{2ca1}'), ('\u{2ca3}', '\u{2ca3}'),
+        ('\u{2ca5}', '\u{2ca5}'), ('\u{2ca7}', '\u{2ca7}'), ('\u{2ca9}',
+        '\u{2ca9}'), ('\u{2cab}', '\u{2cab}'), ('\u{2cad}', '\u{2cad}'),
+        ('\u{2caf}', '\u{2caf}'), ('\u{2cb1}', '\u{2cb1}'), ('\u{2cb3}',
+        '\u{2cb3}'), ('\u{2cb5}', '\u{2cb5}'), ('\u{2cb7}', '\u{2cb7}'),
+        ('\u{2cb9}', '\u{2cb9}'), ('\u{2cbb}', '\u{2cbb}'), ('\u{2cbd}',
+        '\u{2cbd}'), ('\u{2cbf}', '\u{2cbf}'), ('\u{2cc1}', '\u{2cc1}'),
+        ('\u{2cc3}', '\u{2cc3}'), ('\u{2cc5}', '\u{2cc5}'), ('\u{2cc7}',
+        '\u{2cc7}'), ('\u{2cc9}', '\u{2cc9}'), ('\u{2ccb}', '\u{2ccb}'),
+        ('\u{2ccd}', '\u{2ccd}'), ('\u{2ccf}', '\u{2ccf}'), ('\u{2cd1}',
+        '\u{2cd1}'), ('\u{2cd3}', '\u{2cd3}'), ('\u{2cd5}', '\u{2cd5}'),
+        ('\u{2cd7}', '\u{2cd7}'), ('\u{2cd9}', '\u{2cd9}'), ('\u{2cdb}',
+        '\u{2cdb}'), ('\u{2cdd}', '\u{2cdd}'), ('\u{2cdf}', '\u{2cdf}'),
+        ('\u{2ce1}', '\u{2ce1}'), ('\u{2ce3}', '\u{2ce4}'), ('\u{2cec}',
+        '\u{2cec}'), ('\u{2cee}', '\u{2cee}'), ('\u{2cf3}', '\u{2cf3}'),
+        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
+        '\u{2d2d}'), ('\u{a641}', '\u{a641}'), ('\u{a643}', '\u{a643}'),
+        ('\u{a645}', '\u{a645}'), ('\u{a647}', '\u{a647}'), ('\u{a649}',
+        '\u{a649}'), ('\u{a64b}', '\u{a64b}'), ('\u{a64d}', '\u{a64d}'),
+        ('\u{a64f}', '\u{a64f}'), ('\u{a651}', '\u{a651}'), ('\u{a653}',
+        '\u{a653}'), ('\u{a655}', '\u{a655}'), ('\u{a657}', '\u{a657}'),
+        ('\u{a659}', '\u{a659}'), ('\u{a65b}', '\u{a65b}'), ('\u{a65d}',
+        '\u{a65d}'), ('\u{a65f}', '\u{a65f}'), ('\u{a661}', '\u{a661}'),
+        ('\u{a663}', '\u{a663}'), ('\u{a665}', '\u{a665}'), ('\u{a667}',
+        '\u{a667}'), ('\u{a669}', '\u{a669}'), ('\u{a66b}', '\u{a66b}'),
+        ('\u{a66d}', '\u{a66d}'), ('\u{a681}', '\u{a681}'), ('\u{a683}',
+        '\u{a683}'), ('\u{a685}', '\u{a685}'), ('\u{a687}', '\u{a687}'),
+        ('\u{a689}', '\u{a689}'), ('\u{a68b}', '\u{a68b}'), ('\u{a68d}',
+        '\u{a68d}'), ('\u{a68f}', '\u{a68f}'), ('\u{a691}', '\u{a691}'),
+        ('\u{a693}', '\u{a693}'), ('\u{a695}', '\u{a695}'), ('\u{a697}',
+        '\u{a697}'), ('\u{a699}', '\u{a699}'), ('\u{a69b}', '\u{a69d}'),
+        ('\u{a723}', '\u{a723}'), ('\u{a725}', '\u{a725}'), ('\u{a727}',
+        '\u{a727}'), ('\u{a729}', '\u{a729}'), ('\u{a72b}', '\u{a72b}'),
+        ('\u{a72d}', '\u{a72d}'), ('\u{a72f}', '\u{a731}'), ('\u{a733}',
+        '\u{a733}'), ('\u{a735}', '\u{a735}'), ('\u{a737}', '\u{a737}'),
+        ('\u{a739}', '\u{a739}'), ('\u{a73b}', '\u{a73b}'), ('\u{a73d}',
+        '\u{a73d}'), ('\u{a73f}', '\u{a73f}'), ('\u{a741}', '\u{a741}'),
+        ('\u{a743}', '\u{a743}'), ('\u{a745}', '\u{a745}'), ('\u{a747}',
+        '\u{a747}'), ('\u{a749}', '\u{a749}'), ('\u{a74b}', '\u{a74b}'),
+        ('\u{a74d}', '\u{a74d}'), ('\u{a74f}', '\u{a74f}'), ('\u{a751}',
+        '\u{a751}'), ('\u{a753}', '\u{a753}'), ('\u{a755}', '\u{a755}'),
+        ('\u{a757}', '\u{a757}'), ('\u{a759}', '\u{a759}'), ('\u{a75b}',
+        '\u{a75b}'), ('\u{a75d}', '\u{a75d}'), ('\u{a75f}', '\u{a75f}'),
+        ('\u{a761}', '\u{a761}'), ('\u{a763}', '\u{a763}'), ('\u{a765}',
+        '\u{a765}'), ('\u{a767}', '\u{a767}'), ('\u{a769}', '\u{a769}'),
+        ('\u{a76b}', '\u{a76b}'), ('\u{a76d}', '\u{a76d}'), ('\u{a76f}',
+        '\u{a778}'), ('\u{a77a}', '\u{a77a}'), ('\u{a77c}', '\u{a77c}'),
+        ('\u{a77f}', '\u{a77f}'), ('\u{a781}', '\u{a781}'), ('\u{a783}',
+        '\u{a783}'), ('\u{a785}', '\u{a785}'), ('\u{a787}', '\u{a787}'),
+        ('\u{a78c}', '\u{a78c}'), ('\u{a78e}', '\u{a78e}'), ('\u{a791}',
+        '\u{a791}'), ('\u{a793}', '\u{a795}'), ('\u{a797}', '\u{a797}'),
+        ('\u{a799}', '\u{a799}'), ('\u{a79b}', '\u{a79b}'), ('\u{a79d}',
+        '\u{a79d}'), ('\u{a79f}', '\u{a79f}'), ('\u{a7a1}', '\u{a7a1}'),
+        ('\u{a7a3}', '\u{a7a3}'), ('\u{a7a5}', '\u{a7a5}'), ('\u{a7a7}',
+        '\u{a7a7}'), ('\u{a7a9}', '\u{a7a9}'), ('\u{a7b5}', '\u{a7b5}'),
+        ('\u{a7b7}', '\u{a7b7}'), ('\u{a7f8}', '\u{a7fa}'), ('\u{ab30}',
+        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abbf}'),
+        ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{ff41}',
+        '\u{ff5a}'), ('\u{10428}', '\u{1044f}'), ('\u{10cc0}', '\u{10cf2}'),
+        ('\u{118c0}', '\u{118df}'), ('\u{1d41a}', '\u{1d433}'), ('\u{1d44e}',
+        '\u{1d454}'), ('\u{1d456}', '\u{1d467}'), ('\u{1d482}', '\u{1d49b}'),
+        ('\u{1d4b6}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
+        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d4cf}'), ('\u{1d4ea}', '\u{1d503}'),
+        ('\u{1d51e}', '\u{1d537}'), ('\u{1d552}', '\u{1d56b}'), ('\u{1d586}',
+        '\u{1d59f}'), ('\u{1d5ba}', '\u{1d5d3}'), ('\u{1d5ee}', '\u{1d607}'),
+        ('\u{1d622}', '\u{1d63b}'), ('\u{1d656}', '\u{1d66f}'), ('\u{1d68a}',
+        '\u{1d6a5}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6e1}'),
+        ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d71b}'), ('\u{1d736}',
+        '\u{1d74e}'), ('\u{1d750}', '\u{1d755}'), ('\u{1d770}', '\u{1d788}'),
+        ('\u{1d78a}', '\u{1d78f}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}',
+        '\u{1d7c9}'), ('\u{1d7cb}', '\u{1d7cb}')
+    ];
+
+    pub const Uppercase_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'),
+        ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'),
+        ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'),
+        ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), ('\u{110}', '\u{110}'),
+        ('\u{112}', '\u{112}'), ('\u{114}', '\u{114}'), ('\u{116}', '\u{116}'),
+        ('\u{118}', '\u{118}'), ('\u{11a}', '\u{11a}'), ('\u{11c}', '\u{11c}'),
+        ('\u{11e}', '\u{11e}'), ('\u{120}', '\u{120}'), ('\u{122}', '\u{122}'),
+        ('\u{124}', '\u{124}'), ('\u{126}', '\u{126}'), ('\u{128}', '\u{128}'),
+        ('\u{12a}', '\u{12a}'), ('\u{12c}', '\u{12c}'), ('\u{12e}', '\u{12e}'),
+        ('\u{130}', '\u{130}'), ('\u{132}', '\u{132}'), ('\u{134}', '\u{134}'),
+        ('\u{136}', '\u{136}'), ('\u{139}', '\u{139}'), ('\u{13b}', '\u{13b}'),
+        ('\u{13d}', '\u{13d}'), ('\u{13f}', '\u{13f}'), ('\u{141}', '\u{141}'),
+        ('\u{143}', '\u{143}'), ('\u{145}', '\u{145}'), ('\u{147}', '\u{147}'),
+        ('\u{14a}', '\u{14a}'), ('\u{14c}', '\u{14c}'), ('\u{14e}', '\u{14e}'),
+        ('\u{150}', '\u{150}'), ('\u{152}', '\u{152}'), ('\u{154}', '\u{154}'),
+        ('\u{156}', '\u{156}'), ('\u{158}', '\u{158}'), ('\u{15a}', '\u{15a}'),
+        ('\u{15c}', '\u{15c}'), ('\u{15e}', '\u{15e}'), ('\u{160}', '\u{160}'),
+        ('\u{162}', '\u{162}'), ('\u{164}', '\u{164}'), ('\u{166}', '\u{166}'),
+        ('\u{168}', '\u{168}'), ('\u{16a}', '\u{16a}'), ('\u{16c}', '\u{16c}'),
+        ('\u{16e}', '\u{16e}'), ('\u{170}', '\u{170}'), ('\u{172}', '\u{172}'),
+        ('\u{174}', '\u{174}'), ('\u{176}', '\u{176}'), ('\u{178}', '\u{179}'),
+        ('\u{17b}', '\u{17b}'), ('\u{17d}', '\u{17d}'), ('\u{181}', '\u{182}'),
+        ('\u{184}', '\u{184}'), ('\u{186}', '\u{187}'), ('\u{189}', '\u{18b}'),
+        ('\u{18e}', '\u{191}'), ('\u{193}', '\u{194}'), ('\u{196}', '\u{198}'),
+        ('\u{19c}', '\u{19d}'), ('\u{19f}', '\u{1a0}'), ('\u{1a2}', '\u{1a2}'),
+        ('\u{1a4}', '\u{1a4}'), ('\u{1a6}', '\u{1a7}'), ('\u{1a9}', '\u{1a9}'),
+        ('\u{1ac}', '\u{1ac}'), ('\u{1ae}', '\u{1af}'), ('\u{1b1}', '\u{1b3}'),
+        ('\u{1b5}', '\u{1b5}'), ('\u{1b7}', '\u{1b8}'), ('\u{1bc}', '\u{1bc}'),
+        ('\u{1c4}', '\u{1c4}'), ('\u{1c7}', '\u{1c7}'), ('\u{1ca}', '\u{1ca}'),
+        ('\u{1cd}', '\u{1cd}'), ('\u{1cf}', '\u{1cf}'), ('\u{1d1}', '\u{1d1}'),
+        ('\u{1d3}', '\u{1d3}'), ('\u{1d5}', '\u{1d5}'), ('\u{1d7}', '\u{1d7}'),
+        ('\u{1d9}', '\u{1d9}'), ('\u{1db}', '\u{1db}'), ('\u{1de}', '\u{1de}'),
+        ('\u{1e0}', '\u{1e0}'), ('\u{1e2}', '\u{1e2}'), ('\u{1e4}', '\u{1e4}'),
+        ('\u{1e6}', '\u{1e6}'), ('\u{1e8}', '\u{1e8}'), ('\u{1ea}', '\u{1ea}'),
+        ('\u{1ec}', '\u{1ec}'), ('\u{1ee}', '\u{1ee}'), ('\u{1f1}', '\u{1f1}'),
+        ('\u{1f4}', '\u{1f4}'), ('\u{1f6}', '\u{1f8}'), ('\u{1fa}', '\u{1fa}'),
+        ('\u{1fc}', '\u{1fc}'), ('\u{1fe}', '\u{1fe}'), ('\u{200}', '\u{200}'),
+        ('\u{202}', '\u{202}'), ('\u{204}', '\u{204}'), ('\u{206}', '\u{206}'),
+        ('\u{208}', '\u{208}'), ('\u{20a}', '\u{20a}'), ('\u{20c}', '\u{20c}'),
+        ('\u{20e}', '\u{20e}'), ('\u{210}', '\u{210}'), ('\u{212}', '\u{212}'),
+        ('\u{214}', '\u{214}'), ('\u{216}', '\u{216}'), ('\u{218}', '\u{218}'),
+        ('\u{21a}', '\u{21a}'), ('\u{21c}', '\u{21c}'), ('\u{21e}', '\u{21e}'),
+        ('\u{220}', '\u{220}'), ('\u{222}', '\u{222}'), ('\u{224}', '\u{224}'),
+        ('\u{226}', '\u{226}'), ('\u{228}', '\u{228}'), ('\u{22a}', '\u{22a}'),
+        ('\u{22c}', '\u{22c}'), ('\u{22e}', '\u{22e}'), ('\u{230}', '\u{230}'),
+        ('\u{232}', '\u{232}'), ('\u{23a}', '\u{23b}'), ('\u{23d}', '\u{23e}'),
+        ('\u{241}', '\u{241}'), ('\u{243}', '\u{246}'), ('\u{248}', '\u{248}'),
+        ('\u{24a}', '\u{24a}'), ('\u{24c}', '\u{24c}'), ('\u{24e}', '\u{24e}'),
+        ('\u{370}', '\u{370}'), ('\u{372}', '\u{372}'), ('\u{376}', '\u{376}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
+        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{38f}'), ('\u{391}', '\u{3a1}'),
+        ('\u{3a3}', '\u{3ab}'), ('\u{3cf}', '\u{3cf}'), ('\u{3d2}', '\u{3d4}'),
+        ('\u{3d8}', '\u{3d8}'), ('\u{3da}', '\u{3da}'), ('\u{3dc}', '\u{3dc}'),
+        ('\u{3de}', '\u{3de}'), ('\u{3e0}', '\u{3e0}'), ('\u{3e2}', '\u{3e2}'),
+        ('\u{3e4}', '\u{3e4}'), ('\u{3e6}', '\u{3e6}'), ('\u{3e8}', '\u{3e8}'),
+        ('\u{3ea}', '\u{3ea}'), ('\u{3ec}', '\u{3ec}'), ('\u{3ee}', '\u{3ee}'),
+        ('\u{3f4}', '\u{3f4}'), ('\u{3f7}', '\u{3f7}'), ('\u{3f9}', '\u{3fa}'),
+        ('\u{3fd}', '\u{42f}'), ('\u{460}', '\u{460}'), ('\u{462}', '\u{462}'),
+        ('\u{464}', '\u{464}'), ('\u{466}', '\u{466}'), ('\u{468}', '\u{468}'),
+        ('\u{46a}', '\u{46a}'), ('\u{46c}', '\u{46c}'), ('\u{46e}', '\u{46e}'),
+        ('\u{470}', '\u{470}'), ('\u{472}', '\u{472}'), ('\u{474}', '\u{474}'),
+        ('\u{476}', '\u{476}'), ('\u{478}', '\u{478}'), ('\u{47a}', '\u{47a}'),
+        ('\u{47c}', '\u{47c}'), ('\u{47e}', '\u{47e}'), ('\u{480}', '\u{480}'),
+        ('\u{48a}', '\u{48a}'), ('\u{48c}', '\u{48c}'), ('\u{48e}', '\u{48e}'),
+        ('\u{490}', '\u{490}'), ('\u{492}', '\u{492}'), ('\u{494}', '\u{494}'),
+        ('\u{496}', '\u{496}'), ('\u{498}', '\u{498}'), ('\u{49a}', '\u{49a}'),
+        ('\u{49c}', '\u{49c}'), ('\u{49e}', '\u{49e}'), ('\u{4a0}', '\u{4a0}'),
+        ('\u{4a2}', '\u{4a2}'), ('\u{4a4}', '\u{4a4}'), ('\u{4a6}', '\u{4a6}'),
+        ('\u{4a8}', '\u{4a8}'), ('\u{4aa}', '\u{4aa}'), ('\u{4ac}', '\u{4ac}'),
+        ('\u{4ae}', '\u{4ae}'), ('\u{4b0}', '\u{4b0}'), ('\u{4b2}', '\u{4b2}'),
+        ('\u{4b4}', '\u{4b4}'), ('\u{4b6}', '\u{4b6}'), ('\u{4b8}', '\u{4b8}'),
+        ('\u{4ba}', '\u{4ba}'), ('\u{4bc}', '\u{4bc}'), ('\u{4be}', '\u{4be}'),
+        ('\u{4c0}', '\u{4c1}'), ('\u{4c3}', '\u{4c3}'), ('\u{4c5}', '\u{4c5}'),
+        ('\u{4c7}', '\u{4c7}'), ('\u{4c9}', '\u{4c9}'), ('\u{4cb}', '\u{4cb}'),
+        ('\u{4cd}', '\u{4cd}'), ('\u{4d0}', '\u{4d0}'), ('\u{4d2}', '\u{4d2}'),
+        ('\u{4d4}', '\u{4d4}'), ('\u{4d6}', '\u{4d6}'), ('\u{4d8}', '\u{4d8}'),
+        ('\u{4da}', '\u{4da}'), ('\u{4dc}', '\u{4dc}'), ('\u{4de}', '\u{4de}'),
+        ('\u{4e0}', '\u{4e0}'), ('\u{4e2}', '\u{4e2}'), ('\u{4e4}', '\u{4e4}'),
+        ('\u{4e6}', '\u{4e6}'), ('\u{4e8}', '\u{4e8}'), ('\u{4ea}', '\u{4ea}'),
+        ('\u{4ec}', '\u{4ec}'), ('\u{4ee}', '\u{4ee}'), ('\u{4f0}', '\u{4f0}'),
+        ('\u{4f2}', '\u{4f2}'), ('\u{4f4}', '\u{4f4}'), ('\u{4f6}', '\u{4f6}'),
+        ('\u{4f8}', '\u{4f8}'), ('\u{4fa}', '\u{4fa}'), ('\u{4fc}', '\u{4fc}'),
+        ('\u{4fe}', '\u{4fe}'), ('\u{500}', '\u{500}'), ('\u{502}', '\u{502}'),
+        ('\u{504}', '\u{504}'), ('\u{506}', '\u{506}'), ('\u{508}', '\u{508}'),
+        ('\u{50a}', '\u{50a}'), ('\u{50c}', '\u{50c}'), ('\u{50e}', '\u{50e}'),
+        ('\u{510}', '\u{510}'), ('\u{512}', '\u{512}'), ('\u{514}', '\u{514}'),
+        ('\u{516}', '\u{516}'), ('\u{518}', '\u{518}'), ('\u{51a}', '\u{51a}'),
+        ('\u{51c}', '\u{51c}'), ('\u{51e}', '\u{51e}'), ('\u{520}', '\u{520}'),
+        ('\u{522}', '\u{522}'), ('\u{524}', '\u{524}'), ('\u{526}', '\u{526}'),
+        ('\u{528}', '\u{528}'), ('\u{52a}', '\u{52a}'), ('\u{52c}', '\u{52c}'),
+        ('\u{52e}', '\u{52e}'), ('\u{531}', '\u{556}'), ('\u{10a0}',
+        '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'),
+        ('\u{13a0}', '\u{13f5}'), ('\u{1e00}', '\u{1e00}'), ('\u{1e02}',
+        '\u{1e02}'), ('\u{1e04}', '\u{1e04}'), ('\u{1e06}', '\u{1e06}'),
+        ('\u{1e08}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0a}'), ('\u{1e0c}',
+        '\u{1e0c}'), ('\u{1e0e}', '\u{1e0e}'), ('\u{1e10}', '\u{1e10}'),
+        ('\u{1e12}', '\u{1e12}'), ('\u{1e14}', '\u{1e14}'), ('\u{1e16}',
+        '\u{1e16}'), ('\u{1e18}', '\u{1e18}'), ('\u{1e1a}', '\u{1e1a}'),
+        ('\u{1e1c}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1e}'), ('\u{1e20}',
+        '\u{1e20}'), ('\u{1e22}', '\u{1e22}'), ('\u{1e24}', '\u{1e24}'),
+        ('\u{1e26}', '\u{1e26}'), ('\u{1e28}', '\u{1e28}'), ('\u{1e2a}',
+        '\u{1e2a}'), ('\u{1e2c}', '\u{1e2c}'), ('\u{1e2e}', '\u{1e2e}'),
+        ('\u{1e30}', '\u{1e30}'), ('\u{1e32}', '\u{1e32}'), ('\u{1e34}',
+        '\u{1e34}'), ('\u{1e36}', '\u{1e36}'), ('\u{1e38}', '\u{1e38}'),
+        ('\u{1e3a}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3c}'), ('\u{1e3e}',
+        '\u{1e3e}'), ('\u{1e40}', '\u{1e40}'), ('\u{1e42}', '\u{1e42}'),
+        ('\u{1e44}', '\u{1e44}'), ('\u{1e46}', '\u{1e46}'), ('\u{1e48}',
+        '\u{1e48}'), ('\u{1e4a}', '\u{1e4a}'), ('\u{1e4c}', '\u{1e4c}'),
+        ('\u{1e4e}', '\u{1e4e}'), ('\u{1e50}', '\u{1e50}'), ('\u{1e52}',
+        '\u{1e52}'), ('\u{1e54}', '\u{1e54}'), ('\u{1e56}', '\u{1e56}'),
+        ('\u{1e58}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5a}'), ('\u{1e5c}',
+        '\u{1e5c}'), ('\u{1e5e}', '\u{1e5e}'), ('\u{1e60}', '\u{1e60}'),
+        ('\u{1e62}', '\u{1e62}'), ('\u{1e64}', '\u{1e64}'), ('\u{1e66}',
+        '\u{1e66}'), ('\u{1e68}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6a}'),
+        ('\u{1e6c}', '\u{1e6c}'), ('\u{1e6e}', '\u{1e6e}'), ('\u{1e70}',
+        '\u{1e70}'), ('\u{1e72}', '\u{1e72}'), ('\u{1e74}', '\u{1e74}'),
+        ('\u{1e76}', '\u{1e76}'), ('\u{1e78}', '\u{1e78}'), ('\u{1e7a}',
+        '\u{1e7a}'), ('\u{1e7c}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7e}'),
+        ('\u{1e80}', '\u{1e80}'), ('\u{1e82}', '\u{1e82}'), ('\u{1e84}',
+        '\u{1e84}'), ('\u{1e86}', '\u{1e86}'), ('\u{1e88}', '\u{1e88}'),
+        ('\u{1e8a}', '\u{1e8a}'), ('\u{1e8c}', '\u{1e8c}'), ('\u{1e8e}',
+        '\u{1e8e}'), ('\u{1e90}', '\u{1e90}'), ('\u{1e92}', '\u{1e92}'),
+        ('\u{1e94}', '\u{1e94}'), ('\u{1e9e}', '\u{1e9e}'), ('\u{1ea0}',
+        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea2}'), ('\u{1ea4}', '\u{1ea4}'),
+        ('\u{1ea6}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea8}'), ('\u{1eaa}',
+        '\u{1eaa}'), ('\u{1eac}', '\u{1eac}'), ('\u{1eae}', '\u{1eae}'),
+        ('\u{1eb0}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb2}'), ('\u{1eb4}',
+        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb6}'), ('\u{1eb8}', '\u{1eb8}'),
+        ('\u{1eba}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebc}'), ('\u{1ebe}',
+        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec0}'), ('\u{1ec2}', '\u{1ec2}'),
+        ('\u{1ec4}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec6}'), ('\u{1ec8}',
+        '\u{1ec8}'), ('\u{1eca}', '\u{1eca}'), ('\u{1ecc}', '\u{1ecc}'),
+        ('\u{1ece}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed0}'), ('\u{1ed2}',
+        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed4}'), ('\u{1ed6}', '\u{1ed6}'),
+        ('\u{1ed8}', '\u{1ed8}'), ('\u{1eda}', '\u{1eda}'), ('\u{1edc}',
+        '\u{1edc}'), ('\u{1ede}', '\u{1ede}'), ('\u{1ee0}', '\u{1ee0}'),
+        ('\u{1ee2}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee4}'), ('\u{1ee6}',
+        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee8}'), ('\u{1eea}', '\u{1eea}'),
+        ('\u{1eec}', '\u{1eec}'), ('\u{1eee}', '\u{1eee}'), ('\u{1ef0}',
+        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef2}'), ('\u{1ef4}', '\u{1ef4}'),
+        ('\u{1ef6}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef8}'), ('\u{1efa}',
+        '\u{1efa}'), ('\u{1efc}', '\u{1efc}'), ('\u{1efe}', '\u{1efe}'),
+        ('\u{1f08}', '\u{1f0f}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f28}',
+        '\u{1f2f}'), ('\u{1f38}', '\u{1f3f}'), ('\u{1f48}', '\u{1f4d}'),
+        ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
+        '\u{1f5d}'), ('\u{1f5f}', '\u{1f5f}'), ('\u{1f68}', '\u{1f6f}'),
+        ('\u{1fb8}', '\u{1fbb}'), ('\u{1fc8}', '\u{1fcb}'), ('\u{1fd8}',
+        '\u{1fdb}'), ('\u{1fe8}', '\u{1fec}'), ('\u{1ff8}', '\u{1ffb}'),
+        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210b}',
+        '\u{210d}'), ('\u{2110}', '\u{2112}'), ('\u{2115}', '\u{2115}'),
+        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
+        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
+        ('\u{2130}', '\u{2133}'), ('\u{213e}', '\u{213f}'), ('\u{2145}',
+        '\u{2145}'), ('\u{2160}', '\u{216f}'), ('\u{2183}', '\u{2183}'),
+        ('\u{24b6}', '\u{24cf}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c60}',
+        '\u{2c60}'), ('\u{2c62}', '\u{2c64}'), ('\u{2c67}', '\u{2c67}'),
+        ('\u{2c69}', '\u{2c69}'), ('\u{2c6b}', '\u{2c6b}'), ('\u{2c6d}',
+        '\u{2c70}'), ('\u{2c72}', '\u{2c72}'), ('\u{2c75}', '\u{2c75}'),
+        ('\u{2c7e}', '\u{2c80}'), ('\u{2c82}', '\u{2c82}'), ('\u{2c84}',
+        '\u{2c84}'), ('\u{2c86}', '\u{2c86}'), ('\u{2c88}', '\u{2c88}'),
+        ('\u{2c8a}', '\u{2c8a}'), ('\u{2c8c}', '\u{2c8c}'), ('\u{2c8e}',
+        '\u{2c8e}'), ('\u{2c90}', '\u{2c90}'), ('\u{2c92}', '\u{2c92}'),
+        ('\u{2c94}', '\u{2c94}'), ('\u{2c96}', '\u{2c96}'), ('\u{2c98}',
+        '\u{2c98}'), ('\u{2c9a}', '\u{2c9a}'), ('\u{2c9c}', '\u{2c9c}'),
+        ('\u{2c9e}', '\u{2c9e}'), ('\u{2ca0}', '\u{2ca0}'), ('\u{2ca2}',
+        '\u{2ca2}'), ('\u{2ca4}', '\u{2ca4}'), ('\u{2ca6}', '\u{2ca6}'),
+        ('\u{2ca8}', '\u{2ca8}'), ('\u{2caa}', '\u{2caa}'), ('\u{2cac}',
+        '\u{2cac}'), ('\u{2cae}', '\u{2cae}'), ('\u{2cb0}', '\u{2cb0}'),
+        ('\u{2cb2}', '\u{2cb2}'), ('\u{2cb4}', '\u{2cb4}'), ('\u{2cb6}',
+        '\u{2cb6}'), ('\u{2cb8}', '\u{2cb8}'), ('\u{2cba}', '\u{2cba}'),
+        ('\u{2cbc}', '\u{2cbc}'), ('\u{2cbe}', '\u{2cbe}'), ('\u{2cc0}',
+        '\u{2cc0}'), ('\u{2cc2}', '\u{2cc2}'), ('\u{2cc4}', '\u{2cc4}'),
+        ('\u{2cc6}', '\u{2cc6}'), ('\u{2cc8}', '\u{2cc8}'), ('\u{2cca}',
+        '\u{2cca}'), ('\u{2ccc}', '\u{2ccc}'), ('\u{2cce}', '\u{2cce}'),
+        ('\u{2cd0}', '\u{2cd0}'), ('\u{2cd2}', '\u{2cd2}'), ('\u{2cd4}',
+        '\u{2cd4}'), ('\u{2cd6}', '\u{2cd6}'), ('\u{2cd8}', '\u{2cd8}'),
+        ('\u{2cda}', '\u{2cda}'), ('\u{2cdc}', '\u{2cdc}'), ('\u{2cde}',
+        '\u{2cde}'), ('\u{2ce0}', '\u{2ce0}'), ('\u{2ce2}', '\u{2ce2}'),
+        ('\u{2ceb}', '\u{2ceb}'), ('\u{2ced}', '\u{2ced}'), ('\u{2cf2}',
+        '\u{2cf2}'), ('\u{a640}', '\u{a640}'), ('\u{a642}', '\u{a642}'),
+        ('\u{a644}', '\u{a644}'), ('\u{a646}', '\u{a646}'), ('\u{a648}',
+        '\u{a648}'), ('\u{a64a}', '\u{a64a}'), ('\u{a64c}', '\u{a64c}'),
+        ('\u{a64e}', '\u{a64e}'), ('\u{a650}', '\u{a650}'), ('\u{a652}',
+        '\u{a652}'), ('\u{a654}', '\u{a654}'), ('\u{a656}', '\u{a656}'),
+        ('\u{a658}', '\u{a658}'), ('\u{a65a}', '\u{a65a}'), ('\u{a65c}',
+        '\u{a65c}'), ('\u{a65e}', '\u{a65e}'), ('\u{a660}', '\u{a660}'),
+        ('\u{a662}', '\u{a662}'), ('\u{a664}', '\u{a664}'), ('\u{a666}',
+        '\u{a666}'), ('\u{a668}', '\u{a668}'), ('\u{a66a}', '\u{a66a}'),
+        ('\u{a66c}', '\u{a66c}'), ('\u{a680}', '\u{a680}'), ('\u{a682}',
+        '\u{a682}'), ('\u{a684}', '\u{a684}'), ('\u{a686}', '\u{a686}'),
+        ('\u{a688}', '\u{a688}'), ('\u{a68a}', '\u{a68a}'), ('\u{a68c}',
+        '\u{a68c}'), ('\u{a68e}', '\u{a68e}'), ('\u{a690}', '\u{a690}'),
+        ('\u{a692}', '\u{a692}'), ('\u{a694}', '\u{a694}'), ('\u{a696}',
+        '\u{a696}'), ('\u{a698}', '\u{a698}'), ('\u{a69a}', '\u{a69a}'),
+        ('\u{a722}', '\u{a722}'), ('\u{a724}', '\u{a724}'), ('\u{a726}',
+        '\u{a726}'), ('\u{a728}', '\u{a728}'), ('\u{a72a}', '\u{a72a}'),
+        ('\u{a72c}', '\u{a72c}'), ('\u{a72e}', '\u{a72e}'), ('\u{a732}',
+        '\u{a732}'), ('\u{a734}', '\u{a734}'), ('\u{a736}', '\u{a736}'),
+        ('\u{a738}', '\u{a738}'), ('\u{a73a}', '\u{a73a}'), ('\u{a73c}',
+        '\u{a73c}'), ('\u{a73e}', '\u{a73e}'), ('\u{a740}', '\u{a740}'),
+        ('\u{a742}', '\u{a742}'), ('\u{a744}', '\u{a744}'), ('\u{a746}',
+        '\u{a746}'), ('\u{a748}', '\u{a748}'), ('\u{a74a}', '\u{a74a}'),
+        ('\u{a74c}', '\u{a74c}'), ('\u{a74e}', '\u{a74e}'), ('\u{a750}',
+        '\u{a750}'), ('\u{a752}', '\u{a752}'), ('\u{a754}', '\u{a754}'),
+        ('\u{a756}', '\u{a756}'), ('\u{a758}', '\u{a758}'), ('\u{a75a}',
+        '\u{a75a}'), ('\u{a75c}', '\u{a75c}'), ('\u{a75e}', '\u{a75e}'),
+        ('\u{a760}', '\u{a760}'), ('\u{a762}', '\u{a762}'), ('\u{a764}',
+        '\u{a764}'), ('\u{a766}', '\u{a766}'), ('\u{a768}', '\u{a768}'),
+        ('\u{a76a}', '\u{a76a}'), ('\u{a76c}', '\u{a76c}'), ('\u{a76e}',
+        '\u{a76e}'), ('\u{a779}', '\u{a779}'), ('\u{a77b}', '\u{a77b}'),
+        ('\u{a77d}', '\u{a77e}'), ('\u{a780}', '\u{a780}'), ('\u{a782}',
+        '\u{a782}'), ('\u{a784}', '\u{a784}'), ('\u{a786}', '\u{a786}'),
+        ('\u{a78b}', '\u{a78b}'), ('\u{a78d}', '\u{a78d}'), ('\u{a790}',
+        '\u{a790}'), ('\u{a792}', '\u{a792}'), ('\u{a796}', '\u{a796}'),
+        ('\u{a798}', '\u{a798}'), ('\u{a79a}', '\u{a79a}'), ('\u{a79c}',
+        '\u{a79c}'), ('\u{a79e}', '\u{a79e}'), ('\u{a7a0}', '\u{a7a0}'),
+        ('\u{a7a2}', '\u{a7a2}'), ('\u{a7a4}', '\u{a7a4}'), ('\u{a7a6}',
+        '\u{a7a6}'), ('\u{a7a8}', '\u{a7a8}'), ('\u{a7aa}', '\u{a7ad}'),
+        ('\u{a7b0}', '\u{a7b4}'), ('\u{a7b6}', '\u{a7b6}'), ('\u{ff21}',
+        '\u{ff3a}'), ('\u{10400}', '\u{10427}'), ('\u{10c80}', '\u{10cb2}'),
+        ('\u{118a0}', '\u{118bf}'), ('\u{1d400}', '\u{1d419}'), ('\u{1d434}',
+        '\u{1d44d}'), ('\u{1d468}', '\u{1d481}'), ('\u{1d49c}', '\u{1d49c}'),
+        ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}',
+        '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b5}'),
+        ('\u{1d4d0}', '\u{1d4e9}'), ('\u{1d504}', '\u{1d505}'), ('\u{1d507}',
+        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
+        ('\u{1d538}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
+        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
+        ('\u{1d56c}', '\u{1d585}'), ('\u{1d5a0}', '\u{1d5b9}'), ('\u{1d5d4}',
+        '\u{1d5ed}'), ('\u{1d608}', '\u{1d621}'), ('\u{1d63c}', '\u{1d655}'),
+        ('\u{1d670}', '\u{1d689}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6e2}',
+        '\u{1d6fa}'), ('\u{1d71c}', '\u{1d734}'), ('\u{1d756}', '\u{1d76e}'),
+        ('\u{1d790}', '\u{1d7a8}'), ('\u{1d7ca}', '\u{1d7ca}'), ('\u{1f130}',
+        '\u{1f149}'), ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}')
+    ];
+
+    pub const XID_Continue_table: &'static [(char, char)] = &[
+        ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'),
+        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
+        ('\u{b7}', '\u{b7}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
+        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
+        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
+        ('\u{300}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{38a}'), ('\u{38c}', '\u{38c}'),
+        ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'),
+        ('\u{483}', '\u{487}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
+        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{591}', '\u{5bd}'),
+        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
+        ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'),
+        ('\u{610}', '\u{61a}'), ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'),
+        ('\u{6d5}', '\u{6dc}'), ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'),
+        ('\u{6ff}', '\u{6ff}'), ('\u{710}', '\u{74a}'), ('\u{74d}', '\u{7b1}'),
+        ('\u{7c0}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{82d}'),
+        ('\u{840}', '\u{85b}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{963}'),
+        ('\u{966}', '\u{96f}'), ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'),
+        ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'),
+        ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'),
+        ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'),
+        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9f1}'),
+        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
+        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
+        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
+        ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
+        ('\u{a51}', '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
+        ('\u{a66}', '\u{a75}'), ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'),
+        ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'),
+        ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'),
+        ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'),
+        ('\u{ae0}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'),
+        ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
+        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
+        ('\u{b35}', '\u{b39}'), ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'),
+        ('\u{b4b}', '\u{b4d}'), ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'),
+        ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'),
+        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
+        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
+        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
+        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
+        ('\u{bca}', '\u{bcd}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
+        ('\u{be6}', '\u{bef}'), ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'),
+        ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'),
+        ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'),
+        ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'),
+        ('\u{c66}', '\u{c6f}'), ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'),
+        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
+        ('\u{cb5}', '\u{cb9}'), ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'),
+        ('\u{cca}', '\u{ccd}'), ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'),
+        ('\u{ce0}', '\u{ce3}'), ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'),
+        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
+        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
+        ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'),
+        ('\u{d66}', '\u{d6f}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'),
+        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
+        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'),
+        ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'),
+        ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'),
+        ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'),
+        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
+        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
+        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
+        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'),
+        ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{ec8}', '\u{ecd}'),
+        ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
+        ('\u{f18}', '\u{f19}'), ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'),
+        ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'),
+        ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'),
+        ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{1000}',
+        '\u{1049}'), ('\u{1050}', '\u{109d}'), ('\u{10a0}', '\u{10c5}'),
+        ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}',
+        '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'),
+        ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}',
+        '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'),
+        ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}',
+        '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'),
+        ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}',
+        '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{135f}'),
+        ('\u{1369}', '\u{1371}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
+        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
+        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
+        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
+        ('\u{170e}', '\u{1714}'), ('\u{1720}', '\u{1734}'), ('\u{1740}',
+        '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
+        ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'), ('\u{17d7}',
+        '\u{17d7}'), ('\u{17dc}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'),
+        ('\u{180b}', '\u{180d}'), ('\u{1810}', '\u{1819}'), ('\u{1820}',
+        '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'),
+        ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}',
+        '\u{193b}'), ('\u{1946}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
+        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{19d0}',
+        '\u{19da}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'),
+        ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'), ('\u{1a90}',
+        '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}', '\u{1abd}'),
+        ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'), ('\u{1b6b}',
+        '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}', '\u{1c37}'),
+        ('\u{1c40}', '\u{1c49}'), ('\u{1c4d}', '\u{1c7d}'), ('\u{1cd0}',
+        '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}', '\u{1cf9}'),
+        ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'), ('\u{1f18}',
+        '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
+        ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}',
+        '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'),
+        ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}',
+        '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'),
+        ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}',
+        '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'),
+        ('\u{203f}', '\u{2040}'), ('\u{2054}', '\u{2054}'), ('\u{2071}',
+        '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', '\u{209c}'),
+        ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'), ('\u{20e5}',
+        '\u{20f0}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'),
+        ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2118}',
+        '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'),
+        ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}',
+        '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'),
+        ('\u{2160}', '\u{2188}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}',
+        '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'),
+        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
+        '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'),
+        ('\u{2d7f}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}',
+        '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'),
+        ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}',
+        '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{2de0}', '\u{2dff}'),
+        ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}',
+        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'),
+        ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
+        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
+        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
+        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
+        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
+        '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a66f}'),
+        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}',
+        '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'),
+        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'), ('\u{a840}',
+        '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'),
+        ('\u{a8e0}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}',
+        '\u{a8fd}'), ('\u{a900}', '\u{a92d}'), ('\u{a930}', '\u{a953}'),
+        ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}',
+        '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'),
+        ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}', '\u{aa59}'), ('\u{aa60}',
+        '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'),
+        ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}',
+        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
+        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}',
+        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'),
+        ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}',
+        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
+        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
+        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'),
+        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
+        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
+        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}',
+        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
+        ('\u{fdf0}', '\u{fdf9}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}',
+        '\u{fe2f}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'),
+        ('\u{fe71}', '\u{fe71}'), ('\u{fe73}', '\u{fe73}'), ('\u{fe77}',
+        '\u{fe77}'), ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'),
+        ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}', '\u{fefc}'), ('\u{ff10}',
+        '\u{ff19}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'),
+        ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}',
+        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
+        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
+        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
+        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
+        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{101fd}', '\u{101fd}'),
+        ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{102e0}',
+        '\u{102e0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{1034a}'),
+        ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}',
+        '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}', '\u{103d5}'),
+        ('\u{10400}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}'), ('\u{10500}',
+        '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'),
+        ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}',
+        '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'),
+        ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}',
+        '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'),
+        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
+        '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'),
+        ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}',
+        '\u{10a06}'), ('\u{10a0c}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'),
+        ('\u{10a19}', '\u{10a33}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}',
+        '\u{10a3f}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'),
+        ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}',
+        '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'),
+        ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}',
+        '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{11000}', '\u{11046}'),
+        ('\u{11066}', '\u{1106f}'), ('\u{1107f}', '\u{110ba}'), ('\u{110d0}',
+        '\u{110e8}'), ('\u{110f0}', '\u{110f9}'), ('\u{11100}', '\u{11134}'),
+        ('\u{11136}', '\u{1113f}'), ('\u{11150}', '\u{11173}'), ('\u{11176}',
+        '\u{11176}'), ('\u{11180}', '\u{111c4}'), ('\u{111ca}', '\u{111cc}'),
+        ('\u{111d0}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}',
+        '\u{11211}'), ('\u{11213}', '\u{11237}'), ('\u{11280}', '\u{11286}'),
+        ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'), ('\u{1128f}',
+        '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112ea}'),
+        ('\u{112f0}', '\u{112f9}'), ('\u{11300}', '\u{11303}'), ('\u{11305}',
+        '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'),
+        ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}',
+        '\u{11339}'), ('\u{1133c}', '\u{11344}'), ('\u{11347}', '\u{11348}'),
+        ('\u{1134b}', '\u{1134d}'), ('\u{11350}', '\u{11350}'), ('\u{11357}',
+        '\u{11357}'), ('\u{1135d}', '\u{11363}'), ('\u{11366}', '\u{1136c}'),
+        ('\u{11370}', '\u{11374}'), ('\u{11480}', '\u{114c5}'), ('\u{114c7}',
+        '\u{114c7}'), ('\u{114d0}', '\u{114d9}'), ('\u{11580}', '\u{115b5}'),
+        ('\u{115b8}', '\u{115c0}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}',
+        '\u{11640}'), ('\u{11644}', '\u{11644}'), ('\u{11650}', '\u{11659}'),
+        ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}'), ('\u{11700}',
+        '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}', '\u{11739}'),
+        ('\u{118a0}', '\u{118e9}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}',
+        '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'),
+        ('\u{12480}', '\u{12543}'), ('\u{13000}', '\u{1342e}'), ('\u{14400}',
+        '\u{14646}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'),
+        ('\u{16a60}', '\u{16a69}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}',
+        '\u{16af4}'), ('\u{16b00}', '\u{16b36}'), ('\u{16b40}', '\u{16b43}'),
+        ('\u{16b50}', '\u{16b59}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
+        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'),
+        ('\u{16f8f}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}',
+        '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'),
+        ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1d165}',
+        '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'),
+        ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}',
+        '\u{1d244}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'),
+        ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}',
+        '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'),
+        ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}',
+        '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'),
+        ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}',
+        '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'),
+        ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}',
+        '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'),
+        ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}',
+        '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'),
+        ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}',
+        '\u{1d7cb}'), ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'),
+        ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}', '\u{1da75}'), ('\u{1da84}',
+        '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'),
+        ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{1ee00}',
+        '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'),
+        ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}',
+        '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'),
+        ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}',
+        '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'),
+        ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}',
+        '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'),
+        ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}',
+        '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'),
+        ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}',
+        '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'),
+        ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}',
+        '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'),
+        ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}',
+        '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'),
+        ('\u{e0100}', '\u{e01ef}')
+    ];
+
+    pub const XID_Start_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
+        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
+        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
+        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
+        ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
+        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
+        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
+        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
+        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{5d0}', '\u{5ea}'),
+        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'), ('\u{66e}', '\u{66f}'),
+        ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}', '\u{6e6}'),
+        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
+        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
+        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'),
+        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'),
+        ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'), ('\u{840}', '\u{858}'),
+        ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'), ('\u{93d}', '\u{93d}'),
+        ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}', '\u{980}'),
+        ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
+        ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'),
+        ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'),
+        ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'),
+        ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'),
+        ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'),
+        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}', '\u{a74}'),
+        ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
+        ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
+        ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'),
+        ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
+        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
+        ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'), ('\u{b5c}', '\u{b5d}'),
+        ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}', '\u{b83}'),
+        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
+        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
+        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
+        ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
+        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c3d}'),
+        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'), ('\u{c85}', '\u{c8c}'),
+        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
+        ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'),
+        ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'),
+        ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'),
+        ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'),
+        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
+        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{e01}', '\u{e30}'),
+        ('\u{e32}', '\u{e32}'), ('\u{e40}', '\u{e46}'), ('\u{e81}', '\u{e82}'),
+        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
+        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
+        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
+        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb2}'),
+        ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
+        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
+        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
+        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
+        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
+        ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
+        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'),
+        ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
+        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
+        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
+        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
+        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
+        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
+        ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
+        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
+        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
+        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
+        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
+        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
+        ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}',
+        '\u{17dc}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
+        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
+        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
+        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
+        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'),
+        ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}',
+        '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
+        ('\u{1c00}', '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}',
+        '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'),
+        ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}',
+        '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'),
+        ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
+        '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'),
+        ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}',
+        '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'),
+        ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
+        '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
+        ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
+        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'),
+        ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}',
+        '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'),
+        ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}',
+        '\u{2139}'), ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'),
+        ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}',
+        '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'),
+        ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}',
+        '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'),
+        ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}',
+        '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'),
+        ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
+        '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
+        ('\u{2dd8}', '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3021}',
+        '\u{3029}'), ('\u{3031}', '\u{3035}'), ('\u{3038}', '\u{303c}'),
+        ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
+        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
+        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
+        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
+        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
+        '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'),
+        ('\u{a640}', '\u{a66e}'), ('\u{a67f}', '\u{a69d}'), ('\u{a6a0}',
+        '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}', '\u{a788}'),
+        ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}',
+        '\u{a801}'), ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'),
+        ('\u{a80c}', '\u{a822}'), ('\u{a840}', '\u{a873}'), ('\u{a882}',
+        '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'),
+        ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}',
+        '\u{a946}'), ('\u{a960}', '\u{a97c}'), ('\u{a984}', '\u{a9b2}'),
+        ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}',
+        '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'),
+        ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}',
+        '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), ('\u{aa7e}', '\u{aaaf}'),
+        ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}',
+        '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'),
+        ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}',
+        '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'),
+        ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}',
+        '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'),
+        ('\u{ab70}', '\u{abe2}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}',
+        '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'),
+        ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}',
+        '\u{fb17}'), ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'),
+        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
+        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
+        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}',
+        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
+        ('\u{fdf0}', '\u{fdf9}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}',
+        '\u{fe73}'), ('\u{fe77}', '\u{fe77}'), ('\u{fe79}', '\u{fe79}'),
+        ('\u{fe7b}', '\u{fe7b}'), ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}',
+        '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
+        ('\u{ff66}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}',
+        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
+        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
+        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
+        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
+        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'),
+        ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}',
+        '\u{1034a}'), ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'),
+        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}',
+        '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'),
+        ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
+        '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'),
+        ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}',
+        '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'),
+        ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}',
+        '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'),
+        ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
+        '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'),
+        ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}',
+        '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'),
+        ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}',
+        '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'),
+        ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}',
+        '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'),
+        ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}',
+        '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'),
+        ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{111dc}',
+        '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'),
+        ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}',
+        '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'),
+        ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
+        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
+        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}',
+        '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}', '\u{11361}'),
+        ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}',
+        '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'),
+        ('\u{11600}', '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}',
+        '\u{116aa}'), ('\u{11700}', '\u{11719}'), ('\u{118a0}', '\u{118df}'),
+        ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}',
+        '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'),
+        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
+        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'),
+        ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}',
+        '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'),
+        ('\u{16f50}', '\u{16f50}'), ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}',
+        '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'),
+        ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}',
+        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
+        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
+        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
+        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
+        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
+        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
+        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
+        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
+        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
+        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
+        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
+        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}',
+        '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
+        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
+        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
+        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
+        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
+        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
+        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
+        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
+        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
+        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
+        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
+        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
+        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
+        ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}',
+        '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'),
+        ('\u{2f800}', '\u{2fa1d}')
+    ];
+
+}
+
+pub mod script {
+    pub const Ahom_table: &'static [(char, char)] = &[
+        ('\u{11700}', '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}',
+        '\u{1173f}')
+    ];
+
+    pub const Anatolian_Hieroglyphs_table: &'static [(char, char)] = &[
+        ('\u{14400}', '\u{14646}')
+    ];
+
+    pub const Arabic_table: &'static [(char, char)] = &[
+        ('\u{600}', '\u{604}'), ('\u{606}', '\u{60b}'), ('\u{60d}', '\u{61a}'),
+        ('\u{61e}', '\u{61e}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'),
+        ('\u{656}', '\u{66f}'), ('\u{671}', '\u{6dc}'), ('\u{6de}', '\u{6ff}'),
+        ('\u{750}', '\u{77f}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{8ff}'),
+        ('\u{fb50}', '\u{fbc1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}',
+        '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfd}'),
+        ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{10e60}',
+        '\u{10e7e}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
+        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
+        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
+        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
+        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
+        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
+        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
+        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
+        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
+        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
+        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
+        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
+        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
+        ('\u{1eeab}', '\u{1eebb}'), ('\u{1eef0}', '\u{1eef1}')
+    ];
+
+    pub const Armenian_table: &'static [(char, char)] = &[
+        ('\u{531}', '\u{556}'), ('\u{559}', '\u{55f}'), ('\u{561}', '\u{587}'),
+        ('\u{58a}', '\u{58a}'), ('\u{58d}', '\u{58f}'), ('\u{fb13}',
+        '\u{fb17}')
+    ];
+
+    pub const Avestan_table: &'static [(char, char)] = &[
+        ('\u{10b00}', '\u{10b35}'), ('\u{10b39}', '\u{10b3f}')
+    ];
+
+    pub const Balinese_table: &'static [(char, char)] = &[
+        ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b7c}')
+    ];
+
+    pub const Bamum_table: &'static [(char, char)] = &[
+        ('\u{a6a0}', '\u{a6f7}'), ('\u{16800}', '\u{16a38}')
+    ];
+
+    pub const Bassa_Vah_table: &'static [(char, char)] = &[
+        ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}', '\u{16af5}')
+    ];
+
+    pub const Batak_table: &'static [(char, char)] = &[
+        ('\u{1bc0}', '\u{1bf3}'), ('\u{1bfc}', '\u{1bff}')
+    ];
+
+    pub const Bengali_table: &'static [(char, char)] = &[
+        ('\u{980}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
+        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
+        ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
+        ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'),
+        ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9fb}')
+    ];
+
+    pub const Bopomofo_table: &'static [(char, char)] = &[
+        ('\u{2ea}', '\u{2eb}'), ('\u{3105}', '\u{312d}'), ('\u{31a0}',
+        '\u{31ba}')
+    ];
+
+    pub const Brahmi_table: &'static [(char, char)] = &[
+        ('\u{11000}', '\u{1104d}'), ('\u{11052}', '\u{1106f}'), ('\u{1107f}',
+        '\u{1107f}')
+    ];
+
+    pub const Braille_table: &'static [(char, char)] = &[
+        ('\u{2800}', '\u{28ff}')
+    ];
+
+    pub const Buginese_table: &'static [(char, char)] = &[
+        ('\u{1a00}', '\u{1a1b}'), ('\u{1a1e}', '\u{1a1f}')
+    ];
+
+    pub const Buhid_table: &'static [(char, char)] = &[
+        ('\u{1740}', '\u{1753}')
+    ];
+
+    pub const Canadian_Aboriginal_table: &'static [(char, char)] = &[
+        ('\u{1400}', '\u{167f}'), ('\u{18b0}', '\u{18f5}')
+    ];
+
+    pub const Carian_table: &'static [(char, char)] = &[
+        ('\u{102a0}', '\u{102d0}')
+    ];
+
+    pub const Caucasian_Albanian_table: &'static [(char, char)] = &[
+        ('\u{10530}', '\u{10563}'), ('\u{1056f}', '\u{1056f}')
+    ];
+
+    pub const Chakma_table: &'static [(char, char)] = &[
+        ('\u{11100}', '\u{11134}'), ('\u{11136}', '\u{11143}')
+    ];
+
+    pub const Cham_table: &'static [(char, char)] = &[
+        ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}',
+        '\u{aa59}'), ('\u{aa5c}', '\u{aa5f}')
+    ];
+
+    pub const Cherokee_table: &'static [(char, char)] = &[
+        ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{ab70}',
+        '\u{abbf}')
+    ];
+
+    pub const Common_table: &'static [(char, char)] = &[
+        ('\u{0}', '\u{40}'), ('\u{5b}', '\u{60}'), ('\u{7b}', '\u{a9}'),
+        ('\u{ab}', '\u{b9}'), ('\u{bb}', '\u{bf}'), ('\u{d7}', '\u{d7}'),
+        ('\u{f7}', '\u{f7}'), ('\u{2b9}', '\u{2df}'), ('\u{2e5}', '\u{2e9}'),
+        ('\u{2ec}', '\u{2ff}'), ('\u{374}', '\u{374}'), ('\u{37e}', '\u{37e}'),
+        ('\u{385}', '\u{385}'), ('\u{387}', '\u{387}'), ('\u{589}', '\u{589}'),
+        ('\u{605}', '\u{605}'), ('\u{60c}', '\u{60c}'), ('\u{61b}', '\u{61c}'),
+        ('\u{61f}', '\u{61f}'), ('\u{640}', '\u{640}'), ('\u{6dd}', '\u{6dd}'),
+        ('\u{964}', '\u{965}'), ('\u{e3f}', '\u{e3f}'), ('\u{fd5}', '\u{fd8}'),
+        ('\u{10fb}', '\u{10fb}'), ('\u{16eb}', '\u{16ed}'), ('\u{1735}',
+        '\u{1736}'), ('\u{1802}', '\u{1803}'), ('\u{1805}', '\u{1805}'),
+        ('\u{1cd3}', '\u{1cd3}'), ('\u{1ce1}', '\u{1ce1}'), ('\u{1ce9}',
+        '\u{1cec}'), ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'),
+        ('\u{2000}', '\u{200b}'), ('\u{200e}', '\u{2064}'), ('\u{2066}',
+        '\u{2070}'), ('\u{2074}', '\u{207e}'), ('\u{2080}', '\u{208e}'),
+        ('\u{20a0}', '\u{20be}'), ('\u{2100}', '\u{2125}'), ('\u{2127}',
+        '\u{2129}'), ('\u{212c}', '\u{2131}'), ('\u{2133}', '\u{214d}'),
+        ('\u{214f}', '\u{215f}'), ('\u{2189}', '\u{218b}'), ('\u{2190}',
+        '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}', '\u{244a}'),
+        ('\u{2460}', '\u{27ff}'), ('\u{2900}', '\u{2b73}'), ('\u{2b76}',
+        '\u{2b95}'), ('\u{2b98}', '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'),
+        ('\u{2bca}', '\u{2bd1}'), ('\u{2bec}', '\u{2bef}'), ('\u{2e00}',
+        '\u{2e42}'), ('\u{2ff0}', '\u{2ffb}'), ('\u{3000}', '\u{3004}'),
+        ('\u{3006}', '\u{3006}'), ('\u{3008}', '\u{3020}'), ('\u{3030}',
+        '\u{3037}'), ('\u{303c}', '\u{303f}'), ('\u{309b}', '\u{309c}'),
+        ('\u{30a0}', '\u{30a0}'), ('\u{30fb}', '\u{30fc}'), ('\u{3190}',
+        '\u{319f}'), ('\u{31c0}', '\u{31e3}'), ('\u{3220}', '\u{325f}'),
+        ('\u{327f}', '\u{32cf}'), ('\u{3358}', '\u{33ff}'), ('\u{4dc0}',
+        '\u{4dff}'), ('\u{a700}', '\u{a721}'), ('\u{a788}', '\u{a78a}'),
+        ('\u{a830}', '\u{a839}'), ('\u{a92e}', '\u{a92e}'), ('\u{a9cf}',
+        '\u{a9cf}'), ('\u{ab5b}', '\u{ab5b}'), ('\u{fd3e}', '\u{fd3f}'),
+        ('\u{fe10}', '\u{fe19}'), ('\u{fe30}', '\u{fe52}'), ('\u{fe54}',
+        '\u{fe66}'), ('\u{fe68}', '\u{fe6b}'), ('\u{feff}', '\u{feff}'),
+        ('\u{ff01}', '\u{ff20}'), ('\u{ff3b}', '\u{ff40}'), ('\u{ff5b}',
+        '\u{ff65}'), ('\u{ff70}', '\u{ff70}'), ('\u{ff9e}', '\u{ff9f}'),
+        ('\u{ffe0}', '\u{ffe6}'), ('\u{ffe8}', '\u{ffee}'), ('\u{fff9}',
+        '\u{fffd}'), ('\u{10100}', '\u{10102}'), ('\u{10107}', '\u{10133}'),
+        ('\u{10137}', '\u{1013f}'), ('\u{10190}', '\u{1019b}'), ('\u{101d0}',
+        '\u{101fc}'), ('\u{102e1}', '\u{102fb}'), ('\u{1bca0}', '\u{1bca3}'),
+        ('\u{1d000}', '\u{1d0f5}'), ('\u{1d100}', '\u{1d126}'), ('\u{1d129}',
+        '\u{1d166}'), ('\u{1d16a}', '\u{1d17a}'), ('\u{1d183}', '\u{1d184}'),
+        ('\u{1d18c}', '\u{1d1a9}'), ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d300}',
+        '\u{1d356}'), ('\u{1d360}', '\u{1d371}'), ('\u{1d400}', '\u{1d454}'),
+        ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}',
+        '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'),
+        ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
+        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'),
+        ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}',
+        '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
+        ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}',
+        '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d7cb}'), ('\u{1d7ce}', '\u{1d7ff}'),
+        ('\u{1f000}', '\u{1f02b}'), ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}',
+        '\u{1f0ae}'), ('\u{1f0b1}', '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'),
+        ('\u{1f0d1}', '\u{1f0f5}'), ('\u{1f100}', '\u{1f10c}'), ('\u{1f110}',
+        '\u{1f12e}'), ('\u{1f130}', '\u{1f16b}'), ('\u{1f170}', '\u{1f19a}'),
+        ('\u{1f1e6}', '\u{1f1ff}'), ('\u{1f201}', '\u{1f202}'), ('\u{1f210}',
+        '\u{1f23a}'), ('\u{1f240}', '\u{1f248}'), ('\u{1f250}', '\u{1f251}'),
+        ('\u{1f300}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'), ('\u{1f5a5}',
+        '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}', '\u{1f6f3}'),
+        ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'), ('\u{1f800}',
+        '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}', '\u{1f859}'),
+        ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'), ('\u{1f910}',
+        '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}', '\u{1f9c0}'),
+        ('\u{e0001}', '\u{e0001}'), ('\u{e0020}', '\u{e007f}')
+    ];
+
+    pub const Coptic_table: &'static [(char, char)] = &[
+        ('\u{3e2}', '\u{3ef}'), ('\u{2c80}', '\u{2cf3}'), ('\u{2cf9}',
+        '\u{2cff}')
+    ];
+
+    pub const Cuneiform_table: &'static [(char, char)] = &[
+        ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12470}',
+        '\u{12474}'), ('\u{12480}', '\u{12543}')
+    ];
+
+    pub const Cypriot_table: &'static [(char, char)] = &[
+        ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}',
+        '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'),
+        ('\u{1083f}', '\u{1083f}')
+    ];
+
+    pub const Cyrillic_table: &'static [(char, char)] = &[
+        ('\u{400}', '\u{484}'), ('\u{487}', '\u{52f}'), ('\u{1d2b}',
+        '\u{1d2b}'), ('\u{1d78}', '\u{1d78}'), ('\u{2de0}', '\u{2dff}'),
+        ('\u{a640}', '\u{a69f}'), ('\u{fe2e}', '\u{fe2f}')
+    ];
+
+    pub const Deseret_table: &'static [(char, char)] = &[
+        ('\u{10400}', '\u{1044f}')
+    ];
+
+    pub const Devanagari_table: &'static [(char, char)] = &[
+        ('\u{900}', '\u{950}'), ('\u{953}', '\u{963}'), ('\u{966}', '\u{97f}'),
+        ('\u{a8e0}', '\u{a8fd}')
+    ];
+
+    pub const Duployan_table: &'static [(char, char)] = &[
+        ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}',
+        '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9c}', '\u{1bc9f}')
+    ];
+
+    pub const Egyptian_Hieroglyphs_table: &'static [(char, char)] = &[
+        ('\u{13000}', '\u{1342e}')
+    ];
+
+    pub const Elbasan_table: &'static [(char, char)] = &[
+        ('\u{10500}', '\u{10527}')
+    ];
+
+    pub const Ethiopic_table: &'static [(char, char)] = &[
+        ('\u{1200}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
+        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
+        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
+        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
+        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
+        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
+        ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{137c}'), ('\u{1380}',
+        '\u{1399}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
+        ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
+        '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'),
+        ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{ab01}',
+        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
+        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}')
+    ];
+
+    pub const Georgian_table: &'static [(char, char)] = &[
+        ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}',
+        '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{10ff}'),
+        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
+        '\u{2d2d}')
+    ];
+
+    pub const Glagolitic_table: &'static [(char, char)] = &[
+        ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}')
+    ];
+
+    pub const Gothic_table: &'static [(char, char)] = &[
+        ('\u{10330}', '\u{1034a}')
+    ];
+
+    pub const Grantha_table: &'static [(char, char)] = &[
+        ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
+        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
+        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}',
+        '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'),
+        ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}',
+        '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}')
+    ];
+
+    pub const Greek_table: &'static [(char, char)] = &[
+        ('\u{370}', '\u{373}'), ('\u{375}', '\u{377}'), ('\u{37a}', '\u{37d}'),
+        ('\u{37f}', '\u{37f}'), ('\u{384}', '\u{384}'), ('\u{386}', '\u{386}'),
+        ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'),
+        ('\u{3a3}', '\u{3e1}'), ('\u{3f0}', '\u{3ff}'), ('\u{1d26}',
+        '\u{1d2a}'), ('\u{1d5d}', '\u{1d61}'), ('\u{1d66}', '\u{1d6a}'),
+        ('\u{1dbf}', '\u{1dbf}'), ('\u{1f00}', '\u{1f15}'), ('\u{1f18}',
+        '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
+        ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}',
+        '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'),
+        ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fdd}', '\u{1fef}'),
+        ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffe}'), ('\u{2126}',
+        '\u{2126}'), ('\u{ab65}', '\u{ab65}'), ('\u{10140}', '\u{1018c}'),
+        ('\u{101a0}', '\u{101a0}'), ('\u{1d200}', '\u{1d245}')
+    ];
+
+    pub const Gujarati_table: &'static [(char, char)] = &[
+        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
+        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
+        ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
+        ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
+        ('\u{ae6}', '\u{af1}'), ('\u{af9}', '\u{af9}')
+    ];
+
+    pub const Gurmukhi_table: &'static [(char, char)] = &[
+        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
+        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
+        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
+        ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
+        ('\u{a51}', '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
+        ('\u{a66}', '\u{a75}')
+    ];
+
+    pub const Han_table: &'static [(char, char)] = &[
+        ('\u{2e80}', '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}',
+        '\u{2fd5}'), ('\u{3005}', '\u{3005}'), ('\u{3007}', '\u{3007}'),
+        ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303b}'), ('\u{3400}',
+        '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'), ('\u{f900}', '\u{fa6d}'),
+        ('\u{fa70}', '\u{fad9}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}',
+        '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'),
+        ('\u{2f800}', '\u{2fa1d}')
+    ];
+
+    pub const Hangul_table: &'static [(char, char)] = &[
+        ('\u{1100}', '\u{11ff}'), ('\u{302e}', '\u{302f}'), ('\u{3131}',
+        '\u{318e}'), ('\u{3200}', '\u{321e}'), ('\u{3260}', '\u{327e}'),
+        ('\u{a960}', '\u{a97c}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}',
+        '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{ffa0}', '\u{ffbe}'),
+        ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}',
+        '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}')
+    ];
+
+    pub const Hanunoo_table: &'static [(char, char)] = &[
+        ('\u{1720}', '\u{1734}')
+    ];
+
+    pub const Hatran_table: &'static [(char, char)] = &[
+        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{108fb}',
+        '\u{108ff}')
+    ];
+
+    pub const Hebrew_table: &'static [(char, char)] = &[
+        ('\u{591}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f4}'),
+        ('\u{fb1d}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
+        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
+        ('\u{fb46}', '\u{fb4f}')
+    ];
+
+    pub const Hiragana_table: &'static [(char, char)] = &[
+        ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{1b001}',
+        '\u{1b001}'), ('\u{1f200}', '\u{1f200}')
+    ];
+
+    pub const Imperial_Aramaic_table: &'static [(char, char)] = &[
+        ('\u{10840}', '\u{10855}'), ('\u{10857}', '\u{1085f}')
+    ];
+
+    pub const Inherited_table: &'static [(char, char)] = &[
+        ('\u{300}', '\u{36f}'), ('\u{485}', '\u{486}'), ('\u{64b}', '\u{655}'),
+        ('\u{670}', '\u{670}'), ('\u{951}', '\u{952}'), ('\u{1ab0}',
+        '\u{1abe}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'),
+        ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}',
+        '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'),
+        ('\u{1dfc}', '\u{1dff}'), ('\u{200c}', '\u{200d}'), ('\u{20d0}',
+        '\u{20f0}'), ('\u{302a}', '\u{302d}'), ('\u{3099}', '\u{309a}'),
+        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2d}'), ('\u{101fd}',
+        '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{1d167}', '\u{1d169}'),
+        ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}',
+        '\u{1d1ad}'), ('\u{e0100}', '\u{e01ef}')
+    ];
+
+    pub const Inscriptional_Pahlavi_table: &'static [(char, char)] = &[
+        ('\u{10b60}', '\u{10b72}'), ('\u{10b78}', '\u{10b7f}')
+    ];
+
+    pub const Inscriptional_Parthian_table: &'static [(char, char)] = &[
+        ('\u{10b40}', '\u{10b55}'), ('\u{10b58}', '\u{10b5f}')
+    ];
+
+    pub const Javanese_table: &'static [(char, char)] = &[
+        ('\u{a980}', '\u{a9cd}'), ('\u{a9d0}', '\u{a9d9}'), ('\u{a9de}',
+        '\u{a9df}')
+    ];
+
+    pub const Kaithi_table: &'static [(char, char)] = &[
+        ('\u{11080}', '\u{110c1}')
+    ];
+
+    pub const Kannada_table: &'static [(char, char)] = &[
+        ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
+        ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'),
+        ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
+        ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'),
+        ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}')
+    ];
+
+    pub const Katakana_table: &'static [(char, char)] = &[
+        ('\u{30a1}', '\u{30fa}'), ('\u{30fd}', '\u{30ff}'), ('\u{31f0}',
+        '\u{31ff}'), ('\u{32d0}', '\u{32fe}'), ('\u{3300}', '\u{3357}'),
+        ('\u{ff66}', '\u{ff6f}'), ('\u{ff71}', '\u{ff9d}'), ('\u{1b000}',
+        '\u{1b000}')
+    ];
+
+    pub const Kayah_Li_table: &'static [(char, char)] = &[
+        ('\u{a900}', '\u{a92d}'), ('\u{a92f}', '\u{a92f}')
+    ];
+
+    pub const Kharoshthi_table: &'static [(char, char)] = &[
+        ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
+        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
+        ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a47}'), ('\u{10a50}',
+        '\u{10a58}')
+    ];
+
+    pub const Khmer_table: &'static [(char, char)] = &[
+        ('\u{1780}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'), ('\u{17f0}',
+        '\u{17f9}'), ('\u{19e0}', '\u{19ff}')
+    ];
+
+    pub const Khojki_table: &'static [(char, char)] = &[
+        ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1123d}')
+    ];
+
+    pub const Khudawadi_table: &'static [(char, char)] = &[
+        ('\u{112b0}', '\u{112ea}'), ('\u{112f0}', '\u{112f9}')
+    ];
+
+    pub const Lao_table: &'static [(char, char)] = &[
+        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
+        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
+        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
+        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'),
+        ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
+        ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}')
+    ];
+
+    pub const Latin_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
+        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'),
+        ('\u{f8}', '\u{2b8}'), ('\u{2e0}', '\u{2e4}'), ('\u{1d00}', '\u{1d25}'),
+        ('\u{1d2c}', '\u{1d5c}'), ('\u{1d62}', '\u{1d65}'), ('\u{1d6b}',
+        '\u{1d77}'), ('\u{1d79}', '\u{1dbe}'), ('\u{1e00}', '\u{1eff}'),
+        ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}',
+        '\u{209c}'), ('\u{212a}', '\u{212b}'), ('\u{2132}', '\u{2132}'),
+        ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c60}',
+        '\u{2c7f}'), ('\u{a722}', '\u{a787}'), ('\u{a78b}', '\u{a7ad}'),
+        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a7ff}'), ('\u{ab30}',
+        '\u{ab5a}'), ('\u{ab5c}', '\u{ab64}'), ('\u{fb00}', '\u{fb06}'),
+        ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}')
+    ];
+
+    pub const Lepcha_table: &'static [(char, char)] = &[
+        ('\u{1c00}', '\u{1c37}'), ('\u{1c3b}', '\u{1c49}'), ('\u{1c4d}',
+        '\u{1c4f}')
+    ];
+
+    pub const Limbu_table: &'static [(char, char)] = &[
+        ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}',
+        '\u{193b}'), ('\u{1940}', '\u{1940}'), ('\u{1944}', '\u{194f}')
+    ];
+
+    pub const Linear_A_table: &'static [(char, char)] = &[
+        ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}',
+        '\u{10767}')
+    ];
+
+    pub const Linear_B_table: &'static [(char, char)] = &[
+        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
+        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
+        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}')
+    ];
+
+    pub const Lisu_table: &'static [(char, char)] = &[
+        ('\u{a4d0}', '\u{a4ff}')
+    ];
+
+    pub const Lycian_table: &'static [(char, char)] = &[
+        ('\u{10280}', '\u{1029c}')
+    ];
+
+    pub const Lydian_table: &'static [(char, char)] = &[
+        ('\u{10920}', '\u{10939}'), ('\u{1093f}', '\u{1093f}')
+    ];
+
+    pub const Mahajani_table: &'static [(char, char)] = &[
+        ('\u{11150}', '\u{11176}')
+    ];
+
+    pub const Malayalam_table: &'static [(char, char)] = &[
+        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
+        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
+        ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'),
+        ('\u{d66}', '\u{d75}'), ('\u{d79}', '\u{d7f}')
+    ];
+
+    pub const Mandaic_table: &'static [(char, char)] = &[
+        ('\u{840}', '\u{85b}'), ('\u{85e}', '\u{85e}')
+    ];
+
+    pub const Manichaean_table: &'static [(char, char)] = &[
+        ('\u{10ac0}', '\u{10ae6}'), ('\u{10aeb}', '\u{10af6}')
+    ];
+
+    pub const Meetei_Mayek_table: &'static [(char, char)] = &[
+        ('\u{aae0}', '\u{aaf6}'), ('\u{abc0}', '\u{abed}'), ('\u{abf0}',
+        '\u{abf9}')
+    ];
+
+    pub const Mende_Kikakui_table: &'static [(char, char)] = &[
+        ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8c7}', '\u{1e8d6}')
+    ];
+
+    pub const Meroitic_Cursive_table: &'static [(char, char)] = &[
+        ('\u{109a0}', '\u{109b7}'), ('\u{109bc}', '\u{109cf}'), ('\u{109d2}',
+        '\u{109ff}')
+    ];
+
+    pub const Meroitic_Hieroglyphs_table: &'static [(char, char)] = &[
+        ('\u{10980}', '\u{1099f}')
+    ];
+
+    pub const Miao_table: &'static [(char, char)] = &[
+        ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}',
+        '\u{16f9f}')
+    ];
+
+    pub const Modi_table: &'static [(char, char)] = &[
+        ('\u{11600}', '\u{11644}'), ('\u{11650}', '\u{11659}')
+    ];
+
+    pub const Mongolian_table: &'static [(char, char)] = &[
+        ('\u{1800}', '\u{1801}'), ('\u{1804}', '\u{1804}'), ('\u{1806}',
+        '\u{180e}'), ('\u{1810}', '\u{1819}'), ('\u{1820}', '\u{1877}'),
+        ('\u{1880}', '\u{18aa}')
+    ];
+
+    pub const Mro_table: &'static [(char, char)] = &[
+        ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16a6e}',
+        '\u{16a6f}')
+    ];
+
+    pub const Multani_table: &'static [(char, char)] = &[
+        ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}',
+        '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a9}')
+    ];
+
+    pub const Myanmar_table: &'static [(char, char)] = &[
+        ('\u{1000}', '\u{109f}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa60}',
+        '\u{aa7f}')
+    ];
+
+    pub const Nabataean_table: &'static [(char, char)] = &[
+        ('\u{10880}', '\u{1089e}'), ('\u{108a7}', '\u{108af}')
+    ];
+
+    pub const New_Tai_Lue_table: &'static [(char, char)] = &[
+        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{19d0}',
+        '\u{19da}'), ('\u{19de}', '\u{19df}')
+    ];
+
+    pub const Nko_table: &'static [(char, char)] = &[
+        ('\u{7c0}', '\u{7fa}')
+    ];
+
+    pub const Ogham_table: &'static [(char, char)] = &[
+        ('\u{1680}', '\u{169c}')
+    ];
+
+    pub const Ol_Chiki_table: &'static [(char, char)] = &[
+        ('\u{1c50}', '\u{1c7f}')
+    ];
+
+    pub const Old_Hungarian_table: &'static [(char, char)] = &[
+        ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{10cfa}',
+        '\u{10cff}')
+    ];
+
+    pub const Old_Italic_table: &'static [(char, char)] = &[
+        ('\u{10300}', '\u{10323}')
+    ];
+
+    pub const Old_North_Arabian_table: &'static [(char, char)] = &[
+        ('\u{10a80}', '\u{10a9f}')
+    ];
+
+    pub const Old_Permic_table: &'static [(char, char)] = &[
+        ('\u{10350}', '\u{1037a}')
+    ];
+
+    pub const Old_Persian_table: &'static [(char, char)] = &[
+        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103d5}')
+    ];
+
+    pub const Old_South_Arabian_table: &'static [(char, char)] = &[
+        ('\u{10a60}', '\u{10a7f}')
+    ];
+
+    pub const Old_Turkic_table: &'static [(char, char)] = &[
+        ('\u{10c00}', '\u{10c48}')
+    ];
+
+    pub const Oriya_table: &'static [(char, char)] = &[
+        ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
+        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
+        ('\u{b35}', '\u{b39}'), ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'),
+        ('\u{b4b}', '\u{b4d}'), ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'),
+        ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b77}')
+    ];
+
+    pub const Osmanya_table: &'static [(char, char)] = &[
+        ('\u{10480}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}')
+    ];
+
+    pub const Pahawh_Hmong_table: &'static [(char, char)] = &[
+        ('\u{16b00}', '\u{16b45}'), ('\u{16b50}', '\u{16b59}'), ('\u{16b5b}',
+        '\u{16b61}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}')
+    ];
+
+    pub const Palmyrene_table: &'static [(char, char)] = &[
+        ('\u{10860}', '\u{1087f}')
+    ];
+
+    pub const Pau_Cin_Hau_table: &'static [(char, char)] = &[
+        ('\u{11ac0}', '\u{11af8}')
+    ];
+
+    pub const Phags_Pa_table: &'static [(char, char)] = &[
+        ('\u{a840}', '\u{a877}')
+    ];
+
+    pub const Phoenician_table: &'static [(char, char)] = &[
+        ('\u{10900}', '\u{1091b}'), ('\u{1091f}', '\u{1091f}')
+    ];
+
+    pub const Psalter_Pahlavi_table: &'static [(char, char)] = &[
+        ('\u{10b80}', '\u{10b91}'), ('\u{10b99}', '\u{10b9c}'), ('\u{10ba9}',
+        '\u{10baf}')
+    ];
+
+    pub const Rejang_table: &'static [(char, char)] = &[
+        ('\u{a930}', '\u{a953}'), ('\u{a95f}', '\u{a95f}')
+    ];
+
+    pub const Runic_table: &'static [(char, char)] = &[
+        ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}')
+    ];
+
+    pub const Samaritan_table: &'static [(char, char)] = &[
+        ('\u{800}', '\u{82d}'), ('\u{830}', '\u{83e}')
+    ];
+
+    pub const Saurashtra_table: &'static [(char, char)] = &[
+        ('\u{a880}', '\u{a8c4}'), ('\u{a8ce}', '\u{a8d9}')
+    ];
+
+    pub const Sharada_table: &'static [(char, char)] = &[
+        ('\u{11180}', '\u{111cd}'), ('\u{111d0}', '\u{111df}')
+    ];
+
+    pub const Shavian_table: &'static [(char, char)] = &[
+        ('\u{10450}', '\u{1047f}')
+    ];
+
+    pub const Siddham_table: &'static [(char, char)] = &[
+        ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115dd}')
+    ];
+
+    pub const SignWriting_table: &'static [(char, char)] = &[
+        ('\u{1d800}', '\u{1da8b}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}',
+        '\u{1daaf}')
+    ];
+
+    pub const Sinhala_table: &'static [(char, char)] = &[
+        ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'),
+        ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'),
+        ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+        ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df4}'),
+        ('\u{111e1}', '\u{111f4}')
+    ];
+
+    pub const Sora_Sompeng_table: &'static [(char, char)] = &[
+        ('\u{110d0}', '\u{110e8}'), ('\u{110f0}', '\u{110f9}')
+    ];
+
+    pub const Sundanese_table: &'static [(char, char)] = &[
+        ('\u{1b80}', '\u{1bbf}'), ('\u{1cc0}', '\u{1cc7}')
+    ];
+
+    pub const Syloti_Nagri_table: &'static [(char, char)] = &[
+        ('\u{a800}', '\u{a82b}')
+    ];
+
+    pub const Syriac_table: &'static [(char, char)] = &[
+        ('\u{700}', '\u{70d}'), ('\u{70f}', '\u{74a}'), ('\u{74d}', '\u{74f}')
+    ];
+
+    pub const Tagalog_table: &'static [(char, char)] = &[
+        ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1714}')
+    ];
+
+    pub const Tagbanwa_table: &'static [(char, char)] = &[
+        ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'), ('\u{1772}',
+        '\u{1773}')
+    ];
+
+    pub const Tai_Le_table: &'static [(char, char)] = &[
+        ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}')
+    ];
+
+    pub const Tai_Tham_table: &'static [(char, char)] = &[
+        ('\u{1a20}', '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}',
+        '\u{1a89}'), ('\u{1a90}', '\u{1a99}'), ('\u{1aa0}', '\u{1aad}')
+    ];
+
+    pub const Tai_Viet_table: &'static [(char, char)] = &[
+        ('\u{aa80}', '\u{aac2}'), ('\u{aadb}', '\u{aadf}')
+    ];
+
+    pub const Takri_table: &'static [(char, char)] = &[
+        ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}')
+    ];
+
+    pub const Tamil_table: &'static [(char, char)] = &[
+        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
+        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
+        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
+        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
+        ('\u{bca}', '\u{bcd}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
+        ('\u{be6}', '\u{bfa}')
+    ];
+
+    pub const Telugu_table: &'static [(char, char)] = &[
+        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
+        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
+        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
+        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c66}', '\u{c6f}'),
+        ('\u{c78}', '\u{c7f}')
+    ];
+
+    pub const Thaana_table: &'static [(char, char)] = &[
+        ('\u{780}', '\u{7b1}')
+    ];
+
+    pub const Thai_table: &'static [(char, char)] = &[
+        ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e5b}')
+    ];
+
+    pub const Tibetan_table: &'static [(char, char)] = &[
+        ('\u{f00}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f97}'),
+        ('\u{f99}', '\u{fbc}'), ('\u{fbe}', '\u{fcc}'), ('\u{fce}', '\u{fd4}'),
+        ('\u{fd9}', '\u{fda}')
+    ];
+
+    pub const Tifinagh_table: &'static [(char, char)] = &[
+        ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d70}'), ('\u{2d7f}',
+        '\u{2d7f}')
+    ];
+
+    pub const Tirhuta_table: &'static [(char, char)] = &[
+        ('\u{11480}', '\u{114c7}'), ('\u{114d0}', '\u{114d9}')
+    ];
+
+    pub const Ugaritic_table: &'static [(char, char)] = &[
+        ('\u{10380}', '\u{1039d}'), ('\u{1039f}', '\u{1039f}')
+    ];
+
+    pub const Vai_table: &'static [(char, char)] = &[
+        ('\u{a500}', '\u{a62b}')
+    ];
+
+    pub const Warang_Citi_table: &'static [(char, char)] = &[
+        ('\u{118a0}', '\u{118f2}'), ('\u{118ff}', '\u{118ff}')
+    ];
+
+    pub const Yi_table: &'static [(char, char)] = &[
+        ('\u{a000}', '\u{a48c}'), ('\u{a490}', '\u{a4c6}')
+    ];
+
+}
+
+pub mod property {
+    pub const Join_Control_table: &'static [(char, char)] = &[
+        ('\u{200c}', '\u{200d}')
+    ];
+
+    pub const Noncharacter_Code_Point_table: &'static [(char, char)] = &[
+        ('\u{fdd0}', '\u{fdef}'), ('\u{fffe}', '\u{ffff}'), ('\u{1fffe}',
+        '\u{1ffff}'), ('\u{2fffe}', '\u{2ffff}'), ('\u{3fffe}', '\u{3ffff}'),
+        ('\u{4fffe}', '\u{4ffff}'), ('\u{5fffe}', '\u{5ffff}'), ('\u{6fffe}',
+        '\u{6ffff}'), ('\u{7fffe}', '\u{7ffff}'), ('\u{8fffe}', '\u{8ffff}'),
+        ('\u{9fffe}', '\u{9ffff}'), ('\u{afffe}', '\u{affff}'), ('\u{bfffe}',
+        '\u{bffff}'), ('\u{cfffe}', '\u{cffff}'), ('\u{dfffe}', '\u{dffff}'),
+        ('\u{efffe}', '\u{effff}'), ('\u{ffffe}', '\u{fffff}'), ('\u{10fffe}',
+        '\u{10ffff}')
+    ];
+
+    pub const White_Space_table: &'static [(char, char)] = &[
+        ('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'),
+        ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'), ('\u{2000}',
+        '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+        ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}')
+    ];
+
+}
+
+pub mod regex {
+    pub const UNICODE_CLASSES: &'static [(&'static str, &'static [(char, char)])] = &[
+        ("Ahom", super::script::Ahom_table), ("Alphabetic",
+        super::derived_property::Alphabetic_table), ("Anatolian_Hieroglyphs",
+        super::script::Anatolian_Hieroglyphs_table), ("Arabic",
+        super::script::Arabic_table), ("Armenian",
+        super::script::Armenian_table), ("Avestan",
+        super::script::Avestan_table), ("Balinese",
+        super::script::Balinese_table), ("Bamum", super::script::Bamum_table),
+        ("Bassa_Vah", super::script::Bassa_Vah_table), ("Batak",
+        super::script::Batak_table), ("Bengali", super::script::Bengali_table),
+        ("Bopomofo", super::script::Bopomofo_table), ("Brahmi",
+        super::script::Brahmi_table), ("Braille", super::script::Braille_table),
+        ("Buginese", super::script::Buginese_table), ("Buhid",
+        super::script::Buhid_table), ("C", super::general_category::C_table),
+        ("Canadian_Aboriginal", super::script::Canadian_Aboriginal_table),
+        ("Carian", super::script::Carian_table), ("Caucasian_Albanian",
+        super::script::Caucasian_Albanian_table), ("Cc",
+        super::general_category::Cc_table), ("Cf",
+        super::general_category::Cf_table), ("Chakma",
+        super::script::Chakma_table), ("Cham", super::script::Cham_table),
+        ("Cherokee", super::script::Cherokee_table), ("Cn",
+        super::general_category::Cn_table), ("Co",
+        super::general_category::Co_table), ("Common",
+        super::script::Common_table), ("Coptic", super::script::Coptic_table),
+        ("Cuneiform", super::script::Cuneiform_table), ("Cypriot",
+        super::script::Cypriot_table), ("Cyrillic",
+        super::script::Cyrillic_table), ("Default_Ignorable_Code_Point",
+        super::derived_property::Default_Ignorable_Code_Point_table),
+        ("Deseret", super::script::Deseret_table), ("Devanagari",
+        super::script::Devanagari_table), ("Duployan",
+        super::script::Duployan_table), ("Egyptian_Hieroglyphs",
+        super::script::Egyptian_Hieroglyphs_table), ("Elbasan",
+        super::script::Elbasan_table), ("Ethiopic",
+        super::script::Ethiopic_table), ("Georgian",
+        super::script::Georgian_table), ("Glagolitic",
+        super::script::Glagolitic_table), ("Gothic",
+        super::script::Gothic_table), ("Grantha", super::script::Grantha_table),
+        ("Grapheme_Extend", super::derived_property::Grapheme_Extend_table),
+        ("Greek", super::script::Greek_table), ("Gujarati",
+        super::script::Gujarati_table), ("Gurmukhi",
+        super::script::Gurmukhi_table), ("Han", super::script::Han_table),
+        ("Hangul", super::script::Hangul_table), ("Hanunoo",
+        super::script::Hanunoo_table), ("Hatran", super::script::Hatran_table),
+        ("Hebrew", super::script::Hebrew_table), ("Hiragana",
+        super::script::Hiragana_table), ("Imperial_Aramaic",
+        super::script::Imperial_Aramaic_table), ("Inherited",
+        super::script::Inherited_table), ("Inscriptional_Pahlavi",
+        super::script::Inscriptional_Pahlavi_table), ("Inscriptional_Parthian",
+        super::script::Inscriptional_Parthian_table), ("Javanese",
+        super::script::Javanese_table), ("Join_Control",
+        super::property::Join_Control_table), ("Kaithi",
+        super::script::Kaithi_table), ("Kannada", super::script::Kannada_table),
+        ("Katakana", super::script::Katakana_table), ("Kayah_Li",
+        super::script::Kayah_Li_table), ("Kharoshthi",
+        super::script::Kharoshthi_table), ("Khmer", super::script::Khmer_table),
+        ("Khojki", super::script::Khojki_table), ("Khudawadi",
+        super::script::Khudawadi_table), ("L",
+        super::general_category::L_table), ("LC",
+        super::general_category::LC_table), ("Lao", super::script::Lao_table),
+        ("Latin", super::script::Latin_table), ("Lepcha",
+        super::script::Lepcha_table), ("Limbu", super::script::Limbu_table),
+        ("Linear_A", super::script::Linear_A_table), ("Linear_B",
+        super::script::Linear_B_table), ("Lisu", super::script::Lisu_table),
+        ("Ll", super::general_category::Ll_table), ("Lm",
+        super::general_category::Lm_table), ("Lo",
+        super::general_category::Lo_table), ("Lowercase",
+        super::derived_property::Lowercase_table), ("Lt",
+        super::general_category::Lt_table), ("Lu",
+        super::general_category::Lu_table), ("Lycian",
+        super::script::Lycian_table), ("Lydian", super::script::Lydian_table),
+        ("M", super::general_category::M_table), ("Mahajani",
+        super::script::Mahajani_table), ("Malayalam",
+        super::script::Malayalam_table), ("Mandaic",
+        super::script::Mandaic_table), ("Manichaean",
+        super::script::Manichaean_table), ("Mc",
+        super::general_category::Mc_table), ("Me",
+        super::general_category::Me_table), ("Meetei_Mayek",
+        super::script::Meetei_Mayek_table), ("Mende_Kikakui",
+        super::script::Mende_Kikakui_table), ("Meroitic_Cursive",
+        super::script::Meroitic_Cursive_table), ("Meroitic_Hieroglyphs",
+        super::script::Meroitic_Hieroglyphs_table), ("Miao",
+        super::script::Miao_table), ("Mn", super::general_category::Mn_table),
+        ("Modi", super::script::Modi_table), ("Mongolian",
+        super::script::Mongolian_table), ("Mro", super::script::Mro_table),
+        ("Multani", super::script::Multani_table), ("Myanmar",
+        super::script::Myanmar_table), ("N", super::general_category::N_table),
+        ("Nabataean", super::script::Nabataean_table), ("Nd",
+        super::general_category::Nd_table), ("New_Tai_Lue",
+        super::script::New_Tai_Lue_table), ("Nko", super::script::Nko_table),
+        ("Nl", super::general_category::Nl_table), ("No",
+        super::general_category::No_table), ("Noncharacter_Code_Point",
+        super::property::Noncharacter_Code_Point_table), ("Ogham",
+        super::script::Ogham_table), ("Ol_Chiki",
+        super::script::Ol_Chiki_table), ("Old_Hungarian",
+        super::script::Old_Hungarian_table), ("Old_Italic",
+        super::script::Old_Italic_table), ("Old_North_Arabian",
+        super::script::Old_North_Arabian_table), ("Old_Permic",
+        super::script::Old_Permic_table), ("Old_Persian",
+        super::script::Old_Persian_table), ("Old_South_Arabian",
+        super::script::Old_South_Arabian_table), ("Old_Turkic",
+        super::script::Old_Turkic_table), ("Oriya", super::script::Oriya_table),
+        ("Osmanya", super::script::Osmanya_table), ("P",
+        super::general_category::P_table), ("Pahawh_Hmong",
+        super::script::Pahawh_Hmong_table), ("Palmyrene",
+        super::script::Palmyrene_table), ("Pau_Cin_Hau",
+        super::script::Pau_Cin_Hau_table), ("Pc",
+        super::general_category::Pc_table), ("Pd",
+        super::general_category::Pd_table), ("Pe",
+        super::general_category::Pe_table), ("Pf",
+        super::general_category::Pf_table), ("Phags_Pa",
+        super::script::Phags_Pa_table), ("Phoenician",
+        super::script::Phoenician_table), ("Pi",
+        super::general_category::Pi_table), ("Po",
+        super::general_category::Po_table), ("Ps",
+        super::general_category::Ps_table), ("Psalter_Pahlavi",
+        super::script::Psalter_Pahlavi_table), ("Rejang",
+        super::script::Rejang_table), ("Runic", super::script::Runic_table),
+        ("S", super::general_category::S_table), ("Samaritan",
+        super::script::Samaritan_table), ("Saurashtra",
+        super::script::Saurashtra_table), ("Sc",
+        super::general_category::Sc_table), ("Sharada",
+        super::script::Sharada_table), ("Shavian",
+        super::script::Shavian_table), ("Siddham",
+        super::script::Siddham_table), ("SignWriting",
+        super::script::SignWriting_table), ("Sinhala",
+        super::script::Sinhala_table), ("Sk",
+        super::general_category::Sk_table), ("Sm",
+        super::general_category::Sm_table), ("So",
+        super::general_category::So_table), ("Sora_Sompeng",
+        super::script::Sora_Sompeng_table), ("Sundanese",
+        super::script::Sundanese_table), ("Syloti_Nagri",
+        super::script::Syloti_Nagri_table), ("Syriac",
+        super::script::Syriac_table), ("Tagalog", super::script::Tagalog_table),
+        ("Tagbanwa", super::script::Tagbanwa_table), ("Tai_Le",
+        super::script::Tai_Le_table), ("Tai_Tham",
+        super::script::Tai_Tham_table), ("Tai_Viet",
+        super::script::Tai_Viet_table), ("Takri", super::script::Takri_table),
+        ("Tamil", super::script::Tamil_table), ("Telugu",
+        super::script::Telugu_table), ("Thaana", super::script::Thaana_table),
+        ("Thai", super::script::Thai_table), ("Tibetan",
+        super::script::Tibetan_table), ("Tifinagh",
+        super::script::Tifinagh_table), ("Tirhuta",
+        super::script::Tirhuta_table), ("Ugaritic",
+        super::script::Ugaritic_table), ("Uppercase",
+        super::derived_property::Uppercase_table), ("Vai",
+        super::script::Vai_table), ("Warang_Citi",
+        super::script::Warang_Citi_table), ("White_Space",
+        super::property::White_Space_table), ("XID_Continue",
+        super::derived_property::XID_Continue_table), ("XID_Start",
+        super::derived_property::XID_Start_table), ("Yi",
+        super::script::Yi_table), ("Z", super::general_category::Z_table),
+        ("Zl", super::general_category::Zl_table), ("Zp",
+        super::general_category::Zp_table), ("Zs",
+        super::general_category::Zs_table)
+    ];
+
+    pub const PERLD: &'static [(char, char)] = super::general_category::Nd_table;
+
+    pub const PERLS: &'static [(char, char)] = super::property::White_Space_table;
+
+    pub const PERLW: &'static [(char, char)] = &[
+        ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'),
+        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
+        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'),
+        ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'),
+        ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{300}', '\u{374}'),
+        ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'),
+        ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'),
+        ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'),
+        ('\u{483}', '\u{52f}'), ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'),
+        ('\u{561}', '\u{587}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'),
+        ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'),
+        ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{610}', '\u{61a}'),
+        ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'),
+        ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
+        ('\u{710}', '\u{74a}'), ('\u{74d}', '\u{7b1}'), ('\u{7c0}', '\u{7f5}'),
+        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{82d}'), ('\u{840}', '\u{85b}'),
+        ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{963}'), ('\u{966}', '\u{96f}'),
+        ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
+        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
+        ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
+        ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'),
+        ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{a01}', '\u{a03}'),
+        ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'),
+        ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'),
+        ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'), ('\u{a3e}', '\u{a42}'),
+        ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'),
+        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a66}', '\u{a75}'),
+        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
+        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
+        ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
+        ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
+        ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'), ('\u{b01}', '\u{b03}'),
+        ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'),
+        ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'),
+        ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'),
+        ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'),
+        ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'),
+        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
+        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
+        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
+        ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
+        ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{bef}'),
+        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
+        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
+        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
+        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c66}', '\u{c6f}'),
+        ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
+        ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'),
+        ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
+        ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'),
+        ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'), ('\u{d01}', '\u{d03}'),
+        ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'),
+        ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4e}'),
+        ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d66}', '\u{d6f}'),
+        ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'),
+        ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'),
+        ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'),
+        ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'),
+        ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e4e}'),
+        ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'),
+        ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'),
+        ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'),
+        ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'),
+        ('\u{ead}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'),
+        ('\u{ec6}', '\u{ec6}'), ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'),
+        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f18}', '\u{f19}'),
+        ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'),
+        ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'), ('\u{f49}', '\u{f6c}'),
+        ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'), ('\u{f99}', '\u{fbc}'),
+        ('\u{fc6}', '\u{fc6}'), ('\u{1000}', '\u{1049}'), ('\u{1050}',
+        '\u{109d}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'),
+        ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}',
+        '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'),
+        ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}',
+        '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'),
+        ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
+        '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'),
+        ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}',
+        '\u{135a}'), ('\u{135d}', '\u{135f}'), ('\u{1380}', '\u{138f}'),
+        ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}',
+        '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'),
+        ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}',
+        '\u{170c}'), ('\u{170e}', '\u{1714}'), ('\u{1720}', '\u{1734}'),
+        ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}',
+        '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'),
+        ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dd}'), ('\u{17e0}',
+        '\u{17e9}'), ('\u{180b}', '\u{180d}'), ('\u{1810}', '\u{1819}'),
+        ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}',
+        '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'),
+        ('\u{1930}', '\u{193b}'), ('\u{1946}', '\u{196d}'), ('\u{1970}',
+        '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'),
+        ('\u{19d0}', '\u{19d9}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}',
+        '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'),
+        ('\u{1a90}', '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}',
+        '\u{1abe}'), ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'),
+        ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}',
+        '\u{1c37}'), ('\u{1c40}', '\u{1c49}'), ('\u{1c4d}', '\u{1c7d}'),
+        ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}',
+        '\u{1cf9}'), ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'),
+        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
+        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
+        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
+        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
+        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
+        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
+        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
+        '\u{1ffc}'), ('\u{200c}', '\u{200d}'), ('\u{203f}', '\u{2040}'),
+        ('\u{2054}', '\u{2054}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
+        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{20d0}', '\u{20f0}'),
+        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}',
+        '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2119}', '\u{211d}'),
+        ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}',
+        '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2139}'),
+        ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}',
+        '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{24b6}', '\u{24e9}'),
+        ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}',
+        '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'),
+        ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}',
+        '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d96}'),
+        ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}',
+        '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'),
+        ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}',
+        '\u{2dde}'), ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'),
+        ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}',
+        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'),
+        ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
+        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
+        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
+        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
+        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
+        '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a672}'),
+        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}',
+        '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'),
+        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'), ('\u{a840}',
+        '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'),
+        ('\u{a8e0}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}',
+        '\u{a8fd}'), ('\u{a900}', '\u{a92d}'), ('\u{a930}', '\u{a953}'),
+        ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}',
+        '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'),
+        ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}', '\u{aa59}'), ('\u{aa60}',
+        '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'),
+        ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}',
+        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
+        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}',
+        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'),
+        ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}',
+        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
+        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
+        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'),
+        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
+        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
+        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}',
+        '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'),
+        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{fe33}',
+        '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'), ('\u{fe70}', '\u{fe74}'),
+        ('\u{fe76}', '\u{fefc}'), ('\u{ff10}', '\u{ff19}'), ('\u{ff21}',
+        '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'), ('\u{ff41}', '\u{ff5a}'),
+        ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
+        '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'),
+        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
+        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
+        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10140}',
+        '\u{10174}'), ('\u{101fd}', '\u{101fd}'), ('\u{10280}', '\u{1029c}'),
+        ('\u{102a0}', '\u{102d0}'), ('\u{102e0}', '\u{102e0}'), ('\u{10300}',
+        '\u{1031f}'), ('\u{10330}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'),
+        ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}',
+        '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'),
+        ('\u{104a0}', '\u{104a9}'), ('\u{10500}', '\u{10527}'), ('\u{10530}',
+        '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'),
+        ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}',
+        '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'),
+        ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}',
+        '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}', '\u{108f2}'),
+        ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'), ('\u{10920}',
+        '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'),
+        ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
+        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
+        ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'), ('\u{10a60}',
+        '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'),
+        ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}',
+        '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'),
+        ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}',
+        '\u{10cf2}'), ('\u{11000}', '\u{11046}'), ('\u{11066}', '\u{1106f}'),
+        ('\u{1107f}', '\u{110ba}'), ('\u{110d0}', '\u{110e8}'), ('\u{110f0}',
+        '\u{110f9}'), ('\u{11100}', '\u{11134}'), ('\u{11136}', '\u{1113f}'),
+        ('\u{11150}', '\u{11173}'), ('\u{11176}', '\u{11176}'), ('\u{11180}',
+        '\u{111c4}'), ('\u{111ca}', '\u{111cc}'), ('\u{111d0}', '\u{111da}'),
+        ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
+        '\u{11237}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'),
+        ('\u{1128a}', '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}',
+        '\u{112a8}'), ('\u{112b0}', '\u{112ea}'), ('\u{112f0}', '\u{112f9}'),
+        ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
+        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
+        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}',
+        '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'),
+        ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}',
+        '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}'),
+        ('\u{11480}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{114d0}',
+        '\u{114d9}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115c0}'),
+        ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{11640}'), ('\u{11644}',
+        '\u{11644}'), ('\u{11650}', '\u{11659}'), ('\u{11680}', '\u{116b7}'),
+        ('\u{116c0}', '\u{116c9}'), ('\u{11700}', '\u{11719}'), ('\u{1171d}',
+        '\u{1172b}'), ('\u{11730}', '\u{11739}'), ('\u{118a0}', '\u{118e9}'),
+        ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}',
+        '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'),
+        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
+        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'),
+        ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b00}',
+        '\u{16b36}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b50}', '\u{16b59}'),
+        ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}',
+        '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}', '\u{16f9f}'),
+        ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}',
+        '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'),
+        ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}',
+        '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'),
+        ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'), ('\u{1d400}',
+        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
+        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
+        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
+        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
+        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
+        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
+        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
+        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
+        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
+        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
+        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
+        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1d7ce}',
+        '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'),
+        ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}',
+        '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'), ('\u{1e800}', '\u{1e8c4}'),
+        ('\u{1e8d0}', '\u{1e8d6}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}',
+        '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'),
+        ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}',
+        '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
+        ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
+        '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'),
+        ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}',
+        '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'),
+        ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}',
+        '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
+        ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
+        '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'),
+        ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}',
+        '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'),
+        ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}'), ('\u{20000}',
+        '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'),
+        ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'), ('\u{e0100}',
+        '\u{e01ef}')
+    ];
+
+}
+
+pub mod case_folding {
+    pub const C_plus_S_both_table: &'static [(char, char)] = &[
+        ('\u{41}', '\u{61}'), ('\u{42}', '\u{62}'), ('\u{43}', '\u{63}'),
+        ('\u{44}', '\u{64}'), ('\u{45}', '\u{65}'), ('\u{46}', '\u{66}'),
+        ('\u{47}', '\u{67}'), ('\u{48}', '\u{68}'), ('\u{49}', '\u{69}'),
+        ('\u{4a}', '\u{6a}'), ('\u{4b}', '\u{6b}'), ('\u{4b}', '\u{212a}'),
+        ('\u{4c}', '\u{6c}'), ('\u{4d}', '\u{6d}'), ('\u{4e}', '\u{6e}'),
+        ('\u{4f}', '\u{6f}'), ('\u{50}', '\u{70}'), ('\u{51}', '\u{71}'),
+        ('\u{52}', '\u{72}'), ('\u{53}', '\u{73}'), ('\u{53}', '\u{17f}'),
+        ('\u{54}', '\u{74}'), ('\u{55}', '\u{75}'), ('\u{56}', '\u{76}'),
+        ('\u{57}', '\u{77}'), ('\u{58}', '\u{78}'), ('\u{59}', '\u{79}'),
+        ('\u{5a}', '\u{7a}'), ('\u{61}', '\u{41}'), ('\u{62}', '\u{42}'),
+        ('\u{63}', '\u{43}'), ('\u{64}', '\u{44}'), ('\u{65}', '\u{45}'),
+        ('\u{66}', '\u{46}'), ('\u{67}', '\u{47}'), ('\u{68}', '\u{48}'),
+        ('\u{69}', '\u{49}'), ('\u{6a}', '\u{4a}'), ('\u{6b}', '\u{4b}'),
+        ('\u{6b}', '\u{212a}'), ('\u{6c}', '\u{4c}'), ('\u{6d}', '\u{4d}'),
+        ('\u{6e}', '\u{4e}'), ('\u{6f}', '\u{4f}'), ('\u{70}', '\u{50}'),
+        ('\u{71}', '\u{51}'), ('\u{72}', '\u{52}'), ('\u{73}', '\u{53}'),
+        ('\u{73}', '\u{17f}'), ('\u{74}', '\u{54}'), ('\u{75}', '\u{55}'),
+        ('\u{76}', '\u{56}'), ('\u{77}', '\u{57}'), ('\u{78}', '\u{58}'),
+        ('\u{79}', '\u{59}'), ('\u{7a}', '\u{5a}'), ('\u{b5}', '\u{39c}'),
+        ('\u{b5}', '\u{3bc}'), ('\u{c0}', '\u{e0}'), ('\u{c1}', '\u{e1}'),
+        ('\u{c2}', '\u{e2}'), ('\u{c3}', '\u{e3}'), ('\u{c4}', '\u{e4}'),
+        ('\u{c5}', '\u{e5}'), ('\u{c5}', '\u{212b}'), ('\u{c6}', '\u{e6}'),
+        ('\u{c7}', '\u{e7}'), ('\u{c8}', '\u{e8}'), ('\u{c9}', '\u{e9}'),
+        ('\u{ca}', '\u{ea}'), ('\u{cb}', '\u{eb}'), ('\u{cc}', '\u{ec}'),
+        ('\u{cd}', '\u{ed}'), ('\u{ce}', '\u{ee}'), ('\u{cf}', '\u{ef}'),
+        ('\u{d0}', '\u{f0}'), ('\u{d1}', '\u{f1}'), ('\u{d2}', '\u{f2}'),
+        ('\u{d3}', '\u{f3}'), ('\u{d4}', '\u{f4}'), ('\u{d5}', '\u{f5}'),
+        ('\u{d6}', '\u{f6}'), ('\u{d8}', '\u{f8}'), ('\u{d9}', '\u{f9}'),
+        ('\u{da}', '\u{fa}'), ('\u{db}', '\u{fb}'), ('\u{dc}', '\u{fc}'),
+        ('\u{dd}', '\u{fd}'), ('\u{de}', '\u{fe}'), ('\u{df}', '\u{1e9e}'),
+        ('\u{e0}', '\u{c0}'), ('\u{e1}', '\u{c1}'), ('\u{e2}', '\u{c2}'),
+        ('\u{e3}', '\u{c3}'), ('\u{e4}', '\u{c4}'), ('\u{e5}', '\u{c5}'),
+        ('\u{e5}', '\u{212b}'), ('\u{e6}', '\u{c6}'), ('\u{e7}', '\u{c7}'),
+        ('\u{e8}', '\u{c8}'), ('\u{e9}', '\u{c9}'), ('\u{ea}', '\u{ca}'),
+        ('\u{eb}', '\u{cb}'), ('\u{ec}', '\u{cc}'), ('\u{ed}', '\u{cd}'),
+        ('\u{ee}', '\u{ce}'), ('\u{ef}', '\u{cf}'), ('\u{f0}', '\u{d0}'),
+        ('\u{f1}', '\u{d1}'), ('\u{f2}', '\u{d2}'), ('\u{f3}', '\u{d3}'),
+        ('\u{f4}', '\u{d4}'), ('\u{f5}', '\u{d5}'), ('\u{f6}', '\u{d6}'),
+        ('\u{f8}', '\u{d8}'), ('\u{f9}', '\u{d9}'), ('\u{fa}', '\u{da}'),
+        ('\u{fb}', '\u{db}'), ('\u{fc}', '\u{dc}'), ('\u{fd}', '\u{dd}'),
+        ('\u{fe}', '\u{de}'), ('\u{ff}', '\u{178}'), ('\u{100}', '\u{101}'),
+        ('\u{101}', '\u{100}'), ('\u{102}', '\u{103}'), ('\u{103}', '\u{102}'),
+        ('\u{104}', '\u{105}'), ('\u{105}', '\u{104}'), ('\u{106}', '\u{107}'),
+        ('\u{107}', '\u{106}'), ('\u{108}', '\u{109}'), ('\u{109}', '\u{108}'),
+        ('\u{10a}', '\u{10b}'), ('\u{10b}', '\u{10a}'), ('\u{10c}', '\u{10d}'),
+        ('\u{10d}', '\u{10c}'), ('\u{10e}', '\u{10f}'), ('\u{10f}', '\u{10e}'),
+        ('\u{110}', '\u{111}'), ('\u{111}', '\u{110}'), ('\u{112}', '\u{113}'),
+        ('\u{113}', '\u{112}'), ('\u{114}', '\u{115}'), ('\u{115}', '\u{114}'),
+        ('\u{116}', '\u{117}'), ('\u{117}', '\u{116}'), ('\u{118}', '\u{119}'),
+        ('\u{119}', '\u{118}'), ('\u{11a}', '\u{11b}'), ('\u{11b}', '\u{11a}'),
+        ('\u{11c}', '\u{11d}'), ('\u{11d}', '\u{11c}'), ('\u{11e}', '\u{11f}'),
+        ('\u{11f}', '\u{11e}'), ('\u{120}', '\u{121}'), ('\u{121}', '\u{120}'),
+        ('\u{122}', '\u{123}'), ('\u{123}', '\u{122}'), ('\u{124}', '\u{125}'),
+        ('\u{125}', '\u{124}'), ('\u{126}', '\u{127}'), ('\u{127}', '\u{126}'),
+        ('\u{128}', '\u{129}'), ('\u{129}', '\u{128}'), ('\u{12a}', '\u{12b}'),
+        ('\u{12b}', '\u{12a}'), ('\u{12c}', '\u{12d}'), ('\u{12d}', '\u{12c}'),
+        ('\u{12e}', '\u{12f}'), ('\u{12f}', '\u{12e}'), ('\u{132}', '\u{133}'),
+        ('\u{133}', '\u{132}'), ('\u{134}', '\u{135}'), ('\u{135}', '\u{134}'),
+        ('\u{136}', '\u{137}'), ('\u{137}', '\u{136}'), ('\u{139}', '\u{13a}'),
+        ('\u{13a}', '\u{139}'), ('\u{13b}', '\u{13c}'), ('\u{13c}', '\u{13b}'),
+        ('\u{13d}', '\u{13e}'), ('\u{13e}', '\u{13d}'), ('\u{13f}', '\u{140}'),
+        ('\u{140}', '\u{13f}'), ('\u{141}', '\u{142}'), ('\u{142}', '\u{141}'),
+        ('\u{143}', '\u{144}'), ('\u{144}', '\u{143}'), ('\u{145}', '\u{146}'),
+        ('\u{146}', '\u{145}'), ('\u{147}', '\u{148}'), ('\u{148}', '\u{147}'),
+        ('\u{14a}', '\u{14b}'), ('\u{14b}', '\u{14a}'), ('\u{14c}', '\u{14d}'),
+        ('\u{14d}', '\u{14c}'), ('\u{14e}', '\u{14f}'), ('\u{14f}', '\u{14e}'),
+        ('\u{150}', '\u{151}'), ('\u{151}', '\u{150}'), ('\u{152}', '\u{153}'),
+        ('\u{153}', '\u{152}'), ('\u{154}', '\u{155}'), ('\u{155}', '\u{154}'),
+        ('\u{156}', '\u{157}'), ('\u{157}', '\u{156}'), ('\u{158}', '\u{159}'),
+        ('\u{159}', '\u{158}'), ('\u{15a}', '\u{15b}'), ('\u{15b}', '\u{15a}'),
+        ('\u{15c}', '\u{15d}'), ('\u{15d}', '\u{15c}'), ('\u{15e}', '\u{15f}'),
+        ('\u{15f}', '\u{15e}'), ('\u{160}', '\u{161}'), ('\u{161}', '\u{160}'),
+        ('\u{162}', '\u{163}'), ('\u{163}', '\u{162}'), ('\u{164}', '\u{165}'),
+        ('\u{165}', '\u{164}'), ('\u{166}', '\u{167}'), ('\u{167}', '\u{166}'),
+        ('\u{168}', '\u{169}'), ('\u{169}', '\u{168}'), ('\u{16a}', '\u{16b}'),
+        ('\u{16b}', '\u{16a}'), ('\u{16c}', '\u{16d}'), ('\u{16d}', '\u{16c}'),
+        ('\u{16e}', '\u{16f}'), ('\u{16f}', '\u{16e}'), ('\u{170}', '\u{171}'),
+        ('\u{171}', '\u{170}'), ('\u{172}', '\u{173}'), ('\u{173}', '\u{172}'),
+        ('\u{174}', '\u{175}'), ('\u{175}', '\u{174}'), ('\u{176}', '\u{177}'),
+        ('\u{177}', '\u{176}'), ('\u{178}', '\u{ff}'), ('\u{179}', '\u{17a}'),
+        ('\u{17a}', '\u{179}'), ('\u{17b}', '\u{17c}'), ('\u{17c}', '\u{17b}'),
+        ('\u{17d}', '\u{17e}'), ('\u{17e}', '\u{17d}'), ('\u{17f}', '\u{53}'),
+        ('\u{17f}', '\u{73}'), ('\u{180}', '\u{243}'), ('\u{181}', '\u{253}'),
+        ('\u{182}', '\u{183}'), ('\u{183}', '\u{182}'), ('\u{184}', '\u{185}'),
+        ('\u{185}', '\u{184}'), ('\u{186}', '\u{254}'), ('\u{187}', '\u{188}'),
+        ('\u{188}', '\u{187}'), ('\u{189}', '\u{256}'), ('\u{18a}', '\u{257}'),
+        ('\u{18b}', '\u{18c}'), ('\u{18c}', '\u{18b}'), ('\u{18e}', '\u{1dd}'),
+        ('\u{18f}', '\u{259}'), ('\u{190}', '\u{25b}'), ('\u{191}', '\u{192}'),
+        ('\u{192}', '\u{191}'), ('\u{193}', '\u{260}'), ('\u{194}', '\u{263}'),
+        ('\u{195}', '\u{1f6}'), ('\u{196}', '\u{269}'), ('\u{197}', '\u{268}'),
+        ('\u{198}', '\u{199}'), ('\u{199}', '\u{198}'), ('\u{19a}', '\u{23d}'),
+        ('\u{19c}', '\u{26f}'), ('\u{19d}', '\u{272}'), ('\u{19e}', '\u{220}'),
+        ('\u{19f}', '\u{275}'), ('\u{1a0}', '\u{1a1}'), ('\u{1a1}', '\u{1a0}'),
+        ('\u{1a2}', '\u{1a3}'), ('\u{1a3}', '\u{1a2}'), ('\u{1a4}', '\u{1a5}'),
+        ('\u{1a5}', '\u{1a4}'), ('\u{1a6}', '\u{280}'), ('\u{1a7}', '\u{1a8}'),
+        ('\u{1a8}', '\u{1a7}'), ('\u{1a9}', '\u{283}'), ('\u{1ac}', '\u{1ad}'),
+        ('\u{1ad}', '\u{1ac}'), ('\u{1ae}', '\u{288}'), ('\u{1af}', '\u{1b0}'),
+        ('\u{1b0}', '\u{1af}'), ('\u{1b1}', '\u{28a}'), ('\u{1b2}', '\u{28b}'),
+        ('\u{1b3}', '\u{1b4}'), ('\u{1b4}', '\u{1b3}'), ('\u{1b5}', '\u{1b6}'),
+        ('\u{1b6}', '\u{1b5}'), ('\u{1b7}', '\u{292}'), ('\u{1b8}', '\u{1b9}'),
+        ('\u{1b9}', '\u{1b8}'), ('\u{1bc}', '\u{1bd}'), ('\u{1bd}', '\u{1bc}'),
+        ('\u{1bf}', '\u{1f7}'), ('\u{1c4}', '\u{1c5}'), ('\u{1c4}', '\u{1c6}'),
+        ('\u{1c5}', '\u{1c4}'), ('\u{1c5}', '\u{1c6}'), ('\u{1c6}', '\u{1c4}'),
+        ('\u{1c6}', '\u{1c5}'), ('\u{1c7}', '\u{1c8}'), ('\u{1c7}', '\u{1c9}'),
+        ('\u{1c8}', '\u{1c7}'), ('\u{1c8}', '\u{1c9}'), ('\u{1c9}', '\u{1c7}'),
+        ('\u{1c9}', '\u{1c8}'), ('\u{1ca}', '\u{1cb}'), ('\u{1ca}', '\u{1cc}'),
+        ('\u{1cb}', '\u{1ca}'), ('\u{1cb}', '\u{1cc}'), ('\u{1cc}', '\u{1ca}'),
+        ('\u{1cc}', '\u{1cb}'), ('\u{1cd}', '\u{1ce}'), ('\u{1ce}', '\u{1cd}'),
+        ('\u{1cf}', '\u{1d0}'), ('\u{1d0}', '\u{1cf}'), ('\u{1d1}', '\u{1d2}'),
+        ('\u{1d2}', '\u{1d1}'), ('\u{1d3}', '\u{1d4}'), ('\u{1d4}', '\u{1d3}'),
+        ('\u{1d5}', '\u{1d6}'), ('\u{1d6}', '\u{1d5}'), ('\u{1d7}', '\u{1d8}'),
+        ('\u{1d8}', '\u{1d7}'), ('\u{1d9}', '\u{1da}'), ('\u{1da}', '\u{1d9}'),
+        ('\u{1db}', '\u{1dc}'), ('\u{1dc}', '\u{1db}'), ('\u{1dd}', '\u{18e}'),
+        ('\u{1de}', '\u{1df}'), ('\u{1df}', '\u{1de}'), ('\u{1e0}', '\u{1e1}'),
+        ('\u{1e1}', '\u{1e0}'), ('\u{1e2}', '\u{1e3}'), ('\u{1e3}', '\u{1e2}'),
+        ('\u{1e4}', '\u{1e5}'), ('\u{1e5}', '\u{1e4}'), ('\u{1e6}', '\u{1e7}'),
+        ('\u{1e7}', '\u{1e6}'), ('\u{1e8}', '\u{1e9}'), ('\u{1e9}', '\u{1e8}'),
+        ('\u{1ea}', '\u{1eb}'), ('\u{1eb}', '\u{1ea}'), ('\u{1ec}', '\u{1ed}'),
+        ('\u{1ed}', '\u{1ec}'), ('\u{1ee}', '\u{1ef}'), ('\u{1ef}', '\u{1ee}'),
+        ('\u{1f1}', '\u{1f2}'), ('\u{1f1}', '\u{1f3}'), ('\u{1f2}', '\u{1f1}'),
+        ('\u{1f2}', '\u{1f3}'), ('\u{1f3}', '\u{1f1}'), ('\u{1f3}', '\u{1f2}'),
+        ('\u{1f4}', '\u{1f5}'), ('\u{1f5}', '\u{1f4}'), ('\u{1f6}', '\u{195}'),
+        ('\u{1f7}', '\u{1bf}'), ('\u{1f8}', '\u{1f9}'), ('\u{1f9}', '\u{1f8}'),
+        ('\u{1fa}', '\u{1fb}'), ('\u{1fb}', '\u{1fa}'), ('\u{1fc}', '\u{1fd}'),
+        ('\u{1fd}', '\u{1fc}'), ('\u{1fe}', '\u{1ff}'), ('\u{1ff}', '\u{1fe}'),
+        ('\u{200}', '\u{201}'), ('\u{201}', '\u{200}'), ('\u{202}', '\u{203}'),
+        ('\u{203}', '\u{202}'), ('\u{204}', '\u{205}'), ('\u{205}', '\u{204}'),
+        ('\u{206}', '\u{207}'), ('\u{207}', '\u{206}'), ('\u{208}', '\u{209}'),
+        ('\u{209}', '\u{208}'), ('\u{20a}', '\u{20b}'), ('\u{20b}', '\u{20a}'),
+        ('\u{20c}', '\u{20d}'), ('\u{20d}', '\u{20c}'), ('\u{20e}', '\u{20f}'),
+        ('\u{20f}', '\u{20e}'), ('\u{210}', '\u{211}'), ('\u{211}', '\u{210}'),
+        ('\u{212}', '\u{213}'), ('\u{213}', '\u{212}'), ('\u{214}', '\u{215}'),
+        ('\u{215}', '\u{214}'), ('\u{216}', '\u{217}'), ('\u{217}', '\u{216}'),
+        ('\u{218}', '\u{219}'), ('\u{219}', '\u{218}'), ('\u{21a}', '\u{21b}'),
+        ('\u{21b}', '\u{21a}'), ('\u{21c}', '\u{21d}'), ('\u{21d}', '\u{21c}'),
+        ('\u{21e}', '\u{21f}'), ('\u{21f}', '\u{21e}'), ('\u{220}', '\u{19e}'),
+        ('\u{222}', '\u{223}'), ('\u{223}', '\u{222}'), ('\u{224}', '\u{225}'),
+        ('\u{225}', '\u{224}'), ('\u{226}', '\u{227}'), ('\u{227}', '\u{226}'),
+        ('\u{228}', '\u{229}'), ('\u{229}', '\u{228}'), ('\u{22a}', '\u{22b}'),
+        ('\u{22b}', '\u{22a}'), ('\u{22c}', '\u{22d}'), ('\u{22d}', '\u{22c}'),
+        ('\u{22e}', '\u{22f}'), ('\u{22f}', '\u{22e}'), ('\u{230}', '\u{231}'),
+        ('\u{231}', '\u{230}'), ('\u{232}', '\u{233}'), ('\u{233}', '\u{232}'),
+        ('\u{23a}', '\u{2c65}'), ('\u{23b}', '\u{23c}'), ('\u{23c}', '\u{23b}'),
+        ('\u{23d}', '\u{19a}'), ('\u{23e}', '\u{2c66}'), ('\u{23f}',
+        '\u{2c7e}'), ('\u{240}', '\u{2c7f}'), ('\u{241}', '\u{242}'),
+        ('\u{242}', '\u{241}'), ('\u{243}', '\u{180}'), ('\u{244}', '\u{289}'),
+        ('\u{245}', '\u{28c}'), ('\u{246}', '\u{247}'), ('\u{247}', '\u{246}'),
+        ('\u{248}', '\u{249}'), ('\u{249}', '\u{248}'), ('\u{24a}', '\u{24b}'),
+        ('\u{24b}', '\u{24a}'), ('\u{24c}', '\u{24d}'), ('\u{24d}', '\u{24c}'),
+        ('\u{24e}', '\u{24f}'), ('\u{24f}', '\u{24e}'), ('\u{250}', '\u{2c6f}'),
+        ('\u{251}', '\u{2c6d}'), ('\u{252}', '\u{2c70}'), ('\u{253}',
+        '\u{181}'), ('\u{254}', '\u{186}'), ('\u{256}', '\u{189}'), ('\u{257}',
+        '\u{18a}'), ('\u{259}', '\u{18f}'), ('\u{25b}', '\u{190}'), ('\u{25c}',
+        '\u{a7ab}'), ('\u{260}', '\u{193}'), ('\u{261}', '\u{a7ac}'),
+        ('\u{263}', '\u{194}'), ('\u{265}', '\u{a78d}'), ('\u{266}',
+        '\u{a7aa}'), ('\u{268}', '\u{197}'), ('\u{269}', '\u{196}'), ('\u{26b}',
+        '\u{2c62}'), ('\u{26c}', '\u{a7ad}'), ('\u{26f}', '\u{19c}'),
+        ('\u{271}', '\u{2c6e}'), ('\u{272}', '\u{19d}'), ('\u{275}', '\u{19f}'),
+        ('\u{27d}', '\u{2c64}'), ('\u{280}', '\u{1a6}'), ('\u{283}', '\u{1a9}'),
+        ('\u{287}', '\u{a7b1}'), ('\u{288}', '\u{1ae}'), ('\u{289}', '\u{244}'),
+        ('\u{28a}', '\u{1b1}'), ('\u{28b}', '\u{1b2}'), ('\u{28c}', '\u{245}'),
+        ('\u{292}', '\u{1b7}'), ('\u{29d}', '\u{a7b2}'), ('\u{29e}',
+        '\u{a7b0}'), ('\u{345}', '\u{399}'), ('\u{345}', '\u{3b9}'), ('\u{345}',
+        '\u{1fbe}'), ('\u{370}', '\u{371}'), ('\u{371}', '\u{370}'), ('\u{372}',
+        '\u{373}'), ('\u{373}', '\u{372}'), ('\u{376}', '\u{377}'), ('\u{377}',
+        '\u{376}'), ('\u{37b}', '\u{3fd}'), ('\u{37c}', '\u{3fe}'), ('\u{37d}',
+        '\u{3ff}'), ('\u{37f}', '\u{3f3}'), ('\u{386}', '\u{3ac}'), ('\u{388}',
+        '\u{3ad}'), ('\u{389}', '\u{3ae}'), ('\u{38a}', '\u{3af}'), ('\u{38c}',
+        '\u{3cc}'), ('\u{38e}', '\u{3cd}'), ('\u{38f}', '\u{3ce}'), ('\u{391}',
+        '\u{3b1}'), ('\u{392}', '\u{3b2}'), ('\u{392}', '\u{3d0}'), ('\u{393}',
+        '\u{3b3}'), ('\u{394}', '\u{3b4}'), ('\u{395}', '\u{3b5}'), ('\u{395}',
+        '\u{3f5}'), ('\u{396}', '\u{3b6}'), ('\u{397}', '\u{3b7}'), ('\u{398}',
+        '\u{3b8}'), ('\u{398}', '\u{3d1}'), ('\u{398}', '\u{3f4}'), ('\u{399}',
+        '\u{345}'), ('\u{399}', '\u{3b9}'), ('\u{399}', '\u{1fbe}'), ('\u{39a}',
+        '\u{3ba}'), ('\u{39a}', '\u{3f0}'), ('\u{39b}', '\u{3bb}'), ('\u{39c}',
+        '\u{b5}'), ('\u{39c}', '\u{3bc}'), ('\u{39d}', '\u{3bd}'), ('\u{39e}',
+        '\u{3be}'), ('\u{39f}', '\u{3bf}'), ('\u{3a0}', '\u{3c0}'), ('\u{3a0}',
+        '\u{3d6}'), ('\u{3a1}', '\u{3c1}'), ('\u{3a1}', '\u{3f1}'), ('\u{3a3}',
+        '\u{3c2}'), ('\u{3a3}', '\u{3c3}'), ('\u{3a4}', '\u{3c4}'), ('\u{3a5}',
+        '\u{3c5}'), ('\u{3a6}', '\u{3c6}'), ('\u{3a6}', '\u{3d5}'), ('\u{3a7}',
+        '\u{3c7}'), ('\u{3a8}', '\u{3c8}'), ('\u{3a9}', '\u{3c9}'), ('\u{3a9}',
+        '\u{2126}'), ('\u{3aa}', '\u{3ca}'), ('\u{3ab}', '\u{3cb}'), ('\u{3ac}',
+        '\u{386}'), ('\u{3ad}', '\u{388}'), ('\u{3ae}', '\u{389}'), ('\u{3af}',
+        '\u{38a}'), ('\u{3b1}', '\u{391}'), ('\u{3b2}', '\u{392}'), ('\u{3b2}',
+        '\u{3d0}'), ('\u{3b3}', '\u{393}'), ('\u{3b4}', '\u{394}'), ('\u{3b5}',
+        '\u{395}'), ('\u{3b5}', '\u{3f5}'), ('\u{3b6}', '\u{396}'), ('\u{3b7}',
+        '\u{397}'), ('\u{3b8}', '\u{398}'), ('\u{3b8}', '\u{3d1}'), ('\u{3b8}',
+        '\u{3f4}'), ('\u{3b9}', '\u{345}'), ('\u{3b9}', '\u{399}'), ('\u{3b9}',
+        '\u{1fbe}'), ('\u{3ba}', '\u{39a}'), ('\u{3ba}', '\u{3f0}'), ('\u{3bb}',
+        '\u{39b}'), ('\u{3bc}', '\u{b5}'), ('\u{3bc}', '\u{39c}'), ('\u{3bd}',
+        '\u{39d}'), ('\u{3be}', '\u{39e}'), ('\u{3bf}', '\u{39f}'), ('\u{3c0}',
+        '\u{3a0}'), ('\u{3c0}', '\u{3d6}'), ('\u{3c1}', '\u{3a1}'), ('\u{3c1}',
+        '\u{3f1}'), ('\u{3c2}', '\u{3a3}'), ('\u{3c2}', '\u{3c3}'), ('\u{3c3}',
+        '\u{3a3}'), ('\u{3c3}', '\u{3c2}'), ('\u{3c4}', '\u{3a4}'), ('\u{3c5}',
+        '\u{3a5}'), ('\u{3c6}', '\u{3a6}'), ('\u{3c6}', '\u{3d5}'), ('\u{3c7}',
+        '\u{3a7}'), ('\u{3c8}', '\u{3a8}'), ('\u{3c9}', '\u{3a9}'), ('\u{3c9}',
+        '\u{2126}'), ('\u{3ca}', '\u{3aa}'), ('\u{3cb}', '\u{3ab}'), ('\u{3cc}',
+        '\u{38c}'), ('\u{3cd}', '\u{38e}'), ('\u{3ce}', '\u{38f}'), ('\u{3cf}',
+        '\u{3d7}'), ('\u{3d0}', '\u{392}'), ('\u{3d0}', '\u{3b2}'), ('\u{3d1}',
+        '\u{398}'), ('\u{3d1}', '\u{3b8}'), ('\u{3d1}', '\u{3f4}'), ('\u{3d5}',
+        '\u{3a6}'), ('\u{3d5}', '\u{3c6}'), ('\u{3d6}', '\u{3a0}'), ('\u{3d6}',
+        '\u{3c0}'), ('\u{3d7}', '\u{3cf}'), ('\u{3d8}', '\u{3d9}'), ('\u{3d9}',
+        '\u{3d8}'), ('\u{3da}', '\u{3db}'), ('\u{3db}', '\u{3da}'), ('\u{3dc}',
+        '\u{3dd}'), ('\u{3dd}', '\u{3dc}'), ('\u{3de}', '\u{3df}'), ('\u{3df}',
+        '\u{3de}'), ('\u{3e0}', '\u{3e1}'), ('\u{3e1}', '\u{3e0}'), ('\u{3e2}',
+        '\u{3e3}'), ('\u{3e3}', '\u{3e2}'), ('\u{3e4}', '\u{3e5}'), ('\u{3e5}',
+        '\u{3e4}'), ('\u{3e6}', '\u{3e7}'), ('\u{3e7}', '\u{3e6}'), ('\u{3e8}',
+        '\u{3e9}'), ('\u{3e9}', '\u{3e8}'), ('\u{3ea}', '\u{3eb}'), ('\u{3eb}',
+        '\u{3ea}'), ('\u{3ec}', '\u{3ed}'), ('\u{3ed}', '\u{3ec}'), ('\u{3ee}',
+        '\u{3ef}'), ('\u{3ef}', '\u{3ee}'), ('\u{3f0}', '\u{39a}'), ('\u{3f0}',
+        '\u{3ba}'), ('\u{3f1}', '\u{3a1}'), ('\u{3f1}', '\u{3c1}'), ('\u{3f2}',
+        '\u{3f9}'), ('\u{3f3}', '\u{37f}'), ('\u{3f4}', '\u{398}'), ('\u{3f4}',
+        '\u{3b8}'), ('\u{3f4}', '\u{3d1}'), ('\u{3f5}', '\u{395}'), ('\u{3f5}',
+        '\u{3b5}'), ('\u{3f7}', '\u{3f8}'), ('\u{3f8}', '\u{3f7}'), ('\u{3f9}',
+        '\u{3f2}'), ('\u{3fa}', '\u{3fb}'), ('\u{3fb}', '\u{3fa}'), ('\u{3fd}',
+        '\u{37b}'), ('\u{3fe}', '\u{37c}'), ('\u{3ff}', '\u{37d}'), ('\u{400}',
+        '\u{450}'), ('\u{401}', '\u{451}'), ('\u{402}', '\u{452}'), ('\u{403}',
+        '\u{453}'), ('\u{404}', '\u{454}'), ('\u{405}', '\u{455}'), ('\u{406}',
+        '\u{456}'), ('\u{407}', '\u{457}'), ('\u{408}', '\u{458}'), ('\u{409}',
+        '\u{459}'), ('\u{40a}', '\u{45a}'), ('\u{40b}', '\u{45b}'), ('\u{40c}',
+        '\u{45c}'), ('\u{40d}', '\u{45d}'), ('\u{40e}', '\u{45e}'), ('\u{40f}',
+        '\u{45f}'), ('\u{410}', '\u{430}'), ('\u{411}', '\u{431}'), ('\u{412}',
+        '\u{432}'), ('\u{413}', '\u{433}'), ('\u{414}', '\u{434}'), ('\u{415}',
+        '\u{435}'), ('\u{416}', '\u{436}'), ('\u{417}', '\u{437}'), ('\u{418}',
+        '\u{438}'), ('\u{419}', '\u{439}'), ('\u{41a}', '\u{43a}'), ('\u{41b}',
+        '\u{43b}'), ('\u{41c}', '\u{43c}'), ('\u{41d}', '\u{43d}'), ('\u{41e}',
+        '\u{43e}'), ('\u{41f}', '\u{43f}'), ('\u{420}', '\u{440}'), ('\u{421}',
+        '\u{441}'), ('\u{422}', '\u{442}'), ('\u{423}', '\u{443}'), ('\u{424}',
+        '\u{444}'), ('\u{425}', '\u{445}'), ('\u{426}', '\u{446}'), ('\u{427}',
+        '\u{447}'), ('\u{428}', '\u{448}'), ('\u{429}', '\u{449}'), ('\u{42a}',
+        '\u{44a}'), ('\u{42b}', '\u{44b}'), ('\u{42c}', '\u{44c}'), ('\u{42d}',
+        '\u{44d}'), ('\u{42e}', '\u{44e}'), ('\u{42f}', '\u{44f}'), ('\u{430}',
+        '\u{410}'), ('\u{431}', '\u{411}'), ('\u{432}', '\u{412}'), ('\u{433}',
+        '\u{413}'), ('\u{434}', '\u{414}'), ('\u{435}', '\u{415}'), ('\u{436}',
+        '\u{416}'), ('\u{437}', '\u{417}'), ('\u{438}', '\u{418}'), ('\u{439}',
+        '\u{419}'), ('\u{43a}', '\u{41a}'), ('\u{43b}', '\u{41b}'), ('\u{43c}',
+        '\u{41c}'), ('\u{43d}', '\u{41d}'), ('\u{43e}', '\u{41e}'), ('\u{43f}',
+        '\u{41f}'), ('\u{440}', '\u{420}'), ('\u{441}', '\u{421}'), ('\u{442}',
+        '\u{422}'), ('\u{443}', '\u{423}'), ('\u{444}', '\u{424}'), ('\u{445}',
+        '\u{425}'), ('\u{446}', '\u{426}'), ('\u{447}', '\u{427}'), ('\u{448}',
+        '\u{428}'), ('\u{449}', '\u{429}'), ('\u{44a}', '\u{42a}'), ('\u{44b}',
+        '\u{42b}'), ('\u{44c}', '\u{42c}'), ('\u{44d}', '\u{42d}'), ('\u{44e}',
+        '\u{42e}'), ('\u{44f}', '\u{42f}'), ('\u{450}', '\u{400}'), ('\u{451}',
+        '\u{401}'), ('\u{452}', '\u{402}'), ('\u{453}', '\u{403}'), ('\u{454}',
+        '\u{404}'), ('\u{455}', '\u{405}'), ('\u{456}', '\u{406}'), ('\u{457}',
+        '\u{407}'), ('\u{458}', '\u{408}'), ('\u{459}', '\u{409}'), ('\u{45a}',
+        '\u{40a}'), ('\u{45b}', '\u{40b}'), ('\u{45c}', '\u{40c}'), ('\u{45d}',
+        '\u{40d}'), ('\u{45e}', '\u{40e}'), ('\u{45f}', '\u{40f}'), ('\u{460}',
+        '\u{461}'), ('\u{461}', '\u{460}'), ('\u{462}', '\u{463}'), ('\u{463}',
+        '\u{462}'), ('\u{464}', '\u{465}'), ('\u{465}', '\u{464}'), ('\u{466}',
+        '\u{467}'), ('\u{467}', '\u{466}'), ('\u{468}', '\u{469}'), ('\u{469}',
+        '\u{468}'), ('\u{46a}', '\u{46b}'), ('\u{46b}', '\u{46a}'), ('\u{46c}',
+        '\u{46d}'), ('\u{46d}', '\u{46c}'), ('\u{46e}', '\u{46f}'), ('\u{46f}',
+        '\u{46e}'), ('\u{470}', '\u{471}'), ('\u{471}', '\u{470}'), ('\u{472}',
+        '\u{473}'), ('\u{473}', '\u{472}'), ('\u{474}', '\u{475}'), ('\u{475}',
+        '\u{474}'), ('\u{476}', '\u{477}'), ('\u{477}', '\u{476}'), ('\u{478}',
+        '\u{479}'), ('\u{479}', '\u{478}'), ('\u{47a}', '\u{47b}'), ('\u{47b}',
+        '\u{47a}'), ('\u{47c}', '\u{47d}'), ('\u{47d}', '\u{47c}'), ('\u{47e}',
+        '\u{47f}'), ('\u{47f}', '\u{47e}'), ('\u{480}', '\u{481}'), ('\u{481}',
+        '\u{480}'), ('\u{48a}', '\u{48b}'), ('\u{48b}', '\u{48a}'), ('\u{48c}',
+        '\u{48d}'), ('\u{48d}', '\u{48c}'), ('\u{48e}', '\u{48f}'), ('\u{48f}',
+        '\u{48e}'), ('\u{490}', '\u{491}'), ('\u{491}', '\u{490}'), ('\u{492}',
+        '\u{493}'), ('\u{493}', '\u{492}'), ('\u{494}', '\u{495}'), ('\u{495}',
+        '\u{494}'), ('\u{496}', '\u{497}'), ('\u{497}', '\u{496}'), ('\u{498}',
+        '\u{499}'), ('\u{499}', '\u{498}'), ('\u{49a}', '\u{49b}'), ('\u{49b}',
+        '\u{49a}'), ('\u{49c}', '\u{49d}'), ('\u{49d}', '\u{49c}'), ('\u{49e}',
+        '\u{49f}'), ('\u{49f}', '\u{49e}'), ('\u{4a0}', '\u{4a1}'), ('\u{4a1}',
+        '\u{4a0}'), ('\u{4a2}', '\u{4a3}'), ('\u{4a3}', '\u{4a2}'), ('\u{4a4}',
+        '\u{4a5}'), ('\u{4a5}', '\u{4a4}'), ('\u{4a6}', '\u{4a7}'), ('\u{4a7}',
+        '\u{4a6}'), ('\u{4a8}', '\u{4a9}'), ('\u{4a9}', '\u{4a8}'), ('\u{4aa}',
+        '\u{4ab}'), ('\u{4ab}', '\u{4aa}'), ('\u{4ac}', '\u{4ad}'), ('\u{4ad}',
+        '\u{4ac}'), ('\u{4ae}', '\u{4af}'), ('\u{4af}', '\u{4ae}'), ('\u{4b0}',
+        '\u{4b1}'), ('\u{4b1}', '\u{4b0}'), ('\u{4b2}', '\u{4b3}'), ('\u{4b3}',
+        '\u{4b2}'), ('\u{4b4}', '\u{4b5}'), ('\u{4b5}', '\u{4b4}'), ('\u{4b6}',
+        '\u{4b7}'), ('\u{4b7}', '\u{4b6}'), ('\u{4b8}', '\u{4b9}'), ('\u{4b9}',
+        '\u{4b8}'), ('\u{4ba}', '\u{4bb}'), ('\u{4bb}', '\u{4ba}'), ('\u{4bc}',
+        '\u{4bd}'), ('\u{4bd}', '\u{4bc}'), ('\u{4be}', '\u{4bf}'), ('\u{4bf}',
+        '\u{4be}'), ('\u{4c0}', '\u{4cf}'), ('\u{4c1}', '\u{4c2}'), ('\u{4c2}',
+        '\u{4c1}'), ('\u{4c3}', '\u{4c4}'), ('\u{4c4}', '\u{4c3}'), ('\u{4c5}',
+        '\u{4c6}'), ('\u{4c6}', '\u{4c5}'), ('\u{4c7}', '\u{4c8}'), ('\u{4c8}',
+        '\u{4c7}'), ('\u{4c9}', '\u{4ca}'), ('\u{4ca}', '\u{4c9}'), ('\u{4cb}',
+        '\u{4cc}'), ('\u{4cc}', '\u{4cb}'), ('\u{4cd}', '\u{4ce}'), ('\u{4ce}',
+        '\u{4cd}'), ('\u{4cf}', '\u{4c0}'), ('\u{4d0}', '\u{4d1}'), ('\u{4d1}',
+        '\u{4d0}'), ('\u{4d2}', '\u{4d3}'), ('\u{4d3}', '\u{4d2}'), ('\u{4d4}',
+        '\u{4d5}'), ('\u{4d5}', '\u{4d4}'), ('\u{4d6}', '\u{4d7}'), ('\u{4d7}',
+        '\u{4d6}'), ('\u{4d8}', '\u{4d9}'), ('\u{4d9}', '\u{4d8}'), ('\u{4da}',
+        '\u{4db}'), ('\u{4db}', '\u{4da}'), ('\u{4dc}', '\u{4dd}'), ('\u{4dd}',
+        '\u{4dc}'), ('\u{4de}', '\u{4df}'), ('\u{4df}', '\u{4de}'), ('\u{4e0}',
+        '\u{4e1}'), ('\u{4e1}', '\u{4e0}'), ('\u{4e2}', '\u{4e3}'), ('\u{4e3}',
+        '\u{4e2}'), ('\u{4e4}', '\u{4e5}'), ('\u{4e5}', '\u{4e4}'), ('\u{4e6}',
+        '\u{4e7}'), ('\u{4e7}', '\u{4e6}'), ('\u{4e8}', '\u{4e9}'), ('\u{4e9}',
+        '\u{4e8}'), ('\u{4ea}', '\u{4eb}'), ('\u{4eb}', '\u{4ea}'), ('\u{4ec}',
+        '\u{4ed}'), ('\u{4ed}', '\u{4ec}'), ('\u{4ee}', '\u{4ef}'), ('\u{4ef}',
+        '\u{4ee}'), ('\u{4f0}', '\u{4f1}'), ('\u{4f1}', '\u{4f0}'), ('\u{4f2}',
+        '\u{4f3}'), ('\u{4f3}', '\u{4f2}'), ('\u{4f4}', '\u{4f5}'), ('\u{4f5}',
+        '\u{4f4}'), ('\u{4f6}', '\u{4f7}'), ('\u{4f7}', '\u{4f6}'), ('\u{4f8}',
+        '\u{4f9}'), ('\u{4f9}', '\u{4f8}'), ('\u{4fa}', '\u{4fb}'), ('\u{4fb}',
+        '\u{4fa}'), ('\u{4fc}', '\u{4fd}'), ('\u{4fd}', '\u{4fc}'), ('\u{4fe}',
+        '\u{4ff}'), ('\u{4ff}', '\u{4fe}'), ('\u{500}', '\u{501}'), ('\u{501}',
+        '\u{500}'), ('\u{502}', '\u{503}'), ('\u{503}', '\u{502}'), ('\u{504}',
+        '\u{505}'), ('\u{505}', '\u{504}'), ('\u{506}', '\u{507}'), ('\u{507}',
+        '\u{506}'), ('\u{508}', '\u{509}'), ('\u{509}', '\u{508}'), ('\u{50a}',
+        '\u{50b}'), ('\u{50b}', '\u{50a}'), ('\u{50c}', '\u{50d}'), ('\u{50d}',
+        '\u{50c}'), ('\u{50e}', '\u{50f}'), ('\u{50f}', '\u{50e}'), ('\u{510}',
+        '\u{511}'), ('\u{511}', '\u{510}'), ('\u{512}', '\u{513}'), ('\u{513}',
+        '\u{512}'), ('\u{514}', '\u{515}'), ('\u{515}', '\u{514}'), ('\u{516}',
+        '\u{517}'), ('\u{517}', '\u{516}'), ('\u{518}', '\u{519}'), ('\u{519}',
+        '\u{518}'), ('\u{51a}', '\u{51b}'), ('\u{51b}', '\u{51a}'), ('\u{51c}',
+        '\u{51d}'), ('\u{51d}', '\u{51c}'), ('\u{51e}', '\u{51f}'), ('\u{51f}',
+        '\u{51e}'), ('\u{520}', '\u{521}'), ('\u{521}', '\u{520}'), ('\u{522}',
+        '\u{523}'), ('\u{523}', '\u{522}'), ('\u{524}', '\u{525}'), ('\u{525}',
+        '\u{524}'), ('\u{526}', '\u{527}'), ('\u{527}', '\u{526}'), ('\u{528}',
+        '\u{529}'), ('\u{529}', '\u{528}'), ('\u{52a}', '\u{52b}'), ('\u{52b}',
+        '\u{52a}'), ('\u{52c}', '\u{52d}'), ('\u{52d}', '\u{52c}'), ('\u{52e}',
+        '\u{52f}'), ('\u{52f}', '\u{52e}'), ('\u{531}', '\u{561}'), ('\u{532}',
+        '\u{562}'), ('\u{533}', '\u{563}'), ('\u{534}', '\u{564}'), ('\u{535}',
+        '\u{565}'), ('\u{536}', '\u{566}'), ('\u{537}', '\u{567}'), ('\u{538}',
+        '\u{568}'), ('\u{539}', '\u{569}'), ('\u{53a}', '\u{56a}'), ('\u{53b}',
+        '\u{56b}'), ('\u{53c}', '\u{56c}'), ('\u{53d}', '\u{56d}'), ('\u{53e}',
+        '\u{56e}'), ('\u{53f}', '\u{56f}'), ('\u{540}', '\u{570}'), ('\u{541}',
+        '\u{571}'), ('\u{542}', '\u{572}'), ('\u{543}', '\u{573}'), ('\u{544}',
+        '\u{574}'), ('\u{545}', '\u{575}'), ('\u{546}', '\u{576}'), ('\u{547}',
+        '\u{577}'), ('\u{548}', '\u{578}'), ('\u{549}', '\u{579}'), ('\u{54a}',
+        '\u{57a}'), ('\u{54b}', '\u{57b}'), ('\u{54c}', '\u{57c}'), ('\u{54d}',
+        '\u{57d}'), ('\u{54e}', '\u{57e}'), ('\u{54f}', '\u{57f}'), ('\u{550}',
+        '\u{580}'), ('\u{551}', '\u{581}'), ('\u{552}', '\u{582}'), ('\u{553}',
+        '\u{583}'), ('\u{554}', '\u{584}'), ('\u{555}', '\u{585}'), ('\u{556}',
+        '\u{586}'), ('\u{561}', '\u{531}'), ('\u{562}', '\u{532}'), ('\u{563}',
+        '\u{533}'), ('\u{564}', '\u{534}'), ('\u{565}', '\u{535}'), ('\u{566}',
+        '\u{536}'), ('\u{567}', '\u{537}'), ('\u{568}', '\u{538}'), ('\u{569}',
+        '\u{539}'), ('\u{56a}', '\u{53a}'), ('\u{56b}', '\u{53b}'), ('\u{56c}',
+        '\u{53c}'), ('\u{56d}', '\u{53d}'), ('\u{56e}', '\u{53e}'), ('\u{56f}',
+        '\u{53f}'), ('\u{570}', '\u{540}'), ('\u{571}', '\u{541}'), ('\u{572}',
+        '\u{542}'), ('\u{573}', '\u{543}'), ('\u{574}', '\u{544}'), ('\u{575}',
+        '\u{545}'), ('\u{576}', '\u{546}'), ('\u{577}', '\u{547}'), ('\u{578}',
+        '\u{548}'), ('\u{579}', '\u{549}'), ('\u{57a}', '\u{54a}'), ('\u{57b}',
+        '\u{54b}'), ('\u{57c}', '\u{54c}'), ('\u{57d}', '\u{54d}'), ('\u{57e}',
+        '\u{54e}'), ('\u{57f}', '\u{54f}'), ('\u{580}', '\u{550}'), ('\u{581}',
+        '\u{551}'), ('\u{582}', '\u{552}'), ('\u{583}', '\u{553}'), ('\u{584}',
+        '\u{554}'), ('\u{585}', '\u{555}'), ('\u{586}', '\u{556}'), ('\u{10a0}',
+        '\u{2d00}'), ('\u{10a1}', '\u{2d01}'), ('\u{10a2}', '\u{2d02}'),
+        ('\u{10a3}', '\u{2d03}'), ('\u{10a4}', '\u{2d04}'), ('\u{10a5}',
+        '\u{2d05}'), ('\u{10a6}', '\u{2d06}'), ('\u{10a7}', '\u{2d07}'),
+        ('\u{10a8}', '\u{2d08}'), ('\u{10a9}', '\u{2d09}'), ('\u{10aa}',
+        '\u{2d0a}'), ('\u{10ab}', '\u{2d0b}'), ('\u{10ac}', '\u{2d0c}'),
+        ('\u{10ad}', '\u{2d0d}'), ('\u{10ae}', '\u{2d0e}'), ('\u{10af}',
+        '\u{2d0f}'), ('\u{10b0}', '\u{2d10}'), ('\u{10b1}', '\u{2d11}'),
+        ('\u{10b2}', '\u{2d12}'), ('\u{10b3}', '\u{2d13}'), ('\u{10b4}',
+        '\u{2d14}'), ('\u{10b5}', '\u{2d15}'), ('\u{10b6}', '\u{2d16}'),
+        ('\u{10b7}', '\u{2d17}'), ('\u{10b8}', '\u{2d18}'), ('\u{10b9}',
+        '\u{2d19}'), ('\u{10ba}', '\u{2d1a}'), ('\u{10bb}', '\u{2d1b}'),
+        ('\u{10bc}', '\u{2d1c}'), ('\u{10bd}', '\u{2d1d}'), ('\u{10be}',
+        '\u{2d1e}'), ('\u{10bf}', '\u{2d1f}'), ('\u{10c0}', '\u{2d20}'),
+        ('\u{10c1}', '\u{2d21}'), ('\u{10c2}', '\u{2d22}'), ('\u{10c3}',
+        '\u{2d23}'), ('\u{10c4}', '\u{2d24}'), ('\u{10c5}', '\u{2d25}'),
+        ('\u{10c7}', '\u{2d27}'), ('\u{10cd}', '\u{2d2d}'), ('\u{13a0}',
+        '\u{ab70}'), ('\u{13a1}', '\u{ab71}'), ('\u{13a2}', '\u{ab72}'),
+        ('\u{13a3}', '\u{ab73}'), ('\u{13a4}', '\u{ab74}'), ('\u{13a5}',
+        '\u{ab75}'), ('\u{13a6}', '\u{ab76}'), ('\u{13a7}', '\u{ab77}'),
+        ('\u{13a8}', '\u{ab78}'), ('\u{13a9}', '\u{ab79}'), ('\u{13aa}',
+        '\u{ab7a}'), ('\u{13ab}', '\u{ab7b}'), ('\u{13ac}', '\u{ab7c}'),
+        ('\u{13ad}', '\u{ab7d}'), ('\u{13ae}', '\u{ab7e}'), ('\u{13af}',
+        '\u{ab7f}'), ('\u{13b0}', '\u{ab80}'), ('\u{13b1}', '\u{ab81}'),
+        ('\u{13b2}', '\u{ab82}'), ('\u{13b3}', '\u{ab83}'), ('\u{13b4}',
+        '\u{ab84}'), ('\u{13b5}', '\u{ab85}'), ('\u{13b6}', '\u{ab86}'),
+        ('\u{13b7}', '\u{ab87}'), ('\u{13b8}', '\u{ab88}'), ('\u{13b9}',
+        '\u{ab89}'), ('\u{13ba}', '\u{ab8a}'), ('\u{13bb}', '\u{ab8b}'),
+        ('\u{13bc}', '\u{ab8c}'), ('\u{13bd}', '\u{ab8d}'), ('\u{13be}',
+        '\u{ab8e}'), ('\u{13bf}', '\u{ab8f}'), ('\u{13c0}', '\u{ab90}'),
+        ('\u{13c1}', '\u{ab91}'), ('\u{13c2}', '\u{ab92}'), ('\u{13c3}',
+        '\u{ab93}'), ('\u{13c4}', '\u{ab94}'), ('\u{13c5}', '\u{ab95}'),
+        ('\u{13c6}', '\u{ab96}'), ('\u{13c7}', '\u{ab97}'), ('\u{13c8}',
+        '\u{ab98}'), ('\u{13c9}', '\u{ab99}'), ('\u{13ca}', '\u{ab9a}'),
+        ('\u{13cb}', '\u{ab9b}'), ('\u{13cc}', '\u{ab9c}'), ('\u{13cd}',
+        '\u{ab9d}'), ('\u{13ce}', '\u{ab9e}'), ('\u{13cf}', '\u{ab9f}'),
+        ('\u{13d0}', '\u{aba0}'), ('\u{13d1}', '\u{aba1}'), ('\u{13d2}',
+        '\u{aba2}'), ('\u{13d3}', '\u{aba3}'), ('\u{13d4}', '\u{aba4}'),
+        ('\u{13d5}', '\u{aba5}'), ('\u{13d6}', '\u{aba6}'), ('\u{13d7}',
+        '\u{aba7}'), ('\u{13d8}', '\u{aba8}'), ('\u{13d9}', '\u{aba9}'),
+        ('\u{13da}', '\u{abaa}'), ('\u{13db}', '\u{abab}'), ('\u{13dc}',
+        '\u{abac}'), ('\u{13dd}', '\u{abad}'), ('\u{13de}', '\u{abae}'),
+        ('\u{13df}', '\u{abaf}'), ('\u{13e0}', '\u{abb0}'), ('\u{13e1}',
+        '\u{abb1}'), ('\u{13e2}', '\u{abb2}'), ('\u{13e3}', '\u{abb3}'),
+        ('\u{13e4}', '\u{abb4}'), ('\u{13e5}', '\u{abb5}'), ('\u{13e6}',
+        '\u{abb6}'), ('\u{13e7}', '\u{abb7}'), ('\u{13e8}', '\u{abb8}'),
+        ('\u{13e9}', '\u{abb9}'), ('\u{13ea}', '\u{abba}'), ('\u{13eb}',
+        '\u{abbb}'), ('\u{13ec}', '\u{abbc}'), ('\u{13ed}', '\u{abbd}'),
+        ('\u{13ee}', '\u{abbe}'), ('\u{13ef}', '\u{abbf}'), ('\u{13f0}',
+        '\u{13f8}'), ('\u{13f1}', '\u{13f9}'), ('\u{13f2}', '\u{13fa}'),
+        ('\u{13f3}', '\u{13fb}'), ('\u{13f4}', '\u{13fc}'), ('\u{13f5}',
+        '\u{13fd}'), ('\u{13f8}', '\u{13f0}'), ('\u{13f9}', '\u{13f1}'),
+        ('\u{13fa}', '\u{13f2}'), ('\u{13fb}', '\u{13f3}'), ('\u{13fc}',
+        '\u{13f4}'), ('\u{13fd}', '\u{13f5}'), ('\u{1d79}', '\u{a77d}'),
+        ('\u{1d7d}', '\u{2c63}'), ('\u{1e00}', '\u{1e01}'), ('\u{1e01}',
+        '\u{1e00}'), ('\u{1e02}', '\u{1e03}'), ('\u{1e03}', '\u{1e02}'),
+        ('\u{1e04}', '\u{1e05}'), ('\u{1e05}', '\u{1e04}'), ('\u{1e06}',
+        '\u{1e07}'), ('\u{1e07}', '\u{1e06}'), ('\u{1e08}', '\u{1e09}'),
+        ('\u{1e09}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0b}'), ('\u{1e0b}',
+        '\u{1e0a}'), ('\u{1e0c}', '\u{1e0d}'), ('\u{1e0d}', '\u{1e0c}'),
+        ('\u{1e0e}', '\u{1e0f}'), ('\u{1e0f}', '\u{1e0e}'), ('\u{1e10}',
+        '\u{1e11}'), ('\u{1e11}', '\u{1e10}'), ('\u{1e12}', '\u{1e13}'),
+        ('\u{1e13}', '\u{1e12}'), ('\u{1e14}', '\u{1e15}'), ('\u{1e15}',
+        '\u{1e14}'), ('\u{1e16}', '\u{1e17}'), ('\u{1e17}', '\u{1e16}'),
+        ('\u{1e18}', '\u{1e19}'), ('\u{1e19}', '\u{1e18}'), ('\u{1e1a}',
+        '\u{1e1b}'), ('\u{1e1b}', '\u{1e1a}'), ('\u{1e1c}', '\u{1e1d}'),
+        ('\u{1e1d}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1f}'), ('\u{1e1f}',
+        '\u{1e1e}'), ('\u{1e20}', '\u{1e21}'), ('\u{1e21}', '\u{1e20}'),
+        ('\u{1e22}', '\u{1e23}'), ('\u{1e23}', '\u{1e22}'), ('\u{1e24}',
+        '\u{1e25}'), ('\u{1e25}', '\u{1e24}'), ('\u{1e26}', '\u{1e27}'),
+        ('\u{1e27}', '\u{1e26}'), ('\u{1e28}', '\u{1e29}'), ('\u{1e29}',
+        '\u{1e28}'), ('\u{1e2a}', '\u{1e2b}'), ('\u{1e2b}', '\u{1e2a}'),
+        ('\u{1e2c}', '\u{1e2d}'), ('\u{1e2d}', '\u{1e2c}'), ('\u{1e2e}',
+        '\u{1e2f}'), ('\u{1e2f}', '\u{1e2e}'), ('\u{1e30}', '\u{1e31}'),
+        ('\u{1e31}', '\u{1e30}'), ('\u{1e32}', '\u{1e33}'), ('\u{1e33}',
+        '\u{1e32}'), ('\u{1e34}', '\u{1e35}'), ('\u{1e35}', '\u{1e34}'),
+        ('\u{1e36}', '\u{1e37}'), ('\u{1e37}', '\u{1e36}'), ('\u{1e38}',
+        '\u{1e39}'), ('\u{1e39}', '\u{1e38}'), ('\u{1e3a}', '\u{1e3b}'),
+        ('\u{1e3b}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3d}'), ('\u{1e3d}',
+        '\u{1e3c}'), ('\u{1e3e}', '\u{1e3f}'), ('\u{1e3f}', '\u{1e3e}'),
+        ('\u{1e40}', '\u{1e41}'), ('\u{1e41}', '\u{1e40}'), ('\u{1e42}',
+        '\u{1e43}'), ('\u{1e43}', '\u{1e42}'), ('\u{1e44}', '\u{1e45}'),
+        ('\u{1e45}', '\u{1e44}'), ('\u{1e46}', '\u{1e47}'), ('\u{1e47}',
+        '\u{1e46}'), ('\u{1e48}', '\u{1e49}'), ('\u{1e49}', '\u{1e48}'),
+        ('\u{1e4a}', '\u{1e4b}'), ('\u{1e4b}', '\u{1e4a}'), ('\u{1e4c}',
+        '\u{1e4d}'), ('\u{1e4d}', '\u{1e4c}'), ('\u{1e4e}', '\u{1e4f}'),
+        ('\u{1e4f}', '\u{1e4e}'), ('\u{1e50}', '\u{1e51}'), ('\u{1e51}',
+        '\u{1e50}'), ('\u{1e52}', '\u{1e53}'), ('\u{1e53}', '\u{1e52}'),
+        ('\u{1e54}', '\u{1e55}'), ('\u{1e55}', '\u{1e54}'), ('\u{1e56}',
+        '\u{1e57}'), ('\u{1e57}', '\u{1e56}'), ('\u{1e58}', '\u{1e59}'),
+        ('\u{1e59}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5b}'), ('\u{1e5b}',
+        '\u{1e5a}'), ('\u{1e5c}', '\u{1e5d}'), ('\u{1e5d}', '\u{1e5c}'),
+        ('\u{1e5e}', '\u{1e5f}'), ('\u{1e5f}', '\u{1e5e}'), ('\u{1e60}',
+        '\u{1e61}'), ('\u{1e60}', '\u{1e9b}'), ('\u{1e61}', '\u{1e60}'),
+        ('\u{1e61}', '\u{1e9b}'), ('\u{1e62}', '\u{1e63}'), ('\u{1e63}',
+        '\u{1e62}'), ('\u{1e64}', '\u{1e65}'), ('\u{1e65}', '\u{1e64}'),
+        ('\u{1e66}', '\u{1e67}'), ('\u{1e67}', '\u{1e66}'), ('\u{1e68}',
+        '\u{1e69}'), ('\u{1e69}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6b}'),
+        ('\u{1e6b}', '\u{1e6a}'), ('\u{1e6c}', '\u{1e6d}'), ('\u{1e6d}',
+        '\u{1e6c}'), ('\u{1e6e}', '\u{1e6f}'), ('\u{1e6f}', '\u{1e6e}'),
+        ('\u{1e70}', '\u{1e71}'), ('\u{1e71}', '\u{1e70}'), ('\u{1e72}',
+        '\u{1e73}'), ('\u{1e73}', '\u{1e72}'), ('\u{1e74}', '\u{1e75}'),
+        ('\u{1e75}', '\u{1e74}'), ('\u{1e76}', '\u{1e77}'), ('\u{1e77}',
+        '\u{1e76}'), ('\u{1e78}', '\u{1e79}'), ('\u{1e79}', '\u{1e78}'),
+        ('\u{1e7a}', '\u{1e7b}'), ('\u{1e7b}', '\u{1e7a}'), ('\u{1e7c}',
+        '\u{1e7d}'), ('\u{1e7d}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7f}'),
+        ('\u{1e7f}', '\u{1e7e}'), ('\u{1e80}', '\u{1e81}'), ('\u{1e81}',
+        '\u{1e80}'), ('\u{1e82}', '\u{1e83}'), ('\u{1e83}', '\u{1e82}'),
+        ('\u{1e84}', '\u{1e85}'), ('\u{1e85}', '\u{1e84}'), ('\u{1e86}',
+        '\u{1e87}'), ('\u{1e87}', '\u{1e86}'), ('\u{1e88}', '\u{1e89}'),
+        ('\u{1e89}', '\u{1e88}'), ('\u{1e8a}', '\u{1e8b}'), ('\u{1e8b}',
+        '\u{1e8a}'), ('\u{1e8c}', '\u{1e8d}'), ('\u{1e8d}', '\u{1e8c}'),
+        ('\u{1e8e}', '\u{1e8f}'), ('\u{1e8f}', '\u{1e8e}'), ('\u{1e90}',
+        '\u{1e91}'), ('\u{1e91}', '\u{1e90}'), ('\u{1e92}', '\u{1e93}'),
+        ('\u{1e93}', '\u{1e92}'), ('\u{1e94}', '\u{1e95}'), ('\u{1e95}',
+        '\u{1e94}'), ('\u{1e9b}', '\u{1e60}'), ('\u{1e9b}', '\u{1e61}'),
+        ('\u{1e9e}', '\u{df}'), ('\u{1ea0}', '\u{1ea1}'), ('\u{1ea1}',
+        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea3}'), ('\u{1ea3}', '\u{1ea2}'),
+        ('\u{1ea4}', '\u{1ea5}'), ('\u{1ea5}', '\u{1ea4}'), ('\u{1ea6}',
+        '\u{1ea7}'), ('\u{1ea7}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea9}'),
+        ('\u{1ea9}', '\u{1ea8}'), ('\u{1eaa}', '\u{1eab}'), ('\u{1eab}',
+        '\u{1eaa}'), ('\u{1eac}', '\u{1ead}'), ('\u{1ead}', '\u{1eac}'),
+        ('\u{1eae}', '\u{1eaf}'), ('\u{1eaf}', '\u{1eae}'), ('\u{1eb0}',
+        '\u{1eb1}'), ('\u{1eb1}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb3}'),
+        ('\u{1eb3}', '\u{1eb2}'), ('\u{1eb4}', '\u{1eb5}'), ('\u{1eb5}',
+        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb7}'), ('\u{1eb7}', '\u{1eb6}'),
+        ('\u{1eb8}', '\u{1eb9}'), ('\u{1eb9}', '\u{1eb8}'), ('\u{1eba}',
+        '\u{1ebb}'), ('\u{1ebb}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebd}'),
+        ('\u{1ebd}', '\u{1ebc}'), ('\u{1ebe}', '\u{1ebf}'), ('\u{1ebf}',
+        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec1}'), ('\u{1ec1}', '\u{1ec0}'),
+        ('\u{1ec2}', '\u{1ec3}'), ('\u{1ec3}', '\u{1ec2}'), ('\u{1ec4}',
+        '\u{1ec5}'), ('\u{1ec5}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec7}'),
+        ('\u{1ec7}', '\u{1ec6}'), ('\u{1ec8}', '\u{1ec9}'), ('\u{1ec9}',
+        '\u{1ec8}'), ('\u{1eca}', '\u{1ecb}'), ('\u{1ecb}', '\u{1eca}'),
+        ('\u{1ecc}', '\u{1ecd}'), ('\u{1ecd}', '\u{1ecc}'), ('\u{1ece}',
+        '\u{1ecf}'), ('\u{1ecf}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed1}'),
+        ('\u{1ed1}', '\u{1ed0}'), ('\u{1ed2}', '\u{1ed3}'), ('\u{1ed3}',
+        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed5}'), ('\u{1ed5}', '\u{1ed4}'),
+        ('\u{1ed6}', '\u{1ed7}'), ('\u{1ed7}', '\u{1ed6}'), ('\u{1ed8}',
+        '\u{1ed9}'), ('\u{1ed9}', '\u{1ed8}'), ('\u{1eda}', '\u{1edb}'),
+        ('\u{1edb}', '\u{1eda}'), ('\u{1edc}', '\u{1edd}'), ('\u{1edd}',
+        '\u{1edc}'), ('\u{1ede}', '\u{1edf}'), ('\u{1edf}', '\u{1ede}'),
+        ('\u{1ee0}', '\u{1ee1}'), ('\u{1ee1}', '\u{1ee0}'), ('\u{1ee2}',
+        '\u{1ee3}'), ('\u{1ee3}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee5}'),
+        ('\u{1ee5}', '\u{1ee4}'), ('\u{1ee6}', '\u{1ee7}'), ('\u{1ee7}',
+        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee9}'), ('\u{1ee9}', '\u{1ee8}'),
+        ('\u{1eea}', '\u{1eeb}'), ('\u{1eeb}', '\u{1eea}'), ('\u{1eec}',
+        '\u{1eed}'), ('\u{1eed}', '\u{1eec}'), ('\u{1eee}', '\u{1eef}'),
+        ('\u{1eef}', '\u{1eee}'), ('\u{1ef0}', '\u{1ef1}'), ('\u{1ef1}',
+        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef3}'), ('\u{1ef3}', '\u{1ef2}'),
+        ('\u{1ef4}', '\u{1ef5}'), ('\u{1ef5}', '\u{1ef4}'), ('\u{1ef6}',
+        '\u{1ef7}'), ('\u{1ef7}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef9}'),
+        ('\u{1ef9}', '\u{1ef8}'), ('\u{1efa}', '\u{1efb}'), ('\u{1efb}',
+        '\u{1efa}'), ('\u{1efc}', '\u{1efd}'), ('\u{1efd}', '\u{1efc}'),
+        ('\u{1efe}', '\u{1eff}'), ('\u{1eff}', '\u{1efe}'), ('\u{1f00}',
+        '\u{1f08}'), ('\u{1f01}', '\u{1f09}'), ('\u{1f02}', '\u{1f0a}'),
+        ('\u{1f03}', '\u{1f0b}'), ('\u{1f04}', '\u{1f0c}'), ('\u{1f05}',
+        '\u{1f0d}'), ('\u{1f06}', '\u{1f0e}'), ('\u{1f07}', '\u{1f0f}'),
+        ('\u{1f08}', '\u{1f00}'), ('\u{1f09}', '\u{1f01}'), ('\u{1f0a}',
+        '\u{1f02}'), ('\u{1f0b}', '\u{1f03}'), ('\u{1f0c}', '\u{1f04}'),
+        ('\u{1f0d}', '\u{1f05}'), ('\u{1f0e}', '\u{1f06}'), ('\u{1f0f}',
+        '\u{1f07}'), ('\u{1f10}', '\u{1f18}'), ('\u{1f11}', '\u{1f19}'),
+        ('\u{1f12}', '\u{1f1a}'), ('\u{1f13}', '\u{1f1b}'), ('\u{1f14}',
+        '\u{1f1c}'), ('\u{1f15}', '\u{1f1d}'), ('\u{1f18}', '\u{1f10}'),
+        ('\u{1f19}', '\u{1f11}'), ('\u{1f1a}', '\u{1f12}'), ('\u{1f1b}',
+        '\u{1f13}'), ('\u{1f1c}', '\u{1f14}'), ('\u{1f1d}', '\u{1f15}'),
+        ('\u{1f20}', '\u{1f28}'), ('\u{1f21}', '\u{1f29}'), ('\u{1f22}',
+        '\u{1f2a}'), ('\u{1f23}', '\u{1f2b}'), ('\u{1f24}', '\u{1f2c}'),
+        ('\u{1f25}', '\u{1f2d}'), ('\u{1f26}', '\u{1f2e}'), ('\u{1f27}',
+        '\u{1f2f}'), ('\u{1f28}', '\u{1f20}'), ('\u{1f29}', '\u{1f21}'),
+        ('\u{1f2a}', '\u{1f22}'), ('\u{1f2b}', '\u{1f23}'), ('\u{1f2c}',
+        '\u{1f24}'), ('\u{1f2d}', '\u{1f25}'), ('\u{1f2e}', '\u{1f26}'),
+        ('\u{1f2f}', '\u{1f27}'), ('\u{1f30}', '\u{1f38}'), ('\u{1f31}',
+        '\u{1f39}'), ('\u{1f32}', '\u{1f3a}'), ('\u{1f33}', '\u{1f3b}'),
+        ('\u{1f34}', '\u{1f3c}'), ('\u{1f35}', '\u{1f3d}'), ('\u{1f36}',
+        '\u{1f3e}'), ('\u{1f37}', '\u{1f3f}'), ('\u{1f38}', '\u{1f30}'),
+        ('\u{1f39}', '\u{1f31}'), ('\u{1f3a}', '\u{1f32}'), ('\u{1f3b}',
+        '\u{1f33}'), ('\u{1f3c}', '\u{1f34}'), ('\u{1f3d}', '\u{1f35}'),
+        ('\u{1f3e}', '\u{1f36}'), ('\u{1f3f}', '\u{1f37}'), ('\u{1f40}',
+        '\u{1f48}'), ('\u{1f41}', '\u{1f49}'), ('\u{1f42}', '\u{1f4a}'),
+        ('\u{1f43}', '\u{1f4b}'), ('\u{1f44}', '\u{1f4c}'), ('\u{1f45}',
+        '\u{1f4d}'), ('\u{1f48}', '\u{1f40}'), ('\u{1f49}', '\u{1f41}'),
+        ('\u{1f4a}', '\u{1f42}'), ('\u{1f4b}', '\u{1f43}'), ('\u{1f4c}',
+        '\u{1f44}'), ('\u{1f4d}', '\u{1f45}'), ('\u{1f51}', '\u{1f59}'),
+        ('\u{1f53}', '\u{1f5b}'), ('\u{1f55}', '\u{1f5d}'), ('\u{1f57}',
+        '\u{1f5f}'), ('\u{1f59}', '\u{1f51}'), ('\u{1f5b}', '\u{1f53}'),
+        ('\u{1f5d}', '\u{1f55}'), ('\u{1f5f}', '\u{1f57}'), ('\u{1f60}',
+        '\u{1f68}'), ('\u{1f61}', '\u{1f69}'), ('\u{1f62}', '\u{1f6a}'),
+        ('\u{1f63}', '\u{1f6b}'), ('\u{1f64}', '\u{1f6c}'), ('\u{1f65}',
+        '\u{1f6d}'), ('\u{1f66}', '\u{1f6e}'), ('\u{1f67}', '\u{1f6f}'),
+        ('\u{1f68}', '\u{1f60}'), ('\u{1f69}', '\u{1f61}'), ('\u{1f6a}',
+        '\u{1f62}'), ('\u{1f6b}', '\u{1f63}'), ('\u{1f6c}', '\u{1f64}'),
+        ('\u{1f6d}', '\u{1f65}'), ('\u{1f6e}', '\u{1f66}'), ('\u{1f6f}',
+        '\u{1f67}'), ('\u{1f70}', '\u{1fba}'), ('\u{1f71}', '\u{1fbb}'),
+        ('\u{1f72}', '\u{1fc8}'), ('\u{1f73}', '\u{1fc9}'), ('\u{1f74}',
+        '\u{1fca}'), ('\u{1f75}', '\u{1fcb}'), ('\u{1f76}', '\u{1fda}'),
+        ('\u{1f77}', '\u{1fdb}'), ('\u{1f78}', '\u{1ff8}'), ('\u{1f79}',
+        '\u{1ff9}'), ('\u{1f7a}', '\u{1fea}'), ('\u{1f7b}', '\u{1feb}'),
+        ('\u{1f7c}', '\u{1ffa}'), ('\u{1f7d}', '\u{1ffb}'), ('\u{1f80}',
+        '\u{1f88}'), ('\u{1f81}', '\u{1f89}'), ('\u{1f82}', '\u{1f8a}'),
+        ('\u{1f83}', '\u{1f8b}'), ('\u{1f84}', '\u{1f8c}'), ('\u{1f85}',
+        '\u{1f8d}'), ('\u{1f86}', '\u{1f8e}'), ('\u{1f87}', '\u{1f8f}'),
+        ('\u{1f88}', '\u{1f80}'), ('\u{1f89}', '\u{1f81}'), ('\u{1f8a}',
+        '\u{1f82}'), ('\u{1f8b}', '\u{1f83}'), ('\u{1f8c}', '\u{1f84}'),
+        ('\u{1f8d}', '\u{1f85}'), ('\u{1f8e}', '\u{1f86}'), ('\u{1f8f}',
+        '\u{1f87}'), ('\u{1f90}', '\u{1f98}'), ('\u{1f91}', '\u{1f99}'),
+        ('\u{1f92}', '\u{1f9a}'), ('\u{1f93}', '\u{1f9b}'), ('\u{1f94}',
+        '\u{1f9c}'), ('\u{1f95}', '\u{1f9d}'), ('\u{1f96}', '\u{1f9e}'),
+        ('\u{1f97}', '\u{1f9f}'), ('\u{1f98}', '\u{1f90}'), ('\u{1f99}',
+        '\u{1f91}'), ('\u{1f9a}', '\u{1f92}'), ('\u{1f9b}', '\u{1f93}'),
+        ('\u{1f9c}', '\u{1f94}'), ('\u{1f9d}', '\u{1f95}'), ('\u{1f9e}',
+        '\u{1f96}'), ('\u{1f9f}', '\u{1f97}'), ('\u{1fa0}', '\u{1fa8}'),
+        ('\u{1fa1}', '\u{1fa9}'), ('\u{1fa2}', '\u{1faa}'), ('\u{1fa3}',
+        '\u{1fab}'), ('\u{1fa4}', '\u{1fac}'), ('\u{1fa5}', '\u{1fad}'),
+        ('\u{1fa6}', '\u{1fae}'), ('\u{1fa7}', '\u{1faf}'), ('\u{1fa8}',
+        '\u{1fa0}'), ('\u{1fa9}', '\u{1fa1}'), ('\u{1faa}', '\u{1fa2}'),
+        ('\u{1fab}', '\u{1fa3}'), ('\u{1fac}', '\u{1fa4}'), ('\u{1fad}',
+        '\u{1fa5}'), ('\u{1fae}', '\u{1fa6}'), ('\u{1faf}', '\u{1fa7}'),
+        ('\u{1fb0}', '\u{1fb8}'), ('\u{1fb1}', '\u{1fb9}'), ('\u{1fb3}',
+        '\u{1fbc}'), ('\u{1fb8}', '\u{1fb0}'), ('\u{1fb9}', '\u{1fb1}'),
+        ('\u{1fba}', '\u{1f70}'), ('\u{1fbb}', '\u{1f71}'), ('\u{1fbc}',
+        '\u{1fb3}'), ('\u{1fbe}', '\u{345}'), ('\u{1fbe}', '\u{399}'),
+        ('\u{1fbe}', '\u{3b9}'), ('\u{1fc3}', '\u{1fcc}'), ('\u{1fc8}',
+        '\u{1f72}'), ('\u{1fc9}', '\u{1f73}'), ('\u{1fca}', '\u{1f74}'),
+        ('\u{1fcb}', '\u{1f75}'), ('\u{1fcc}', '\u{1fc3}'), ('\u{1fd0}',
+        '\u{1fd8}'), ('\u{1fd1}', '\u{1fd9}'), ('\u{1fd8}', '\u{1fd0}'),
+        ('\u{1fd9}', '\u{1fd1}'), ('\u{1fda}', '\u{1f76}'), ('\u{1fdb}',
+        '\u{1f77}'), ('\u{1fe0}', '\u{1fe8}'), ('\u{1fe1}', '\u{1fe9}'),
+        ('\u{1fe5}', '\u{1fec}'), ('\u{1fe8}', '\u{1fe0}'), ('\u{1fe9}',
+        '\u{1fe1}'), ('\u{1fea}', '\u{1f7a}'), ('\u{1feb}', '\u{1f7b}'),
+        ('\u{1fec}', '\u{1fe5}'), ('\u{1ff3}', '\u{1ffc}'), ('\u{1ff8}',
+        '\u{1f78}'), ('\u{1ff9}', '\u{1f79}'), ('\u{1ffa}', '\u{1f7c}'),
+        ('\u{1ffb}', '\u{1f7d}'), ('\u{1ffc}', '\u{1ff3}'), ('\u{2126}',
+        '\u{3a9}'), ('\u{2126}', '\u{3c9}'), ('\u{212a}', '\u{4b}'),
+        ('\u{212a}', '\u{6b}'), ('\u{212b}', '\u{c5}'), ('\u{212b}', '\u{e5}'),
+        ('\u{2132}', '\u{214e}'), ('\u{214e}', '\u{2132}'), ('\u{2160}',
+        '\u{2170}'), ('\u{2161}', '\u{2171}'), ('\u{2162}', '\u{2172}'),
+        ('\u{2163}', '\u{2173}'), ('\u{2164}', '\u{2174}'), ('\u{2165}',
+        '\u{2175}'), ('\u{2166}', '\u{2176}'), ('\u{2167}', '\u{2177}'),
+        ('\u{2168}', '\u{2178}'), ('\u{2169}', '\u{2179}'), ('\u{216a}',
+        '\u{217a}'), ('\u{216b}', '\u{217b}'), ('\u{216c}', '\u{217c}'),
+        ('\u{216d}', '\u{217d}'), ('\u{216e}', '\u{217e}'), ('\u{216f}',
+        '\u{217f}'), ('\u{2170}', '\u{2160}'), ('\u{2171}', '\u{2161}'),
+        ('\u{2172}', '\u{2162}'), ('\u{2173}', '\u{2163}'), ('\u{2174}',
+        '\u{2164}'), ('\u{2175}', '\u{2165}'), ('\u{2176}', '\u{2166}'),
+        ('\u{2177}', '\u{2167}'), ('\u{2178}', '\u{2168}'), ('\u{2179}',
+        '\u{2169}'), ('\u{217a}', '\u{216a}'), ('\u{217b}', '\u{216b}'),
+        ('\u{217c}', '\u{216c}'), ('\u{217d}', '\u{216d}'), ('\u{217e}',
+        '\u{216e}'), ('\u{217f}', '\u{216f}'), ('\u{2183}', '\u{2184}'),
+        ('\u{2184}', '\u{2183}'), ('\u{24b6}', '\u{24d0}'), ('\u{24b7}',
+        '\u{24d1}'), ('\u{24b8}', '\u{24d2}'), ('\u{24b9}', '\u{24d3}'),
+        ('\u{24ba}', '\u{24d4}'), ('\u{24bb}', '\u{24d5}'), ('\u{24bc}',
+        '\u{24d6}'), ('\u{24bd}', '\u{24d7}'), ('\u{24be}', '\u{24d8}'),
+        ('\u{24bf}', '\u{24d9}'), ('\u{24c0}', '\u{24da}'), ('\u{24c1}',
+        '\u{24db}'), ('\u{24c2}', '\u{24dc}'), ('\u{24c3}', '\u{24dd}'),
+        ('\u{24c4}', '\u{24de}'), ('\u{24c5}', '\u{24df}'), ('\u{24c6}',
+        '\u{24e0}'), ('\u{24c7}', '\u{24e1}'), ('\u{24c8}', '\u{24e2}'),
+        ('\u{24c9}', '\u{24e3}'), ('\u{24ca}', '\u{24e4}'), ('\u{24cb}',
+        '\u{24e5}'), ('\u{24cc}', '\u{24e6}'), ('\u{24cd}', '\u{24e7}'),
+        ('\u{24ce}', '\u{24e8}'), ('\u{24cf}', '\u{24e9}'), ('\u{24d0}',
+        '\u{24b6}'), ('\u{24d1}', '\u{24b7}'), ('\u{24d2}', '\u{24b8}'),
+        ('\u{24d3}', '\u{24b9}'), ('\u{24d4}', '\u{24ba}'), ('\u{24d5}',
+        '\u{24bb}'), ('\u{24d6}', '\u{24bc}'), ('\u{24d7}', '\u{24bd}'),
+        ('\u{24d8}', '\u{24be}'), ('\u{24d9}', '\u{24bf}'), ('\u{24da}',
+        '\u{24c0}'), ('\u{24db}', '\u{24c1}'), ('\u{24dc}', '\u{24c2}'),
+        ('\u{24dd}', '\u{24c3}'), ('\u{24de}', '\u{24c4}'), ('\u{24df}',
+        '\u{24c5}'), ('\u{24e0}', '\u{24c6}'), ('\u{24e1}', '\u{24c7}'),
+        ('\u{24e2}', '\u{24c8}'), ('\u{24e3}', '\u{24c9}'), ('\u{24e4}',
+        '\u{24ca}'), ('\u{24e5}', '\u{24cb}'), ('\u{24e6}', '\u{24cc}'),
+        ('\u{24e7}', '\u{24cd}'), ('\u{24e8}', '\u{24ce}'), ('\u{24e9}',
+        '\u{24cf}'), ('\u{2c00}', '\u{2c30}'), ('\u{2c01}', '\u{2c31}'),
+        ('\u{2c02}', '\u{2c32}'), ('\u{2c03}', '\u{2c33}'), ('\u{2c04}',
+        '\u{2c34}'), ('\u{2c05}', '\u{2c35}'), ('\u{2c06}', '\u{2c36}'),
+        ('\u{2c07}', '\u{2c37}'), ('\u{2c08}', '\u{2c38}'), ('\u{2c09}',
+        '\u{2c39}'), ('\u{2c0a}', '\u{2c3a}'), ('\u{2c0b}', '\u{2c3b}'),
+        ('\u{2c0c}', '\u{2c3c}'), ('\u{2c0d}', '\u{2c3d}'), ('\u{2c0e}',
+        '\u{2c3e}'), ('\u{2c0f}', '\u{2c3f}'), ('\u{2c10}', '\u{2c40}'),
+        ('\u{2c11}', '\u{2c41}'), ('\u{2c12}', '\u{2c42}'), ('\u{2c13}',
+        '\u{2c43}'), ('\u{2c14}', '\u{2c44}'), ('\u{2c15}', '\u{2c45}'),
+        ('\u{2c16}', '\u{2c46}'), ('\u{2c17}', '\u{2c47}'), ('\u{2c18}',
+        '\u{2c48}'), ('\u{2c19}', '\u{2c49}'), ('\u{2c1a}', '\u{2c4a}'),
+        ('\u{2c1b}', '\u{2c4b}'), ('\u{2c1c}', '\u{2c4c}'), ('\u{2c1d}',
+        '\u{2c4d}'), ('\u{2c1e}', '\u{2c4e}'), ('\u{2c1f}', '\u{2c4f}'),
+        ('\u{2c20}', '\u{2c50}'), ('\u{2c21}', '\u{2c51}'), ('\u{2c22}',
+        '\u{2c52}'), ('\u{2c23}', '\u{2c53}'), ('\u{2c24}', '\u{2c54}'),
+        ('\u{2c25}', '\u{2c55}'), ('\u{2c26}', '\u{2c56}'), ('\u{2c27}',
+        '\u{2c57}'), ('\u{2c28}', '\u{2c58}'), ('\u{2c29}', '\u{2c59}'),
+        ('\u{2c2a}', '\u{2c5a}'), ('\u{2c2b}', '\u{2c5b}'), ('\u{2c2c}',
+        '\u{2c5c}'), ('\u{2c2d}', '\u{2c5d}'), ('\u{2c2e}', '\u{2c5e}'),
+        ('\u{2c30}', '\u{2c00}'), ('\u{2c31}', '\u{2c01}'), ('\u{2c32}',
+        '\u{2c02}'), ('\u{2c33}', '\u{2c03}'), ('\u{2c34}', '\u{2c04}'),
+        ('\u{2c35}', '\u{2c05}'), ('\u{2c36}', '\u{2c06}'), ('\u{2c37}',
+        '\u{2c07}'), ('\u{2c38}', '\u{2c08}'), ('\u{2c39}', '\u{2c09}'),
+        ('\u{2c3a}', '\u{2c0a}'), ('\u{2c3b}', '\u{2c0b}'), ('\u{2c3c}',
+        '\u{2c0c}'), ('\u{2c3d}', '\u{2c0d}'), ('\u{2c3e}', '\u{2c0e}'),
+        ('\u{2c3f}', '\u{2c0f}'), ('\u{2c40}', '\u{2c10}'), ('\u{2c41}',
+        '\u{2c11}'), ('\u{2c42}', '\u{2c12}'), ('\u{2c43}', '\u{2c13}'),
+        ('\u{2c44}', '\u{2c14}'), ('\u{2c45}', '\u{2c15}'), ('\u{2c46}',
+        '\u{2c16}'), ('\u{2c47}', '\u{2c17}'), ('\u{2c48}', '\u{2c18}'),
+        ('\u{2c49}', '\u{2c19}'), ('\u{2c4a}', '\u{2c1a}'), ('\u{2c4b}',
+        '\u{2c1b}'), ('\u{2c4c}', '\u{2c1c}'), ('\u{2c4d}', '\u{2c1d}'),
+        ('\u{2c4e}', '\u{2c1e}'), ('\u{2c4f}', '\u{2c1f}'), ('\u{2c50}',
+        '\u{2c20}'), ('\u{2c51}', '\u{2c21}'), ('\u{2c52}', '\u{2c22}'),
+        ('\u{2c53}', '\u{2c23}'), ('\u{2c54}', '\u{2c24}'), ('\u{2c55}',
+        '\u{2c25}'), ('\u{2c56}', '\u{2c26}'), ('\u{2c57}', '\u{2c27}'),
+        ('\u{2c58}', '\u{2c28}'), ('\u{2c59}', '\u{2c29}'), ('\u{2c5a}',
+        '\u{2c2a}'), ('\u{2c5b}', '\u{2c2b}'), ('\u{2c5c}', '\u{2c2c}'),
+        ('\u{2c5d}', '\u{2c2d}'), ('\u{2c5e}', '\u{2c2e}'), ('\u{2c60}',
+        '\u{2c61}'), ('\u{2c61}', '\u{2c60}'), ('\u{2c62}', '\u{26b}'),
+        ('\u{2c63}', '\u{1d7d}'), ('\u{2c64}', '\u{27d}'), ('\u{2c65}',
+        '\u{23a}'), ('\u{2c66}', '\u{23e}'), ('\u{2c67}', '\u{2c68}'),
+        ('\u{2c68}', '\u{2c67}'), ('\u{2c69}', '\u{2c6a}'), ('\u{2c6a}',
+        '\u{2c69}'), ('\u{2c6b}', '\u{2c6c}'), ('\u{2c6c}', '\u{2c6b}'),
+        ('\u{2c6d}', '\u{251}'), ('\u{2c6e}', '\u{271}'), ('\u{2c6f}',
+        '\u{250}'), ('\u{2c70}', '\u{252}'), ('\u{2c72}', '\u{2c73}'),
+        ('\u{2c73}', '\u{2c72}'), ('\u{2c75}', '\u{2c76}'), ('\u{2c76}',
+        '\u{2c75}'), ('\u{2c7e}', '\u{23f}'), ('\u{2c7f}', '\u{240}'),
+        ('\u{2c80}', '\u{2c81}'), ('\u{2c81}', '\u{2c80}'), ('\u{2c82}',
+        '\u{2c83}'), ('\u{2c83}', '\u{2c82}'), ('\u{2c84}', '\u{2c85}'),
+        ('\u{2c85}', '\u{2c84}'), ('\u{2c86}', '\u{2c87}'), ('\u{2c87}',
+        '\u{2c86}'), ('\u{2c88}', '\u{2c89}'), ('\u{2c89}', '\u{2c88}'),
+        ('\u{2c8a}', '\u{2c8b}'), ('\u{2c8b}', '\u{2c8a}'), ('\u{2c8c}',
+        '\u{2c8d}'), ('\u{2c8d}', '\u{2c8c}'), ('\u{2c8e}', '\u{2c8f}'),
+        ('\u{2c8f}', '\u{2c8e}'), ('\u{2c90}', '\u{2c91}'), ('\u{2c91}',
+        '\u{2c90}'), ('\u{2c92}', '\u{2c93}'), ('\u{2c93}', '\u{2c92}'),
+        ('\u{2c94}', '\u{2c95}'), ('\u{2c95}', '\u{2c94}'), ('\u{2c96}',
+        '\u{2c97}'), ('\u{2c97}', '\u{2c96}'), ('\u{2c98}', '\u{2c99}'),
+        ('\u{2c99}', '\u{2c98}'), ('\u{2c9a}', '\u{2c9b}'), ('\u{2c9b}',
+        '\u{2c9a}'), ('\u{2c9c}', '\u{2c9d}'), ('\u{2c9d}', '\u{2c9c}'),
+        ('\u{2c9e}', '\u{2c9f}'), ('\u{2c9f}', '\u{2c9e}'), ('\u{2ca0}',
+        '\u{2ca1}'), ('\u{2ca1}', '\u{2ca0}'), ('\u{2ca2}', '\u{2ca3}'),
+        ('\u{2ca3}', '\u{2ca2}'), ('\u{2ca4}', '\u{2ca5}'), ('\u{2ca5}',
+        '\u{2ca4}'), ('\u{2ca6}', '\u{2ca7}'), ('\u{2ca7}', '\u{2ca6}'),
+        ('\u{2ca8}', '\u{2ca9}'), ('\u{2ca9}', '\u{2ca8}'), ('\u{2caa}',
+        '\u{2cab}'), ('\u{2cab}', '\u{2caa}'), ('\u{2cac}', '\u{2cad}'),
+        ('\u{2cad}', '\u{2cac}'), ('\u{2cae}', '\u{2caf}'), ('\u{2caf}',
+        '\u{2cae}'), ('\u{2cb0}', '\u{2cb1}'), ('\u{2cb1}', '\u{2cb0}'),
+        ('\u{2cb2}', '\u{2cb3}'), ('\u{2cb3}', '\u{2cb2}'), ('\u{2cb4}',
+        '\u{2cb5}'), ('\u{2cb5}', '\u{2cb4}'), ('\u{2cb6}', '\u{2cb7}'),
+        ('\u{2cb7}', '\u{2cb6}'), ('\u{2cb8}', '\u{2cb9}'), ('\u{2cb9}',
+        '\u{2cb8}'), ('\u{2cba}', '\u{2cbb}'), ('\u{2cbb}', '\u{2cba}'),
+        ('\u{2cbc}', '\u{2cbd}'), ('\u{2cbd}', '\u{2cbc}'), ('\u{2cbe}',
+        '\u{2cbf}'), ('\u{2cbf}', '\u{2cbe}'), ('\u{2cc0}', '\u{2cc1}'),
+        ('\u{2cc1}', '\u{2cc0}'), ('\u{2cc2}', '\u{2cc3}'), ('\u{2cc3}',
+        '\u{2cc2}'), ('\u{2cc4}', '\u{2cc5}'), ('\u{2cc5}', '\u{2cc4}'),
+        ('\u{2cc6}', '\u{2cc7}'), ('\u{2cc7}', '\u{2cc6}'), ('\u{2cc8}',
+        '\u{2cc9}'), ('\u{2cc9}', '\u{2cc8}'), ('\u{2cca}', '\u{2ccb}'),
+        ('\u{2ccb}', '\u{2cca}'), ('\u{2ccc}', '\u{2ccd}'), ('\u{2ccd}',
+        '\u{2ccc}'), ('\u{2cce}', '\u{2ccf}'), ('\u{2ccf}', '\u{2cce}'),
+        ('\u{2cd0}', '\u{2cd1}'), ('\u{2cd1}', '\u{2cd0}'), ('\u{2cd2}',
+        '\u{2cd3}'), ('\u{2cd3}', '\u{2cd2}'), ('\u{2cd4}', '\u{2cd5}'),
+        ('\u{2cd5}', '\u{2cd4}'), ('\u{2cd6}', '\u{2cd7}'), ('\u{2cd7}',
+        '\u{2cd6}'), ('\u{2cd8}', '\u{2cd9}'), ('\u{2cd9}', '\u{2cd8}'),
+        ('\u{2cda}', '\u{2cdb}'), ('\u{2cdb}', '\u{2cda}'), ('\u{2cdc}',
+        '\u{2cdd}'), ('\u{2cdd}', '\u{2cdc}'), ('\u{2cde}', '\u{2cdf}'),
+        ('\u{2cdf}', '\u{2cde}'), ('\u{2ce0}', '\u{2ce1}'), ('\u{2ce1}',
+        '\u{2ce0}'), ('\u{2ce2}', '\u{2ce3}'), ('\u{2ce3}', '\u{2ce2}'),
+        ('\u{2ceb}', '\u{2cec}'), ('\u{2cec}', '\u{2ceb}'), ('\u{2ced}',
+        '\u{2cee}'), ('\u{2cee}', '\u{2ced}'), ('\u{2cf2}', '\u{2cf3}'),
+        ('\u{2cf3}', '\u{2cf2}'), ('\u{2d00}', '\u{10a0}'), ('\u{2d01}',
+        '\u{10a1}'), ('\u{2d02}', '\u{10a2}'), ('\u{2d03}', '\u{10a3}'),
+        ('\u{2d04}', '\u{10a4}'), ('\u{2d05}', '\u{10a5}'), ('\u{2d06}',
+        '\u{10a6}'), ('\u{2d07}', '\u{10a7}'), ('\u{2d08}', '\u{10a8}'),
+        ('\u{2d09}', '\u{10a9}'), ('\u{2d0a}', '\u{10aa}'), ('\u{2d0b}',
+        '\u{10ab}'), ('\u{2d0c}', '\u{10ac}'), ('\u{2d0d}', '\u{10ad}'),
+        ('\u{2d0e}', '\u{10ae}'), ('\u{2d0f}', '\u{10af}'), ('\u{2d10}',
+        '\u{10b0}'), ('\u{2d11}', '\u{10b1}'), ('\u{2d12}', '\u{10b2}'),
+        ('\u{2d13}', '\u{10b3}'), ('\u{2d14}', '\u{10b4}'), ('\u{2d15}',
+        '\u{10b5}'), ('\u{2d16}', '\u{10b6}'), ('\u{2d17}', '\u{10b7}'),
+        ('\u{2d18}', '\u{10b8}'), ('\u{2d19}', '\u{10b9}'), ('\u{2d1a}',
+        '\u{10ba}'), ('\u{2d1b}', '\u{10bb}'), ('\u{2d1c}', '\u{10bc}'),
+        ('\u{2d1d}', '\u{10bd}'), ('\u{2d1e}', '\u{10be}'), ('\u{2d1f}',
+        '\u{10bf}'), ('\u{2d20}', '\u{10c0}'), ('\u{2d21}', '\u{10c1}'),
+        ('\u{2d22}', '\u{10c2}'), ('\u{2d23}', '\u{10c3}'), ('\u{2d24}',
+        '\u{10c4}'), ('\u{2d25}', '\u{10c5}'), ('\u{2d27}', '\u{10c7}'),
+        ('\u{2d2d}', '\u{10cd}'), ('\u{a640}', '\u{a641}'), ('\u{a641}',
+        '\u{a640}'), ('\u{a642}', '\u{a643}'), ('\u{a643}', '\u{a642}'),
+        ('\u{a644}', '\u{a645}'), ('\u{a645}', '\u{a644}'), ('\u{a646}',
+        '\u{a647}'), ('\u{a647}', '\u{a646}'), ('\u{a648}', '\u{a649}'),
+        ('\u{a649}', '\u{a648}'), ('\u{a64a}', '\u{a64b}'), ('\u{a64b}',
+        '\u{a64a}'), ('\u{a64c}', '\u{a64d}'), ('\u{a64d}', '\u{a64c}'),
+        ('\u{a64e}', '\u{a64f}'), ('\u{a64f}', '\u{a64e}'), ('\u{a650}',
+        '\u{a651}'), ('\u{a651}', '\u{a650}'), ('\u{a652}', '\u{a653}'),
+        ('\u{a653}', '\u{a652}'), ('\u{a654}', '\u{a655}'), ('\u{a655}',
+        '\u{a654}'), ('\u{a656}', '\u{a657}'), ('\u{a657}', '\u{a656}'),
+        ('\u{a658}', '\u{a659}'), ('\u{a659}', '\u{a658}'), ('\u{a65a}',
+        '\u{a65b}'), ('\u{a65b}', '\u{a65a}'), ('\u{a65c}', '\u{a65d}'),
+        ('\u{a65d}', '\u{a65c}'), ('\u{a65e}', '\u{a65f}'), ('\u{a65f}',
+        '\u{a65e}'), ('\u{a660}', '\u{a661}'), ('\u{a661}', '\u{a660}'),
+        ('\u{a662}', '\u{a663}'), ('\u{a663}', '\u{a662}'), ('\u{a664}',
+        '\u{a665}'), ('\u{a665}', '\u{a664}'), ('\u{a666}', '\u{a667}'),
+        ('\u{a667}', '\u{a666}'), ('\u{a668}', '\u{a669}'), ('\u{a669}',
+        '\u{a668}'), ('\u{a66a}', '\u{a66b}'), ('\u{a66b}', '\u{a66a}'),
+        ('\u{a66c}', '\u{a66d}'), ('\u{a66d}', '\u{a66c}'), ('\u{a680}',
+        '\u{a681}'), ('\u{a681}', '\u{a680}'), ('\u{a682}', '\u{a683}'),
+        ('\u{a683}', '\u{a682}'), ('\u{a684}', '\u{a685}'), ('\u{a685}',
+        '\u{a684}'), ('\u{a686}', '\u{a687}'), ('\u{a687}', '\u{a686}'),
+        ('\u{a688}', '\u{a689}'), ('\u{a689}', '\u{a688}'), ('\u{a68a}',
+        '\u{a68b}'), ('\u{a68b}', '\u{a68a}'), ('\u{a68c}', '\u{a68d}'),
+        ('\u{a68d}', '\u{a68c}'), ('\u{a68e}', '\u{a68f}'), ('\u{a68f}',
+        '\u{a68e}'), ('\u{a690}', '\u{a691}'), ('\u{a691}', '\u{a690}'),
+        ('\u{a692}', '\u{a693}'), ('\u{a693}', '\u{a692}'), ('\u{a694}',
+        '\u{a695}'), ('\u{a695}', '\u{a694}'), ('\u{a696}', '\u{a697}'),
+        ('\u{a697}', '\u{a696}'), ('\u{a698}', '\u{a699}'), ('\u{a699}',
+        '\u{a698}'), ('\u{a69a}', '\u{a69b}'), ('\u{a69b}', '\u{a69a}'),
+        ('\u{a722}', '\u{a723}'), ('\u{a723}', '\u{a722}'), ('\u{a724}',
+        '\u{a725}'), ('\u{a725}', '\u{a724}'), ('\u{a726}', '\u{a727}'),
+        ('\u{a727}', '\u{a726}'), ('\u{a728}', '\u{a729}'), ('\u{a729}',
+        '\u{a728}'), ('\u{a72a}', '\u{a72b}'), ('\u{a72b}', '\u{a72a}'),
+        ('\u{a72c}', '\u{a72d}'), ('\u{a72d}', '\u{a72c}'), ('\u{a72e}',
+        '\u{a72f}'), ('\u{a72f}', '\u{a72e}'), ('\u{a732}', '\u{a733}'),
+        ('\u{a733}', '\u{a732}'), ('\u{a734}', '\u{a735}'), ('\u{a735}',
+        '\u{a734}'), ('\u{a736}', '\u{a737}'), ('\u{a737}', '\u{a736}'),
+        ('\u{a738}', '\u{a739}'), ('\u{a739}', '\u{a738}'), ('\u{a73a}',
+        '\u{a73b}'), ('\u{a73b}', '\u{a73a}'), ('\u{a73c}', '\u{a73d}'),
+        ('\u{a73d}', '\u{a73c}'), ('\u{a73e}', '\u{a73f}'), ('\u{a73f}',
+        '\u{a73e}'), ('\u{a740}', '\u{a741}'), ('\u{a741}', '\u{a740}'),
+        ('\u{a742}', '\u{a743}'), ('\u{a743}', '\u{a742}'), ('\u{a744}',
+        '\u{a745}'), ('\u{a745}', '\u{a744}'), ('\u{a746}', '\u{a747}'),
+        ('\u{a747}', '\u{a746}'), ('\u{a748}', '\u{a749}'), ('\u{a749}',
+        '\u{a748}'), ('\u{a74a}', '\u{a74b}'), ('\u{a74b}', '\u{a74a}'),
+        ('\u{a74c}', '\u{a74d}'), ('\u{a74d}', '\u{a74c}'), ('\u{a74e}',
+        '\u{a74f}'), ('\u{a74f}', '\u{a74e}'), ('\u{a750}', '\u{a751}'),
+        ('\u{a751}', '\u{a750}'), ('\u{a752}', '\u{a753}'), ('\u{a753}',
+        '\u{a752}'), ('\u{a754}', '\u{a755}'), ('\u{a755}', '\u{a754}'),
+        ('\u{a756}', '\u{a757}'), ('\u{a757}', '\u{a756}'), ('\u{a758}',
+        '\u{a759}'), ('\u{a759}', '\u{a758}'), ('\u{a75a}', '\u{a75b}'),
+        ('\u{a75b}', '\u{a75a}'), ('\u{a75c}', '\u{a75d}'), ('\u{a75d}',
+        '\u{a75c}'), ('\u{a75e}', '\u{a75f}'), ('\u{a75f}', '\u{a75e}'),
+        ('\u{a760}', '\u{a761}'), ('\u{a761}', '\u{a760}'), ('\u{a762}',
+        '\u{a763}'), ('\u{a763}', '\u{a762}'), ('\u{a764}', '\u{a765}'),
+        ('\u{a765}', '\u{a764}'), ('\u{a766}', '\u{a767}'), ('\u{a767}',
+        '\u{a766}'), ('\u{a768}', '\u{a769}'), ('\u{a769}', '\u{a768}'),
+        ('\u{a76a}', '\u{a76b}'), ('\u{a76b}', '\u{a76a}'), ('\u{a76c}',
+        '\u{a76d}'), ('\u{a76d}', '\u{a76c}'), ('\u{a76e}', '\u{a76f}'),
+        ('\u{a76f}', '\u{a76e}'), ('\u{a779}', '\u{a77a}'), ('\u{a77a}',
+        '\u{a779}'), ('\u{a77b}', '\u{a77c}'), ('\u{a77c}', '\u{a77b}'),
+        ('\u{a77d}', '\u{1d79}'), ('\u{a77e}', '\u{a77f}'), ('\u{a77f}',
+        '\u{a77e}'), ('\u{a780}', '\u{a781}'), ('\u{a781}', '\u{a780}'),
+        ('\u{a782}', '\u{a783}'), ('\u{a783}', '\u{a782}'), ('\u{a784}',
+        '\u{a785}'), ('\u{a785}', '\u{a784}'), ('\u{a786}', '\u{a787}'),
+        ('\u{a787}', '\u{a786}'), ('\u{a78b}', '\u{a78c}'), ('\u{a78c}',
+        '\u{a78b}'), ('\u{a78d}', '\u{265}'), ('\u{a790}', '\u{a791}'),
+        ('\u{a791}', '\u{a790}'), ('\u{a792}', '\u{a793}'), ('\u{a793}',
+        '\u{a792}'), ('\u{a796}', '\u{a797}'), ('\u{a797}', '\u{a796}'),
+        ('\u{a798}', '\u{a799}'), ('\u{a799}', '\u{a798}'), ('\u{a79a}',
+        '\u{a79b}'), ('\u{a79b}', '\u{a79a}'), ('\u{a79c}', '\u{a79d}'),
+        ('\u{a79d}', '\u{a79c}'), ('\u{a79e}', '\u{a79f}'), ('\u{a79f}',
+        '\u{a79e}'), ('\u{a7a0}', '\u{a7a1}'), ('\u{a7a1}', '\u{a7a0}'),
+        ('\u{a7a2}', '\u{a7a3}'), ('\u{a7a3}', '\u{a7a2}'), ('\u{a7a4}',
+        '\u{a7a5}'), ('\u{a7a5}', '\u{a7a4}'), ('\u{a7a6}', '\u{a7a7}'),
+        ('\u{a7a7}', '\u{a7a6}'), ('\u{a7a8}', '\u{a7a9}'), ('\u{a7a9}',
+        '\u{a7a8}'), ('\u{a7aa}', '\u{266}'), ('\u{a7ab}', '\u{25c}'),
+        ('\u{a7ac}', '\u{261}'), ('\u{a7ad}', '\u{26c}'), ('\u{a7b0}',
+        '\u{29e}'), ('\u{a7b1}', '\u{287}'), ('\u{a7b2}', '\u{29d}'),
+        ('\u{a7b3}', '\u{ab53}'), ('\u{a7b4}', '\u{a7b5}'), ('\u{a7b5}',
+        '\u{a7b4}'), ('\u{a7b6}', '\u{a7b7}'), ('\u{a7b7}', '\u{a7b6}'),
+        ('\u{ab53}', '\u{a7b3}'), ('\u{ab70}', '\u{13a0}'), ('\u{ab71}',
+        '\u{13a1}'), ('\u{ab72}', '\u{13a2}'), ('\u{ab73}', '\u{13a3}'),
+        ('\u{ab74}', '\u{13a4}'), ('\u{ab75}', '\u{13a5}'), ('\u{ab76}',
+        '\u{13a6}'), ('\u{ab77}', '\u{13a7}'), ('\u{ab78}', '\u{13a8}'),
+        ('\u{ab79}', '\u{13a9}'), ('\u{ab7a}', '\u{13aa}'), ('\u{ab7b}',
+        '\u{13ab}'), ('\u{ab7c}', '\u{13ac}'), ('\u{ab7d}', '\u{13ad}'),
+        ('\u{ab7e}', '\u{13ae}'), ('\u{ab7f}', '\u{13af}'), ('\u{ab80}',
+        '\u{13b0}'), ('\u{ab81}', '\u{13b1}'), ('\u{ab82}', '\u{13b2}'),
+        ('\u{ab83}', '\u{13b3}'), ('\u{ab84}', '\u{13b4}'), ('\u{ab85}',
+        '\u{13b5}'), ('\u{ab86}', '\u{13b6}'), ('\u{ab87}', '\u{13b7}'),
+        ('\u{ab88}', '\u{13b8}'), ('\u{ab89}', '\u{13b9}'), ('\u{ab8a}',
+        '\u{13ba}'), ('\u{ab8b}', '\u{13bb}'), ('\u{ab8c}', '\u{13bc}'),
+        ('\u{ab8d}', '\u{13bd}'), ('\u{ab8e}', '\u{13be}'), ('\u{ab8f}',
+        '\u{13bf}'), ('\u{ab90}', '\u{13c0}'), ('\u{ab91}', '\u{13c1}'),
+        ('\u{ab92}', '\u{13c2}'), ('\u{ab93}', '\u{13c3}'), ('\u{ab94}',
+        '\u{13c4}'), ('\u{ab95}', '\u{13c5}'), ('\u{ab96}', '\u{13c6}'),
+        ('\u{ab97}', '\u{13c7}'), ('\u{ab98}', '\u{13c8}'), ('\u{ab99}',
+        '\u{13c9}'), ('\u{ab9a}', '\u{13ca}'), ('\u{ab9b}', '\u{13cb}'),
+        ('\u{ab9c}', '\u{13cc}'), ('\u{ab9d}', '\u{13cd}'), ('\u{ab9e}',
+        '\u{13ce}'), ('\u{ab9f}', '\u{13cf}'), ('\u{aba0}', '\u{13d0}'),
+        ('\u{aba1}', '\u{13d1}'), ('\u{aba2}', '\u{13d2}'), ('\u{aba3}',
+        '\u{13d3}'), ('\u{aba4}', '\u{13d4}'), ('\u{aba5}', '\u{13d5}'),
+        ('\u{aba6}', '\u{13d6}'), ('\u{aba7}', '\u{13d7}'), ('\u{aba8}',
+        '\u{13d8}'), ('\u{aba9}', '\u{13d9}'), ('\u{abaa}', '\u{13da}'),
+        ('\u{abab}', '\u{13db}'), ('\u{abac}', '\u{13dc}'), ('\u{abad}',
+        '\u{13dd}'), ('\u{abae}', '\u{13de}'), ('\u{abaf}', '\u{13df}'),
+        ('\u{abb0}', '\u{13e0}'), ('\u{abb1}', '\u{13e1}'), ('\u{abb2}',
+        '\u{13e2}'), ('\u{abb3}', '\u{13e3}'), ('\u{abb4}', '\u{13e4}'),
+        ('\u{abb5}', '\u{13e5}'), ('\u{abb6}', '\u{13e6}'), ('\u{abb7}',
+        '\u{13e7}'), ('\u{abb8}', '\u{13e8}'), ('\u{abb9}', '\u{13e9}'),
+        ('\u{abba}', '\u{13ea}'), ('\u{abbb}', '\u{13eb}'), ('\u{abbc}',
+        '\u{13ec}'), ('\u{abbd}', '\u{13ed}'), ('\u{abbe}', '\u{13ee}'),
+        ('\u{abbf}', '\u{13ef}'), ('\u{ff21}', '\u{ff41}'), ('\u{ff22}',
+        '\u{ff42}'), ('\u{ff23}', '\u{ff43}'), ('\u{ff24}', '\u{ff44}'),
+        ('\u{ff25}', '\u{ff45}'), ('\u{ff26}', '\u{ff46}'), ('\u{ff27}',
+        '\u{ff47}'), ('\u{ff28}', '\u{ff48}'), ('\u{ff29}', '\u{ff49}'),
+        ('\u{ff2a}', '\u{ff4a}'), ('\u{ff2b}', '\u{ff4b}'), ('\u{ff2c}',
+        '\u{ff4c}'), ('\u{ff2d}', '\u{ff4d}'), ('\u{ff2e}', '\u{ff4e}'),
+        ('\u{ff2f}', '\u{ff4f}'), ('\u{ff30}', '\u{ff50}'), ('\u{ff31}',
+        '\u{ff51}'), ('\u{ff32}', '\u{ff52}'), ('\u{ff33}', '\u{ff53}'),
+        ('\u{ff34}', '\u{ff54}'), ('\u{ff35}', '\u{ff55}'), ('\u{ff36}',
+        '\u{ff56}'), ('\u{ff37}', '\u{ff57}'), ('\u{ff38}', '\u{ff58}'),
+        ('\u{ff39}', '\u{ff59}'), ('\u{ff3a}', '\u{ff5a}'), ('\u{ff41}',
+        '\u{ff21}'), ('\u{ff42}', '\u{ff22}'), ('\u{ff43}', '\u{ff23}'),
+        ('\u{ff44}', '\u{ff24}'), ('\u{ff45}', '\u{ff25}'), ('\u{ff46}',
+        '\u{ff26}'), ('\u{ff47}', '\u{ff27}'), ('\u{ff48}', '\u{ff28}'),
+        ('\u{ff49}', '\u{ff29}'), ('\u{ff4a}', '\u{ff2a}'), ('\u{ff4b}',
+        '\u{ff2b}'), ('\u{ff4c}', '\u{ff2c}'), ('\u{ff4d}', '\u{ff2d}'),
+        ('\u{ff4e}', '\u{ff2e}'), ('\u{ff4f}', '\u{ff2f}'), ('\u{ff50}',
+        '\u{ff30}'), ('\u{ff51}', '\u{ff31}'), ('\u{ff52}', '\u{ff32}'),
+        ('\u{ff53}', '\u{ff33}'), ('\u{ff54}', '\u{ff34}'), ('\u{ff55}',
+        '\u{ff35}'), ('\u{ff56}', '\u{ff36}'), ('\u{ff57}', '\u{ff37}'),
+        ('\u{ff58}', '\u{ff38}'), ('\u{ff59}', '\u{ff39}'), ('\u{ff5a}',
+        '\u{ff3a}'), ('\u{10400}', '\u{10428}'), ('\u{10401}', '\u{10429}'),
+        ('\u{10402}', '\u{1042a}'), ('\u{10403}', '\u{1042b}'), ('\u{10404}',
+        '\u{1042c}'), ('\u{10405}', '\u{1042d}'), ('\u{10406}', '\u{1042e}'),
+        ('\u{10407}', '\u{1042f}'), ('\u{10408}', '\u{10430}'), ('\u{10409}',
+        '\u{10431}'), ('\u{1040a}', '\u{10432}'), ('\u{1040b}', '\u{10433}'),
+        ('\u{1040c}', '\u{10434}'), ('\u{1040d}', '\u{10435}'), ('\u{1040e}',
+        '\u{10436}'), ('\u{1040f}', '\u{10437}'), ('\u{10410}', '\u{10438}'),
+        ('\u{10411}', '\u{10439}'), ('\u{10412}', '\u{1043a}'), ('\u{10413}',
+        '\u{1043b}'), ('\u{10414}', '\u{1043c}'), ('\u{10415}', '\u{1043d}'),
+        ('\u{10416}', '\u{1043e}'), ('\u{10417}', '\u{1043f}'), ('\u{10418}',
+        '\u{10440}'), ('\u{10419}', '\u{10441}'), ('\u{1041a}', '\u{10442}'),
+        ('\u{1041b}', '\u{10443}'), ('\u{1041c}', '\u{10444}'), ('\u{1041d}',
+        '\u{10445}'), ('\u{1041e}', '\u{10446}'), ('\u{1041f}', '\u{10447}'),
+        ('\u{10420}', '\u{10448}'), ('\u{10421}', '\u{10449}'), ('\u{10422}',
+        '\u{1044a}'), ('\u{10423}', '\u{1044b}'), ('\u{10424}', '\u{1044c}'),
+        ('\u{10425}', '\u{1044d}'), ('\u{10426}', '\u{1044e}'), ('\u{10427}',
+        '\u{1044f}'), ('\u{10428}', '\u{10400}'), ('\u{10429}', '\u{10401}'),
+        ('\u{1042a}', '\u{10402}'), ('\u{1042b}', '\u{10403}'), ('\u{1042c}',
+        '\u{10404}'), ('\u{1042d}', '\u{10405}'), ('\u{1042e}', '\u{10406}'),
+        ('\u{1042f}', '\u{10407}'), ('\u{10430}', '\u{10408}'), ('\u{10431}',
+        '\u{10409}'), ('\u{10432}', '\u{1040a}'), ('\u{10433}', '\u{1040b}'),
+        ('\u{10434}', '\u{1040c}'), ('\u{10435}', '\u{1040d}'), ('\u{10436}',
+        '\u{1040e}'), ('\u{10437}', '\u{1040f}'), ('\u{10438}', '\u{10410}'),
+        ('\u{10439}', '\u{10411}'), ('\u{1043a}', '\u{10412}'), ('\u{1043b}',
+        '\u{10413}'), ('\u{1043c}', '\u{10414}'), ('\u{1043d}', '\u{10415}'),
+        ('\u{1043e}', '\u{10416}'), ('\u{1043f}', '\u{10417}'), ('\u{10440}',
+        '\u{10418}'), ('\u{10441}', '\u{10419}'), ('\u{10442}', '\u{1041a}'),
+        ('\u{10443}', '\u{1041b}'), ('\u{10444}', '\u{1041c}'), ('\u{10445}',
+        '\u{1041d}'), ('\u{10446}', '\u{1041e}'), ('\u{10447}', '\u{1041f}'),
+        ('\u{10448}', '\u{10420}'), ('\u{10449}', '\u{10421}'), ('\u{1044a}',
+        '\u{10422}'), ('\u{1044b}', '\u{10423}'), ('\u{1044c}', '\u{10424}'),
+        ('\u{1044d}', '\u{10425}'), ('\u{1044e}', '\u{10426}'), ('\u{1044f}',
+        '\u{10427}'), ('\u{10c80}', '\u{10cc0}'), ('\u{10c81}', '\u{10cc1}'),
+        ('\u{10c82}', '\u{10cc2}'), ('\u{10c83}', '\u{10cc3}'), ('\u{10c84}',
+        '\u{10cc4}'), ('\u{10c85}', '\u{10cc5}'), ('\u{10c86}', '\u{10cc6}'),
+        ('\u{10c87}', '\u{10cc7}'), ('\u{10c88}', '\u{10cc8}'), ('\u{10c89}',
+        '\u{10cc9}'), ('\u{10c8a}', '\u{10cca}'), ('\u{10c8b}', '\u{10ccb}'),
+        ('\u{10c8c}', '\u{10ccc}'), ('\u{10c8d}', '\u{10ccd}'), ('\u{10c8e}',
+        '\u{10cce}'), ('\u{10c8f}', '\u{10ccf}'), ('\u{10c90}', '\u{10cd0}'),
+        ('\u{10c91}', '\u{10cd1}'), ('\u{10c92}', '\u{10cd2}'), ('\u{10c93}',
+        '\u{10cd3}'), ('\u{10c94}', '\u{10cd4}'), ('\u{10c95}', '\u{10cd5}'),
+        ('\u{10c96}', '\u{10cd6}'), ('\u{10c97}', '\u{10cd7}'), ('\u{10c98}',
+        '\u{10cd8}'), ('\u{10c99}', '\u{10cd9}'), ('\u{10c9a}', '\u{10cda}'),
+        ('\u{10c9b}', '\u{10cdb}'), ('\u{10c9c}', '\u{10cdc}'), ('\u{10c9d}',
+        '\u{10cdd}'), ('\u{10c9e}', '\u{10cde}'), ('\u{10c9f}', '\u{10cdf}'),
+        ('\u{10ca0}', '\u{10ce0}'), ('\u{10ca1}', '\u{10ce1}'), ('\u{10ca2}',
+        '\u{10ce2}'), ('\u{10ca3}', '\u{10ce3}'), ('\u{10ca4}', '\u{10ce4}'),
+        ('\u{10ca5}', '\u{10ce5}'), ('\u{10ca6}', '\u{10ce6}'), ('\u{10ca7}',
+        '\u{10ce7}'), ('\u{10ca8}', '\u{10ce8}'), ('\u{10ca9}', '\u{10ce9}'),
+        ('\u{10caa}', '\u{10cea}'), ('\u{10cab}', '\u{10ceb}'), ('\u{10cac}',
+        '\u{10cec}'), ('\u{10cad}', '\u{10ced}'), ('\u{10cae}', '\u{10cee}'),
+        ('\u{10caf}', '\u{10cef}'), ('\u{10cb0}', '\u{10cf0}'), ('\u{10cb1}',
+        '\u{10cf1}'), ('\u{10cb2}', '\u{10cf2}'), ('\u{10cc0}', '\u{10c80}'),
+        ('\u{10cc1}', '\u{10c81}'), ('\u{10cc2}', '\u{10c82}'), ('\u{10cc3}',
+        '\u{10c83}'), ('\u{10cc4}', '\u{10c84}'), ('\u{10cc5}', '\u{10c85}'),
+        ('\u{10cc6}', '\u{10c86}'), ('\u{10cc7}', '\u{10c87}'), ('\u{10cc8}',
+        '\u{10c88}'), ('\u{10cc9}', '\u{10c89}'), ('\u{10cca}', '\u{10c8a}'),
+        ('\u{10ccb}', '\u{10c8b}'), ('\u{10ccc}', '\u{10c8c}'), ('\u{10ccd}',
+        '\u{10c8d}'), ('\u{10cce}', '\u{10c8e}'), ('\u{10ccf}', '\u{10c8f}'),
+        ('\u{10cd0}', '\u{10c90}'), ('\u{10cd1}', '\u{10c91}'), ('\u{10cd2}',
+        '\u{10c92}'), ('\u{10cd3}', '\u{10c93}'), ('\u{10cd4}', '\u{10c94}'),
+        ('\u{10cd5}', '\u{10c95}'), ('\u{10cd6}', '\u{10c96}'), ('\u{10cd7}',
+        '\u{10c97}'), ('\u{10cd8}', '\u{10c98}'), ('\u{10cd9}', '\u{10c99}'),
+        ('\u{10cda}', '\u{10c9a}'), ('\u{10cdb}', '\u{10c9b}'), ('\u{10cdc}',
+        '\u{10c9c}'), ('\u{10cdd}', '\u{10c9d}'), ('\u{10cde}', '\u{10c9e}'),
+        ('\u{10cdf}', '\u{10c9f}'), ('\u{10ce0}', '\u{10ca0}'), ('\u{10ce1}',
+        '\u{10ca1}'), ('\u{10ce2}', '\u{10ca2}'), ('\u{10ce3}', '\u{10ca3}'),
+        ('\u{10ce4}', '\u{10ca4}'), ('\u{10ce5}', '\u{10ca5}'), ('\u{10ce6}',
+        '\u{10ca6}'), ('\u{10ce7}', '\u{10ca7}'), ('\u{10ce8}', '\u{10ca8}'),
+        ('\u{10ce9}', '\u{10ca9}'), ('\u{10cea}', '\u{10caa}'), ('\u{10ceb}',
+        '\u{10cab}'), ('\u{10cec}', '\u{10cac}'), ('\u{10ced}', '\u{10cad}'),
+        ('\u{10cee}', '\u{10cae}'), ('\u{10cef}', '\u{10caf}'), ('\u{10cf0}',
+        '\u{10cb0}'), ('\u{10cf1}', '\u{10cb1}'), ('\u{10cf2}', '\u{10cb2}'),
+        ('\u{118a0}', '\u{118c0}'), ('\u{118a1}', '\u{118c1}'), ('\u{118a2}',
+        '\u{118c2}'), ('\u{118a3}', '\u{118c3}'), ('\u{118a4}', '\u{118c4}'),
+        ('\u{118a5}', '\u{118c5}'), ('\u{118a6}', '\u{118c6}'), ('\u{118a7}',
+        '\u{118c7}'), ('\u{118a8}', '\u{118c8}'), ('\u{118a9}', '\u{118c9}'),
+        ('\u{118aa}', '\u{118ca}'), ('\u{118ab}', '\u{118cb}'), ('\u{118ac}',
+        '\u{118cc}'), ('\u{118ad}', '\u{118cd}'), ('\u{118ae}', '\u{118ce}'),
+        ('\u{118af}', '\u{118cf}'), ('\u{118b0}', '\u{118d0}'), ('\u{118b1}',
+        '\u{118d1}'), ('\u{118b2}', '\u{118d2}'), ('\u{118b3}', '\u{118d3}'),
+        ('\u{118b4}', '\u{118d4}'), ('\u{118b5}', '\u{118d5}'), ('\u{118b6}',
+        '\u{118d6}'), ('\u{118b7}', '\u{118d7}'), ('\u{118b8}', '\u{118d8}'),
+        ('\u{118b9}', '\u{118d9}'), ('\u{118ba}', '\u{118da}'), ('\u{118bb}',
+        '\u{118db}'), ('\u{118bc}', '\u{118dc}'), ('\u{118bd}', '\u{118dd}'),
+        ('\u{118be}', '\u{118de}'), ('\u{118bf}', '\u{118df}'), ('\u{118c0}',
+        '\u{118a0}'), ('\u{118c1}', '\u{118a1}'), ('\u{118c2}', '\u{118a2}'),
+        ('\u{118c3}', '\u{118a3}'), ('\u{118c4}', '\u{118a4}'), ('\u{118c5}',
+        '\u{118a5}'), ('\u{118c6}', '\u{118a6}'), ('\u{118c7}', '\u{118a7}'),
+        ('\u{118c8}', '\u{118a8}'), ('\u{118c9}', '\u{118a9}'), ('\u{118ca}',
+        '\u{118aa}'), ('\u{118cb}', '\u{118ab}'), ('\u{118cc}', '\u{118ac}'),
+        ('\u{118cd}', '\u{118ad}'), ('\u{118ce}', '\u{118ae}'), ('\u{118cf}',
+        '\u{118af}'), ('\u{118d0}', '\u{118b0}'), ('\u{118d1}', '\u{118b1}'),
+        ('\u{118d2}', '\u{118b2}'), ('\u{118d3}', '\u{118b3}'), ('\u{118d4}',
+        '\u{118b4}'), ('\u{118d5}', '\u{118b5}'), ('\u{118d6}', '\u{118b6}'),
+        ('\u{118d7}', '\u{118b7}'), ('\u{118d8}', '\u{118b8}'), ('\u{118d9}',
+        '\u{118b9}'), ('\u{118da}', '\u{118ba}'), ('\u{118db}', '\u{118bb}'),
+        ('\u{118dc}', '\u{118bc}'), ('\u{118dd}', '\u{118bd}'), ('\u{118de}',
+        '\u{118be}'), ('\u{118df}', '\u{118bf}')
+    ];
+
+}
+
diff --git a/third_party/rust/regex-syntax/.cargo-checksum.json b/third_party/rust/regex-syntax/.cargo-checksum.json
index df93a3670e12..0c763bc56ab1 100644
--- a/third_party/rust/regex-syntax/.cargo-checksum.json
+++ b/third_party/rust/regex-syntax/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"264a95f5e516e60aecbe9f8a5f1c551bf71debb7249cf4bc3c102d68b9bb0dde","src/lib.rs":"e8eb3529e5bf62913439605d478b7385e43e5ef8ebb6c4800630a16f8ab3cb26","src/literals.rs":"4e7d4afa303ffe241bd17621728a1e0c018386f4f77b4d8f0f4403f74650bc6a","src/parser.rs":"975f570f86914c8bc8a132f5ced11484fa912ed0f7071f2bd2764600b611ec46","src/properties.rs":"ba19030e905d133039eb97b167dc82b4a9f78dd88c3b79b381ec7e5fbc6f6a8c","src/unicode.rs":"5bbab13485910b55a56e8f8437786e820f409902e96d07ba2018c28cecb033fc"},"package":"ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"}
\ No newline at end of file
+{"files":{"Cargo.toml":"338ad5d3160f57e256aa9be8348e320d8ad3932a83a132786769e43041f520ca","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","benches/bench.rs":"4d09c75f457459f850877ee334a924f331c701a22fa19b1f7942c3504c8981f4","src/ast/mod.rs":"31825eaa0fdc0ae9939cf118f07c9a3ce7c0485065e0646df353a2d310ae5cd8","src/ast/parse.rs":"d1b5a837df7f7b09e5f6b70350407eeef56dfa5e6d27519fd903c07d16968fd1","src/ast/print.rs":"c7281fdec95b796c4e32393d3f750ab58cb5bea1dd77e87d4284c0ea0a304f1e","src/ast/visitor.rs":"493be4ba270f8cfeffe096b981947a12a5992542c1df1ed470e015f1c41ed081","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"ae638c6e6adcc7843dec98eb52b2dda2e5085a7c029a8d7f005ef40d35557617","src/hir/interval.rs":"3c2599c9c07149afb0770eca720ab66ed9599402ee58b34bf6709eac4c895239","src/hir/literal/mod.rs":"4fd26946232d056342a5052b4c84a28b6c0b956f57b4a4ff8fe64eb1b710aae5","src/hir/mod.rs":"07bdd0dc1c7c60194ab8a3242cb2fe58d5b51ba36d303d495dcd394726ea469e","src/hir/print.rs":"a7efad3703d1718de65c6657eff6be72a4e96bc3db8a56d08d2a96c0abdb99b8","src/hir/translate.rs":"9f6e1f8bd5f4623db0554a42218a919c18ac0fb1ac271c109147058c6f96a3d3","src/hir/visitor.rs":"8e15e646c8c219fd1f4620fc3611dfbd0d63d598bc5c8bcbfb0106053134613c","src/lib.rs":"d1cbe98975034f18276e149bc42ce44d77623a62d53385b7d3a3fa1e2df9f383","src/parser.rs":"70e0386d373af3bc4e491c0371be06069a773cfb0476e44224702c3da643ce24","src/unicode.rs":"74e35b368555ad683284dc4795084e5b7f7cc9bb8fddd17bdd8e40a51588f43e","src/unicode_tables/age.rs":"ad5413c1e4811d85ad845ccb21f12e6bbf33f7d048d0f91863b18da143eb49e8","src/unicode_tables/case_folding_simple.rs":"270a52df6dcb639cafaa9de563ff4dc88522fa9bfe7174f0b8c140d4208c71c7","src/unicode_tables/general_category.rs":"d0e8e05acf7563e426835502b2b510595a01a2739374ae54db29eefee642ed51","src/unicode_tables/mod.rs":"c395afbe606c4a9ef8656cd315b1ce2d5c1729fd60c99da8c6d661c49c47adf4","src/unicode_tables/perl_word.rs":"34050803ae07324c0bd1c976ffeac65df35ea8da3874ab391c997ece258130f3","src/unicode_tables/property_bool.rs":"12f0298e3cbaf7170ba8a9abaa4c1449ac9cc54a8126927e481f3aa350f42641","src/unicode_tables/property_names.rs":"3d1a6a69fb2780089e30919504f3b8314c71847bc89be24b98bc3fa96a5e1567","src/unicode_tables/property_values.rs":"2a86b2723a72f2c164f32b91907895edaf759a98e01b92f135fd2a70a62e5f00","src/unicode_tables/script.rs":"1584c2d3360fc331c0ae697903b59e7bd309d60a6920db8f6ef35d24a6846ec3","src/unicode_tables/script_extension.rs":"269b12f032940e098abcfa88234a3a0f0c74e036756bb3835d76fc197a73c54d"},"package":"747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"}
\ No newline at end of file
diff --git a/third_party/rust/regex-syntax/Cargo.toml b/third_party/rust/regex-syntax/Cargo.toml
index c6295395b861..b638c74a3eda 100644
--- a/third_party/rust/regex-syntax/Cargo.toml
+++ b/third_party/rust/regex-syntax/Cargo.toml
@@ -1,13 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
 name = "regex-syntax"
-version = "0.4.1"  #:version
+version = "0.6.2"
 authors = ["The Rust Project Developers"]
+description = "A regular expression parser."
+homepage = "https://github.com/rust-lang/regex"
+documentation = "https://docs.rs/regex-syntax"
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-lang/regex"
-documentation = "http://doc.rust-lang.org/regex/regex_syntax/index.html"
-homepage = "https://github.com/rust-lang/regex"
-description = "A regular expression parser."
-
-[dev-dependencies]
-quickcheck = { version = "0.4.1", default-features = false }
-rand = "0.3.15"
+[dependencies.ucd-util]
+version = "0.1.0"
diff --git a/third_party/rust/regex-syntax/LICENSE-APACHE b/third_party/rust/regex-syntax/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/regex-syntax/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/regex-syntax/LICENSE-MIT b/third_party/rust/regex-syntax/LICENSE-MIT
new file mode 100644
index 000000000000..39d4bdb5acd3
--- /dev/null
+++ b/third_party/rust/regex-syntax/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/regex-syntax/benches/bench.rs b/third_party/rust/regex-syntax/benches/bench.rs
new file mode 100644
index 000000000000..60aea9e98433
--- /dev/null
+++ b/third_party/rust/regex-syntax/benches/bench.rs
@@ -0,0 +1,73 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(test)]
+
+extern crate regex_syntax;
+extern crate test;
+
+use regex_syntax::Parser;
+use test::Bencher;
+
+#[bench]
+fn parse_simple1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"^bc(d|e)*$";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_simple2(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"'[a-zA-Z_][a-zA-Z0-9_]*(')\b";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_small1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{L}|\p{N}|\s|.|\d";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium1(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\pL\p{Greek}\p{Hiragana}\p{Alphabetic}\p{Hebrew}\p{Arabic}";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium2(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\s\S\w\W\d\D";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_medium3(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{age:3.2}\p{hira}\p{scx:hira}\p{alphabetic}\p{sc:Greek}\pL";
+        Parser::new().parse(re).unwrap()
+    });
+}
+
+#[bench]
+fn parse_huge(b: &mut Bencher) {
+    b.iter(|| {
+        let re = r"\p{L}{100}";
+        Parser::new().parse(re).unwrap()
+    });
+}
diff --git a/third_party/rust/regex-syntax/src/ast/mod.rs b/third_party/rust/regex-syntax/src/ast/mod.rs
new file mode 100644
index 000000000000..884fcfa35c97
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/ast/mod.rs
@@ -0,0 +1,1515 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Defines an abstract syntax for regular expressions.
+*/
+
+use std::cmp::Ordering;
+use std::error;
+use std::fmt;
+
+pub use ast::visitor::{Visitor, visit};
+
+pub mod parse;
+pub mod print;
+mod visitor;
+
+/// An error that occurred while parsing a regular expression into an abstract
+/// syntax tree.
+///
+/// Note that note all ASTs represents a valid regular expression. For example,
+/// an AST is constructed without error for `\p{Quux}`, but `Quux` is not a
+/// valid Unicode property name. That particular error is reported when
+/// translating an AST to the high-level intermediate representation (`HIR`).
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Error {
+    /// The kind of error.
+    kind: ErrorKind,
+    /// The original pattern that the parser generated the error from. Every
+    /// span in an error is a valid range into this string.
+    pattern: String,
+    /// The span of this error.
+    span: Span,
+}
+
+impl Error {
+    /// Return the type of this error.
+    pub fn kind(&self) -> &ErrorKind {
+        &self.kind
+    }
+
+    /// The original pattern string in which this error occurred.
+    ///
+    /// Every span reported by this error is reported in terms of this string.
+    pub fn pattern(&self) -> &str {
+        &self.pattern
+    }
+
+    /// Return the span at which this error occurred.
+    pub fn span(&self) -> &Span {
+        &self.span
+    }
+
+    /// Return an auxiliary span. This span exists only for some errors that
+    /// benefit from being able to point to two locations in the original
+    /// regular expression. For example, "duplicate" errors will have the
+    /// main error position set to the duplicate occurrence while its
+    /// auxiliary span will be set to the initial occurrence.
+    pub fn auxiliary_span(&self) -> Option<&Span> {
+        use self::ErrorKind::*;
+        match self.kind {
+            FlagDuplicate { ref original } => Some(original),
+            FlagRepeatedNegation { ref original, .. } => Some(original),
+            GroupNameDuplicate { ref original, .. } => Some(original),
+            _ => None,
+        }
+    }
+}
+
+/// The type of an error that occurred while building an AST.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ErrorKind {
+    /// The capturing group limit was exceeded.
+    ///
+    /// Note that this represents a limit on the total number of capturing
+    /// groups in a regex and not necessarily the number of nested capturing
+    /// groups. That is, the nest limit can be low and it is still possible for
+    /// this error to occur.
+    CaptureLimitExceeded,
+    /// An invalid escape sequence was found in a character class set.
+    ClassEscapeInvalid,
+    /// An invalid character class range was found. An invalid range is any
+    /// range where the start is greater than the end.
+    ClassRangeInvalid,
+    /// An invalid range boundary was found in a character class. Range
+    /// boundaries must be a single literal codepoint, but this error indicates
+    /// that something else was found, such as a nested class.
+    ClassRangeLiteral,
+    /// An opening `[` was found with no corresponding closing `]`.
+    ClassUnclosed,
+    /// An empty decimal number was given where one was expected.
+    DecimalEmpty,
+    /// An invalid decimal number was given where one was expected.
+    DecimalInvalid,
+    /// A bracketed hex literal was empty.
+    EscapeHexEmpty,
+    /// A bracketed hex literal did not correspond to a Unicode scalar value.
+    EscapeHexInvalid,
+    /// An invalid hexadecimal digit was found.
+    EscapeHexInvalidDigit,
+    /// EOF was found before an escape sequence was completed.
+    EscapeUnexpectedEof,
+    /// An unrecognized escape sequence.
+    EscapeUnrecognized,
+    /// A dangling negation was used when setting flags, e.g., `i-`.
+    FlagDanglingNegation,
+    /// A flag was used twice, e.g., `i-i`.
+    FlagDuplicate {
+        /// The position of the original flag. The error position
+        /// points to the duplicate flag.
+        original: Span,
+    },
+    /// The negation operator was used twice, e.g., `-i-s`.
+    FlagRepeatedNegation {
+        /// The position of the original negation operator. The error position
+        /// points to the duplicate negation operator.
+        original: Span,
+    },
+    /// Expected a flag but got EOF, e.g., `(?`.
+    FlagUnexpectedEof,
+    /// Unrecognized flag, e.g., `a`.
+    FlagUnrecognized,
+    /// A duplicate capture name was found.
+    GroupNameDuplicate {
+        /// The position of the initial occurrence of the capture name. The
+        /// error position itself points to the duplicate occurrence.
+        original: Span,
+    },
+    /// A capture group name is empty, e.g., `(?P<>abc)`.
+    GroupNameEmpty,
+    /// An invalid character was seen for a capture group name. This includes
+    /// errors where the first character is a digit (even though subsequent
+    /// characters are allowed to be digits).
+    GroupNameInvalid,
+    /// A closing `>` could not be found for a capture group name.
+    GroupNameUnexpectedEof,
+    /// An unclosed group, e.g., `(ab`.
+    ///
+    /// The span of this error corresponds to the unclosed parenthesis.
+    GroupUnclosed,
+    /// An unopened group, e.g., `ab)`.
+    GroupUnopened,
+    /// The nest limit was exceeded. The limit stored here is the limit
+    /// configured in the parser.
+    NestLimitExceeded(u32),
+    /// The range provided in a counted repetition operator is invalid. The
+    /// range is invalid if the start is greater than the end.
+    RepetitionCountInvalid,
+    /// An opening `{` was found with no corresponding closing `}`.
+    RepetitionCountUnclosed,
+    /// A repetition operator was applied to a missing sub-expression. This
+    /// occurs, for example, in the regex consisting of just a `*` or even
+    /// `(?i)*`. It is, however, possible to create a repetition operating on
+    /// an empty sub-expression. For example, `()*` is still considered valid.
+    RepetitionMissing,
+    /// When octal support is disabled, this error is produced when an octal
+    /// escape is used. The octal escape is assumed to be an invocation of
+    /// a backreference, which is the common case.
+    UnsupportedBackreference,
+    /// When syntax similar to PCRE's look-around is used, this error is
+    /// returned. Some example syntaxes that are rejected include, but are
+    /// not necessarily limited to, `(?=re)`, `(?!re)`, `(?<=re)` and
+    /// `(?<!re)`. Note that all of these syntaxes are otherwise invalid; this
+    /// error is used to improve the user experience.
+    UnsupportedLookAround,
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        use self::ErrorKind::*;
+        match self.kind {
+            CaptureLimitExceeded => "capture group limit exceeded",
+            ClassEscapeInvalid => "invalid escape sequence in character class",
+            ClassRangeInvalid => "invalid character class range",
+            ClassRangeLiteral => "invalid range boundary, must be a literal",
+            ClassUnclosed => "unclosed character class",
+            DecimalEmpty => "empty decimal literal",
+            DecimalInvalid => "invalid decimal literal",
+            EscapeHexEmpty => "empty hexadecimal literal",
+            EscapeHexInvalid => "invalid hexadecimal literal",
+            EscapeHexInvalidDigit => "invalid hexadecimal digit",
+            EscapeUnexpectedEof => "unexpected eof (escape sequence)",
+            EscapeUnrecognized => "unrecognized escape sequence",
+            FlagDanglingNegation => "dangling flag negation operator",
+            FlagDuplicate{..} => "duplicate flag",
+            FlagRepeatedNegation{..} => "repeated negation",
+            FlagUnexpectedEof => "unexpected eof (flag)",
+            FlagUnrecognized => "unrecognized flag",
+            GroupNameDuplicate{..} => "duplicate capture group name",
+            GroupNameEmpty => "empty capture group name",
+            GroupNameInvalid => "invalid capture group name",
+            GroupNameUnexpectedEof => "unclosed capture group name",
+            GroupUnclosed => "unclosed group",
+            GroupUnopened => "unopened group",
+            NestLimitExceeded(_) => "nest limit exceeded",
+            RepetitionCountInvalid => "invalid repetition count range",
+            RepetitionCountUnclosed => "unclosed counted repetition",
+            RepetitionMissing => "repetition operator missing expression",
+            UnsupportedBackreference => "backreferences are not supported",
+            UnsupportedLookAround => "look-around is not supported",
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ::error::Formatter::from(self).fmt(f)
+    }
+}
+
+impl fmt::Display for ErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::ErrorKind::*;
+        match *self {
+            CaptureLimitExceeded => {
+                write!(f, "exceeded the maximum number of \
+                           capturing groups ({})", ::std::u32::MAX)
+            }
+            ClassEscapeInvalid => {
+                write!(f, "invalid escape sequence found in character class")
+            }
+            ClassRangeInvalid => {
+                write!(f, "invalid character class range, \
+                           the start must be <= the end")
+            }
+            ClassRangeLiteral => {
+                write!(f, "invalid range boundary, must be a literal")
+            }
+            ClassUnclosed => {
+                write!(f, "unclosed character class")
+            }
+            DecimalEmpty => {
+                write!(f, "decimal literal empty")
+            }
+            DecimalInvalid => {
+                write!(f, "decimal literal invalid")
+            }
+            EscapeHexEmpty => {
+                write!(f, "hexadecimal literal empty")
+            }
+            EscapeHexInvalid => {
+                write!(f, "hexadecimal literal is not a Unicode scalar value")
+            }
+            EscapeHexInvalidDigit => {
+                write!(f, "invalid hexadecimal digit")
+            }
+            EscapeUnexpectedEof => {
+                write!(f, "incomplete escape sequence, \
+                           reached end of pattern prematurely")
+            }
+            EscapeUnrecognized => {
+                write!(f, "unrecognized escape sequence")
+            }
+            FlagDanglingNegation => {
+                write!(f, "dangling flag negation operator")
+            }
+            FlagDuplicate{..} => {
+                write!(f, "duplicate flag")
+            }
+            FlagRepeatedNegation{..} => {
+                write!(f, "flag negation operator repeated")
+            }
+            FlagUnexpectedEof => {
+                write!(f, "expected flag but got end of regex")
+            }
+            FlagUnrecognized => {
+                write!(f, "unrecognized flag")
+            }
+            GroupNameDuplicate{..} => {
+                write!(f, "duplicate capture group name")
+            }
+            GroupNameEmpty => {
+                write!(f, "empty capture group name")
+            }
+            GroupNameInvalid => {
+                write!(f, "invalid capture group character")
+            }
+            GroupNameUnexpectedEof => {
+                write!(f, "unclosed capture group name")
+            }
+            GroupUnclosed => {
+                write!(f, "unclosed group")
+            }
+            GroupUnopened => {
+                write!(f, "unopened group")
+            }
+            NestLimitExceeded(limit) => {
+                write!(f, "exceed the maximum number of \
+                           nested parentheses/brackets ({})", limit)
+            }
+            RepetitionCountInvalid => {
+                write!(f, "invalid repetition count range, \
+                           the start must be <= the end")
+            }
+            RepetitionCountUnclosed => {
+                write!(f, "unclosed counted repetition")
+            }
+            RepetitionMissing => {
+                write!(f, "repetition operator missing expression")
+            }
+            UnsupportedBackreference => {
+                write!(f, "backreferences are not supported")
+            }
+            UnsupportedLookAround => {
+                write!(f, "look-around, including look-ahead and look-behind, \
+                           is not supported")
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
+/// Span represents the position information of a single AST item.
+///
+/// All span positions are absolute byte offsets that can be used on the
+/// original regular expression that was parsed.
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Span {
+    /// The start byte offset.
+    pub start: Position,
+    /// The end byte offset.
+    pub end: Position,
+}
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Span({:?}, {:?})", self.start, self.end)
+    }
+}
+
+impl Ord for Span {
+    fn cmp(&self, other: &Span) -> Ordering {
+        (&self.start, &self.end).cmp(&(&other.start, &other.end))
+    }
+}
+
+impl PartialOrd for Span {
+    fn partial_cmp(&self, other: &Span) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+/// A single position in a regular expression.
+///
+/// A position encodes one half of a span, and include the byte offset, line
+/// number and column number.
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Position {
+    /// The absolute offset of this position, starting at `0` from the
+    /// beginning of the regular expression pattern string.
+    pub offset: usize,
+    /// The line number, starting at `1`.
+    pub line: usize,
+    /// The approximate column number, starting at `1`.
+    pub column: usize,
+}
+
+impl fmt::Debug for Position {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "Position(o: {:?}, l: {:?}, c: {:?})",
+            self.offset, self.line, self.column)
+    }
+}
+
+impl Ord for Position {
+    fn cmp(&self, other: &Position) -> Ordering {
+        self.offset.cmp(&other.offset)
+    }
+}
+
+impl PartialOrd for Position {
+    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Span {
+    /// Create a new span with the given positions.
+    pub fn new(start: Position, end: Position) -> Span {
+        Span { start: start, end: end }
+    }
+
+    /// Create a new span using the given position as the start and end.
+    pub fn splat(pos: Position) -> Span {
+        Span::new(pos, pos)
+    }
+
+    /// Create a new span by replacing the starting the position with the one
+    /// given.
+    pub fn with_start(self, pos: Position) -> Span {
+        Span { start: pos, ..self }
+    }
+
+    /// Create a new span by replacing the ending the position with the one
+    /// given.
+    pub fn with_end(self, pos: Position) -> Span {
+        Span { end: pos, ..self }
+    }
+
+    /// Returns true if and only if this span occurs on a single line.
+    pub fn is_one_line(&self) -> bool {
+        self.start.line == self.end.line
+    }
+
+    /// Returns true if and only if this span is empty. That is, it points to
+    /// a single position in the concrete syntax of a regular expression.
+    pub fn is_empty(&self) -> bool {
+        self.start.offset == self.end.offset
+    }
+}
+
+impl Position {
+    /// Create a new position with the given information.
+    ///
+    /// `offset` is the absolute offset of the position, starting at `0` from
+    /// the beginning of the regular expression pattern string.
+    ///
+    /// `line` is the line number, starting at `1`.
+    ///
+    /// `column` is the approximate column number, starting at `1`.
+    pub fn new(offset: usize, line: usize, column: usize) -> Position {
+        Position { offset: offset, line: line, column: column }
+    }
+}
+
+/// An abstract syntax tree for a singular expression along with comments
+/// found.
+///
+/// Comments are not stored in the tree itself to avoid complexity. Each
+/// comment contains a span of precisely where it occurred in the original
+/// regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct WithComments {
+    /// The actual ast.
+    pub ast: Ast,
+    /// All comments found in the original regular expression.
+    pub comments: Vec<Comment>,
+}
+
+/// A comment from a regular expression with an associated span.
+///
+/// A regular expression can only contain comments when the `x` flag is
+/// enabled.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Comment {
+    /// The span of this comment, including the beginning `#` and ending `\n`.
+    pub span: Span,
+    /// The comment text, starting with the first character following the `#`
+    /// and ending with the last character preceding the `\n`.
+    pub comment: String,
+}
+
+/// An abstract syntax tree for a single regular expression.
+///
+/// An `Ast`'s `fmt::Display` implementation uses constant stack space and heap
+/// space proportional to the size of the `Ast`.
+///
+/// This type defines its own destructor that uses constant stack space and
+/// heap space proportional to the size of the `Ast`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Ast {
+    /// An empty regex that matches everything.
+    Empty(Span),
+    /// A set of flags, e.g., `(?is)`.
+    Flags(SetFlags),
+    /// A single character literal, which includes escape sequences.
+    Literal(Literal),
+    /// The "any character" class.
+    Dot(Span),
+    /// A single zero-width assertion.
+    Assertion(Assertion),
+    /// A single character class. This includes all forms of character classes
+    /// except for `.`. e.g., `\d`, `\pN`, `[a-z]` and `[[:alpha:]]`.
+    Class(Class),
+    /// A repetition operator applied to an arbitrary regular expression.
+    Repetition(Repetition),
+    /// A grouped regular expression.
+    Group(Group),
+    /// An alternation of regular expressions.
+    Alternation(Alternation),
+    /// A concatenation of regular expressions.
+    Concat(Concat),
+}
+
+impl Ast {
+    /// Return the span of this abstract syntax tree.
+    pub fn span(&self) -> &Span {
+        match *self {
+            Ast::Empty(ref span) => span,
+            Ast::Flags(ref x) => &x.span,
+            Ast::Literal(ref x) => &x.span,
+            Ast::Dot(ref span) => span,
+            Ast::Assertion(ref x) => &x.span,
+            Ast::Class(ref x) => x.span(),
+            Ast::Repetition(ref x) => &x.span,
+            Ast::Group(ref x) => &x.span,
+            Ast::Alternation(ref x) => &x.span,
+            Ast::Concat(ref x) => &x.span,
+        }
+    }
+
+    /// Return true if and only if this Ast is empty.
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            Ast::Empty(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if this AST has any (including possibly empty)
+    /// subexpressions.
+    fn has_subexprs(&self) -> bool {
+        match *self {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_) => false,
+            Ast::Class(_)
+            | Ast::Repetition(_)
+            | Ast::Group(_)
+            | Ast::Alternation(_)
+            | Ast::Concat(_) => true,
+        }
+    }
+}
+
+/// Print a display representation of this Ast.
+///
+/// This does not preserve any of the original whitespace formatting that may
+/// have originally been present in the concrete syntax from which this Ast
+/// was generated.
+///
+/// This implementation uses constant stack space and heap space proportional
+/// to the size of the `Ast`.
+impl fmt::Display for Ast {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use ast::print::Printer;
+        Printer::new().print(self, f)
+    }
+}
+
+/// An alternation of regular expressions.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Alternation {
+    /// The span of this alternation.
+    pub span: Span,
+    /// The alternate regular expressions.
+    pub asts: Vec<Ast>,
+}
+
+impl Alternation {
+    /// Return this alternation as an AST.
+    ///
+    /// If this alternation contains zero ASTs, then Ast::Empty is
+    /// returned. If this alternation contains exactly 1 AST, then the
+    /// corresponding AST is returned. Otherwise, Ast::Alternation is returned.
+    pub fn into_ast(mut self) -> Ast {
+        match self.asts.len() {
+            0 => Ast::Empty(self.span),
+            1 => self.asts.pop().unwrap(),
+            _ => Ast::Alternation(self),
+        }
+    }
+}
+
+/// A concatenation of regular expressions.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Concat {
+    /// The span of this concatenation.
+    pub span: Span,
+    /// The concatenation regular expressions.
+    pub asts: Vec<Ast>,
+}
+
+impl Concat {
+    /// Return this concatenation as an AST.
+    ///
+    /// If this concatenation contains zero ASTs, then Ast::Empty is
+    /// returned. If this concatenation contains exactly 1 AST, then the
+    /// corresponding AST is returned. Otherwise, Ast::Concat is returned.
+    pub fn into_ast(mut self) -> Ast {
+        match self.asts.len() {
+            0 => Ast::Empty(self.span),
+            1 => self.asts.pop().unwrap(),
+            _ => Ast::Concat(self),
+        }
+    }
+}
+
+/// A single literal expression.
+///
+/// A literal corresponds to a single Unicode scalar value. Literals may be
+/// represented in their literal form, e.g., `a` or in their escaped form,
+/// e.g., `\x61`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Literal {
+    /// The span of this literal.
+    pub span: Span,
+    /// The kind of this literal.
+    pub kind: LiteralKind,
+    /// The Unicode scalar value corresponding to this literal.
+    pub c: char,
+}
+
+impl Literal {
+    /// If this literal was written as a `\x` hex escape, then this returns
+    /// the corresponding byte value. Otherwise, this returns `None`.
+    pub fn byte(&self) -> Option<u8> {
+        let short_hex = LiteralKind::HexFixed(HexLiteralKind::X);
+        if self.c as u32 <= 255 && self.kind == short_hex {
+            Some(self.c as u8)
+        } else {
+            None
+        }
+    }
+}
+
+/// The kind of a single literal expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum LiteralKind {
+    /// The literal is written verbatim, e.g., `a` or `☃`.
+    Verbatim,
+    /// The literal is written as an escape because it is punctuation, e.g.,
+    /// `\*` or `\[`.
+    Punctuation,
+    /// The literal is written as an octal escape, e.g., `\141`.
+    Octal,
+    /// The literal is written as a hex code with a fixed number of digits
+    /// depending on the type of the escape, e.g., `\x61` or or `\u0061` or
+    /// `\U00000061`.
+    HexFixed(HexLiteralKind),
+    /// The literal is written as a hex code with a bracketed number of
+    /// digits. The only restriction is that the bracketed hex code must refer
+    /// to a valid Unicode scalar value.
+    HexBrace(HexLiteralKind),
+    /// The literal is written as a specially recognized escape, e.g., `\f`
+    /// or `\n`.
+    Special(SpecialLiteralKind),
+}
+
+/// The type of a special literal.
+///
+/// A special literal is a special escape sequence recognized by the regex
+/// parser, e.g., `\f` or `\n`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum SpecialLiteralKind {
+    /// Bell, spelled `\a` (`\x07`).
+    Bell,
+    /// Form feed, spelled `\f` (`\x0C`).
+    FormFeed,
+    /// Tab, spelled `\t` (`\x09`).
+    Tab,
+    /// Line feed, spelled `\n` (`\x0A`).
+    LineFeed,
+    /// Carriage return, spelled `\r` (`\x0D`).
+    CarriageReturn,
+    /// Vertical tab, spelled `\v` (`\x0B`).
+    VerticalTab,
+    /// Space, spelled `\ ` (`\x20`). Note that this can only appear when
+    /// parsing in verbose mode.
+    Space,
+}
+
+/// The type of a Unicode hex literal.
+///
+/// Note that all variants behave the same when used with brackets. They only
+/// differ when used without brackets in the number of hex digits that must
+/// follow.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum HexLiteralKind {
+    /// A `\x` prefix. When used without brackets, this form is limited to
+    /// two digits.
+    X,
+    /// A `\u` prefix. When used without brackets, this form is limited to
+    /// four digits.
+    UnicodeShort,
+    /// A `\U` prefix. When used without brackets, this form is limited to
+    /// eight digits.
+    UnicodeLong,
+}
+
+impl HexLiteralKind {
+    /// The number of digits that must be used with this literal form when
+    /// used without brackets. When used with brackets, there is no
+    /// restriction on the number of digits.
+    pub fn digits(&self) -> u32 {
+        match *self {
+            HexLiteralKind::X => 2,
+            HexLiteralKind::UnicodeShort => 4,
+            HexLiteralKind::UnicodeLong => 8,
+        }
+    }
+}
+
+/// A single character class expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Class {
+    /// A Unicode character class, e.g., `\pL` or `\p{Greek}`.
+    Unicode(ClassUnicode),
+    /// A perl character class, e.g., `\d` or `\W`.
+    Perl(ClassPerl),
+    /// A bracketed character class set, which may contain zero or more
+    /// character ranges and/or zero or more nested classes. e.g.,
+    /// `[a-zA-Z\pL]`.
+    Bracketed(ClassBracketed),
+}
+
+impl Class {
+    /// Return the span of this character class.
+    pub fn span(&self) -> &Span {
+        match *self {
+            Class::Perl(ref x) => &x.span,
+            Class::Unicode(ref x) => &x.span,
+            Class::Bracketed(ref x) => &x.span,
+        }
+    }
+}
+
+/// A Perl character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassPerl {
+    /// The span of this class.
+    pub span: Span,
+    /// The kind of Perl class.
+    pub kind: ClassPerlKind,
+    /// Whether the class is negated or not. e.g., `\d` is not negated but
+    /// `\D` is.
+    pub negated: bool,
+}
+
+/// The available Perl character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassPerlKind {
+    /// Decimal numbers.
+    Digit,
+    /// Whitespace.
+    Space,
+    /// Word characters.
+    Word,
+}
+
+/// An ASCII character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassAscii {
+    /// The span of this class.
+    pub span: Span,
+    /// The kind of ASCII class.
+    pub kind: ClassAsciiKind,
+    /// Whether the class is negated or not. e.g., `[[:alpha:]]` is not negated
+    /// but `[[:^alpha:]]` is.
+    pub negated: bool,
+}
+
+/// The available ASCII character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassAsciiKind {
+    /// `[0-9A-Za-z]`
+    Alnum,
+    /// `[A-Za-z]`
+    Alpha,
+    /// `[\x00-\x7F]`
+    Ascii,
+    /// `[ \t]`
+    Blank,
+    /// `[\x00-\x1F\x7F]`
+    Cntrl,
+    /// `[0-9]`
+    Digit,
+    /// `[!-~]`
+    Graph,
+    /// `[a-z]`
+    Lower,
+    /// `[ -~]`
+    Print,
+    /// `[!-/:-@\[-`{-~]`
+    Punct,
+    /// `[\t\n\v\f\r ]`
+    Space,
+    /// `[A-Z]`
+    Upper,
+    /// `[0-9A-Za-z_]`
+    Word,
+    /// `[0-9A-Fa-f]`
+    Xdigit,
+}
+
+impl ClassAsciiKind {
+    /// Return the corresponding ClassAsciiKind variant for the given name.
+    ///
+    /// The name given should correspond to the lowercase version of the
+    /// variant name. e.g., `cntrl` is the name for `ClassAsciiKind::Cntrl`.
+    ///
+    /// If no variant with the corresponding name exists, then `None` is
+    /// returned.
+    pub fn from_name(name: &str) -> Option<ClassAsciiKind> {
+        use self::ClassAsciiKind::*;
+        match name {
+            "alnum" => Some(Alnum),
+            "alpha" => Some(Alpha),
+            "ascii" => Some(Ascii),
+            "blank" => Some(Blank),
+            "cntrl" => Some(Cntrl),
+            "digit" => Some(Digit),
+            "graph" => Some(Graph),
+            "lower" => Some(Lower),
+            "print" => Some(Print),
+            "punct" => Some(Punct),
+            "space" => Some(Space),
+            "upper" => Some(Upper),
+            "word" => Some(Word),
+            "xdigit" => Some(Xdigit),
+            _ => None,
+        }
+    }
+}
+
+/// A Unicode character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassUnicode {
+    /// The span of this class.
+    pub span: Span,
+    /// Whether this class is negated or not.
+    ///
+    /// Note: be careful when using this attribute. This specifically refers
+    /// to whether the class is written as `\p` or `\P`, where the latter
+    /// is `negated = true`. However, it also possible to write something like
+    /// `\P{scx!=Katakana}` which is actually equivalent to
+    /// `\p{scx=Katakana}` and is therefore not actually negated even though
+    /// `negated = true` here. To test whether this class is truly negated
+    /// or not, use the `is_negated` method.
+    pub negated: bool,
+    /// The kind of Unicode class.
+    pub kind: ClassUnicodeKind,
+}
+
+impl ClassUnicode {
+    /// Returns true if this class has been negated.
+    ///
+    /// Note that this takes the Unicode op into account, if it's present.
+    /// e.g., `is_negated` for `\P{scx!=Katakana}` will return `false`.
+    pub fn is_negated(&self) -> bool {
+        match self.kind {
+            ClassUnicodeKind::NamedValue {
+                op: ClassUnicodeOpKind::NotEqual, ..
+            } => !self.negated,
+            _ => self.negated,
+        }
+    }
+}
+
+/// The available forms of Unicode character classes.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassUnicodeKind {
+    /// A one letter abbreviated class, e.g., `\pN`.
+    OneLetter(char),
+    /// A binary property, general category or script. The string may be
+    /// empty.
+    Named(String),
+    /// A property name and an associated value.
+    NamedValue {
+        /// The type of Unicode op used to associate `name` with `value`.
+        op: ClassUnicodeOpKind,
+        /// The property name (which may be empty).
+        name: String,
+        /// The property value (which may be empty).
+        value: String,
+    },
+}
+
+/// The type of op used in a Unicode character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassUnicodeOpKind {
+    /// A property set to a specific value, e.g., `\p{scx=Katakana}`.
+    Equal,
+    /// A property set to a specific value using a colon, e.g.,
+    /// `\p{scx:Katakana}`.
+    Colon,
+    /// A property that isn't a particular value, e.g., `\p{scx!=Katakana}`.
+    NotEqual,
+}
+
+impl ClassUnicodeOpKind {
+    /// Whether the op is an equality op or not.
+    pub fn is_equal(&self) -> bool {
+        match *self {
+            ClassUnicodeOpKind::Equal|ClassUnicodeOpKind::Colon => true,
+            _ => false,
+        }
+    }
+}
+
+/// A bracketed character class, e.g., `[a-z0-9]`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassBracketed {
+    /// The span of this class.
+    pub span: Span,
+    /// Whether this class is negated or not. e.g., `[a]` is not negated but
+    /// `[^a]` is.
+    pub negated: bool,
+    /// The type of this set. A set is either a normal union of things, e.g.,
+    /// `[abc]` or a result of applying set operations, e.g., `[\pL--c]`.
+    pub kind: ClassSet,
+}
+
+/// A character class set.
+///
+/// This type corresponds to the internal structure of a bracketed character
+/// class. That is, every bracketed character is one of two types: a union of
+/// items (literals, ranges, other bracketed classes) or a tree of binary set
+/// operations.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassSet {
+    /// An item, which can be a single literal, range, nested character class
+    /// or a union of items.
+    Item(ClassSetItem),
+    /// A single binary operation (i.e., &&, -- or ~~).
+    BinaryOp(ClassSetBinaryOp),
+}
+
+impl ClassSet {
+    /// Build a set from a union.
+    pub fn union(ast: ClassSetUnion) -> ClassSet {
+        ClassSet::Item(ClassSetItem::Union(ast))
+    }
+
+    /// Return the span of this character class set.
+    pub fn span(&self) -> &Span {
+        match *self {
+            ClassSet::Item(ref x) => x.span(),
+            ClassSet::BinaryOp(ref x) => &x.span,
+        }
+    }
+
+    /// Return true if and only if this class set is empty.
+    fn is_empty(&self) -> bool {
+        match *self {
+            ClassSet::Item(ClassSetItem::Empty(_)) => true,
+            _ => false,
+        }
+    }
+}
+
+/// A single component of a character class set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ClassSetItem {
+    /// An empty item.
+    ///
+    /// Note that a bracketed character class cannot contain a single empty
+    /// item. Empty items can appear when using one of the binary operators.
+    /// For example, `[&&]` is the intersection of two empty classes.
+    Empty(Span),
+    /// A single literal.
+    Literal(Literal),
+    /// A range between two literals.
+    Range(ClassSetRange),
+    /// An ASCII character class, e.g., `[:alnum:]` or `[:punct:]`.
+    Ascii(ClassAscii),
+    /// A Unicode character class, e.g., `\pL` or `\p{Greek}`.
+    Unicode(ClassUnicode),
+    /// A perl character class, e.g., `\d` or `\W`.
+    Perl(ClassPerl),
+    /// A bracketed character class set, which may contain zero or more
+    /// character ranges and/or zero or more nested classes. e.g.,
+    /// `[a-zA-Z\pL]`.
+    Bracketed(Box<ClassBracketed>),
+    /// A union of items.
+    Union(ClassSetUnion),
+}
+
+impl ClassSetItem {
+    /// Return the span of this character class set item.
+    pub fn span(&self) -> &Span {
+        match *self {
+            ClassSetItem::Empty(ref span) => span,
+            ClassSetItem::Literal(ref x) => &x.span,
+            ClassSetItem::Range(ref x) => &x.span,
+            ClassSetItem::Ascii(ref x) => &x.span,
+            ClassSetItem::Perl(ref x) => &x.span,
+            ClassSetItem::Unicode(ref x) => &x.span,
+            ClassSetItem::Bracketed(ref x) => &x.span,
+            ClassSetItem::Union(ref x) => &x.span,
+        }
+    }
+}
+
+/// A single character class range in a set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetRange {
+    /// The span of this range.
+    pub span: Span,
+    /// The start of this range.
+    pub start: Literal,
+    /// The end of this range.
+    pub end: Literal,
+}
+
+impl ClassSetRange {
+    /// Returns true if and only if this character class range is valid.
+    ///
+    /// The only case where a range is invalid is if its start is greater than
+    /// its end.
+    pub fn is_valid(&self) -> bool {
+        self.start.c <= self.end.c
+    }
+}
+
+/// A union of items inside a character class set.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetUnion {
+    /// The span of the items in this operation. e.g., the `a-z0-9` in
+    /// `[^a-z0-9]`
+    pub span: Span,
+    /// The sequence of items that make up this union.
+    pub items: Vec<ClassSetItem>,
+}
+
+impl ClassSetUnion {
+    /// Push a new item in this union.
+    ///
+    /// The ending position of this union's span is updated to the ending
+    /// position of the span of the item given. If the union is empty, then
+    /// the starting position of this union is set to the starting position
+    /// of this item.
+    ///
+    /// In other words, if you only use this method to add items to a union
+    /// and you set the spans on each item correctly, then you should never
+    /// need to adjust the span of the union directly.
+    pub fn push(&mut self, item: ClassSetItem) {
+        if self.items.is_empty() {
+            self.span.start = item.span().start;
+        }
+        self.span.end = item.span().end;
+        self.items.push(item);
+    }
+
+    /// Return this union as a character class set item.
+    ///
+    /// If this union contains zero items, then an empty union is
+    /// returned. If this concatenation contains exactly 1 item, then the
+    /// corresponding item is returned. Otherwise, ClassSetItem::Union is
+    /// returned.
+    pub fn into_item(mut self) -> ClassSetItem {
+        match self.items.len() {
+            0 => ClassSetItem::Empty(self.span),
+            1 => self.items.pop().unwrap(),
+            _ => ClassSetItem::Union(self),
+        }
+    }
+}
+
+/// A Unicode character class set operation.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassSetBinaryOp {
+    /// The span of this operation. e.g., the `a-z--[h-p]` in `[a-z--h-p]`.
+    pub span: Span,
+    /// The type of this set operation.
+    pub kind: ClassSetBinaryOpKind,
+    /// The left hand side of the operation.
+    pub lhs: Box<ClassSet>,
+    /// The right hand side of the operation.
+    pub rhs: Box<ClassSet>,
+}
+
+/// The type of a Unicode character class set operation.
+///
+/// Note that this doesn't explicitly represent union since there is no
+/// explicit union operator. Concatenation inside a character class corresponds
+/// to the union operation.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ClassSetBinaryOpKind {
+    /// The intersection of two sets, e.g., `\pN&&[a-z]`.
+    Intersection,
+    /// The difference of two sets, e.g., `\pN--[0-9]`.
+    Difference,
+    /// The symmetric difference of two sets. The symmetric difference is the
+    /// set of elements belonging to one but not both sets.
+    /// e.g., `[\pL~~[:ascii:]]`.
+    SymmetricDifference,
+}
+
+/// A single zero-width assertion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Assertion {
+    /// The span of this assertion.
+    pub span: Span,
+    /// The assertion kind, e.g., `\b` or `^`.
+    pub kind: AssertionKind,
+}
+
+/// An assertion kind.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum AssertionKind {
+    /// `^`
+    StartLine,
+    /// `$`
+    EndLine,
+    /// `\A`
+    StartText,
+    /// `\z`
+    EndText,
+    /// `\b`
+    WordBoundary,
+    /// `\B`
+    NotWordBoundary,
+}
+
+/// A repetition operation applied to a regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Repetition {
+    /// The span of this operation.
+    pub span: Span,
+    /// The actual operation.
+    pub op: RepetitionOp,
+    /// Whether this operation was applied greedily or not.
+    pub greedy: bool,
+    /// The regular expression under repetition.
+    pub ast: Box<Ast>,
+}
+
+/// The repetition operator itself.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct RepetitionOp {
+    /// The span of this operator. This includes things like `+`, `*?` and
+    /// `{m,n}`.
+    pub span: Span,
+    /// The type of operation.
+    pub kind: RepetitionKind,
+}
+
+/// The kind of a repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionKind {
+    /// `?`
+    ZeroOrOne,
+    /// `*`
+    ZeroOrMore,
+    /// `+`
+    OneOrMore,
+    /// `{m,n}`
+    Range(RepetitionRange),
+}
+
+/// A range repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionRange {
+    /// `{m}`
+    Exactly(u32),
+    /// `{m,}`
+    AtLeast(u32),
+    /// `{m,n}`
+    Bounded(u32, u32),
+}
+
+impl RepetitionRange {
+    /// Returns true if and only if this repetition range is valid.
+    ///
+    /// The only case where a repetition range is invalid is if it is bounded
+    /// and its start is greater than its end.
+    pub fn is_valid(&self) -> bool {
+        match *self {
+            RepetitionRange::Bounded(s, e) if s > e => false,
+            _ => true,
+        }
+    }
+}
+
+/// A grouped regular expression.
+///
+/// This includes both capturing and non-capturing groups. This does **not**
+/// include flag-only groups like `(?is)`, but does contain any group that
+/// contains a sub-expression, e.g., `(a)`, `(?P<name>a)`, `(?:a)` and
+/// `(?is:a)`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Group {
+    /// The span of this group.
+    pub span: Span,
+    /// The kind of this group.
+    pub kind: GroupKind,
+    /// The regular expression in this group.
+    pub ast: Box<Ast>,
+}
+
+impl Group {
+    /// If this group is non-capturing, then this returns the (possibly empty)
+    /// set of flags. Otherwise, `None` is returned.
+    pub fn flags(&self) -> Option<&Flags> {
+        match self.kind {
+            GroupKind::NonCapturing(ref flags) => Some(flags),
+            _ => None,
+        }
+    }
+
+    /// Returns true if and only if this group is capturing.
+    pub fn is_capturing(&self) -> bool {
+        match self.kind {
+            GroupKind::CaptureIndex(_) | GroupKind::CaptureName(_) => true,
+            GroupKind::NonCapturing(_) => false,
+        }
+    }
+
+    /// Returns the capture index of this group, if this is a capturing group.
+    ///
+    /// This returns a capture index precisely when `is_capturing` is `true`.
+    pub fn capture_index(&self) -> Option<u32> {
+        match self.kind {
+            GroupKind::CaptureIndex(i) => Some(i),
+            GroupKind::CaptureName(ref x) => Some(x.index),
+            GroupKind::NonCapturing(_) => None,
+        }
+    }
+}
+
+/// The kind of a group.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum GroupKind {
+    /// `(a)`
+    CaptureIndex(u32),
+    /// `(?P<name>a)`
+    CaptureName(CaptureName),
+    /// `(?:a)` and `(?i:a)`
+    NonCapturing(Flags),
+}
+
+/// A capture name.
+///
+/// This corresponds to the name itself between the angle brackets in, e.g.,
+/// `(?P<foo>expr)`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct CaptureName {
+    /// The span of this capture name.
+    pub span: Span,
+    /// The capture name.
+    pub name: String,
+    /// The capture index.
+    pub index: u32,
+}
+
+/// A group of flags that is not applied to a particular regular expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct SetFlags {
+    /// The span of these flags, including the grouping parentheses.
+    pub span: Span,
+    /// The actual sequence of flags.
+    pub flags: Flags,
+}
+
+/// A group of flags.
+///
+/// This corresponds only to the sequence of flags themselves, e.g., `is-u`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Flags {
+    /// The span of this group of flags.
+    pub span: Span,
+    /// A sequence of flag items. Each item is either a flag or a negation
+    /// operator.
+    pub items: Vec<FlagsItem>,
+}
+
+impl Flags {
+    /// Add the given item to this sequence of flags.
+    ///
+    /// If the item was added successfully, then `None` is returned. If the
+    /// given item is a duplicate, then `Some(i)` is returned, where
+    /// `items[i].kind == item.kind`.
+    pub fn add_item(&mut self, item: FlagsItem) -> Option<usize> {
+        for (i, x) in self.items.iter().enumerate() {
+            if x.kind == item.kind {
+                return Some(i);
+            }
+        }
+        self.items.push(item);
+        None
+    }
+
+    /// Returns the state of the given flag in this set.
+    ///
+    /// If the given flag is in the set but is negated, then `Some(false)` is
+    /// returned.
+    ///
+    /// If the given flag is in the set and is not negated, then `Some(true)`
+    /// is returned.
+    ///
+    /// Otherwise, `None` is returned.
+    pub fn flag_state(&self, flag: Flag) -> Option<bool> {
+        let mut negated = false;
+        for x in &self.items {
+            match x.kind {
+                FlagsItemKind::Negation => {
+                    negated = true;
+                }
+                FlagsItemKind::Flag(ref xflag) if xflag == &flag => {
+                    return Some(!negated);
+                }
+                _ => {}
+            }
+        }
+        None
+    }
+}
+
+/// A single item in a group of flags.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct FlagsItem {
+    /// The span of this item.
+    pub span: Span,
+    /// The kind of this item.
+    pub kind: FlagsItemKind,
+}
+
+/// The kind of an item in a group of flags.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum FlagsItemKind {
+    /// A negation operator applied to all subsequent flags in the enclosing
+    /// group.
+    Negation,
+    /// A single flag in a group.
+    Flag(Flag),
+}
+
+impl FlagsItemKind {
+    /// Returns true if and only if this item is a negation operator.
+    pub fn is_negation(&self) -> bool {
+        match *self {
+            FlagsItemKind::Negation => true,
+            _ => false,
+        }
+    }
+}
+
+/// A single flag.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Flag {
+    /// `i`
+    CaseInsensitive,
+    /// `m`
+    MultiLine,
+    /// `s`
+    DotMatchesNewLine,
+    /// `U`
+    SwapGreed,
+    /// `u`
+    Unicode,
+    /// `x`
+    IgnoreWhitespace,
+}
+
+/// A custom `Drop` impl is used for `Ast` such that it uses constant stack
+/// space but heap space proportional to the depth of the `Ast`.
+impl Drop for Ast {
+    fn drop(&mut self) {
+        use std::mem;
+
+        match *self {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            // Classes are recursive, so they get their own Drop impl.
+            | Ast::Class(_) => return,
+            Ast::Repetition(ref x) if !x.ast.has_subexprs() => return,
+            Ast::Group(ref x) if !x.ast.has_subexprs() => return,
+            Ast::Alternation(ref x) if x.asts.is_empty() => return,
+            Ast::Concat(ref x) if x.asts.is_empty() => return,
+            _ => {}
+        }
+
+        let empty_span = || Span::splat(Position::new(0, 0, 0));
+        let empty_ast = || Ast::Empty(empty_span());
+        let mut stack = vec![mem::replace(self, empty_ast())];
+        while let Some(mut ast) = stack.pop() {
+            match ast {
+                Ast::Empty(_)
+                | Ast::Flags(_)
+                | Ast::Literal(_)
+                | Ast::Dot(_)
+                | Ast::Assertion(_)
+                // Classes are recursive, so they get their own Drop impl.
+                | Ast::Class(_) => {}
+                Ast::Repetition(ref mut x) => {
+                    stack.push(mem::replace(&mut x.ast, empty_ast()));
+                }
+                Ast::Group(ref mut x) => {
+                    stack.push(mem::replace(&mut x.ast, empty_ast()));
+                }
+                Ast::Alternation(ref mut x) => {
+                    stack.extend(x.asts.drain(..));
+                }
+                Ast::Concat(ref mut x) => {
+                    stack.extend(x.asts.drain(..));
+                }
+            }
+        }
+    }
+}
+
+/// A custom `Drop` impl is used for `ClassSet` such that it uses constant
+/// stack space but heap space proportional to the depth of the `ClassSet`.
+impl Drop for ClassSet {
+    fn drop(&mut self) {
+        use std::mem;
+
+        match *self {
+            ClassSet::Item(ref item) => {
+                match *item {
+                    ClassSetItem::Empty(_)
+                    | ClassSetItem::Literal(_)
+                    | ClassSetItem::Range(_)
+                    | ClassSetItem::Ascii(_)
+                    | ClassSetItem::Unicode(_)
+                    | ClassSetItem::Perl(_) => return,
+                    ClassSetItem::Bracketed(ref x) => {
+                        if x.kind.is_empty() {
+                            return;
+                        }
+                    }
+                    ClassSetItem::Union(ref x) => {
+                        if x.items.is_empty() {
+                            return;
+                        }
+                    }
+                }
+            }
+            ClassSet::BinaryOp(ref op) => {
+                if op.lhs.is_empty() && op.rhs.is_empty() {
+                    return;
+                }
+            }
+        }
+
+        let empty_span = || Span::splat(Position::new(0, 0, 0));
+        let empty_set = || ClassSet::Item(ClassSetItem::Empty(empty_span()));
+        let mut stack = vec![mem::replace(self, empty_set())];
+        while let Some(mut set) = stack.pop() {
+            match set {
+                ClassSet::Item(ref mut item) => {
+                    match *item {
+                        ClassSetItem::Empty(_)
+                        | ClassSetItem::Literal(_)
+                        | ClassSetItem::Range(_)
+                        | ClassSetItem::Ascii(_)
+                        | ClassSetItem::Unicode(_)
+                        | ClassSetItem::Perl(_) => {}
+                        ClassSetItem::Bracketed(ref mut x) => {
+                            stack.push(mem::replace(&mut x.kind, empty_set()));
+                        }
+                        ClassSetItem::Union(ref mut x) => {
+                            stack.extend(
+                                x.items.drain(..).map(ClassSet::Item));
+                        }
+                    }
+                }
+                ClassSet::BinaryOp(ref mut op) => {
+                    stack.push(mem::replace(&mut op.lhs, empty_set()));
+                    stack.push(mem::replace(&mut op.rhs, empty_set()));
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    // We use a thread with an explicit stack size to test that our destructor
+    // for Ast can handle arbitrarily sized expressions in constant stack
+    // space. In case we run on a platform without threads (WASM?), we limit
+    // this test to Windows/Unix.
+    #[test]
+    #[cfg(any(unix, windows))]
+    fn no_stack_overflow_on_drop() {
+        use std::thread;
+
+        let run = || {
+            let span = || Span::splat(Position::new(0, 0, 0));
+            let mut ast = Ast::Empty(span());
+            for i in 0..200 {
+                ast = Ast::Group(Group {
+                    span: span(),
+                    kind: GroupKind::CaptureIndex(i),
+                    ast: Box::new(ast),
+                });
+            }
+            assert!(!ast.is_empty());
+        };
+
+        // We run our test on a thread with a small stack size so we can
+        // force the issue more easily.
+        thread::Builder::new()
+            .stack_size(1<<10)
+            .spawn(run)
+            .unwrap()
+            .join()
+            .unwrap();
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/ast/parse.rs b/third_party/rust/regex-syntax/src/ast/parse.rs
new file mode 100644
index 000000000000..b73baee7353d
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/ast/parse.rs
@@ -0,0 +1,5365 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This module provides a regular expression parser.
+*/
+
+use std::borrow::Borrow;
+use std::cell::{Cell, RefCell};
+use std::mem;
+use std::result;
+
+use ast::{self, Ast, Position, Span};
+use either::Either;
+
+use is_meta_character;
+
+type Result<T> = result::Result<T, ast::Error>;
+
+/// A primitive is an expression with no sub-expressions. This includes
+/// literals, assertions and non-set character classes. This representation
+/// is used as intermediate state in the parser.
+///
+/// This does not include ASCII character classes, since they can only appear
+/// within a set character class.
+#[derive(Clone, Debug, Eq, PartialEq)]
+enum Primitive {
+    Literal(ast::Literal),
+    Assertion(ast::Assertion),
+    Dot(Span),
+    Perl(ast::ClassPerl),
+    Unicode(ast::ClassUnicode),
+}
+
+impl Primitive {
+    /// Return the span of this primitive.
+    fn span(&self) -> &Span {
+        match *self {
+            Primitive::Literal(ref x) => &x.span,
+            Primitive::Assertion(ref x) => &x.span,
+            Primitive::Dot(ref span) => span,
+            Primitive::Perl(ref x) => &x.span,
+            Primitive::Unicode(ref x) => &x.span,
+        }
+    }
+
+    /// Convert this primitive into a proper AST.
+    fn into_ast(self) -> Ast {
+        match self {
+            Primitive::Literal(lit) => Ast::Literal(lit),
+            Primitive::Assertion(assert) => Ast::Assertion(assert),
+            Primitive::Dot(span) => Ast::Dot(span),
+            Primitive::Perl(cls) => Ast::Class(ast::Class::Perl(cls)),
+            Primitive::Unicode(cls) => Ast::Class(ast::Class::Unicode(cls)),
+        }
+    }
+
+    /// Convert this primitive into an item in a character class.
+    ///
+    /// If this primitive is not a legal item (i.e., an assertion or a dot),
+    /// then return an error.
+    fn into_class_set_item<P: Borrow<Parser>>(
+        self,
+        p: &ParserI<P>,
+    ) -> Result<ast::ClassSetItem> {
+        use ast::ClassSetItem;
+        use self::Primitive::*;
+
+        match self {
+            Literal(lit) => Ok(ClassSetItem::Literal(lit)),
+            Perl(cls) => Ok(ClassSetItem::Perl(cls)),
+            Unicode(cls) => Ok(ClassSetItem::Unicode(cls)),
+            x => Err(p.error(*x.span(), ast::ErrorKind::ClassEscapeInvalid)),
+        }
+    }
+
+    /// Convert this primitive into a literal in a character class. In
+    /// particular, literals are the only valid items that can appear in
+    /// ranges.
+    ///
+    /// If this primitive is not a legal item (i.e., a class, assertion or a
+    /// dot), then return an error.
+    fn into_class_literal<P: Borrow<Parser>>(
+        self,
+        p: &ParserI<P>,
+    ) -> Result<ast::Literal> {
+        use self::Primitive::*;
+
+        match self {
+            Literal(lit) => Ok(lit),
+            x => Err(p.error(*x.span(), ast::ErrorKind::ClassRangeLiteral)),
+        }
+    }
+}
+
+/// Returns true if the given character is a hexadecimal digit.
+fn is_hex(c: char) -> bool {
+    ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
+}
+
+/// Returns true if the given character is a valid in a capture group name.
+///
+/// If `first` is true, then `c` is treated as the first character in the
+/// group name (which is not allowed to be a digit).
+fn is_capture_char(c: char, first: bool) -> bool {
+    c == '_' || (!first && c >= '0' && c <= '9')
+    || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+/// A builder for a regular expression parser.
+///
+/// This builder permits modifying configuration options for the parser.
+#[derive(Clone, Debug)]
+pub struct ParserBuilder {
+    ignore_whitespace: bool,
+    nest_limit: u32,
+    octal: bool,
+}
+
+impl Default for ParserBuilder {
+    fn default() -> ParserBuilder {
+        ParserBuilder::new()
+    }
+}
+
+impl ParserBuilder {
+    /// Create a new parser builder with a default configuration.
+    pub fn new() -> ParserBuilder {
+        ParserBuilder {
+            ignore_whitespace: false,
+            nest_limit: 250,
+            octal: false,
+        }
+    }
+
+    /// Build a parser from this configuration with the given pattern.
+    pub fn build(&self) -> Parser {
+        Parser {
+            pos: Cell::new(Position { offset: 0, line: 1, column: 1 }),
+            capture_index: Cell::new(0),
+            nest_limit: self.nest_limit,
+            octal: self.octal,
+            initial_ignore_whitespace: self.ignore_whitespace,
+            ignore_whitespace: Cell::new(self.ignore_whitespace),
+            comments: RefCell::new(vec![]),
+            stack_group: RefCell::new(vec![]),
+            stack_class: RefCell::new(vec![]),
+            capture_names: RefCell::new(vec![]),
+            scratch: RefCell::new(String::new()),
+        }
+    }
+
+    /// Set the nesting limit for this parser.
+    ///
+    /// The nesting limit controls how deep the abstract syntax tree is allowed
+    /// to be. If the AST exceeds the given limit (e.g., with too many nested
+    /// groups), then an error is returned by the parser.
+    ///
+    /// The purpose of this limit is to act as a heuristic to prevent stack
+    /// overflow for consumers that do structural induction on an `Ast` using
+    /// explicit recursion. While this crate never does this (instead using
+    /// constant stack space and moving the call stack to the heap), other
+    /// crates may.
+    ///
+    /// This limit is not checked until the entire Ast is parsed. Therefore,
+    /// if callers want to put a limit on the amount of heap space used, then
+    /// they should impose a limit on the length, in bytes, of the concrete
+    /// pattern string. In particular, this is viable since this parser
+    /// implementation will limit itself to heap space proportional to the
+    /// lenth of the pattern string.
+    ///
+    /// Note that a nest limit of `0` will return a nest limit error for most
+    /// patterns but not all. For example, a nest limit of `0` permits `a` but
+    /// not `ab`, since `ab` requires a concatenation, which results in a nest
+    /// depth of `1`. In general, a nest limit is not something that manifests
+    /// in an obvious way in the concrete syntax, therefore, it should not be
+    /// used in a granular way.
+    pub fn nest_limit(&mut self, limit: u32) -> &mut ParserBuilder {
+        self.nest_limit = limit;
+        self
+    }
+
+    /// Whether to support octal syntax or not.
+    ///
+    /// Octal syntax is a little-known way of uttering Unicode codepoints in
+    /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+    /// `\141` are all equivalent regular expressions, where the last example
+    /// shows octal syntax.
+    ///
+    /// While supporting octal syntax isn't in and of itself a problem, it does
+    /// make good error messages harder. That is, in PCRE based regex engines,
+    /// syntax like `\0` invokes a backreference, which is explicitly
+    /// unsupported in Rust's regex engine. However, many users expect it to
+    /// be supported. Therefore, when octal support is disabled, the error
+    /// message will explicitly mention that backreferences aren't supported.
+    ///
+    /// Octal syntax is disabled by default.
+    pub fn octal(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.octal = yes;
+        self
+    }
+
+    /// Enable verbose mode in the regular expression.
+    ///
+    /// When enabled, verbose mode permits insigificant whitespace in many
+    /// places in the regular expression, as well as comments. Comments are
+    /// started using `#` and continue until the end of the line.
+    ///
+    /// By default, this is disabled. It may be selectively enabled in the
+    /// regular expression by using the `x` flag regardless of this setting.
+    pub fn ignore_whitespace(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.ignore_whitespace = yes;
+        self
+    }
+}
+
+/// A regular expression parser.
+///
+/// This parses a string representation of a regular expression into an
+/// abstract syntax tree. The size of the tree is proportional to the length
+/// of the regular expression pattern.
+///
+/// A `Parser` can be configured in more detail via a
+/// [`ParserBuilder`](struct.ParserBuilder.html).
+#[derive(Clone, Debug)]
+pub struct Parser {
+    /// The current position of the parser.
+    pos: Cell<Position>,
+    /// The current capture index.
+    capture_index: Cell<u32>,
+    /// The maximum number of open parens/brackets allowed. If the parser
+    /// exceeds this number, then an error is returned.
+    nest_limit: u32,
+    /// Whether to support octal syntax or not. When `false`, the parser will
+    /// return an error helpfully pointing out that backreferences are not
+    /// supported.
+    octal: bool,
+    /// The initial setting for `ignore_whitespace` as provided by
+    /// Th`ParserBuilder`. is is used when reseting the parser's state.
+    initial_ignore_whitespace: bool,
+    /// Whether whitespace should be ignored. When enabled, comments are
+    /// also permitted.
+    ignore_whitespace: Cell<bool>,
+    /// A list of comments, in order of appearance.
+    comments: RefCell<Vec<ast::Comment>>,
+    /// A stack of grouped sub-expressions, including alternations.
+    stack_group: RefCell<Vec<GroupState>>,
+    /// A stack of nested character classes. This is only non-empty when
+    /// parsing a class.
+    stack_class: RefCell<Vec<ClassState>>,
+    /// A sorted sequence of capture names. This is used to detect duplicate
+    /// capture names and report an error if one is detected.
+    capture_names: RefCell<Vec<ast::CaptureName>>,
+    /// A scratch buffer used in various places. Mostly this is used to
+    /// accumulate relevant characters from parts of a pattern.
+    scratch: RefCell<String>,
+}
+
+/// ParserI is the internal parser implementation.
+///
+/// We use this separate type so that we can carry the provided pattern string
+/// along with us. In particular, a `Parser` internal state is not tied to any
+/// one pattern, but `ParserI` is.
+///
+/// This type also lets us use `ParserI<&Parser>` in production code while
+/// retaining the convenience of `ParserI<Parser>` for tests, which sometimes
+/// work against the internal interface of the parser.
+#[derive(Clone, Debug)]
+struct ParserI<'s, P> {
+    /// The parser state/configuration.
+    parser: P,
+    /// The full regular expression provided by the user.
+    pattern: &'s str,
+}
+
+/// GroupState represents a single stack frame while parsing nested groups
+/// and alternations. Each frame records the state up to an opening parenthesis
+/// or a alternating bracket `|`.
+#[derive(Clone, Debug)]
+enum GroupState {
+    /// This state is pushed whenever an opening group is found.
+    Group {
+        /// The concatenation immediately preceding the opening group.
+        concat: ast::Concat,
+        /// The group that has been opened. Its sub-AST is always empty.
+        group: ast::Group,
+        /// Whether this group has the `x` flag enabled or not.
+        ignore_whitespace: bool,
+    },
+    /// This state is pushed whenever a new alternation branch is found. If
+    /// an alternation branch is found and this state is at the top of the
+    /// stack, then this state should be modified to include the new
+    /// alternation.
+    Alternation(ast::Alternation),
+}
+
+/// ClassState represents a single stack frame while parsing character classes.
+/// Each frame records the state up to an intersection, difference, symmetric
+/// difference or nested class.
+///
+/// Note that a parser's character class stack is only non-empty when parsing
+/// a character class. In all other cases, it is empty.
+#[derive(Clone, Debug)]
+enum ClassState {
+    /// This state is pushed whenever an opening bracket is found.
+    Open {
+        /// The union of class items immediately preceding this class.
+        union: ast::ClassSetUnion,
+        /// The class that has been opened. Typically this just corresponds
+        /// to the `[`, but it can also include `[^` since `^` indicates
+        /// negation of the class.
+        set: ast::ClassBracketed,
+    },
+    /// This state is pushed when a operator is seen. When popped, the stored
+    /// set becomes the left hand side of the operator.
+    Op {
+        /// The type of the operation, i.e., &&, -- or ~~.
+        kind: ast::ClassSetBinaryOpKind,
+        /// The left-hand side of the operator.
+        lhs: ast::ClassSet,
+    },
+}
+
+impl Parser {
+    /// Create a new parser with a default configuration.
+    ///
+    /// The parser can be run with either the `parse` or `parse_with_comments`
+    /// methods. The parse methods return an abstract syntax tree.
+    ///
+    /// To set configuration options on the parser, use
+    /// [`ParserBuilder`](struct.ParserBuilder.html).
+    pub fn new() -> Parser {
+        ParserBuilder::new().build()
+    }
+
+    /// Parse the regular expression into an abstract syntax tree.
+    pub fn parse(&mut self, pattern: &str) -> Result<Ast> {
+        ParserI::new(self, pattern).parse()
+    }
+
+    /// Parse the regular expression and return an abstract syntax tree with
+    /// all of the comments found in the pattern.
+    pub fn parse_with_comments(
+        &mut self,
+        pattern: &str,
+    ) -> Result<ast::WithComments> {
+        ParserI::new(self, pattern).parse_with_comments()
+    }
+
+    /// Reset the internal state of a parser.
+    ///
+    /// This is called at the beginning of every parse. This prevents the
+    /// parser from running with inconsistent state (say, if a previous
+    /// invocation returned an error and the parser is reused).
+    fn reset(&self) {
+        // These settings should be in line with the construction
+        // in `ParserBuilder::build`.
+        self.pos.set(Position { offset: 0, line: 1, column: 1});
+        self.ignore_whitespace.set(self.initial_ignore_whitespace);
+        self.comments.borrow_mut().clear();
+        self.stack_group.borrow_mut().clear();
+        self.stack_class.borrow_mut().clear();
+    }
+}
+
+impl<'s, P: Borrow<Parser>> ParserI<'s, P> {
+    /// Build an internal parser from a parser configuration and a pattern.
+    fn new(parser: P, pattern: &'s str) -> ParserI<'s, P> {
+        ParserI { parser: parser, pattern: pattern }
+    }
+
+    /// Return a reference to the parser state.
+    fn parser(&self) -> &Parser {
+        self.parser.borrow()
+    }
+
+    /// Return a reference to the pattern being parsed.
+    fn pattern(&self) -> &str {
+        self.pattern.borrow()
+    }
+
+    /// Create a new error with the given span and error type.
+    fn error(&self, span: Span, kind: ast::ErrorKind) -> ast::Error {
+        ast::Error {
+            kind: kind,
+            pattern: self.pattern().to_string(),
+            span: span,
+        }
+    }
+
+    /// Return the current offset of the parser.
+    ///
+    /// The offset starts at `0` from the beginning of the regular expression
+    /// pattern string.
+    fn offset(&self) -> usize {
+        self.parser().pos.get().offset
+    }
+
+    /// Return the current line number of the parser.
+    ///
+    /// The line number starts at `1`.
+    fn line(&self) -> usize {
+        self.parser().pos.get().line
+    }
+
+    /// Return the current column of the parser.
+    ///
+    /// The column number starts at `1` and is reset whenever a `\n` is seen.
+    fn column(&self) -> usize {
+        self.parser().pos.get().column
+    }
+
+    /// Return the next capturing index. Each subsequent call increments the
+    /// internal index.
+    ///
+    /// The span given should correspond to the location of the opening
+    /// parenthesis.
+    ///
+    /// If the capture limit is exceeded, then an error is returned.
+    fn next_capture_index(&self, span: Span) -> Result<u32> {
+        let current = self.parser().capture_index.get();
+        let i = current.checked_add(1).ok_or_else(|| {
+            self.error(span, ast::ErrorKind::CaptureLimitExceeded)
+        })?;
+        self.parser().capture_index.set(i);
+        Ok(i)
+    }
+
+    /// Adds the given capture name to this parser. If this capture name has
+    /// already been used, then an error is returned.
+    fn add_capture_name(&self, cap: &ast::CaptureName) -> Result<()> {
+        let mut names = self.parser().capture_names.borrow_mut();
+        match names.binary_search_by_key(
+            &cap.name.as_str(),
+            |c| c.name.as_str(),
+        ) {
+            Err(i) => {
+                names.insert(i, cap.clone());
+                Ok(())
+            }
+            Ok(i) => {
+                Err(self.error(cap.span, ast::ErrorKind::GroupNameDuplicate {
+                    original: names[i].span,
+                }))
+            }
+        }
+    }
+
+    /// Return whether the parser should ignore whitespace or not.
+    fn ignore_whitespace(&self) -> bool {
+        self.parser().ignore_whitespace.get()
+    }
+
+    /// Return the character at the current position of the parser.
+    ///
+    /// This panics if the current position does not point to a valid char.
+    fn char(&self) -> char {
+        self.char_at(self.offset())
+    }
+
+    /// Return the character at the given position.
+    ///
+    /// This panics if the given position does not point to a valid char.
+    fn char_at(&self, i: usize) -> char {
+        self.pattern()[i..].chars().next()
+            .unwrap_or_else(|| {
+                panic!("expected char at offset {}", i)
+            })
+    }
+
+    /// Bump the parser to the next Unicode scalar value.
+    ///
+    /// If the end of the input has been reached, then `false` is returned.
+    fn bump(&self) -> bool {
+        if self.is_eof() {
+            return false;
+        }
+        let Position { mut offset, mut line, mut column } = self.pos();
+        if self.char() == '\n' {
+            line = line.checked_add(1).unwrap();
+            column = 1;
+        } else {
+            column = column.checked_add(1).unwrap();
+        }
+        offset += self.char().len_utf8();
+        self.parser().pos.set(Position {
+            offset: offset,
+            line: line,
+            column: column,
+        });
+        self.pattern()[self.offset()..].chars().next().is_some()
+    }
+
+    /// If the substring starting at the current position of the parser has
+    /// the given prefix, then bump the parser to the character immediately
+    /// following the prefix and return true. Otherwise, don't bump the parser
+    /// and return false.
+    fn bump_if(&self, prefix: &str) -> bool {
+        if self.pattern()[self.offset()..].starts_with(prefix) {
+            for _ in 0..prefix.chars().count() {
+                self.bump();
+            }
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Returns true if and only if the parser is positioned at a look-around
+    /// prefix. The conditions under which this returns true must always
+    /// correspond to a regular expression that would otherwise be consider
+    /// invalid.
+    ///
+    /// This should only be called immediately after parsing the opening of
+    /// a group or a set of flags.
+    fn is_lookaround_prefix(&self) -> bool {
+        self.bump_if("?=")
+        || self.bump_if("?!")
+        || self.bump_if("?<=")
+        || self.bump_if("?<!")
+    }
+
+    /// Bump the parser, and if the `x` flag is enabled, bump through any
+    /// subsequent spaces. Return true if and only if the parser is not at
+    /// EOF.
+    fn bump_and_bump_space(&self) -> bool {
+        if !self.bump() {
+            return false;
+        }
+        self.bump_space();
+        !self.is_eof()
+    }
+
+    /// If the `x` flag is enabled (i.e., whitespace insensitivity with
+    /// comments), then this will advance the parser through all whitespace
+    /// and comments to the next non-whitespace non-comment byte.
+    ///
+    /// If the `x` flag is disabled, then this is a no-op.
+    ///
+    /// This should be used selectively throughout the parser where
+    /// arbitrary whitespace is permitted when the `x` flag is enabled. For
+    /// example, `{   5  , 6}` is equivalent to `{5,6}`.
+    fn bump_space(&self) {
+        if !self.ignore_whitespace() {
+            return;
+        }
+        while !self.is_eof() {
+            if self.char().is_whitespace() {
+                self.bump();
+            } else if self.char() == '#' {
+                let start = self.pos();
+                let mut comment_text = String::new();
+                self.bump();
+                while !self.is_eof() {
+                    let c = self.char();
+                    self.bump();
+                    if c == '\n' {
+                        break;
+                    }
+                    comment_text.push(c);
+                }
+                let comment = ast::Comment {
+                    span: Span::new(start, self.pos()),
+                    comment: comment_text,
+                };
+                self.parser().comments.borrow_mut().push(comment);
+            } else {
+                break;
+            }
+        }
+    }
+
+    /// Peek at the next character in the input without advancing the parser.
+    ///
+    /// If the input has been exhausted, then this returns `None`.
+    fn peek(&self) -> Option<char> {
+        if self.is_eof() {
+            return None;
+        }
+        self.pattern()[self.offset() + self.char().len_utf8()..].chars().next()
+    }
+
+    /// Like peek, but will ignore spaces when the parser is in whitespace
+    /// insensitive mode.
+    fn peek_space(&self) -> Option<char> {
+        if !self.ignore_whitespace() {
+            return self.peek();
+        }
+        if self.is_eof() {
+            return None;
+        }
+        let mut start = self.offset() + self.char().len_utf8();
+        let mut in_comment = false;
+        for (i, c) in self.pattern()[start..].char_indices() {
+            if c.is_whitespace() {
+                continue;
+            } else if !in_comment && c == '#' {
+                in_comment = true;
+            } else if in_comment && c == '\n' {
+                in_comment = false;
+            } else {
+                start += i;
+                break;
+            }
+        }
+        self.pattern()[start..].chars().next()
+    }
+
+    /// Returns true if the next call to `bump` would return false.
+    fn is_eof(&self) -> bool {
+        self.offset() == self.pattern().len()
+    }
+
+    /// Return the current position of the parser, which includes the offset,
+    /// line and column.
+    fn pos(&self) -> Position {
+        self.parser().pos.get()
+    }
+
+    /// Create a span at the current position of the parser. Both the start
+    /// and end of the span are set.
+    fn span(&self) -> Span {
+        Span::splat(self.pos())
+    }
+
+    /// Create a span that covers the current character.
+    fn span_char(&self) -> Span {
+        let mut next = Position {
+            offset: self.offset().checked_add(self.char().len_utf8()).unwrap(),
+            line: self.line(),
+            column: self.column().checked_add(1).unwrap(),
+        };
+        if self.char() == '\n' {
+            next.line += 1;
+            next.column = 1;
+        }
+        Span::new(self.pos(), next)
+    }
+
+    /// Parse and push a single alternation on to the parser's internal stack.
+    /// If the top of the stack already has an alternation, then add to that
+    /// instead of pushing a new one.
+    ///
+    /// The concatenation given corresponds to a single alternation branch.
+    /// The concatenation returned starts the next branch and is empty.
+    ///
+    /// This assumes the parser is currently positioned at `|` and will advance
+    /// the parser to the character following `|`.
+    fn push_alternate(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
+        assert_eq!(self.char(), '|');
+        concat.span.end = self.pos();
+        self.push_or_add_alternation(concat);
+        self.bump();
+        Ok(ast::Concat {
+            span: self.span(),
+            asts: vec![],
+        })
+    }
+
+    /// Pushes or adds the given branch of an alternation to the parser's
+    /// internal stack of state.
+    fn push_or_add_alternation(&self, concat: ast::Concat) {
+        use self::GroupState::*;
+
+        let mut stack = self.parser().stack_group.borrow_mut();
+        if let Some(&mut Alternation(ref mut alts)) = stack.last_mut() {
+            alts.asts.push(concat.into_ast());
+            return;
+        }
+        stack.push(Alternation(ast::Alternation {
+            span: Span::new(concat.span.start, self.pos()),
+            asts: vec![concat.into_ast()],
+        }));
+    }
+
+    /// Parse and push a group AST (and its parent concatenation) on to the
+    /// parser's internal stack. Return a fresh concatenation corresponding
+    /// to the group's sub-AST.
+    ///
+    /// If a set of flags was found (with no group), then the concatenation
+    /// is returned with that set of flags added.
+    ///
+    /// This assumes that the parser is currently positioned on the opening
+    /// parenthesis. It advances the parser to the character at the start
+    /// of the sub-expression (or adjoining expression).
+    ///
+    /// If there was a problem parsing the start of the group, then an error
+    /// is returned.
+    fn push_group(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
+        assert_eq!(self.char(), '(');
+        match self.parse_group()? {
+            Either::Left(set) => {
+                let ignore = set.flags.flag_state(ast::Flag::IgnoreWhitespace);
+                if let Some(v) = ignore {
+                    self.parser().ignore_whitespace.set(v);
+                }
+
+                concat.asts.push(Ast::Flags(set));
+                Ok(concat)
+            }
+            Either::Right(group) => {
+                let old_ignore_whitespace = self.ignore_whitespace();
+                let new_ignore_whitespace = group
+                    .flags()
+                    .and_then(|f| f.flag_state(ast::Flag::IgnoreWhitespace))
+                    .unwrap_or(old_ignore_whitespace);
+                self.parser().stack_group.borrow_mut().push(GroupState::Group {
+                    concat: concat,
+                    group: group,
+                    ignore_whitespace: old_ignore_whitespace,
+                });
+                self.parser().ignore_whitespace.set(new_ignore_whitespace);
+                Ok(ast::Concat {
+                    span: self.span(),
+                    asts: vec![],
+                })
+            }
+        }
+    }
+
+    /// Pop a group AST from the parser's internal stack and set the group's
+    /// AST to the given concatenation. Return the concatenation containing
+    /// the group.
+    ///
+    /// This assumes that the parser is currently positioned on the closing
+    /// parenthesis and advances the parser to the character following the `)`.
+    ///
+    /// If no such group could be popped, then an unopened group error is
+    /// returned.
+    fn pop_group(&self, mut group_concat: ast::Concat) -> Result<ast::Concat> {
+        use self::GroupState::*;
+
+        assert_eq!(self.char(), ')');
+        let mut stack = self.parser().stack_group.borrow_mut();
+        let (mut prior_concat, mut group, ignore_whitespace, alt) =
+            match stack.pop() {
+                Some(Group { concat, group, ignore_whitespace }) => {
+                    (concat, group, ignore_whitespace, None)
+                }
+                Some(Alternation(alt)) => {
+                    match stack.pop() {
+                        Some(Group { concat, group, ignore_whitespace }) => {
+                            (concat, group, ignore_whitespace, Some(alt))
+                        }
+                        None | Some(Alternation(_)) => {
+                            return Err(self.error(
+                                self.span_char(),
+                                ast::ErrorKind::GroupUnopened,
+                            ));
+                        }
+                    }
+                }
+                None => {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::GroupUnopened,
+                    ));
+                }
+            };
+        self.parser().ignore_whitespace.set(ignore_whitespace);
+        group_concat.span.end = self.pos();
+        self.bump();
+        group.span.end = self.pos();
+        match alt {
+            Some(mut alt) => {
+                alt.span.end = group_concat.span.end;
+                alt.asts.push(group_concat.into_ast());
+                group.ast = Box::new(alt.into_ast());
+            }
+            None => {
+                group.ast = Box::new(group_concat.into_ast());
+            }
+        }
+        prior_concat.asts.push(Ast::Group(group));
+        Ok(prior_concat)
+    }
+
+    /// Pop the last state from the parser's internal stack, if it exists, and
+    /// add the given concatenation to it. There either must be no state or a
+    /// single alternation item on the stack. Any other scenario produces an
+    /// error.
+    ///
+    /// This assumes that the parser has advanced to the end.
+    fn pop_group_end(&self, mut concat: ast::Concat) -> Result<Ast> {
+        concat.span.end = self.pos();
+        let mut stack = self.parser().stack_group.borrow_mut();
+        let ast = match stack.pop() {
+            None => Ok(concat.into_ast()),
+            Some(GroupState::Alternation(mut alt)) => {
+                alt.span.end = self.pos();
+                alt.asts.push(concat.into_ast());
+                Ok(Ast::Alternation(alt))
+            }
+            Some(GroupState::Group { group, .. }) => {
+                return Err(self.error(
+                    group.span,
+                    ast::ErrorKind::GroupUnclosed,
+                ));
+            }
+        };
+        // If we try to pop again, there should be nothing.
+        match stack.pop() {
+            None => ast,
+            Some(GroupState::Alternation(_)) => {
+                // This unreachable is unfortunate. This case can't happen
+                // because the only way we can be here is if there were two
+                // `GroupState::Alternation`s adjacent in the parser's stack,
+                // which we guarantee to never happen because we never push a
+                // `GroupState::Alternation` if one is already at the top of
+                // the stack.
+                unreachable!()
+            }
+            Some(GroupState::Group { group, .. }) => {
+                Err(self.error(group.span, ast::ErrorKind::GroupUnclosed))
+            }
+        }
+    }
+
+    /// Parse the opening of a character class and push the current class
+    /// parsing context onto the parser's stack. This assumes that the parser
+    /// is positioned at an opening `[`. The given union should correspond to
+    /// the union of set items built up before seeing the `[`.
+    ///
+    /// If there was a problem parsing the opening of the class, then an error
+    /// is returned. Otherwise, a new union of set items for the class is
+    /// returned (which may be populated with either a `]` or a `-`).
+    fn push_class_open(
+        &self,
+        parent_union: ast::ClassSetUnion,
+    ) -> Result<ast::ClassSetUnion> {
+        assert_eq!(self.char(), '[');
+
+        let (nested_set, nested_union) = self.parse_set_class_open()?;
+        self.parser().stack_class.borrow_mut().push(ClassState::Open {
+            union: parent_union,
+            set: nested_set,
+        });
+        Ok(nested_union)
+    }
+
+    /// Parse the end of a character class set and pop the character class
+    /// parser stack. The union given corresponds to the last union built
+    /// before seeing the closing `]`. The union returned corresponds to the
+    /// parent character class set with the nested class added to it.
+    ///
+    /// This assumes that the parser is positioned at a `]` and will advance
+    /// the parser to the byte immediately following the `]`.
+    ///
+    /// If the stack is empty after popping, then this returns the final
+    /// "top-level" character class AST (where a "top-level" character class
+    /// is one that is not nested inside any other character class).
+    ///
+    /// If there is no corresponding opening bracket on the parser's stack,
+    /// then an error is returned.
+    fn pop_class(
+        &self,
+        nested_union: ast::ClassSetUnion,
+    ) -> Result<Either<ast::ClassSetUnion, ast::Class>> {
+        assert_eq!(self.char(), ']');
+
+        let item = ast::ClassSet::Item(nested_union.into_item());
+        let prevset = self.pop_class_op(item);
+        let mut stack = self.parser().stack_class.borrow_mut();
+        match stack.pop() {
+            None => {
+                // We can never observe an empty stack:
+                //
+                // 1) We are guaranteed to start with a non-empty stack since
+                //    the character class parser is only initiated when it sees
+                //    a `[`.
+                // 2) If we ever observe an empty stack while popping after
+                //    seeing a `]`, then we signal the character class parser
+                //    to terminate.
+                panic!("unexpected empty character class stack")
+            },
+            Some(ClassState::Op { .. }) => {
+                // This panic is unfortunate, but this case is impossible
+                // since we already popped the Op state if one exists above.
+                // Namely, every push to the class parser stack is guarded by
+                // whether an existing Op is already on the top of the stack.
+                // If it is, the existing Op is modified. That is, the stack
+                // can never have consecutive Op states.
+                panic!("unexpected ClassState::Op")
+            }
+            Some(ClassState::Open { mut union, mut set }) => {
+                self.bump();
+                set.span.end = self.pos();
+                set.kind = prevset;
+                if stack.is_empty() {
+                    Ok(Either::Right(ast::Class::Bracketed(set)))
+                } else {
+                    union.push(ast::ClassSetItem::Bracketed(Box::new(set)));
+                    Ok(Either::Left(union))
+                }
+            }
+        }
+    }
+
+    /// Return an "unclosed class" error whose span points to the most
+    /// recently opened class.
+    ///
+    /// This should only be called while parsing a character class.
+    fn unclosed_class_error(&self) -> ast::Error {
+        for state in self.parser().stack_class.borrow().iter().rev() {
+            match *state {
+                ClassState::Open { ref set, .. } => {
+                    return self.error(set.span, ast::ErrorKind::ClassUnclosed);
+                }
+                _ => {}
+            }
+        }
+        // We are guaranteed to have a non-empty stack with at least
+        // one open bracket, so we should never get here.
+        panic!("no open character class found")
+    }
+
+    /// Push the current set of class items on to the class parser's stack as
+    /// the left hand side of the given operator.
+    ///
+    /// A fresh set union is returned, which should be used to build the right
+    /// hand side of this operator.
+    fn push_class_op(
+        &self,
+        next_kind: ast::ClassSetBinaryOpKind,
+        next_union: ast::ClassSetUnion,
+    ) -> ast::ClassSetUnion {
+
+        let item = ast::ClassSet::Item(next_union.into_item());
+        let new_lhs = self.pop_class_op(item);
+        self.parser().stack_class.borrow_mut().push(ClassState::Op {
+            kind: next_kind,
+            lhs: new_lhs,
+        });
+        ast::ClassSetUnion { span: self.span(), items: vec![] }
+    }
+
+    /// Pop a character class set from the character class parser stack. If the
+    /// top of the stack is just an item (not an operation), then return the
+    /// given set unchanged. If the top of the stack is an operation, then the
+    /// given set will be used as the rhs of the operation on the top of the
+    /// stack. In that case, the binary operation is returned as a set.
+    fn pop_class_op(&self, rhs: ast::ClassSet) -> ast::ClassSet {
+        let mut stack = self.parser().stack_class.borrow_mut();
+        let (kind, lhs) = match stack.pop() {
+            Some(ClassState::Op { kind, lhs }) => (kind, lhs),
+            Some(state @ ClassState::Open { .. }) => {
+                stack.push(state);
+                return rhs;
+            }
+            None => unreachable!(),
+        };
+        let span = Span::new(lhs.span().start, rhs.span().end);
+        ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+            span: span,
+            kind: kind,
+            lhs: Box::new(lhs),
+            rhs: Box::new(rhs),
+        })
+    }
+}
+
+impl<'s, P: Borrow<Parser>> ParserI<'s, P> {
+    /// Parse the regular expression into an abstract syntax tree.
+    fn parse(&self) -> Result<Ast> {
+        self.parse_with_comments().map(|astc| astc.ast)
+    }
+
+    /// Parse the regular expression and return an abstract syntax tree with
+    /// all of the comments found in the pattern.
+    fn parse_with_comments(&self) -> Result<ast::WithComments> {
+        assert_eq!(self.offset(), 0, "parser can only be used once");
+        self.parser().reset();
+        let mut concat = ast::Concat {
+            span: self.span(),
+            asts: vec![],
+        };
+        loop {
+            self.bump_space();
+            if self.is_eof() {
+                break;
+            }
+            match self.char() {
+                '(' => concat = self.push_group(concat)?,
+                ')' => concat = self.pop_group(concat)?,
+                '|' => concat = self.push_alternate(concat)?,
+                '[' => {
+                    let class = self.parse_set_class()?;
+                    concat.asts.push(Ast::Class(class));
+                }
+                '?' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::ZeroOrOne)?;
+                }
+                '*' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::ZeroOrMore)?;
+                }
+                '+' => {
+                    concat = self.parse_uncounted_repetition(
+                        concat, ast::RepetitionKind::OneOrMore)?;
+                }
+                '{' => {
+                    concat = self.parse_counted_repetition(concat)?;
+                }
+                _ => concat.asts.push(self.parse_primitive()?.into_ast()),
+            }
+        }
+        let ast = self.pop_group_end(concat)?;
+        NestLimiter::new(self).check(&ast)?;
+        Ok(ast::WithComments {
+            ast: ast,
+            comments: mem::replace(
+                &mut *self.parser().comments.borrow_mut(),
+                vec![],
+            ),
+        })
+    }
+
+    /// Parses an uncounted repetition operation. An uncounted repetition
+    /// operator includes ?, * and +, but does not include the {m,n} syntax.
+    /// The given `kind` should correspond to the operator observed by the
+    /// caller.
+    ///
+    /// This assumes that the paser is currently positioned at the repetition
+    /// operator and advances the parser to the first character after the
+    /// operator. (Note that the operator may include a single additional `?`,
+    /// which makes the operator ungreedy.)
+    ///
+    /// The caller should include the concatenation that is being built. The
+    /// concatenation returned includes the repetition operator applied to the
+    /// last expression in the given concatenation.
+    fn parse_uncounted_repetition(
+        &self,
+        mut concat: ast::Concat,
+        kind: ast::RepetitionKind,
+    ) -> Result<ast::Concat> {
+        assert!(
+            self.char() == '?' || self.char() == '*' || self.char() == '+');
+        let op_start = self.pos();
+        let ast = match concat.asts.pop() {
+            Some(ast) => ast,
+            None => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+        };
+        match ast {
+            Ast::Empty(_) | Ast::Flags(_) => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+            _ => {}
+        }
+        let mut greedy = true;
+        if self.bump() && self.char() == '?' {
+            greedy = false;
+            self.bump();
+        }
+        concat.asts.push(Ast::Repetition(ast::Repetition {
+            span: ast.span().with_end(self.pos()),
+            op: ast::RepetitionOp {
+                span: Span::new(op_start, self.pos()),
+                kind: kind,
+            },
+            greedy: greedy,
+            ast: Box::new(ast),
+        }));
+        Ok(concat)
+    }
+
+    /// Parses a counted repetition operation. A counted repetition operator
+    /// corresponds to the {m,n} syntax, and does not include the ?, * or +
+    /// operators.
+    ///
+    /// This assumes that the paser is currently positioned at the opening `{`
+    /// and advances the parser to the first character after the operator.
+    /// (Note that the operator may include a single additional `?`, which
+    /// makes the operator ungreedy.)
+    ///
+    /// The caller should include the concatenation that is being built. The
+    /// concatenation returned includes the repetition operator applied to the
+    /// last expression in the given concatenation.
+    fn parse_counted_repetition(
+        &self,
+        mut concat: ast::Concat,
+    ) -> Result<ast::Concat> {
+        assert!(self.char() == '{');
+        let start = self.pos();
+        let ast = match concat.asts.pop() {
+            Some(ast) => ast,
+            None => return Err(self.error(
+                self.span(),
+                ast::ErrorKind::RepetitionMissing,
+            )),
+        };
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+        let count_start = self.parse_decimal()?;
+        let mut range = ast::RepetitionRange::Exactly(count_start);
+        if self.is_eof() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+        if self.char() == ',' {
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::RepetitionCountUnclosed,
+                ));
+            }
+            if self.char() != '}' {
+                let count_end = self.parse_decimal()?;
+                range = ast::RepetitionRange::Bounded(count_start, count_end);
+            } else {
+                range = ast::RepetitionRange::AtLeast(count_start);
+            }
+        }
+        if self.is_eof() || self.char() != '}' {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::RepetitionCountUnclosed,
+            ));
+        }
+
+        let mut greedy = true;
+        if self.bump_and_bump_space() && self.char() == '?' {
+            greedy = false;
+            self.bump();
+        }
+
+        let op_span = Span::new(start, self.pos());
+        if !range.is_valid() {
+            return Err(self.error(
+                op_span,
+                ast::ErrorKind::RepetitionCountInvalid,
+            ));
+        }
+        concat.asts.push(Ast::Repetition(ast::Repetition {
+            span: ast.span().with_end(self.pos()),
+            op: ast::RepetitionOp {
+                span: op_span,
+                kind: ast::RepetitionKind::Range(range),
+            },
+            greedy: greedy,
+            ast: Box::new(ast),
+        }));
+        Ok(concat)
+    }
+
+    /// Parse a group (which contains a sub-expression) or a set of flags.
+    ///
+    /// If a group was found, then it is returned with an empty AST. If a set
+    /// of flags is found, then that set is returned.
+    ///
+    /// The parser should be positioned at the opening parenthesis.
+    ///
+    /// This advances the parser to the character before the start of the
+    /// sub-expression (in the case of a group) or to the closing parenthesis
+    /// immediately following the set of flags.
+    ///
+    /// # Errors
+    ///
+    /// If flags are given and incorrectly specified, then a corresponding
+    /// error is returned.
+    ///
+    /// If a capture name is given and it is incorrectly specified, then a
+    /// corresponding error is returned.
+    fn parse_group(&self) -> Result<Either<ast::SetFlags, ast::Group>> {
+        assert_eq!(self.char(), '(');
+        let open_span = self.span_char();
+        self.bump();
+        self.bump_space();
+        if self.is_lookaround_prefix() {
+            return Err(self.error(
+                Span::new(open_span.start, self.span().end),
+                ast::ErrorKind::UnsupportedLookAround,
+            ));
+        }
+        let inner_span = self.span();
+        if self.bump_if("?P<") {
+            let capture_index = self.next_capture_index(open_span)?;
+            let cap = self.parse_capture_name(capture_index)?;
+            Ok(Either::Right(ast::Group {
+                span: open_span,
+                kind: ast::GroupKind::CaptureName(cap),
+                ast: Box::new(Ast::Empty(self.span())),
+            }))
+        } else if self.bump_if("?") {
+            if self.is_eof() {
+                return Err(self.error(
+                    open_span,
+                    ast::ErrorKind::GroupUnclosed,
+                ));
+            }
+            let flags = self.parse_flags()?;
+            let char_end = self.char();
+            self.bump();
+            if char_end == ')' {
+                // We don't allow empty flags, e.g., `(?)`. We instead
+                // interpret it as a repetition operator missing its argument.
+                if flags.items.is_empty() {
+                    return Err(self.error(
+                        inner_span,
+                        ast::ErrorKind::RepetitionMissing,
+                    ));
+                }
+                Ok(Either::Left(ast::SetFlags {
+                    span: Span { end: self.pos(), ..open_span },
+                    flags: flags,
+                }))
+            } else {
+                assert_eq!(char_end, ':');
+                Ok(Either::Right(ast::Group {
+                    span: open_span,
+                    kind: ast::GroupKind::NonCapturing(flags),
+                    ast: Box::new(Ast::Empty(self.span())),
+                }))
+            }
+        } else {
+            let capture_index = self.next_capture_index(open_span)?;
+            Ok(Either::Right(ast::Group {
+                span: open_span,
+                kind: ast::GroupKind::CaptureIndex(capture_index),
+                ast: Box::new(Ast::Empty(self.span())),
+            }))
+        }
+    }
+
+    /// Parses a capture group name. Assumes that the parser is positioned at
+    /// the first character in the name following the opening `<` (and may
+    /// possibly be EOF). This advances the parser to the first character
+    /// following the closing `>`.
+    ///
+    /// The caller must provide the capture index of the group for this name.
+    fn parse_capture_name(
+        &self,
+        capture_index: u32,
+    ) -> Result<ast::CaptureName> {
+        if self.is_eof() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::GroupNameUnexpectedEof,
+            ));
+        }
+        let start = self.pos();
+        loop {
+            if self.char() == '>' {
+                break;
+            }
+            if !is_capture_char(self.char(), self.pos() == start) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::GroupNameInvalid,
+                ));
+            }
+            if !self.bump() {
+                break;
+            }
+        }
+        let end = self.pos();
+        if self.is_eof() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::GroupNameUnexpectedEof,
+            ));
+        }
+        assert_eq!(self.char(), '>');
+        self.bump();
+        let name = &self.pattern()[start.offset..end.offset];
+        if name.is_empty() {
+            return Err(self.error(
+                Span::new(start, start),
+                ast::ErrorKind::GroupNameEmpty,
+            ));
+        }
+        let capname = ast::CaptureName {
+            span: Span::new(start, end),
+            name: name.to_string(),
+            index: capture_index,
+        };
+        self.add_capture_name(&capname)?;
+        Ok(capname)
+    }
+
+    /// Parse a sequence of flags starting at the current character.
+    ///
+    /// This advances the parser to the character immediately following the
+    /// flags, which is guaranteed to be either `:` or `)`.
+    ///
+    /// # Errors
+    ///
+    /// If any flags are duplicated, then an error is returned.
+    ///
+    /// If the negation operator is used more than once, then an error is
+    /// returned.
+    ///
+    /// If no flags could be found or if the negation operation is not followed
+    /// by any flags, then an error is returned.
+    fn parse_flags(&self) -> Result<ast::Flags> {
+        let mut flags = ast::Flags {
+            span: self.span(),
+            items: vec![],
+        };
+        let mut last_was_negation = None;
+        while self.char() != ':' && self.char() != ')' {
+            if self.char() == '-' {
+                last_was_negation = Some(self.span_char());
+                let item = ast::FlagsItem {
+                    span: self.span_char(),
+                    kind: ast::FlagsItemKind::Negation,
+                };
+                if let Some(i) = flags.add_item(item) {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::FlagRepeatedNegation {
+                            original: flags.items[i].span,
+                        },
+                    ));
+                }
+            } else {
+                last_was_negation = None;
+                let item = ast::FlagsItem {
+                    span: self.span_char(),
+                    kind: ast::FlagsItemKind::Flag(self.parse_flag()?),
+                };
+                if let Some(i) = flags.add_item(item) {
+                    return Err(self.error(
+                        self.span_char(),
+                        ast::ErrorKind::FlagDuplicate {
+                            original: flags.items[i].span,
+                        },
+                    ));
+                }
+            }
+            if !self.bump() {
+                return Err(self.error(
+                    self.span(),
+                    ast::ErrorKind::FlagUnexpectedEof,
+                ));
+            }
+        }
+        if let Some(span) = last_was_negation {
+            return Err(self.error(span, ast::ErrorKind::FlagDanglingNegation));
+        }
+        flags.span.end = self.pos();
+        Ok(flags)
+    }
+
+    /// Parse the current character as a flag. Do not advance the parser.
+    ///
+    /// # Errors
+    ///
+    /// If the flag is not recognized, then an error is returned.
+    fn parse_flag(&self) -> Result<ast::Flag> {
+        match self.char() {
+            'i' => Ok(ast::Flag::CaseInsensitive),
+            'm' => Ok(ast::Flag::MultiLine),
+            's' => Ok(ast::Flag::DotMatchesNewLine),
+            'U' => Ok(ast::Flag::SwapGreed),
+            'u' => Ok(ast::Flag::Unicode),
+            'x' => Ok(ast::Flag::IgnoreWhitespace),
+            _ => Err(self.error(
+                self.span_char(),
+                ast::ErrorKind::FlagUnrecognized,
+            )),
+        }
+    }
+
+    /// Parse a primitive AST. e.g., A literal, non-set character class or
+    /// assertion.
+    ///
+    /// This assumes that the parser expects a primitive at the current
+    /// location. i.e., All other non-primitive cases have been handled.
+    /// For example, if the parser's position is at `|`, then `|` will be
+    /// treated as a literal (e.g., inside a character class).
+    ///
+    /// This advances the parser to the first character immediately following
+    /// the primitive.
+    fn parse_primitive(&self) -> Result<Primitive> {
+        match self.char() {
+            '\\' => self.parse_escape(),
+            '.' => {
+                let ast = Primitive::Dot(self.span_char());
+                self.bump();
+                Ok(ast)
+            }
+            '^' => {
+                let ast = Primitive::Assertion(ast::Assertion {
+                    span: self.span_char(),
+                    kind: ast::AssertionKind::StartLine,
+                });
+                self.bump();
+                Ok(ast)
+            }
+            '$' => {
+                let ast = Primitive::Assertion(ast::Assertion {
+                    span: self.span_char(),
+                    kind: ast::AssertionKind::EndLine,
+                });
+                self.bump();
+                Ok(ast)
+            }
+            c => {
+                let ast = Primitive::Literal(ast::Literal {
+                    span: self.span_char(),
+                    kind: ast::LiteralKind::Verbatim,
+                    c: c,
+                });
+                self.bump();
+                Ok(ast)
+            }
+        }
+    }
+
+    /// Parse an escape sequence as a primitive AST.
+    ///
+    /// This assumes the parser is positioned at the start of the escape
+    /// sequence, i.e., `\`. It advances the parser to the first position
+    /// immediately following the escape sequence.
+    fn parse_escape(&self) -> Result<Primitive> {
+        assert_eq!(self.char(), '\\');
+        let start = self.pos();
+        if !self.bump() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let c = self.char();
+        // Put some of the more complicated routines into helpers.
+        match c {
+            '0'...'7' => {
+                if !self.parser().octal {
+                    return Err(self.error(
+                        Span::new(start, self.span_char().end),
+                        ast::ErrorKind::UnsupportedBackreference,
+                    ));
+                }
+                let mut lit = self.parse_octal();
+                lit.span.start = start;
+                return Ok(Primitive::Literal(lit));
+            }
+            '8'...'9' if !self.parser().octal => {
+                return Err(self.error(
+                    Span::new(start, self.span_char().end),
+                    ast::ErrorKind::UnsupportedBackreference,
+                ));
+            }
+            'x' | 'u' | 'U' => {
+                let mut lit = self.parse_hex()?;
+                lit.span.start = start;
+                return Ok(Primitive::Literal(lit));
+            }
+            'p' | 'P' => {
+                let mut cls = self.parse_unicode_class()?;
+                cls.span.start = start;
+                return Ok(Primitive::Unicode(cls));
+            }
+            'd' | 's' | 'w' | 'D' | 'S' | 'W' => {
+                let mut cls = self.parse_perl_class();
+                cls.span.start = start;
+                return Ok(Primitive::Perl(cls));
+            }
+            _ => {}
+        }
+
+        // Handle all of the one letter sequences inline.
+        self.bump();
+        let span = Span::new(start, self.pos());
+        if is_meta_character(c) {
+            return Ok(Primitive::Literal(ast::Literal {
+                span: span,
+                kind: ast::LiteralKind::Punctuation,
+                c: c,
+            }));
+        }
+        let special = |kind, c| Ok(Primitive::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Special(kind),
+            c: c,
+        }));
+        match c {
+            'a' => special(ast::SpecialLiteralKind::Bell, '\x07'),
+            'f' => special(ast::SpecialLiteralKind::FormFeed, '\x0C'),
+            't' => special(ast::SpecialLiteralKind::Tab, '\t'),
+            'n' => special(ast::SpecialLiteralKind::LineFeed, '\n'),
+            'r' => special(ast::SpecialLiteralKind::CarriageReturn, '\r'),
+            'v' => special(ast::SpecialLiteralKind::VerticalTab, '\x0B'),
+            ' ' if self.ignore_whitespace() => {
+                special(ast::SpecialLiteralKind::Space, ' ')
+            }
+            'A' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::StartText,
+            })),
+            'z' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::EndText,
+            })),
+            'b' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::WordBoundary,
+            })),
+            'B' => Ok(Primitive::Assertion(ast::Assertion {
+                span: span,
+                kind: ast::AssertionKind::NotWordBoundary,
+            })),
+            _ => Err(self.error(span, ast::ErrorKind::EscapeUnrecognized)),
+        }
+    }
+
+    /// Parse an octal representation of a Unicode codepoint up to 3 digits
+    /// long. This expects the parser to be positioned at the first octal
+    /// digit and advances the parser to the first character immediately
+    /// following the octal number. This also assumes that parsing octal
+    /// escapes is enabled.
+    ///
+    /// Assuming the preconditions are met, this routine can never fail.
+    fn parse_octal(&self) -> ast::Literal {
+        use std::char;
+        use std::u32;
+
+        assert!(self.parser().octal);
+        assert!('0' <= self.char() && self.char() <= '7');
+        let start = self.pos();
+        // Parse up to two more digits.
+        while
+            self.bump() &&
+            '0' <= self.char() && self.char() <= '7' &&
+            self.pos().offset - start.offset <= 2
+        {}
+        let end = self.pos();
+        let octal = &self.pattern()[start.offset..end.offset];
+        // Parsing the octal should never fail since the above guarantees a
+        // valid number.
+        let codepoint =
+            u32::from_str_radix(octal, 8).expect("valid octal number");
+        // The max value for 3 digit octal is 0777 = 511 and [0, 511] has no
+        // invalid Unicode scalar values.
+        let c = char::from_u32(codepoint).expect("Unicode scalar value");
+        ast::Literal {
+            span: Span::new(start, end),
+            kind: ast::LiteralKind::Octal,
+            c: c,
+        }
+    }
+
+    /// Parse a hex representation of a Unicode codepoint. This handles both
+    /// hex notations, i.e., `\xFF` and `\x{FFFF}`. This expects the parser to
+    /// be positioned at the `x`, `u` or `U` prefix. The parser is advanced to
+    /// the first character immediately following the hexadecimal literal.
+    fn parse_hex(&self) -> Result<ast::Literal> {
+        assert!(self.char() == 'x'
+                || self.char() == 'u'
+                || self.char() == 'U');
+
+        let hex_kind = match self.char() {
+            'x' => ast::HexLiteralKind::X,
+            'u' => ast::HexLiteralKind::UnicodeShort,
+            _ => ast::HexLiteralKind::UnicodeLong,
+        };
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        if self.char() == '{' {
+            self.parse_hex_brace(hex_kind)
+        } else {
+            self.parse_hex_digits(hex_kind)
+        }
+    }
+
+    /// Parse an N-digit hex representation of a Unicode codepoint. This
+    /// expects the parser to be positioned at the first digit and will advance
+    /// the parser to the first character immediately following the escape
+    /// sequence.
+    ///
+    /// The number of digits given must be 2 (for `\xNN`), 4 (for `\uNNNN`)
+    /// or 8 (for `\UNNNNNNNN`).
+    fn parse_hex_digits(
+        &self,
+        kind: ast::HexLiteralKind,
+    ) -> Result<ast::Literal> {
+        use std::char;
+        use std::u32;
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let start = self.pos();
+        for i in 0..kind.digits() {
+            if i > 0 && !self.bump_and_bump_space() {
+                return Err(self.error(
+                    self.span(),
+                    ast::ErrorKind::EscapeUnexpectedEof,
+                ));
+            }
+            if !is_hex(self.char()) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::EscapeHexInvalidDigit,
+                ));
+            }
+            scratch.push(self.char());
+        }
+        // The final bump just moves the parser past the literal, which may
+        // be EOF.
+        self.bump_and_bump_space();
+        let end = self.pos();
+        let hex = scratch.as_str();
+        match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
+            None => Err(self.error(
+                Span::new(start, end),
+                ast::ErrorKind::EscapeHexInvalid,
+            )),
+            Some(c) => Ok(ast::Literal {
+                span: Span::new(start, end),
+                kind: ast::LiteralKind::HexFixed(kind),
+                c: c,
+            }),
+        }
+    }
+
+    /// Parse a hex representation of any Unicode scalar value. This expects
+    /// the parser to be positioned at the opening brace `{` and will advance
+    /// the parser to the first character following the closing brace `}`.
+    fn parse_hex_brace(
+        &self,
+        kind: ast::HexLiteralKind,
+    ) -> Result<ast::Literal> {
+        use std::char;
+        use std::u32;
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let brace_pos = self.pos();
+        let start = self.span_char().end;
+        while self.bump_and_bump_space() && self.char() != '}' {
+            if !is_hex(self.char()) {
+                return Err(self.error(
+                    self.span_char(),
+                    ast::ErrorKind::EscapeHexInvalidDigit,
+                ));
+            }
+            scratch.push(self.char());
+        }
+        if self.is_eof() {
+            return Err(self.error(
+                Span::new(brace_pos, self.pos()),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let end = self.pos();
+        let hex = scratch.as_str();
+        assert_eq!(self.char(), '}');
+        self.bump_and_bump_space();
+
+        if hex.is_empty() {
+            return Err(self.error(
+                Span::new(brace_pos, self.pos()),
+                ast::ErrorKind::EscapeHexEmpty,
+            ));
+        }
+        match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
+            None => Err(self.error(
+                Span::new(start, end),
+                ast::ErrorKind::EscapeHexInvalid,
+            )),
+            Some(c) => Ok(ast::Literal {
+                span: Span::new(start, self.pos()),
+                kind: ast::LiteralKind::HexBrace(kind),
+                c: c,
+            }),
+        }
+    }
+
+    /// Parse a decimal number into a u32 while trimming leading and trailing
+    /// whitespace.
+    ///
+    /// This expects the parser to be positioned at the first position where
+    /// a decimal digit could occur. This will advance the parser to the byte
+    /// immediately following the last contiguous decimal digit.
+    ///
+    /// If no decimal digit could be found or if there was a problem parsing
+    /// the complete set of digits into a u32, then an error is returned.
+    fn parse_decimal(&self) -> Result<u32> {
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        while !self.is_eof() && self.char().is_whitespace() {
+            self.bump();
+        }
+        let start = self.pos();
+        while !self.is_eof() && '0' <= self.char() && self.char() <= '9' {
+            scratch.push(self.char());
+            self.bump_and_bump_space();
+        }
+        let span = Span::new(start, self.pos());
+        while !self.is_eof() && self.char().is_whitespace() {
+            self.bump_and_bump_space();
+        }
+        let digits = scratch.as_str();
+        if digits.is_empty() {
+            return Err(self.error(span, ast::ErrorKind::DecimalEmpty));
+        }
+        match u32::from_str_radix(digits, 10).ok() {
+            Some(n) => Ok(n),
+            None => Err(self.error(span, ast::ErrorKind::DecimalInvalid)),
+        }
+    }
+
+    /// Parse a standard character class consisting primarily of characters or
+    /// character ranges, but can also contain nested character classes of
+    /// any type (sans `.`).
+    ///
+    /// This assumes the parser is positioned at the opening `[`. If parsing
+    /// is successful, then the parser is advanced to the position immediately
+    /// following the closing `]`.
+    fn parse_set_class(&self) -> Result<ast::Class> {
+        assert_eq!(self.char(), '[');
+
+        let mut union = ast::ClassSetUnion {
+            span: self.span(),
+            items: vec![],
+        };
+        loop {
+            self.bump_space();
+            if self.is_eof() {
+                return Err(self.unclosed_class_error());
+            }
+            match self.char() {
+                '[' => {
+                    // If we've already parsed the opening bracket, then
+                    // attempt to treat this as the beginning of an ASCII
+                    // class. If ASCII class parsing fails, then the parser
+                    // backs up to `[`.
+                    if !self.parser().stack_class.borrow().is_empty() {
+                        if let Some(cls) = self.maybe_parse_ascii_class() {
+                            union.push(ast::ClassSetItem::Ascii(cls));
+                            continue;
+                        }
+                    }
+                    union = self.push_class_open(union)?;
+                }
+                ']' => {
+                    match self.pop_class(union)? {
+                        Either::Left(nested_union) => { union = nested_union; }
+                        Either::Right(class) => return Ok(class),
+                    }
+                }
+                '&' if self.peek() == Some('&') => {
+                    assert!(self.bump_if("&&"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::Intersection, union);
+                }
+                '-' if self.peek() == Some('-') => {
+                    assert!(self.bump_if("--"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::Difference, union);
+                }
+                '~' if self.peek() == Some('~') => {
+                    assert!(self.bump_if("~~"));
+                    union = self.push_class_op(
+                        ast::ClassSetBinaryOpKind::SymmetricDifference, union);
+                }
+                _ => {
+                    union.push(self.parse_set_class_range()?);
+                }
+            }
+        }
+    }
+
+    /// Parse a single primitive item in a character class set. The item to
+    /// be parsed can either be one of a simple literal character, a range
+    /// between two simple literal characters or a "primitive" character
+    /// class like \w or \p{Greek}.
+    ///
+    /// If an invalid escape is found, or if a character class is found where
+    /// a simple literal is expected (e.g., in a range), then an error is
+    /// returned.
+    fn parse_set_class_range(&self) -> Result<ast::ClassSetItem> {
+        let prim1 = self.parse_set_class_item()?;
+        self.bump_space();
+        if self.is_eof() {
+            return Err(self.unclosed_class_error());
+        }
+        // If the next char isn't a `-`, then we don't have a range.
+        // There are two exceptions. If the char after a `-` is a `]`, then
+        // `-` is interpreted as a literal `-`. Alternatively, if the char
+        // after a `-` is a `-`, then `--` corresponds to a "difference"
+        // operation.
+        if self.char() != '-'
+            || self.peek_space() == Some(']')
+            || self.peek_space() == Some('-')
+        {
+            return prim1.into_class_set_item(self);
+        }
+        // OK, now we're parsing a range, so bump past the `-` and parse the
+        // second half of the range.
+        if !self.bump_and_bump_space() {
+            return Err(self.unclosed_class_error());
+        }
+        let prim2 = self.parse_set_class_item()?;
+        let range = ast::ClassSetRange {
+            span: Span::new(prim1.span().start, prim2.span().end),
+            start: prim1.into_class_literal(self)?,
+            end: prim2.into_class_literal(self)?,
+        };
+        if !range.is_valid() {
+            return Err(self.error(
+                range.span,
+                ast::ErrorKind::ClassRangeInvalid,
+            ));
+        }
+        Ok(ast::ClassSetItem::Range(range))
+    }
+
+    /// Parse a single item in a character class as a primitive, where the
+    /// primitive either consists of a verbatim literal or a single escape
+    /// sequence.
+    ///
+    /// This assumes the parser is positioned at the beginning of a primitive,
+    /// and advances the parser to the first position after the primitive if
+    /// successful.
+    ///
+    /// Note that it is the caller's responsibility to report an error if an
+    /// illegal primitive was parsed.
+    fn parse_set_class_item(&self) -> Result<Primitive> {
+        if self.char() == '\\' {
+            self.parse_escape()
+        } else {
+            let x = Primitive::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: self.char(),
+            });
+            self.bump();
+            Ok(x)
+        }
+    }
+
+    /// Parses the opening of a character class set. This includes the opening
+    /// bracket along with `^` if present to indicate negation. This also
+    /// starts parsing the opening set of unioned items if applicable, since
+    /// there are special rules applied to certain characters in the opening
+    /// of a character class. For example, `[^]]` is the class of all
+    /// characters not equal to `]`. (`]` would need to be escaped in any other
+    /// position.) Similarly for `-`.
+    ///
+    /// In all cases, the op inside the returned `ast::ClassBracketed` is an
+    /// empty union. This empty union should be replaced with the actual item
+    /// when it is popped from the parser's stack.
+    ///
+    /// This assumes the parser is positioned at the opening `[` and advances
+    /// the parser to the first non-special byte of the character class.
+    ///
+    /// An error is returned if EOF is found.
+    fn parse_set_class_open(
+        &self,
+    ) -> Result<(ast::ClassBracketed, ast::ClassSetUnion)> {
+        assert_eq!(self.char(), '[');
+        let start = self.pos();
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                Span::new(start, self.pos()),
+                ast::ErrorKind::ClassUnclosed,
+            ));
+        }
+
+        let negated =
+            if self.char() != '^' {
+                false
+            } else {
+                if !self.bump_and_bump_space() {
+                    return Err(self.error(
+                        Span::new(start, self.pos()),
+                        ast::ErrorKind::ClassUnclosed,
+                    ));
+                }
+                true
+            };
+        // Accept any number of `-` as literal `-`.
+        let mut union = ast::ClassSetUnion {
+            span: self.span(),
+            items: vec![],
+        };
+        while self.char() == '-' {
+            union.push(ast::ClassSetItem::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: '-',
+            }));
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::ClassUnclosed,
+                ));
+            }
+        }
+        // If `]` is the *first* char in a set, then interpret it as a literal
+        // `]`. That is, an empty class is impossible to write.
+        if union.items.is_empty() && self.char() == ']' {
+            union.push(ast::ClassSetItem::Literal(ast::Literal {
+                span: self.span_char(),
+                kind: ast::LiteralKind::Verbatim,
+                c: ']',
+            }));
+            if !self.bump_and_bump_space() {
+                return Err(self.error(
+                    Span::new(start, self.pos()),
+                    ast::ErrorKind::ClassUnclosed,
+                ));
+            }
+        }
+        let set = ast::ClassBracketed {
+            span: Span::new(start, self.pos()),
+            negated: negated,
+            kind: ast::ClassSet::union(ast::ClassSetUnion {
+                span: Span::new(union.span.start, union.span.start),
+                items: vec![],
+            }),
+        };
+        Ok((set, union))
+    }
+
+    /// Attempt to parse an ASCII character class, e.g., `[:alnum:]`.
+    ///
+    /// This assumes the parser is positioned at the opening `[`.
+    ///
+    /// If no valid ASCII character class could be found, then this does not
+    /// advance the parser and `None` is returned. Otherwise, the parser is
+    /// advanced to the first byte following the closing `]` and the
+    /// corresponding ASCII class is returned.
+    fn maybe_parse_ascii_class(&self) -> Option<ast::ClassAscii> {
+        // ASCII character classes are interesting from a parsing perspective
+        // because parsing cannot fail with any interesting error. For example,
+        // in order to use an ASCII character class, it must be enclosed in
+        // double brackets, e.g., `[[:alnum:]]`. Alternatively, you might think
+        // of it as "ASCII character characters have the syntax `[:NAME:]`
+        // which can only appear within character brackets." This means that
+        // things like `[[:lower:]A]` are legal constructs.
+        //
+        // However, if one types an incorrect ASCII character class, e.g.,
+        // `[[:loower:]]`, then we treat that as a normal nested character
+        // class containing the characters `:elorw`. One might argue that we
+        // should return an error instead since the repeated colons give away
+        // the intent to write an ASCII class. But what if the user typed
+        // `[[:lower]]` instead? How can we tell that was intended to be an
+        // ASCII class and not just a normal nested class?
+        //
+        // Reasonable people can probably disagree over this, but for better
+        // or worse, we implement semantics that never fails at the expense
+        // of better failure modes.
+        assert_eq!(self.char(), '[');
+        // If parsing fails, then we back up the parser to this starting point.
+        let start = self.pos();
+        let mut negated = false;
+        if !self.bump() || self.char() != ':' {
+            self.parser().pos.set(start);
+            return None;
+        }
+        if !self.bump() {
+            self.parser().pos.set(start);
+            return None;
+        }
+        if self.char() == '^' {
+            negated = true;
+            if !self.bump() {
+                self.parser().pos.set(start);
+                return None;
+            }
+        }
+        let name_start = self.offset();
+        while self.char() != ':' && self.bump() {}
+        if self.is_eof() {
+            self.parser().pos.set(start);
+            return None;
+        }
+        let name = &self.pattern()[name_start..self.offset()];
+        if !self.bump_if(":]") {
+            self.parser().pos.set(start);
+            return None;
+        }
+        let kind = match ast::ClassAsciiKind::from_name(name) {
+            Some(kind) => kind,
+            None => {
+                self.parser().pos.set(start);
+                return None;
+            }
+        };
+        Some(ast::ClassAscii {
+            span: Span::new(start, self.pos()),
+            kind: kind,
+            negated: negated,
+        })
+    }
+
+    /// Parse a Unicode class in either the single character notation, `\pN`
+    /// or the multi-character bracketed notation, `\p{Greek}`. This assumes
+    /// the parser is positioned at the `p` (or `P` for negation) and will
+    /// advance the parser to the character immediately following the class.
+    ///
+    /// Note that this does not check whether the class name is valid or not.
+    fn parse_unicode_class(&self) -> Result<ast::ClassUnicode> {
+        assert!(self.char() == 'p' || self.char() == 'P');
+
+        let mut scratch = self.parser().scratch.borrow_mut();
+        scratch.clear();
+
+        let negated = self.char() == 'P';
+        if !self.bump_and_bump_space() {
+            return Err(self.error(
+                self.span(),
+                ast::ErrorKind::EscapeUnexpectedEof,
+            ));
+        }
+        let (start, kind) =
+            if self.char() == '{' {
+                let start = self.span_char().end;
+                while self.bump_and_bump_space() && self.char() != '}' {
+                    scratch.push(self.char());
+                }
+                if self.is_eof() {
+                    return Err(self.error(
+                        self.span(),
+                        ast::ErrorKind::EscapeUnexpectedEof,
+                    ));
+                }
+                assert_eq!(self.char(), '}');
+                self.bump();
+
+                let name = scratch.as_str();
+                if let Some(i) = name.find("!=") {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::NotEqual,
+                        name: name[..i].to_string(),
+                        value: name[i+2..].to_string(),
+                    })
+                } else if let Some(i) = name.find(':') {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::Colon,
+                        name: name[..i].to_string(),
+                        value: name[i+1..].to_string(),
+                    })
+                } else if let Some(i) = name.find('=') {
+                    (start, ast::ClassUnicodeKind::NamedValue {
+                        op: ast::ClassUnicodeOpKind::Equal,
+                        name: name[..i].to_string(),
+                        value: name[i+1..].to_string(),
+                    })
+                } else {
+                    (start, ast::ClassUnicodeKind::Named(name.to_string()))
+                }
+            } else {
+                let start = self.pos();
+                let c = self.char();
+                self.bump_and_bump_space();
+                let kind = ast::ClassUnicodeKind::OneLetter(c);
+                (start, kind)
+            };
+        Ok(ast::ClassUnicode {
+            span: Span::new(start, self.pos()),
+            negated: negated,
+            kind: kind,
+        })
+    }
+
+    /// Parse a Perl character class, e.g., `\d` or `\W`. This assumes the
+    /// parser is currently at a valid character class name and will be
+    /// advanced to the character immediately following the class.
+    fn parse_perl_class(&self) -> ast::ClassPerl {
+        let c = self.char();
+        let span = self.span_char();
+        self.bump();
+        let (negated, kind) = match c {
+            'd' => (false, ast::ClassPerlKind::Digit),
+            'D' => (true, ast::ClassPerlKind::Digit),
+            's' => (false, ast::ClassPerlKind::Space),
+            'S' => (true, ast::ClassPerlKind::Space),
+            'w' => (false, ast::ClassPerlKind::Word),
+            'W' => (true, ast::ClassPerlKind::Word),
+            c => panic!("expected valid Perl class but got '{}'", c),
+        };
+        ast::ClassPerl { span: span, kind: kind, negated: negated }
+    }
+}
+
+/// A type that traverses a fully parsed Ast and checks whether its depth
+/// exceeds the specified nesting limit. If it does, then an error is returned.
+#[derive(Debug)]
+struct NestLimiter<'p, 's: 'p, P: 'p + 's> {
+    /// The parser that is checking the nest limit.
+    p: &'p ParserI<'s, P>,
+    /// The current depth while walking an Ast.
+    depth: u32,
+}
+
+impl<'p, 's, P: Borrow<Parser>> NestLimiter<'p, 's, P> {
+    fn new(p: &'p ParserI<'s, P>) -> NestLimiter<'p, 's, P> {
+        NestLimiter { p: p, depth: 0 }
+    }
+
+    fn check(self, ast: &Ast) -> Result<()> {
+        ast::visit(ast, self)
+    }
+
+    fn increment_depth(&mut self, span: &Span) -> Result<()> {
+        let new = self.depth.checked_add(1).ok_or_else(|| self.p.error(
+            span.clone(),
+            ast::ErrorKind::NestLimitExceeded(::std::u32::MAX),
+        ))?;
+        let limit = self.p.parser().nest_limit;
+        if new > limit {
+            return Err(self.p.error(
+                span.clone(),
+                ast::ErrorKind::NestLimitExceeded(limit),
+            ));
+        }
+        self.depth = new;
+        Ok(())
+    }
+
+    fn decrement_depth(&mut self) {
+        // Assuming the correctness of the visitor, this should never drop
+        // below 0.
+        self.depth = self.depth.checked_sub(1).unwrap();
+    }
+}
+
+impl<'p, 's, P: Borrow<Parser>> ast::Visitor for NestLimiter<'p, 's, P> {
+    type Output = ();
+    type Err = ast::Error;
+
+    fn finish(self) -> Result<()> {
+        Ok(())
+    }
+
+    fn visit_pre(&mut self, ast: &Ast) -> Result<()> {
+        let span = match *ast {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            | Ast::Class(ast::Class::Unicode(_))
+            | Ast::Class(ast::Class::Perl(_)) => {
+                // These are all base cases, so we don't increment depth.
+                return Ok(());
+            }
+            Ast::Class(ast::Class::Bracketed(ref x)) => &x.span,
+            Ast::Repetition(ref x) => &x.span,
+            Ast::Group(ref x) => &x.span,
+            Ast::Alternation(ref x) => &x.span,
+            Ast::Concat(ref x) => &x.span,
+        };
+        self.increment_depth(span)
+    }
+
+    fn visit_post(&mut self, ast: &Ast) -> Result<()> {
+        match *ast {
+            Ast::Empty(_)
+            | Ast::Flags(_)
+            | Ast::Literal(_)
+            | Ast::Dot(_)
+            | Ast::Assertion(_)
+            | Ast::Class(ast::Class::Unicode(_))
+            | Ast::Class(ast::Class::Perl(_)) => {
+                // These are all base cases, so we don't decrement depth.
+                Ok(())
+            }
+            Ast::Class(ast::Class::Bracketed(_))
+            | Ast::Repetition(_)
+            | Ast::Group(_)
+            | Ast::Alternation(_)
+            | Ast::Concat(_) => {
+                self.decrement_depth();
+                Ok(())
+            }
+        }
+    }
+
+    fn visit_class_set_item_pre(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        let span = match *ast {
+            ast::ClassSetItem::Empty(_)
+            | ast::ClassSetItem::Literal(_)
+            | ast::ClassSetItem::Range(_)
+            | ast::ClassSetItem::Ascii(_)
+            | ast::ClassSetItem::Unicode(_)
+            | ast::ClassSetItem::Perl(_) => {
+                // These are all base cases, so we don't increment depth.
+                return Ok(());
+            }
+            ast::ClassSetItem::Bracketed(ref x) => &x.span,
+            ast::ClassSetItem::Union(ref x) => &x.span,
+        };
+        self.increment_depth(span)
+    }
+
+    fn visit_class_set_item_post(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        match *ast {
+            ast::ClassSetItem::Empty(_)
+            | ast::ClassSetItem::Literal(_)
+            | ast::ClassSetItem::Range(_)
+            | ast::ClassSetItem::Ascii(_)
+            | ast::ClassSetItem::Unicode(_)
+            | ast::ClassSetItem::Perl(_) => {
+                // These are all base cases, so we don't decrement depth.
+                Ok(())
+            }
+            ast::ClassSetItem::Bracketed(_)
+            | ast::ClassSetItem::Union(_) => {
+                self.decrement_depth();
+                Ok(())
+            }
+        }
+    }
+
+    fn visit_class_set_binary_op_pre(
+        &mut self,
+        ast: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        self.increment_depth(&ast.span)
+    }
+
+    fn visit_class_set_binary_op_post(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        self.decrement_depth();
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::ops::Range;
+
+    use ast::{self, Ast, Position, Span};
+    use super::{Parser, ParserI, ParserBuilder, Primitive};
+
+    // Our own assert_eq, which has slightly better formatting (but honestly
+    // still kind of crappy).
+    macro_rules! assert_eq {
+        ($left:expr, $right:expr) => ({
+            match (&$left, &$right) {
+                (left_val, right_val) => {
+                    if !(*left_val == *right_val) {
+                        panic!("assertion failed: `(left == right)`\n\n\
+                               left:  `{:?}`\nright: `{:?}`\n\n",
+                               left_val, right_val)
+                    }
+                }
+            }
+        });
+    }
+
+    // We create these errors to compare with real ast::Errors in the tests.
+    // We define equality between TestError and ast::Error to disregard the
+    // pattern string in ast::Error, which is annoying to provide in tests.
+    #[derive(Clone, Debug)]
+    struct TestError {
+        span: Span,
+        kind: ast::ErrorKind,
+    }
+
+    impl PartialEq<ast::Error> for TestError {
+        fn eq(&self, other: &ast::Error) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    impl PartialEq<TestError> for ast::Error {
+        fn eq(&self, other: &TestError) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    fn s(str: &str) -> String {
+        str.to_string()
+    }
+
+    fn parser(pattern: &str) -> ParserI<Parser> {
+        ParserI::new(Parser::new(), pattern)
+    }
+
+    fn parser_octal(pattern: &str) -> ParserI<Parser> {
+        let parser = ParserBuilder::new().octal(true).build();
+        ParserI::new(parser, pattern)
+    }
+
+    fn parser_nest_limit(pattern: &str, nest_limit: u32) -> ParserI<Parser> {
+        let p = ParserBuilder::new().nest_limit(nest_limit).build();
+        ParserI::new(p, pattern)
+    }
+
+    fn parser_ignore_whitespace(pattern: &str) -> ParserI<Parser> {
+        let p = ParserBuilder::new().ignore_whitespace(true).build();
+        ParserI::new(p, pattern)
+    }
+
+    /// Short alias for creating a new span.
+    fn nspan(start: Position, end: Position) -> Span {
+        Span::new(start, end)
+    }
+
+    /// Short alias for creating a new position.
+    fn npos(offset: usize, line: usize, column: usize) -> Position {
+        Position::new(offset, line, column)
+    }
+
+    /// Create a new span from the given offset range. This assumes a single
+    /// line and sets the columns based on the offsets. i.e., This only works
+    /// out of the box for ASCII, which is fine for most tests.
+    fn span(range: Range<usize>) -> Span {
+        let start = Position::new(range.start, 1, range.start + 1);
+        let end = Position::new(range.end, 1, range.end + 1);
+        Span::new(start, end)
+    }
+
+    /// Create a new span for the corresponding byte range in the given string.
+    fn span_range(subject: &str, range: Range<usize>) -> Span {
+        let start = Position {
+            offset: range.start,
+            line: 1 + subject[..range.start].matches('\n').count(),
+            column: 1 + subject[..range.start]
+                .chars()
+                .rev()
+                .position(|c| c == '\n')
+                .unwrap_or(subject[..range.start].chars().count()),
+        };
+        let end = Position {
+            offset: range.end,
+            line: 1 + subject[..range.end].matches('\n').count(),
+            column: 1 + subject[..range.end]
+                .chars()
+                .rev()
+                .position(|c| c == '\n')
+                .unwrap_or(subject[..range.end].chars().count()),
+        };
+        Span::new(start, end)
+    }
+
+    /// Create a verbatim literal starting at the given position.
+    fn lit(c: char, start: usize) -> Ast {
+        lit_with(c, span(start..start + c.len_utf8()))
+    }
+
+    /// Create a punctuation literal starting at the given position.
+    fn punct_lit(c: char, span: Span) -> Ast {
+        Ast::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Punctuation,
+            c: c,
+        })
+    }
+
+    /// Create a verbatim literal with the given span.
+    fn lit_with(c: char, span: Span) -> Ast {
+        Ast::Literal(ast::Literal {
+            span: span,
+            kind: ast::LiteralKind::Verbatim,
+            c: c,
+        })
+    }
+
+    /// Create a concatenation with the given range.
+    fn concat(range: Range<usize>, asts: Vec<Ast>) -> Ast {
+        concat_with(span(range), asts)
+    }
+
+    /// Create a concatenation with the given span.
+    fn concat_with(span: Span, asts: Vec<Ast>) -> Ast {
+        Ast::Concat(ast::Concat { span: span, asts: asts })
+    }
+
+    /// Create an alternation with the given span.
+    fn alt(range: Range<usize>, asts: Vec<Ast>) -> Ast {
+        Ast::Alternation(ast::Alternation { span: span(range), asts: asts })
+    }
+
+    /// Create a capturing group with the given span.
+    fn group(range: Range<usize>, index: u32, ast: Ast) -> Ast {
+        Ast::Group(ast::Group {
+            span: span(range),
+            kind: ast::GroupKind::CaptureIndex(index),
+            ast: Box::new(ast),
+        })
+    }
+
+    /// Create an ast::SetFlags.
+    ///
+    /// The given pattern should be the full pattern string. The range given
+    /// should correspond to the byte offsets where the flag set occurs.
+    ///
+    /// If negated is true, then the set is interpreted as beginning with a
+    /// negation.
+    fn flag_set(
+        pat: &str,
+        range: Range<usize>,
+        flag: ast::Flag,
+        negated: bool,
+    ) -> Ast {
+        let mut items = vec![
+            ast::FlagsItem {
+                span: span_range(pat, (range.end - 2)..(range.end - 1)),
+                kind: ast::FlagsItemKind::Flag(flag),
+            },
+        ];
+        if negated {
+            items.insert(0, ast::FlagsItem {
+                span: span_range(pat, (range.start + 2)..(range.end - 2)),
+                kind: ast::FlagsItemKind::Negation,
+            });
+        }
+        Ast::Flags(ast::SetFlags {
+            span: span_range(pat, range.clone()),
+            flags: ast::Flags {
+                span: span_range(pat, (range.start + 2)..(range.end - 1)),
+                items: items,
+            },
+        })
+    }
+
+    #[test]
+    fn parse_nest_limit() {
+        // A nest limit of 0 still allows some types of regexes.
+        assert_eq!(
+            parser_nest_limit("", 0).parse(),
+            Ok(Ast::Empty(span(0..0))));
+        assert_eq!(
+            parser_nest_limit("a", 0).parse(),
+            Ok(lit('a', 0)));
+
+        // Test repetition operations, which require one level of nesting.
+        assert_eq!(
+            parser_nest_limit("a+", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("a+", 1).parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::OneOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser_nest_limit("(a)+", 1).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("a+*", 1).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("a+*", 2).parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..3),
+                op: ast::RepetitionOp {
+                    span: span(2..3),
+                    kind: ast::RepetitionKind::ZeroOrMore,
+                },
+                greedy: true,
+                ast: Box::new(Ast::Repetition(ast::Repetition {
+                    span: span(0..2),
+                    op: ast::RepetitionOp {
+                        span: span(1..2),
+                        kind: ast::RepetitionKind::OneOrMore,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 0)),
+                })),
+            })));
+
+        // Test concatenations. A concatenation requires one level of nesting.
+        assert_eq!(
+            parser_nest_limit("ab", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("ab", 1).parse(),
+            Ok(concat(0..2, vec![lit('a', 0), lit('b', 1)])));
+        assert_eq!(
+            parser_nest_limit("abc", 1).parse(),
+            Ok(concat(0..3, vec![lit('a', 0), lit('b', 1), lit('c', 2)])));
+
+        // Test alternations. An alternation requires one level of nesting.
+        assert_eq!(
+            parser_nest_limit("a|b", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("a|b", 1).parse(),
+            Ok(alt(0..3, vec![lit('a', 0), lit('b', 2)])));
+        assert_eq!(
+            parser_nest_limit("a|b|c", 1).parse(),
+            Ok(alt(0..5, vec![lit('a', 0), lit('b', 2), lit('c', 4)])));
+
+        // Test character classes. Classes form their own mini-recursive
+        // syntax!
+        assert_eq!(
+            parser_nest_limit("[a]", 0).parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::NestLimitExceeded(0),
+            });
+        assert_eq!(
+            parser_nest_limit("[a]", 1).parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: ast::ClassSet::Item(
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..2),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'a',
+                    })
+                ),
+            }))));
+        assert_eq!(
+            parser_nest_limit("[ab]", 1).parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("[ab[cd]]", 2).parse().unwrap_err(),
+            TestError {
+                span: span(3..7),
+                kind: ast::ErrorKind::NestLimitExceeded(2),
+            });
+        assert_eq!(
+            parser_nest_limit("[ab[cd]]", 3).parse().unwrap_err(),
+            TestError {
+                span: span(4..6),
+                kind: ast::ErrorKind::NestLimitExceeded(3),
+            });
+        assert_eq!(
+            parser_nest_limit("[a--b]", 1).parse().unwrap_err(),
+            TestError {
+                span: span(1..5),
+                kind: ast::ErrorKind::NestLimitExceeded(1),
+            });
+        assert_eq!(
+            parser_nest_limit("[a--bc]", 2).parse().unwrap_err(),
+            TestError {
+                span: span(4..6),
+                kind: ast::ErrorKind::NestLimitExceeded(2),
+            });
+    }
+
+    #[test]
+    fn parse_comments() {
+        let pat = "(?x)
+# This is comment 1.
+foo # This is comment 2.
+  # This is comment 3.
+bar
+# This is comment 4.";
+        let astc = parser(pat).parse_with_comments().unwrap();
+        assert_eq!(
+            astc.ast,
+            concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('f', span_range(pat, 26..27)),
+                lit_with('o', span_range(pat, 27..28)),
+                lit_with('o', span_range(pat, 28..29)),
+                lit_with('b', span_range(pat, 74..75)),
+                lit_with('a', span_range(pat, 75..76)),
+                lit_with('r', span_range(pat, 76..77)),
+            ]));
+        assert_eq!(astc.comments, vec![
+            ast::Comment {
+                span: span_range(pat, 5..26),
+                comment: s(" This is comment 1."),
+            },
+            ast::Comment {
+                span: span_range(pat, 30..51),
+                comment: s(" This is comment 2."),
+            },
+            ast::Comment {
+                span: span_range(pat, 53..74),
+                comment: s(" This is comment 3."),
+            },
+            ast::Comment {
+                span: span_range(pat, 78..98),
+                comment: s(" This is comment 4."),
+            },
+        ]);
+    }
+
+    #[test]
+    fn parse_holistic() {
+        assert_eq!(
+            parser("]").parse(),
+            Ok(lit(']', 0)));
+        assert_eq!(
+            parser(r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#\&\-\~").parse(),
+            Ok(concat(0..36, vec![
+                punct_lit('\\', span(0..2)),
+                punct_lit('.', span(2..4)),
+                punct_lit('+', span(4..6)),
+                punct_lit('*', span(6..8)),
+                punct_lit('?', span(8..10)),
+                punct_lit('(', span(10..12)),
+                punct_lit(')', span(12..14)),
+                punct_lit('|', span(14..16)),
+                punct_lit('[', span(16..18)),
+                punct_lit(']', span(18..20)),
+                punct_lit('{', span(20..22)),
+                punct_lit('}', span(22..24)),
+                punct_lit('^', span(24..26)),
+                punct_lit('$', span(26..28)),
+                punct_lit('#', span(28..30)),
+                punct_lit('&', span(30..32)),
+                punct_lit('-', span(32..34)),
+                punct_lit('~', span(34..36)),
+            ])));
+    }
+
+    #[test]
+    fn parse_ignore_whitespace() {
+        // Test that basic whitespace insensitivity works.
+        let pat = "(?x)a b";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(nspan(npos(0, 1, 1), npos(7, 1, 8)), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('b', nspan(npos(6, 1, 7), npos(7, 1, 8))),
+            ])));
+
+        // Test that we can toggle whitespace insensitivity.
+        let pat = "(?x)a b(?-x)a b";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(nspan(npos(0, 1, 1), npos(15, 1, 16)), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('b', nspan(npos(6, 1, 7), npos(7, 1, 8))),
+                flag_set(pat, 7..12, ast::Flag::IgnoreWhitespace, true),
+                lit_with('a', nspan(npos(12, 1, 13), npos(13, 1, 14))),
+                lit_with(' ', nspan(npos(13, 1, 14), npos(14, 1, 15))),
+                lit_with('b', nspan(npos(14, 1, 15), npos(15, 1, 16))),
+            ])));
+
+        // Test that nesting whitespace insensitive flags works.
+        let pat = "a (?x:a )a ";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..11), vec![
+                lit_with('a', span_range(pat, 0..1)),
+                lit_with(' ', span_range(pat, 1..2)),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 2..9),
+                    kind: ast::GroupKind::NonCapturing(ast::Flags {
+                        span: span_range(pat, 4..5),
+                        items: vec![
+                            ast::FlagsItem {
+                                span: span_range(pat, 4..5),
+                                kind: ast::FlagsItemKind::Flag(
+                                    ast::Flag::IgnoreWhitespace),
+                            },
+                        ],
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 6..7))),
+                }),
+                lit_with('a', span_range(pat, 9..10)),
+                lit_with(' ', span_range(pat, 10..11)),
+            ])));
+
+        // Test that whitespace after an opening paren is insignificant.
+        let pat = "(?x)( ?P<foo> a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                        span: span_range(pat, 9..12),
+                        name: s("foo"),
+                        index: 1,
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 14..15))),
+                }),
+            ])));
+        let pat = "(?x)(  a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::CaptureIndex(1),
+                    ast: Box::new(lit_with('a', span_range(pat, 7..8))),
+                }),
+            ])));
+        let pat = "(?x)(  ?:  a )";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Group(ast::Group {
+                    span: span_range(pat, 4..pat.len()),
+                    kind: ast::GroupKind::NonCapturing(ast::Flags {
+                        span: span_range(pat, 8..8),
+                        items: vec![],
+                    }),
+                    ast: Box::new(lit_with('a', span_range(pat, 11..12))),
+                }),
+            ])));
+        let pat = r"(?x)\x { 53 }";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Literal(ast::Literal {
+                    span: span(4..13),
+                    kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                    c: 'S',
+                }),
+            ])));
+
+        // Test that whitespace after an escape is OK.
+        let pat = r"(?x)\ ";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                flag_set(pat, 0..4, ast::Flag::IgnoreWhitespace, false),
+                Ast::Literal(ast::Literal {
+                    span: span_range(pat, 4..6),
+                    kind: ast::LiteralKind::Special(
+                        ast::SpecialLiteralKind::Space),
+                    c: ' ',
+                }),
+            ])));
+        // ... but only when `x` mode is enabled.
+        let pat = r"\ ";
+        assert_eq!(
+            parser(pat).parse().unwrap_err(),
+            TestError {
+                span: span_range(pat, 0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_newlines() {
+        let pat = ".\n.";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..3), vec![
+                Ast::Dot(span_range(pat, 0..1)),
+                lit_with('\n', span_range(pat, 1..2)),
+                Ast::Dot(span_range(pat, 2..3)),
+            ])));
+
+        let pat = "foobar\nbaz\nquux\n";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(concat_with(span_range(pat, 0..pat.len()), vec![
+                lit_with('f', nspan(npos(0, 1, 1), npos(1, 1, 2))),
+                lit_with('o', nspan(npos(1, 1, 2), npos(2, 1, 3))),
+                lit_with('o', nspan(npos(2, 1, 3), npos(3, 1, 4))),
+                lit_with('b', nspan(npos(3, 1, 4), npos(4, 1, 5))),
+                lit_with('a', nspan(npos(4, 1, 5), npos(5, 1, 6))),
+                lit_with('r', nspan(npos(5, 1, 6), npos(6, 1, 7))),
+                lit_with('\n', nspan(npos(6, 1, 7), npos(7, 2, 1))),
+                lit_with('b', nspan(npos(7, 2, 1), npos(8, 2, 2))),
+                lit_with('a', nspan(npos(8, 2, 2), npos(9, 2, 3))),
+                lit_with('z', nspan(npos(9, 2, 3), npos(10, 2, 4))),
+                lit_with('\n', nspan(npos(10, 2, 4), npos(11, 3, 1))),
+                lit_with('q', nspan(npos(11, 3, 1), npos(12, 3, 2))),
+                lit_with('u', nspan(npos(12, 3, 2), npos(13, 3, 3))),
+                lit_with('u', nspan(npos(13, 3, 3), npos(14, 3, 4))),
+                lit_with('x', nspan(npos(14, 3, 4), npos(15, 3, 5))),
+                lit_with('\n', nspan(npos(15, 3, 5), npos(16, 4, 1))),
+            ])));
+    }
+
+    #[test]
+    fn parse_uncounted_repetition() {
+        assert_eq!(
+            parser(r"a*").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a+").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::OneOrMore,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+
+        assert_eq!(
+            parser(r"a?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a??").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..3),
+                op: ast::RepetitionOp {
+                    span: span(1..3),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..2),
+                op: ast::RepetitionOp {
+                    span: span(1..2),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a?b").parse(),
+            Ok(concat(0..3, vec![
+                Ast::Repetition(ast::Repetition {
+                    span: span(0..2),
+                    op: ast::RepetitionOp {
+                        span: span(1..2),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 0)),
+                }),
+                lit('b', 2),
+            ])));
+        assert_eq!(
+            parser(r"a??b").parse(),
+            Ok(concat(0..4, vec![
+                Ast::Repetition(ast::Repetition {
+                    span: span(0..3),
+                    op: ast::RepetitionOp {
+                        span: span(1..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: false,
+                    ast: Box::new(lit('a', 0)),
+                }),
+                lit('b', 3),
+            ])));
+        assert_eq!(
+            parser(r"ab?").parse(),
+            Ok(concat(0..3, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..3),
+                    op: ast::RepetitionOp {
+                        span: span(2..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+            ])));
+        assert_eq!(
+            parser(r"(ab)?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(4..5),
+                    kind: ast::RepetitionKind::ZeroOrOne,
+                },
+                greedy: true,
+                ast: Box::new(group(0..4, 1, concat(1..3, vec![
+                    lit('a', 1),
+                    lit('b', 2),
+                ]))),
+            })));
+        assert_eq!(
+            parser(r"|a?").parse(),
+            Ok(alt(0..3, vec![
+                Ast::Empty(span(0..0)),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..3),
+                    op: ast::RepetitionOp {
+                        span: span(2..3),
+                        kind: ast::RepetitionKind::ZeroOrOne,
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('a', 1)),
+                }),
+            ])));
+
+        assert_eq!(
+            parser(r"*").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?i)*").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(*)").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?:?)").parse().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"+").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"?").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"(?)").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|*").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|+").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|?").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+    }
+
+    #[test]
+    fn parse_counted_repetition() {
+        assert_eq!(
+            parser(r"a{5}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..4),
+                op: ast::RepetitionOp {
+                    span: span(1..4),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5,}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(1..5),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::AtLeast(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5,9}").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..6),
+                op: ast::RepetitionOp {
+                    span: span(1..6),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{5}?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..5),
+                op: ast::RepetitionOp {
+                    span: span(1..5),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"ab{5}").parse(),
+            Ok(concat(0..5, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..5),
+                    op: ast::RepetitionOp {
+                        span: span(2..5),
+                        kind: ast::RepetitionKind::Range(
+                            ast::RepetitionRange::Exactly(5)),
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+            ])));
+        assert_eq!(
+            parser(r"ab{5}c").parse(),
+            Ok(concat(0..6, vec![
+                lit('a', 0),
+                Ast::Repetition(ast::Repetition {
+                    span: span(1..5),
+                    op: ast::RepetitionOp {
+                        span: span(2..5),
+                        kind: ast::RepetitionKind::Range(
+                            ast::RepetitionRange::Exactly(5)),
+                    },
+                    greedy: true,
+                    ast: Box::new(lit('b', 1)),
+                }),
+                lit('c', 5),
+            ])));
+
+        assert_eq!(
+            parser(r"a{ 5 }").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..6),
+                op: ast::RepetitionOp {
+                    span: span(1..6),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Exactly(5)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser(r"a{ 5 , 9 }").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..10),
+                op: ast::RepetitionOp {
+                    span: span(1..10),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: true,
+                ast: Box::new(lit('a', 0)),
+            })));
+        assert_eq!(
+            parser_ignore_whitespace(r"a{5,9} ?").parse(),
+            Ok(Ast::Repetition(ast::Repetition {
+                span: span(0..8),
+                op: ast::RepetitionOp {
+                    span: span(1..8),
+                    kind: ast::RepetitionKind::Range(
+                        ast::RepetitionRange::Bounded(5, 9)),
+                },
+                greedy: false,
+                ast: Box::new(lit('a', 0)),
+            })));
+
+        assert_eq!(
+            parser(r"a{").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{}").parse().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{a").parse().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{9999999999}").parse().unwrap_err(),
+            TestError {
+                span: span(2..12),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+        assert_eq!(
+            parser(r"a{9").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{9,a").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser(r"a{9,9999999999}").parse().unwrap_err(),
+            TestError {
+                span: span(4..14),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+        assert_eq!(
+            parser(r"a{9,").parse().unwrap_err(),
+            TestError {
+                span: span(1..4),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{9,11").parse().unwrap_err(),
+            TestError {
+                span: span(1..6),
+                kind: ast::ErrorKind::RepetitionCountUnclosed,
+            });
+        assert_eq!(
+            parser(r"a{2,1}").parse().unwrap_err(),
+            TestError {
+                span: span(1..6),
+                kind: ast::ErrorKind::RepetitionCountInvalid,
+            });
+        assert_eq!(
+            parser(r"{5}").parse().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+        assert_eq!(
+            parser(r"|{5}").parse().unwrap_err(),
+            TestError {
+                span: span(1..1),
+                kind: ast::ErrorKind::RepetitionMissing,
+            });
+    }
+
+    #[test]
+    fn parse_alternate() {
+        assert_eq!(
+            parser(r"a|b").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..3),
+                asts: vec![lit('a', 0), lit('b', 2)],
+            })));
+        assert_eq!(
+            parser(r"(a|b)").parse(),
+            Ok(group(0..5, 1, Ast::Alternation(ast::Alternation {
+                span: span(1..4),
+                asts: vec![lit('a', 1), lit('b', 3)],
+            }))));
+
+        assert_eq!(
+            parser(r"a|b|c").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..5),
+                asts: vec![lit('a', 0), lit('b', 2), lit('c', 4)],
+            })));
+        assert_eq!(
+            parser(r"ax|by|cz").parse(),
+            Ok(Ast::Alternation(ast::Alternation {
+                span: span(0..8),
+                asts: vec![
+                    concat(0..2, vec![lit('a', 0), lit('x', 1)]),
+                    concat(3..5, vec![lit('b', 3), lit('y', 4)]),
+                    concat(6..8, vec![lit('c', 6), lit('z', 7)]),
+                ],
+            })));
+        assert_eq!(
+            parser(r"(ax|by|cz)").parse(),
+            Ok(group(0..10, 1, Ast::Alternation(ast::Alternation {
+                span: span(1..9),
+                asts: vec![
+                    concat(1..3, vec![lit('a', 1), lit('x', 2)]),
+                    concat(4..6, vec![lit('b', 4), lit('y', 5)]),
+                    concat(7..9, vec![lit('c', 7), lit('z', 8)]),
+                ],
+            }))));
+        assert_eq!(
+            parser(r"(ax|(by|(cz)))").parse(),
+            Ok(group(0..14, 1, alt(1..13, vec![
+                concat(1..3, vec![lit('a', 1), lit('x', 2)]),
+                group(4..13, 2, alt(5..12, vec![
+                    concat(5..7, vec![lit('b', 5), lit('y', 6)]),
+                    group(8..12, 3, concat(9..11, vec![
+                        lit('c', 9),
+                        lit('z', 10),
+                    ])),
+                ])),
+            ]))));
+
+        assert_eq!(
+            parser(r"|").parse(), Ok(alt(0..1, vec![
+                Ast::Empty(span(0..0)), Ast::Empty(span(1..1)),
+            ])));
+        assert_eq!(
+            parser(r"||").parse(), Ok(alt(0..2, vec![
+                Ast::Empty(span(0..0)),
+                Ast::Empty(span(1..1)),
+                Ast::Empty(span(2..2)),
+            ])));
+        assert_eq!(
+            parser(r"a|").parse(), Ok(alt(0..2, vec![
+                lit('a', 0), Ast::Empty(span(2..2)),
+            ])));
+        assert_eq!(
+            parser(r"|a").parse(), Ok(alt(0..2, vec![
+                Ast::Empty(span(0..0)), lit('a', 1),
+            ])));
+
+        assert_eq!(
+            parser(r"(|)").parse(), Ok(group(0..3, 1, alt(1..2, vec![
+                Ast::Empty(span(1..1)), Ast::Empty(span(2..2)),
+            ]))));
+        assert_eq!(
+            parser(r"(a|)").parse(), Ok(group(0..4, 1, alt(1..3, vec![
+                lit('a', 1), Ast::Empty(span(3..3)),
+            ]))));
+        assert_eq!(
+            parser(r"(|a)").parse(), Ok(group(0..4, 1, alt(1..3, vec![
+                Ast::Empty(span(1..1)), lit('a', 2),
+            ]))));
+
+        assert_eq!(
+            parser(r"a|b)").parse().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+        assert_eq!(
+            parser(r"(a|b").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+    }
+
+    #[test]
+    fn parse_unsupported_lookaround() {
+        assert_eq!(
+            parser(r"(?=a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?!a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?<=a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..4),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+        assert_eq!(
+            parser(r"(?<!a)").parse().unwrap_err(),
+            TestError {
+                span: span(0..4),
+                kind: ast::ErrorKind::UnsupportedLookAround,
+            });
+    }
+
+    #[test]
+    fn parse_group() {
+        assert_eq!(parser("(?i)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..4),
+            flags: ast::Flags {
+                span: span(2..3),
+                items: vec![ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                }],
+            },
+        })));
+        assert_eq!(parser("(?iU)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..5),
+            flags: ast::Flags {
+                span: span(2..4),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            },
+        })));
+        assert_eq!(parser("(?i-U)").parse(), Ok(Ast::Flags(ast::SetFlags {
+            span: span(0..6),
+            flags: ast::Flags {
+                span: span(2..5),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Negation,
+                    },
+                    ast::FlagsItem {
+                        span: span(4..5),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            },
+        })));
+
+        assert_eq!(parser("()").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..2),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(Ast::Empty(span(1..1))),
+        })));
+        assert_eq!(parser("(a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..3),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(lit('a', 1)),
+        })));
+        assert_eq!(parser("(())").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..4),
+            kind: ast::GroupKind::CaptureIndex(1),
+            ast: Box::new(Ast::Group(ast::Group {
+                span: span(1..3),
+                kind: ast::GroupKind::CaptureIndex(2),
+                ast: Box::new(Ast::Empty(span(2..2))),
+            })),
+        })));
+
+        assert_eq!(parser("(?:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..5),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..2),
+                items: vec![],
+            }),
+            ast: Box::new(lit('a', 3)),
+        })));
+
+        assert_eq!(parser("(?i:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..6),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..3),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                ],
+            }),
+            ast: Box::new(lit('a', 4)),
+        })));
+        assert_eq!(parser("(?i-U:a)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..8),
+            kind: ast::GroupKind::NonCapturing(ast::Flags {
+                span: span(2..5),
+                items: vec![
+                    ast::FlagsItem {
+                        span: span(2..3),
+                        kind: ast::FlagsItemKind::Flag(
+                            ast::Flag::CaseInsensitive),
+                    },
+                    ast::FlagsItem {
+                        span: span(3..4),
+                        kind: ast::FlagsItemKind::Negation,
+                    },
+                    ast::FlagsItem {
+                        span: span(4..5),
+                        kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                    },
+                ],
+            }),
+            ast: Box::new(lit('a', 6)),
+        })));
+
+        assert_eq!(
+            parser("(").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(?").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(?P").parse().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("(?P<").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(a").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser("(()").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnclosed,
+            });
+        assert_eq!(
+            parser(")").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+        assert_eq!(
+            parser("a)").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::GroupUnopened,
+            });
+    }
+
+    #[test]
+    fn parse_capture_name() {
+        assert_eq!(parser("(?P<a>z)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..8),
+            kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                span: span(4..5),
+                name: s("a"),
+                index: 1,
+            }),
+            ast: Box::new(lit('z', 6)),
+        })));
+        assert_eq!(parser("(?P<abc>z)").parse(), Ok(Ast::Group(ast::Group {
+            span: span(0..10),
+            kind: ast::GroupKind::CaptureName(ast::CaptureName {
+                span: span(4..7),
+                name: s("abc"),
+                index: 1,
+            }),
+            ast: Box::new(lit('z', 8)),
+        })));
+
+        assert_eq!(
+            parser("(?P<").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<>z)").parse().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::GroupNameEmpty,
+            });
+        assert_eq!(
+            parser("(?P<a").parse().unwrap_err(),
+            TestError {
+                span: span(5..5),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<ab").parse().unwrap_err(),
+            TestError {
+                span: span(6..6),
+                kind: ast::ErrorKind::GroupNameUnexpectedEof,
+            });
+        assert_eq!(
+            parser("(?P<0a").parse().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<~").parse().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<abc~").parse().unwrap_err(),
+            TestError {
+                span: span(7..8),
+                kind: ast::ErrorKind::GroupNameInvalid,
+            });
+        assert_eq!(
+            parser("(?P<a>y)(?P<a>z)").parse().unwrap_err(),
+            TestError {
+                span: span(12..13),
+                kind: ast::ErrorKind::GroupNameDuplicate {
+                    original: span(4..5),
+                },
+            });
+    }
+
+    #[test]
+    fn parse_flags() {
+        assert_eq!(parser("i:").parse_flags(), Ok(ast::Flags {
+            span: span(0..1),
+            items: vec![ast::FlagsItem {
+                span: span(0..1),
+                kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+            }],
+        }));
+        assert_eq!(parser("i)").parse_flags(), Ok(ast::Flags {
+            span: span(0..1),
+            items: vec![ast::FlagsItem {
+                span: span(0..1),
+                kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+            }],
+        }));
+
+        assert_eq!(parser("isU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..3),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+
+        assert_eq!(parser("-isU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..4),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Negation,
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(3..4),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+        assert_eq!(parser("i-sU:").parse_flags(), Ok(ast::Flags {
+            span: span(0..4),
+            items: vec![
+                ast::FlagsItem {
+                    span: span(0..1),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive),
+                },
+                ast::FlagsItem {
+                    span: span(1..2),
+                    kind: ast::FlagsItemKind::Negation,
+                },
+                ast::FlagsItem {
+                    span: span(2..3),
+                    kind: ast::FlagsItemKind::Flag(
+                        ast::Flag::DotMatchesNewLine),
+                },
+                ast::FlagsItem {
+                    span: span(3..4),
+                    kind: ast::FlagsItemKind::Flag(ast::Flag::SwapGreed),
+                },
+            ],
+        }));
+
+        assert_eq!(
+            parser("isU").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::FlagUnexpectedEof,
+            });
+        assert_eq!(
+            parser("isUa:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("isUi:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::FlagDuplicate {
+                    original: span(0..1),
+                },
+            });
+        assert_eq!(
+            parser("i-sU-i:").parse_flags().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::FlagRepeatedNegation {
+                    original: span(1..2),
+                },
+            });
+        assert_eq!(
+            parser("-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+        assert_eq!(
+            parser("i-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+        assert_eq!(
+            parser("iU-)").parse_flags().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::FlagDanglingNegation,
+            });
+    }
+
+    #[test]
+    fn parse_flag() {
+        assert_eq!(parser("i").parse_flag(), Ok(ast::Flag::CaseInsensitive));
+        assert_eq!(parser("m").parse_flag(), Ok(ast::Flag::MultiLine));
+        assert_eq!(parser("s").parse_flag(), Ok(ast::Flag::DotMatchesNewLine));
+        assert_eq!(parser("U").parse_flag(), Ok(ast::Flag::SwapGreed));
+        assert_eq!(parser("u").parse_flag(), Ok(ast::Flag::Unicode));
+        assert_eq!(parser("x").parse_flag(), Ok(ast::Flag::IgnoreWhitespace));
+
+        assert_eq!(
+            parser("a").parse_flag().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+        assert_eq!(
+            parser("☃").parse_flag().unwrap_err(),
+            TestError {
+                span: span_range("☃", 0..3),
+                kind: ast::ErrorKind::FlagUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_primitive_non_escape() {
+        assert_eq!(
+            parser(r".").parse_primitive(),
+            Ok(Primitive::Dot(span(0..1))));
+        assert_eq!(
+            parser(r"^").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..1),
+                kind: ast::AssertionKind::StartLine,
+            })));
+        assert_eq!(
+            parser(r"$").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..1),
+                kind: ast::AssertionKind::EndLine,
+            })));
+
+        assert_eq!(
+            parser(r"a").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..1),
+                kind: ast::LiteralKind::Verbatim,
+                c: 'a',
+            })));
+        assert_eq!(
+            parser(r"|").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..1),
+                kind: ast::LiteralKind::Verbatim,
+                c: '|',
+            })));
+        assert_eq!(
+            parser(r"☃").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span_range("☃", 0..3),
+                kind: ast::LiteralKind::Verbatim,
+                c: '☃',
+            })));
+    }
+
+    #[test]
+    fn parse_escape() {
+        assert_eq!(
+            parser(r"\|").parse_primitive(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..2),
+                kind: ast::LiteralKind::Punctuation,
+                c: '|',
+            })));
+        let specials = &[
+            (r"\a", '\x07', ast::SpecialLiteralKind::Bell),
+            (r"\f", '\x0C', ast::SpecialLiteralKind::FormFeed),
+            (r"\t", '\t', ast::SpecialLiteralKind::Tab),
+            (r"\n", '\n', ast::SpecialLiteralKind::LineFeed),
+            (r"\r", '\r', ast::SpecialLiteralKind::CarriageReturn),
+            (r"\v", '\x0B', ast::SpecialLiteralKind::VerticalTab),
+        ];
+        for &(pat, c, ref kind) in specials {
+            assert_eq!(
+                parser(pat).parse_primitive(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..2),
+                    kind: ast::LiteralKind::Special(kind.clone()),
+                    c: c,
+                })));
+        }
+        assert_eq!(
+            parser(r"\A").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::StartText,
+            })));
+        assert_eq!(
+            parser(r"\z").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::EndText,
+            })));
+        assert_eq!(
+            parser(r"\b").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::WordBoundary,
+            })));
+        assert_eq!(
+            parser(r"\B").parse_primitive(),
+            Ok(Primitive::Assertion(ast::Assertion {
+                span: span(0..2),
+                kind: ast::AssertionKind::NotWordBoundary,
+            })));
+
+        assert_eq!(
+            parser(r"\").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\y").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_unsupported_backreference() {
+        assert_eq!(
+            parser(r"\0").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::UnsupportedBackreference,
+            });
+        assert_eq!(
+            parser(r"\9").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::UnsupportedBackreference,
+            });
+    }
+
+    #[test]
+    fn parse_octal() {
+        for i in 0..511 {
+            let pat = format!(r"\{:o}", i);
+            assert_eq!(
+                parser_octal(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::Octal,
+                    c: ::std::char::from_u32(i).unwrap(),
+                })));
+        }
+        assert_eq!(
+            parser_octal(r"\778").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..3),
+                kind: ast::LiteralKind::Octal,
+                c: '?',
+            })));
+        assert_eq!(
+            parser_octal(r"\7777").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..4),
+                kind: ast::LiteralKind::Octal,
+                c: '\u{01FF}',
+            })));
+        assert_eq!(
+            parser_octal(r"\778").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..4),
+                asts: vec![
+                    Ast::Literal(ast::Literal {
+                        span: span(0..3),
+                        kind: ast::LiteralKind::Octal,
+                        c: '?',
+                    }),
+                    Ast::Literal(ast::Literal {
+                        span: span(3..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '8',
+                    }),
+                ],
+            })));
+        assert_eq!(
+            parser_octal(r"\7777").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..5),
+                asts: vec![
+                    Ast::Literal(ast::Literal {
+                        span: span(0..4),
+                        kind: ast::LiteralKind::Octal,
+                        c: '\u{01FF}',
+                    }),
+                    Ast::Literal(ast::Literal {
+                        span: span(4..5),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '7',
+                    }),
+                ],
+            })));
+
+        assert_eq!(
+            parser_octal(r"\8").parse_escape().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::EscapeUnrecognized,
+            });
+    }
+
+    #[test]
+    fn parse_hex_two() {
+        for i in 0..256 {
+            let pat = format!(r"\x{:02x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(ast::HexLiteralKind::X),
+                    c: ::std::char::from_u32(i).unwrap(),
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\xF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\xG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\xFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+    }
+
+    #[test]
+    fn parse_hex_four() {
+        for i in 0..65536 {
+            let c = match ::std::char::from_u32(i) {
+                None => continue,
+                Some(c) => c,
+            };
+            let pat = format!(r"\u{:04x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(
+                        ast::HexLiteralKind::UnicodeShort),
+                    c: c,
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\uF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\uG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(5..6),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\uD800").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..6),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_hex_eight() {
+        for i in 0..65536 {
+            let c = match ::std::char::from_u32(i) {
+                None => continue,
+                Some(c) => c,
+            };
+            let pat = format!(r"\U{:08x}", i);
+            assert_eq!(
+                parser(&pat).parse_escape(),
+                Ok(Primitive::Literal(ast::Literal {
+                    span: span(0..pat.len()),
+                    kind: ast::LiteralKind::HexFixed(
+                        ast::HexLiteralKind::UnicodeLong),
+                    c: c,
+                })));
+        }
+
+        assert_eq!(
+            parser(r"\UF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\UG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..4),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(5..6),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(6..7),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(7..8),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(8..9),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\UFFFFFFFG").parse_escape().unwrap_err(),
+            TestError {
+                span: span(9..10),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+    }
+
+    #[test]
+    fn parse_hex_brace() {
+        assert_eq!(
+            parser(r"\u{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(
+                    ast::HexLiteralKind::UnicodeShort),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\U{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(
+                    ast::HexLiteralKind::UnicodeLong),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{26c4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{26C4}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..8),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '⛄',
+            })));
+        assert_eq!(
+            parser(r"\x{10fFfF}").parse_escape(),
+            Ok(Primitive::Literal(ast::Literal {
+                span: span(0..10),
+                kind: ast::LiteralKind::HexBrace(ast::HexLiteralKind::X),
+                c: '\u{10FFFF}',
+            })));
+
+        assert_eq!(
+            parser(r"\x").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{FF").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..5),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\x{}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..4),
+                kind: ast::ErrorKind::EscapeHexEmpty,
+            });
+        assert_eq!(
+            parser(r"\x{FGF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..5),
+                kind: ast::ErrorKind::EscapeHexInvalidDigit,
+            });
+        assert_eq!(
+            parser(r"\x{FFFFFF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..9),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+        assert_eq!(
+            parser(r"\x{D800}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..7),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+        assert_eq!(
+            parser(r"\x{FFFFFFFFF}").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..12),
+                kind: ast::ErrorKind::EscapeHexInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_decimal() {
+        assert_eq!(parser("123").parse_decimal(), Ok(123));
+        assert_eq!(parser("0").parse_decimal(), Ok(0));
+        assert_eq!(parser("01").parse_decimal(), Ok(1));
+
+        assert_eq!(
+            parser("-1").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser("").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..0),
+                kind: ast::ErrorKind::DecimalEmpty,
+            });
+        assert_eq!(
+            parser("9999999999").parse_decimal().unwrap_err(),
+            TestError {
+                span: span(0..10),
+                kind: ast::ErrorKind::DecimalInvalid,
+            });
+    }
+
+    #[test]
+    fn parse_set_class() {
+        fn union(span: Span, items: Vec<ast::ClassSetItem>) -> ast::ClassSet {
+            ast::ClassSet::union(ast::ClassSetUnion {
+                span: span,
+                items: items,
+            })
+        }
+
+        fn intersection(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::Intersection,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn difference(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::Difference,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn symdifference(
+            span: Span,
+            lhs: ast::ClassSet,
+            rhs: ast::ClassSet,
+        ) -> ast::ClassSet {
+            ast::ClassSet::BinaryOp(ast::ClassSetBinaryOp {
+                span: span,
+                kind: ast::ClassSetBinaryOpKind::SymmetricDifference,
+                lhs: Box::new(lhs),
+                rhs: Box::new(rhs),
+            })
+        }
+
+        fn itemset(item: ast::ClassSetItem) -> ast::ClassSet {
+            ast::ClassSet::Item(item)
+        }
+
+        fn item_ascii(cls: ast::ClassAscii) -> ast::ClassSetItem {
+            ast::ClassSetItem::Ascii(cls)
+        }
+
+        fn item_unicode(cls: ast::ClassUnicode) -> ast::ClassSetItem {
+            ast::ClassSetItem::Unicode(cls)
+        }
+
+        fn item_perl(cls: ast::ClassPerl) -> ast::ClassSetItem {
+            ast::ClassSetItem::Perl(cls)
+        }
+
+        fn item_bracket(cls: ast::ClassBracketed) -> ast::ClassSetItem {
+            ast::ClassSetItem::Bracketed(Box::new(cls))
+        }
+
+        fn lit(span: Span, c: char) -> ast::ClassSetItem {
+            ast::ClassSetItem::Literal(ast::Literal {
+                span: span,
+                kind: ast::LiteralKind::Verbatim,
+                c: c,
+            })
+        }
+
+        fn empty(span: Span) -> ast::ClassSetItem {
+            ast::ClassSetItem::Empty(span)
+        }
+
+        fn range(span: Span, start: char, end: char) -> ast::ClassSetItem {
+            let pos1 = Position {
+                offset: span.start.offset + start.len_utf8(),
+                column: span.start.column + 1,
+                ..span.start
+            };
+            let pos2 = Position {
+                offset: span.end.offset - end.len_utf8(),
+                column: span.end.column - 1,
+                ..span.end
+            };
+            ast::ClassSetItem::Range(ast::ClassSetRange {
+                span: span,
+                start: ast::Literal {
+                    span: Span { end: pos1, ..span },
+                    kind: ast::LiteralKind::Verbatim,
+                    c: start,
+                },
+                end: ast::Literal {
+                    span: Span { start: pos2, ..span },
+                    kind: ast::LiteralKind::Verbatim,
+                    c: end,
+                },
+            })
+        }
+
+        fn alnum(span: Span, negated: bool) -> ast::ClassAscii {
+            ast::ClassAscii {
+                span: span,
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: negated,
+            }
+        }
+
+        fn lower(span: Span, negated: bool) -> ast::ClassAscii {
+            ast::ClassAscii {
+                span: span,
+                kind: ast::ClassAsciiKind::Lower,
+                negated: negated,
+            }
+        }
+
+        assert_eq!(
+            parser("[[:alnum:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..11),
+                negated: false,
+                kind: itemset(item_ascii(alnum(span(1..10), false))),
+            }))));
+        assert_eq!(
+            parser("[[[:alnum:]]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..13),
+                negated: false,
+                kind: itemset(item_bracket(ast::ClassBracketed {
+                    span: span(1..12),
+                    negated: false,
+                    kind: itemset(item_ascii(alnum(span(2..11), false))),
+                })),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]&&[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: intersection(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]--[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: difference(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+        assert_eq!(
+            parser("[[:alnum:]~~[:lower:]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..22),
+                negated: false,
+                kind: symdifference(
+                    span(1..21),
+                    itemset(item_ascii(alnum(span(1..10), false))),
+                    itemset(item_ascii(lower(span(12..21), false))),
+                ),
+            }))));
+
+        assert_eq!(
+            parser("[a]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: itemset(lit(span(1..2), 'a')),
+            }))));
+        assert_eq!(
+            parser(r"[a\]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: union(span(1..4), vec![
+                    lit(span(1..2), 'a'),
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: ']',
+                    }),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[a\-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: union(span(1..5), vec![
+                    lit(span(1..2), 'a'),
+                    ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '-',
+                    }),
+                    lit(span(4..5), 'z'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[ab]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), 'a'),
+                    lit(span(2..3), 'b'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[a-]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), 'a'),
+                    lit(span(2..3), '-'),
+                ]),
+            }))));
+        assert_eq!(
+            parser("[-a]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: union(span(1..3), vec![
+                    lit(span(1..2), '-'),
+                    lit(span(2..3), 'a'),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\pL]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: itemset(item_unicode(ast::ClassUnicode {
+                    span: span(1..4),
+                    negated: false,
+                    kind: ast::ClassUnicodeKind::OneLetter('L'),
+                })),
+            }))));
+        assert_eq!(
+            parser(r"[\w]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..4),
+                negated: false,
+                kind: itemset(item_perl(ast::ClassPerl {
+                    span: span(1..3),
+                    kind: ast::ClassPerlKind::Word,
+                    negated: false,
+                })),
+            }))));
+        assert_eq!(
+            parser(r"[a\wz]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: union(span(1..5), vec![
+                    lit(span(1..2), 'a'),
+                    item_perl(ast::ClassPerl {
+                        span: span(2..4),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    }),
+                    lit(span(4..5), 'z'),
+                ]),
+            }))));
+
+        assert_eq!(
+            parser("[a-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: itemset(range(span(1..4), 'a', 'z')),
+            }))));
+        assert_eq!(
+            parser("[a-cx-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..8),
+                negated: false,
+                kind: union(span(1..7), vec![
+                    range(span(1..4), 'a', 'c'),
+                    range(span(4..7), 'x', 'z'),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\w&&a-cx-z]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..12),
+                negated: false,
+                kind: intersection(
+                    span(1..11),
+                    itemset(item_perl(ast::ClassPerl {
+                        span: span(1..3),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    })),
+                    union(span(5..11), vec![
+                        range(span(5..8), 'a', 'c'),
+                        range(span(8..11), 'x', 'z'),
+                    ]),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a-cx-z&&\w]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..12),
+                negated: false,
+                kind: intersection(
+                    span(1..11),
+                    union(span(1..7), vec![
+                        range(span(1..4), 'a', 'c'),
+                        range(span(4..7), 'x', 'z'),
+                    ]),
+                    itemset(item_perl(ast::ClassPerl {
+                        span: span(9..11),
+                        kind: ast::ClassPerlKind::Word,
+                        negated: false,
+                    })),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a--b--c]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..9),
+                negated: false,
+                kind: difference(
+                    span(1..8),
+                    difference(
+                        span(1..5),
+                        itemset(lit(span(1..2), 'a')),
+                        itemset(lit(span(4..5), 'b')),
+                    ),
+                    itemset(lit(span(7..8), 'c')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[a~~b~~c]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..9),
+                negated: false,
+                kind: symdifference(
+                    span(1..8),
+                    symdifference(
+                        span(1..5),
+                        itemset(lit(span(1..2), 'a')),
+                        itemset(lit(span(4..5), 'b')),
+                    ),
+                    itemset(lit(span(7..8), 'c')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[\^&&^]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..7),
+                negated: false,
+                kind: intersection(
+                    span(1..6),
+                    itemset(ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '^',
+                    })),
+                    itemset(lit(span(5..6), '^')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[\&&&&]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..7),
+                negated: false,
+                kind: intersection(
+                    span(1..6),
+                    itemset(ast::ClassSetItem::Literal(ast::Literal {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '&',
+                    })),
+                    itemset(lit(span(5..6), '&')),
+                ),
+            }))));
+        assert_eq!(
+            parser(r"[&&&&]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..6),
+                negated: false,
+                kind: intersection(
+                    span(1..5),
+                    intersection(
+                        span(1..3),
+                        itemset(empty(span(1..1))),
+                        itemset(empty(span(3..3))),
+                    ),
+                    itemset(empty(span(5..5))),
+                ),
+            }))));
+
+        let pat = "[☃-⛄]";
+        assert_eq!(
+            parser(pat).parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span_range(pat, 0..9),
+                negated: false,
+                kind: itemset(ast::ClassSetItem::Range(ast::ClassSetRange {
+                    span: span_range(pat, 1..8),
+                    start: ast::Literal {
+                        span: span_range(pat, 1..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '☃',
+                    },
+                    end: ast::Literal {
+                        span: span_range(pat, 5..8),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: '⛄',
+                    },
+                })),
+            }))));
+
+        assert_eq!(
+            parser(r"[]]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..3),
+                negated: false,
+                kind: itemset(lit(span(1..2), ']')),
+            }))));
+        assert_eq!(
+            parser(r"[]\[]").parse(),
+            Ok(Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                span: span(0..5),
+                negated: false,
+                kind: union(span(1..4), vec![
+                    lit(span(1..2), ']'),
+                    ast::ClassSetItem::Literal(ast::Literal  {
+                        span: span(2..4),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '[',
+                    }),
+                ]),
+            }))));
+        assert_eq!(
+            parser(r"[\[]]").parse(),
+            Ok(concat(0..5, vec![
+                Ast::Class(ast::Class::Bracketed(ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: itemset(ast::ClassSetItem::Literal(ast::Literal  {
+                        span: span(1..3),
+                        kind: ast::LiteralKind::Punctuation,
+                        c: '[',
+                    })),
+                })),
+                Ast::Literal(ast::Literal {
+                    span: span(4..5),
+                    kind: ast::LiteralKind::Verbatim,
+                    c: ']',
+                }),
+            ])));
+
+        assert_eq!(
+            parser("[").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[-]").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[[[:alnum:]").parse().unwrap_err(),
+            TestError {
+                span: span(1..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser(r"[\b]").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::ClassEscapeInvalid,
+            });
+        assert_eq!(
+            parser(r"[\w-a]").parse().unwrap_err(),
+            TestError {
+                span: span(1..3),
+                kind: ast::ErrorKind::ClassRangeLiteral,
+            });
+        assert_eq!(
+            parser(r"[a-\w]").parse().unwrap_err(),
+            TestError {
+                span: span(3..5),
+                kind: ast::ErrorKind::ClassRangeLiteral,
+            });
+        assert_eq!(
+            parser(r"[z-a]").parse().unwrap_err(),
+            TestError {
+                span: span(1..4),
+                kind: ast::ErrorKind::ClassRangeInvalid,
+            });
+
+        assert_eq!(
+            parser_ignore_whitespace("[a ").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[a- ").parse().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+    }
+
+    #[test]
+    fn parse_set_class_open() {
+        assert_eq!(
+            parser("[a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..1),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..1),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[   a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(4..4),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(4..4),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..2),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ ^ a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(4..4),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(4..4),
+                    items: vec![],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[-a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ - a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^-a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[--a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[ ] a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..4),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[^]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..3),
+                    negated: true,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(2..2),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(2..3),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(2..3),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: ']',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+        assert_eq!(
+            parser("[-]a]").parse_set_class_open(), {
+                let set = ast::ClassBracketed {
+                    span: span(0..2),
+                    negated: false,
+                    kind: ast::ClassSet::union(ast::ClassSetUnion {
+                        span: span(1..1),
+                        items: vec![],
+                    }),
+                };
+                let union = ast::ClassSetUnion {
+                    span: span(1..2),
+                    items: vec![
+                        ast::ClassSetItem::Literal(ast::Literal {
+                            span: span(1..2),
+                            kind: ast::LiteralKind::Verbatim,
+                            c: '-',
+                        }),
+                    ],
+                };
+                Ok((set, union))
+            });
+
+        assert_eq!(
+            parser("[").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..1),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser_ignore_whitespace("[    ")
+            .parse_set_class_open()
+            .unwrap_err(),
+            TestError {
+                span: span(0..5),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[^").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[]").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[-").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..2),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+        assert_eq!(
+            parser("[--").parse_set_class_open().unwrap_err(),
+            TestError {
+                span: span(0..3),
+                kind: ast::ErrorKind::ClassUnclosed,
+            });
+    }
+
+    #[test]
+    fn maybe_parse_ascii_class() {
+        assert_eq!(
+            parser(r"[:alnum:]").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..9),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: false,
+            }));
+        assert_eq!(
+            parser(r"[:alnum:]A").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..9),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: false,
+            }));
+        assert_eq!(
+            parser(r"[:^alnum:]").maybe_parse_ascii_class(),
+            Some(ast::ClassAscii {
+                span: span(0..10),
+                kind: ast::ClassAsciiKind::Alnum,
+                negated: true,
+            }));
+
+        let p = parser(r"[:");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:^");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[^:alnum:]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnnum:]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnum]");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+
+        let p = parser(r"[:alnum:");
+        assert_eq!(p.maybe_parse_ascii_class(), None);
+        assert_eq!(p.offset(), 0);
+    }
+
+    #[test]
+    fn parse_unicode_class() {
+        assert_eq!(
+            parser(r"\pN").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..3),
+                negated: false,
+                kind: ast::ClassUnicodeKind::OneLetter('N'),
+            })));
+        assert_eq!(
+            parser(r"\PN").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..3),
+                negated: true,
+                kind: ast::ClassUnicodeKind::OneLetter('N'),
+            })));
+        assert_eq!(
+            parser(r"\p{N}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::Named(s("N")),
+            })));
+        assert_eq!(
+            parser(r"\P{N}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: true,
+                kind: ast::ClassUnicodeKind::Named(s("N")),
+            })));
+        assert_eq!(
+            parser(r"\p{Greek}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..9),
+                negated: false,
+                kind: ast::ClassUnicodeKind::Named(s("Greek")),
+            })));
+
+        assert_eq!(
+            parser(r"\p{scx:Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..16),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Colon,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{scx=Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..16),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Equal,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{scx!=Katakana}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..17),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::NotEqual,
+                    name: s("scx"),
+                    value: s("Katakana"),
+                },
+            })));
+
+        assert_eq!(
+            parser(r"\p{:}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Colon,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{=}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..5),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::Equal,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+        assert_eq!(
+            parser(r"\p{!=}").parse_escape(),
+            Ok(Primitive::Unicode(ast::ClassUnicode {
+                span: span(0..6),
+                negated: false,
+                kind: ast::ClassUnicodeKind::NamedValue {
+                    op: ast::ClassUnicodeOpKind::NotEqual,
+                    name: s(""),
+                    value: s(""),
+                },
+            })));
+
+        assert_eq!(
+            parser(r"\p").parse_escape().unwrap_err(),
+            TestError {
+                span: span(2..2),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{").parse_escape().unwrap_err(),
+            TestError {
+                span: span(3..3),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{N").parse_escape().unwrap_err(),
+            TestError {
+                span: span(4..4),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+        assert_eq!(
+            parser(r"\p{Greek").parse_escape().unwrap_err(),
+            TestError {
+                span: span(8..8),
+                kind: ast::ErrorKind::EscapeUnexpectedEof,
+            });
+
+        assert_eq!(
+            parser(r"\pNz").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..4),
+                asts: vec![
+                    Ast::Class(ast::Class::Unicode(ast::ClassUnicode {
+                        span: span(0..3),
+                        negated: false,
+                        kind: ast::ClassUnicodeKind::OneLetter('N'),
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(3..4),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+        assert_eq!(
+            parser(r"\p{Greek}z").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..10),
+                asts: vec![
+                    Ast::Class(ast::Class::Unicode(ast::ClassUnicode {
+                        span: span(0..9),
+                        negated: false,
+                        kind: ast::ClassUnicodeKind::Named(s("Greek")),
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(9..10),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+    }
+
+    #[test]
+    fn parse_perl_class() {
+        assert_eq!(
+            parser(r"\d").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\D").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: true,
+            })));
+        assert_eq!(
+            parser(r"\s").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Space,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\S").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Space,
+                negated: true,
+            })));
+        assert_eq!(
+            parser(r"\w").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Word,
+                negated: false,
+            })));
+        assert_eq!(
+            parser(r"\W").parse_escape(),
+            Ok(Primitive::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Word,
+                negated: true,
+            })));
+
+        assert_eq!(
+            parser(r"\d").parse(),
+            Ok(Ast::Class(ast::Class::Perl(ast::ClassPerl {
+                span: span(0..2),
+                kind: ast::ClassPerlKind::Digit,
+                negated: false,
+            }))));
+        assert_eq!(
+            parser(r"\dz").parse(),
+            Ok(Ast::Concat(ast::Concat {
+                span: span(0..3),
+                asts: vec![
+                    Ast::Class(ast::Class::Perl(ast::ClassPerl {
+                        span: span(0..2),
+                        kind: ast::ClassPerlKind::Digit,
+                        negated: false,
+                    })),
+                    Ast::Literal(ast::Literal {
+                        span: span(2..3),
+                        kind: ast::LiteralKind::Verbatim,
+                        c: 'z',
+                    }),
+                ],
+            })));
+    }
+
+    // This tests a bug fix where the nest limit checker wasn't decrementing
+    // its depth during post-traversal, which causes long regexes to trip
+    // the default limit too aggressively.
+    #[test]
+    fn regression_454_nest_too_big() {
+        let pattern = r#"
+        2(?:
+          [45]\d{3}|
+          7(?:
+            1[0-267]|
+            2[0-289]|
+            3[0-29]|
+            4[01]|
+            5[1-3]|
+            6[013]|
+            7[0178]|
+            91
+          )|
+          8(?:
+            0[125]|
+            [139][1-6]|
+            2[0157-9]|
+            41|
+            6[1-35]|
+            7[1-5]|
+            8[1-8]|
+            90
+          )|
+          9(?:
+            0[0-2]|
+            1[0-4]|
+            2[568]|
+            3[3-6]|
+            5[5-7]|
+            6[0167]|
+            7[15]|
+            8[0146-9]
+          )
+        )\d{4}
+        "#;
+        assert!(parser_nest_limit(pattern, 50).parse().is_ok());
+    }
+
+    // This tests that we treat a trailing `-` in a character class as a
+    // literal `-` even when whitespace mode is enabled and there is whitespace
+    // after the trailing `-`.
+    #[test]
+    fn regression_455_trailing_dash_ignore_whitespace() {
+        assert!(parser("(?x)[ / - ]").parse().is_ok());
+        assert!(parser("(?x)[ a - ]").parse().is_ok());
+        assert!(parser("(?x)[
+            a
+            - ]
+        ").parse().is_ok());
+        assert!(parser("(?x)[
+            a # wat
+            - ]
+        ").parse().is_ok());
+
+        assert!(parser("(?x)[ / -").parse().is_err());
+        assert!(parser("(?x)[ / - ").parse().is_err());
+        assert!(parser("(?x)[
+            / -
+        ").parse().is_err());
+        assert!(parser("(?x)[
+            / - # wat
+        ").parse().is_err());
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/ast/print.rs b/third_party/rust/regex-syntax/src/ast/print.rs
new file mode 100644
index 000000000000..4441b4d5802f
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/ast/print.rs
@@ -0,0 +1,586 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+This module provides a regular expression printer for `Ast`.
+*/
+
+use std::fmt;
+
+use ast::{self, Ast};
+use ast::visitor::{self, Visitor};
+
+/// A builder for constructing a printer.
+///
+/// Note that since a printer doesn't have any configuration knobs, this type
+/// remains unexported.
+#[derive(Clone, Debug)]
+struct PrinterBuilder {
+    _priv: (),
+}
+
+impl Default for PrinterBuilder {
+    fn default() -> PrinterBuilder {
+        PrinterBuilder::new()
+    }
+}
+
+impl PrinterBuilder {
+    fn new() -> PrinterBuilder {
+        PrinterBuilder {
+            _priv: (),
+        }
+    }
+
+    fn build(&self) -> Printer {
+        Printer {
+            _priv: (),
+        }
+    }
+}
+
+/// A printer for a regular expression abstract syntax tree.
+///
+/// A printer converts an abstract syntax tree (AST) to a regular expression
+/// pattern string. This particular printer uses constant stack space and heap
+/// space proportional to the size of the AST.
+///
+/// This printer will not necessarily preserve the original formatting of the
+/// regular expression pattern string. For example, all whitespace and comments
+/// are ignored.
+#[derive(Debug)]
+pub struct Printer {
+    _priv: (),
+}
+
+impl Printer {
+    /// Create a new printer.
+    pub fn new() -> Printer {
+        PrinterBuilder::new().build()
+    }
+
+    /// Print the given `Ast` to the given writer. The writer must implement
+    /// `fmt::Write`. Typical implementations of `fmt::Write` that can be used
+    /// here are a `fmt::Formatter` (which is available in `fmt::Display`
+    /// implementations) or a `&mut String`.
+    pub fn print<W: fmt::Write>(&mut self, ast: &Ast, wtr: W) -> fmt::Result {
+        visitor::visit(ast, Writer { printer: self, wtr: wtr })
+    }
+}
+
+#[derive(Debug)]
+struct Writer<'p, W> {
+    printer: &'p mut Printer,
+    wtr: W,
+}
+
+impl<'p, W: fmt::Write> Visitor for Writer<'p, W> {
+    type Output = ();
+    type Err = fmt::Error;
+
+    fn finish(self) -> fmt::Result {
+        Ok(())
+    }
+
+    fn visit_pre(&mut self, ast: &Ast) -> fmt::Result {
+        match *ast {
+            Ast::Group(ref x) => self.fmt_group_pre(x),
+            Ast::Class(ast::Class::Bracketed(ref x)) => {
+                self.fmt_class_bracketed_pre(x)
+            }
+            _ => Ok(())
+        }
+    }
+
+    fn visit_post(&mut self, ast: &Ast) -> fmt::Result {
+        use ast::Class;
+
+        match *ast {
+            Ast::Empty(_) => Ok(()),
+            Ast::Flags(ref x) => self.fmt_set_flags(x),
+            Ast::Literal(ref x) => self.fmt_literal(x),
+            Ast::Dot(_) => self.wtr.write_str("."),
+            Ast::Assertion(ref x) => self.fmt_assertion(x),
+            Ast::Class(Class::Perl(ref x)) => self.fmt_class_perl(x),
+            Ast::Class(Class::Unicode(ref x)) => self.fmt_class_unicode(x),
+            Ast::Class(Class::Bracketed(ref x)) => {
+                self.fmt_class_bracketed_post(x)
+            }
+            Ast::Repetition(ref x) => self.fmt_repetition(x),
+            Ast::Group(ref x) => self.fmt_group_post(x),
+            Ast::Alternation(_) => Ok(()),
+            Ast::Concat(_) => Ok(()),
+        }
+    }
+
+    fn visit_alternation_in(&mut self) -> fmt::Result {
+        self.wtr.write_str("|")
+    }
+
+    fn visit_class_set_item_pre(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        match *ast {
+            ast::ClassSetItem::Bracketed(ref x) => {
+                self.fmt_class_bracketed_pre(x)
+            }
+            _ => Ok(()),
+        }
+    }
+
+    fn visit_class_set_item_post(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        use ast::ClassSetItem::*;
+
+        match *ast {
+            Empty(_) => Ok(()),
+            Literal(ref x) => self.fmt_literal(x),
+            Range(ref x) => {
+                self.fmt_literal(&x.start)?;
+                self.wtr.write_str("-")?;
+                self.fmt_literal(&x.end)?;
+                Ok(())
+            }
+            Ascii(ref x) => self.fmt_class_ascii(x),
+            Unicode(ref x) => self.fmt_class_unicode(x),
+            Perl(ref x) => self.fmt_class_perl(x),
+            Bracketed(ref x) => self.fmt_class_bracketed_post(x),
+            Union(_) => Ok(()),
+        }
+    }
+
+    fn visit_class_set_binary_op_in(
+        &mut self,
+        ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        self.fmt_class_set_binary_op_kind(&ast.kind)
+    }
+}
+
+impl<'p, W: fmt::Write> Writer<'p, W> {
+    fn fmt_group_pre(&mut self, ast: &ast::Group) -> fmt::Result {
+        use ast::GroupKind::*;
+        match ast.kind {
+            CaptureIndex(_) => self.wtr.write_str("("),
+            CaptureName(ref x) => {
+                self.wtr.write_str("(?P<")?;
+                self.wtr.write_str(&x.name)?;
+                self.wtr.write_str(">")?;
+                Ok(())
+            }
+            NonCapturing(ref flags) => {
+                self.wtr.write_str("(?")?;
+                self.fmt_flags(flags)?;
+                self.wtr.write_str(":")?;
+                Ok(())
+            }
+        }
+    }
+
+    fn fmt_group_post(&mut self, _ast: &ast::Group) -> fmt::Result {
+        self.wtr.write_str(")")
+    }
+
+    fn fmt_repetition(&mut self, ast: &ast::Repetition) -> fmt::Result {
+        use ast::RepetitionKind::*;
+        match ast.op.kind {
+            ZeroOrOne if ast.greedy => self.wtr.write_str("?"),
+            ZeroOrOne => self.wtr.write_str("??"),
+            ZeroOrMore if ast.greedy => self.wtr.write_str("*"),
+            ZeroOrMore => self.wtr.write_str("*?"),
+            OneOrMore if ast.greedy => self.wtr.write_str("+"),
+            OneOrMore => self.wtr.write_str("+?"),
+            Range(ref x) => {
+                self.fmt_repetition_range(x)?;
+                if !ast.greedy {
+                    self.wtr.write_str("?")?;
+                }
+                Ok(())
+            }
+        }
+    }
+
+    fn fmt_repetition_range(
+        &mut self,
+        ast: &ast::RepetitionRange,
+    ) -> fmt::Result {
+        use ast::RepetitionRange::*;
+        match *ast {
+            Exactly(x) => write!(self.wtr, "{{{}}}", x),
+            AtLeast(x) => write!(self.wtr, "{{{},}}", x),
+            Bounded(x, y) => write!(self.wtr, "{{{},{}}}", x, y),
+        }
+    }
+
+    fn fmt_literal(&mut self, ast: &ast::Literal) -> fmt::Result {
+        use ast::LiteralKind::*;
+
+        match ast.kind {
+            Verbatim => self.wtr.write_char(ast.c),
+            Punctuation => write!(self.wtr, r"\{}", ast.c),
+            Octal => write!(self.wtr, r"\{:o}", ast.c as u32),
+            HexFixed(ast::HexLiteralKind::X) => {
+                write!(self.wtr, r"\x{:02X}", ast.c as u32)
+            }
+            HexFixed(ast::HexLiteralKind::UnicodeShort) => {
+                write!(self.wtr, r"\u{:04X}", ast.c as u32)
+            }
+            HexFixed(ast::HexLiteralKind::UnicodeLong) => {
+                write!(self.wtr, r"\U{:08X}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::X) => {
+                write!(self.wtr, r"\x{{{:X}}}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::UnicodeShort) => {
+                write!(self.wtr, r"\u{{{:X}}}", ast.c as u32)
+            }
+            HexBrace(ast::HexLiteralKind::UnicodeLong) => {
+                write!(self.wtr, r"\U{{{:X}}}", ast.c as u32)
+            }
+            Special(ast::SpecialLiteralKind::Bell) => {
+                self.wtr.write_str(r"\a")
+            }
+            Special(ast::SpecialLiteralKind::FormFeed) => {
+                self.wtr.write_str(r"\f")
+            }
+            Special(ast::SpecialLiteralKind::Tab) => {
+                self.wtr.write_str(r"\t")
+            }
+            Special(ast::SpecialLiteralKind::LineFeed) => {
+                self.wtr.write_str(r"\n")
+            }
+            Special(ast::SpecialLiteralKind::CarriageReturn) => {
+                self.wtr.write_str(r"\r")
+            }
+            Special(ast::SpecialLiteralKind::VerticalTab) => {
+                self.wtr.write_str(r"\v")
+            }
+            Special(ast::SpecialLiteralKind::Space) => {
+                self.wtr.write_str(r"\ ")
+            }
+        }
+    }
+
+    fn fmt_assertion(&mut self, ast: &ast::Assertion) -> fmt::Result {
+        use ast::AssertionKind::*;
+        match ast.kind {
+            StartLine => self.wtr.write_str("^"),
+            EndLine => self.wtr.write_str("$"),
+            StartText => self.wtr.write_str(r"\A"),
+            EndText => self.wtr.write_str(r"\z"),
+            WordBoundary => self.wtr.write_str(r"\b"),
+            NotWordBoundary => self.wtr.write_str(r"\B"),
+        }
+    }
+
+    fn fmt_set_flags(&mut self, ast: &ast::SetFlags) -> fmt::Result {
+        self.wtr.write_str("(?")?;
+        self.fmt_flags(&ast.flags)?;
+        self.wtr.write_str(")")?;
+        Ok(())
+    }
+
+    fn fmt_flags(&mut self, ast: &ast::Flags) -> fmt::Result {
+        use ast::{Flag, FlagsItemKind};
+
+        for item in &ast.items {
+            match item.kind {
+                FlagsItemKind::Negation => self.wtr.write_str("-"),
+                FlagsItemKind::Flag(ref flag) => {
+                    match *flag {
+                        Flag::CaseInsensitive => self.wtr.write_str("i"),
+                        Flag::MultiLine => self.wtr.write_str("m"),
+                        Flag::DotMatchesNewLine => self.wtr.write_str("s"),
+                        Flag::SwapGreed => self.wtr.write_str("U"),
+                        Flag::Unicode => self.wtr.write_str("u"),
+                        Flag::IgnoreWhitespace => self.wtr.write_str("x"),
+                    }
+                }
+            }?;
+        }
+        Ok(())
+    }
+
+    fn fmt_class_bracketed_pre(
+        &mut self,
+        ast: &ast::ClassBracketed,
+    ) -> fmt::Result {
+        if ast.negated {
+            self.wtr.write_str("[^")
+        } else {
+            self.wtr.write_str("[")
+        }
+    }
+
+    fn fmt_class_bracketed_post(
+        &mut self,
+        _ast: &ast::ClassBracketed,
+    ) -> fmt::Result {
+        self.wtr.write_str("]")
+    }
+
+    fn fmt_class_set_binary_op_kind(
+        &mut self,
+        ast: &ast::ClassSetBinaryOpKind,
+    ) -> fmt::Result {
+        use ast::ClassSetBinaryOpKind::*;
+        match *ast {
+            Intersection => self.wtr.write_str("&&"),
+            Difference => self.wtr.write_str("--"),
+            SymmetricDifference => self.wtr.write_str("~~"),
+        }
+    }
+
+    fn fmt_class_perl(&mut self, ast: &ast::ClassPerl) -> fmt::Result {
+        use ast::ClassPerlKind::*;
+        match ast.kind {
+            Digit if ast.negated => self.wtr.write_str(r"\D"),
+            Digit => self.wtr.write_str(r"\d"),
+            Space if ast.negated => self.wtr.write_str(r"\S"),
+            Space => self.wtr.write_str(r"\s"),
+            Word if ast.negated => self.wtr.write_str(r"\W"),
+            Word => self.wtr.write_str(r"\w"),
+        }
+    }
+
+    fn fmt_class_ascii(&mut self, ast: &ast::ClassAscii) -> fmt::Result {
+        use ast::ClassAsciiKind::*;
+        match ast.kind {
+            Alnum if ast.negated => self.wtr.write_str("[:^alnum:]"),
+            Alnum => self.wtr.write_str("[:alnum:]"),
+            Alpha if ast.negated => self.wtr.write_str("[:^alpha:]"),
+            Alpha => self.wtr.write_str("[:alpha:]"),
+            Ascii if ast.negated => self.wtr.write_str("[:^ascii:]"),
+            Ascii => self.wtr.write_str("[:ascii:]"),
+            Blank if ast.negated => self.wtr.write_str("[:^blank:]"),
+            Blank => self.wtr.write_str("[:blank:]"),
+            Cntrl if ast.negated => self.wtr.write_str("[:^cntrl:]"),
+            Cntrl => self.wtr.write_str("[:cntrl:]"),
+            Digit if ast.negated => self.wtr.write_str("[:^digit:]"),
+            Digit => self.wtr.write_str("[:digit:]"),
+            Graph if ast.negated => self.wtr.write_str("[:^graph:]"),
+            Graph => self.wtr.write_str("[:graph:]"),
+            Lower if ast.negated => self.wtr.write_str("[:^lower:]"),
+            Lower => self.wtr.write_str("[:lower:]"),
+            Print if ast.negated => self.wtr.write_str("[:^print:]"),
+            Print => self.wtr.write_str("[:print:]"),
+            Punct if ast.negated => self.wtr.write_str("[:^punct:]"),
+            Punct => self.wtr.write_str("[:punct:]"),
+            Space if ast.negated => self.wtr.write_str("[:^space:]"),
+            Space => self.wtr.write_str("[:space:]"),
+            Upper if ast.negated => self.wtr.write_str("[:^upper:]"),
+            Upper => self.wtr.write_str("[:upper:]"),
+            Word if ast.negated => self.wtr.write_str("[:^word:]"),
+            Word => self.wtr.write_str("[:word:]"),
+            Xdigit if ast.negated => self.wtr.write_str("[:^xdigit:]"),
+            Xdigit => self.wtr.write_str("[:xdigit:]"),
+        }
+    }
+
+    fn fmt_class_unicode(&mut self, ast: &ast::ClassUnicode) -> fmt::Result {
+        use ast::ClassUnicodeKind::*;
+        use ast::ClassUnicodeOpKind::*;
+
+        if ast.negated {
+            self.wtr.write_str(r"\P")?;
+        } else {
+            self.wtr.write_str(r"\p")?;
+        }
+        match ast.kind {
+            OneLetter(c) => self.wtr.write_char(c),
+            Named(ref x) => write!(self.wtr, "{{{}}}", x),
+            NamedValue { op: Equal, ref name, ref value } => {
+                write!(self.wtr, "{{{}={}}}", name, value)
+            }
+            NamedValue { op: Colon, ref name, ref value } => {
+                write!(self.wtr, "{{{}:{}}}", name, value)
+            }
+            NamedValue { op: NotEqual, ref name, ref value } => {
+                write!(self.wtr, "{{{}!={}}}", name, value)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ast::parse::ParserBuilder;
+    use super::Printer;
+
+    fn roundtrip(given: &str) {
+        roundtrip_with(|b| b, given);
+    }
+
+    fn roundtrip_with<F>(mut f: F, given: &str)
+    where F: FnMut(&mut ParserBuilder) -> &mut ParserBuilder
+    {
+        let mut builder = ParserBuilder::new();
+        f(&mut builder);
+        let ast = builder.build().parse(given).unwrap();
+
+        let mut printer = Printer::new();
+        let mut dst = String::new();
+        printer.print(&ast, &mut dst).unwrap();
+        assert_eq!(given, dst);
+    }
+
+    #[test]
+    fn print_literal() {
+        roundtrip("a");
+        roundtrip(r"\[");
+        roundtrip_with(|b| b.octal(true), r"\141");
+        roundtrip(r"\x61");
+        roundtrip(r"\x7F");
+        roundtrip(r"\u0061");
+        roundtrip(r"\U00000061");
+        roundtrip(r"\x{61}");
+        roundtrip(r"\x{7F}");
+        roundtrip(r"\u{61}");
+        roundtrip(r"\U{61}");
+
+        roundtrip(r"\a");
+        roundtrip(r"\f");
+        roundtrip(r"\t");
+        roundtrip(r"\n");
+        roundtrip(r"\r");
+        roundtrip(r"\v");
+        roundtrip(r"(?x)\ ");
+    }
+
+    #[test]
+    fn print_dot() {
+        roundtrip(".");
+    }
+
+    #[test]
+    fn print_concat() {
+        roundtrip("ab");
+        roundtrip("abcde");
+        roundtrip("a(bcd)ef");
+    }
+
+    #[test]
+    fn print_alternation() {
+        roundtrip("a|b");
+        roundtrip("a|b|c|d|e");
+        roundtrip("|a|b|c|d|e");
+        roundtrip("|a|b|c|d|e|");
+        roundtrip("a(b|c|d)|e|f");
+    }
+
+    #[test]
+    fn print_assertion() {
+        roundtrip(r"^");
+        roundtrip(r"$");
+        roundtrip(r"\A");
+        roundtrip(r"\z");
+        roundtrip(r"\b");
+        roundtrip(r"\B");
+    }
+
+    #[test]
+    fn print_repetition() {
+        roundtrip("a?");
+        roundtrip("a??");
+        roundtrip("a*");
+        roundtrip("a*?");
+        roundtrip("a+");
+        roundtrip("a+?");
+        roundtrip("a{5}");
+        roundtrip("a{5}?");
+        roundtrip("a{5,}");
+        roundtrip("a{5,}?");
+        roundtrip("a{5,10}");
+        roundtrip("a{5,10}?");
+    }
+
+    #[test]
+    fn print_flags() {
+        roundtrip("(?i)");
+        roundtrip("(?-i)");
+        roundtrip("(?s-i)");
+        roundtrip("(?-si)");
+        roundtrip("(?siUmux)");
+    }
+
+    #[test]
+    fn print_group() {
+        roundtrip("(?i:a)");
+        roundtrip("(?P<foo>a)");
+        roundtrip("(a)");
+    }
+
+    #[test]
+    fn print_class() {
+        roundtrip(r"[abc]");
+        roundtrip(r"[a-z]");
+        roundtrip(r"[^a-z]");
+        roundtrip(r"[a-z0-9]");
+        roundtrip(r"[-a-z0-9]");
+        roundtrip(r"[-a-z0-9]");
+        roundtrip(r"[a-z0-9---]");
+        roundtrip(r"[a-z&&m-n]");
+        roundtrip(r"[[a-z&&m-n]]");
+        roundtrip(r"[a-z--m-n]");
+        roundtrip(r"[a-z~~m-n]");
+        roundtrip(r"[a-z[0-9]]");
+        roundtrip(r"[a-z[^0-9]]");
+
+        roundtrip(r"\d");
+        roundtrip(r"\D");
+        roundtrip(r"\s");
+        roundtrip(r"\S");
+        roundtrip(r"\w");
+        roundtrip(r"\W");
+
+        roundtrip(r"[[:alnum:]]");
+        roundtrip(r"[[:^alnum:]]");
+        roundtrip(r"[[:alpha:]]");
+        roundtrip(r"[[:^alpha:]]");
+        roundtrip(r"[[:ascii:]]");
+        roundtrip(r"[[:^ascii:]]");
+        roundtrip(r"[[:blank:]]");
+        roundtrip(r"[[:^blank:]]");
+        roundtrip(r"[[:cntrl:]]");
+        roundtrip(r"[[:^cntrl:]]");
+        roundtrip(r"[[:digit:]]");
+        roundtrip(r"[[:^digit:]]");
+        roundtrip(r"[[:graph:]]");
+        roundtrip(r"[[:^graph:]]");
+        roundtrip(r"[[:lower:]]");
+        roundtrip(r"[[:^lower:]]");
+        roundtrip(r"[[:print:]]");
+        roundtrip(r"[[:^print:]]");
+        roundtrip(r"[[:punct:]]");
+        roundtrip(r"[[:^punct:]]");
+        roundtrip(r"[[:space:]]");
+        roundtrip(r"[[:^space:]]");
+        roundtrip(r"[[:upper:]]");
+        roundtrip(r"[[:^upper:]]");
+        roundtrip(r"[[:word:]]");
+        roundtrip(r"[[:^word:]]");
+        roundtrip(r"[[:xdigit:]]");
+        roundtrip(r"[[:^xdigit:]]");
+
+        roundtrip(r"\pL");
+        roundtrip(r"\PL");
+        roundtrip(r"\p{L}");
+        roundtrip(r"\P{L}");
+        roundtrip(r"\p{X=Y}");
+        roundtrip(r"\P{X=Y}");
+        roundtrip(r"\p{X:Y}");
+        roundtrip(r"\P{X:Y}");
+        roundtrip(r"\p{X!=Y}");
+        roundtrip(r"\P{X!=Y}");
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/ast/visitor.rs b/third_party/rust/regex-syntax/src/ast/visitor.rs
new file mode 100644
index 000000000000..9b93a1ae1593
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/ast/visitor.rs
@@ -0,0 +1,557 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+use ast::{self, Ast};
+
+/// A trait for visiting an abstract syntax tree (AST) in depth first order.
+///
+/// The principle aim of this trait is to enable callers to perform case
+/// analysis on an abstract syntax tree without necessarily using recursion.
+/// In particular, this permits callers to do case analysis with constant stack
+/// usage, which can be important since the size of an abstract syntax tree
+/// may be proportional to end user input.
+///
+/// Typical usage of this trait involves providing an implementation and then
+/// running it using the [`visit`](fn.visit.html) function.
+///
+/// Note that the abstract syntax tree for a regular expression is quite
+/// complex. Unless you specifically need it, you might be able to use the
+/// much simpler
+/// [high-level intermediate representation](../hir/struct.Hir.html)
+/// and its
+/// [corresponding `Visitor` trait](../hir/trait.Visitor.html)
+/// instead.
+pub trait Visitor {
+    /// The result of visiting an AST.
+    type Output;
+    /// An error that visiting an AST might return.
+    type Err;
+
+    /// All implementors of `Visitor` must provide a `finish` method, which
+    /// yields the result of visiting the AST or an error.
+    fn finish(self) -> Result<Self::Output, Self::Err>;
+
+    /// This method is called before beginning traversal of the AST.
+    fn start(&mut self) {}
+
+    /// This method is called on an `Ast` before descending into child `Ast`
+    /// nodes.
+    fn visit_pre(&mut self, _ast: &Ast) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on an `Ast` after descending all of its child
+    /// `Ast` nodes.
+    fn visit_post(&mut self, _ast: &Ast) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called between child nodes of an
+    /// [`Alternation`](struct.Alternation.html).
+    fn visit_alternation_in(&mut self) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetItem`](enum.ClassSetItem.html)
+    /// before descending into child nodes.
+    fn visit_class_set_item_pre(
+        &mut self,
+        _ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetItem`](enum.ClassSetItem.html)
+    /// after descending into child nodes.
+    fn visit_class_set_item_post(
+        &mut self,
+        _ast: &ast::ClassSetItem,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html)
+    /// before descending into child nodes.
+    fn visit_class_set_binary_op_pre(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on every
+    /// [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html)
+    /// after descending into child nodes.
+    fn visit_class_set_binary_op_post(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called between the left hand and right hand child nodes
+    /// of a [`ClassSetBinaryOp`](struct.ClassSetBinaryOp.html).
+    fn visit_class_set_binary_op_in(
+        &mut self,
+        _ast: &ast::ClassSetBinaryOp,
+    ) -> Result<(), Self::Err> {
+        Ok(())
+    }
+}
+
+/// Executes an implementation of `Visitor` in constant stack space.
+///
+/// This function will visit every node in the given `Ast` while calling the
+/// appropriate methods provided by the
+/// [`Visitor`](trait.Visitor.html) trait.
+///
+/// The primary use case for this method is when one wants to perform case
+/// analysis over an `Ast` without using a stack size proportional to the depth
+/// of the `Ast`. Namely, this method will instead use constant stack size, but
+/// will use heap space proportional to the size of the `Ast`. This may be
+/// desirable in cases where the size of `Ast` is proportional to end user
+/// input.
+///
+/// If the visitor returns an error at any point, then visiting is stopped and
+/// the error is returned.
+pub fn visit<V: Visitor>(ast: &Ast, visitor: V) -> Result<V::Output, V::Err> {
+    HeapVisitor::new().visit(ast, visitor)
+}
+
+/// HeapVisitor visits every item in an `Ast` recursively using constant stack
+/// size and a heap size proportional to the size of the `Ast`.
+struct HeapVisitor<'a> {
+    /// A stack of `Ast` nodes. This is roughly analogous to the call stack
+    /// used in a typical recursive visitor.
+    stack: Vec<(&'a Ast, Frame<'a>)>,
+    /// Similar to the `Ast` stack above, but is used only for character
+    /// classes. In particular, character classes embed their own mini
+    /// recursive syntax.
+    stack_class: Vec<(ClassInduct<'a>, ClassFrame<'a>)>,
+}
+
+/// Represents a single stack frame while performing structural induction over
+/// an `Ast`.
+enum Frame<'a> {
+    /// A stack frame allocated just before descending into a repetition
+    /// operator's child node.
+    Repetition(&'a ast::Repetition),
+    /// A stack frame allocated just before descending into a group's child
+    /// node.
+    Group(&'a ast::Group),
+    /// The stack frame used while visiting every child node of a concatenation
+    /// of expressions.
+    Concat {
+        /// The child node we are currently visiting.
+        head: &'a Ast,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Ast],
+    },
+    /// The stack frame used while visiting every child node of an alternation
+    /// of expressions.
+    Alternation {
+        /// The child node we are currently visiting.
+        head: &'a Ast,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Ast],
+    },
+}
+
+/// Represents a single stack frame while performing structural induction over
+/// a character class.
+enum ClassFrame<'a> {
+    /// The stack frame used while visiting every child node of a union of
+    /// character class items.
+    Union {
+        /// The child node we are currently visiting.
+        head: &'a ast::ClassSetItem,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [ast::ClassSetItem],
+    },
+    /// The stack frame used while a binary class operation.
+    Binary {
+        op: &'a ast::ClassSetBinaryOp,
+    },
+    /// A stack frame allocated just before descending into a binary operator's
+    /// left hand child node.
+    BinaryLHS {
+        op: &'a ast::ClassSetBinaryOp,
+        lhs: &'a ast::ClassSet,
+        rhs: &'a ast::ClassSet,
+    },
+    /// A stack frame allocated just before descending into a binary operator's
+    /// right hand child node.
+    BinaryRHS {
+        op: &'a ast::ClassSetBinaryOp,
+        rhs: &'a ast::ClassSet,
+    },
+}
+
+/// A representation of the inductive step when performing structural induction
+/// over a character class.
+///
+/// Note that there is no analogous explicit type for the inductive step for
+/// `Ast` nodes because the inductive step is just an `Ast`. For character
+/// classes, the inductive step can produce one of two possible child nodes:
+/// an item or a binary operation. (An item cannot be a binary operation
+/// because that would imply binary operations can be unioned in the concrete
+/// syntax, which is not possible.)
+enum ClassInduct<'a> {
+    Item(&'a ast::ClassSetItem),
+    BinaryOp(&'a ast::ClassSetBinaryOp),
+}
+
+impl<'a> HeapVisitor<'a> {
+    fn new() -> HeapVisitor<'a> {
+        HeapVisitor { stack: vec![], stack_class: vec![] }
+    }
+
+    fn visit<V: Visitor>(
+        &mut self,
+        mut ast: &'a Ast,
+        mut visitor: V,
+    ) -> Result<V::Output, V::Err> {
+        self.stack.clear();
+        self.stack_class.clear();
+
+        visitor.start();
+        loop {
+            visitor.visit_pre(ast)?;
+            if let Some(x) = self.induct(ast, &mut visitor)? {
+                let child = x.child();
+                self.stack.push((ast, x));
+                ast = child;
+                continue;
+            }
+            // No induction means we have a base case, so we can post visit
+            // it now.
+            visitor.visit_post(ast)?;
+
+            // At this point, we now try to pop our call stack until it is
+            // either empty or we hit another inductive case.
+            loop {
+                let (post_ast, frame) = match self.stack.pop() {
+                    None => return visitor.finish(),
+                    Some((post_ast, frame)) => (post_ast, frame),
+                };
+                // If this is a concat/alternate, then we might have additional
+                // inductive steps to process.
+                if let Some(x) = self.pop(frame) {
+                    if let Frame::Alternation {..} = x {
+                        visitor.visit_alternation_in()?;
+                    }
+                    ast = x.child();
+                    self.stack.push((post_ast, x));
+                    break;
+                }
+                // Otherwise, we've finished visiting all the child nodes for
+                // this AST, so we can post visit it now.
+                visitor.visit_post(post_ast)?;
+            }
+        }
+    }
+
+    /// Build a stack frame for the given AST if one is needed (which occurs if
+    /// and only if there are child nodes in the AST). Otherwise, return None.
+    ///
+    /// If this visits a class, then the underlying visitor implementation may
+    /// return an error which will be passed on here.
+    fn induct<V: Visitor>(
+        &mut self,
+        ast: &'a Ast,
+        visitor: &mut V,
+    ) -> Result<Option<Frame<'a>>, V::Err> {
+        Ok(match *ast {
+            Ast::Class(ast::Class::Bracketed(ref x)) => {
+                self.visit_class(x, visitor)?;
+                None
+            }
+            Ast::Repetition(ref x) => Some(Frame::Repetition(x)),
+            Ast::Group(ref x) => Some(Frame::Group(x)),
+            Ast::Concat(ref x) if x.asts.is_empty() => None,
+            Ast::Concat(ref x) => {
+                Some(Frame::Concat {
+                    head: &x.asts[0],
+                    tail: &x.asts[1..],
+                })
+            }
+            Ast::Alternation(ref x) if x.asts.is_empty() => None,
+            Ast::Alternation(ref x) => {
+                Some(Frame::Alternation {
+                    head: &x.asts[0],
+                    tail: &x.asts[1..],
+                })
+            }
+            _ => None,
+        })
+    }
+
+    /// Pops the given frame. If the frame has an additional inductive step,
+    /// then return it, otherwise return `None`.
+    fn pop(&self, induct: Frame<'a>) -> Option<Frame<'a>> {
+        match induct {
+            Frame::Repetition(_) => None,
+            Frame::Group(_) => None,
+            Frame::Concat { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Concat {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+            Frame::Alternation { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Alternation {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+        }
+    }
+
+    fn visit_class<V: Visitor>(
+        &mut self,
+        ast: &'a ast::ClassBracketed,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        let mut ast = ClassInduct::from_bracketed(ast);
+        loop {
+            self.visit_class_pre(&ast, visitor)?;
+            if let Some(x) = self.induct_class(&ast) {
+                let child = x.child();
+                self.stack_class.push((ast, x));
+                ast = child;
+                continue;
+            }
+            self.visit_class_post(&ast, visitor)?;
+
+            // At this point, we now try to pop our call stack until it is
+            // either empty or we hit another inductive case.
+            loop {
+                let (post_ast, frame) = match self.stack_class.pop() {
+                    None => return Ok(()),
+                    Some((post_ast, frame)) => (post_ast, frame),
+                };
+                // If this is a union or a binary op, then we might have
+                // additional inductive steps to process.
+                if let Some(x) = self.pop_class(frame) {
+                    if let ClassFrame::BinaryRHS { ref op, .. } = x {
+                        visitor.visit_class_set_binary_op_in(op)?;
+                    }
+                    ast = x.child();
+                    self.stack_class.push((post_ast, x));
+                    break;
+                }
+                // Otherwise, we've finished visiting all the child nodes for
+                // this class node, so we can post visit it now.
+                self.visit_class_post(&post_ast, visitor)?;
+            }
+        }
+    }
+
+    /// Call the appropriate `Visitor` methods given an inductive step.
+    fn visit_class_pre<V: Visitor>(
+        &self,
+        ast: &ClassInduct<'a>,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        match *ast {
+            ClassInduct::Item(item) => {
+                visitor.visit_class_set_item_pre(item)?;
+            }
+            ClassInduct::BinaryOp(op) => {
+                visitor.visit_class_set_binary_op_pre(op)?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Call the appropriate `Visitor` methods given an inductive step.
+    fn visit_class_post<V: Visitor>(
+        &self,
+        ast: &ClassInduct<'a>,
+        visitor: &mut V,
+    ) -> Result<(), V::Err> {
+        match *ast {
+            ClassInduct::Item(item) => {
+                visitor.visit_class_set_item_post(item)?;
+            }
+            ClassInduct::BinaryOp(op) => {
+                visitor.visit_class_set_binary_op_post(op)?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Build a stack frame for the given class node if one is needed (which
+    /// occurs if and only if there are child nodes). Otherwise, return None.
+    fn induct_class(
+        &self,
+        ast: &ClassInduct<'a>,
+    ) -> Option<ClassFrame<'a>> {
+        match *ast {
+            ClassInduct::Item(&ast::ClassSetItem::Bracketed(ref x)) => {
+                match x.kind {
+                    ast::ClassSet::Item(ref item) => {
+                        Some(ClassFrame::Union {
+                            head: item,
+                            tail: &[],
+                        })
+                    }
+                    ast::ClassSet::BinaryOp(ref op) => {
+                        Some(ClassFrame::Binary { op: op })
+                    }
+                }
+            }
+            ClassInduct::Item(&ast::ClassSetItem::Union(ref x)) => {
+                if x.items.is_empty() {
+                    None
+                } else {
+                    Some(ClassFrame::Union {
+                        head: &x.items[0],
+                        tail: &x.items[1..],
+                    })
+                }
+            }
+            ClassInduct::BinaryOp(op) => {
+                Some(ClassFrame::BinaryLHS {
+                    op: op,
+                    lhs: &op.lhs,
+                    rhs: &op.rhs,
+                })
+            }
+            _ => None,
+        }
+    }
+
+    /// Pops the given frame. If the frame has an additional inductive step,
+    /// then return it, otherwise return `None`.
+    fn pop_class(&self, induct: ClassFrame<'a>) -> Option<ClassFrame<'a>> {
+        match induct {
+            ClassFrame::Union { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(ClassFrame::Union {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+            ClassFrame::Binary {..} => None,
+            ClassFrame::BinaryLHS { op, rhs, .. } => {
+                Some(ClassFrame::BinaryRHS {
+                    op: op,
+                    rhs: rhs,
+                })
+            }
+            ClassFrame::BinaryRHS {..} => None,
+        }
+    }
+}
+
+impl<'a> Frame<'a> {
+    /// Perform the next inductive step on this frame and return the next
+    /// child AST node to visit.
+    fn child(&self) -> &'a Ast {
+        match *self {
+            Frame::Repetition(rep) => &rep.ast,
+            Frame::Group(group) => &group.ast,
+            Frame::Concat { head, .. } => head,
+            Frame::Alternation { head, .. } => head,
+        }
+    }
+}
+
+impl<'a> ClassFrame<'a> {
+    /// Perform the next inductive step on this frame and return the next
+    /// child class node to visit.
+    fn child(&self) -> ClassInduct<'a> {
+        match *self {
+            ClassFrame::Union { head, .. } => ClassInduct::Item(head),
+            ClassFrame::Binary { op, .. } => ClassInduct::BinaryOp(op),
+            ClassFrame::BinaryLHS { ref lhs, .. } => {
+                ClassInduct::from_set(lhs)
+            }
+            ClassFrame::BinaryRHS { ref rhs, .. } => {
+                ClassInduct::from_set(rhs)
+            }
+        }
+    }
+}
+
+impl<'a> ClassInduct<'a> {
+    fn from_bracketed(ast: &'a ast::ClassBracketed) -> ClassInduct<'a> {
+        ClassInduct::from_set(&ast.kind)
+    }
+
+    fn from_set(ast: &'a ast::ClassSet) -> ClassInduct<'a> {
+        match *ast {
+            ast::ClassSet::Item(ref item) => ClassInduct::Item(item),
+            ast::ClassSet::BinaryOp(ref op) => ClassInduct::BinaryOp(op),
+        }
+    }
+}
+
+impl<'a> fmt::Debug for ClassFrame<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let x = match *self {
+            ClassFrame::Union{..} => "Union",
+            ClassFrame::Binary{..} => "Binary",
+            ClassFrame::BinaryLHS{..} => "BinaryLHS",
+            ClassFrame::BinaryRHS{..} => "BinaryRHS",
+        };
+        write!(f, "{}", x)
+    }
+}
+
+impl<'a> fmt::Debug for ClassInduct<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let x = match *self {
+            ClassInduct::Item(it) => {
+                match *it {
+                    ast::ClassSetItem::Empty(_) => "Item(Empty)",
+                    ast::ClassSetItem::Literal(_) => "Item(Literal)",
+                    ast::ClassSetItem::Range(_) => "Item(Range)",
+                    ast::ClassSetItem::Ascii(_) => "Item(Ascii)",
+                    ast::ClassSetItem::Perl(_) => "Item(Perl)",
+                    ast::ClassSetItem::Unicode(_) => "Item(Unicode)",
+                    ast::ClassSetItem::Bracketed(_) => "Item(Bracketed)",
+                    ast::ClassSetItem::Union(_) => "Item(Union)",
+                }
+            }
+            ClassInduct::BinaryOp(it) => {
+                match it.kind {
+                    ast::ClassSetBinaryOpKind::Intersection => {
+                        "BinaryOp(Intersection)"
+                    }
+                    ast::ClassSetBinaryOpKind::Difference => {
+                        "BinaryOp(Difference)"
+                    }
+                    ast::ClassSetBinaryOpKind::SymmetricDifference => {
+                        "BinaryOp(SymmetricDifference)"
+                    }
+                }
+            }
+        };
+        write!(f, "{}", x)
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/either.rs b/third_party/rust/regex-syntax/src/either.rs
new file mode 100644
index 000000000000..7ae41e4ced74
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/either.rs
@@ -0,0 +1,8 @@
+/// A simple binary sum type.
+///
+/// This is occasionally useful in an ad hoc fashion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Either<Left, Right> {
+    Left(Left),
+    Right(Right),
+}
diff --git a/third_party/rust/regex-syntax/src/error.rs b/third_party/rust/regex-syntax/src/error.rs
new file mode 100644
index 000000000000..1f5b8f817d80
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/error.rs
@@ -0,0 +1,297 @@
+use std::cmp;
+use std::error;
+use std::fmt;
+use std::result;
+
+use ast;
+use hir;
+
+/// A type alias for dealing with errors returned by this crate.
+pub type Result<T> = result::Result<T, Error>;
+
+/// This error type encompasses any error that can be returned by this crate.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Error {
+    /// An error that occurred while translating concrete syntax into abstract
+    /// syntax (AST).
+    Parse(ast::Error),
+    /// An error that occurred while translating abstract syntax into a high
+    /// level intermediate representation (HIR).
+    Translate(hir::Error),
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl From<ast::Error> for Error {
+    fn from(err: ast::Error) -> Error {
+        Error::Parse(err)
+    }
+}
+
+impl From<hir::Error> for Error {
+    fn from(err: hir::Error) -> Error {
+        Error::Translate(err)
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        match *self {
+            Error::Parse(ref x) => x.description(),
+            Error::Translate(ref x) => x.description(),
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Parse(ref x) => x.fmt(f),
+            Error::Translate(ref x) => x.fmt(f),
+            _ => unreachable!(),
+        }
+    }
+}
+
+/// A helper type for formatting nice error messages.
+///
+/// This type is responsible for reporting regex parse errors in a nice human
+/// readable format. Most of its complexity is from interspersing notational
+/// markers pointing out the position where an error occurred.
+#[derive(Debug)]
+pub struct Formatter<'e, E: 'e> {
+    /// The original regex pattern in which the error occurred.
+    pattern: &'e str,
+    /// The error kind. It must impl fmt::Display.
+    err: &'e E,
+    /// The primary span of the error.
+    span: &'e ast::Span,
+    /// An auxiliary and optional span, in case the error needs to point to
+    /// two locations (e.g., when reporting a duplicate capture group name).
+    aux_span: Option<&'e ast::Span>,
+}
+
+impl<'e> From<&'e ast::Error> for Formatter<'e, ast::ErrorKind> {
+    fn from(err: &'e ast::Error) -> Self {
+        Formatter {
+            pattern: err.pattern(),
+            err: err.kind(),
+            span: err.span(),
+            aux_span: err.auxiliary_span(),
+        }
+    }
+}
+
+impl<'e> From<&'e hir::Error> for Formatter<'e, hir::ErrorKind> {
+    fn from(err: &'e hir::Error) -> Self {
+        Formatter {
+            pattern: err.pattern(),
+            err: err.kind(),
+            span: err.span(),
+            aux_span: None,
+        }
+    }
+}
+
+impl<'e, E: fmt::Display> fmt::Display for Formatter<'e, E> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let spans = Spans::from_formatter(self);
+        if self.pattern.contains('\n') {
+            let divider = repeat_char('~', 79);
+
+            writeln!(f, "regex parse error:")?;
+            writeln!(f, "{}", divider)?;
+            let notated = spans.notate();
+            write!(f, "{}", notated)?;
+            writeln!(f, "{}", divider)?;
+            // If we have error spans that cover multiple lines, then we just
+            // note the line numbers.
+            if !spans.multi_line.is_empty() {
+                let mut notes = vec![];
+                for span in &spans.multi_line {
+                    notes.push(format!(
+                        "on line {} (column {}) through line {} (column {})",
+                        span.start.line, span.start.column,
+                        span.end.line, span.end.column - 1));
+                }
+                writeln!(f, "{}", notes.join("\n"))?;
+            }
+            write!(f, "error: {}", self.err)?;
+        } else {
+            writeln!(f, "regex parse error:")?;
+            let notated = Spans::from_formatter(self).notate();
+            write!(f, "{}", notated)?;
+            write!(f, "error: {}", self.err)?;
+        }
+        Ok(())
+    }
+}
+
+/// This type represents an arbitrary number of error spans in a way that makes
+/// it convenient to notate the regex pattern. ("Notate" means "point out
+/// exactly where the error occurred in the regex pattern.")
+///
+/// Technically, we can only ever have two spans given our current error
+/// structure. However, after toiling with a specific algorithm for handling
+/// two spans, it became obvious that an algorithm to handle an arbitrary
+/// number of spans was actually much simpler.
+struct Spans<'p> {
+    /// The original regex pattern string.
+    pattern: &'p str,
+    /// The total width that should be used for line numbers. The width is
+    /// used for left padding the line numbers for alignment.
+    ///
+    /// A value of `0` means line numbers should not be displayed. That is,
+    /// the pattern is itself only one line.
+    line_number_width: usize,
+    /// All error spans that occur on a single line. This sequence always has
+    /// length equivalent to the number of lines in `pattern`, where the index
+    /// of the sequence represents a line number, starting at `0`. The spans
+    /// in each line are sorted in ascending order.
+    by_line: Vec<Vec<ast::Span>>,
+    /// All error spans that occur over one or more lines. That is, the start
+    /// and end position of the span have different line numbers. The spans are
+    /// sorted in ascending order.
+    multi_line: Vec<ast::Span>,
+}
+
+impl<'p> Spans<'p> {
+    /// Build a sequence of spans from a formatter.
+    fn from_formatter<'e, E: fmt::Display>(
+        fmter: &'p Formatter<'e, E>,
+    ) -> Spans<'p> {
+        let mut line_count = fmter.pattern.lines().count();
+        // If the pattern ends with a `\n` literal, then our line count is
+        // off by one, since a span can occur immediately after the last `\n`,
+        // which is consider to be an additional line.
+        if fmter.pattern.ends_with('\n') {
+            line_count += 1;
+        }
+        let line_number_width =
+            if line_count <= 1 {
+                0
+            } else {
+                line_count.to_string().len()
+            };
+        let mut spans = Spans {
+            pattern: &fmter.pattern,
+            line_number_width: line_number_width,
+            by_line: vec![vec![]; line_count],
+            multi_line: vec![],
+        };
+        spans.add(fmter.span.clone());
+        if let Some(span) = fmter.aux_span {
+            spans.add(span.clone());
+        }
+        spans
+    }
+
+    /// Add the given span to this sequence, putting it in the right place.
+    fn add(&mut self, span: ast::Span) {
+        // This is grossly inefficient since we sort after each add, but right
+        // now, we only ever add two spans at most.
+        if span.is_one_line() {
+            let i = span.start.line - 1; // because lines are 1-indexed
+            self.by_line[i].push(span);
+            self.by_line[i].sort();
+        } else {
+            self.multi_line.push(span);
+            self.multi_line.sort();
+        }
+    }
+
+    /// Notate the pattern string with carents (`^`) pointing at each span
+    /// location. This only applies to spans that occur within a single line.
+    fn notate(&self) -> String {
+        let mut notated = String::new();
+        for (i, line) in self.pattern.lines().enumerate() {
+            if self.line_number_width > 0 {
+                notated.push_str(&self.left_pad_line_number(i + 1));
+                notated.push_str(": ");
+            } else {
+                notated.push_str("    ");
+            }
+            notated.push_str(line);
+            notated.push('\n');
+            if let Some(notes) = self.notate_line(i) {
+                notated.push_str(&notes);
+                notated.push('\n');
+            }
+        }
+        notated
+    }
+
+    /// Return notes for the line indexed at `i` (zero-based). If there are no
+    /// spans for the given line, then `None` is returned. Otherwise, an
+    /// appropriately space padded string with correctly positioned `^` is
+    /// returned, accounting for line numbers.
+    fn notate_line(&self, i: usize) -> Option<String> {
+        let spans = &self.by_line[i];
+        if spans.is_empty() {
+            return None;
+        }
+        let mut notes = String::new();
+        for _ in 0..self.line_number_padding() {
+            notes.push(' ');
+        }
+        let mut pos = 0;
+        for span in spans {
+            for _ in pos..(span.start.column - 1) {
+                notes.push(' ');
+                pos += 1;
+            }
+            let note_len = span.end.column.saturating_sub(span.start.column);
+            for _ in 0..cmp::max(1, note_len) {
+                notes.push('^');
+                pos += 1;
+            }
+        }
+        Some(notes)
+    }
+
+    /// Left pad the given line number with spaces such that it is aligned with
+    /// other line numbers.
+    fn left_pad_line_number(&self, n: usize) -> String {
+        let n = n.to_string();
+        let pad = self.line_number_width.checked_sub(n.len()).unwrap();
+        let mut result = repeat_char(' ', pad);
+        result.push_str(&n);
+        result
+    }
+
+    /// Return the line number padding beginning at the start of each line of
+    /// the pattern.
+    ///
+    /// If the pattern is only one line, then this returns a fixed padding
+    /// for visual indentation.
+    fn line_number_padding(&self) -> usize {
+        if self.line_number_width == 0 {
+            4
+        } else {
+            2 + self.line_number_width
+        }
+    }
+}
+
+fn repeat_char(c: char, count: usize) -> String {
+    ::std::iter::repeat(c).take(count).collect()
+}
+
+#[cfg(test)]
+mod tests {
+    use ast::parse::Parser;
+
+    // See: https://github.com/rust-lang/regex/issues/464
+    #[test]
+    fn regression_464() {
+        let err = Parser::new().parse("a{\n").unwrap_err();
+        // This test checks that the error formatter doesn't panic.
+        assert!(!err.to_string().is_empty());
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/hir/interval.rs b/third_party/rust/regex-syntax/src/hir/interval.rs
new file mode 100644
index 000000000000..a7e70ef59642
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/interval.rs
@@ -0,0 +1,490 @@
+use std::char;
+use std::cmp;
+use std::fmt::Debug;
+use std::slice;
+use std::u8;
+
+// This module contains an *internal* implementation of interval sets.
+//
+// The primary invariant that interval sets guards is canonical ordering. That
+// is, every interval set contains an ordered sequence of intervals where
+// no two intervals are overlapping or adjacent. While this invariant is
+// ocassionally broken within the implementation, it should be impossible for
+// callers to observe it.
+//
+// Since case folding (as implemented below) breaks that invariant, we roll
+// that into this API even though it is a little out of place in an otherwise
+// generic interval set.
+//
+// Some of the implementation complexity here is a result of me wanting to
+// preserve the sequential representation without using additional memory.
+// In many cases, we do use linear extra memory, but it is at most 2x and it
+// is amortized. If we relaxed the memory requirements, this implementation
+// could become much simpler. The extra memory is honestly probably OK, but
+// character classes (especially of the Unicode variety) can become quite
+// large, and it would be nice to keep regex compilation snappy even in debug
+// builds. (In the past, I have been careless with this area of code and it has
+// caused slow regex compilations in debug mode, so this isn't entirely
+// unwarranted.)
+//
+// Tests on this are relegated to the public API of HIR in src/hir.rs.
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct IntervalSet<I> {
+    ranges: Vec<I>,
+}
+
+impl<I: Interval> IntervalSet<I> {
+    /// Create a new set from a sequence of intervals. Each interval is
+    /// specified as a pair of bounds, where both bounds are inclusive.
+    ///
+    /// The given ranges do not need to be in any specific order, and ranges
+    /// may overlap.
+    pub fn new<T: IntoIterator<Item=I>>(intervals: T) -> IntervalSet<I> {
+        let mut set = IntervalSet { ranges: intervals.into_iter().collect() };
+        set.canonicalize();
+        set
+    }
+
+    /// Add a new interval to this set.
+    pub fn push(&mut self, interval: I) {
+        // TODO: This could be faster. e.g., Push the interval such that
+        // it preserves canonicalization.
+        self.ranges.push(interval);
+        self.canonicalize();
+    }
+
+    /// Return an iterator over all intervals in this set.
+    ///
+    /// The iterator yields intervals in ascending order.
+    pub fn iter(&self) -> IntervalSetIter<I> {
+        IntervalSetIter(self.ranges.iter())
+    }
+
+    /// Return an immutable slice of intervals in this set.
+    ///
+    /// The sequence returned is in canonical ordering.
+    pub fn intervals(&self) -> &[I] {
+        &self.ranges
+    }
+
+    /// Expand this interval set such that it contains all case folded
+    /// characters. For example, if this class consists of the range `a-z`,
+    /// then applying case folding will result in the class containing both the
+    /// ranges `a-z` and `A-Z`.
+    pub fn case_fold_simple(&mut self) {
+        let len = self.ranges.len();
+        for i in 0..len {
+            let range = self.ranges[i];
+            range.case_fold_simple(&mut self.ranges);
+        }
+        self.canonicalize();
+    }
+
+    /// Union this set with the given set, in place.
+    pub fn union(&mut self, other: &IntervalSet<I>) {
+        // This could almost certainly be done more efficiently.
+        self.ranges.extend(&other.ranges);
+        self.canonicalize();
+    }
+
+    /// Intersect this set with the given set, in place.
+    pub fn intersect(&mut self, other: &IntervalSet<I>) {
+        if self.ranges.is_empty() {
+            return;
+        }
+        if other.ranges.is_empty() {
+            self.ranges.clear();
+            return;
+        }
+
+        // There should be a way to do this in-place with constant memory,
+        // but I couldn't figure out a simple way to do it. So just append
+        // the intersection to the end of this range, and then drain it before
+        // we're done.
+        let drain_end = self.ranges.len();
+
+        let mut ita = (0..drain_end).into_iter();
+        let mut itb = (0..other.ranges.len()).into_iter();
+        let mut a = ita.next().unwrap();
+        let mut b = itb.next().unwrap();
+        loop {
+            if let Some(ab) = self.ranges[a].intersect(&other.ranges[b]) {
+                self.ranges.push(ab);
+            }
+            let (it, aorb) =
+                if self.ranges[a].upper() < other.ranges[b].upper() {
+                    (&mut ita, &mut a)
+                } else {
+                    (&mut itb, &mut b)
+                };
+            match it.next() {
+                Some(v) => *aorb = v,
+                None => break,
+            }
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Subtract the given set from this set, in place.
+    pub fn difference(&mut self, other: &IntervalSet<I>) {
+        if self.ranges.is_empty() || other.ranges.is_empty() {
+            return;
+        }
+
+        // This algorithm is (to me) surprisingly complex. A search of the
+        // interwebs indicate that this is a potentially interesting problem.
+        // Folks seem to suggest interval or segment trees, but I'd like to
+        // avoid the overhead (both runtime and conceptual) of that.
+        //
+        // The following is basically my Shitty First Draft. Therefore, in
+        // order to grok it, you probably need to read each line carefully.
+        // Simplifications are most welcome!
+        //
+        // Remember, we can assume the canonical format invariant here, which
+        // says that all ranges are sorted, not overlapping and not adjacent in
+        // each class.
+        let drain_end = self.ranges.len();
+        let (mut a, mut b) = (0, 0);
+    'LOOP:
+        while a < drain_end && b < other.ranges.len() {
+            // Basically, the easy cases are when neither range overlaps with
+            // each other. If the `b` range is less than our current `a`
+            // range, then we can skip it and move on.
+            if other.ranges[b].upper() < self.ranges[a].lower() {
+                b += 1;
+                continue;
+            }
+            // ... similarly for the `a` range. If it's less than the smallest
+            // `b` range, then we can add it as-is.
+            if self.ranges[a].upper() < other.ranges[b].lower() {
+                let range = self.ranges[a];
+                self.ranges.push(range);
+                a += 1;
+                continue;
+            }
+            // Otherwise, we have overlapping ranges.
+            assert!(!self.ranges[a].is_intersection_empty(&other.ranges[b]));
+
+            // This part is tricky and was non-obvious to me without looking
+            // at explicit examples (see the tests). The trickiness stems from
+            // two things: 1) subtracting a range from another range could
+            // yield two ranges and 2) after subtracting a range, it's possible
+            // that future ranges can have an impact. The loop below advances
+            // the `b` ranges until they can't possible impact the current
+            // range.
+            //
+            // For example, if our `a` range is `a-t` and our next three `b`
+            // ranges are `a-c`, `g-i`, `r-t` and `x-z`, then we need to apply
+            // subtraction three times before moving on to the next `a` range.
+            let mut range = self.ranges[a];
+            while b < other.ranges.len()
+                && !range.is_intersection_empty(&other.ranges[b])
+            {
+                let old_range = range;
+                range = match range.difference(&other.ranges[b]) {
+                    (None, None) => {
+                        // We lost the entire range, so move on to the next
+                        // without adding this one.
+                        a += 1;
+                        continue 'LOOP;
+                    }
+                    (Some(range1), None) | (None, Some(range1)) => range1,
+                    (Some(range1), Some(range2)) => {
+                        self.ranges.push(range1);
+                        range2
+                    }
+                };
+                // It's possible that the `b` range has more to contribute
+                // here. In particular, if it is greater than the original
+                // range, then it might impact the next `a` range *and* it
+                // has impacted the current `a` range as much as possible,
+                // so we can quit. We don't bump `b` so that the next `a`
+                // range can apply it.
+                if other.ranges[b].upper() > old_range.upper() {
+                    break;
+                }
+                // Otherwise, the next `b` range might apply to the current
+                // `a` range.
+                b += 1;
+            }
+            self.ranges.push(range);
+            a += 1;
+        }
+        while a < drain_end {
+            let range = self.ranges[a];
+            self.ranges.push(range);
+            a += 1;
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Compute the symmetric difference of the two sets, in place.
+    ///
+    /// This computes the symmetric difference of two interval sets. This
+    /// removes all elements in this set that are also in the given set,
+    /// but also adds all elements from the given set that aren't in this
+    /// set. That is, the set will contain all elements in either set,
+    /// but will not contain any elements that are in both sets.
+    pub fn symmetric_difference(&mut self, other: &IntervalSet<I>) {
+        // TODO(burntsushi): Fix this so that it amortizes allocation.
+        let mut intersection = self.clone();
+        intersection.intersect(other);
+        self.union(other);
+        self.difference(&intersection);
+    }
+
+    /// Negate this interval set.
+    ///
+    /// For all `x` where `x` is any element, if `x` was in this set, then it
+    /// will not be in this set after negation.
+    pub fn negate(&mut self) {
+        if self.ranges.is_empty() {
+            let (min, max) = (I::Bound::min_value(), I::Bound::max_value());
+            self.ranges.push(I::create(min, max));
+            return;
+        }
+
+        // There should be a way to do this in-place with constant memory,
+        // but I couldn't figure out a simple way to do it. So just append
+        // the negation to the end of this range, and then drain it before
+        // we're done.
+        let drain_end = self.ranges.len();
+
+        // We do checked arithmetic below because of the canonical ordering
+        // invariant.
+        if self.ranges[0].lower() > I::Bound::min_value() {
+            let upper = self.ranges[0].lower().decrement();
+            self.ranges.push(I::create(I::Bound::min_value(), upper));
+        }
+        for i in 1..drain_end {
+            let lower = self.ranges[i - 1].upper().increment();
+            let upper = self.ranges[i].lower().decrement();
+            self.ranges.push(I::create(lower, upper));
+        }
+        if self.ranges[drain_end - 1].upper() < I::Bound::max_value() {
+            let lower = self.ranges[drain_end - 1].upper().increment();
+            self.ranges.push(I::create(lower, I::Bound::max_value()));
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Converts this set into a canonical ordering.
+    fn canonicalize(&mut self) {
+        if self.is_canonical() {
+            return;
+        }
+        self.ranges.sort();
+        assert!(!self.ranges.is_empty());
+
+        // Is there a way to do this in-place with constant memory? I couldn't
+        // figure out a way to do it. So just append the canonicalization to
+        // the end of this range, and then drain it before we're done.
+        let drain_end = self.ranges.len();
+        for oldi in 0..drain_end {
+            // If we've added at least one new range, then check if we can
+            // merge this range in the previously added range.
+            if self.ranges.len() > drain_end {
+                let (last, rest) = self.ranges.split_last_mut().unwrap();
+                if let Some(union) = last.union(&rest[oldi]) {
+                    *last = union;
+                    continue;
+                }
+            }
+            let range = self.ranges[oldi];
+            self.ranges.push(range);
+        }
+        self.ranges.drain(..drain_end);
+    }
+
+    /// Returns true if and only if this class is in a canonical ordering.
+    fn is_canonical(&self) -> bool {
+        for pair in self.ranges.windows(2) {
+            if pair[0] >= pair[1] {
+                return false;
+            }
+            if pair[0].is_contiguous(&pair[1]) {
+                return false;
+            }
+        }
+        true
+    }
+}
+
+/// An iterator over intervals.
+#[derive(Debug)]
+pub struct IntervalSetIter<'a, I: 'a>(slice::Iter<'a, I>);
+
+impl<'a, I> Iterator for IntervalSetIter<'a, I> {
+    type Item = &'a I;
+
+    fn next(&mut self) -> Option<&'a I> {
+        self.0.next()
+    }
+}
+
+pub trait Interval:
+    Clone + Copy + Debug + Default + Eq + PartialEq + PartialOrd + Ord
+{
+    type Bound: Bound;
+
+    fn lower(&self) -> Self::Bound;
+    fn upper(&self) -> Self::Bound;
+    fn set_lower(&mut self, bound: Self::Bound);
+    fn set_upper(&mut self, bound: Self::Bound);
+    fn case_fold_simple(&self, intervals: &mut Vec<Self>);
+
+    /// Create a new interval.
+    fn create(lower: Self::Bound, upper: Self::Bound) -> Self {
+        let mut int = Self::default();
+        if lower <= upper {
+            int.set_lower(lower);
+            int.set_upper(upper);
+        } else {
+            int.set_lower(upper);
+            int.set_upper(lower);
+        }
+        int
+    }
+
+    /// Union the given overlapping range into this range.
+    ///
+    /// If the two ranges aren't contiguous, then this returns `None`.
+    fn union(&self, other: &Self) -> Option<Self> {
+        if !self.is_contiguous(other) {
+            return None;
+        }
+        let lower = cmp::min(self.lower(), other.lower());
+        let upper = cmp::max(self.upper(), other.upper());
+        Some(Self::create(lower, upper))
+    }
+
+    /// Intersect this range with the given range and return the result.
+    ///
+    /// If the intersection is empty, then this returns `None`.
+    fn intersect(&self, other: &Self) -> Option<Self> {
+        let lower = cmp::max(self.lower(), other.lower());
+        let upper = cmp::min(self.upper(), other.upper());
+        if lower <= upper {
+            Some(Self::create(lower, upper))
+        } else {
+            None
+        }
+    }
+
+    /// Subtract the given range from this range and return the resulting
+    /// ranges.
+    ///
+    /// If subtraction would result in an empty range, then no ranges are
+    /// returned.
+    fn difference(&self, other: &Self) -> (Option<Self>, Option<Self>) {
+        if self.is_subset(other) {
+            return (None, None);
+        }
+        if self.is_intersection_empty(other) {
+            return (Some(self.clone()), None);
+        }
+        let add_lower = other.lower() > self.lower();
+        let add_upper = other.upper() < self.upper();
+        // We know this because !self.is_subset(other) and the ranges have
+        // a non-empty intersection.
+        assert!(add_lower || add_upper);
+        let mut ret = (None, None);
+        if add_lower {
+            let upper = other.lower().decrement();
+            ret.0 = Some(Self::create(self.lower(), upper));
+        }
+        if add_upper {
+            let lower = other.upper().increment();
+            let range = Self::create(lower, self.upper());
+            if ret.0.is_none() {
+                ret.0 = Some(range);
+            } else {
+                ret.1 = Some(range);
+            }
+        }
+        ret
+    }
+
+    /// Compute the symmetric difference the given range from this range. This
+    /// returns the union of the two ranges minus its intersection.
+    fn symmetric_difference(
+        &self,
+        other: &Self,
+    ) -> (Option<Self>, Option<Self>) {
+        let union = match self.union(other) {
+            None => return (Some(self.clone()), Some(other.clone())),
+            Some(union) => union,
+        };
+        let intersection = match self.intersect(other) {
+            None => return (Some(self.clone()), Some(other.clone())),
+            Some(intersection) => intersection,
+        };
+        union.difference(&intersection)
+    }
+
+    /// Returns true if and only if the two ranges are contiguous. Two ranges
+    /// are contiguous if and only if the ranges are either overlapping or
+    /// adjacent.
+    fn is_contiguous(&self, other: &Self) -> bool {
+        let lower1 = self.lower().as_u32();
+        let upper1 = self.upper().as_u32();
+        let lower2 = other.lower().as_u32();
+        let upper2 = other.upper().as_u32();
+        cmp::max(lower1, lower2) <= cmp::min(upper1, upper2).saturating_add(1)
+    }
+
+    /// Returns true if and only if the intersection of this range and the
+    /// other range is empty.
+    fn is_intersection_empty(&self, other: &Self) -> bool {
+        let (lower1, upper1) = (self.lower(), self.upper());
+        let (lower2, upper2) = (other.lower(), other.upper());
+        cmp::max(lower1, lower2) > cmp::min(upper1, upper2)
+    }
+
+    /// Returns true if and only if this range is a subset of the other range.
+    fn is_subset(&self, other: &Self) -> bool {
+        let (lower1, upper1) = (self.lower(), self.upper());
+        let (lower2, upper2) = (other.lower(), other.upper());
+        (lower2 <= lower1 && lower1 <= upper2)
+        && (lower2 <= upper1 && upper1 <= upper2)
+    }
+}
+
+pub trait Bound: Copy + Clone + Debug + Eq + PartialEq + PartialOrd + Ord {
+    fn min_value() -> Self;
+    fn max_value() -> Self;
+    fn as_u32(self) -> u32;
+    fn increment(self) -> Self;
+    fn decrement(self) -> Self;
+}
+
+impl Bound for u8 {
+    fn min_value() -> Self { u8::MIN }
+    fn max_value() -> Self { u8::MAX }
+    fn as_u32(self) -> u32 { self as u32 }
+    fn increment(self) -> Self { self.checked_add(1).unwrap() }
+    fn decrement(self) -> Self { self.checked_sub(1).unwrap() }
+}
+
+impl Bound for char {
+    fn min_value() -> Self { '\x00' }
+    fn max_value() -> Self { '\u{10FFFF}' }
+    fn as_u32(self) -> u32 { self as u32 }
+
+    fn increment(self) -> Self {
+        match self {
+            '\u{D7FF}' => '\u{E000}',
+            c => char::from_u32((c as u32).checked_add(1).unwrap()).unwrap(),
+        }
+    }
+
+    fn decrement(self) -> Self {
+        match self {
+            '\u{E000}' => '\u{D7FF}',
+            c => char::from_u32((c as u32).checked_sub(1).unwrap()).unwrap(),
+        }
+    }
+}
+
+// Tests for interval sets are written in src/hir.rs against the public API.
diff --git a/third_party/rust/regex-syntax/src/hir/literal/mod.rs b/third_party/rust/regex-syntax/src/hir/literal/mod.rs
new file mode 100644
index 000000000000..b7d9c1db2742
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/literal/mod.rs
@@ -0,0 +1,1551 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Provides routines for extracting literal prefixes and suffixes from an `Hir`.
+*/
+
+use std::cmp;
+use std::fmt;
+use std::iter;
+use std::mem;
+use std::ops;
+
+use hir::{self, Hir, HirKind};
+
+/// A set of literal byte strings extracted from a regular expression.
+///
+/// Every member of the set is a `Literal`, which is represented by a
+/// `Vec<u8>`. (Notably, it may contain invalid UTF-8.) Every member is
+/// said to be either *complete* or *cut*. A complete literal means that
+/// it extends until the beginning (or end) of the regular expression. In
+/// some circumstances, this can be used to indicate a match in the regular
+/// expression.
+///
+/// A key aspect of literal extraction is knowing when to stop. It is not
+/// feasible to blindly extract all literals from a regular expression, even if
+/// there are finitely many. For example, the regular expression `[0-9]{10}`
+/// has `10^10` distinct literals. For this reason, literal extraction is
+/// bounded to some low number by default using heuristics, but the limits can
+/// be tweaked.
+///
+/// **WARNING**: Literal extraction uses stack space proportional to the size
+/// of the `Hir` expression. At some point, this drawback will be eliminated.
+/// To protect yourself, set a reasonable
+/// [`nest_limit` on your `Parser`](../../struct.ParserBuilder.html#method.nest_limit).
+/// This is done for you by default.
+#[derive(Clone, Eq, PartialEq)]
+pub struct Literals {
+    lits: Vec<Literal>,
+    limit_size: usize,
+    limit_class: usize,
+}
+
+/// A single member of a set of literals extracted from a regular expression.
+///
+/// This type has `Deref` and `DerefMut` impls to `Vec<u8>` so that all slice
+/// and `Vec` operations are available.
+#[derive(Clone, Eq, Ord)]
+pub struct Literal {
+    v: Vec<u8>,
+    cut: bool,
+}
+
+impl Literals {
+    /// Returns a new empty set of literals using default limits.
+    pub fn empty() -> Literals {
+        Literals {
+            lits: vec![],
+            limit_size: 250,
+            limit_class: 10,
+        }
+    }
+
+    /// Returns a set of literal prefixes extracted from the given `Hir`.
+    pub fn prefixes(expr: &Hir) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_prefixes(expr);
+        lits
+    }
+
+    /// Returns a set of literal suffixes extracted from the given `Hir`.
+    pub fn suffixes(expr: &Hir) -> Literals {
+        let mut lits = Literals::empty();
+        lits.union_suffixes(expr);
+        lits
+    }
+
+    /// Get the approximate size limit (in bytes) of this set.
+    pub fn limit_size(&self) -> usize {
+        self.limit_size
+    }
+
+    /// Set the approximate size limit (in bytes) of this set.
+    ///
+    /// If extracting a literal would put the set over this limit, then
+    /// extraction stops.
+    ///
+    /// The new limits will only apply to additions to this set. Existing
+    /// members remain unchanged, even if the set exceeds the new limit.
+    pub fn set_limit_size(&mut self, size: usize) -> &mut Literals {
+        self.limit_size = size;
+        self
+    }
+
+    /// Get the character class size limit for this set.
+    pub fn limit_class(&self) -> usize {
+        self.limit_class
+    }
+
+    /// Limits the size of character(or byte) classes considered.
+    ///
+    /// A value of `0` prevents all character classes from being considered.
+    ///
+    /// This limit also applies to case insensitive literals, since each
+    /// character in the case insensitive literal is converted to a class, and
+    /// then case folded.
+    ///
+    /// The new limits will only apply to additions to this set. Existing
+    /// members remain unchanged, even if the set exceeds the new limit.
+    pub fn set_limit_class(&mut self, size: usize) -> &mut Literals {
+        self.limit_class = size;
+        self
+    }
+
+    /// Returns the set of literals as a slice. Its order is unspecified.
+    pub fn literals(&self) -> &[Literal] {
+        &self.lits
+    }
+
+    /// Returns the length of the smallest literal.
+    ///
+    /// Returns None is there are no literals in the set.
+    pub fn min_len(&self) -> Option<usize> {
+        let mut min = None;
+        for lit in &self.lits {
+            match min {
+                None => min = Some(lit.len()),
+                Some(m) if lit.len() < m => min = Some(lit.len()),
+                _ => {}
+            }
+        }
+        min
+    }
+
+    /// Returns true if all members in this set are complete.
+    pub fn all_complete(&self) -> bool {
+        !self.lits.is_empty() && self.lits.iter().all(|l| !l.is_cut())
+    }
+
+    /// Returns true if any member in this set is complete.
+    pub fn any_complete(&self) -> bool {
+        self.lits.iter().any(|lit| !lit.is_cut())
+    }
+
+    /// Returns true if this set contains an empty literal.
+    pub fn contains_empty(&self) -> bool {
+        self.lits.iter().any(|lit| lit.is_empty())
+    }
+
+    /// Returns true if this set is empty or if all of its members is empty.
+    pub fn is_empty(&self) -> bool {
+        self.lits.is_empty() || self.lits.iter().all(|lit| lit.is_empty())
+    }
+
+    /// Returns a new empty set of literals using this set's limits.
+    pub fn to_empty(&self) -> Literals {
+        let mut lits = Literals::empty();
+        lits.set_limit_size(self.limit_size)
+            .set_limit_class(self.limit_class);
+        lits
+    }
+
+    /// Returns the longest common prefix of all members in this set.
+    pub fn longest_common_prefix(&self) -> &[u8] {
+        if self.is_empty() {
+            return &[];
+        }
+        let lit0 = &*self.lits[0];
+        let mut len = lit0.len();
+        for lit in &self.lits[1..] {
+            len = cmp::min(
+                len,
+                lit.iter()
+                   .zip(lit0)
+                   .take_while(|&(a, b)| a == b)
+                   .count());
+        }
+        &self.lits[0][..len]
+    }
+
+    /// Returns the longest common suffix of all members in this set.
+    pub fn longest_common_suffix(&self) -> &[u8] {
+        if self.is_empty() {
+            return &[];
+        }
+        let lit0 = &*self.lits[0];
+        let mut len = lit0.len();
+        for lit in &self.lits[1..] {
+            len = cmp::min(
+                len,
+                lit.iter()
+                   .rev()
+                   .zip(lit0.iter().rev())
+                   .take_while(|&(a, b)| a == b)
+                   .count());
+        }
+        &self.lits[0][self.lits[0].len() - len..]
+    }
+
+    /// Returns a new set of literals with the given number of bytes trimmed
+    /// from the suffix of each literal.
+    ///
+    /// If any literal would be cut out completely by trimming, then None is
+    /// returned.
+    ///
+    /// Any duplicates that are created as a result of this transformation are
+    /// removed.
+    pub fn trim_suffix(&self, num_bytes: usize) -> Option<Literals> {
+        if self.min_len().map(|len| len <= num_bytes).unwrap_or(true) {
+            return None;
+        }
+        let mut new = self.to_empty();
+        for mut lit in self.lits.iter().cloned() {
+            let new_len = lit.len() - num_bytes;
+            lit.truncate(new_len);
+            lit.cut();
+            new.lits.push(lit);
+        }
+        new.lits.sort();
+        new.lits.dedup();
+        Some(new)
+    }
+
+    /// Returns a new set of prefixes of this set of literals that are
+    /// guaranteed to be unambiguous.
+    ///
+    /// Any substring match with a member of the set is returned is guaranteed
+    /// to never overlap with a substring match of another member of the set
+    /// at the same starting position.
+    ///
+    /// Given any two members of the returned set, neither is a substring of
+    /// the other.
+    pub fn unambiguous_prefixes(&self) -> Literals {
+        if self.lits.is_empty() {
+            return self.to_empty();
+        }
+        let mut old: Vec<Literal> = self.lits.iter().cloned().collect();
+        let mut new = self.to_empty();
+    'OUTER:
+        while let Some(mut candidate) = old.pop() {
+            if candidate.is_empty() {
+                continue;
+            }
+            if new.lits.is_empty() {
+                new.lits.push(candidate);
+                continue;
+            }
+            for lit2 in &mut new.lits {
+                if lit2.is_empty() {
+                    continue;
+                }
+                if &candidate == lit2 {
+                    // If the literal is already in the set, then we can
+                    // just drop it. But make sure that cut literals are
+                    // infectious!
+                    candidate.cut = candidate.cut || lit2.cut;
+                    lit2.cut = candidate.cut;
+                    continue 'OUTER;
+                }
+                if candidate.len() < lit2.len() {
+                    if let Some(i) = position(&candidate, &lit2) {
+                        candidate.cut();
+                        let mut lit3 = lit2.clone();
+                        lit3.truncate(i);
+                        lit3.cut();
+                        old.push(lit3);
+                        lit2.clear();
+                    }
+                } else {
+                    if let Some(i) = position(&lit2, &candidate) {
+                        lit2.cut();
+                        let mut new_candidate = candidate.clone();
+                        new_candidate.truncate(i);
+                        new_candidate.cut();
+                        old.push(new_candidate);
+                        candidate.clear();
+                    }
+                }
+                // Oops, the candidate is already represented in the set.
+                if candidate.is_empty() {
+                    continue 'OUTER;
+                }
+            }
+            new.lits.push(candidate);
+        }
+        new.lits.retain(|lit| !lit.is_empty());
+        new.lits.sort();
+        new.lits.dedup();
+        new
+    }
+
+    /// Returns a new set of suffixes of this set of literals that are
+    /// guaranteed to be unambiguous.
+    ///
+    /// Any substring match with a member of the set is returned is guaranteed
+    /// to never overlap with a substring match of another member of the set
+    /// at the same ending position.
+    ///
+    /// Given any two members of the returned set, neither is a substring of
+    /// the other.
+    pub fn unambiguous_suffixes(&self) -> Literals {
+        // This is a touch wasteful...
+        let mut lits = self.clone();
+        lits.reverse();
+        let mut unamb = lits.unambiguous_prefixes();
+        unamb.reverse();
+        unamb
+    }
+
+    /// Unions the prefixes from the given expression to this set.
+    ///
+    /// If prefixes could not be added (for example, this set would exceed its
+    /// size limits or the set of prefixes from `expr` includes the empty
+    /// string), then false is returned.
+    ///
+    /// Note that prefix literals extracted from `expr` are said to be complete
+    /// if and only if the literal extends from the beginning of `expr` to the
+    /// end of `expr`.
+    pub fn union_prefixes(&mut self, expr: &Hir) -> bool {
+        let mut lits = self.to_empty();
+        prefixes(expr, &mut lits);
+        !lits.is_empty() && !lits.contains_empty() && self.union(lits)
+    }
+
+    /// Unions the suffixes from the given expression to this set.
+    ///
+    /// If suffixes could not be added (for example, this set would exceed its
+    /// size limits or the set of suffixes from `expr` includes the empty
+    /// string), then false is returned.
+    ///
+    /// Note that prefix literals extracted from `expr` are said to be complete
+    /// if and only if the literal extends from the end of `expr` to the
+    /// beginning of `expr`.
+    pub fn union_suffixes(&mut self, expr: &Hir) -> bool {
+        let mut lits = self.to_empty();
+        suffixes(expr, &mut lits);
+        lits.reverse();
+        !lits.is_empty() && !lits.contains_empty() && self.union(lits)
+    }
+
+    /// Unions this set with another set.
+    ///
+    /// If the union would cause the set to exceed its limits, then the union
+    /// is skipped and it returns false. Otherwise, if the union succeeds, it
+    /// returns true.
+    pub fn union(&mut self, lits: Literals) -> bool {
+        if self.num_bytes() + lits.num_bytes() > self.limit_size {
+            return false;
+        }
+        if lits.is_empty() {
+            self.lits.push(Literal::empty());
+        } else {
+            self.lits.extend(lits.lits);
+        }
+        true
+    }
+
+    /// Extends this set with another set.
+    ///
+    /// The set of literals is extended via a cross product.
+    ///
+    /// If a cross product would cause this set to exceed its limits, then the
+    /// cross product is skipped and it returns false. Otherwise, if the cross
+    /// product succeeds, it returns true.
+    pub fn cross_product(&mut self, lits: &Literals) -> bool {
+        if lits.is_empty() {
+            return true;
+        }
+        // Check that we make sure we stay in our limits.
+        let mut size_after;
+        if self.is_empty() || !self.any_complete() {
+            size_after = self.num_bytes();
+            for lits_lit in lits.literals() {
+                size_after += lits_lit.len();
+            }
+        } else {
+            size_after = self.lits.iter().fold(0, |accum, lit| {
+                accum + if lit.is_cut() { lit.len() } else { 0 }
+            });
+            for lits_lit in lits.literals() {
+                for self_lit in self.literals() {
+                    if !self_lit.is_cut() {
+                        size_after += self_lit.len() + lits_lit.len();
+                    }
+                }
+            }
+        }
+        if size_after > self.limit_size {
+            return false;
+        }
+
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for lits_lit in lits.literals() {
+            for mut self_lit in base.clone() {
+                self_lit.extend(&**lits_lit);
+                self_lit.cut = lits_lit.cut;
+                self.lits.push(self_lit);
+            }
+        }
+        true
+    }
+
+    /// Extends each literal in this set with the bytes given.
+    ///
+    /// If the set is empty, then the given literal is added to the set.
+    ///
+    /// If adding any number of bytes to all members of this set causes a limit
+    /// to be exceeded, then no bytes are added and false is returned. If a
+    /// prefix of `bytes` can be fit into this set, then it is used and all
+    /// resulting literals are cut.
+    pub fn cross_add(&mut self, bytes: &[u8]) -> bool {
+        // N.B. This could be implemented by simply calling cross_product with
+        // a literal set containing just `bytes`, but we can be smarter about
+        // taking shorter prefixes of `bytes` if they'll fit.
+        if bytes.is_empty() {
+            return true;
+        }
+        if self.lits.is_empty() {
+            let i = cmp::min(self.limit_size, bytes.len());
+            self.lits.push(Literal::new(bytes[..i].to_owned()));
+            self.lits[0].cut = i < bytes.len();
+            return !self.lits[0].is_cut();
+        }
+        let size = self.num_bytes();
+        if size + self.lits.len() >= self.limit_size {
+            return false;
+        }
+        let mut i = 1;
+        while size + (i * self.lits.len()) <= self.limit_size
+            && i < bytes.len() {
+            i += 1;
+        }
+        for lit in &mut self.lits {
+            if !lit.is_cut() {
+                lit.extend(&bytes[..i]);
+                if i < bytes.len() {
+                    lit.cut();
+                }
+            }
+        }
+        true
+    }
+
+    /// Adds the given literal to this set.
+    ///
+    /// Returns false if adding this literal would cause the class to be too
+    /// big.
+    pub fn add(&mut self, lit: Literal) -> bool {
+        if self.num_bytes() + lit.len() > self.limit_size {
+            return false;
+        }
+        self.lits.push(lit);
+        true
+    }
+
+    /// Extends each literal in this set with the character class given.
+    ///
+    /// Returns false if the character class was too big to add.
+    pub fn add_char_class(&mut self, cls: &hir::ClassUnicode) -> bool {
+        self._add_char_class(cls, false)
+    }
+
+    /// Extends each literal in this set with the character class given,
+    /// writing the bytes of each character in reverse.
+    ///
+    /// Returns false if the character class was too big to add.
+    fn add_char_class_reverse(&mut self, cls: &hir::ClassUnicode) -> bool {
+        self._add_char_class(cls, true)
+    }
+
+    fn _add_char_class(
+        &mut self,
+        cls: &hir::ClassUnicode,
+        reverse: bool,
+    ) -> bool {
+        use std::char;
+
+        if self.class_exceeds_limits(cls_char_count(cls)) {
+            return false;
+        }
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for r in cls.iter() {
+            let (s, e) = (r.start as u32, r.end as u32 + 1);
+            for c in (s..e).filter_map(char::from_u32) {
+                for mut lit in base.clone() {
+                    let mut bytes = c.to_string().into_bytes();
+                    if reverse {
+                        bytes.reverse();
+                    }
+                    lit.extend(&bytes);
+                    self.lits.push(lit);
+                }
+            }
+        }
+        true
+    }
+
+    /// Extends each literal in this set with the byte class given.
+    ///
+    /// Returns false if the byte class was too big to add.
+    pub fn add_byte_class(&mut self, cls: &hir::ClassBytes) -> bool {
+        if self.class_exceeds_limits(cls_byte_count(cls)) {
+            return false;
+        }
+        let mut base = self.remove_complete();
+        if base.is_empty() {
+            base = vec![Literal::empty()];
+        }
+        for r in cls.iter() {
+            let (s, e) = (r.start as u32, r.end as u32 + 1);
+            for b in (s..e).map(|b| b as u8) {
+                for mut lit in base.clone() {
+                    lit.push(b);
+                    self.lits.push(lit);
+                }
+            }
+        }
+        true
+    }
+
+    /// Cuts every member of this set. When a member is cut, it can never
+    /// be extended.
+    pub fn cut(&mut self) {
+        for lit in &mut self.lits {
+            lit.cut();
+        }
+    }
+
+    /// Reverses all members in place.
+    pub fn reverse(&mut self) {
+        for lit in &mut self.lits {
+            lit.reverse();
+        }
+    }
+
+    /// Clears this set of all members.
+    pub fn clear(&mut self) {
+        self.lits.clear();
+    }
+
+    /// Pops all complete literals out of this set.
+    fn remove_complete(&mut self) -> Vec<Literal> {
+        let mut base = vec![];
+        for lit in mem::replace(&mut self.lits, vec![]) {
+            if lit.is_cut() {
+                self.lits.push(lit);
+            } else {
+                base.push(lit);
+            }
+        }
+        base
+    }
+
+    /// Returns the total number of bytes in this set.
+    fn num_bytes(&self) -> usize {
+        self.lits.iter().fold(0, |accum, lit| accum + lit.len())
+    }
+
+    /// Returns true if a character class with the given size would cause this
+    /// set to exceed its limits.
+    ///
+    /// The size given should correspond to the number of items in the class.
+    fn class_exceeds_limits(&self, size: usize) -> bool {
+        if size > self.limit_class {
+            return true;
+        }
+        // This is an approximation since codepoints in a char class can encode
+        // to 1-4 bytes.
+        let new_byte_count =
+            if self.lits.is_empty() {
+                size
+            } else {
+                self.lits
+                    .iter()
+                    .fold(0, |accum, lit| {
+                        accum + if lit.is_cut() {
+                            // If the literal is cut, then we'll never add
+                            // anything to it, so don't count it.
+                            0
+                        } else {
+                            (lit.len() + 1) * size
+                        }
+                    })
+            };
+        new_byte_count > self.limit_size
+    }
+}
+
+fn prefixes(expr: &Hir, lits: &mut Literals) {
+    match *expr.kind() {
+        HirKind::Literal(hir::Literal::Unicode(c)) => {
+            let mut buf = [0; 4];
+            lits.cross_add(c.encode_utf8(&mut buf).as_bytes());
+        }
+        HirKind::Literal(hir::Literal::Byte(b)) => {
+            lits.cross_add(&[b]);
+        }
+        HirKind::Class(hir::Class::Unicode(ref cls)) => {
+            if !lits.add_char_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Class(hir::Class::Bytes(ref cls)) => {
+            if !lits.add_byte_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Group(hir::Group { ref hir, .. }) => {
+            prefixes(&**hir, lits);
+        }
+        HirKind::Repetition(ref x) => {
+            match x.kind {
+                hir::RepetitionKind::ZeroOrOne => {
+                    repeat_zero_or_one_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::ZeroOrMore => {
+                    repeat_zero_or_more_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::OneOrMore => {
+                    repeat_one_or_more_literals(&x.hir, lits, prefixes);
+                }
+                hir::RepetitionKind::Range(ref rng) => {
+                    let (min, max) = match *rng {
+                        hir::RepetitionRange::Exactly(m) => {
+                            (m, Some(m))
+                        }
+                        hir::RepetitionRange::AtLeast(m) => {
+                            (m, None)
+                        }
+                        hir::RepetitionRange::Bounded(m, n) => {
+                            (m, Some(n))
+                        }
+                    };
+                    repeat_range_literals(
+                        &x.hir, min, max, x.greedy, lits, prefixes)
+                }
+            }
+        }
+        HirKind::Concat(ref es) if es.is_empty() => {}
+        HirKind::Concat(ref es) if es.len() == 1 => prefixes(&es[0], lits),
+        HirKind::Concat(ref es) => {
+            for e in es {
+                if let HirKind::Anchor(hir::Anchor::StartText) = *e.kind() {
+                    if !lits.is_empty() {
+                        lits.cut();
+                        break;
+                    }
+                    lits.add(Literal::empty());
+                    continue;
+                }
+                let mut lits2 = lits.to_empty();
+                prefixes(e, &mut lits2);
+                if !lits.cross_product(&lits2) || !lits2.any_complete() {
+                    // If this expression couldn't yield any literal that
+                    // could be extended, then we need to quit. Since we're
+                    // short-circuiting, we also need to freeze every member.
+                    lits.cut();
+                    break;
+                }
+            }
+        }
+        HirKind::Alternation(ref es) => {
+            alternate_literals(es, lits, prefixes);
+        }
+        _ => lits.cut(),
+    }
+}
+
+fn suffixes(expr: &Hir, lits: &mut Literals) {
+    match *expr.kind() {
+        HirKind::Literal(hir::Literal::Unicode(c)) => {
+            let mut buf = [0u8; 4];
+            let i = c.encode_utf8(&mut buf).len();
+            let mut buf = &mut buf[..i];
+            buf.reverse();
+            lits.cross_add(buf);
+        }
+        HirKind::Literal(hir::Literal::Byte(b)) => {
+            lits.cross_add(&[b]);
+        }
+        HirKind::Class(hir::Class::Unicode(ref cls)) => {
+            if !lits.add_char_class_reverse(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Class(hir::Class::Bytes(ref cls)) => {
+            if !lits.add_byte_class(cls) {
+                lits.cut();
+            }
+        }
+        HirKind::Group(hir::Group { ref hir, .. }) => {
+            suffixes(&**hir, lits);
+        }
+        HirKind::Repetition(ref x) => {
+            match x.kind {
+                hir::RepetitionKind::ZeroOrOne => {
+                    repeat_zero_or_one_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::ZeroOrMore => {
+                    repeat_zero_or_more_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::OneOrMore => {
+                    repeat_one_or_more_literals(&x.hir, lits, suffixes);
+                }
+                hir::RepetitionKind::Range(ref rng) => {
+                    let (min, max) = match *rng {
+                        hir::RepetitionRange::Exactly(m) => {
+                            (m, Some(m))
+                        }
+                        hir::RepetitionRange::AtLeast(m) => {
+                            (m, None)
+                        }
+                        hir::RepetitionRange::Bounded(m, n) => {
+                            (m, Some(n))
+                        }
+                    };
+                    repeat_range_literals(
+                        &x.hir, min, max, x.greedy, lits, suffixes)
+                }
+            }
+        }
+        HirKind::Concat(ref es) if es.is_empty() => {}
+        HirKind::Concat(ref es) if es.len() == 1 => suffixes(&es[0], lits),
+        HirKind::Concat(ref es) => {
+            for e in es.iter().rev() {
+                if let HirKind::Anchor(hir::Anchor::EndText) = *e.kind() {
+                    if !lits.is_empty() {
+                        lits.cut();
+                        break;
+                    }
+                    lits.add(Literal::empty());
+                    continue;
+                }
+                let mut lits2 = lits.to_empty();
+                suffixes(e, &mut lits2);
+                if !lits.cross_product(&lits2) || !lits2.any_complete() {
+                    // If this expression couldn't yield any literal that
+                    // could be extended, then we need to quit. Since we're
+                    // short-circuiting, we also need to freeze every member.
+                    lits.cut();
+                    break;
+                }
+            }
+        }
+        HirKind::Alternation(ref es) => {
+            alternate_literals(es, lits, suffixes);
+        }
+        _ => lits.cut(),
+    }
+}
+
+fn repeat_zero_or_one_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let (mut lits2, mut lits3) = (lits.clone(), lits.to_empty());
+    lits3.set_limit_size(lits.limit_size() / 2);
+    f(e, &mut lits3);
+
+    if lits3.is_empty() || !lits2.cross_product(&lits3) {
+        lits.cut();
+        return;
+    }
+    lits2.add(Literal::empty());
+    if !lits.union(lits2) {
+        lits.cut();
+    }
+}
+
+fn repeat_zero_or_more_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let (mut lits2, mut lits3) = (lits.clone(), lits.to_empty());
+    lits3.set_limit_size(lits.limit_size() / 2);
+    f(e, &mut lits3);
+
+    if lits3.is_empty() || !lits2.cross_product(&lits3) {
+        lits.cut();
+        return;
+    }
+    lits2.cut();
+    lits2.add(Literal::empty());
+    if !lits.union(lits2) {
+        lits.cut();
+    }
+}
+
+fn repeat_one_or_more_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    f(e, lits);
+    lits.cut();
+}
+
+fn repeat_range_literals<F: FnMut(&Hir, &mut Literals)>(
+    e: &Hir,
+    min: u32,
+    max: Option<u32>,
+    greedy: bool,
+    lits: &mut Literals,
+    mut f: F,
+) {
+    if min == 0 {
+        // This is a bit conservative. If `max` is set, then we could
+        // treat this as a finite set of alternations. For now, we
+        // just treat it as `e*`.
+        f(&Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::ZeroOrMore,
+            greedy: greedy,
+            hir: Box::new(e.clone()),
+        }), lits);
+    } else {
+        if min > 0 {
+            let n = cmp::min(lits.limit_size, min as usize);
+            let es = iter::repeat(e.clone()).take(n).collect();
+            f(&Hir::concat(es), lits);
+            if n < min as usize || lits.contains_empty() {
+                lits.cut();
+            }
+        }
+        if max.map_or(true, |max| min < max) {
+            lits.cut();
+        }
+    }
+}
+
+fn alternate_literals<F: FnMut(&Hir, &mut Literals)>(
+    es: &[Hir],
+    lits: &mut Literals,
+    mut f: F,
+) {
+    let mut lits2 = lits.to_empty();
+    for e in es {
+        let mut lits3 = lits.to_empty();
+        lits3.set_limit_size(lits.limit_size() / 5);
+        f(e, &mut lits3);
+        if lits3.is_empty() || !lits2.union(lits3) {
+            // If we couldn't find suffixes for *any* of the
+            // alternates, then the entire alternation has to be thrown
+            // away and any existing members must be frozen. Similarly,
+            // if the union couldn't complete, stop and freeze.
+            lits.cut();
+            return;
+        }
+    }
+    if !lits.cross_product(&lits2) {
+        lits.cut();
+    }
+}
+
+impl fmt::Debug for Literals {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Literals")
+         .field("lits", &self.lits)
+         .field("limit_size", &self.limit_size)
+         .field("limit_class", &self.limit_class)
+         .finish()
+    }
+}
+
+impl Literal {
+    /// Returns a new complete literal with the bytes given.
+    pub fn new(bytes: Vec<u8>) -> Literal {
+        Literal { v: bytes, cut: false }
+    }
+
+    /// Returns a new complete empty literal.
+    pub fn empty() -> Literal {
+        Literal { v: vec![], cut: false }
+    }
+
+    /// Returns true if this literal was "cut."
+    pub fn is_cut(&self) -> bool {
+        self.cut
+    }
+
+    /// Cuts this literal.
+    pub fn cut(&mut self) {
+        self.cut = true;
+    }
+}
+
+impl PartialEq for Literal {
+    fn eq(&self, other: &Literal) -> bool {
+        self.v == other.v
+    }
+}
+
+impl PartialOrd for Literal {
+    fn partial_cmp(&self, other: &Literal) -> Option<cmp::Ordering> {
+        self.v.partial_cmp(&other.v)
+    }
+}
+
+impl fmt::Debug for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.is_cut() {
+            write!(f, "Cut({})", escape_unicode(&self.v))
+        } else {
+            write!(f, "Complete({})", escape_unicode(&self.v))
+        }
+    }
+}
+
+impl AsRef<[u8]> for Literal {
+    fn as_ref(&self) -> &[u8] { &self.v }
+}
+
+impl ops::Deref for Literal {
+    type Target = Vec<u8>;
+    fn deref(&self) -> &Vec<u8> { &self.v }
+}
+
+impl ops::DerefMut for Literal {
+    fn deref_mut(&mut self) -> &mut Vec<u8> { &mut self.v }
+}
+
+fn position(needle: &[u8], mut haystack: &[u8]) -> Option<usize> {
+    let mut i = 0;
+    while haystack.len() >= needle.len() {
+        if needle == &haystack[..needle.len()] {
+            return Some(i);
+        }
+        i += 1;
+        haystack = &haystack[1..];
+    }
+    None
+}
+
+fn escape_unicode(bytes: &[u8]) -> String {
+    let show = match ::std::str::from_utf8(bytes) {
+        Ok(v) => v.to_string(),
+        Err(_) => escape_bytes(bytes),
+    };
+    let mut space_escaped = String::new();
+    for c in show.chars() {
+        if c.is_whitespace() {
+            let escaped = if c as u32 <= 0x7F {
+                escape_byte(c as u8)
+            } else {
+                if c as u32 <= 0xFFFF {
+                    format!(r"\u{{{:04x}}}", c as u32)
+                } else {
+                    format!(r"\U{{{:08x}}}", c as u32)
+                }
+            };
+            space_escaped.push_str(&escaped);
+        } else {
+            space_escaped.push(c);
+        }
+    }
+    space_escaped
+}
+
+fn escape_bytes(bytes: &[u8]) -> String {
+    let mut s = String::new();
+    for &b in bytes {
+        s.push_str(&escape_byte(b));
+    }
+    s
+}
+
+fn escape_byte(byte: u8) -> String {
+    use std::ascii::escape_default;
+
+    let escaped: Vec<u8> = escape_default(byte).collect();
+    String::from_utf8_lossy(&escaped).into_owned()
+}
+
+fn cls_char_count(cls: &hir::ClassUnicode) -> usize {
+    cls.iter()
+        .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+        .sum::<u32>() as usize
+}
+
+fn cls_byte_count(cls: &hir::ClassBytes) -> usize {
+    cls.iter()
+        .map(|&r| 1 + (r.end as u32) - (r.start as u32))
+        .sum::<u32>() as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use std::fmt;
+
+    use ParserBuilder;
+    use hir::Hir;
+    use super::{Literals, Literal, escape_bytes};
+
+    // To make test failures easier to read.
+    #[derive(Debug, Eq, PartialEq)]
+    struct Bytes(Vec<ULiteral>);
+    #[derive(Debug, Eq, PartialEq)]
+    struct Unicode(Vec<ULiteral>);
+
+    fn escape_lits(blits: &[Literal]) -> Vec<ULiteral> {
+        let mut ulits = vec![];
+        for blit in blits {
+            ulits.push(ULiteral {
+                v: escape_bytes(&blit),
+                cut: blit.is_cut(),
+            });
+        }
+        ulits
+    }
+
+    fn create_lits<I: IntoIterator<Item=Literal>>(it: I) -> Literals {
+        Literals {
+            lits: it.into_iter().collect(),
+            limit_size: 0,
+            limit_class: 0,
+        }
+    }
+
+    // Needs to be pub for 1.3?
+    #[derive(Clone, Eq, PartialEq)]
+    pub struct ULiteral {
+        v: String,
+        cut: bool,
+    }
+
+    impl ULiteral {
+        fn is_cut(&self) -> bool { self.cut }
+    }
+
+    impl fmt::Debug for ULiteral {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            if self.is_cut() {
+                write!(f, "Cut({})", self.v)
+            } else {
+                write!(f, "Complete({})", self.v)
+            }
+        }
+    }
+
+    impl PartialEq<Literal> for ULiteral {
+        fn eq(&self, other: &Literal) -> bool {
+            self.v.as_bytes() == &*other.v && self.is_cut() == other.is_cut()
+        }
+    }
+
+    impl PartialEq<ULiteral> for Literal {
+        fn eq(&self, other: &ULiteral) -> bool {
+            &*self.v == other.v.as_bytes() && self.is_cut() == other.is_cut()
+        }
+    }
+
+    #[allow(non_snake_case)]
+    fn C(s: &'static str) -> ULiteral {
+        ULiteral { v: s.to_owned(), cut: true }
+    }
+    #[allow(non_snake_case)]
+    fn M(s: &'static str) -> ULiteral {
+        ULiteral { v: s.to_owned(), cut: false }
+    }
+
+    fn prefixes(lits: &mut Literals, expr: &Hir) {
+        lits.union_prefixes(expr);
+    }
+
+    fn suffixes(lits: &mut Literals, expr: &Hir) {
+        lits.union_suffixes(expr);
+    }
+
+    macro_rules! assert_lit_eq {
+        ($which:ident, $got_lits:expr, $($expected_lit:expr),*) => {{
+            let expected: Vec<ULiteral> = vec![$($expected_lit),*];
+            let lits = $got_lits;
+            assert_eq!(
+                $which(expected.clone()),
+                $which(escape_lits(lits.literals())));
+            assert_eq!(
+                !expected.is_empty() && expected.iter().all(|l| !l.is_cut()),
+                lits.all_complete());
+            assert_eq!(
+                expected.iter().any(|l| !l.is_cut()),
+                lits.any_complete());
+        }};
+    }
+
+    macro_rules! test_lit {
+        ($name:ident, $which:ident, $re:expr) => {
+            test_lit!($name, $which, $re,);
+        };
+        ($name:ident, $which:ident, $re:expr, $($lit:expr),*) => {
+            #[test]
+            fn $name() {
+                let expr = ParserBuilder::new()
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let lits = Literals::$which(&expr);
+                assert_lit_eq!(Unicode, lits, $($lit),*);
+
+                let expr = ParserBuilder::new()
+                    .allow_invalid_utf8(true)
+                    .unicode(false)
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let lits = Literals::$which(&expr);
+                assert_lit_eq!(Bytes, lits, $($lit),*);
+            }
+        };
+    }
+
+    // ************************************************************************
+    // Tests for prefix literal extraction.
+    // ************************************************************************
+
+    // Elementary tests.
+    test_lit!(pfx_one_lit1, prefixes, "a", M("a"));
+    test_lit!(pfx_one_lit2, prefixes, "abc", M("abc"));
+    test_lit!(pfx_one_lit3, prefixes, "(?u)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_one_lit4, prefixes, "(?ui)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_class1, prefixes, "[1-4]",
+              M("1"), M("2"), M("3"), M("4"));
+    test_lit!(pfx_class2, prefixes, "(?u)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_class3, prefixes, "(?ui)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x85\\xb0"),
+              M("\\xe2\\x98\\x83"));
+    test_lit!(pfx_one_lit_casei1, prefixes, "(?i)a",
+              M("A"), M("a"));
+    test_lit!(pfx_one_lit_casei2, prefixes, "(?i)abc",
+              M("ABC"), M("aBC"), M("AbC"), M("abC"),
+              M("ABc"), M("aBc"), M("Abc"), M("abc"));
+    test_lit!(pfx_group1, prefixes, "(a)", M("a"));
+    test_lit!(pfx_rep_zero_or_one1, prefixes, "a?");
+    test_lit!(pfx_rep_zero_or_one2, prefixes, "(?:abc)?");
+    test_lit!(pfx_rep_zero_or_more1, prefixes, "a*");
+    test_lit!(pfx_rep_zero_or_more2, prefixes, "(?:abc)*");
+    test_lit!(pfx_rep_one_or_more1, prefixes, "a+", C("a"));
+    test_lit!(pfx_rep_one_or_more2, prefixes, "(?:abc)+", C("abc"));
+    test_lit!(pfx_rep_nested_one_or_more, prefixes, "(?:a+)+", C("a"));
+    test_lit!(pfx_rep_range1, prefixes, "a{0}");
+    test_lit!(pfx_rep_range2, prefixes, "a{0,}");
+    test_lit!(pfx_rep_range3, prefixes, "a{0,1}");
+    test_lit!(pfx_rep_range4, prefixes, "a{1}", M("a"));
+    test_lit!(pfx_rep_range5, prefixes, "a{2}", M("aa"));
+    test_lit!(pfx_rep_range6, prefixes, "a{1,2}", C("a"));
+    test_lit!(pfx_rep_range7, prefixes, "a{2,3}", C("aa"));
+
+    // Test regexes with concatenations.
+    test_lit!(pfx_cat1, prefixes, "(?:a)(?:b)", M("ab"));
+    test_lit!(pfx_cat2, prefixes, "[ab]z", M("az"), M("bz"));
+    test_lit!(pfx_cat3, prefixes, "(?i)[ab]z",
+              M("AZ"), M("BZ"), M("aZ"), M("bZ"),
+              M("Az"), M("Bz"), M("az"), M("bz"));
+    test_lit!(pfx_cat4, prefixes, "[ab][yz]",
+              M("ay"), M("by"), M("az"), M("bz"));
+    test_lit!(pfx_cat5, prefixes, "a*b", C("a"), M("b"));
+    test_lit!(pfx_cat6, prefixes, "a*b*c", C("a"), C("b"), M("c"));
+    test_lit!(pfx_cat7, prefixes, "a*b*c+", C("a"), C("b"), C("c"));
+    test_lit!(pfx_cat8, prefixes, "a*b+c", C("a"), C("b"));
+    test_lit!(pfx_cat9, prefixes, "a*b+c*", C("a"), C("b"));
+    test_lit!(pfx_cat10, prefixes, "ab*", C("ab"), M("a"));
+    test_lit!(pfx_cat11, prefixes, "ab*c", C("ab"), M("ac"));
+    test_lit!(pfx_cat12, prefixes, "ab+", C("ab"));
+    test_lit!(pfx_cat13, prefixes, "ab+c", C("ab"));
+    test_lit!(pfx_cat14, prefixes, "a^", C("a"));
+    test_lit!(pfx_cat15, prefixes, "$a");
+    test_lit!(pfx_cat16, prefixes, r"ab*c", C("ab"), M("ac"));
+    test_lit!(pfx_cat17, prefixes, r"ab+c", C("ab"));
+    test_lit!(pfx_cat18, prefixes, r"z*azb", C("z"), M("azb"));
+    test_lit!(pfx_cat19, prefixes, "a.z", C("a"));
+
+    // Test regexes with alternations.
+    test_lit!(pfx_alt1, prefixes, "a|b", M("a"), M("b"));
+    test_lit!(pfx_alt2, prefixes, "[1-3]|b", M("1"), M("2"), M("3"), M("b"));
+    test_lit!(pfx_alt3, prefixes, "y(?:a|b)z", M("yaz"), M("ybz"));
+    test_lit!(pfx_alt4, prefixes, "a|b*");
+    test_lit!(pfx_alt5, prefixes, "a|b+", M("a"), C("b"));
+    test_lit!(pfx_alt6, prefixes, "a|(?:b|c*)");
+    test_lit!(pfx_alt7, prefixes, "(a|b)*c|(a|ab)*c",
+              C("a"), C("b"), M("c"), C("a"), C("ab"), M("c"));
+    test_lit!(pfx_alt8, prefixes, "a*b|c", C("a"), M("b"), M("c"));
+
+    // Test regexes with empty assertions.
+    test_lit!(pfx_empty1, prefixes, "^a", M("a"));
+    test_lit!(pfx_empty2, prefixes, "a${2}", C("a"));
+    test_lit!(pfx_empty3, prefixes, "^abc", M("abc"));
+    test_lit!(pfx_empty4, prefixes, "(?:^abc)|(?:^z)", M("abc"), M("z"));
+
+    // Make sure some curious regexes have no prefixes.
+    test_lit!(pfx_nothing1, prefixes, ".");
+    test_lit!(pfx_nothing2, prefixes, "(?s).");
+    test_lit!(pfx_nothing3, prefixes, "^");
+    test_lit!(pfx_nothing4, prefixes, "$");
+    test_lit!(pfx_nothing6, prefixes, "(?m)$");
+    test_lit!(pfx_nothing7, prefixes, r"\b");
+    test_lit!(pfx_nothing8, prefixes, r"\B");
+
+    // Test a few regexes that defeat any prefix literal detection.
+    test_lit!(pfx_defeated1, prefixes, ".a");
+    test_lit!(pfx_defeated2, prefixes, "(?s).a");
+    test_lit!(pfx_defeated3, prefixes, "a*b*c*");
+    test_lit!(pfx_defeated4, prefixes, "a|.");
+    test_lit!(pfx_defeated5, prefixes, ".|a");
+    test_lit!(pfx_defeated6, prefixes, "a|^");
+    test_lit!(pfx_defeated7, prefixes, ".(?:a(?:b)(?:c))");
+    test_lit!(pfx_defeated8, prefixes, "$a");
+    test_lit!(pfx_defeated9, prefixes, "(?m)$a");
+    test_lit!(pfx_defeated10, prefixes, r"\ba");
+    test_lit!(pfx_defeated11, prefixes, r"\Ba");
+    test_lit!(pfx_defeated12, prefixes, "^*a");
+    test_lit!(pfx_defeated13, prefixes, "^+a");
+
+    test_lit!(
+        pfx_crazy1,
+        prefixes,
+        r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]",
+        C("Mo\\'am"), C("Mu\\'am"), C("Moam"), C("Muam"));
+
+    // ************************************************************************
+    // Tests for quiting prefix literal search.
+    // ************************************************************************
+
+    macro_rules! test_exhausted {
+        ($name:ident, $which:ident, $re:expr) => {
+            test_exhausted!($name, $which, $re,);
+        };
+        ($name:ident, $which:ident, $re:expr, $($lit:expr),*) => {
+            #[test]
+            fn $name() {
+                let expr = ParserBuilder::new()
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let mut lits = Literals::empty();
+                lits.set_limit_size(20).set_limit_class(10);
+                $which(&mut lits, &expr);
+                assert_lit_eq!(Unicode, lits, $($lit),*);
+
+                let expr = ParserBuilder::new()
+                    .allow_invalid_utf8(true)
+                    .unicode(false)
+                    .build()
+                    .parse($re)
+                    .unwrap();
+                let mut lits = Literals::empty();
+                lits.set_limit_size(20).set_limit_class(10);
+                $which(&mut lits, &expr);
+                assert_lit_eq!(Bytes, lits, $($lit),*);
+            }
+        };
+    }
+
+    // These test use a much lower limit than the default so that we can
+    // write test cases of reasonable size.
+    test_exhausted!(pfx_exhausted1, prefixes, "[a-z]");
+    test_exhausted!(pfx_exhausted2, prefixes, "[a-z]*A");
+    test_exhausted!(pfx_exhausted3, prefixes, "A[a-z]Z", C("A"));
+    test_exhausted!(pfx_exhausted4, prefixes, "(?i)foobar",
+                    C("FO"), C("fO"), C("Fo"), C("fo"));
+    test_exhausted!(pfx_exhausted5, prefixes, "(?:ab){100}",
+                    C("abababababababababab"));
+    test_exhausted!(pfx_exhausted6, prefixes, "(?:(?:ab){100})*cd",
+                    C("ababababab"), M("cd"));
+    test_exhausted!(pfx_exhausted7, prefixes, "z(?:(?:ab){100})*cd",
+                    C("zababababab"), M("zcd"));
+    test_exhausted!(pfx_exhausted8, prefixes, "aaaaaaaaaaaaaaaaaaaaz",
+                    C("aaaaaaaaaaaaaaaaaaaa"));
+
+    // ************************************************************************
+    // Tests for suffix literal extraction.
+    // ************************************************************************
+
+    // Elementary tests.
+    test_lit!(sfx_one_lit1, suffixes, "a", M("a"));
+    test_lit!(sfx_one_lit2, suffixes, "abc", M("abc"));
+    test_lit!(sfx_one_lit3, suffixes, "(?u)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_one_lit4, suffixes, "(?ui)☃", M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_class1, suffixes, "[1-4]",
+              M("1"), M("2"), M("3"), M("4"));
+    test_lit!(sfx_class2, suffixes, "(?u)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_class3, suffixes, "(?ui)[☃Ⅰ]",
+              M("\\xe2\\x85\\xa0"), M("\\xe2\\x85\\xb0"),
+              M("\\xe2\\x98\\x83"));
+    test_lit!(sfx_one_lit_casei1, suffixes, "(?i)a",
+              M("A"), M("a"));
+    test_lit!(sfx_one_lit_casei2, suffixes, "(?i)abc",
+              M("ABC"), M("ABc"), M("AbC"), M("Abc"),
+              M("aBC"), M("aBc"), M("abC"), M("abc"));
+    test_lit!(sfx_group1, suffixes, "(a)", M("a"));
+    test_lit!(sfx_rep_zero_or_one1, suffixes, "a?");
+    test_lit!(sfx_rep_zero_or_one2, suffixes, "(?:abc)?");
+    test_lit!(sfx_rep_zero_or_more1, suffixes, "a*");
+    test_lit!(sfx_rep_zero_or_more2, suffixes, "(?:abc)*");
+    test_lit!(sfx_rep_one_or_more1, suffixes, "a+", C("a"));
+    test_lit!(sfx_rep_one_or_more2, suffixes, "(?:abc)+", C("abc"));
+    test_lit!(sfx_rep_nested_one_or_more, suffixes, "(?:a+)+", C("a"));
+    test_lit!(sfx_rep_range1, suffixes, "a{0}");
+    test_lit!(sfx_rep_range2, suffixes, "a{0,}");
+    test_lit!(sfx_rep_range3, suffixes, "a{0,1}");
+    test_lit!(sfx_rep_range4, suffixes, "a{1}", M("a"));
+    test_lit!(sfx_rep_range5, suffixes, "a{2}", M("aa"));
+    test_lit!(sfx_rep_range6, suffixes, "a{1,2}", C("a"));
+    test_lit!(sfx_rep_range7, suffixes, "a{2,3}", C("aa"));
+
+    // Test regexes with concatenations.
+    test_lit!(sfx_cat1, suffixes, "(?:a)(?:b)", M("ab"));
+    test_lit!(sfx_cat2, suffixes, "[ab]z", M("az"), M("bz"));
+    test_lit!(sfx_cat3, suffixes, "(?i)[ab]z",
+              M("AZ"), M("Az"), M("BZ"), M("Bz"),
+              M("aZ"), M("az"), M("bZ"), M("bz"));
+    test_lit!(sfx_cat4, suffixes, "[ab][yz]",
+              M("ay"), M("az"), M("by"), M("bz"));
+    test_lit!(sfx_cat5, suffixes, "a*b", C("ab"), M("b"));
+    test_lit!(sfx_cat6, suffixes, "a*b*c", C("bc"), C("ac"), M("c"));
+    test_lit!(sfx_cat7, suffixes, "a*b*c+", C("c"));
+    test_lit!(sfx_cat8, suffixes, "a*b+c", C("bc"));
+    test_lit!(sfx_cat9, suffixes, "a*b+c*", C("c"), C("b"));
+    test_lit!(sfx_cat10, suffixes, "ab*", C("b"), M("a"));
+    test_lit!(sfx_cat11, suffixes, "ab*c", C("bc"), M("ac"));
+    test_lit!(sfx_cat12, suffixes, "ab+", C("b"));
+    test_lit!(sfx_cat13, suffixes, "ab+c", C("bc"));
+    test_lit!(sfx_cat14, suffixes, "a^");
+    test_lit!(sfx_cat15, suffixes, "$a", C("a"));
+    test_lit!(sfx_cat16, suffixes, r"ab*c", C("bc"), M("ac"));
+    test_lit!(sfx_cat17, suffixes, r"ab+c", C("bc"));
+    test_lit!(sfx_cat18, suffixes, r"z*azb", C("zazb"), M("azb"));
+    test_lit!(sfx_cat19, suffixes, "a.z", C("z"));
+
+    // Test regexes with alternations.
+    test_lit!(sfx_alt1, suffixes, "a|b", M("a"), M("b"));
+    test_lit!(sfx_alt2, suffixes, "[1-3]|b", M("1"), M("2"), M("3"), M("b"));
+    test_lit!(sfx_alt3, suffixes, "y(?:a|b)z", M("yaz"), M("ybz"));
+    test_lit!(sfx_alt4, suffixes, "a|b*");
+    test_lit!(sfx_alt5, suffixes, "a|b+", M("a"), C("b"));
+    test_lit!(sfx_alt6, suffixes, "a|(?:b|c*)");
+    test_lit!(sfx_alt7, suffixes, "(a|b)*c|(a|ab)*c",
+              C("ac"), C("bc"), M("c"), C("ac"), C("abc"), M("c"));
+    test_lit!(sfx_alt8, suffixes, "a*b|c", C("ab"), M("b"), M("c"));
+
+    // Test regexes with empty assertions.
+    test_lit!(sfx_empty1, suffixes, "a$", M("a"));
+    test_lit!(sfx_empty2, suffixes, "${2}a", C("a"));
+
+    // Make sure some curious regexes have no suffixes.
+    test_lit!(sfx_nothing1, suffixes, ".");
+    test_lit!(sfx_nothing2, suffixes, "(?s).");
+    test_lit!(sfx_nothing3, suffixes, "^");
+    test_lit!(sfx_nothing4, suffixes, "$");
+    test_lit!(sfx_nothing6, suffixes, "(?m)$");
+    test_lit!(sfx_nothing7, suffixes, r"\b");
+    test_lit!(sfx_nothing8, suffixes, r"\B");
+
+    // Test a few regexes that defeat any suffix literal detection.
+    test_lit!(sfx_defeated1, suffixes, "a.");
+    test_lit!(sfx_defeated2, suffixes, "(?s)a.");
+    test_lit!(sfx_defeated3, suffixes, "a*b*c*");
+    test_lit!(sfx_defeated4, suffixes, "a|.");
+    test_lit!(sfx_defeated5, suffixes, ".|a");
+    test_lit!(sfx_defeated6, suffixes, "a|^");
+    test_lit!(sfx_defeated7, suffixes, "(?:a(?:b)(?:c)).");
+    test_lit!(sfx_defeated8, suffixes, "a^");
+    test_lit!(sfx_defeated9, suffixes, "(?m)a$");
+    test_lit!(sfx_defeated10, suffixes, r"a\b");
+    test_lit!(sfx_defeated11, suffixes, r"a\B");
+    test_lit!(sfx_defeated12, suffixes, "a^*");
+    test_lit!(sfx_defeated13, suffixes, "a^+");
+
+    // These test use a much lower limit than the default so that we can
+    // write test cases of reasonable size.
+    test_exhausted!(sfx_exhausted1, suffixes, "[a-z]");
+    test_exhausted!(sfx_exhausted2, suffixes, "A[a-z]*");
+    test_exhausted!(sfx_exhausted3, suffixes, "A[a-z]Z", C("Z"));
+    test_exhausted!(sfx_exhausted4, suffixes, "(?i)foobar",
+                    C("AR"), C("Ar"), C("aR"), C("ar"));
+    test_exhausted!(sfx_exhausted5, suffixes, "(?:ab){100}",
+                    C("abababababababababab"));
+    test_exhausted!(sfx_exhausted6, suffixes, "cd(?:(?:ab){100})*",
+                    C("ababababab"), M("cd"));
+    test_exhausted!(sfx_exhausted7, suffixes, "cd(?:(?:ab){100})*z",
+                    C("abababababz"), M("cdz"));
+    test_exhausted!(sfx_exhausted8, suffixes, "zaaaaaaaaaaaaaaaaaaaa",
+                    C("aaaaaaaaaaaaaaaaaaaa"));
+
+    // ************************************************************************
+    // Tests for generating unambiguous literal sets.
+    // ************************************************************************
+
+    macro_rules! test_unamb {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|ul| {
+                        let cut = ul.is_cut();
+                        Literal { v: ul.v.into_bytes(), cut: cut }
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.unambiguous_prefixes();
+                assert_eq!($expected, escape_lits(got.literals()));
+            }
+        };
+    }
+
+    test_unamb!(unambiguous1, vec![M("z"), M("azb")], vec![C("a"), C("z")]);
+    test_unamb!(unambiguous2,
+                vec![M("zaaaaaa"), M("aa")], vec![C("aa"), C("z")]);
+    test_unamb!(unambiguous3,
+                vec![M("Sherlock"), M("Watson")],
+                vec![M("Sherlock"), M("Watson")]);
+    test_unamb!(unambiguous4, vec![M("abc"), M("bc")], vec![C("a"), C("bc")]);
+    test_unamb!(unambiguous5, vec![M("bc"), M("abc")], vec![C("a"), C("bc")]);
+    test_unamb!(unambiguous6, vec![M("a"), M("aa")], vec![C("a")]);
+    test_unamb!(unambiguous7, vec![M("aa"), M("a")], vec![C("a")]);
+    test_unamb!(unambiguous8, vec![M("ab"), M("a")], vec![C("a")]);
+    test_unamb!(unambiguous9,
+                vec![M("ac"), M("bc"), M("c"), M("ac"), M("abc"), M("c")],
+                vec![C("a"), C("b"), C("c")]);
+    test_unamb!(unambiguous10,
+                vec![M("Mo'"), M("Mu'"), M("Mo"), M("Mu")],
+                vec![C("Mo"), C("Mu")]);
+    test_unamb!(unambiguous11,
+                vec![M("zazb"), M("azb")], vec![C("a"), C("z")]);
+    test_unamb!(unambiguous12, vec![M("foo"), C("foo")], vec![C("foo")]);
+    test_unamb!(unambiguous13,
+                vec![M("ABCX"), M("CDAX"), M("BCX")],
+                vec![C("A"), C("BCX"), C("CD")]);
+    test_unamb!(unambiguous14,
+                vec![M("IMGX"), M("MVIX"), M("MGX"), M("DSX")],
+                vec![M("DSX"), C("I"), C("MGX"), C("MV")]);
+    test_unamb!(unambiguous15,
+                vec![M("IMG_"), M("MG_"), M("CIMG")],
+                vec![C("C"), C("I"), C("MG_")]);
+
+
+    // ************************************************************************
+    // Tests for suffix trimming.
+    // ************************************************************************
+    macro_rules! test_trim {
+        ($name:ident, $trim:expr, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|ul| {
+                        let cut = ul.is_cut();
+                        Literal { v: ul.v.into_bytes(), cut: cut }
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.trim_suffix($trim).unwrap();
+                assert_eq!($expected, escape_lits(got.literals()));
+            }
+        }
+    }
+
+    test_trim!(trim1, 1, vec![M("ab"), M("yz")], vec![C("a"), C("y")]);
+    test_trim!(trim2, 1, vec![M("abc"), M("abd")], vec![C("ab")]);
+    test_trim!(trim3, 2, vec![M("abc"), M("abd")], vec![C("a")]);
+    test_trim!(trim4, 2, vec![M("abc"), M("ghij")], vec![C("a"), C("gh")]);
+
+    // ************************************************************************
+    // Tests for longest common prefix.
+    // ************************************************************************
+
+    macro_rules! test_lcp {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|s: &str| Literal {
+                        v: s.to_owned().into_bytes(),
+                        cut: false,
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.longest_common_prefix();
+                assert_eq!($expected, escape_bytes(got));
+            }
+        };
+    }
+
+    test_lcp!(lcp1, vec!["a"], "a");
+    test_lcp!(lcp2, vec![], "");
+    test_lcp!(lcp3, vec!["a", "b"], "");
+    test_lcp!(lcp4, vec!["ab", "ab"], "ab");
+    test_lcp!(lcp5, vec!["ab", "a"], "a");
+    test_lcp!(lcp6, vec!["a", "ab"], "a");
+    test_lcp!(lcp7, vec!["ab", "b"], "");
+    test_lcp!(lcp8, vec!["b", "ab"], "");
+    test_lcp!(lcp9, vec!["foobar", "foobaz"], "fooba");
+    test_lcp!(lcp10, vec!["foobar", "foobaz", "a"], "");
+    test_lcp!(lcp11, vec!["a", "foobar", "foobaz"], "");
+    test_lcp!(lcp12, vec!["foo", "flub", "flab", "floo"], "f");
+
+    // ************************************************************************
+    // Tests for longest common suffix.
+    // ************************************************************************
+
+    macro_rules! test_lcs {
+        ($name:ident, $given:expr, $expected:expr) => {
+            #[test]
+            fn $name() {
+                let given: Vec<Literal> =
+                    $given
+                    .into_iter()
+                    .map(|s: &str| Literal {
+                        v: s.to_owned().into_bytes(),
+                        cut: false,
+                    })
+                    .collect();
+                let lits = create_lits(given);
+                let got = lits.longest_common_suffix();
+                assert_eq!($expected, escape_bytes(got));
+            }
+        };
+    }
+
+    test_lcs!(lcs1, vec!["a"], "a");
+    test_lcs!(lcs2, vec![], "");
+    test_lcs!(lcs3, vec!["a", "b"], "");
+    test_lcs!(lcs4, vec!["ab", "ab"], "ab");
+    test_lcs!(lcs5, vec!["ab", "a"], "");
+    test_lcs!(lcs6, vec!["a", "ab"], "");
+    test_lcs!(lcs7, vec!["ab", "b"], "b");
+    test_lcs!(lcs8, vec!["b", "ab"], "b");
+    test_lcs!(lcs9, vec!["barfoo", "bazfoo"], "foo");
+    test_lcs!(lcs10, vec!["barfoo", "bazfoo", "a"], "");
+    test_lcs!(lcs11, vec!["a", "barfoo", "bazfoo"], "");
+    test_lcs!(lcs12, vec!["flub", "bub", "boob", "dub"], "b");
+}
diff --git a/third_party/rust/regex-syntax/src/hir/mod.rs b/third_party/rust/regex-syntax/src/hir/mod.rs
new file mode 100644
index 000000000000..903e6085be2e
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/mod.rs
@@ -0,0 +1,2055 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Defines a high-level intermediate representation for regular expressions.
+*/
+use std::char;
+use std::cmp;
+use std::error;
+use std::fmt;
+use std::u8;
+
+use ast::Span;
+use hir::interval::{Interval, IntervalSet, IntervalSetIter};
+use unicode;
+
+pub use hir::visitor::{Visitor, visit};
+
+mod interval;
+pub mod literal;
+pub mod print;
+pub mod translate;
+mod visitor;
+
+/// An error that can occur while translating an `Ast` to a `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Error {
+    /// The kind of error.
+    kind: ErrorKind,
+    /// The original pattern that the translator's Ast was parsed from. Every
+    /// span in an error is a valid range into this string.
+    pattern: String,
+    /// The span of this error, derived from the Ast given to the translator.
+    span: Span,
+}
+
+impl Error {
+    /// Return the type of this error.
+    pub fn kind(&self) -> &ErrorKind {
+        &self.kind
+    }
+
+    /// The original pattern string in which this error occurred.
+    ///
+    /// Every span reported by this error is reported in terms of this string.
+    pub fn pattern(&self) -> &str {
+        &self.pattern
+    }
+
+    /// Return the span at which this error occurred.
+    pub fn span(&self) -> &Span {
+        &self.span
+    }
+}
+
+/// The type of an error that occurred while building an `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum ErrorKind {
+    /// This error occurs when a Unicode feature is used when Unicode
+    /// support is disabled. For example `(?-u:\pL)` would trigger this error.
+    UnicodeNotAllowed,
+    /// This error occurs when translating a pattern that could match a byte
+    /// sequence that isn't UTF-8 and `allow_invalid_utf8` was disabled.
+    InvalidUtf8,
+    /// This occurs when an unrecognized Unicode property name could not
+    /// be found.
+    UnicodePropertyNotFound,
+    /// This occurs when an unrecognized Unicode property value could not
+    /// be found.
+    UnicodePropertyValueNotFound,
+    /// This occurs when the translator attempts to construct a character class
+    /// that is empty.
+    ///
+    /// Note that this restriction in the translator may be removed in the
+    /// future.
+    EmptyClassNotAllowed,
+    /// Hints that destructuring should not be exhaustive.
+    ///
+    /// This enum may grow additional variants, so this makes sure clients
+    /// don't count on exhaustive matching. (Otherwise, adding a new variant
+    /// could break existing code.)
+    #[doc(hidden)]
+    __Nonexhaustive,
+}
+
+impl ErrorKind {
+    fn description(&self) -> &str {
+        use self::ErrorKind::*;
+        match *self {
+            UnicodeNotAllowed => "Unicode not allowed here",
+            InvalidUtf8 => "pattern can match invalid UTF-8",
+            UnicodePropertyNotFound => "Unicode property not found",
+            UnicodePropertyValueNotFound => "Unicode property value not found",
+            EmptyClassNotAllowed => "empty character classes are not allowed",
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        self.kind.description()
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ::error::Formatter::from(self).fmt(f)
+    }
+}
+
+impl fmt::Display for ErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(self.description())
+    }
+}
+
+/// A high-level intermediate representation (HIR) for a regular expression.
+///
+/// The HIR of a regular expression represents an intermediate step between its
+/// abstract syntax (a structured description of the concrete syntax) and
+/// compiled byte codes. The purpose of HIR is to make regular expressions
+/// easier to analyze. In particular, the AST is much more complex than the
+/// HIR. For example, while an AST supports arbitrarily nested character
+/// classes, the HIR will flatten all nested classes into a single set. The HIR
+/// will also "compile away" every flag present in the concrete syntax. For
+/// example, users of HIR expressions never need to worry about case folding;
+/// it is handled automatically by the translator (e.g., by translating `(?i)A`
+/// to `[aA]`).
+///
+/// If the HIR was produced by a translator that disallows invalid UTF-8, then
+/// the HIR is guaranteed to match UTF-8 exclusively.
+///
+/// This type defines its own destructor that uses constant stack space and
+/// heap space proportional to the size of the HIR.
+///
+/// The specific type of an HIR expression can be accessed via its `kind`
+/// or `into_kind` methods. This extra level of indirection exists for two
+/// reasons:
+///
+/// 1. Construction of an HIR expression *must* use the constructor methods
+///    on this `Hir` type instead of building the `HirKind` values directly.
+///    This permits construction to enforce invariants like "concatenations
+///    always consist of two or more sub-expressions."
+/// 2. Every HIR expression contains attributes that are defined inductively,
+///    and can be computed cheaply during the construction process. For
+///    example, one such attribute is whether the expression must match at the
+///    beginning of the text.
+///
+/// Also, an `Hir`'s `fmt::Display` implementation prints an HIR as a regular
+/// expression pattern string, and uses constant stack space and heap space
+/// proportional to the size of the `Hir`.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Hir {
+    /// The underlying HIR kind.
+    kind: HirKind,
+    /// Analysis info about this HIR, computed during construction.
+    info: HirInfo,
+}
+
+/// The kind of an arbitrary `Hir` expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum HirKind {
+    /// The empty regular expression, which matches everything, including the
+    /// empty string.
+    Empty,
+    /// A single literal character that matches exactly this character.
+    Literal(Literal),
+    /// A single character class that matches any of the characters in the
+    /// class. A class can either consist of Unicode scalar values as
+    /// characters, or it can use bytes.
+    Class(Class),
+    /// An anchor assertion. An anchor assertion match always has zero length.
+    Anchor(Anchor),
+    /// A word boundary assertion, which may or may not be Unicode aware. A
+    /// word boundary assertion match always has zero length.
+    WordBoundary(WordBoundary),
+    /// A repetition operation applied to a child expression.
+    Repetition(Repetition),
+    /// A possibly capturing group, which contains a child expression.
+    Group(Group),
+    /// A concatenation of expressions. A concatenation always has at least two
+    /// child expressions.
+    ///
+    /// A concatenation matches only if each of its child expression matches
+    /// one after the other.
+    Concat(Vec<Hir>),
+    /// An alternation of expressions. An alternation always has at least two
+    /// child expressions.
+    ///
+    /// An alternation matches only if at least one of its child expression
+    /// matches. If multiple expressions match, then the leftmost is preferred.
+    Alternation(Vec<Hir>),
+}
+
+impl Hir {
+    /// Returns a reference to the underlying HIR kind.
+    pub fn kind(&self) -> &HirKind {
+        &self.kind
+    }
+
+    /// Consumes ownership of this HIR expression and returns its underlying
+    /// `HirKind`.
+    pub fn into_kind(mut self) -> HirKind {
+        use std::mem;
+        mem::replace(&mut self.kind, HirKind::Empty)
+    }
+
+    /// Returns an empty HIR expression.
+    ///
+    /// An empty HIR expression always matches, including the empty string.
+    pub fn empty() -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(true);
+        Hir {
+            kind: HirKind::Empty,
+            info: info,
+        }
+    }
+
+    /// Creates a literal HIR expression.
+    ///
+    /// If the given literal has a `Byte` variant with an ASCII byte, then this
+    /// method panics. This enforces the invariant that `Byte` variants are
+    /// only used to express matching of invalid UTF-8.
+    pub fn literal(lit: Literal) -> Hir {
+        if let Literal::Byte(b) = lit {
+            assert!(b > 0x7F);
+        }
+
+        let mut info = HirInfo::new();
+        info.set_always_utf8(lit.is_unicode());
+        info.set_all_assertions(false);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(false);
+        Hir {
+            kind: HirKind::Literal(lit),
+            info: info,
+        }
+    }
+
+    /// Creates a class HIR expression.
+    pub fn class(class: Class) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(class.is_always_utf8());
+        info.set_all_assertions(false);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(false);
+        Hir {
+            kind: HirKind::Class(class),
+            info: info,
+        }
+    }
+
+    /// Creates an anchor assertion HIR expression.
+    pub fn anchor(anchor: Anchor) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        info.set_match_empty(true);
+        if let Anchor::StartText = anchor {
+            info.set_anchored_start(true);
+            info.set_any_anchored_start(true);
+        }
+        if let Anchor::EndText = anchor {
+            info.set_anchored_end(true);
+            info.set_any_anchored_end(true);
+        }
+        Hir {
+            kind: HirKind::Anchor(anchor),
+            info: info,
+        }
+    }
+
+    /// Creates a word boundary assertion HIR expression.
+    pub fn word_boundary(word_boundary: WordBoundary) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(true);
+        info.set_all_assertions(true);
+        info.set_anchored_start(false);
+        info.set_anchored_end(false);
+        info.set_any_anchored_start(false);
+        info.set_any_anchored_end(false);
+        // A negated word boundary matches the empty string, but a normal
+        // word boundary does not!
+        info.set_match_empty(word_boundary.is_negated());
+        // Negated ASCII word boundaries can match invalid UTF-8.
+        if let WordBoundary::AsciiNegate = word_boundary {
+            info.set_always_utf8(false);
+        }
+        Hir {
+            kind: HirKind::WordBoundary(word_boundary),
+            info: info,
+        }
+    }
+
+    /// Creates a repetition HIR expression.
+    pub fn repetition(rep: Repetition) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(rep.hir.is_always_utf8());
+        info.set_all_assertions(rep.hir.is_all_assertions());
+        // If this operator can match the empty string, then it can never
+        // be anchored.
+        info.set_anchored_start(
+            !rep.is_match_empty() && rep.hir.is_anchored_start()
+        );
+        info.set_anchored_end(
+            !rep.is_match_empty() && rep.hir.is_anchored_end()
+        );
+        info.set_any_anchored_start(rep.hir.is_any_anchored_start());
+        info.set_any_anchored_end(rep.hir.is_any_anchored_end());
+        info.set_match_empty(rep.is_match_empty() || rep.hir.is_match_empty());
+        Hir {
+            kind: HirKind::Repetition(rep),
+            info: info,
+        }
+    }
+
+    /// Creates a group HIR expression.
+    pub fn group(group: Group) -> Hir {
+        let mut info = HirInfo::new();
+        info.set_always_utf8(group.hir.is_always_utf8());
+        info.set_all_assertions(group.hir.is_all_assertions());
+        info.set_anchored_start(group.hir.is_anchored_start());
+        info.set_anchored_end(group.hir.is_anchored_end());
+        info.set_any_anchored_start(group.hir.is_any_anchored_start());
+        info.set_any_anchored_end(group.hir.is_any_anchored_end());
+        info.set_match_empty(group.hir.is_match_empty());
+        Hir {
+            kind: HirKind::Group(group),
+            info: info,
+        }
+    }
+
+    /// Returns the concatenation of the given expressions.
+    ///
+    /// This flattens the concatenation as appropriate.
+    pub fn concat(mut exprs: Vec<Hir>) -> Hir {
+        match exprs.len() {
+            0 => Hir::empty(),
+            1 => exprs.pop().unwrap(),
+            _ => {
+                let mut info = HirInfo::new();
+                info.set_always_utf8(true);
+                info.set_all_assertions(true);
+                info.set_any_anchored_start(false);
+                info.set_any_anchored_end(false);
+                info.set_match_empty(true);
+
+                // Some attributes require analyzing all sub-expressions.
+                for e in &exprs {
+                    let x = info.is_always_utf8() && e.is_always_utf8();
+                    info.set_always_utf8(x);
+
+                    let x = info.is_all_assertions() && e.is_all_assertions();
+                    info.set_all_assertions(x);
+
+                    let x =
+                        info.is_any_anchored_start()
+                        || e.is_any_anchored_start();
+                    info.set_any_anchored_start(x);
+
+                    let x =
+                        info.is_any_anchored_end()
+                        || e.is_any_anchored_end();
+                    info.set_any_anchored_end(x);
+
+                    let x = info.is_match_empty() && e.is_match_empty();
+                    info.set_match_empty(x);
+                }
+                // Anchored attributes require something slightly more
+                // sophisticated. Normally, WLOG, to determine whether an
+                // expression is anchored to the start, we'd only need to check
+                // the first expression of a concatenation. However,
+                // expressions like `$\b^` are still anchored to the start,
+                // but the first expression in the concatenation *isn't*
+                // anchored to the start. So the "first" expression to look at
+                // is actually one that is either not an assertion or is
+                // specifically the StartText assertion.
+                info.set_anchored_start(
+                    exprs.iter()
+                        .take_while(|e| {
+                            e.is_anchored_start() || e.is_all_assertions()
+                        })
+                        .any(|e| {
+                            e.is_anchored_start()
+                        }));
+                // Similarly for the end anchor, but in reverse.
+                info.set_anchored_end(
+                    exprs.iter()
+                        .rev()
+                        .take_while(|e| {
+                            e.is_anchored_end() || e.is_all_assertions()
+                        })
+                        .any(|e| {
+                            e.is_anchored_end()
+                        }));
+                Hir {
+                    kind: HirKind::Concat(exprs),
+                    info: info,
+                }
+            }
+        }
+    }
+
+    /// Returns the alternation of the given expressions.
+    ///
+    /// This flattens the alternation as appropriate.
+    pub fn alternation(mut exprs: Vec<Hir>) -> Hir {
+        match exprs.len() {
+            0 => Hir::empty(),
+            1 => exprs.pop().unwrap(),
+            _ => {
+                let mut info = HirInfo::new();
+                info.set_always_utf8(true);
+                info.set_all_assertions(true);
+                info.set_anchored_start(true);
+                info.set_anchored_end(true);
+                info.set_any_anchored_start(false);
+                info.set_any_anchored_end(false);
+                info.set_match_empty(false);
+
+                // Some attributes require analyzing all sub-expressions.
+                for e in &exprs {
+                    let x = info.is_always_utf8() && e.is_always_utf8();
+                    info.set_always_utf8(x);
+
+                    let x = info.is_all_assertions() && e.is_all_assertions();
+                    info.set_all_assertions(x);
+
+                    let x = info.is_anchored_start() && e.is_anchored_start();
+                    info.set_anchored_start(x);
+
+                    let x = info.is_anchored_end() && e.is_anchored_end();
+                    info.set_anchored_end(x);
+
+                    let x =
+                        info.is_any_anchored_start()
+                        || e.is_any_anchored_start();
+                    info.set_any_anchored_start(x);
+
+                    let x =
+                        info.is_any_anchored_end()
+                        || e.is_any_anchored_end();
+                    info.set_any_anchored_end(x);
+
+                    let x = info.is_match_empty() || e.is_match_empty();
+                    info.set_match_empty(x);
+                }
+                Hir {
+                    kind: HirKind::Alternation(exprs),
+                    info: info,
+                }
+            }
+        }
+    }
+
+    /// Build an HIR expression for `.`.
+    ///
+    /// A `.` expression matches any character except for `\n`. To build an
+    /// expression that matches any character, including `\n`, use the `any`
+    /// method.
+    ///
+    /// If `bytes` is `true`, then this assumes characters are limited to a
+    /// single byte.
+    pub fn dot(bytes: bool) -> Hir {
+        if bytes {
+            let mut cls = ClassBytes::empty();
+            cls.push(ClassBytesRange::new(b'\0', b'\x09'));
+            cls.push(ClassBytesRange::new(b'\x0B', b'\xFF'));
+            Hir::class(Class::Bytes(cls))
+        } else {
+            let mut cls = ClassUnicode::empty();
+            cls.push(ClassUnicodeRange::new('\0', '\x09'));
+            cls.push(ClassUnicodeRange::new('\x0B', '\u{10FFFF}'));
+            Hir::class(Class::Unicode(cls))
+        }
+    }
+
+    /// Build an HIR expression for `(?s).`.
+    ///
+    /// A `(?s).` expression matches any character, including `\n`. To build an
+    /// expression that matches any character except for `\n`, then use the
+    /// `dot` method.
+    ///
+    /// If `bytes` is `true`, then this assumes characters are limited to a
+    /// single byte.
+    pub fn any(bytes: bool) -> Hir {
+        if bytes {
+            let mut cls = ClassBytes::empty();
+            cls.push(ClassBytesRange::new(b'\0', b'\xFF'));
+            Hir::class(Class::Bytes(cls))
+        } else {
+            let mut cls = ClassUnicode::empty();
+            cls.push(ClassUnicodeRange::new('\0', '\u{10FFFF}'));
+            Hir::class(Class::Unicode(cls))
+        }
+    }
+
+    /// Return true if and only if this HIR will always match valid UTF-8.
+    ///
+    /// When this returns false, then it is possible for this HIR expression
+    /// to match invalid UTF-8.
+    pub fn is_always_utf8(&self) -> bool {
+        self.info.is_always_utf8()
+    }
+
+    /// Returns true if and only if this entire HIR expression is made up of
+    /// zero-width assertions.
+    ///
+    /// This includes expressions like `^$\b\A\z` and even `((\b)+())*^`, but
+    /// not `^a`.
+    pub fn is_all_assertions(&self) -> bool {
+        self.info.is_all_assertions()
+    }
+
+    /// Return true if and only if this HIR is required to match from the
+    /// beginning of text. This includes expressions like `^foo`, `^(foo|bar)`,
+    /// `^foo|^bar` but not `^foo|bar`.
+    pub fn is_anchored_start(&self) -> bool {
+        self.info.is_anchored_start()
+    }
+
+    /// Return true if and only if this HIR is required to match at the end
+    /// of text. This includes expressions like `foo$`, `(foo|bar)$`,
+    /// `foo$|bar$` but not `foo$|bar`.
+    pub fn is_anchored_end(&self) -> bool {
+        self.info.is_anchored_end()
+    }
+
+    /// Return true if and only if this HIR contains any sub-expression that
+    /// is required to match at the beginning of text. Specifically, this
+    /// returns true if the `^` symbol (when multiline mode is disabled) or the
+    /// `\A` escape appear anywhere in the regex.
+    pub fn is_any_anchored_start(&self) -> bool {
+        self.info.is_any_anchored_start()
+    }
+
+    /// Return true if and only if this HIR contains any sub-expression that is
+    /// required to match at the end of text. Specifically, this returns true
+    /// if the `$` symbol (when multiline mode is disabled) or the `\z` escape
+    /// appear anywhere in the regex.
+    pub fn is_any_anchored_end(&self) -> bool {
+        self.info.is_any_anchored_end()
+    }
+
+    /// Return true if and only if the empty string is part of the language
+    /// matched by this regular expression.
+    ///
+    /// This includes `a*`, `a?b*`, `a{0}`, `()`, `()+`, `^$`, `a|b?`, `\B`,
+    /// but not `a`, `a+` or `\b`.
+    pub fn is_match_empty(&self) -> bool {
+        self.info.is_match_empty()
+    }
+}
+
+impl HirKind {
+    /// Return true if and only if this HIR is the empty regular expression.
+    ///
+    /// Note that this is not defined inductively. That is, it only tests if
+    /// this kind is the `Empty` variant. To get the inductive definition,
+    /// use the `is_match_empty` method on [`Hir`](struct.Hir.html).
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            HirKind::Empty => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if and only if this kind has any (including possibly
+    /// empty) subexpressions.
+    pub fn has_subexprs(&self) -> bool {
+        match *self {
+            HirKind::Empty
+            | HirKind::Literal(_)
+            | HirKind::Class(_)
+            | HirKind::Anchor(_)
+            | HirKind::WordBoundary(_) => false,
+            HirKind::Group(_)
+            | HirKind::Repetition(_)
+            | HirKind::Concat(_)
+            | HirKind::Alternation(_) => true,
+        }
+    }
+}
+
+/// Print a display representation of this Hir.
+///
+/// The result of this is a valid regular expression pattern string.
+///
+/// This implementation uses constant stack space and heap space proportional
+/// to the size of the `Hir`.
+impl fmt::Display for Hir {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use hir::print::Printer;
+        Printer::new().print(self, f)
+    }
+}
+
+/// The high-level intermediate representation of a literal.
+///
+/// A literal corresponds to a single character, where a character is either
+/// defined by a Unicode scalar value or an arbitrary byte. Unicode characters
+/// are preferred whenever possible. In particular, a `Byte` variant is only
+/// ever produced when it could match invalid UTF-8.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Literal {
+    /// A single character represented by a Unicode scalar value.
+    Unicode(char),
+    /// A single character represented by an arbitrary byte.
+    Byte(u8),
+}
+
+impl Literal {
+    /// Returns true if and only if this literal corresponds to a Unicode
+    /// scalar value.
+    pub fn is_unicode(&self) -> bool {
+        match *self {
+            Literal::Unicode(_) => true,
+            Literal::Byte(b) if b <= 0x7F => true,
+            Literal::Byte(_) => false,
+        }
+    }
+}
+
+/// The high-level intermediate representation of a character class.
+///
+/// A character class corresponds to a set of characters. A character is either
+/// defined by a Unicode scalar value or a byte. Unicode characters are used
+/// by default, while bytes are used when Unicode mode (via the `u` flag) is
+/// disabled.
+///
+/// A character class, regardless of its character type, is represented by a
+/// sequence of non-overlapping non-adjacent ranges of characters.
+///
+/// Note that unlike [`Literal`](enum.Literal.html), a `Bytes` variant may
+/// be produced even when it exclusively matches valid UTF-8. This is because
+/// a `Bytes` variant represents an intention by the author of the regular
+/// expression to disable Unicode mode, which in turn impacts the semantics of
+/// case insensitive matching. For example, `(?i)k` and `(?i-u)k` will not
+/// match the same set of strings.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Class {
+    /// A set of characters represented by Unicode scalar values.
+    Unicode(ClassUnicode),
+    /// A set of characters represented by arbitrary bytes (one byte per
+    /// character).
+    Bytes(ClassBytes),
+}
+
+impl Class {
+    /// Apply Unicode simple case folding to this character class, in place.
+    /// The character class will be expanded to include all simple case folded
+    /// character variants.
+    ///
+    /// If this is a byte oriented character class, then this will be limited
+    /// to the ASCII ranges `A-Z` and `a-z`.
+    pub fn case_fold_simple(&mut self) {
+        match *self {
+            Class::Unicode(ref mut x) => x.case_fold_simple(),
+            Class::Bytes(ref mut x) => x.case_fold_simple(),
+        }
+    }
+
+    /// Negate this character class in place.
+    ///
+    /// After completion, this character class will contain precisely the
+    /// characters that weren't previously in the class.
+    pub fn negate(&mut self) {
+        match *self {
+            Class::Unicode(ref mut x) => x.negate(),
+            Class::Bytes(ref mut x) => x.negate(),
+        }
+    }
+
+    /// Returns true if and only if this character class will only ever match
+    /// valid UTF-8.
+    ///
+    /// A character class can match invalid UTF-8 only when the following
+    /// conditions are met:
+    ///
+    /// 1. The translator was configured to permit generating an expression
+    ///    that can match invalid UTF-8. (By default, this is disabled.)
+    /// 2. Unicode mode (via the `u` flag) was disabled either in the concrete
+    ///    syntax or in the parser builder. By default, Unicode mode is
+    ///    enabled.
+    pub fn is_always_utf8(&self) -> bool {
+        match *self {
+            Class::Unicode(_) => true,
+            Class::Bytes(ref x) => x.is_all_ascii(),
+        }
+    }
+}
+
+/// A set of characters represented by Unicode scalar values.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassUnicode {
+    set: IntervalSet<ClassUnicodeRange>,
+}
+
+impl ClassUnicode {
+    /// Create a new class from a sequence of ranges.
+    ///
+    /// The given ranges do not need to be in any specific order, and ranges
+    /// may overlap.
+    pub fn new<I>(ranges: I) -> ClassUnicode
+    where I: IntoIterator<Item=ClassUnicodeRange>
+    {
+        ClassUnicode { set: IntervalSet::new(ranges) }
+    }
+
+    /// Create a new class with no ranges.
+    pub fn empty() -> ClassUnicode {
+        ClassUnicode::new(vec![])
+    }
+
+    /// Add a new range to this set.
+    pub fn push(&mut self, range: ClassUnicodeRange) {
+        self.set.push(range);
+    }
+
+    /// Return an iterator over all ranges in this class.
+    ///
+    /// The iterator yields ranges in ascending order.
+    pub fn iter(&self) -> ClassUnicodeIter {
+        ClassUnicodeIter(self.set.iter())
+    }
+
+    /// Return the underlying ranges as a slice.
+    pub fn ranges(&self) -> &[ClassUnicodeRange] {
+        self.set.intervals()
+    }
+
+    /// Expand this character class such that it contains all case folded
+    /// characters, according to Unicode's "simple" mapping. For example, if
+    /// this class consists of the range `a-z`, then applying case folding will
+    /// result in the class containing both the ranges `a-z` and `A-Z`.
+    pub fn case_fold_simple(&mut self) {
+        self.set.case_fold_simple();
+    }
+
+    /// Negate this character class.
+    ///
+    /// For all `c` where `c` is a Unicode scalar value, if `c` was in this
+    /// set, then it will not be in this set after negation.
+    pub fn negate(&mut self) {
+        self.set.negate();
+    }
+
+    /// Union this character class with the given character class, in place.
+    pub fn union(&mut self, other: &ClassUnicode) {
+        self.set.union(&other.set);
+    }
+
+    /// Intersect this character class with the given character class, in
+    /// place.
+    pub fn intersect(&mut self, other: &ClassUnicode) {
+        self.set.intersect(&other.set);
+    }
+
+    /// Subtract the given character class from this character class, in place.
+    pub fn difference(&mut self, other: &ClassUnicode) {
+        self.set.difference(&other.set);
+    }
+
+    /// Compute the symmetric difference of the given character classes, in
+    /// place.
+    ///
+    /// This computes the symmetric difference of two character classes. This
+    /// removes all elements in this class that are also in the given class,
+    /// but all adds all elements from the given class that aren't in this
+    /// class. That is, the class will contain all elements in either class,
+    /// but will not contain any elements that are in both classes.
+    pub fn symmetric_difference(&mut self, other: &ClassUnicode) {
+        self.set.symmetric_difference(&other.set);
+    }
+}
+
+/// An iterator over all ranges in a Unicode character class.
+///
+/// The lifetime `'a` refers to the lifetime of the underlying class.
+#[derive(Debug)]
+pub struct ClassUnicodeIter<'a>(IntervalSetIter<'a, ClassUnicodeRange>);
+
+impl<'a> Iterator for ClassUnicodeIter<'a> {
+    type Item = &'a ClassUnicodeRange;
+
+    fn next(&mut self) -> Option<&'a ClassUnicodeRange> {
+        self.0.next()
+    }
+}
+
+/// A single range of characters represented by Unicode scalar values.
+///
+/// The range is closed. That is, the start and end of the range are included
+/// in the range.
+#[derive(Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord)]
+pub struct ClassUnicodeRange {
+    start: char,
+    end: char,
+}
+
+impl fmt::Debug for ClassUnicodeRange {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let start =
+            if !self.start.is_whitespace() && !self.start.is_control() {
+                self.start.to_string()
+            } else {
+                format!("0x{:X}", self.start as u32)
+            };
+        let end =
+            if !self.end.is_whitespace() && !self.end.is_control() {
+                self.end.to_string()
+            } else {
+                format!("0x{:X}", self.end as u32)
+            };
+        f.debug_struct("ClassUnicodeRange")
+         .field("start", &start)
+         .field("end", &end)
+         .finish()
+    }
+}
+
+impl Interval for ClassUnicodeRange {
+    type Bound = char;
+
+    #[inline] fn lower(&self) -> char { self.start }
+    #[inline] fn upper(&self) -> char { self.end }
+    #[inline] fn set_lower(&mut self, bound: char) { self.start = bound; }
+    #[inline] fn set_upper(&mut self, bound: char) { self.end = bound; }
+
+    /// Apply simple case folding to this Unicode scalar value range.
+    ///
+    /// Additional ranges are appended to the given vector. Canonical ordering
+    /// is *not* maintained in the given vector.
+    fn case_fold_simple(&self, ranges: &mut Vec<ClassUnicodeRange>) {
+        if !unicode::contains_simple_case_mapping(self.start, self.end) {
+            return;
+        }
+        let start = self.start as u32;
+        let end = (self.end as u32).saturating_add(1);
+        let mut next_simple_cp = None;
+        for cp in (start..end).filter_map(char::from_u32) {
+            if next_simple_cp.map_or(false, |next| cp < next) {
+                continue;
+            }
+            let it = match unicode::simple_fold(cp) {
+                Ok(it) => it,
+                Err(next) => {
+                    next_simple_cp = next;
+                    continue;
+                }
+            };
+            for cp_folded in it {
+                ranges.push(ClassUnicodeRange::new(cp_folded, cp_folded));
+            }
+        }
+    }
+}
+
+impl ClassUnicodeRange {
+    /// Create a new Unicode scalar value range for a character class.
+    ///
+    /// The returned range is always in a canonical form. That is, the range
+    /// returned always satisfies the invariant that `start <= end`.
+    pub fn new(start: char, end: char) -> ClassUnicodeRange {
+        ClassUnicodeRange::create(start, end)
+    }
+
+    /// Return the start of this range.
+    ///
+    /// The start of a range is always less than or equal to the end of the
+    /// range.
+    pub fn start(&self) -> char {
+        self.start
+    }
+
+    /// Return the end of this range.
+    ///
+    /// The end of a range is always greater than or equal to the start of the
+    /// range.
+    pub fn end(&self) -> char {
+        self.end
+    }
+}
+
+/// A set of characters represented by arbitrary bytes (where one byte
+/// corresponds to one character).
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ClassBytes {
+    set: IntervalSet<ClassBytesRange>,
+}
+
+impl ClassBytes {
+    /// Create a new class from a sequence of ranges.
+    ///
+    /// The given ranges do not need to be in any specific order, and ranges
+    /// may overlap.
+    pub fn new<I>(ranges: I) -> ClassBytes
+    where I: IntoIterator<Item=ClassBytesRange>
+    {
+        ClassBytes { set: IntervalSet::new(ranges) }
+    }
+
+    /// Create a new class with no ranges.
+    pub fn empty() -> ClassBytes {
+        ClassBytes::new(vec![])
+    }
+
+    /// Add a new range to this set.
+    pub fn push(&mut self, range: ClassBytesRange) {
+        self.set.push(range);
+    }
+
+    /// Return an iterator over all ranges in this class.
+    ///
+    /// The iterator yields ranges in ascending order.
+    pub fn iter(&self) -> ClassBytesIter {
+        ClassBytesIter(self.set.iter())
+    }
+
+    /// Return the underlying ranges as a slice.
+    pub fn ranges(&self) -> &[ClassBytesRange] {
+        self.set.intervals()
+    }
+
+    /// Expand this character class such that it contains all case folded
+    /// characters. For example, if this class consists of the range `a-z`,
+    /// then applying case folding will result in the class containing both the
+    /// ranges `a-z` and `A-Z`.
+    ///
+    /// Note that this only applies ASCII case folding, which is limited to the
+    /// characters `a-z` and `A-Z`.
+    pub fn case_fold_simple(&mut self) {
+        self.set.case_fold_simple();
+    }
+
+    /// Negate this byte class.
+    ///
+    /// For all `b` where `b` is a any byte, if `b` was in this set, then it
+    /// will not be in this set after negation.
+    pub fn negate(&mut self) {
+        self.set.negate();
+    }
+
+    /// Union this byte class with the given byte class, in place.
+    pub fn union(&mut self, other: &ClassBytes) {
+        self.set.union(&other.set);
+    }
+
+    /// Intersect this byte class with the given byte class, in place.
+    pub fn intersect(&mut self, other: &ClassBytes) {
+        self.set.intersect(&other.set);
+    }
+
+    /// Subtract the given byte class from this byte class, in place.
+    pub fn difference(&mut self, other: &ClassBytes) {
+        self.set.difference(&other.set);
+    }
+
+    /// Compute the symmetric difference of the given byte classes, in place.
+    ///
+    /// This computes the symmetric difference of two byte classes. This
+    /// removes all elements in this class that are also in the given class,
+    /// but all adds all elements from the given class that aren't in this
+    /// class. That is, the class will contain all elements in either class,
+    /// but will not contain any elements that are in both classes.
+    pub fn symmetric_difference(&mut self, other: &ClassBytes) {
+        self.set.symmetric_difference(&other.set);
+    }
+
+    /// Returns true if and only if this character class will either match
+    /// nothing or only ASCII bytes. Stated differently, this returns false
+    /// if and only if this class contains a non-ASCII byte.
+    pub fn is_all_ascii(&self) -> bool {
+        self.set.intervals().last().map_or(true, |r| r.end <= 0x7F)
+    }
+}
+
+/// An iterator over all ranges in a byte character class.
+///
+/// The lifetime `'a` refers to the lifetime of the underlying class.
+#[derive(Debug)]
+pub struct ClassBytesIter<'a>(IntervalSetIter<'a, ClassBytesRange>);
+
+impl<'a> Iterator for ClassBytesIter<'a> {
+    type Item = &'a ClassBytesRange;
+
+    fn next(&mut self) -> Option<&'a ClassBytesRange> {
+        self.0.next()
+    }
+}
+
+/// A single range of characters represented by arbitrary bytes.
+///
+/// The range is closed. That is, the start and end of the range are included
+/// in the range.
+#[derive(Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord)]
+pub struct ClassBytesRange {
+    start: u8,
+    end: u8,
+}
+
+impl Interval for ClassBytesRange {
+    type Bound = u8;
+
+    #[inline] fn lower(&self) -> u8 { self.start }
+    #[inline] fn upper(&self) -> u8 { self.end }
+    #[inline] fn set_lower(&mut self, bound: u8) { self.start = bound; }
+    #[inline] fn set_upper(&mut self, bound: u8) { self.end = bound; }
+
+    /// Apply simple case folding to this byte range. Only ASCII case mappings
+    /// (for a-z) are applied.
+    ///
+    /// Additional ranges are appended to the given vector. Canonical ordering
+    /// is *not* maintained in the given vector.
+    fn case_fold_simple(&self, ranges: &mut Vec<ClassBytesRange>) {
+        if !ClassBytesRange::new(b'a', b'z').is_intersection_empty(self) {
+            let lower = cmp::max(self.start, b'a');
+            let upper = cmp::min(self.end, b'z');
+            ranges.push(ClassBytesRange::new(lower - 32, upper - 32));
+        }
+        if !ClassBytesRange::new(b'A', b'Z').is_intersection_empty(self) {
+            let lower = cmp::max(self.start, b'A');
+            let upper = cmp::min(self.end, b'Z');
+            ranges.push(ClassBytesRange::new(lower + 32, upper + 32));
+        }
+    }
+}
+
+impl ClassBytesRange {
+    /// Create a new byte range for a character class.
+    ///
+    /// The returned range is always in a canonical form. That is, the range
+    /// returned always satisfies the invariant that `start <= end`.
+    pub fn new(start: u8, end: u8) -> ClassBytesRange {
+        ClassBytesRange::create(start, end)
+    }
+
+    /// Return the start of this range.
+    ///
+    /// The start of a range is always less than or equal to the end of the
+    /// range.
+    pub fn start(&self) -> u8 {
+        self.start
+    }
+
+    /// Return the end of this range.
+    ///
+    /// The end of a range is always greater than or equal to the start of the
+    /// range.
+    pub fn end(&self) -> u8 {
+        self.end
+    }
+}
+
+impl fmt::Debug for ClassBytesRange {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = f.debug_struct("ClassBytesRange");
+        if self.start <= 0x7F {
+            debug.field("start", &(self.start as char));
+        } else {
+            debug.field("start", &self.start);
+        }
+        if self.end <= 0x7F {
+            debug.field("end", &(self.end as char));
+        } else {
+            debug.field("end", &self.end);
+        }
+        debug.finish()
+    }
+}
+
+/// The high-level intermediate representation for an anchor assertion.
+///
+/// A matching anchor assertion is always zero-length.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Anchor {
+    /// Match the beginning of a line or the beginning of text. Specifically,
+    /// this matches at the starting position of the input, or at the position
+    /// immediately following a `\n` character.
+    StartLine,
+    /// Match the end of a line or the end of text. Specifically,
+    /// this matches at the end position of the input, or at the position
+    /// immediately preceding a `\n` character.
+    EndLine,
+    /// Match the beginning of text. Specifically, this matches at the starting
+    /// position of the input.
+    StartText,
+    /// Match the end of text. Specifically, this matches at the ending
+    /// position of the input.
+    EndText,
+}
+
+/// The high-level intermediate representation for a word-boundary assertion.
+///
+/// A matching word boundary assertion is always zero-length.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum WordBoundary {
+    /// Match a Unicode-aware word boundary. That is, this matches a position
+    /// where the left adjacent character and right adjacent character
+    /// correspond to a word and non-word or a non-word and word character.
+    Unicode,
+    /// Match a Unicode-aware negation of a word boundary.
+    UnicodeNegate,
+    /// Match an ASCII-only word boundary. That is, this matches a position
+    /// where the left adjacent character and right adjacent character
+    /// correspond to a word and non-word or a non-word and word character.
+    Ascii,
+    /// Match an ASCII-only negation of a word boundary.
+    AsciiNegate,
+}
+
+impl WordBoundary {
+    /// Returns true if and only if this word boundary assertion is negated.
+    pub fn is_negated(&self) -> bool {
+        match *self {
+            WordBoundary::Unicode |  WordBoundary::Ascii => false,
+            WordBoundary::UnicodeNegate |  WordBoundary::AsciiNegate => true,
+        }
+    }
+}
+
+/// The high-level intermediate representation for a group.
+///
+/// This represents one of three possible group types:
+///
+/// 1. A non-capturing group (e.g., `(?:expr)`).
+/// 2. A capturing group (e.g., `(expr)`).
+/// 3. A named capturing group (e.g., `(?P<name>expr)`).
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Group {
+    /// The kind of this group. If it is a capturing group, then the kind
+    /// contains the capture group index (and the name, if it is a named
+    /// group).
+    pub kind: GroupKind,
+    /// The expression inside the capturing group, which may be empty.
+    pub hir: Box<Hir>,
+}
+
+/// The kind of group.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum GroupKind {
+    /// A normal unnamed capturing group.
+    ///
+    /// The value is the capture index of the group.
+    CaptureIndex(u32),
+    /// A named capturing group.
+    CaptureName {
+        /// The name of the group.
+        name: String,
+        /// The capture index of the group.
+        index: u32,
+    },
+    /// A non-capturing group.
+    NonCapturing,
+}
+
+/// The high-level intermediate representation of a repetition operator.
+///
+/// A repetition operator permits the repetition of an arbitrary
+/// sub-expression.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Repetition {
+    /// The kind of this repetition operator.
+    pub kind: RepetitionKind,
+    /// Whether this repetition operator is greedy or not. A greedy operator
+    /// will match as much as it can. A non-greedy operator will match as
+    /// little as it can.
+    ///
+    /// Typically, operators are greedy by default and are only non-greedy when
+    /// a `?` suffix is used, e.g., `(expr)*` is greedy while `(expr)*?` is
+    /// not. However, this can be inverted via the `U` "ungreedy" flag.
+    pub greedy: bool,
+    /// The expression being repeated.
+    pub hir: Box<Hir>,
+}
+
+impl Repetition {
+    /// Returns true if and only if this repetition operator makes it possible
+    /// to match the empty string.
+    ///
+    /// Note that this is not defined inductively. For example, while `a*`
+    /// will report `true`, `()+` will not, even though `()` matches the empty
+    /// string and one or more occurrences of something that matches the empty
+    /// string will always match the empty string. In order to get the
+    /// inductive definition, see the corresponding method on
+    /// [`Hir`](struct.Hir.html).
+    pub fn is_match_empty(&self) -> bool {
+        match self.kind {
+            RepetitionKind::ZeroOrOne => true,
+            RepetitionKind::ZeroOrMore => true,
+            RepetitionKind::OneOrMore => false,
+            RepetitionKind::Range(RepetitionRange::Exactly(m)) => m == 0,
+            RepetitionKind::Range(RepetitionRange::AtLeast(m)) => m == 0,
+            RepetitionKind::Range(RepetitionRange::Bounded(m, _)) => m == 0,
+        }
+    }
+}
+
+/// The kind of a repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionKind {
+    /// Matches a sub-expression zero or one times.
+    ZeroOrOne,
+    /// Matches a sub-expression zero or more times.
+    ZeroOrMore,
+    /// Matches a sub-expression one or more times.
+    OneOrMore,
+    /// Matches a sub-expression within a bounded range of times.
+    Range(RepetitionRange),
+}
+
+/// The kind of a counted repetition operator.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum RepetitionRange {
+    /// Matches a sub-expression exactly this many times.
+    Exactly(u32),
+    /// Matches a sub-expression at least this many times.
+    AtLeast(u32),
+    /// Matches a sub-expression at least `m` times and at most `n` times.
+    Bounded(u32, u32),
+}
+
+/// A custom `Drop` impl is used for `HirKind` such that it uses constant stack
+/// space but heap space proportional to the depth of the total `Hir`.
+impl Drop for Hir {
+    fn drop(&mut self) {
+        use std::mem;
+
+        match *self.kind() {
+            HirKind::Empty
+            | HirKind::Literal(_)
+            | HirKind::Class(_)
+            | HirKind::Anchor(_)
+            | HirKind::WordBoundary(_) => return,
+            HirKind::Group(ref x) if !x.hir.kind.has_subexprs() => return,
+            HirKind::Repetition(ref x) if !x.hir.kind.has_subexprs() => return,
+            HirKind::Concat(ref x) if x.is_empty() => return,
+            HirKind::Alternation(ref x) if x.is_empty() => return,
+            _ => {}
+        }
+
+        let mut stack = vec![mem::replace(self, Hir::empty())];
+        while let Some(mut expr) = stack.pop() {
+            match expr.kind {
+                HirKind::Empty
+                | HirKind::Literal(_)
+                | HirKind::Class(_)
+                | HirKind::Anchor(_)
+                | HirKind::WordBoundary(_) => {}
+                HirKind::Group(ref mut x) => {
+                    stack.push(mem::replace(&mut x.hir, Hir::empty()));
+                }
+                HirKind::Repetition(ref mut x) => {
+                    stack.push(mem::replace(&mut x.hir, Hir::empty()));
+                }
+                HirKind::Concat(ref mut x) => {
+                    stack.extend(x.drain(..));
+                }
+                HirKind::Alternation(ref mut x) => {
+                    stack.extend(x.drain(..));
+                }
+            }
+        }
+    }
+}
+
+/// A type that documents various attributes of an HIR expression.
+///
+/// These attributes are typically defined inductively on the HIR.
+#[derive(Clone, Debug, Eq, PartialEq)]
+struct HirInfo {
+    /// Represent yes/no questions by a bitfield to conserve space, since
+    /// this is included in every HIR expression.
+    ///
+    /// If more attributes need to be added, it is OK to increase the size of
+    /// this as appropriate.
+    bools: u8,
+}
+
+// A simple macro for defining bitfield accessors/mutators.
+macro_rules! define_bool {
+    ($bit:expr, $is_fn_name:ident, $set_fn_name:ident) => {
+        fn $is_fn_name(&self) -> bool {
+            self.bools & (0b1 << $bit) > 0
+        }
+
+        fn $set_fn_name(&mut self, yes: bool) {
+            if yes {
+                self.bools |= 1 << $bit;
+            } else {
+                self.bools &= !(1 << $bit);
+            }
+        }
+    }
+}
+
+impl HirInfo {
+    fn new() -> HirInfo {
+        HirInfo {
+            bools: 0,
+        }
+    }
+
+    define_bool!(0, is_always_utf8, set_always_utf8);
+    define_bool!(1, is_all_assertions, set_all_assertions);
+    define_bool!(2, is_anchored_start, set_anchored_start);
+    define_bool!(3, is_anchored_end, set_anchored_end);
+    define_bool!(4, is_any_anchored_start, set_any_anchored_start);
+    define_bool!(5, is_any_anchored_end, set_any_anchored_end);
+    define_bool!(6, is_match_empty, set_match_empty);
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn uclass(ranges: &[(char, char)]) -> ClassUnicode {
+        let ranges: Vec<ClassUnicodeRange> = ranges
+            .iter()
+            .map(|&(s, e)| ClassUnicodeRange::new(s, e))
+            .collect();
+        ClassUnicode::new(ranges)
+    }
+
+    fn bclass(ranges: &[(u8, u8)]) -> ClassBytes {
+        let ranges: Vec<ClassBytesRange> = ranges
+            .iter()
+            .map(|&(s, e)| ClassBytesRange::new(s, e))
+            .collect();
+        ClassBytes::new(ranges)
+    }
+
+    fn uranges(cls: &ClassUnicode) -> Vec<(char, char)> {
+        cls.iter().map(|x| (x.start(), x.end())).collect()
+    }
+
+    fn ucasefold(cls: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls.clone();
+        cls_.case_fold_simple();
+        cls_
+    }
+
+    fn uunion(cls1: &ClassUnicode, cls2: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls1.clone();
+        cls_.union(cls2);
+        cls_
+    }
+
+    fn uintersect(cls1: &ClassUnicode, cls2: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls1.clone();
+        cls_.intersect(cls2);
+        cls_
+    }
+
+    fn udifference(cls1: &ClassUnicode, cls2: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls1.clone();
+        cls_.difference(cls2);
+        cls_
+    }
+
+    fn usymdifference(cls1: &ClassUnicode, cls2: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls1.clone();
+        cls_.symmetric_difference(cls2);
+        cls_
+    }
+
+    fn unegate(cls: &ClassUnicode) -> ClassUnicode {
+        let mut cls_ = cls.clone();
+        cls_.negate();
+        cls_
+    }
+
+    fn branges(cls: &ClassBytes) -> Vec<(u8, u8)> {
+        cls.iter().map(|x| (x.start(), x.end())).collect()
+    }
+
+    fn bcasefold(cls: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls.clone();
+        cls_.case_fold_simple();
+        cls_
+    }
+
+    fn bunion(cls1: &ClassBytes, cls2: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls1.clone();
+        cls_.union(cls2);
+        cls_
+    }
+
+    fn bintersect(cls1: &ClassBytes, cls2: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls1.clone();
+        cls_.intersect(cls2);
+        cls_
+    }
+
+    fn bdifference(cls1: &ClassBytes, cls2: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls1.clone();
+        cls_.difference(cls2);
+        cls_
+    }
+
+    fn bsymdifference(cls1: &ClassBytes, cls2: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls1.clone();
+        cls_.symmetric_difference(cls2);
+        cls_
+    }
+
+    fn bnegate(cls: &ClassBytes) -> ClassBytes {
+        let mut cls_ = cls.clone();
+        cls_.negate();
+        cls_
+    }
+
+    #[test]
+    fn class_range_canonical_unicode() {
+        let range = ClassUnicodeRange::new('\u{00FF}', '\0');
+        assert_eq!('\0', range.start());
+        assert_eq!('\u{00FF}', range.end());
+    }
+
+    #[test]
+    fn class_range_canonical_bytes() {
+        let range = ClassBytesRange::new(b'\xFF', b'\0');
+        assert_eq!(b'\0', range.start());
+        assert_eq!(b'\xFF', range.end());
+    }
+
+    #[test]
+    fn class_canonicalize_unicode() {
+        let cls = uclass(&[('a', 'c'), ('x', 'z')]);
+        let expected = vec![('a', 'c'), ('x', 'z')];
+        assert_eq!(expected, uranges(&cls));
+
+        let cls = uclass(&[('x', 'z'), ('a', 'c')]);
+        let expected = vec![('a', 'c'), ('x', 'z')];
+        assert_eq!(expected, uranges(&cls));
+
+        let cls = uclass(&[('x', 'z'), ('w', 'y')]);
+        let expected = vec![('w', 'z')];
+        assert_eq!(expected, uranges(&cls));
+
+        let cls = uclass(&[
+            ('c', 'f'), ('a', 'g'), ('d', 'j'), ('a', 'c'),
+            ('m', 'p'), ('l', 's'),
+        ]);
+        let expected = vec![('a', 'j'), ('l', 's')];
+        assert_eq!(expected, uranges(&cls));
+
+        let cls = uclass(&[('x', 'z'), ('u', 'w')]);
+        let expected = vec![('u', 'z')];
+        assert_eq!(expected, uranges(&cls));
+
+        let cls = uclass(&[('\x00', '\u{10FFFF}'), ('\x00', '\u{10FFFF}')]);
+        let expected = vec![('\x00', '\u{10FFFF}')];
+        assert_eq!(expected, uranges(&cls));
+
+
+        let cls = uclass(&[('a', 'a'), ('b', 'b')]);
+        let expected = vec![('a', 'b')];
+        assert_eq!(expected, uranges(&cls));
+    }
+
+    #[test]
+    fn class_canonicalize_bytes() {
+        let cls = bclass(&[(b'a', b'c'), (b'x', b'z')]);
+        let expected = vec![(b'a', b'c'), (b'x', b'z')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[(b'x', b'z'), (b'a', b'c')]);
+        let expected = vec![(b'a', b'c'), (b'x', b'z')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[(b'x', b'z'), (b'w', b'y')]);
+        let expected = vec![(b'w', b'z')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[
+            (b'c', b'f'), (b'a', b'g'), (b'd', b'j'), (b'a', b'c'),
+            (b'm', b'p'), (b'l', b's'),
+        ]);
+        let expected = vec![(b'a', b'j'), (b'l', b's')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[(b'x', b'z'), (b'u', b'w')]);
+        let expected = vec![(b'u', b'z')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[(b'\x00', b'\xFF'), (b'\x00', b'\xFF')]);
+        let expected = vec![(b'\x00', b'\xFF')];
+        assert_eq!(expected, branges(&cls));
+
+        let cls = bclass(&[(b'a', b'a'), (b'b', b'b')]);
+        let expected = vec![(b'a', b'b')];
+        assert_eq!(expected, branges(&cls));
+    }
+
+    #[test]
+    fn class_case_fold_unicode() {
+        let cls = uclass(&[
+            ('C', 'F'), ('A', 'G'), ('D', 'J'), ('A', 'C'),
+            ('M', 'P'), ('L', 'S'), ('c', 'f'),
+        ]);
+        let expected = uclass(&[
+            ('A', 'J'), ('L', 'S'),
+            ('a', 'j'), ('l', 's'),
+            ('\u{17F}', '\u{17F}'),
+        ]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('A', 'Z')]);
+        let expected = uclass(&[
+            ('A', 'Z'), ('a', 'z'),
+            ('\u{17F}', '\u{17F}'),
+            ('\u{212A}', '\u{212A}'),
+        ]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('a', 'z')]);
+        let expected = uclass(&[
+            ('A', 'Z'), ('a', 'z'),
+            ('\u{17F}', '\u{17F}'),
+            ('\u{212A}', '\u{212A}'),
+        ]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('A', 'A'), ('_', '_')]);
+        let expected = uclass(&[('A', 'A'), ('_', '_'), ('a', 'a')]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('A', 'A'), ('=', '=')]);
+        let expected = uclass(&[('=', '='), ('A', 'A'), ('a', 'a')]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('\x00', '\x10')]);
+        assert_eq!(cls, ucasefold(&cls));
+
+        let cls = uclass(&[('k', 'k')]);
+        let expected = uclass(&[
+            ('K', 'K'), ('k', 'k'), ('\u{212A}', '\u{212A}'),
+        ]);
+        assert_eq!(expected, ucasefold(&cls));
+
+        let cls = uclass(&[('@', '@')]);
+        assert_eq!(cls, ucasefold(&cls));
+    }
+
+    #[test]
+    fn class_case_fold_bytes() {
+        let cls = bclass(&[
+            (b'C', b'F'), (b'A', b'G'), (b'D', b'J'), (b'A', b'C'),
+            (b'M', b'P'), (b'L', b'S'), (b'c', b'f'),
+        ]);
+        let expected = bclass(&[
+            (b'A', b'J'), (b'L', b'S'),
+            (b'a', b'j'), (b'l', b's'),
+        ]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'A', b'Z')]);
+        let expected = bclass(&[(b'A', b'Z'), (b'a', b'z')]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'a', b'z')]);
+        let expected = bclass(&[(b'A', b'Z'), (b'a', b'z')]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'A', b'A'), (b'_', b'_')]);
+        let expected = bclass(&[(b'A', b'A'), (b'_', b'_'), (b'a', b'a')]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'A', b'A'), (b'=', b'=')]);
+        let expected = bclass(&[(b'=', b'='), (b'A', b'A'), (b'a', b'a')]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'\x00', b'\x10')]);
+        assert_eq!(cls, bcasefold(&cls));
+
+        let cls = bclass(&[(b'k', b'k')]);
+        let expected = bclass(&[(b'K', b'K'), (b'k', b'k')]);
+        assert_eq!(expected, bcasefold(&cls));
+
+        let cls = bclass(&[(b'@', b'@')]);
+        assert_eq!(cls, bcasefold(&cls));
+    }
+
+    #[test]
+    fn class_negate_unicode() {
+        let cls = uclass(&[('a', 'a')]);
+        let expected = uclass(&[('\x00', '\x60'), ('\x62', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('a', 'a'), ('b', 'b')]);
+        let expected = uclass(&[('\x00', '\x60'), ('\x63', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('a', 'c'), ('x', 'z')]);
+        let expected = uclass(&[
+            ('\x00', '\x60'), ('\x64', '\x77'), ('\x7B', '\u{10FFFF}'),
+        ]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\x00', 'a')]);
+        let expected = uclass(&[('\x62', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('a', '\u{10FFFF}')]);
+        let expected = uclass(&[('\x00', '\x60')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\x00', '\u{10FFFF}')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[]);
+        let expected = uclass(&[('\x00', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[
+            ('\x00', '\u{10FFFD}'), ('\u{10FFFF}', '\u{10FFFF}'),
+        ]);
+        let expected = uclass(&[('\u{10FFFE}', '\u{10FFFE}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\x00', '\u{D7FF}')]);
+        let expected = uclass(&[('\u{E000}', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\x00', '\u{D7FE}')]);
+        let expected = uclass(&[('\u{D7FF}', '\u{10FFFF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\u{E000}', '\u{10FFFF}')]);
+        let expected = uclass(&[('\x00', '\u{D7FF}')]);
+        assert_eq!(expected, unegate(&cls));
+
+        let cls = uclass(&[('\u{E001}', '\u{10FFFF}')]);
+        let expected = uclass(&[('\x00', '\u{E000}')]);
+        assert_eq!(expected, unegate(&cls));
+    }
+
+    #[test]
+    fn class_negate_bytes() {
+        let cls = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[(b'\x00', b'\x60'), (b'\x62', b'\xFF')]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'a', b'a'), (b'b', b'b')]);
+        let expected = bclass(&[(b'\x00', b'\x60'), (b'\x63', b'\xFF')]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'a', b'c'), (b'x', b'z')]);
+        let expected = bclass(&[
+            (b'\x00', b'\x60'), (b'\x64', b'\x77'), (b'\x7B', b'\xFF'),
+        ]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'\x00', b'a')]);
+        let expected = bclass(&[(b'\x62', b'\xFF')]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'a', b'\xFF')]);
+        let expected = bclass(&[(b'\x00', b'\x60')]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'\x00', b'\xFF')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[]);
+        let expected = bclass(&[(b'\x00', b'\xFF')]);
+        assert_eq!(expected, bnegate(&cls));
+
+        let cls = bclass(&[(b'\x00', b'\xFD'), (b'\xFF', b'\xFF')]);
+        let expected = bclass(&[(b'\xFE', b'\xFE')]);
+        assert_eq!(expected, bnegate(&cls));
+    }
+
+    #[test]
+    fn class_union_unicode() {
+        let cls1 = uclass(&[('a', 'g'), ('m', 't'), ('A', 'C')]);
+        let cls2 = uclass(&[('a', 'z')]);
+        let expected = uclass(&[('a', 'z'), ('A', 'C')]);
+        assert_eq!(expected, uunion(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_union_bytes() {
+        let cls1 = bclass(&[(b'a', b'g'), (b'm', b't'), (b'A', b'C')]);
+        let cls2 = bclass(&[(b'a', b'z')]);
+        let expected = bclass(&[(b'a', b'z'), (b'A', b'C')]);
+        assert_eq!(expected, bunion(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_intersect_unicode() {
+        let cls1 = uclass(&[]);
+        let cls2 = uclass(&[('a', 'a')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'a')]);
+        let cls2 = uclass(&[('a', 'a')]);
+        let expected = uclass(&[('a', 'a')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'a')]);
+        let cls2 = uclass(&[('b', 'b')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'a')]);
+        let cls2 = uclass(&[('a', 'c')]);
+        let expected = uclass(&[('a', 'a')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b')]);
+        let cls2 = uclass(&[('a', 'c')]);
+        let expected = uclass(&[('a', 'b')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b')]);
+        let cls2 = uclass(&[('b', 'c')]);
+        let expected = uclass(&[('b', 'b')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b')]);
+        let cls2 = uclass(&[('c', 'd')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('b', 'c')]);
+        let cls2 = uclass(&[('a', 'd')]);
+        let expected = uclass(&[('b', 'c')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = uclass(&[('a', 'h')]);
+        let expected = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let expected = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('g', 'h')]);
+        let cls2 = uclass(&[('d', 'e'), ('k', 'l')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
+        let cls2 = uclass(&[('h', 'h')]);
+        let expected = uclass(&[('h', 'h')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('e', 'f'), ('i', 'j')]);
+        let cls2 = uclass(&[('c', 'd'), ('g', 'h'), ('k', 'l')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'b'), ('c', 'd'), ('e', 'f')]);
+        let cls2 = uclass(&[('b', 'c'), ('d', 'e'), ('f', 'g')]);
+        let expected = uclass(&[('b', 'f')]);
+        assert_eq!(expected, uintersect(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_intersect_bytes() {
+        let cls1 = bclass(&[]);
+        let cls2 = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'a')]);
+        let cls2 = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[(b'a', b'a')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'a')]);
+        let cls2 = bclass(&[(b'b', b'b')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'a')]);
+        let cls2 = bclass(&[(b'a', b'c')]);
+        let expected = bclass(&[(b'a', b'a')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b')]);
+        let cls2 = bclass(&[(b'a', b'c')]);
+        let expected = bclass(&[(b'a', b'b')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b')]);
+        let cls2 = bclass(&[(b'b', b'c')]);
+        let expected = bclass(&[(b'b', b'b')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b')]);
+        let cls2 = bclass(&[(b'c', b'd')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'b', b'c')]);
+        let cls2 = bclass(&[(b'a', b'd')]);
+        let expected = bclass(&[(b'b', b'c')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        let cls2 = bclass(&[(b'a', b'h')]);
+        let expected = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        let cls2 = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        let expected = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'g', b'h')]);
+        let cls2 = bclass(&[(b'd', b'e'), (b'k', b'l')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'd', b'e'), (b'g', b'h')]);
+        let cls2 = bclass(&[(b'h', b'h')]);
+        let expected = bclass(&[(b'h', b'h')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'e', b'f'), (b'i', b'j')]);
+        let cls2 = bclass(&[(b'c', b'd'), (b'g', b'h'), (b'k', b'l')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'b'), (b'c', b'd'), (b'e', b'f')]);
+        let cls2 = bclass(&[(b'b', b'c'), (b'd', b'e'), (b'f', b'g')]);
+        let expected = bclass(&[(b'b', b'f')]);
+        assert_eq!(expected, bintersect(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_difference_unicode() {
+        let cls1 = uclass(&[('a', 'a')]);
+        let cls2 = uclass(&[('a', 'a')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'a')]);
+        let cls2 = uclass(&[]);
+        let expected = uclass(&[('a', 'a')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[]);
+        let cls2 = uclass(&[('a', 'a')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'z')]);
+        let cls2 = uclass(&[('a', 'a')]);
+        let expected = uclass(&[('b', 'z')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'z')]);
+        let cls2 = uclass(&[('z', 'z')]);
+        let expected = uclass(&[('a', 'y')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'z')]);
+        let cls2 = uclass(&[('m', 'm')]);
+        let expected = uclass(&[('a', 'l'), ('n', 'z')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'c'), ('g', 'i'), ('r', 't')]);
+        let cls2 = uclass(&[('a', 'z')]);
+        let expected = uclass(&[]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'c'), ('g', 'i'), ('r', 't')]);
+        let cls2 = uclass(&[('d', 'v')]);
+        let expected = uclass(&[('a', 'c')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'c'), ('g', 'i'), ('r', 't')]);
+        let cls2 = uclass(&[('b', 'g'), ('s', 'u')]);
+        let expected = uclass(&[('a', 'a'), ('h', 'i'), ('r', 'r')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'c'), ('g', 'i'), ('r', 't')]);
+        let cls2 = uclass(&[('b', 'd'), ('e', 'g'), ('s', 'u')]);
+        let expected = uclass(&[('a', 'a'), ('h', 'i'), ('r', 'r')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('x', 'z')]);
+        let cls2 = uclass(&[('a', 'c'), ('e', 'g'), ('s', 'u')]);
+        let expected = uclass(&[('x', 'z')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+
+        let cls1 = uclass(&[('a', 'z')]);
+        let cls2 = uclass(&[('a', 'c'), ('e', 'g'), ('s', 'u')]);
+        let expected = uclass(&[('d', 'd'), ('h', 'r'), ('v', 'z')]);
+        assert_eq!(expected, udifference(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_difference_bytes() {
+        let cls1 = bclass(&[(b'a', b'a')]);
+        let cls2 = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'a')]);
+        let cls2 = bclass(&[]);
+        let expected = bclass(&[(b'a', b'a')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[]);
+        let cls2 = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'z')]);
+        let cls2 = bclass(&[(b'a', b'a')]);
+        let expected = bclass(&[(b'b', b'z')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'z')]);
+        let cls2 = bclass(&[(b'z', b'z')]);
+        let expected = bclass(&[(b'a', b'y')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'z')]);
+        let cls2 = bclass(&[(b'm', b'm')]);
+        let expected = bclass(&[(b'a', b'l'), (b'n', b'z')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'c'), (b'g', b'i'), (b'r', b't')]);
+        let cls2 = bclass(&[(b'a', b'z')]);
+        let expected = bclass(&[]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'c'), (b'g', b'i'), (b'r', b't')]);
+        let cls2 = bclass(&[(b'd', b'v')]);
+        let expected = bclass(&[(b'a', b'c')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'c'), (b'g', b'i'), (b'r', b't')]);
+        let cls2 = bclass(&[(b'b', b'g'), (b's', b'u')]);
+        let expected = bclass(&[(b'a', b'a'), (b'h', b'i'), (b'r', b'r')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'c'), (b'g', b'i'), (b'r', b't')]);
+        let cls2 = bclass(&[(b'b', b'd'), (b'e', b'g'), (b's', b'u')]);
+        let expected = bclass(&[(b'a', b'a'), (b'h', b'i'), (b'r', b'r')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'x', b'z')]);
+        let cls2 = bclass(&[(b'a', b'c'), (b'e', b'g'), (b's', b'u')]);
+        let expected = bclass(&[(b'x', b'z')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+
+        let cls1 = bclass(&[(b'a', b'z')]);
+        let cls2 = bclass(&[(b'a', b'c'), (b'e', b'g'), (b's', b'u')]);
+        let expected = bclass(&[(b'd', b'd'), (b'h', b'r'), (b'v', b'z')]);
+        assert_eq!(expected, bdifference(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_symmetric_difference_unicode() {
+        let cls1 = uclass(&[('a', 'm')]);
+        let cls2 = uclass(&[('g', 't')]);
+        let expected = uclass(&[('a', 'f'), ('n', 't')]);
+        assert_eq!(expected, usymdifference(&cls1, &cls2));
+    }
+
+    #[test]
+    fn class_symmetric_difference_bytes() {
+        let cls1 = bclass(&[(b'a', b'm')]);
+        let cls2 = bclass(&[(b'g', b't')]);
+        let expected = bclass(&[(b'a', b'f'), (b'n', b't')]);
+        assert_eq!(expected, bsymdifference(&cls1, &cls2));
+    }
+
+    #[test]
+    #[should_panic]
+    fn hir_byte_literal_non_ascii() {
+        Hir::literal(Literal::Byte(b'a'));
+    }
+
+    // We use a thread with an explicit stack size to test that our destructor
+    // for Hir can handle arbitrarily sized expressions in constant stack
+    // space. In case we run on a platform without threads (WASM?), we limit
+    // this test to Windows/Unix.
+    #[test]
+    #[cfg(any(unix, windows))]
+    fn no_stack_overflow_on_drop() {
+        use std::thread;
+
+        let run = || {
+            let mut expr = Hir::empty();
+            for _ in 0..100 {
+                expr = Hir::group(Group {
+                    kind: GroupKind::NonCapturing,
+                    hir: Box::new(expr),
+                });
+                expr = Hir::repetition(Repetition {
+                    kind: RepetitionKind::ZeroOrOne,
+                    greedy: true,
+                    hir: Box::new(expr),
+                });
+
+                expr = Hir {
+                    kind: HirKind::Concat(vec![expr]),
+                    info: HirInfo::new(),
+                };
+                expr = Hir {
+                    kind: HirKind::Alternation(vec![expr]),
+                    info: HirInfo::new(),
+                };
+            }
+            assert!(!expr.kind.is_empty());
+        };
+
+        // We run our test on a thread with a small stack size so we can
+        // force the issue more easily.
+        thread::Builder::new()
+            .stack_size(1<<10)
+            .spawn(run)
+            .unwrap()
+            .join()
+            .unwrap();
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/hir/print.rs b/third_party/rust/regex-syntax/src/hir/print.rs
new file mode 100644
index 000000000000..e312d8852ca4
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/print.rs
@@ -0,0 +1,375 @@
+/*!
+This module provides a regular expression printer for `Hir`.
+*/
+
+use std::fmt;
+
+use hir::{self, Hir, HirKind};
+use hir::visitor::{self, Visitor};
+use is_meta_character;
+
+/// A builder for constructing a printer.
+///
+/// Note that since a printer doesn't have any configuration knobs, this type
+/// remains unexported.
+#[derive(Clone, Debug)]
+struct PrinterBuilder {
+    _priv: (),
+}
+
+impl Default for PrinterBuilder {
+    fn default() -> PrinterBuilder {
+        PrinterBuilder::new()
+    }
+}
+
+impl PrinterBuilder {
+    fn new() -> PrinterBuilder {
+        PrinterBuilder {
+            _priv: (),
+        }
+    }
+
+    fn build(&self) -> Printer {
+        Printer {
+            _priv: (),
+        }
+    }
+}
+
+/// A printer for a regular expression's high-level intermediate
+/// representation.
+///
+/// A printer converts a high-level intermediate representation (HIR) to a
+/// regular expression pattern string. This particular printer uses constant
+/// stack space and heap space proportional to the size of the HIR.
+///
+/// Since this printer is only using the HIR, the pattern it prints will likely
+/// not resemble the original pattern at all. For example, a pattern like
+/// `\pL` will have its entire class written out.
+///
+/// The purpose of this printer is to provide a means to mutate an HIR and then
+/// build a regular expression from the result of that mutation. (A regex
+/// library could provide a constructor from this HIR explicitly, but that
+/// creates an unnecessary public coupling between the regex library and this
+/// specific HIR representation.)
+#[derive(Debug)]
+pub struct Printer {
+    _priv: (),
+}
+
+impl Printer {
+    /// Create a new printer.
+    pub fn new() -> Printer {
+        PrinterBuilder::new().build()
+    }
+
+    /// Print the given `Ast` to the given writer. The writer must implement
+    /// `fmt::Write`. Typical implementations of `fmt::Write` that can be used
+    /// here are a `fmt::Formatter` (which is available in `fmt::Display`
+    /// implementations) or a `&mut String`.
+    pub fn print<W: fmt::Write>(&mut self, hir: &Hir, wtr: W) -> fmt::Result {
+        visitor::visit(hir, Writer { printer: self, wtr: wtr })
+    }
+}
+
+#[derive(Debug)]
+struct Writer<'p, W> {
+    printer: &'p mut Printer,
+    wtr: W,
+}
+
+impl<'p, W: fmt::Write> Visitor for Writer<'p, W> {
+    type Output = ();
+    type Err = fmt::Error;
+
+    fn finish(self) -> fmt::Result {
+        Ok(())
+    }
+
+    fn visit_pre(&mut self, hir: &Hir) -> fmt::Result {
+        match *hir.kind() {
+            HirKind::Empty
+            | HirKind::Repetition(_)
+            | HirKind::Concat(_)
+            | HirKind::Alternation(_) => {}
+            HirKind::Literal(hir::Literal::Unicode(c)) => {
+                self.write_literal_char(c)?;
+            }
+            HirKind::Literal(hir::Literal::Byte(b)) => {
+                self.write_literal_byte(b)?;
+            }
+            HirKind::Class(hir::Class::Unicode(ref cls)) => {
+                self.wtr.write_str("[")?;
+                for range in cls.iter() {
+                    if range.start() == range.end() {
+                        self.write_literal_char(range.start())?;
+                    } else {
+                        self.write_literal_char(range.start())?;
+                        self.wtr.write_str("-")?;
+                        self.write_literal_char(range.end())?;
+                    }
+                }
+                self.wtr.write_str("]")?;
+            }
+            HirKind::Class(hir::Class::Bytes(ref cls)) => {
+                self.wtr.write_str("(?-u:[")?;
+                for range in cls.iter() {
+                    if range.start() == range.end() {
+                        self.write_literal_class_byte(range.start())?;
+                    } else {
+                        self.write_literal_class_byte(range.start())?;
+                        self.wtr.write_str("-")?;
+                        self.write_literal_class_byte(range.end())?;
+                    }
+                }
+                self.wtr.write_str("])")?;
+            }
+            HirKind::Anchor(hir::Anchor::StartLine) => {
+                self.wtr.write_str("(?m:^)")?;
+            }
+            HirKind::Anchor(hir::Anchor::EndLine) => {
+                self.wtr.write_str("(?m:$)")?;
+            }
+            HirKind::Anchor(hir::Anchor::StartText) => {
+                self.wtr.write_str(r"\A")?;
+            }
+            HirKind::Anchor(hir::Anchor::EndText) => {
+                self.wtr.write_str(r"\z")?;
+            }
+            HirKind::WordBoundary(hir::WordBoundary::Unicode) => {
+                self.wtr.write_str(r"\b")?;
+            }
+            HirKind::WordBoundary(hir::WordBoundary::UnicodeNegate) => {
+                self.wtr.write_str(r"\B")?;
+            }
+            HirKind::WordBoundary(hir::WordBoundary::Ascii) => {
+                self.wtr.write_str(r"(?-u:\b)")?;
+            }
+            HirKind::WordBoundary(hir::WordBoundary::AsciiNegate) => {
+                self.wtr.write_str(r"(?-u:\B)")?;
+            }
+            HirKind::Group(ref x) => {
+                match x.kind {
+                    hir::GroupKind::CaptureIndex(_) => {
+                        self.wtr.write_str("(")?;
+                    }
+                    hir::GroupKind::CaptureName { ref name, .. } => {
+                        write!(self.wtr, "(?P<{}>", name)?;
+                    }
+                    hir::GroupKind::NonCapturing => {
+                        self.wtr.write_str("(?:")?;
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
+
+    fn visit_post(&mut self, hir: &Hir) -> fmt::Result {
+        match *hir.kind() {
+            // Handled during visit_pre
+            HirKind::Empty
+            | HirKind::Literal(_)
+            | HirKind::Class(_)
+            | HirKind::Anchor(_)
+            | HirKind::WordBoundary(_)
+            | HirKind::Concat(_)
+            | HirKind::Alternation(_) => {}
+            HirKind::Repetition(ref x) => {
+                match x.kind {
+                    hir::RepetitionKind::ZeroOrOne => {
+                        self.wtr.write_str("?")?;
+                    }
+                    hir::RepetitionKind::ZeroOrMore => {
+                        self.wtr.write_str("*")?;
+                    }
+                    hir::RepetitionKind::OneOrMore => {
+                        self.wtr.write_str("+")?;
+                    }
+                    hir::RepetitionKind::Range(ref x) => {
+                        match *x {
+                            hir::RepetitionRange::Exactly(m) => {
+                                write!(self.wtr, "{{{}}}", m)?;
+                            }
+                            hir::RepetitionRange::AtLeast(m) => {
+                                write!(self.wtr, "{{{},}}", m)?;
+                            }
+                            hir::RepetitionRange::Bounded(m, n) => {
+                                write!(self.wtr, "{{{},{}}}", m, n)?;
+                            }
+                        }
+                    }
+                }
+                if !x.greedy {
+                    self.wtr.write_str("?")?;
+                }
+            }
+            HirKind::Group(_) => {
+                self.wtr.write_str(")")?;
+            }
+        }
+        Ok(())
+    }
+
+    fn visit_alternation_in(&mut self) -> fmt::Result {
+        self.wtr.write_str("|")
+    }
+}
+
+impl<'p, W: fmt::Write> Writer<'p, W> {
+    fn write_literal_char(&mut self, c: char) -> fmt::Result {
+        if is_meta_character(c) {
+            self.wtr.write_str("\\")?;
+        }
+        self.wtr.write_char(c)
+    }
+
+    fn write_literal_byte(&mut self, b: u8) -> fmt::Result {
+        let c = b as char;
+        if c <= 0x7F as char && !c.is_control() && !c.is_whitespace() {
+            self.write_literal_char(c)
+        } else {
+            write!(self.wtr, "(?-u:\\x{:02X})", b)
+        }
+    }
+
+    fn write_literal_class_byte(&mut self, b: u8) -> fmt::Result {
+        let c = b as char;
+        if c <= 0x7F as char && !c.is_control() && !c.is_whitespace() {
+            self.write_literal_char(c)
+        } else {
+            write!(self.wtr, "\\x{:02X}", b)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ParserBuilder;
+    use super::Printer;
+
+    fn roundtrip(given: &str, expected: &str) {
+        roundtrip_with(|b| b, given, expected);
+    }
+
+    fn roundtrip_bytes(given: &str, expected: &str) {
+        roundtrip_with(|b| b.allow_invalid_utf8(true), given, expected);
+    }
+
+    fn roundtrip_with<F>(mut f: F, given: &str, expected: &str)
+    where F: FnMut(&mut ParserBuilder) -> &mut ParserBuilder
+    {
+        let mut builder = ParserBuilder::new();
+        f(&mut builder);
+        let hir = builder.build().parse(given).unwrap();
+
+        let mut printer = Printer::new();
+        let mut dst = String::new();
+        printer.print(&hir, &mut dst).unwrap();
+
+        // Check that the result is actually valid.
+        builder.build().parse(&dst).unwrap();
+
+        assert_eq!(expected, dst);
+    }
+
+    #[test]
+    fn print_literal() {
+        roundtrip("a", "a");
+        roundtrip(r"\xff", "\u{FF}");
+        roundtrip_bytes(r"\xff", "\u{FF}");
+        roundtrip_bytes(r"(?-u)\xff", r"(?-u:\xFF)");
+        roundtrip("☃", "☃");
+    }
+
+    #[test]
+    fn print_class() {
+        roundtrip(r"[a]", r"[a]");
+        roundtrip(r"[a-z]", r"[a-z]");
+        roundtrip(r"[a-z--b-c--x-y]", r"[ad-wz]");
+        roundtrip(r"[^\x01-\u{10FFFF}]", "[\u{0}]");
+        roundtrip(r"[-]", r"[\-]");
+        roundtrip(r"[☃-⛄]", r"[☃-⛄]");
+
+        roundtrip(r"(?-u)[a]", r"(?-u:[a])");
+        roundtrip(r"(?-u)[a-z]", r"(?-u:[a-z])");
+        roundtrip_bytes(r"(?-u)[a-\xFF]", r"(?-u:[a-\xFF])");
+
+        // The following test that the printer escapes meta characters
+        // in character classes.
+        roundtrip(r"[\[]", r"[\[]");
+        roundtrip(r"[Z-_]", r"[Z-_]");
+        roundtrip(r"[Z-_--Z]", r"[\[-_]");
+
+        // The following test that the printer escapes meta characters
+        // in byte oriented character classes.
+        roundtrip_bytes(r"(?-u)[\[]", r"(?-u:[\[])");
+        roundtrip_bytes(r"(?-u)[Z-_]", r"(?-u:[Z-_])");
+        roundtrip_bytes(r"(?-u)[Z-_--Z]", r"(?-u:[\[-_])");
+    }
+
+    #[test]
+    fn print_anchor() {
+        roundtrip(r"^", r"\A");
+        roundtrip(r"$", r"\z");
+        roundtrip(r"(?m)^", r"(?m:^)");
+        roundtrip(r"(?m)$", r"(?m:$)");
+    }
+
+    #[test]
+    fn print_word_boundary() {
+        roundtrip(r"\b", r"\b");
+        roundtrip(r"\B", r"\B");
+        roundtrip(r"(?-u)\b", r"(?-u:\b)");
+        roundtrip_bytes(r"(?-u)\B", r"(?-u:\B)");
+    }
+
+    #[test]
+    fn print_repetition() {
+        roundtrip("a?", "a?");
+        roundtrip("a??", "a??");
+        roundtrip("(?U)a?", "a??");
+
+        roundtrip("a*", "a*");
+        roundtrip("a*?", "a*?");
+        roundtrip("(?U)a*", "a*?");
+
+        roundtrip("a+", "a+");
+        roundtrip("a+?", "a+?");
+        roundtrip("(?U)a+", "a+?");
+
+        roundtrip("a{1}", "a{1}");
+        roundtrip("a{1,}", "a{1,}");
+        roundtrip("a{1,5}", "a{1,5}");
+        roundtrip("a{1}?", "a{1}?");
+        roundtrip("a{1,}?", "a{1,}?");
+        roundtrip("a{1,5}?", "a{1,5}?");
+        roundtrip("(?U)a{1}", "a{1}?");
+        roundtrip("(?U)a{1,}", "a{1,}?");
+        roundtrip("(?U)a{1,5}", "a{1,5}?");
+    }
+
+    #[test]
+    fn print_group() {
+        roundtrip("()", "()");
+        roundtrip("(?P<foo>)", "(?P<foo>)");
+        roundtrip("(?:)", "(?:)");
+
+        roundtrip("(a)", "(a)");
+        roundtrip("(?P<foo>a)", "(?P<foo>a)");
+        roundtrip("(?:a)", "(?:a)");
+
+        roundtrip("((((a))))", "((((a))))");
+    }
+
+    #[test]
+    fn print_alternation() {
+        roundtrip("|", "|");
+        roundtrip("||", "||");
+
+        roundtrip("a|b", "a|b");
+        roundtrip("a|b|c", "a|b|c");
+        roundtrip("foo|bar|quux", "foo|bar|quux");
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/hir/translate.rs b/third_party/rust/regex-syntax/src/hir/translate.rs
new file mode 100644
index 000000000000..8fea00b164b1
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/translate.rs
@@ -0,0 +1,2532 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Defines a translator that converts an `Ast` to an `Hir`.
+*/
+
+use std::cell::{Cell, RefCell};
+use std::result;
+
+use ast::{self, Ast, Span, Visitor};
+use hir::{self, Error, ErrorKind, Hir};
+use unicode::{self, ClassQuery};
+
+type Result<T> = result::Result<T, Error>;
+
+/// A builder for constructing an AST->HIR translator.
+#[derive(Clone, Debug)]
+pub struct TranslatorBuilder {
+    allow_invalid_utf8: bool,
+    flags: Flags,
+}
+
+impl Default for TranslatorBuilder {
+    fn default() -> TranslatorBuilder {
+        TranslatorBuilder::new()
+    }
+}
+
+impl TranslatorBuilder {
+    /// Create a new translator builder with a default c onfiguration.
+    pub fn new() -> TranslatorBuilder {
+        TranslatorBuilder {
+            allow_invalid_utf8: false,
+            flags: Flags::default(),
+        }
+    }
+
+    /// Build a translator using the current configuration.
+    pub fn build(&self) -> Translator {
+        Translator {
+            stack: RefCell::new(vec![]),
+            flags: Cell::new(self.flags),
+            allow_invalid_utf8: self.allow_invalid_utf8,
+        }
+    }
+
+    /// When enabled, translation will permit the construction of a regular
+    /// expression that may match invalid UTF-8.
+    ///
+    /// When disabled (the default), the translator is guaranteed to produce
+    /// an expression that will only ever match valid UTF-8 (otherwise, the
+    /// translator will return an error).
+    ///
+    /// Perhaps surprisingly, when invalid UTF-8 isn't allowed, a negated ASCII
+    /// word boundary (uttered as `(?-u:\B)` in the concrete syntax) will cause
+    /// the parser to return an error. Namely, a negated ASCII word boundary
+    /// can result in matching positions that aren't valid UTF-8 boundaries.
+    pub fn allow_invalid_utf8(
+        &mut self,
+        yes: bool,
+    ) -> &mut TranslatorBuilder {
+        self.allow_invalid_utf8 = yes;
+        self
+    }
+
+    /// Enable or disable the case insensitive flag (`i`) by default.
+    pub fn case_insensitive(&mut self, yes: bool) -> &mut TranslatorBuilder {
+        self.flags.case_insensitive = if yes { Some(true) } else { None };
+        self
+    }
+
+    /// Enable or disable the multi-line matching flag (`m`) by default.
+    pub fn multi_line(&mut self, yes: bool) -> &mut TranslatorBuilder {
+        self.flags.multi_line = if yes { Some(true) } else { None };
+        self
+    }
+
+    /// Enable or disable the "dot matches any character" flag (`s`) by
+    /// default.
+    pub fn dot_matches_new_line(
+        &mut self,
+        yes: bool,
+    ) -> &mut TranslatorBuilder {
+        self.flags.dot_matches_new_line = if yes { Some(true) } else { None };
+        self
+    }
+
+    /// Enable or disable the "swap greed" flag (`U`) by default.
+    pub fn swap_greed(&mut self, yes: bool) -> &mut TranslatorBuilder {
+        self.flags.swap_greed = if yes { Some(true) } else { None };
+        self
+    }
+
+    /// Enable or disable the Unicode flag (`u`) by default.
+    pub fn unicode(&mut self, yes: bool) -> &mut TranslatorBuilder {
+        self.flags.unicode = if yes { None } else { Some(false) };
+        self
+    }
+}
+
+/// A translator maps abstract syntax to a high level intermediate
+/// representation.
+///
+/// A translator may be benefit from reuse. That is, a translator can translate
+/// many abstract syntax trees.
+///
+/// A `Translator` can be configured in more detail via a
+/// [`TranslatorBuilder`](struct.TranslatorBuilder.html).
+#[derive(Clone, Debug)]
+pub struct Translator {
+    /// Our call stack, but on the heap.
+    stack: RefCell<Vec<HirFrame>>,
+    /// The current flag settings.
+    flags: Cell<Flags>,
+    /// Whether we're allowed to produce HIR that can match arbitrary bytes.
+    allow_invalid_utf8: bool,
+}
+
+impl Translator {
+    /// Create a new translator using the default configuration.
+    pub fn new() -> Translator {
+        TranslatorBuilder::new().build()
+    }
+
+    /// Translate the given abstract syntax tree (AST) into a high level
+    /// intermediate representation (HIR).
+    ///
+    /// If there was a problem doing the translation, then an HIR-specific
+    /// error is returned.
+    ///
+    /// The original pattern string used to produce the `Ast` *must* also be
+    /// provided. The translator does not use the pattern string during any
+    /// correct translation, but is used for error reporting.
+    pub fn translate(&mut self, pattern: &str, ast: &Ast) -> Result<Hir> {
+        ast::visit(ast, TranslatorI::new(self, pattern))
+    }
+}
+
+/// An HirFrame is a single stack frame, represented explicitly, which is
+/// created for each item in the Ast that we traverse.
+///
+/// Note that technically, this type doesn't represent our entire stack
+/// frame. In particular, the Ast visitor represents any state associated with
+/// traversing the Ast itself.
+#[derive(Clone, Debug)]
+enum HirFrame {
+    /// An arbitrary HIR expression. These get pushed whenever we hit a base
+    /// case in the Ast. They get popped after an inductive (i.e., recursive)
+    /// step is complete.
+    Expr(Hir),
+    /// A Unicode character class. This frame is mutated as we descend into
+    /// the Ast of a character class (which is itself its own mini recursive
+    /// structure).
+    ClassUnicode(hir::ClassUnicode),
+    /// A byte-oriented character class. This frame is mutated as we descend
+    /// into the Ast of a character class (which is itself its own mini
+    /// recursive structure).
+    ///
+    /// Byte character classes are created when Unicode mode (`u`) is disabled.
+    /// If `allow_invalid_utf8` is disabled (the default), then a byte
+    /// character is only permitted to match ASCII text.
+    ClassBytes(hir::ClassBytes),
+    /// This is pushed on to the stack upon first seeing any kind of group,
+    /// indicated by parentheses (including non-capturing groups). It is popped
+    /// upon leaving a group.
+    Group {
+        /// The old active flags, if any, when this group was opened.
+        ///
+        /// If this group sets flags, then the new active flags are set to the
+        /// result of merging the old flags with the flags introduced by this
+        /// group.
+        ///
+        /// When this group is popped, the active flags should be restored to
+        /// the flags set here.
+        ///
+        /// The "active" flags correspond to whatever flags are set in the
+        /// Translator.
+        old_flags: Option<Flags>,
+    },
+    /// This is pushed whenever a concatenation is observed. After visiting
+    /// every sub-expression in the concatenation, the translator's stack is
+    /// popped until it sees a Concat frame.
+    Concat,
+    /// This is pushed whenever an alternation is observed. After visiting
+    /// every sub-expression in the alternation, the translator's stack is
+    /// popped until it sees an Alternation frame.
+    Alternation,
+}
+
+impl HirFrame {
+    /// Assert that the current stack frame is an Hir expression and return it.
+    fn unwrap_expr(self) -> Hir {
+        match self {
+            HirFrame::Expr(expr) => expr,
+            _ => panic!("tried to unwrap expr from HirFrame, got: {:?}", self)
+        }
+    }
+
+    /// Assert that the current stack frame is a Unicode class expression and
+    /// return it.
+    fn unwrap_class_unicode(self) -> hir::ClassUnicode {
+        match self {
+            HirFrame::ClassUnicode(cls) => cls,
+            _ => panic!("tried to unwrap Unicode class \
+                         from HirFrame, got: {:?}", self)
+        }
+    }
+
+    /// Assert that the current stack frame is a byte class expression and
+    /// return it.
+    fn unwrap_class_bytes(self) -> hir::ClassBytes {
+        match self {
+            HirFrame::ClassBytes(cls) => cls,
+            _ => panic!("tried to unwrap byte class \
+                         from HirFrame, got: {:?}", self)
+        }
+    }
+
+    /// Assert that the current stack frame is a group indicator and return
+    /// its corresponding flags (the flags that were active at the time the
+    /// group was entered) if they exist.
+    fn unwrap_group(self) -> Option<Flags> {
+        match self {
+            HirFrame::Group { old_flags } => old_flags,
+            _ => panic!("tried to unwrap group from HirFrame, got: {:?}", self)
+        }
+    }
+}
+
+impl<'t, 'p> Visitor for TranslatorI<'t, 'p> {
+    type Output = Hir;
+    type Err = Error;
+
+    fn finish(self) -> Result<Hir> {
+        if self.trans().stack.borrow().is_empty() {
+            // This can happen if the Ast given consists of a single set of
+            // flags. e.g., `(?i)`. /shrug
+            return Ok(Hir::empty());
+        }
+        // ... otherwise, we should have exactly one HIR on the stack.
+        assert_eq!(self.trans().stack.borrow().len(), 1);
+        Ok(self.pop().unwrap().unwrap_expr())
+    }
+
+    fn visit_pre(&mut self, ast: &Ast) -> Result<()> {
+        match *ast {
+            Ast::Class(ast::Class::Bracketed(_)) => {
+                if self.flags().unicode() {
+                    let cls = hir::ClassUnicode::empty();
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let cls = hir::ClassBytes::empty();
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            Ast::Group(ref x) => {
+                let old_flags = x.flags().map(|ast| self.set_flags(ast));
+                self.push(HirFrame::Group {
+                    old_flags: old_flags,
+                });
+            }
+            Ast::Concat(ref x) if x.asts.is_empty() => {}
+            Ast::Concat(_) => {
+                self.push(HirFrame::Concat);
+            }
+            Ast::Alternation(ref x) if x.asts.is_empty() => {}
+            Ast::Alternation(_) => {
+                self.push(HirFrame::Alternation);
+            }
+            _ => {}
+        }
+        Ok(())
+    }
+
+    fn visit_post(&mut self, ast: &Ast) -> Result<()> {
+        match *ast {
+            Ast::Empty(_) => {
+                self.push(HirFrame::Expr(Hir::empty()));
+            }
+            Ast::Flags(ref x) => {
+                self.set_flags(&x.flags);
+            }
+            Ast::Literal(ref x) => {
+                self.push(HirFrame::Expr(self.hir_literal(x)?));
+            }
+            Ast::Dot(span) => {
+                self.push(HirFrame::Expr(self.hir_dot(span)?));
+            }
+            Ast::Assertion(ref x) => {
+                self.push(HirFrame::Expr(self.hir_assertion(x)?));
+            }
+            Ast::Class(ast::Class::Perl(ref x)) => {
+                if self.flags().unicode() {
+                    let cls = self.hir_perl_unicode_class(x);
+                    let hcls = hir::Class::Unicode(cls);
+                    self.push(HirFrame::Expr(Hir::class(hcls)));
+                } else {
+                    let cls = self.hir_perl_byte_class(x);
+                    let hcls = hir::Class::Bytes(cls);
+                    self.push(HirFrame::Expr(Hir::class(hcls)));
+                }
+            }
+            Ast::Class(ast::Class::Unicode(ref x)) => {
+                let cls = hir::Class::Unicode(self.hir_unicode_class(x)?);
+                self.push(HirFrame::Expr(Hir::class(cls)));
+            }
+            Ast::Class(ast::Class::Bracketed(ref ast)) => {
+                if self.flags().unicode() {
+                    let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                    self.unicode_fold_and_negate(ast.negated, &mut cls);
+                    if cls.iter().next().is_none() {
+                        return Err(self.error(
+                            ast.span, ErrorKind::EmptyClassNotAllowed));
+                    }
+                    let expr = Hir::class(hir::Class::Unicode(cls));
+                    self.push(HirFrame::Expr(expr));
+                } else {
+                    let mut cls = self.pop().unwrap().unwrap_class_bytes();
+                    self.bytes_fold_and_negate(
+                        &ast.span, ast.negated, &mut cls)?;
+                    if cls.iter().next().is_none() {
+                        return Err(self.error(
+                            ast.span, ErrorKind::EmptyClassNotAllowed));
+                    }
+
+                    let expr = Hir::class(hir::Class::Bytes(cls));
+                    self.push(HirFrame::Expr(expr));
+                }
+            }
+            Ast::Repetition(ref x) => {
+                let expr = self.pop().unwrap().unwrap_expr();
+                self.push(HirFrame::Expr(self.hir_repetition(x, expr)));
+            }
+            Ast::Group(ref x) => {
+                let expr = self.pop().unwrap().unwrap_expr();
+                if let Some(flags) = self.pop().unwrap().unwrap_group() {
+                    self.trans().flags.set(flags);
+                }
+                self.push(HirFrame::Expr(self.hir_group(x, expr)));
+            }
+            Ast::Concat(_) => {
+                let mut exprs = vec![];
+                while let Some(HirFrame::Expr(expr)) = self.pop() {
+                    if !expr.kind().is_empty() {
+                        exprs.push(expr);
+                    }
+                }
+                exprs.reverse();
+                self.push(HirFrame::Expr(Hir::concat(exprs)));
+            }
+            Ast::Alternation(_) => {
+                let mut exprs = vec![];
+                while let Some(HirFrame::Expr(expr)) = self.pop() {
+                    exprs.push(expr);
+                }
+                exprs.reverse();
+                self.push(HirFrame::Expr(Hir::alternation(exprs)));
+            }
+        }
+        Ok(())
+    }
+
+    fn visit_class_set_item_pre(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        match *ast {
+            ast::ClassSetItem::Bracketed(_) => {
+                if self.flags().unicode() {
+                    let cls = hir::ClassUnicode::empty();
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let cls = hir::ClassBytes::empty();
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            // We needn't handle the Union case here since the visitor will
+            // do it for us.
+            _ => {}
+        }
+        Ok(())
+    }
+
+    fn visit_class_set_item_post(
+        &mut self,
+        ast: &ast::ClassSetItem,
+    ) -> Result<()> {
+        match *ast {
+            ast::ClassSetItem::Empty(_) => {}
+            ast::ClassSetItem::Literal(ref x) => {
+                if self.flags().unicode() {
+                    let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                    cls.push(hir::ClassUnicodeRange::new(x.c, x.c));
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let mut cls = self.pop().unwrap().unwrap_class_bytes();
+                    let byte = self.class_literal_byte(x)?;
+                    cls.push(hir::ClassBytesRange::new(byte, byte));
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            ast::ClassSetItem::Range(ref x) => {
+                if self.flags().unicode() {
+                    let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                    cls.push(hir::ClassUnicodeRange::new(x.start.c, x.end.c));
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let mut cls = self.pop().unwrap().unwrap_class_bytes();
+                    let start = self.class_literal_byte(&x.start)?;
+                    let end = self.class_literal_byte(&x.end)?;
+                    cls.push(hir::ClassBytesRange::new(start, end));
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            ast::ClassSetItem::Ascii(ref x) => {
+                if self.flags().unicode() {
+                    let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                    for &(s, e) in ascii_class(&x.kind) {
+                        cls.push(hir::ClassUnicodeRange::new(s, e));
+                    }
+                    self.unicode_fold_and_negate(x.negated, &mut cls);
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let mut cls = self.pop().unwrap().unwrap_class_bytes();
+                    for &(s, e) in ascii_class(&x.kind) {
+                        cls.push(hir::ClassBytesRange::new(s as u8, e as u8));
+                    }
+                    self.bytes_fold_and_negate(
+                        &x.span, x.negated, &mut cls)?;
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            ast::ClassSetItem::Unicode(ref x) => {
+                let xcls = self.hir_unicode_class(x)?;
+                let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                cls.union(&xcls);
+                self.push(HirFrame::ClassUnicode(cls));
+            }
+            ast::ClassSetItem::Perl(ref x) => {
+                if self.flags().unicode() {
+                    let xcls = self.hir_perl_unicode_class(x);
+                    let mut cls = self.pop().unwrap().unwrap_class_unicode();
+                    cls.union(&xcls);
+                    self.push(HirFrame::ClassUnicode(cls));
+                } else {
+                    let xcls = self.hir_perl_byte_class(x);
+                    let mut cls = self.pop().unwrap().unwrap_class_bytes();
+                    cls.union(&xcls);
+                    self.push(HirFrame::ClassBytes(cls));
+                }
+            }
+            ast::ClassSetItem::Bracketed(ref ast) => {
+                if self.flags().unicode() {
+                    let mut cls1 = self.pop().unwrap().unwrap_class_unicode();
+                    self.unicode_fold_and_negate(ast.negated, &mut cls1);
+
+                    let mut cls2 = self.pop().unwrap().unwrap_class_unicode();
+                    cls2.union(&cls1);
+                    self.push(HirFrame::ClassUnicode(cls2));
+                } else {
+                    let mut cls1 = self.pop().unwrap().unwrap_class_bytes();
+                    self.bytes_fold_and_negate(
+                        &ast.span, ast.negated, &mut cls1)?;
+
+                    let mut cls2 = self.pop().unwrap().unwrap_class_bytes();
+                    cls2.union(&cls1);
+                    self.push(HirFrame::ClassBytes(cls2));
+                }
+            }
+            // This is handled automatically by the visitor.
+            ast::ClassSetItem::Union(_) => {}
+        }
+        Ok(())
+    }
+
+    fn visit_class_set_binary_op_pre(
+        &mut self,
+        _op: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        if self.flags().unicode() {
+            let cls = hir::ClassUnicode::empty();
+            self.push(HirFrame::ClassUnicode(cls));
+        } else {
+            let cls = hir::ClassBytes::empty();
+            self.push(HirFrame::ClassBytes(cls));
+        }
+        Ok(())
+    }
+
+    fn visit_class_set_binary_op_in(
+        &mut self,
+        _op: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        if self.flags().unicode() {
+            let cls = hir::ClassUnicode::empty();
+            self.push(HirFrame::ClassUnicode(cls));
+        } else {
+            let cls = hir::ClassBytes::empty();
+            self.push(HirFrame::ClassBytes(cls));
+        }
+        Ok(())
+    }
+
+    fn visit_class_set_binary_op_post(
+        &mut self,
+        op: &ast::ClassSetBinaryOp,
+    ) -> Result<()> {
+        use ast::ClassSetBinaryOpKind::*;
+
+        if self.flags().unicode() {
+            let mut rhs = self.pop().unwrap().unwrap_class_unicode();
+            let mut lhs = self.pop().unwrap().unwrap_class_unicode();
+            let mut cls = self.pop().unwrap().unwrap_class_unicode();
+            if self.flags().case_insensitive() {
+                rhs.case_fold_simple();
+                lhs.case_fold_simple();
+            }
+            match op.kind {
+                Intersection => lhs.intersect(&rhs),
+                Difference => lhs.difference(&rhs),
+                SymmetricDifference => lhs.symmetric_difference(&rhs),
+            }
+            cls.union(&lhs);
+            self.push(HirFrame::ClassUnicode(cls));
+        } else {
+            let mut rhs = self.pop().unwrap().unwrap_class_bytes();
+            let mut lhs = self.pop().unwrap().unwrap_class_bytes();
+            let mut cls = self.pop().unwrap().unwrap_class_bytes();
+            if self.flags().case_insensitive() {
+                rhs.case_fold_simple();
+                lhs.case_fold_simple();
+            }
+            match op.kind {
+                Intersection => lhs.intersect(&rhs),
+                Difference => lhs.difference(&rhs),
+                SymmetricDifference => lhs.symmetric_difference(&rhs),
+            }
+            cls.union(&lhs);
+            self.push(HirFrame::ClassBytes(cls));
+        }
+        Ok(())
+    }
+}
+
+/// The internal implementation of a translator.
+///
+/// This type is responsible for carrying around the original pattern string,
+/// which is not tied to the internal state of a translator.
+///
+/// A TranslatorI exists for the time it takes to translate a single Ast.
+#[derive(Clone, Debug)]
+struct TranslatorI<'t, 'p> {
+    trans: &'t Translator,
+    pattern: &'p str,
+}
+
+impl<'t, 'p> TranslatorI<'t, 'p> {
+    /// Build a new internal translator.
+    fn new(trans: &'t Translator, pattern: &'p str) -> TranslatorI<'t, 'p> {
+        TranslatorI { trans: trans, pattern: pattern }
+    }
+
+    /// Return a reference to the underlying translator.
+    fn trans(&self) -> &Translator {
+        &self.trans
+    }
+
+    /// Push the given frame on to the call stack.
+    fn push(&self, frame: HirFrame) {
+        self.trans().stack.borrow_mut().push(frame);
+    }
+
+    /// Pop the top of the call stack. If the call stack is empty, return None.
+    fn pop(&self) -> Option<HirFrame> {
+        self.trans().stack.borrow_mut().pop()
+    }
+
+    /// Create a new error with the given span and error type.
+    fn error(&self, span: Span, kind: ErrorKind) -> Error {
+        Error { kind: kind, pattern: self.pattern.to_string(), span: span }
+    }
+
+    /// Return a copy of the active flags.
+    fn flags(&self) -> Flags {
+        self.trans().flags.get()
+    }
+
+    /// Set the flags of this translator from the flags set in the given AST.
+    /// Then, return the old flags.
+    fn set_flags(&self, ast_flags: &ast::Flags) -> Flags {
+        let old_flags = self.flags();
+        let mut new_flags = Flags::from_ast(ast_flags);
+        new_flags.merge(&old_flags);
+        self.trans().flags.set(new_flags);
+        old_flags
+    }
+
+    fn hir_literal(&self, lit: &ast::Literal) -> Result<Hir> {
+        let ch = match self.literal_to_char(lit)? {
+            byte @ hir::Literal::Byte(_) => return Ok(Hir::literal(byte)),
+            hir::Literal::Unicode(ch) => ch,
+        };
+        if self.flags().case_insensitive() {
+            self.hir_from_char_case_insensitive(lit.span, ch)
+        } else {
+            self.hir_from_char(lit.span, ch)
+        }
+    }
+
+    /// Convert an Ast literal to its scalar representation.
+    ///
+    /// When Unicode mode is enabled, then this always succeeds and returns a
+    /// `char` (Unicode scalar value).
+    ///
+    /// When Unicode mode is disabled, then a raw byte is returned. If that
+    /// byte is not ASCII and invalid UTF-8 is not allowed, then this returns
+    /// an error.
+    fn literal_to_char(&self, lit: &ast::Literal) -> Result<hir::Literal> {
+        if self.flags().unicode() {
+            return Ok(hir::Literal::Unicode(lit.c));
+        }
+        let byte = match lit.byte() {
+            None => return Ok(hir::Literal::Unicode(lit.c)),
+            Some(byte) => byte,
+        };
+        if byte <= 0x7F {
+            return Ok(hir::Literal::Unicode(byte as char));
+        }
+        if !self.trans().allow_invalid_utf8 {
+            return Err(self.error(lit.span, ErrorKind::InvalidUtf8));
+        }
+        Ok(hir::Literal::Byte(byte))
+    }
+
+    fn hir_from_char(&self, span: Span, c: char) -> Result<Hir> {
+        if !self.flags().unicode() && c.len_utf8() > 1 {
+            return Err(self.error(span, ErrorKind::UnicodeNotAllowed));
+        }
+        Ok(Hir::literal(hir::Literal::Unicode(c)))
+    }
+
+    fn hir_from_char_case_insensitive(
+        &self,
+        span: Span,
+        c: char,
+    ) -> Result<Hir> {
+        // If case folding won't do anything, then don't bother trying.
+        if !unicode::contains_simple_case_mapping(c, c) {
+            return self.hir_from_char(span, c);
+        }
+        if self.flags().unicode() {
+            let mut cls = hir::ClassUnicode::new(vec![
+                hir::ClassUnicodeRange::new(c, c),
+            ]);
+            cls.case_fold_simple();
+            Ok(Hir::class(hir::Class::Unicode(cls)))
+        } else {
+            if c.len_utf8() > 1 {
+                return Err(self.error(span, ErrorKind::UnicodeNotAllowed));
+            }
+            let mut cls = hir::ClassBytes::new(vec![
+                hir::ClassBytesRange::new(c as u8, c as u8),
+            ]);
+            cls.case_fold_simple();
+            Ok(Hir::class(hir::Class::Bytes(cls)))
+        }
+    }
+
+    fn hir_dot(&self, span: Span) -> Result<Hir> {
+        let unicode = self.flags().unicode();
+        if !unicode && !self.trans().allow_invalid_utf8 {
+            return Err(self.error(span, ErrorKind::InvalidUtf8));
+        }
+        Ok(if self.flags().dot_matches_new_line() {
+            Hir::any(!unicode)
+        } else {
+            Hir::dot(!unicode)
+        })
+    }
+
+    fn hir_assertion(&self, asst: &ast::Assertion) -> Result<Hir> {
+        let unicode = self.flags().unicode();
+        let multi_line = self.flags().multi_line();
+        Ok(match asst.kind {
+            ast::AssertionKind::StartLine => {
+                Hir::anchor(if multi_line {
+                    hir::Anchor::StartLine
+                } else {
+                    hir::Anchor::StartText
+                })
+            }
+            ast::AssertionKind::EndLine => {
+                Hir::anchor(if multi_line {
+                    hir::Anchor::EndLine
+                } else {
+                    hir::Anchor::EndText
+                })
+            }
+            ast::AssertionKind::StartText => {
+                Hir::anchor(hir::Anchor::StartText)
+            }
+            ast::AssertionKind::EndText => {
+                Hir::anchor(hir::Anchor::EndText)
+            }
+            ast::AssertionKind::WordBoundary => {
+                Hir::word_boundary(if unicode {
+                    hir::WordBoundary::Unicode
+                } else {
+                    hir::WordBoundary::Ascii
+                })
+            }
+            ast::AssertionKind::NotWordBoundary => {
+                Hir::word_boundary(if unicode {
+                    hir::WordBoundary::UnicodeNegate
+                } else {
+                    // It is possible for negated ASCII word boundaries to
+                    // match at invalid UTF-8 boundaries, even when searching
+                    // valid UTF-8.
+                    if !self.trans().allow_invalid_utf8 {
+                        return Err(self.error(
+                            asst.span, ErrorKind::InvalidUtf8));
+                    }
+                    hir::WordBoundary::AsciiNegate
+                })
+            }
+        })
+    }
+
+    fn hir_group(&self, group: &ast::Group, expr: Hir) -> Hir {
+        let kind = match group.kind {
+            ast::GroupKind::CaptureIndex(idx) => {
+                hir::GroupKind::CaptureIndex(idx)
+            }
+            ast::GroupKind::CaptureName(ref capname) => {
+                hir::GroupKind::CaptureName {
+                    name: capname.name.clone(),
+                    index: capname.index,
+                }
+            }
+            ast::GroupKind::NonCapturing(_) => hir::GroupKind::NonCapturing,
+        };
+        Hir::group(hir::Group {
+            kind: kind,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_repetition(&self, rep: &ast::Repetition, expr: Hir) -> Hir {
+        let kind = match rep.op.kind {
+            ast::RepetitionKind::ZeroOrOne => hir::RepetitionKind::ZeroOrOne,
+            ast::RepetitionKind::ZeroOrMore => hir::RepetitionKind::ZeroOrMore,
+            ast::RepetitionKind::OneOrMore => hir::RepetitionKind::OneOrMore,
+            ast::RepetitionKind::Range(ast::RepetitionRange::Exactly(m)) => {
+                hir::RepetitionKind::Range(hir::RepetitionRange::Exactly(m))
+            }
+            ast::RepetitionKind::Range(ast::RepetitionRange::AtLeast(m)) => {
+                hir::RepetitionKind::Range(hir::RepetitionRange::AtLeast(m))
+            }
+            ast::RepetitionKind::Range(ast::RepetitionRange::Bounded(m,n)) => {
+                hir::RepetitionKind::Range(hir::RepetitionRange::Bounded(m, n))
+            }
+        };
+        let greedy =
+            if self.flags().swap_greed() {
+                !rep.greedy
+            } else {
+                rep.greedy
+            };
+        Hir::repetition(hir::Repetition {
+            kind: kind,
+            greedy: greedy,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_unicode_class(
+        &self,
+        ast_class: &ast::ClassUnicode,
+    ) -> Result<hir::ClassUnicode> {
+        use ast::ClassUnicodeKind::*;
+
+        if !self.flags().unicode() {
+            return Err(self.error(
+                ast_class.span,
+                ErrorKind::UnicodeNotAllowed,
+            ));
+        }
+        let query = match ast_class.kind {
+            OneLetter(name) => ClassQuery::OneLetter(name),
+            Named(ref name) => ClassQuery::Binary(name),
+            NamedValue { ref name, ref value, .. } => {
+                ClassQuery::ByValue {
+                    property_name: name,
+                    property_value: value,
+                }
+            }
+        };
+        match unicode::class(query) {
+            Ok(mut class) => {
+                self.unicode_fold_and_negate(ast_class.negated, &mut class);
+                Ok(class)
+            }
+            Err(unicode::Error::PropertyNotFound) => {
+                Err(self.error(
+                    ast_class.span,
+                    ErrorKind::UnicodePropertyNotFound,
+                ))
+            }
+            Err(unicode::Error::PropertyValueNotFound) => {
+                Err(self.error(
+                    ast_class.span,
+                    ErrorKind::UnicodePropertyValueNotFound,
+                ))
+            }
+        }
+    }
+
+    fn hir_perl_unicode_class(
+        &self,
+        ast_class: &ast::ClassPerl,
+    ) -> hir::ClassUnicode {
+        use ast::ClassPerlKind::*;
+        use unicode_tables::perl_word::PERL_WORD;
+
+        assert!(self.flags().unicode());
+        let mut class = match ast_class.kind {
+            Digit => {
+                let query = ClassQuery::Binary("Decimal_Number");
+                unicode::class(query).unwrap()
+            }
+            Space => {
+                let query = ClassQuery::Binary("Whitespace");
+                unicode::class(query).unwrap()
+            }
+            Word => unicode::hir_class(PERL_WORD),
+        };
+        // We needn't apply case folding here because the Perl Unicode classes
+        // are already closed under Unicode simple case folding.
+        if ast_class.negated {
+            class.negate();
+        }
+        class
+    }
+
+    fn hir_perl_byte_class(
+        &self,
+        ast_class: &ast::ClassPerl,
+    ) -> hir::ClassBytes {
+        use ast::ClassPerlKind::*;
+
+        assert!(!self.flags().unicode());
+        let mut class = match ast_class.kind {
+            Digit => hir_ascii_class_bytes(&ast::ClassAsciiKind::Digit),
+            Space => hir_ascii_class_bytes(&ast::ClassAsciiKind::Space),
+            Word => hir_ascii_class_bytes(&ast::ClassAsciiKind::Word),
+        };
+        // We needn't apply case folding here because the Perl ASCII classes
+        // are already closed (under ASCII case folding).
+        if ast_class.negated {
+            class.negate();
+        }
+        class
+    }
+
+    fn unicode_fold_and_negate(
+        &self,
+        negated: bool,
+        class: &mut hir::ClassUnicode,
+    ) {
+        // Note that we must apply case folding before negation!
+        // Consider `(?i)[^x]`. If we applied negation field, then
+        // the result would be the character class that matched any
+        // Unicode scalar value.
+        if self.flags().case_insensitive() {
+            class.case_fold_simple();
+        }
+        if negated {
+            class.negate();
+        }
+    }
+
+    fn bytes_fold_and_negate(
+        &self,
+        span: &Span,
+        negated: bool,
+        class: &mut hir::ClassBytes,
+    ) -> Result<()> {
+        // Note that we must apply case folding before negation!
+        // Consider `(?i)[^x]`. If we applied negation field, then
+        // the result would be the character class that matched any
+        // Unicode scalar value.
+        if self.flags().case_insensitive() {
+            class.case_fold_simple();
+        }
+        if negated {
+            class.negate();
+        }
+        if !self.trans().allow_invalid_utf8 && !class.is_all_ascii() {
+            return Err(self.error(span.clone(), ErrorKind::InvalidUtf8));
+        }
+        Ok(())
+    }
+
+    /// Return a scalar byte value suitable for use as a literal in a byte
+    /// character class.
+    fn class_literal_byte(&self, ast: &ast::Literal) -> Result<u8> {
+        match self.literal_to_char(ast)? {
+            hir::Literal::Byte(byte) => Ok(byte),
+            hir::Literal::Unicode(ch) => {
+                if ch <= 0x7F as char {
+                    Ok(ch as u8)
+                } else {
+                    // We can't feasibly support Unicode in
+                    // byte oriented classes. Byte classes don't
+                    // do Unicode case folding.
+                    Err(self.error(ast.span, ErrorKind::UnicodeNotAllowed))
+                }
+            }
+        }
+    }
+}
+
+/// A translator's representation of a regular expression's flags at any given
+/// moment in time.
+///
+/// Each flag can be in one of three states: absent, present but disabled or
+/// present but enabled.
+#[derive(Clone, Copy, Debug, Default)]
+struct Flags {
+    case_insensitive: Option<bool>,
+    multi_line: Option<bool>,
+    dot_matches_new_line: Option<bool>,
+    swap_greed: Option<bool>,
+    unicode: Option<bool>,
+    // Note that `ignore_whitespace` is omitted here because it is handled
+    // entirely in the parser.
+}
+
+impl Flags {
+    fn from_ast(ast: &ast::Flags) -> Flags {
+        let mut flags = Flags::default();
+        let mut enable = true;
+        for item in &ast.items {
+            match item.kind {
+                ast::FlagsItemKind::Negation => {
+                    enable = false;
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::CaseInsensitive) => {
+                    flags.case_insensitive = Some(enable);
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::MultiLine) => {
+                    flags.multi_line = Some(enable);
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::DotMatchesNewLine) => {
+                    flags.dot_matches_new_line = Some(enable);
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::SwapGreed) => {
+                    flags.swap_greed = Some(enable);
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::Unicode) => {
+                    flags.unicode = Some(enable);
+                }
+                ast::FlagsItemKind::Flag(ast::Flag::IgnoreWhitespace) => {}
+            }
+        }
+        flags
+    }
+
+    fn merge(&mut self, previous: &Flags) {
+        if self.case_insensitive.is_none() {
+            self.case_insensitive = previous.case_insensitive;
+        }
+        if self.multi_line.is_none() {
+            self.multi_line = previous.multi_line;
+        }
+        if self.dot_matches_new_line.is_none() {
+            self.dot_matches_new_line = previous.dot_matches_new_line;
+        }
+        if self.swap_greed.is_none() {
+            self.swap_greed = previous.swap_greed;
+        }
+        if self.unicode.is_none() {
+            self.unicode = previous.unicode;
+        }
+    }
+
+    fn case_insensitive(&self) -> bool {
+        self.case_insensitive.unwrap_or(false)
+    }
+
+    fn multi_line(&self) -> bool {
+        self.multi_line.unwrap_or(false)
+    }
+
+    fn dot_matches_new_line(&self) -> bool {
+        self.dot_matches_new_line.unwrap_or(false)
+    }
+
+    fn swap_greed(&self) -> bool {
+        self.swap_greed.unwrap_or(false)
+    }
+
+    fn unicode(&self) -> bool {
+        self.unicode.unwrap_or(true)
+    }
+}
+
+fn hir_ascii_class_bytes(kind: &ast::ClassAsciiKind) -> hir::ClassBytes {
+    let ranges: Vec<_> = ascii_class(kind).iter().cloned().map(|(s, e)| {
+        hir::ClassBytesRange::new(s as u8, e as u8)
+    }).collect();
+    hir::ClassBytes::new(ranges)
+}
+
+fn ascii_class(kind: &ast::ClassAsciiKind) -> &'static [(char, char)] {
+    use ast::ClassAsciiKind::*;
+
+    // The contortions below with `const` appear necessary for older versions
+    // of Rust.
+    type T = &'static [(char, char)];
+    match *kind {
+        Alnum => {
+            const X: T = &[('0', '9'), ('A', 'Z'), ('a', 'z')];
+            X
+        }
+        Alpha => {
+            const X: T = &[('A', 'Z'), ('a', 'z')];
+            X
+        }
+        Ascii => {
+            const X: T = &[('\x00', '\x7F')];
+            X
+        }
+        Blank => {
+            const X: T = &[(' ', '\t')];
+            X
+        }
+        Cntrl => {
+            const X: T = &[('\x00', '\x1F'), ('\x7F', '\x7F')];
+            X
+        }
+        Digit => {
+            const X: T = &[('0', '9')];
+            X
+        }
+        Graph => {
+            const X: T = &[('!', '~')];
+            X
+        }
+        Lower => {
+            const X: T = &[('a', 'z')];
+            X
+        }
+        Print => {
+            const X: T = &[(' ', '~')];
+            X
+        }
+        Punct => {
+            const X: T = &[('!', '/'), (':', '@'), ('[', '`'), ('{', '~')];
+            X
+        }
+        Space => {
+            const X: T = &[
+                ('\t', '\t'), ('\n', '\n'), ('\x0B', '\x0B'), ('\x0C', '\x0C'),
+                ('\r', '\r'), (' ', ' '),
+            ];
+            X
+        }
+        Upper => {
+            const X: T = &[('A', 'Z')];
+            X
+        }
+        Word => {
+            const X: T = &[('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z')];
+            X
+        }
+        Xdigit => {
+            const X: T = &[('0', '9'), ('A', 'F'), ('a', 'f')];
+            X
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ast::{self, Ast, Position, Span};
+    use ast::parse::ParserBuilder;
+    use hir::{self, Hir, HirKind};
+    use unicode::{self, ClassQuery};
+
+    use super::{TranslatorBuilder, ascii_class};
+
+    // We create these errors to compare with real hir::Errors in the tests.
+    // We define equality between TestError and hir::Error to disregard the
+    // pattern string in hir::Error, which is annoying to provide in tests.
+    #[derive(Clone, Debug)]
+    struct TestError {
+        span: Span,
+        kind: hir::ErrorKind,
+    }
+
+    impl PartialEq<hir::Error> for TestError {
+        fn eq(&self, other: &hir::Error) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    impl PartialEq<TestError> for hir::Error {
+        fn eq(&self, other: &TestError) -> bool {
+            self.span == other.span && self.kind == other.kind
+        }
+    }
+
+    fn parse(pattern: &str) -> Ast {
+        ParserBuilder::new().octal(true).build().parse(pattern).unwrap()
+    }
+
+    fn t(pattern: &str) -> Hir {
+        TranslatorBuilder::new()
+            .allow_invalid_utf8(false)
+            .build()
+            .translate(pattern, &parse(pattern))
+            .unwrap()
+    }
+
+    fn t_err(pattern: &str) -> hir::Error {
+        TranslatorBuilder::new()
+            .allow_invalid_utf8(false)
+            .build()
+            .translate(pattern, &parse(pattern))
+            .unwrap_err()
+    }
+
+    fn t_bytes(pattern: &str) -> Hir {
+        TranslatorBuilder::new()
+            .allow_invalid_utf8(true)
+            .build()
+            .translate(pattern, &parse(pattern))
+            .unwrap()
+    }
+
+    fn hir_lit(s: &str) -> Hir {
+        match s.len() {
+            0 => Hir::empty(),
+            _ => {
+                let lits = s
+                    .chars()
+                    .map(hir::Literal::Unicode)
+                    .map(Hir::literal)
+                    .collect();
+                Hir::concat(lits)
+            }
+        }
+    }
+
+    fn hir_blit(s: &[u8]) -> Hir {
+        match s.len() {
+            0 => Hir::empty(),
+            1 => Hir::literal(hir::Literal::Byte(s[0])),
+            _ => {
+                let lits = s
+                    .iter()
+                    .cloned()
+                    .map(hir::Literal::Byte)
+                    .map(Hir::literal)
+                    .collect();
+                Hir::concat(lits)
+            }
+        }
+    }
+
+    fn hir_group(i: u32, expr: Hir)  -> Hir {
+        Hir::group(hir::Group {
+            kind: hir::GroupKind::CaptureIndex(i),
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_group_name(i: u32, name: &str, expr: Hir)  -> Hir {
+        Hir::group(hir::Group {
+            kind: hir::GroupKind::CaptureName {
+                name: name.to_string(),
+                index: i,
+            },
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_group_nocap(expr: Hir)  -> Hir {
+        Hir::group(hir::Group {
+            kind: hir::GroupKind::NonCapturing,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_quest(greedy: bool, expr: Hir) -> Hir {
+        Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::ZeroOrOne,
+            greedy: greedy,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_star(greedy: bool, expr: Hir) -> Hir {
+        Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::ZeroOrMore,
+            greedy: greedy,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_plus(greedy: bool, expr: Hir) -> Hir {
+        Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::OneOrMore,
+            greedy: greedy,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_range(greedy: bool, range: hir::RepetitionRange, expr: Hir) -> Hir {
+        Hir::repetition(hir::Repetition {
+            kind: hir::RepetitionKind::Range(range),
+            greedy: greedy,
+            hir: Box::new(expr),
+        })
+    }
+
+    fn hir_alt(alts: Vec<Hir>) -> Hir {
+        Hir::alternation(alts)
+    }
+
+    fn hir_cat(exprs: Vec<Hir>) -> Hir {
+        Hir::concat(exprs)
+    }
+
+    fn hir_uclass_query(query: ClassQuery) -> Hir {
+        Hir::class(hir::Class::Unicode(unicode::class(query).unwrap()))
+    }
+
+    fn hir_uclass_perl_word() -> Hir {
+        use unicode_tables::perl_word::PERL_WORD;
+        Hir::class(hir::Class::Unicode(unicode::hir_class(PERL_WORD)))
+    }
+
+    fn hir_uclass(ranges: &[(char, char)]) -> Hir {
+        let ranges: Vec<hir::ClassUnicodeRange> = ranges
+            .iter()
+            .map(|&(s, e)| hir::ClassUnicodeRange::new(s, e))
+            .collect();
+        Hir::class(hir::Class::Unicode(hir::ClassUnicode::new(ranges)))
+    }
+
+    fn hir_bclass(ranges: &[(u8, u8)]) -> Hir {
+        let ranges: Vec<hir::ClassBytesRange> = ranges
+            .iter()
+            .map(|&(s, e)| hir::ClassBytesRange::new(s, e))
+            .collect();
+        Hir::class(hir::Class::Bytes(hir::ClassBytes::new(ranges)))
+    }
+
+    fn hir_bclass_from_char(ranges: &[(char, char)]) -> Hir {
+        let ranges: Vec<hir::ClassBytesRange> = ranges
+            .iter()
+            .map(|&(s, e)| {
+                assert!(s as u32 <= 0x7F);
+                assert!(e as u32 <= 0x7F);
+                hir::ClassBytesRange::new(s as u8, e as u8)
+            })
+            .collect();
+        Hir::class(hir::Class::Bytes(hir::ClassBytes::new(ranges)))
+    }
+
+    fn hir_case_fold(expr: Hir) -> Hir {
+        match expr.into_kind() {
+            HirKind::Class(mut cls) => {
+                cls.case_fold_simple();
+                Hir::class(cls)
+            }
+            _ => panic!("cannot case fold non-class Hir expr"),
+        }
+    }
+
+    fn hir_negate(expr: Hir) -> Hir {
+        match expr.into_kind() {
+            HirKind::Class(mut cls) => {
+                cls.negate();
+                Hir::class(cls)
+            }
+            _ => panic!("cannot negate non-class Hir expr"),
+        }
+    }
+
+    fn hir_union(expr1: Hir, expr2: Hir) -> Hir {
+        use hir::Class::{Bytes, Unicode};
+
+        match (expr1.into_kind(), expr2.into_kind()) {
+            (
+                HirKind::Class(Unicode(mut c1)),
+                HirKind::Class(Unicode(c2)),
+            ) => {
+                c1.union(&c2);
+                Hir::class(hir::Class::Unicode(c1))
+            }
+            (
+                HirKind::Class(Bytes(mut c1)),
+                HirKind::Class(Bytes(c2)),
+            ) => {
+                c1.union(&c2);
+                Hir::class(hir::Class::Bytes(c1))
+            }
+            _ => panic!("cannot union non-class Hir exprs"),
+        }
+    }
+
+    fn hir_difference(expr1: Hir, expr2: Hir) -> Hir {
+        use hir::Class::{Bytes, Unicode};
+
+        match (expr1.into_kind(), expr2.into_kind()) {
+            (
+                HirKind::Class(Unicode(mut c1)),
+                HirKind::Class(Unicode(c2)),
+            ) => {
+                c1.difference(&c2);
+                Hir::class(hir::Class::Unicode(c1))
+            }
+            (
+                HirKind::Class(Bytes(mut c1)),
+                HirKind::Class(Bytes(c2)),
+            ) => {
+                c1.difference(&c2);
+                Hir::class(hir::Class::Bytes(c1))
+            }
+            _ => panic!("cannot difference non-class Hir exprs"),
+        }
+    }
+
+    fn hir_anchor(anchor: hir::Anchor) -> Hir {
+        Hir::anchor(anchor)
+    }
+
+    fn hir_word(wb: hir::WordBoundary) -> Hir {
+        Hir::word_boundary(wb)
+    }
+
+    #[test]
+    fn empty() {
+        assert_eq!(t(""), Hir::empty());
+        assert_eq!(t("(?i)"), Hir::empty());
+        assert_eq!(t("()"), hir_group(1, Hir::empty()));
+        assert_eq!(t("(?:)"), hir_group_nocap(Hir::empty()));
+        assert_eq!(t("(?P<wat>)"), hir_group_name(1, "wat", Hir::empty()));
+        assert_eq!(t("|"), hir_alt(vec![Hir::empty(), Hir::empty()]));
+        assert_eq!(t("()|()"), hir_alt(vec![
+            hir_group(1, Hir::empty()),
+            hir_group(2, Hir::empty()),
+        ]));
+        assert_eq!(t("(|b)"), hir_group(1, hir_alt(vec![
+            Hir::empty(),
+            hir_lit("b"),
+        ])));
+        assert_eq!(t("(a|)"), hir_group(1, hir_alt(vec![
+            hir_lit("a"),
+            Hir::empty(),
+        ])));
+        assert_eq!(t("(a||c)"), hir_group(1, hir_alt(vec![
+            hir_lit("a"),
+            Hir::empty(),
+            hir_lit("c"),
+        ])));
+        assert_eq!(t("(||)"), hir_group(1, hir_alt(vec![
+            Hir::empty(),
+            Hir::empty(),
+            Hir::empty(),
+        ])));
+    }
+
+    #[test]
+    fn literal() {
+        assert_eq!(t("a"), hir_lit("a"));
+        assert_eq!(t("(?-u)a"), hir_lit("a"));
+        assert_eq!(t("☃"), hir_lit("☃"));
+        assert_eq!(t("abcd"), hir_lit("abcd"));
+
+        assert_eq!(t_bytes("(?-u)a"), hir_lit("a"));
+        assert_eq!(t_bytes("(?-u)\x61"), hir_lit("a"));
+        assert_eq!(t_bytes(r"(?-u)\x61"), hir_lit("a"));
+        assert_eq!(t_bytes(r"(?-u)\xFF"), hir_blit(b"\xFF"));
+
+        assert_eq!(t_err("(?-u)☃"), TestError {
+            kind: hir::ErrorKind::UnicodeNotAllowed,
+            span: Span::new(Position::new(5, 1, 6), Position::new(8, 1, 7)),
+        });
+        assert_eq!(t_err(r"(?-u)\xFF"), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(5, 1, 6), Position::new(9, 1, 10)),
+        });
+    }
+
+    #[test]
+    fn literal_case_insensitive() {
+        assert_eq!(t("(?i)a"), hir_uclass(&[
+            ('A', 'A'), ('a', 'a'),
+        ]));
+        assert_eq!(t("(?i:a)"), hir_group_nocap(hir_uclass(&[
+            ('A', 'A'), ('a', 'a')],
+        )));
+        assert_eq!(t("a(?i)a(?-i)a"), hir_cat(vec![
+            hir_lit("a"),
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            hir_lit("a"),
+        ]));
+        assert_eq!(t("(?i)ab@c"), hir_cat(vec![
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            hir_uclass(&[('B', 'B'), ('b', 'b')]),
+            hir_lit("@"),
+            hir_uclass(&[('C', 'C'), ('c', 'c')]),
+        ]));
+        assert_eq!(t("(?i)β"), hir_uclass(&[
+            ('Β', 'Β'), ('β', 'β'), ('ϐ', 'ϐ'),
+        ]));
+
+        assert_eq!(t("(?i-u)a"), hir_bclass(&[
+            (b'A', b'A'), (b'a', b'a'),
+        ]));
+        assert_eq!(t("(?-u)a(?i)a(?-i)a"), hir_cat(vec![
+            hir_lit("a"),
+            hir_bclass(&[(b'A', b'A'), (b'a', b'a')]),
+            hir_lit("a"),
+        ]));
+        assert_eq!(t("(?i-u)ab@c"), hir_cat(vec![
+            hir_bclass(&[(b'A', b'A'), (b'a', b'a')]),
+            hir_bclass(&[(b'B', b'B'), (b'b', b'b')]),
+            hir_lit("@"),
+            hir_bclass(&[(b'C', b'C'), (b'c', b'c')]),
+        ]));
+
+        assert_eq!(t_bytes("(?i-u)a"), hir_bclass(&[
+            (b'A', b'A'), (b'a', b'a'),
+        ]));
+        assert_eq!(t_bytes("(?i-u)\x61"), hir_bclass(&[
+            (b'A', b'A'), (b'a', b'a'),
+        ]));
+        assert_eq!(t_bytes(r"(?i-u)\x61"), hir_bclass(&[
+            (b'A', b'A'), (b'a', b'a'),
+        ]));
+        assert_eq!(t_bytes(r"(?i-u)\xFF"), hir_blit(b"\xFF"));
+
+        assert_eq!(t_err("(?i-u)β"), TestError {
+            kind: hir::ErrorKind::UnicodeNotAllowed,
+            span: Span::new(
+                Position::new(6, 1, 7),
+                Position::new(8, 1, 8),
+            ),
+        });
+    }
+
+    #[test]
+    fn dot() {
+        assert_eq!(t("."), hir_uclass(&[
+            ('\0', '\t'),
+            ('\x0B', '\u{10FFFF}'),
+        ]));
+        assert_eq!(t("(?s)."), hir_uclass(&[
+            ('\0', '\u{10FFFF}'),
+        ]));
+        assert_eq!(t_bytes("(?-u)."), hir_bclass(&[
+            (b'\0', b'\t'),
+            (b'\x0B', b'\xFF'),
+        ]));
+        assert_eq!(t_bytes("(?s-u)."), hir_bclass(&[
+            (b'\0', b'\xFF'),
+        ]));
+
+        // If invalid UTF-8 isn't allowed, then non-Unicode `.` isn't allowed.
+        assert_eq!(t_err("(?-u)."), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(5, 1, 6), Position::new(6, 1, 7)),
+        });
+        assert_eq!(t_err("(?s-u)."), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(6, 1, 7), Position::new(7, 1, 8)),
+        });
+    }
+
+    #[test]
+    fn assertions() {
+        assert_eq!(t("^"), hir_anchor(hir::Anchor::StartText));
+        assert_eq!(t("$"), hir_anchor(hir::Anchor::EndText));
+        assert_eq!(t(r"\A"), hir_anchor(hir::Anchor::StartText));
+        assert_eq!(t(r"\z"), hir_anchor(hir::Anchor::EndText));
+        assert_eq!(t("(?m)^"), hir_anchor(hir::Anchor::StartLine));
+        assert_eq!(t("(?m)$"), hir_anchor(hir::Anchor::EndLine));
+        assert_eq!(t(r"(?m)\A"), hir_anchor(hir::Anchor::StartText));
+        assert_eq!(t(r"(?m)\z"), hir_anchor(hir::Anchor::EndText));
+
+        assert_eq!(t(r"\b"), hir_word(hir::WordBoundary::Unicode));
+        assert_eq!(t(r"\B"), hir_word(hir::WordBoundary::UnicodeNegate));
+        assert_eq!(t(r"(?-u)\b"), hir_word(hir::WordBoundary::Ascii));
+        assert_eq!(
+            t_bytes(r"(?-u)\B"),
+            hir_word(hir::WordBoundary::AsciiNegate));
+
+        assert_eq!(t_err(r"(?-u)\B"), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(5, 1, 6), Position::new(7, 1, 8)),
+        });
+    }
+
+    #[test]
+    fn group() {
+        assert_eq!(t("(a)"), hir_group(1, hir_lit("a")));
+        assert_eq!(t("(a)(b)"), hir_cat(vec![
+            hir_group(1, hir_lit("a")),
+            hir_group(2, hir_lit("b")),
+        ]));
+        assert_eq!(t("(a)|(b)"), hir_alt(vec![
+            hir_group(1, hir_lit("a")),
+            hir_group(2, hir_lit("b")),
+        ]));
+        assert_eq!(t("(?P<foo>)"), hir_group_name(1, "foo", Hir::empty()));
+        assert_eq!(t("(?P<foo>a)"), hir_group_name(1, "foo", hir_lit("a")));
+        assert_eq!(t("(?P<foo>a)(?P<bar>b)"), hir_cat(vec![
+            hir_group_name(1, "foo", hir_lit("a")),
+            hir_group_name(2, "bar", hir_lit("b")),
+        ]));
+        assert_eq!(t("(?:)"), hir_group_nocap(Hir::empty()));
+        assert_eq!(t("(?:a)"), hir_group_nocap(hir_lit("a")));
+        assert_eq!(t("(?:a)(b)"), hir_cat(vec![
+            hir_group_nocap(hir_lit("a")),
+            hir_group(1, hir_lit("b")),
+        ]));
+        assert_eq!(t("(a)(?:b)(c)"), hir_cat(vec![
+            hir_group(1, hir_lit("a")),
+            hir_group_nocap(hir_lit("b")),
+            hir_group(2, hir_lit("c")),
+        ]));
+        assert_eq!(t("(a)(?P<foo>b)(c)"), hir_cat(vec![
+            hir_group(1, hir_lit("a")),
+            hir_group_name(2, "foo", hir_lit("b")),
+            hir_group(3, hir_lit("c")),
+        ]));
+    }
+
+    #[test]
+    fn flags() {
+        assert_eq!(t("(?i:a)a"), hir_cat(vec![
+            hir_group_nocap(hir_uclass(&[('A', 'A'), ('a', 'a')])),
+            hir_lit("a"),
+        ]));
+        assert_eq!(t("(?i-u:a)β"), hir_cat(vec![
+            hir_group_nocap(hir_bclass(&[(b'A', b'A'), (b'a', b'a')])),
+            hir_lit("β"),
+        ]));
+        assert_eq!(t("(?i)(?-i:a)a"), hir_cat(vec![
+            hir_group_nocap(hir_lit("a")),
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+        ]));
+        assert_eq!(t("(?im)a^"), hir_cat(vec![
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            hir_anchor(hir::Anchor::StartLine),
+        ]));
+        assert_eq!(t("(?im)a^(?i-m)a^"), hir_cat(vec![
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            hir_anchor(hir::Anchor::StartLine),
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            hir_anchor(hir::Anchor::StartText),
+        ]));
+        assert_eq!(t("(?U)a*a*?(?-U)a*a*?"), hir_cat(vec![
+            hir_star(false, hir_lit("a")),
+            hir_star(true, hir_lit("a")),
+            hir_star(true, hir_lit("a")),
+            hir_star(false, hir_lit("a")),
+        ]));
+        assert_eq!(t("(?:a(?i)a)a"), hir_cat(vec![
+            hir_group_nocap(hir_cat(vec![
+                hir_lit("a"),
+                hir_uclass(&[('A', 'A'), ('a', 'a')]),
+            ])),
+            hir_lit("a"),
+        ]));
+        assert_eq!(t("(?i)(?:a(?-i)a)a"), hir_cat(vec![
+            hir_group_nocap(hir_cat(vec![
+                hir_uclass(&[('A', 'A'), ('a', 'a')]),
+                hir_lit("a"),
+            ])),
+            hir_uclass(&[('A', 'A'), ('a', 'a')]),
+        ]));
+    }
+
+    #[test]
+    fn escape() {
+        assert_eq!(
+            t(r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#"),
+            hir_lit(r"\.+*?()|[]{}^$#"));
+    }
+
+    #[test]
+    fn repetition() {
+        assert_eq!(t("a?"), hir_quest(true, hir_lit("a")));
+        assert_eq!(t("a*"), hir_star(true, hir_lit("a")));
+        assert_eq!(t("a+"), hir_plus(true, hir_lit("a")));
+        assert_eq!(t("a??"), hir_quest(false, hir_lit("a")));
+        assert_eq!(t("a*?"), hir_star(false, hir_lit("a")));
+        assert_eq!(t("a+?"), hir_plus(false, hir_lit("a")));
+
+        assert_eq!(
+            t("a{1}"),
+            hir_range(
+                true,
+                hir::RepetitionRange::Exactly(1),
+                hir_lit("a"),
+            ));
+        assert_eq!(
+            t("a{1,}"),
+            hir_range(
+                true,
+                hir::RepetitionRange::AtLeast(1),
+                hir_lit("a"),
+            ));
+        assert_eq!(
+            t("a{1,2}"),
+            hir_range(
+                true,
+                hir::RepetitionRange::Bounded(1, 2),
+                hir_lit("a"),
+            ));
+        assert_eq!(
+            t("a{1}?"),
+            hir_range(
+                false,
+                hir::RepetitionRange::Exactly(1),
+                hir_lit("a"),
+            ));
+        assert_eq!(
+            t("a{1,}?"),
+            hir_range(
+                false,
+                hir::RepetitionRange::AtLeast(1),
+                hir_lit("a"),
+            ));
+        assert_eq!(
+            t("a{1,2}?"),
+            hir_range(
+                false,
+                hir::RepetitionRange::Bounded(1, 2),
+                hir_lit("a"),
+            ));
+
+        assert_eq!(t("ab?"), hir_cat(vec![
+            hir_lit("a"),
+            hir_quest(true, hir_lit("b")),
+        ]));
+        assert_eq!(t("(ab)?"), hir_quest(true, hir_group(1, hir_cat(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+        ]))));
+        assert_eq!(t("a|b?"), hir_alt(vec![
+            hir_lit("a"),
+            hir_quest(true, hir_lit("b")),
+        ]));
+    }
+
+    #[test]
+    fn cat_alt() {
+        assert_eq!(t("(ab)"), hir_group(1, hir_cat(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+        ])));
+        assert_eq!(t("a|b"), hir_alt(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+        ]));
+        assert_eq!(t("a|b|c"), hir_alt(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+            hir_lit("c"),
+        ]));
+        assert_eq!(t("ab|bc|cd"), hir_alt(vec![
+            hir_lit("ab"),
+            hir_lit("bc"),
+            hir_lit("cd"),
+        ]));
+        assert_eq!(t("(a|b)"), hir_group(1, hir_alt(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+        ])));
+        assert_eq!(t("(a|b|c)"), hir_group(1, hir_alt(vec![
+            hir_lit("a"),
+            hir_lit("b"),
+            hir_lit("c"),
+        ])));
+        assert_eq!(t("(ab|bc|cd)"), hir_group(1, hir_alt(vec![
+            hir_lit("ab"),
+            hir_lit("bc"),
+            hir_lit("cd"),
+        ])));
+        assert_eq!(t("(ab|(bc|(cd)))"), hir_group(1, hir_alt(vec![
+            hir_lit("ab"),
+            hir_group(2, hir_alt(vec![
+                hir_lit("bc"),
+                hir_group(3, hir_lit("cd")),
+            ])),
+        ])));
+    }
+
+    #[test]
+    fn class_ascii() {
+        assert_eq!(
+            t("[[:alnum:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Alnum)));
+        assert_eq!(
+            t("[[:alpha:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Alpha)));
+        assert_eq!(
+            t("[[:ascii:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Ascii)));
+        assert_eq!(
+            t("[[:blank:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Blank)));
+        assert_eq!(
+            t("[[:cntrl:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Cntrl)));
+        assert_eq!(
+            t("[[:digit:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Digit)));
+        assert_eq!(
+            t("[[:graph:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Graph)));
+        assert_eq!(
+            t("[[:lower:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Lower)));
+        assert_eq!(
+            t("[[:print:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Print)));
+        assert_eq!(
+            t("[[:punct:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Punct)));
+        assert_eq!(
+            t("[[:space:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Space)));
+        assert_eq!(
+            t("[[:upper:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Upper)));
+        assert_eq!(
+            t("[[:word:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Word)));
+        assert_eq!(
+            t("[[:xdigit:]]"),
+            hir_uclass(ascii_class(&ast::ClassAsciiKind::Xdigit)));
+
+        assert_eq!(
+            t("[[:^lower:]]"),
+            hir_negate(hir_uclass(ascii_class(&ast::ClassAsciiKind::Lower))));
+        assert_eq!(
+            t("(?i)[[:lower:]]"),
+            hir_uclass(&[
+                ('A', 'Z'), ('a', 'z'),
+                ('\u{17F}', '\u{17F}'),
+                ('\u{212A}', '\u{212A}'),
+            ]));
+
+        assert_eq!(
+            t("(?-u)[[:lower:]]"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Lower)));
+        assert_eq!(
+            t("(?i-u)[[:lower:]]"),
+            hir_case_fold(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Lower))));
+
+        assert_eq!(t_err("(?-u)[[:^lower:]]"), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(6, 1, 7), Position::new(16, 1, 17)),
+        });
+        assert_eq!(t_err("(?i-u)[[:^lower:]]"), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(7, 1, 8), Position::new(17, 1, 18)),
+        });
+    }
+
+    #[test]
+    fn class_perl() {
+        // Unicode
+        assert_eq!(
+            t(r"\d"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"\s"),
+            hir_uclass_query(ClassQuery::Binary("space")));
+        assert_eq!(
+            t(r"\w"),
+            hir_uclass_perl_word());
+        assert_eq!(
+            t(r"(?i)\d"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"(?i)\s"),
+            hir_uclass_query(ClassQuery::Binary("space")));
+        assert_eq!(
+            t(r"(?i)\w"),
+            hir_uclass_perl_word());
+
+        // Unicode, negated
+        assert_eq!(
+            t(r"\D"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("digit"))));
+        assert_eq!(
+            t(r"\S"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("space"))));
+        assert_eq!(
+            t(r"\W"),
+            hir_negate(hir_uclass_perl_word()));
+        assert_eq!(
+            t(r"(?i)\D"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("digit"))));
+        assert_eq!(
+            t(r"(?i)\S"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("space"))));
+        assert_eq!(
+            t(r"(?i)\W"),
+            hir_negate(hir_uclass_perl_word()));
+
+        // ASCII only
+        assert_eq!(
+            t(r"(?-u)\d"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Digit)));
+        assert_eq!(
+            t(r"(?-u)\s"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Space)));
+        assert_eq!(
+            t(r"(?-u)\w"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Word)));
+        assert_eq!(
+            t(r"(?i-u)\d"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Digit)));
+        assert_eq!(
+            t(r"(?i-u)\s"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Space)));
+        assert_eq!(
+            t(r"(?i-u)\w"),
+            hir_bclass_from_char(ascii_class(&ast::ClassAsciiKind::Word)));
+
+        // ASCII only, negated
+        assert_eq!(
+            t(r"(?-u)\D"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Digit))));
+        assert_eq!(
+            t(r"(?-u)\S"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Space))));
+        assert_eq!(
+            t(r"(?-u)\W"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Word))));
+        assert_eq!(
+            t(r"(?i-u)\D"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Digit))));
+        assert_eq!(
+            t(r"(?i-u)\S"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Space))));
+        assert_eq!(
+            t(r"(?i-u)\W"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Word))));
+    }
+
+    #[test]
+    fn class_unicode() {
+        assert_eq!(
+            t(r"\pZ"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\pz"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\p{Separator}"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\p{se      PaRa ToR}"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\p{gc:Separator}"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\p{gc=Separator}"),
+            hir_uclass_query(ClassQuery::Binary("Z")));
+        assert_eq!(
+            t(r"\p{Other}"),
+            hir_uclass_query(ClassQuery::Binary("Other")));
+        assert_eq!(
+            t(r"\pC"),
+            hir_uclass_query(ClassQuery::Binary("Other")));
+
+        assert_eq!(
+            t(r"\PZ"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("Z"))));
+        assert_eq!(
+            t(r"\P{separator}"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("Z"))));
+        assert_eq!(
+            t(r"\P{gc!=separator}"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("Z"))));
+
+        assert_eq!(
+            t(r"\p{Greek}"),
+            hir_uclass_query(ClassQuery::Binary("Greek")));
+        assert_eq!(
+            t(r"(?i)\p{Greek}"),
+            hir_case_fold(hir_uclass_query(ClassQuery::Binary("Greek"))));
+        assert_eq!(
+            t(r"(?i)\P{Greek}"),
+            hir_negate(hir_case_fold(hir_uclass_query(
+                ClassQuery::Binary("Greek")))));
+
+        assert_eq!(
+            t(r"\p{any}"),
+            hir_uclass_query(ClassQuery::Binary("Any")));
+        assert_eq!(
+            t(r"\p{assigned}"),
+            hir_uclass_query(ClassQuery::Binary("Assigned")));
+        assert_eq!(
+            t(r"\p{ascii}"),
+            hir_uclass_query(ClassQuery::Binary("ASCII")));
+        assert_eq!(
+            t(r"\p{gc:any}"),
+            hir_uclass_query(ClassQuery::Binary("Any")));
+        assert_eq!(
+            t(r"\p{gc:assigned}"),
+            hir_uclass_query(ClassQuery::Binary("Assigned")));
+        assert_eq!(
+            t(r"\p{gc:ascii}"),
+            hir_uclass_query(ClassQuery::Binary("ASCII")));
+
+        assert_eq!(t_err(r"(?-u)\pZ"), TestError {
+            kind: hir::ErrorKind::UnicodeNotAllowed,
+            span: Span::new(Position::new(5, 1, 6), Position::new(8, 1, 9)),
+        });
+        assert_eq!(t_err(r"(?-u)\p{Separator}"), TestError {
+            kind: hir::ErrorKind::UnicodeNotAllowed,
+            span: Span::new(Position::new(5, 1, 6), Position::new(18, 1, 19)),
+        });
+        assert_eq!(t_err(r"\pE"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(3, 1, 4)),
+        });
+        assert_eq!(t_err(r"\p{Foo}"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(7, 1, 8)),
+        });
+        assert_eq!(t_err(r"\p{gc:Foo}"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyValueNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(10, 1, 11)),
+        });
+        assert_eq!(t_err(r"\p{sc:Foo}"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyValueNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(10, 1, 11)),
+        });
+        assert_eq!(t_err(r"\p{scx:Foo}"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyValueNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(11, 1, 12)),
+        });
+        assert_eq!(t_err(r"\p{age:Foo}"), TestError {
+            kind: hir::ErrorKind::UnicodePropertyValueNotFound,
+            span: Span::new(Position::new(0, 1, 1), Position::new(11, 1, 12)),
+        });
+    }
+
+    #[test]
+    fn class_bracketed() {
+        assert_eq!(t("[a]"), hir_uclass(&[('a', 'a')]));
+        assert_eq!(t("[^[a]]"), hir_negate(hir_uclass(&[('a', 'a')])));
+        assert_eq!(t("[a-z]"), hir_uclass(&[('a', 'z')]));
+        assert_eq!(t("[a-fd-h]"), hir_uclass(&[('a', 'h')]));
+        assert_eq!(t("[a-fg-m]"), hir_uclass(&[('a', 'm')]));
+        assert_eq!(t(r"[\x00]"), hir_uclass(&[('\0', '\0')]));
+        assert_eq!(t(r"[\n]"), hir_uclass(&[('\n', '\n')]));
+        assert_eq!(t("[\n]"), hir_uclass(&[('\n', '\n')]));
+        assert_eq!(
+            t(r"[\d]"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"[\pZ]"),
+            hir_uclass_query(ClassQuery::Binary("separator")));
+        assert_eq!(
+            t(r"[\p{separator}]"),
+            hir_uclass_query(ClassQuery::Binary("separator")));
+        assert_eq!(
+            t(r"[^\D]"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"[^\PZ]"),
+            hir_uclass_query(ClassQuery::Binary("separator")));
+        assert_eq!(
+            t(r"[^\P{separator}]"),
+            hir_uclass_query(ClassQuery::Binary("separator")));
+        assert_eq!(
+            t(r"(?i)[^\D]"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"(?i)[^\P{greek}]"),
+            hir_case_fold(hir_uclass_query(ClassQuery::Binary("greek"))));
+
+        assert_eq!(t("(?-u)[a]"), hir_bclass(&[(b'a', b'a')]));
+        assert_eq!(t(r"(?-u)[\x00]"), hir_bclass(&[(b'\0', b'\0')]));
+        assert_eq!(t_bytes(r"(?-u)[\xFF]"), hir_bclass(&[(b'\xFF', b'\xFF')]));
+
+        assert_eq!(t("(?i)[a]"), hir_uclass(&[('A', 'A'), ('a', 'a')]));
+        assert_eq!(t("(?i)[k]"), hir_uclass(&[
+            ('K', 'K'), ('k', 'k'), ('\u{212A}', '\u{212A}'),
+        ]));
+        assert_eq!(t("(?i)[β]"), hir_uclass(&[
+            ('Β', 'Β'), ('β', 'β'), ('ϐ', 'ϐ'),
+        ]));
+        assert_eq!(t("(?i-u)[k]"), hir_bclass(&[
+            (b'K', b'K'), (b'k', b'k'),
+        ]));
+
+        assert_eq!(t("[^a]"), hir_negate(hir_uclass(&[('a', 'a')])));
+        assert_eq!(t(r"[^\x00]"), hir_negate(hir_uclass(&[('\0', '\0')])));
+        assert_eq!(
+            t_bytes("(?-u)[^a]"),
+            hir_negate(hir_bclass(&[(b'a', b'a')])));
+        assert_eq!(
+            t(r"[^\d]"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("digit"))));
+        assert_eq!(
+            t(r"[^\pZ]"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("separator"))));
+        assert_eq!(
+            t(r"[^\p{separator}]"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("separator"))));
+        assert_eq!(
+            t(r"(?i)[^\p{greek}]"),
+            hir_negate(hir_case_fold(hir_uclass_query(
+                ClassQuery::Binary("greek")))));
+        assert_eq!(
+            t(r"(?i)[\P{greek}]"),
+            hir_negate(hir_case_fold(hir_uclass_query(
+                ClassQuery::Binary("greek")))));
+
+        // Test some weird cases.
+        assert_eq!(t(r"[\[]"), hir_uclass(&[('[', '[')]));
+
+        assert_eq!(t(r"[&]"), hir_uclass(&[('&', '&')]));
+        assert_eq!(t(r"[\&]"), hir_uclass(&[('&', '&')]));
+        assert_eq!(t(r"[\&\&]"), hir_uclass(&[('&', '&')]));
+        assert_eq!(t(r"[\x00-&]"), hir_uclass(&[('\0', '&')]));
+        assert_eq!(t(r"[&-\xFF]"), hir_uclass(&[('&', '\u{FF}')]));
+
+        assert_eq!(t(r"[~]"), hir_uclass(&[('~', '~')]));
+        assert_eq!(t(r"[\~]"), hir_uclass(&[('~', '~')]));
+        assert_eq!(t(r"[\~\~]"), hir_uclass(&[('~', '~')]));
+        assert_eq!(t(r"[\x00-~]"), hir_uclass(&[('\0', '~')]));
+        assert_eq!(t(r"[~-\xFF]"), hir_uclass(&[('~', '\u{FF}')]));
+
+        assert_eq!(t(r"[-]"), hir_uclass(&[('-', '-')]));
+        assert_eq!(t(r"[\-]"), hir_uclass(&[('-', '-')]));
+        assert_eq!(t(r"[\-\-]"), hir_uclass(&[('-', '-')]));
+        assert_eq!(t(r"[\x00-\-]"), hir_uclass(&[('\0', '-')]));
+        assert_eq!(t(r"[\--\xFF]"), hir_uclass(&[('-', '\u{FF}')]));
+
+        assert_eq!(t_err("(?-u)[^a]"), TestError {
+            kind: hir::ErrorKind::InvalidUtf8,
+            span: Span::new(Position::new(5, 1, 6), Position::new(9, 1, 10)),
+        });
+        assert_eq!(t_err(r"[^\s\S]"), TestError {
+            kind: hir::ErrorKind::EmptyClassNotAllowed,
+            span: Span::new(Position::new(0, 1, 1), Position::new(7, 1, 8)),
+        });
+        assert_eq!(t_err(r"(?-u)[^\s\S]"), TestError {
+            kind: hir::ErrorKind::EmptyClassNotAllowed,
+            span: Span::new(Position::new(5, 1, 6), Position::new(12, 1, 13)),
+        });
+    }
+
+    #[test]
+    fn class_bracketed_union() {
+        assert_eq!(
+            t("[a-zA-Z]"),
+            hir_uclass(&[('A', 'Z'), ('a', 'z')]));
+        assert_eq!(
+            t(r"[a\pZb]"),
+            hir_union(
+                hir_uclass(&[('a', 'b')]),
+                hir_uclass_query(ClassQuery::Binary("separator"))));
+        assert_eq!(
+            t(r"[\pZ\p{Greek}]"),
+            hir_union(
+                hir_uclass_query(ClassQuery::Binary("greek")),
+                hir_uclass_query(ClassQuery::Binary("separator"))));
+        assert_eq!(
+            t(r"[\p{age:3.0}\pZ\p{Greek}]"),
+            hir_union(
+                hir_uclass_query(ClassQuery::ByValue {
+                    property_name: "age",
+                    property_value: "3.0",
+                }),
+                hir_union(
+                    hir_uclass_query(ClassQuery::Binary("greek")),
+                    hir_uclass_query(ClassQuery::Binary("separator")))));
+        assert_eq!(
+            t(r"[[[\p{age:3.0}\pZ]\p{Greek}][\p{Cyrillic}]]"),
+            hir_union(
+                hir_uclass_query(ClassQuery::ByValue {
+                    property_name: "age",
+                    property_value: "3.0",
+                }),
+                hir_union(
+                    hir_uclass_query(ClassQuery::Binary("cyrillic")),
+                    hir_union(
+                        hir_uclass_query(ClassQuery::Binary("greek")),
+                        hir_uclass_query(ClassQuery::Binary("separator"))))));
+
+        assert_eq!(
+            t(r"(?i)[\p{age:3.0}\pZ\p{Greek}]"),
+            hir_case_fold(hir_union(
+                hir_uclass_query(ClassQuery::ByValue {
+                    property_name: "age",
+                    property_value: "3.0",
+                }),
+                hir_union(
+                    hir_uclass_query(ClassQuery::Binary("greek")),
+                    hir_uclass_query(ClassQuery::Binary("separator"))))));
+        assert_eq!(
+            t(r"[^\p{age:3.0}\pZ\p{Greek}]"),
+            hir_negate(hir_union(
+                hir_uclass_query(ClassQuery::ByValue {
+                    property_name: "age",
+                    property_value: "3.0",
+                }),
+                hir_union(
+                    hir_uclass_query(ClassQuery::Binary("greek")),
+                    hir_uclass_query(ClassQuery::Binary("separator"))))));
+        assert_eq!(
+            t(r"(?i)[^\p{age:3.0}\pZ\p{Greek}]"),
+            hir_negate(hir_case_fold(hir_union(
+                hir_uclass_query(ClassQuery::ByValue {
+                    property_name: "age",
+                    property_value: "3.0",
+                }),
+                hir_union(
+                    hir_uclass_query(ClassQuery::Binary("greek")),
+                    hir_uclass_query(ClassQuery::Binary("separator")))))));
+    }
+
+    #[test]
+    fn class_bracketed_nested() {
+        assert_eq!(
+            t(r"[a[^c]]"),
+            hir_negate(hir_uclass(&[('c', 'c')])));
+        assert_eq!(
+            t(r"[a-b[^c]]"),
+            hir_negate(hir_uclass(&[('c', 'c')])));
+        assert_eq!(
+            t(r"[a-c[^c]]"),
+            hir_negate(hir_uclass(&[])));
+
+        assert_eq!(
+            t(r"[^a[^c]]"),
+            hir_uclass(&[('c', 'c')]));
+        assert_eq!(
+            t(r"[^a-b[^c]]"),
+            hir_uclass(&[('c', 'c')]));
+
+        assert_eq!(
+            t(r"(?i)[a[^c]]"),
+            hir_negate(hir_case_fold(hir_uclass(&[('c', 'c')]))));
+        assert_eq!(
+            t(r"(?i)[a-b[^c]]"),
+            hir_negate(hir_case_fold(hir_uclass(&[('c', 'c')]))));
+
+        assert_eq!(
+            t(r"(?i)[^a[^c]]"),
+            hir_uclass(&[('C', 'C'), ('c', 'c')]));
+        assert_eq!(
+            t(r"(?i)[^a-b[^c]]"),
+            hir_uclass(&[('C', 'C'), ('c', 'c')]));
+
+        assert_eq!(t_err(r"[^a-c[^c]]"), TestError {
+            kind: hir::ErrorKind::EmptyClassNotAllowed,
+            span: Span::new(Position::new(0, 1, 1), Position::new(10, 1, 11)),
+        });
+        assert_eq!(t_err(r"(?i)[^a-c[^c]]"), TestError {
+            kind: hir::ErrorKind::EmptyClassNotAllowed,
+            span: Span::new(Position::new(4, 1, 5), Position::new(14, 1, 15)),
+        });
+    }
+
+    #[test]
+    fn class_bracketed_intersect() {
+        assert_eq!(t("[abc&&b-c]"), hir_uclass(&[('b', 'c')]));
+        assert_eq!(t("[abc&&[b-c]]"), hir_uclass(&[('b', 'c')]));
+        assert_eq!(t("[[abc]&&[b-c]]"), hir_uclass(&[('b', 'c')]));
+        assert_eq!(t("[a-z&&b-y&&c-x]"), hir_uclass(&[('c', 'x')]));
+        assert_eq!(t("[c-da-b&&a-d]"), hir_uclass(&[('a', 'd')]));
+        assert_eq!(t("[a-d&&c-da-b]"), hir_uclass(&[('a', 'd')]));
+        assert_eq!(t(r"[a-z&&a-c]"), hir_uclass(&[('a', 'c')]));
+        assert_eq!(t(r"[[a-z&&a-c]]"), hir_uclass(&[('a', 'c')]));
+        assert_eq!(t(r"[^[a-z&&a-c]]"), hir_negate(hir_uclass(&[('a', 'c')])));
+
+        assert_eq!(t("(?-u)[abc&&b-c]"), hir_bclass(&[(b'b', b'c')]));
+        assert_eq!(t("(?-u)[abc&&[b-c]]"), hir_bclass(&[(b'b', b'c')]));
+        assert_eq!(t("(?-u)[[abc]&&[b-c]]"), hir_bclass(&[(b'b', b'c')]));
+        assert_eq!(t("(?-u)[a-z&&b-y&&c-x]"), hir_bclass(&[(b'c', b'x')]));
+        assert_eq!(t("(?-u)[c-da-b&&a-d]"), hir_bclass(&[(b'a', b'd')]));
+        assert_eq!(t("(?-u)[a-d&&c-da-b]"), hir_bclass(&[(b'a', b'd')]));
+
+        assert_eq!(
+            t("(?i)[abc&&b-c]"),
+            hir_case_fold(hir_uclass(&[('b', 'c')])));
+        assert_eq!(
+            t("(?i)[abc&&[b-c]]"),
+            hir_case_fold(hir_uclass(&[('b', 'c')])));
+        assert_eq!(
+            t("(?i)[[abc]&&[b-c]]"),
+            hir_case_fold(hir_uclass(&[('b', 'c')])));
+        assert_eq!(
+            t("(?i)[a-z&&b-y&&c-x]"),
+            hir_case_fold(hir_uclass(&[('c', 'x')])));
+        assert_eq!(
+            t("(?i)[c-da-b&&a-d]"),
+            hir_case_fold(hir_uclass(&[('a', 'd')])));
+        assert_eq!(
+            t("(?i)[a-d&&c-da-b]"),
+            hir_case_fold(hir_uclass(&[('a', 'd')])));
+
+        assert_eq!(
+            t("(?i-u)[abc&&b-c]"),
+            hir_case_fold(hir_bclass(&[(b'b', b'c')])));
+        assert_eq!(
+            t("(?i-u)[abc&&[b-c]]"),
+            hir_case_fold(hir_bclass(&[(b'b', b'c')])));
+        assert_eq!(
+            t("(?i-u)[[abc]&&[b-c]]"),
+            hir_case_fold(hir_bclass(&[(b'b', b'c')])));
+        assert_eq!(
+            t("(?i-u)[a-z&&b-y&&c-x]"),
+            hir_case_fold(hir_bclass(&[(b'c', b'x')])));
+        assert_eq!(
+            t("(?i-u)[c-da-b&&a-d]"),
+            hir_case_fold(hir_bclass(&[(b'a', b'd')])));
+        assert_eq!(
+            t("(?i-u)[a-d&&c-da-b]"),
+            hir_case_fold(hir_bclass(&[(b'a', b'd')])));
+
+        // In `[a^]`, `^` does not need to be escaped, so it makes sense that
+        // `^` is also allowed to be unescaped after `&&`.
+        assert_eq!(t(r"[\^&&^]"), hir_uclass(&[('^', '^')]));
+        // `]` needs to be escaped after `&&` since it's not at start of class.
+        assert_eq!(t(r"[]&&\]]"), hir_uclass(&[(']', ']')]));
+        assert_eq!(t(r"[-&&-]"), hir_uclass(&[('-', '-')]));
+        assert_eq!(t(r"[\&&&&]"), hir_uclass(&[('&', '&')]));
+        assert_eq!(t(r"[\&&&\&]"), hir_uclass(&[('&', '&')]));
+        // Test precedence.
+        assert_eq!(
+            t(r"[a-w&&[^c-g]z]"),
+            hir_uclass(&[('a', 'b'), ('h', 'w')]));
+    }
+
+    #[test]
+    fn class_bracketed_intersect_negate() {
+        assert_eq!(
+            t(r"[^\w&&\d]"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("digit"))));
+        assert_eq!(
+            t(r"[^[a-z&&a-c]]"),
+            hir_negate(hir_uclass(&[('a', 'c')])));
+        assert_eq!(
+            t(r"[^[\w&&\d]]"),
+            hir_negate(hir_uclass_query(ClassQuery::Binary("digit"))));
+        assert_eq!(
+            t(r"[^[^\w&&\d]]"),
+            hir_uclass_query(ClassQuery::Binary("digit")));
+        assert_eq!(
+            t(r"[[[^\w]&&[^\d]]]"),
+            hir_negate(hir_uclass_perl_word()));
+
+        assert_eq!(
+            t_bytes(r"(?-u)[^\w&&\d]"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Digit))));
+        assert_eq!(
+            t_bytes(r"(?-u)[^[a-z&&a-c]]"),
+            hir_negate(hir_bclass(&[(b'a', b'c')])));
+        assert_eq!(
+            t_bytes(r"(?-u)[^[\w&&\d]]"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Digit))));
+        assert_eq!(
+            t_bytes(r"(?-u)[^[^\w&&\d]]"),
+            hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Digit)));
+        assert_eq!(
+            t_bytes(r"(?-u)[[[^\w]&&[^\d]]]"),
+            hir_negate(hir_bclass_from_char(ascii_class(
+                &ast::ClassAsciiKind::Word))));
+    }
+
+    #[test]
+    fn class_bracketed_difference() {
+        assert_eq!(
+            t(r"[\pL--[:ascii:]]"),
+            hir_difference(
+                hir_uclass_query(ClassQuery::Binary("letter")),
+                hir_uclass(&[('\0', '\x7F')])));
+
+        assert_eq!(
+            t(r"(?-u)[[:alpha:]--[:lower:]]"),
+            hir_bclass(&[(b'A', b'Z')]));
+    }
+
+    #[test]
+    fn class_bracketed_symmetric_difference() {
+        assert_eq!(
+            t(r"[\p{sc:Greek}~~\p{scx:Greek}]"),
+            hir_uclass(&[
+                ('\u{0342}', '\u{0342}'),
+                ('\u{0345}', '\u{0345}'),
+                ('\u{1DC0}', '\u{1DC1}'),
+            ]));
+        assert_eq!(
+            t(r"[a-g~~c-j]"),
+            hir_uclass(&[('a', 'b'), ('h', 'j')]));
+
+        assert_eq!(
+            t(r"(?-u)[a-g~~c-j]"),
+            hir_bclass(&[(b'a', b'b'), (b'h', b'j')]));
+    }
+
+    #[test]
+    fn ignore_whitespace() {
+        assert_eq!(t(r"(?x)\12 3"), hir_lit("\n3"));
+        assert_eq!(t(r"(?x)\x { 53 }"), hir_lit("S"));
+        assert_eq!(t(r"(?x)\x # comment
+{ # comment
+    53 # comment
+} #comment"), hir_lit("S"));
+
+        assert_eq!(t(r"(?x)\x 53"), hir_lit("S"));
+        assert_eq!(t(r"(?x)\x # comment
+        53 # comment"), hir_lit("S"));
+        assert_eq!(t(r"(?x)\x5 3"), hir_lit("S"));
+
+        assert_eq!(t(r"(?x)\p # comment
+{ # comment
+    Separator # comment
+} # comment"), hir_uclass_query(ClassQuery::Binary("separator")));
+
+        assert_eq!(t(r"(?x)a # comment
+{ # comment
+    5 # comment
+    , # comment
+    10 # comment
+} # comment"),
+            hir_range(
+                true, hir::RepetitionRange::Bounded(5, 10), hir_lit("a")));
+
+        assert_eq!(t(r"(?x)a\  # hi there"), hir_lit("a "));
+    }
+
+    #[test]
+    fn analysis_is_always_utf8() {
+        // Positive examples.
+        assert!(t_bytes(r"a").is_always_utf8());
+        assert!(t_bytes(r"ab").is_always_utf8());
+        assert!(t_bytes(r"(?-u)a").is_always_utf8());
+        assert!(t_bytes(r"(?-u)ab").is_always_utf8());
+        assert!(t_bytes(r"\xFF").is_always_utf8());
+        assert!(t_bytes(r"\xFF\xFF").is_always_utf8());
+        assert!(t_bytes(r"[^a]").is_always_utf8());
+        assert!(t_bytes(r"[^a][^a]").is_always_utf8());
+        assert!(t_bytes(r"\b").is_always_utf8());
+        assert!(t_bytes(r"\B").is_always_utf8());
+        assert!(t_bytes(r"(?-u)\b").is_always_utf8());
+
+        // Negative examples.
+        assert!(!t_bytes(r"(?-u)\xFF").is_always_utf8());
+        assert!(!t_bytes(r"(?-u)\xFF\xFF").is_always_utf8());
+        assert!(!t_bytes(r"(?-u)[^a]").is_always_utf8());
+        assert!(!t_bytes(r"(?-u)[^a][^a]").is_always_utf8());
+        assert!(!t_bytes(r"(?-u)\B").is_always_utf8());
+    }
+
+    #[test]
+    fn analysis_is_all_assertions() {
+        // Positive examples.
+        assert!(t(r"\b").is_all_assertions());
+        assert!(t(r"\B").is_all_assertions());
+        assert!(t(r"^").is_all_assertions());
+        assert!(t(r"$").is_all_assertions());
+        assert!(t(r"\A").is_all_assertions());
+        assert!(t(r"\z").is_all_assertions());
+        assert!(t(r"$^\z\A\b\B").is_all_assertions());
+        assert!(t(r"$|^|\z|\A|\b|\B").is_all_assertions());
+        assert!(t(r"^$|$^").is_all_assertions());
+        assert!(t(r"((\b)+())*^").is_all_assertions());
+
+        // Negative examples.
+        assert!(!t(r"^a").is_all_assertions());
+    }
+
+    #[test]
+    fn analysis_is_anchored() {
+        // Positive examples.
+        assert!(t(r"^").is_anchored_start());
+        assert!(t(r"$").is_anchored_end());
+
+        assert!(t(r"^^").is_anchored_start());
+        assert!(t(r"$$").is_anchored_end());
+
+        assert!(t(r"^$").is_anchored_start());
+        assert!(t(r"^$").is_anchored_end());
+
+        assert!(t(r"^foo").is_anchored_start());
+        assert!(t(r"foo$").is_anchored_end());
+
+        assert!(t(r"^foo|^bar").is_anchored_start());
+        assert!(t(r"foo$|bar$").is_anchored_end());
+
+        assert!(t(r"^(foo|bar)").is_anchored_start());
+        assert!(t(r"(foo|bar)$").is_anchored_end());
+
+        assert!(t(r"^+").is_anchored_start());
+        assert!(t(r"$+").is_anchored_end());
+        assert!(t(r"^++").is_anchored_start());
+        assert!(t(r"$++").is_anchored_end());
+        assert!(t(r"(^)+").is_anchored_start());
+        assert!(t(r"($)+").is_anchored_end());
+
+        assert!(t(r"$^").is_anchored_start());
+        assert!(t(r"$^").is_anchored_end());
+        assert!(t(r"$^|^$").is_anchored_start());
+        assert!(t(r"$^|^$").is_anchored_end());
+
+        assert!(t(r"\b^").is_anchored_start());
+        assert!(t(r"$\b").is_anchored_end());
+        assert!(t(r"^(?m:^)").is_anchored_start());
+        assert!(t(r"(?m:$)$").is_anchored_end());
+        assert!(t(r"(?m:^)^").is_anchored_start());
+        assert!(t(r"$(?m:$)").is_anchored_end());
+
+        // Negative examples.
+        assert!(!t(r"(?m)^").is_anchored_start());
+        assert!(!t(r"(?m)$").is_anchored_end());
+        assert!(!t(r"(?m:^$)|$^").is_anchored_start());
+        assert!(!t(r"(?m:^$)|$^").is_anchored_end());
+        assert!(!t(r"$^|(?m:^$)").is_anchored_start());
+        assert!(!t(r"$^|(?m:^$)").is_anchored_end());
+
+        assert!(!t(r"a^").is_anchored_start());
+        assert!(!t(r"$a").is_anchored_start());
+
+        assert!(!t(r"a^").is_anchored_start());
+        assert!(!t(r"$a").is_anchored_start());
+
+        assert!(!t(r"^foo|bar").is_anchored_start());
+        assert!(!t(r"foo|bar$").is_anchored_end());
+
+        assert!(!t(r"^*").is_anchored_start());
+        assert!(!t(r"$*").is_anchored_end());
+        assert!(!t(r"^*+").is_anchored_start());
+        assert!(!t(r"$*+").is_anchored_end());
+        assert!(!t(r"^+*").is_anchored_start());
+        assert!(!t(r"$+*").is_anchored_end());
+        assert!(!t(r"(^)*").is_anchored_start());
+        assert!(!t(r"($)*").is_anchored_end());
+    }
+
+    #[test]
+    fn analysis_is_any_anchored() {
+        // Positive examples.
+        assert!(t(r"^").is_any_anchored_start());
+        assert!(t(r"$").is_any_anchored_end());
+        assert!(t(r"\A").is_any_anchored_start());
+        assert!(t(r"\z").is_any_anchored_end());
+
+        // Negative examples.
+        assert!(!t(r"(?m)^").is_any_anchored_start());
+        assert!(!t(r"(?m)$").is_any_anchored_end());
+        assert!(!t(r"$").is_any_anchored_start());
+        assert!(!t(r"^").is_any_anchored_end());
+    }
+
+    #[test]
+    fn analysis_is_match_empty() {
+        // Positive examples.
+        assert!(t(r"").is_match_empty());
+        assert!(t(r"()").is_match_empty());
+        assert!(t(r"()*").is_match_empty());
+        assert!(t(r"()+").is_match_empty());
+        assert!(t(r"()?").is_match_empty());
+        assert!(t(r"a*").is_match_empty());
+        assert!(t(r"a?").is_match_empty());
+        assert!(t(r"a{0}").is_match_empty());
+        assert!(t(r"a{0,}").is_match_empty());
+        assert!(t(r"a{0,1}").is_match_empty());
+        assert!(t(r"a{0,10}").is_match_empty());
+        assert!(t(r"\pL*").is_match_empty());
+        assert!(t(r"a*|b").is_match_empty());
+        assert!(t(r"b|a*").is_match_empty());
+        assert!(t(r"a*a?(abcd)*").is_match_empty());
+        assert!(t(r"^").is_match_empty());
+        assert!(t(r"$").is_match_empty());
+        assert!(t(r"(?m)^").is_match_empty());
+        assert!(t(r"(?m)$").is_match_empty());
+        assert!(t(r"\A").is_match_empty());
+        assert!(t(r"\z").is_match_empty());
+        assert!(t(r"\B").is_match_empty());
+        assert!(t_bytes(r"(?-u)\B").is_match_empty());
+
+        // Negative examples.
+        assert!(!t(r"a+").is_match_empty());
+        assert!(!t(r"a{1}").is_match_empty());
+        assert!(!t(r"a{1,}").is_match_empty());
+        assert!(!t(r"a{1,2}").is_match_empty());
+        assert!(!t(r"a{1,10}").is_match_empty());
+        assert!(!t(r"b|a").is_match_empty());
+        assert!(!t(r"a*a+(abcd)*").is_match_empty());
+        assert!(!t(r"\b").is_match_empty());
+        assert!(!t(r"(?-u)\b").is_match_empty());
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/hir/visitor.rs b/third_party/rust/regex-syntax/src/hir/visitor.rs
new file mode 100644
index 000000000000..58be7ad0783c
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/hir/visitor.rs
@@ -0,0 +1,222 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use hir::{self, Hir, HirKind};
+
+/// A trait for visiting the high-level IR (HIR) in depth first order.
+///
+/// The principle aim of this trait is to enable callers to perform case
+/// analysis on a high-level intermediate representation of a regular
+/// expression without necessarily using recursion. In particular, this permits
+/// callers to do case analysis with constant stack usage, which can be
+/// important since the size of an HIR may be proportional to end user input.
+///
+/// Typical usage of this trait involves providing an implementation and then
+/// running it using the [`visit`](fn.visit.html) function.
+pub trait Visitor {
+    /// The result of visiting an HIR.
+    type Output;
+    /// An error that visiting an HIR might return.
+    type Err;
+
+    /// All implementors of `Visitor` must provide a `finish` method, which
+    /// yields the result of visiting the HIR or an error.
+    fn finish(self) -> Result<Self::Output, Self::Err>;
+
+    /// This method is called before beginning traversal of the HIR.
+    fn start(&mut self) {}
+
+    /// This method is called on an `Hir` before descending into child `Hir`
+    /// nodes.
+    fn visit_pre(&mut self, _hir: &Hir) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called on an `Hir` after descending all of its child
+    /// `Hir` nodes.
+    fn visit_post(&mut self, _hir: &Hir) -> Result<(), Self::Err> {
+        Ok(())
+    }
+
+    /// This method is called between child nodes of an alternation.
+    fn visit_alternation_in(&mut self) -> Result<(), Self::Err> {
+        Ok(())
+    }
+}
+
+/// Executes an implementation of `Visitor` in constant stack space.
+///
+/// This function will visit every node in the given `Hir` while calling
+/// appropriate methods provided by the
+/// [`Visitor`](trait.Visitor.html) trait.
+///
+/// The primary use case for this method is when one wants to perform case
+/// analysis over an `Hir` without using a stack size proportional to the depth
+/// of the `Hir`. Namely, this method will instead use constant stack space,
+/// but will use heap space proportional to the size of the `Hir`. This may be
+/// desirable in cases where the size of `Hir` is proportional to end user
+/// input.
+///
+/// If the visitor returns an error at any point, then visiting is stopped and
+/// the error is returned.
+pub fn visit<V: Visitor>(hir: &Hir, visitor: V) -> Result<V::Output, V::Err> {
+    HeapVisitor::new().visit(hir, visitor)
+}
+
+/// HeapVisitor visits every item in an `Hir` recursively using constant stack
+/// size and a heap size proportional to the size of the `Hir`.
+struct HeapVisitor<'a> {
+    /// A stack of `Hir` nodes. This is roughly analogous to the call stack
+    /// used in a typical recursive visitor.
+    stack: Vec<(&'a Hir, Frame<'a>)>,
+}
+
+/// Represents a single stack frame while performing structural induction over
+/// an `Hir`.
+enum Frame<'a> {
+    /// A stack frame allocated just before descending into a repetition
+    /// operator's child node.
+    Repetition(&'a hir::Repetition),
+    /// A stack frame allocated just before descending into a group's child
+    /// node.
+    Group(&'a hir::Group),
+    /// The stack frame used while visiting every child node of a concatenation
+    /// of expressions.
+    Concat {
+        /// The child node we are currently visiting.
+        head: &'a Hir,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Hir],
+    },
+    /// The stack frame used while visiting every child node of an alternation
+    /// of expressions.
+    Alternation {
+        /// The child node we are currently visiting.
+        head: &'a Hir,
+        /// The remaining child nodes to visit (which may be empty).
+        tail: &'a [Hir],
+    },
+}
+
+impl<'a> HeapVisitor<'a> {
+    fn new() -> HeapVisitor<'a> {
+        HeapVisitor { stack: vec![] }
+    }
+
+    fn visit<V: Visitor>(
+        &mut self,
+        mut hir: &'a Hir,
+        mut visitor: V,
+    ) -> Result<V::Output, V::Err> {
+        self.stack.clear();
+
+        visitor.start();
+        loop {
+            visitor.visit_pre(hir)?;
+            if let Some(x) = self.induct(hir) {
+                let child = x.child();
+                self.stack.push((hir, x));
+                hir = child;
+                continue;
+            }
+            // No induction means we have a base case, so we can post visit
+            // it now.
+            visitor.visit_post(hir)?;
+
+            // At this point, we now try to pop our call stack until it is
+            // either empty or we hit another inductive case.
+            loop {
+                let (post_hir, frame) = match self.stack.pop() {
+                    None => return visitor.finish(),
+                    Some((post_hir, frame)) => (post_hir, frame),
+                };
+                // If this is a concat/alternate, then we might have additional
+                // inductive steps to process.
+                if let Some(x) = self.pop(frame) {
+                    if let Frame::Alternation {..} = x {
+                        visitor.visit_alternation_in()?;
+                    }
+                    hir = x.child();
+                    self.stack.push((post_hir, x));
+                    break;
+                }
+                // Otherwise, we've finished visiting all the child nodes for
+                // this HIR, so we can post visit it now.
+                visitor.visit_post(post_hir)?;
+            }
+        }
+    }
+
+    /// Build a stack frame for the given HIR if one is needed (which occurs if
+    /// and only if there are child nodes in the HIR). Otherwise, return None.
+    fn induct(&mut self, hir: &'a Hir) -> Option<Frame<'a>> {
+        match *hir.kind() {
+            HirKind::Repetition(ref x) => Some(Frame::Repetition(x)),
+            HirKind::Group(ref x) => Some(Frame::Group(x)),
+            HirKind::Concat(ref x) if x.is_empty() => None,
+            HirKind::Concat(ref x) => {
+                Some(Frame::Concat {
+                    head: &x[0],
+                    tail: &x[1..],
+                })
+            }
+            HirKind::Alternation(ref x) if x.is_empty() => None,
+            HirKind::Alternation(ref x) => {
+                Some(Frame::Alternation {
+                    head: &x[0],
+                    tail: &x[1..],
+                })
+            }
+            _ => None,
+        }
+    }
+
+    /// Pops the given frame. If the frame has an additional inductive step,
+    /// then return it, otherwise return `None`.
+    fn pop(&self, induct: Frame<'a>) -> Option<Frame<'a>> {
+        match induct {
+            Frame::Repetition(_) => None,
+            Frame::Group(_) => None,
+            Frame::Concat { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Concat {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+            Frame::Alternation { tail, .. } => {
+                if tail.is_empty() {
+                    None
+                } else {
+                    Some(Frame::Alternation {
+                        head: &tail[0],
+                        tail: &tail[1..],
+                    })
+                }
+            }
+        }
+    }
+}
+
+impl<'a> Frame<'a> {
+    /// Perform the next inductive step on this frame and return the next
+    /// child HIR node to visit.
+    fn child(&self) -> &'a Hir {
+        match *self {
+            Frame::Repetition(rep) => &rep.hir,
+            Frame::Group(group) => &group.hir,
+            Frame::Concat { head, .. } => head,
+            Frame::Alternation { head, .. } => head,
+        }
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/lib.rs b/third_party/rust/regex-syntax/src/lib.rs
index 83260d7e0368..f47ad9ce433c 100644
--- a/third_party/rust/regex-syntax/src/lib.rs
+++ b/third_party/rust/regex-syntax/src/lib.rs
@@ -1,2214 +1,228 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 /*!
-This crate provides a regular expression parser and an abstract syntax for
-regular expressions. The abstract syntax is defined by the `Expr` type. The
-concrete syntax is enumerated in the
-[`regex`](../regex/index.html#syntax)
-crate documentation.
+This crate provides a robust regular expression parser.
 
-Note that since this crate is first and foremost an implementation detail for
-the `regex` crate, it may experience more frequent breaking changes. It is
-exposed as a separate crate so that others may use it to do analysis on regular
-expressions or even build their own matching engine.
+This crate defines two primary types:
 
-# Example: parsing an expression
+* [`Ast`](ast/enum.Ast.html) is the abstract syntax of a regular expression.
+  An abstract syntax corresponds to a *structured representation* of the
+  concrete syntax of a regular expression, where the concrete syntax is the
+  pattern string itself (e.g., `foo(bar)+`). Given some abstract syntax, it
+  can be converted back to the original concrete syntax (modulo some details,
+  like whitespace). To a first approximation, the abstract syntax is complex
+  and difficult to analyze.
+* [`Hir`](hir/struct.Hir.html) is the high-level intermediate representation
+  ("HIR" or "high-level IR" for short) of regular expression. It corresponds to
+  an intermediate state of a regular expression that sits between the abstract
+  syntax and the low level compiled opcodes that are eventually responsible for
+  executing a regular expression search. Given some high-level IR, it is not
+  possible to produce the original concrete syntax (although it is possible to
+  produce an equivalent conrete syntax, but it will likely scarcely resemble
+  the original pattern). To a first approximation, the high-level IR is simple
+  and easy to analyze.
 
-Parsing a regular expression can be done with the `Expr::parse` function.
+These two types come with conversion routines:
 
-```rust
-use regex_syntax::Expr;
+* An [`ast::parse::Parser`](ast/parse/struct.Parser.html) converts concrete
+  syntax (a `&str`) to an [`Ast`](ast/enum.Ast.html).
+* A [`hir::translate::Translator`](hir/translate/struct.Translator.html)
+  converts an [`Ast`](ast/enum.Ast.html) to a [`Hir`](hir/struct.Hir.html).
 
-assert_eq!(Expr::parse(r"ab|yz").unwrap(), Expr::Alternate(vec![
-    Expr::Literal { chars: vec!['a', 'b'], casei: false },
-    Expr::Literal { chars: vec!['y', 'z'], casei: false },
-]));
-```
+As a convenience, the above two conversion routines are combined into one via
+the top-level [`Parser`](struct.Parser.html) type. This `Parser` will first
+convert your pattern to an `Ast` and then convert the `Ast` to an `Hir`.
 
-# Example: inspecting an error
 
-The parser in this crate provides very detailed error values. For example,
-if an invalid character class range is given:
+# Example
 
-```rust
-use regex_syntax::{Expr, ErrorKind};
+This example shows how to parse a pattern string into its HIR:
 
-let err = Expr::parse(r"[z-a]").unwrap_err();
-assert_eq!(err.position(), 4);
-assert_eq!(err.kind(), &ErrorKind::InvalidClassRange {
-    start: 'z',
-    end: 'a',
-});
 ```
+use regex_syntax::Parser;
+use regex_syntax::hir::{self, Hir};
 
-Or unbalanced parentheses:
-
-```rust
-use regex_syntax::{Expr, ErrorKind};
-
-let err = Expr::parse(r"ab(cd").unwrap_err();
-assert_eq!(err.position(), 2);
-assert_eq!(err.kind(), &ErrorKind::UnclosedParen);
+let hir = Parser::new().parse("a|b").unwrap();
+assert_eq!(hir, Hir::alternation(vec![
+    Hir::literal(hir::Literal::Unicode('a')),
+    Hir::literal(hir::Literal::Unicode('b')),
+]));
 ```
-*/
-
-#![deny(missing_docs)]
-#![cfg_attr(test, deny(warnings))]
-
-#[cfg(test)] extern crate quickcheck;
-#[cfg(test)] extern crate rand;
-
-mod literals;
-mod parser;
-mod unicode;
-
-use std::ascii;
-use std::char;
-use std::cmp::{Ordering, max, min};
-use std::fmt;
-use std::iter::IntoIterator;
-use std::ops::Deref;
-use std::result;
-use std::slice;
-use std::u8;
-use std::vec;
-
-use unicode::case_folding;
-
-use self::Expr::*;
-use self::Repeater::*;
-
-use parser::{Flags, Parser};
-
-pub use literals::{Literals, Lit};
-
-/// A regular expression abstract syntax tree.
-///
-/// An `Expr` represents the abstract syntax of a regular expression.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum Expr {
-    /// An empty regex (which never matches any text).
-    Empty,
-    /// A sequence of one or more literal characters to be matched.
-    Literal {
-        /// The characters.
-        chars: Vec<char>,
-        /// Whether to match case insensitively.
-        casei: bool,
-    },
-    /// A sequence of one or more literal bytes to be matched.
-    LiteralBytes {
-        /// The bytes.
-        bytes: Vec<u8>,
-        /// Whether to match case insensitively.
-        ///
-        /// The interpretation of "case insensitive" in this context is
-        /// ambiguous since `bytes` can be arbitrary. However, a good heuristic
-        /// is to assume that the bytes are ASCII-compatible and do simple
-        /// ASCII case folding.
-        casei: bool,
-    },
-    /// Match any character.
-    AnyChar,
-    /// Match any character, excluding new line (`0xA`).
-    AnyCharNoNL,
-    /// Match any byte.
-    AnyByte,
-    /// Match any byte, excluding new line (`0xA`).
-    AnyByteNoNL,
-    /// A character class.
-    Class(CharClass),
-    /// A character class with byte ranges only.
-    ClassBytes(ByteClass),
-    /// Match the start of a line or beginning of input.
-    StartLine,
-    /// Match the end of a line or end of input.
-    EndLine,
-    /// Match the beginning of input.
-    StartText,
-    /// Match the end of input.
-    EndText,
-    /// Match a word boundary (word character on one side and a non-word
-    /// character on the other).
-    WordBoundary,
-    /// Match a position that is not a word boundary (word or non-word
-    /// characters on both sides).
-    NotWordBoundary,
-    /// Match an ASCII word boundary.
-    WordBoundaryAscii,
-    /// Match a position that is not an ASCII word boundary.
-    NotWordBoundaryAscii,
-    /// A group, possibly non-capturing.
-    Group {
-        /// The expression inside the group.
-        e: Box<Expr>,
-        /// The capture index (starting at `1`) only for capturing groups.
-        i: Option<usize>,
-        /// The capture name, only for capturing named groups.
-        name: Option<String>,
-    },
-    /// A repeat operator (`?`, `*`, `+` or `{m,n}`).
-    Repeat {
-        /// The expression to be repeated. Limited to literals, `.`, classes
-        /// or grouped expressions.
-        e: Box<Expr>,
-        /// The type of repeat operator used.
-        r: Repeater,
-        /// Whether the repeat is greedy (match the most) or not (match the
-        /// least).
-        greedy: bool,
-    },
-    /// A concatenation of expressions. Must be matched one after the other.
-    ///
-    /// N.B. A concat expression can only appear at the top-level or
-    /// immediately inside a group expression.
-    Concat(Vec<Expr>),
-    /// An alternation of expressions. Only one must match.
-    ///
-    /// N.B. An alternate expression can only appear at the top-level or
-    /// immediately inside a group expression.
-    Alternate(Vec<Expr>),
-}
-
-type CaptureIndex = Option<usize>;
-
-type CaptureName = Option<String>;
-
-/// The type of a repeat operator expression.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum Repeater {
-    /// Match zero or one (`?`).
-    ZeroOrOne,
-    /// Match zero or more (`*`).
-    ZeroOrMore,
-    /// Match one or more (`+`).
-    OneOrMore,
-    /// Match for at least `min` and at most `max` (`{m,n}`).
-    ///
-    /// When `max` is `None`, there is no upper bound on the number of matches.
-    Range {
-        /// Lower bound on the number of matches.
-        min: u32,
-        /// Optional upper bound on the number of matches.
-        max: Option<u32>,
-    },
-}
-
-impl Repeater {
-    /// Returns true if and only if this repetition can match the empty string.
-    fn matches_empty(&self) -> bool {
-        use self::Repeater::*;
-        match *self {
-            ZeroOrOne => true,
-            ZeroOrMore => true,
-            OneOrMore => false,
-            Range { min, .. } => min == 0,
-        }
-    }
-}
-
-/// A character class.
-///
-/// A character class has a canonical format that the parser guarantees. Its
-/// canonical format is defined by the following invariants:
-///
-/// 1. Given any Unicode scalar value, it is matched by *at most* one character
-///    range in a canonical character class.
-/// 2. Every adjacent character range is separated by at least one Unicode
-///    scalar value.
-/// 3. Given any pair of character ranges `r1` and `r2`, if
-///    `r1.end < r2.start`, then `r1` comes before `r2` in a canonical
-///    character class.
-///
-/// In sum, any `CharClass` produced by this crate's parser is a sorted
-/// sequence of non-overlapping ranges. This makes it possible to test whether
-/// a character is matched by a class with a binary search.
-///
-/// If the case insensitive flag was set when parsing a character class, then
-/// simple case folding is done automatically. For example, `(?i)[a-c]` is
-/// automatically translated to `[a-cA-C]`.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct CharClass {
-    ranges: Vec<ClassRange>,
-}
-
-/// A single inclusive range in a character class.
-///
-/// Since range boundaries are defined by Unicode scalar values, the boundaries
-/// can never be in the open interval `(0xD7FF, 0xE000)`. However, a range may
-/// *cover* codepoints that are not scalar values.
-///
-/// Note that this has a few convenient impls on `PartialEq` and `PartialOrd`
-/// for testing whether a character is contained inside a given range.
-#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
-pub struct ClassRange {
-    /// The start character of the range.
-    ///
-    /// This must be less than or equal to `end`.
-    pub start: char,
-
-    /// The end character of the range.
-    ///
-    /// This must be greater than or equal to `start`.
-    pub end: char,
-}
-
-/// A byte class for byte ranges only.
-///
-/// A byte class has a canonical format that the parser guarantees. Its
-/// canonical format is defined by the following invariants:
-///
-/// 1. Given any byte, it is matched by *at most* one byte range in a canonical
-///    character class.
-/// 2. Every adjacent byte range is separated by at least one byte.
-/// 3. Given any pair of byte ranges `r1` and `r2`, if
-///    `r1.end < r2.start`, then `r1` comes before `r2` in a canonical
-///    character class.
-///
-/// In sum, any `ByteClass` produced by this crate's parser is a sorted
-/// sequence of non-overlapping ranges. This makes it possible to test whether
-/// a byte is matched by a class with a binary search.
-///
-/// If the case insensitive flag was set when parsing a character class,
-/// then simple ASCII-only case folding is done automatically. For example,
-/// `(?i)[a-c]` is automatically translated to `[a-cA-C]`.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ByteClass {
-    ranges: Vec<ByteRange>,
-}
-
-/// A single inclusive range in a byte class.
-///
-/// Note that this has a few convenient impls on `PartialEq` and `PartialOrd`
-/// for testing whether a byte is contained inside a given range.
-#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
-pub struct ByteRange {
-    /// The start byte of the range.
-    ///
-    /// This must be less than or equal to `end`.
-    pub start: u8,
-
-    /// The end byte of the range.
-    ///
-    /// This must be greater than or equal to `end`.
-    pub end: u8,
-}
-
-/// A builder for configuring regular expression parsing.
-///
-/// This allows setting the default values of flags and other options, such
-/// as the maximum nesting depth.
-#[derive(Clone, Debug)]
-pub struct ExprBuilder {
-    flags: Flags,
-    nest_limit: usize,
-}
-
-impl ExprBuilder {
-    /// Create a new builder for configuring expression parsing.
-    ///
-    /// Note that all flags are disabled by default.
-    pub fn new() -> ExprBuilder {
-        ExprBuilder {
-            flags: Flags::default(),
-            nest_limit: 200,
-        }
-    }
-
-    /// Set the default value for the case insensitive (`i`) flag.
-    pub fn case_insensitive(mut self, yes: bool) -> ExprBuilder {
-        self.flags.casei = yes;
-        self
-    }
-
-    /// Set the default value for the multi-line matching (`m`) flag.
-    pub fn multi_line(mut self, yes: bool) -> ExprBuilder {
-        self.flags.multi = yes;
-        self
-    }
-
-    /// Set the default value for the any character (`s`) flag.
-    pub fn dot_matches_new_line(mut self, yes: bool) -> ExprBuilder {
-        self.flags.dotnl = yes;
-        self
-    }
-
-    /// Set the default value for the greedy swap (`U`) flag.
-    pub fn swap_greed(mut self, yes: bool) -> ExprBuilder {
-        self.flags.swap_greed = yes;
-        self
-    }
-
-    /// Set the default value for the ignore whitespace (`x`) flag.
-    pub fn ignore_whitespace(mut self, yes: bool) -> ExprBuilder {
-        self.flags.ignore_space = yes;
-        self
-    }
-
-    /// Set the default value for the Unicode (`u`) flag.
-    ///
-    /// If `yes` is false, then `allow_bytes` is set to true.
-    pub fn unicode(mut self, yes: bool) -> ExprBuilder {
-        self.flags.unicode = yes;
-        if !yes {
-            self.allow_bytes(true)
-        } else {
-            self
-        }
-    }
-
-    /// Whether the parser allows matching arbitrary bytes or not.
-    ///
-    /// When the `u` flag is disabled (either with this builder or in the
-    /// expression itself), the parser switches to interpreting the expression
-    /// as matching arbitrary bytes instead of Unicode codepoints. For example,
-    /// the expression `(?u:\xFF)` matches the *codepoint* `\xFF`, which
-    /// corresponds to the UTF-8 byte sequence `\xCE\xBF`. Conversely,
-    /// `(?-u:\xFF)` matches the *byte* `\xFF`, which is not valid UTF-8.
-    ///
-    /// When `allow_bytes` is disabled (the default), an expression like
-    /// `(?-u:\xFF)` will cause the parser to return an error, since it would
-    /// otherwise match invalid UTF-8. When enabled, it will be allowed.
-    pub fn allow_bytes(mut self, yes: bool) -> ExprBuilder {
-        self.flags.allow_bytes = yes;
-        self
-    }
-
-    /// Set the nesting limit for regular expression parsing.
-    ///
-    /// Regular expressions that nest more than this limit will result in a
-    /// `StackExhausted` error.
-    pub fn nest_limit(mut self, limit: usize) -> ExprBuilder {
-        self.nest_limit = limit;
-        self
-    }
-
-    /// Parse a string as a regular expression using the current configuraiton.
-    pub fn parse(self, s: &str) -> Result<Expr> {
-        Parser::parse(s, self.flags).and_then(|e| e.simplify(self.nest_limit))
-    }
-}
-
-impl Expr {
-    /// Parses a string in a regular expression syntax tree.
-    ///
-    /// This is a convenience method for parsing an expression using the
-    /// default configuration. To tweak parsing options (such as which flags
-    /// are enabled by default), use the `ExprBuilder` type.
-    pub fn parse(s: &str) -> Result<Expr> {
-        ExprBuilder::new().parse(s)
-    }
-
-    /// Returns true iff the expression can be repeated by a quantifier.
-    fn can_repeat(&self) -> bool {
-        match *self {
-            Literal{..} | LiteralBytes{..}
-            | AnyChar | AnyCharNoNL | AnyByte | AnyByteNoNL
-            | Class(_) | ClassBytes(_)
-            | StartLine | EndLine | StartText | EndText
-            | WordBoundary | NotWordBoundary
-            | WordBoundaryAscii | NotWordBoundaryAscii
-            | Group{..}
-            => true,
-            _ => false,
-        }
-    }
-
-    fn simplify(self, nest_limit: usize) -> Result<Expr> {
-        fn combine_literals(es: &mut Vec<Expr>, e: Expr) {
-            match (es.pop(), e) {
-                (None, e) => es.push(e),
-                (Some(Literal { chars: mut chars1, casei: casei1 }),
-                      Literal { chars: chars2, casei: casei2 }) => {
-                    if casei1 == casei2 {
-                        chars1.extend(chars2);
-                        es.push(Literal { chars: chars1, casei: casei1 });
-                    } else {
-                        es.push(Literal { chars: chars1, casei: casei1 });
-                        es.push(Literal { chars: chars2, casei: casei2 });
-                    }
-                }
-                (Some(LiteralBytes { bytes: mut bytes1, casei: casei1 }),
-                      LiteralBytes { bytes: bytes2, casei: casei2 }) => {
-                    if casei1 == casei2 {
-                        bytes1.extend(bytes2);
-                        es.push(LiteralBytes { bytes: bytes1, casei: casei1 });
-                    } else {
-                        es.push(LiteralBytes { bytes: bytes1, casei: casei1 });
-                        es.push(LiteralBytes { bytes: bytes2, casei: casei2 });
-                    }
-                }
-                (Some(e1), e2) => {
-                    es.push(e1);
-                    es.push(e2);
-                }
-            }
-        }
-        fn simp(expr: Expr, recurse: usize, limit: usize) -> Result<Expr> {
-            if recurse > limit {
-                return Err(Error {
-                    pos: 0,
-                    surround: "".to_owned(),
-                    kind: ErrorKind::StackExhausted,
-                });
-            }
-            let simplify = |e| simp(e, recurse + 1, limit);
-            Ok(match expr {
-                Repeat { e, r, greedy } => Repeat {
-                    e: Box::new(try!(simplify(*e))),
-                    r: r,
-                    greedy: greedy,
-                },
-                Group { e, i, name } => {
-                    let e = try!(simplify(*e));
-                    if i.is_none() && name.is_none() && e.can_repeat() {
-                        e
-                    } else {
-                        Group { e: Box::new(e), i: i, name: name }
-                    }
-                }
-                Concat(es) => {
-                    let mut new_es = Vec::with_capacity(es.len());
-                    for e in es {
-                        combine_literals(&mut new_es, try!(simplify(e)));
-                    }
-                    if new_es.len() == 1 {
-                        new_es.pop().unwrap()
-                    } else {
-                        Concat(new_es)
-                    }
-                }
-                Alternate(es) => {
-                    let mut new_es = Vec::with_capacity(es.len());
-                    for e in es {
-                        new_es.push(try!(simplify(e)));
-                    }
-                    Alternate(new_es)
-                }
-                e => e,
-            })
-        }
-        simp(self, 0, nest_limit)
-    }
-
-    /// Returns a set of literal prefixes extracted from this expression.
-    pub fn prefixes(&self) -> Literals {
-        let mut lits = Literals::empty();
-        lits.union_prefixes(self);
-        lits
-    }
-
-    /// Returns a set of literal suffixes extracted from this expression.
-    pub fn suffixes(&self) -> Literals {
-        let mut lits = Literals::empty();
-        lits.union_suffixes(self);
-        lits
-    }
-
-    /// Returns true if and only if the expression is required to match from
-    /// the beginning of text.
-    pub fn is_anchored_start(&self) -> bool {
-        match *self {
-            Repeat { ref e, r, .. } => {
-                !r.matches_empty() && e.is_anchored_start()
-            }
-            Group { ref e, .. } => e.is_anchored_start(),
-            Concat(ref es) => es[0].is_anchored_start(),
-            Alternate(ref es) => es.iter().all(|e| e.is_anchored_start()),
-            StartText => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if and only if the expression has at least one matchable
-    /// sub-expression that must match the beginning of text.
-    pub fn has_anchored_start(&self) -> bool {
-        match *self {
-            Repeat { ref e, r, .. } => {
-                !r.matches_empty() && e.has_anchored_start()
-            }
-            Group { ref e, .. } => e.has_anchored_start(),
-            Concat(ref es) => es[0].has_anchored_start(),
-            Alternate(ref es) => es.iter().any(|e| e.has_anchored_start()),
-            StartText => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if and only if the expression is required to match at the
-    /// end of the text.
-    pub fn is_anchored_end(&self) -> bool {
-        match *self {
-            Repeat { ref e, r, .. } => {
-                !r.matches_empty() && e.is_anchored_end()
-            }
-            Group { ref e, .. } => e.is_anchored_end(),
-            Concat(ref es) => es[es.len() - 1].is_anchored_end(),
-            Alternate(ref es) => es.iter().all(|e| e.is_anchored_end()),
-            EndText => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if and only if the expression has at least one matchable
-    /// sub-expression that must match the beginning of text.
-    pub fn has_anchored_end(&self) -> bool {
-        match *self {
-            Repeat { ref e, r, .. } => {
-                !r.matches_empty() && e.has_anchored_end()
-            }
-            Group { ref e, .. } => e.has_anchored_end(),
-            Concat(ref es) => es[es.len() - 1].has_anchored_end(),
-            Alternate(ref es) => es.iter().any(|e| e.has_anchored_end()),
-            EndText => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if and only if the expression contains sub-expressions
-    /// that can match arbitrary bytes.
-    pub fn has_bytes(&self) -> bool {
-        match *self {
-            Repeat { ref e, .. } => e.has_bytes(),
-            Group { ref e, .. } => e.has_bytes(),
-            Concat(ref es) => es.iter().any(|e| e.has_bytes()),
-            Alternate(ref es) => es.iter().any(|e| e.has_bytes()),
-            LiteralBytes{..} => true,
-            AnyByte | AnyByteNoNL => true,
-            ClassBytes(_) => true,
-            WordBoundaryAscii | NotWordBoundaryAscii => true,
-            _ => false,
-        }
-    }
-}
-
-impl Deref for CharClass {
-    type Target = Vec<ClassRange>;
-    fn deref(&self) -> &Vec<ClassRange> { &self.ranges }
-}
-
-impl IntoIterator for CharClass {
-    type Item = ClassRange;
-    type IntoIter = vec::IntoIter<ClassRange>;
-    fn into_iter(self) -> vec::IntoIter<ClassRange> { self.ranges.into_iter() }
-}
-
-impl<'a> IntoIterator for &'a CharClass {
-    type Item = &'a ClassRange;
-    type IntoIter = slice::Iter<'a, ClassRange>;
-    fn into_iter(self) -> slice::Iter<'a, ClassRange> { self.iter() }
-}
-
-impl CharClass {
-    /// Create a new class from an existing set of ranges.
-    pub fn new(ranges: Vec<ClassRange>) -> CharClass {
-        CharClass { ranges: ranges }
-    }
-
-    /// Create an empty class.
-    fn empty() -> CharClass {
-        CharClass::new(Vec::new())
-    }
-
-    /// Returns true if `c` is matched by this character class.
-    pub fn matches(&self, c: char) -> bool {
-        self.binary_search_by(|range| c.partial_cmp(range).unwrap()).is_ok()
-    }
-
-    /// Removes the given character from the class if it exists.
-    ///
-    /// Note that this takes `O(n)` time in the number of ranges.
-    pub fn remove(&mut self, c: char) {
-        let mut i = match self.binary_search_by(|r| c.partial_cmp(r).unwrap()) {
-            Ok(i) => i,
-            Err(_) => return,
-        };
-        let mut r = self.ranges.remove(i);
-        if r.start == c {
-            r.start = inc_char(c);
-            if r.start > r.end || c == char::MAX {
-                return;
-            }
-            self.ranges.insert(i, r);
-        } else if r.end == c {
-            r.end = dec_char(c);
-            if r.end < r.start || c == '\x00' {
-                return;
-            }
-            self.ranges.insert(0, r);
-        } else {
-            let (mut r1, mut r2) = (r.clone(), r.clone());
-            r1.end = dec_char(c);
-            if r1.start <= r1.end {
-                self.ranges.insert(i, r1);
-                i += 1;
-            }
-            r2.start = inc_char(c);
-            if r2.start <= r2.end {
-                self.ranges.insert(i, r2);
-            }
-        }
-    }
-
-    /// Create a new empty class from this one.
-    fn to_empty(&self) -> CharClass {
-        CharClass { ranges: Vec::with_capacity(self.len()) }
-    }
-
-    /// Create a byte class from this character class.
-    ///
-    /// Codepoints above 0xFF are removed.
-    fn to_byte_class(self) -> ByteClass {
-        ByteClass::new(
-            self.ranges.into_iter()
-                       .filter_map(|r| r.to_byte_range())
-                       .collect()).canonicalize()
-    }
-
-    /// Merge two classes and canonicalize them.
-    #[cfg(test)]
-    fn merge(mut self, other: CharClass) -> CharClass {
-        self.ranges.extend(other);
-        self.canonicalize()
-    }
-
-    /// Canonicalize any sequence of ranges.
-    ///
-    /// This is responsible for enforcing the canonical format invariants
-    /// as described on the docs for the `CharClass` type.
-    fn canonicalize(mut self) -> CharClass {
-        // TODO: Save some cycles here by checking if already canonicalized.
-        self.ranges.sort();
-        let mut ordered = self.to_empty(); // TODO: Do this in place?
-        for candidate in self {
-            // If the candidate overlaps with an existing range, then it must
-            // be the most recent range added because we process the candidates
-            // in order.
-            if let Some(or) = ordered.ranges.last_mut() {
-                if or.overlapping(candidate) {
-                    *or = or.merge(candidate);
-                    continue;
-                }
-            }
-            ordered.ranges.push(candidate);
-        }
-        ordered
-    }
-
-    /// Calculate the intersection of two canonical character classes.
-    ///
-    /// The returned intersection is canonical.
-    fn intersection(&self, other: &CharClass) -> CharClass {
-        if self.ranges.is_empty() || other.ranges.is_empty() {
-            return CharClass::empty();
-        }
-
-        let mut intersection = CharClass::empty();
-
-        let mut iter_a = self.ranges.iter();
-        let mut iter_b = other.ranges.iter();
-        let mut a = iter_a.next().unwrap();
-        let mut b = iter_b.next().unwrap();
-        loop {
-            if let Some(i) = a.intersection(&b) {
-                intersection.ranges.push(i);
-            }
-
-            // If the range with the smaller end didn't match this time,
-            // it won't ever match, so move on to the next one.
-            let (iter, item) = if a.end < b.end {
-                (&mut iter_a, &mut a)
-            } else {
-                (&mut iter_b, &mut b)
-            };
-            match iter.next() {
-                Some(v) => *item = v,
-                None => break, // no more ranges to check, done
-            }
-        }
-
-        intersection.canonicalize()
-    }
-
-    /// Negates the character class.
-    ///
-    /// For all `c` where `c` is a Unicode scalar value, `c` matches `self`
-    /// if and only if `c` does not match `self.negate()`.
-    pub fn negate(mut self) -> CharClass {
-        fn range(s: char, e: char) -> ClassRange { ClassRange::new(s, e) }
-
-        if self.is_empty() {
-            // Inverting an empty range yields all of Unicode.
-            return CharClass {
-                ranges: vec![ClassRange { start: '\x00', end: '\u{10ffff}' }],
-            };
-        }
-        self = self.canonicalize();
-        let mut inv = self.to_empty();
-        if self[0].start > '\x00' {
-            inv.ranges.push(range('\x00', dec_char(self[0].start)));
-        }
-        for win in self.windows(2) {
-            inv.ranges.push(range(inc_char(win[0].end),
-                                  dec_char(win[1].start)));
-        }
-        if self[self.len() - 1].end < char::MAX {
-            inv.ranges.push(range(inc_char(self[self.len() - 1].end),
-                                  char::MAX));
-        }
-        inv
-    }
 
-    /// Apply case folding to this character class.
-    ///
-    /// N.B. Applying case folding to a negated character class probably
-    /// won't produce the expected result. e.g., `(?i)[^x]` really should
-    /// match any character sans `x` and `X`, but if `[^x]` is negated
-    /// before being case folded, you'll end up matching any character.
-    pub fn case_fold(self) -> CharClass {
-        let mut folded = self.to_empty();
-        for r in self {
-            // Applying case folding to a range is expensive because *every*
-            // character needs to be examined. Thus, we avoid that drudgery
-            // if no character in the current range is in our case folding
-            // table.
-            if r.needs_case_folding() {
-                folded.ranges.extend(r.case_fold());
-            }
-            folded.ranges.push(r);
-        }
-        folded.canonicalize()
-    }
 
-    /// Returns the number of characters that match this class.
-    fn num_chars(&self) -> usize {
-        self.ranges.iter()
-            .map(|&r| 1 + (r.end as u32) - (r.start as u32))
-            .fold(0, |acc, len| acc + len)
-            as usize
-    }
-}
+# Concrete syntax supported
 
-impl ClassRange {
-    /// Create a new class range.
-    ///
-    /// If `end < start`, then the two values are swapped so that
-    /// the invariant `start <= end` is preserved.
-    fn new(start: char, end: char) -> ClassRange {
-        if start <= end {
-            ClassRange { start: start, end: end }
-        } else {
-            ClassRange { start: end, end: start }
-        }
-    }
+The concrete syntax is documented as part of the public API of the
+[`regex` crate](https://docs.rs/regex/%2A/regex/#syntax).
 
-    /// Translate this to a byte class.
-    ///
-    /// If the start codepoint exceeds 0xFF, then this returns `None`.
-    ///
-    /// If the end codepoint exceeds 0xFF, then it is set to 0xFF.
-    fn to_byte_range(self) -> Option<ByteRange> {
-        if self.start > '\u{FF}' {
-            None
-        } else {
-            let s = self.start as u8;
-            let e = min('\u{FF}', self.end) as u8;
-            Some(ByteRange::new(s, e))
-        }
-    }
 
-    /// Create a range of one character.
-    fn one(c: char) -> ClassRange {
-        ClassRange { start: c, end: c }
-    }
+# Input safety
 
-    /// Returns true if and only if the two ranges are overlapping. Note that
-    /// since ranges are inclusive, `a-c` and `d-f` are overlapping!
-    fn overlapping(self, other: ClassRange) -> bool {
-        max(self.start, other.start) <= inc_char(min(self.end, other.end))
-    }
+A key feature of this library is that it is safe to use with end user facing
+input. This plays a significant role in the internal implementation. In
+particular:
 
-    /// Returns the intersection of the two ranges if they have common
-    /// characters, `None` otherwise.
-    fn intersection(&self, other: &ClassRange) -> Option<ClassRange> {
-        let start = max(self.start, other.start);
-        let end = min(self.end, other.end);
-        if start <= end {
-            Some(ClassRange::new(start, end))
-        } else {
-            None
-        }
-    }
+1. Parsers provide a `nest_limit` option that permits callers to control how
+   deeply nested a regular expression is allowed to be. This makes it possible
+   to do case analysis over an `Ast` or an `Hir` using recursion without
+   worrying about stack overflow.
+2. Since relying on a particular stack size is brittle, this crate goes to
+   great lengths to ensure that all interactions with both the `Ast` and the
+   `Hir` do not use recursion. Namely, they use constant stack space and heap
+   space proportional to the size of the original pattern string (in bytes).
+   This includes the type's corresponding destructors. (One exception to this
+   is literal extraction, but this will eventually get fixed.)
 
-    /// Creates a new range representing the union of `self` and `other.
-    fn merge(self, other: ClassRange) -> ClassRange {
-        ClassRange {
-            start: min(self.start, other.start),
-            end: max(self.end, other.end),
-        }
-    }
 
-    /// Returns true if and only if this range contains a character that is
-    /// in the case folding table.
-    fn needs_case_folding(self) -> bool {
-        case_folding::C_plus_S_both_table
-        .binary_search_by(|&(c, _)| self.partial_cmp(&c).unwrap()).is_ok()
-    }
+# Error reporting
 
-    /// Apply case folding to this range.
-    ///
-    /// Since case folding might add characters such that the range is no
-    /// longer contiguous, this returns multiple class ranges. They are in
-    /// canonical order.
-    fn case_fold(self) -> Vec<ClassRange> {
-        let table = &case_folding::C_plus_S_both_table;
-        let (s, e) = (self.start as u32, self.end as u32 + 1);
-        let mut start = self.start;
-        let mut end = start;
-        let mut next_case_fold = '\x00';
-        let mut ranges = Vec::with_capacity(10);
-        for mut c in (s..e).filter_map(char::from_u32) {
-            if c >= next_case_fold {
-                c = match simple_case_fold_both_result(c) {
-                    Ok(i) => {
-                        for &(c1, c2) in &table[i..] {
-                            if c1 != c {
-                                break;
-                            }
-                            if c2 != inc_char(end) {
-                                ranges.push(ClassRange::new(start, end));
-                                start = c2;
-                            }
-                            end = c2;
-                        }
-                        continue;
-                    }
-                    Err(i) => {
-                        if i < table.len() {
-                            next_case_fold = table[i].0;
-                        } else {
-                            next_case_fold = '\u{10FFFF}';
-                        }
-                        c
-                    }
-                };
-            }
-            // The fast path. We know this character doesn't have an entry
-            // in the case folding table.
-            if c != inc_char(end) {
-                ranges.push(ClassRange::new(start, end));
-                start = c;
-            }
-            end = c;
-        }
-        ranges.push(ClassRange::new(start, end));
-        ranges
-    }
-}
+The `Display` implementations on all `Error` types exposed in this library
+provide nice human readable errors that are suitable for showing to end users
+in a monospace font.
 
-impl PartialEq<char> for ClassRange {
-    #[inline]
-    fn eq(&self, other: &char) -> bool {
-        self.start <= *other && *other <= self.end
-    }
-}
 
-impl PartialEq<ClassRange> for char {
-    #[inline]
-    fn eq(&self, other: &ClassRange) -> bool {
-        other.eq(self)
-    }
-}
+# Literal extraction
 
-impl PartialOrd<char> for ClassRange {
-    #[inline]
-    fn partial_cmp(&self, other: &char) -> Option<Ordering> {
-        Some(if self == other {
-            Ordering::Equal
-        } else if *other > self.end {
-            Ordering::Greater
-        } else {
-            Ordering::Less
-        })
-    }
-}
+This crate provides limited support for
+[literal extraction from `Hir` values](hir/literal/struct.Literals.html).
+Be warned that literal extraction currently uses recursion, and therefore,
+stack size proportional to the size of the `Hir`.
 
-impl PartialOrd<ClassRange> for char {
-    #[inline]
-    fn partial_cmp(&self, other: &ClassRange) -> Option<Ordering> {
-        other.partial_cmp(self).map(|o| o.reverse())
-    }
-}
-
-impl ByteClass {
-    /// Create a new class from an existing set of ranges.
-    pub fn new(ranges: Vec<ByteRange>) -> ByteClass {
-        ByteClass { ranges: ranges }
-    }
-
-    /// Returns true if `b` is matched by this byte class.
-    pub fn matches(&self, b: u8) -> bool {
-        self.binary_search_by(|range| b.partial_cmp(range).unwrap()).is_ok()
-    }
-
-    /// Removes the given byte from the class if it exists.
-    ///
-    /// Note that this takes `O(n)` time in the number of ranges.
-    pub fn remove(&mut self, b: u8) {
-        let mut i = match self.binary_search_by(|r| b.partial_cmp(r).unwrap()) {
-            Ok(i) => i,
-            Err(_) => return,
-        };
-        let mut r = self.ranges.remove(i);
-        if r.start == b {
-            r.start = b.saturating_add(1);
-            if r.start > r.end || b == u8::MAX {
-                return;
-            }
-            self.ranges.insert(i, r);
-        } else if r.end == b {
-            r.end = b.saturating_sub(1);
-            if r.end < r.start || b == b'\x00' {
-                return;
-            }
-            self.ranges.insert(0, r);
-        } else {
-            let (mut r1, mut r2) = (r.clone(), r.clone());
-            r1.end = b.saturating_sub(1);
-            if r1.start <= r1.end {
-                self.ranges.insert(i, r1);
-                i += 1;
-            }
-            r2.start = b.saturating_add(1);
-            if r2.start <= r2.end {
-                self.ranges.insert(i, r2);
-            }
-        }
-    }
-
-    /// Create a new empty class from this one.
-    fn to_empty(&self) -> ByteClass {
-        ByteClass { ranges: Vec::with_capacity(self.len()) }
-    }
-
-    /// Canonicalze any sequence of ranges.
-    ///
-    /// This is responsible for enforcing the canonical format invariants
-    /// as described on the docs for the `ByteClass` type.
-    fn canonicalize(mut self) -> ByteClass {
-        // TODO: Save some cycles here by checking if already canonicalized.
-        self.ranges.sort();
-        let mut ordered = self.to_empty(); // TODO: Do this in place?
-        for candidate in self {
-            // If the candidate overlaps with an existing range, then it must
-            // be the most recent range added because we process the candidates
-            // in order.
-            if let Some(or) = ordered.ranges.last_mut() {
-                if or.overlapping(candidate) {
-                    *or = or.merge(candidate);
-                    continue;
-                }
-            }
-            ordered.ranges.push(candidate);
-        }
-        ordered
-    }
-
-    /// Negates the byte class.
-    ///
-    /// For all `b` where `b` is a byte, `b` matches `self` if and only if `b`
-    /// does not match `self.negate()`.
-    pub fn negate(mut self) -> ByteClass {
-        fn range(s: u8, e: u8) -> ByteRange { ByteRange::new(s, e) }
-
-        if self.is_empty() {
-            // Inverting an empty range yields all bytes.
-            return ByteClass {
-                ranges: vec![ByteRange { start: b'\x00', end: b'\xff' }],
-            };
-        }
-        self = self.canonicalize();
-        let mut inv = self.to_empty();
-        if self[0].start > b'\x00' {
-            inv.ranges.push(range(b'\x00', self[0].start.saturating_sub(1)));
-        }
-        for win in self.windows(2) {
-            inv.ranges.push(range(win[0].end.saturating_add(1),
-                                  win[1].start.saturating_sub(1)));
-        }
-        if self[self.len() - 1].end < u8::MAX {
-            inv.ranges.push(range(self[self.len() - 1].end.saturating_add(1),
-                                  u8::MAX));
-        }
-        inv
-    }
-
-    /// Apply case folding to this byte class.
-    ///
-    /// This assumes that the bytes in the ranges are ASCII compatible.
-    ///
-    /// N.B. Applying case folding to a negated character class probably
-    /// won't produce the expected result. e.g., `(?i)[^x]` really should
-    /// match any character sans `x` and `X`, but if `[^x]` is negated
-    /// before being case folded, you'll end up matching any character.
-    pub fn case_fold(self) -> ByteClass {
-        let mut folded = self.to_empty();
-        for r in self {
-            folded.ranges.extend(r.case_fold());
-        }
-        folded.canonicalize()
-    }
-
-    /// Returns the number of bytes that match this class.
-    fn num_bytes(&self) -> usize {
-        self.ranges.iter()
-            .map(|&r| 1 + (r.end as u32) - (r.start as u32))
-            .fold(0, |acc, len| acc + len)
-            as usize
-    }
-}
-
-impl ByteRange {
-    /// Create a new class range.
-    ///
-    /// If `end < start`, then the two values are swapped so that
-    /// the invariant `start <= end` is preserved.
-    fn new(start: u8, end: u8) -> ByteRange {
-        if start <= end {
-            ByteRange { start: start, end: end }
-        } else {
-            ByteRange { start: end, end: start }
-        }
-    }
-
-    /// Returns true if and only if the two ranges are overlapping. Note that
-    /// since ranges are inclusive, `a-c` and `d-f` are overlapping!
-    fn overlapping(self, other: ByteRange) -> bool {
-        max(self.start, other.start)
-        <= min(self.end, other.end).saturating_add(1)
-    }
-
-    /// Returns true if and only if the intersection of self and other is non
-    /// empty.
-    fn is_intersect_empty(self, other: ByteRange) -> bool {
-        max(self.start, other.start) > min(self.end, other.end)
-    }
-
-    /// Creates a new range representing the union of `self` and `other.
-    fn merge(self, other: ByteRange) -> ByteRange {
-        ByteRange {
-            start: min(self.start, other.start),
-            end: max(self.end, other.end),
-        }
-    }
-
-    /// Apply case folding to this range.
-    ///
-    /// Since case folding might add bytes such that the range is no
-    /// longer contiguous, this returns multiple byte ranges.
-    ///
-    /// This assumes that the bytes in this range are ASCII compatible.
-    fn case_fold(self) -> Vec<ByteRange> {
-        // So much easier than Unicode case folding!
-        let mut ranges = vec![self];
-        if !ByteRange::new(b'a', b'z').is_intersect_empty(self) {
-            let lower = max(self.start, b'a');
-            let upper = min(self.end, b'z');
-            ranges.push(ByteRange::new(lower - 32, upper - 32));
-        }
-        if !ByteRange::new(b'A', b'Z').is_intersect_empty(self) {
-            let lower = max(self.start, b'A');
-            let upper = min(self.end, b'Z');
-            ranges.push(ByteRange::new(lower + 32, upper + 32));
-        }
-        ranges
-    }
-}
-
-impl Deref for ByteClass {
-    type Target = Vec<ByteRange>;
-    fn deref(&self) -> &Vec<ByteRange> { &self.ranges }
-}
-
-impl IntoIterator for ByteClass {
-    type Item = ByteRange;
-    type IntoIter = vec::IntoIter<ByteRange>;
-    fn into_iter(self) -> vec::IntoIter<ByteRange> { self.ranges.into_iter() }
-}
-
-impl<'a> IntoIterator for &'a ByteClass {
-    type Item = &'a ByteRange;
-    type IntoIter = slice::Iter<'a, ByteRange>;
-    fn into_iter(self) -> slice::Iter<'a, ByteRange> { self.iter() }
-}
-
-impl PartialEq<u8> for ByteRange {
-    #[inline]
-    fn eq(&self, other: &u8) -> bool {
-        self.start <= *other && *other <= self.end
-    }
-}
-
-impl PartialEq<ByteRange> for u8 {
-    #[inline]
-    fn eq(&self, other: &ByteRange) -> bool {
-        other.eq(self)
-    }
-}
-
-impl PartialOrd<u8> for ByteRange {
-    #[inline]
-    fn partial_cmp(&self, other: &u8) -> Option<Ordering> {
-        Some(if self == other {
-            Ordering::Equal
-        } else if *other > self.end {
-            Ordering::Greater
-        } else {
-            Ordering::Less
-        })
-    }
-}
-
-impl PartialOrd<ByteRange> for u8 {
-    #[inline]
-    fn partial_cmp(&self, other: &ByteRange) -> Option<Ordering> {
-        other.partial_cmp(self).map(|o| o.reverse())
-    }
-}
-
-/// This implementation of `Display` will write a regular expression from the
-/// syntax tree. It does not write the original string parsed.
-impl fmt::Display for Expr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Empty => write!(f, ""),
-            Literal { ref chars, casei } => {
-                if casei {
-                    try!(write!(f, "(?iu:"));
-                } else {
-                    try!(write!(f, "(?u:"));
-                }
-                for &c in chars {
-                    try!(write!(f, "{}", quote_char(c)));
-                }
-                try!(write!(f, ")"));
-                Ok(())
-            }
-            LiteralBytes { ref bytes, casei } => {
-                if casei {
-                    try!(write!(f, "(?i-u:"));
-                } else {
-                    try!(write!(f, "(?-u:"));
-                }
-                for &b in bytes {
-                    try!(write!(f, "{}", quote_byte(b)));
-                }
-                try!(write!(f, ")"));
-                Ok(())
-            }
-            AnyChar => write!(f, "(?su:.)"),
-            AnyCharNoNL => write!(f, "(?u:.)"),
-            AnyByte => write!(f, "(?s-u:.)"),
-            AnyByteNoNL => write!(f, "(?-u:.)"),
-            Class(ref cls) => write!(f, "{}", cls),
-            ClassBytes(ref cls) => write!(f, "{}", cls),
-            StartLine => write!(f, "(?m:^)"),
-            EndLine => write!(f, "(?m:$)"),
-            StartText => write!(f, r"^"),
-            EndText => write!(f, r"$"),
-            WordBoundary => write!(f, r"(?u:\b)"),
-            NotWordBoundary => write!(f, r"(?u:\B)"),
-            WordBoundaryAscii => write!(f, r"(?-u:\b)"),
-            NotWordBoundaryAscii => write!(f, r"(?-u:\B)"),
-            Group { ref e, i: None, name: None } => write!(f, "(?:{})", e),
-            Group { ref e, name: None, .. } => write!(f, "({})", e),
-            Group { ref e, name: Some(ref n), .. } => {
-                write!(f, "(?P<{}>{})", n, e)
-            }
-            Repeat { ref e, r, greedy } => {
-                match &**e {
-                    &Literal { ref chars, .. } if chars.len() > 1 => {
-                        try!(write!(f, "(?:{}){}", e, r))
-                    }
-                    _ => try!(write!(f, "{}{}", e, r)),
-                }
-                if !greedy { try!(write!(f, "?")); }
-                Ok(())
-            }
-            Concat(ref es) => {
-                for e in es {
-                    try!(write!(f, "{}", e));
-                }
-                Ok(())
-            }
-            Alternate(ref es) => {
-                for (i, e) in es.iter().enumerate() {
-                    if i > 0 { try!(write!(f, "|")); }
-                    try!(write!(f, "{}", e));
-                }
-                Ok(())
-            }
-        }
-    }
-}
-
-impl fmt::Display for Repeater {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            ZeroOrOne => write!(f, "?"),
-            ZeroOrMore => write!(f, "*"),
-            OneOrMore => write!(f, "+"),
-            Range { min: s, max: None } => write!(f, "{{{},}}", s),
-            Range { min: s, max: Some(e) } if s == e => write!(f, "{{{}}}", s),
-            Range { min: s, max: Some(e) } => write!(f, "{{{}, {}}}", s, e),
-        }
-    }
-}
-
-impl fmt::Display for CharClass {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "(?u:["));
-        for range in self.iter() {
-            if range.start == '-' || range.end == '-' {
-                try!(write!(f, "-"));
-                break;
-            }
-        }
-        for range in self.iter() {
-            let mut range = *range;
-            if range.start == '-' {
-                range.start = ((range.start as u8) + 1) as char;
-            }
-            if range.end == '-' {
-                range.end = ((range.end as u8) - 1) as char;
-            }
-            if range.start > range.end {
-                continue;
-            }
-            try!(write!(f, "{}", range));
-        }
-        try!(write!(f, "])"));
-        Ok(())
-    }
-}
-
-impl fmt::Display for ClassRange {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}-{}", quote_char(self.start), quote_char(self.end))
-    }
-}
-
-impl fmt::Display for ByteClass {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "(?-u:["));
-        for range in self.iter() {
-            if range.start == b'-' || range.end == b'-' {
-                try!(write!(f, "-"));
-                break;
-            }
-        }
-        for range in self.iter() {
-            let mut range = *range;
-            if range.start == b'-' {
-                range.start += 1;
-            }
-            if range.end == b'-' {
-                range.start -= 1;
-            }
-            if range.start > range.end {
-                continue;
-            }
-            try!(write!(f, "{}", range));
-        }
-        try!(write!(f, "])"));
-        Ok(())
-    }
-}
-
-impl fmt::Display for ByteRange {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}-{}", quote_byte(self.start), quote_byte(self.end))
-    }
-}
-
-/// An alias for computations that can return a `Error`.
-pub type Result<T> = ::std::result::Result<T, Error>;
-
-/// A parse error.
-///
-/// This includes details about the specific type of error and a rough
-/// approximation of where it occurred.
-#[derive(Clone, Debug, PartialEq)]
-pub struct Error {
-    pos: usize,
-    surround: String,
-    kind: ErrorKind,
-}
-
-/// The specific type of parse error that can occur.
-#[derive(Clone, Debug, PartialEq)]
-pub enum ErrorKind {
-    /// A negation symbol is used twice in flag settings.
-    /// e.g., `(?-i-s)`.
-    DoubleFlagNegation,
-    /// The same capture name was used more than once.
-    /// e.g., `(?P<a>.)(?P<a>.)`.
-    DuplicateCaptureName(String),
-    /// An alternate is empty. e.g., `(|a)`.
-    EmptyAlternate,
-    /// A capture group name is empty. e.g., `(?P<>a)`.
-    EmptyCaptureName,
-    /// A negation symbol was not proceded by any flags. e.g., `(?i-)`.
-    EmptyFlagNegation,
-    /// A group is empty. e.g., `()`.
-    EmptyGroup,
-    /// An invalid number was used in a counted repetition. e.g., `a{b}`.
-    InvalidBase10(String),
-    /// An invalid hexadecimal number was used in an escape sequence.
-    /// e.g., `\xAG`.
-    InvalidBase16(String),
-    /// An invalid capture name was used. e.g., `(?P<0a>b)`.
-    InvalidCaptureName(String),
-    /// An invalid class range was givien. Specifically, when the start of the
-    /// range is greater than the end. e.g., `[z-a]`.
-    InvalidClassRange {
-        /// The first character specified in the range.
-        start: char,
-        /// The second character specified in the range.
-        end: char,
-    },
-    /// An escape sequence was used in a character class where it is not
-    /// allowed. e.g., `[a-\pN]` or `[\A]`.
-    InvalidClassEscape(Expr),
-    /// An invalid counted repetition min/max was given. e.g., `a{2,1}`.
-    InvalidRepeatRange {
-        /// The first number specified in the repetition.
-        min: u32,
-        /// The second number specified in the repetition.
-        max: u32,
-    },
-    /// An invalid Unicode scalar value was used in a long hexadecimal
-    /// sequence. e.g., `\x{D800}`.
-    InvalidScalarValue(u32),
-    /// An empty counted repetition operator. e.g., `a{}`.
-    MissingBase10,
-    /// A repetition operator was not applied to an expression. e.g., `*`.
-    RepeaterExpectsExpr,
-    /// A repetition operator was applied to an expression that cannot be
-    /// repeated. e.g., `a+*` or `a|*`.
-    RepeaterUnexpectedExpr(Expr),
-    /// A capture group name that is never closed. e.g., `(?P<a`.
-    UnclosedCaptureName(String),
-    /// An unclosed hexadecimal literal. e.g., `\x{a`.
-    UnclosedHex,
-    /// An unclosed parenthesis. e.g., `(a`.
-    UnclosedParen,
-    /// An unclosed counted repetition operator. e.g., `a{2`.
-    UnclosedRepeat,
-    /// An unclosed named Unicode class. e.g., `\p{Yi`.
-    UnclosedUnicodeName,
-    /// Saw end of regex before class was closed. e.g., `[a`.
-    UnexpectedClassEof,
-    /// Saw end of regex before escape sequence was closed. e.g., `\`.
-    UnexpectedEscapeEof,
-    /// Saw end of regex before flags were closed. e.g., `(?i`.
-    UnexpectedFlagEof,
-    /// Saw end of regex before two hexadecimal digits were seen. e.g., `\xA`.
-    UnexpectedTwoDigitHexEof,
-    /// Unopened parenthesis. e.g., `)`.
-    UnopenedParen,
-    /// Unrecognized escape sequence. e.g., `\q`.
-    UnrecognizedEscape(char),
-    /// Unrecognized flag. e.g., `(?a)`.
-    UnrecognizedFlag(char),
-    /// Unrecognized named Unicode class. e.g., `\p{Foo}`.
-    UnrecognizedUnicodeClass(String),
-    /// Indicates that the regex uses too much nesting.
-    ///
-    /// (N.B. This error exists because traversing the Expr is recursive and
-    /// an explicit heap allocated stack is not (yet?) used. Regardless, some
-    /// sort of limit must be applied to avoid unbounded memory growth.
-    StackExhausted,
-    /// A disallowed flag was found (e.g., `u`).
-    FlagNotAllowed(char),
-    /// A Unicode class was used when the Unicode (`u`) flag was disabled.
-    UnicodeNotAllowed,
-    /// InvalidUtf8 indicates that the expression may match non-UTF-8 bytes.
-    /// This never returned if the parser is permitted to allow expressions
-    /// that match arbitrary bytes.
-    InvalidUtf8,
-    /// A character class was constructed such that it is empty.
-    /// e.g., `[^\d\D]`.
-    EmptyClass,
-    /// Indicates that unsupported notation was used in a character class.
-    ///
-    /// The char in this error corresponds to the illegal character.
-    ///
-    /// The intent of this error is to carve a path to support set notation
-    /// as described in UTS#18 RL1.3. We do this by rejecting regexes that
-    /// would use the notation.
-    ///
-    /// The work around for end users is to escape the character included in
-    /// this error message.
-    UnsupportedClassChar(char),
-    /// Hints that destructuring should not be exhaustive.
-    ///
-    /// This enum may grow additional variants, so this makes sure clients
-    /// don't count on exhaustive matching. (Otherwise, adding a new variant
-    /// could break existing code.)
-    #[doc(hidden)]
-    __Nonexhaustive,
-}
-
-impl Error {
-    /// Returns an approximate *character* offset at which the error occurred.
-    ///
-    /// The character offset may be equal to the number of characters in the
-    /// string, in which case it should be interpreted as pointing to the end
-    /// of the regex.
-    pub fn position(&self) -> usize {
-        self.pos
-    }
-
-    /// Returns the type of the regex parse error.
-    pub fn kind(&self) -> &ErrorKind {
-        &self.kind
-    }
-}
-
-impl ErrorKind {
-    fn description(&self) -> &str {
-        use ErrorKind::*;
-        match *self {
-            DoubleFlagNegation => "double flag negation",
-            DuplicateCaptureName(_) => "duplicate capture name",
-            EmptyAlternate => "empty alternate",
-            EmptyCaptureName => "empty capture name",
-            EmptyFlagNegation => "flag negation without any flags",
-            EmptyGroup => "empty group (e.g., '()')",
-            InvalidBase10(_) => "invalid base 10 number",
-            InvalidBase16(_) => "invalid base 16 number",
-            InvalidCaptureName(_) => "invalid capture name",
-            InvalidClassRange{..} => "invalid character class range",
-            InvalidClassEscape(_) => "invalid escape sequence in class",
-            InvalidRepeatRange{..} => "invalid counted repetition range",
-            InvalidScalarValue(_) => "invalid Unicode scalar value",
-            MissingBase10 => "missing count in repetition operator",
-            RepeaterExpectsExpr => "repetition operator missing expression",
-            RepeaterUnexpectedExpr(_) => "expression cannot be repeated",
-            UnclosedCaptureName(_) => "unclosed capture group name",
-            UnclosedHex => "unclosed hexadecimal literal",
-            UnclosedParen => "unclosed parenthesis",
-            UnclosedRepeat => "unclosed counted repetition operator",
-            UnclosedUnicodeName => "unclosed Unicode class literal",
-            UnexpectedClassEof => "unexpected EOF in character class",
-            UnexpectedEscapeEof => "unexpected EOF in escape sequence",
-            UnexpectedFlagEof => "unexpected EOF in flags",
-            UnexpectedTwoDigitHexEof => "unexpected EOF in hex literal",
-            UnopenedParen => "unopened parenthesis",
-            UnrecognizedEscape(_) => "unrecognized escape sequence",
-            UnrecognizedFlag(_) => "unrecognized flag",
-            UnrecognizedUnicodeClass(_) => "unrecognized Unicode class name",
-            StackExhausted => "stack exhausted, too much nesting",
-            FlagNotAllowed(_) => "flag not allowed",
-            UnicodeNotAllowed => "Unicode features not allowed",
-            InvalidUtf8 => "matching arbitrary bytes is not allowed",
-            EmptyClass => "empty character class",
-            UnsupportedClassChar(_) => "unsupported class notation",
-            __Nonexhaustive => unreachable!(),
-        }
-    }
-}
-
-impl ::std::error::Error for Error {
-    fn description(&self) -> &str {
-        self.kind.description()
-    }
-}
+The purpose of literal extraction is to speed up searches. That is, if you
+know a regular expression must match a prefix or suffix literal, then it is
+often quicker to search for instances of that literal, and then confirm or deny
+the match using the full regular expression engine. These optimizations are
+done automatically in the `regex` crate.
+*/
 
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let ErrorKind::StackExhausted = self.kind {
-            write!(f, "Error parsing regex: {}", self.kind)
-        } else {
-            write!(
-                f, "Error parsing regex near '{}' at character offset {}: {}",
-                self.surround, self.pos, self.kind)
-        }
-    }
-}
+#![deny(missing_docs)]
 
-impl fmt::Display for ErrorKind {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use ErrorKind::*;
-        match *self {
-            DoubleFlagNegation =>
-                write!(f, "Only one negation symbol is allowed in flags."),
-            DuplicateCaptureName(ref s) =>
-                write!(f, "Capture name '{}' is used more than once.", s),
-            EmptyAlternate =>
-                write!(f, "Alternations cannot be empty."),
-            EmptyCaptureName =>
-                write!(f, "Capture names cannot be empty."),
-            EmptyFlagNegation =>
-                write!(f, "Flag negation requires setting at least one flag."),
-            EmptyGroup =>
-                write!(f, "Empty regex groups (e.g., '()') are not allowed."),
-            InvalidBase10(ref s) =>
-                write!(f, "Not a valid base 10 number: '{}'", s),
-            InvalidBase16(ref s) =>
-                write!(f, "Not a valid base 16 number: '{}'", s),
-            InvalidCaptureName(ref s) =>
-                write!(f, "Invalid capture name: '{}'. Capture names must \
-                           consist of [_a-zA-Z0-9] and are not allowed to \
-                           start with with a number.", s),
-            InvalidClassRange { start, end } =>
-                write!(f, "Invalid character class range '{}-{}'. \
-                           Character class ranges must start with the smaller \
-                           character, but {} > {}", start, end, start, end),
-            InvalidClassEscape(ref e) =>
-                write!(f, "Invalid escape sequence in character \
-                           class: '{}'.", e),
-            InvalidRepeatRange { min, max } =>
-                write!(f, "Invalid counted repetition range: {{{}, {}}}. \
-                           Counted repetition ranges must start with the \
-                           minimum, but {} > {}", min, max, min, max),
-            InvalidScalarValue(c) =>
-                write!(f, "Number does not correspond to a Unicode scalar \
-                           value: '{}'.", c),
-            MissingBase10 =>
-                write!(f, "Missing maximum in counted
-repetition operator."),
-            RepeaterExpectsExpr =>
-                write!(f, "Missing expression for repetition operator."),
-            RepeaterUnexpectedExpr(ref e) =>
-                write!(f, "Invalid application of repetition operator to: \
-                          '{}'.", e),
-            UnclosedCaptureName(ref s) =>
-                write!(f, "Capture name group for '{}' is not closed. \
-                           (Missing a '>'.)", s),
-            UnclosedHex =>
-                write!(f, "Unclosed hexadecimal literal (missing a '}}')."),
-            UnclosedParen =>
-                write!(f, "Unclosed parenthesis."),
-            UnclosedRepeat =>
-                write!(f, "Unclosed counted repetition (missing a '}}')."),
-            UnclosedUnicodeName =>
-                write!(f, "Unclosed Unicode literal (missing a '}}')."),
-            UnexpectedClassEof =>
-                write!(f, "Character class was not closed before the end of \
-                           the regex (missing a ']')."),
-            UnexpectedEscapeEof =>
-                write!(f, "Started an escape sequence that didn't finish \
-                           before the end of the regex."),
-            UnexpectedFlagEof =>
-                write!(f, "Inline flag settings was not closed before the end \
-                           of the regex (missing a ')' or ':')."),
-            UnexpectedTwoDigitHexEof =>
-                write!(f, "Unexpected end of two digit hexadecimal literal."),
-            UnopenedParen =>
-                write!(f, "Unopened parenthesis."),
-            UnrecognizedEscape(c) =>
-                write!(f, "Unrecognized escape sequence: '\\{}'.", c),
-            UnrecognizedFlag(c) =>
-                write!(f, "Unrecognized flag: '{}'. \
-                           (Allowed flags: i, m, s, U, u, x.)", c),
-            UnrecognizedUnicodeClass(ref s) =>
-                write!(f, "Unrecognized Unicode class name: '{}'.", s),
-            StackExhausted =>
-                write!(f, "Exhausted space required to parse regex with too \
-                           much nesting."),
-            FlagNotAllowed(flag) =>
-                write!(f, "Use of the flag '{}' is not allowed.", flag),
-            UnicodeNotAllowed =>
-                write!(f, "Unicode features are not allowed when the Unicode \
-                           (u) flag is not set."),
-            InvalidUtf8 =>
-                write!(f, "Matching arbitrary bytes is not allowed."),
-            EmptyClass =>
-                write!(f, "Empty character classes are not allowed."),
-            UnsupportedClassChar(c) =>
-                write!(f, "Use of unescaped '{}' in character class is \
-                           not allowed.", c),
-            __Nonexhaustive => unreachable!(),
-        }
-    }
-}
+extern crate ucd_util;
 
-/// The result of binary search on the simple case folding table.
-///
-/// Note that this binary search is done on the "both" table, such that
-/// the index returned corresponds to the *first* location of `c1` in the
-/// table. The table can then be scanned linearly starting from the position
-/// returned to find other case mappings for `c1`.
-fn simple_case_fold_both_result(c1: char) -> result::Result<usize, usize> {
-    let table = &case_folding::C_plus_S_both_table;
-    let i = binary_search(table, |&(c2, _)| c1 <= c2);
-    if i >= table.len() || table[i].0 != c1 {
-        Err(i)
-    } else {
-        Ok(i)
-    }
-}
+pub use error::{Error, Result};
+pub use parser::{Parser, ParserBuilder};
 
-/// Binary search to find first element such that `pred(T) == true`.
-///
-/// Assumes that if `pred(xs[i]) == true` then `pred(xs[i+1]) == true`.
-///
-/// If all elements yield `pred(T) == false`, then `xs.len()` is returned.
-fn binary_search<T, F>(xs: &[T], mut pred: F) -> usize
-        where F: FnMut(&T) -> bool {
-    let (mut left, mut right) = (0, xs.len());
-    while left < right {
-        let mid = (left + right) / 2;
-        if pred(&xs[mid]) {
-            right = mid;
-        } else {
-            left = mid + 1;
-        }
-    }
-    left
-}
+pub mod ast;
+mod either;
+mod error;
+pub mod hir;
+mod parser;
+mod unicode;
+mod unicode_tables;
 
 /// Escapes all regular expression meta characters in `text`.
 ///
 /// The string returned may be safely used as a literal in a regular
 /// expression.
 pub fn escape(text: &str) -> String {
     let mut quoted = String::with_capacity(text.len());
-    for c in text.chars() {
-        if parser::is_punct(c) {
-            quoted.push('\\');
-        }
-        quoted.push(c);
-    }
+    escape_into(text, &mut quoted);
     quoted
 }
 
-fn quote_char(c: char) -> String {
-    let mut s = String::new();
-    if parser::is_punct(c) {
-        s.push('\\');
-    }
-    s.push(c);
-    s
-}
-
-fn quote_byte(b: u8) -> String {
-    if parser::is_punct(b as char) || b == b'\'' || b == b'"' {
-        quote_char(b as char)
-    } else {
-        let escaped: Vec<u8> = ascii::escape_default(b).collect();
-        String::from_utf8(escaped).unwrap()
+/// Escapes all meta characters in `text` and writes the result into `buf`.
+///
+/// This will append escape characters into the given buffer. The characters
+/// that are appended are safe to use as a literal in a regular expression.
+pub fn escape_into(text: &str, buf: &mut String) {
+    for c in text.chars() {
+        if is_meta_character(c) {
+            buf.push('\\');
+        }
+        buf.push(c);
     }
 }
 
-fn inc_char(c: char) -> char {
+/// Returns true if the give character has significance in a regex.
+///
+/// These are the only characters that are allowed to be escaped, with one
+/// exception: an ASCII space character may be escaped when extended mode (with
+/// the `x` flag) is enabld. In particular, `is_meta_character(' ')` returns
+/// `false`.
+///
+/// Note that the set of characters for which this function returns `true` or
+/// `false` is fixed and won't change in a semver compatible release.
+pub fn is_meta_character(c: char) -> bool {
     match c {
-        char::MAX => char::MAX,
-        '\u{D7FF}' => '\u{E000}',
-        c => char::from_u32(c as u32 + 1).unwrap(),
+        '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' |
+        '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~' => true,
+        _ => false,
     }
 }
 
-fn dec_char(c: char) -> char {
-    match c {
-        '\x00' => '\x00',
-        '\u{E000}' => '\u{D7FF}',
-        c => char::from_u32(c as u32 - 1).unwrap(),
-    }
-}
+/// Returns true if and only if the given character is a Unicode word
+/// character.
+///
+/// A Unicode word character is defined by
+/// [UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties).
+/// In particular, a character
+/// is considered a word character if it is in either of the `Alphabetic` or
+/// `Join_Control` properties, or is in one of the `Decimal_Number`, `Mark`
+/// or `Connector_Punctuation` general categories.
+pub fn is_word_character(c: char) -> bool {
+    use std::cmp::Ordering;
+    use unicode_tables::perl_word::PERL_WORD;
 
-/// Returns true if and only if `c` is a word character.
-#[doc(hidden)]
-pub fn is_word_char(c: char) -> bool {
-    match c {
-        '_' | '0' ... '9' | 'a' ... 'z' | 'A' ... 'Z'  => true,
-        _ => ::unicode::regex::PERLW.binary_search_by(|&(start, end)| {
-            if c >= start && c <= end {
+    if c <= 0x7F as char && is_word_byte(c as u8) {
+        return true;
+    }
+    PERL_WORD
+        .binary_search_by(|&(start, end)| {
+            if start <= c && c <= end {
                 Ordering::Equal
             } else if start > c {
                 Ordering::Greater
             } else {
                 Ordering::Less
             }
-        }).is_ok(),
-    }
+        }).is_ok()
 }
 
-/// Returns true if and only if `c` is an ASCII word byte.
-#[doc(hidden)]
-pub fn is_word_byte(b: u8) -> bool {
-    match b {
+/// Returns true if and only if the given character is an ASCII word character.
+///
+/// An ASCII word character is defined by the following character class:
+/// `[_0-9a-zA-Z]'.
+pub fn is_word_byte(c: u8) -> bool {
+    match c {
         b'_' | b'0' ... b'9' | b'a' ... b'z' | b'A' ... b'Z'  => true,
         _ => false,
     }
 }
 
-#[cfg(test)]
-mod properties;
-
 #[cfg(test)]
 mod tests {
-    use {CharClass, ClassRange, ByteClass, ByteRange, Expr};
-
-    fn class(ranges: &[(char, char)]) -> CharClass {
-        let ranges = ranges.iter().cloned()
-                           .map(|(c1, c2)| ClassRange::new(c1, c2)).collect();
-        CharClass::new(ranges)
-    }
-
-    fn bclass(ranges: &[(u8, u8)]) -> ByteClass {
-        let ranges = ranges.iter().cloned()
-                           .map(|(c1, c2)| ByteRange::new(c1, c2)).collect();
-        ByteClass::new(ranges)
-    }
-
-    fn e(re: &str) -> Expr { Expr::parse(re).unwrap() }
-
-    #[test]
-    fn stack_exhaustion() {
-        use std::iter::repeat;
-
-        let open: String = repeat('(').take(200).collect();
-        let close: String = repeat(')').take(200).collect();
-        assert!(Expr::parse(&format!("{}a{}", open, close)).is_ok());
-
-        let open: String = repeat('(').take(200 + 1).collect();
-        let close: String = repeat(')').take(200 + 1).collect();
-        assert!(Expr::parse(&format!("{}a{}", open, close)).is_err());
-    }
-
-    #[test]
-    fn anchored_start() {
-        assert!(e("^a").is_anchored_start());
-        assert!(e("(^a)").is_anchored_start());
-        assert!(e("^a|^b").is_anchored_start());
-        assert!(e("(^a)|(^b)").is_anchored_start());
-        assert!(e("(^(a|b))").is_anchored_start());
-
-        assert!(!e("^a|b").is_anchored_start());
-        assert!(!e("a|^b").is_anchored_start());
-    }
+    use super::*;
 
     #[test]
-    fn anchored_end() {
-        assert!(e("a$").is_anchored_end());
-        assert!(e("(a$)").is_anchored_end());
-        assert!(e("a$|b$").is_anchored_end());
-        assert!(e("(a$)|(b$)").is_anchored_end());
-        assert!(e("((a|b)$)").is_anchored_end());
-
-        assert!(!e("a$|b").is_anchored_end());
-        assert!(!e("a|b$").is_anchored_end());
+    fn escape_meta() {
+        assert_eq!(
+            escape(r"\.+*?()|[]{}^$#&-~"),
+            r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#\&\-\~".to_string());
     }
 
     #[test]
-    fn class_canon_no_change() {
-        let cls = class(&[('a', 'c'), ('x', 'z')]);
-        assert_eq!(cls.clone().canonicalize(), cls);
-    }
-
-    #[test]
-    fn class_canon_unordered() {
-        let cls = class(&[('x', 'z'), ('a', 'c')]);
-        assert_eq!(cls.canonicalize(), class(&[
-            ('a', 'c'), ('x', 'z'),
-        ]));
-    }
-
-    #[test]
-    fn class_canon_overlap() {
-        let cls = class(&[('x', 'z'), ('w', 'y')]);
-        assert_eq!(cls.canonicalize(), class(&[
-            ('w', 'z'),
-        ]));
-    }
-
-    #[test]
-    fn class_canon_overlap_many() {
-        let cls = class(&[
-            ('c', 'f'), ('a', 'g'), ('d', 'j'), ('a', 'c'),
-            ('m', 'p'), ('l', 's'),
-        ]);
-        assert_eq!(cls.clone().canonicalize(), class(&[
-            ('a', 'j'), ('l', 's'),
-        ]));
-    }
-
-    #[test]
-    fn class_canon_overlap_boundary() {
-        let cls = class(&[('x', 'z'), ('u', 'w')]);
-        assert_eq!(cls.canonicalize(), class(&[
-            ('u', 'z'),
-        ]));
-    }
-
-    #[test]
-    fn class_canon_extreme_edge_case() {
-        let cls = class(&[('\x00', '\u{10FFFF}'), ('\x00', '\u{10FFFF}')]);
-        assert_eq!(cls.canonicalize(), class(&[
-            ('\x00', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_canon_singles() {
-        let cls = class(&[('a', 'a'), ('b', 'b')]);
-        assert_eq!(cls.canonicalize(), class(&[('a', 'b')]));
-    }
-
-    #[test]
-    fn class_negate_single() {
-        let cls = class(&[('a', 'a')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\x60'), ('\x62', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_singles() {
-        let cls = class(&[('a', 'a'), ('b', 'b')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\x60'), ('\x63', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_multiples() {
-        let cls = class(&[('a', 'c'), ('x', 'z')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\x60'), ('\x64', '\x77'), ('\x7b', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_min_scalar() {
-        let cls = class(&[('\x00', 'a')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x62', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_max_scalar() {
-        let cls = class(&[('a', '\u{10FFFF}')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\x60'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_everything() {
-        let cls = class(&[('\x00', '\u{10FFFF}')]);
-        assert_eq!(cls.negate(), class(&[]));
-    }
-
-    #[test]
-    fn class_negate_everything_sans_one() {
-        let cls = class(&[
-            ('\x00', '\u{10FFFD}'), ('\u{10FFFF}', '\u{10FFFF}')
-        ]);
-        assert_eq!(cls.negate(), class(&[
-            ('\u{10FFFE}', '\u{10FFFE}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_surrogates_min() {
-        let cls = class(&[('\x00', '\u{D7FF}')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\u{E000}', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_surrogates_min_edge() {
-        let cls = class(&[('\x00', '\u{D7FE}')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\u{D7FF}', '\u{10FFFF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_surrogates_max() {
-        let cls = class(&[('\u{E000}', '\u{10FFFF}')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\u{D7FF}'),
-        ]));
-    }
-
-    #[test]
-    fn class_negate_surrogates_max_edge() {
-        let cls = class(&[('\u{E001}', '\u{10FFFF}')]);
-        assert_eq!(cls.negate(), class(&[
-            ('\x00', '\u{E000}'),
-        ]));
-    }
-
-    #[test]
-    fn class_intersection_empty() {
-        let cls1 = class(&[]);
-        let cls2 = class(&[('a', 'a')]);
-        assert_intersection(cls1, cls2, class(&[]));
-    }
-
-    #[test]
-    fn class_intersection_single_equal() {
-        let cls1 = class(&[('a', 'a')]);
-        let cls2 = class(&[('a', 'a')]);
-        assert_intersection(cls1, cls2, class(&[('a', 'a')]));
-    }
-
-    #[test]
-    fn class_intersection_single_unequal() {
-        let cls1 = class(&[('a', 'a')]);
-        let cls2 = class(&[('b', 'b')]);
-        assert_intersection(cls1, cls2, class(&[]));
-    }
-
-    #[test]
-    fn class_intersection_single_in_other() {
-        let cls1 = class(&[('a', 'a')]);
-        let cls2 = class(&[('a', 'c')]);
-        assert_intersection(cls1, cls2, class(&[('a', 'a')]));
-    }
-
-    #[test]
-    fn class_intersection_range_in_other() {
-        let cls1 = class(&[('a', 'b')]);
-        let cls2 = class(&[('a', 'c')]);
-        assert_intersection(cls1, cls2, class(&[('a', 'b')]));
-    }
-
-    #[test]
-    fn class_intersection_range_intersection() {
-        let cls1 = class(&[('a', 'b')]);
-        let cls2 = class(&[('b', 'c')]);
-        assert_intersection(cls1, cls2, class(&[('b', 'b')]));
-    }
-
-    #[test]
-    fn class_intersection_only_adjacent() {
-        let cls1 = class(&[('a', 'b')]);
-        let cls2 = class(&[('c', 'd')]);
-        assert_intersection(cls1, cls2, class(&[]));
-    }
-
-    #[test]
-    fn class_intersection_range_subset() {
-        let cls1 = class(&[('b', 'c')]);
-        let cls2 = class(&[('a', 'd')]);
-        assert_intersection(cls1, cls2, class(&[('b', 'c')]));
-    }
-
-    #[test]
-    fn class_intersection_many_ranges_in_one_big() {
-        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
-        let cls2 = class(&[('a', 'h')]);
-        assert_intersection(cls1, cls2, class(&[
-            ('a', 'b'), ('d', 'e'), ('g', 'h')
-        ]));
-    }
-
-    #[test]
-    fn class_intersection_many_ranges_same() {
-        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
-        let cls2 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
-        assert_intersection(cls1, cls2, class(&[
-            ('a', 'b'), ('d', 'e'), ('g', 'h')
-        ]));
-    }
-
-    #[test]
-    fn class_intersection_multiple_non_intersecting() {
-        let cls1 = class(&[('a', 'b'), ('g', 'h')]);
-        let cls2 = class(&[('d', 'e'), ('k', 'l')]);
-        assert_intersection(cls1, cls2, class(&[]));
-    }
-
-    #[test]
-    fn class_intersection_non_intersecting_then_intersecting() {
-        let cls1 = class(&[('a', 'b'), ('d', 'e'), ('g', 'h')]);
-        let cls2 = class(&[('h', 'h')]);
-        assert_intersection(cls1, cls2, class(&[('h', 'h')]));
-    }
-
-    #[test]
-    fn class_intersection_adjacent_alternating() {
-        let cls1 = class(&[('a', 'b'), ('e', 'f'), ('i', 'j')]);
-        let cls2 = class(&[('c', 'd'), ('g', 'h'), ('k', 'l')]);
-        assert_intersection(cls1, cls2, class(&[]));
-    }
-
-    #[test]
-    fn class_intersection_overlapping_alternating() {
-        let cls1 = class(&[('a', 'b'), ('c', 'd'), ('e', 'f')]);
-        let cls2 = class(&[('b', 'c'), ('d', 'e'), ('f', 'g')]);
-        assert_intersection(cls1, cls2, class(&[('b', 'f')]));
-    }
-
-    #[test]
-    fn class_canon_overlap_many_case_fold() {
-        let cls = class(&[
-            ('C', 'F'), ('A', 'G'), ('D', 'J'), ('A', 'C'),
-            ('M', 'P'), ('L', 'S'), ('c', 'f'),
-        ]);
-        assert_eq!(cls.case_fold(), class(&[
-            ('A', 'J'), ('L', 'S'),
-            ('a', 'j'), ('l', 's'),
-            ('\u{17F}', '\u{17F}'),
-        ]));
-
-        let cls = bclass(&[
-            (b'C', b'F'), (b'A', b'G'), (b'D', b'J'), (b'A', b'C'),
-            (b'M', b'P'), (b'L', b'S'), (b'c', b'f'),
-        ]);
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'A', b'J'), (b'L', b'S'),
-            (b'a', b'j'), (b'l', b's'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_az() {
-        let cls = class(&[('A', 'Z')]);
-        assert_eq!(cls.case_fold(), class(&[
-            ('A', 'Z'), ('a', 'z'),
-            ('\u{17F}', '\u{17F}'),
-            ('\u{212A}', '\u{212A}'),
-        ]));
-        let cls = class(&[('a', 'z')]);
-        assert_eq!(cls.case_fold(), class(&[
-            ('A', 'Z'), ('a', 'z'),
-            ('\u{17F}', '\u{17F}'),
-            ('\u{212A}', '\u{212A}'),
-        ]));
-
-        let cls = bclass(&[(b'A', b'Z')]);
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'A', b'Z'), (b'a', b'z'),
-        ]));
-        let cls = bclass(&[(b'a', b'z')]);
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'A', b'Z'), (b'a', b'z'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_a_underscore() {
-        let cls = class(&[('A', 'A'), ('_', '_')]);
-        assert_eq!(cls.clone().canonicalize(), class(&[
-            ('A', 'A'), ('_', '_'),
-        ]));
-        assert_eq!(cls.case_fold(), class(&[
-            ('A', 'A'), ('_', '_'), ('a', 'a'),
-        ]));
-
-        let cls = bclass(&[(b'A', b'A'), (b'_', b'_')]);
-        assert_eq!(cls.clone().canonicalize(), bclass(&[
-            (b'A', b'A'), (b'_', b'_'),
-        ]));
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'A', b'A'), (b'_', b'_'), (b'a', b'a'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_a_equals() {
-        let cls = class(&[('A', 'A'), ('=', '=')]);
-        assert_eq!(cls.clone().canonicalize(), class(&[
-            ('=', '='), ('A', 'A'),
-        ]));
-        assert_eq!(cls.case_fold(), class(&[
-            ('=', '='), ('A', 'A'), ('a', 'a'),
-        ]));
-
-        let cls = bclass(&[(b'A', b'A'), (b'=', b'=')]);
-        assert_eq!(cls.clone().canonicalize(), bclass(&[
-            (b'=', b'='), (b'A', b'A'),
-        ]));
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'=', b'='), (b'A', b'A'), (b'a', b'a'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_no_folding_needed() {
-        let cls = class(&[('\x00', '\x10')]);
-        assert_eq!(cls.case_fold(), class(&[
-            ('\x00', '\x10'),
-        ]));
-
-        let cls = bclass(&[(b'\x00', b'\x10')]);
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'\x00', b'\x10'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_negated() {
-        let cls = class(&[('x', 'x')]);
-        assert_eq!(cls.clone().case_fold(), class(&[
-            ('X', 'X'), ('x', 'x'),
-        ]));
-        assert_eq!(cls.case_fold().negate(), class(&[
-            ('\x00', 'W'), ('Y', 'w'), ('y', '\u{10FFFF}'),
-        ]));
-
-        let cls = bclass(&[(b'x', b'x')]);
-        assert_eq!(cls.clone().case_fold(), bclass(&[
-            (b'X', b'X'), (b'x', b'x'),
-        ]));
-        assert_eq!(cls.case_fold().negate(), bclass(&[
-            (b'\x00', b'W'), (b'Y', b'w'), (b'y', b'\xff'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_single_to_multiple() {
-        let cls = class(&[('k', 'k')]);
-        assert_eq!(cls.case_fold(), class(&[
-            ('K', 'K'), ('k', 'k'), ('\u{212A}', '\u{212A}'),
-        ]));
-
-        let cls = bclass(&[(b'k', b'k')]);
-        assert_eq!(cls.case_fold(), bclass(&[
-            (b'K', b'K'), (b'k', b'k'),
-        ]));
-    }
-
-    #[test]
-    fn class_fold_at() {
-        let cls = class(&[('@', '@')]);
-        assert_eq!(cls.clone().canonicalize(), class(&[('@', '@')]));
-        assert_eq!(cls.case_fold(), class(&[('@', '@')]));
-
-        let cls = bclass(&[(b'@', b'@')]);
-        assert_eq!(cls.clone().canonicalize(), bclass(&[(b'@', b'@')]));
-        assert_eq!(cls.case_fold(), bclass(&[(b'@', b'@')]));
-    }
-
-    #[test]
-    fn roundtrip_class_hypen() {
-        let expr = e("[-./]");
-        assert_eq!("(?u:[-\\.-/])", expr.to_string());
-
-        let expr = e("(?-u)[-./]");
-        assert_eq!("(?-u:[-\\.-/])", expr.to_string());
-    }
+    fn word() {
+        assert!(is_word_byte(b'a'));
+        assert!(!is_word_byte(b'-'));
 
-    fn assert_intersection(cls1: CharClass, cls2: CharClass, expected: CharClass) {
-        // intersection operation should be commutative
-        assert_eq!(cls1.intersection(&cls2), expected);
-        assert_eq!(cls2.intersection(&cls1), expected);
+        assert!(is_word_character('a'), "ASCII");
+        assert!(is_word_character('à'), "Latin-1");
+        assert!(is_word_character('β'), "Greek");
+        assert!(is_word_character('\u{11011}'), "Brahmi (Unicode 6.0)");
+        assert!(is_word_character('\u{11611}'), "Modi (Unicode 7.0)");
+        assert!(is_word_character('\u{11711}'), "Ahom (Unicode 8.0)");
+        assert!(is_word_character('\u{17828}'), "Tangut (Unicode 9.0)");
+        assert!(is_word_character('\u{1B1B1}'), "Nushu (Unicode 10.0)");
+        assert!(is_word_character('\u{16E40}'), "Medefaidrin (Unicode 11.0)");
+        assert!(!is_word_character('-'));
+        assert!(!is_word_character('☃'));
     }
 }
diff --git a/third_party/rust/regex-syntax/src/parser.rs b/third_party/rust/regex-syntax/src/parser.rs
index 62ab76fb4f6b..9788ad5573b0 100644
--- a/third_party/rust/regex-syntax/src/parser.rs
+++ b/third_party/rust/regex-syntax/src/parser.rs
@@ -1,3311 +1,206 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+use ast;
+use hir;
 
-use std::cmp::{max, min};
-use std::u8;
+use Result;
 
-use unicode::regex::UNICODE_CLASSES;
-
-use {
-    Expr, Repeater, CharClass, ClassRange,
-    CaptureIndex, CaptureName,
-    Error, ErrorKind, Result,
-};
-
-/// Parser state.
+/// A builder for a regular expression parser.
 ///
-/// Keeps the entire input in memory and maintains a cursor (char offset).
+/// This builder permits modifying configuration options for the parser.
 ///
-/// It also keeps an expression stack, which is responsible for managing
-/// grouped expressions and flag state.
-#[derive(Debug)]
-pub struct Parser {
-    chars: Vec<char>,
-    chari: usize,
-    stack: Vec<Build>,
-    caps: usize,
-    names: Vec<String>, // to check for duplicates
-    flags: Flags,
-}
-
-/// Flag state used in the parser.
-#[derive(Clone, Copy, Debug)]
-pub struct Flags {
-    /// i
-    pub casei: bool,
-    /// m
-    pub multi: bool,
-    /// s
-    pub dotnl: bool,
-    /// U
-    pub swap_greed: bool,
-    /// x
-    pub ignore_space: bool,
-    /// u
-    pub unicode: bool,
-    /// Not actually a flag, but when disabled, every regex that may not match
-    /// UTF-8 exclusively will cause the parser to return an error.
-    pub allow_bytes: bool,
+/// This type combines the builder options for both the
+/// [AST `ParserBuilder`](ast/parse/struct.ParserBuilder.html)
+/// and the
+/// [HIR `TranslatorBuilder`](hir/translate/struct.TranslatorBuilder.html).
+#[derive(Clone, Debug, Default)]
+pub struct ParserBuilder {
+    ast: ast::parse::ParserBuilder,
+    hir: hir::translate::TranslatorBuilder,
 }
 
-impl Default for Flags {
-    fn default() -> Self {
-        Flags {
-            casei: false,
-            multi: false,
-            dotnl: false,
-            swap_greed: false,
-            ignore_space: false,
-            unicode: true,
-            allow_bytes: false,
-        }
+impl ParserBuilder {
+    /// Create a new parser builder with a default configuration.
+    pub fn new() -> ParserBuilder {
+        ParserBuilder::default()
     }
-}
 
-/// An ephemeral type for representing the expression stack.
+    /// Build a parser from this configuration with the given pattern.
+    pub fn build(&self) -> Parser {
+        Parser {
+            ast: self.ast.build(),
+            hir: self.hir.build(),
+        }
+    }
+
+    /// Set the nesting limit for this parser.
+    ///
+    /// The nesting limit controls how deep the abstract syntax tree is allowed
+    /// to be. If the AST exceeds the given limit (e.g., with too many nested
+    /// groups), then an error is returned by the parser.
+    ///
+    /// The purpose of this limit is to act as a heuristic to prevent stack
+    /// overflow for consumers that do structural induction on an `Ast` using
+    /// explicit recursion. While this crate never does this (instead using
+    /// constant stack space and moving the call stack to the heap), other
+    /// crates may.
+    ///
+    /// This limit is not checked until the entire Ast is parsed. Therefore,
+    /// if callers want to put a limit on the amount of heap space used, then
+    /// they should impose a limit on the length, in bytes, of the concrete
+    /// pattern string. In particular, this is viable since this parser
+    /// implementation will limit itself to heap space proportional to the
+    /// lenth of the pattern string.
+    ///
+    /// Note that a nest limit of `0` will return a nest limit error for most
+    /// patterns but not all. For example, a nest limit of `0` permits `a` but
+    /// not `ab`, since `ab` requires a concatenation, which results in a nest
+    /// depth of `1`. In general, a nest limit is not something that manifests
+    /// in an obvious way in the concrete syntax, therefore, it should not be
+    /// used in a granular way.
+    pub fn nest_limit(&mut self, limit: u32) -> &mut ParserBuilder {
+        self.ast.nest_limit(limit);
+        self
+    }
+
+    /// Whether to support octal syntax or not.
+    ///
+    /// Octal syntax is a little-known way of uttering Unicode codepoints in
+    /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+    /// `\141` are all equivalent regular expressions, where the last example
+    /// shows octal syntax.
+    ///
+    /// While supporting octal syntax isn't in and of itself a problem, it does
+    /// make good error messages harder. That is, in PCRE based regex engines,
+    /// syntax like `\0` invokes a backreference, which is explicitly
+    /// unsupported in Rust's regex engine. However, many users expect it to
+    /// be supported. Therefore, when octal support is disabled, the error
+    /// message will explicitly mention that backreferences aren't supported.
+    ///
+    /// Octal syntax is disabled by default.
+    pub fn octal(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.ast.octal(yes);
+        self
+    }
+
+    /// When enabled, the parser will permit the construction of a regular
+    /// expression that may match invalid UTF-8.
+    ///
+    /// When disabled (the default), the parser is guaranteed to produce
+    /// an expression that will only ever match valid UTF-8 (otherwise, the
+    /// parser will return an error).
+    ///
+    /// Perhaps surprisingly, when invalid UTF-8 isn't allowed, a negated ASCII
+    /// word boundary (uttered as `(?-u:\B)` in the concrete syntax) will cause
+    /// the parser to return an error. Namely, a negated ASCII word boundary
+    /// can result in matching positions that aren't valid UTF-8 boundaries.
+    pub fn allow_invalid_utf8(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.hir.allow_invalid_utf8(yes);
+        self
+    }
+
+    /// Enable verbose mode in the regular expression.
+    ///
+    /// When enabled, verbose mode permits insigificant whitespace in many
+    /// places in the regular expression, as well as comments. Comments are
+    /// started using `#` and continue until the end of the line.
+    ///
+    /// By default, this is disabled. It may be selectively enabled in the
+    /// regular expression by using the `x` flag regardless of this setting.
+    pub fn ignore_whitespace(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.ast.ignore_whitespace(yes);
+        self
+    }
+
+    /// Enable or disable the case insensitive flag by default.
+    ///
+    /// By default this is disabled. It may alternatively be selectively
+    /// enabled in the regular expression itself via the `i` flag.
+    pub fn case_insensitive(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.hir.case_insensitive(yes);
+        self
+    }
+
+    /// Enable or disable the multi-line matching flag by default.
+    ///
+    /// By default this is disabled. It may alternatively be selectively
+    /// enabled in the regular expression itself via the `m` flag.
+    pub fn multi_line(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.hir.multi_line(yes);
+        self
+    }
+
+    /// Enable or disable the "dot matches any character" flag by default.
+    ///
+    /// By default this is disabled. It may alternatively be selectively
+    /// enabled in the regular expression itself via the `s` flag.
+    pub fn dot_matches_new_line(
+        &mut self,
+        yes: bool,
+    ) -> &mut ParserBuilder {
+        self.hir.dot_matches_new_line(yes);
+        self
+    }
+
+    /// Enable or disable the "swap greed" flag by default.
+    ///
+    /// By default this is disabled. It may alternatively be selectively
+    /// enabled in the regular expression itself via the `U` flag.
+    pub fn swap_greed(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.hir.swap_greed(yes);
+        self
+    }
+
+    /// Enable or disable the Unicode flag (`u`) by default.
+    ///
+    /// By default this is **enabled**. It may alternatively be selectively
+    /// disabled in the regular expression itself via the `u` flag.
+    ///
+    /// Note that unless `allow_invalid_utf8` is enabled (it's disabled by
+    /// default), a regular expression will fail to parse if Unicode mode is
+    /// disabled and a sub-expression could possibly match invalid UTF-8.
+    pub fn unicode(&mut self, yes: bool) -> &mut ParserBuilder {
+        self.hir.unicode(yes);
+        self
+    }
+}
+
+/// A convenience parser for regular expressions.
 ///
-/// Everything on the stack is either a regular expression or a marker
-/// indicating the opening of a group (possibly non-capturing). The opening
-/// of a group copies the current flag state, which is reset on the parser
-/// state once the group closes.
-#[derive(Debug)]
-enum Build {
-    Expr(Expr),
-    LeftParen {
-        i: CaptureIndex,
-        name: CaptureName,
-        chari: usize,
-        old_flags: Flags,
-    },
-}
-
-/// A type for representing the elements of a bracket stack used for parsing
-/// character classes.
+/// This parser takes as input a regular expression pattern string (the
+/// "concrete syntax") and returns a high-level intermediate representation
+/// (the HIR) suitable for most types of analysis. In particular, this parser
+/// hides the intermediate state of producing an AST (the "abstract syntax").
+/// The AST is itself far more complex than the HIR, so this parser serves as a
+/// convenience for never having to deal with it at all.
 ///
-/// This is for parsing nested character classes without recursion.
-#[derive(Debug)]
-enum Bracket {
-    /// The opening of a character class (possibly negated)
-    LeftBracket {
-        negated: bool,
-    },
-    /// A set of characters within a character class, e.g., `a-z`
-    Set(CharClass),
-    /// An intersection operator (`&&`)
-    Intersection,
-}
-
-// Primary expression parsing routines.
-impl Parser {
-    pub fn parse(s: &str, flags: Flags) -> Result<Expr> {
-        Parser {
-            chars: s.chars().collect(),
-            chari: 0,
-            stack: vec![],
-            caps: 0,
-            names: vec![],
-            flags: flags,
-        }.parse_expr()
-    }
-
-    // Top-level expression parser.
-    //
-    // Starts at the beginning of the input and consumes until either the end
-    // of input or an error.
-    fn parse_expr(mut self) -> Result<Expr> {
-        loop {
-            self.ignore_space();
-            if self.eof() {
-                break;
-            }
-            let build_expr = match self.cur() {
-                '\\' => try!(self.parse_escape()),
-                '|' => { let e = try!(self.alternate()); self.bump(); e }
-                '?' => try!(self.parse_simple_repeat(Repeater::ZeroOrOne)),
-                '*' => try!(self.parse_simple_repeat(Repeater::ZeroOrMore)),
-                '+' => try!(self.parse_simple_repeat(Repeater::OneOrMore)),
-                '{' => try!(self.parse_counted_repeat()),
-                '[' => try!(self.parse_class()),
-                '^' => {
-                    if self.flags.multi {
-                        self.parse_one(Expr::StartLine)
-                    } else {
-                        self.parse_one(Expr::StartText)
-                    }
-                }
-                '$' => {
-                    if self.flags.multi {
-                        self.parse_one(Expr::EndLine)
-                    } else {
-                        self.parse_one(Expr::EndText)
-                    }
-                }
-                '.' => {
-                    if self.flags.dotnl {
-                        if self.flags.unicode {
-                            self.parse_one(Expr::AnyChar)
-                        } else {
-                            if !self.flags.allow_bytes {
-                                return Err(self.err(ErrorKind::InvalidUtf8));
-                            }
-                            self.parse_one(Expr::AnyByte)
-                        }
-                    } else {
-                        if self.flags.unicode {
-                            self.parse_one(Expr::AnyCharNoNL)
-                        } else {
-                            if !self.flags.allow_bytes {
-                                return Err(self.err(ErrorKind::InvalidUtf8));
-                            }
-                            self.parse_one(Expr::AnyByteNoNL)
-                        }
-                    }
-                }
-                '(' => try!(self.parse_group()),
-                ')' => {
-                    let (old_flags, e) = try!(self.close_paren());
-                    self.bump();
-                    self.flags = old_flags;
-                    e
-                }
-                _ => {
-                    let c = self.bump();
-                    try!(self.lit(c))
-                }
-            };
-            if !build_expr.is_empty() {
-                self.stack.push(build_expr);
-            }
-        }
-        self.finish_concat()
-    }
-
-    // Parses an escape sequence, e.g., \Ax
-    //
-    // Start: `\`
-    // End:   `x`
-    fn parse_escape(&mut self) -> Result<Build> {
-        self.bump();
-        if self.eof() {
-            return Err(self.err(ErrorKind::UnexpectedEscapeEof));
-        }
-        let c = self.cur();
-        if is_punct(c) || (self.flags.ignore_space && c.is_whitespace()) {
-            let c = self.bump();
-            return Ok(try!(self.lit(c)));
-        }
-        match c {
-            'a' => { self.bump(); Ok(try!(self.lit('\x07'))) }
-            'f' => { self.bump(); Ok(try!(self.lit('\x0C'))) }
-            't' => { self.bump(); Ok(try!(self.lit('\t'))) }
-            'n' => { self.bump(); Ok(try!(self.lit('\n'))) }
-            'r' => { self.bump(); Ok(try!(self.lit('\r'))) }
-            'v' => { self.bump(); Ok(try!(self.lit('\x0B'))) }
-            'A' => { self.bump(); Ok(Build::Expr(Expr::StartText)) }
-            'z' => { self.bump(); Ok(Build::Expr(Expr::EndText)) }
-            'b' => {
-                self.bump();
-                Ok(Build::Expr(if self.flags.unicode {
-                    Expr::WordBoundary
-                } else {
-                    Expr::WordBoundaryAscii
-                }))
-            }
-            'B' => {
-                self.bump();
-                Ok(Build::Expr(if self.flags.unicode {
-                    Expr::NotWordBoundary
-                } else {
-                    Expr::NotWordBoundaryAscii
-                }))
-            }
-            '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7' => self.parse_octal(),
-            'x' => { self.bump(); self.parse_hex() }
-            'p'|'P' => {
-                self.bump();
-                self.parse_unicode_class(c == 'P')
-                    .map(|cls| Build::Expr(Expr::Class(cls)))
-            }
-            'd'|'s'|'w'|'D'|'S'|'W' => {
-                self.bump();
-                Ok(Build::Expr(Expr::Class(self.parse_perl_class(c))))
-            }
-            c => Err(self.err(ErrorKind::UnrecognizedEscape(c))),
-        }
-    }
-
-    // Parses a group, e.g., `(abc)`.
-    //
-    // Start: `(`
-    // End:   `a`
-    //
-    // A more interesting example, `(?P<foo>abc)`.
-    //
-    // Start: `(`
-    // End:   `a`
-    fn parse_group(&mut self) -> Result<Build> {
-        let chari = self.chari;
-        let mut name: CaptureName = None;
-        self.bump();
-        self.ignore_space();
-        if self.bump_if("?P<") {
-            let n = try!(self.parse_group_name());
-            if self.names.iter().any(|n2| n2 == &n) {
-                return Err(self.err(ErrorKind::DuplicateCaptureName(n)));
-            }
-            self.names.push(n.clone());
-            name = Some(n);
-        } else if self.bump_if("?") {
-            // This can never be capturing. It's either setting flags for
-            // the current group, or it's opening a non-capturing group or
-            // it's opening a group with a specific set of flags (which is
-            // also non-capturing).
-            // Anything else is an error.
-            return self.parse_group_flags(chari);
-        }
-        self.caps = checkadd(self.caps, 1);
-        Ok(Build::LeftParen {
-            i: Some(self.caps),
-            name: name,
-            chari: chari,
-            old_flags: self.flags, // no flags changed if we're here
-        })
-    }
-
-    // Parses flags (inline or grouped), e.g., `(?s-i:abc)`.
-    //
-    // Start: `s`
-    // End:   `a`
-    //
-    // Another example, `(?s-i)a`.
-    //
-    // Start: `s`
-    // End:   `a`
-    fn parse_group_flags(&mut self, opening_chari: usize) -> Result<Build> {
-        let old_flags = self.flags;
-        let mut sign = true;
-        let mut saw_flag = false;
-        loop {
-            if self.eof() {
-                // e.g., (?i
-                return Err(self.err(ErrorKind::UnexpectedFlagEof));
-            }
-            match self.cur() {
-                'i' => { self.flags.casei = sign; saw_flag = true }
-                'm' => { self.flags.multi = sign; saw_flag = true }
-                's' => { self.flags.dotnl = sign; saw_flag = true }
-                'U' => { self.flags.swap_greed = sign; saw_flag = true }
-                'x' => { self.flags.ignore_space = sign; saw_flag = true }
-                'u' => { self.flags.unicode = sign; saw_flag = true }
-                '-' => {
-                    if !sign {
-                        // e.g., (?-i-s)
-                        return Err(self.err(ErrorKind::DoubleFlagNegation));
-                    }
-                    sign = false;
-                    saw_flag = false;
-                }
-                ')' => {
-                    if !saw_flag {
-                        // e.g., (?)
-                        return Err(self.err(ErrorKind::EmptyFlagNegation));
-                    }
-                    // At this point, we're just changing the flags inside
-                    // the current group, which means the old flags have
-                    // been saved elsewhere. Our modifications in place are
-                    // okey dokey!
-                    //
-                    // This particular flag expression only has a stateful
-                    // impact on a regex's AST, so nothing gets explicitly
-                    // added.
-                    self.bump();
-                    return Ok(Build::Expr(Expr::Empty));
-                }
-                ':' => {
-                    if !sign && !saw_flag {
-                        // e.g., (?i-:a)
-                        // Note that if there's no negation, it's OK not
-                        // to see flag, because you end up with a regular
-                        // non-capturing group: `(?:a)`.
-                        return Err(self.err(ErrorKind::EmptyFlagNegation));
-                    }
-                    self.bump();
-                    return Ok(Build::LeftParen {
-                        i: None,
-                        name: None,
-                        chari: opening_chari,
-                        old_flags: old_flags,
-                    });
-                }
-                // e.g., (?z:a)
-                c => return Err(self.err(ErrorKind::UnrecognizedFlag(c))),
-            }
-            self.bump();
-        }
-    }
-
-    // Parses a group name, e.g., `foo` in `(?P<foo>abc)`.
-    //
-    // Start: `f`
-    // End:   `a`
-    fn parse_group_name(&mut self) -> Result<String> {
-        let mut name = String::new();
-        while !self.eof() && !self.peek_is('>') {
-            name.push(self.bump());
-        }
-        if self.eof() {
-            // e.g., (?P<a
-            return Err(self.err(ErrorKind::UnclosedCaptureName(name)));
-        }
-        let all_valid = name.chars().all(is_valid_capture_char);
-        match name.chars().next() {
-            // e.g., (?P<>a)
-            None => Err(self.err(ErrorKind::EmptyCaptureName)),
-            Some(c) if (c >= '0' && c <= '9') || !all_valid => {
-                // e.g., (?P<a#>x)
-                // e.g., (?P<1a>x)
-                Err(self.err(ErrorKind::InvalidCaptureName(name)))
-            }
-            _ => {
-                self.bump(); // for `>`
-                Ok(name)
-            }
-        }
-    }
-
-    // Parses a counted repeition operator, e.g., `a{2,4}?z`.
-    //
-    // Start: `{`
-    // End:   `z`
-    fn parse_counted_repeat(&mut self) -> Result<Build> {
-        let e = try!(self.pop(ErrorKind::RepeaterExpectsExpr)); // e.g., ({5}
-        if !e.can_repeat() {
-            // e.g., a*{5}
-            return Err(self.err(ErrorKind::RepeaterUnexpectedExpr(e)));
-        }
-        self.bump();
-        self.ignore_space();
-        let min = try!(self.parse_decimal());
-        let mut max_opt = Some(min);
-        self.ignore_space();
-        if self.bump_if(',') {
-            self.ignore_space();
-            if self.peek_is('}') {
-                max_opt = None;
-            } else {
-                let max = try!(self.parse_decimal());
-                if min > max {
-                    // e.g., a{2,1}
-                    return Err(self.err(ErrorKind::InvalidRepeatRange {
-                        min: min,
-                        max: max,
-                    }));
-                }
-                max_opt = Some(max);
-            }
-        }
-        self.ignore_space();
-        if !self.bump_if('}') {
-            Err(self.err(ErrorKind::UnclosedRepeat))
-        } else {
-            Ok(Build::Expr(Expr::Repeat {
-                e: Box::new(e),
-                r: Repeater::Range { min: min, max: max_opt },
-                greedy: !self.bump_if('?') ^ self.flags.swap_greed,
-            }))
-        }
-    }
-
-    // Parses a simple repetition operator, e.g., `a+?z`.
-    //
-    // Start: `+`
-    // End:   `z`
-    //
-    // N.B. "simple" in this context means "not min/max repetition",
-    // e.g., `a{1,2}`.
-    fn parse_simple_repeat(&mut self, rep: Repeater) -> Result<Build> {
-        let e = try!(self.pop(ErrorKind::RepeaterExpectsExpr)); // e.g., (*
-        if !e.can_repeat() {
-            // e.g., a**
-            return Err(self.err(ErrorKind::RepeaterUnexpectedExpr(e)));
-        }
-        self.bump();
-        Ok(Build::Expr(Expr::Repeat {
-            e: Box::new(e),
-            r: rep,
-            greedy: !self.bump_if('?') ^ self.flags.swap_greed,
-        }))
-    }
-
-    // Parses a decimal number until the given character, e.g., `a{123,456}`.
-    //
-    // Start: `1`
-    // End:   `,` (where `until == ','`)
-    fn parse_decimal(&mut self) -> Result<u32> {
-        match self.bump_get(|c| is_ascii_word(c) || c.is_whitespace()) {
-            // e.g., a{}
-            None => Err(self.err(ErrorKind::MissingBase10)),
-            Some(n) => {
-                // e.g., a{xyz
-                // e.g., a{9999999999}
-                let n = n.trim();
-                u32::from_str_radix(n, 10)
-                    .map_err(|_| self.err(ErrorKind::InvalidBase10(n.into())))
-            }
-        }
-    }
-
-    // Parses an octal number, up to 3 digits, e.g., `a\123b`
-    //
-    // Start: `1`
-    // End:   `b`
-    fn parse_octal(&mut self) -> Result<Build> {
-        use std::char;
-        let mut i = 0; // counter for limiting octal to 3 digits.
-        let n = self.bump_get(|c| { i += 1; i <= 3 && c >= '0' && c <= '7' })
-                    .expect("octal string"); // guaranteed at least 1 digit
-        // I think both of the following unwraps are impossible to fail.
-        // We limit it to a three digit octal number, which maxes out at
-        // `0777` or `511` in decimal. Since all digits are in `0...7`, we'll
-        // always have a valid `u32` number. Moreover, since all numbers in
-        // the range `0...511` are valid Unicode scalar values, it will always
-        // be a valid `char`.
-        //
-        // Hence, we `unwrap` with reckless abandon.
-        let n = u32::from_str_radix(&n, 8).ok().expect("valid octal number");
-        if !self.flags.unicode {
-            return Ok(try!(self.u32_to_one_byte(n)));
-        }
-        let c = char::from_u32(n).expect("Unicode scalar value");
-        Ok(try!(self.lit(c)))
-    }
-
-    // Parses a hex number, e.g., `a\x5ab`.
-    //
-    // Start: `5`
-    // End:   `b`
-    //
-    // And also, `a\x{2603}b`.
-    //
-    // Start: `{`
-    // End:   `b`
-    fn parse_hex(&mut self) -> Result<Build> {
-        self.ignore_space();
-        if self.bump_if('{') {
-            self.parse_hex_many_digits()
-        } else {
-            self.parse_hex_two_digits()
-        }
-    }
-
-    // Parses a many-digit hex number, e.g., `a\x{2603}b`.
-    //
-    // Start: `2`
-    // End:   `b`
-    fn parse_hex_many_digits(&mut self) -> Result<Build> {
-        use std::char;
-
-        self.ignore_space();
-        let s = self.bump_get(is_ascii_word).unwrap_or("".into());
-        let n = try!(u32::from_str_radix(&s, 16)
-                         .map_err(|_| self.err(ErrorKind::InvalidBase16(s))));
-        self.ignore_space();
-        if !self.bump_if('}') {
-            // e.g., a\x{d
-            return Err(self.err(ErrorKind::UnclosedHex));
-        }
-        if !self.flags.unicode {
-            return Ok(try!(self.u32_to_one_byte(n)));
-        }
-        let c = try!(char::from_u32(n)
-                          .ok_or(self.err(ErrorKind::InvalidScalarValue(n))));
-        Ok(try!(self.lit(c)))
-    }
-
-    // Parses a two-digit hex number, e.g., `a\x5ab`.
-    //
-    // Start: `5`
-    // End:   `b`
-    fn parse_hex_two_digits(&mut self) -> Result<Build> {
-        use std::char;
-
-        let mut i = 0;
-        let s = self.bump_get(|_| { i += 1; i <= 2 }).unwrap_or("".into());
-        if s.len() < 2 {
-            // e.g., a\x
-            // e.g., a\xf
-            return Err(self.err(ErrorKind::UnexpectedTwoDigitHexEof));
-        }
-        let n = try!(u32::from_str_radix(&s, 16)
-                         .map_err(|_| self.err(ErrorKind::InvalidBase16(s))));
-        if !self.flags.unicode {
-            return Ok(try!(self.u32_to_one_byte(n)));
-        }
-        let c = char::from_u32(n).expect("Unicode scalar value");
-        Ok(try!(self.lit(c)))
-    }
-
-    // Parses a character class, e.g., `[^a-zA-Z0-9]+`.
-    //
-    // If the Unicode flag is enabled, the class is returned as a `CharClass`,
-    // otherwise it is converted to a `ByteClass`.
-    //
-    // Start: `[`
-    // End:   `+`
-    fn parse_class(&mut self) -> Result<Build> {
-        let class = try!(self.parse_class_as_chars());
-        Ok(Build::Expr(if self.flags.unicode {
-            Expr::Class(class)
-        } else {
-            let byte_class = class.to_byte_class();
-
-            // If `class` was only non-empty due to multibyte characters, the
-            // corresponding byte class will now be empty.
-            //
-            // See https://github.com/rust-lang/regex/issues/303
-            if byte_class.is_empty() {
-                // e.g., (?-u)[^\x00-\xFF]
-                return Err(self.err(ErrorKind::EmptyClass));
-            }
-
-            Expr::ClassBytes(byte_class)
-        }))
-    }
-
-    // Parses a character class as a `CharClass`, e.g., `[^a-zA-Z0-9]+`.
-    //
-    // Start: `[`
-    // End:   `+`
-    fn parse_class_as_chars(&mut self) -> Result<CharClass> {
-        let mut bracket_stack = vec![];
-        bracket_stack.extend(self.parse_open_bracket());
-        loop {
-            self.ignore_space();
-            if self.eof() {
-                // e.g., [a
-                return Err(self.err(ErrorKind::UnexpectedClassEof));
-            }
-            match self.cur() {
-                '[' => {
-                    if let Some(class) = self.maybe_parse_ascii() {
-                        // e.g. `[:alnum:]`
-                        bracket_stack.push(Bracket::Set(class));
-                    } else {
-                        // nested set, e.g. `[c-d]` in `[a-b[c-d]]`
-                        bracket_stack.extend(self.parse_open_bracket());
-                    }
-                }
-                ']' => {
-                    self.bump();
-                    let class = try!(self.close_bracket(&mut bracket_stack));
-                    if bracket_stack.is_empty() {
-                        // That was the outermost class, so stop now
-                        return Ok(class);
-                    }
-                    bracket_stack.push(Bracket::Set(class));
-                }
-                '\\' => {
-                    let class = try!(self.parse_class_escape());
-                    bracket_stack.push(Bracket::Set(class));
-                }
-                '&' if self.peek_is("&&") => {
-                    self.bump();
-                    self.bump();
-                    bracket_stack.push(Bracket::Intersection);
-                }
-                start => {
-                    if !self.flags.unicode {
-                        let _ = try!(self.codepoint_to_one_byte(start));
-                    }
-                    self.bump();
-                    match start {
-                        '~'|'-' => {
-                            // Only report an error if we see ~~ or --.
-                            if self.peek_is(start) {
-                                return Err(self.err(
-                                    ErrorKind::UnsupportedClassChar(start)));
-                            }
-                        }
-                        _ => {}
-                    }
-                    let class = try!(self.parse_class_range(start));
-                    bracket_stack.push(Bracket::Set(class));
-                }
-            }
-        }
-    }
-
-    // Parses the start of a character class or a nested character class.
-    // That includes negation using `^` and unescaped `-` and `]` allowed at
-    // the start of the class.
-    //
-    // e.g., `[^a]` or `[-a]` or `[]a]`
-    //
-    // Start: `[`
-    // End:   `a`
-    fn parse_open_bracket(&mut self) -> Vec<Bracket> {
-        self.bump();
-        self.ignore_space();
-        let negated = self.bump_if('^');
-        self.ignore_space();
-
-        let mut class = CharClass::empty();
-        while self.bump_if('-') {
-            class.ranges.push(ClassRange::one('-'));
-            self.ignore_space();
-        }
-        if class.is_empty() {
-            if self.bump_if(']') {
-                class.ranges.push(ClassRange::one(']'));
-                self.ignore_space();
-            }
-        }
-
-        let bracket = Bracket::LeftBracket { negated: negated };
-        if class.is_empty() {
-            vec![bracket]
-        } else {
-            vec![bracket, Bracket::Set(class)]
-        }
-    }
-
-    // Parses an escape in a character class.
-    //
-    // This is a helper for `parse_class`. Instead of returning an `Ok` value,
-    // it either mutates the char class or returns an error.
-    //
-    // e.g., `\wx`
-    //
-    // Start: `\`
-    // End:   `x`
-    fn parse_class_escape(&mut self) -> Result<CharClass> {
-        match try!(self.parse_escape()) {
-            Build::Expr(Expr::Class(class)) => {
-                Ok(class)
-            }
-            Build::Expr(Expr::ClassBytes(class2)) => {
-                let mut class = CharClass::empty();
-                for byte_range in class2 {
-                    let s = byte_range.start as char;
-                    let e = byte_range.end as char;
-                    class.ranges.push(ClassRange::new(s, e));
-                }
-                Ok(class)
-            }
-            Build::Expr(Expr::Literal { chars, .. }) => {
-                self.parse_class_range(chars[0])
-            }
-            Build::Expr(Expr::LiteralBytes { bytes, .. }) => {
-                let start = bytes[0] as char;
-                self.parse_class_range(start)
-            }
-            Build::Expr(e) => {
-                let err = ErrorKind::InvalidClassEscape(e);
-                Err(self.err(err))
-            }
-            // Because `parse_escape` can never return `LeftParen`.
-            _ => unreachable!(),
-        }
-    }
-
-    // Parses a single range in a character class.
-    //
-    // e.g., `[a-z]`
-    //
-    // Start: `-` (with start == `a`)
-    // End:   `]`
-    fn parse_class_range(&mut self, start: char) -> Result<CharClass> {
-        self.ignore_space();
-        if !self.bump_if('-') {
-            // Not a range, so just return a singleton range.
-            return Ok(CharClass::new(vec![ClassRange::one(start)]));
-        }
-        self.ignore_space();
-        if self.eof() {
-            // e.g., [a-
-            return Err(self.err(ErrorKind::UnexpectedClassEof));
-        }
-        if self.peek_is(']') {
-            // This is the end of the class, so we permit use of `-` as a
-            // regular char (just like we do in the beginning).
-            return Ok(CharClass::new(vec![ClassRange::one(start), ClassRange::one('-')]));
-        }
-
-        // We have a real range. Just need to check to parse literal and
-        // make sure it's a valid range.
-        let end = match self.cur() {
-            '\\' => match try!(self.parse_escape()) {
-                Build::Expr(Expr::Literal { chars, .. }) => {
-                    chars[0]
-                }
-                Build::Expr(Expr::LiteralBytes { bytes, .. }) => {
-                    bytes[0] as char
-                }
-                Build::Expr(e) => {
-                    return Err(self.err(ErrorKind::InvalidClassEscape(e)));
-                }
-                // Because `parse_escape` can never return `LeftParen`.
-                _ => unreachable!(),
-            },
-            c => {
-                self.bump();
-                if c == '-' {
-                    return Err(self.err(ErrorKind::UnsupportedClassChar('-')));
-                }
-                if !self.flags.unicode {
-                    let _ = try!(self.codepoint_to_one_byte(c));
-                }
-                c
-            }
-        };
-        if end < start {
-            // e.g., [z-a]
-            return Err(self.err(ErrorKind::InvalidClassRange {
-                start: start,
-                end: end,
-            }));
-        }
-        Ok(CharClass::new(vec![ClassRange::new(start, end)]))
-    }
-
-    // Parses an ASCII class, e.g., `[:alnum:]+`.
-    //
-    // Start: `[`
-    // End:   `+`
-    //
-    // Also supports negation, e.g., `[:^alnum:]`.
-    //
-    // This parsing routine is distinct from the others in that it doesn't
-    // actually report any errors. Namely, if it fails, then the parser should
-    // fall back to parsing a regular class.
-    //
-    // This method will only make progress in the parser if it succeeds.
-    // Otherwise, the input remains where it started.
-    fn maybe_parse_ascii(&mut self) -> Option<CharClass> {
-        fn parse(p: &mut Parser) -> Option<CharClass> {
-            p.bump(); // the `[`
-            if !p.bump_if(':') { return None; }
-            let negate = p.bump_if('^');
-            let name = match p.bump_get(|c| c != ':') {
-                None => return None,
-                Some(name) => name,
-            };
-            if !p.bump_if(":]") { return None; }
-            ascii_class(&name).map(|cls| p.class_transform(negate, cls))
-        }
-        let start = self.chari;
-        match parse(self) {
-            None => { self.chari = start; None }
-            result => result,
-        }
-    }
-
-    // Parses a Uncode class name, e.g., `a\pLb`.
-    //
-    // Start: `L`
-    // End:   `b`
-    //
-    // And also, `a\p{Greek}b`.
-    //
-    // Start: `{`
-    // End:   `b`
-    //
-    // `negate` is true when the class name is used with `\P`.
-    fn parse_unicode_class(&mut self, neg: bool) -> Result<CharClass> {
-        self.ignore_space();
-        let name =
-            if self.bump_if('{') {
-                self.ignore_space();
-                let n = self.bump_get(is_ascii_word).unwrap_or("".into());
-                self.ignore_space();
-                if n.is_empty() || !self.bump_if('}') {
-                    // e.g., \p{Greek
-                    return Err(self.err(ErrorKind::UnclosedUnicodeName));
-                }
-                n
-            } else {
-                if self.eof() {
-                    // e.g., \p
-                    return Err(self.err(ErrorKind::UnexpectedEscapeEof));
-                }
-                self.bump().to_string()
-            };
-        match unicode_class(&name) {
-            None => Err(self.err(ErrorKind::UnrecognizedUnicodeClass(name))),
-            Some(cls) => {
-                if self.flags.unicode {
-                    Ok(self.class_transform(neg, cls))
-                } else {
-                    Err(self.err(ErrorKind::UnicodeNotAllowed))
-                }
-            }
-        }
-    }
-
-    // Parses a perl character class with Unicode support.
-    //
-    // `name` must be one of d, s, w, D, S, W. If not, this function panics.
-    //
-    // No parser state is changed.
-    fn parse_perl_class(&mut self, name: char) -> CharClass {
-        use unicode::regex::{PERLD, PERLS, PERLW};
-        let (cls, negate) = match (self.flags.unicode, name) {
-            (true, 'd') => (raw_class_to_expr(PERLD), false),
-            (true, 'D') => (raw_class_to_expr(PERLD), true),
-            (true, 's') => (raw_class_to_expr(PERLS), false),
-            (true, 'S') => (raw_class_to_expr(PERLS), true),
-            (true, 'w') => (raw_class_to_expr(PERLW), false),
-            (true, 'W') => (raw_class_to_expr(PERLW), true),
-            (false, 'd') => (ascii_class("digit").unwrap(), false),
-            (false, 'D') => (ascii_class("digit").unwrap(), true),
-            (false, 's') => (ascii_class("space").unwrap(), false),
-            (false, 'S') => (ascii_class("space").unwrap(), true),
-            (false, 'w') => (ascii_class("word").unwrap(), false),
-            (false, 'W') => (ascii_class("word").unwrap(), true),
-            _ => unreachable!(),
-        };
-        self.class_transform(negate, cls)
-    }
-
-    // Always bump to the next input and return the given expression as a
-    // `Build`.
-    //
-    // This is mostly for convenience when the surrounding context implies
-    // that the next character corresponds to the given expression.
-    fn parse_one(&mut self, e: Expr) -> Build {
-        self.bump();
-        Build::Expr(e)
-    }
-}
-
-// Auxiliary helper methods.
-impl Parser {
-    fn chars(&self) -> Chars {
-        Chars::new(&self.chars[self.chari..])
-    }
-
-    fn ignore_space(&mut self) {
-        if !self.flags.ignore_space {
-            return;
-        }
-        while !self.eof() {
-            match self.cur() {
-                '#' => {
-                    self.bump();
-                    while !self.eof() {
-                        match self.bump() {
-                            '\n' => break,
-                            _ => continue,
-                        }
-                    }
-                },
-                c => if !c.is_whitespace() {
-                    return;
-                } else {
-                    self.bump();
-                }
-            }
-        }
-    }
-
-    fn bump(&mut self) -> char {
-        let c = self.cur();
-        self.chari = checkadd(self.chari, self.chars().next_count());
-        c
-    }
-
-    fn cur(&self) -> char { self.chars().next().unwrap() }
-
-    fn eof(&self) -> bool { self.chars().next().is_none() }
-
-    fn bump_get<B: Bumpable>(&mut self, s: B) -> Option<String> {
-        let n = s.match_end(self);
-        if n == 0 {
-            None
-        } else {
-            let end = checkadd(self.chari, n);
-            let s = self.chars[self.chari..end]
-                        .iter().cloned().collect::<String>();
-            self.chari = end;
-            Some(s)
-        }
-    }
-
-    fn bump_if<B: Bumpable>(&mut self, s: B) -> bool {
-        let n = s.match_end(self);
-        if n == 0 {
-            false
-        } else {
-            self.chari = checkadd(self.chari, n);
-            true
-        }
-    }
-
-    fn peek_is<B: Bumpable>(&self, s: B) -> bool {
-        s.match_end(self) > 0
-    }
-
-    fn err(&self, kind: ErrorKind) -> Error {
-        self.errat(self.chari, kind)
-    }
-
-    fn errat(&self, pos: usize, kind: ErrorKind) -> Error {
-        Error { pos: pos, surround: self.windowat(pos), kind: kind }
-    }
-
-    fn windowat(&self, pos: usize) -> String {
-        let s = max(5, pos) - 5;
-        let e = min(self.chars.len(), checkadd(pos, 5));
-        self.chars[s..e].iter().cloned().collect()
-    }
-
-    fn pop(&mut self, expected: ErrorKind) -> Result<Expr> {
-        match self.stack.pop() {
-            None | Some(Build::LeftParen{..}) => Err(self.err(expected)),
-            Some(Build::Expr(e)) => Ok(e),
-        }
-    }
-
-    // If the current context calls for case insensitivity, then apply
-    // case folding. Similarly, if `negate` is `true`, then negate the
-    // class. (Negation always proceeds case folding.)
-    fn class_transform(&self, negate: bool, mut cls: CharClass) -> CharClass {
-        if self.flags.casei {
-            cls = cls.case_fold();
-        }
-        if negate {
-            cls = cls.negate();
-        }
-        cls
-    }
-
-    // Translates a Unicode codepoint into a single UTF-8 byte, and returns an
-    // error if it's not possible.
-    //
-    // This will panic if self.flags.unicode == true.
-    fn codepoint_to_one_byte(&self, c: char) -> Result<u8> {
-        assert!(!self.flags.unicode);
-        let bytes = c.to_string().as_bytes().to_owned();
-        if bytes.len() > 1 {
-            return Err(self.err(ErrorKind::UnicodeNotAllowed));
-        }
-        Ok(bytes[0])
-    }
-
-    // Creates a new byte literal from a single byte.
-    //
-    // If the given number can't fit into a single byte, then it is assumed
-    // to be a Unicode codepoint and an error is returned.
-    //
-    // This should only be called when the bytes flag is enabled.
-    fn u32_to_one_byte(&self, b: u32) -> Result<Build> {
-        assert!(!self.flags.unicode);
-        if b > u8::MAX as u32 {
-            Err(self.err(ErrorKind::UnicodeNotAllowed))
-        } else if !self.flags.allow_bytes && b > 0x7F {
-            Err(self.err(ErrorKind::InvalidUtf8))
-        } else {
-            Ok(Build::Expr(Expr::LiteralBytes {
-                bytes: vec![b as u8],
-                casei: self.flags.casei,
-            }))
-        }
-    }
-
-    // Creates a new literal expr from a Unicode codepoint.
-    //
-    // Creates a byte literal if the `bytes` flag is set.
-    fn lit(&self, c: char) -> Result<Build> {
-        Ok(Build::Expr(if self.flags.unicode {
-            Expr::Literal {
-                chars: vec![c],
-                casei: self.flags.casei,
-            }
-        } else {
-            Expr::LiteralBytes {
-                bytes: vec![try!(self.codepoint_to_one_byte(c))],
-                casei: self.flags.casei,
-            }
-        }))
-    }
-}
-
-struct Chars<'a> {
-    chars: &'a [char],
-    cur: usize,
-}
-
-impl<'a> Iterator for Chars<'a> {
-    type Item = char;
-    fn next(&mut self) -> Option<char> {
-        let x = self.c();
-        self.advance();
-        return x;
-    }
-}
-
-impl<'a> Chars<'a> {
-    fn new(chars: &[char]) -> Chars {
-        Chars {
-            chars: chars,
-            cur: 0,
-        }
-    }
-
-    fn c(&self) -> Option<char> {
-        self.chars.get(self.cur).map(|&c| c)
-    }
-
-    fn advance(&mut self) {
-        self.cur = checkadd(self.cur, 1);
-    }
-
-    fn next_count(&mut self) -> usize {
-        self.next();
-        self.cur
-    }
-}
-
-// Auxiliary methods for manipulating the expression stack.
-impl Parser {
-    // Called whenever an alternate (`|`) is found.
-    //
-    // This pops the expression stack until:
-    //
-    //  1. The stack is empty. Pushes an alternation with one arm.
-    //  2. An opening parenthesis is found. Leave the parenthesis
-    //     on the stack and push an alternation with one arm.
-    //  3. An alternate (`|`) is found. Pop the existing alternation,
-    //     add an arm and push the modified alternation.
-    //
-    // Each "arm" in the above corresponds to the concatenation of all
-    // popped expressions.
-    //
-    // In the first two cases, the stack is left in an invalid state
-    // because an alternation with one arm is not allowed. This
-    // particular state will be detected by `finish_concat` and an
-    // error will be reported.
-    //
-    // In none of the cases is an empty arm allowed. If an empty arm
-    // is found, an error is reported.
-    fn alternate(&mut self) -> Result<Build> {
-        let mut concat = vec![];
-        let alts = |es| Ok(Build::Expr(Expr::Alternate(es)));
-        loop {
-            match self.stack.pop() {
-                None => {
-                    if concat.is_empty() {
-                        // e.g., |a
-                        return Err(self.err(ErrorKind::EmptyAlternate));
-                    }
-                    return alts(vec![rev_concat(concat)]);
-                }
-                Some(e @ Build::LeftParen{..}) => {
-                    if concat.is_empty() {
-                        // e.g., (|a)
-                        return Err(self.err(ErrorKind::EmptyAlternate));
-                    }
-                    self.stack.push(e);
-                    return alts(vec![rev_concat(concat)]);
-                }
-                Some(Build::Expr(Expr::Alternate(mut es))) => {
-                    if concat.is_empty() {
-                        // e.g., a||
-                        return Err(self.err(ErrorKind::EmptyAlternate));
-                    }
-                    es.push(rev_concat(concat));
-                    return alts(es);
-                }
-                Some(Build::Expr(e)) => { concat.push(e); }
-            }
-        }
-    }
-
-    // Called whenever a closing parenthesis (`)`) is found.
-    //
-    // This pops the expression stack until:
-    //
-    //  1. The stack is empty. An error is reported because this
-    //     indicates an unopened parenthesis.
-    //  2. An opening parenthesis is found. Pop the opening parenthesis
-    //     and push a `Group` expression.
-    //  3. An alternate (`|`) is found. Pop the existing alternation
-    //     and an arm to it in place. Pop one more item from the stack.
-    //     If the stack was empty, then report an unopened parenthesis
-    //     error, otherwise assume it is an opening parenthesis and
-    //     push a `Group` expression with the popped alternation.
-    //     (We can assume this is an opening parenthesis because an
-    //     alternation either corresponds to the entire Regex or it
-    //     corresponds to an entire group. This is guaranteed by the
-    //     `alternate` method.)
-    //
-    // Each "arm" in the above corresponds to the concatenation of all
-    // popped expressions.
-    //
-    // Empty arms nor empty groups are allowed.
-    fn close_paren(&mut self) -> Result<(Flags, Build)> {
-        let mut concat = vec![];
-        loop {
-            match self.stack.pop() {
-                // e.g., )
-                None => return Err(self.err(ErrorKind::UnopenedParen)),
-                Some(Build::LeftParen { i, name, old_flags, .. }) => {
-                    if concat.is_empty() {
-                        // e.g., ()
-                        return Err(self.err(ErrorKind::EmptyGroup));
-                    }
-                    return Ok((old_flags, Build::Expr(Expr::Group {
-                        e: Box::new(rev_concat(concat)),
-                        i: i,
-                        name: name,
-                    })));
-                }
-                Some(Build::Expr(Expr::Alternate(mut es))) => {
-                    if concat.is_empty() {
-                        // e.g., (a|)
-                        return Err(self.err(ErrorKind::EmptyAlternate));
-                    }
-                    es.push(rev_concat(concat));
-                    match self.stack.pop() {
-                        // e.g., a|b)
-                        None => return Err(self.err(ErrorKind::UnopenedParen)),
-                        Some(Build::Expr(_)) => unreachable!(),
-                        Some(Build::LeftParen { i, name, old_flags, .. }) => {
-                            return Ok((old_flags, Build::Expr(Expr::Group {
-                                e: Box::new(Expr::Alternate(es)),
-                                i: i,
-                                name: name,
-                            })));
-                        }
-                    }
-                }
-                Some(Build::Expr(e)) => { concat.push(e); }
-            }
-        }
-    }
-
-    // Called only when the parser reaches the end of input.
-    //
-    // This pops the expression stack until:
-    //
-    //  1. The stack is empty. Return concatenation of popped
-    //     expressions. This concatenation may be empty!
-    //  2. An alternation is found. Pop the alternation and push
-    //     a new arm. Return the alternation as the entire Regex.
-    //     After this, the stack must be empty, or else there is
-    //     an unclosed paren.
-    //
-    // If an opening parenthesis is popped, then an error is
-    // returned since it indicates an unclosed parenthesis.
-    fn finish_concat(&mut self) -> Result<Expr> {
-        let mut concat = vec![];
-        loop {
-            match self.stack.pop() {
-                None => { return Ok(rev_concat(concat)); }
-                Some(Build::LeftParen{ chari, ..}) => {
-                    // e.g., a(b
-                    return Err(self.errat(chari, ErrorKind::UnclosedParen));
-                }
-                Some(Build::Expr(Expr::Alternate(mut es))) => {
-                    if concat.is_empty() {
-                        // e.g., a|
-                        return Err(self.err(ErrorKind::EmptyAlternate));
-                    }
-                    es.push(rev_concat(concat));
-                    // Make sure there are no opening parens remaining.
-                    match self.stack.pop() {
-                        None => return Ok(Expr::Alternate(es)),
-                        Some(Build::LeftParen{ chari, ..}) => {
-                            // e.g., (a|b
-                            return Err(self.errat(
-                                chari, ErrorKind::UnclosedParen));
-                        }
-                        e => unreachable!("{:?}", e),
-                    }
-                }
-                Some(Build::Expr(e)) => { concat.push(e); }
-            }
-        }
-    }
+/// If callers have more fine grained use cases that need an AST, then please
+/// see the [`ast::parse`](ast/parse/index.html) module.
+///
+/// A `Parser` can be configured in more detail via a
+/// [`ParserBuilder`](struct.ParserBuilder.html).
+#[derive(Clone, Debug)]
+pub struct Parser {
+    ast: ast::parse::Parser,
+    hir: hir::translate::Translator,
 }
 
-// Methods for working with the bracket stack used for character class parsing.
 impl Parser {
-
-    // After parsing a closing bracket `]`, process elements of the bracket
-    // stack until finding the corresponding opening bracket `[`, and return
-    // the combined character class. E.g. with `[^b-f&&ab-c]`:
-    //
-    // 1. Adjacent sets are merged into a single union: `ab-c` -> `a-c`
-    // 2. Unions separated by `&&` are intersected: `b-f` and `a-c` -> `b-c`
-    // 3. Negation is applied if necessary: `b-c` -> negation of `b-c`
-    fn close_bracket(&self, stack: &mut Vec<Bracket>) -> Result<CharClass> {
-        let mut union = CharClass::empty();
-        let mut intersect = vec![];
-        loop {
-            match stack.pop() {
-                Some(Bracket::Set(class)) => {
-                    union.ranges.extend(class);
-                }
-                Some(Bracket::Intersection) => {
-                    let class = self.class_union_transform(union);
-                    intersect.push(class);
-                    union = CharClass::empty();
-                }
-                Some(Bracket::LeftBracket { negated }) => {
-                    let mut class = self.class_union_transform(union);
-                    for c in intersect {
-                        class = class.intersection(&c);
-                    }
-                    // negate after combining all sets (`^` has lower precedence than `&&`)
-                    if negated {
-                        class = class.negate();
-                    }
-                    if class.is_empty() {
-                        // e.g., [^\d\D]
-                        return Err(self.err(ErrorKind::EmptyClass));
-                    }
-                    return Ok(class);
-                }
-                // The first element on the stack is a `LeftBracket`
-                None => unreachable!()
-            }
-        }
-    }
-
-    // Apply case folding if requested on the union character class, and
-    // return a canonicalized class.
-    fn class_union_transform(&self, class: CharClass) -> CharClass {
-        if self.flags.casei {
-            // Case folding canonicalizes too
-            class.case_fold()
-        } else {
-            class.canonicalize()
-        }
-    }
-}
-
-impl Build {
-    fn is_empty(&self) -> bool {
-        match *self {
-            Build::Expr(Expr::Empty) => true,
-            _ => false,
-        }
-    }
-}
-
-// Make it ergonomic to conditionally bump the parser.
-// i.e., `bump_if('a')` or `bump_if("abc")`.
-trait Bumpable {
-    fn match_end(self, p: &Parser) -> usize;
-}
-
-impl Bumpable for char {
-    fn match_end(self, p: &Parser) -> usize {
-        let mut chars = p.chars();
-        if chars.next().map(|c| c == self).unwrap_or(false) {
-            chars.cur
-        } else {
-            0
-        }
-    }
-}
-
-impl<'a> Bumpable for &'a str {
-    fn match_end(self, p: &Parser) -> usize {
-        let mut search = self.chars();
-        let mut rest = p.chars();
-        let mut count = 0;
-        loop {
-            match (rest.next(), search.next()) {
-                (Some(c1), Some(c2)) if c1 == c2 => count = rest.cur,
-                (_, None) => return count,
-                _ => return 0,
-            }
-        }
-    }
-}
-
-impl<F: FnMut(char) -> bool> Bumpable for F {
-    fn match_end(mut self, p: &Parser) -> usize {
-        let mut chars = p.chars();
-        let mut count = 0;
-        while let Some(c) = chars.next() {
-            if !self(c) {
-                break
-            }
-            count = chars.cur;
-        }
-        count
-    }
-}
-
-// Turn a sequence of expressions into a concatenation.
-// This only uses `Concat` if there are 2 or more expressions.
-fn rev_concat(mut exprs: Vec<Expr>) -> Expr {
-    if exprs.len() == 0 {
-        Expr::Empty
-    } else if exprs.len() == 1 {
-        exprs.pop().unwrap()
-    } else {
-        exprs.reverse();
-        Expr::Concat(exprs)
-    }
-}
-
-// Returns true if and only if the given character is allowed in a capture
-// name. Note that the first char of a capture name must not be numeric.
-fn is_valid_capture_char(c: char) -> bool {
-    c == '_' || (c >= '0' && c <= '9')
-    || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-}
-
-fn is_ascii_word(c: char) -> bool {
-    match c {
-        'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => true,
-        _ => false,
-    }
-}
-
-/// Returns true if the give character has significance in a regex.
-pub fn is_punct(c: char) -> bool {
-    match c {
-        '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' |
-        '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~' => true,
-        _ => false,
-    }
-}
-
-fn checkadd(x: usize, y: usize) -> usize {
-    x.checked_add(y).expect("regex length overflow")
-}
-
-fn unicode_class(name: &str) -> Option<CharClass> {
-    UNICODE_CLASSES.binary_search_by(|&(s, _)| s.cmp(name)).ok().map(|i| {
-        raw_class_to_expr(UNICODE_CLASSES[i].1)
-    })
-}
-
-fn ascii_class(name: &str) -> Option<CharClass> {
-    ASCII_CLASSES.binary_search_by(|&(s, _)| s.cmp(name)).ok().map(|i| {
-        raw_class_to_expr(ASCII_CLASSES[i].1)
-    })
-}
-
-fn raw_class_to_expr(raw: &[(char, char)]) -> CharClass {
-    let range = |&(s, e)| ClassRange { start: s, end: e };
-    CharClass::new(raw.iter().map(range).collect())
-}
-
-type Class = &'static [(char, char)];
-type NamedClasses = &'static [(&'static str, Class)];
-
-const ASCII_CLASSES: NamedClasses = &[
-    // Classes must be in alphabetical order so that bsearch works.
-    // [:alnum:]      alphanumeric (== [0-9A-Za-z])
-    // [:alpha:]      alphabetic (== [A-Za-z])
-    // [:ascii:]      ASCII (== [\x00-\x7F])
-    // [:blank:]      blank (== [\t ])
-    // [:cntrl:]      control (== [\x00-\x1F\x7F])
-    // [:digit:]      digits (== [0-9])
-    // [:graph:]      graphical (== [!-~])
-    // [:lower:]      lower case (== [a-z])
-    // [:print:]      printable (== [ -~] == [ [:graph:]])
-    // [:punct:]      punctuation (== [!-/:-@[-`{-~])
-    // [:space:]      whitespace (== [\t\n\v\f\r ])
-    // [:upper:]      upper case (== [A-Z])
-    // [:word:]       word characters (== [0-9A-Za-z_])
-    // [:xdigit:]     hex digit (== [0-9A-Fa-f])
-    // Taken from: http://golang.org/pkg/regex/syntax/
-    ("alnum", &ALNUM),
-    ("alpha", &ALPHA),
-    ("ascii", &ASCII),
-    ("blank", &BLANK),
-    ("cntrl", &CNTRL),
-    ("digit", &DIGIT),
-    ("graph", &GRAPH),
-    ("lower", &LOWER),
-    ("print", &PRINT),
-    ("punct", &PUNCT),
-    ("space", &SPACE),
-    ("upper", &UPPER),
-    ("word", &WORD),
-    ("xdigit", &XDIGIT),
-];
-
-const ALNUM: Class = &[('0', '9'), ('A', 'Z'), ('a', 'z')];
-const ALPHA: Class = &[('A', 'Z'), ('a', 'z')];
-const ASCII: Class = &[('\x00', '\x7F')];
-const BLANK: Class = &[(' ', ' '), ('\t', '\t')];
-const CNTRL: Class = &[('\x00', '\x1F'), ('\x7F', '\x7F')];
-const DIGIT: Class = &[('0', '9')];
-const GRAPH: Class = &[('!', '~')];
-const LOWER: Class = &[('a', 'z')];
-const PRINT: Class = &[(' ', '~')];
-const PUNCT: Class = &[('!', '/'), (':', '@'), ('[', '`'), ('{', '~')];
-const SPACE: Class = &[('\t', '\t'), ('\n', '\n'), ('\x0B', '\x0B'),
-                       ('\x0C', '\x0C'), ('\r', '\r'), (' ', ' ')];
-const UPPER: Class = &[('A', 'Z')];
-const WORD: Class = &[('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z')];
-const XDIGIT: Class = &[('0', '9'), ('A', 'F'), ('a', 'f')];
-
-#[cfg(test)]
-mod tests {
-    use {
-        CharClass, ClassRange, ByteClass, ByteRange,
-        Expr, Repeater,
-        ErrorKind,
-    };
-    use unicode::regex::{PERLD, PERLS, PERLW};
-    use super::{LOWER, UPPER, WORD, Flags, Parser, ascii_class};
-
-    static YI: &'static [(char, char)] = &[
-        ('\u{a000}', '\u{a48c}'), ('\u{a490}', '\u{a4c6}'),
-    ];
-
-    fn p(s: &str) -> Expr { Parser::parse(s, Flags::default()).unwrap() }
-    fn pf(s: &str, flags: Flags) -> Expr { Parser::parse(s, flags).unwrap() }
-    fn lit(c: char) -> Expr { Expr::Literal { chars: vec![c], casei: false } }
-    fn liti(c: char) -> Expr { Expr::Literal { chars: vec![c], casei: true } }
-    fn b<T>(v: T) -> Box<T> { Box::new(v) }
-    fn c(es: &[Expr]) -> Expr { Expr::Concat(es.to_vec()) }
-
-    fn pb(s: &str) -> Expr {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        Parser::parse(s, flags).unwrap()
-    }
-
-    fn blit(b: u8) -> Expr {
-        Expr::LiteralBytes {
-            bytes: vec![b],
-            casei: false,
-        }
-    }
-
-    fn bliti(b: u8) -> Expr {
-        Expr::LiteralBytes {
-            bytes: vec![b],
-            casei: true,
-        }
-    }
-
-    fn class(ranges: &[(char, char)]) -> CharClass {
-        let ranges = ranges.iter().cloned()
-                           .map(|(c1, c2)| ClassRange::new(c1, c2)).collect();
-        CharClass::new(ranges)
-    }
-
-    fn classes(classes: &[&[(char, char)]]) -> CharClass {
-        let mut cls = CharClass::empty();
-        for &ranges in classes {
-            cls.ranges.extend(class(ranges));
-        }
-        cls.canonicalize()
-    }
-
-    fn bclass(ranges: &[(u8, u8)]) -> ByteClass {
-        let ranges = ranges.iter().cloned()
-                           .map(|(c1, c2)| ByteRange::new(c1, c2)).collect();
-        ByteClass::new(ranges)
-    }
-
-    fn asciid() -> CharClass {
-        ascii_class("digit").unwrap()
-    }
-
-    fn asciis() -> CharClass {
-        ascii_class("space").unwrap()
-    }
-
-    fn asciiw() -> CharClass {
-        ascii_class("word").unwrap()
-    }
-
-    fn asciid_bytes() -> ByteClass {
-        asciid().to_byte_class()
-    }
-
-    fn asciis_bytes() -> ByteClass {
-        asciis().to_byte_class()
-    }
-
-    fn asciiw_bytes() -> ByteClass {
-        asciiw().to_byte_class()
-    }
-
-    #[test]
-    fn empty() {
-        assert_eq!(p(""), Expr::Empty);
-    }
-
-    #[test]
-    fn literal() {
-        assert_eq!(p("a"), lit('a'));
-        assert_eq!(pb("(?-u)a"), blit(b'a'));
-    }
-
-    #[test]
-    fn literal_string() {
-        assert_eq!(p("ab"), Expr::Concat(vec![lit('a'), lit('b')]));
-        assert_eq!(pb("(?-u)ab"), Expr::Concat(vec![blit(b'a'), blit(b'b')]));
-    }
-
-    #[test]
-    fn start_literal() {
-        assert_eq!(p("^a"), Expr::Concat(vec![
-            Expr::StartText,
-            Expr::Literal { chars: vec!['a'], casei: false },
-        ]));
-    }
-
-    #[test]
-    fn repeat_zero_or_one_greedy() {
-        assert_eq!(p("a?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrOne,
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_zero_or_one_greedy_concat() {
-        assert_eq!(p("ab?"), Expr::Concat(vec![
-            lit('a'),
-            Expr::Repeat {
-                e: b(lit('b')),
-                r: Repeater::ZeroOrOne,
-                greedy: true,
-            },
-        ]));
-    }
-
-    #[test]
-    fn repeat_zero_or_one_nongreedy() {
-        assert_eq!(p("a??"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrOne,
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_one_or_more_greedy() {
-        assert_eq!(p("a+"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::OneOrMore,
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_one_or_more_nongreedy() {
-        assert_eq!(p("a+?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::OneOrMore,
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_zero_or_more_greedy() {
-        assert_eq!(p("a*"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrMore,
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_zero_or_more_nongreedy() {
-        assert_eq!(p("a*?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrMore,
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_exact() {
-        assert_eq!(p("a{5}"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(5) },
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_min() {
-        assert_eq!(p("a{5,}"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: None },
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_min_max() {
-        assert_eq!(p("a{5,10}"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(10) },
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_exact_nongreedy() {
-        assert_eq!(p("a{5}?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(5) },
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_min_nongreedy() {
-        assert_eq!(p("a{5,}?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: None },
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_min_max_nongreedy() {
-        assert_eq!(p("a{5,10}?"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(10) },
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn repeat_counted_whitespace() {
-        assert_eq!(p("a{ 5   }"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(5) },
-            greedy: true,
-        });
-        assert_eq!(p("a{ 5 , 10 }"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(10) },
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn group_literal() {
-        assert_eq!(p("(a)"), Expr::Group {
-            e: b(lit('a')),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn group_literal_concat() {
-        assert_eq!(p("(ab)"), Expr::Group {
-            e: b(c(&[lit('a'), lit('b')])),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn alt_two() {
-        assert_eq!(p("a|b"), Expr::Alternate(vec![lit('a'), lit('b')]));
-    }
-
-    #[test]
-    fn alt_many() {
-        assert_eq!(p("a|b|c"), Expr::Alternate(vec![
-            lit('a'), lit('b'), lit('c'),
-        ]));
-    }
-
-    #[test]
-    fn alt_many_concat() {
-        assert_eq!(p("ab|bc|cd"), Expr::Alternate(vec![
-            c(&[lit('a'), lit('b')]),
-            c(&[lit('b'), lit('c')]),
-            c(&[lit('c'), lit('d')]),
-        ]));
-    }
-
-    #[test]
-    fn alt_group_two() {
-        assert_eq!(p("(a|b)"), Expr::Group {
-            e: b(Expr::Alternate(vec![lit('a'), lit('b')])),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn alt_group_many() {
-        assert_eq!(p("(a|b|c)"), Expr::Group {
-            e: b(Expr::Alternate(vec![lit('a'), lit('b'), lit('c')])),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn alt_group_many_concat() {
-        assert_eq!(p("(ab|bc|cd)"), Expr::Group {
-            e: b(Expr::Alternate(vec![
-                c(&[lit('a'), lit('b')]),
-                c(&[lit('b'), lit('c')]),
-                c(&[lit('c'), lit('d')]),
-            ])),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn alt_group_nested() {
-        assert_eq!(p("(ab|(bc|(cd)))"), Expr::Group {
-            e: b(Expr::Alternate(vec![
-                c(&[lit('a'), lit('b')]),
-                Expr::Group {
-                    e: b(Expr::Alternate(vec![
-                        c(&[lit('b'), lit('c')]),
-                        Expr::Group {
-                            e: b(c(&[lit('c'), lit('d')])),
-                            i: Some(3),
-                            name: None,
-                        }
-                    ])),
-                    i: Some(2),
-                    name: None,
-                },
-            ])),
-            i: Some(1),
-            name: None,
-        });
-    }
-
-    #[test]
-    fn group_name() {
-        assert_eq!(p("(?P<foo>a)"), Expr::Group {
-            e: b(lit('a')),
-            i: Some(1),
-            name: Some("foo".into()),
-        });
-    }
-
-    #[test]
-    fn group_no_capture() {
-        assert_eq!(p("(?:a)"), Expr::Group {
-            e: b(lit('a')),
-            i: None,
-            name: None,
-        });
-    }
-
-    #[test]
-    fn group_flags() {
-        assert_eq!(p("(?i:a)"), Expr::Group {
-            e: b(liti('a')),
-            i: None,
-            name: None,
-        });
-        assert_eq!(pb("(?i-u:a)"), Expr::Group {
-            e: b(bliti(b'a')),
-            i: None,
-            name: None,
-        });
-    }
-
-    #[test]
-    fn group_flags_returned() {
-        assert_eq!(p("(?i:a)a"), c(&[
-            Expr::Group {
-                e: b(liti('a')),
-                i: None,
-                name: None,
-            },
-            lit('a'),
-        ]));
-        assert_eq!(pb("(?i-u:a)a"), c(&[
-            Expr::Group {
-                e: b(bliti(b'a')),
-                i: None,
-                name: None,
-            },
-            lit('a'),
-        ]));
-    }
-
-    #[test]
-    fn group_flags_retained() {
-        assert_eq!(p("(?i)(?-i:a)a"), c(&[
-            Expr::Group {
-                e: b(lit('a')),
-                i: None,
-                name: None,
-            },
-            liti('a'),
-        ]));
-        assert_eq!(pb("(?i-u)(?u-i:a)a"), c(&[
-            Expr::Group {
-                e: b(lit('a')),
-                i: None,
-                name: None,
-            },
-            bliti(b'a'),
-        ]));
-    }
-
-    #[test]
-    fn flags_inline() {
-        assert_eq!(p("(?i)a"), liti('a'));
-    }
-
-    #[test]
-    fn flags_inline_multiple() {
-        assert_eq!(p("(?is)a."), c(&[liti('a'), Expr::AnyChar]));
-    }
-
-    #[test]
-    fn flags_inline_multiline() {
-        assert_eq!(p("(?m)^(?-m)$"), c(&[Expr::StartLine, Expr::EndText]));
-    }
-
-    #[test]
-    fn flags_inline_swap_greed() {
-        assert_eq!(p("(?U)a*a*?(?i-U)a*a*?"), c(&[
-            Expr::Repeat {
-                e: b(lit('a')),
-                r: Repeater::ZeroOrMore,
-                greedy: false,
-            },
-            Expr::Repeat {
-                e: b(lit('a')),
-                r: Repeater::ZeroOrMore,
-                greedy: true,
-            },
-            Expr::Repeat {
-                e: b(liti('a')),
-                r: Repeater::ZeroOrMore,
-                greedy: true,
-            },
-            Expr::Repeat {
-                e: b(liti('a')),
-                r: Repeater::ZeroOrMore,
-                greedy: false,
-            },
-        ]));
-    }
-
-    #[test]
-    fn flags_inline_multiple_negate_one() {
-        assert_eq!(p("(?is)a.(?i-s)a."), c(&[
-            liti('a'), Expr::AnyChar, liti('a'), Expr::AnyCharNoNL,
-        ]));
-    }
-
-    #[test]
-    fn any_byte() {
-        assert_eq!(
-            pb("(?-u).(?u)."), c(&[Expr::AnyByteNoNL, Expr::AnyCharNoNL]));
-        assert_eq!(
-            pb("(?s)(?-u).(?u)."), c(&[Expr::AnyByte, Expr::AnyChar]));
-    }
-
-    #[test]
-    fn flags_inline_negate() {
-        assert_eq!(p("(?i)a(?-i)a"), c(&[liti('a'), lit('a')]));
-    }
-
-    #[test]
-    fn flags_group_inline() {
-        assert_eq!(p("(a(?i)a)a"), c(&[
-            Expr::Group {
-                e: b(c(&[lit('a'), liti('a')])),
-                i: Some(1),
-                name: None,
-            },
-            lit('a'),
-        ]));
-    }
-
-    #[test]
-    fn flags_group_inline_retain() {
-        assert_eq!(p("(?i)((?-i)a)a"), c(&[
-            Expr::Group {
-                e: b(lit('a')),
-                i: Some(1),
-                name: None,
-            },
-            liti('a'),
-        ]));
-    }
-
-    #[test]
-    fn flags_default_casei() {
-        let flags = Flags { casei: true, .. Flags::default() };
-        assert_eq!(pf("a", flags), liti('a'));
-    }
-
-    #[test]
-    fn flags_default_multi() {
-        let flags = Flags { multi: true, .. Flags::default() };
-        assert_eq!(pf("^", flags), Expr::StartLine);
-    }
-
-    #[test]
-    fn flags_default_dotnl() {
-        let flags = Flags { dotnl: true, .. Flags::default() };
-        assert_eq!(pf(".", flags), Expr::AnyChar);
-    }
-
-    #[test]
-    fn flags_default_swap_greed() {
-        let flags = Flags { swap_greed: true, .. Flags::default() };
-        assert_eq!(pf("a+", flags), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::OneOrMore,
-            greedy: false,
-        });
-    }
-
-    #[test]
-    fn flags_default_ignore_space() {
-        let flags = Flags { ignore_space: true, .. Flags::default() };
-        assert_eq!(pf(" a ", flags), lit('a'));
-    }
-
-    #[test]
-    fn escape_simple() {
-        assert_eq!(p(r"\a\f\t\n\r\v"), c(&[
-            lit('\x07'), lit('\x0C'), lit('\t'),
-            lit('\n'), lit('\r'), lit('\x0B'),
-        ]));
-    }
-
-    #[test]
-    fn escape_boundaries() {
-        assert_eq!(p(r"\A\z\b\B"), c(&[
-            Expr::StartText, Expr::EndText,
-            Expr::WordBoundary, Expr::NotWordBoundary,
-        ]));
-        assert_eq!(pb(r"(?-u)\b\B"), c(&[
-            Expr::WordBoundaryAscii, Expr::NotWordBoundaryAscii,
-        ]));
-    }
-
-    #[test]
-    fn escape_punctuation() {
-        assert_eq!(p(r"\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#"), c(&[
-            lit('\\'), lit('.'), lit('+'), lit('*'), lit('?'),
-            lit('('), lit(')'), lit('|'), lit('['), lit(']'),
-            lit('{'), lit('}'), lit('^'), lit('$'), lit('#'),
-        ]));
-    }
-
-    #[test]
-    fn escape_octal() {
-        assert_eq!(p(r"\123"), lit('S'));
-        assert_eq!(p(r"\1234"), c(&[lit('S'), lit('4')]));
-
-        assert_eq!(pb(r"(?-u)\377"), blit(0xFF));
-    }
-
-    #[test]
-    fn escape_hex2() {
-        assert_eq!(p(r"\x53"), lit('S'));
-        assert_eq!(p(r"\x534"), c(&[lit('S'), lit('4')]));
-
-        assert_eq!(pb(r"(?-u)\xff"), blit(0xFF));
-        assert_eq!(pb(r"(?-u)\x00"), blit(0x0));
-        assert_eq!(pb(r"(?-u)[\x00]"),
-                   Expr::ClassBytes(bclass(&[(b'\x00', b'\x00')])));
-        assert_eq!(pb(r"(?-u)[^\x00]"),
-                   Expr::ClassBytes(bclass(&[(b'\x01', b'\xFF')])));
-    }
-
-    #[test]
-    fn escape_hex() {
-        assert_eq!(p(r"\x{53}"), lit('S'));
-        assert_eq!(p(r"\x{53}4"), c(&[lit('S'), lit('4')]));
-        assert_eq!(p(r"\x{2603}"), lit('\u{2603}'));
-
-        assert_eq!(pb(r"(?-u)\x{00FF}"), blit(0xFF));
-    }
-
-    #[test]
-    fn escape_unicode_name() {
-        assert_eq!(p(r"\p{Yi}"), Expr::Class(class(YI)));
-    }
-
-    #[test]
-    fn escape_unicode_letter() {
-        assert_eq!(p(r"\pZ"), Expr::Class(class(&[
-            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
-            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
-            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
-            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
-        ])));
-    }
-
-    #[test]
-    fn escape_unicode_name_case_fold() {
-        assert_eq!(p(r"(?i)\p{Yi}"), Expr::Class(class(YI).case_fold()));
-    }
-
-    #[test]
-    fn escape_unicode_letter_case_fold() {
-        assert_eq!(p(r"(?i)\pZ"), Expr::Class(class(&[
-            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
-            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
-            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
-            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
-        ]).case_fold()));
-    }
-
-    #[test]
-    fn escape_unicode_name_negate() {
-        assert_eq!(p(r"\P{Yi}"), Expr::Class(class(YI).negate()));
-    }
-
-    #[test]
-    fn escape_unicode_letter_negate() {
-        assert_eq!(p(r"\PZ"), Expr::Class(class(&[
-            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
-            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
-            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
-            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
-        ]).negate()));
-    }
-
-    #[test]
-    fn escape_unicode_name_negate_case_fold() {
-        assert_eq!(p(r"(?i)\P{Yi}"),
-                   Expr::Class(class(YI).negate().case_fold()));
-    }
-
-    #[test]
-    fn escape_unicode_letter_negate_case_fold() {
-        assert_eq!(p(r"(?i)\PZ"), Expr::Class(class(&[
-            ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'),
-            ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
-            ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
-            ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
-        ]).negate().case_fold()));
-    }
-
-    #[test]
-    fn escape_perl_d() {
-        assert_eq!(p(r"\d"), Expr::Class(class(PERLD)));
-        assert_eq!(pb(r"(?-u)\d"), Expr::Class(asciid()));
-    }
-
-    #[test]
-    fn escape_perl_s() {
-        assert_eq!(p(r"\s"), Expr::Class(class(PERLS)));
-        assert_eq!(pb(r"(?-u)\s"), Expr::Class(asciis()));
-    }
-
-    #[test]
-    fn escape_perl_w() {
-        assert_eq!(p(r"\w"), Expr::Class(class(PERLW)));
-        assert_eq!(pb(r"(?-u)\w"), Expr::Class(asciiw()));
-    }
-
-    #[test]
-    fn escape_perl_d_negate() {
-        assert_eq!(p(r"\D"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(pb(r"(?-u)\D"), Expr::Class(asciid().negate()));
-    }
-
-    #[test]
-    fn escape_perl_s_negate() {
-        assert_eq!(p(r"\S"), Expr::Class(class(PERLS).negate()));
-        assert_eq!(pb(r"(?-u)\S"), Expr::Class(asciis().negate()));
-    }
-
-    #[test]
-    fn escape_perl_w_negate() {
-        assert_eq!(p(r"\W"), Expr::Class(class(PERLW).negate()));
-        assert_eq!(pb(r"(?-u)\W"), Expr::Class(asciiw().negate()));
-    }
-
-    #[test]
-    fn escape_perl_d_case_fold() {
-        assert_eq!(p(r"(?i)\d"), Expr::Class(class(PERLD).case_fold()));
-        assert_eq!(pb(r"(?i-u)\d"), Expr::Class(asciid().case_fold()));
-    }
-
-    #[test]
-    fn escape_perl_s_case_fold() {
-        assert_eq!(p(r"(?i)\s"), Expr::Class(class(PERLS).case_fold()));
-        assert_eq!(pb(r"(?i-u)\s"), Expr::Class(asciis().case_fold()));
-    }
-
-    #[test]
-    fn escape_perl_w_case_fold() {
-        assert_eq!(p(r"(?i)\w"), Expr::Class(class(PERLW).case_fold()));
-        assert_eq!(pb(r"(?i-u)\w"), Expr::Class(asciiw().case_fold()));
-    }
-
-    #[test]
-    fn escape_perl_d_case_fold_negate() {
-        assert_eq!(p(r"(?i)\D"),
-                   Expr::Class(class(PERLD).case_fold().negate()));
-        let bytes = asciid().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)\D"), Expr::Class(bytes));
-    }
-
-    #[test]
-    fn escape_perl_s_case_fold_negate() {
-        assert_eq!(p(r"(?i)\S"),
-                   Expr::Class(class(PERLS).case_fold().negate()));
-        let bytes = asciis().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)\S"), Expr::Class(bytes));
-    }
-
-    #[test]
-    fn escape_perl_w_case_fold_negate() {
-        assert_eq!(p(r"(?i)\W"),
-                   Expr::Class(class(PERLW).case_fold().negate()));
-        let bytes = asciiw().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)\W"), Expr::Class(bytes));
-    }
-
-    #[test]
-    fn class_singleton() {
-        assert_eq!(p(r"[a]"), Expr::Class(class(&[('a', 'a')])));
-        assert_eq!(p(r"[\x00]"), Expr::Class(class(&[('\x00', '\x00')])));
-        assert_eq!(p(r"[\n]"), Expr::Class(class(&[('\n', '\n')])));
-        assert_eq!(p("[\n]"), Expr::Class(class(&[('\n', '\n')])));
-
-        assert_eq!(pb(r"(?-u)[a]"), Expr::ClassBytes(bclass(&[(b'a', b'a')])));
-        assert_eq!(pb(r"(?-u)[\x00]"), Expr::ClassBytes(bclass(&[(0, 0)])));
-        assert_eq!(pb(r"(?-u)[\xFF]"),
-                   Expr::ClassBytes(bclass(&[(0xFF, 0xFF)])));
-        assert_eq!(pb("(?-u)[\n]"),
-                   Expr::ClassBytes(bclass(&[(b'\n', b'\n')])));
-        assert_eq!(pb(r"(?-u)[\n]"),
-                   Expr::ClassBytes(bclass(&[(b'\n', b'\n')])));
-    }
-
-    #[test]
-    fn class_singleton_negate() {
-        assert_eq!(p(r"[^a]"), Expr::Class(class(&[
-            ('\x00', '\x60'), ('\x62', '\u{10FFFF}'),
-        ])));
-        assert_eq!(p(r"[^\x00]"), Expr::Class(class(&[
-            ('\x01', '\u{10FFFF}'),
-        ])));
-        assert_eq!(p(r"[^\n]"), Expr::Class(class(&[
-            ('\x00', '\x09'), ('\x0b', '\u{10FFFF}'),
-        ])));
-        assert_eq!(p("[^\n]"), Expr::Class(class(&[
-            ('\x00', '\x09'), ('\x0b', '\u{10FFFF}'),
-        ])));
-
-        assert_eq!(pb(r"(?-u)[^a]"), Expr::ClassBytes(bclass(&[
-            (0x00, 0x60), (0x62, 0xFF),
-        ])));
-        assert_eq!(pb(r"(?-u)[^\x00]"), Expr::ClassBytes(bclass(&[
-            (0x01, 0xFF),
-        ])));
-        assert_eq!(pb(r"(?-u)[^\n]"), Expr::ClassBytes(bclass(&[
-            (0x00, 0x09), (0x0B, 0xFF),
-        ])));
-        assert_eq!(pb("(?-u)[^\n]"), Expr::ClassBytes(bclass(&[
-            (0x00, 0x09), (0x0B, 0xFF),
-        ])));
-    }
-
-    #[test]
-    fn class_singleton_class() {
-        assert_eq!(p(r"[\d]"), Expr::Class(class(PERLD)));
-        assert_eq!(p(r"[\p{Yi}]"), Expr::Class(class(YI)));
-
-        let bytes = class(PERLD).to_byte_class();
-        assert_eq!(pb(r"(?-u)[\d]"), Expr::ClassBytes(bytes));
-    }
-
-    #[test]
-    fn class_singleton_class_negate() {
-        assert_eq!(p(r"[^\d]"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(p(r"[^\w]"), Expr::Class(class(PERLW).negate()));
-        assert_eq!(p(r"[^\s]"), Expr::Class(class(PERLS).negate()));
-
-        let bytes = asciid_bytes().negate();
-        assert_eq!(pb(r"(?-u)[^\d]"), Expr::ClassBytes(bytes));
-        let bytes = asciiw_bytes().negate();
-        assert_eq!(pb(r"(?-u)[^\w]"), Expr::ClassBytes(bytes));
-        let bytes = asciis_bytes().negate();
-        assert_eq!(pb(r"(?-u)[^\s]"), Expr::ClassBytes(bytes));
-    }
-
-    #[test]
-    fn class_singleton_class_negate_negate() {
-        assert_eq!(p(r"[^\D]"), Expr::Class(class(PERLD)));
-        assert_eq!(p(r"[^\W]"), Expr::Class(class(PERLW)));
-        assert_eq!(p(r"[^\S]"), Expr::Class(class(PERLS)));
-
-        assert_eq!(pb(r"(?-u)[^\D]"), Expr::ClassBytes(asciid_bytes()));
-        assert_eq!(pb(r"(?-u)[^\W]"), Expr::ClassBytes(asciiw_bytes()));
-        assert_eq!(pb(r"(?-u)[^\S]"), Expr::ClassBytes(asciis_bytes()));
-    }
-
-    #[test]
-    fn class_singleton_class_casei() {
-        assert_eq!(p(r"(?i)[\d]"), Expr::Class(class(PERLD).case_fold()));
-        assert_eq!(p(r"(?i)[\p{Yi}]"), Expr::Class(class(YI).case_fold()));
-
-        assert_eq!(pb(r"(?i-u)[\d]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold()));
-    }
-
-    #[test]
-    fn class_singleton_class_negate_casei() {
-        assert_eq!(p(r"(?i)[^\d]"),
-                   Expr::Class(class(PERLD).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^\w]"),
-                   Expr::Class(class(PERLW).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^\s]"),
-                   Expr::Class(class(PERLS).case_fold().negate()));
-
-        let bytes = asciid_bytes().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)[^\d]"), Expr::ClassBytes(bytes));
-        let bytes = asciiw_bytes().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)[^\w]"), Expr::ClassBytes(bytes));
-        let bytes = asciis_bytes().case_fold().negate();
-        assert_eq!(pb(r"(?i-u)[^\s]"), Expr::ClassBytes(bytes));
-    }
-
-    #[test]
-    fn class_singleton_class_negate_negate_casei() {
-        assert_eq!(p(r"(?i)[^\D]"), Expr::Class(class(PERLD).case_fold()));
-        assert_eq!(p(r"(?i)[^\W]"), Expr::Class(class(PERLW).case_fold()));
-        assert_eq!(p(r"(?i)[^\S]"), Expr::Class(class(PERLS).case_fold()));
-
-        assert_eq!(pb(r"(?i-u)[^\D]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold()));
-        assert_eq!(pb(r"(?i-u)[^\W]"),
-                   Expr::ClassBytes(asciiw_bytes().case_fold()));
-        assert_eq!(pb(r"(?i-u)[^\S]"),
-                   Expr::ClassBytes(asciis_bytes().case_fold()));
-    }
-
-    #[test]
-    fn class_multiple_class() {
-        assert_eq!(p(r"[\d\p{Yi}]"), Expr::Class(classes(&[
-            PERLD, YI,
-        ])));
-    }
-
-    #[test]
-    fn class_multiple_class_negate() {
-        assert_eq!(p(r"[^\d\p{Yi}]"), Expr::Class(classes(&[
-            PERLD, YI,
-        ]).negate()));
-    }
-
-    #[test]
-    fn class_multiple_class_negate_negate() {
-        let nperlw = class(PERLW).negate();
-        let nyi = class(YI).negate();
-        let cls = CharClass::empty().merge(nperlw).merge(nyi);
-        assert_eq!(p(r"[^\W\P{Yi}]"), Expr::Class(cls.negate()));
-    }
-
-    #[test]
-    fn class_multiple_class_casei() {
-        assert_eq!(p(r"(?i)[\d\p{Yi}]"), Expr::Class(classes(&[
-            PERLD, YI,
-        ]).case_fold()));
-    }
-
-    #[test]
-    fn class_multiple_class_negate_casei() {
-        assert_eq!(p(r"(?i)[^\d\p{Yi}]"), Expr::Class(classes(&[
-            PERLD, YI,
-        ]).case_fold().negate()));
-    }
-
-    #[test]
-    fn class_multiple_class_negate_negate_casei() {
-        let nperlw = class(PERLW).negate();
-        let nyi = class(YI).negate();
-        let class = CharClass::empty().merge(nperlw).merge(nyi);
-        assert_eq!(p(r"(?i)[^\W\P{Yi}]"),
-                   Expr::Class(class.case_fold().negate()));
-    }
-
-    #[test]
-    fn class_class_hypen() {
-        assert_eq!(p(r"[\p{Yi}-]"), Expr::Class(classes(&[
-            &[('-', '-')], YI,
-        ])));
-        assert_eq!(p(r"[\p{Yi}-a]"), Expr::Class(classes(&[
-            &[('-', '-')], &[('a', 'a')], YI,
-        ])));
-    }
-
-    #[test]
-    fn class_brackets() {
-        assert_eq!(p(r"[]]"), Expr::Class(class(&[(']', ']')])));
-        assert_eq!(p(r"[]\[]"), Expr::Class(class(&[('[', '['), (']', ']')])));
-        assert_eq!(p(r"[\[]]"), Expr::Concat(vec![
-            Expr::Class(class(&[('[', '[')])),
-            lit(']'),
-        ]));
-    }
-
-    #[test]
-    fn class_brackets_hypen() {
-        assert_eq!(p("[]-]"), Expr::Class(class(&[('-', '-'), (']', ']')])));
-        assert_eq!(p("[-]]"), Expr::Concat(vec![
-            Expr::Class(class(&[('-', '-')])),
-            lit(']'),
-        ]));
-    }
-
-    #[test]
-    fn class_nested_class_union() {
-        assert_eq!(p(r"[c[a-b]]"), Expr::Class(class(&[('a', 'c')])));
-        assert_eq!(p(r"[[a-b]]"), Expr::Class(class(&[('a', 'b')])));
-        assert_eq!(p(r"[[c][a-b]]"), Expr::Class(class(&[('a', 'c')])));
-
-        assert_eq!(pb(r"(?-u)[c[a-b]]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'c')])));
-        assert_eq!(pb(r"(?-u)[[a-b]]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'b')])));
-        assert_eq!(pb(r"(?-u)[[c][a-b]]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'c')])));
-    }
-
-    #[test]
-    fn class_nested_class_union_casei() {
-        assert_eq!(p(r"(?i)[c[a-b]]"),
-                   Expr::Class(class(&[('a', 'c')]).case_fold()));
-        assert_eq!(p(r"(?i)[[a-b]]"),
-                   Expr::Class(class(&[('a', 'b')]).case_fold()));
-        assert_eq!(p(r"(?i)[[c][a-b]]"),
-                   Expr::Class(class(&[('a', 'c')]).case_fold()));
-
-        assert_eq!(pb(r"(?i-u)[[\d]]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold()));
-    }
-
-    #[test]
-    fn class_nested_class_negate() {
-        assert_eq!(p(r"[^[\d]]"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(p(r"[[^\d]]"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(p(r"[^[^\d]]"), Expr::Class(class(PERLD)));
-        assert_eq!(p(r"[^[\w]]"), Expr::Class(class(PERLW).negate()));
-        assert_eq!(p(r"[[^\w]]"), Expr::Class(class(PERLW).negate()));
-        assert_eq!(p(r"[^[^\w]]"), Expr::Class(class(PERLW)));
-        assert_eq!(p(r"[a-b[^c]]"),
-                   Expr::Class(class(&[('\u{0}', 'b'), ('d', '\u{10FFFF}')])));
-
-        assert_eq!(pb(r"(?-u)[^[\d]]"),
-                   Expr::ClassBytes(asciid_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[[^\d]]"),
-                   Expr::ClassBytes(asciid_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[^[^\d]]"),
-                   Expr::ClassBytes(asciid_bytes()));
-        assert_eq!(pb(r"(?-u)[^[\w]]"),
-                   Expr::ClassBytes(asciiw_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[[^\w]]"),
-                   Expr::ClassBytes(asciiw_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[^[^\w]]"),
-                   Expr::ClassBytes(asciiw_bytes()));
-        assert_eq!(pb(r"(?-u)[a-b[^c]]"),
-                   Expr::ClassBytes(bclass(&[(b'\x00', b'b'), (b'd', b'\xFF')])))
-    }
-
-    #[test]
-    fn class_nested_class_negate_casei() {
-        assert_eq!(p(r"(?i)[^[\d]]"),
-                   Expr::Class(class(PERLD).case_fold().negate()));
-        assert_eq!(p(r"(?i)[[^\d]]"),
-                   Expr::Class(class(PERLD).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^[^\d]]"),
-                   Expr::Class(class(PERLD).case_fold()));
-        assert_eq!(p(r"(?i)[^[\w]]"),
-                   Expr::Class(class(PERLW).case_fold().negate()));
-        assert_eq!(p(r"(?i)[[^\w]]"),
-                   Expr::Class(class(PERLW).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^[^\w]]"),
-                   Expr::Class(class(PERLW).case_fold()));
-        let mut cls = CharClass::empty().negate();
-        cls.remove('c');
-        cls.remove('C');
-        assert_eq!(p(r"(?i)[a-b[^c]]"), Expr::Class(cls));
-
-        assert_eq!(pb(r"(?i-u)[^[\d]]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[[^\d]]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[^[^\d]]"),
-                   Expr::ClassBytes(asciid_bytes().case_fold()));
-        assert_eq!(pb(r"(?i-u)[^[\w]]"),
-                   Expr::ClassBytes(asciiw_bytes().case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[[^\w]]"),
-                   Expr::ClassBytes(asciiw_bytes().case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[^[^\w]]"),
-                   Expr::ClassBytes(asciiw_bytes().case_fold()));
-        let mut bytes = ByteClass::new(vec![]).negate();
-        bytes.remove(b'c');
-        bytes.remove(b'C');
-        assert_eq!(pb(r"(?i-u)[a-b[^c]]"), Expr::ClassBytes(bytes));
-    }
-
-    #[test]
-    fn class_nested_class_brackets_hyphen() {
-        // This is confusing, but `]` is allowed if first character within a class
-        // It parses as a nested class with the `]` and `-` characters
-        assert_eq!(p(r"[[]-]]"), Expr::Class(class(&[('-', '-'), (']', ']')])));
-        assert_eq!(p(r"[[\[]]"), Expr::Class(class(&[('[', '[')])));
-        assert_eq!(p(r"[[\]]]"), Expr::Class(class(&[(']', ']')])));
-    }
-
-    #[test]
-    fn class_nested_class_deep_nesting() {
-        // Makes sure that implementation can handle deep nesting.
-        // With recursive parsing, this regex would blow the stack size.
-        use std::iter::repeat;
-        let nesting = 10_000;
-        let open: String = repeat("[").take(nesting).collect();
-        let close: String = repeat("]").take(nesting).collect();
-        let s  = format!("{}a{}", open, close);
-        assert_eq!(p(&s), Expr::Class(class(&[('a', 'a')])));
-    }
-
-    #[test]
-    fn class_intersection_ranges() {
-        assert_eq!(p(r"[abc&&b-c]"), Expr::Class(class(&[('b', 'c')])));
-        assert_eq!(p(r"[abc&&[b-c]]"), Expr::Class(class(&[('b', 'c')])));
-        assert_eq!(p(r"[[abc]&&[b-c]]"), Expr::Class(class(&[('b', 'c')])));
-        assert_eq!(p(r"[a-z&&b-y&&c-x]"), Expr::Class(class(&[('c', 'x')])));
-        assert_eq!(p(r"[c-da-b&&a-d]"), Expr::Class(class(&[('a', 'd')])));
-        assert_eq!(p(r"[a-d&&c-da-b]"), Expr::Class(class(&[('a', 'd')])));
-
-        assert_eq!(pb(r"(?-u)[abc&&b-c]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
-        assert_eq!(pb(r"(?-u)[abc&&[b-c]]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
-        assert_eq!(pb(r"(?-u)[[abc]&&[b-c]]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')])));
-        assert_eq!(pb(r"(?-u)[a-z&&b-y&&c-x]"),
-                   Expr::ClassBytes(bclass(&[(b'c', b'x')])));
-        assert_eq!(pb(r"(?-u)[c-da-b&&a-d]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'd')])));
-    }
-
-    #[test]
-    fn class_intersection_ranges_casei() {
-        assert_eq!(p(r"(?i)[abc&&b-c]"),
-                   Expr::Class(class(&[('b', 'c')]).case_fold()));
-        assert_eq!(p(r"(?i)[abc&&[b-c]]"),
-                   Expr::Class(class(&[('b', 'c')]).case_fold()));
-        assert_eq!(p(r"(?i)[[abc]&&[b-c]]"),
-                   Expr::Class(class(&[('b', 'c')]).case_fold()));
-        assert_eq!(p(r"(?i)[a-z&&b-y&&c-x]"),
-                   Expr::Class(class(&[('c', 'x')]).case_fold()));
-        assert_eq!(p(r"(?i)[c-da-b&&a-d]"),
-                   Expr::Class(class(&[('a', 'd')]).case_fold()));
-
-        assert_eq!(pb(r"(?i-u)[abc&&b-c]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
-        assert_eq!(pb(r"(?i-u)[abc&&[b-c]]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
-        assert_eq!(pb(r"(?i-u)[[abc]&&[b-c]]"),
-                   Expr::ClassBytes(bclass(&[(b'b', b'c')]).case_fold()));
-        assert_eq!(pb(r"(?i-u)[a-z&&b-y&&c-x]"),
-                   Expr::ClassBytes(bclass(&[(b'c', b'x')]).case_fold()));
-        assert_eq!(pb(r"(?i-u)[c-da-b&&a-d]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'd')]).case_fold()));
-    }
-
-    #[test]
-    fn class_intersection_classes() {
-        assert_eq!(p(r"[\w&&\d]"), Expr::Class(class(PERLD)));
-        assert_eq!(p(r"[\w&&[[:ascii:]]]"), Expr::Class(asciiw()));
-        assert_eq!(p(r"[\x00-\xFF&&\pZ]"),
-                   Expr::Class(class(&[('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}')])));
-
-        assert_eq!(pb(r"(?-u)[\w&&\d]"), Expr::ClassBytes(asciid_bytes()));
-        assert_eq!(pb(r"(?-u)[\w&&[[:ascii:]]]"), Expr::ClassBytes(asciiw_bytes()));
-    }
-
-    #[test]
-    fn class_intersection_classes_casei() {
-        assert_eq!(p(r"(?i)[\w&&\d]"), Expr::Class(class(PERLD).case_fold()));
-        assert_eq!(p(r"(?i)[\w&&[[:ascii:]]]"), Expr::Class(asciiw().case_fold()));
-        assert_eq!(p(r"(?i)[\x00-\xFF&&\pZ]"),
-                   Expr::Class(class(&[('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}')])));
-
-        assert_eq!(pb(r"(?i-u)[\w&&\d]"), Expr::ClassBytes(asciid_bytes().case_fold()));
-        assert_eq!(pb(r"(?i-u)[\w&&[[:ascii:]]]"), Expr::ClassBytes(asciiw_bytes().case_fold()));
-    }
-
-    #[test]
-    fn class_intersection_negate() {
-        assert_eq!(p(r"[^\w&&\d]"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(p(r"[^[\w&&\d]]"), Expr::Class(class(PERLD).negate()));
-        assert_eq!(p(r"[^[^\w&&\d]]"), Expr::Class(class(PERLD)));
-        assert_eq!(p(r"[\w&&[^\d]]"),
-                   Expr::Class(class(PERLW).intersection(&class(PERLD).negate())));
-        assert_eq!(p(r"[[^\w]&&[^\d]]"),
-                   Expr::Class(class(PERLW).negate()));
-
-        assert_eq!(pb(r"(?-u)[^\w&&\d]"),
-                   Expr::ClassBytes(asciid_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[^[\w&&\d]]"),
-                   Expr::ClassBytes(asciid_bytes().negate()));
-        assert_eq!(pb(r"(?-u)[^[^\w&&\d]]"),
-                   Expr::ClassBytes(asciid_bytes()));
-        assert_eq!(pb(r"(?-u)[\w&&[^\d]]"),
-                   Expr::ClassBytes(asciiw().intersection(&asciid().negate()).to_byte_class()));
-        assert_eq!(pb(r"(?-u)[[^\w]&&[^\d]]"),
-                   Expr::ClassBytes(asciiw_bytes().negate()));
-    }
-
-    #[test]
-    fn class_intersection_negate_casei() {
-        assert_eq!(p(r"(?i)[^\w&&a-z]"),
-                   Expr::Class(class(&[('a', 'z')]).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^[\w&&a-z]]"),
-                   Expr::Class(class(&[('a', 'z')]).case_fold().negate()));
-        assert_eq!(p(r"(?i)[^[^\w&&a-z]]"),
-                   Expr::Class(class(&[('a', 'z')]).case_fold()));
-        assert_eq!(p(r"(?i)[\w&&[^a-z]]"),
-                   Expr::Class(
-                       class(PERLW).intersection(&class(&[('a', 'z')])
-                       .case_fold().negate())));
-        assert_eq!(p(r"(?i)[[^\w]&&[^a-z]]"),
-                   Expr::Class(class(PERLW).negate()));
-
-        assert_eq!(pb(r"(?i-u)[^\w&&a-z]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[^[\w&&a-z]]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold().negate()));
-        assert_eq!(pb(r"(?i-u)[^[^\w&&a-z]]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'z')]).case_fold()));
-        assert_eq!(pb(r"(?i-u)[\w&&[^a-z]]"),
-                   Expr::ClassBytes(bclass(&[(b'0', b'9'), (b'_', b'_')])));
-        assert_eq!(pb(r"(?i-u)[[^\w]&&[^a-z]]"),
-                   Expr::ClassBytes(asciiw_bytes().negate()));
-    }
-
-    #[test]
-    fn class_intersection_caret() {
-        // In `[a^]`, `^` does not need to be escaped, so it makes sense that
-        // `^` is also allowed to be unescaped after `&&`.
-        assert_eq!(p(r"[\^&&^]"), Expr::Class(class(&[('^', '^')])));
-    }
-
-    #[test]
-    fn class_intersection_brackets_hyphen() {
-        // `]` needs to be escaped after `&&` because it is not at the start of the class.
-        assert_eq!(p(r"[]&&\]]"), Expr::Class(class(&[(']', ']')])));
-
-        assert_eq!(p(r"[-&&-]"), Expr::Class(class(&[('-', '-')])));
-    }
-
-    #[test]
-    fn class_intersection_ampersand() {
-        // Unescaped `&` after `&&`
-        assert_eq!(p(r"[\&&&&]"), Expr::Class(class(&[('&', '&')])));
-        assert_eq!(p(r"[\&&&\&]"), Expr::Class(class(&[('&', '&')])));
-    }
-
-    #[test]
-    fn class_intersection_precedence() {
-        assert_eq!(p(r"[a-w&&[^c-g]z]"), Expr::Class(class(&[('a', 'b'), ('h', 'w')])));
-    }
-
-    #[test]
-    fn class_special_escaped_set_chars() {
-        // These tests ensure that some special characters require escaping
-        // for use in character classes. The intention is to use these
-        // characters to implement sets as described in UTS#18 RL1.3. Once
-        // that's done, these tests should be removed and replaced with others.
-        assert_eq!(p(r"[\[]"), Expr::Class(class(&[('[', '[')])));
-        assert_eq!(p(r"[&]"), Expr::Class(class(&[('&', '&')])));
-        assert_eq!(p(r"[\&]"), Expr::Class(class(&[('&', '&')])));
-        assert_eq!(p(r"[\&\&]"), Expr::Class(class(&[('&', '&')])));
-        assert_eq!(p(r"[\x00-&]"), Expr::Class(class(&[('\u{0}', '&')])));
-        assert_eq!(p(r"[&-\xFF]"), Expr::Class(class(&[('&', '\u{FF}')])));
-
-        assert_eq!(p(r"[~]"), Expr::Class(class(&[('~', '~')])));
-        assert_eq!(p(r"[\~]"), Expr::Class(class(&[('~', '~')])));
-        assert_eq!(p(r"[\~\~]"), Expr::Class(class(&[('~', '~')])));
-        assert_eq!(p(r"[\x00-~]"), Expr::Class(class(&[('\u{0}', '~')])));
-        assert_eq!(p(r"[~-\xFF]"), Expr::Class(class(&[('~', '\u{FF}')])));
-
-        assert_eq!(p(r"[+-\-]"), Expr::Class(class(&[('+', '-')])));
-        assert_eq!(p(r"[a-a\--\xFF]"), Expr::Class(class(&[
-            ('-', '\u{FF}'),
-        ])));
-    }
-
-    #[test]
-    fn class_overlapping() {
-        assert_eq!(p("[a-fd-h]"), Expr::Class(class(&[('a', 'h')])));
-        assert_eq!(p("[a-fg-m]"), Expr::Class(class(&[('a', 'm')])));
-
-        assert_eq!(pb("(?-u)[a-fd-h]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'h')])));
-        assert_eq!(pb("(?-u)[a-fg-m]"),
-                   Expr::ClassBytes(bclass(&[(b'a', b'm')])));
-    }
-
-    #[test]
-    fn ascii_classes() {
-        assert_eq!(p("[:blank:]"), Expr::Class(class(&[
-            (':', ':'), ('a', 'b'), ('k', 'l'), ('n', 'n'),
-        ])));
-        assert_eq!(p("[[:upper:]]"), Expr::Class(class(UPPER)));
-
-        assert_eq!(pb("(?-u)[[:upper:]]"),
-                   Expr::ClassBytes(class(UPPER).to_byte_class()));
-    }
-
-    #[test]
-    fn ascii_classes_not() {
-        assert_eq!(p("[:abc:]"),
-                   Expr::Class(class(&[(':', ':'), ('a', 'c')])));
-        assert_eq!(pb("(?-u)[:abc:]"),
-                   Expr::ClassBytes(bclass(&[(b':', b':'), (b'a', b'c')])));
-    }
-
-    #[test]
-    fn ascii_classes_multiple() {
-        assert_eq!(p("[[:lower:][:upper:]]"),
-                   Expr::Class(classes(&[UPPER, LOWER])));
-
-        assert_eq!(pb("(?-u)[[:lower:][:upper:]]"),
-                   Expr::ClassBytes(classes(&[UPPER, LOWER]).to_byte_class()));
-    }
-
-    #[test]
-    fn ascii_classes_negate() {
-        assert_eq!(p("[[:^upper:]]"), Expr::Class(class(UPPER).negate()));
-        assert_eq!(p("[^[:^upper:]]"), Expr::Class(class(UPPER)));
-
-        assert_eq!(pb("(?-u)[[:^upper:]]"),
-                   Expr::ClassBytes(class(UPPER).to_byte_class().negate()));
-        assert_eq!(pb("(?-u)[^[:^upper:]]"),
-                   Expr::ClassBytes(class(UPPER).to_byte_class()));
-    }
-
-    #[test]
-    fn ascii_classes_negate_multiple() {
-        let (nlower, nword) = (class(LOWER).negate(), class(WORD).negate());
-        let cls = CharClass::empty().merge(nlower).merge(nword);
-        assert_eq!(p("[[:^lower:][:^word:]]"), Expr::Class(cls.clone()));
-        assert_eq!(p("[^[:^lower:][:^word:]]"), Expr::Class(cls.negate()));
-    }
-
-    #[test]
-    fn ascii_classes_case_fold() {
-        assert_eq!(p("(?i)[[:upper:]]"),
-                   Expr::Class(class(UPPER).case_fold()));
-
-        assert_eq!(pb("(?i-u)[[:upper:]]"),
-                   Expr::ClassBytes(class(UPPER).to_byte_class().case_fold()));
-    }
-
-    #[test]
-    fn ascii_classes_negate_case_fold() {
-        assert_eq!(p("(?i)[[:^upper:]]"),
-                   Expr::Class(class(UPPER).case_fold().negate()));
-        assert_eq!(p("(?i)[^[:^upper:]]"),
-                   Expr::Class(class(UPPER).case_fold()));
-
-        assert_eq!(pb("(?i-u)[[:^upper:]]"),
-                   Expr::ClassBytes(
-                       class(UPPER).to_byte_class().case_fold().negate()));
-        assert_eq!(pb("(?i-u)[^[:^upper:]]"),
-                   Expr::ClassBytes(class(UPPER).to_byte_class().case_fold()));
-    }
-
-    #[test]
-    fn single_class_negate_case_fold() {
-        assert_eq!(p("(?i)[^x]"),
-                   Expr::Class(class(&[('x', 'x')]).case_fold().negate()));
-
-        assert_eq!(pb("(?i-u)[^x]"),
-                   Expr::ClassBytes(
-                       class(&[('x', 'x')])
-                       .to_byte_class().case_fold().negate()));
-    }
-
-    #[test]
-    fn ignore_space_empty() {
-        assert_eq!(p("(?x) "), Expr::Empty);
-    }
-
-    #[test]
-    fn ignore_space_literal() {
-        assert_eq!(p("(?x) a b c"), Expr::Concat(vec![
-            lit('a'), lit('b'), lit('c'),
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_literal_off() {
-        assert_eq!(p("(?x) a b c(?-x) a"), Expr::Concat(vec![
-            lit('a'), lit('b'), lit('c'), lit(' '), lit('a'),
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_class() {
-        assert_eq!(p("(?x)[a
-        - z
-]"), Expr::Class(class(&[('a', 'z')])));
-        assert_eq!(p("(?x)[  ^   a
-        - z
-]"), Expr::Class(class(&[('a', 'z')]).negate()));
-    }
-
-    #[test]
-    fn ignore_space_escape_octal() {
-        assert_eq!(p(r"(?x)\12 3"), Expr::Concat(vec![
-            lit('\n'),
-            lit('3'),
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_escape_hex() {
-        assert_eq!(p(r"(?x)\x { 53 }"), lit('S'));
-        assert_eq!(p(r"(?x)\x # comment
-{ # comment
-    53 # comment
-} # comment"), lit('S'));
-    }
-
-    #[test]
-    fn ignore_space_escape_hex2() {
-        assert_eq!(p(r"(?x)\x 53"), lit('S'));
-        assert_eq!(p(r"(?x)\x # comment
-        53 # comment"), lit('S'));
-    }
-
-    #[test]
-    fn ignore_space_escape_unicode_name() {
-        assert_eq!(p(r"(?x)\p # comment
-{ # comment
-    Yi # comment
-} # comment"), Expr::Class(class(YI)));
-    }
-
-    #[test]
-    fn ignore_space_repeat_counted() {
-        assert_eq!(p("(?x)a # comment
-{ # comment
-    5 # comment
-    , # comment
-    10 # comment
-}"), Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::Range { min: 5, max: Some(10) },
-            greedy: true,
-        });
-    }
-
-    #[test]
-    fn ignore_space_comments() {
-        assert_eq!(p(r"(?x)(?P<foo>
-    a # comment 1
-)(?P<bar>
-    z # comment 2
-)"), Expr::Concat(vec![
-        Expr::Group {
-            e: Box::new(lit('a')),
-            i: Some(1),
-            name: Some("foo".into()),
-        },
-        Expr::Group {
-            e: Box::new(lit('z')),
-            i: Some(2),
-            name: Some("bar".into()),
-        },
-    ]));
-    }
-
-    #[test]
-    fn ignore_space_comments_re_enable() {
-        assert_eq!(p(r"(?x)a # hi
-(?-x:#) # sweet"), Expr::Concat(vec![
-            lit('a'),
-            Expr::Group {
-                e: Box::new(lit('#')),
-                i: None,
-                name: None,
-            },
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_escape_punctuation() {
-        assert_eq!(p(r"(?x)\\\.\+\*\?\(\)\|\[\]\{\}\^\$\#"), c(&[
-            lit('\\'), lit('.'), lit('+'), lit('*'), lit('?'),
-            lit('('), lit(')'), lit('|'), lit('['), lit(']'),
-            lit('{'), lit('}'), lit('^'), lit('$'), lit('#'),
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_escape_hash() {
-        assert_eq!(p(r"(?x)a\# # hi there"), Expr::Concat(vec![
-            lit('a'),
-            lit('#'),
-        ]));
-    }
-
-    #[test]
-    fn ignore_space_escape_space() {
-        assert_eq!(p(r"(?x)a\  # hi there"), Expr::Concat(vec![
-            lit('a'),
-            lit(' '),
-        ]));
-    }
-
-    // Test every single possible error case.
-
-    macro_rules! test_err {
-        ($re:expr, $pos:expr, $kind:expr) => {
-            test_err!($re, $pos, $kind, Flags::default());
-        };
-        ($re:expr, $pos:expr, $kind:expr, $flags:expr) => {{
-            let err = Parser::parse($re, $flags).unwrap_err();
-            assert_eq!($pos, err.pos);
-            assert_eq!($kind, err.kind);
-            assert!($re.contains(&err.surround));
-        }}
-    }
-
-    #[test]
-    fn invalid_utf8_not_allowed() {
-        // let flags = Flags { unicode: false, .. Flags::default() };
-        test_err!(r"(?-u)\xFF", 9, ErrorKind::InvalidUtf8);
-        test_err!(r"(?-u).", 5, ErrorKind::InvalidUtf8);
-        test_err!(r"(?-u)(?s).", 9, ErrorKind::InvalidUtf8);
-        test_err!(r"(?-u)[\x00-\x80]", 15, ErrorKind::InvalidUtf8);
-        test_err!(r"(?-u)\222", 9, ErrorKind::InvalidUtf8);
-        test_err!(r"(?-u)\x{0080}", 13, ErrorKind::InvalidUtf8);
-    }
-
-    #[test]
-    fn unicode_char_not_allowed() {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!("☃(?-u:☃)", 7, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn unicode_class_not_allowed() {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"☃(?-u:\pL)", 9, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn unicode_class_literal_not_allowed() {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"(?-u)[☃]", 6, ErrorKind::UnicodeNotAllowed, flags);
-        test_err!(r"(?-u)[☃-☃]", 6, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn unicode_hex_not_allowed() {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"(?-u)\x{FFFF}", 13, ErrorKind::UnicodeNotAllowed, flags);
-        test_err!(r"(?-u)\x{100}", 12, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn unicode_octal_not_allowed() {
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"(?-u)\400", 9, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn error_repeat_no_expr_simple() {
-        test_err!("(*", 1, ErrorKind::RepeaterExpectsExpr);
-    }
-
-    #[test]
-    fn error_repeat_no_expr_counted() {
-        test_err!("({5}", 1, ErrorKind::RepeaterExpectsExpr);
-    }
-
-    #[test]
-    fn error_repeat_beginning_counted() {
-        test_err!("{5}", 0, ErrorKind::RepeaterExpectsExpr);
-    }
-
-    #[test]
-    fn error_repeat_illegal_exprs_simple() {
-        test_err!("a**", 2, ErrorKind::RepeaterUnexpectedExpr(Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrMore,
-            greedy: true,
-        }));
-        test_err!("a|*", 2,
-            ErrorKind::RepeaterUnexpectedExpr(Expr::Alternate(vec![lit('a')]))
-        );
-    }
-
-    #[test]
-    fn error_repeat_illegal_exprs_counted() {
-        test_err!("a*{5}", 2, ErrorKind::RepeaterUnexpectedExpr(Expr::Repeat {
-            e: b(lit('a')),
-            r: Repeater::ZeroOrMore,
-            greedy: true,
-        }));
-        test_err!("a|{5}", 2,
-            ErrorKind::RepeaterUnexpectedExpr(Expr::Alternate(vec![lit('a')]))
-        );
-    }
-
-    #[test]
-    fn error_repeat_empty_number() {
-        test_err!("a{}", 2, ErrorKind::MissingBase10);
-    }
-
-    #[test]
-    fn error_repeat_eof() {
-        test_err!("a{5", 3, ErrorKind::UnclosedRepeat);
-    }
-
-    #[test]
-    fn error_repeat_empty_number_eof() {
-        test_err!("a{xyz", 5, ErrorKind::InvalidBase10("xyz".into()));
-        test_err!("a{12,xyz", 8, ErrorKind::InvalidBase10("xyz".into()));
-    }
-
-    #[test]
-    fn error_repeat_invalid_number() {
-        test_err!("a{9999999999}", 12,
-                  ErrorKind::InvalidBase10("9999999999".into()));
-        test_err!("a{1,9999999999}", 14,
-                  ErrorKind::InvalidBase10("9999999999".into()));
-    }
-
-    #[test]
-    fn error_repeat_invalid_number_extra() {
-        test_err!("a{12x}", 5, ErrorKind::InvalidBase10("12x".into()));
-        test_err!("a{1,12x}", 7, ErrorKind::InvalidBase10("12x".into()));
-    }
-
-    #[test]
-    fn error_repeat_invalid_range() {
-        test_err!("a{2,1}", 5,
-                  ErrorKind::InvalidRepeatRange { min: 2, max: 1 });
-    }
-
-    #[test]
-    fn error_alternate_empty() {
-        test_err!("|a", 0, ErrorKind::EmptyAlternate);
-    }
-
-    #[test]
-    fn error_alternate_empty_with_group() {
-        test_err!("(|a)", 1, ErrorKind::EmptyAlternate);
-    }
-
-    #[test]
-    fn error_alternate_empty_with_alternate() {
-        test_err!("a||", 2, ErrorKind::EmptyAlternate);
-    }
-
-    #[test]
-    fn error_close_paren_unopened_empty() {
-        test_err!(")", 0, ErrorKind::UnopenedParen);
-    }
-
-    #[test]
-    fn error_close_paren_unopened() {
-        test_err!("ab)", 2, ErrorKind::UnopenedParen);
-    }
-
-    #[test]
-    fn error_close_paren_unopened_with_alt() {
-        test_err!("a|b)", 3, ErrorKind::UnopenedParen);
-    }
-
-    #[test]
-    fn error_close_paren_unclosed_with_alt() {
-        test_err!("(a|b", 0, ErrorKind::UnclosedParen);
-    }
-
-    #[test]
-    fn error_close_paren_empty_alt() {
-        test_err!("(a|)", 3, ErrorKind::EmptyAlternate);
-    }
-
-    #[test]
-    fn error_close_paren_empty_group() {
-        test_err!("()", 1, ErrorKind::EmptyGroup);
-    }
-
-    #[test]
-    fn error_close_paren_empty_group_with_name() {
-        test_err!("(?P<foo>)", 8, ErrorKind::EmptyGroup);
-    }
-
-    #[test]
-    fn error_finish_concat_unclosed() {
-        test_err!("ab(xy", 2, ErrorKind::UnclosedParen);
-    }
-
-    #[test]
-    fn error_finish_concat_empty_alt() {
-        test_err!("a|", 2, ErrorKind::EmptyAlternate);
-    }
-
-    #[test]
-    fn error_group_name_invalid() {
-        test_err!("(?P<a#>x)", 6, ErrorKind::InvalidCaptureName("a#".into()));
-    }
-
-    #[test]
-    fn error_group_name_invalid_leading() {
-        test_err!("(?P<1a>a)", 6, ErrorKind::InvalidCaptureName("1a".into()));
-    }
-
-    #[test]
-    fn error_group_name_unexpected_eof() {
-        test_err!("(?P<a", 5, ErrorKind::UnclosedCaptureName("a".into()));
-    }
-
-    #[test]
-    fn error_group_name_empty() {
-        test_err!("(?P<>a)", 4, ErrorKind::EmptyCaptureName);
-    }
-
-    #[test]
-    fn error_group_opts_unrecognized_flag() {
-        test_err!("(?z:a)", 2, ErrorKind::UnrecognizedFlag('z'));
-    }
-
-    #[test]
-    fn error_group_opts_unexpected_eof() {
-        test_err!("(?i", 3, ErrorKind::UnexpectedFlagEof);
-    }
-
-    #[test]
-    fn error_group_opts_double_negation() {
-        test_err!("(?-i-s:a)", 4, ErrorKind::DoubleFlagNegation);
-    }
-
-    #[test]
-    fn error_group_opts_empty_negation() {
-        test_err!("(?i-:a)", 4, ErrorKind::EmptyFlagNegation);
-    }
-
-    #[test]
-    fn error_group_opts_empty() {
-        test_err!("(?)", 2, ErrorKind::EmptyFlagNegation);
-    }
-
-    #[test]
-    fn error_escape_unexpected_eof() {
-        test_err!(r"\", 1, ErrorKind::UnexpectedEscapeEof);
-    }
-
-    #[test]
-    fn error_escape_unrecognized() {
-        test_err!(r"\m", 1, ErrorKind::UnrecognizedEscape('m'));
-    }
-
-    #[test]
-    fn error_escape_hex2_eof0() {
-        test_err!(r"\x", 2, ErrorKind::UnexpectedTwoDigitHexEof);
-    }
-
-    #[test]
-    fn error_escape_hex2_eof1() {
-        test_err!(r"\xA", 3, ErrorKind::UnexpectedTwoDigitHexEof);
-    }
-
-    #[test]
-    fn error_escape_hex2_invalid() {
-        test_err!(r"\xAG", 4, ErrorKind::InvalidBase16("AG".into()));
-    }
-
-    #[test]
-    fn error_escape_hex_eof0() {
-        test_err!(r"\x{", 3, ErrorKind::InvalidBase16("".into()));
-    }
-
-    #[test]
-    fn error_escape_hex_eof1() {
-        test_err!(r"\x{A", 4, ErrorKind::UnclosedHex);
-    }
-
-    #[test]
-    fn error_escape_hex_invalid() {
-        test_err!(r"\x{AG}", 5, ErrorKind::InvalidBase16("AG".into()));
-    }
-
-    #[test]
-    fn error_escape_hex_invalid_scalar_value_surrogate() {
-        test_err!(r"\x{D800}", 8, ErrorKind::InvalidScalarValue(0xD800));
-    }
-
-    #[test]
-    fn error_escape_hex_invalid_scalar_value_high() {
-        test_err!(r"\x{110000}", 10, ErrorKind::InvalidScalarValue(0x110000));
-    }
-
-    #[test]
-    fn error_escape_hex_invalid_u32() {
-        test_err!(r"\x{9999999999}", 13,
-                  ErrorKind::InvalidBase16("9999999999".into()));
-    }
-
-    #[test]
-    fn error_unicode_unclosed() {
-        test_err!(r"\p{", 3, ErrorKind::UnclosedUnicodeName);
-        test_err!(r"\p{Greek", 8, ErrorKind::UnclosedUnicodeName);
-    }
-
-    #[test]
-    fn error_unicode_no_letter() {
-        test_err!(r"\p", 2, ErrorKind::UnexpectedEscapeEof);
-    }
-
-    #[test]
-    fn error_unicode_unknown_letter() {
-        test_err!(r"\pA", 3, ErrorKind::UnrecognizedUnicodeClass("A".into()));
-    }
-
-    #[test]
-    fn error_unicode_unknown_name() {
-        test_err!(r"\p{Yii}", 7,
-                  ErrorKind::UnrecognizedUnicodeClass("Yii".into()));
-    }
-
-    #[test]
-    fn error_class_eof_empty() {
-        test_err!("[", 1, ErrorKind::UnexpectedClassEof);
-        test_err!("[^", 2, ErrorKind::UnexpectedClassEof);
-    }
-
-    #[test]
-    fn error_class_eof_non_empty() {
-        test_err!("[a", 2, ErrorKind::UnexpectedClassEof);
-        test_err!("[^a", 3, ErrorKind::UnexpectedClassEof);
-    }
-
-    #[test]
-    fn error_class_eof_range() {
-        test_err!("[a-", 3, ErrorKind::UnexpectedClassEof);
-        test_err!("[^a-", 4, ErrorKind::UnexpectedClassEof);
-        test_err!("[---", 4, ErrorKind::UnexpectedClassEof);
-    }
-
-    #[test]
-    fn error_class_invalid_escape() {
-        test_err!(r"[\pA]", 4,
-                  ErrorKind::UnrecognizedUnicodeClass("A".into()));
-    }
-
-    #[test]
-    fn error_class_valid_escape_not_allowed() {
-        test_err!(r"[\A]", 3, ErrorKind::InvalidClassEscape(Expr::StartText));
-    }
-
-    #[test]
-    fn error_class_range_valid_escape_not_allowed() {
-        test_err!(r"[a-\d]", 5,
-                  ErrorKind::InvalidClassEscape(Expr::Class(class(PERLD))));
-        test_err!(r"[a-\A]", 5,
-                  ErrorKind::InvalidClassEscape(Expr::StartText));
-        test_err!(r"[\A-a]", 3,
-                  ErrorKind::InvalidClassEscape(Expr::StartText));
-    }
-
-    #[test]
-    fn error_class_invalid_range() {
-        test_err!("[z-a]", 4, ErrorKind::InvalidClassRange {
-            start: 'z',
-            end: 'a',
-        });
-    }
-
-    #[test]
-    fn error_class_empty_range() {
-        test_err!("[]", 2, ErrorKind::UnexpectedClassEof);
-        test_err!("[^]", 3, ErrorKind::UnexpectedClassEof);
-        test_err!(r"[^\d\D]", 7, ErrorKind::EmptyClass);
-
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"(?-u)[^\x00-\xFF]", 17, ErrorKind::EmptyClass, flags);
-    }
-
-    #[test]
-    fn error_class_unsupported_char() {
-        // These tests ensure that some unescaped special characters are
-        // rejected in character classes. The intention is to use these
-        // characters to implement sets as described in UTS#18 RL1.3. Once
-        // that's done, these tests should be removed and replaced with others.
-        test_err!("[~~]", 2, ErrorKind::UnsupportedClassChar('~'));
-        test_err!("[+--]", 4, ErrorKind::UnsupportedClassChar('-'));
-        test_err!(r"[a-a--\xFF]", 5, ErrorKind::UnsupportedClassChar('-'));
-        test_err!(r"[a&&~~]", 5, ErrorKind::UnsupportedClassChar('~'));
-        test_err!(r"[a&&--]", 5, ErrorKind::UnsupportedClassChar('-'));
-    }
-
-    #[test]
-    fn error_class_nested_class() {
-        test_err!(r"[[]]", 4, ErrorKind::UnexpectedClassEof);
-        test_err!(r"[[][]]", 6, ErrorKind::UnexpectedClassEof);
-        test_err!(r"[[^\d\D]]", 8, ErrorKind::EmptyClass);
-        test_err!(r"[[]", 3, ErrorKind::UnexpectedClassEof);
-        test_err!(r"[[^]", 4, ErrorKind::UnexpectedClassEof);
-    }
-
-    #[test]
-    fn error_class_intersection() {
-        test_err!(r"[&&]", 4, ErrorKind::EmptyClass);
-        test_err!(r"[a&&]", 5, ErrorKind::EmptyClass);
-        test_err!(r"[&&&&]", 6, ErrorKind::EmptyClass);
-        // `]` after `&&` is not the same as in (`[]]`), because it's also not
-        // allowed unescaped in `[a]]`.
-        test_err!(r"[]&&]]", 5, ErrorKind::EmptyClass);
-
-        let flags = Flags { allow_bytes: true, .. Flags::default() };
-        test_err!(r"(?-u)[a&&\pZ]", 12, ErrorKind::UnicodeNotAllowed, flags);
-    }
-
-    #[test]
-    fn error_duplicate_capture_name() {
-        test_err!("(?P<a>.)(?P<a>.)", 14,
-                  ErrorKind::DuplicateCaptureName("a".into()));
-    }
-
-    #[test]
-    fn error_ignore_space_escape_hex() {
-        test_err!(r"(?x)\x{ 5 3 }", 10, ErrorKind::UnclosedHex);
-    }
-
-    #[test]
-    fn error_ignore_space_escape_hex2() {
-        test_err!(r"(?x)\x 5 3", 9, ErrorKind::InvalidBase16("5 ".into()));
-    }
-
-    #[test]
-    fn error_ignore_space_escape_unicode_name() {
-        test_err!(r"(?x)\p{Y i}", 9, ErrorKind::UnclosedUnicodeName);
+    /// Create a new parser with a default configuration.
+    ///
+    /// The parser can be run with `parse` method. The parse method returns
+    /// a high level intermediate representation of the given regular
+    /// expression.
+    ///
+    /// To set configuration options on the parser, use
+    /// [`ParserBuilder`](struct.ParserBuilder.html).
+    pub fn new() -> Parser {
+        ParserBuilder::new().build()
+    }
+
+    /// Parse the regular expression into a high level intermediate
+    /// representation.
+    pub fn parse(&mut self, pattern: &str) -> Result<hir::Hir> {
+        let ast = self.ast.parse(pattern)?;
+        let hir = self.hir.translate(pattern, &ast)?;
+        Ok(hir)
     }
 }
diff --git a/third_party/rust/regex-syntax/src/unicode.rs b/third_party/rust/regex-syntax/src/unicode.rs
index 3132f63bd4e1..c400fdd4b6df 100644
--- a/third_party/rust/regex-syntax/src/unicode.rs
+++ b/third_party/rust/regex-syntax/src/unicode.rs
@@ -1,5715 +1,437 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// NOTE: The following code was generated by "scripts/unicode.py", do not edit
-// directly
-
-#![allow(warnings)]
-pub mod general_category {
-    pub const C_table: &'static [(char, char)] = &[
-        ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}'), ('\u{ad}', '\u{ad}'),
-        ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
-        ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
-        ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'),
-        ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'), ('\u{5c8}', '\u{5cf}'),
-        ('\u{5eb}', '\u{5ef}'), ('\u{5f5}', '\u{605}'), ('\u{61c}', '\u{61d}'),
-        ('\u{6dd}', '\u{6dd}'), ('\u{70e}', '\u{70f}'), ('\u{74b}', '\u{74c}'),
-        ('\u{7b2}', '\u{7bf}'), ('\u{7fb}', '\u{7ff}'), ('\u{82e}', '\u{82f}'),
-        ('\u{83f}', '\u{83f}'), ('\u{85c}', '\u{85d}'), ('\u{85f}', '\u{89f}'),
-        ('\u{8b5}', '\u{8e2}'), ('\u{984}', '\u{984}'), ('\u{98d}', '\u{98e}'),
-        ('\u{991}', '\u{992}'), ('\u{9a9}', '\u{9a9}'), ('\u{9b1}', '\u{9b1}'),
-        ('\u{9b3}', '\u{9b5}'), ('\u{9ba}', '\u{9bb}'), ('\u{9c5}', '\u{9c6}'),
-        ('\u{9c9}', '\u{9ca}'), ('\u{9cf}', '\u{9d6}'), ('\u{9d8}', '\u{9db}'),
-        ('\u{9de}', '\u{9de}'), ('\u{9e4}', '\u{9e5}'), ('\u{9fc}', '\u{a00}'),
-        ('\u{a04}', '\u{a04}'), ('\u{a0b}', '\u{a0e}'), ('\u{a11}', '\u{a12}'),
-        ('\u{a29}', '\u{a29}'), ('\u{a31}', '\u{a31}'), ('\u{a34}', '\u{a34}'),
-        ('\u{a37}', '\u{a37}'), ('\u{a3a}', '\u{a3b}'), ('\u{a3d}', '\u{a3d}'),
-        ('\u{a43}', '\u{a46}'), ('\u{a49}', '\u{a4a}'), ('\u{a4e}', '\u{a50}'),
-        ('\u{a52}', '\u{a58}'), ('\u{a5d}', '\u{a5d}'), ('\u{a5f}', '\u{a65}'),
-        ('\u{a76}', '\u{a80}'), ('\u{a84}', '\u{a84}'), ('\u{a8e}', '\u{a8e}'),
-        ('\u{a92}', '\u{a92}'), ('\u{aa9}', '\u{aa9}'), ('\u{ab1}', '\u{ab1}'),
-        ('\u{ab4}', '\u{ab4}'), ('\u{aba}', '\u{abb}'), ('\u{ac6}', '\u{ac6}'),
-        ('\u{aca}', '\u{aca}'), ('\u{ace}', '\u{acf}'), ('\u{ad1}', '\u{adf}'),
-        ('\u{ae4}', '\u{ae5}'), ('\u{af2}', '\u{af8}'), ('\u{afa}', '\u{b00}'),
-        ('\u{b04}', '\u{b04}'), ('\u{b0d}', '\u{b0e}'), ('\u{b11}', '\u{b12}'),
-        ('\u{b29}', '\u{b29}'), ('\u{b31}', '\u{b31}'), ('\u{b34}', '\u{b34}'),
-        ('\u{b3a}', '\u{b3b}'), ('\u{b45}', '\u{b46}'), ('\u{b49}', '\u{b4a}'),
-        ('\u{b4e}', '\u{b55}'), ('\u{b58}', '\u{b5b}'), ('\u{b5e}', '\u{b5e}'),
-        ('\u{b64}', '\u{b65}'), ('\u{b78}', '\u{b81}'), ('\u{b84}', '\u{b84}'),
-        ('\u{b8b}', '\u{b8d}'), ('\u{b91}', '\u{b91}'), ('\u{b96}', '\u{b98}'),
-        ('\u{b9b}', '\u{b9b}'), ('\u{b9d}', '\u{b9d}'), ('\u{ba0}', '\u{ba2}'),
-        ('\u{ba5}', '\u{ba7}'), ('\u{bab}', '\u{bad}'), ('\u{bba}', '\u{bbd}'),
-        ('\u{bc3}', '\u{bc5}'), ('\u{bc9}', '\u{bc9}'), ('\u{bce}', '\u{bcf}'),
-        ('\u{bd1}', '\u{bd6}'), ('\u{bd8}', '\u{be5}'), ('\u{bfb}', '\u{bff}'),
-        ('\u{c04}', '\u{c04}'), ('\u{c0d}', '\u{c0d}'), ('\u{c11}', '\u{c11}'),
-        ('\u{c29}', '\u{c29}'), ('\u{c3a}', '\u{c3c}'), ('\u{c45}', '\u{c45}'),
-        ('\u{c49}', '\u{c49}'), ('\u{c4e}', '\u{c54}'), ('\u{c57}', '\u{c57}'),
-        ('\u{c5b}', '\u{c5f}'), ('\u{c64}', '\u{c65}'), ('\u{c70}', '\u{c77}'),
-        ('\u{c80}', '\u{c80}'), ('\u{c84}', '\u{c84}'), ('\u{c8d}', '\u{c8d}'),
-        ('\u{c91}', '\u{c91}'), ('\u{ca9}', '\u{ca9}'), ('\u{cb4}', '\u{cb4}'),
-        ('\u{cba}', '\u{cbb}'), ('\u{cc5}', '\u{cc5}'), ('\u{cc9}', '\u{cc9}'),
-        ('\u{cce}', '\u{cd4}'), ('\u{cd7}', '\u{cdd}'), ('\u{cdf}', '\u{cdf}'),
-        ('\u{ce4}', '\u{ce5}'), ('\u{cf0}', '\u{cf0}'), ('\u{cf3}', '\u{d00}'),
-        ('\u{d04}', '\u{d04}'), ('\u{d0d}', '\u{d0d}'), ('\u{d11}', '\u{d11}'),
-        ('\u{d3b}', '\u{d3c}'), ('\u{d45}', '\u{d45}'), ('\u{d49}', '\u{d49}'),
-        ('\u{d4f}', '\u{d56}'), ('\u{d58}', '\u{d5e}'), ('\u{d64}', '\u{d65}'),
-        ('\u{d76}', '\u{d78}'), ('\u{d80}', '\u{d81}'), ('\u{d84}', '\u{d84}'),
-        ('\u{d97}', '\u{d99}'), ('\u{db2}', '\u{db2}'), ('\u{dbc}', '\u{dbc}'),
-        ('\u{dbe}', '\u{dbf}'), ('\u{dc7}', '\u{dc9}'), ('\u{dcb}', '\u{dce}'),
-        ('\u{dd5}', '\u{dd5}'), ('\u{dd7}', '\u{dd7}'), ('\u{de0}', '\u{de5}'),
-        ('\u{df0}', '\u{df1}'), ('\u{df5}', '\u{e00}'), ('\u{e3b}', '\u{e3e}'),
-        ('\u{e5c}', '\u{e80}'), ('\u{e83}', '\u{e83}'), ('\u{e85}', '\u{e86}'),
-        ('\u{e89}', '\u{e89}'), ('\u{e8b}', '\u{e8c}'), ('\u{e8e}', '\u{e93}'),
-        ('\u{e98}', '\u{e98}'), ('\u{ea0}', '\u{ea0}'), ('\u{ea4}', '\u{ea4}'),
-        ('\u{ea6}', '\u{ea6}'), ('\u{ea8}', '\u{ea9}'), ('\u{eac}', '\u{eac}'),
-        ('\u{eba}', '\u{eba}'), ('\u{ebe}', '\u{ebf}'), ('\u{ec5}', '\u{ec5}'),
-        ('\u{ec7}', '\u{ec7}'), ('\u{ece}', '\u{ecf}'), ('\u{eda}', '\u{edb}'),
-        ('\u{ee0}', '\u{eff}'), ('\u{f48}', '\u{f48}'), ('\u{f6d}', '\u{f70}'),
-        ('\u{f98}', '\u{f98}'), ('\u{fbd}', '\u{fbd}'), ('\u{fcd}', '\u{fcd}'),
-        ('\u{fdb}', '\u{fff}'), ('\u{10c6}', '\u{10c6}'), ('\u{10c8}',
-        '\u{10cc}'), ('\u{10ce}', '\u{10cf}'), ('\u{1249}', '\u{1249}'),
-        ('\u{124e}', '\u{124f}'), ('\u{1257}', '\u{1257}'), ('\u{1259}',
-        '\u{1259}'), ('\u{125e}', '\u{125f}'), ('\u{1289}', '\u{1289}'),
-        ('\u{128e}', '\u{128f}'), ('\u{12b1}', '\u{12b1}'), ('\u{12b6}',
-        '\u{12b7}'), ('\u{12bf}', '\u{12bf}'), ('\u{12c1}', '\u{12c1}'),
-        ('\u{12c6}', '\u{12c7}'), ('\u{12d7}', '\u{12d7}'), ('\u{1311}',
-        '\u{1311}'), ('\u{1316}', '\u{1317}'), ('\u{135b}', '\u{135c}'),
-        ('\u{137d}', '\u{137f}'), ('\u{139a}', '\u{139f}'), ('\u{13f6}',
-        '\u{13f7}'), ('\u{13fe}', '\u{13ff}'), ('\u{169d}', '\u{169f}'),
-        ('\u{16f9}', '\u{16ff}'), ('\u{170d}', '\u{170d}'), ('\u{1715}',
-        '\u{171f}'), ('\u{1737}', '\u{173f}'), ('\u{1754}', '\u{175f}'),
-        ('\u{176d}', '\u{176d}'), ('\u{1771}', '\u{1771}'), ('\u{1774}',
-        '\u{177f}'), ('\u{17de}', '\u{17df}'), ('\u{17ea}', '\u{17ef}'),
-        ('\u{17fa}', '\u{17ff}'), ('\u{180e}', '\u{180f}'), ('\u{181a}',
-        '\u{181f}'), ('\u{1878}', '\u{187f}'), ('\u{18ab}', '\u{18af}'),
-        ('\u{18f6}', '\u{18ff}'), ('\u{191f}', '\u{191f}'), ('\u{192c}',
-        '\u{192f}'), ('\u{193c}', '\u{193f}'), ('\u{1941}', '\u{1943}'),
-        ('\u{196e}', '\u{196f}'), ('\u{1975}', '\u{197f}'), ('\u{19ac}',
-        '\u{19af}'), ('\u{19ca}', '\u{19cf}'), ('\u{19db}', '\u{19dd}'),
-        ('\u{1a1c}', '\u{1a1d}'), ('\u{1a5f}', '\u{1a5f}'), ('\u{1a7d}',
-        '\u{1a7e}'), ('\u{1a8a}', '\u{1a8f}'), ('\u{1a9a}', '\u{1a9f}'),
-        ('\u{1aae}', '\u{1aaf}'), ('\u{1abf}', '\u{1aff}'), ('\u{1b4c}',
-        '\u{1b4f}'), ('\u{1b7d}', '\u{1b7f}'), ('\u{1bf4}', '\u{1bfb}'),
-        ('\u{1c38}', '\u{1c3a}'), ('\u{1c4a}', '\u{1c4c}'), ('\u{1c80}',
-        '\u{1cbf}'), ('\u{1cc8}', '\u{1ccf}'), ('\u{1cf7}', '\u{1cf7}'),
-        ('\u{1cfa}', '\u{1cff}'), ('\u{1df6}', '\u{1dfb}'), ('\u{1f16}',
-        '\u{1f17}'), ('\u{1f1e}', '\u{1f1f}'), ('\u{1f46}', '\u{1f47}'),
-        ('\u{1f4e}', '\u{1f4f}'), ('\u{1f58}', '\u{1f58}'), ('\u{1f5a}',
-        '\u{1f5a}'), ('\u{1f5c}', '\u{1f5c}'), ('\u{1f5e}', '\u{1f5e}'),
-        ('\u{1f7e}', '\u{1f7f}'), ('\u{1fb5}', '\u{1fb5}'), ('\u{1fc5}',
-        '\u{1fc5}'), ('\u{1fd4}', '\u{1fd5}'), ('\u{1fdc}', '\u{1fdc}'),
-        ('\u{1ff0}', '\u{1ff1}'), ('\u{1ff5}', '\u{1ff5}'), ('\u{1fff}',
-        '\u{1fff}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
-        ('\u{2060}', '\u{206f}'), ('\u{2072}', '\u{2073}'), ('\u{208f}',
-        '\u{208f}'), ('\u{209d}', '\u{209f}'), ('\u{20bf}', '\u{20cf}'),
-        ('\u{20f1}', '\u{20ff}'), ('\u{218c}', '\u{218f}'), ('\u{23fb}',
-        '\u{23ff}'), ('\u{2427}', '\u{243f}'), ('\u{244b}', '\u{245f}'),
-        ('\u{2b74}', '\u{2b75}'), ('\u{2b96}', '\u{2b97}'), ('\u{2bba}',
-        '\u{2bbc}'), ('\u{2bc9}', '\u{2bc9}'), ('\u{2bd2}', '\u{2beb}'),
-        ('\u{2bf0}', '\u{2bff}'), ('\u{2c2f}', '\u{2c2f}'), ('\u{2c5f}',
-        '\u{2c5f}'), ('\u{2cf4}', '\u{2cf8}'), ('\u{2d26}', '\u{2d26}'),
-        ('\u{2d28}', '\u{2d2c}'), ('\u{2d2e}', '\u{2d2f}'), ('\u{2d68}',
-        '\u{2d6e}'), ('\u{2d71}', '\u{2d7e}'), ('\u{2d97}', '\u{2d9f}'),
-        ('\u{2da7}', '\u{2da7}'), ('\u{2daf}', '\u{2daf}'), ('\u{2db7}',
-        '\u{2db7}'), ('\u{2dbf}', '\u{2dbf}'), ('\u{2dc7}', '\u{2dc7}'),
-        ('\u{2dcf}', '\u{2dcf}'), ('\u{2dd7}', '\u{2dd7}'), ('\u{2ddf}',
-        '\u{2ddf}'), ('\u{2e43}', '\u{2e7f}'), ('\u{2e9a}', '\u{2e9a}'),
-        ('\u{2ef4}', '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}',
-        '\u{2fff}'), ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'),
-        ('\u{3100}', '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}',
-        '\u{318f}'), ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'),
-        ('\u{321f}', '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{4db6}',
-        '\u{4dbf}'), ('\u{9fd6}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'),
-        ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a6f8}',
-        '\u{a6ff}'), ('\u{a7ae}', '\u{a7af}'), ('\u{a7b8}', '\u{a7f6}'),
-        ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}',
-        '\u{a87f}'), ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'),
-        ('\u{a8fe}', '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}',
-        '\u{a97f}'), ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'),
-        ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}',
-        '\u{aa4f}'), ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'),
-        ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}',
-        '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'),
-        ('\u{ab2f}', '\u{ab2f}'), ('\u{ab66}', '\u{ab6f}'), ('\u{abee}',
-        '\u{abef}'), ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'),
-        ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{e000}',
-        '\u{f8ff}'), ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', '\u{faff}'),
-        ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}',
-        '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'),
-        ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', '\u{fb45}'), ('\u{fbc2}',
-        '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'),
-        ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}',
-        '\u{fe1f}'), ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'),
-        ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}', '\u{fe75}'), ('\u{fefd}',
-        '\u{ff00}'), ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'),
-        ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}',
-        '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fffb}'),
-        ('\u{fffe}', '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}',
-        '\u{10027}'), ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'),
-        ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', '\u{1007f}'), ('\u{100fb}',
-        '\u{100ff}'), ('\u{10103}', '\u{10106}'), ('\u{10134}', '\u{10136}'),
-        ('\u{1018d}', '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), ('\u{101a1}',
-        '\u{101cf}'), ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'),
-        ('\u{102d1}', '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}',
-        '\u{1032f}'), ('\u{1034b}', '\u{1034f}'), ('\u{1037b}', '\u{1037f}'),
-        ('\u{1039e}', '\u{1039e}'), ('\u{103c4}', '\u{103c7}'), ('\u{103d6}',
-        '\u{103ff}'), ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104ff}'),
-        ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'), ('\u{10570}',
-        '\u{105ff}'), ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'),
-        ('\u{10768}', '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}',
-        '\u{10809}'), ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'),
-        ('\u{1083d}', '\u{1083e}'), ('\u{10856}', '\u{10856}'), ('\u{1089f}',
-        '\u{108a6}'), ('\u{108b0}', '\u{108df}'), ('\u{108f3}', '\u{108f3}'),
-        ('\u{108f6}', '\u{108fa}'), ('\u{1091c}', '\u{1091e}'), ('\u{1093a}',
-        '\u{1093e}'), ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'),
-        ('\u{109d0}', '\u{109d1}'), ('\u{10a04}', '\u{10a04}'), ('\u{10a07}',
-        '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'),
-        ('\u{10a34}', '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}',
-        '\u{10a4f}'), ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'),
-        ('\u{10ae7}', '\u{10aea}'), ('\u{10af7}', '\u{10aff}'), ('\u{10b36}',
-        '\u{10b38}'), ('\u{10b56}', '\u{10b57}'), ('\u{10b73}', '\u{10b77}'),
-        ('\u{10b92}', '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}',
-        '\u{10bff}'), ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'),
-        ('\u{10cf3}', '\u{10cf9}'), ('\u{10d00}', '\u{10e5f}'), ('\u{10e7f}',
-        '\u{10fff}'), ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'),
-        ('\u{110bd}', '\u{110bd}'), ('\u{110c2}', '\u{110cf}'), ('\u{110e9}',
-        '\u{110ef}'), ('\u{110fa}', '\u{110ff}'), ('\u{11135}', '\u{11135}'),
-        ('\u{11144}', '\u{1114f}'), ('\u{11177}', '\u{1117f}'), ('\u{111ce}',
-        '\u{111cf}'), ('\u{111e0}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'),
-        ('\u{11212}', '\u{11212}'), ('\u{1123e}', '\u{1127f}'), ('\u{11287}',
-        '\u{11287}'), ('\u{11289}', '\u{11289}'), ('\u{1128e}', '\u{1128e}'),
-        ('\u{1129e}', '\u{1129e}'), ('\u{112aa}', '\u{112af}'), ('\u{112eb}',
-        '\u{112ef}'), ('\u{112fa}', '\u{112ff}'), ('\u{11304}', '\u{11304}'),
-        ('\u{1130d}', '\u{1130e}'), ('\u{11311}', '\u{11312}'), ('\u{11329}',
-        '\u{11329}'), ('\u{11331}', '\u{11331}'), ('\u{11334}', '\u{11334}'),
-        ('\u{1133a}', '\u{1133b}'), ('\u{11345}', '\u{11346}'), ('\u{11349}',
-        '\u{1134a}'), ('\u{1134e}', '\u{1134f}'), ('\u{11351}', '\u{11356}'),
-        ('\u{11358}', '\u{1135c}'), ('\u{11364}', '\u{11365}'), ('\u{1136d}',
-        '\u{1136f}'), ('\u{11375}', '\u{1147f}'), ('\u{114c8}', '\u{114cf}'),
-        ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'), ('\u{115de}',
-        '\u{115ff}'), ('\u{11645}', '\u{1164f}'), ('\u{1165a}', '\u{1167f}'),
-        ('\u{116b8}', '\u{116bf}'), ('\u{116ca}', '\u{116ff}'), ('\u{1171a}',
-        '\u{1171c}'), ('\u{1172c}', '\u{1172f}'), ('\u{11740}', '\u{1189f}'),
-        ('\u{118f3}', '\u{118fe}'), ('\u{11900}', '\u{11abf}'), ('\u{11af9}',
-        '\u{11fff}'), ('\u{1239a}', '\u{123ff}'), ('\u{1246f}', '\u{1246f}'),
-        ('\u{12475}', '\u{1247f}'), ('\u{12544}', '\u{12fff}'), ('\u{1342f}',
-        '\u{143ff}'), ('\u{14647}', '\u{167ff}'), ('\u{16a39}', '\u{16a3f}'),
-        ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'), ('\u{16a70}',
-        '\u{16acf}'), ('\u{16aee}', '\u{16aef}'), ('\u{16af6}', '\u{16aff}'),
-        ('\u{16b46}', '\u{16b4f}'), ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}',
-        '\u{16b62}'), ('\u{16b78}', '\u{16b7c}'), ('\u{16b90}', '\u{16eff}'),
-        ('\u{16f45}', '\u{16f4f}'), ('\u{16f7f}', '\u{16f8e}'), ('\u{16fa0}',
-        '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'), ('\u{1bc6b}', '\u{1bc6f}'),
-        ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'), ('\u{1bc9a}',
-        '\u{1bc9b}'), ('\u{1bca0}', '\u{1cfff}'), ('\u{1d0f6}', '\u{1d0ff}'),
-        ('\u{1d127}', '\u{1d128}'), ('\u{1d173}', '\u{1d17a}'), ('\u{1d1e9}',
-        '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), ('\u{1d357}', '\u{1d35f}'),
-        ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}',
-        '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'),
-        ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}',
-        '\u{1d4ba}'), ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'),
-        ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}',
-        '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', '\u{1d53a}'),
-        ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), ('\u{1d547}',
-        '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'),
-        ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1da8c}', '\u{1da9a}'), ('\u{1daa0}',
-        '\u{1daa0}'), ('\u{1dab0}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'),
-        ('\u{1e8d7}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}',
-        '\u{1ee20}'), ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'),
-        ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}',
-        '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', '\u{1ee41}'),
-        ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}',
-        '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'),
-        ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}',
-        '\u{1ee58}'), ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'),
-        ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}',
-        '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', '\u{1ee6b}'),
-        ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}',
-        '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'),
-        ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}',
-        '\u{1eeaa}'), ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'),
-        ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}',
-        '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', '\u{1f0d0}'),
-        ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), ('\u{1f12f}',
-        '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'),
-        ('\u{1f203}', '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}',
-        '\u{1f24f}'), ('\u{1f252}', '\u{1f2ff}'), ('\u{1f57a}', '\u{1f57a}'),
-        ('\u{1f5a4}', '\u{1f5a4}'), ('\u{1f6d1}', '\u{1f6df}'), ('\u{1f6ed}',
-        '\u{1f6ef}'), ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'),
-        ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}',
-        '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', '\u{1f88f}'),
-        ('\u{1f8ae}', '\u{1f90f}'), ('\u{1f919}', '\u{1f97f}'), ('\u{1f985}',
-        '\u{1f9bf}'), ('\u{1f9c1}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'),
-        ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2b81f}'), ('\u{2cea2}',
-        '\u{2f7ff}'), ('\u{2fa1e}', '\u{e00ff}'), ('\u{e01f0}', '\u{10ffff}')
-    ];
-
-    pub const Cc_table: &'static [(char, char)] = &[
-        ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}')
-    ];
-
-    pub const Cf_table: &'static [(char, char)] = &[
-        ('\u{ad}', '\u{ad}'), ('\u{600}', '\u{605}'), ('\u{61c}', '\u{61c}'),
-        ('\u{6dd}', '\u{6dd}'), ('\u{70f}', '\u{70f}'), ('\u{180e}',
-        '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
-        ('\u{2060}', '\u{2064}'), ('\u{2066}', '\u{206f}'), ('\u{feff}',
-        '\u{feff}'), ('\u{fff9}', '\u{fffb}'), ('\u{110bd}', '\u{110bd}'),
-        ('\u{1bca0}', '\u{1bca3}'), ('\u{1d173}', '\u{1d17a}'), ('\u{e0001}',
-        '\u{e0001}'), ('\u{e0020}', '\u{e007f}')
-    ];
-
-    pub const Cn_table: &'static [(char, char)] = &[
-        ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
-        ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
-        ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'),
-        ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'), ('\u{5c8}', '\u{5cf}'),
-        ('\u{5eb}', '\u{5ef}'), ('\u{5f5}', '\u{5ff}'), ('\u{61d}', '\u{61d}'),
-        ('\u{70e}', '\u{70e}'), ('\u{74b}', '\u{74c}'), ('\u{7b2}', '\u{7bf}'),
-        ('\u{7fb}', '\u{7ff}'), ('\u{82e}', '\u{82f}'), ('\u{83f}', '\u{83f}'),
-        ('\u{85c}', '\u{85d}'), ('\u{85f}', '\u{89f}'), ('\u{8b5}', '\u{8e2}'),
-        ('\u{984}', '\u{984}'), ('\u{98d}', '\u{98e}'), ('\u{991}', '\u{992}'),
-        ('\u{9a9}', '\u{9a9}'), ('\u{9b1}', '\u{9b1}'), ('\u{9b3}', '\u{9b5}'),
-        ('\u{9ba}', '\u{9bb}'), ('\u{9c5}', '\u{9c6}'), ('\u{9c9}', '\u{9ca}'),
-        ('\u{9cf}', '\u{9d6}'), ('\u{9d8}', '\u{9db}'), ('\u{9de}', '\u{9de}'),
-        ('\u{9e4}', '\u{9e5}'), ('\u{9fc}', '\u{a00}'), ('\u{a04}', '\u{a04}'),
-        ('\u{a0b}', '\u{a0e}'), ('\u{a11}', '\u{a12}'), ('\u{a29}', '\u{a29}'),
-        ('\u{a31}', '\u{a31}'), ('\u{a34}', '\u{a34}'), ('\u{a37}', '\u{a37}'),
-        ('\u{a3a}', '\u{a3b}'), ('\u{a3d}', '\u{a3d}'), ('\u{a43}', '\u{a46}'),
-        ('\u{a49}', '\u{a4a}'), ('\u{a4e}', '\u{a50}'), ('\u{a52}', '\u{a58}'),
-        ('\u{a5d}', '\u{a5d}'), ('\u{a5f}', '\u{a65}'), ('\u{a76}', '\u{a80}'),
-        ('\u{a84}', '\u{a84}'), ('\u{a8e}', '\u{a8e}'), ('\u{a92}', '\u{a92}'),
-        ('\u{aa9}', '\u{aa9}'), ('\u{ab1}', '\u{ab1}'), ('\u{ab4}', '\u{ab4}'),
-        ('\u{aba}', '\u{abb}'), ('\u{ac6}', '\u{ac6}'), ('\u{aca}', '\u{aca}'),
-        ('\u{ace}', '\u{acf}'), ('\u{ad1}', '\u{adf}'), ('\u{ae4}', '\u{ae5}'),
-        ('\u{af2}', '\u{af8}'), ('\u{afa}', '\u{b00}'), ('\u{b04}', '\u{b04}'),
-        ('\u{b0d}', '\u{b0e}'), ('\u{b11}', '\u{b12}'), ('\u{b29}', '\u{b29}'),
-        ('\u{b31}', '\u{b31}'), ('\u{b34}', '\u{b34}'), ('\u{b3a}', '\u{b3b}'),
-        ('\u{b45}', '\u{b46}'), ('\u{b49}', '\u{b4a}'), ('\u{b4e}', '\u{b55}'),
-        ('\u{b58}', '\u{b5b}'), ('\u{b5e}', '\u{b5e}'), ('\u{b64}', '\u{b65}'),
-        ('\u{b78}', '\u{b81}'), ('\u{b84}', '\u{b84}'), ('\u{b8b}', '\u{b8d}'),
-        ('\u{b91}', '\u{b91}'), ('\u{b96}', '\u{b98}'), ('\u{b9b}', '\u{b9b}'),
-        ('\u{b9d}', '\u{b9d}'), ('\u{ba0}', '\u{ba2}'), ('\u{ba5}', '\u{ba7}'),
-        ('\u{bab}', '\u{bad}'), ('\u{bba}', '\u{bbd}'), ('\u{bc3}', '\u{bc5}'),
-        ('\u{bc9}', '\u{bc9}'), ('\u{bce}', '\u{bcf}'), ('\u{bd1}', '\u{bd6}'),
-        ('\u{bd8}', '\u{be5}'), ('\u{bfb}', '\u{bff}'), ('\u{c04}', '\u{c04}'),
-        ('\u{c0d}', '\u{c0d}'), ('\u{c11}', '\u{c11}'), ('\u{c29}', '\u{c29}'),
-        ('\u{c3a}', '\u{c3c}'), ('\u{c45}', '\u{c45}'), ('\u{c49}', '\u{c49}'),
-        ('\u{c4e}', '\u{c54}'), ('\u{c57}', '\u{c57}'), ('\u{c5b}', '\u{c5f}'),
-        ('\u{c64}', '\u{c65}'), ('\u{c70}', '\u{c77}'), ('\u{c80}', '\u{c80}'),
-        ('\u{c84}', '\u{c84}'), ('\u{c8d}', '\u{c8d}'), ('\u{c91}', '\u{c91}'),
-        ('\u{ca9}', '\u{ca9}'), ('\u{cb4}', '\u{cb4}'), ('\u{cba}', '\u{cbb}'),
-        ('\u{cc5}', '\u{cc5}'), ('\u{cc9}', '\u{cc9}'), ('\u{cce}', '\u{cd4}'),
-        ('\u{cd7}', '\u{cdd}'), ('\u{cdf}', '\u{cdf}'), ('\u{ce4}', '\u{ce5}'),
-        ('\u{cf0}', '\u{cf0}'), ('\u{cf3}', '\u{d00}'), ('\u{d04}', '\u{d04}'),
-        ('\u{d0d}', '\u{d0d}'), ('\u{d11}', '\u{d11}'), ('\u{d3b}', '\u{d3c}'),
-        ('\u{d45}', '\u{d45}'), ('\u{d49}', '\u{d49}'), ('\u{d4f}', '\u{d56}'),
-        ('\u{d58}', '\u{d5e}'), ('\u{d64}', '\u{d65}'), ('\u{d76}', '\u{d78}'),
-        ('\u{d80}', '\u{d81}'), ('\u{d84}', '\u{d84}'), ('\u{d97}', '\u{d99}'),
-        ('\u{db2}', '\u{db2}'), ('\u{dbc}', '\u{dbc}'), ('\u{dbe}', '\u{dbf}'),
-        ('\u{dc7}', '\u{dc9}'), ('\u{dcb}', '\u{dce}'), ('\u{dd5}', '\u{dd5}'),
-        ('\u{dd7}', '\u{dd7}'), ('\u{de0}', '\u{de5}'), ('\u{df0}', '\u{df1}'),
-        ('\u{df5}', '\u{e00}'), ('\u{e3b}', '\u{e3e}'), ('\u{e5c}', '\u{e80}'),
-        ('\u{e83}', '\u{e83}'), ('\u{e85}', '\u{e86}'), ('\u{e89}', '\u{e89}'),
-        ('\u{e8b}', '\u{e8c}'), ('\u{e8e}', '\u{e93}'), ('\u{e98}', '\u{e98}'),
-        ('\u{ea0}', '\u{ea0}'), ('\u{ea4}', '\u{ea4}'), ('\u{ea6}', '\u{ea6}'),
-        ('\u{ea8}', '\u{ea9}'), ('\u{eac}', '\u{eac}'), ('\u{eba}', '\u{eba}'),
-        ('\u{ebe}', '\u{ebf}'), ('\u{ec5}', '\u{ec5}'), ('\u{ec7}', '\u{ec7}'),
-        ('\u{ece}', '\u{ecf}'), ('\u{eda}', '\u{edb}'), ('\u{ee0}', '\u{eff}'),
-        ('\u{f48}', '\u{f48}'), ('\u{f6d}', '\u{f70}'), ('\u{f98}', '\u{f98}'),
-        ('\u{fbd}', '\u{fbd}'), ('\u{fcd}', '\u{fcd}'), ('\u{fdb}', '\u{fff}'),
-        ('\u{10c6}', '\u{10c6}'), ('\u{10c8}', '\u{10cc}'), ('\u{10ce}',
-        '\u{10cf}'), ('\u{1249}', '\u{1249}'), ('\u{124e}', '\u{124f}'),
-        ('\u{1257}', '\u{1257}'), ('\u{1259}', '\u{1259}'), ('\u{125e}',
-        '\u{125f}'), ('\u{1289}', '\u{1289}'), ('\u{128e}', '\u{128f}'),
-        ('\u{12b1}', '\u{12b1}'), ('\u{12b6}', '\u{12b7}'), ('\u{12bf}',
-        '\u{12bf}'), ('\u{12c1}', '\u{12c1}'), ('\u{12c6}', '\u{12c7}'),
-        ('\u{12d7}', '\u{12d7}'), ('\u{1311}', '\u{1311}'), ('\u{1316}',
-        '\u{1317}'), ('\u{135b}', '\u{135c}'), ('\u{137d}', '\u{137f}'),
-        ('\u{139a}', '\u{139f}'), ('\u{13f6}', '\u{13f7}'), ('\u{13fe}',
-        '\u{13ff}'), ('\u{169d}', '\u{169f}'), ('\u{16f9}', '\u{16ff}'),
-        ('\u{170d}', '\u{170d}'), ('\u{1715}', '\u{171f}'), ('\u{1737}',
-        '\u{173f}'), ('\u{1754}', '\u{175f}'), ('\u{176d}', '\u{176d}'),
-        ('\u{1771}', '\u{1771}'), ('\u{1774}', '\u{177f}'), ('\u{17de}',
-        '\u{17df}'), ('\u{17ea}', '\u{17ef}'), ('\u{17fa}', '\u{17ff}'),
-        ('\u{180f}', '\u{180f}'), ('\u{181a}', '\u{181f}'), ('\u{1878}',
-        '\u{187f}'), ('\u{18ab}', '\u{18af}'), ('\u{18f6}', '\u{18ff}'),
-        ('\u{191f}', '\u{191f}'), ('\u{192c}', '\u{192f}'), ('\u{193c}',
-        '\u{193f}'), ('\u{1941}', '\u{1943}'), ('\u{196e}', '\u{196f}'),
-        ('\u{1975}', '\u{197f}'), ('\u{19ac}', '\u{19af}'), ('\u{19ca}',
-        '\u{19cf}'), ('\u{19db}', '\u{19dd}'), ('\u{1a1c}', '\u{1a1d}'),
-        ('\u{1a5f}', '\u{1a5f}'), ('\u{1a7d}', '\u{1a7e}'), ('\u{1a8a}',
-        '\u{1a8f}'), ('\u{1a9a}', '\u{1a9f}'), ('\u{1aae}', '\u{1aaf}'),
-        ('\u{1abf}', '\u{1aff}'), ('\u{1b4c}', '\u{1b4f}'), ('\u{1b7d}',
-        '\u{1b7f}'), ('\u{1bf4}', '\u{1bfb}'), ('\u{1c38}', '\u{1c3a}'),
-        ('\u{1c4a}', '\u{1c4c}'), ('\u{1c80}', '\u{1cbf}'), ('\u{1cc8}',
-        '\u{1ccf}'), ('\u{1cf7}', '\u{1cf7}'), ('\u{1cfa}', '\u{1cff}'),
-        ('\u{1df6}', '\u{1dfb}'), ('\u{1f16}', '\u{1f17}'), ('\u{1f1e}',
-        '\u{1f1f}'), ('\u{1f46}', '\u{1f47}'), ('\u{1f4e}', '\u{1f4f}'),
-        ('\u{1f58}', '\u{1f58}'), ('\u{1f5a}', '\u{1f5a}'), ('\u{1f5c}',
-        '\u{1f5c}'), ('\u{1f5e}', '\u{1f5e}'), ('\u{1f7e}', '\u{1f7f}'),
-        ('\u{1fb5}', '\u{1fb5}'), ('\u{1fc5}', '\u{1fc5}'), ('\u{1fd4}',
-        '\u{1fd5}'), ('\u{1fdc}', '\u{1fdc}'), ('\u{1ff0}', '\u{1ff1}'),
-        ('\u{1ff5}', '\u{1ff5}'), ('\u{1fff}', '\u{1fff}'), ('\u{2065}',
-        '\u{2065}'), ('\u{2072}', '\u{2073}'), ('\u{208f}', '\u{208f}'),
-        ('\u{209d}', '\u{209f}'), ('\u{20bf}', '\u{20cf}'), ('\u{20f1}',
-        '\u{20ff}'), ('\u{218c}', '\u{218f}'), ('\u{23fb}', '\u{23ff}'),
-        ('\u{2427}', '\u{243f}'), ('\u{244b}', '\u{245f}'), ('\u{2b74}',
-        '\u{2b75}'), ('\u{2b96}', '\u{2b97}'), ('\u{2bba}', '\u{2bbc}'),
-        ('\u{2bc9}', '\u{2bc9}'), ('\u{2bd2}', '\u{2beb}'), ('\u{2bf0}',
-        '\u{2bff}'), ('\u{2c2f}', '\u{2c2f}'), ('\u{2c5f}', '\u{2c5f}'),
-        ('\u{2cf4}', '\u{2cf8}'), ('\u{2d26}', '\u{2d26}'), ('\u{2d28}',
-        '\u{2d2c}'), ('\u{2d2e}', '\u{2d2f}'), ('\u{2d68}', '\u{2d6e}'),
-        ('\u{2d71}', '\u{2d7e}'), ('\u{2d97}', '\u{2d9f}'), ('\u{2da7}',
-        '\u{2da7}'), ('\u{2daf}', '\u{2daf}'), ('\u{2db7}', '\u{2db7}'),
-        ('\u{2dbf}', '\u{2dbf}'), ('\u{2dc7}', '\u{2dc7}'), ('\u{2dcf}',
-        '\u{2dcf}'), ('\u{2dd7}', '\u{2dd7}'), ('\u{2ddf}', '\u{2ddf}'),
-        ('\u{2e43}', '\u{2e7f}'), ('\u{2e9a}', '\u{2e9a}'), ('\u{2ef4}',
-        '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}', '\u{2fff}'),
-        ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'), ('\u{3100}',
-        '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}', '\u{318f}'),
-        ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'), ('\u{321f}',
-        '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{4db6}', '\u{4dbf}'),
-        ('\u{9fd6}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'), ('\u{a4c7}',
-        '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a6f8}', '\u{a6ff}'),
-        ('\u{a7ae}', '\u{a7af}'), ('\u{a7b8}', '\u{a7f6}'), ('\u{a82c}',
-        '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'),
-        ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'), ('\u{a8fe}',
-        '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}', '\u{a97f}'),
-        ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), ('\u{a9ff}',
-        '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'),
-        ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), ('\u{aaf7}',
-        '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}', '\u{ab10}'),
-        ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}',
-        '\u{ab2f}'), ('\u{ab66}', '\u{ab6f}'), ('\u{abee}', '\u{abef}'),
-        ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}',
-        '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{fa6e}', '\u{fa6f}'),
-        ('\u{fada}', '\u{faff}'), ('\u{fb07}', '\u{fb12}'), ('\u{fb18}',
-        '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'),
-        ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), ('\u{fb45}',
-        '\u{fb45}'), ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'),
-        ('\u{fd90}', '\u{fd91}'), ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}',
-        '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), ('\u{fe53}', '\u{fe53}'),
-        ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}',
-        '\u{fe75}'), ('\u{fefd}', '\u{fefe}'), ('\u{ff00}', '\u{ff00}'),
-        ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), ('\u{ffd0}',
-        '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}', '\u{ffdf}'),
-        ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fff8}'), ('\u{fffe}',
-        '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'),
-        ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'), ('\u{1004e}',
-        '\u{1004f}'), ('\u{1005e}', '\u{1007f}'), ('\u{100fb}', '\u{100ff}'),
-        ('\u{10103}', '\u{10106}'), ('\u{10134}', '\u{10136}'), ('\u{1018d}',
-        '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), ('\u{101a1}', '\u{101cf}'),
-        ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'), ('\u{102d1}',
-        '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}', '\u{1032f}'),
-        ('\u{1034b}', '\u{1034f}'), ('\u{1037b}', '\u{1037f}'), ('\u{1039e}',
-        '\u{1039e}'), ('\u{103c4}', '\u{103c7}'), ('\u{103d6}', '\u{103ff}'),
-        ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104ff}'), ('\u{10528}',
-        '\u{1052f}'), ('\u{10564}', '\u{1056e}'), ('\u{10570}', '\u{105ff}'),
-        ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'), ('\u{10768}',
-        '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'),
-        ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'), ('\u{1083d}',
-        '\u{1083e}'), ('\u{10856}', '\u{10856}'), ('\u{1089f}', '\u{108a6}'),
-        ('\u{108b0}', '\u{108df}'), ('\u{108f3}', '\u{108f3}'), ('\u{108f6}',
-        '\u{108fa}'), ('\u{1091c}', '\u{1091e}'), ('\u{1093a}', '\u{1093e}'),
-        ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'), ('\u{109d0}',
-        '\u{109d1}'), ('\u{10a04}', '\u{10a04}'), ('\u{10a07}', '\u{10a0b}'),
-        ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'), ('\u{10a34}',
-        '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}', '\u{10a4f}'),
-        ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'), ('\u{10ae7}',
-        '\u{10aea}'), ('\u{10af7}', '\u{10aff}'), ('\u{10b36}', '\u{10b38}'),
-        ('\u{10b56}', '\u{10b57}'), ('\u{10b73}', '\u{10b77}'), ('\u{10b92}',
-        '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}', '\u{10bff}'),
-        ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'), ('\u{10cf3}',
-        '\u{10cf9}'), ('\u{10d00}', '\u{10e5f}'), ('\u{10e7f}', '\u{10fff}'),
-        ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'), ('\u{110c2}',
-        '\u{110cf}'), ('\u{110e9}', '\u{110ef}'), ('\u{110fa}', '\u{110ff}'),
-        ('\u{11135}', '\u{11135}'), ('\u{11144}', '\u{1114f}'), ('\u{11177}',
-        '\u{1117f}'), ('\u{111ce}', '\u{111cf}'), ('\u{111e0}', '\u{111e0}'),
-        ('\u{111f5}', '\u{111ff}'), ('\u{11212}', '\u{11212}'), ('\u{1123e}',
-        '\u{1127f}'), ('\u{11287}', '\u{11287}'), ('\u{11289}', '\u{11289}'),
-        ('\u{1128e}', '\u{1128e}'), ('\u{1129e}', '\u{1129e}'), ('\u{112aa}',
-        '\u{112af}'), ('\u{112eb}', '\u{112ef}'), ('\u{112fa}', '\u{112ff}'),
-        ('\u{11304}', '\u{11304}'), ('\u{1130d}', '\u{1130e}'), ('\u{11311}',
-        '\u{11312}'), ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'),
-        ('\u{11334}', '\u{11334}'), ('\u{1133a}', '\u{1133b}'), ('\u{11345}',
-        '\u{11346}'), ('\u{11349}', '\u{1134a}'), ('\u{1134e}', '\u{1134f}'),
-        ('\u{11351}', '\u{11356}'), ('\u{11358}', '\u{1135c}'), ('\u{11364}',
-        '\u{11365}'), ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{1147f}'),
-        ('\u{114c8}', '\u{114cf}'), ('\u{114da}', '\u{1157f}'), ('\u{115b6}',
-        '\u{115b7}'), ('\u{115de}', '\u{115ff}'), ('\u{11645}', '\u{1164f}'),
-        ('\u{1165a}', '\u{1167f}'), ('\u{116b8}', '\u{116bf}'), ('\u{116ca}',
-        '\u{116ff}'), ('\u{1171a}', '\u{1171c}'), ('\u{1172c}', '\u{1172f}'),
-        ('\u{11740}', '\u{1189f}'), ('\u{118f3}', '\u{118fe}'), ('\u{11900}',
-        '\u{11abf}'), ('\u{11af9}', '\u{11fff}'), ('\u{1239a}', '\u{123ff}'),
-        ('\u{1246f}', '\u{1246f}'), ('\u{12475}', '\u{1247f}'), ('\u{12544}',
-        '\u{12fff}'), ('\u{1342f}', '\u{143ff}'), ('\u{14647}', '\u{167ff}'),
-        ('\u{16a39}', '\u{16a3f}'), ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}',
-        '\u{16a6d}'), ('\u{16a70}', '\u{16acf}'), ('\u{16aee}', '\u{16aef}'),
-        ('\u{16af6}', '\u{16aff}'), ('\u{16b46}', '\u{16b4f}'), ('\u{16b5a}',
-        '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'), ('\u{16b78}', '\u{16b7c}'),
-        ('\u{16b90}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'), ('\u{16f7f}',
-        '\u{16f8e}'), ('\u{16fa0}', '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'),
-        ('\u{1bc6b}', '\u{1bc6f}'), ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}',
-        '\u{1bc8f}'), ('\u{1bc9a}', '\u{1bc9b}'), ('\u{1bca4}', '\u{1cfff}'),
-        ('\u{1d0f6}', '\u{1d0ff}'), ('\u{1d127}', '\u{1d128}'), ('\u{1d1e9}',
-        '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), ('\u{1d357}', '\u{1d35f}'),
-        ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}',
-        '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'),
-        ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}',
-        '\u{1d4ba}'), ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'),
-        ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}',
-        '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', '\u{1d53a}'),
-        ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), ('\u{1d547}',
-        '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'),
-        ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1da8c}', '\u{1da9a}'), ('\u{1daa0}',
-        '\u{1daa0}'), ('\u{1dab0}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'),
-        ('\u{1e8d7}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}',
-        '\u{1ee20}'), ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'),
-        ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}',
-        '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', '\u{1ee41}'),
-        ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}',
-        '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'),
-        ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}',
-        '\u{1ee58}'), ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'),
-        ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}',
-        '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', '\u{1ee6b}'),
-        ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}',
-        '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'),
-        ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}',
-        '\u{1eeaa}'), ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'),
-        ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}',
-        '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', '\u{1f0d0}'),
-        ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), ('\u{1f12f}',
-        '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'),
-        ('\u{1f203}', '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}',
-        '\u{1f24f}'), ('\u{1f252}', '\u{1f2ff}'), ('\u{1f57a}', '\u{1f57a}'),
-        ('\u{1f5a4}', '\u{1f5a4}'), ('\u{1f6d1}', '\u{1f6df}'), ('\u{1f6ed}',
-        '\u{1f6ef}'), ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'),
-        ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}',
-        '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', '\u{1f88f}'),
-        ('\u{1f8ae}', '\u{1f90f}'), ('\u{1f919}', '\u{1f97f}'), ('\u{1f985}',
-        '\u{1f9bf}'), ('\u{1f9c1}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'),
-        ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2b81f}'), ('\u{2cea2}',
-        '\u{2f7ff}'), ('\u{2fa1e}', '\u{e0000}'), ('\u{e0002}', '\u{e001f}'),
-        ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{effff}'), ('\u{ffffe}',
-        '\u{fffff}'), ('\u{10fffe}', '\u{10ffff}')
-    ];
-
-    pub const Co_table: &'static [(char, char)] = &[
-        ('\u{e000}', '\u{f8ff}'), ('\u{f0000}', '\u{ffffd}'), ('\u{100000}',
-        '\u{10fffd}')
-    ];
-
-    pub const L_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
-        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
-        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
-        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
-        ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
-        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
-        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
-        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{5d0}', '\u{5ea}'),
-        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'), ('\u{66e}', '\u{66f}'),
-        ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}', '\u{6e6}'),
-        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
-        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
-        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'),
-        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'),
-        ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'), ('\u{840}', '\u{858}'),
-        ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'), ('\u{93d}', '\u{93d}'),
-        ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}', '\u{980}'),
-        ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
-        ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'),
-        ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'),
-        ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'),
-        ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'),
-        ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'),
-        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}', '\u{a74}'),
-        ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
-        ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
-        ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'),
-        ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
-        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
-        ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'), ('\u{b5c}', '\u{b5d}'),
-        ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}', '\u{b83}'),
-        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
-        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
-        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
-        ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
-        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c3d}'),
-        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'), ('\u{c85}', '\u{c8c}'),
-        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
-        ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'),
-        ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'),
-        ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'),
-        ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'),
-        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
-        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{e01}', '\u{e30}'),
-        ('\u{e32}', '\u{e33}'), ('\u{e40}', '\u{e46}'), ('\u{e81}', '\u{e82}'),
-        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
-        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
-        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
-        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb3}'),
-        ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
-        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
-        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
-        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
-        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
-        ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
-        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'),
-        ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
-        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
-        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
-        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
-        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
-        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
-        ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
-        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
-        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16f1}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
-        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
-        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
-        ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}',
-        '\u{17dc}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
-        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
-        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
-        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'),
-        ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}',
-        '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
-        ('\u{1c00}', '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}',
-        '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'),
-        ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}',
-        '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'),
-        ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
-        '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'),
-        ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}',
-        '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'),
-        ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
-        '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
-        ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
-        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'),
-        ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}',
-        '\u{2115}'), ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'),
-        ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}',
-        '\u{212d}'), ('\u{212f}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
-        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2183}',
-        '\u{2184}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'),
-        ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}',
-        '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'),
-        ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}',
-        '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
-        ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
-        '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'),
-        ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{2e2f}',
-        '\u{2e2f}'), ('\u{3005}', '\u{3006}'), ('\u{3031}', '\u{3035}'),
-        ('\u{303b}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}',
-        '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'),
-        ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}',
-        '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'),
-        ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}',
-        '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'),
-        ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), ('\u{a67f}',
-        '\u{a69d}'), ('\u{a6a0}', '\u{a6e5}'), ('\u{a717}', '\u{a71f}'),
-        ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}',
-        '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
-        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'),
-        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
-        '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'),
-        ('\u{a984}', '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}',
-        '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'),
-        ('\u{aa00}', '\u{aa28}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa44}',
-        '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
-        ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}',
-        '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'),
-        ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}',
-        '\u{aaea}'), ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'),
-        ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}',
-        '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'),
-        ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abe2}'), ('\u{ac00}',
-        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
-        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
-        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb1d}'),
-        ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}',
-        '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'),
-        ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}',
-        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
-        ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}',
-        '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
-        ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
-        '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'),
-        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
-        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
-        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10280}',
-        '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'),
-        ('\u{10330}', '\u{10340}'), ('\u{10342}', '\u{10349}'), ('\u{10350}',
-        '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'),
-        ('\u{103c8}', '\u{103cf}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}',
-        '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'),
-        ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}',
-        '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'),
-        ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}',
-        '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'),
-        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
-        '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'),
-        ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}',
-        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
-        ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}',
-        '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'),
-        ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}',
-        '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'),
-        ('\u{10cc0}', '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}',
-        '\u{110af}'), ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'),
-        ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}',
-        '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'),
-        ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
-        '\u{1122b}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'),
-        ('\u{1128a}', '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}',
-        '\u{112a8}'), ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'),
-        ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}',
-        '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'),
-        ('\u{1133d}', '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}',
-        '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'),
-        ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}',
-        '\u{115db}'), ('\u{11600}', '\u{1162f}'), ('\u{11644}', '\u{11644}'),
-        ('\u{11680}', '\u{116aa}'), ('\u{11700}', '\u{11719}'), ('\u{118a0}',
-        '\u{118df}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'),
-        ('\u{12000}', '\u{12399}'), ('\u{12480}', '\u{12543}'), ('\u{13000}',
-        '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'),
-        ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}',
-        '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'),
-        ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}',
-        '\u{16f50}'), ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'),
-        ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}',
-        '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}', '\u{1d454}'),
-        ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}',
-        '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'),
-        ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
-        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'),
-        ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}',
-        '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
-        ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}',
-        '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'),
-        ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}',
-        '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'),
-        ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}',
-        '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}', '\u{1e8c4}'),
-        ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}',
-        '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'),
-        ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}',
-        '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'),
-        ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}',
-        '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'),
-        ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}',
-        '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'),
-        ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}',
-        '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'),
-        ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}',
-        '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'),
-        ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}',
-        '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'),
-        ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}',
-        '\u{2fa1d}')
-    ];
-
-    pub const LC_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'),
-        ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'),
-        ('\u{1bc}', '\u{1bf}'), ('\u{1c4}', '\u{293}'), ('\u{295}', '\u{2af}'),
-        ('\u{370}', '\u{373}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
-        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
-        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
-        ('\u{561}', '\u{587}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
-        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{13a0}', '\u{13f5}'),
-        ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', '\u{1d2b}'), ('\u{1d6b}',
-        '\u{1d77}'), ('\u{1d79}', '\u{1d9a}'), ('\u{1e00}', '\u{1f15}'),
-        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
-        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
-        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
-        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
-        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
-        '\u{1ffc}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'),
-        ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2119}',
-        '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'),
-        ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}',
-        '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
-        ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2183}',
-        '\u{2184}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'),
-        ('\u{2c60}', '\u{2c7b}'), ('\u{2c7e}', '\u{2ce4}'), ('\u{2ceb}',
-        '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'),
-        ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{a640}',
-        '\u{a66d}'), ('\u{a680}', '\u{a69b}'), ('\u{a722}', '\u{a76f}'),
-        ('\u{a771}', '\u{a787}'), ('\u{a78b}', '\u{a78e}'), ('\u{a790}',
-        '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7fa}', '\u{a7fa}'),
-        ('\u{ab30}', '\u{ab5a}'), ('\u{ab60}', '\u{ab65}'), ('\u{ab70}',
-        '\u{abbf}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'),
-        ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10400}',
-        '\u{1044f}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'),
-        ('\u{118a0}', '\u{118df}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}',
-        '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
-        ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}',
-        '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'),
-        ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}',
-        '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'),
-        ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}',
-        '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'),
-        ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}',
-        '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'),
-        ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}',
-        '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'),
-        ('\u{1d7c4}', '\u{1d7cb}')
-    ];
-
-    pub const Ll_table: &'static [(char, char)] = &[
-        ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'), ('\u{df}', '\u{f6}'),
-        ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'),
-        ('\u{105}', '\u{105}'), ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'),
-        ('\u{10b}', '\u{10b}'), ('\u{10d}', '\u{10d}'), ('\u{10f}', '\u{10f}'),
-        ('\u{111}', '\u{111}'), ('\u{113}', '\u{113}'), ('\u{115}', '\u{115}'),
-        ('\u{117}', '\u{117}'), ('\u{119}', '\u{119}'), ('\u{11b}', '\u{11b}'),
-        ('\u{11d}', '\u{11d}'), ('\u{11f}', '\u{11f}'), ('\u{121}', '\u{121}'),
-        ('\u{123}', '\u{123}'), ('\u{125}', '\u{125}'), ('\u{127}', '\u{127}'),
-        ('\u{129}', '\u{129}'), ('\u{12b}', '\u{12b}'), ('\u{12d}', '\u{12d}'),
-        ('\u{12f}', '\u{12f}'), ('\u{131}', '\u{131}'), ('\u{133}', '\u{133}'),
-        ('\u{135}', '\u{135}'), ('\u{137}', '\u{138}'), ('\u{13a}', '\u{13a}'),
-        ('\u{13c}', '\u{13c}'), ('\u{13e}', '\u{13e}'), ('\u{140}', '\u{140}'),
-        ('\u{142}', '\u{142}'), ('\u{144}', '\u{144}'), ('\u{146}', '\u{146}'),
-        ('\u{148}', '\u{149}'), ('\u{14b}', '\u{14b}'), ('\u{14d}', '\u{14d}'),
-        ('\u{14f}', '\u{14f}'), ('\u{151}', '\u{151}'), ('\u{153}', '\u{153}'),
-        ('\u{155}', '\u{155}'), ('\u{157}', '\u{157}'), ('\u{159}', '\u{159}'),
-        ('\u{15b}', '\u{15b}'), ('\u{15d}', '\u{15d}'), ('\u{15f}', '\u{15f}'),
-        ('\u{161}', '\u{161}'), ('\u{163}', '\u{163}'), ('\u{165}', '\u{165}'),
-        ('\u{167}', '\u{167}'), ('\u{169}', '\u{169}'), ('\u{16b}', '\u{16b}'),
-        ('\u{16d}', '\u{16d}'), ('\u{16f}', '\u{16f}'), ('\u{171}', '\u{171}'),
-        ('\u{173}', '\u{173}'), ('\u{175}', '\u{175}'), ('\u{177}', '\u{177}'),
-        ('\u{17a}', '\u{17a}'), ('\u{17c}', '\u{17c}'), ('\u{17e}', '\u{180}'),
-        ('\u{183}', '\u{183}'), ('\u{185}', '\u{185}'), ('\u{188}', '\u{188}'),
-        ('\u{18c}', '\u{18d}'), ('\u{192}', '\u{192}'), ('\u{195}', '\u{195}'),
-        ('\u{199}', '\u{19b}'), ('\u{19e}', '\u{19e}'), ('\u{1a1}', '\u{1a1}'),
-        ('\u{1a3}', '\u{1a3}'), ('\u{1a5}', '\u{1a5}'), ('\u{1a8}', '\u{1a8}'),
-        ('\u{1aa}', '\u{1ab}'), ('\u{1ad}', '\u{1ad}'), ('\u{1b0}', '\u{1b0}'),
-        ('\u{1b4}', '\u{1b4}'), ('\u{1b6}', '\u{1b6}'), ('\u{1b9}', '\u{1ba}'),
-        ('\u{1bd}', '\u{1bf}'), ('\u{1c6}', '\u{1c6}'), ('\u{1c9}', '\u{1c9}'),
-        ('\u{1cc}', '\u{1cc}'), ('\u{1ce}', '\u{1ce}'), ('\u{1d0}', '\u{1d0}'),
-        ('\u{1d2}', '\u{1d2}'), ('\u{1d4}', '\u{1d4}'), ('\u{1d6}', '\u{1d6}'),
-        ('\u{1d8}', '\u{1d8}'), ('\u{1da}', '\u{1da}'), ('\u{1dc}', '\u{1dd}'),
-        ('\u{1df}', '\u{1df}'), ('\u{1e1}', '\u{1e1}'), ('\u{1e3}', '\u{1e3}'),
-        ('\u{1e5}', '\u{1e5}'), ('\u{1e7}', '\u{1e7}'), ('\u{1e9}', '\u{1e9}'),
-        ('\u{1eb}', '\u{1eb}'), ('\u{1ed}', '\u{1ed}'), ('\u{1ef}', '\u{1f0}'),
-        ('\u{1f3}', '\u{1f3}'), ('\u{1f5}', '\u{1f5}'), ('\u{1f9}', '\u{1f9}'),
-        ('\u{1fb}', '\u{1fb}'), ('\u{1fd}', '\u{1fd}'), ('\u{1ff}', '\u{1ff}'),
-        ('\u{201}', '\u{201}'), ('\u{203}', '\u{203}'), ('\u{205}', '\u{205}'),
-        ('\u{207}', '\u{207}'), ('\u{209}', '\u{209}'), ('\u{20b}', '\u{20b}'),
-        ('\u{20d}', '\u{20d}'), ('\u{20f}', '\u{20f}'), ('\u{211}', '\u{211}'),
-        ('\u{213}', '\u{213}'), ('\u{215}', '\u{215}'), ('\u{217}', '\u{217}'),
-        ('\u{219}', '\u{219}'), ('\u{21b}', '\u{21b}'), ('\u{21d}', '\u{21d}'),
-        ('\u{21f}', '\u{21f}'), ('\u{221}', '\u{221}'), ('\u{223}', '\u{223}'),
-        ('\u{225}', '\u{225}'), ('\u{227}', '\u{227}'), ('\u{229}', '\u{229}'),
-        ('\u{22b}', '\u{22b}'), ('\u{22d}', '\u{22d}'), ('\u{22f}', '\u{22f}'),
-        ('\u{231}', '\u{231}'), ('\u{233}', '\u{239}'), ('\u{23c}', '\u{23c}'),
-        ('\u{23f}', '\u{240}'), ('\u{242}', '\u{242}'), ('\u{247}', '\u{247}'),
-        ('\u{249}', '\u{249}'), ('\u{24b}', '\u{24b}'), ('\u{24d}', '\u{24d}'),
-        ('\u{24f}', '\u{293}'), ('\u{295}', '\u{2af}'), ('\u{371}', '\u{371}'),
-        ('\u{373}', '\u{373}'), ('\u{377}', '\u{377}'), ('\u{37b}', '\u{37d}'),
-        ('\u{390}', '\u{390}'), ('\u{3ac}', '\u{3ce}'), ('\u{3d0}', '\u{3d1}'),
-        ('\u{3d5}', '\u{3d7}'), ('\u{3d9}', '\u{3d9}'), ('\u{3db}', '\u{3db}'),
-        ('\u{3dd}', '\u{3dd}'), ('\u{3df}', '\u{3df}'), ('\u{3e1}', '\u{3e1}'),
-        ('\u{3e3}', '\u{3e3}'), ('\u{3e5}', '\u{3e5}'), ('\u{3e7}', '\u{3e7}'),
-        ('\u{3e9}', '\u{3e9}'), ('\u{3eb}', '\u{3eb}'), ('\u{3ed}', '\u{3ed}'),
-        ('\u{3ef}', '\u{3f3}'), ('\u{3f5}', '\u{3f5}'), ('\u{3f8}', '\u{3f8}'),
-        ('\u{3fb}', '\u{3fc}'), ('\u{430}', '\u{45f}'), ('\u{461}', '\u{461}'),
-        ('\u{463}', '\u{463}'), ('\u{465}', '\u{465}'), ('\u{467}', '\u{467}'),
-        ('\u{469}', '\u{469}'), ('\u{46b}', '\u{46b}'), ('\u{46d}', '\u{46d}'),
-        ('\u{46f}', '\u{46f}'), ('\u{471}', '\u{471}'), ('\u{473}', '\u{473}'),
-        ('\u{475}', '\u{475}'), ('\u{477}', '\u{477}'), ('\u{479}', '\u{479}'),
-        ('\u{47b}', '\u{47b}'), ('\u{47d}', '\u{47d}'), ('\u{47f}', '\u{47f}'),
-        ('\u{481}', '\u{481}'), ('\u{48b}', '\u{48b}'), ('\u{48d}', '\u{48d}'),
-        ('\u{48f}', '\u{48f}'), ('\u{491}', '\u{491}'), ('\u{493}', '\u{493}'),
-        ('\u{495}', '\u{495}'), ('\u{497}', '\u{497}'), ('\u{499}', '\u{499}'),
-        ('\u{49b}', '\u{49b}'), ('\u{49d}', '\u{49d}'), ('\u{49f}', '\u{49f}'),
-        ('\u{4a1}', '\u{4a1}'), ('\u{4a3}', '\u{4a3}'), ('\u{4a5}', '\u{4a5}'),
-        ('\u{4a7}', '\u{4a7}'), ('\u{4a9}', '\u{4a9}'), ('\u{4ab}', '\u{4ab}'),
-        ('\u{4ad}', '\u{4ad}'), ('\u{4af}', '\u{4af}'), ('\u{4b1}', '\u{4b1}'),
-        ('\u{4b3}', '\u{4b3}'), ('\u{4b5}', '\u{4b5}'), ('\u{4b7}', '\u{4b7}'),
-        ('\u{4b9}', '\u{4b9}'), ('\u{4bb}', '\u{4bb}'), ('\u{4bd}', '\u{4bd}'),
-        ('\u{4bf}', '\u{4bf}'), ('\u{4c2}', '\u{4c2}'), ('\u{4c4}', '\u{4c4}'),
-        ('\u{4c6}', '\u{4c6}'), ('\u{4c8}', '\u{4c8}'), ('\u{4ca}', '\u{4ca}'),
-        ('\u{4cc}', '\u{4cc}'), ('\u{4ce}', '\u{4cf}'), ('\u{4d1}', '\u{4d1}'),
-        ('\u{4d3}', '\u{4d3}'), ('\u{4d5}', '\u{4d5}'), ('\u{4d7}', '\u{4d7}'),
-        ('\u{4d9}', '\u{4d9}'), ('\u{4db}', '\u{4db}'), ('\u{4dd}', '\u{4dd}'),
-        ('\u{4df}', '\u{4df}'), ('\u{4e1}', '\u{4e1}'), ('\u{4e3}', '\u{4e3}'),
-        ('\u{4e5}', '\u{4e5}'), ('\u{4e7}', '\u{4e7}'), ('\u{4e9}', '\u{4e9}'),
-        ('\u{4eb}', '\u{4eb}'), ('\u{4ed}', '\u{4ed}'), ('\u{4ef}', '\u{4ef}'),
-        ('\u{4f1}', '\u{4f1}'), ('\u{4f3}', '\u{4f3}'), ('\u{4f5}', '\u{4f5}'),
-        ('\u{4f7}', '\u{4f7}'), ('\u{4f9}', '\u{4f9}'), ('\u{4fb}', '\u{4fb}'),
-        ('\u{4fd}', '\u{4fd}'), ('\u{4ff}', '\u{4ff}'), ('\u{501}', '\u{501}'),
-        ('\u{503}', '\u{503}'), ('\u{505}', '\u{505}'), ('\u{507}', '\u{507}'),
-        ('\u{509}', '\u{509}'), ('\u{50b}', '\u{50b}'), ('\u{50d}', '\u{50d}'),
-        ('\u{50f}', '\u{50f}'), ('\u{511}', '\u{511}'), ('\u{513}', '\u{513}'),
-        ('\u{515}', '\u{515}'), ('\u{517}', '\u{517}'), ('\u{519}', '\u{519}'),
-        ('\u{51b}', '\u{51b}'), ('\u{51d}', '\u{51d}'), ('\u{51f}', '\u{51f}'),
-        ('\u{521}', '\u{521}'), ('\u{523}', '\u{523}'), ('\u{525}', '\u{525}'),
-        ('\u{527}', '\u{527}'), ('\u{529}', '\u{529}'), ('\u{52b}', '\u{52b}'),
-        ('\u{52d}', '\u{52d}'), ('\u{52f}', '\u{52f}'), ('\u{561}', '\u{587}'),
-        ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', '\u{1d2b}'), ('\u{1d6b}',
-        '\u{1d77}'), ('\u{1d79}', '\u{1d9a}'), ('\u{1e01}', '\u{1e01}'),
-        ('\u{1e03}', '\u{1e03}'), ('\u{1e05}', '\u{1e05}'), ('\u{1e07}',
-        '\u{1e07}'), ('\u{1e09}', '\u{1e09}'), ('\u{1e0b}', '\u{1e0b}'),
-        ('\u{1e0d}', '\u{1e0d}'), ('\u{1e0f}', '\u{1e0f}'), ('\u{1e11}',
-        '\u{1e11}'), ('\u{1e13}', '\u{1e13}'), ('\u{1e15}', '\u{1e15}'),
-        ('\u{1e17}', '\u{1e17}'), ('\u{1e19}', '\u{1e19}'), ('\u{1e1b}',
-        '\u{1e1b}'), ('\u{1e1d}', '\u{1e1d}'), ('\u{1e1f}', '\u{1e1f}'),
-        ('\u{1e21}', '\u{1e21}'), ('\u{1e23}', '\u{1e23}'), ('\u{1e25}',
-        '\u{1e25}'), ('\u{1e27}', '\u{1e27}'), ('\u{1e29}', '\u{1e29}'),
-        ('\u{1e2b}', '\u{1e2b}'), ('\u{1e2d}', '\u{1e2d}'), ('\u{1e2f}',
-        '\u{1e2f}'), ('\u{1e31}', '\u{1e31}'), ('\u{1e33}', '\u{1e33}'),
-        ('\u{1e35}', '\u{1e35}'), ('\u{1e37}', '\u{1e37}'), ('\u{1e39}',
-        '\u{1e39}'), ('\u{1e3b}', '\u{1e3b}'), ('\u{1e3d}', '\u{1e3d}'),
-        ('\u{1e3f}', '\u{1e3f}'), ('\u{1e41}', '\u{1e41}'), ('\u{1e43}',
-        '\u{1e43}'), ('\u{1e45}', '\u{1e45}'), ('\u{1e47}', '\u{1e47}'),
-        ('\u{1e49}', '\u{1e49}'), ('\u{1e4b}', '\u{1e4b}'), ('\u{1e4d}',
-        '\u{1e4d}'), ('\u{1e4f}', '\u{1e4f}'), ('\u{1e51}', '\u{1e51}'),
-        ('\u{1e53}', '\u{1e53}'), ('\u{1e55}', '\u{1e55}'), ('\u{1e57}',
-        '\u{1e57}'), ('\u{1e59}', '\u{1e59}'), ('\u{1e5b}', '\u{1e5b}'),
-        ('\u{1e5d}', '\u{1e5d}'), ('\u{1e5f}', '\u{1e5f}'), ('\u{1e61}',
-        '\u{1e61}'), ('\u{1e63}', '\u{1e63}'), ('\u{1e65}', '\u{1e65}'),
-        ('\u{1e67}', '\u{1e67}'), ('\u{1e69}', '\u{1e69}'), ('\u{1e6b}',
-        '\u{1e6b}'), ('\u{1e6d}', '\u{1e6d}'), ('\u{1e6f}', '\u{1e6f}'),
-        ('\u{1e71}', '\u{1e71}'), ('\u{1e73}', '\u{1e73}'), ('\u{1e75}',
-        '\u{1e75}'), ('\u{1e77}', '\u{1e77}'), ('\u{1e79}', '\u{1e79}'),
-        ('\u{1e7b}', '\u{1e7b}'), ('\u{1e7d}', '\u{1e7d}'), ('\u{1e7f}',
-        '\u{1e7f}'), ('\u{1e81}', '\u{1e81}'), ('\u{1e83}', '\u{1e83}'),
-        ('\u{1e85}', '\u{1e85}'), ('\u{1e87}', '\u{1e87}'), ('\u{1e89}',
-        '\u{1e89}'), ('\u{1e8b}', '\u{1e8b}'), ('\u{1e8d}', '\u{1e8d}'),
-        ('\u{1e8f}', '\u{1e8f}'), ('\u{1e91}', '\u{1e91}'), ('\u{1e93}',
-        '\u{1e93}'), ('\u{1e95}', '\u{1e9d}'), ('\u{1e9f}', '\u{1e9f}'),
-        ('\u{1ea1}', '\u{1ea1}'), ('\u{1ea3}', '\u{1ea3}'), ('\u{1ea5}',
-        '\u{1ea5}'), ('\u{1ea7}', '\u{1ea7}'), ('\u{1ea9}', '\u{1ea9}'),
-        ('\u{1eab}', '\u{1eab}'), ('\u{1ead}', '\u{1ead}'), ('\u{1eaf}',
-        '\u{1eaf}'), ('\u{1eb1}', '\u{1eb1}'), ('\u{1eb3}', '\u{1eb3}'),
-        ('\u{1eb5}', '\u{1eb5}'), ('\u{1eb7}', '\u{1eb7}'), ('\u{1eb9}',
-        '\u{1eb9}'), ('\u{1ebb}', '\u{1ebb}'), ('\u{1ebd}', '\u{1ebd}'),
-        ('\u{1ebf}', '\u{1ebf}'), ('\u{1ec1}', '\u{1ec1}'), ('\u{1ec3}',
-        '\u{1ec3}'), ('\u{1ec5}', '\u{1ec5}'), ('\u{1ec7}', '\u{1ec7}'),
-        ('\u{1ec9}', '\u{1ec9}'), ('\u{1ecb}', '\u{1ecb}'), ('\u{1ecd}',
-        '\u{1ecd}'), ('\u{1ecf}', '\u{1ecf}'), ('\u{1ed1}', '\u{1ed1}'),
-        ('\u{1ed3}', '\u{1ed3}'), ('\u{1ed5}', '\u{1ed5}'), ('\u{1ed7}',
-        '\u{1ed7}'), ('\u{1ed9}', '\u{1ed9}'), ('\u{1edb}', '\u{1edb}'),
-        ('\u{1edd}', '\u{1edd}'), ('\u{1edf}', '\u{1edf}'), ('\u{1ee1}',
-        '\u{1ee1}'), ('\u{1ee3}', '\u{1ee3}'), ('\u{1ee5}', '\u{1ee5}'),
-        ('\u{1ee7}', '\u{1ee7}'), ('\u{1ee9}', '\u{1ee9}'), ('\u{1eeb}',
-        '\u{1eeb}'), ('\u{1eed}', '\u{1eed}'), ('\u{1eef}', '\u{1eef}'),
-        ('\u{1ef1}', '\u{1ef1}'), ('\u{1ef3}', '\u{1ef3}'), ('\u{1ef5}',
-        '\u{1ef5}'), ('\u{1ef7}', '\u{1ef7}'), ('\u{1ef9}', '\u{1ef9}'),
-        ('\u{1efb}', '\u{1efb}'), ('\u{1efd}', '\u{1efd}'), ('\u{1eff}',
-        '\u{1f07}'), ('\u{1f10}', '\u{1f15}'), ('\u{1f20}', '\u{1f27}'),
-        ('\u{1f30}', '\u{1f37}'), ('\u{1f40}', '\u{1f45}'), ('\u{1f50}',
-        '\u{1f57}'), ('\u{1f60}', '\u{1f67}'), ('\u{1f70}', '\u{1f7d}'),
-        ('\u{1f80}', '\u{1f87}'), ('\u{1f90}', '\u{1f97}'), ('\u{1fa0}',
-        '\u{1fa7}'), ('\u{1fb0}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fb7}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fc7}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fd7}'),
-        ('\u{1fe0}', '\u{1fe7}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
-        '\u{1ff7}'), ('\u{210a}', '\u{210a}'), ('\u{210e}', '\u{210f}'),
-        ('\u{2113}', '\u{2113}'), ('\u{212f}', '\u{212f}'), ('\u{2134}',
-        '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213d}'),
-        ('\u{2146}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2184}',
-        '\u{2184}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c61}', '\u{2c61}'),
-        ('\u{2c65}', '\u{2c66}'), ('\u{2c68}', '\u{2c68}'), ('\u{2c6a}',
-        '\u{2c6a}'), ('\u{2c6c}', '\u{2c6c}'), ('\u{2c71}', '\u{2c71}'),
-        ('\u{2c73}', '\u{2c74}'), ('\u{2c76}', '\u{2c7b}'), ('\u{2c81}',
-        '\u{2c81}'), ('\u{2c83}', '\u{2c83}'), ('\u{2c85}', '\u{2c85}'),
-        ('\u{2c87}', '\u{2c87}'), ('\u{2c89}', '\u{2c89}'), ('\u{2c8b}',
-        '\u{2c8b}'), ('\u{2c8d}', '\u{2c8d}'), ('\u{2c8f}', '\u{2c8f}'),
-        ('\u{2c91}', '\u{2c91}'), ('\u{2c93}', '\u{2c93}'), ('\u{2c95}',
-        '\u{2c95}'), ('\u{2c97}', '\u{2c97}'), ('\u{2c99}', '\u{2c99}'),
-        ('\u{2c9b}', '\u{2c9b}'), ('\u{2c9d}', '\u{2c9d}'), ('\u{2c9f}',
-        '\u{2c9f}'), ('\u{2ca1}', '\u{2ca1}'), ('\u{2ca3}', '\u{2ca3}'),
-        ('\u{2ca5}', '\u{2ca5}'), ('\u{2ca7}', '\u{2ca7}'), ('\u{2ca9}',
-        '\u{2ca9}'), ('\u{2cab}', '\u{2cab}'), ('\u{2cad}', '\u{2cad}'),
-        ('\u{2caf}', '\u{2caf}'), ('\u{2cb1}', '\u{2cb1}'), ('\u{2cb3}',
-        '\u{2cb3}'), ('\u{2cb5}', '\u{2cb5}'), ('\u{2cb7}', '\u{2cb7}'),
-        ('\u{2cb9}', '\u{2cb9}'), ('\u{2cbb}', '\u{2cbb}'), ('\u{2cbd}',
-        '\u{2cbd}'), ('\u{2cbf}', '\u{2cbf}'), ('\u{2cc1}', '\u{2cc1}'),
-        ('\u{2cc3}', '\u{2cc3}'), ('\u{2cc5}', '\u{2cc5}'), ('\u{2cc7}',
-        '\u{2cc7}'), ('\u{2cc9}', '\u{2cc9}'), ('\u{2ccb}', '\u{2ccb}'),
-        ('\u{2ccd}', '\u{2ccd}'), ('\u{2ccf}', '\u{2ccf}'), ('\u{2cd1}',
-        '\u{2cd1}'), ('\u{2cd3}', '\u{2cd3}'), ('\u{2cd5}', '\u{2cd5}'),
-        ('\u{2cd7}', '\u{2cd7}'), ('\u{2cd9}', '\u{2cd9}'), ('\u{2cdb}',
-        '\u{2cdb}'), ('\u{2cdd}', '\u{2cdd}'), ('\u{2cdf}', '\u{2cdf}'),
-        ('\u{2ce1}', '\u{2ce1}'), ('\u{2ce3}', '\u{2ce4}'), ('\u{2cec}',
-        '\u{2cec}'), ('\u{2cee}', '\u{2cee}'), ('\u{2cf3}', '\u{2cf3}'),
-        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
-        '\u{2d2d}'), ('\u{a641}', '\u{a641}'), ('\u{a643}', '\u{a643}'),
-        ('\u{a645}', '\u{a645}'), ('\u{a647}', '\u{a647}'), ('\u{a649}',
-        '\u{a649}'), ('\u{a64b}', '\u{a64b}'), ('\u{a64d}', '\u{a64d}'),
-        ('\u{a64f}', '\u{a64f}'), ('\u{a651}', '\u{a651}'), ('\u{a653}',
-        '\u{a653}'), ('\u{a655}', '\u{a655}'), ('\u{a657}', '\u{a657}'),
-        ('\u{a659}', '\u{a659}'), ('\u{a65b}', '\u{a65b}'), ('\u{a65d}',
-        '\u{a65d}'), ('\u{a65f}', '\u{a65f}'), ('\u{a661}', '\u{a661}'),
-        ('\u{a663}', '\u{a663}'), ('\u{a665}', '\u{a665}'), ('\u{a667}',
-        '\u{a667}'), ('\u{a669}', '\u{a669}'), ('\u{a66b}', '\u{a66b}'),
-        ('\u{a66d}', '\u{a66d}'), ('\u{a681}', '\u{a681}'), ('\u{a683}',
-        '\u{a683}'), ('\u{a685}', '\u{a685}'), ('\u{a687}', '\u{a687}'),
-        ('\u{a689}', '\u{a689}'), ('\u{a68b}', '\u{a68b}'), ('\u{a68d}',
-        '\u{a68d}'), ('\u{a68f}', '\u{a68f}'), ('\u{a691}', '\u{a691}'),
-        ('\u{a693}', '\u{a693}'), ('\u{a695}', '\u{a695}'), ('\u{a697}',
-        '\u{a697}'), ('\u{a699}', '\u{a699}'), ('\u{a69b}', '\u{a69b}'),
-        ('\u{a723}', '\u{a723}'), ('\u{a725}', '\u{a725}'), ('\u{a727}',
-        '\u{a727}'), ('\u{a729}', '\u{a729}'), ('\u{a72b}', '\u{a72b}'),
-        ('\u{a72d}', '\u{a72d}'), ('\u{a72f}', '\u{a731}'), ('\u{a733}',
-        '\u{a733}'), ('\u{a735}', '\u{a735}'), ('\u{a737}', '\u{a737}'),
-        ('\u{a739}', '\u{a739}'), ('\u{a73b}', '\u{a73b}'), ('\u{a73d}',
-        '\u{a73d}'), ('\u{a73f}', '\u{a73f}'), ('\u{a741}', '\u{a741}'),
-        ('\u{a743}', '\u{a743}'), ('\u{a745}', '\u{a745}'), ('\u{a747}',
-        '\u{a747}'), ('\u{a749}', '\u{a749}'), ('\u{a74b}', '\u{a74b}'),
-        ('\u{a74d}', '\u{a74d}'), ('\u{a74f}', '\u{a74f}'), ('\u{a751}',
-        '\u{a751}'), ('\u{a753}', '\u{a753}'), ('\u{a755}', '\u{a755}'),
-        ('\u{a757}', '\u{a757}'), ('\u{a759}', '\u{a759}'), ('\u{a75b}',
-        '\u{a75b}'), ('\u{a75d}', '\u{a75d}'), ('\u{a75f}', '\u{a75f}'),
-        ('\u{a761}', '\u{a761}'), ('\u{a763}', '\u{a763}'), ('\u{a765}',
-        '\u{a765}'), ('\u{a767}', '\u{a767}'), ('\u{a769}', '\u{a769}'),
-        ('\u{a76b}', '\u{a76b}'), ('\u{a76d}', '\u{a76d}'), ('\u{a76f}',
-        '\u{a76f}'), ('\u{a771}', '\u{a778}'), ('\u{a77a}', '\u{a77a}'),
-        ('\u{a77c}', '\u{a77c}'), ('\u{a77f}', '\u{a77f}'), ('\u{a781}',
-        '\u{a781}'), ('\u{a783}', '\u{a783}'), ('\u{a785}', '\u{a785}'),
-        ('\u{a787}', '\u{a787}'), ('\u{a78c}', '\u{a78c}'), ('\u{a78e}',
-        '\u{a78e}'), ('\u{a791}', '\u{a791}'), ('\u{a793}', '\u{a795}'),
-        ('\u{a797}', '\u{a797}'), ('\u{a799}', '\u{a799}'), ('\u{a79b}',
-        '\u{a79b}'), ('\u{a79d}', '\u{a79d}'), ('\u{a79f}', '\u{a79f}'),
-        ('\u{a7a1}', '\u{a7a1}'), ('\u{a7a3}', '\u{a7a3}'), ('\u{a7a5}',
-        '\u{a7a5}'), ('\u{a7a7}', '\u{a7a7}'), ('\u{a7a9}', '\u{a7a9}'),
-        ('\u{a7b5}', '\u{a7b5}'), ('\u{a7b7}', '\u{a7b7}'), ('\u{a7fa}',
-        '\u{a7fa}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab60}', '\u{ab65}'),
-        ('\u{ab70}', '\u{abbf}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}',
-        '\u{fb17}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10428}', '\u{1044f}'),
-        ('\u{10cc0}', '\u{10cf2}'), ('\u{118c0}', '\u{118df}'), ('\u{1d41a}',
-        '\u{1d433}'), ('\u{1d44e}', '\u{1d454}'), ('\u{1d456}', '\u{1d467}'),
-        ('\u{1d482}', '\u{1d49b}'), ('\u{1d4b6}', '\u{1d4b9}'), ('\u{1d4bb}',
-        '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d4cf}'),
-        ('\u{1d4ea}', '\u{1d503}'), ('\u{1d51e}', '\u{1d537}'), ('\u{1d552}',
-        '\u{1d56b}'), ('\u{1d586}', '\u{1d59f}'), ('\u{1d5ba}', '\u{1d5d3}'),
-        ('\u{1d5ee}', '\u{1d607}'), ('\u{1d622}', '\u{1d63b}'), ('\u{1d656}',
-        '\u{1d66f}'), ('\u{1d68a}', '\u{1d6a5}'), ('\u{1d6c2}', '\u{1d6da}'),
-        ('\u{1d6dc}', '\u{1d6e1}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}',
-        '\u{1d71b}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d755}'),
-        ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d78f}'), ('\u{1d7aa}',
-        '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7c9}'), ('\u{1d7cb}', '\u{1d7cb}')
-    ];
-
-    pub const Lm_table: &'static [(char, char)] = &[
-        ('\u{2b0}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'),
-        ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{374}', '\u{374}'),
-        ('\u{37a}', '\u{37a}'), ('\u{559}', '\u{559}'), ('\u{640}', '\u{640}'),
-        ('\u{6e5}', '\u{6e6}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
-        ('\u{81a}', '\u{81a}'), ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'),
-        ('\u{971}', '\u{971}'), ('\u{e46}', '\u{e46}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{10fc}', '\u{10fc}'), ('\u{17d7}', '\u{17d7}'), ('\u{1843}',
-        '\u{1843}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1c78}', '\u{1c7d}'),
-        ('\u{1d2c}', '\u{1d6a}'), ('\u{1d78}', '\u{1d78}'), ('\u{1d9b}',
-        '\u{1dbf}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
-        ('\u{2090}', '\u{209c}'), ('\u{2c7c}', '\u{2c7d}'), ('\u{2d6f}',
-        '\u{2d6f}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}', '\u{3005}'),
-        ('\u{3031}', '\u{3035}'), ('\u{303b}', '\u{303b}'), ('\u{309d}',
-        '\u{309e}'), ('\u{30fc}', '\u{30fe}'), ('\u{a015}', '\u{a015}'),
-        ('\u{a4f8}', '\u{a4fd}'), ('\u{a60c}', '\u{a60c}'), ('\u{a67f}',
-        '\u{a67f}'), ('\u{a69c}', '\u{a69d}'), ('\u{a717}', '\u{a71f}'),
-        ('\u{a770}', '\u{a770}'), ('\u{a788}', '\u{a788}'), ('\u{a7f8}',
-        '\u{a7f9}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e6}', '\u{a9e6}'),
-        ('\u{aa70}', '\u{aa70}'), ('\u{aadd}', '\u{aadd}'), ('\u{aaf3}',
-        '\u{aaf4}'), ('\u{ab5c}', '\u{ab5f}'), ('\u{ff70}', '\u{ff70}'),
-        ('\u{ff9e}', '\u{ff9f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16f93}',
-        '\u{16f9f}')
-    ];
-
-    pub const Lo_table: &'static [(char, char)] = &[
-        ('\u{aa}', '\u{aa}'), ('\u{ba}', '\u{ba}'), ('\u{1bb}', '\u{1bb}'),
-        ('\u{1c0}', '\u{1c3}'), ('\u{294}', '\u{294}'), ('\u{5d0}', '\u{5ea}'),
-        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'),
-        ('\u{66e}', '\u{66f}'), ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'),
-        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
-        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
-        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{800}', '\u{815}'),
-        ('\u{840}', '\u{858}'), ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'),
-        ('\u{93d}', '\u{93d}'), ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'),
-        ('\u{972}', '\u{980}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
-        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
-        ('\u{9b6}', '\u{9b9}'), ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'),
-        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'),
-        ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'),
-        ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'),
-        ('\u{a38}', '\u{a39}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
-        ('\u{a72}', '\u{a74}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
-        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
-        ('\u{ab5}', '\u{ab9}'), ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'),
-        ('\u{ae0}', '\u{ae1}'), ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'),
-        ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'),
-        ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'),
-        ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'),
-        ('\u{b83}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
-        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
-        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
-        ('\u{bae}', '\u{bb9}'), ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'),
-        ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'),
-        ('\u{c3d}', '\u{c3d}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'),
-        ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'),
-        ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'),
-        ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'),
-        ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'),
-        ('\u{d3d}', '\u{d3d}'), ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'),
-        ('\u{d7a}', '\u{d7f}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'),
-        ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'),
-        ('\u{e01}', '\u{e30}'), ('\u{e32}', '\u{e33}'), ('\u{e40}', '\u{e45}'),
-        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
-        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
-        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
-        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'),
-        ('\u{eb2}', '\u{eb3}'), ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'),
-        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
-        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
-        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
-        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
-        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
-        ('\u{108e}', '\u{108e}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fd}',
-        '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'),
-        ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}',
-        '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'),
-        ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
-        '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'),
-        ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}',
-        '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{1401}', '\u{166c}'),
-        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16f1}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
-        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
-        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
-        ('\u{1780}', '\u{17b3}'), ('\u{17dc}', '\u{17dc}'), ('\u{1820}',
-        '\u{1842}'), ('\u{1844}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
-        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
-        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
-        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1b05}', '\u{1b33}'),
-        ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}', '\u{1ba0}'), ('\u{1bae}',
-        '\u{1baf}'), ('\u{1bba}', '\u{1be5}'), ('\u{1c00}', '\u{1c23}'),
-        ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}', '\u{1c77}'), ('\u{1ce9}',
-        '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'), ('\u{1cf5}', '\u{1cf6}'),
-        ('\u{2135}', '\u{2138}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d80}',
-        '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'),
-        ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
-        '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
-        ('\u{2dd8}', '\u{2dde}'), ('\u{3006}', '\u{3006}'), ('\u{303c}',
-        '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309f}', '\u{309f}'),
-        ('\u{30a1}', '\u{30fa}'), ('\u{30ff}', '\u{30ff}'), ('\u{3105}',
-        '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'),
-        ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}',
-        '\u{9fd5}'), ('\u{a000}', '\u{a014}'), ('\u{a016}', '\u{a48c}'),
-        ('\u{a4d0}', '\u{a4f7}'), ('\u{a500}', '\u{a60b}'), ('\u{a610}',
-        '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a66e}', '\u{a66e}'),
-        ('\u{a6a0}', '\u{a6e5}'), ('\u{a78f}', '\u{a78f}'), ('\u{a7f7}',
-        '\u{a7f7}'), ('\u{a7fb}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
-        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'),
-        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
-        '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'),
-        ('\u{a984}', '\u{a9b2}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e7}',
-        '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'),
-        ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}',
-        '\u{aa6f}'), ('\u{aa71}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
-        ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}',
-        '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'),
-        ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadc}'), ('\u{aae0}',
-        '\u{aaea}'), ('\u{aaf2}', '\u{aaf2}'), ('\u{ab01}', '\u{ab06}'),
-        ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}',
-        '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{abc0}', '\u{abe2}'),
-        ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}',
-        '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'),
-        ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}',
-        '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'),
-        ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}',
-        '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'),
-        ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}',
-        '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff66}', '\u{ff6f}'),
-        ('\u{ff71}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}',
-        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
-        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
-        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
-        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
-        '\u{100fa}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'),
-        ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{10340}'), ('\u{10342}',
-        '\u{10349}'), ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'),
-        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{10450}',
-        '\u{1049d}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', '\u{10563}'),
-        ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}',
-        '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'),
-        ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}',
-        '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'),
-        ('\u{10880}', '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}',
-        '\u{108f5}'), ('\u{10900}', '\u{10915}'), ('\u{10920}', '\u{10939}'),
-        ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'), ('\u{10a00}',
-        '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'),
-        ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}',
-        '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'),
-        ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}',
-        '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'),
-        ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'), ('\u{110d0}',
-        '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', '\u{11172}'),
-        ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}',
-        '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'),
-        ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'), ('\u{11280}',
-        '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
-        ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}',
-        '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'),
-        ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}',
-        '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{1133d}'),
-        ('\u{11350}', '\u{11350}'), ('\u{1135d}', '\u{11361}'), ('\u{11480}',
-        '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'),
-        ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'), ('\u{11600}',
-        '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'),
-        ('\u{11700}', '\u{11719}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}',
-        '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12480}', '\u{12543}'),
-        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
-        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'),
-        ('\u{16b00}', '\u{16b2f}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
-        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'),
-        ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}',
-        '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'),
-        ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}',
-        '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'),
-        ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}',
-        '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
-        ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
-        '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'),
-        ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}',
-        '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'),
-        ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}',
-        '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
-        ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
-        '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'),
-        ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}',
-        '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'),
-        ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}',
-        '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}')
-    ];
-
-    pub const Lt_table: &'static [(char, char)] = &[
-        ('\u{1c5}', '\u{1c5}'), ('\u{1c8}', '\u{1c8}'), ('\u{1cb}', '\u{1cb}'),
-        ('\u{1f2}', '\u{1f2}'), ('\u{1f88}', '\u{1f8f}'), ('\u{1f98}',
-        '\u{1f9f}'), ('\u{1fa8}', '\u{1faf}'), ('\u{1fbc}', '\u{1fbc}'),
-        ('\u{1fcc}', '\u{1fcc}'), ('\u{1ffc}', '\u{1ffc}')
-    ];
-
-    pub const Lu_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'),
-        ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'),
-        ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'),
-        ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), ('\u{110}', '\u{110}'),
-        ('\u{112}', '\u{112}'), ('\u{114}', '\u{114}'), ('\u{116}', '\u{116}'),
-        ('\u{118}', '\u{118}'), ('\u{11a}', '\u{11a}'), ('\u{11c}', '\u{11c}'),
-        ('\u{11e}', '\u{11e}'), ('\u{120}', '\u{120}'), ('\u{122}', '\u{122}'),
-        ('\u{124}', '\u{124}'), ('\u{126}', '\u{126}'), ('\u{128}', '\u{128}'),
-        ('\u{12a}', '\u{12a}'), ('\u{12c}', '\u{12c}'), ('\u{12e}', '\u{12e}'),
-        ('\u{130}', '\u{130}'), ('\u{132}', '\u{132}'), ('\u{134}', '\u{134}'),
-        ('\u{136}', '\u{136}'), ('\u{139}', '\u{139}'), ('\u{13b}', '\u{13b}'),
-        ('\u{13d}', '\u{13d}'), ('\u{13f}', '\u{13f}'), ('\u{141}', '\u{141}'),
-        ('\u{143}', '\u{143}'), ('\u{145}', '\u{145}'), ('\u{147}', '\u{147}'),
-        ('\u{14a}', '\u{14a}'), ('\u{14c}', '\u{14c}'), ('\u{14e}', '\u{14e}'),
-        ('\u{150}', '\u{150}'), ('\u{152}', '\u{152}'), ('\u{154}', '\u{154}'),
-        ('\u{156}', '\u{156}'), ('\u{158}', '\u{158}'), ('\u{15a}', '\u{15a}'),
-        ('\u{15c}', '\u{15c}'), ('\u{15e}', '\u{15e}'), ('\u{160}', '\u{160}'),
-        ('\u{162}', '\u{162}'), ('\u{164}', '\u{164}'), ('\u{166}', '\u{166}'),
-        ('\u{168}', '\u{168}'), ('\u{16a}', '\u{16a}'), ('\u{16c}', '\u{16c}'),
-        ('\u{16e}', '\u{16e}'), ('\u{170}', '\u{170}'), ('\u{172}', '\u{172}'),
-        ('\u{174}', '\u{174}'), ('\u{176}', '\u{176}'), ('\u{178}', '\u{179}'),
-        ('\u{17b}', '\u{17b}'), ('\u{17d}', '\u{17d}'), ('\u{181}', '\u{182}'),
-        ('\u{184}', '\u{184}'), ('\u{186}', '\u{187}'), ('\u{189}', '\u{18b}'),
-        ('\u{18e}', '\u{191}'), ('\u{193}', '\u{194}'), ('\u{196}', '\u{198}'),
-        ('\u{19c}', '\u{19d}'), ('\u{19f}', '\u{1a0}'), ('\u{1a2}', '\u{1a2}'),
-        ('\u{1a4}', '\u{1a4}'), ('\u{1a6}', '\u{1a7}'), ('\u{1a9}', '\u{1a9}'),
-        ('\u{1ac}', '\u{1ac}'), ('\u{1ae}', '\u{1af}'), ('\u{1b1}', '\u{1b3}'),
-        ('\u{1b5}', '\u{1b5}'), ('\u{1b7}', '\u{1b8}'), ('\u{1bc}', '\u{1bc}'),
-        ('\u{1c4}', '\u{1c4}'), ('\u{1c7}', '\u{1c7}'), ('\u{1ca}', '\u{1ca}'),
-        ('\u{1cd}', '\u{1cd}'), ('\u{1cf}', '\u{1cf}'), ('\u{1d1}', '\u{1d1}'),
-        ('\u{1d3}', '\u{1d3}'), ('\u{1d5}', '\u{1d5}'), ('\u{1d7}', '\u{1d7}'),
-        ('\u{1d9}', '\u{1d9}'), ('\u{1db}', '\u{1db}'), ('\u{1de}', '\u{1de}'),
-        ('\u{1e0}', '\u{1e0}'), ('\u{1e2}', '\u{1e2}'), ('\u{1e4}', '\u{1e4}'),
-        ('\u{1e6}', '\u{1e6}'), ('\u{1e8}', '\u{1e8}'), ('\u{1ea}', '\u{1ea}'),
-        ('\u{1ec}', '\u{1ec}'), ('\u{1ee}', '\u{1ee}'), ('\u{1f1}', '\u{1f1}'),
-        ('\u{1f4}', '\u{1f4}'), ('\u{1f6}', '\u{1f8}'), ('\u{1fa}', '\u{1fa}'),
-        ('\u{1fc}', '\u{1fc}'), ('\u{1fe}', '\u{1fe}'), ('\u{200}', '\u{200}'),
-        ('\u{202}', '\u{202}'), ('\u{204}', '\u{204}'), ('\u{206}', '\u{206}'),
-        ('\u{208}', '\u{208}'), ('\u{20a}', '\u{20a}'), ('\u{20c}', '\u{20c}'),
-        ('\u{20e}', '\u{20e}'), ('\u{210}', '\u{210}'), ('\u{212}', '\u{212}'),
-        ('\u{214}', '\u{214}'), ('\u{216}', '\u{216}'), ('\u{218}', '\u{218}'),
-        ('\u{21a}', '\u{21a}'), ('\u{21c}', '\u{21c}'), ('\u{21e}', '\u{21e}'),
-        ('\u{220}', '\u{220}'), ('\u{222}', '\u{222}'), ('\u{224}', '\u{224}'),
-        ('\u{226}', '\u{226}'), ('\u{228}', '\u{228}'), ('\u{22a}', '\u{22a}'),
-        ('\u{22c}', '\u{22c}'), ('\u{22e}', '\u{22e}'), ('\u{230}', '\u{230}'),
-        ('\u{232}', '\u{232}'), ('\u{23a}', '\u{23b}'), ('\u{23d}', '\u{23e}'),
-        ('\u{241}', '\u{241}'), ('\u{243}', '\u{246}'), ('\u{248}', '\u{248}'),
-        ('\u{24a}', '\u{24a}'), ('\u{24c}', '\u{24c}'), ('\u{24e}', '\u{24e}'),
-        ('\u{370}', '\u{370}'), ('\u{372}', '\u{372}'), ('\u{376}', '\u{376}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
-        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{38f}'), ('\u{391}', '\u{3a1}'),
-        ('\u{3a3}', '\u{3ab}'), ('\u{3cf}', '\u{3cf}'), ('\u{3d2}', '\u{3d4}'),
-        ('\u{3d8}', '\u{3d8}'), ('\u{3da}', '\u{3da}'), ('\u{3dc}', '\u{3dc}'),
-        ('\u{3de}', '\u{3de}'), ('\u{3e0}', '\u{3e0}'), ('\u{3e2}', '\u{3e2}'),
-        ('\u{3e4}', '\u{3e4}'), ('\u{3e6}', '\u{3e6}'), ('\u{3e8}', '\u{3e8}'),
-        ('\u{3ea}', '\u{3ea}'), ('\u{3ec}', '\u{3ec}'), ('\u{3ee}', '\u{3ee}'),
-        ('\u{3f4}', '\u{3f4}'), ('\u{3f7}', '\u{3f7}'), ('\u{3f9}', '\u{3fa}'),
-        ('\u{3fd}', '\u{42f}'), ('\u{460}', '\u{460}'), ('\u{462}', '\u{462}'),
-        ('\u{464}', '\u{464}'), ('\u{466}', '\u{466}'), ('\u{468}', '\u{468}'),
-        ('\u{46a}', '\u{46a}'), ('\u{46c}', '\u{46c}'), ('\u{46e}', '\u{46e}'),
-        ('\u{470}', '\u{470}'), ('\u{472}', '\u{472}'), ('\u{474}', '\u{474}'),
-        ('\u{476}', '\u{476}'), ('\u{478}', '\u{478}'), ('\u{47a}', '\u{47a}'),
-        ('\u{47c}', '\u{47c}'), ('\u{47e}', '\u{47e}'), ('\u{480}', '\u{480}'),
-        ('\u{48a}', '\u{48a}'), ('\u{48c}', '\u{48c}'), ('\u{48e}', '\u{48e}'),
-        ('\u{490}', '\u{490}'), ('\u{492}', '\u{492}'), ('\u{494}', '\u{494}'),
-        ('\u{496}', '\u{496}'), ('\u{498}', '\u{498}'), ('\u{49a}', '\u{49a}'),
-        ('\u{49c}', '\u{49c}'), ('\u{49e}', '\u{49e}'), ('\u{4a0}', '\u{4a0}'),
-        ('\u{4a2}', '\u{4a2}'), ('\u{4a4}', '\u{4a4}'), ('\u{4a6}', '\u{4a6}'),
-        ('\u{4a8}', '\u{4a8}'), ('\u{4aa}', '\u{4aa}'), ('\u{4ac}', '\u{4ac}'),
-        ('\u{4ae}', '\u{4ae}'), ('\u{4b0}', '\u{4b0}'), ('\u{4b2}', '\u{4b2}'),
-        ('\u{4b4}', '\u{4b4}'), ('\u{4b6}', '\u{4b6}'), ('\u{4b8}', '\u{4b8}'),
-        ('\u{4ba}', '\u{4ba}'), ('\u{4bc}', '\u{4bc}'), ('\u{4be}', '\u{4be}'),
-        ('\u{4c0}', '\u{4c1}'), ('\u{4c3}', '\u{4c3}'), ('\u{4c5}', '\u{4c5}'),
-        ('\u{4c7}', '\u{4c7}'), ('\u{4c9}', '\u{4c9}'), ('\u{4cb}', '\u{4cb}'),
-        ('\u{4cd}', '\u{4cd}'), ('\u{4d0}', '\u{4d0}'), ('\u{4d2}', '\u{4d2}'),
-        ('\u{4d4}', '\u{4d4}'), ('\u{4d6}', '\u{4d6}'), ('\u{4d8}', '\u{4d8}'),
-        ('\u{4da}', '\u{4da}'), ('\u{4dc}', '\u{4dc}'), ('\u{4de}', '\u{4de}'),
-        ('\u{4e0}', '\u{4e0}'), ('\u{4e2}', '\u{4e2}'), ('\u{4e4}', '\u{4e4}'),
-        ('\u{4e6}', '\u{4e6}'), ('\u{4e8}', '\u{4e8}'), ('\u{4ea}', '\u{4ea}'),
-        ('\u{4ec}', '\u{4ec}'), ('\u{4ee}', '\u{4ee}'), ('\u{4f0}', '\u{4f0}'),
-        ('\u{4f2}', '\u{4f2}'), ('\u{4f4}', '\u{4f4}'), ('\u{4f6}', '\u{4f6}'),
-        ('\u{4f8}', '\u{4f8}'), ('\u{4fa}', '\u{4fa}'), ('\u{4fc}', '\u{4fc}'),
-        ('\u{4fe}', '\u{4fe}'), ('\u{500}', '\u{500}'), ('\u{502}', '\u{502}'),
-        ('\u{504}', '\u{504}'), ('\u{506}', '\u{506}'), ('\u{508}', '\u{508}'),
-        ('\u{50a}', '\u{50a}'), ('\u{50c}', '\u{50c}'), ('\u{50e}', '\u{50e}'),
-        ('\u{510}', '\u{510}'), ('\u{512}', '\u{512}'), ('\u{514}', '\u{514}'),
-        ('\u{516}', '\u{516}'), ('\u{518}', '\u{518}'), ('\u{51a}', '\u{51a}'),
-        ('\u{51c}', '\u{51c}'), ('\u{51e}', '\u{51e}'), ('\u{520}', '\u{520}'),
-        ('\u{522}', '\u{522}'), ('\u{524}', '\u{524}'), ('\u{526}', '\u{526}'),
-        ('\u{528}', '\u{528}'), ('\u{52a}', '\u{52a}'), ('\u{52c}', '\u{52c}'),
-        ('\u{52e}', '\u{52e}'), ('\u{531}', '\u{556}'), ('\u{10a0}',
-        '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'),
-        ('\u{13a0}', '\u{13f5}'), ('\u{1e00}', '\u{1e00}'), ('\u{1e02}',
-        '\u{1e02}'), ('\u{1e04}', '\u{1e04}'), ('\u{1e06}', '\u{1e06}'),
-        ('\u{1e08}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0a}'), ('\u{1e0c}',
-        '\u{1e0c}'), ('\u{1e0e}', '\u{1e0e}'), ('\u{1e10}', '\u{1e10}'),
-        ('\u{1e12}', '\u{1e12}'), ('\u{1e14}', '\u{1e14}'), ('\u{1e16}',
-        '\u{1e16}'), ('\u{1e18}', '\u{1e18}'), ('\u{1e1a}', '\u{1e1a}'),
-        ('\u{1e1c}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1e}'), ('\u{1e20}',
-        '\u{1e20}'), ('\u{1e22}', '\u{1e22}'), ('\u{1e24}', '\u{1e24}'),
-        ('\u{1e26}', '\u{1e26}'), ('\u{1e28}', '\u{1e28}'), ('\u{1e2a}',
-        '\u{1e2a}'), ('\u{1e2c}', '\u{1e2c}'), ('\u{1e2e}', '\u{1e2e}'),
-        ('\u{1e30}', '\u{1e30}'), ('\u{1e32}', '\u{1e32}'), ('\u{1e34}',
-        '\u{1e34}'), ('\u{1e36}', '\u{1e36}'), ('\u{1e38}', '\u{1e38}'),
-        ('\u{1e3a}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3c}'), ('\u{1e3e}',
-        '\u{1e3e}'), ('\u{1e40}', '\u{1e40}'), ('\u{1e42}', '\u{1e42}'),
-        ('\u{1e44}', '\u{1e44}'), ('\u{1e46}', '\u{1e46}'), ('\u{1e48}',
-        '\u{1e48}'), ('\u{1e4a}', '\u{1e4a}'), ('\u{1e4c}', '\u{1e4c}'),
-        ('\u{1e4e}', '\u{1e4e}'), ('\u{1e50}', '\u{1e50}'), ('\u{1e52}',
-        '\u{1e52}'), ('\u{1e54}', '\u{1e54}'), ('\u{1e56}', '\u{1e56}'),
-        ('\u{1e58}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5a}'), ('\u{1e5c}',
-        '\u{1e5c}'), ('\u{1e5e}', '\u{1e5e}'), ('\u{1e60}', '\u{1e60}'),
-        ('\u{1e62}', '\u{1e62}'), ('\u{1e64}', '\u{1e64}'), ('\u{1e66}',
-        '\u{1e66}'), ('\u{1e68}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6a}'),
-        ('\u{1e6c}', '\u{1e6c}'), ('\u{1e6e}', '\u{1e6e}'), ('\u{1e70}',
-        '\u{1e70}'), ('\u{1e72}', '\u{1e72}'), ('\u{1e74}', '\u{1e74}'),
-        ('\u{1e76}', '\u{1e76}'), ('\u{1e78}', '\u{1e78}'), ('\u{1e7a}',
-        '\u{1e7a}'), ('\u{1e7c}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7e}'),
-        ('\u{1e80}', '\u{1e80}'), ('\u{1e82}', '\u{1e82}'), ('\u{1e84}',
-        '\u{1e84}'), ('\u{1e86}', '\u{1e86}'), ('\u{1e88}', '\u{1e88}'),
-        ('\u{1e8a}', '\u{1e8a}'), ('\u{1e8c}', '\u{1e8c}'), ('\u{1e8e}',
-        '\u{1e8e}'), ('\u{1e90}', '\u{1e90}'), ('\u{1e92}', '\u{1e92}'),
-        ('\u{1e94}', '\u{1e94}'), ('\u{1e9e}', '\u{1e9e}'), ('\u{1ea0}',
-        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea2}'), ('\u{1ea4}', '\u{1ea4}'),
-        ('\u{1ea6}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea8}'), ('\u{1eaa}',
-        '\u{1eaa}'), ('\u{1eac}', '\u{1eac}'), ('\u{1eae}', '\u{1eae}'),
-        ('\u{1eb0}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb2}'), ('\u{1eb4}',
-        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb6}'), ('\u{1eb8}', '\u{1eb8}'),
-        ('\u{1eba}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebc}'), ('\u{1ebe}',
-        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec0}'), ('\u{1ec2}', '\u{1ec2}'),
-        ('\u{1ec4}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec6}'), ('\u{1ec8}',
-        '\u{1ec8}'), ('\u{1eca}', '\u{1eca}'), ('\u{1ecc}', '\u{1ecc}'),
-        ('\u{1ece}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed0}'), ('\u{1ed2}',
-        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed4}'), ('\u{1ed6}', '\u{1ed6}'),
-        ('\u{1ed8}', '\u{1ed8}'), ('\u{1eda}', '\u{1eda}'), ('\u{1edc}',
-        '\u{1edc}'), ('\u{1ede}', '\u{1ede}'), ('\u{1ee0}', '\u{1ee0}'),
-        ('\u{1ee2}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee4}'), ('\u{1ee6}',
-        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee8}'), ('\u{1eea}', '\u{1eea}'),
-        ('\u{1eec}', '\u{1eec}'), ('\u{1eee}', '\u{1eee}'), ('\u{1ef0}',
-        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef2}'), ('\u{1ef4}', '\u{1ef4}'),
-        ('\u{1ef6}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef8}'), ('\u{1efa}',
-        '\u{1efa}'), ('\u{1efc}', '\u{1efc}'), ('\u{1efe}', '\u{1efe}'),
-        ('\u{1f08}', '\u{1f0f}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f28}',
-        '\u{1f2f}'), ('\u{1f38}', '\u{1f3f}'), ('\u{1f48}', '\u{1f4d}'),
-        ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
-        '\u{1f5d}'), ('\u{1f5f}', '\u{1f5f}'), ('\u{1f68}', '\u{1f6f}'),
-        ('\u{1fb8}', '\u{1fbb}'), ('\u{1fc8}', '\u{1fcb}'), ('\u{1fd8}',
-        '\u{1fdb}'), ('\u{1fe8}', '\u{1fec}'), ('\u{1ff8}', '\u{1ffb}'),
-        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210b}',
-        '\u{210d}'), ('\u{2110}', '\u{2112}'), ('\u{2115}', '\u{2115}'),
-        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
-        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
-        ('\u{2130}', '\u{2133}'), ('\u{213e}', '\u{213f}'), ('\u{2145}',
-        '\u{2145}'), ('\u{2183}', '\u{2183}'), ('\u{2c00}', '\u{2c2e}'),
-        ('\u{2c60}', '\u{2c60}'), ('\u{2c62}', '\u{2c64}'), ('\u{2c67}',
-        '\u{2c67}'), ('\u{2c69}', '\u{2c69}'), ('\u{2c6b}', '\u{2c6b}'),
-        ('\u{2c6d}', '\u{2c70}'), ('\u{2c72}', '\u{2c72}'), ('\u{2c75}',
-        '\u{2c75}'), ('\u{2c7e}', '\u{2c80}'), ('\u{2c82}', '\u{2c82}'),
-        ('\u{2c84}', '\u{2c84}'), ('\u{2c86}', '\u{2c86}'), ('\u{2c88}',
-        '\u{2c88}'), ('\u{2c8a}', '\u{2c8a}'), ('\u{2c8c}', '\u{2c8c}'),
-        ('\u{2c8e}', '\u{2c8e}'), ('\u{2c90}', '\u{2c90}'), ('\u{2c92}',
-        '\u{2c92}'), ('\u{2c94}', '\u{2c94}'), ('\u{2c96}', '\u{2c96}'),
-        ('\u{2c98}', '\u{2c98}'), ('\u{2c9a}', '\u{2c9a}'), ('\u{2c9c}',
-        '\u{2c9c}'), ('\u{2c9e}', '\u{2c9e}'), ('\u{2ca0}', '\u{2ca0}'),
-        ('\u{2ca2}', '\u{2ca2}'), ('\u{2ca4}', '\u{2ca4}'), ('\u{2ca6}',
-        '\u{2ca6}'), ('\u{2ca8}', '\u{2ca8}'), ('\u{2caa}', '\u{2caa}'),
-        ('\u{2cac}', '\u{2cac}'), ('\u{2cae}', '\u{2cae}'), ('\u{2cb0}',
-        '\u{2cb0}'), ('\u{2cb2}', '\u{2cb2}'), ('\u{2cb4}', '\u{2cb4}'),
-        ('\u{2cb6}', '\u{2cb6}'), ('\u{2cb8}', '\u{2cb8}'), ('\u{2cba}',
-        '\u{2cba}'), ('\u{2cbc}', '\u{2cbc}'), ('\u{2cbe}', '\u{2cbe}'),
-        ('\u{2cc0}', '\u{2cc0}'), ('\u{2cc2}', '\u{2cc2}'), ('\u{2cc4}',
-        '\u{2cc4}'), ('\u{2cc6}', '\u{2cc6}'), ('\u{2cc8}', '\u{2cc8}'),
-        ('\u{2cca}', '\u{2cca}'), ('\u{2ccc}', '\u{2ccc}'), ('\u{2cce}',
-        '\u{2cce}'), ('\u{2cd0}', '\u{2cd0}'), ('\u{2cd2}', '\u{2cd2}'),
-        ('\u{2cd4}', '\u{2cd4}'), ('\u{2cd6}', '\u{2cd6}'), ('\u{2cd8}',
-        '\u{2cd8}'), ('\u{2cda}', '\u{2cda}'), ('\u{2cdc}', '\u{2cdc}'),
-        ('\u{2cde}', '\u{2cde}'), ('\u{2ce0}', '\u{2ce0}'), ('\u{2ce2}',
-        '\u{2ce2}'), ('\u{2ceb}', '\u{2ceb}'), ('\u{2ced}', '\u{2ced}'),
-        ('\u{2cf2}', '\u{2cf2}'), ('\u{a640}', '\u{a640}'), ('\u{a642}',
-        '\u{a642}'), ('\u{a644}', '\u{a644}'), ('\u{a646}', '\u{a646}'),
-        ('\u{a648}', '\u{a648}'), ('\u{a64a}', '\u{a64a}'), ('\u{a64c}',
-        '\u{a64c}'), ('\u{a64e}', '\u{a64e}'), ('\u{a650}', '\u{a650}'),
-        ('\u{a652}', '\u{a652}'), ('\u{a654}', '\u{a654}'), ('\u{a656}',
-        '\u{a656}'), ('\u{a658}', '\u{a658}'), ('\u{a65a}', '\u{a65a}'),
-        ('\u{a65c}', '\u{a65c}'), ('\u{a65e}', '\u{a65e}'), ('\u{a660}',
-        '\u{a660}'), ('\u{a662}', '\u{a662}'), ('\u{a664}', '\u{a664}'),
-        ('\u{a666}', '\u{a666}'), ('\u{a668}', '\u{a668}'), ('\u{a66a}',
-        '\u{a66a}'), ('\u{a66c}', '\u{a66c}'), ('\u{a680}', '\u{a680}'),
-        ('\u{a682}', '\u{a682}'), ('\u{a684}', '\u{a684}'), ('\u{a686}',
-        '\u{a686}'), ('\u{a688}', '\u{a688}'), ('\u{a68a}', '\u{a68a}'),
-        ('\u{a68c}', '\u{a68c}'), ('\u{a68e}', '\u{a68e}'), ('\u{a690}',
-        '\u{a690}'), ('\u{a692}', '\u{a692}'), ('\u{a694}', '\u{a694}'),
-        ('\u{a696}', '\u{a696}'), ('\u{a698}', '\u{a698}'), ('\u{a69a}',
-        '\u{a69a}'), ('\u{a722}', '\u{a722}'), ('\u{a724}', '\u{a724}'),
-        ('\u{a726}', '\u{a726}'), ('\u{a728}', '\u{a728}'), ('\u{a72a}',
-        '\u{a72a}'), ('\u{a72c}', '\u{a72c}'), ('\u{a72e}', '\u{a72e}'),
-        ('\u{a732}', '\u{a732}'), ('\u{a734}', '\u{a734}'), ('\u{a736}',
-        '\u{a736}'), ('\u{a738}', '\u{a738}'), ('\u{a73a}', '\u{a73a}'),
-        ('\u{a73c}', '\u{a73c}'), ('\u{a73e}', '\u{a73e}'), ('\u{a740}',
-        '\u{a740}'), ('\u{a742}', '\u{a742}'), ('\u{a744}', '\u{a744}'),
-        ('\u{a746}', '\u{a746}'), ('\u{a748}', '\u{a748}'), ('\u{a74a}',
-        '\u{a74a}'), ('\u{a74c}', '\u{a74c}'), ('\u{a74e}', '\u{a74e}'),
-        ('\u{a750}', '\u{a750}'), ('\u{a752}', '\u{a752}'), ('\u{a754}',
-        '\u{a754}'), ('\u{a756}', '\u{a756}'), ('\u{a758}', '\u{a758}'),
-        ('\u{a75a}', '\u{a75a}'), ('\u{a75c}', '\u{a75c}'), ('\u{a75e}',
-        '\u{a75e}'), ('\u{a760}', '\u{a760}'), ('\u{a762}', '\u{a762}'),
-        ('\u{a764}', '\u{a764}'), ('\u{a766}', '\u{a766}'), ('\u{a768}',
-        '\u{a768}'), ('\u{a76a}', '\u{a76a}'), ('\u{a76c}', '\u{a76c}'),
-        ('\u{a76e}', '\u{a76e}'), ('\u{a779}', '\u{a779}'), ('\u{a77b}',
-        '\u{a77b}'), ('\u{a77d}', '\u{a77e}'), ('\u{a780}', '\u{a780}'),
-        ('\u{a782}', '\u{a782}'), ('\u{a784}', '\u{a784}'), ('\u{a786}',
-        '\u{a786}'), ('\u{a78b}', '\u{a78b}'), ('\u{a78d}', '\u{a78d}'),
-        ('\u{a790}', '\u{a790}'), ('\u{a792}', '\u{a792}'), ('\u{a796}',
-        '\u{a796}'), ('\u{a798}', '\u{a798}'), ('\u{a79a}', '\u{a79a}'),
-        ('\u{a79c}', '\u{a79c}'), ('\u{a79e}', '\u{a79e}'), ('\u{a7a0}',
-        '\u{a7a0}'), ('\u{a7a2}', '\u{a7a2}'), ('\u{a7a4}', '\u{a7a4}'),
-        ('\u{a7a6}', '\u{a7a6}'), ('\u{a7a8}', '\u{a7a8}'), ('\u{a7aa}',
-        '\u{a7ad}'), ('\u{a7b0}', '\u{a7b4}'), ('\u{a7b6}', '\u{a7b6}'),
-        ('\u{ff21}', '\u{ff3a}'), ('\u{10400}', '\u{10427}'), ('\u{10c80}',
-        '\u{10cb2}'), ('\u{118a0}', '\u{118bf}'), ('\u{1d400}', '\u{1d419}'),
-        ('\u{1d434}', '\u{1d44d}'), ('\u{1d468}', '\u{1d481}'), ('\u{1d49c}',
-        '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
-        ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}',
-        '\u{1d4b5}'), ('\u{1d4d0}', '\u{1d4e9}'), ('\u{1d504}', '\u{1d505}'),
-        ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}',
-        '\u{1d51c}'), ('\u{1d538}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'),
-        ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}',
-        '\u{1d550}'), ('\u{1d56c}', '\u{1d585}'), ('\u{1d5a0}', '\u{1d5b9}'),
-        ('\u{1d5d4}', '\u{1d5ed}'), ('\u{1d608}', '\u{1d621}'), ('\u{1d63c}',
-        '\u{1d655}'), ('\u{1d670}', '\u{1d689}'), ('\u{1d6a8}', '\u{1d6c0}'),
-        ('\u{1d6e2}', '\u{1d6fa}'), ('\u{1d71c}', '\u{1d734}'), ('\u{1d756}',
-        '\u{1d76e}'), ('\u{1d790}', '\u{1d7a8}'), ('\u{1d7ca}', '\u{1d7ca}')
-    ];
-
-    pub const M_table: &'static [(char, char)] = &[
-        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'),
-        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
-        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
-        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
-        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
-        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
-        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
-        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{903}'),
-        ('\u{93a}', '\u{93c}'), ('\u{93e}', '\u{94f}'), ('\u{951}', '\u{957}'),
-        ('\u{962}', '\u{963}'), ('\u{981}', '\u{983}'), ('\u{9bc}', '\u{9bc}'),
-        ('\u{9be}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cd}'),
-        ('\u{9d7}', '\u{9d7}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a03}'),
-        ('\u{a3c}', '\u{a3c}'), ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'),
-        ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'),
-        ('\u{a75}', '\u{a75}'), ('\u{a81}', '\u{a83}'), ('\u{abc}', '\u{abc}'),
-        ('\u{abe}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'),
-        ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b03}'), ('\u{b3c}', '\u{b3c}'),
-        ('\u{b3e}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'),
-        ('\u{b56}', '\u{b57}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'),
-        ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
-        ('\u{bd7}', '\u{bd7}'), ('\u{c00}', '\u{c03}'), ('\u{c3e}', '\u{c44}'),
-        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
-        ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c83}'), ('\u{cbc}', '\u{cbc}'),
-        ('\u{cbe}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
-        ('\u{cd5}', '\u{cd6}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d03}'),
-        ('\u{d3e}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4d}'),
-        ('\u{d57}', '\u{d57}'), ('\u{d62}', '\u{d63}'), ('\u{d82}', '\u{d83}'),
-        ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
-        ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{e31}', '\u{e31}'),
-        ('\u{e34}', '\u{e3a}'), ('\u{e47}', '\u{e4e}'), ('\u{eb1}', '\u{eb1}'),
-        ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'), ('\u{ec8}', '\u{ecd}'),
-        ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'),
-        ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f3f}'), ('\u{f71}', '\u{f84}'),
-        ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'),
-        ('\u{fc6}', '\u{fc6}'), ('\u{102b}', '\u{103e}'), ('\u{1056}',
-        '\u{1059}'), ('\u{105e}', '\u{1060}'), ('\u{1062}', '\u{1064}'),
-        ('\u{1067}', '\u{106d}'), ('\u{1071}', '\u{1074}'), ('\u{1082}',
-        '\u{108d}'), ('\u{108f}', '\u{108f}'), ('\u{109a}', '\u{109d}'),
-        ('\u{135d}', '\u{135f}'), ('\u{1712}', '\u{1714}'), ('\u{1732}',
-        '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}', '\u{1773}'),
-        ('\u{17b4}', '\u{17d3}'), ('\u{17dd}', '\u{17dd}'), ('\u{180b}',
-        '\u{180d}'), ('\u{18a9}', '\u{18a9}'), ('\u{1920}', '\u{192b}'),
-        ('\u{1930}', '\u{193b}'), ('\u{1a17}', '\u{1a1b}'), ('\u{1a55}',
-        '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a7f}'),
-        ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}', '\u{1b04}'), ('\u{1b34}',
-        '\u{1b44}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1b82}'),
-        ('\u{1ba1}', '\u{1bad}'), ('\u{1be6}', '\u{1bf3}'), ('\u{1c24}',
-        '\u{1c37}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce8}'),
-        ('\u{1ced}', '\u{1ced}'), ('\u{1cf2}', '\u{1cf4}'), ('\u{1cf8}',
-        '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'), ('\u{1dfc}', '\u{1dff}'),
-        ('\u{20d0}', '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}',
-        '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302f}'),
-        ('\u{3099}', '\u{309a}'), ('\u{a66f}', '\u{a672}'), ('\u{a674}',
-        '\u{a67d}'), ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'),
-        ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}',
-        '\u{a80b}'), ('\u{a823}', '\u{a827}'), ('\u{a880}', '\u{a881}'),
-        ('\u{a8b4}', '\u{a8c4}'), ('\u{a8e0}', '\u{a8f1}'), ('\u{a926}',
-        '\u{a92d}'), ('\u{a947}', '\u{a953}'), ('\u{a980}', '\u{a983}'),
-        ('\u{a9b3}', '\u{a9c0}'), ('\u{a9e5}', '\u{a9e5}'), ('\u{aa29}',
-        '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4d}'),
-        ('\u{aa7b}', '\u{aa7d}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}',
-        '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'),
-        ('\u{aac1}', '\u{aac1}'), ('\u{aaeb}', '\u{aaef}'), ('\u{aaf5}',
-        '\u{aaf6}'), ('\u{abe3}', '\u{abea}'), ('\u{abec}', '\u{abed}'),
-        ('\u{fb1e}', '\u{fb1e}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}',
-        '\u{fe2f}'), ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', '\u{102e0}'),
-        ('\u{10376}', '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}',
-        '\u{10a06}'), ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'),
-        ('\u{10a3f}', '\u{10a3f}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{11000}',
-        '\u{11002}'), ('\u{11038}', '\u{11046}'), ('\u{1107f}', '\u{11082}'),
-        ('\u{110b0}', '\u{110ba}'), ('\u{11100}', '\u{11102}'), ('\u{11127}',
-        '\u{11134}'), ('\u{11173}', '\u{11173}'), ('\u{11180}', '\u{11182}'),
-        ('\u{111b3}', '\u{111c0}'), ('\u{111ca}', '\u{111cc}'), ('\u{1122c}',
-        '\u{11237}'), ('\u{112df}', '\u{112ea}'), ('\u{11300}', '\u{11303}'),
-        ('\u{1133c}', '\u{1133c}'), ('\u{1133e}', '\u{11344}'), ('\u{11347}',
-        '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11357}', '\u{11357}'),
-        ('\u{11362}', '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
-        '\u{11374}'), ('\u{114b0}', '\u{114c3}'), ('\u{115af}', '\u{115b5}'),
-        ('\u{115b8}', '\u{115c0}'), ('\u{115dc}', '\u{115dd}'), ('\u{11630}',
-        '\u{11640}'), ('\u{116ab}', '\u{116b7}'), ('\u{1171d}', '\u{1172b}'),
-        ('\u{16af0}', '\u{16af4}'), ('\u{16b30}', '\u{16b36}'), ('\u{16f51}',
-        '\u{16f7e}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}', '\u{1bc9e}'),
-        ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}',
-        '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'),
-        ('\u{1d242}', '\u{1d244}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}',
-        '\u{1da6c}'), ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'),
-        ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}',
-        '\u{1e8d6}'), ('\u{e0100}', '\u{e01ef}')
-    ];
-
-    pub const Mc_table: &'static [(char, char)] = &[
-        ('\u{903}', '\u{903}'), ('\u{93b}', '\u{93b}'), ('\u{93e}', '\u{940}'),
-        ('\u{949}', '\u{94c}'), ('\u{94e}', '\u{94f}'), ('\u{982}', '\u{983}'),
-        ('\u{9be}', '\u{9c0}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cc}'),
-        ('\u{9d7}', '\u{9d7}'), ('\u{a03}', '\u{a03}'), ('\u{a3e}', '\u{a40}'),
-        ('\u{a83}', '\u{a83}'), ('\u{abe}', '\u{ac0}'), ('\u{ac9}', '\u{ac9}'),
-        ('\u{acb}', '\u{acc}'), ('\u{b02}', '\u{b03}'), ('\u{b3e}', '\u{b3e}'),
-        ('\u{b40}', '\u{b40}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4c}'),
-        ('\u{b57}', '\u{b57}'), ('\u{bbe}', '\u{bbf}'), ('\u{bc1}', '\u{bc2}'),
-        ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcc}'), ('\u{bd7}', '\u{bd7}'),
-        ('\u{c01}', '\u{c03}'), ('\u{c41}', '\u{c44}'), ('\u{c82}', '\u{c83}'),
-        ('\u{cbe}', '\u{cbe}'), ('\u{cc0}', '\u{cc4}'), ('\u{cc7}', '\u{cc8}'),
-        ('\u{cca}', '\u{ccb}'), ('\u{cd5}', '\u{cd6}'), ('\u{d02}', '\u{d03}'),
-        ('\u{d3e}', '\u{d40}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4c}'),
-        ('\u{d57}', '\u{d57}'), ('\u{d82}', '\u{d83}'), ('\u{dcf}', '\u{dd1}'),
-        ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{f3e}', '\u{f3f}'),
-        ('\u{f7f}', '\u{f7f}'), ('\u{102b}', '\u{102c}'), ('\u{1031}',
-        '\u{1031}'), ('\u{1038}', '\u{1038}'), ('\u{103b}', '\u{103c}'),
-        ('\u{1056}', '\u{1057}'), ('\u{1062}', '\u{1064}'), ('\u{1067}',
-        '\u{106d}'), ('\u{1083}', '\u{1084}'), ('\u{1087}', '\u{108c}'),
-        ('\u{108f}', '\u{108f}'), ('\u{109a}', '\u{109c}'), ('\u{17b6}',
-        '\u{17b6}'), ('\u{17be}', '\u{17c5}'), ('\u{17c7}', '\u{17c8}'),
-        ('\u{1923}', '\u{1926}'), ('\u{1929}', '\u{192b}'), ('\u{1930}',
-        '\u{1931}'), ('\u{1933}', '\u{1938}'), ('\u{1a19}', '\u{1a1a}'),
-        ('\u{1a55}', '\u{1a55}'), ('\u{1a57}', '\u{1a57}'), ('\u{1a61}',
-        '\u{1a61}'), ('\u{1a63}', '\u{1a64}'), ('\u{1a6d}', '\u{1a72}'),
-        ('\u{1b04}', '\u{1b04}'), ('\u{1b35}', '\u{1b35}'), ('\u{1b3b}',
-        '\u{1b3b}'), ('\u{1b3d}', '\u{1b41}'), ('\u{1b43}', '\u{1b44}'),
-        ('\u{1b82}', '\u{1b82}'), ('\u{1ba1}', '\u{1ba1}'), ('\u{1ba6}',
-        '\u{1ba7}'), ('\u{1baa}', '\u{1baa}'), ('\u{1be7}', '\u{1be7}'),
-        ('\u{1bea}', '\u{1bec}'), ('\u{1bee}', '\u{1bee}'), ('\u{1bf2}',
-        '\u{1bf3}'), ('\u{1c24}', '\u{1c2b}'), ('\u{1c34}', '\u{1c35}'),
-        ('\u{1ce1}', '\u{1ce1}'), ('\u{1cf2}', '\u{1cf3}'), ('\u{302e}',
-        '\u{302f}'), ('\u{a823}', '\u{a824}'), ('\u{a827}', '\u{a827}'),
-        ('\u{a880}', '\u{a881}'), ('\u{a8b4}', '\u{a8c3}'), ('\u{a952}',
-        '\u{a953}'), ('\u{a983}', '\u{a983}'), ('\u{a9b4}', '\u{a9b5}'),
-        ('\u{a9ba}', '\u{a9bb}'), ('\u{a9bd}', '\u{a9c0}'), ('\u{aa2f}',
-        '\u{aa30}'), ('\u{aa33}', '\u{aa34}'), ('\u{aa4d}', '\u{aa4d}'),
-        ('\u{aa7b}', '\u{aa7b}'), ('\u{aa7d}', '\u{aa7d}'), ('\u{aaeb}',
-        '\u{aaeb}'), ('\u{aaee}', '\u{aaef}'), ('\u{aaf5}', '\u{aaf5}'),
-        ('\u{abe3}', '\u{abe4}'), ('\u{abe6}', '\u{abe7}'), ('\u{abe9}',
-        '\u{abea}'), ('\u{abec}', '\u{abec}'), ('\u{11000}', '\u{11000}'),
-        ('\u{11002}', '\u{11002}'), ('\u{11082}', '\u{11082}'), ('\u{110b0}',
-        '\u{110b2}'), ('\u{110b7}', '\u{110b8}'), ('\u{1112c}', '\u{1112c}'),
-        ('\u{11182}', '\u{11182}'), ('\u{111b3}', '\u{111b5}'), ('\u{111bf}',
-        '\u{111c0}'), ('\u{1122c}', '\u{1122e}'), ('\u{11232}', '\u{11233}'),
-        ('\u{11235}', '\u{11235}'), ('\u{112e0}', '\u{112e2}'), ('\u{11302}',
-        '\u{11303}'), ('\u{1133e}', '\u{1133f}'), ('\u{11341}', '\u{11344}'),
-        ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11357}',
-        '\u{11357}'), ('\u{11362}', '\u{11363}'), ('\u{114b0}', '\u{114b2}'),
-        ('\u{114b9}', '\u{114b9}'), ('\u{114bb}', '\u{114be}'), ('\u{114c1}',
-        '\u{114c1}'), ('\u{115af}', '\u{115b1}'), ('\u{115b8}', '\u{115bb}'),
-        ('\u{115be}', '\u{115be}'), ('\u{11630}', '\u{11632}'), ('\u{1163b}',
-        '\u{1163c}'), ('\u{1163e}', '\u{1163e}'), ('\u{116ac}', '\u{116ac}'),
-        ('\u{116ae}', '\u{116af}'), ('\u{116b6}', '\u{116b6}'), ('\u{11720}',
-        '\u{11721}'), ('\u{11726}', '\u{11726}'), ('\u{16f51}', '\u{16f7e}'),
-        ('\u{1d165}', '\u{1d166}'), ('\u{1d16d}', '\u{1d172}')
-    ];
-
-    pub const Me_table: &'static [(char, char)] = &[
-        ('\u{488}', '\u{489}'), ('\u{1abe}', '\u{1abe}'), ('\u{20dd}',
-        '\u{20e0}'), ('\u{20e2}', '\u{20e4}'), ('\u{a670}', '\u{a672}')
-    ];
-
-    pub const Mn_table: &'static [(char, char)] = &[
-        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{487}'), ('\u{591}', '\u{5bd}'),
-        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
-        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
-        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
-        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
-        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
-        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
-        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{902}'),
-        ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}', '\u{948}'),
-        ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'),
-        ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9c1}', '\u{9c4}'),
-        ('\u{9cd}', '\u{9cd}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'),
-        ('\u{a3c}', '\u{a3c}'), ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'),
-        ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'),
-        ('\u{a75}', '\u{a75}'), ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'),
-        ('\u{ac1}', '\u{ac5}'), ('\u{ac7}', '\u{ac8}'), ('\u{acd}', '\u{acd}'),
-        ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b01}'), ('\u{b3c}', '\u{b3c}'),
-        ('\u{b3f}', '\u{b3f}'), ('\u{b41}', '\u{b44}'), ('\u{b4d}', '\u{b4d}'),
-        ('\u{b56}', '\u{b56}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'),
-        ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{c00}', '\u{c00}'),
-        ('\u{c3e}', '\u{c40}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'),
-        ('\u{c55}', '\u{c56}'), ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c81}'),
-        ('\u{cbc}', '\u{cbc}'), ('\u{cbf}', '\u{cbf}'), ('\u{cc6}', '\u{cc6}'),
-        ('\u{ccc}', '\u{ccd}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d01}'),
-        ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'), ('\u{d62}', '\u{d63}'),
-        ('\u{dca}', '\u{dca}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
-        ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'), ('\u{e47}', '\u{e4e}'),
-        ('\u{eb1}', '\u{eb1}'), ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'),
-        ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'),
-        ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f71}', '\u{f7e}'),
-        ('\u{f80}', '\u{f84}'), ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'),
-        ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{102d}',
-        '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}', '\u{103a}'),
-        ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'), ('\u{105e}',
-        '\u{1060}'), ('\u{1071}', '\u{1074}'), ('\u{1082}', '\u{1082}'),
-        ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'), ('\u{109d}',
-        '\u{109d}'), ('\u{135d}', '\u{135f}'), ('\u{1712}', '\u{1714}'),
-        ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}',
-        '\u{1773}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b7}', '\u{17bd}'),
-        ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', '\u{17d3}'), ('\u{17dd}',
-        '\u{17dd}'), ('\u{180b}', '\u{180d}'), ('\u{18a9}', '\u{18a9}'),
-        ('\u{1920}', '\u{1922}'), ('\u{1927}', '\u{1928}'), ('\u{1932}',
-        '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}', '\u{1a18}'),
-        ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'), ('\u{1a58}',
-        '\u{1a5e}'), ('\u{1a60}', '\u{1a60}'), ('\u{1a62}', '\u{1a62}'),
-        ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'), ('\u{1a7f}',
-        '\u{1a7f}'), ('\u{1ab0}', '\u{1abd}'), ('\u{1b00}', '\u{1b03}'),
-        ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'), ('\u{1b3c}',
-        '\u{1b3c}'), ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}', '\u{1b73}'),
-        ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', '\u{1ba5}'), ('\u{1ba8}',
-        '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}', '\u{1be6}'),
-        ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bef}',
-        '\u{1bf1}'), ('\u{1c2c}', '\u{1c33}'), ('\u{1c36}', '\u{1c37}'),
-        ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}',
-        '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}', '\u{1cf4}'),
-        ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'), ('\u{1dfc}',
-        '\u{1dff}'), ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'),
-        ('\u{20e5}', '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}',
-        '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302d}'),
-        ('\u{3099}', '\u{309a}'), ('\u{a66f}', '\u{a66f}'), ('\u{a674}',
-        '\u{a67d}'), ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'),
-        ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}',
-        '\u{a80b}'), ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'),
-        ('\u{a8e0}', '\u{a8f1}'), ('\u{a926}', '\u{a92d}'), ('\u{a947}',
-        '\u{a951}'), ('\u{a980}', '\u{a982}'), ('\u{a9b3}', '\u{a9b3}'),
-        ('\u{a9b6}', '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9e5}',
-        '\u{a9e5}'), ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'),
-        ('\u{aa35}', '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}',
-        '\u{aa4c}'), ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'),
-        ('\u{aab2}', '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}',
-        '\u{aabf}'), ('\u{aac1}', '\u{aac1}'), ('\u{aaec}', '\u{aaed}'),
-        ('\u{aaf6}', '\u{aaf6}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}',
-        '\u{abe8}'), ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'),
-        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{101fd}',
-        '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}', '\u{1037a}'),
-        ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
-        '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'),
-        ('\u{10ae5}', '\u{10ae6}'), ('\u{11001}', '\u{11001}'), ('\u{11038}',
-        '\u{11046}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}', '\u{110b6}'),
-        ('\u{110b9}', '\u{110ba}'), ('\u{11100}', '\u{11102}'), ('\u{11127}',
-        '\u{1112b}'), ('\u{1112d}', '\u{11134}'), ('\u{11173}', '\u{11173}'),
-        ('\u{11180}', '\u{11181}'), ('\u{111b6}', '\u{111be}'), ('\u{111ca}',
-        '\u{111cc}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}', '\u{11234}'),
-        ('\u{11236}', '\u{11237}'), ('\u{112df}', '\u{112df}'), ('\u{112e3}',
-        '\u{112ea}'), ('\u{11300}', '\u{11301}'), ('\u{1133c}', '\u{1133c}'),
-        ('\u{11340}', '\u{11340}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
-        '\u{11374}'), ('\u{114b3}', '\u{114b8}'), ('\u{114ba}', '\u{114ba}'),
-        ('\u{114bf}', '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115b2}',
-        '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}', '\u{115c0}'),
-        ('\u{115dc}', '\u{115dd}'), ('\u{11633}', '\u{1163a}'), ('\u{1163d}',
-        '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}', '\u{116ab}'),
-        ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', '\u{116b5}'), ('\u{116b7}',
-        '\u{116b7}'), ('\u{1171d}', '\u{1171f}'), ('\u{11722}', '\u{11725}'),
-        ('\u{11727}', '\u{1172b}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b30}',
-        '\u{16b36}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}', '\u{1bc9e}'),
-        ('\u{1d167}', '\u{1d169}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}',
-        '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'),
-        ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}',
-        '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'),
-        ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{e0100}',
-        '\u{e01ef}')
-    ];
-
-    pub const N_table: &'static [(char, char)] = &[
-        ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'),
-        ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'),
-        ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'),
-        ('\u{be6}', '\u{bef}'), ('\u{c66}', '\u{c6f}'), ('\u{ce6}', '\u{cef}'),
-        ('\u{d66}', '\u{d6f}'), ('\u{de6}', '\u{def}'), ('\u{e50}', '\u{e59}'),
-        ('\u{ed0}', '\u{ed9}'), ('\u{f20}', '\u{f29}'), ('\u{1040}',
-        '\u{1049}'), ('\u{1090}', '\u{1099}'), ('\u{16ee}', '\u{16f0}'),
-        ('\u{17e0}', '\u{17e9}'), ('\u{1810}', '\u{1819}'), ('\u{1946}',
-        '\u{194f}'), ('\u{19d0}', '\u{19d9}'), ('\u{1a80}', '\u{1a89}'),
-        ('\u{1a90}', '\u{1a99}'), ('\u{1b50}', '\u{1b59}'), ('\u{1bb0}',
-        '\u{1bb9}'), ('\u{1c40}', '\u{1c49}'), ('\u{1c50}', '\u{1c59}'),
-        ('\u{2160}', '\u{2182}'), ('\u{2185}', '\u{2188}'), ('\u{3007}',
-        '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303a}'),
-        ('\u{a620}', '\u{a629}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{a8d0}',
-        '\u{a8d9}'), ('\u{a900}', '\u{a909}'), ('\u{a9d0}', '\u{a9d9}'),
-        ('\u{a9f0}', '\u{a9f9}'), ('\u{aa50}', '\u{aa59}'), ('\u{abf0}',
-        '\u{abf9}'), ('\u{ff10}', '\u{ff19}'), ('\u{10140}', '\u{10174}'),
-        ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'), ('\u{103d1}',
-        '\u{103d5}'), ('\u{104a0}', '\u{104a9}'), ('\u{11066}', '\u{1106f}'),
-        ('\u{110f0}', '\u{110f9}'), ('\u{11136}', '\u{1113f}'), ('\u{111d0}',
-        '\u{111d9}'), ('\u{112f0}', '\u{112f9}'), ('\u{114d0}', '\u{114d9}'),
-        ('\u{11650}', '\u{11659}'), ('\u{116c0}', '\u{116c9}'), ('\u{11730}',
-        '\u{11739}'), ('\u{118e0}', '\u{118e9}'), ('\u{12400}', '\u{1246e}'),
-        ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'), ('\u{1d7ce}',
-        '\u{1d7ff}')
-    ];
-
-    pub const Nd_table: &'static [(char, char)] = &[
-        ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'),
-        ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'),
-        ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'),
-        ('\u{be6}', '\u{bef}'), ('\u{c66}', '\u{c6f}'), ('\u{ce6}', '\u{cef}'),
-        ('\u{d66}', '\u{d6f}'), ('\u{de6}', '\u{def}'), ('\u{e50}', '\u{e59}'),
-        ('\u{ed0}', '\u{ed9}'), ('\u{f20}', '\u{f29}'), ('\u{1040}',
-        '\u{1049}'), ('\u{1090}', '\u{1099}'), ('\u{17e0}', '\u{17e9}'),
-        ('\u{1810}', '\u{1819}'), ('\u{1946}', '\u{194f}'), ('\u{19d0}',
-        '\u{19d9}'), ('\u{1a80}', '\u{1a89}'), ('\u{1a90}', '\u{1a99}'),
-        ('\u{1b50}', '\u{1b59}'), ('\u{1bb0}', '\u{1bb9}'), ('\u{1c40}',
-        '\u{1c49}'), ('\u{1c50}', '\u{1c59}'), ('\u{a620}', '\u{a629}'),
-        ('\u{a8d0}', '\u{a8d9}'), ('\u{a900}', '\u{a909}'), ('\u{a9d0}',
-        '\u{a9d9}'), ('\u{a9f0}', '\u{a9f9}'), ('\u{aa50}', '\u{aa59}'),
-        ('\u{abf0}', '\u{abf9}'), ('\u{ff10}', '\u{ff19}'), ('\u{104a0}',
-        '\u{104a9}'), ('\u{11066}', '\u{1106f}'), ('\u{110f0}', '\u{110f9}'),
-        ('\u{11136}', '\u{1113f}'), ('\u{111d0}', '\u{111d9}'), ('\u{112f0}',
-        '\u{112f9}'), ('\u{114d0}', '\u{114d9}'), ('\u{11650}', '\u{11659}'),
-        ('\u{116c0}', '\u{116c9}'), ('\u{11730}', '\u{11739}'), ('\u{118e0}',
-        '\u{118e9}'), ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'),
-        ('\u{1d7ce}', '\u{1d7ff}')
-    ];
-
-    pub const Nl_table: &'static [(char, char)] = &[
-        ('\u{16ee}', '\u{16f0}'), ('\u{2160}', '\u{2182}'), ('\u{2185}',
-        '\u{2188}'), ('\u{3007}', '\u{3007}'), ('\u{3021}', '\u{3029}'),
-        ('\u{3038}', '\u{303a}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{10140}',
-        '\u{10174}'), ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'),
-        ('\u{103d1}', '\u{103d5}'), ('\u{12400}', '\u{1246e}')
-    ];
-
-    pub const No_table: &'static [(char, char)] = &[
-        ('\u{b2}', '\u{b3}'), ('\u{b9}', '\u{b9}'), ('\u{bc}', '\u{be}'),
-        ('\u{9f4}', '\u{9f9}'), ('\u{b72}', '\u{b77}'), ('\u{bf0}', '\u{bf2}'),
-        ('\u{c78}', '\u{c7e}'), ('\u{d70}', '\u{d75}'), ('\u{f2a}', '\u{f33}'),
-        ('\u{1369}', '\u{137c}'), ('\u{17f0}', '\u{17f9}'), ('\u{19da}',
-        '\u{19da}'), ('\u{2070}', '\u{2070}'), ('\u{2074}', '\u{2079}'),
-        ('\u{2080}', '\u{2089}'), ('\u{2150}', '\u{215f}'), ('\u{2189}',
-        '\u{2189}'), ('\u{2460}', '\u{249b}'), ('\u{24ea}', '\u{24ff}'),
-        ('\u{2776}', '\u{2793}'), ('\u{2cfd}', '\u{2cfd}'), ('\u{3192}',
-        '\u{3195}'), ('\u{3220}', '\u{3229}'), ('\u{3248}', '\u{324f}'),
-        ('\u{3251}', '\u{325f}'), ('\u{3280}', '\u{3289}'), ('\u{32b1}',
-        '\u{32bf}'), ('\u{a830}', '\u{a835}'), ('\u{10107}', '\u{10133}'),
-        ('\u{10175}', '\u{10178}'), ('\u{1018a}', '\u{1018b}'), ('\u{102e1}',
-        '\u{102fb}'), ('\u{10320}', '\u{10323}'), ('\u{10858}', '\u{1085f}'),
-        ('\u{10879}', '\u{1087f}'), ('\u{108a7}', '\u{108af}'), ('\u{108fb}',
-        '\u{108ff}'), ('\u{10916}', '\u{1091b}'), ('\u{109bc}', '\u{109bd}'),
-        ('\u{109c0}', '\u{109cf}'), ('\u{109d2}', '\u{109ff}'), ('\u{10a40}',
-        '\u{10a47}'), ('\u{10a7d}', '\u{10a7e}'), ('\u{10a9d}', '\u{10a9f}'),
-        ('\u{10aeb}', '\u{10aef}'), ('\u{10b58}', '\u{10b5f}'), ('\u{10b78}',
-        '\u{10b7f}'), ('\u{10ba9}', '\u{10baf}'), ('\u{10cfa}', '\u{10cff}'),
-        ('\u{10e60}', '\u{10e7e}'), ('\u{11052}', '\u{11065}'), ('\u{111e1}',
-        '\u{111f4}'), ('\u{1173a}', '\u{1173b}'), ('\u{118ea}', '\u{118f2}'),
-        ('\u{16b5b}', '\u{16b61}'), ('\u{1d360}', '\u{1d371}'), ('\u{1e8c7}',
-        '\u{1e8cf}'), ('\u{1f100}', '\u{1f10c}')
-    ];
-
-    pub const P_table: &'static [(char, char)] = &[
-        ('\u{21}', '\u{23}'), ('\u{25}', '\u{2a}'), ('\u{2c}', '\u{2f}'),
-        ('\u{3a}', '\u{3b}'), ('\u{3f}', '\u{40}'), ('\u{5b}', '\u{5d}'),
-        ('\u{5f}', '\u{5f}'), ('\u{7b}', '\u{7b}'), ('\u{7d}', '\u{7d}'),
-        ('\u{a1}', '\u{a1}'), ('\u{a7}', '\u{a7}'), ('\u{ab}', '\u{ab}'),
-        ('\u{b6}', '\u{b7}'), ('\u{bb}', '\u{bb}'), ('\u{bf}', '\u{bf}'),
-        ('\u{37e}', '\u{37e}'), ('\u{387}', '\u{387}'), ('\u{55a}', '\u{55f}'),
-        ('\u{589}', '\u{58a}'), ('\u{5be}', '\u{5be}'), ('\u{5c0}', '\u{5c0}'),
-        ('\u{5c3}', '\u{5c3}'), ('\u{5c6}', '\u{5c6}'), ('\u{5f3}', '\u{5f4}'),
-        ('\u{609}', '\u{60a}'), ('\u{60c}', '\u{60d}'), ('\u{61b}', '\u{61b}'),
-        ('\u{61e}', '\u{61f}'), ('\u{66a}', '\u{66d}'), ('\u{6d4}', '\u{6d4}'),
-        ('\u{700}', '\u{70d}'), ('\u{7f7}', '\u{7f9}'), ('\u{830}', '\u{83e}'),
-        ('\u{85e}', '\u{85e}'), ('\u{964}', '\u{965}'), ('\u{970}', '\u{970}'),
-        ('\u{af0}', '\u{af0}'), ('\u{df4}', '\u{df4}'), ('\u{e4f}', '\u{e4f}'),
-        ('\u{e5a}', '\u{e5b}'), ('\u{f04}', '\u{f12}'), ('\u{f14}', '\u{f14}'),
-        ('\u{f3a}', '\u{f3d}'), ('\u{f85}', '\u{f85}'), ('\u{fd0}', '\u{fd4}'),
-        ('\u{fd9}', '\u{fda}'), ('\u{104a}', '\u{104f}'), ('\u{10fb}',
-        '\u{10fb}'), ('\u{1360}', '\u{1368}'), ('\u{1400}', '\u{1400}'),
-        ('\u{166d}', '\u{166e}'), ('\u{169b}', '\u{169c}'), ('\u{16eb}',
-        '\u{16ed}'), ('\u{1735}', '\u{1736}'), ('\u{17d4}', '\u{17d6}'),
-        ('\u{17d8}', '\u{17da}'), ('\u{1800}', '\u{180a}'), ('\u{1944}',
-        '\u{1945}'), ('\u{1a1e}', '\u{1a1f}'), ('\u{1aa0}', '\u{1aa6}'),
-        ('\u{1aa8}', '\u{1aad}'), ('\u{1b5a}', '\u{1b60}'), ('\u{1bfc}',
-        '\u{1bff}'), ('\u{1c3b}', '\u{1c3f}'), ('\u{1c7e}', '\u{1c7f}'),
-        ('\u{1cc0}', '\u{1cc7}'), ('\u{1cd3}', '\u{1cd3}'), ('\u{2010}',
-        '\u{2027}'), ('\u{2030}', '\u{2043}'), ('\u{2045}', '\u{2051}'),
-        ('\u{2053}', '\u{205e}'), ('\u{207d}', '\u{207e}'), ('\u{208d}',
-        '\u{208e}'), ('\u{2308}', '\u{230b}'), ('\u{2329}', '\u{232a}'),
-        ('\u{2768}', '\u{2775}'), ('\u{27c5}', '\u{27c6}'), ('\u{27e6}',
-        '\u{27ef}'), ('\u{2983}', '\u{2998}'), ('\u{29d8}', '\u{29db}'),
-        ('\u{29fc}', '\u{29fd}'), ('\u{2cf9}', '\u{2cfc}'), ('\u{2cfe}',
-        '\u{2cff}'), ('\u{2d70}', '\u{2d70}'), ('\u{2e00}', '\u{2e2e}'),
-        ('\u{2e30}', '\u{2e42}'), ('\u{3001}', '\u{3003}'), ('\u{3008}',
-        '\u{3011}'), ('\u{3014}', '\u{301f}'), ('\u{3030}', '\u{3030}'),
-        ('\u{303d}', '\u{303d}'), ('\u{30a0}', '\u{30a0}'), ('\u{30fb}',
-        '\u{30fb}'), ('\u{a4fe}', '\u{a4ff}'), ('\u{a60d}', '\u{a60f}'),
-        ('\u{a673}', '\u{a673}'), ('\u{a67e}', '\u{a67e}'), ('\u{a6f2}',
-        '\u{a6f7}'), ('\u{a874}', '\u{a877}'), ('\u{a8ce}', '\u{a8cf}'),
-        ('\u{a8f8}', '\u{a8fa}'), ('\u{a8fc}', '\u{a8fc}'), ('\u{a92e}',
-        '\u{a92f}'), ('\u{a95f}', '\u{a95f}'), ('\u{a9c1}', '\u{a9cd}'),
-        ('\u{a9de}', '\u{a9df}'), ('\u{aa5c}', '\u{aa5f}'), ('\u{aade}',
-        '\u{aadf}'), ('\u{aaf0}', '\u{aaf1}'), ('\u{abeb}', '\u{abeb}'),
-        ('\u{fd3e}', '\u{fd3f}'), ('\u{fe10}', '\u{fe19}'), ('\u{fe30}',
-        '\u{fe52}'), ('\u{fe54}', '\u{fe61}'), ('\u{fe63}', '\u{fe63}'),
-        ('\u{fe68}', '\u{fe68}'), ('\u{fe6a}', '\u{fe6b}'), ('\u{ff01}',
-        '\u{ff03}'), ('\u{ff05}', '\u{ff0a}'), ('\u{ff0c}', '\u{ff0f}'),
-        ('\u{ff1a}', '\u{ff1b}'), ('\u{ff1f}', '\u{ff20}'), ('\u{ff3b}',
-        '\u{ff3d}'), ('\u{ff3f}', '\u{ff3f}'), ('\u{ff5b}', '\u{ff5b}'),
-        ('\u{ff5d}', '\u{ff5d}'), ('\u{ff5f}', '\u{ff65}'), ('\u{10100}',
-        '\u{10102}'), ('\u{1039f}', '\u{1039f}'), ('\u{103d0}', '\u{103d0}'),
-        ('\u{1056f}', '\u{1056f}'), ('\u{10857}', '\u{10857}'), ('\u{1091f}',
-        '\u{1091f}'), ('\u{1093f}', '\u{1093f}'), ('\u{10a50}', '\u{10a58}'),
-        ('\u{10a7f}', '\u{10a7f}'), ('\u{10af0}', '\u{10af6}'), ('\u{10b39}',
-        '\u{10b3f}'), ('\u{10b99}', '\u{10b9c}'), ('\u{11047}', '\u{1104d}'),
-        ('\u{110bb}', '\u{110bc}'), ('\u{110be}', '\u{110c1}'), ('\u{11140}',
-        '\u{11143}'), ('\u{11174}', '\u{11175}'), ('\u{111c5}', '\u{111c9}'),
-        ('\u{111cd}', '\u{111cd}'), ('\u{111db}', '\u{111db}'), ('\u{111dd}',
-        '\u{111df}'), ('\u{11238}', '\u{1123d}'), ('\u{112a9}', '\u{112a9}'),
-        ('\u{114c6}', '\u{114c6}'), ('\u{115c1}', '\u{115d7}'), ('\u{11641}',
-        '\u{11643}'), ('\u{1173c}', '\u{1173e}'), ('\u{12470}', '\u{12474}'),
-        ('\u{16a6e}', '\u{16a6f}'), ('\u{16af5}', '\u{16af5}'), ('\u{16b37}',
-        '\u{16b3b}'), ('\u{16b44}', '\u{16b44}'), ('\u{1bc9f}', '\u{1bc9f}'),
-        ('\u{1da87}', '\u{1da8b}')
-    ];
-
-    pub const Pc_table: &'static [(char, char)] = &[
-        ('\u{5f}', '\u{5f}'), ('\u{203f}', '\u{2040}'), ('\u{2054}',
-        '\u{2054}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'),
-        ('\u{ff3f}', '\u{ff3f}')
-    ];
-
-    pub const Pd_table: &'static [(char, char)] = &[
-        ('\u{2d}', '\u{2d}'), ('\u{58a}', '\u{58a}'), ('\u{5be}', '\u{5be}'),
-        ('\u{1400}', '\u{1400}'), ('\u{1806}', '\u{1806}'), ('\u{2010}',
-        '\u{2015}'), ('\u{2e17}', '\u{2e17}'), ('\u{2e1a}', '\u{2e1a}'),
-        ('\u{2e3a}', '\u{2e3b}'), ('\u{2e40}', '\u{2e40}'), ('\u{301c}',
-        '\u{301c}'), ('\u{3030}', '\u{3030}'), ('\u{30a0}', '\u{30a0}'),
-        ('\u{fe31}', '\u{fe32}'), ('\u{fe58}', '\u{fe58}'), ('\u{fe63}',
-        '\u{fe63}'), ('\u{ff0d}', '\u{ff0d}')
-    ];
-
-    pub const Pe_table: &'static [(char, char)] = &[
-        ('\u{29}', '\u{29}'), ('\u{5d}', '\u{5d}'), ('\u{7d}', '\u{7d}'),
-        ('\u{f3b}', '\u{f3b}'), ('\u{f3d}', '\u{f3d}'), ('\u{169c}',
-        '\u{169c}'), ('\u{2046}', '\u{2046}'), ('\u{207e}', '\u{207e}'),
-        ('\u{208e}', '\u{208e}'), ('\u{2309}', '\u{2309}'), ('\u{230b}',
-        '\u{230b}'), ('\u{232a}', '\u{232a}'), ('\u{2769}', '\u{2769}'),
-        ('\u{276b}', '\u{276b}'), ('\u{276d}', '\u{276d}'), ('\u{276f}',
-        '\u{276f}'), ('\u{2771}', '\u{2771}'), ('\u{2773}', '\u{2773}'),
-        ('\u{2775}', '\u{2775}'), ('\u{27c6}', '\u{27c6}'), ('\u{27e7}',
-        '\u{27e7}'), ('\u{27e9}', '\u{27e9}'), ('\u{27eb}', '\u{27eb}'),
-        ('\u{27ed}', '\u{27ed}'), ('\u{27ef}', '\u{27ef}'), ('\u{2984}',
-        '\u{2984}'), ('\u{2986}', '\u{2986}'), ('\u{2988}', '\u{2988}'),
-        ('\u{298a}', '\u{298a}'), ('\u{298c}', '\u{298c}'), ('\u{298e}',
-        '\u{298e}'), ('\u{2990}', '\u{2990}'), ('\u{2992}', '\u{2992}'),
-        ('\u{2994}', '\u{2994}'), ('\u{2996}', '\u{2996}'), ('\u{2998}',
-        '\u{2998}'), ('\u{29d9}', '\u{29d9}'), ('\u{29db}', '\u{29db}'),
-        ('\u{29fd}', '\u{29fd}'), ('\u{2e23}', '\u{2e23}'), ('\u{2e25}',
-        '\u{2e25}'), ('\u{2e27}', '\u{2e27}'), ('\u{2e29}', '\u{2e29}'),
-        ('\u{3009}', '\u{3009}'), ('\u{300b}', '\u{300b}'), ('\u{300d}',
-        '\u{300d}'), ('\u{300f}', '\u{300f}'), ('\u{3011}', '\u{3011}'),
-        ('\u{3015}', '\u{3015}'), ('\u{3017}', '\u{3017}'), ('\u{3019}',
-        '\u{3019}'), ('\u{301b}', '\u{301b}'), ('\u{301e}', '\u{301f}'),
-        ('\u{fd3e}', '\u{fd3e}'), ('\u{fe18}', '\u{fe18}'), ('\u{fe36}',
-        '\u{fe36}'), ('\u{fe38}', '\u{fe38}'), ('\u{fe3a}', '\u{fe3a}'),
-        ('\u{fe3c}', '\u{fe3c}'), ('\u{fe3e}', '\u{fe3e}'), ('\u{fe40}',
-        '\u{fe40}'), ('\u{fe42}', '\u{fe42}'), ('\u{fe44}', '\u{fe44}'),
-        ('\u{fe48}', '\u{fe48}'), ('\u{fe5a}', '\u{fe5a}'), ('\u{fe5c}',
-        '\u{fe5c}'), ('\u{fe5e}', '\u{fe5e}'), ('\u{ff09}', '\u{ff09}'),
-        ('\u{ff3d}', '\u{ff3d}'), ('\u{ff5d}', '\u{ff5d}'), ('\u{ff60}',
-        '\u{ff60}'), ('\u{ff63}', '\u{ff63}')
-    ];
-
-    pub const Pf_table: &'static [(char, char)] = &[
-        ('\u{bb}', '\u{bb}'), ('\u{2019}', '\u{2019}'), ('\u{201d}',
-        '\u{201d}'), ('\u{203a}', '\u{203a}'), ('\u{2e03}', '\u{2e03}'),
-        ('\u{2e05}', '\u{2e05}'), ('\u{2e0a}', '\u{2e0a}'), ('\u{2e0d}',
-        '\u{2e0d}'), ('\u{2e1d}', '\u{2e1d}'), ('\u{2e21}', '\u{2e21}')
-    ];
-
-    pub const Pi_table: &'static [(char, char)] = &[
-        ('\u{ab}', '\u{ab}'), ('\u{2018}', '\u{2018}'), ('\u{201b}',
-        '\u{201c}'), ('\u{201f}', '\u{201f}'), ('\u{2039}', '\u{2039}'),
-        ('\u{2e02}', '\u{2e02}'), ('\u{2e04}', '\u{2e04}'), ('\u{2e09}',
-        '\u{2e09}'), ('\u{2e0c}', '\u{2e0c}'), ('\u{2e1c}', '\u{2e1c}'),
-        ('\u{2e20}', '\u{2e20}')
-    ];
-
-    pub const Po_table: &'static [(char, char)] = &[
-        ('\u{21}', '\u{23}'), ('\u{25}', '\u{27}'), ('\u{2a}', '\u{2a}'),
-        ('\u{2c}', '\u{2c}'), ('\u{2e}', '\u{2f}'), ('\u{3a}', '\u{3b}'),
-        ('\u{3f}', '\u{40}'), ('\u{5c}', '\u{5c}'), ('\u{a1}', '\u{a1}'),
-        ('\u{a7}', '\u{a7}'), ('\u{b6}', '\u{b7}'), ('\u{bf}', '\u{bf}'),
-        ('\u{37e}', '\u{37e}'), ('\u{387}', '\u{387}'), ('\u{55a}', '\u{55f}'),
-        ('\u{589}', '\u{589}'), ('\u{5c0}', '\u{5c0}'), ('\u{5c3}', '\u{5c3}'),
-        ('\u{5c6}', '\u{5c6}'), ('\u{5f3}', '\u{5f4}'), ('\u{609}', '\u{60a}'),
-        ('\u{60c}', '\u{60d}'), ('\u{61b}', '\u{61b}'), ('\u{61e}', '\u{61f}'),
-        ('\u{66a}', '\u{66d}'), ('\u{6d4}', '\u{6d4}'), ('\u{700}', '\u{70d}'),
-        ('\u{7f7}', '\u{7f9}'), ('\u{830}', '\u{83e}'), ('\u{85e}', '\u{85e}'),
-        ('\u{964}', '\u{965}'), ('\u{970}', '\u{970}'), ('\u{af0}', '\u{af0}'),
-        ('\u{df4}', '\u{df4}'), ('\u{e4f}', '\u{e4f}'), ('\u{e5a}', '\u{e5b}'),
-        ('\u{f04}', '\u{f12}'), ('\u{f14}', '\u{f14}'), ('\u{f85}', '\u{f85}'),
-        ('\u{fd0}', '\u{fd4}'), ('\u{fd9}', '\u{fda}'), ('\u{104a}',
-        '\u{104f}'), ('\u{10fb}', '\u{10fb}'), ('\u{1360}', '\u{1368}'),
-        ('\u{166d}', '\u{166e}'), ('\u{16eb}', '\u{16ed}'), ('\u{1735}',
-        '\u{1736}'), ('\u{17d4}', '\u{17d6}'), ('\u{17d8}', '\u{17da}'),
-        ('\u{1800}', '\u{1805}'), ('\u{1807}', '\u{180a}'), ('\u{1944}',
-        '\u{1945}'), ('\u{1a1e}', '\u{1a1f}'), ('\u{1aa0}', '\u{1aa6}'),
-        ('\u{1aa8}', '\u{1aad}'), ('\u{1b5a}', '\u{1b60}'), ('\u{1bfc}',
-        '\u{1bff}'), ('\u{1c3b}', '\u{1c3f}'), ('\u{1c7e}', '\u{1c7f}'),
-        ('\u{1cc0}', '\u{1cc7}'), ('\u{1cd3}', '\u{1cd3}'), ('\u{2016}',
-        '\u{2017}'), ('\u{2020}', '\u{2027}'), ('\u{2030}', '\u{2038}'),
-        ('\u{203b}', '\u{203e}'), ('\u{2041}', '\u{2043}'), ('\u{2047}',
-        '\u{2051}'), ('\u{2053}', '\u{2053}'), ('\u{2055}', '\u{205e}'),
-        ('\u{2cf9}', '\u{2cfc}'), ('\u{2cfe}', '\u{2cff}'), ('\u{2d70}',
-        '\u{2d70}'), ('\u{2e00}', '\u{2e01}'), ('\u{2e06}', '\u{2e08}'),
-        ('\u{2e0b}', '\u{2e0b}'), ('\u{2e0e}', '\u{2e16}'), ('\u{2e18}',
-        '\u{2e19}'), ('\u{2e1b}', '\u{2e1b}'), ('\u{2e1e}', '\u{2e1f}'),
-        ('\u{2e2a}', '\u{2e2e}'), ('\u{2e30}', '\u{2e39}'), ('\u{2e3c}',
-        '\u{2e3f}'), ('\u{2e41}', '\u{2e41}'), ('\u{3001}', '\u{3003}'),
-        ('\u{303d}', '\u{303d}'), ('\u{30fb}', '\u{30fb}'), ('\u{a4fe}',
-        '\u{a4ff}'), ('\u{a60d}', '\u{a60f}'), ('\u{a673}', '\u{a673}'),
-        ('\u{a67e}', '\u{a67e}'), ('\u{a6f2}', '\u{a6f7}'), ('\u{a874}',
-        '\u{a877}'), ('\u{a8ce}', '\u{a8cf}'), ('\u{a8f8}', '\u{a8fa}'),
-        ('\u{a8fc}', '\u{a8fc}'), ('\u{a92e}', '\u{a92f}'), ('\u{a95f}',
-        '\u{a95f}'), ('\u{a9c1}', '\u{a9cd}'), ('\u{a9de}', '\u{a9df}'),
-        ('\u{aa5c}', '\u{aa5f}'), ('\u{aade}', '\u{aadf}'), ('\u{aaf0}',
-        '\u{aaf1}'), ('\u{abeb}', '\u{abeb}'), ('\u{fe10}', '\u{fe16}'),
-        ('\u{fe19}', '\u{fe19}'), ('\u{fe30}', '\u{fe30}'), ('\u{fe45}',
-        '\u{fe46}'), ('\u{fe49}', '\u{fe4c}'), ('\u{fe50}', '\u{fe52}'),
-        ('\u{fe54}', '\u{fe57}'), ('\u{fe5f}', '\u{fe61}'), ('\u{fe68}',
-        '\u{fe68}'), ('\u{fe6a}', '\u{fe6b}'), ('\u{ff01}', '\u{ff03}'),
-        ('\u{ff05}', '\u{ff07}'), ('\u{ff0a}', '\u{ff0a}'), ('\u{ff0c}',
-        '\u{ff0c}'), ('\u{ff0e}', '\u{ff0f}'), ('\u{ff1a}', '\u{ff1b}'),
-        ('\u{ff1f}', '\u{ff20}'), ('\u{ff3c}', '\u{ff3c}'), ('\u{ff61}',
-        '\u{ff61}'), ('\u{ff64}', '\u{ff65}'), ('\u{10100}', '\u{10102}'),
-        ('\u{1039f}', '\u{1039f}'), ('\u{103d0}', '\u{103d0}'), ('\u{1056f}',
-        '\u{1056f}'), ('\u{10857}', '\u{10857}'), ('\u{1091f}', '\u{1091f}'),
-        ('\u{1093f}', '\u{1093f}'), ('\u{10a50}', '\u{10a58}'), ('\u{10a7f}',
-        '\u{10a7f}'), ('\u{10af0}', '\u{10af6}'), ('\u{10b39}', '\u{10b3f}'),
-        ('\u{10b99}', '\u{10b9c}'), ('\u{11047}', '\u{1104d}'), ('\u{110bb}',
-        '\u{110bc}'), ('\u{110be}', '\u{110c1}'), ('\u{11140}', '\u{11143}'),
-        ('\u{11174}', '\u{11175}'), ('\u{111c5}', '\u{111c9}'), ('\u{111cd}',
-        '\u{111cd}'), ('\u{111db}', '\u{111db}'), ('\u{111dd}', '\u{111df}'),
-        ('\u{11238}', '\u{1123d}'), ('\u{112a9}', '\u{112a9}'), ('\u{114c6}',
-        '\u{114c6}'), ('\u{115c1}', '\u{115d7}'), ('\u{11641}', '\u{11643}'),
-        ('\u{1173c}', '\u{1173e}'), ('\u{12470}', '\u{12474}'), ('\u{16a6e}',
-        '\u{16a6f}'), ('\u{16af5}', '\u{16af5}'), ('\u{16b37}', '\u{16b3b}'),
-        ('\u{16b44}', '\u{16b44}'), ('\u{1bc9f}', '\u{1bc9f}'), ('\u{1da87}',
-        '\u{1da8b}')
-    ];
-
-    pub const Ps_table: &'static [(char, char)] = &[
-        ('\u{28}', '\u{28}'), ('\u{5b}', '\u{5b}'), ('\u{7b}', '\u{7b}'),
-        ('\u{f3a}', '\u{f3a}'), ('\u{f3c}', '\u{f3c}'), ('\u{169b}',
-        '\u{169b}'), ('\u{201a}', '\u{201a}'), ('\u{201e}', '\u{201e}'),
-        ('\u{2045}', '\u{2045}'), ('\u{207d}', '\u{207d}'), ('\u{208d}',
-        '\u{208d}'), ('\u{2308}', '\u{2308}'), ('\u{230a}', '\u{230a}'),
-        ('\u{2329}', '\u{2329}'), ('\u{2768}', '\u{2768}'), ('\u{276a}',
-        '\u{276a}'), ('\u{276c}', '\u{276c}'), ('\u{276e}', '\u{276e}'),
-        ('\u{2770}', '\u{2770}'), ('\u{2772}', '\u{2772}'), ('\u{2774}',
-        '\u{2774}'), ('\u{27c5}', '\u{27c5}'), ('\u{27e6}', '\u{27e6}'),
-        ('\u{27e8}', '\u{27e8}'), ('\u{27ea}', '\u{27ea}'), ('\u{27ec}',
-        '\u{27ec}'), ('\u{27ee}', '\u{27ee}'), ('\u{2983}', '\u{2983}'),
-        ('\u{2985}', '\u{2985}'), ('\u{2987}', '\u{2987}'), ('\u{2989}',
-        '\u{2989}'), ('\u{298b}', '\u{298b}'), ('\u{298d}', '\u{298d}'),
-        ('\u{298f}', '\u{298f}'), ('\u{2991}', '\u{2991}'), ('\u{2993}',
-        '\u{2993}'), ('\u{2995}', '\u{2995}'), ('\u{2997}', '\u{2997}'),
-        ('\u{29d8}', '\u{29d8}'), ('\u{29da}', '\u{29da}'), ('\u{29fc}',
-        '\u{29fc}'), ('\u{2e22}', '\u{2e22}'), ('\u{2e24}', '\u{2e24}'),
-        ('\u{2e26}', '\u{2e26}'), ('\u{2e28}', '\u{2e28}'), ('\u{2e42}',
-        '\u{2e42}'), ('\u{3008}', '\u{3008}'), ('\u{300a}', '\u{300a}'),
-        ('\u{300c}', '\u{300c}'), ('\u{300e}', '\u{300e}'), ('\u{3010}',
-        '\u{3010}'), ('\u{3014}', '\u{3014}'), ('\u{3016}', '\u{3016}'),
-        ('\u{3018}', '\u{3018}'), ('\u{301a}', '\u{301a}'), ('\u{301d}',
-        '\u{301d}'), ('\u{fd3f}', '\u{fd3f}'), ('\u{fe17}', '\u{fe17}'),
-        ('\u{fe35}', '\u{fe35}'), ('\u{fe37}', '\u{fe37}'), ('\u{fe39}',
-        '\u{fe39}'), ('\u{fe3b}', '\u{fe3b}'), ('\u{fe3d}', '\u{fe3d}'),
-        ('\u{fe3f}', '\u{fe3f}'), ('\u{fe41}', '\u{fe41}'), ('\u{fe43}',
-        '\u{fe43}'), ('\u{fe47}', '\u{fe47}'), ('\u{fe59}', '\u{fe59}'),
-        ('\u{fe5b}', '\u{fe5b}'), ('\u{fe5d}', '\u{fe5d}'), ('\u{ff08}',
-        '\u{ff08}'), ('\u{ff3b}', '\u{ff3b}'), ('\u{ff5b}', '\u{ff5b}'),
-        ('\u{ff5f}', '\u{ff5f}'), ('\u{ff62}', '\u{ff62}')
-    ];
-
-    pub const S_table: &'static [(char, char)] = &[
-        ('\u{24}', '\u{24}'), ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'),
-        ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{7c}', '\u{7c}'),
-        ('\u{7e}', '\u{7e}'), ('\u{a2}', '\u{a6}'), ('\u{a8}', '\u{a9}'),
-        ('\u{ac}', '\u{ac}'), ('\u{ae}', '\u{b1}'), ('\u{b4}', '\u{b4}'),
-        ('\u{b8}', '\u{b8}'), ('\u{d7}', '\u{d7}'), ('\u{f7}', '\u{f7}'),
-        ('\u{2c2}', '\u{2c5}'), ('\u{2d2}', '\u{2df}'), ('\u{2e5}', '\u{2eb}'),
-        ('\u{2ed}', '\u{2ed}'), ('\u{2ef}', '\u{2ff}'), ('\u{375}', '\u{375}'),
-        ('\u{384}', '\u{385}'), ('\u{3f6}', '\u{3f6}'), ('\u{482}', '\u{482}'),
-        ('\u{58d}', '\u{58f}'), ('\u{606}', '\u{608}'), ('\u{60b}', '\u{60b}'),
-        ('\u{60e}', '\u{60f}'), ('\u{6de}', '\u{6de}'), ('\u{6e9}', '\u{6e9}'),
-        ('\u{6fd}', '\u{6fe}'), ('\u{7f6}', '\u{7f6}'), ('\u{9f2}', '\u{9f3}'),
-        ('\u{9fa}', '\u{9fb}'), ('\u{af1}', '\u{af1}'), ('\u{b70}', '\u{b70}'),
-        ('\u{bf3}', '\u{bfa}'), ('\u{c7f}', '\u{c7f}'), ('\u{d79}', '\u{d79}'),
-        ('\u{e3f}', '\u{e3f}'), ('\u{f01}', '\u{f03}'), ('\u{f13}', '\u{f13}'),
-        ('\u{f15}', '\u{f17}'), ('\u{f1a}', '\u{f1f}'), ('\u{f34}', '\u{f34}'),
-        ('\u{f36}', '\u{f36}'), ('\u{f38}', '\u{f38}'), ('\u{fbe}', '\u{fc5}'),
-        ('\u{fc7}', '\u{fcc}'), ('\u{fce}', '\u{fcf}'), ('\u{fd5}', '\u{fd8}'),
-        ('\u{109e}', '\u{109f}'), ('\u{1390}', '\u{1399}'), ('\u{17db}',
-        '\u{17db}'), ('\u{1940}', '\u{1940}'), ('\u{19de}', '\u{19ff}'),
-        ('\u{1b61}', '\u{1b6a}'), ('\u{1b74}', '\u{1b7c}'), ('\u{1fbd}',
-        '\u{1fbd}'), ('\u{1fbf}', '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'),
-        ('\u{1fdd}', '\u{1fdf}'), ('\u{1fed}', '\u{1fef}'), ('\u{1ffd}',
-        '\u{1ffe}'), ('\u{2044}', '\u{2044}'), ('\u{2052}', '\u{2052}'),
-        ('\u{207a}', '\u{207c}'), ('\u{208a}', '\u{208c}'), ('\u{20a0}',
-        '\u{20be}'), ('\u{2100}', '\u{2101}'), ('\u{2103}', '\u{2106}'),
-        ('\u{2108}', '\u{2109}'), ('\u{2114}', '\u{2114}'), ('\u{2116}',
-        '\u{2118}'), ('\u{211e}', '\u{2123}'), ('\u{2125}', '\u{2125}'),
-        ('\u{2127}', '\u{2127}'), ('\u{2129}', '\u{2129}'), ('\u{212e}',
-        '\u{212e}'), ('\u{213a}', '\u{213b}'), ('\u{2140}', '\u{2144}'),
-        ('\u{214a}', '\u{214d}'), ('\u{214f}', '\u{214f}'), ('\u{218a}',
-        '\u{218b}'), ('\u{2190}', '\u{2307}'), ('\u{230c}', '\u{2328}'),
-        ('\u{232b}', '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}',
-        '\u{244a}'), ('\u{249c}', '\u{24e9}'), ('\u{2500}', '\u{2767}'),
-        ('\u{2794}', '\u{27c4}'), ('\u{27c7}', '\u{27e5}'), ('\u{27f0}',
-        '\u{2982}'), ('\u{2999}', '\u{29d7}'), ('\u{29dc}', '\u{29fb}'),
-        ('\u{29fe}', '\u{2b73}'), ('\u{2b76}', '\u{2b95}'), ('\u{2b98}',
-        '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'), ('\u{2bca}', '\u{2bd1}'),
-        ('\u{2bec}', '\u{2bef}'), ('\u{2ce5}', '\u{2cea}'), ('\u{2e80}',
-        '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}', '\u{2fd5}'),
-        ('\u{2ff0}', '\u{2ffb}'), ('\u{3004}', '\u{3004}'), ('\u{3012}',
-        '\u{3013}'), ('\u{3020}', '\u{3020}'), ('\u{3036}', '\u{3037}'),
-        ('\u{303e}', '\u{303f}'), ('\u{309b}', '\u{309c}'), ('\u{3190}',
-        '\u{3191}'), ('\u{3196}', '\u{319f}'), ('\u{31c0}', '\u{31e3}'),
-        ('\u{3200}', '\u{321e}'), ('\u{322a}', '\u{3247}'), ('\u{3250}',
-        '\u{3250}'), ('\u{3260}', '\u{327f}'), ('\u{328a}', '\u{32b0}'),
-        ('\u{32c0}', '\u{32fe}'), ('\u{3300}', '\u{33ff}'), ('\u{4dc0}',
-        '\u{4dff}'), ('\u{a490}', '\u{a4c6}'), ('\u{a700}', '\u{a716}'),
-        ('\u{a720}', '\u{a721}'), ('\u{a789}', '\u{a78a}'), ('\u{a828}',
-        '\u{a82b}'), ('\u{a836}', '\u{a839}'), ('\u{aa77}', '\u{aa79}'),
-        ('\u{ab5b}', '\u{ab5b}'), ('\u{fb29}', '\u{fb29}'), ('\u{fbb2}',
-        '\u{fbc1}'), ('\u{fdfc}', '\u{fdfd}'), ('\u{fe62}', '\u{fe62}'),
-        ('\u{fe64}', '\u{fe66}'), ('\u{fe69}', '\u{fe69}'), ('\u{ff04}',
-        '\u{ff04}'), ('\u{ff0b}', '\u{ff0b}'), ('\u{ff1c}', '\u{ff1e}'),
-        ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'), ('\u{ff5c}',
-        '\u{ff5c}'), ('\u{ff5e}', '\u{ff5e}'), ('\u{ffe0}', '\u{ffe6}'),
-        ('\u{ffe8}', '\u{ffee}'), ('\u{fffc}', '\u{fffd}'), ('\u{10137}',
-        '\u{1013f}'), ('\u{10179}', '\u{10189}'), ('\u{1018c}', '\u{1018c}'),
-        ('\u{10190}', '\u{1019b}'), ('\u{101a0}', '\u{101a0}'), ('\u{101d0}',
-        '\u{101fc}'), ('\u{10877}', '\u{10878}'), ('\u{10ac8}', '\u{10ac8}'),
-        ('\u{1173f}', '\u{1173f}'), ('\u{16b3c}', '\u{16b3f}'), ('\u{16b45}',
-        '\u{16b45}'), ('\u{1bc9c}', '\u{1bc9c}'), ('\u{1d000}', '\u{1d0f5}'),
-        ('\u{1d100}', '\u{1d126}'), ('\u{1d129}', '\u{1d164}'), ('\u{1d16a}',
-        '\u{1d16c}'), ('\u{1d183}', '\u{1d184}'), ('\u{1d18c}', '\u{1d1a9}'),
-        ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d200}', '\u{1d241}'), ('\u{1d245}',
-        '\u{1d245}'), ('\u{1d300}', '\u{1d356}'), ('\u{1d6c1}', '\u{1d6c1}'),
-        ('\u{1d6db}', '\u{1d6db}'), ('\u{1d6fb}', '\u{1d6fb}'), ('\u{1d715}',
-        '\u{1d715}'), ('\u{1d735}', '\u{1d735}'), ('\u{1d74f}', '\u{1d74f}'),
-        ('\u{1d76f}', '\u{1d76f}'), ('\u{1d789}', '\u{1d789}'), ('\u{1d7a9}',
-        '\u{1d7a9}'), ('\u{1d7c3}', '\u{1d7c3}'), ('\u{1d800}', '\u{1d9ff}'),
-        ('\u{1da37}', '\u{1da3a}'), ('\u{1da6d}', '\u{1da74}'), ('\u{1da76}',
-        '\u{1da83}'), ('\u{1da85}', '\u{1da86}'), ('\u{1eef0}', '\u{1eef1}'),
-        ('\u{1f000}', '\u{1f02b}'), ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}',
-        '\u{1f0ae}'), ('\u{1f0b1}', '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'),
-        ('\u{1f0d1}', '\u{1f0f5}'), ('\u{1f110}', '\u{1f12e}'), ('\u{1f130}',
-        '\u{1f16b}'), ('\u{1f170}', '\u{1f19a}'), ('\u{1f1e6}', '\u{1f202}'),
-        ('\u{1f210}', '\u{1f23a}'), ('\u{1f240}', '\u{1f248}'), ('\u{1f250}',
-        '\u{1f251}'), ('\u{1f300}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'),
-        ('\u{1f5a5}', '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}',
-        '\u{1f6f3}'), ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'),
-        ('\u{1f800}', '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}',
-        '\u{1f859}'), ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'),
-        ('\u{1f910}', '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}',
-        '\u{1f9c0}')
-    ];
-
-    pub const Sc_table: &'static [(char, char)] = &[
-        ('\u{24}', '\u{24}'), ('\u{a2}', '\u{a5}'), ('\u{58f}', '\u{58f}'),
-        ('\u{60b}', '\u{60b}'), ('\u{9f2}', '\u{9f3}'), ('\u{9fb}', '\u{9fb}'),
-        ('\u{af1}', '\u{af1}'), ('\u{bf9}', '\u{bf9}'), ('\u{e3f}', '\u{e3f}'),
-        ('\u{17db}', '\u{17db}'), ('\u{20a0}', '\u{20be}'), ('\u{a838}',
-        '\u{a838}'), ('\u{fdfc}', '\u{fdfc}'), ('\u{fe69}', '\u{fe69}'),
-        ('\u{ff04}', '\u{ff04}'), ('\u{ffe0}', '\u{ffe1}'), ('\u{ffe5}',
-        '\u{ffe6}')
-    ];
-
-    pub const Sk_table: &'static [(char, char)] = &[
-        ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{a8}', '\u{a8}'),
-        ('\u{af}', '\u{af}'), ('\u{b4}', '\u{b4}'), ('\u{b8}', '\u{b8}'),
-        ('\u{2c2}', '\u{2c5}'), ('\u{2d2}', '\u{2df}'), ('\u{2e5}', '\u{2eb}'),
-        ('\u{2ed}', '\u{2ed}'), ('\u{2ef}', '\u{2ff}'), ('\u{375}', '\u{375}'),
-        ('\u{384}', '\u{385}'), ('\u{1fbd}', '\u{1fbd}'), ('\u{1fbf}',
-        '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'), ('\u{1fdd}', '\u{1fdf}'),
-        ('\u{1fed}', '\u{1fef}'), ('\u{1ffd}', '\u{1ffe}'), ('\u{309b}',
-        '\u{309c}'), ('\u{a700}', '\u{a716}'), ('\u{a720}', '\u{a721}'),
-        ('\u{a789}', '\u{a78a}'), ('\u{ab5b}', '\u{ab5b}'), ('\u{fbb2}',
-        '\u{fbc1}'), ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'),
-        ('\u{ffe3}', '\u{ffe3}'), ('\u{1f3fb}', '\u{1f3ff}')
-    ];
-
-    pub const Sm_table: &'static [(char, char)] = &[
-        ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'), ('\u{7c}', '\u{7c}'),
-        ('\u{7e}', '\u{7e}'), ('\u{ac}', '\u{ac}'), ('\u{b1}', '\u{b1}'),
-        ('\u{d7}', '\u{d7}'), ('\u{f7}', '\u{f7}'), ('\u{3f6}', '\u{3f6}'),
-        ('\u{606}', '\u{608}'), ('\u{2044}', '\u{2044}'), ('\u{2052}',
-        '\u{2052}'), ('\u{207a}', '\u{207c}'), ('\u{208a}', '\u{208c}'),
-        ('\u{2118}', '\u{2118}'), ('\u{2140}', '\u{2144}'), ('\u{214b}',
-        '\u{214b}'), ('\u{2190}', '\u{2194}'), ('\u{219a}', '\u{219b}'),
-        ('\u{21a0}', '\u{21a0}'), ('\u{21a3}', '\u{21a3}'), ('\u{21a6}',
-        '\u{21a6}'), ('\u{21ae}', '\u{21ae}'), ('\u{21ce}', '\u{21cf}'),
-        ('\u{21d2}', '\u{21d2}'), ('\u{21d4}', '\u{21d4}'), ('\u{21f4}',
-        '\u{22ff}'), ('\u{2320}', '\u{2321}'), ('\u{237c}', '\u{237c}'),
-        ('\u{239b}', '\u{23b3}'), ('\u{23dc}', '\u{23e1}'), ('\u{25b7}',
-        '\u{25b7}'), ('\u{25c1}', '\u{25c1}'), ('\u{25f8}', '\u{25ff}'),
-        ('\u{266f}', '\u{266f}'), ('\u{27c0}', '\u{27c4}'), ('\u{27c7}',
-        '\u{27e5}'), ('\u{27f0}', '\u{27ff}'), ('\u{2900}', '\u{2982}'),
-        ('\u{2999}', '\u{29d7}'), ('\u{29dc}', '\u{29fb}'), ('\u{29fe}',
-        '\u{2aff}'), ('\u{2b30}', '\u{2b44}'), ('\u{2b47}', '\u{2b4c}'),
-        ('\u{fb29}', '\u{fb29}'), ('\u{fe62}', '\u{fe62}'), ('\u{fe64}',
-        '\u{fe66}'), ('\u{ff0b}', '\u{ff0b}'), ('\u{ff1c}', '\u{ff1e}'),
-        ('\u{ff5c}', '\u{ff5c}'), ('\u{ff5e}', '\u{ff5e}'), ('\u{ffe2}',
-        '\u{ffe2}'), ('\u{ffe9}', '\u{ffec}'), ('\u{1d6c1}', '\u{1d6c1}'),
-        ('\u{1d6db}', '\u{1d6db}'), ('\u{1d6fb}', '\u{1d6fb}'), ('\u{1d715}',
-        '\u{1d715}'), ('\u{1d735}', '\u{1d735}'), ('\u{1d74f}', '\u{1d74f}'),
-        ('\u{1d76f}', '\u{1d76f}'), ('\u{1d789}', '\u{1d789}'), ('\u{1d7a9}',
-        '\u{1d7a9}'), ('\u{1d7c3}', '\u{1d7c3}'), ('\u{1eef0}', '\u{1eef1}')
-    ];
-
-    pub const So_table: &'static [(char, char)] = &[
-        ('\u{a6}', '\u{a6}'), ('\u{a9}', '\u{a9}'), ('\u{ae}', '\u{ae}'),
-        ('\u{b0}', '\u{b0}'), ('\u{482}', '\u{482}'), ('\u{58d}', '\u{58e}'),
-        ('\u{60e}', '\u{60f}'), ('\u{6de}', '\u{6de}'), ('\u{6e9}', '\u{6e9}'),
-        ('\u{6fd}', '\u{6fe}'), ('\u{7f6}', '\u{7f6}'), ('\u{9fa}', '\u{9fa}'),
-        ('\u{b70}', '\u{b70}'), ('\u{bf3}', '\u{bf8}'), ('\u{bfa}', '\u{bfa}'),
-        ('\u{c7f}', '\u{c7f}'), ('\u{d79}', '\u{d79}'), ('\u{f01}', '\u{f03}'),
-        ('\u{f13}', '\u{f13}'), ('\u{f15}', '\u{f17}'), ('\u{f1a}', '\u{f1f}'),
-        ('\u{f34}', '\u{f34}'), ('\u{f36}', '\u{f36}'), ('\u{f38}', '\u{f38}'),
-        ('\u{fbe}', '\u{fc5}'), ('\u{fc7}', '\u{fcc}'), ('\u{fce}', '\u{fcf}'),
-        ('\u{fd5}', '\u{fd8}'), ('\u{109e}', '\u{109f}'), ('\u{1390}',
-        '\u{1399}'), ('\u{1940}', '\u{1940}'), ('\u{19de}', '\u{19ff}'),
-        ('\u{1b61}', '\u{1b6a}'), ('\u{1b74}', '\u{1b7c}'), ('\u{2100}',
-        '\u{2101}'), ('\u{2103}', '\u{2106}'), ('\u{2108}', '\u{2109}'),
-        ('\u{2114}', '\u{2114}'), ('\u{2116}', '\u{2117}'), ('\u{211e}',
-        '\u{2123}'), ('\u{2125}', '\u{2125}'), ('\u{2127}', '\u{2127}'),
-        ('\u{2129}', '\u{2129}'), ('\u{212e}', '\u{212e}'), ('\u{213a}',
-        '\u{213b}'), ('\u{214a}', '\u{214a}'), ('\u{214c}', '\u{214d}'),
-        ('\u{214f}', '\u{214f}'), ('\u{218a}', '\u{218b}'), ('\u{2195}',
-        '\u{2199}'), ('\u{219c}', '\u{219f}'), ('\u{21a1}', '\u{21a2}'),
-        ('\u{21a4}', '\u{21a5}'), ('\u{21a7}', '\u{21ad}'), ('\u{21af}',
-        '\u{21cd}'), ('\u{21d0}', '\u{21d1}'), ('\u{21d3}', '\u{21d3}'),
-        ('\u{21d5}', '\u{21f3}'), ('\u{2300}', '\u{2307}'), ('\u{230c}',
-        '\u{231f}'), ('\u{2322}', '\u{2328}'), ('\u{232b}', '\u{237b}'),
-        ('\u{237d}', '\u{239a}'), ('\u{23b4}', '\u{23db}'), ('\u{23e2}',
-        '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}', '\u{244a}'),
-        ('\u{249c}', '\u{24e9}'), ('\u{2500}', '\u{25b6}'), ('\u{25b8}',
-        '\u{25c0}'), ('\u{25c2}', '\u{25f7}'), ('\u{2600}', '\u{266e}'),
-        ('\u{2670}', '\u{2767}'), ('\u{2794}', '\u{27bf}'), ('\u{2800}',
-        '\u{28ff}'), ('\u{2b00}', '\u{2b2f}'), ('\u{2b45}', '\u{2b46}'),
-        ('\u{2b4d}', '\u{2b73}'), ('\u{2b76}', '\u{2b95}'), ('\u{2b98}',
-        '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'), ('\u{2bca}', '\u{2bd1}'),
-        ('\u{2bec}', '\u{2bef}'), ('\u{2ce5}', '\u{2cea}'), ('\u{2e80}',
-        '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}', '\u{2fd5}'),
-        ('\u{2ff0}', '\u{2ffb}'), ('\u{3004}', '\u{3004}'), ('\u{3012}',
-        '\u{3013}'), ('\u{3020}', '\u{3020}'), ('\u{3036}', '\u{3037}'),
-        ('\u{303e}', '\u{303f}'), ('\u{3190}', '\u{3191}'), ('\u{3196}',
-        '\u{319f}'), ('\u{31c0}', '\u{31e3}'), ('\u{3200}', '\u{321e}'),
-        ('\u{322a}', '\u{3247}'), ('\u{3250}', '\u{3250}'), ('\u{3260}',
-        '\u{327f}'), ('\u{328a}', '\u{32b0}'), ('\u{32c0}', '\u{32fe}'),
-        ('\u{3300}', '\u{33ff}'), ('\u{4dc0}', '\u{4dff}'), ('\u{a490}',
-        '\u{a4c6}'), ('\u{a828}', '\u{a82b}'), ('\u{a836}', '\u{a837}'),
-        ('\u{a839}', '\u{a839}'), ('\u{aa77}', '\u{aa79}'), ('\u{fdfd}',
-        '\u{fdfd}'), ('\u{ffe4}', '\u{ffe4}'), ('\u{ffe8}', '\u{ffe8}'),
-        ('\u{ffed}', '\u{ffee}'), ('\u{fffc}', '\u{fffd}'), ('\u{10137}',
-        '\u{1013f}'), ('\u{10179}', '\u{10189}'), ('\u{1018c}', '\u{1018c}'),
-        ('\u{10190}', '\u{1019b}'), ('\u{101a0}', '\u{101a0}'), ('\u{101d0}',
-        '\u{101fc}'), ('\u{10877}', '\u{10878}'), ('\u{10ac8}', '\u{10ac8}'),
-        ('\u{1173f}', '\u{1173f}'), ('\u{16b3c}', '\u{16b3f}'), ('\u{16b45}',
-        '\u{16b45}'), ('\u{1bc9c}', '\u{1bc9c}'), ('\u{1d000}', '\u{1d0f5}'),
-        ('\u{1d100}', '\u{1d126}'), ('\u{1d129}', '\u{1d164}'), ('\u{1d16a}',
-        '\u{1d16c}'), ('\u{1d183}', '\u{1d184}'), ('\u{1d18c}', '\u{1d1a9}'),
-        ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d200}', '\u{1d241}'), ('\u{1d245}',
-        '\u{1d245}'), ('\u{1d300}', '\u{1d356}'), ('\u{1d800}', '\u{1d9ff}'),
-        ('\u{1da37}', '\u{1da3a}'), ('\u{1da6d}', '\u{1da74}'), ('\u{1da76}',
-        '\u{1da83}'), ('\u{1da85}', '\u{1da86}'), ('\u{1f000}', '\u{1f02b}'),
-        ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}', '\u{1f0ae}'), ('\u{1f0b1}',
-        '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'), ('\u{1f0d1}', '\u{1f0f5}'),
-        ('\u{1f110}', '\u{1f12e}'), ('\u{1f130}', '\u{1f16b}'), ('\u{1f170}',
-        '\u{1f19a}'), ('\u{1f1e6}', '\u{1f202}'), ('\u{1f210}', '\u{1f23a}'),
-        ('\u{1f240}', '\u{1f248}'), ('\u{1f250}', '\u{1f251}'), ('\u{1f300}',
-        '\u{1f3fa}'), ('\u{1f400}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'),
-        ('\u{1f5a5}', '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}',
-        '\u{1f6f3}'), ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'),
-        ('\u{1f800}', '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}',
-        '\u{1f859}'), ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'),
-        ('\u{1f910}', '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}',
-        '\u{1f9c0}')
-    ];
-
-    pub const Z_table: &'static [(char, char)] = &[
-        ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
-        ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}',
-        '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}')
-    ];
-
-    pub const Zl_table: &'static [(char, char)] = &[
-        ('\u{2028}', '\u{2028}')
-    ];
-
-    pub const Zp_table: &'static [(char, char)] = &[
-        ('\u{2029}', '\u{2029}')
-    ];
-
-    pub const Zs_table: &'static [(char, char)] = &[
-        ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
-        ('\u{2000}', '\u{200a}'), ('\u{202f}', '\u{202f}'), ('\u{205f}',
-        '\u{205f}'), ('\u{3000}', '\u{3000}')
-    ];
-
+use std::cmp::Ordering;
+use std::result;
+
+use ucd_util::{self, PropertyValues};
+
+use hir;
+use unicode_tables::age;
+use unicode_tables::case_folding_simple::CASE_FOLDING_SIMPLE;
+use unicode_tables::general_category;
+use unicode_tables::property_bool;
+use unicode_tables::property_names::PROPERTY_NAMES;
+use unicode_tables::property_values::PROPERTY_VALUES;
+use unicode_tables::script;
+use unicode_tables::script_extension;
+
+type Result<T> = result::Result<T, Error>;
+
+/// An error that occurs when dealing with Unicode.
+///
+/// We don't impl the Error trait here because these always get converted
+/// into other public errors. (This error type isn't exported.)
+#[derive(Debug)]
+pub enum Error {
+    PropertyNotFound,
+    PropertyValueNotFound,
 }
 
-pub mod derived_property {
-    pub const Alphabetic_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
-        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
-        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
-        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
-        ('\u{345}', '\u{345}'), ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'),
-        ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'),
-        ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'),
-        ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'),
-        ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'),
-        ('\u{5b0}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'),
-        ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'),
-        ('\u{5f0}', '\u{5f2}'), ('\u{610}', '\u{61a}'), ('\u{620}', '\u{657}'),
-        ('\u{659}', '\u{65f}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'),
-        ('\u{6e1}', '\u{6e8}'), ('\u{6ed}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'),
-        ('\u{6ff}', '\u{6ff}'), ('\u{710}', '\u{73f}'), ('\u{74d}', '\u{7b1}'),
-        ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'),
-        ('\u{800}', '\u{817}'), ('\u{81a}', '\u{82c}'), ('\u{840}', '\u{858}'),
-        ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{8e9}'), ('\u{8f0}', '\u{93b}'),
-        ('\u{93d}', '\u{94c}'), ('\u{94e}', '\u{950}'), ('\u{955}', '\u{963}'),
-        ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
-        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
-        ('\u{9b6}', '\u{9b9}'), ('\u{9bd}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
-        ('\u{9cb}', '\u{9cc}'), ('\u{9ce}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'),
-        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e3}'), ('\u{9f0}', '\u{9f1}'),
-        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
-        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
-        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3e}', '\u{a42}'),
-        ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4c}'), ('\u{a51}', '\u{a51}'),
-        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a70}', '\u{a75}'),
-        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
-        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
-        ('\u{ab5}', '\u{ab9}'), ('\u{abd}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
-        ('\u{acb}', '\u{acc}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
-        ('\u{af9}', '\u{af9}'), ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'),
-        ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'),
-        ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b44}'),
-        ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4c}'), ('\u{b56}', '\u{b57}'),
-        ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'), ('\u{b71}', '\u{b71}'),
-        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
-        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
-        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
-        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
-        ('\u{bca}', '\u{bcc}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
-        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
-        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
-        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4c}'), ('\u{c55}', '\u{c56}'),
-        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c81}', '\u{c83}'),
-        ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'),
-        ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cc4}'),
-        ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccc}'), ('\u{cd5}', '\u{cd6}'),
-        ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{cf1}', '\u{cf2}'),
-        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
-        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
-        ('\u{d4a}', '\u{d4c}'), ('\u{d4e}', '\u{d4e}'), ('\u{d57}', '\u{d57}'),
-        ('\u{d5f}', '\u{d63}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'),
-        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
-        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dcf}', '\u{dd4}'),
-        ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'),
-        ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e46}'), ('\u{e4d}', '\u{e4d}'),
-        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
-        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
-        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
-        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'),
-        ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{ecd}', '\u{ecd}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
-        ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f81}'),
-        ('\u{f88}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{1000}',
-        '\u{1036}'), ('\u{1038}', '\u{1038}'), ('\u{103b}', '\u{103f}'),
-        ('\u{1050}', '\u{1062}'), ('\u{1065}', '\u{1068}'), ('\u{106e}',
-        '\u{1086}'), ('\u{108e}', '\u{108e}'), ('\u{109c}', '\u{109d}'),
-        ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}',
-        '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{1248}'),
-        ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}',
-        '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'),
-        ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}',
-        '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'),
-        ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}',
-        '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'),
-        ('\u{135f}', '\u{135f}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
-        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
-        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
-        ('\u{170e}', '\u{1713}'), ('\u{1720}', '\u{1733}'), ('\u{1740}',
-        '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
-        ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17b3}'), ('\u{17b6}',
-        '\u{17c8}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'),
-        ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}',
-        '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'),
-        ('\u{1930}', '\u{1938}'), ('\u{1950}', '\u{196d}'), ('\u{1970}',
-        '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'),
-        ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'), ('\u{1a61}',
-        '\u{1a74}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1b00}', '\u{1b33}'),
-        ('\u{1b35}', '\u{1b43}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b80}',
-        '\u{1ba9}'), ('\u{1bac}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
-        ('\u{1be7}', '\u{1bf1}'), ('\u{1c00}', '\u{1c35}'), ('\u{1c4d}',
-        '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'),
-        ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}',
-        '\u{1dbf}'), ('\u{1de7}', '\u{1df4}'), ('\u{1e00}', '\u{1f15}'),
-        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
-        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
-        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
-        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
-        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
-        '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
-        ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}',
-        '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'),
-        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
-        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
-        ('\u{212f}', '\u{2139}'), ('\u{213c}', '\u{213f}'), ('\u{2145}',
-        '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'),
-        ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}',
-        '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'),
-        ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}',
-        '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'),
-        ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}',
-        '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'),
-        ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}',
-        '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'),
-        ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}',
-        '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3031}', '\u{3035}'),
-        ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}',
-        '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'),
-        ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}',
-        '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'),
-        ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}',
-        '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'),
-        ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), ('\u{a674}',
-        '\u{a67b}'), ('\u{a67f}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'),
-        ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}',
-        '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'), ('\u{a803}', '\u{a805}'),
-        ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a827}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a880}', '\u{a8c3}'), ('\u{a8f2}', '\u{a8f7}'),
-        ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}',
-        '\u{a92a}'), ('\u{a930}', '\u{a952}'), ('\u{a960}', '\u{a97c}'),
-        ('\u{a980}', '\u{a9b2}'), ('\u{a9b4}', '\u{a9bf}'), ('\u{a9cf}',
-        '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'),
-        ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'), ('\u{aa40}',
-        '\u{aa4d}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'),
-        ('\u{aa7e}', '\u{aabe}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}',
-        '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaef}'),
-        ('\u{aaf2}', '\u{aaf5}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}',
-        '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'),
-        ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}',
-        '\u{ab65}'), ('\u{ab70}', '\u{abea}'), ('\u{ac00}', '\u{d7a3}'),
-        ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}',
-        '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'),
-        ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}',
-        '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'),
-        ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}',
-        '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'),
-        ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}',
-        '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'),
-        ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}',
-        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
-        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
-        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
-        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
-        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'),
-        ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}',
-        '\u{1034a}'), ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'),
-        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}',
-        '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'),
-        ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
-        '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'),
-        ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}',
-        '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'),
-        ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}',
-        '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'),
-        ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
-        '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'),
-        ('\u{10a0c}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}',
-        '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'),
-        ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}',
-        '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'),
-        ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}',
-        '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{11000}', '\u{11045}'),
-        ('\u{11082}', '\u{110b8}'), ('\u{110d0}', '\u{110e8}'), ('\u{11100}',
-        '\u{11132}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'),
-        ('\u{11180}', '\u{111bf}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}',
-        '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'),
-        ('\u{11213}', '\u{11234}'), ('\u{11237}', '\u{11237}'), ('\u{11280}',
-        '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
-        ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}',
-        '\u{112e8}'), ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'),
-        ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}',
-        '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'),
-        ('\u{1133d}', '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}',
-        '\u{1134c}'), ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'),
-        ('\u{1135d}', '\u{11363}'), ('\u{11480}', '\u{114c1}'), ('\u{114c4}',
-        '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115b5}'),
-        ('\u{115b8}', '\u{115be}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}',
-        '\u{1163e}'), ('\u{11640}', '\u{11640}'), ('\u{11644}', '\u{11644}'),
-        ('\u{11680}', '\u{116b5}'), ('\u{11700}', '\u{11719}'), ('\u{1171d}',
-        '\u{1172a}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'),
-        ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}',
-        '\u{1246e}'), ('\u{12480}', '\u{12543}'), ('\u{13000}', '\u{1342e}'),
-        ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}',
-        '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}', '\u{16b36}'),
-        ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
-        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'),
-        ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}',
-        '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'),
-        ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9e}', '\u{1bc9e}'), ('\u{1d400}',
-        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
-        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
-        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
-        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
-        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
-        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
-        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
-        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
-        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
-        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
-        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
-        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}',
-        '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
-        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
-        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
-        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
-        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
-        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
-        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
-        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
-        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
-        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
-        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
-        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
-        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
-        ('\u{1eeab}', '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'), ('\u{1f150}',
-        '\u{1f169}'), ('\u{1f170}', '\u{1f189}'), ('\u{20000}', '\u{2a6d6}'),
-        ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}',
-        '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}')
-    ];
-
-    pub const Default_Ignorable_Code_Point_table: &'static [(char, char)] = &[
-        ('\u{ad}', '\u{ad}'), ('\u{34f}', '\u{34f}'), ('\u{61c}', '\u{61c}'),
-        ('\u{115f}', '\u{1160}'), ('\u{17b4}', '\u{17b5}'), ('\u{180b}',
-        '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
-        ('\u{2060}', '\u{206f}'), ('\u{3164}', '\u{3164}'), ('\u{fe00}',
-        '\u{fe0f}'), ('\u{feff}', '\u{feff}'), ('\u{ffa0}', '\u{ffa0}'),
-        ('\u{fff0}', '\u{fff8}'), ('\u{1bca0}', '\u{1bca3}'), ('\u{1d173}',
-        '\u{1d17a}'), ('\u{e0000}', '\u{e0fff}')
-    ];
+/// An iterator over a codepoint's simple case equivalence class.
+#[derive(Debug)]
+pub struct SimpleFoldIter(::std::slice::Iter<'static, char>);
 
-    pub const Grapheme_Extend_table: &'static [(char, char)] = &[
-        ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'),
-        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
-        ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'),
-        ('\u{670}', '\u{670}'), ('\u{6d6}', '\u{6dc}'), ('\u{6df}', '\u{6e4}'),
-        ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{711}', '\u{711}'),
-        ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', '\u{7f3}'),
-        ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), ('\u{825}', '\u{827}'),
-        ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{8e3}', '\u{902}'),
-        ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}', '\u{948}'),
-        ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'),
-        ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9be}', '\u{9be}'),
-        ('\u{9c1}', '\u{9c4}'), ('\u{9cd}', '\u{9cd}'), ('\u{9d7}', '\u{9d7}'),
-        ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'), ('\u{a3c}', '\u{a3c}'),
-        ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
-        ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'), ('\u{a75}', '\u{a75}'),
-        ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'), ('\u{ac1}', '\u{ac5}'),
-        ('\u{ac7}', '\u{ac8}'), ('\u{acd}', '\u{acd}'), ('\u{ae2}', '\u{ae3}'),
-        ('\u{b01}', '\u{b01}'), ('\u{b3c}', '\u{b3c}'), ('\u{b3e}', '\u{b3f}'),
-        ('\u{b41}', '\u{b44}'), ('\u{b4d}', '\u{b4d}'), ('\u{b56}', '\u{b57}'),
-        ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'), ('\u{bbe}', '\u{bbe}'),
-        ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{bd7}', '\u{bd7}'),
-        ('\u{c00}', '\u{c00}'), ('\u{c3e}', '\u{c40}'), ('\u{c46}', '\u{c48}'),
-        ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'), ('\u{c62}', '\u{c63}'),
-        ('\u{c81}', '\u{c81}'), ('\u{cbc}', '\u{cbc}'), ('\u{cbf}', '\u{cbf}'),
-        ('\u{cc2}', '\u{cc2}'), ('\u{cc6}', '\u{cc6}'), ('\u{ccc}', '\u{ccd}'),
-        ('\u{cd5}', '\u{cd6}'), ('\u{ce2}', '\u{ce3}'), ('\u{d01}', '\u{d01}'),
-        ('\u{d3e}', '\u{d3e}'), ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'),
-        ('\u{d57}', '\u{d57}'), ('\u{d62}', '\u{d63}'), ('\u{dca}', '\u{dca}'),
-        ('\u{dcf}', '\u{dcf}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
-        ('\u{ddf}', '\u{ddf}'), ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'),
-        ('\u{e47}', '\u{e4e}'), ('\u{eb1}', '\u{eb1}'), ('\u{eb4}', '\u{eb9}'),
-        ('\u{ebb}', '\u{ebc}'), ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'),
-        ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'),
-        ('\u{f71}', '\u{f7e}'), ('\u{f80}', '\u{f84}'), ('\u{f86}', '\u{f87}'),
-        ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'),
-        ('\u{102d}', '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}',
-        '\u{103a}'), ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'),
-        ('\u{105e}', '\u{1060}'), ('\u{1071}', '\u{1074}'), ('\u{1082}',
-        '\u{1082}'), ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'),
-        ('\u{109d}', '\u{109d}'), ('\u{135d}', '\u{135f}'), ('\u{1712}',
-        '\u{1714}'), ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'),
-        ('\u{1772}', '\u{1773}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b7}',
-        '\u{17bd}'), ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', '\u{17d3}'),
-        ('\u{17dd}', '\u{17dd}'), ('\u{180b}', '\u{180d}'), ('\u{18a9}',
-        '\u{18a9}'), ('\u{1920}', '\u{1922}'), ('\u{1927}', '\u{1928}'),
-        ('\u{1932}', '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}',
-        '\u{1a18}'), ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'),
-        ('\u{1a58}', '\u{1a5e}'), ('\u{1a60}', '\u{1a60}'), ('\u{1a62}',
-        '\u{1a62}'), ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'),
-        ('\u{1a7f}', '\u{1a7f}'), ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}',
-        '\u{1b03}'), ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'),
-        ('\u{1b3c}', '\u{1b3c}'), ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}',
-        '\u{1b73}'), ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', '\u{1ba5}'),
-        ('\u{1ba8}', '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}',
-        '\u{1be6}'), ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'),
-        ('\u{1bef}', '\u{1bf1}'), ('\u{1c2c}', '\u{1c33}'), ('\u{1c36}',
-        '\u{1c37}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'),
-        ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}',
-        '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'),
-        ('\u{1dfc}', '\u{1dff}'), ('\u{200c}', '\u{200d}'), ('\u{20d0}',
-        '\u{20f0}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2d7f}', '\u{2d7f}'),
-        ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302f}'), ('\u{3099}',
-        '\u{309a}'), ('\u{a66f}', '\u{a672}'), ('\u{a674}', '\u{a67d}'),
-        ('\u{a69e}', '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'), ('\u{a802}',
-        '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}', '\u{a80b}'),
-        ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'), ('\u{a8e0}',
-        '\u{a8f1}'), ('\u{a926}', '\u{a92d}'), ('\u{a947}', '\u{a951}'),
-        ('\u{a980}', '\u{a982}'), ('\u{a9b3}', '\u{a9b3}'), ('\u{a9b6}',
-        '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9e5}', '\u{a9e5}'),
-        ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'), ('\u{aa35}',
-        '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4c}'),
-        ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}',
-        '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'),
-        ('\u{aac1}', '\u{aac1}'), ('\u{aaec}', '\u{aaed}'), ('\u{aaf6}',
-        '\u{aaf6}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}', '\u{abe8}'),
-        ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'), ('\u{fe00}',
-        '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{ff9e}', '\u{ff9f}'),
-        ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}',
-        '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'),
-        ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}',
-        '\u{10a3f}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{11001}', '\u{11001}'),
-        ('\u{11038}', '\u{11046}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}',
-        '\u{110b6}'), ('\u{110b9}', '\u{110ba}'), ('\u{11100}', '\u{11102}'),
-        ('\u{11127}', '\u{1112b}'), ('\u{1112d}', '\u{11134}'), ('\u{11173}',
-        '\u{11173}'), ('\u{11180}', '\u{11181}'), ('\u{111b6}', '\u{111be}'),
-        ('\u{111ca}', '\u{111cc}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}',
-        '\u{11234}'), ('\u{11236}', '\u{11237}'), ('\u{112df}', '\u{112df}'),
-        ('\u{112e3}', '\u{112ea}'), ('\u{11300}', '\u{11301}'), ('\u{1133c}',
-        '\u{1133c}'), ('\u{1133e}', '\u{1133e}'), ('\u{11340}', '\u{11340}'),
-        ('\u{11357}', '\u{11357}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}',
-        '\u{11374}'), ('\u{114b0}', '\u{114b0}'), ('\u{114b3}', '\u{114b8}'),
-        ('\u{114ba}', '\u{114ba}'), ('\u{114bd}', '\u{114bd}'), ('\u{114bf}',
-        '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115af}', '\u{115af}'),
-        ('\u{115b2}', '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}',
-        '\u{115c0}'), ('\u{115dc}', '\u{115dd}'), ('\u{11633}', '\u{1163a}'),
-        ('\u{1163d}', '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}',
-        '\u{116ab}'), ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', '\u{116b5}'),
-        ('\u{116b7}', '\u{116b7}'), ('\u{1171d}', '\u{1171f}'), ('\u{11722}',
-        '\u{11725}'), ('\u{11727}', '\u{1172b}'), ('\u{16af0}', '\u{16af4}'),
-        ('\u{16b30}', '\u{16b36}'), ('\u{16f8f}', '\u{16f92}'), ('\u{1bc9d}',
-        '\u{1bc9e}'), ('\u{1d165}', '\u{1d165}'), ('\u{1d167}', '\u{1d169}'),
-        ('\u{1d16e}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}',
-        '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'),
-        ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}',
-        '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'),
-        ('\u{1daa1}', '\u{1daaf}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{e0100}',
-        '\u{e01ef}')
-    ];
-
-    pub const Lowercase_table: &'static [(char, char)] = &[
-        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
-        ('\u{ba}', '\u{ba}'), ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'),
-        ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'), ('\u{105}', '\u{105}'),
-        ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'), ('\u{10b}', '\u{10b}'),
-        ('\u{10d}', '\u{10d}'), ('\u{10f}', '\u{10f}'), ('\u{111}', '\u{111}'),
-        ('\u{113}', '\u{113}'), ('\u{115}', '\u{115}'), ('\u{117}', '\u{117}'),
-        ('\u{119}', '\u{119}'), ('\u{11b}', '\u{11b}'), ('\u{11d}', '\u{11d}'),
-        ('\u{11f}', '\u{11f}'), ('\u{121}', '\u{121}'), ('\u{123}', '\u{123}'),
-        ('\u{125}', '\u{125}'), ('\u{127}', '\u{127}'), ('\u{129}', '\u{129}'),
-        ('\u{12b}', '\u{12b}'), ('\u{12d}', '\u{12d}'), ('\u{12f}', '\u{12f}'),
-        ('\u{131}', '\u{131}'), ('\u{133}', '\u{133}'), ('\u{135}', '\u{135}'),
-        ('\u{137}', '\u{138}'), ('\u{13a}', '\u{13a}'), ('\u{13c}', '\u{13c}'),
-        ('\u{13e}', '\u{13e}'), ('\u{140}', '\u{140}'), ('\u{142}', '\u{142}'),
-        ('\u{144}', '\u{144}'), ('\u{146}', '\u{146}'), ('\u{148}', '\u{149}'),
-        ('\u{14b}', '\u{14b}'), ('\u{14d}', '\u{14d}'), ('\u{14f}', '\u{14f}'),
-        ('\u{151}', '\u{151}'), ('\u{153}', '\u{153}'), ('\u{155}', '\u{155}'),
-        ('\u{157}', '\u{157}'), ('\u{159}', '\u{159}'), ('\u{15b}', '\u{15b}'),
-        ('\u{15d}', '\u{15d}'), ('\u{15f}', '\u{15f}'), ('\u{161}', '\u{161}'),
-        ('\u{163}', '\u{163}'), ('\u{165}', '\u{165}'), ('\u{167}', '\u{167}'),
-        ('\u{169}', '\u{169}'), ('\u{16b}', '\u{16b}'), ('\u{16d}', '\u{16d}'),
-        ('\u{16f}', '\u{16f}'), ('\u{171}', '\u{171}'), ('\u{173}', '\u{173}'),
-        ('\u{175}', '\u{175}'), ('\u{177}', '\u{177}'), ('\u{17a}', '\u{17a}'),
-        ('\u{17c}', '\u{17c}'), ('\u{17e}', '\u{180}'), ('\u{183}', '\u{183}'),
-        ('\u{185}', '\u{185}'), ('\u{188}', '\u{188}'), ('\u{18c}', '\u{18d}'),
-        ('\u{192}', '\u{192}'), ('\u{195}', '\u{195}'), ('\u{199}', '\u{19b}'),
-        ('\u{19e}', '\u{19e}'), ('\u{1a1}', '\u{1a1}'), ('\u{1a3}', '\u{1a3}'),
-        ('\u{1a5}', '\u{1a5}'), ('\u{1a8}', '\u{1a8}'), ('\u{1aa}', '\u{1ab}'),
-        ('\u{1ad}', '\u{1ad}'), ('\u{1b0}', '\u{1b0}'), ('\u{1b4}', '\u{1b4}'),
-        ('\u{1b6}', '\u{1b6}'), ('\u{1b9}', '\u{1ba}'), ('\u{1bd}', '\u{1bf}'),
-        ('\u{1c6}', '\u{1c6}'), ('\u{1c9}', '\u{1c9}'), ('\u{1cc}', '\u{1cc}'),
-        ('\u{1ce}', '\u{1ce}'), ('\u{1d0}', '\u{1d0}'), ('\u{1d2}', '\u{1d2}'),
-        ('\u{1d4}', '\u{1d4}'), ('\u{1d6}', '\u{1d6}'), ('\u{1d8}', '\u{1d8}'),
-        ('\u{1da}', '\u{1da}'), ('\u{1dc}', '\u{1dd}'), ('\u{1df}', '\u{1df}'),
-        ('\u{1e1}', '\u{1e1}'), ('\u{1e3}', '\u{1e3}'), ('\u{1e5}', '\u{1e5}'),
-        ('\u{1e7}', '\u{1e7}'), ('\u{1e9}', '\u{1e9}'), ('\u{1eb}', '\u{1eb}'),
-        ('\u{1ed}', '\u{1ed}'), ('\u{1ef}', '\u{1f0}'), ('\u{1f3}', '\u{1f3}'),
-        ('\u{1f5}', '\u{1f5}'), ('\u{1f9}', '\u{1f9}'), ('\u{1fb}', '\u{1fb}'),
-        ('\u{1fd}', '\u{1fd}'), ('\u{1ff}', '\u{1ff}'), ('\u{201}', '\u{201}'),
-        ('\u{203}', '\u{203}'), ('\u{205}', '\u{205}'), ('\u{207}', '\u{207}'),
-        ('\u{209}', '\u{209}'), ('\u{20b}', '\u{20b}'), ('\u{20d}', '\u{20d}'),
-        ('\u{20f}', '\u{20f}'), ('\u{211}', '\u{211}'), ('\u{213}', '\u{213}'),
-        ('\u{215}', '\u{215}'), ('\u{217}', '\u{217}'), ('\u{219}', '\u{219}'),
-        ('\u{21b}', '\u{21b}'), ('\u{21d}', '\u{21d}'), ('\u{21f}', '\u{21f}'),
-        ('\u{221}', '\u{221}'), ('\u{223}', '\u{223}'), ('\u{225}', '\u{225}'),
-        ('\u{227}', '\u{227}'), ('\u{229}', '\u{229}'), ('\u{22b}', '\u{22b}'),
-        ('\u{22d}', '\u{22d}'), ('\u{22f}', '\u{22f}'), ('\u{231}', '\u{231}'),
-        ('\u{233}', '\u{239}'), ('\u{23c}', '\u{23c}'), ('\u{23f}', '\u{240}'),
-        ('\u{242}', '\u{242}'), ('\u{247}', '\u{247}'), ('\u{249}', '\u{249}'),
-        ('\u{24b}', '\u{24b}'), ('\u{24d}', '\u{24d}'), ('\u{24f}', '\u{293}'),
-        ('\u{295}', '\u{2b8}'), ('\u{2c0}', '\u{2c1}'), ('\u{2e0}', '\u{2e4}'),
-        ('\u{345}', '\u{345}'), ('\u{371}', '\u{371}'), ('\u{373}', '\u{373}'),
-        ('\u{377}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{390}', '\u{390}'),
-        ('\u{3ac}', '\u{3ce}'), ('\u{3d0}', '\u{3d1}'), ('\u{3d5}', '\u{3d7}'),
-        ('\u{3d9}', '\u{3d9}'), ('\u{3db}', '\u{3db}'), ('\u{3dd}', '\u{3dd}'),
-        ('\u{3df}', '\u{3df}'), ('\u{3e1}', '\u{3e1}'), ('\u{3e3}', '\u{3e3}'),
-        ('\u{3e5}', '\u{3e5}'), ('\u{3e7}', '\u{3e7}'), ('\u{3e9}', '\u{3e9}'),
-        ('\u{3eb}', '\u{3eb}'), ('\u{3ed}', '\u{3ed}'), ('\u{3ef}', '\u{3f3}'),
-        ('\u{3f5}', '\u{3f5}'), ('\u{3f8}', '\u{3f8}'), ('\u{3fb}', '\u{3fc}'),
-        ('\u{430}', '\u{45f}'), ('\u{461}', '\u{461}'), ('\u{463}', '\u{463}'),
-        ('\u{465}', '\u{465}'), ('\u{467}', '\u{467}'), ('\u{469}', '\u{469}'),
-        ('\u{46b}', '\u{46b}'), ('\u{46d}', '\u{46d}'), ('\u{46f}', '\u{46f}'),
-        ('\u{471}', '\u{471}'), ('\u{473}', '\u{473}'), ('\u{475}', '\u{475}'),
-        ('\u{477}', '\u{477}'), ('\u{479}', '\u{479}'), ('\u{47b}', '\u{47b}'),
-        ('\u{47d}', '\u{47d}'), ('\u{47f}', '\u{47f}'), ('\u{481}', '\u{481}'),
-        ('\u{48b}', '\u{48b}'), ('\u{48d}', '\u{48d}'), ('\u{48f}', '\u{48f}'),
-        ('\u{491}', '\u{491}'), ('\u{493}', '\u{493}'), ('\u{495}', '\u{495}'),
-        ('\u{497}', '\u{497}'), ('\u{499}', '\u{499}'), ('\u{49b}', '\u{49b}'),
-        ('\u{49d}', '\u{49d}'), ('\u{49f}', '\u{49f}'), ('\u{4a1}', '\u{4a1}'),
-        ('\u{4a3}', '\u{4a3}'), ('\u{4a5}', '\u{4a5}'), ('\u{4a7}', '\u{4a7}'),
-        ('\u{4a9}', '\u{4a9}'), ('\u{4ab}', '\u{4ab}'), ('\u{4ad}', '\u{4ad}'),
-        ('\u{4af}', '\u{4af}'), ('\u{4b1}', '\u{4b1}'), ('\u{4b3}', '\u{4b3}'),
-        ('\u{4b5}', '\u{4b5}'), ('\u{4b7}', '\u{4b7}'), ('\u{4b9}', '\u{4b9}'),
-        ('\u{4bb}', '\u{4bb}'), ('\u{4bd}', '\u{4bd}'), ('\u{4bf}', '\u{4bf}'),
-        ('\u{4c2}', '\u{4c2}'), ('\u{4c4}', '\u{4c4}'), ('\u{4c6}', '\u{4c6}'),
-        ('\u{4c8}', '\u{4c8}'), ('\u{4ca}', '\u{4ca}'), ('\u{4cc}', '\u{4cc}'),
-        ('\u{4ce}', '\u{4cf}'), ('\u{4d1}', '\u{4d1}'), ('\u{4d3}', '\u{4d3}'),
-        ('\u{4d5}', '\u{4d5}'), ('\u{4d7}', '\u{4d7}'), ('\u{4d9}', '\u{4d9}'),
-        ('\u{4db}', '\u{4db}'), ('\u{4dd}', '\u{4dd}'), ('\u{4df}', '\u{4df}'),
-        ('\u{4e1}', '\u{4e1}'), ('\u{4e3}', '\u{4e3}'), ('\u{4e5}', '\u{4e5}'),
-        ('\u{4e7}', '\u{4e7}'), ('\u{4e9}', '\u{4e9}'), ('\u{4eb}', '\u{4eb}'),
-        ('\u{4ed}', '\u{4ed}'), ('\u{4ef}', '\u{4ef}'), ('\u{4f1}', '\u{4f1}'),
-        ('\u{4f3}', '\u{4f3}'), ('\u{4f5}', '\u{4f5}'), ('\u{4f7}', '\u{4f7}'),
-        ('\u{4f9}', '\u{4f9}'), ('\u{4fb}', '\u{4fb}'), ('\u{4fd}', '\u{4fd}'),
-        ('\u{4ff}', '\u{4ff}'), ('\u{501}', '\u{501}'), ('\u{503}', '\u{503}'),
-        ('\u{505}', '\u{505}'), ('\u{507}', '\u{507}'), ('\u{509}', '\u{509}'),
-        ('\u{50b}', '\u{50b}'), ('\u{50d}', '\u{50d}'), ('\u{50f}', '\u{50f}'),
-        ('\u{511}', '\u{511}'), ('\u{513}', '\u{513}'), ('\u{515}', '\u{515}'),
-        ('\u{517}', '\u{517}'), ('\u{519}', '\u{519}'), ('\u{51b}', '\u{51b}'),
-        ('\u{51d}', '\u{51d}'), ('\u{51f}', '\u{51f}'), ('\u{521}', '\u{521}'),
-        ('\u{523}', '\u{523}'), ('\u{525}', '\u{525}'), ('\u{527}', '\u{527}'),
-        ('\u{529}', '\u{529}'), ('\u{52b}', '\u{52b}'), ('\u{52d}', '\u{52d}'),
-        ('\u{52f}', '\u{52f}'), ('\u{561}', '\u{587}'), ('\u{13f8}',
-        '\u{13fd}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e01}', '\u{1e01}'),
-        ('\u{1e03}', '\u{1e03}'), ('\u{1e05}', '\u{1e05}'), ('\u{1e07}',
-        '\u{1e07}'), ('\u{1e09}', '\u{1e09}'), ('\u{1e0b}', '\u{1e0b}'),
-        ('\u{1e0d}', '\u{1e0d}'), ('\u{1e0f}', '\u{1e0f}'), ('\u{1e11}',
-        '\u{1e11}'), ('\u{1e13}', '\u{1e13}'), ('\u{1e15}', '\u{1e15}'),
-        ('\u{1e17}', '\u{1e17}'), ('\u{1e19}', '\u{1e19}'), ('\u{1e1b}',
-        '\u{1e1b}'), ('\u{1e1d}', '\u{1e1d}'), ('\u{1e1f}', '\u{1e1f}'),
-        ('\u{1e21}', '\u{1e21}'), ('\u{1e23}', '\u{1e23}'), ('\u{1e25}',
-        '\u{1e25}'), ('\u{1e27}', '\u{1e27}'), ('\u{1e29}', '\u{1e29}'),
-        ('\u{1e2b}', '\u{1e2b}'), ('\u{1e2d}', '\u{1e2d}'), ('\u{1e2f}',
-        '\u{1e2f}'), ('\u{1e31}', '\u{1e31}'), ('\u{1e33}', '\u{1e33}'),
-        ('\u{1e35}', '\u{1e35}'), ('\u{1e37}', '\u{1e37}'), ('\u{1e39}',
-        '\u{1e39}'), ('\u{1e3b}', '\u{1e3b}'), ('\u{1e3d}', '\u{1e3d}'),
-        ('\u{1e3f}', '\u{1e3f}'), ('\u{1e41}', '\u{1e41}'), ('\u{1e43}',
-        '\u{1e43}'), ('\u{1e45}', '\u{1e45}'), ('\u{1e47}', '\u{1e47}'),
-        ('\u{1e49}', '\u{1e49}'), ('\u{1e4b}', '\u{1e4b}'), ('\u{1e4d}',
-        '\u{1e4d}'), ('\u{1e4f}', '\u{1e4f}'), ('\u{1e51}', '\u{1e51}'),
-        ('\u{1e53}', '\u{1e53}'), ('\u{1e55}', '\u{1e55}'), ('\u{1e57}',
-        '\u{1e57}'), ('\u{1e59}', '\u{1e59}'), ('\u{1e5b}', '\u{1e5b}'),
-        ('\u{1e5d}', '\u{1e5d}'), ('\u{1e5f}', '\u{1e5f}'), ('\u{1e61}',
-        '\u{1e61}'), ('\u{1e63}', '\u{1e63}'), ('\u{1e65}', '\u{1e65}'),
-        ('\u{1e67}', '\u{1e67}'), ('\u{1e69}', '\u{1e69}'), ('\u{1e6b}',
-        '\u{1e6b}'), ('\u{1e6d}', '\u{1e6d}'), ('\u{1e6f}', '\u{1e6f}'),
-        ('\u{1e71}', '\u{1e71}'), ('\u{1e73}', '\u{1e73}'), ('\u{1e75}',
-        '\u{1e75}'), ('\u{1e77}', '\u{1e77}'), ('\u{1e79}', '\u{1e79}'),
-        ('\u{1e7b}', '\u{1e7b}'), ('\u{1e7d}', '\u{1e7d}'), ('\u{1e7f}',
-        '\u{1e7f}'), ('\u{1e81}', '\u{1e81}'), ('\u{1e83}', '\u{1e83}'),
-        ('\u{1e85}', '\u{1e85}'), ('\u{1e87}', '\u{1e87}'), ('\u{1e89}',
-        '\u{1e89}'), ('\u{1e8b}', '\u{1e8b}'), ('\u{1e8d}', '\u{1e8d}'),
-        ('\u{1e8f}', '\u{1e8f}'), ('\u{1e91}', '\u{1e91}'), ('\u{1e93}',
-        '\u{1e93}'), ('\u{1e95}', '\u{1e9d}'), ('\u{1e9f}', '\u{1e9f}'),
-        ('\u{1ea1}', '\u{1ea1}'), ('\u{1ea3}', '\u{1ea3}'), ('\u{1ea5}',
-        '\u{1ea5}'), ('\u{1ea7}', '\u{1ea7}'), ('\u{1ea9}', '\u{1ea9}'),
-        ('\u{1eab}', '\u{1eab}'), ('\u{1ead}', '\u{1ead}'), ('\u{1eaf}',
-        '\u{1eaf}'), ('\u{1eb1}', '\u{1eb1}'), ('\u{1eb3}', '\u{1eb3}'),
-        ('\u{1eb5}', '\u{1eb5}'), ('\u{1eb7}', '\u{1eb7}'), ('\u{1eb9}',
-        '\u{1eb9}'), ('\u{1ebb}', '\u{1ebb}'), ('\u{1ebd}', '\u{1ebd}'),
-        ('\u{1ebf}', '\u{1ebf}'), ('\u{1ec1}', '\u{1ec1}'), ('\u{1ec3}',
-        '\u{1ec3}'), ('\u{1ec5}', '\u{1ec5}'), ('\u{1ec7}', '\u{1ec7}'),
-        ('\u{1ec9}', '\u{1ec9}'), ('\u{1ecb}', '\u{1ecb}'), ('\u{1ecd}',
-        '\u{1ecd}'), ('\u{1ecf}', '\u{1ecf}'), ('\u{1ed1}', '\u{1ed1}'),
-        ('\u{1ed3}', '\u{1ed3}'), ('\u{1ed5}', '\u{1ed5}'), ('\u{1ed7}',
-        '\u{1ed7}'), ('\u{1ed9}', '\u{1ed9}'), ('\u{1edb}', '\u{1edb}'),
-        ('\u{1edd}', '\u{1edd}'), ('\u{1edf}', '\u{1edf}'), ('\u{1ee1}',
-        '\u{1ee1}'), ('\u{1ee3}', '\u{1ee3}'), ('\u{1ee5}', '\u{1ee5}'),
-        ('\u{1ee7}', '\u{1ee7}'), ('\u{1ee9}', '\u{1ee9}'), ('\u{1eeb}',
-        '\u{1eeb}'), ('\u{1eed}', '\u{1eed}'), ('\u{1eef}', '\u{1eef}'),
-        ('\u{1ef1}', '\u{1ef1}'), ('\u{1ef3}', '\u{1ef3}'), ('\u{1ef5}',
-        '\u{1ef5}'), ('\u{1ef7}', '\u{1ef7}'), ('\u{1ef9}', '\u{1ef9}'),
-        ('\u{1efb}', '\u{1efb}'), ('\u{1efd}', '\u{1efd}'), ('\u{1eff}',
-        '\u{1f07}'), ('\u{1f10}', '\u{1f15}'), ('\u{1f20}', '\u{1f27}'),
-        ('\u{1f30}', '\u{1f37}'), ('\u{1f40}', '\u{1f45}'), ('\u{1f50}',
-        '\u{1f57}'), ('\u{1f60}', '\u{1f67}'), ('\u{1f70}', '\u{1f7d}'),
-        ('\u{1f80}', '\u{1f87}'), ('\u{1f90}', '\u{1f97}'), ('\u{1fa0}',
-        '\u{1fa7}'), ('\u{1fb0}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fb7}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fc7}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fd7}'),
-        ('\u{1fe0}', '\u{1fe7}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
-        '\u{1ff7}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'),
-        ('\u{2090}', '\u{209c}'), ('\u{210a}', '\u{210a}'), ('\u{210e}',
-        '\u{210f}'), ('\u{2113}', '\u{2113}'), ('\u{212f}', '\u{212f}'),
-        ('\u{2134}', '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}',
-        '\u{213d}'), ('\u{2146}', '\u{2149}'), ('\u{214e}', '\u{214e}'),
-        ('\u{2170}', '\u{217f}'), ('\u{2184}', '\u{2184}'), ('\u{24d0}',
-        '\u{24e9}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c61}', '\u{2c61}'),
-        ('\u{2c65}', '\u{2c66}'), ('\u{2c68}', '\u{2c68}'), ('\u{2c6a}',
-        '\u{2c6a}'), ('\u{2c6c}', '\u{2c6c}'), ('\u{2c71}', '\u{2c71}'),
-        ('\u{2c73}', '\u{2c74}'), ('\u{2c76}', '\u{2c7d}'), ('\u{2c81}',
-        '\u{2c81}'), ('\u{2c83}', '\u{2c83}'), ('\u{2c85}', '\u{2c85}'),
-        ('\u{2c87}', '\u{2c87}'), ('\u{2c89}', '\u{2c89}'), ('\u{2c8b}',
-        '\u{2c8b}'), ('\u{2c8d}', '\u{2c8d}'), ('\u{2c8f}', '\u{2c8f}'),
-        ('\u{2c91}', '\u{2c91}'), ('\u{2c93}', '\u{2c93}'), ('\u{2c95}',
-        '\u{2c95}'), ('\u{2c97}', '\u{2c97}'), ('\u{2c99}', '\u{2c99}'),
-        ('\u{2c9b}', '\u{2c9b}'), ('\u{2c9d}', '\u{2c9d}'), ('\u{2c9f}',
-        '\u{2c9f}'), ('\u{2ca1}', '\u{2ca1}'), ('\u{2ca3}', '\u{2ca3}'),
-        ('\u{2ca5}', '\u{2ca5}'), ('\u{2ca7}', '\u{2ca7}'), ('\u{2ca9}',
-        '\u{2ca9}'), ('\u{2cab}', '\u{2cab}'), ('\u{2cad}', '\u{2cad}'),
-        ('\u{2caf}', '\u{2caf}'), ('\u{2cb1}', '\u{2cb1}'), ('\u{2cb3}',
-        '\u{2cb3}'), ('\u{2cb5}', '\u{2cb5}'), ('\u{2cb7}', '\u{2cb7}'),
-        ('\u{2cb9}', '\u{2cb9}'), ('\u{2cbb}', '\u{2cbb}'), ('\u{2cbd}',
-        '\u{2cbd}'), ('\u{2cbf}', '\u{2cbf}'), ('\u{2cc1}', '\u{2cc1}'),
-        ('\u{2cc3}', '\u{2cc3}'), ('\u{2cc5}', '\u{2cc5}'), ('\u{2cc7}',
-        '\u{2cc7}'), ('\u{2cc9}', '\u{2cc9}'), ('\u{2ccb}', '\u{2ccb}'),
-        ('\u{2ccd}', '\u{2ccd}'), ('\u{2ccf}', '\u{2ccf}'), ('\u{2cd1}',
-        '\u{2cd1}'), ('\u{2cd3}', '\u{2cd3}'), ('\u{2cd5}', '\u{2cd5}'),
-        ('\u{2cd7}', '\u{2cd7}'), ('\u{2cd9}', '\u{2cd9}'), ('\u{2cdb}',
-        '\u{2cdb}'), ('\u{2cdd}', '\u{2cdd}'), ('\u{2cdf}', '\u{2cdf}'),
-        ('\u{2ce1}', '\u{2ce1}'), ('\u{2ce3}', '\u{2ce4}'), ('\u{2cec}',
-        '\u{2cec}'), ('\u{2cee}', '\u{2cee}'), ('\u{2cf3}', '\u{2cf3}'),
-        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
-        '\u{2d2d}'), ('\u{a641}', '\u{a641}'), ('\u{a643}', '\u{a643}'),
-        ('\u{a645}', '\u{a645}'), ('\u{a647}', '\u{a647}'), ('\u{a649}',
-        '\u{a649}'), ('\u{a64b}', '\u{a64b}'), ('\u{a64d}', '\u{a64d}'),
-        ('\u{a64f}', '\u{a64f}'), ('\u{a651}', '\u{a651}'), ('\u{a653}',
-        '\u{a653}'), ('\u{a655}', '\u{a655}'), ('\u{a657}', '\u{a657}'),
-        ('\u{a659}', '\u{a659}'), ('\u{a65b}', '\u{a65b}'), ('\u{a65d}',
-        '\u{a65d}'), ('\u{a65f}', '\u{a65f}'), ('\u{a661}', '\u{a661}'),
-        ('\u{a663}', '\u{a663}'), ('\u{a665}', '\u{a665}'), ('\u{a667}',
-        '\u{a667}'), ('\u{a669}', '\u{a669}'), ('\u{a66b}', '\u{a66b}'),
-        ('\u{a66d}', '\u{a66d}'), ('\u{a681}', '\u{a681}'), ('\u{a683}',
-        '\u{a683}'), ('\u{a685}', '\u{a685}'), ('\u{a687}', '\u{a687}'),
-        ('\u{a689}', '\u{a689}'), ('\u{a68b}', '\u{a68b}'), ('\u{a68d}',
-        '\u{a68d}'), ('\u{a68f}', '\u{a68f}'), ('\u{a691}', '\u{a691}'),
-        ('\u{a693}', '\u{a693}'), ('\u{a695}', '\u{a695}'), ('\u{a697}',
-        '\u{a697}'), ('\u{a699}', '\u{a699}'), ('\u{a69b}', '\u{a69d}'),
-        ('\u{a723}', '\u{a723}'), ('\u{a725}', '\u{a725}'), ('\u{a727}',
-        '\u{a727}'), ('\u{a729}', '\u{a729}'), ('\u{a72b}', '\u{a72b}'),
-        ('\u{a72d}', '\u{a72d}'), ('\u{a72f}', '\u{a731}'), ('\u{a733}',
-        '\u{a733}'), ('\u{a735}', '\u{a735}'), ('\u{a737}', '\u{a737}'),
-        ('\u{a739}', '\u{a739}'), ('\u{a73b}', '\u{a73b}'), ('\u{a73d}',
-        '\u{a73d}'), ('\u{a73f}', '\u{a73f}'), ('\u{a741}', '\u{a741}'),
-        ('\u{a743}', '\u{a743}'), ('\u{a745}', '\u{a745}'), ('\u{a747}',
-        '\u{a747}'), ('\u{a749}', '\u{a749}'), ('\u{a74b}', '\u{a74b}'),
-        ('\u{a74d}', '\u{a74d}'), ('\u{a74f}', '\u{a74f}'), ('\u{a751}',
-        '\u{a751}'), ('\u{a753}', '\u{a753}'), ('\u{a755}', '\u{a755}'),
-        ('\u{a757}', '\u{a757}'), ('\u{a759}', '\u{a759}'), ('\u{a75b}',
-        '\u{a75b}'), ('\u{a75d}', '\u{a75d}'), ('\u{a75f}', '\u{a75f}'),
-        ('\u{a761}', '\u{a761}'), ('\u{a763}', '\u{a763}'), ('\u{a765}',
-        '\u{a765}'), ('\u{a767}', '\u{a767}'), ('\u{a769}', '\u{a769}'),
-        ('\u{a76b}', '\u{a76b}'), ('\u{a76d}', '\u{a76d}'), ('\u{a76f}',
-        '\u{a778}'), ('\u{a77a}', '\u{a77a}'), ('\u{a77c}', '\u{a77c}'),
-        ('\u{a77f}', '\u{a77f}'), ('\u{a781}', '\u{a781}'), ('\u{a783}',
-        '\u{a783}'), ('\u{a785}', '\u{a785}'), ('\u{a787}', '\u{a787}'),
-        ('\u{a78c}', '\u{a78c}'), ('\u{a78e}', '\u{a78e}'), ('\u{a791}',
-        '\u{a791}'), ('\u{a793}', '\u{a795}'), ('\u{a797}', '\u{a797}'),
-        ('\u{a799}', '\u{a799}'), ('\u{a79b}', '\u{a79b}'), ('\u{a79d}',
-        '\u{a79d}'), ('\u{a79f}', '\u{a79f}'), ('\u{a7a1}', '\u{a7a1}'),
-        ('\u{a7a3}', '\u{a7a3}'), ('\u{a7a5}', '\u{a7a5}'), ('\u{a7a7}',
-        '\u{a7a7}'), ('\u{a7a9}', '\u{a7a9}'), ('\u{a7b5}', '\u{a7b5}'),
-        ('\u{a7b7}', '\u{a7b7}'), ('\u{a7f8}', '\u{a7fa}'), ('\u{ab30}',
-        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abbf}'),
-        ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{ff41}',
-        '\u{ff5a}'), ('\u{10428}', '\u{1044f}'), ('\u{10cc0}', '\u{10cf2}'),
-        ('\u{118c0}', '\u{118df}'), ('\u{1d41a}', '\u{1d433}'), ('\u{1d44e}',
-        '\u{1d454}'), ('\u{1d456}', '\u{1d467}'), ('\u{1d482}', '\u{1d49b}'),
-        ('\u{1d4b6}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
-        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d4cf}'), ('\u{1d4ea}', '\u{1d503}'),
-        ('\u{1d51e}', '\u{1d537}'), ('\u{1d552}', '\u{1d56b}'), ('\u{1d586}',
-        '\u{1d59f}'), ('\u{1d5ba}', '\u{1d5d3}'), ('\u{1d5ee}', '\u{1d607}'),
-        ('\u{1d622}', '\u{1d63b}'), ('\u{1d656}', '\u{1d66f}'), ('\u{1d68a}',
-        '\u{1d6a5}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6e1}'),
-        ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d71b}'), ('\u{1d736}',
-        '\u{1d74e}'), ('\u{1d750}', '\u{1d755}'), ('\u{1d770}', '\u{1d788}'),
-        ('\u{1d78a}', '\u{1d78f}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}',
-        '\u{1d7c9}'), ('\u{1d7cb}', '\u{1d7cb}')
-    ];
-
-    pub const Uppercase_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'),
-        ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'),
-        ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'),
-        ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), ('\u{110}', '\u{110}'),
-        ('\u{112}', '\u{112}'), ('\u{114}', '\u{114}'), ('\u{116}', '\u{116}'),
-        ('\u{118}', '\u{118}'), ('\u{11a}', '\u{11a}'), ('\u{11c}', '\u{11c}'),
-        ('\u{11e}', '\u{11e}'), ('\u{120}', '\u{120}'), ('\u{122}', '\u{122}'),
-        ('\u{124}', '\u{124}'), ('\u{126}', '\u{126}'), ('\u{128}', '\u{128}'),
-        ('\u{12a}', '\u{12a}'), ('\u{12c}', '\u{12c}'), ('\u{12e}', '\u{12e}'),
-        ('\u{130}', '\u{130}'), ('\u{132}', '\u{132}'), ('\u{134}', '\u{134}'),
-        ('\u{136}', '\u{136}'), ('\u{139}', '\u{139}'), ('\u{13b}', '\u{13b}'),
-        ('\u{13d}', '\u{13d}'), ('\u{13f}', '\u{13f}'), ('\u{141}', '\u{141}'),
-        ('\u{143}', '\u{143}'), ('\u{145}', '\u{145}'), ('\u{147}', '\u{147}'),
-        ('\u{14a}', '\u{14a}'), ('\u{14c}', '\u{14c}'), ('\u{14e}', '\u{14e}'),
-        ('\u{150}', '\u{150}'), ('\u{152}', '\u{152}'), ('\u{154}', '\u{154}'),
-        ('\u{156}', '\u{156}'), ('\u{158}', '\u{158}'), ('\u{15a}', '\u{15a}'),
-        ('\u{15c}', '\u{15c}'), ('\u{15e}', '\u{15e}'), ('\u{160}', '\u{160}'),
-        ('\u{162}', '\u{162}'), ('\u{164}', '\u{164}'), ('\u{166}', '\u{166}'),
-        ('\u{168}', '\u{168}'), ('\u{16a}', '\u{16a}'), ('\u{16c}', '\u{16c}'),
-        ('\u{16e}', '\u{16e}'), ('\u{170}', '\u{170}'), ('\u{172}', '\u{172}'),
-        ('\u{174}', '\u{174}'), ('\u{176}', '\u{176}'), ('\u{178}', '\u{179}'),
-        ('\u{17b}', '\u{17b}'), ('\u{17d}', '\u{17d}'), ('\u{181}', '\u{182}'),
-        ('\u{184}', '\u{184}'), ('\u{186}', '\u{187}'), ('\u{189}', '\u{18b}'),
-        ('\u{18e}', '\u{191}'), ('\u{193}', '\u{194}'), ('\u{196}', '\u{198}'),
-        ('\u{19c}', '\u{19d}'), ('\u{19f}', '\u{1a0}'), ('\u{1a2}', '\u{1a2}'),
-        ('\u{1a4}', '\u{1a4}'), ('\u{1a6}', '\u{1a7}'), ('\u{1a9}', '\u{1a9}'),
-        ('\u{1ac}', '\u{1ac}'), ('\u{1ae}', '\u{1af}'), ('\u{1b1}', '\u{1b3}'),
-        ('\u{1b5}', '\u{1b5}'), ('\u{1b7}', '\u{1b8}'), ('\u{1bc}', '\u{1bc}'),
-        ('\u{1c4}', '\u{1c4}'), ('\u{1c7}', '\u{1c7}'), ('\u{1ca}', '\u{1ca}'),
-        ('\u{1cd}', '\u{1cd}'), ('\u{1cf}', '\u{1cf}'), ('\u{1d1}', '\u{1d1}'),
-        ('\u{1d3}', '\u{1d3}'), ('\u{1d5}', '\u{1d5}'), ('\u{1d7}', '\u{1d7}'),
-        ('\u{1d9}', '\u{1d9}'), ('\u{1db}', '\u{1db}'), ('\u{1de}', '\u{1de}'),
-        ('\u{1e0}', '\u{1e0}'), ('\u{1e2}', '\u{1e2}'), ('\u{1e4}', '\u{1e4}'),
-        ('\u{1e6}', '\u{1e6}'), ('\u{1e8}', '\u{1e8}'), ('\u{1ea}', '\u{1ea}'),
-        ('\u{1ec}', '\u{1ec}'), ('\u{1ee}', '\u{1ee}'), ('\u{1f1}', '\u{1f1}'),
-        ('\u{1f4}', '\u{1f4}'), ('\u{1f6}', '\u{1f8}'), ('\u{1fa}', '\u{1fa}'),
-        ('\u{1fc}', '\u{1fc}'), ('\u{1fe}', '\u{1fe}'), ('\u{200}', '\u{200}'),
-        ('\u{202}', '\u{202}'), ('\u{204}', '\u{204}'), ('\u{206}', '\u{206}'),
-        ('\u{208}', '\u{208}'), ('\u{20a}', '\u{20a}'), ('\u{20c}', '\u{20c}'),
-        ('\u{20e}', '\u{20e}'), ('\u{210}', '\u{210}'), ('\u{212}', '\u{212}'),
-        ('\u{214}', '\u{214}'), ('\u{216}', '\u{216}'), ('\u{218}', '\u{218}'),
-        ('\u{21a}', '\u{21a}'), ('\u{21c}', '\u{21c}'), ('\u{21e}', '\u{21e}'),
-        ('\u{220}', '\u{220}'), ('\u{222}', '\u{222}'), ('\u{224}', '\u{224}'),
-        ('\u{226}', '\u{226}'), ('\u{228}', '\u{228}'), ('\u{22a}', '\u{22a}'),
-        ('\u{22c}', '\u{22c}'), ('\u{22e}', '\u{22e}'), ('\u{230}', '\u{230}'),
-        ('\u{232}', '\u{232}'), ('\u{23a}', '\u{23b}'), ('\u{23d}', '\u{23e}'),
-        ('\u{241}', '\u{241}'), ('\u{243}', '\u{246}'), ('\u{248}', '\u{248}'),
-        ('\u{24a}', '\u{24a}'), ('\u{24c}', '\u{24c}'), ('\u{24e}', '\u{24e}'),
-        ('\u{370}', '\u{370}'), ('\u{372}', '\u{372}'), ('\u{376}', '\u{376}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
-        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{38f}'), ('\u{391}', '\u{3a1}'),
-        ('\u{3a3}', '\u{3ab}'), ('\u{3cf}', '\u{3cf}'), ('\u{3d2}', '\u{3d4}'),
-        ('\u{3d8}', '\u{3d8}'), ('\u{3da}', '\u{3da}'), ('\u{3dc}', '\u{3dc}'),
-        ('\u{3de}', '\u{3de}'), ('\u{3e0}', '\u{3e0}'), ('\u{3e2}', '\u{3e2}'),
-        ('\u{3e4}', '\u{3e4}'), ('\u{3e6}', '\u{3e6}'), ('\u{3e8}', '\u{3e8}'),
-        ('\u{3ea}', '\u{3ea}'), ('\u{3ec}', '\u{3ec}'), ('\u{3ee}', '\u{3ee}'),
-        ('\u{3f4}', '\u{3f4}'), ('\u{3f7}', '\u{3f7}'), ('\u{3f9}', '\u{3fa}'),
-        ('\u{3fd}', '\u{42f}'), ('\u{460}', '\u{460}'), ('\u{462}', '\u{462}'),
-        ('\u{464}', '\u{464}'), ('\u{466}', '\u{466}'), ('\u{468}', '\u{468}'),
-        ('\u{46a}', '\u{46a}'), ('\u{46c}', '\u{46c}'), ('\u{46e}', '\u{46e}'),
-        ('\u{470}', '\u{470}'), ('\u{472}', '\u{472}'), ('\u{474}', '\u{474}'),
-        ('\u{476}', '\u{476}'), ('\u{478}', '\u{478}'), ('\u{47a}', '\u{47a}'),
-        ('\u{47c}', '\u{47c}'), ('\u{47e}', '\u{47e}'), ('\u{480}', '\u{480}'),
-        ('\u{48a}', '\u{48a}'), ('\u{48c}', '\u{48c}'), ('\u{48e}', '\u{48e}'),
-        ('\u{490}', '\u{490}'), ('\u{492}', '\u{492}'), ('\u{494}', '\u{494}'),
-        ('\u{496}', '\u{496}'), ('\u{498}', '\u{498}'), ('\u{49a}', '\u{49a}'),
-        ('\u{49c}', '\u{49c}'), ('\u{49e}', '\u{49e}'), ('\u{4a0}', '\u{4a0}'),
-        ('\u{4a2}', '\u{4a2}'), ('\u{4a4}', '\u{4a4}'), ('\u{4a6}', '\u{4a6}'),
-        ('\u{4a8}', '\u{4a8}'), ('\u{4aa}', '\u{4aa}'), ('\u{4ac}', '\u{4ac}'),
-        ('\u{4ae}', '\u{4ae}'), ('\u{4b0}', '\u{4b0}'), ('\u{4b2}', '\u{4b2}'),
-        ('\u{4b4}', '\u{4b4}'), ('\u{4b6}', '\u{4b6}'), ('\u{4b8}', '\u{4b8}'),
-        ('\u{4ba}', '\u{4ba}'), ('\u{4bc}', '\u{4bc}'), ('\u{4be}', '\u{4be}'),
-        ('\u{4c0}', '\u{4c1}'), ('\u{4c3}', '\u{4c3}'), ('\u{4c5}', '\u{4c5}'),
-        ('\u{4c7}', '\u{4c7}'), ('\u{4c9}', '\u{4c9}'), ('\u{4cb}', '\u{4cb}'),
-        ('\u{4cd}', '\u{4cd}'), ('\u{4d0}', '\u{4d0}'), ('\u{4d2}', '\u{4d2}'),
-        ('\u{4d4}', '\u{4d4}'), ('\u{4d6}', '\u{4d6}'), ('\u{4d8}', '\u{4d8}'),
-        ('\u{4da}', '\u{4da}'), ('\u{4dc}', '\u{4dc}'), ('\u{4de}', '\u{4de}'),
-        ('\u{4e0}', '\u{4e0}'), ('\u{4e2}', '\u{4e2}'), ('\u{4e4}', '\u{4e4}'),
-        ('\u{4e6}', '\u{4e6}'), ('\u{4e8}', '\u{4e8}'), ('\u{4ea}', '\u{4ea}'),
-        ('\u{4ec}', '\u{4ec}'), ('\u{4ee}', '\u{4ee}'), ('\u{4f0}', '\u{4f0}'),
-        ('\u{4f2}', '\u{4f2}'), ('\u{4f4}', '\u{4f4}'), ('\u{4f6}', '\u{4f6}'),
-        ('\u{4f8}', '\u{4f8}'), ('\u{4fa}', '\u{4fa}'), ('\u{4fc}', '\u{4fc}'),
-        ('\u{4fe}', '\u{4fe}'), ('\u{500}', '\u{500}'), ('\u{502}', '\u{502}'),
-        ('\u{504}', '\u{504}'), ('\u{506}', '\u{506}'), ('\u{508}', '\u{508}'),
-        ('\u{50a}', '\u{50a}'), ('\u{50c}', '\u{50c}'), ('\u{50e}', '\u{50e}'),
-        ('\u{510}', '\u{510}'), ('\u{512}', '\u{512}'), ('\u{514}', '\u{514}'),
-        ('\u{516}', '\u{516}'), ('\u{518}', '\u{518}'), ('\u{51a}', '\u{51a}'),
-        ('\u{51c}', '\u{51c}'), ('\u{51e}', '\u{51e}'), ('\u{520}', '\u{520}'),
-        ('\u{522}', '\u{522}'), ('\u{524}', '\u{524}'), ('\u{526}', '\u{526}'),
-        ('\u{528}', '\u{528}'), ('\u{52a}', '\u{52a}'), ('\u{52c}', '\u{52c}'),
-        ('\u{52e}', '\u{52e}'), ('\u{531}', '\u{556}'), ('\u{10a0}',
-        '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'),
-        ('\u{13a0}', '\u{13f5}'), ('\u{1e00}', '\u{1e00}'), ('\u{1e02}',
-        '\u{1e02}'), ('\u{1e04}', '\u{1e04}'), ('\u{1e06}', '\u{1e06}'),
-        ('\u{1e08}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0a}'), ('\u{1e0c}',
-        '\u{1e0c}'), ('\u{1e0e}', '\u{1e0e}'), ('\u{1e10}', '\u{1e10}'),
-        ('\u{1e12}', '\u{1e12}'), ('\u{1e14}', '\u{1e14}'), ('\u{1e16}',
-        '\u{1e16}'), ('\u{1e18}', '\u{1e18}'), ('\u{1e1a}', '\u{1e1a}'),
-        ('\u{1e1c}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1e}'), ('\u{1e20}',
-        '\u{1e20}'), ('\u{1e22}', '\u{1e22}'), ('\u{1e24}', '\u{1e24}'),
-        ('\u{1e26}', '\u{1e26}'), ('\u{1e28}', '\u{1e28}'), ('\u{1e2a}',
-        '\u{1e2a}'), ('\u{1e2c}', '\u{1e2c}'), ('\u{1e2e}', '\u{1e2e}'),
-        ('\u{1e30}', '\u{1e30}'), ('\u{1e32}', '\u{1e32}'), ('\u{1e34}',
-        '\u{1e34}'), ('\u{1e36}', '\u{1e36}'), ('\u{1e38}', '\u{1e38}'),
-        ('\u{1e3a}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3c}'), ('\u{1e3e}',
-        '\u{1e3e}'), ('\u{1e40}', '\u{1e40}'), ('\u{1e42}', '\u{1e42}'),
-        ('\u{1e44}', '\u{1e44}'), ('\u{1e46}', '\u{1e46}'), ('\u{1e48}',
-        '\u{1e48}'), ('\u{1e4a}', '\u{1e4a}'), ('\u{1e4c}', '\u{1e4c}'),
-        ('\u{1e4e}', '\u{1e4e}'), ('\u{1e50}', '\u{1e50}'), ('\u{1e52}',
-        '\u{1e52}'), ('\u{1e54}', '\u{1e54}'), ('\u{1e56}', '\u{1e56}'),
-        ('\u{1e58}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5a}'), ('\u{1e5c}',
-        '\u{1e5c}'), ('\u{1e5e}', '\u{1e5e}'), ('\u{1e60}', '\u{1e60}'),
-        ('\u{1e62}', '\u{1e62}'), ('\u{1e64}', '\u{1e64}'), ('\u{1e66}',
-        '\u{1e66}'), ('\u{1e68}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6a}'),
-        ('\u{1e6c}', '\u{1e6c}'), ('\u{1e6e}', '\u{1e6e}'), ('\u{1e70}',
-        '\u{1e70}'), ('\u{1e72}', '\u{1e72}'), ('\u{1e74}', '\u{1e74}'),
-        ('\u{1e76}', '\u{1e76}'), ('\u{1e78}', '\u{1e78}'), ('\u{1e7a}',
-        '\u{1e7a}'), ('\u{1e7c}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7e}'),
-        ('\u{1e80}', '\u{1e80}'), ('\u{1e82}', '\u{1e82}'), ('\u{1e84}',
-        '\u{1e84}'), ('\u{1e86}', '\u{1e86}'), ('\u{1e88}', '\u{1e88}'),
-        ('\u{1e8a}', '\u{1e8a}'), ('\u{1e8c}', '\u{1e8c}'), ('\u{1e8e}',
-        '\u{1e8e}'), ('\u{1e90}', '\u{1e90}'), ('\u{1e92}', '\u{1e92}'),
-        ('\u{1e94}', '\u{1e94}'), ('\u{1e9e}', '\u{1e9e}'), ('\u{1ea0}',
-        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea2}'), ('\u{1ea4}', '\u{1ea4}'),
-        ('\u{1ea6}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea8}'), ('\u{1eaa}',
-        '\u{1eaa}'), ('\u{1eac}', '\u{1eac}'), ('\u{1eae}', '\u{1eae}'),
-        ('\u{1eb0}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb2}'), ('\u{1eb4}',
-        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb6}'), ('\u{1eb8}', '\u{1eb8}'),
-        ('\u{1eba}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebc}'), ('\u{1ebe}',
-        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec0}'), ('\u{1ec2}', '\u{1ec2}'),
-        ('\u{1ec4}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec6}'), ('\u{1ec8}',
-        '\u{1ec8}'), ('\u{1eca}', '\u{1eca}'), ('\u{1ecc}', '\u{1ecc}'),
-        ('\u{1ece}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed0}'), ('\u{1ed2}',
-        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed4}'), ('\u{1ed6}', '\u{1ed6}'),
-        ('\u{1ed8}', '\u{1ed8}'), ('\u{1eda}', '\u{1eda}'), ('\u{1edc}',
-        '\u{1edc}'), ('\u{1ede}', '\u{1ede}'), ('\u{1ee0}', '\u{1ee0}'),
-        ('\u{1ee2}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee4}'), ('\u{1ee6}',
-        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee8}'), ('\u{1eea}', '\u{1eea}'),
-        ('\u{1eec}', '\u{1eec}'), ('\u{1eee}', '\u{1eee}'), ('\u{1ef0}',
-        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef2}'), ('\u{1ef4}', '\u{1ef4}'),
-        ('\u{1ef6}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef8}'), ('\u{1efa}',
-        '\u{1efa}'), ('\u{1efc}', '\u{1efc}'), ('\u{1efe}', '\u{1efe}'),
-        ('\u{1f08}', '\u{1f0f}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f28}',
-        '\u{1f2f}'), ('\u{1f38}', '\u{1f3f}'), ('\u{1f48}', '\u{1f4d}'),
-        ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
-        '\u{1f5d}'), ('\u{1f5f}', '\u{1f5f}'), ('\u{1f68}', '\u{1f6f}'),
-        ('\u{1fb8}', '\u{1fbb}'), ('\u{1fc8}', '\u{1fcb}'), ('\u{1fd8}',
-        '\u{1fdb}'), ('\u{1fe8}', '\u{1fec}'), ('\u{1ff8}', '\u{1ffb}'),
-        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210b}',
-        '\u{210d}'), ('\u{2110}', '\u{2112}'), ('\u{2115}', '\u{2115}'),
-        ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
-        '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'),
-        ('\u{2130}', '\u{2133}'), ('\u{213e}', '\u{213f}'), ('\u{2145}',
-        '\u{2145}'), ('\u{2160}', '\u{216f}'), ('\u{2183}', '\u{2183}'),
-        ('\u{24b6}', '\u{24cf}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c60}',
-        '\u{2c60}'), ('\u{2c62}', '\u{2c64}'), ('\u{2c67}', '\u{2c67}'),
-        ('\u{2c69}', '\u{2c69}'), ('\u{2c6b}', '\u{2c6b}'), ('\u{2c6d}',
-        '\u{2c70}'), ('\u{2c72}', '\u{2c72}'), ('\u{2c75}', '\u{2c75}'),
-        ('\u{2c7e}', '\u{2c80}'), ('\u{2c82}', '\u{2c82}'), ('\u{2c84}',
-        '\u{2c84}'), ('\u{2c86}', '\u{2c86}'), ('\u{2c88}', '\u{2c88}'),
-        ('\u{2c8a}', '\u{2c8a}'), ('\u{2c8c}', '\u{2c8c}'), ('\u{2c8e}',
-        '\u{2c8e}'), ('\u{2c90}', '\u{2c90}'), ('\u{2c92}', '\u{2c92}'),
-        ('\u{2c94}', '\u{2c94}'), ('\u{2c96}', '\u{2c96}'), ('\u{2c98}',
-        '\u{2c98}'), ('\u{2c9a}', '\u{2c9a}'), ('\u{2c9c}', '\u{2c9c}'),
-        ('\u{2c9e}', '\u{2c9e}'), ('\u{2ca0}', '\u{2ca0}'), ('\u{2ca2}',
-        '\u{2ca2}'), ('\u{2ca4}', '\u{2ca4}'), ('\u{2ca6}', '\u{2ca6}'),
-        ('\u{2ca8}', '\u{2ca8}'), ('\u{2caa}', '\u{2caa}'), ('\u{2cac}',
-        '\u{2cac}'), ('\u{2cae}', '\u{2cae}'), ('\u{2cb0}', '\u{2cb0}'),
-        ('\u{2cb2}', '\u{2cb2}'), ('\u{2cb4}', '\u{2cb4}'), ('\u{2cb6}',
-        '\u{2cb6}'), ('\u{2cb8}', '\u{2cb8}'), ('\u{2cba}', '\u{2cba}'),
-        ('\u{2cbc}', '\u{2cbc}'), ('\u{2cbe}', '\u{2cbe}'), ('\u{2cc0}',
-        '\u{2cc0}'), ('\u{2cc2}', '\u{2cc2}'), ('\u{2cc4}', '\u{2cc4}'),
-        ('\u{2cc6}', '\u{2cc6}'), ('\u{2cc8}', '\u{2cc8}'), ('\u{2cca}',
-        '\u{2cca}'), ('\u{2ccc}', '\u{2ccc}'), ('\u{2cce}', '\u{2cce}'),
-        ('\u{2cd0}', '\u{2cd0}'), ('\u{2cd2}', '\u{2cd2}'), ('\u{2cd4}',
-        '\u{2cd4}'), ('\u{2cd6}', '\u{2cd6}'), ('\u{2cd8}', '\u{2cd8}'),
-        ('\u{2cda}', '\u{2cda}'), ('\u{2cdc}', '\u{2cdc}'), ('\u{2cde}',
-        '\u{2cde}'), ('\u{2ce0}', '\u{2ce0}'), ('\u{2ce2}', '\u{2ce2}'),
-        ('\u{2ceb}', '\u{2ceb}'), ('\u{2ced}', '\u{2ced}'), ('\u{2cf2}',
-        '\u{2cf2}'), ('\u{a640}', '\u{a640}'), ('\u{a642}', '\u{a642}'),
-        ('\u{a644}', '\u{a644}'), ('\u{a646}', '\u{a646}'), ('\u{a648}',
-        '\u{a648}'), ('\u{a64a}', '\u{a64a}'), ('\u{a64c}', '\u{a64c}'),
-        ('\u{a64e}', '\u{a64e}'), ('\u{a650}', '\u{a650}'), ('\u{a652}',
-        '\u{a652}'), ('\u{a654}', '\u{a654}'), ('\u{a656}', '\u{a656}'),
-        ('\u{a658}', '\u{a658}'), ('\u{a65a}', '\u{a65a}'), ('\u{a65c}',
-        '\u{a65c}'), ('\u{a65e}', '\u{a65e}'), ('\u{a660}', '\u{a660}'),
-        ('\u{a662}', '\u{a662}'), ('\u{a664}', '\u{a664}'), ('\u{a666}',
-        '\u{a666}'), ('\u{a668}', '\u{a668}'), ('\u{a66a}', '\u{a66a}'),
-        ('\u{a66c}', '\u{a66c}'), ('\u{a680}', '\u{a680}'), ('\u{a682}',
-        '\u{a682}'), ('\u{a684}', '\u{a684}'), ('\u{a686}', '\u{a686}'),
-        ('\u{a688}', '\u{a688}'), ('\u{a68a}', '\u{a68a}'), ('\u{a68c}',
-        '\u{a68c}'), ('\u{a68e}', '\u{a68e}'), ('\u{a690}', '\u{a690}'),
-        ('\u{a692}', '\u{a692}'), ('\u{a694}', '\u{a694}'), ('\u{a696}',
-        '\u{a696}'), ('\u{a698}', '\u{a698}'), ('\u{a69a}', '\u{a69a}'),
-        ('\u{a722}', '\u{a722}'), ('\u{a724}', '\u{a724}'), ('\u{a726}',
-        '\u{a726}'), ('\u{a728}', '\u{a728}'), ('\u{a72a}', '\u{a72a}'),
-        ('\u{a72c}', '\u{a72c}'), ('\u{a72e}', '\u{a72e}'), ('\u{a732}',
-        '\u{a732}'), ('\u{a734}', '\u{a734}'), ('\u{a736}', '\u{a736}'),
-        ('\u{a738}', '\u{a738}'), ('\u{a73a}', '\u{a73a}'), ('\u{a73c}',
-        '\u{a73c}'), ('\u{a73e}', '\u{a73e}'), ('\u{a740}', '\u{a740}'),
-        ('\u{a742}', '\u{a742}'), ('\u{a744}', '\u{a744}'), ('\u{a746}',
-        '\u{a746}'), ('\u{a748}', '\u{a748}'), ('\u{a74a}', '\u{a74a}'),
-        ('\u{a74c}', '\u{a74c}'), ('\u{a74e}', '\u{a74e}'), ('\u{a750}',
-        '\u{a750}'), ('\u{a752}', '\u{a752}'), ('\u{a754}', '\u{a754}'),
-        ('\u{a756}', '\u{a756}'), ('\u{a758}', '\u{a758}'), ('\u{a75a}',
-        '\u{a75a}'), ('\u{a75c}', '\u{a75c}'), ('\u{a75e}', '\u{a75e}'),
-        ('\u{a760}', '\u{a760}'), ('\u{a762}', '\u{a762}'), ('\u{a764}',
-        '\u{a764}'), ('\u{a766}', '\u{a766}'), ('\u{a768}', '\u{a768}'),
-        ('\u{a76a}', '\u{a76a}'), ('\u{a76c}', '\u{a76c}'), ('\u{a76e}',
-        '\u{a76e}'), ('\u{a779}', '\u{a779}'), ('\u{a77b}', '\u{a77b}'),
-        ('\u{a77d}', '\u{a77e}'), ('\u{a780}', '\u{a780}'), ('\u{a782}',
-        '\u{a782}'), ('\u{a784}', '\u{a784}'), ('\u{a786}', '\u{a786}'),
-        ('\u{a78b}', '\u{a78b}'), ('\u{a78d}', '\u{a78d}'), ('\u{a790}',
-        '\u{a790}'), ('\u{a792}', '\u{a792}'), ('\u{a796}', '\u{a796}'),
-        ('\u{a798}', '\u{a798}'), ('\u{a79a}', '\u{a79a}'), ('\u{a79c}',
-        '\u{a79c}'), ('\u{a79e}', '\u{a79e}'), ('\u{a7a0}', '\u{a7a0}'),
-        ('\u{a7a2}', '\u{a7a2}'), ('\u{a7a4}', '\u{a7a4}'), ('\u{a7a6}',
-        '\u{a7a6}'), ('\u{a7a8}', '\u{a7a8}'), ('\u{a7aa}', '\u{a7ad}'),
-        ('\u{a7b0}', '\u{a7b4}'), ('\u{a7b6}', '\u{a7b6}'), ('\u{ff21}',
-        '\u{ff3a}'), ('\u{10400}', '\u{10427}'), ('\u{10c80}', '\u{10cb2}'),
-        ('\u{118a0}', '\u{118bf}'), ('\u{1d400}', '\u{1d419}'), ('\u{1d434}',
-        '\u{1d44d}'), ('\u{1d468}', '\u{1d481}'), ('\u{1d49c}', '\u{1d49c}'),
-        ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}',
-        '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b5}'),
-        ('\u{1d4d0}', '\u{1d4e9}'), ('\u{1d504}', '\u{1d505}'), ('\u{1d507}',
-        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
-        ('\u{1d538}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
-        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
-        ('\u{1d56c}', '\u{1d585}'), ('\u{1d5a0}', '\u{1d5b9}'), ('\u{1d5d4}',
-        '\u{1d5ed}'), ('\u{1d608}', '\u{1d621}'), ('\u{1d63c}', '\u{1d655}'),
-        ('\u{1d670}', '\u{1d689}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6e2}',
-        '\u{1d6fa}'), ('\u{1d71c}', '\u{1d734}'), ('\u{1d756}', '\u{1d76e}'),
-        ('\u{1d790}', '\u{1d7a8}'), ('\u{1d7ca}', '\u{1d7ca}'), ('\u{1f130}',
-        '\u{1f149}'), ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}')
-    ];
-
-    pub const XID_Continue_table: &'static [(char, char)] = &[
-        ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'),
-        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
-        ('\u{b7}', '\u{b7}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
-        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
-        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
-        ('\u{300}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{38a}'), ('\u{38c}', '\u{38c}'),
-        ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'),
-        ('\u{483}', '\u{487}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
-        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{591}', '\u{5bd}'),
-        ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'),
-        ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'),
-        ('\u{610}', '\u{61a}'), ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'),
-        ('\u{6d5}', '\u{6dc}'), ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'),
-        ('\u{6ff}', '\u{6ff}'), ('\u{710}', '\u{74a}'), ('\u{74d}', '\u{7b1}'),
-        ('\u{7c0}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{82d}'),
-        ('\u{840}', '\u{85b}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{963}'),
-        ('\u{966}', '\u{96f}'), ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'),
-        ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'),
-        ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'),
-        ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'),
-        ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9f1}'),
-        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
-        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
-        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
-        ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
-        ('\u{a51}', '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
-        ('\u{a66}', '\u{a75}'), ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'),
-        ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'),
-        ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'),
-        ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'),
-        ('\u{ae0}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'),
-        ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
-        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
-        ('\u{b35}', '\u{b39}'), ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'),
-        ('\u{b4b}', '\u{b4d}'), ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'),
-        ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'),
-        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
-        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
-        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
-        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
-        ('\u{bca}', '\u{bcd}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
-        ('\u{be6}', '\u{bef}'), ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'),
-        ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'),
-        ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'),
-        ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'),
-        ('\u{c66}', '\u{c6f}'), ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'),
-        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
-        ('\u{cb5}', '\u{cb9}'), ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'),
-        ('\u{cca}', '\u{ccd}'), ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'),
-        ('\u{ce0}', '\u{ce3}'), ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'),
-        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
-        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
-        ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'),
-        ('\u{d66}', '\u{d6f}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'),
-        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
-        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'),
-        ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'),
-        ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'),
-        ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'),
-        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
-        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
-        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
-        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'),
-        ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{ec8}', '\u{ecd}'),
-        ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
-        ('\u{f18}', '\u{f19}'), ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'),
-        ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'),
-        ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'),
-        ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{1000}',
-        '\u{1049}'), ('\u{1050}', '\u{109d}'), ('\u{10a0}', '\u{10c5}'),
-        ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}',
-        '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'),
-        ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}',
-        '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'),
-        ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}',
-        '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'),
-        ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}',
-        '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{135f}'),
-        ('\u{1369}', '\u{1371}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
-        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
-        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
-        ('\u{170e}', '\u{1714}'), ('\u{1720}', '\u{1734}'), ('\u{1740}',
-        '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
-        ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'), ('\u{17d7}',
-        '\u{17d7}'), ('\u{17dc}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'),
-        ('\u{180b}', '\u{180d}'), ('\u{1810}', '\u{1819}'), ('\u{1820}',
-        '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'),
-        ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}',
-        '\u{193b}'), ('\u{1946}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{19d0}',
-        '\u{19da}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'),
-        ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'), ('\u{1a90}',
-        '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}', '\u{1abd}'),
-        ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'), ('\u{1b6b}',
-        '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}', '\u{1c37}'),
-        ('\u{1c40}', '\u{1c49}'), ('\u{1c4d}', '\u{1c7d}'), ('\u{1cd0}',
-        '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}', '\u{1cf9}'),
-        ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'), ('\u{1f18}',
-        '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
-        ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}',
-        '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'),
-        ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}',
-        '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'),
-        ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}',
-        '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'),
-        ('\u{203f}', '\u{2040}'), ('\u{2054}', '\u{2054}'), ('\u{2071}',
-        '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', '\u{209c}'),
-        ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'), ('\u{20e5}',
-        '\u{20f0}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'),
-        ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2118}',
-        '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'),
-        ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}',
-        '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'),
-        ('\u{2160}', '\u{2188}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}',
-        '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'),
-        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
-        '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'),
-        ('\u{2d7f}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}',
-        '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'),
-        ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}',
-        '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{2de0}', '\u{2dff}'),
-        ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}',
-        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'),
-        ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
-        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
-        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
-        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
-        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
-        '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a66f}'),
-        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}',
-        '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'),
-        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'),
-        ('\u{a8e0}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}',
-        '\u{a8fd}'), ('\u{a900}', '\u{a92d}'), ('\u{a930}', '\u{a953}'),
-        ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}',
-        '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'),
-        ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}', '\u{aa59}'), ('\u{aa60}',
-        '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'),
-        ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}',
-        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
-        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}',
-        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'),
-        ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}',
-        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
-        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
-        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'),
-        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
-        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
-        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}',
-        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
-        ('\u{fdf0}', '\u{fdf9}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}',
-        '\u{fe2f}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'),
-        ('\u{fe71}', '\u{fe71}'), ('\u{fe73}', '\u{fe73}'), ('\u{fe77}',
-        '\u{fe77}'), ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'),
-        ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}', '\u{fefc}'), ('\u{ff10}',
-        '\u{ff19}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'),
-        ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}',
-        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
-        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
-        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
-        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
-        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{101fd}', '\u{101fd}'),
-        ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{102e0}',
-        '\u{102e0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{1034a}'),
-        ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}',
-        '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}', '\u{103d5}'),
-        ('\u{10400}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}'), ('\u{10500}',
-        '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'),
-        ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}',
-        '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'),
-        ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}',
-        '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'),
-        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
-        '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'),
-        ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}',
-        '\u{10a06}'), ('\u{10a0c}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'),
-        ('\u{10a19}', '\u{10a33}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}',
-        '\u{10a3f}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'),
-        ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}',
-        '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'),
-        ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}',
-        '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{11000}', '\u{11046}'),
-        ('\u{11066}', '\u{1106f}'), ('\u{1107f}', '\u{110ba}'), ('\u{110d0}',
-        '\u{110e8}'), ('\u{110f0}', '\u{110f9}'), ('\u{11100}', '\u{11134}'),
-        ('\u{11136}', '\u{1113f}'), ('\u{11150}', '\u{11173}'), ('\u{11176}',
-        '\u{11176}'), ('\u{11180}', '\u{111c4}'), ('\u{111ca}', '\u{111cc}'),
-        ('\u{111d0}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}',
-        '\u{11211}'), ('\u{11213}', '\u{11237}'), ('\u{11280}', '\u{11286}'),
-        ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'), ('\u{1128f}',
-        '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112ea}'),
-        ('\u{112f0}', '\u{112f9}'), ('\u{11300}', '\u{11303}'), ('\u{11305}',
-        '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'),
-        ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}',
-        '\u{11339}'), ('\u{1133c}', '\u{11344}'), ('\u{11347}', '\u{11348}'),
-        ('\u{1134b}', '\u{1134d}'), ('\u{11350}', '\u{11350}'), ('\u{11357}',
-        '\u{11357}'), ('\u{1135d}', '\u{11363}'), ('\u{11366}', '\u{1136c}'),
-        ('\u{11370}', '\u{11374}'), ('\u{11480}', '\u{114c5}'), ('\u{114c7}',
-        '\u{114c7}'), ('\u{114d0}', '\u{114d9}'), ('\u{11580}', '\u{115b5}'),
-        ('\u{115b8}', '\u{115c0}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}',
-        '\u{11640}'), ('\u{11644}', '\u{11644}'), ('\u{11650}', '\u{11659}'),
-        ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}'), ('\u{11700}',
-        '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}', '\u{11739}'),
-        ('\u{118a0}', '\u{118e9}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}',
-        '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'),
-        ('\u{12480}', '\u{12543}'), ('\u{13000}', '\u{1342e}'), ('\u{14400}',
-        '\u{14646}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'),
-        ('\u{16a60}', '\u{16a69}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}',
-        '\u{16af4}'), ('\u{16b00}', '\u{16b36}'), ('\u{16b40}', '\u{16b43}'),
-        ('\u{16b50}', '\u{16b59}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}',
-        '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'),
-        ('\u{16f8f}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}',
-        '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'),
-        ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1d165}',
-        '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'),
-        ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}',
-        '\u{1d244}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'),
-        ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}',
-        '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'),
-        ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}',
-        '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'),
-        ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}',
-        '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'),
-        ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}',
-        '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'),
-        ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}',
-        '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'),
-        ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}',
-        '\u{1d7cb}'), ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'),
-        ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}', '\u{1da75}'), ('\u{1da84}',
-        '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'),
-        ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{1ee00}',
-        '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'),
-        ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}',
-        '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'),
-        ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}',
-        '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'),
-        ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}',
-        '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'),
-        ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}',
-        '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'),
-        ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}',
-        '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'),
-        ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}',
-        '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'),
-        ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}',
-        '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'),
-        ('\u{e0100}', '\u{e01ef}')
-    ];
-
-    pub const XID_Start_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
-        ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'),
-        ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'),
-        ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'),
-        ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'),
-        ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'),
-        ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'),
-        ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{5d0}', '\u{5ea}'),
-        ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'), ('\u{66e}', '\u{66f}'),
-        ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}', '\u{6e6}'),
-        ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
-        ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'),
-        ('\u{7b1}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'),
-        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'),
-        ('\u{824}', '\u{824}'), ('\u{828}', '\u{828}'), ('\u{840}', '\u{858}'),
-        ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'), ('\u{93d}', '\u{93d}'),
-        ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}', '\u{980}'),
-        ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
-        ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'),
-        ('\u{9bd}', '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'),
-        ('\u{9df}', '\u{9e1}'), ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'),
-        ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'),
-        ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'),
-        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}', '\u{a74}'),
-        ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
-        ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
-        ('\u{abd}', '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'),
-        ('\u{af9}', '\u{af9}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
-        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
-        ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'), ('\u{b5c}', '\u{b5d}'),
-        ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}', '\u{b83}'),
-        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
-        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
-        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
-        ('\u{bd0}', '\u{bd0}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
-        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c3d}'),
-        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'), ('\u{c85}', '\u{c8c}'),
-        ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'),
-        ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'),
-        ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'),
-        ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'),
-        ('\u{d4e}', '\u{d4e}'), ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'),
-        ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'),
-        ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{e01}', '\u{e30}'),
-        ('\u{e32}', '\u{e32}'), ('\u{e40}', '\u{e46}'), ('\u{e81}', '\u{e82}'),
-        ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'),
-        ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'),
-        ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'),
-        ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb2}'),
-        ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'),
-        ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}',
-        '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'),
-        ('\u{105a}', '\u{105d}'), ('\u{1061}', '\u{1061}'), ('\u{1065}',
-        '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', '\u{1081}'),
-        ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}',
-        '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'),
-        ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
-        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
-        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
-        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
-        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
-        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
-        ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}',
-        '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'),
-        ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}',
-        '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'),
-        ('\u{170e}', '\u{1711}'), ('\u{1720}', '\u{1731}'), ('\u{1740}',
-        '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'),
-        ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}',
-        '\u{17dc}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'),
-        ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}',
-        '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'),
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}',
-        '\u{1a16}'), ('\u{1a20}', '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'),
-        ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b83}',
-        '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'),
-        ('\u{1c00}', '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}',
-        '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf1}'),
-        ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}',
-        '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'),
-        ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
-        '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'),
-        ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}',
-        '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'),
-        ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
-        '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
-        ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
-        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'),
-        ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}',
-        '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'),
-        ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}',
-        '\u{2139}'), ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'),
-        ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}',
-        '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'),
-        ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}',
-        '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'),
-        ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}',
-        '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'),
-        ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
-        '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
-        ('\u{2dd8}', '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3021}',
-        '\u{3029}'), ('\u{3031}', '\u{3035}'), ('\u{3038}', '\u{303c}'),
-        ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
-        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
-        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
-        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
-        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
-        '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'),
-        ('\u{a640}', '\u{a66e}'), ('\u{a67f}', '\u{a69d}'), ('\u{a6a0}',
-        '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}', '\u{a788}'),
-        ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}',
-        '\u{a801}'), ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'),
-        ('\u{a80c}', '\u{a822}'), ('\u{a840}', '\u{a873}'), ('\u{a882}',
-        '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'),
-        ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}',
-        '\u{a946}'), ('\u{a960}', '\u{a97c}'), ('\u{a984}', '\u{a9b2}'),
-        ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}',
-        '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'),
-        ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}',
-        '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), ('\u{aa7e}', '\u{aaaf}'),
-        ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}',
-        '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'),
-        ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}',
-        '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'),
-        ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}',
-        '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'),
-        ('\u{ab70}', '\u{abe2}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}',
-        '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'),
-        ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}',
-        '\u{fb17}'), ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'),
-        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
-        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
-        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}',
-        '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'),
-        ('\u{fdf0}', '\u{fdf9}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}',
-        '\u{fe73}'), ('\u{fe77}', '\u{fe77}'), ('\u{fe79}', '\u{fe79}'),
-        ('\u{fe7b}', '\u{fe7b}'), ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}',
-        '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
-        ('\u{ff66}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}',
-        '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'),
-        ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
-        '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
-        ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}',
-        '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'),
-        ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}',
-        '\u{1034a}'), ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'),
-        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}',
-        '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'),
-        ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
-        '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'),
-        ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}',
-        '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'),
-        ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}',
-        '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'),
-        ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
-        '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'),
-        ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}',
-        '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'),
-        ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}',
-        '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'),
-        ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}',
-        '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'),
-        ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}',
-        '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'),
-        ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{111dc}',
-        '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'),
-        ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}',
-        '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'),
-        ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
-        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
-        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}',
-        '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}', '\u{11361}'),
-        ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}',
-        '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'),
-        ('\u{11600}', '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}',
-        '\u{116aa}'), ('\u{11700}', '\u{11719}'), ('\u{118a0}', '\u{118df}'),
-        ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}',
-        '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'),
-        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
-        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'),
-        ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}',
-        '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'),
-        ('\u{16f50}', '\u{16f50}'), ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}',
-        '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'),
-        ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}',
-        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
-        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
-        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
-        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
-        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
-        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
-        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
-        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
-        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
-        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
-        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
-        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}',
-        '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
-        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
-        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
-        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
-        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
-        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
-        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
-        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
-        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
-        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
-        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
-        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
-        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
-        ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}',
-        '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'),
-        ('\u{2f800}', '\u{2fa1d}')
-    ];
+impl Iterator for SimpleFoldIter {
+    type Item = char;
 
+    fn next(&mut self) -> Option<char> {
+        self.0.next().map(|c| *c)
+    }
 }
 
-pub mod script {
-    pub const Ahom_table: &'static [(char, char)] = &[
-        ('\u{11700}', '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}',
-        '\u{1173f}')
-    ];
-
-    pub const Anatolian_Hieroglyphs_table: &'static [(char, char)] = &[
-        ('\u{14400}', '\u{14646}')
-    ];
-
-    pub const Arabic_table: &'static [(char, char)] = &[
-        ('\u{600}', '\u{604}'), ('\u{606}', '\u{60b}'), ('\u{60d}', '\u{61a}'),
-        ('\u{61e}', '\u{61e}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'),
-        ('\u{656}', '\u{66f}'), ('\u{671}', '\u{6dc}'), ('\u{6de}', '\u{6ff}'),
-        ('\u{750}', '\u{77f}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{8ff}'),
-        ('\u{fb50}', '\u{fbc1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}',
-        '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfd}'),
-        ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{10e60}',
-        '\u{10e7e}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'),
-        ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}',
-        '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'),
-        ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}',
-        '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
-        ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
-        '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'),
-        ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}',
-        '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'),
-        ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}',
-        '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
-        ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
-        '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'),
-        ('\u{1eeab}', '\u{1eebb}'), ('\u{1eef0}', '\u{1eef1}')
-    ];
-
-    pub const Armenian_table: &'static [(char, char)] = &[
-        ('\u{531}', '\u{556}'), ('\u{559}', '\u{55f}'), ('\u{561}', '\u{587}'),
-        ('\u{58a}', '\u{58a}'), ('\u{58d}', '\u{58f}'), ('\u{fb13}',
-        '\u{fb17}')
-    ];
-
-    pub const Avestan_table: &'static [(char, char)] = &[
-        ('\u{10b00}', '\u{10b35}'), ('\u{10b39}', '\u{10b3f}')
-    ];
-
-    pub const Balinese_table: &'static [(char, char)] = &[
-        ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b7c}')
-    ];
-
-    pub const Bamum_table: &'static [(char, char)] = &[
-        ('\u{a6a0}', '\u{a6f7}'), ('\u{16800}', '\u{16a38}')
-    ];
-
-    pub const Bassa_Vah_table: &'static [(char, char)] = &[
-        ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}', '\u{16af5}')
-    ];
-
-    pub const Batak_table: &'static [(char, char)] = &[
-        ('\u{1bc0}', '\u{1bf3}'), ('\u{1bfc}', '\u{1bff}')
-    ];
-
-    pub const Bengali_table: &'static [(char, char)] = &[
-        ('\u{980}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
-        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
-        ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
-        ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'),
-        ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9fb}')
-    ];
-
-    pub const Bopomofo_table: &'static [(char, char)] = &[
-        ('\u{2ea}', '\u{2eb}'), ('\u{3105}', '\u{312d}'), ('\u{31a0}',
-        '\u{31ba}')
-    ];
-
-    pub const Brahmi_table: &'static [(char, char)] = &[
-        ('\u{11000}', '\u{1104d}'), ('\u{11052}', '\u{1106f}'), ('\u{1107f}',
-        '\u{1107f}')
-    ];
-
-    pub const Braille_table: &'static [(char, char)] = &[
-        ('\u{2800}', '\u{28ff}')
-    ];
-
-    pub const Buginese_table: &'static [(char, char)] = &[
-        ('\u{1a00}', '\u{1a1b}'), ('\u{1a1e}', '\u{1a1f}')
-    ];
-
-    pub const Buhid_table: &'static [(char, char)] = &[
-        ('\u{1740}', '\u{1753}')
-    ];
-
-    pub const Canadian_Aboriginal_table: &'static [(char, char)] = &[
-        ('\u{1400}', '\u{167f}'), ('\u{18b0}', '\u{18f5}')
-    ];
-
-    pub const Carian_table: &'static [(char, char)] = &[
-        ('\u{102a0}', '\u{102d0}')
-    ];
-
-    pub const Caucasian_Albanian_table: &'static [(char, char)] = &[
-        ('\u{10530}', '\u{10563}'), ('\u{1056f}', '\u{1056f}')
-    ];
-
-    pub const Chakma_table: &'static [(char, char)] = &[
-        ('\u{11100}', '\u{11134}'), ('\u{11136}', '\u{11143}')
-    ];
-
-    pub const Cham_table: &'static [(char, char)] = &[
-        ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}',
-        '\u{aa59}'), ('\u{aa5c}', '\u{aa5f}')
-    ];
-
-    pub const Cherokee_table: &'static [(char, char)] = &[
-        ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{ab70}',
-        '\u{abbf}')
-    ];
-
-    pub const Common_table: &'static [(char, char)] = &[
-        ('\u{0}', '\u{40}'), ('\u{5b}', '\u{60}'), ('\u{7b}', '\u{a9}'),
-        ('\u{ab}', '\u{b9}'), ('\u{bb}', '\u{bf}'), ('\u{d7}', '\u{d7}'),
-        ('\u{f7}', '\u{f7}'), ('\u{2b9}', '\u{2df}'), ('\u{2e5}', '\u{2e9}'),
-        ('\u{2ec}', '\u{2ff}'), ('\u{374}', '\u{374}'), ('\u{37e}', '\u{37e}'),
-        ('\u{385}', '\u{385}'), ('\u{387}', '\u{387}'), ('\u{589}', '\u{589}'),
-        ('\u{605}', '\u{605}'), ('\u{60c}', '\u{60c}'), ('\u{61b}', '\u{61c}'),
-        ('\u{61f}', '\u{61f}'), ('\u{640}', '\u{640}'), ('\u{6dd}', '\u{6dd}'),
-        ('\u{964}', '\u{965}'), ('\u{e3f}', '\u{e3f}'), ('\u{fd5}', '\u{fd8}'),
-        ('\u{10fb}', '\u{10fb}'), ('\u{16eb}', '\u{16ed}'), ('\u{1735}',
-        '\u{1736}'), ('\u{1802}', '\u{1803}'), ('\u{1805}', '\u{1805}'),
-        ('\u{1cd3}', '\u{1cd3}'), ('\u{1ce1}', '\u{1ce1}'), ('\u{1ce9}',
-        '\u{1cec}'), ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'),
-        ('\u{2000}', '\u{200b}'), ('\u{200e}', '\u{2064}'), ('\u{2066}',
-        '\u{2070}'), ('\u{2074}', '\u{207e}'), ('\u{2080}', '\u{208e}'),
-        ('\u{20a0}', '\u{20be}'), ('\u{2100}', '\u{2125}'), ('\u{2127}',
-        '\u{2129}'), ('\u{212c}', '\u{2131}'), ('\u{2133}', '\u{214d}'),
-        ('\u{214f}', '\u{215f}'), ('\u{2189}', '\u{218b}'), ('\u{2190}',
-        '\u{23fa}'), ('\u{2400}', '\u{2426}'), ('\u{2440}', '\u{244a}'),
-        ('\u{2460}', '\u{27ff}'), ('\u{2900}', '\u{2b73}'), ('\u{2b76}',
-        '\u{2b95}'), ('\u{2b98}', '\u{2bb9}'), ('\u{2bbd}', '\u{2bc8}'),
-        ('\u{2bca}', '\u{2bd1}'), ('\u{2bec}', '\u{2bef}'), ('\u{2e00}',
-        '\u{2e42}'), ('\u{2ff0}', '\u{2ffb}'), ('\u{3000}', '\u{3004}'),
-        ('\u{3006}', '\u{3006}'), ('\u{3008}', '\u{3020}'), ('\u{3030}',
-        '\u{3037}'), ('\u{303c}', '\u{303f}'), ('\u{309b}', '\u{309c}'),
-        ('\u{30a0}', '\u{30a0}'), ('\u{30fb}', '\u{30fc}'), ('\u{3190}',
-        '\u{319f}'), ('\u{31c0}', '\u{31e3}'), ('\u{3220}', '\u{325f}'),
-        ('\u{327f}', '\u{32cf}'), ('\u{3358}', '\u{33ff}'), ('\u{4dc0}',
-        '\u{4dff}'), ('\u{a700}', '\u{a721}'), ('\u{a788}', '\u{a78a}'),
-        ('\u{a830}', '\u{a839}'), ('\u{a92e}', '\u{a92e}'), ('\u{a9cf}',
-        '\u{a9cf}'), ('\u{ab5b}', '\u{ab5b}'), ('\u{fd3e}', '\u{fd3f}'),
-        ('\u{fe10}', '\u{fe19}'), ('\u{fe30}', '\u{fe52}'), ('\u{fe54}',
-        '\u{fe66}'), ('\u{fe68}', '\u{fe6b}'), ('\u{feff}', '\u{feff}'),
-        ('\u{ff01}', '\u{ff20}'), ('\u{ff3b}', '\u{ff40}'), ('\u{ff5b}',
-        '\u{ff65}'), ('\u{ff70}', '\u{ff70}'), ('\u{ff9e}', '\u{ff9f}'),
-        ('\u{ffe0}', '\u{ffe6}'), ('\u{ffe8}', '\u{ffee}'), ('\u{fff9}',
-        '\u{fffd}'), ('\u{10100}', '\u{10102}'), ('\u{10107}', '\u{10133}'),
-        ('\u{10137}', '\u{1013f}'), ('\u{10190}', '\u{1019b}'), ('\u{101d0}',
-        '\u{101fc}'), ('\u{102e1}', '\u{102fb}'), ('\u{1bca0}', '\u{1bca3}'),
-        ('\u{1d000}', '\u{1d0f5}'), ('\u{1d100}', '\u{1d126}'), ('\u{1d129}',
-        '\u{1d166}'), ('\u{1d16a}', '\u{1d17a}'), ('\u{1d183}', '\u{1d184}'),
-        ('\u{1d18c}', '\u{1d1a9}'), ('\u{1d1ae}', '\u{1d1e8}'), ('\u{1d300}',
-        '\u{1d356}'), ('\u{1d360}', '\u{1d371}'), ('\u{1d400}', '\u{1d454}'),
-        ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}',
-        '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'),
-        ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}',
-        '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'),
-        ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}',
-        '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
-        ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}',
-        '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d7cb}'), ('\u{1d7ce}', '\u{1d7ff}'),
-        ('\u{1f000}', '\u{1f02b}'), ('\u{1f030}', '\u{1f093}'), ('\u{1f0a0}',
-        '\u{1f0ae}'), ('\u{1f0b1}', '\u{1f0bf}'), ('\u{1f0c1}', '\u{1f0cf}'),
-        ('\u{1f0d1}', '\u{1f0f5}'), ('\u{1f100}', '\u{1f10c}'), ('\u{1f110}',
-        '\u{1f12e}'), ('\u{1f130}', '\u{1f16b}'), ('\u{1f170}', '\u{1f19a}'),
-        ('\u{1f1e6}', '\u{1f1ff}'), ('\u{1f201}', '\u{1f202}'), ('\u{1f210}',
-        '\u{1f23a}'), ('\u{1f240}', '\u{1f248}'), ('\u{1f250}', '\u{1f251}'),
-        ('\u{1f300}', '\u{1f579}'), ('\u{1f57b}', '\u{1f5a3}'), ('\u{1f5a5}',
-        '\u{1f6d0}'), ('\u{1f6e0}', '\u{1f6ec}'), ('\u{1f6f0}', '\u{1f6f3}'),
-        ('\u{1f700}', '\u{1f773}'), ('\u{1f780}', '\u{1f7d4}'), ('\u{1f800}',
-        '\u{1f80b}'), ('\u{1f810}', '\u{1f847}'), ('\u{1f850}', '\u{1f859}'),
-        ('\u{1f860}', '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}'), ('\u{1f910}',
-        '\u{1f918}'), ('\u{1f980}', '\u{1f984}'), ('\u{1f9c0}', '\u{1f9c0}'),
-        ('\u{e0001}', '\u{e0001}'), ('\u{e0020}', '\u{e007f}')
-    ];
-
-    pub const Coptic_table: &'static [(char, char)] = &[
-        ('\u{3e2}', '\u{3ef}'), ('\u{2c80}', '\u{2cf3}'), ('\u{2cf9}',
-        '\u{2cff}')
-    ];
-
-    pub const Cuneiform_table: &'static [(char, char)] = &[
-        ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12470}',
-        '\u{12474}'), ('\u{12480}', '\u{12543}')
-    ];
-
-    pub const Cypriot_table: &'static [(char, char)] = &[
-        ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}',
-        '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'),
-        ('\u{1083f}', '\u{1083f}')
-    ];
-
-    pub const Cyrillic_table: &'static [(char, char)] = &[
-        ('\u{400}', '\u{484}'), ('\u{487}', '\u{52f}'), ('\u{1d2b}',
-        '\u{1d2b}'), ('\u{1d78}', '\u{1d78}'), ('\u{2de0}', '\u{2dff}'),
-        ('\u{a640}', '\u{a69f}'), ('\u{fe2e}', '\u{fe2f}')
-    ];
-
-    pub const Deseret_table: &'static [(char, char)] = &[
-        ('\u{10400}', '\u{1044f}')
-    ];
-
-    pub const Devanagari_table: &'static [(char, char)] = &[
-        ('\u{900}', '\u{950}'), ('\u{953}', '\u{963}'), ('\u{966}', '\u{97f}'),
-        ('\u{a8e0}', '\u{a8fd}')
-    ];
-
-    pub const Duployan_table: &'static [(char, char)] = &[
-        ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}',
-        '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9c}', '\u{1bc9f}')
-    ];
-
-    pub const Egyptian_Hieroglyphs_table: &'static [(char, char)] = &[
-        ('\u{13000}', '\u{1342e}')
-    ];
-
-    pub const Elbasan_table: &'static [(char, char)] = &[
-        ('\u{10500}', '\u{10527}')
-    ];
-
-    pub const Ethiopic_table: &'static [(char, char)] = &[
-        ('\u{1200}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
-        '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'),
-        ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
-        '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
-        ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
-        '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
-        ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{137c}'), ('\u{1380}',
-        '\u{1399}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
-        ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
-        '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'),
-        ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{ab01}',
-        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
-        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}')
-    ];
-
-    pub const Georgian_table: &'static [(char, char)] = &[
-        ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}',
-        '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{10ff}'),
-        ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
-        '\u{2d2d}')
-    ];
-
-    pub const Glagolitic_table: &'static [(char, char)] = &[
-        ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}')
-    ];
-
-    pub const Gothic_table: &'static [(char, char)] = &[
-        ('\u{10330}', '\u{1034a}')
-    ];
-
-    pub const Grantha_table: &'static [(char, char)] = &[
-        ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
-        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
-        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}',
-        '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'),
-        ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}',
-        '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}')
-    ];
-
-    pub const Greek_table: &'static [(char, char)] = &[
-        ('\u{370}', '\u{373}'), ('\u{375}', '\u{377}'), ('\u{37a}', '\u{37d}'),
-        ('\u{37f}', '\u{37f}'), ('\u{384}', '\u{384}'), ('\u{386}', '\u{386}'),
-        ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'),
-        ('\u{3a3}', '\u{3e1}'), ('\u{3f0}', '\u{3ff}'), ('\u{1d26}',
-        '\u{1d2a}'), ('\u{1d5d}', '\u{1d61}'), ('\u{1d66}', '\u{1d6a}'),
-        ('\u{1dbf}', '\u{1dbf}'), ('\u{1f00}', '\u{1f15}'), ('\u{1f18}',
-        '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
-        ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}',
-        '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'),
-        ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fdd}', '\u{1fef}'),
-        ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffe}'), ('\u{2126}',
-        '\u{2126}'), ('\u{ab65}', '\u{ab65}'), ('\u{10140}', '\u{1018c}'),
-        ('\u{101a0}', '\u{101a0}'), ('\u{1d200}', '\u{1d245}')
-    ];
-
-    pub const Gujarati_table: &'static [(char, char)] = &[
-        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
-        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
-        ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
-        ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
-        ('\u{ae6}', '\u{af1}'), ('\u{af9}', '\u{af9}')
-    ];
-
-    pub const Gurmukhi_table: &'static [(char, char)] = &[
-        ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'),
-        ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'),
-        ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
-        ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'),
-        ('\u{a51}', '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'),
-        ('\u{a66}', '\u{a75}')
-    ];
-
-    pub const Han_table: &'static [(char, char)] = &[
-        ('\u{2e80}', '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}',
-        '\u{2fd5}'), ('\u{3005}', '\u{3005}'), ('\u{3007}', '\u{3007}'),
-        ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303b}'), ('\u{3400}',
-        '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'), ('\u{f900}', '\u{fa6d}'),
-        ('\u{fa70}', '\u{fad9}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}',
-        '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'),
-        ('\u{2f800}', '\u{2fa1d}')
-    ];
-
-    pub const Hangul_table: &'static [(char, char)] = &[
-        ('\u{1100}', '\u{11ff}'), ('\u{302e}', '\u{302f}'), ('\u{3131}',
-        '\u{318e}'), ('\u{3200}', '\u{321e}'), ('\u{3260}', '\u{327e}'),
-        ('\u{a960}', '\u{a97c}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}',
-        '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{ffa0}', '\u{ffbe}'),
-        ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}',
-        '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}')
-    ];
-
-    pub const Hanunoo_table: &'static [(char, char)] = &[
-        ('\u{1720}', '\u{1734}')
-    ];
-
-    pub const Hatran_table: &'static [(char, char)] = &[
-        ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{108fb}',
-        '\u{108ff}')
-    ];
-
-    pub const Hebrew_table: &'static [(char, char)] = &[
-        ('\u{591}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f4}'),
-        ('\u{fb1d}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
-        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
-        ('\u{fb46}', '\u{fb4f}')
-    ];
-
-    pub const Hiragana_table: &'static [(char, char)] = &[
-        ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{1b001}',
-        '\u{1b001}'), ('\u{1f200}', '\u{1f200}')
-    ];
-
-    pub const Imperial_Aramaic_table: &'static [(char, char)] = &[
-        ('\u{10840}', '\u{10855}'), ('\u{10857}', '\u{1085f}')
-    ];
-
-    pub const Inherited_table: &'static [(char, char)] = &[
-        ('\u{300}', '\u{36f}'), ('\u{485}', '\u{486}'), ('\u{64b}', '\u{655}'),
-        ('\u{670}', '\u{670}'), ('\u{951}', '\u{952}'), ('\u{1ab0}',
-        '\u{1abe}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'),
-        ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}',
-        '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1dc0}', '\u{1df5}'),
-        ('\u{1dfc}', '\u{1dff}'), ('\u{200c}', '\u{200d}'), ('\u{20d0}',
-        '\u{20f0}'), ('\u{302a}', '\u{302d}'), ('\u{3099}', '\u{309a}'),
-        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2d}'), ('\u{101fd}',
-        '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{1d167}', '\u{1d169}'),
-        ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}',
-        '\u{1d1ad}'), ('\u{e0100}', '\u{e01ef}')
-    ];
-
-    pub const Inscriptional_Pahlavi_table: &'static [(char, char)] = &[
-        ('\u{10b60}', '\u{10b72}'), ('\u{10b78}', '\u{10b7f}')
-    ];
-
-    pub const Inscriptional_Parthian_table: &'static [(char, char)] = &[
-        ('\u{10b40}', '\u{10b55}'), ('\u{10b58}', '\u{10b5f}')
-    ];
-
-    pub const Javanese_table: &'static [(char, char)] = &[
-        ('\u{a980}', '\u{a9cd}'), ('\u{a9d0}', '\u{a9d9}'), ('\u{a9de}',
-        '\u{a9df}')
-    ];
-
-    pub const Kaithi_table: &'static [(char, char)] = &[
-        ('\u{11080}', '\u{110c1}')
-    ];
-
-    pub const Kannada_table: &'static [(char, char)] = &[
-        ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
-        ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'),
-        ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
-        ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'),
-        ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}')
-    ];
-
-    pub const Katakana_table: &'static [(char, char)] = &[
-        ('\u{30a1}', '\u{30fa}'), ('\u{30fd}', '\u{30ff}'), ('\u{31f0}',
-        '\u{31ff}'), ('\u{32d0}', '\u{32fe}'), ('\u{3300}', '\u{3357}'),
-        ('\u{ff66}', '\u{ff6f}'), ('\u{ff71}', '\u{ff9d}'), ('\u{1b000}',
-        '\u{1b000}')
-    ];
-
-    pub const Kayah_Li_table: &'static [(char, char)] = &[
-        ('\u{a900}', '\u{a92d}'), ('\u{a92f}', '\u{a92f}')
-    ];
-
-    pub const Kharoshthi_table: &'static [(char, char)] = &[
-        ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
-        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
-        ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a47}'), ('\u{10a50}',
-        '\u{10a58}')
-    ];
-
-    pub const Khmer_table: &'static [(char, char)] = &[
-        ('\u{1780}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'), ('\u{17f0}',
-        '\u{17f9}'), ('\u{19e0}', '\u{19ff}')
-    ];
-
-    pub const Khojki_table: &'static [(char, char)] = &[
-        ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1123d}')
-    ];
-
-    pub const Khudawadi_table: &'static [(char, char)] = &[
-        ('\u{112b0}', '\u{112ea}'), ('\u{112f0}', '\u{112f9}')
-    ];
-
-    pub const Lao_table: &'static [(char, char)] = &[
-        ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'),
-        ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'),
-        ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
-        ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'),
-        ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
-        ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}')
-    ];
-
-    pub const Latin_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'),
-        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'),
-        ('\u{f8}', '\u{2b8}'), ('\u{2e0}', '\u{2e4}'), ('\u{1d00}', '\u{1d25}'),
-        ('\u{1d2c}', '\u{1d5c}'), ('\u{1d62}', '\u{1d65}'), ('\u{1d6b}',
-        '\u{1d77}'), ('\u{1d79}', '\u{1dbe}'), ('\u{1e00}', '\u{1eff}'),
-        ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}',
-        '\u{209c}'), ('\u{212a}', '\u{212b}'), ('\u{2132}', '\u{2132}'),
-        ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c60}',
-        '\u{2c7f}'), ('\u{a722}', '\u{a787}'), ('\u{a78b}', '\u{a7ad}'),
-        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a7ff}'), ('\u{ab30}',
-        '\u{ab5a}'), ('\u{ab5c}', '\u{ab64}'), ('\u{fb00}', '\u{fb06}'),
-        ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}')
-    ];
-
-    pub const Lepcha_table: &'static [(char, char)] = &[
-        ('\u{1c00}', '\u{1c37}'), ('\u{1c3b}', '\u{1c49}'), ('\u{1c4d}',
-        '\u{1c4f}')
-    ];
-
-    pub const Limbu_table: &'static [(char, char)] = &[
-        ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}',
-        '\u{193b}'), ('\u{1940}', '\u{1940}'), ('\u{1944}', '\u{194f}')
-    ];
-
-    pub const Linear_A_table: &'static [(char, char)] = &[
-        ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}',
-        '\u{10767}')
-    ];
-
-    pub const Linear_B_table: &'static [(char, char)] = &[
-        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
-        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
-        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}')
-    ];
-
-    pub const Lisu_table: &'static [(char, char)] = &[
-        ('\u{a4d0}', '\u{a4ff}')
-    ];
-
-    pub const Lycian_table: &'static [(char, char)] = &[
-        ('\u{10280}', '\u{1029c}')
-    ];
-
-    pub const Lydian_table: &'static [(char, char)] = &[
-        ('\u{10920}', '\u{10939}'), ('\u{1093f}', '\u{1093f}')
-    ];
-
-    pub const Mahajani_table: &'static [(char, char)] = &[
-        ('\u{11150}', '\u{11176}')
-    ];
-
-    pub const Malayalam_table: &'static [(char, char)] = &[
-        ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'),
-        ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'),
-        ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'),
-        ('\u{d66}', '\u{d75}'), ('\u{d79}', '\u{d7f}')
-    ];
-
-    pub const Mandaic_table: &'static [(char, char)] = &[
-        ('\u{840}', '\u{85b}'), ('\u{85e}', '\u{85e}')
-    ];
-
-    pub const Manichaean_table: &'static [(char, char)] = &[
-        ('\u{10ac0}', '\u{10ae6}'), ('\u{10aeb}', '\u{10af6}')
-    ];
-
-    pub const Meetei_Mayek_table: &'static [(char, char)] = &[
-        ('\u{aae0}', '\u{aaf6}'), ('\u{abc0}', '\u{abed}'), ('\u{abf0}',
-        '\u{abf9}')
-    ];
-
-    pub const Mende_Kikakui_table: &'static [(char, char)] = &[
-        ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8c7}', '\u{1e8d6}')
-    ];
-
-    pub const Meroitic_Cursive_table: &'static [(char, char)] = &[
-        ('\u{109a0}', '\u{109b7}'), ('\u{109bc}', '\u{109cf}'), ('\u{109d2}',
-        '\u{109ff}')
-    ];
-
-    pub const Meroitic_Hieroglyphs_table: &'static [(char, char)] = &[
-        ('\u{10980}', '\u{1099f}')
-    ];
-
-    pub const Miao_table: &'static [(char, char)] = &[
-        ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}',
-        '\u{16f9f}')
-    ];
-
-    pub const Modi_table: &'static [(char, char)] = &[
-        ('\u{11600}', '\u{11644}'), ('\u{11650}', '\u{11659}')
-    ];
-
-    pub const Mongolian_table: &'static [(char, char)] = &[
-        ('\u{1800}', '\u{1801}'), ('\u{1804}', '\u{1804}'), ('\u{1806}',
-        '\u{180e}'), ('\u{1810}', '\u{1819}'), ('\u{1820}', '\u{1877}'),
-        ('\u{1880}', '\u{18aa}')
-    ];
-
-    pub const Mro_table: &'static [(char, char)] = &[
-        ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16a6e}',
-        '\u{16a6f}')
-    ];
-
-    pub const Multani_table: &'static [(char, char)] = &[
-        ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}',
-        '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a9}')
-    ];
-
-    pub const Myanmar_table: &'static [(char, char)] = &[
-        ('\u{1000}', '\u{109f}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa60}',
-        '\u{aa7f}')
-    ];
-
-    pub const Nabataean_table: &'static [(char, char)] = &[
-        ('\u{10880}', '\u{1089e}'), ('\u{108a7}', '\u{108af}')
-    ];
-
-    pub const New_Tai_Lue_table: &'static [(char, char)] = &[
-        ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{19d0}',
-        '\u{19da}'), ('\u{19de}', '\u{19df}')
-    ];
-
-    pub const Nko_table: &'static [(char, char)] = &[
-        ('\u{7c0}', '\u{7fa}')
-    ];
-
-    pub const Ogham_table: &'static [(char, char)] = &[
-        ('\u{1680}', '\u{169c}')
-    ];
-
-    pub const Ol_Chiki_table: &'static [(char, char)] = &[
-        ('\u{1c50}', '\u{1c7f}')
-    ];
-
-    pub const Old_Hungarian_table: &'static [(char, char)] = &[
-        ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{10cfa}',
-        '\u{10cff}')
-    ];
-
-    pub const Old_Italic_table: &'static [(char, char)] = &[
-        ('\u{10300}', '\u{10323}')
-    ];
-
-    pub const Old_North_Arabian_table: &'static [(char, char)] = &[
-        ('\u{10a80}', '\u{10a9f}')
-    ];
-
-    pub const Old_Permic_table: &'static [(char, char)] = &[
-        ('\u{10350}', '\u{1037a}')
-    ];
-
-    pub const Old_Persian_table: &'static [(char, char)] = &[
-        ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103d5}')
-    ];
-
-    pub const Old_South_Arabian_table: &'static [(char, char)] = &[
-        ('\u{10a60}', '\u{10a7f}')
-    ];
-
-    pub const Old_Turkic_table: &'static [(char, char)] = &[
-        ('\u{10c00}', '\u{10c48}')
-    ];
-
-    pub const Oriya_table: &'static [(char, char)] = &[
-        ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
-        ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
-        ('\u{b35}', '\u{b39}'), ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'),
-        ('\u{b4b}', '\u{b4d}'), ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'),
-        ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b77}')
-    ];
-
-    pub const Osmanya_table: &'static [(char, char)] = &[
-        ('\u{10480}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}')
-    ];
-
-    pub const Pahawh_Hmong_table: &'static [(char, char)] = &[
-        ('\u{16b00}', '\u{16b45}'), ('\u{16b50}', '\u{16b59}'), ('\u{16b5b}',
-        '\u{16b61}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}')
-    ];
-
-    pub const Palmyrene_table: &'static [(char, char)] = &[
-        ('\u{10860}', '\u{1087f}')
-    ];
-
-    pub const Pau_Cin_Hau_table: &'static [(char, char)] = &[
-        ('\u{11ac0}', '\u{11af8}')
-    ];
-
-    pub const Phags_Pa_table: &'static [(char, char)] = &[
-        ('\u{a840}', '\u{a877}')
-    ];
-
-    pub const Phoenician_table: &'static [(char, char)] = &[
-        ('\u{10900}', '\u{1091b}'), ('\u{1091f}', '\u{1091f}')
-    ];
-
-    pub const Psalter_Pahlavi_table: &'static [(char, char)] = &[
-        ('\u{10b80}', '\u{10b91}'), ('\u{10b99}', '\u{10b9c}'), ('\u{10ba9}',
-        '\u{10baf}')
-    ];
-
-    pub const Rejang_table: &'static [(char, char)] = &[
-        ('\u{a930}', '\u{a953}'), ('\u{a95f}', '\u{a95f}')
-    ];
-
-    pub const Runic_table: &'static [(char, char)] = &[
-        ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}')
-    ];
-
-    pub const Samaritan_table: &'static [(char, char)] = &[
-        ('\u{800}', '\u{82d}'), ('\u{830}', '\u{83e}')
-    ];
-
-    pub const Saurashtra_table: &'static [(char, char)] = &[
-        ('\u{a880}', '\u{a8c4}'), ('\u{a8ce}', '\u{a8d9}')
-    ];
-
-    pub const Sharada_table: &'static [(char, char)] = &[
-        ('\u{11180}', '\u{111cd}'), ('\u{111d0}', '\u{111df}')
-    ];
-
-    pub const Shavian_table: &'static [(char, char)] = &[
-        ('\u{10450}', '\u{1047f}')
-    ];
-
-    pub const Siddham_table: &'static [(char, char)] = &[
-        ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115dd}')
-    ];
-
-    pub const SignWriting_table: &'static [(char, char)] = &[
-        ('\u{1d800}', '\u{1da8b}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}',
-        '\u{1daaf}')
-    ];
-
-    pub const Sinhala_table: &'static [(char, char)] = &[
-        ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'),
-        ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'),
-        ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
-        ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df4}'),
-        ('\u{111e1}', '\u{111f4}')
-    ];
-
-    pub const Sora_Sompeng_table: &'static [(char, char)] = &[
-        ('\u{110d0}', '\u{110e8}'), ('\u{110f0}', '\u{110f9}')
-    ];
-
-    pub const Sundanese_table: &'static [(char, char)] = &[
-        ('\u{1b80}', '\u{1bbf}'), ('\u{1cc0}', '\u{1cc7}')
-    ];
-
-    pub const Syloti_Nagri_table: &'static [(char, char)] = &[
-        ('\u{a800}', '\u{a82b}')
-    ];
-
-    pub const Syriac_table: &'static [(char, char)] = &[
-        ('\u{700}', '\u{70d}'), ('\u{70f}', '\u{74a}'), ('\u{74d}', '\u{74f}')
-    ];
-
-    pub const Tagalog_table: &'static [(char, char)] = &[
-        ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1714}')
-    ];
-
-    pub const Tagbanwa_table: &'static [(char, char)] = &[
-        ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'), ('\u{1772}',
-        '\u{1773}')
-    ];
-
-    pub const Tai_Le_table: &'static [(char, char)] = &[
-        ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}')
-    ];
-
-    pub const Tai_Tham_table: &'static [(char, char)] = &[
-        ('\u{1a20}', '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}',
-        '\u{1a89}'), ('\u{1a90}', '\u{1a99}'), ('\u{1aa0}', '\u{1aad}')
-    ];
-
-    pub const Tai_Viet_table: &'static [(char, char)] = &[
-        ('\u{aa80}', '\u{aac2}'), ('\u{aadb}', '\u{aadf}')
-    ];
-
-    pub const Takri_table: &'static [(char, char)] = &[
-        ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}')
-    ];
-
-    pub const Tamil_table: &'static [(char, char)] = &[
-        ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'),
-        ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'),
-        ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'),
-        ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'),
-        ('\u{bca}', '\u{bcd}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
-        ('\u{be6}', '\u{bfa}')
-    ];
-
-    pub const Telugu_table: &'static [(char, char)] = &[
-        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
-        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
-        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
-        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c66}', '\u{c6f}'),
-        ('\u{c78}', '\u{c7f}')
-    ];
-
-    pub const Thaana_table: &'static [(char, char)] = &[
-        ('\u{780}', '\u{7b1}')
-    ];
-
-    pub const Thai_table: &'static [(char, char)] = &[
-        ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e5b}')
-    ];
-
-    pub const Tibetan_table: &'static [(char, char)] = &[
-        ('\u{f00}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f97}'),
-        ('\u{f99}', '\u{fbc}'), ('\u{fbe}', '\u{fcc}'), ('\u{fce}', '\u{fd4}'),
-        ('\u{fd9}', '\u{fda}')
-    ];
-
-    pub const Tifinagh_table: &'static [(char, char)] = &[
-        ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d70}'), ('\u{2d7f}',
-        '\u{2d7f}')
-    ];
-
-    pub const Tirhuta_table: &'static [(char, char)] = &[
-        ('\u{11480}', '\u{114c7}'), ('\u{114d0}', '\u{114d9}')
-    ];
+/// Return an iterator over the equivalence class of simple case mappings
+/// for the given codepoint. The equivalence class does not include the
+/// given codepoint.
+///
+/// If the equivalence class is empty, then this returns the next scalar
+/// value that has a non-empty equivalence class, if it exists. If no such
+/// scalar value exists, then `None` is returned. The point of this behavior
+/// is to permit callers to avoid calling `simple_fold` more than they need
+/// to, since there is some cost to fetching the equivalence class.
+pub fn simple_fold(c: char) -> result::Result<SimpleFoldIter, Option<char>> {
+    CASE_FOLDING_SIMPLE
+        .binary_search_by_key(&c, |&(c1, _)| c1)
+        .map(|i| SimpleFoldIter(CASE_FOLDING_SIMPLE[i].1.iter()))
+        .map_err(|i| {
+            if i >= CASE_FOLDING_SIMPLE.len() {
+                None
+            } else {
+                Some(CASE_FOLDING_SIMPLE[i].0)
+            }
+        })
+}
 
-    pub const Ugaritic_table: &'static [(char, char)] = &[
-        ('\u{10380}', '\u{1039d}'), ('\u{1039f}', '\u{1039f}')
-    ];
+/// Returns true if and only if the given (inclusive) range contains at least
+/// one Unicode scalar value that has a non-empty non-trivial simple case
+/// mapping.
+///
+/// This function panics if `end < start`.
+pub fn contains_simple_case_mapping(start: char, end: char) -> bool {
+    assert!(start <= end);
+    CASE_FOLDING_SIMPLE
+        .binary_search_by(|&(c, _)| {
+            if start <= c && c <= end {
+                Ordering::Equal
+            } else if c > end {
+                Ordering::Greater
+            } else {
+                Ordering::Less
+            }
+        }).is_ok()
+}
 
-    pub const Vai_table: &'static [(char, char)] = &[
-        ('\u{a500}', '\u{a62b}')
-    ];
+/// A query for finding a character class defined by Unicode. This supports
+/// either use of a property name directly, or lookup by property value. The
+/// former generally refers to Binary properties (see UTS#44, Table 8), but
+/// as a special exception (see UTS#18, Section 1.2) both general categories
+/// (an enumeration) and scripts (a catalog) are supported as if each of their
+/// possible values were a binary property.
+///
+/// In all circumstances, property names and values are normalized and
+/// canonicalized. That is, `GC == gc == GeneralCategory == general_category`.
+///
+/// The lifetime `'a` refers to the shorter of the lifetimes of property name
+/// and property value.
+#[derive(Debug)]
+pub enum ClassQuery<'a> {
+    /// Return a class corresponding to a Unicode binary property, named by
+    /// a single letter.
+    OneLetter(char),
+    /// Return a class corresponding to a Unicode binary property.
+    ///
+    /// Note that, by special exception (see UTS#18, Section 1.2), both
+    /// general category values and script values are permitted here as if
+    /// they were a binary property.
+    Binary(&'a str),
+    /// Return a class corresponding to all codepoints whose property
+    /// (identified by `property_name`) corresponds to the given value
+    /// (identified by `property_value`).
+    ByValue {
+        /// A property name.
+        property_name: &'a str,
+        /// A property value.
+        property_value: &'a str,
+    },
+}
 
-    pub const Warang_Citi_table: &'static [(char, char)] = &[
-        ('\u{118a0}', '\u{118f2}'), ('\u{118ff}', '\u{118ff}')
-    ];
+impl<'a> ClassQuery<'a> {
+    fn canonicalize(&self) -> Result<CanonicalClassQuery> {
+        match *self {
+            ClassQuery::OneLetter(c) => self.canonical_binary(&c.to_string()),
+            ClassQuery::Binary(name) => self.canonical_binary(name),
+            ClassQuery::ByValue { property_name, property_value } => {
+                let property_name = normalize(property_name);
+                let property_value = normalize(property_value);
+
+                let canon_name = match canonical_prop(&property_name) {
+                    None => return Err(Error::PropertyNotFound),
+                    Some(canon_name) => canon_name,
+                };
+                Ok(match canon_name {
+                    "General_Category" => {
+                        let canon = match canonical_gencat(&property_value) {
+                            None => return Err(Error::PropertyValueNotFound),
+                            Some(canon) => canon,
+                        };
+                        CanonicalClassQuery::GeneralCategory(canon)
+                    }
+                    "Script" => {
+                        let canon = match canonical_script(&property_value) {
+                            None => return Err(Error::PropertyValueNotFound),
+                            Some(canon) => canon,
+                        };
+                        CanonicalClassQuery::Script(canon)
+                    }
+                    _ => {
+                        let vals = match property_values(canon_name) {
+                            None => return Err(Error::PropertyValueNotFound),
+                            Some(vals) => vals,
+                        };
+                        let canon_val = match canonical_value(
+                            vals,
+                            &property_value,
+                        ) {
+                            None => return Err(Error::PropertyValueNotFound),
+                            Some(canon_val) => canon_val,
+                        };
+                        CanonicalClassQuery::ByValue {
+                            property_name: canon_name,
+                            property_value: canon_val,
+                        }
+                    }
+                })
+            }
+        }
+    }
+
+    fn canonical_binary(&self, name: &str) -> Result<CanonicalClassQuery> {
+        let norm = normalize(name);
+
+        if let Some(canon) = canonical_prop(&norm) {
+            return Ok(CanonicalClassQuery::Binary(canon));
+        }
+        if let Some(canon) = canonical_gencat(&norm) {
+            return Ok(CanonicalClassQuery::GeneralCategory(canon));
+        }
+        if let Some(canon) = canonical_script(&norm) {
+            return Ok(CanonicalClassQuery::Script(canon));
+        }
+        Err(Error::PropertyNotFound)
+    }
+}
 
-    pub const Yi_table: &'static [(char, char)] = &[
-        ('\u{a000}', '\u{a48c}'), ('\u{a490}', '\u{a4c6}')
-    ];
+/// Like ClassQuery, but its parameters have been canonicalized. This also
+/// differentiates binary properties from flattened general categories and
+/// scripts.
+#[derive(Debug, Eq, PartialEq)]
+enum CanonicalClassQuery {
+    /// The canonical binary property name.
+    Binary(&'static str),
+    /// The canonical general category name.
+    GeneralCategory(&'static str),
+    /// The canonical script name.
+    Script(&'static str),
+    /// An arbitrary association between property and value, both of which
+    /// have been canonicalized.
+    ///
+    /// Note that by construction, the property name of ByValue will never
+    /// be General_Category or Script. Those two cases are subsumed by the
+    /// eponymous variants.
+    ByValue {
+        /// The canonical property name.
+        property_name: &'static str,
+        /// The canonical property value.
+        property_value: &'static str,
+    },
+}
 
+/// Looks up a Unicode class given a query. If one doesn't exist, then
+/// `None` is returned.
+pub fn class<'a>(query: ClassQuery<'a>) -> Result<hir::ClassUnicode> {
+    use self::CanonicalClassQuery::*;
+
+    match query.canonicalize()? {
+        Binary(name) => {
+            property_set(property_bool::BY_NAME, name)
+                .map(hir_class)
+                .ok_or(Error::PropertyNotFound)
+        }
+        GeneralCategory("Any") => {
+            Ok(hir_class(&[('\0', '\u{10FFFF}')]))
+        }
+        GeneralCategory("Assigned") => {
+            let mut cls =
+                property_set(general_category::BY_NAME, "Unassigned")
+                    .map(hir_class)
+                    .ok_or(Error::PropertyNotFound)?;
+            cls.negate();
+            Ok(cls)
+        }
+        GeneralCategory("ASCII") => {
+            Ok(hir_class(&[('\0', '\x7F')]))
+        }
+        GeneralCategory(name) => {
+            property_set(general_category::BY_NAME, name)
+                .map(hir_class)
+                .ok_or(Error::PropertyValueNotFound)
+        }
+        Script(name) => {
+            property_set(script::BY_NAME, name)
+                .map(hir_class)
+                .ok_or(Error::PropertyValueNotFound)
+        }
+        ByValue { property_name: "Age", property_value } => {
+            let mut class = hir::ClassUnicode::empty();
+            for set in ages(property_value)? {
+                class.union(&hir_class(set));
+            }
+            Ok(class)
+        }
+        ByValue { property_name: "Script_Extensions", property_value } => {
+            property_set(script_extension::BY_NAME, property_value)
+                .map(hir_class)
+                .ok_or(Error::PropertyValueNotFound)
+        }
+        _ => {
+            // What else should we support?
+            Err(Error::PropertyNotFound)
+        }
+    }
 }
 
-pub mod property {
-    pub const Join_Control_table: &'static [(char, char)] = &[
-        ('\u{200c}', '\u{200d}')
-    ];
+/// Build a Unicode HIR class from a sequence of Unicode scalar value ranges.
+pub fn hir_class(ranges: &[(char, char)]) -> hir::ClassUnicode {
+    let hir_ranges: Vec<hir::ClassUnicodeRange> = ranges
+        .iter()
+        .map(|&(s, e)| hir::ClassUnicodeRange::new(s, e))
+        .collect();
+    hir::ClassUnicode::new(hir_ranges)
+}
 
-    pub const Noncharacter_Code_Point_table: &'static [(char, char)] = &[
-        ('\u{fdd0}', '\u{fdef}'), ('\u{fffe}', '\u{ffff}'), ('\u{1fffe}',
-        '\u{1ffff}'), ('\u{2fffe}', '\u{2ffff}'), ('\u{3fffe}', '\u{3ffff}'),
-        ('\u{4fffe}', '\u{4ffff}'), ('\u{5fffe}', '\u{5ffff}'), ('\u{6fffe}',
-        '\u{6ffff}'), ('\u{7fffe}', '\u{7ffff}'), ('\u{8fffe}', '\u{8ffff}'),
-        ('\u{9fffe}', '\u{9ffff}'), ('\u{afffe}', '\u{affff}'), ('\u{bfffe}',
-        '\u{bffff}'), ('\u{cfffe}', '\u{cffff}'), ('\u{dfffe}', '\u{dffff}'),
-        ('\u{efffe}', '\u{effff}'), ('\u{ffffe}', '\u{fffff}'), ('\u{10fffe}',
-        '\u{10ffff}')
-    ];
+fn canonical_prop(normalized_name: &str) -> Option<&'static str> {
+    ucd_util::canonical_property_name(PROPERTY_NAMES, normalized_name)
+}
 
-    pub const White_Space_table: &'static [(char, char)] = &[
-        ('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'),
-        ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'), ('\u{2000}',
-        '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
-        ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}')
-    ];
+fn canonical_gencat(normalized_value: &str) -> Option<&'static str> {
+    match normalized_value {
+        "any" => Some("Any"),
+        "assigned" => Some("Assigned"),
+        "ascii" => Some("ASCII"),
+        _ => {
+            let gencats = property_values("General_Category").unwrap();
+            canonical_value(gencats, normalized_value)
+        }
+    }
+}
 
+fn canonical_script(normalized_value: &str) -> Option<&'static str> {
+    let scripts = property_values("Script").unwrap();
+    canonical_value(scripts, normalized_value)
 }
 
-pub mod regex {
-    pub const UNICODE_CLASSES: &'static [(&'static str, &'static [(char, char)])] = &[
-        ("Ahom", super::script::Ahom_table), ("Alphabetic",
-        super::derived_property::Alphabetic_table), ("Anatolian_Hieroglyphs",
-        super::script::Anatolian_Hieroglyphs_table), ("Arabic",
-        super::script::Arabic_table), ("Armenian",
-        super::script::Armenian_table), ("Avestan",
-        super::script::Avestan_table), ("Balinese",
-        super::script::Balinese_table), ("Bamum", super::script::Bamum_table),
-        ("Bassa_Vah", super::script::Bassa_Vah_table), ("Batak",
-        super::script::Batak_table), ("Bengali", super::script::Bengali_table),
-        ("Bopomofo", super::script::Bopomofo_table), ("Brahmi",
-        super::script::Brahmi_table), ("Braille", super::script::Braille_table),
-        ("Buginese", super::script::Buginese_table), ("Buhid",
-        super::script::Buhid_table), ("C", super::general_category::C_table),
-        ("Canadian_Aboriginal", super::script::Canadian_Aboriginal_table),
-        ("Carian", super::script::Carian_table), ("Caucasian_Albanian",
-        super::script::Caucasian_Albanian_table), ("Cc",
-        super::general_category::Cc_table), ("Cf",
-        super::general_category::Cf_table), ("Chakma",
-        super::script::Chakma_table), ("Cham", super::script::Cham_table),
-        ("Cherokee", super::script::Cherokee_table), ("Cn",
-        super::general_category::Cn_table), ("Co",
-        super::general_category::Co_table), ("Common",
-        super::script::Common_table), ("Coptic", super::script::Coptic_table),
-        ("Cuneiform", super::script::Cuneiform_table), ("Cypriot",
-        super::script::Cypriot_table), ("Cyrillic",
-        super::script::Cyrillic_table), ("Default_Ignorable_Code_Point",
-        super::derived_property::Default_Ignorable_Code_Point_table),
-        ("Deseret", super::script::Deseret_table), ("Devanagari",
-        super::script::Devanagari_table), ("Duployan",
-        super::script::Duployan_table), ("Egyptian_Hieroglyphs",
-        super::script::Egyptian_Hieroglyphs_table), ("Elbasan",
-        super::script::Elbasan_table), ("Ethiopic",
-        super::script::Ethiopic_table), ("Georgian",
-        super::script::Georgian_table), ("Glagolitic",
-        super::script::Glagolitic_table), ("Gothic",
-        super::script::Gothic_table), ("Grantha", super::script::Grantha_table),
-        ("Grapheme_Extend", super::derived_property::Grapheme_Extend_table),
-        ("Greek", super::script::Greek_table), ("Gujarati",
-        super::script::Gujarati_table), ("Gurmukhi",
-        super::script::Gurmukhi_table), ("Han", super::script::Han_table),
-        ("Hangul", super::script::Hangul_table), ("Hanunoo",
-        super::script::Hanunoo_table), ("Hatran", super::script::Hatran_table),
-        ("Hebrew", super::script::Hebrew_table), ("Hiragana",
-        super::script::Hiragana_table), ("Imperial_Aramaic",
-        super::script::Imperial_Aramaic_table), ("Inherited",
-        super::script::Inherited_table), ("Inscriptional_Pahlavi",
-        super::script::Inscriptional_Pahlavi_table), ("Inscriptional_Parthian",
-        super::script::Inscriptional_Parthian_table), ("Javanese",
-        super::script::Javanese_table), ("Join_Control",
-        super::property::Join_Control_table), ("Kaithi",
-        super::script::Kaithi_table), ("Kannada", super::script::Kannada_table),
-        ("Katakana", super::script::Katakana_table), ("Kayah_Li",
-        super::script::Kayah_Li_table), ("Kharoshthi",
-        super::script::Kharoshthi_table), ("Khmer", super::script::Khmer_table),
-        ("Khojki", super::script::Khojki_table), ("Khudawadi",
-        super::script::Khudawadi_table), ("L",
-        super::general_category::L_table), ("LC",
-        super::general_category::LC_table), ("Lao", super::script::Lao_table),
-        ("Latin", super::script::Latin_table), ("Lepcha",
-        super::script::Lepcha_table), ("Limbu", super::script::Limbu_table),
-        ("Linear_A", super::script::Linear_A_table), ("Linear_B",
-        super::script::Linear_B_table), ("Lisu", super::script::Lisu_table),
-        ("Ll", super::general_category::Ll_table), ("Lm",
-        super::general_category::Lm_table), ("Lo",
-        super::general_category::Lo_table), ("Lowercase",
-        super::derived_property::Lowercase_table), ("Lt",
-        super::general_category::Lt_table), ("Lu",
-        super::general_category::Lu_table), ("Lycian",
-        super::script::Lycian_table), ("Lydian", super::script::Lydian_table),
-        ("M", super::general_category::M_table), ("Mahajani",
-        super::script::Mahajani_table), ("Malayalam",
-        super::script::Malayalam_table), ("Mandaic",
-        super::script::Mandaic_table), ("Manichaean",
-        super::script::Manichaean_table), ("Mc",
-        super::general_category::Mc_table), ("Me",
-        super::general_category::Me_table), ("Meetei_Mayek",
-        super::script::Meetei_Mayek_table), ("Mende_Kikakui",
-        super::script::Mende_Kikakui_table), ("Meroitic_Cursive",
-        super::script::Meroitic_Cursive_table), ("Meroitic_Hieroglyphs",
-        super::script::Meroitic_Hieroglyphs_table), ("Miao",
-        super::script::Miao_table), ("Mn", super::general_category::Mn_table),
-        ("Modi", super::script::Modi_table), ("Mongolian",
-        super::script::Mongolian_table), ("Mro", super::script::Mro_table),
-        ("Multani", super::script::Multani_table), ("Myanmar",
-        super::script::Myanmar_table), ("N", super::general_category::N_table),
-        ("Nabataean", super::script::Nabataean_table), ("Nd",
-        super::general_category::Nd_table), ("New_Tai_Lue",
-        super::script::New_Tai_Lue_table), ("Nko", super::script::Nko_table),
-        ("Nl", super::general_category::Nl_table), ("No",
-        super::general_category::No_table), ("Noncharacter_Code_Point",
-        super::property::Noncharacter_Code_Point_table), ("Ogham",
-        super::script::Ogham_table), ("Ol_Chiki",
-        super::script::Ol_Chiki_table), ("Old_Hungarian",
-        super::script::Old_Hungarian_table), ("Old_Italic",
-        super::script::Old_Italic_table), ("Old_North_Arabian",
-        super::script::Old_North_Arabian_table), ("Old_Permic",
-        super::script::Old_Permic_table), ("Old_Persian",
-        super::script::Old_Persian_table), ("Old_South_Arabian",
-        super::script::Old_South_Arabian_table), ("Old_Turkic",
-        super::script::Old_Turkic_table), ("Oriya", super::script::Oriya_table),
-        ("Osmanya", super::script::Osmanya_table), ("P",
-        super::general_category::P_table), ("Pahawh_Hmong",
-        super::script::Pahawh_Hmong_table), ("Palmyrene",
-        super::script::Palmyrene_table), ("Pau_Cin_Hau",
-        super::script::Pau_Cin_Hau_table), ("Pc",
-        super::general_category::Pc_table), ("Pd",
-        super::general_category::Pd_table), ("Pe",
-        super::general_category::Pe_table), ("Pf",
-        super::general_category::Pf_table), ("Phags_Pa",
-        super::script::Phags_Pa_table), ("Phoenician",
-        super::script::Phoenician_table), ("Pi",
-        super::general_category::Pi_table), ("Po",
-        super::general_category::Po_table), ("Ps",
-        super::general_category::Ps_table), ("Psalter_Pahlavi",
-        super::script::Psalter_Pahlavi_table), ("Rejang",
-        super::script::Rejang_table), ("Runic", super::script::Runic_table),
-        ("S", super::general_category::S_table), ("Samaritan",
-        super::script::Samaritan_table), ("Saurashtra",
-        super::script::Saurashtra_table), ("Sc",
-        super::general_category::Sc_table), ("Sharada",
-        super::script::Sharada_table), ("Shavian",
-        super::script::Shavian_table), ("Siddham",
-        super::script::Siddham_table), ("SignWriting",
-        super::script::SignWriting_table), ("Sinhala",
-        super::script::Sinhala_table), ("Sk",
-        super::general_category::Sk_table), ("Sm",
-        super::general_category::Sm_table), ("So",
-        super::general_category::So_table), ("Sora_Sompeng",
-        super::script::Sora_Sompeng_table), ("Sundanese",
-        super::script::Sundanese_table), ("Syloti_Nagri",
-        super::script::Syloti_Nagri_table), ("Syriac",
-        super::script::Syriac_table), ("Tagalog", super::script::Tagalog_table),
-        ("Tagbanwa", super::script::Tagbanwa_table), ("Tai_Le",
-        super::script::Tai_Le_table), ("Tai_Tham",
-        super::script::Tai_Tham_table), ("Tai_Viet",
-        super::script::Tai_Viet_table), ("Takri", super::script::Takri_table),
-        ("Tamil", super::script::Tamil_table), ("Telugu",
-        super::script::Telugu_table), ("Thaana", super::script::Thaana_table),
-        ("Thai", super::script::Thai_table), ("Tibetan",
-        super::script::Tibetan_table), ("Tifinagh",
-        super::script::Tifinagh_table), ("Tirhuta",
-        super::script::Tirhuta_table), ("Ugaritic",
-        super::script::Ugaritic_table), ("Uppercase",
-        super::derived_property::Uppercase_table), ("Vai",
-        super::script::Vai_table), ("Warang_Citi",
-        super::script::Warang_Citi_table), ("White_Space",
-        super::property::White_Space_table), ("XID_Continue",
-        super::derived_property::XID_Continue_table), ("XID_Start",
-        super::derived_property::XID_Start_table), ("Yi",
-        super::script::Yi_table), ("Z", super::general_category::Z_table),
-        ("Zl", super::general_category::Zl_table), ("Zp",
-        super::general_category::Zp_table), ("Zs",
-        super::general_category::Zs_table)
-    ];
+fn canonical_value(
+    vals: PropertyValues,
+    normalized_value: &str,
+) -> Option<&'static str> {
+    ucd_util::canonical_property_value(vals, normalized_value)
+}
 
-    pub const PERLD: &'static [(char, char)] = super::general_category::Nd_table;
+fn normalize(x: &str) -> String {
+    let mut x = x.to_string();
+    ucd_util::symbolic_name_normalize(&mut x);
+    x
+}
 
-    pub const PERLS: &'static [(char, char)] = super::property::White_Space_table;
+fn property_values(
+    canonical_property_name: &'static str,
+) -> Option<PropertyValues>
+{
+    ucd_util::property_values(PROPERTY_VALUES, canonical_property_name)
+}
 
-    pub const PERLW: &'static [(char, char)] = &[
-        ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'),
-        ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'),
-        ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'),
-        ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'),
-        ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{300}', '\u{374}'),
-        ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'),
-        ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'),
-        ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'),
-        ('\u{483}', '\u{52f}'), ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'),
-        ('\u{561}', '\u{587}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'),
-        ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'),
-        ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{610}', '\u{61a}'),
-        ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'),
-        ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'),
-        ('\u{710}', '\u{74a}'), ('\u{74d}', '\u{7b1}'), ('\u{7c0}', '\u{7f5}'),
-        ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{82d}'), ('\u{840}', '\u{85b}'),
-        ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{963}'), ('\u{966}', '\u{96f}'),
-        ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'),
-        ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'),
-        ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
-        ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'),
-        ('\u{9df}', '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{a01}', '\u{a03}'),
-        ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'),
-        ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'),
-        ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'), ('\u{a3e}', '\u{a42}'),
-        ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'),
-        ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a66}', '\u{a75}'),
-        ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'),
-        ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'),
-        ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'),
-        ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'),
-        ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'), ('\u{b01}', '\u{b03}'),
-        ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'),
-        ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'),
-        ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'),
-        ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'),
-        ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'),
-        ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
-        ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'),
-        ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'),
-        ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
-        ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{bef}'),
-        ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'),
-        ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'),
-        ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
-        ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c66}', '\u{c6f}'),
-        ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
-        ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'),
-        ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
-        ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'),
-        ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'), ('\u{d01}', '\u{d03}'),
-        ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'),
-        ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4e}'),
-        ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d66}', '\u{d6f}'),
-        ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'),
-        ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'),
-        ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'),
-        ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'),
-        ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e4e}'),
-        ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'),
-        ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'),
-        ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'),
-        ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'),
-        ('\u{ead}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'),
-        ('\u{ec6}', '\u{ec6}'), ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'),
-        ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f18}', '\u{f19}'),
-        ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'),
-        ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'), ('\u{f49}', '\u{f6c}'),
-        ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'), ('\u{f99}', '\u{fbc}'),
-        ('\u{fc6}', '\u{fc6}'), ('\u{1000}', '\u{1049}'), ('\u{1050}',
-        '\u{109d}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'),
-        ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}',
-        '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'),
-        ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}',
-        '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'),
-        ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
-        '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'),
-        ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}',
-        '\u{135a}'), ('\u{135d}', '\u{135f}'), ('\u{1380}', '\u{138f}'),
-        ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}',
-        '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'),
-        ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}',
-        '\u{170c}'), ('\u{170e}', '\u{1714}'), ('\u{1720}', '\u{1734}'),
-        ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}',
-        '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'),
-        ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dd}'), ('\u{17e0}',
-        '\u{17e9}'), ('\u{180b}', '\u{180d}'), ('\u{1810}', '\u{1819}'),
-        ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}',
-        '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'),
-        ('\u{1930}', '\u{193b}'), ('\u{1946}', '\u{196d}'), ('\u{1970}',
-        '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'),
-        ('\u{19d0}', '\u{19d9}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}',
-        '\u{1a5e}'), ('\u{1a60}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'),
-        ('\u{1a90}', '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}',
-        '\u{1abe}'), ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'),
-        ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}',
-        '\u{1c37}'), ('\u{1c40}', '\u{1c49}'), ('\u{1c4d}', '\u{1c7d}'),
-        ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}',
-        '\u{1cf9}'), ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'),
-        ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}',
-        '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
-        ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
-        '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
-        ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
-        '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'),
-        ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}',
-        '\u{1ffc}'), ('\u{200c}', '\u{200d}'), ('\u{203f}', '\u{2040}'),
-        ('\u{2054}', '\u{2054}'), ('\u{2071}', '\u{2071}'), ('\u{207f}',
-        '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{20d0}', '\u{20f0}'),
-        ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}',
-        '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2119}', '\u{211d}'),
-        ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}',
-        '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2139}'),
-        ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}',
-        '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{24b6}', '\u{24e9}'),
-        ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}',
-        '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'),
-        ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}',
-        '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d96}'),
-        ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}',
-        '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'),
-        ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}',
-        '\u{2dde}'), ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'),
-        ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}',
-        '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'),
-        ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}',
-        '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'),
-        ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}',
-        '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'),
-        ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
-        '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a672}'),
-        ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}',
-        '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'),
-        ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'), ('\u{a840}',
-        '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'),
-        ('\u{a8e0}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}',
-        '\u{a8fd}'), ('\u{a900}', '\u{a92d}'), ('\u{a930}', '\u{a953}'),
-        ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}',
-        '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'),
-        ('\u{aa40}', '\u{aa4d}'), ('\u{aa50}', '\u{aa59}'), ('\u{aa60}',
-        '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'),
-        ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}',
-        '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
-        ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}',
-        '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'),
-        ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}',
-        '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'),
-        ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}',
-        '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'),
-        ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
-        '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'),
-        ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}',
-        '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'),
-        ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{fe33}',
-        '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'), ('\u{fe70}', '\u{fe74}'),
-        ('\u{fe76}', '\u{fefc}'), ('\u{ff10}', '\u{ff19}'), ('\u{ff21}',
-        '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'), ('\u{ff41}', '\u{ff5a}'),
-        ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
-        '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'),
-        ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}',
-        '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'),
-        ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10140}',
-        '\u{10174}'), ('\u{101fd}', '\u{101fd}'), ('\u{10280}', '\u{1029c}'),
-        ('\u{102a0}', '\u{102d0}'), ('\u{102e0}', '\u{102e0}'), ('\u{10300}',
-        '\u{1031f}'), ('\u{10330}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'),
-        ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}',
-        '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'),
-        ('\u{104a0}', '\u{104a9}'), ('\u{10500}', '\u{10527}'), ('\u{10530}',
-        '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'),
-        ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}',
-        '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'),
-        ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}',
-        '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{108e0}', '\u{108f2}'),
-        ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'), ('\u{10920}',
-        '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'),
-        ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
-        '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'),
-        ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'), ('\u{10a60}',
-        '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'),
-        ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}',
-        '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'),
-        ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}',
-        '\u{10cf2}'), ('\u{11000}', '\u{11046}'), ('\u{11066}', '\u{1106f}'),
-        ('\u{1107f}', '\u{110ba}'), ('\u{110d0}', '\u{110e8}'), ('\u{110f0}',
-        '\u{110f9}'), ('\u{11100}', '\u{11134}'), ('\u{11136}', '\u{1113f}'),
-        ('\u{11150}', '\u{11173}'), ('\u{11176}', '\u{11176}'), ('\u{11180}',
-        '\u{111c4}'), ('\u{111ca}', '\u{111cc}'), ('\u{111d0}', '\u{111da}'),
-        ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
-        '\u{11237}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'),
-        ('\u{1128a}', '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}',
-        '\u{112a8}'), ('\u{112b0}', '\u{112ea}'), ('\u{112f0}', '\u{112f9}'),
-        ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}',
-        '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'),
-        ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}',
-        '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'),
-        ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}',
-        '\u{11363}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}'),
-        ('\u{11480}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{114d0}',
-        '\u{114d9}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115c0}'),
-        ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{11640}'), ('\u{11644}',
-        '\u{11644}'), ('\u{11650}', '\u{11659}'), ('\u{11680}', '\u{116b7}'),
-        ('\u{116c0}', '\u{116c9}'), ('\u{11700}', '\u{11719}'), ('\u{1171d}',
-        '\u{1172b}'), ('\u{11730}', '\u{11739}'), ('\u{118a0}', '\u{118e9}'),
-        ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}',
-        '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'),
-        ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
-        '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'),
-        ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b00}',
-        '\u{16b36}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b50}', '\u{16b59}'),
-        ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}',
-        '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}', '\u{16f9f}'),
-        ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}',
-        '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'),
-        ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}',
-        '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'),
-        ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'), ('\u{1d400}',
-        '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'),
-        ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}',
-        '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'),
-        ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
-        '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
-        ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}',
-        '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'),
-        ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}',
-        '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'),
-        ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
-        '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
-        ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1d7ce}',
-        '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'),
-        ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}',
-        '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'), ('\u{1e800}', '\u{1e8c4}'),
-        ('\u{1e8d0}', '\u{1e8d6}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}',
-        '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'),
-        ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}',
-        '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
-        ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
-        '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'),
-        ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}',
-        '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'),
-        ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}',
-        '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
-        ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
-        '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'),
-        ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}',
-        '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'),
-        ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}'), ('\u{20000}',
-        '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'),
-        ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'), ('\u{e0100}',
-        '\u{e01ef}')
-    ];
+fn property_set(
+    name_map: &'static [(&'static str, &'static [(char, char)])],
+    canonical: &'static str,
+) -> Option<&'static [(char, char)]> {
+    name_map
+        .binary_search_by_key(&canonical, |x| x.0)
+        .ok()
+        .map(|i| name_map[i].1)
+}
 
+/// An iterator over Unicode Age sets. Each item corresponds to a set of
+/// codepoints that were added in a particular revision of Unicode. The
+/// iterator yields items in chronological order.
+#[derive(Debug)]
+struct AgeIter {
+    ages: &'static [(&'static str, &'static [(char, char)])],
 }
 
-pub mod case_folding {
-    pub const C_plus_S_both_table: &'static [(char, char)] = &[
-        ('\u{41}', '\u{61}'), ('\u{42}', '\u{62}'), ('\u{43}', '\u{63}'),
-        ('\u{44}', '\u{64}'), ('\u{45}', '\u{65}'), ('\u{46}', '\u{66}'),
-        ('\u{47}', '\u{67}'), ('\u{48}', '\u{68}'), ('\u{49}', '\u{69}'),
-        ('\u{4a}', '\u{6a}'), ('\u{4b}', '\u{6b}'), ('\u{4b}', '\u{212a}'),
-        ('\u{4c}', '\u{6c}'), ('\u{4d}', '\u{6d}'), ('\u{4e}', '\u{6e}'),
-        ('\u{4f}', '\u{6f}'), ('\u{50}', '\u{70}'), ('\u{51}', '\u{71}'),
-        ('\u{52}', '\u{72}'), ('\u{53}', '\u{73}'), ('\u{53}', '\u{17f}'),
-        ('\u{54}', '\u{74}'), ('\u{55}', '\u{75}'), ('\u{56}', '\u{76}'),
-        ('\u{57}', '\u{77}'), ('\u{58}', '\u{78}'), ('\u{59}', '\u{79}'),
-        ('\u{5a}', '\u{7a}'), ('\u{61}', '\u{41}'), ('\u{62}', '\u{42}'),
-        ('\u{63}', '\u{43}'), ('\u{64}', '\u{44}'), ('\u{65}', '\u{45}'),
-        ('\u{66}', '\u{46}'), ('\u{67}', '\u{47}'), ('\u{68}', '\u{48}'),
-        ('\u{69}', '\u{49}'), ('\u{6a}', '\u{4a}'), ('\u{6b}', '\u{4b}'),
-        ('\u{6b}', '\u{212a}'), ('\u{6c}', '\u{4c}'), ('\u{6d}', '\u{4d}'),
-        ('\u{6e}', '\u{4e}'), ('\u{6f}', '\u{4f}'), ('\u{70}', '\u{50}'),
-        ('\u{71}', '\u{51}'), ('\u{72}', '\u{52}'), ('\u{73}', '\u{53}'),
-        ('\u{73}', '\u{17f}'), ('\u{74}', '\u{54}'), ('\u{75}', '\u{55}'),
-        ('\u{76}', '\u{56}'), ('\u{77}', '\u{57}'), ('\u{78}', '\u{58}'),
-        ('\u{79}', '\u{59}'), ('\u{7a}', '\u{5a}'), ('\u{b5}', '\u{39c}'),
-        ('\u{b5}', '\u{3bc}'), ('\u{c0}', '\u{e0}'), ('\u{c1}', '\u{e1}'),
-        ('\u{c2}', '\u{e2}'), ('\u{c3}', '\u{e3}'), ('\u{c4}', '\u{e4}'),
-        ('\u{c5}', '\u{e5}'), ('\u{c5}', '\u{212b}'), ('\u{c6}', '\u{e6}'),
-        ('\u{c7}', '\u{e7}'), ('\u{c8}', '\u{e8}'), ('\u{c9}', '\u{e9}'),
-        ('\u{ca}', '\u{ea}'), ('\u{cb}', '\u{eb}'), ('\u{cc}', '\u{ec}'),
-        ('\u{cd}', '\u{ed}'), ('\u{ce}', '\u{ee}'), ('\u{cf}', '\u{ef}'),
-        ('\u{d0}', '\u{f0}'), ('\u{d1}', '\u{f1}'), ('\u{d2}', '\u{f2}'),
-        ('\u{d3}', '\u{f3}'), ('\u{d4}', '\u{f4}'), ('\u{d5}', '\u{f5}'),
-        ('\u{d6}', '\u{f6}'), ('\u{d8}', '\u{f8}'), ('\u{d9}', '\u{f9}'),
-        ('\u{da}', '\u{fa}'), ('\u{db}', '\u{fb}'), ('\u{dc}', '\u{fc}'),
-        ('\u{dd}', '\u{fd}'), ('\u{de}', '\u{fe}'), ('\u{df}', '\u{1e9e}'),
-        ('\u{e0}', '\u{c0}'), ('\u{e1}', '\u{c1}'), ('\u{e2}', '\u{c2}'),
-        ('\u{e3}', '\u{c3}'), ('\u{e4}', '\u{c4}'), ('\u{e5}', '\u{c5}'),
-        ('\u{e5}', '\u{212b}'), ('\u{e6}', '\u{c6}'), ('\u{e7}', '\u{c7}'),
-        ('\u{e8}', '\u{c8}'), ('\u{e9}', '\u{c9}'), ('\u{ea}', '\u{ca}'),
-        ('\u{eb}', '\u{cb}'), ('\u{ec}', '\u{cc}'), ('\u{ed}', '\u{cd}'),
-        ('\u{ee}', '\u{ce}'), ('\u{ef}', '\u{cf}'), ('\u{f0}', '\u{d0}'),
-        ('\u{f1}', '\u{d1}'), ('\u{f2}', '\u{d2}'), ('\u{f3}', '\u{d3}'),
-        ('\u{f4}', '\u{d4}'), ('\u{f5}', '\u{d5}'), ('\u{f6}', '\u{d6}'),
-        ('\u{f8}', '\u{d8}'), ('\u{f9}', '\u{d9}'), ('\u{fa}', '\u{da}'),
-        ('\u{fb}', '\u{db}'), ('\u{fc}', '\u{dc}'), ('\u{fd}', '\u{dd}'),
-        ('\u{fe}', '\u{de}'), ('\u{ff}', '\u{178}'), ('\u{100}', '\u{101}'),
-        ('\u{101}', '\u{100}'), ('\u{102}', '\u{103}'), ('\u{103}', '\u{102}'),
-        ('\u{104}', '\u{105}'), ('\u{105}', '\u{104}'), ('\u{106}', '\u{107}'),
-        ('\u{107}', '\u{106}'), ('\u{108}', '\u{109}'), ('\u{109}', '\u{108}'),
-        ('\u{10a}', '\u{10b}'), ('\u{10b}', '\u{10a}'), ('\u{10c}', '\u{10d}'),
-        ('\u{10d}', '\u{10c}'), ('\u{10e}', '\u{10f}'), ('\u{10f}', '\u{10e}'),
-        ('\u{110}', '\u{111}'), ('\u{111}', '\u{110}'), ('\u{112}', '\u{113}'),
-        ('\u{113}', '\u{112}'), ('\u{114}', '\u{115}'), ('\u{115}', '\u{114}'),
-        ('\u{116}', '\u{117}'), ('\u{117}', '\u{116}'), ('\u{118}', '\u{119}'),
-        ('\u{119}', '\u{118}'), ('\u{11a}', '\u{11b}'), ('\u{11b}', '\u{11a}'),
-        ('\u{11c}', '\u{11d}'), ('\u{11d}', '\u{11c}'), ('\u{11e}', '\u{11f}'),
-        ('\u{11f}', '\u{11e}'), ('\u{120}', '\u{121}'), ('\u{121}', '\u{120}'),
-        ('\u{122}', '\u{123}'), ('\u{123}', '\u{122}'), ('\u{124}', '\u{125}'),
-        ('\u{125}', '\u{124}'), ('\u{126}', '\u{127}'), ('\u{127}', '\u{126}'),
-        ('\u{128}', '\u{129}'), ('\u{129}', '\u{128}'), ('\u{12a}', '\u{12b}'),
-        ('\u{12b}', '\u{12a}'), ('\u{12c}', '\u{12d}'), ('\u{12d}', '\u{12c}'),
-        ('\u{12e}', '\u{12f}'), ('\u{12f}', '\u{12e}'), ('\u{132}', '\u{133}'),
-        ('\u{133}', '\u{132}'), ('\u{134}', '\u{135}'), ('\u{135}', '\u{134}'),
-        ('\u{136}', '\u{137}'), ('\u{137}', '\u{136}'), ('\u{139}', '\u{13a}'),
-        ('\u{13a}', '\u{139}'), ('\u{13b}', '\u{13c}'), ('\u{13c}', '\u{13b}'),
-        ('\u{13d}', '\u{13e}'), ('\u{13e}', '\u{13d}'), ('\u{13f}', '\u{140}'),
-        ('\u{140}', '\u{13f}'), ('\u{141}', '\u{142}'), ('\u{142}', '\u{141}'),
-        ('\u{143}', '\u{144}'), ('\u{144}', '\u{143}'), ('\u{145}', '\u{146}'),
-        ('\u{146}', '\u{145}'), ('\u{147}', '\u{148}'), ('\u{148}', '\u{147}'),
-        ('\u{14a}', '\u{14b}'), ('\u{14b}', '\u{14a}'), ('\u{14c}', '\u{14d}'),
-        ('\u{14d}', '\u{14c}'), ('\u{14e}', '\u{14f}'), ('\u{14f}', '\u{14e}'),
-        ('\u{150}', '\u{151}'), ('\u{151}', '\u{150}'), ('\u{152}', '\u{153}'),
-        ('\u{153}', '\u{152}'), ('\u{154}', '\u{155}'), ('\u{155}', '\u{154}'),
-        ('\u{156}', '\u{157}'), ('\u{157}', '\u{156}'), ('\u{158}', '\u{159}'),
-        ('\u{159}', '\u{158}'), ('\u{15a}', '\u{15b}'), ('\u{15b}', '\u{15a}'),
-        ('\u{15c}', '\u{15d}'), ('\u{15d}', '\u{15c}'), ('\u{15e}', '\u{15f}'),
-        ('\u{15f}', '\u{15e}'), ('\u{160}', '\u{161}'), ('\u{161}', '\u{160}'),
-        ('\u{162}', '\u{163}'), ('\u{163}', '\u{162}'), ('\u{164}', '\u{165}'),
-        ('\u{165}', '\u{164}'), ('\u{166}', '\u{167}'), ('\u{167}', '\u{166}'),
-        ('\u{168}', '\u{169}'), ('\u{169}', '\u{168}'), ('\u{16a}', '\u{16b}'),
-        ('\u{16b}', '\u{16a}'), ('\u{16c}', '\u{16d}'), ('\u{16d}', '\u{16c}'),
-        ('\u{16e}', '\u{16f}'), ('\u{16f}', '\u{16e}'), ('\u{170}', '\u{171}'),
-        ('\u{171}', '\u{170}'), ('\u{172}', '\u{173}'), ('\u{173}', '\u{172}'),
-        ('\u{174}', '\u{175}'), ('\u{175}', '\u{174}'), ('\u{176}', '\u{177}'),
-        ('\u{177}', '\u{176}'), ('\u{178}', '\u{ff}'), ('\u{179}', '\u{17a}'),
-        ('\u{17a}', '\u{179}'), ('\u{17b}', '\u{17c}'), ('\u{17c}', '\u{17b}'),
-        ('\u{17d}', '\u{17e}'), ('\u{17e}', '\u{17d}'), ('\u{17f}', '\u{53}'),
-        ('\u{17f}', '\u{73}'), ('\u{180}', '\u{243}'), ('\u{181}', '\u{253}'),
-        ('\u{182}', '\u{183}'), ('\u{183}', '\u{182}'), ('\u{184}', '\u{185}'),
-        ('\u{185}', '\u{184}'), ('\u{186}', '\u{254}'), ('\u{187}', '\u{188}'),
-        ('\u{188}', '\u{187}'), ('\u{189}', '\u{256}'), ('\u{18a}', '\u{257}'),
-        ('\u{18b}', '\u{18c}'), ('\u{18c}', '\u{18b}'), ('\u{18e}', '\u{1dd}'),
-        ('\u{18f}', '\u{259}'), ('\u{190}', '\u{25b}'), ('\u{191}', '\u{192}'),
-        ('\u{192}', '\u{191}'), ('\u{193}', '\u{260}'), ('\u{194}', '\u{263}'),
-        ('\u{195}', '\u{1f6}'), ('\u{196}', '\u{269}'), ('\u{197}', '\u{268}'),
-        ('\u{198}', '\u{199}'), ('\u{199}', '\u{198}'), ('\u{19a}', '\u{23d}'),
-        ('\u{19c}', '\u{26f}'), ('\u{19d}', '\u{272}'), ('\u{19e}', '\u{220}'),
-        ('\u{19f}', '\u{275}'), ('\u{1a0}', '\u{1a1}'), ('\u{1a1}', '\u{1a0}'),
-        ('\u{1a2}', '\u{1a3}'), ('\u{1a3}', '\u{1a2}'), ('\u{1a4}', '\u{1a5}'),
-        ('\u{1a5}', '\u{1a4}'), ('\u{1a6}', '\u{280}'), ('\u{1a7}', '\u{1a8}'),
-        ('\u{1a8}', '\u{1a7}'), ('\u{1a9}', '\u{283}'), ('\u{1ac}', '\u{1ad}'),
-        ('\u{1ad}', '\u{1ac}'), ('\u{1ae}', '\u{288}'), ('\u{1af}', '\u{1b0}'),
-        ('\u{1b0}', '\u{1af}'), ('\u{1b1}', '\u{28a}'), ('\u{1b2}', '\u{28b}'),
-        ('\u{1b3}', '\u{1b4}'), ('\u{1b4}', '\u{1b3}'), ('\u{1b5}', '\u{1b6}'),
-        ('\u{1b6}', '\u{1b5}'), ('\u{1b7}', '\u{292}'), ('\u{1b8}', '\u{1b9}'),
-        ('\u{1b9}', '\u{1b8}'), ('\u{1bc}', '\u{1bd}'), ('\u{1bd}', '\u{1bc}'),
-        ('\u{1bf}', '\u{1f7}'), ('\u{1c4}', '\u{1c5}'), ('\u{1c4}', '\u{1c6}'),
-        ('\u{1c5}', '\u{1c4}'), ('\u{1c5}', '\u{1c6}'), ('\u{1c6}', '\u{1c4}'),
-        ('\u{1c6}', '\u{1c5}'), ('\u{1c7}', '\u{1c8}'), ('\u{1c7}', '\u{1c9}'),
-        ('\u{1c8}', '\u{1c7}'), ('\u{1c8}', '\u{1c9}'), ('\u{1c9}', '\u{1c7}'),
-        ('\u{1c9}', '\u{1c8}'), ('\u{1ca}', '\u{1cb}'), ('\u{1ca}', '\u{1cc}'),
-        ('\u{1cb}', '\u{1ca}'), ('\u{1cb}', '\u{1cc}'), ('\u{1cc}', '\u{1ca}'),
-        ('\u{1cc}', '\u{1cb}'), ('\u{1cd}', '\u{1ce}'), ('\u{1ce}', '\u{1cd}'),
-        ('\u{1cf}', '\u{1d0}'), ('\u{1d0}', '\u{1cf}'), ('\u{1d1}', '\u{1d2}'),
-        ('\u{1d2}', '\u{1d1}'), ('\u{1d3}', '\u{1d4}'), ('\u{1d4}', '\u{1d3}'),
-        ('\u{1d5}', '\u{1d6}'), ('\u{1d6}', '\u{1d5}'), ('\u{1d7}', '\u{1d8}'),
-        ('\u{1d8}', '\u{1d7}'), ('\u{1d9}', '\u{1da}'), ('\u{1da}', '\u{1d9}'),
-        ('\u{1db}', '\u{1dc}'), ('\u{1dc}', '\u{1db}'), ('\u{1dd}', '\u{18e}'),
-        ('\u{1de}', '\u{1df}'), ('\u{1df}', '\u{1de}'), ('\u{1e0}', '\u{1e1}'),
-        ('\u{1e1}', '\u{1e0}'), ('\u{1e2}', '\u{1e3}'), ('\u{1e3}', '\u{1e2}'),
-        ('\u{1e4}', '\u{1e5}'), ('\u{1e5}', '\u{1e4}'), ('\u{1e6}', '\u{1e7}'),
-        ('\u{1e7}', '\u{1e6}'), ('\u{1e8}', '\u{1e9}'), ('\u{1e9}', '\u{1e8}'),
-        ('\u{1ea}', '\u{1eb}'), ('\u{1eb}', '\u{1ea}'), ('\u{1ec}', '\u{1ed}'),
-        ('\u{1ed}', '\u{1ec}'), ('\u{1ee}', '\u{1ef}'), ('\u{1ef}', '\u{1ee}'),
-        ('\u{1f1}', '\u{1f2}'), ('\u{1f1}', '\u{1f3}'), ('\u{1f2}', '\u{1f1}'),
-        ('\u{1f2}', '\u{1f3}'), ('\u{1f3}', '\u{1f1}'), ('\u{1f3}', '\u{1f2}'),
-        ('\u{1f4}', '\u{1f5}'), ('\u{1f5}', '\u{1f4}'), ('\u{1f6}', '\u{195}'),
-        ('\u{1f7}', '\u{1bf}'), ('\u{1f8}', '\u{1f9}'), ('\u{1f9}', '\u{1f8}'),
-        ('\u{1fa}', '\u{1fb}'), ('\u{1fb}', '\u{1fa}'), ('\u{1fc}', '\u{1fd}'),
-        ('\u{1fd}', '\u{1fc}'), ('\u{1fe}', '\u{1ff}'), ('\u{1ff}', '\u{1fe}'),
-        ('\u{200}', '\u{201}'), ('\u{201}', '\u{200}'), ('\u{202}', '\u{203}'),
-        ('\u{203}', '\u{202}'), ('\u{204}', '\u{205}'), ('\u{205}', '\u{204}'),
-        ('\u{206}', '\u{207}'), ('\u{207}', '\u{206}'), ('\u{208}', '\u{209}'),
-        ('\u{209}', '\u{208}'), ('\u{20a}', '\u{20b}'), ('\u{20b}', '\u{20a}'),
-        ('\u{20c}', '\u{20d}'), ('\u{20d}', '\u{20c}'), ('\u{20e}', '\u{20f}'),
-        ('\u{20f}', '\u{20e}'), ('\u{210}', '\u{211}'), ('\u{211}', '\u{210}'),
-        ('\u{212}', '\u{213}'), ('\u{213}', '\u{212}'), ('\u{214}', '\u{215}'),
-        ('\u{215}', '\u{214}'), ('\u{216}', '\u{217}'), ('\u{217}', '\u{216}'),
-        ('\u{218}', '\u{219}'), ('\u{219}', '\u{218}'), ('\u{21a}', '\u{21b}'),
-        ('\u{21b}', '\u{21a}'), ('\u{21c}', '\u{21d}'), ('\u{21d}', '\u{21c}'),
-        ('\u{21e}', '\u{21f}'), ('\u{21f}', '\u{21e}'), ('\u{220}', '\u{19e}'),
-        ('\u{222}', '\u{223}'), ('\u{223}', '\u{222}'), ('\u{224}', '\u{225}'),
-        ('\u{225}', '\u{224}'), ('\u{226}', '\u{227}'), ('\u{227}', '\u{226}'),
-        ('\u{228}', '\u{229}'), ('\u{229}', '\u{228}'), ('\u{22a}', '\u{22b}'),
-        ('\u{22b}', '\u{22a}'), ('\u{22c}', '\u{22d}'), ('\u{22d}', '\u{22c}'),
-        ('\u{22e}', '\u{22f}'), ('\u{22f}', '\u{22e}'), ('\u{230}', '\u{231}'),
-        ('\u{231}', '\u{230}'), ('\u{232}', '\u{233}'), ('\u{233}', '\u{232}'),
-        ('\u{23a}', '\u{2c65}'), ('\u{23b}', '\u{23c}'), ('\u{23c}', '\u{23b}'),
-        ('\u{23d}', '\u{19a}'), ('\u{23e}', '\u{2c66}'), ('\u{23f}',
-        '\u{2c7e}'), ('\u{240}', '\u{2c7f}'), ('\u{241}', '\u{242}'),
-        ('\u{242}', '\u{241}'), ('\u{243}', '\u{180}'), ('\u{244}', '\u{289}'),
-        ('\u{245}', '\u{28c}'), ('\u{246}', '\u{247}'), ('\u{247}', '\u{246}'),
-        ('\u{248}', '\u{249}'), ('\u{249}', '\u{248}'), ('\u{24a}', '\u{24b}'),
-        ('\u{24b}', '\u{24a}'), ('\u{24c}', '\u{24d}'), ('\u{24d}', '\u{24c}'),
-        ('\u{24e}', '\u{24f}'), ('\u{24f}', '\u{24e}'), ('\u{250}', '\u{2c6f}'),
-        ('\u{251}', '\u{2c6d}'), ('\u{252}', '\u{2c70}'), ('\u{253}',
-        '\u{181}'), ('\u{254}', '\u{186}'), ('\u{256}', '\u{189}'), ('\u{257}',
-        '\u{18a}'), ('\u{259}', '\u{18f}'), ('\u{25b}', '\u{190}'), ('\u{25c}',
-        '\u{a7ab}'), ('\u{260}', '\u{193}'), ('\u{261}', '\u{a7ac}'),
-        ('\u{263}', '\u{194}'), ('\u{265}', '\u{a78d}'), ('\u{266}',
-        '\u{a7aa}'), ('\u{268}', '\u{197}'), ('\u{269}', '\u{196}'), ('\u{26b}',
-        '\u{2c62}'), ('\u{26c}', '\u{a7ad}'), ('\u{26f}', '\u{19c}'),
-        ('\u{271}', '\u{2c6e}'), ('\u{272}', '\u{19d}'), ('\u{275}', '\u{19f}'),
-        ('\u{27d}', '\u{2c64}'), ('\u{280}', '\u{1a6}'), ('\u{283}', '\u{1a9}'),
-        ('\u{287}', '\u{a7b1}'), ('\u{288}', '\u{1ae}'), ('\u{289}', '\u{244}'),
-        ('\u{28a}', '\u{1b1}'), ('\u{28b}', '\u{1b2}'), ('\u{28c}', '\u{245}'),
-        ('\u{292}', '\u{1b7}'), ('\u{29d}', '\u{a7b2}'), ('\u{29e}',
-        '\u{a7b0}'), ('\u{345}', '\u{399}'), ('\u{345}', '\u{3b9}'), ('\u{345}',
-        '\u{1fbe}'), ('\u{370}', '\u{371}'), ('\u{371}', '\u{370}'), ('\u{372}',
-        '\u{373}'), ('\u{373}', '\u{372}'), ('\u{376}', '\u{377}'), ('\u{377}',
-        '\u{376}'), ('\u{37b}', '\u{3fd}'), ('\u{37c}', '\u{3fe}'), ('\u{37d}',
-        '\u{3ff}'), ('\u{37f}', '\u{3f3}'), ('\u{386}', '\u{3ac}'), ('\u{388}',
-        '\u{3ad}'), ('\u{389}', '\u{3ae}'), ('\u{38a}', '\u{3af}'), ('\u{38c}',
-        '\u{3cc}'), ('\u{38e}', '\u{3cd}'), ('\u{38f}', '\u{3ce}'), ('\u{391}',
-        '\u{3b1}'), ('\u{392}', '\u{3b2}'), ('\u{392}', '\u{3d0}'), ('\u{393}',
-        '\u{3b3}'), ('\u{394}', '\u{3b4}'), ('\u{395}', '\u{3b5}'), ('\u{395}',
-        '\u{3f5}'), ('\u{396}', '\u{3b6}'), ('\u{397}', '\u{3b7}'), ('\u{398}',
-        '\u{3b8}'), ('\u{398}', '\u{3d1}'), ('\u{398}', '\u{3f4}'), ('\u{399}',
-        '\u{345}'), ('\u{399}', '\u{3b9}'), ('\u{399}', '\u{1fbe}'), ('\u{39a}',
-        '\u{3ba}'), ('\u{39a}', '\u{3f0}'), ('\u{39b}', '\u{3bb}'), ('\u{39c}',
-        '\u{b5}'), ('\u{39c}', '\u{3bc}'), ('\u{39d}', '\u{3bd}'), ('\u{39e}',
-        '\u{3be}'), ('\u{39f}', '\u{3bf}'), ('\u{3a0}', '\u{3c0}'), ('\u{3a0}',
-        '\u{3d6}'), ('\u{3a1}', '\u{3c1}'), ('\u{3a1}', '\u{3f1}'), ('\u{3a3}',
-        '\u{3c2}'), ('\u{3a3}', '\u{3c3}'), ('\u{3a4}', '\u{3c4}'), ('\u{3a5}',
-        '\u{3c5}'), ('\u{3a6}', '\u{3c6}'), ('\u{3a6}', '\u{3d5}'), ('\u{3a7}',
-        '\u{3c7}'), ('\u{3a8}', '\u{3c8}'), ('\u{3a9}', '\u{3c9}'), ('\u{3a9}',
-        '\u{2126}'), ('\u{3aa}', '\u{3ca}'), ('\u{3ab}', '\u{3cb}'), ('\u{3ac}',
-        '\u{386}'), ('\u{3ad}', '\u{388}'), ('\u{3ae}', '\u{389}'), ('\u{3af}',
-        '\u{38a}'), ('\u{3b1}', '\u{391}'), ('\u{3b2}', '\u{392}'), ('\u{3b2}',
-        '\u{3d0}'), ('\u{3b3}', '\u{393}'), ('\u{3b4}', '\u{394}'), ('\u{3b5}',
-        '\u{395}'), ('\u{3b5}', '\u{3f5}'), ('\u{3b6}', '\u{396}'), ('\u{3b7}',
-        '\u{397}'), ('\u{3b8}', '\u{398}'), ('\u{3b8}', '\u{3d1}'), ('\u{3b8}',
-        '\u{3f4}'), ('\u{3b9}', '\u{345}'), ('\u{3b9}', '\u{399}'), ('\u{3b9}',
-        '\u{1fbe}'), ('\u{3ba}', '\u{39a}'), ('\u{3ba}', '\u{3f0}'), ('\u{3bb}',
-        '\u{39b}'), ('\u{3bc}', '\u{b5}'), ('\u{3bc}', '\u{39c}'), ('\u{3bd}',
-        '\u{39d}'), ('\u{3be}', '\u{39e}'), ('\u{3bf}', '\u{39f}'), ('\u{3c0}',
-        '\u{3a0}'), ('\u{3c0}', '\u{3d6}'), ('\u{3c1}', '\u{3a1}'), ('\u{3c1}',
-        '\u{3f1}'), ('\u{3c2}', '\u{3a3}'), ('\u{3c2}', '\u{3c3}'), ('\u{3c3}',
-        '\u{3a3}'), ('\u{3c3}', '\u{3c2}'), ('\u{3c4}', '\u{3a4}'), ('\u{3c5}',
-        '\u{3a5}'), ('\u{3c6}', '\u{3a6}'), ('\u{3c6}', '\u{3d5}'), ('\u{3c7}',
-        '\u{3a7}'), ('\u{3c8}', '\u{3a8}'), ('\u{3c9}', '\u{3a9}'), ('\u{3c9}',
-        '\u{2126}'), ('\u{3ca}', '\u{3aa}'), ('\u{3cb}', '\u{3ab}'), ('\u{3cc}',
-        '\u{38c}'), ('\u{3cd}', '\u{38e}'), ('\u{3ce}', '\u{38f}'), ('\u{3cf}',
-        '\u{3d7}'), ('\u{3d0}', '\u{392}'), ('\u{3d0}', '\u{3b2}'), ('\u{3d1}',
-        '\u{398}'), ('\u{3d1}', '\u{3b8}'), ('\u{3d1}', '\u{3f4}'), ('\u{3d5}',
-        '\u{3a6}'), ('\u{3d5}', '\u{3c6}'), ('\u{3d6}', '\u{3a0}'), ('\u{3d6}',
-        '\u{3c0}'), ('\u{3d7}', '\u{3cf}'), ('\u{3d8}', '\u{3d9}'), ('\u{3d9}',
-        '\u{3d8}'), ('\u{3da}', '\u{3db}'), ('\u{3db}', '\u{3da}'), ('\u{3dc}',
-        '\u{3dd}'), ('\u{3dd}', '\u{3dc}'), ('\u{3de}', '\u{3df}'), ('\u{3df}',
-        '\u{3de}'), ('\u{3e0}', '\u{3e1}'), ('\u{3e1}', '\u{3e0}'), ('\u{3e2}',
-        '\u{3e3}'), ('\u{3e3}', '\u{3e2}'), ('\u{3e4}', '\u{3e5}'), ('\u{3e5}',
-        '\u{3e4}'), ('\u{3e6}', '\u{3e7}'), ('\u{3e7}', '\u{3e6}'), ('\u{3e8}',
-        '\u{3e9}'), ('\u{3e9}', '\u{3e8}'), ('\u{3ea}', '\u{3eb}'), ('\u{3eb}',
-        '\u{3ea}'), ('\u{3ec}', '\u{3ed}'), ('\u{3ed}', '\u{3ec}'), ('\u{3ee}',
-        '\u{3ef}'), ('\u{3ef}', '\u{3ee}'), ('\u{3f0}', '\u{39a}'), ('\u{3f0}',
-        '\u{3ba}'), ('\u{3f1}', '\u{3a1}'), ('\u{3f1}', '\u{3c1}'), ('\u{3f2}',
-        '\u{3f9}'), ('\u{3f3}', '\u{37f}'), ('\u{3f4}', '\u{398}'), ('\u{3f4}',
-        '\u{3b8}'), ('\u{3f4}', '\u{3d1}'), ('\u{3f5}', '\u{395}'), ('\u{3f5}',
-        '\u{3b5}'), ('\u{3f7}', '\u{3f8}'), ('\u{3f8}', '\u{3f7}'), ('\u{3f9}',
-        '\u{3f2}'), ('\u{3fa}', '\u{3fb}'), ('\u{3fb}', '\u{3fa}'), ('\u{3fd}',
-        '\u{37b}'), ('\u{3fe}', '\u{37c}'), ('\u{3ff}', '\u{37d}'), ('\u{400}',
-        '\u{450}'), ('\u{401}', '\u{451}'), ('\u{402}', '\u{452}'), ('\u{403}',
-        '\u{453}'), ('\u{404}', '\u{454}'), ('\u{405}', '\u{455}'), ('\u{406}',
-        '\u{456}'), ('\u{407}', '\u{457}'), ('\u{408}', '\u{458}'), ('\u{409}',
-        '\u{459}'), ('\u{40a}', '\u{45a}'), ('\u{40b}', '\u{45b}'), ('\u{40c}',
-        '\u{45c}'), ('\u{40d}', '\u{45d}'), ('\u{40e}', '\u{45e}'), ('\u{40f}',
-        '\u{45f}'), ('\u{410}', '\u{430}'), ('\u{411}', '\u{431}'), ('\u{412}',
-        '\u{432}'), ('\u{413}', '\u{433}'), ('\u{414}', '\u{434}'), ('\u{415}',
-        '\u{435}'), ('\u{416}', '\u{436}'), ('\u{417}', '\u{437}'), ('\u{418}',
-        '\u{438}'), ('\u{419}', '\u{439}'), ('\u{41a}', '\u{43a}'), ('\u{41b}',
-        '\u{43b}'), ('\u{41c}', '\u{43c}'), ('\u{41d}', '\u{43d}'), ('\u{41e}',
-        '\u{43e}'), ('\u{41f}', '\u{43f}'), ('\u{420}', '\u{440}'), ('\u{421}',
-        '\u{441}'), ('\u{422}', '\u{442}'), ('\u{423}', '\u{443}'), ('\u{424}',
-        '\u{444}'), ('\u{425}', '\u{445}'), ('\u{426}', '\u{446}'), ('\u{427}',
-        '\u{447}'), ('\u{428}', '\u{448}'), ('\u{429}', '\u{449}'), ('\u{42a}',
-        '\u{44a}'), ('\u{42b}', '\u{44b}'), ('\u{42c}', '\u{44c}'), ('\u{42d}',
-        '\u{44d}'), ('\u{42e}', '\u{44e}'), ('\u{42f}', '\u{44f}'), ('\u{430}',
-        '\u{410}'), ('\u{431}', '\u{411}'), ('\u{432}', '\u{412}'), ('\u{433}',
-        '\u{413}'), ('\u{434}', '\u{414}'), ('\u{435}', '\u{415}'), ('\u{436}',
-        '\u{416}'), ('\u{437}', '\u{417}'), ('\u{438}', '\u{418}'), ('\u{439}',
-        '\u{419}'), ('\u{43a}', '\u{41a}'), ('\u{43b}', '\u{41b}'), ('\u{43c}',
-        '\u{41c}'), ('\u{43d}', '\u{41d}'), ('\u{43e}', '\u{41e}'), ('\u{43f}',
-        '\u{41f}'), ('\u{440}', '\u{420}'), ('\u{441}', '\u{421}'), ('\u{442}',
-        '\u{422}'), ('\u{443}', '\u{423}'), ('\u{444}', '\u{424}'), ('\u{445}',
-        '\u{425}'), ('\u{446}', '\u{426}'), ('\u{447}', '\u{427}'), ('\u{448}',
-        '\u{428}'), ('\u{449}', '\u{429}'), ('\u{44a}', '\u{42a}'), ('\u{44b}',
-        '\u{42b}'), ('\u{44c}', '\u{42c}'), ('\u{44d}', '\u{42d}'), ('\u{44e}',
-        '\u{42e}'), ('\u{44f}', '\u{42f}'), ('\u{450}', '\u{400}'), ('\u{451}',
-        '\u{401}'), ('\u{452}', '\u{402}'), ('\u{453}', '\u{403}'), ('\u{454}',
-        '\u{404}'), ('\u{455}', '\u{405}'), ('\u{456}', '\u{406}'), ('\u{457}',
-        '\u{407}'), ('\u{458}', '\u{408}'), ('\u{459}', '\u{409}'), ('\u{45a}',
-        '\u{40a}'), ('\u{45b}', '\u{40b}'), ('\u{45c}', '\u{40c}'), ('\u{45d}',
-        '\u{40d}'), ('\u{45e}', '\u{40e}'), ('\u{45f}', '\u{40f}'), ('\u{460}',
-        '\u{461}'), ('\u{461}', '\u{460}'), ('\u{462}', '\u{463}'), ('\u{463}',
-        '\u{462}'), ('\u{464}', '\u{465}'), ('\u{465}', '\u{464}'), ('\u{466}',
-        '\u{467}'), ('\u{467}', '\u{466}'), ('\u{468}', '\u{469}'), ('\u{469}',
-        '\u{468}'), ('\u{46a}', '\u{46b}'), ('\u{46b}', '\u{46a}'), ('\u{46c}',
-        '\u{46d}'), ('\u{46d}', '\u{46c}'), ('\u{46e}', '\u{46f}'), ('\u{46f}',
-        '\u{46e}'), ('\u{470}', '\u{471}'), ('\u{471}', '\u{470}'), ('\u{472}',
-        '\u{473}'), ('\u{473}', '\u{472}'), ('\u{474}', '\u{475}'), ('\u{475}',
-        '\u{474}'), ('\u{476}', '\u{477}'), ('\u{477}', '\u{476}'), ('\u{478}',
-        '\u{479}'), ('\u{479}', '\u{478}'), ('\u{47a}', '\u{47b}'), ('\u{47b}',
-        '\u{47a}'), ('\u{47c}', '\u{47d}'), ('\u{47d}', '\u{47c}'), ('\u{47e}',
-        '\u{47f}'), ('\u{47f}', '\u{47e}'), ('\u{480}', '\u{481}'), ('\u{481}',
-        '\u{480}'), ('\u{48a}', '\u{48b}'), ('\u{48b}', '\u{48a}'), ('\u{48c}',
-        '\u{48d}'), ('\u{48d}', '\u{48c}'), ('\u{48e}', '\u{48f}'), ('\u{48f}',
-        '\u{48e}'), ('\u{490}', '\u{491}'), ('\u{491}', '\u{490}'), ('\u{492}',
-        '\u{493}'), ('\u{493}', '\u{492}'), ('\u{494}', '\u{495}'), ('\u{495}',
-        '\u{494}'), ('\u{496}', '\u{497}'), ('\u{497}', '\u{496}'), ('\u{498}',
-        '\u{499}'), ('\u{499}', '\u{498}'), ('\u{49a}', '\u{49b}'), ('\u{49b}',
-        '\u{49a}'), ('\u{49c}', '\u{49d}'), ('\u{49d}', '\u{49c}'), ('\u{49e}',
-        '\u{49f}'), ('\u{49f}', '\u{49e}'), ('\u{4a0}', '\u{4a1}'), ('\u{4a1}',
-        '\u{4a0}'), ('\u{4a2}', '\u{4a3}'), ('\u{4a3}', '\u{4a2}'), ('\u{4a4}',
-        '\u{4a5}'), ('\u{4a5}', '\u{4a4}'), ('\u{4a6}', '\u{4a7}'), ('\u{4a7}',
-        '\u{4a6}'), ('\u{4a8}', '\u{4a9}'), ('\u{4a9}', '\u{4a8}'), ('\u{4aa}',
-        '\u{4ab}'), ('\u{4ab}', '\u{4aa}'), ('\u{4ac}', '\u{4ad}'), ('\u{4ad}',
-        '\u{4ac}'), ('\u{4ae}', '\u{4af}'), ('\u{4af}', '\u{4ae}'), ('\u{4b0}',
-        '\u{4b1}'), ('\u{4b1}', '\u{4b0}'), ('\u{4b2}', '\u{4b3}'), ('\u{4b3}',
-        '\u{4b2}'), ('\u{4b4}', '\u{4b5}'), ('\u{4b5}', '\u{4b4}'), ('\u{4b6}',
-        '\u{4b7}'), ('\u{4b7}', '\u{4b6}'), ('\u{4b8}', '\u{4b9}'), ('\u{4b9}',
-        '\u{4b8}'), ('\u{4ba}', '\u{4bb}'), ('\u{4bb}', '\u{4ba}'), ('\u{4bc}',
-        '\u{4bd}'), ('\u{4bd}', '\u{4bc}'), ('\u{4be}', '\u{4bf}'), ('\u{4bf}',
-        '\u{4be}'), ('\u{4c0}', '\u{4cf}'), ('\u{4c1}', '\u{4c2}'), ('\u{4c2}',
-        '\u{4c1}'), ('\u{4c3}', '\u{4c4}'), ('\u{4c4}', '\u{4c3}'), ('\u{4c5}',
-        '\u{4c6}'), ('\u{4c6}', '\u{4c5}'), ('\u{4c7}', '\u{4c8}'), ('\u{4c8}',
-        '\u{4c7}'), ('\u{4c9}', '\u{4ca}'), ('\u{4ca}', '\u{4c9}'), ('\u{4cb}',
-        '\u{4cc}'), ('\u{4cc}', '\u{4cb}'), ('\u{4cd}', '\u{4ce}'), ('\u{4ce}',
-        '\u{4cd}'), ('\u{4cf}', '\u{4c0}'), ('\u{4d0}', '\u{4d1}'), ('\u{4d1}',
-        '\u{4d0}'), ('\u{4d2}', '\u{4d3}'), ('\u{4d3}', '\u{4d2}'), ('\u{4d4}',
-        '\u{4d5}'), ('\u{4d5}', '\u{4d4}'), ('\u{4d6}', '\u{4d7}'), ('\u{4d7}',
-        '\u{4d6}'), ('\u{4d8}', '\u{4d9}'), ('\u{4d9}', '\u{4d8}'), ('\u{4da}',
-        '\u{4db}'), ('\u{4db}', '\u{4da}'), ('\u{4dc}', '\u{4dd}'), ('\u{4dd}',
-        '\u{4dc}'), ('\u{4de}', '\u{4df}'), ('\u{4df}', '\u{4de}'), ('\u{4e0}',
-        '\u{4e1}'), ('\u{4e1}', '\u{4e0}'), ('\u{4e2}', '\u{4e3}'), ('\u{4e3}',
-        '\u{4e2}'), ('\u{4e4}', '\u{4e5}'), ('\u{4e5}', '\u{4e4}'), ('\u{4e6}',
-        '\u{4e7}'), ('\u{4e7}', '\u{4e6}'), ('\u{4e8}', '\u{4e9}'), ('\u{4e9}',
-        '\u{4e8}'), ('\u{4ea}', '\u{4eb}'), ('\u{4eb}', '\u{4ea}'), ('\u{4ec}',
-        '\u{4ed}'), ('\u{4ed}', '\u{4ec}'), ('\u{4ee}', '\u{4ef}'), ('\u{4ef}',
-        '\u{4ee}'), ('\u{4f0}', '\u{4f1}'), ('\u{4f1}', '\u{4f0}'), ('\u{4f2}',
-        '\u{4f3}'), ('\u{4f3}', '\u{4f2}'), ('\u{4f4}', '\u{4f5}'), ('\u{4f5}',
-        '\u{4f4}'), ('\u{4f6}', '\u{4f7}'), ('\u{4f7}', '\u{4f6}'), ('\u{4f8}',
-        '\u{4f9}'), ('\u{4f9}', '\u{4f8}'), ('\u{4fa}', '\u{4fb}'), ('\u{4fb}',
-        '\u{4fa}'), ('\u{4fc}', '\u{4fd}'), ('\u{4fd}', '\u{4fc}'), ('\u{4fe}',
-        '\u{4ff}'), ('\u{4ff}', '\u{4fe}'), ('\u{500}', '\u{501}'), ('\u{501}',
-        '\u{500}'), ('\u{502}', '\u{503}'), ('\u{503}', '\u{502}'), ('\u{504}',
-        '\u{505}'), ('\u{505}', '\u{504}'), ('\u{506}', '\u{507}'), ('\u{507}',
-        '\u{506}'), ('\u{508}', '\u{509}'), ('\u{509}', '\u{508}'), ('\u{50a}',
-        '\u{50b}'), ('\u{50b}', '\u{50a}'), ('\u{50c}', '\u{50d}'), ('\u{50d}',
-        '\u{50c}'), ('\u{50e}', '\u{50f}'), ('\u{50f}', '\u{50e}'), ('\u{510}',
-        '\u{511}'), ('\u{511}', '\u{510}'), ('\u{512}', '\u{513}'), ('\u{513}',
-        '\u{512}'), ('\u{514}', '\u{515}'), ('\u{515}', '\u{514}'), ('\u{516}',
-        '\u{517}'), ('\u{517}', '\u{516}'), ('\u{518}', '\u{519}'), ('\u{519}',
-        '\u{518}'), ('\u{51a}', '\u{51b}'), ('\u{51b}', '\u{51a}'), ('\u{51c}',
-        '\u{51d}'), ('\u{51d}', '\u{51c}'), ('\u{51e}', '\u{51f}'), ('\u{51f}',
-        '\u{51e}'), ('\u{520}', '\u{521}'), ('\u{521}', '\u{520}'), ('\u{522}',
-        '\u{523}'), ('\u{523}', '\u{522}'), ('\u{524}', '\u{525}'), ('\u{525}',
-        '\u{524}'), ('\u{526}', '\u{527}'), ('\u{527}', '\u{526}'), ('\u{528}',
-        '\u{529}'), ('\u{529}', '\u{528}'), ('\u{52a}', '\u{52b}'), ('\u{52b}',
-        '\u{52a}'), ('\u{52c}', '\u{52d}'), ('\u{52d}', '\u{52c}'), ('\u{52e}',
-        '\u{52f}'), ('\u{52f}', '\u{52e}'), ('\u{531}', '\u{561}'), ('\u{532}',
-        '\u{562}'), ('\u{533}', '\u{563}'), ('\u{534}', '\u{564}'), ('\u{535}',
-        '\u{565}'), ('\u{536}', '\u{566}'), ('\u{537}', '\u{567}'), ('\u{538}',
-        '\u{568}'), ('\u{539}', '\u{569}'), ('\u{53a}', '\u{56a}'), ('\u{53b}',
-        '\u{56b}'), ('\u{53c}', '\u{56c}'), ('\u{53d}', '\u{56d}'), ('\u{53e}',
-        '\u{56e}'), ('\u{53f}', '\u{56f}'), ('\u{540}', '\u{570}'), ('\u{541}',
-        '\u{571}'), ('\u{542}', '\u{572}'), ('\u{543}', '\u{573}'), ('\u{544}',
-        '\u{574}'), ('\u{545}', '\u{575}'), ('\u{546}', '\u{576}'), ('\u{547}',
-        '\u{577}'), ('\u{548}', '\u{578}'), ('\u{549}', '\u{579}'), ('\u{54a}',
-        '\u{57a}'), ('\u{54b}', '\u{57b}'), ('\u{54c}', '\u{57c}'), ('\u{54d}',
-        '\u{57d}'), ('\u{54e}', '\u{57e}'), ('\u{54f}', '\u{57f}'), ('\u{550}',
-        '\u{580}'), ('\u{551}', '\u{581}'), ('\u{552}', '\u{582}'), ('\u{553}',
-        '\u{583}'), ('\u{554}', '\u{584}'), ('\u{555}', '\u{585}'), ('\u{556}',
-        '\u{586}'), ('\u{561}', '\u{531}'), ('\u{562}', '\u{532}'), ('\u{563}',
-        '\u{533}'), ('\u{564}', '\u{534}'), ('\u{565}', '\u{535}'), ('\u{566}',
-        '\u{536}'), ('\u{567}', '\u{537}'), ('\u{568}', '\u{538}'), ('\u{569}',
-        '\u{539}'), ('\u{56a}', '\u{53a}'), ('\u{56b}', '\u{53b}'), ('\u{56c}',
-        '\u{53c}'), ('\u{56d}', '\u{53d}'), ('\u{56e}', '\u{53e}'), ('\u{56f}',
-        '\u{53f}'), ('\u{570}', '\u{540}'), ('\u{571}', '\u{541}'), ('\u{572}',
-        '\u{542}'), ('\u{573}', '\u{543}'), ('\u{574}', '\u{544}'), ('\u{575}',
-        '\u{545}'), ('\u{576}', '\u{546}'), ('\u{577}', '\u{547}'), ('\u{578}',
-        '\u{548}'), ('\u{579}', '\u{549}'), ('\u{57a}', '\u{54a}'), ('\u{57b}',
-        '\u{54b}'), ('\u{57c}', '\u{54c}'), ('\u{57d}', '\u{54d}'), ('\u{57e}',
-        '\u{54e}'), ('\u{57f}', '\u{54f}'), ('\u{580}', '\u{550}'), ('\u{581}',
-        '\u{551}'), ('\u{582}', '\u{552}'), ('\u{583}', '\u{553}'), ('\u{584}',
-        '\u{554}'), ('\u{585}', '\u{555}'), ('\u{586}', '\u{556}'), ('\u{10a0}',
-        '\u{2d00}'), ('\u{10a1}', '\u{2d01}'), ('\u{10a2}', '\u{2d02}'),
-        ('\u{10a3}', '\u{2d03}'), ('\u{10a4}', '\u{2d04}'), ('\u{10a5}',
-        '\u{2d05}'), ('\u{10a6}', '\u{2d06}'), ('\u{10a7}', '\u{2d07}'),
-        ('\u{10a8}', '\u{2d08}'), ('\u{10a9}', '\u{2d09}'), ('\u{10aa}',
-        '\u{2d0a}'), ('\u{10ab}', '\u{2d0b}'), ('\u{10ac}', '\u{2d0c}'),
-        ('\u{10ad}', '\u{2d0d}'), ('\u{10ae}', '\u{2d0e}'), ('\u{10af}',
-        '\u{2d0f}'), ('\u{10b0}', '\u{2d10}'), ('\u{10b1}', '\u{2d11}'),
-        ('\u{10b2}', '\u{2d12}'), ('\u{10b3}', '\u{2d13}'), ('\u{10b4}',
-        '\u{2d14}'), ('\u{10b5}', '\u{2d15}'), ('\u{10b6}', '\u{2d16}'),
-        ('\u{10b7}', '\u{2d17}'), ('\u{10b8}', '\u{2d18}'), ('\u{10b9}',
-        '\u{2d19}'), ('\u{10ba}', '\u{2d1a}'), ('\u{10bb}', '\u{2d1b}'),
-        ('\u{10bc}', '\u{2d1c}'), ('\u{10bd}', '\u{2d1d}'), ('\u{10be}',
-        '\u{2d1e}'), ('\u{10bf}', '\u{2d1f}'), ('\u{10c0}', '\u{2d20}'),
-        ('\u{10c1}', '\u{2d21}'), ('\u{10c2}', '\u{2d22}'), ('\u{10c3}',
-        '\u{2d23}'), ('\u{10c4}', '\u{2d24}'), ('\u{10c5}', '\u{2d25}'),
-        ('\u{10c7}', '\u{2d27}'), ('\u{10cd}', '\u{2d2d}'), ('\u{13a0}',
-        '\u{ab70}'), ('\u{13a1}', '\u{ab71}'), ('\u{13a2}', '\u{ab72}'),
-        ('\u{13a3}', '\u{ab73}'), ('\u{13a4}', '\u{ab74}'), ('\u{13a5}',
-        '\u{ab75}'), ('\u{13a6}', '\u{ab76}'), ('\u{13a7}', '\u{ab77}'),
-        ('\u{13a8}', '\u{ab78}'), ('\u{13a9}', '\u{ab79}'), ('\u{13aa}',
-        '\u{ab7a}'), ('\u{13ab}', '\u{ab7b}'), ('\u{13ac}', '\u{ab7c}'),
-        ('\u{13ad}', '\u{ab7d}'), ('\u{13ae}', '\u{ab7e}'), ('\u{13af}',
-        '\u{ab7f}'), ('\u{13b0}', '\u{ab80}'), ('\u{13b1}', '\u{ab81}'),
-        ('\u{13b2}', '\u{ab82}'), ('\u{13b3}', '\u{ab83}'), ('\u{13b4}',
-        '\u{ab84}'), ('\u{13b5}', '\u{ab85}'), ('\u{13b6}', '\u{ab86}'),
-        ('\u{13b7}', '\u{ab87}'), ('\u{13b8}', '\u{ab88}'), ('\u{13b9}',
-        '\u{ab89}'), ('\u{13ba}', '\u{ab8a}'), ('\u{13bb}', '\u{ab8b}'),
-        ('\u{13bc}', '\u{ab8c}'), ('\u{13bd}', '\u{ab8d}'), ('\u{13be}',
-        '\u{ab8e}'), ('\u{13bf}', '\u{ab8f}'), ('\u{13c0}', '\u{ab90}'),
-        ('\u{13c1}', '\u{ab91}'), ('\u{13c2}', '\u{ab92}'), ('\u{13c3}',
-        '\u{ab93}'), ('\u{13c4}', '\u{ab94}'), ('\u{13c5}', '\u{ab95}'),
-        ('\u{13c6}', '\u{ab96}'), ('\u{13c7}', '\u{ab97}'), ('\u{13c8}',
-        '\u{ab98}'), ('\u{13c9}', '\u{ab99}'), ('\u{13ca}', '\u{ab9a}'),
-        ('\u{13cb}', '\u{ab9b}'), ('\u{13cc}', '\u{ab9c}'), ('\u{13cd}',
-        '\u{ab9d}'), ('\u{13ce}', '\u{ab9e}'), ('\u{13cf}', '\u{ab9f}'),
-        ('\u{13d0}', '\u{aba0}'), ('\u{13d1}', '\u{aba1}'), ('\u{13d2}',
-        '\u{aba2}'), ('\u{13d3}', '\u{aba3}'), ('\u{13d4}', '\u{aba4}'),
-        ('\u{13d5}', '\u{aba5}'), ('\u{13d6}', '\u{aba6}'), ('\u{13d7}',
-        '\u{aba7}'), ('\u{13d8}', '\u{aba8}'), ('\u{13d9}', '\u{aba9}'),
-        ('\u{13da}', '\u{abaa}'), ('\u{13db}', '\u{abab}'), ('\u{13dc}',
-        '\u{abac}'), ('\u{13dd}', '\u{abad}'), ('\u{13de}', '\u{abae}'),
-        ('\u{13df}', '\u{abaf}'), ('\u{13e0}', '\u{abb0}'), ('\u{13e1}',
-        '\u{abb1}'), ('\u{13e2}', '\u{abb2}'), ('\u{13e3}', '\u{abb3}'),
-        ('\u{13e4}', '\u{abb4}'), ('\u{13e5}', '\u{abb5}'), ('\u{13e6}',
-        '\u{abb6}'), ('\u{13e7}', '\u{abb7}'), ('\u{13e8}', '\u{abb8}'),
-        ('\u{13e9}', '\u{abb9}'), ('\u{13ea}', '\u{abba}'), ('\u{13eb}',
-        '\u{abbb}'), ('\u{13ec}', '\u{abbc}'), ('\u{13ed}', '\u{abbd}'),
-        ('\u{13ee}', '\u{abbe}'), ('\u{13ef}', '\u{abbf}'), ('\u{13f0}',
-        '\u{13f8}'), ('\u{13f1}', '\u{13f9}'), ('\u{13f2}', '\u{13fa}'),
-        ('\u{13f3}', '\u{13fb}'), ('\u{13f4}', '\u{13fc}'), ('\u{13f5}',
-        '\u{13fd}'), ('\u{13f8}', '\u{13f0}'), ('\u{13f9}', '\u{13f1}'),
-        ('\u{13fa}', '\u{13f2}'), ('\u{13fb}', '\u{13f3}'), ('\u{13fc}',
-        '\u{13f4}'), ('\u{13fd}', '\u{13f5}'), ('\u{1d79}', '\u{a77d}'),
-        ('\u{1d7d}', '\u{2c63}'), ('\u{1e00}', '\u{1e01}'), ('\u{1e01}',
-        '\u{1e00}'), ('\u{1e02}', '\u{1e03}'), ('\u{1e03}', '\u{1e02}'),
-        ('\u{1e04}', '\u{1e05}'), ('\u{1e05}', '\u{1e04}'), ('\u{1e06}',
-        '\u{1e07}'), ('\u{1e07}', '\u{1e06}'), ('\u{1e08}', '\u{1e09}'),
-        ('\u{1e09}', '\u{1e08}'), ('\u{1e0a}', '\u{1e0b}'), ('\u{1e0b}',
-        '\u{1e0a}'), ('\u{1e0c}', '\u{1e0d}'), ('\u{1e0d}', '\u{1e0c}'),
-        ('\u{1e0e}', '\u{1e0f}'), ('\u{1e0f}', '\u{1e0e}'), ('\u{1e10}',
-        '\u{1e11}'), ('\u{1e11}', '\u{1e10}'), ('\u{1e12}', '\u{1e13}'),
-        ('\u{1e13}', '\u{1e12}'), ('\u{1e14}', '\u{1e15}'), ('\u{1e15}',
-        '\u{1e14}'), ('\u{1e16}', '\u{1e17}'), ('\u{1e17}', '\u{1e16}'),
-        ('\u{1e18}', '\u{1e19}'), ('\u{1e19}', '\u{1e18}'), ('\u{1e1a}',
-        '\u{1e1b}'), ('\u{1e1b}', '\u{1e1a}'), ('\u{1e1c}', '\u{1e1d}'),
-        ('\u{1e1d}', '\u{1e1c}'), ('\u{1e1e}', '\u{1e1f}'), ('\u{1e1f}',
-        '\u{1e1e}'), ('\u{1e20}', '\u{1e21}'), ('\u{1e21}', '\u{1e20}'),
-        ('\u{1e22}', '\u{1e23}'), ('\u{1e23}', '\u{1e22}'), ('\u{1e24}',
-        '\u{1e25}'), ('\u{1e25}', '\u{1e24}'), ('\u{1e26}', '\u{1e27}'),
-        ('\u{1e27}', '\u{1e26}'), ('\u{1e28}', '\u{1e29}'), ('\u{1e29}',
-        '\u{1e28}'), ('\u{1e2a}', '\u{1e2b}'), ('\u{1e2b}', '\u{1e2a}'),
-        ('\u{1e2c}', '\u{1e2d}'), ('\u{1e2d}', '\u{1e2c}'), ('\u{1e2e}',
-        '\u{1e2f}'), ('\u{1e2f}', '\u{1e2e}'), ('\u{1e30}', '\u{1e31}'),
-        ('\u{1e31}', '\u{1e30}'), ('\u{1e32}', '\u{1e33}'), ('\u{1e33}',
-        '\u{1e32}'), ('\u{1e34}', '\u{1e35}'), ('\u{1e35}', '\u{1e34}'),
-        ('\u{1e36}', '\u{1e37}'), ('\u{1e37}', '\u{1e36}'), ('\u{1e38}',
-        '\u{1e39}'), ('\u{1e39}', '\u{1e38}'), ('\u{1e3a}', '\u{1e3b}'),
-        ('\u{1e3b}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3d}'), ('\u{1e3d}',
-        '\u{1e3c}'), ('\u{1e3e}', '\u{1e3f}'), ('\u{1e3f}', '\u{1e3e}'),
-        ('\u{1e40}', '\u{1e41}'), ('\u{1e41}', '\u{1e40}'), ('\u{1e42}',
-        '\u{1e43}'), ('\u{1e43}', '\u{1e42}'), ('\u{1e44}', '\u{1e45}'),
-        ('\u{1e45}', '\u{1e44}'), ('\u{1e46}', '\u{1e47}'), ('\u{1e47}',
-        '\u{1e46}'), ('\u{1e48}', '\u{1e49}'), ('\u{1e49}', '\u{1e48}'),
-        ('\u{1e4a}', '\u{1e4b}'), ('\u{1e4b}', '\u{1e4a}'), ('\u{1e4c}',
-        '\u{1e4d}'), ('\u{1e4d}', '\u{1e4c}'), ('\u{1e4e}', '\u{1e4f}'),
-        ('\u{1e4f}', '\u{1e4e}'), ('\u{1e50}', '\u{1e51}'), ('\u{1e51}',
-        '\u{1e50}'), ('\u{1e52}', '\u{1e53}'), ('\u{1e53}', '\u{1e52}'),
-        ('\u{1e54}', '\u{1e55}'), ('\u{1e55}', '\u{1e54}'), ('\u{1e56}',
-        '\u{1e57}'), ('\u{1e57}', '\u{1e56}'), ('\u{1e58}', '\u{1e59}'),
-        ('\u{1e59}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5b}'), ('\u{1e5b}',
-        '\u{1e5a}'), ('\u{1e5c}', '\u{1e5d}'), ('\u{1e5d}', '\u{1e5c}'),
-        ('\u{1e5e}', '\u{1e5f}'), ('\u{1e5f}', '\u{1e5e}'), ('\u{1e60}',
-        '\u{1e61}'), ('\u{1e60}', '\u{1e9b}'), ('\u{1e61}', '\u{1e60}'),
-        ('\u{1e61}', '\u{1e9b}'), ('\u{1e62}', '\u{1e63}'), ('\u{1e63}',
-        '\u{1e62}'), ('\u{1e64}', '\u{1e65}'), ('\u{1e65}', '\u{1e64}'),
-        ('\u{1e66}', '\u{1e67}'), ('\u{1e67}', '\u{1e66}'), ('\u{1e68}',
-        '\u{1e69}'), ('\u{1e69}', '\u{1e68}'), ('\u{1e6a}', '\u{1e6b}'),
-        ('\u{1e6b}', '\u{1e6a}'), ('\u{1e6c}', '\u{1e6d}'), ('\u{1e6d}',
-        '\u{1e6c}'), ('\u{1e6e}', '\u{1e6f}'), ('\u{1e6f}', '\u{1e6e}'),
-        ('\u{1e70}', '\u{1e71}'), ('\u{1e71}', '\u{1e70}'), ('\u{1e72}',
-        '\u{1e73}'), ('\u{1e73}', '\u{1e72}'), ('\u{1e74}', '\u{1e75}'),
-        ('\u{1e75}', '\u{1e74}'), ('\u{1e76}', '\u{1e77}'), ('\u{1e77}',
-        '\u{1e76}'), ('\u{1e78}', '\u{1e79}'), ('\u{1e79}', '\u{1e78}'),
-        ('\u{1e7a}', '\u{1e7b}'), ('\u{1e7b}', '\u{1e7a}'), ('\u{1e7c}',
-        '\u{1e7d}'), ('\u{1e7d}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7f}'),
-        ('\u{1e7f}', '\u{1e7e}'), ('\u{1e80}', '\u{1e81}'), ('\u{1e81}',
-        '\u{1e80}'), ('\u{1e82}', '\u{1e83}'), ('\u{1e83}', '\u{1e82}'),
-        ('\u{1e84}', '\u{1e85}'), ('\u{1e85}', '\u{1e84}'), ('\u{1e86}',
-        '\u{1e87}'), ('\u{1e87}', '\u{1e86}'), ('\u{1e88}', '\u{1e89}'),
-        ('\u{1e89}', '\u{1e88}'), ('\u{1e8a}', '\u{1e8b}'), ('\u{1e8b}',
-        '\u{1e8a}'), ('\u{1e8c}', '\u{1e8d}'), ('\u{1e8d}', '\u{1e8c}'),
-        ('\u{1e8e}', '\u{1e8f}'), ('\u{1e8f}', '\u{1e8e}'), ('\u{1e90}',
-        '\u{1e91}'), ('\u{1e91}', '\u{1e90}'), ('\u{1e92}', '\u{1e93}'),
-        ('\u{1e93}', '\u{1e92}'), ('\u{1e94}', '\u{1e95}'), ('\u{1e95}',
-        '\u{1e94}'), ('\u{1e9b}', '\u{1e60}'), ('\u{1e9b}', '\u{1e61}'),
-        ('\u{1e9e}', '\u{df}'), ('\u{1ea0}', '\u{1ea1}'), ('\u{1ea1}',
-        '\u{1ea0}'), ('\u{1ea2}', '\u{1ea3}'), ('\u{1ea3}', '\u{1ea2}'),
-        ('\u{1ea4}', '\u{1ea5}'), ('\u{1ea5}', '\u{1ea4}'), ('\u{1ea6}',
-        '\u{1ea7}'), ('\u{1ea7}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea9}'),
-        ('\u{1ea9}', '\u{1ea8}'), ('\u{1eaa}', '\u{1eab}'), ('\u{1eab}',
-        '\u{1eaa}'), ('\u{1eac}', '\u{1ead}'), ('\u{1ead}', '\u{1eac}'),
-        ('\u{1eae}', '\u{1eaf}'), ('\u{1eaf}', '\u{1eae}'), ('\u{1eb0}',
-        '\u{1eb1}'), ('\u{1eb1}', '\u{1eb0}'), ('\u{1eb2}', '\u{1eb3}'),
-        ('\u{1eb3}', '\u{1eb2}'), ('\u{1eb4}', '\u{1eb5}'), ('\u{1eb5}',
-        '\u{1eb4}'), ('\u{1eb6}', '\u{1eb7}'), ('\u{1eb7}', '\u{1eb6}'),
-        ('\u{1eb8}', '\u{1eb9}'), ('\u{1eb9}', '\u{1eb8}'), ('\u{1eba}',
-        '\u{1ebb}'), ('\u{1ebb}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebd}'),
-        ('\u{1ebd}', '\u{1ebc}'), ('\u{1ebe}', '\u{1ebf}'), ('\u{1ebf}',
-        '\u{1ebe}'), ('\u{1ec0}', '\u{1ec1}'), ('\u{1ec1}', '\u{1ec0}'),
-        ('\u{1ec2}', '\u{1ec3}'), ('\u{1ec3}', '\u{1ec2}'), ('\u{1ec4}',
-        '\u{1ec5}'), ('\u{1ec5}', '\u{1ec4}'), ('\u{1ec6}', '\u{1ec7}'),
-        ('\u{1ec7}', '\u{1ec6}'), ('\u{1ec8}', '\u{1ec9}'), ('\u{1ec9}',
-        '\u{1ec8}'), ('\u{1eca}', '\u{1ecb}'), ('\u{1ecb}', '\u{1eca}'),
-        ('\u{1ecc}', '\u{1ecd}'), ('\u{1ecd}', '\u{1ecc}'), ('\u{1ece}',
-        '\u{1ecf}'), ('\u{1ecf}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed1}'),
-        ('\u{1ed1}', '\u{1ed0}'), ('\u{1ed2}', '\u{1ed3}'), ('\u{1ed3}',
-        '\u{1ed2}'), ('\u{1ed4}', '\u{1ed5}'), ('\u{1ed5}', '\u{1ed4}'),
-        ('\u{1ed6}', '\u{1ed7}'), ('\u{1ed7}', '\u{1ed6}'), ('\u{1ed8}',
-        '\u{1ed9}'), ('\u{1ed9}', '\u{1ed8}'), ('\u{1eda}', '\u{1edb}'),
-        ('\u{1edb}', '\u{1eda}'), ('\u{1edc}', '\u{1edd}'), ('\u{1edd}',
-        '\u{1edc}'), ('\u{1ede}', '\u{1edf}'), ('\u{1edf}', '\u{1ede}'),
-        ('\u{1ee0}', '\u{1ee1}'), ('\u{1ee1}', '\u{1ee0}'), ('\u{1ee2}',
-        '\u{1ee3}'), ('\u{1ee3}', '\u{1ee2}'), ('\u{1ee4}', '\u{1ee5}'),
-        ('\u{1ee5}', '\u{1ee4}'), ('\u{1ee6}', '\u{1ee7}'), ('\u{1ee7}',
-        '\u{1ee6}'), ('\u{1ee8}', '\u{1ee9}'), ('\u{1ee9}', '\u{1ee8}'),
-        ('\u{1eea}', '\u{1eeb}'), ('\u{1eeb}', '\u{1eea}'), ('\u{1eec}',
-        '\u{1eed}'), ('\u{1eed}', '\u{1eec}'), ('\u{1eee}', '\u{1eef}'),
-        ('\u{1eef}', '\u{1eee}'), ('\u{1ef0}', '\u{1ef1}'), ('\u{1ef1}',
-        '\u{1ef0}'), ('\u{1ef2}', '\u{1ef3}'), ('\u{1ef3}', '\u{1ef2}'),
-        ('\u{1ef4}', '\u{1ef5}'), ('\u{1ef5}', '\u{1ef4}'), ('\u{1ef6}',
-        '\u{1ef7}'), ('\u{1ef7}', '\u{1ef6}'), ('\u{1ef8}', '\u{1ef9}'),
-        ('\u{1ef9}', '\u{1ef8}'), ('\u{1efa}', '\u{1efb}'), ('\u{1efb}',
-        '\u{1efa}'), ('\u{1efc}', '\u{1efd}'), ('\u{1efd}', '\u{1efc}'),
-        ('\u{1efe}', '\u{1eff}'), ('\u{1eff}', '\u{1efe}'), ('\u{1f00}',
-        '\u{1f08}'), ('\u{1f01}', '\u{1f09}'), ('\u{1f02}', '\u{1f0a}'),
-        ('\u{1f03}', '\u{1f0b}'), ('\u{1f04}', '\u{1f0c}'), ('\u{1f05}',
-        '\u{1f0d}'), ('\u{1f06}', '\u{1f0e}'), ('\u{1f07}', '\u{1f0f}'),
-        ('\u{1f08}', '\u{1f00}'), ('\u{1f09}', '\u{1f01}'), ('\u{1f0a}',
-        '\u{1f02}'), ('\u{1f0b}', '\u{1f03}'), ('\u{1f0c}', '\u{1f04}'),
-        ('\u{1f0d}', '\u{1f05}'), ('\u{1f0e}', '\u{1f06}'), ('\u{1f0f}',
-        '\u{1f07}'), ('\u{1f10}', '\u{1f18}'), ('\u{1f11}', '\u{1f19}'),
-        ('\u{1f12}', '\u{1f1a}'), ('\u{1f13}', '\u{1f1b}'), ('\u{1f14}',
-        '\u{1f1c}'), ('\u{1f15}', '\u{1f1d}'), ('\u{1f18}', '\u{1f10}'),
-        ('\u{1f19}', '\u{1f11}'), ('\u{1f1a}', '\u{1f12}'), ('\u{1f1b}',
-        '\u{1f13}'), ('\u{1f1c}', '\u{1f14}'), ('\u{1f1d}', '\u{1f15}'),
-        ('\u{1f20}', '\u{1f28}'), ('\u{1f21}', '\u{1f29}'), ('\u{1f22}',
-        '\u{1f2a}'), ('\u{1f23}', '\u{1f2b}'), ('\u{1f24}', '\u{1f2c}'),
-        ('\u{1f25}', '\u{1f2d}'), ('\u{1f26}', '\u{1f2e}'), ('\u{1f27}',
-        '\u{1f2f}'), ('\u{1f28}', '\u{1f20}'), ('\u{1f29}', '\u{1f21}'),
-        ('\u{1f2a}', '\u{1f22}'), ('\u{1f2b}', '\u{1f23}'), ('\u{1f2c}',
-        '\u{1f24}'), ('\u{1f2d}', '\u{1f25}'), ('\u{1f2e}', '\u{1f26}'),
-        ('\u{1f2f}', '\u{1f27}'), ('\u{1f30}', '\u{1f38}'), ('\u{1f31}',
-        '\u{1f39}'), ('\u{1f32}', '\u{1f3a}'), ('\u{1f33}', '\u{1f3b}'),
-        ('\u{1f34}', '\u{1f3c}'), ('\u{1f35}', '\u{1f3d}'), ('\u{1f36}',
-        '\u{1f3e}'), ('\u{1f37}', '\u{1f3f}'), ('\u{1f38}', '\u{1f30}'),
-        ('\u{1f39}', '\u{1f31}'), ('\u{1f3a}', '\u{1f32}'), ('\u{1f3b}',
-        '\u{1f33}'), ('\u{1f3c}', '\u{1f34}'), ('\u{1f3d}', '\u{1f35}'),
-        ('\u{1f3e}', '\u{1f36}'), ('\u{1f3f}', '\u{1f37}'), ('\u{1f40}',
-        '\u{1f48}'), ('\u{1f41}', '\u{1f49}'), ('\u{1f42}', '\u{1f4a}'),
-        ('\u{1f43}', '\u{1f4b}'), ('\u{1f44}', '\u{1f4c}'), ('\u{1f45}',
-        '\u{1f4d}'), ('\u{1f48}', '\u{1f40}'), ('\u{1f49}', '\u{1f41}'),
-        ('\u{1f4a}', '\u{1f42}'), ('\u{1f4b}', '\u{1f43}'), ('\u{1f4c}',
-        '\u{1f44}'), ('\u{1f4d}', '\u{1f45}'), ('\u{1f51}', '\u{1f59}'),
-        ('\u{1f53}', '\u{1f5b}'), ('\u{1f55}', '\u{1f5d}'), ('\u{1f57}',
-        '\u{1f5f}'), ('\u{1f59}', '\u{1f51}'), ('\u{1f5b}', '\u{1f53}'),
-        ('\u{1f5d}', '\u{1f55}'), ('\u{1f5f}', '\u{1f57}'), ('\u{1f60}',
-        '\u{1f68}'), ('\u{1f61}', '\u{1f69}'), ('\u{1f62}', '\u{1f6a}'),
-        ('\u{1f63}', '\u{1f6b}'), ('\u{1f64}', '\u{1f6c}'), ('\u{1f65}',
-        '\u{1f6d}'), ('\u{1f66}', '\u{1f6e}'), ('\u{1f67}', '\u{1f6f}'),
-        ('\u{1f68}', '\u{1f60}'), ('\u{1f69}', '\u{1f61}'), ('\u{1f6a}',
-        '\u{1f62}'), ('\u{1f6b}', '\u{1f63}'), ('\u{1f6c}', '\u{1f64}'),
-        ('\u{1f6d}', '\u{1f65}'), ('\u{1f6e}', '\u{1f66}'), ('\u{1f6f}',
-        '\u{1f67}'), ('\u{1f70}', '\u{1fba}'), ('\u{1f71}', '\u{1fbb}'),
-        ('\u{1f72}', '\u{1fc8}'), ('\u{1f73}', '\u{1fc9}'), ('\u{1f74}',
-        '\u{1fca}'), ('\u{1f75}', '\u{1fcb}'), ('\u{1f76}', '\u{1fda}'),
-        ('\u{1f77}', '\u{1fdb}'), ('\u{1f78}', '\u{1ff8}'), ('\u{1f79}',
-        '\u{1ff9}'), ('\u{1f7a}', '\u{1fea}'), ('\u{1f7b}', '\u{1feb}'),
-        ('\u{1f7c}', '\u{1ffa}'), ('\u{1f7d}', '\u{1ffb}'), ('\u{1f80}',
-        '\u{1f88}'), ('\u{1f81}', '\u{1f89}'), ('\u{1f82}', '\u{1f8a}'),
-        ('\u{1f83}', '\u{1f8b}'), ('\u{1f84}', '\u{1f8c}'), ('\u{1f85}',
-        '\u{1f8d}'), ('\u{1f86}', '\u{1f8e}'), ('\u{1f87}', '\u{1f8f}'),
-        ('\u{1f88}', '\u{1f80}'), ('\u{1f89}', '\u{1f81}'), ('\u{1f8a}',
-        '\u{1f82}'), ('\u{1f8b}', '\u{1f83}'), ('\u{1f8c}', '\u{1f84}'),
-        ('\u{1f8d}', '\u{1f85}'), ('\u{1f8e}', '\u{1f86}'), ('\u{1f8f}',
-        '\u{1f87}'), ('\u{1f90}', '\u{1f98}'), ('\u{1f91}', '\u{1f99}'),
-        ('\u{1f92}', '\u{1f9a}'), ('\u{1f93}', '\u{1f9b}'), ('\u{1f94}',
-        '\u{1f9c}'), ('\u{1f95}', '\u{1f9d}'), ('\u{1f96}', '\u{1f9e}'),
-        ('\u{1f97}', '\u{1f9f}'), ('\u{1f98}', '\u{1f90}'), ('\u{1f99}',
-        '\u{1f91}'), ('\u{1f9a}', '\u{1f92}'), ('\u{1f9b}', '\u{1f93}'),
-        ('\u{1f9c}', '\u{1f94}'), ('\u{1f9d}', '\u{1f95}'), ('\u{1f9e}',
-        '\u{1f96}'), ('\u{1f9f}', '\u{1f97}'), ('\u{1fa0}', '\u{1fa8}'),
-        ('\u{1fa1}', '\u{1fa9}'), ('\u{1fa2}', '\u{1faa}'), ('\u{1fa3}',
-        '\u{1fab}'), ('\u{1fa4}', '\u{1fac}'), ('\u{1fa5}', '\u{1fad}'),
-        ('\u{1fa6}', '\u{1fae}'), ('\u{1fa7}', '\u{1faf}'), ('\u{1fa8}',
-        '\u{1fa0}'), ('\u{1fa9}', '\u{1fa1}'), ('\u{1faa}', '\u{1fa2}'),
-        ('\u{1fab}', '\u{1fa3}'), ('\u{1fac}', '\u{1fa4}'), ('\u{1fad}',
-        '\u{1fa5}'), ('\u{1fae}', '\u{1fa6}'), ('\u{1faf}', '\u{1fa7}'),
-        ('\u{1fb0}', '\u{1fb8}'), ('\u{1fb1}', '\u{1fb9}'), ('\u{1fb3}',
-        '\u{1fbc}'), ('\u{1fb8}', '\u{1fb0}'), ('\u{1fb9}', '\u{1fb1}'),
-        ('\u{1fba}', '\u{1f70}'), ('\u{1fbb}', '\u{1f71}'), ('\u{1fbc}',
-        '\u{1fb3}'), ('\u{1fbe}', '\u{345}'), ('\u{1fbe}', '\u{399}'),
-        ('\u{1fbe}', '\u{3b9}'), ('\u{1fc3}', '\u{1fcc}'), ('\u{1fc8}',
-        '\u{1f72}'), ('\u{1fc9}', '\u{1f73}'), ('\u{1fca}', '\u{1f74}'),
-        ('\u{1fcb}', '\u{1f75}'), ('\u{1fcc}', '\u{1fc3}'), ('\u{1fd0}',
-        '\u{1fd8}'), ('\u{1fd1}', '\u{1fd9}'), ('\u{1fd8}', '\u{1fd0}'),
-        ('\u{1fd9}', '\u{1fd1}'), ('\u{1fda}', '\u{1f76}'), ('\u{1fdb}',
-        '\u{1f77}'), ('\u{1fe0}', '\u{1fe8}'), ('\u{1fe1}', '\u{1fe9}'),
-        ('\u{1fe5}', '\u{1fec}'), ('\u{1fe8}', '\u{1fe0}'), ('\u{1fe9}',
-        '\u{1fe1}'), ('\u{1fea}', '\u{1f7a}'), ('\u{1feb}', '\u{1f7b}'),
-        ('\u{1fec}', '\u{1fe5}'), ('\u{1ff3}', '\u{1ffc}'), ('\u{1ff8}',
-        '\u{1f78}'), ('\u{1ff9}', '\u{1f79}'), ('\u{1ffa}', '\u{1f7c}'),
-        ('\u{1ffb}', '\u{1f7d}'), ('\u{1ffc}', '\u{1ff3}'), ('\u{2126}',
-        '\u{3a9}'), ('\u{2126}', '\u{3c9}'), ('\u{212a}', '\u{4b}'),
-        ('\u{212a}', '\u{6b}'), ('\u{212b}', '\u{c5}'), ('\u{212b}', '\u{e5}'),
-        ('\u{2132}', '\u{214e}'), ('\u{214e}', '\u{2132}'), ('\u{2160}',
-        '\u{2170}'), ('\u{2161}', '\u{2171}'), ('\u{2162}', '\u{2172}'),
-        ('\u{2163}', '\u{2173}'), ('\u{2164}', '\u{2174}'), ('\u{2165}',
-        '\u{2175}'), ('\u{2166}', '\u{2176}'), ('\u{2167}', '\u{2177}'),
-        ('\u{2168}', '\u{2178}'), ('\u{2169}', '\u{2179}'), ('\u{216a}',
-        '\u{217a}'), ('\u{216b}', '\u{217b}'), ('\u{216c}', '\u{217c}'),
-        ('\u{216d}', '\u{217d}'), ('\u{216e}', '\u{217e}'), ('\u{216f}',
-        '\u{217f}'), ('\u{2170}', '\u{2160}'), ('\u{2171}', '\u{2161}'),
-        ('\u{2172}', '\u{2162}'), ('\u{2173}', '\u{2163}'), ('\u{2174}',
-        '\u{2164}'), ('\u{2175}', '\u{2165}'), ('\u{2176}', '\u{2166}'),
-        ('\u{2177}', '\u{2167}'), ('\u{2178}', '\u{2168}'), ('\u{2179}',
-        '\u{2169}'), ('\u{217a}', '\u{216a}'), ('\u{217b}', '\u{216b}'),
-        ('\u{217c}', '\u{216c}'), ('\u{217d}', '\u{216d}'), ('\u{217e}',
-        '\u{216e}'), ('\u{217f}', '\u{216f}'), ('\u{2183}', '\u{2184}'),
-        ('\u{2184}', '\u{2183}'), ('\u{24b6}', '\u{24d0}'), ('\u{24b7}',
-        '\u{24d1}'), ('\u{24b8}', '\u{24d2}'), ('\u{24b9}', '\u{24d3}'),
-        ('\u{24ba}', '\u{24d4}'), ('\u{24bb}', '\u{24d5}'), ('\u{24bc}',
-        '\u{24d6}'), ('\u{24bd}', '\u{24d7}'), ('\u{24be}', '\u{24d8}'),
-        ('\u{24bf}', '\u{24d9}'), ('\u{24c0}', '\u{24da}'), ('\u{24c1}',
-        '\u{24db}'), ('\u{24c2}', '\u{24dc}'), ('\u{24c3}', '\u{24dd}'),
-        ('\u{24c4}', '\u{24de}'), ('\u{24c5}', '\u{24df}'), ('\u{24c6}',
-        '\u{24e0}'), ('\u{24c7}', '\u{24e1}'), ('\u{24c8}', '\u{24e2}'),
-        ('\u{24c9}', '\u{24e3}'), ('\u{24ca}', '\u{24e4}'), ('\u{24cb}',
-        '\u{24e5}'), ('\u{24cc}', '\u{24e6}'), ('\u{24cd}', '\u{24e7}'),
-        ('\u{24ce}', '\u{24e8}'), ('\u{24cf}', '\u{24e9}'), ('\u{24d0}',
-        '\u{24b6}'), ('\u{24d1}', '\u{24b7}'), ('\u{24d2}', '\u{24b8}'),
-        ('\u{24d3}', '\u{24b9}'), ('\u{24d4}', '\u{24ba}'), ('\u{24d5}',
-        '\u{24bb}'), ('\u{24d6}', '\u{24bc}'), ('\u{24d7}', '\u{24bd}'),
-        ('\u{24d8}', '\u{24be}'), ('\u{24d9}', '\u{24bf}'), ('\u{24da}',
-        '\u{24c0}'), ('\u{24db}', '\u{24c1}'), ('\u{24dc}', '\u{24c2}'),
-        ('\u{24dd}', '\u{24c3}'), ('\u{24de}', '\u{24c4}'), ('\u{24df}',
-        '\u{24c5}'), ('\u{24e0}', '\u{24c6}'), ('\u{24e1}', '\u{24c7}'),
-        ('\u{24e2}', '\u{24c8}'), ('\u{24e3}', '\u{24c9}'), ('\u{24e4}',
-        '\u{24ca}'), ('\u{24e5}', '\u{24cb}'), ('\u{24e6}', '\u{24cc}'),
-        ('\u{24e7}', '\u{24cd}'), ('\u{24e8}', '\u{24ce}'), ('\u{24e9}',
-        '\u{24cf}'), ('\u{2c00}', '\u{2c30}'), ('\u{2c01}', '\u{2c31}'),
-        ('\u{2c02}', '\u{2c32}'), ('\u{2c03}', '\u{2c33}'), ('\u{2c04}',
-        '\u{2c34}'), ('\u{2c05}', '\u{2c35}'), ('\u{2c06}', '\u{2c36}'),
-        ('\u{2c07}', '\u{2c37}'), ('\u{2c08}', '\u{2c38}'), ('\u{2c09}',
-        '\u{2c39}'), ('\u{2c0a}', '\u{2c3a}'), ('\u{2c0b}', '\u{2c3b}'),
-        ('\u{2c0c}', '\u{2c3c}'), ('\u{2c0d}', '\u{2c3d}'), ('\u{2c0e}',
-        '\u{2c3e}'), ('\u{2c0f}', '\u{2c3f}'), ('\u{2c10}', '\u{2c40}'),
-        ('\u{2c11}', '\u{2c41}'), ('\u{2c12}', '\u{2c42}'), ('\u{2c13}',
-        '\u{2c43}'), ('\u{2c14}', '\u{2c44}'), ('\u{2c15}', '\u{2c45}'),
-        ('\u{2c16}', '\u{2c46}'), ('\u{2c17}', '\u{2c47}'), ('\u{2c18}',
-        '\u{2c48}'), ('\u{2c19}', '\u{2c49}'), ('\u{2c1a}', '\u{2c4a}'),
-        ('\u{2c1b}', '\u{2c4b}'), ('\u{2c1c}', '\u{2c4c}'), ('\u{2c1d}',
-        '\u{2c4d}'), ('\u{2c1e}', '\u{2c4e}'), ('\u{2c1f}', '\u{2c4f}'),
-        ('\u{2c20}', '\u{2c50}'), ('\u{2c21}', '\u{2c51}'), ('\u{2c22}',
-        '\u{2c52}'), ('\u{2c23}', '\u{2c53}'), ('\u{2c24}', '\u{2c54}'),
-        ('\u{2c25}', '\u{2c55}'), ('\u{2c26}', '\u{2c56}'), ('\u{2c27}',
-        '\u{2c57}'), ('\u{2c28}', '\u{2c58}'), ('\u{2c29}', '\u{2c59}'),
-        ('\u{2c2a}', '\u{2c5a}'), ('\u{2c2b}', '\u{2c5b}'), ('\u{2c2c}',
-        '\u{2c5c}'), ('\u{2c2d}', '\u{2c5d}'), ('\u{2c2e}', '\u{2c5e}'),
-        ('\u{2c30}', '\u{2c00}'), ('\u{2c31}', '\u{2c01}'), ('\u{2c32}',
-        '\u{2c02}'), ('\u{2c33}', '\u{2c03}'), ('\u{2c34}', '\u{2c04}'),
-        ('\u{2c35}', '\u{2c05}'), ('\u{2c36}', '\u{2c06}'), ('\u{2c37}',
-        '\u{2c07}'), ('\u{2c38}', '\u{2c08}'), ('\u{2c39}', '\u{2c09}'),
-        ('\u{2c3a}', '\u{2c0a}'), ('\u{2c3b}', '\u{2c0b}'), ('\u{2c3c}',
-        '\u{2c0c}'), ('\u{2c3d}', '\u{2c0d}'), ('\u{2c3e}', '\u{2c0e}'),
-        ('\u{2c3f}', '\u{2c0f}'), ('\u{2c40}', '\u{2c10}'), ('\u{2c41}',
-        '\u{2c11}'), ('\u{2c42}', '\u{2c12}'), ('\u{2c43}', '\u{2c13}'),
-        ('\u{2c44}', '\u{2c14}'), ('\u{2c45}', '\u{2c15}'), ('\u{2c46}',
-        '\u{2c16}'), ('\u{2c47}', '\u{2c17}'), ('\u{2c48}', '\u{2c18}'),
-        ('\u{2c49}', '\u{2c19}'), ('\u{2c4a}', '\u{2c1a}'), ('\u{2c4b}',
-        '\u{2c1b}'), ('\u{2c4c}', '\u{2c1c}'), ('\u{2c4d}', '\u{2c1d}'),
-        ('\u{2c4e}', '\u{2c1e}'), ('\u{2c4f}', '\u{2c1f}'), ('\u{2c50}',
-        '\u{2c20}'), ('\u{2c51}', '\u{2c21}'), ('\u{2c52}', '\u{2c22}'),
-        ('\u{2c53}', '\u{2c23}'), ('\u{2c54}', '\u{2c24}'), ('\u{2c55}',
-        '\u{2c25}'), ('\u{2c56}', '\u{2c26}'), ('\u{2c57}', '\u{2c27}'),
-        ('\u{2c58}', '\u{2c28}'), ('\u{2c59}', '\u{2c29}'), ('\u{2c5a}',
-        '\u{2c2a}'), ('\u{2c5b}', '\u{2c2b}'), ('\u{2c5c}', '\u{2c2c}'),
-        ('\u{2c5d}', '\u{2c2d}'), ('\u{2c5e}', '\u{2c2e}'), ('\u{2c60}',
-        '\u{2c61}'), ('\u{2c61}', '\u{2c60}'), ('\u{2c62}', '\u{26b}'),
-        ('\u{2c63}', '\u{1d7d}'), ('\u{2c64}', '\u{27d}'), ('\u{2c65}',
-        '\u{23a}'), ('\u{2c66}', '\u{23e}'), ('\u{2c67}', '\u{2c68}'),
-        ('\u{2c68}', '\u{2c67}'), ('\u{2c69}', '\u{2c6a}'), ('\u{2c6a}',
-        '\u{2c69}'), ('\u{2c6b}', '\u{2c6c}'), ('\u{2c6c}', '\u{2c6b}'),
-        ('\u{2c6d}', '\u{251}'), ('\u{2c6e}', '\u{271}'), ('\u{2c6f}',
-        '\u{250}'), ('\u{2c70}', '\u{252}'), ('\u{2c72}', '\u{2c73}'),
-        ('\u{2c73}', '\u{2c72}'), ('\u{2c75}', '\u{2c76}'), ('\u{2c76}',
-        '\u{2c75}'), ('\u{2c7e}', '\u{23f}'), ('\u{2c7f}', '\u{240}'),
-        ('\u{2c80}', '\u{2c81}'), ('\u{2c81}', '\u{2c80}'), ('\u{2c82}',
-        '\u{2c83}'), ('\u{2c83}', '\u{2c82}'), ('\u{2c84}', '\u{2c85}'),
-        ('\u{2c85}', '\u{2c84}'), ('\u{2c86}', '\u{2c87}'), ('\u{2c87}',
-        '\u{2c86}'), ('\u{2c88}', '\u{2c89}'), ('\u{2c89}', '\u{2c88}'),
-        ('\u{2c8a}', '\u{2c8b}'), ('\u{2c8b}', '\u{2c8a}'), ('\u{2c8c}',
-        '\u{2c8d}'), ('\u{2c8d}', '\u{2c8c}'), ('\u{2c8e}', '\u{2c8f}'),
-        ('\u{2c8f}', '\u{2c8e}'), ('\u{2c90}', '\u{2c91}'), ('\u{2c91}',
-        '\u{2c90}'), ('\u{2c92}', '\u{2c93}'), ('\u{2c93}', '\u{2c92}'),
-        ('\u{2c94}', '\u{2c95}'), ('\u{2c95}', '\u{2c94}'), ('\u{2c96}',
-        '\u{2c97}'), ('\u{2c97}', '\u{2c96}'), ('\u{2c98}', '\u{2c99}'),
-        ('\u{2c99}', '\u{2c98}'), ('\u{2c9a}', '\u{2c9b}'), ('\u{2c9b}',
-        '\u{2c9a}'), ('\u{2c9c}', '\u{2c9d}'), ('\u{2c9d}', '\u{2c9c}'),
-        ('\u{2c9e}', '\u{2c9f}'), ('\u{2c9f}', '\u{2c9e}'), ('\u{2ca0}',
-        '\u{2ca1}'), ('\u{2ca1}', '\u{2ca0}'), ('\u{2ca2}', '\u{2ca3}'),
-        ('\u{2ca3}', '\u{2ca2}'), ('\u{2ca4}', '\u{2ca5}'), ('\u{2ca5}',
-        '\u{2ca4}'), ('\u{2ca6}', '\u{2ca7}'), ('\u{2ca7}', '\u{2ca6}'),
-        ('\u{2ca8}', '\u{2ca9}'), ('\u{2ca9}', '\u{2ca8}'), ('\u{2caa}',
-        '\u{2cab}'), ('\u{2cab}', '\u{2caa}'), ('\u{2cac}', '\u{2cad}'),
-        ('\u{2cad}', '\u{2cac}'), ('\u{2cae}', '\u{2caf}'), ('\u{2caf}',
-        '\u{2cae}'), ('\u{2cb0}', '\u{2cb1}'), ('\u{2cb1}', '\u{2cb0}'),
-        ('\u{2cb2}', '\u{2cb3}'), ('\u{2cb3}', '\u{2cb2}'), ('\u{2cb4}',
-        '\u{2cb5}'), ('\u{2cb5}', '\u{2cb4}'), ('\u{2cb6}', '\u{2cb7}'),
-        ('\u{2cb7}', '\u{2cb6}'), ('\u{2cb8}', '\u{2cb9}'), ('\u{2cb9}',
-        '\u{2cb8}'), ('\u{2cba}', '\u{2cbb}'), ('\u{2cbb}', '\u{2cba}'),
-        ('\u{2cbc}', '\u{2cbd}'), ('\u{2cbd}', '\u{2cbc}'), ('\u{2cbe}',
-        '\u{2cbf}'), ('\u{2cbf}', '\u{2cbe}'), ('\u{2cc0}', '\u{2cc1}'),
-        ('\u{2cc1}', '\u{2cc0}'), ('\u{2cc2}', '\u{2cc3}'), ('\u{2cc3}',
-        '\u{2cc2}'), ('\u{2cc4}', '\u{2cc5}'), ('\u{2cc5}', '\u{2cc4}'),
-        ('\u{2cc6}', '\u{2cc7}'), ('\u{2cc7}', '\u{2cc6}'), ('\u{2cc8}',
-        '\u{2cc9}'), ('\u{2cc9}', '\u{2cc8}'), ('\u{2cca}', '\u{2ccb}'),
-        ('\u{2ccb}', '\u{2cca}'), ('\u{2ccc}', '\u{2ccd}'), ('\u{2ccd}',
-        '\u{2ccc}'), ('\u{2cce}', '\u{2ccf}'), ('\u{2ccf}', '\u{2cce}'),
-        ('\u{2cd0}', '\u{2cd1}'), ('\u{2cd1}', '\u{2cd0}'), ('\u{2cd2}',
-        '\u{2cd3}'), ('\u{2cd3}', '\u{2cd2}'), ('\u{2cd4}', '\u{2cd5}'),
-        ('\u{2cd5}', '\u{2cd4}'), ('\u{2cd6}', '\u{2cd7}'), ('\u{2cd7}',
-        '\u{2cd6}'), ('\u{2cd8}', '\u{2cd9}'), ('\u{2cd9}', '\u{2cd8}'),
-        ('\u{2cda}', '\u{2cdb}'), ('\u{2cdb}', '\u{2cda}'), ('\u{2cdc}',
-        '\u{2cdd}'), ('\u{2cdd}', '\u{2cdc}'), ('\u{2cde}', '\u{2cdf}'),
-        ('\u{2cdf}', '\u{2cde}'), ('\u{2ce0}', '\u{2ce1}'), ('\u{2ce1}',
-        '\u{2ce0}'), ('\u{2ce2}', '\u{2ce3}'), ('\u{2ce3}', '\u{2ce2}'),
-        ('\u{2ceb}', '\u{2cec}'), ('\u{2cec}', '\u{2ceb}'), ('\u{2ced}',
-        '\u{2cee}'), ('\u{2cee}', '\u{2ced}'), ('\u{2cf2}', '\u{2cf3}'),
-        ('\u{2cf3}', '\u{2cf2}'), ('\u{2d00}', '\u{10a0}'), ('\u{2d01}',
-        '\u{10a1}'), ('\u{2d02}', '\u{10a2}'), ('\u{2d03}', '\u{10a3}'),
-        ('\u{2d04}', '\u{10a4}'), ('\u{2d05}', '\u{10a5}'), ('\u{2d06}',
-        '\u{10a6}'), ('\u{2d07}', '\u{10a7}'), ('\u{2d08}', '\u{10a8}'),
-        ('\u{2d09}', '\u{10a9}'), ('\u{2d0a}', '\u{10aa}'), ('\u{2d0b}',
-        '\u{10ab}'), ('\u{2d0c}', '\u{10ac}'), ('\u{2d0d}', '\u{10ad}'),
-        ('\u{2d0e}', '\u{10ae}'), ('\u{2d0f}', '\u{10af}'), ('\u{2d10}',
-        '\u{10b0}'), ('\u{2d11}', '\u{10b1}'), ('\u{2d12}', '\u{10b2}'),
-        ('\u{2d13}', '\u{10b3}'), ('\u{2d14}', '\u{10b4}'), ('\u{2d15}',
-        '\u{10b5}'), ('\u{2d16}', '\u{10b6}'), ('\u{2d17}', '\u{10b7}'),
-        ('\u{2d18}', '\u{10b8}'), ('\u{2d19}', '\u{10b9}'), ('\u{2d1a}',
-        '\u{10ba}'), ('\u{2d1b}', '\u{10bb}'), ('\u{2d1c}', '\u{10bc}'),
-        ('\u{2d1d}', '\u{10bd}'), ('\u{2d1e}', '\u{10be}'), ('\u{2d1f}',
-        '\u{10bf}'), ('\u{2d20}', '\u{10c0}'), ('\u{2d21}', '\u{10c1}'),
-        ('\u{2d22}', '\u{10c2}'), ('\u{2d23}', '\u{10c3}'), ('\u{2d24}',
-        '\u{10c4}'), ('\u{2d25}', '\u{10c5}'), ('\u{2d27}', '\u{10c7}'),
-        ('\u{2d2d}', '\u{10cd}'), ('\u{a640}', '\u{a641}'), ('\u{a641}',
-        '\u{a640}'), ('\u{a642}', '\u{a643}'), ('\u{a643}', '\u{a642}'),
-        ('\u{a644}', '\u{a645}'), ('\u{a645}', '\u{a644}'), ('\u{a646}',
-        '\u{a647}'), ('\u{a647}', '\u{a646}'), ('\u{a648}', '\u{a649}'),
-        ('\u{a649}', '\u{a648}'), ('\u{a64a}', '\u{a64b}'), ('\u{a64b}',
-        '\u{a64a}'), ('\u{a64c}', '\u{a64d}'), ('\u{a64d}', '\u{a64c}'),
-        ('\u{a64e}', '\u{a64f}'), ('\u{a64f}', '\u{a64e}'), ('\u{a650}',
-        '\u{a651}'), ('\u{a651}', '\u{a650}'), ('\u{a652}', '\u{a653}'),
-        ('\u{a653}', '\u{a652}'), ('\u{a654}', '\u{a655}'), ('\u{a655}',
-        '\u{a654}'), ('\u{a656}', '\u{a657}'), ('\u{a657}', '\u{a656}'),
-        ('\u{a658}', '\u{a659}'), ('\u{a659}', '\u{a658}'), ('\u{a65a}',
-        '\u{a65b}'), ('\u{a65b}', '\u{a65a}'), ('\u{a65c}', '\u{a65d}'),
-        ('\u{a65d}', '\u{a65c}'), ('\u{a65e}', '\u{a65f}'), ('\u{a65f}',
-        '\u{a65e}'), ('\u{a660}', '\u{a661}'), ('\u{a661}', '\u{a660}'),
-        ('\u{a662}', '\u{a663}'), ('\u{a663}', '\u{a662}'), ('\u{a664}',
-        '\u{a665}'), ('\u{a665}', '\u{a664}'), ('\u{a666}', '\u{a667}'),
-        ('\u{a667}', '\u{a666}'), ('\u{a668}', '\u{a669}'), ('\u{a669}',
-        '\u{a668}'), ('\u{a66a}', '\u{a66b}'), ('\u{a66b}', '\u{a66a}'),
-        ('\u{a66c}', '\u{a66d}'), ('\u{a66d}', '\u{a66c}'), ('\u{a680}',
-        '\u{a681}'), ('\u{a681}', '\u{a680}'), ('\u{a682}', '\u{a683}'),
-        ('\u{a683}', '\u{a682}'), ('\u{a684}', '\u{a685}'), ('\u{a685}',
-        '\u{a684}'), ('\u{a686}', '\u{a687}'), ('\u{a687}', '\u{a686}'),
-        ('\u{a688}', '\u{a689}'), ('\u{a689}', '\u{a688}'), ('\u{a68a}',
-        '\u{a68b}'), ('\u{a68b}', '\u{a68a}'), ('\u{a68c}', '\u{a68d}'),
-        ('\u{a68d}', '\u{a68c}'), ('\u{a68e}', '\u{a68f}'), ('\u{a68f}',
-        '\u{a68e}'), ('\u{a690}', '\u{a691}'), ('\u{a691}', '\u{a690}'),
-        ('\u{a692}', '\u{a693}'), ('\u{a693}', '\u{a692}'), ('\u{a694}',
-        '\u{a695}'), ('\u{a695}', '\u{a694}'), ('\u{a696}', '\u{a697}'),
-        ('\u{a697}', '\u{a696}'), ('\u{a698}', '\u{a699}'), ('\u{a699}',
-        '\u{a698}'), ('\u{a69a}', '\u{a69b}'), ('\u{a69b}', '\u{a69a}'),
-        ('\u{a722}', '\u{a723}'), ('\u{a723}', '\u{a722}'), ('\u{a724}',
-        '\u{a725}'), ('\u{a725}', '\u{a724}'), ('\u{a726}', '\u{a727}'),
-        ('\u{a727}', '\u{a726}'), ('\u{a728}', '\u{a729}'), ('\u{a729}',
-        '\u{a728}'), ('\u{a72a}', '\u{a72b}'), ('\u{a72b}', '\u{a72a}'),
-        ('\u{a72c}', '\u{a72d}'), ('\u{a72d}', '\u{a72c}'), ('\u{a72e}',
-        '\u{a72f}'), ('\u{a72f}', '\u{a72e}'), ('\u{a732}', '\u{a733}'),
-        ('\u{a733}', '\u{a732}'), ('\u{a734}', '\u{a735}'), ('\u{a735}',
-        '\u{a734}'), ('\u{a736}', '\u{a737}'), ('\u{a737}', '\u{a736}'),
-        ('\u{a738}', '\u{a739}'), ('\u{a739}', '\u{a738}'), ('\u{a73a}',
-        '\u{a73b}'), ('\u{a73b}', '\u{a73a}'), ('\u{a73c}', '\u{a73d}'),
-        ('\u{a73d}', '\u{a73c}'), ('\u{a73e}', '\u{a73f}'), ('\u{a73f}',
-        '\u{a73e}'), ('\u{a740}', '\u{a741}'), ('\u{a741}', '\u{a740}'),
-        ('\u{a742}', '\u{a743}'), ('\u{a743}', '\u{a742}'), ('\u{a744}',
-        '\u{a745}'), ('\u{a745}', '\u{a744}'), ('\u{a746}', '\u{a747}'),
-        ('\u{a747}', '\u{a746}'), ('\u{a748}', '\u{a749}'), ('\u{a749}',
-        '\u{a748}'), ('\u{a74a}', '\u{a74b}'), ('\u{a74b}', '\u{a74a}'),
-        ('\u{a74c}', '\u{a74d}'), ('\u{a74d}', '\u{a74c}'), ('\u{a74e}',
-        '\u{a74f}'), ('\u{a74f}', '\u{a74e}'), ('\u{a750}', '\u{a751}'),
-        ('\u{a751}', '\u{a750}'), ('\u{a752}', '\u{a753}'), ('\u{a753}',
-        '\u{a752}'), ('\u{a754}', '\u{a755}'), ('\u{a755}', '\u{a754}'),
-        ('\u{a756}', '\u{a757}'), ('\u{a757}', '\u{a756}'), ('\u{a758}',
-        '\u{a759}'), ('\u{a759}', '\u{a758}'), ('\u{a75a}', '\u{a75b}'),
-        ('\u{a75b}', '\u{a75a}'), ('\u{a75c}', '\u{a75d}'), ('\u{a75d}',
-        '\u{a75c}'), ('\u{a75e}', '\u{a75f}'), ('\u{a75f}', '\u{a75e}'),
-        ('\u{a760}', '\u{a761}'), ('\u{a761}', '\u{a760}'), ('\u{a762}',
-        '\u{a763}'), ('\u{a763}', '\u{a762}'), ('\u{a764}', '\u{a765}'),
-        ('\u{a765}', '\u{a764}'), ('\u{a766}', '\u{a767}'), ('\u{a767}',
-        '\u{a766}'), ('\u{a768}', '\u{a769}'), ('\u{a769}', '\u{a768}'),
-        ('\u{a76a}', '\u{a76b}'), ('\u{a76b}', '\u{a76a}'), ('\u{a76c}',
-        '\u{a76d}'), ('\u{a76d}', '\u{a76c}'), ('\u{a76e}', '\u{a76f}'),
-        ('\u{a76f}', '\u{a76e}'), ('\u{a779}', '\u{a77a}'), ('\u{a77a}',
-        '\u{a779}'), ('\u{a77b}', '\u{a77c}'), ('\u{a77c}', '\u{a77b}'),
-        ('\u{a77d}', '\u{1d79}'), ('\u{a77e}', '\u{a77f}'), ('\u{a77f}',
-        '\u{a77e}'), ('\u{a780}', '\u{a781}'), ('\u{a781}', '\u{a780}'),
-        ('\u{a782}', '\u{a783}'), ('\u{a783}', '\u{a782}'), ('\u{a784}',
-        '\u{a785}'), ('\u{a785}', '\u{a784}'), ('\u{a786}', '\u{a787}'),
-        ('\u{a787}', '\u{a786}'), ('\u{a78b}', '\u{a78c}'), ('\u{a78c}',
-        '\u{a78b}'), ('\u{a78d}', '\u{265}'), ('\u{a790}', '\u{a791}'),
-        ('\u{a791}', '\u{a790}'), ('\u{a792}', '\u{a793}'), ('\u{a793}',
-        '\u{a792}'), ('\u{a796}', '\u{a797}'), ('\u{a797}', '\u{a796}'),
-        ('\u{a798}', '\u{a799}'), ('\u{a799}', '\u{a798}'), ('\u{a79a}',
-        '\u{a79b}'), ('\u{a79b}', '\u{a79a}'), ('\u{a79c}', '\u{a79d}'),
-        ('\u{a79d}', '\u{a79c}'), ('\u{a79e}', '\u{a79f}'), ('\u{a79f}',
-        '\u{a79e}'), ('\u{a7a0}', '\u{a7a1}'), ('\u{a7a1}', '\u{a7a0}'),
-        ('\u{a7a2}', '\u{a7a3}'), ('\u{a7a3}', '\u{a7a2}'), ('\u{a7a4}',
-        '\u{a7a5}'), ('\u{a7a5}', '\u{a7a4}'), ('\u{a7a6}', '\u{a7a7}'),
-        ('\u{a7a7}', '\u{a7a6}'), ('\u{a7a8}', '\u{a7a9}'), ('\u{a7a9}',
-        '\u{a7a8}'), ('\u{a7aa}', '\u{266}'), ('\u{a7ab}', '\u{25c}'),
-        ('\u{a7ac}', '\u{261}'), ('\u{a7ad}', '\u{26c}'), ('\u{a7b0}',
-        '\u{29e}'), ('\u{a7b1}', '\u{287}'), ('\u{a7b2}', '\u{29d}'),
-        ('\u{a7b3}', '\u{ab53}'), ('\u{a7b4}', '\u{a7b5}'), ('\u{a7b5}',
-        '\u{a7b4}'), ('\u{a7b6}', '\u{a7b7}'), ('\u{a7b7}', '\u{a7b6}'),
-        ('\u{ab53}', '\u{a7b3}'), ('\u{ab70}', '\u{13a0}'), ('\u{ab71}',
-        '\u{13a1}'), ('\u{ab72}', '\u{13a2}'), ('\u{ab73}', '\u{13a3}'),
-        ('\u{ab74}', '\u{13a4}'), ('\u{ab75}', '\u{13a5}'), ('\u{ab76}',
-        '\u{13a6}'), ('\u{ab77}', '\u{13a7}'), ('\u{ab78}', '\u{13a8}'),
-        ('\u{ab79}', '\u{13a9}'), ('\u{ab7a}', '\u{13aa}'), ('\u{ab7b}',
-        '\u{13ab}'), ('\u{ab7c}', '\u{13ac}'), ('\u{ab7d}', '\u{13ad}'),
-        ('\u{ab7e}', '\u{13ae}'), ('\u{ab7f}', '\u{13af}'), ('\u{ab80}',
-        '\u{13b0}'), ('\u{ab81}', '\u{13b1}'), ('\u{ab82}', '\u{13b2}'),
-        ('\u{ab83}', '\u{13b3}'), ('\u{ab84}', '\u{13b4}'), ('\u{ab85}',
-        '\u{13b5}'), ('\u{ab86}', '\u{13b6}'), ('\u{ab87}', '\u{13b7}'),
-        ('\u{ab88}', '\u{13b8}'), ('\u{ab89}', '\u{13b9}'), ('\u{ab8a}',
-        '\u{13ba}'), ('\u{ab8b}', '\u{13bb}'), ('\u{ab8c}', '\u{13bc}'),
-        ('\u{ab8d}', '\u{13bd}'), ('\u{ab8e}', '\u{13be}'), ('\u{ab8f}',
-        '\u{13bf}'), ('\u{ab90}', '\u{13c0}'), ('\u{ab91}', '\u{13c1}'),
-        ('\u{ab92}', '\u{13c2}'), ('\u{ab93}', '\u{13c3}'), ('\u{ab94}',
-        '\u{13c4}'), ('\u{ab95}', '\u{13c5}'), ('\u{ab96}', '\u{13c6}'),
-        ('\u{ab97}', '\u{13c7}'), ('\u{ab98}', '\u{13c8}'), ('\u{ab99}',
-        '\u{13c9}'), ('\u{ab9a}', '\u{13ca}'), ('\u{ab9b}', '\u{13cb}'),
-        ('\u{ab9c}', '\u{13cc}'), ('\u{ab9d}', '\u{13cd}'), ('\u{ab9e}',
-        '\u{13ce}'), ('\u{ab9f}', '\u{13cf}'), ('\u{aba0}', '\u{13d0}'),
-        ('\u{aba1}', '\u{13d1}'), ('\u{aba2}', '\u{13d2}'), ('\u{aba3}',
-        '\u{13d3}'), ('\u{aba4}', '\u{13d4}'), ('\u{aba5}', '\u{13d5}'),
-        ('\u{aba6}', '\u{13d6}'), ('\u{aba7}', '\u{13d7}'), ('\u{aba8}',
-        '\u{13d8}'), ('\u{aba9}', '\u{13d9}'), ('\u{abaa}', '\u{13da}'),
-        ('\u{abab}', '\u{13db}'), ('\u{abac}', '\u{13dc}'), ('\u{abad}',
-        '\u{13dd}'), ('\u{abae}', '\u{13de}'), ('\u{abaf}', '\u{13df}'),
-        ('\u{abb0}', '\u{13e0}'), ('\u{abb1}', '\u{13e1}'), ('\u{abb2}',
-        '\u{13e2}'), ('\u{abb3}', '\u{13e3}'), ('\u{abb4}', '\u{13e4}'),
-        ('\u{abb5}', '\u{13e5}'), ('\u{abb6}', '\u{13e6}'), ('\u{abb7}',
-        '\u{13e7}'), ('\u{abb8}', '\u{13e8}'), ('\u{abb9}', '\u{13e9}'),
-        ('\u{abba}', '\u{13ea}'), ('\u{abbb}', '\u{13eb}'), ('\u{abbc}',
-        '\u{13ec}'), ('\u{abbd}', '\u{13ed}'), ('\u{abbe}', '\u{13ee}'),
-        ('\u{abbf}', '\u{13ef}'), ('\u{ff21}', '\u{ff41}'), ('\u{ff22}',
-        '\u{ff42}'), ('\u{ff23}', '\u{ff43}'), ('\u{ff24}', '\u{ff44}'),
-        ('\u{ff25}', '\u{ff45}'), ('\u{ff26}', '\u{ff46}'), ('\u{ff27}',
-        '\u{ff47}'), ('\u{ff28}', '\u{ff48}'), ('\u{ff29}', '\u{ff49}'),
-        ('\u{ff2a}', '\u{ff4a}'), ('\u{ff2b}', '\u{ff4b}'), ('\u{ff2c}',
-        '\u{ff4c}'), ('\u{ff2d}', '\u{ff4d}'), ('\u{ff2e}', '\u{ff4e}'),
-        ('\u{ff2f}', '\u{ff4f}'), ('\u{ff30}', '\u{ff50}'), ('\u{ff31}',
-        '\u{ff51}'), ('\u{ff32}', '\u{ff52}'), ('\u{ff33}', '\u{ff53}'),
-        ('\u{ff34}', '\u{ff54}'), ('\u{ff35}', '\u{ff55}'), ('\u{ff36}',
-        '\u{ff56}'), ('\u{ff37}', '\u{ff57}'), ('\u{ff38}', '\u{ff58}'),
-        ('\u{ff39}', '\u{ff59}'), ('\u{ff3a}', '\u{ff5a}'), ('\u{ff41}',
-        '\u{ff21}'), ('\u{ff42}', '\u{ff22}'), ('\u{ff43}', '\u{ff23}'),
-        ('\u{ff44}', '\u{ff24}'), ('\u{ff45}', '\u{ff25}'), ('\u{ff46}',
-        '\u{ff26}'), ('\u{ff47}', '\u{ff27}'), ('\u{ff48}', '\u{ff28}'),
-        ('\u{ff49}', '\u{ff29}'), ('\u{ff4a}', '\u{ff2a}'), ('\u{ff4b}',
-        '\u{ff2b}'), ('\u{ff4c}', '\u{ff2c}'), ('\u{ff4d}', '\u{ff2d}'),
-        ('\u{ff4e}', '\u{ff2e}'), ('\u{ff4f}', '\u{ff2f}'), ('\u{ff50}',
-        '\u{ff30}'), ('\u{ff51}', '\u{ff31}'), ('\u{ff52}', '\u{ff32}'),
-        ('\u{ff53}', '\u{ff33}'), ('\u{ff54}', '\u{ff34}'), ('\u{ff55}',
-        '\u{ff35}'), ('\u{ff56}', '\u{ff36}'), ('\u{ff57}', '\u{ff37}'),
-        ('\u{ff58}', '\u{ff38}'), ('\u{ff59}', '\u{ff39}'), ('\u{ff5a}',
-        '\u{ff3a}'), ('\u{10400}', '\u{10428}'), ('\u{10401}', '\u{10429}'),
-        ('\u{10402}', '\u{1042a}'), ('\u{10403}', '\u{1042b}'), ('\u{10404}',
-        '\u{1042c}'), ('\u{10405}', '\u{1042d}'), ('\u{10406}', '\u{1042e}'),
-        ('\u{10407}', '\u{1042f}'), ('\u{10408}', '\u{10430}'), ('\u{10409}',
-        '\u{10431}'), ('\u{1040a}', '\u{10432}'), ('\u{1040b}', '\u{10433}'),
-        ('\u{1040c}', '\u{10434}'), ('\u{1040d}', '\u{10435}'), ('\u{1040e}',
-        '\u{10436}'), ('\u{1040f}', '\u{10437}'), ('\u{10410}', '\u{10438}'),
-        ('\u{10411}', '\u{10439}'), ('\u{10412}', '\u{1043a}'), ('\u{10413}',
-        '\u{1043b}'), ('\u{10414}', '\u{1043c}'), ('\u{10415}', '\u{1043d}'),
-        ('\u{10416}', '\u{1043e}'), ('\u{10417}', '\u{1043f}'), ('\u{10418}',
-        '\u{10440}'), ('\u{10419}', '\u{10441}'), ('\u{1041a}', '\u{10442}'),
-        ('\u{1041b}', '\u{10443}'), ('\u{1041c}', '\u{10444}'), ('\u{1041d}',
-        '\u{10445}'), ('\u{1041e}', '\u{10446}'), ('\u{1041f}', '\u{10447}'),
-        ('\u{10420}', '\u{10448}'), ('\u{10421}', '\u{10449}'), ('\u{10422}',
-        '\u{1044a}'), ('\u{10423}', '\u{1044b}'), ('\u{10424}', '\u{1044c}'),
-        ('\u{10425}', '\u{1044d}'), ('\u{10426}', '\u{1044e}'), ('\u{10427}',
-        '\u{1044f}'), ('\u{10428}', '\u{10400}'), ('\u{10429}', '\u{10401}'),
-        ('\u{1042a}', '\u{10402}'), ('\u{1042b}', '\u{10403}'), ('\u{1042c}',
-        '\u{10404}'), ('\u{1042d}', '\u{10405}'), ('\u{1042e}', '\u{10406}'),
-        ('\u{1042f}', '\u{10407}'), ('\u{10430}', '\u{10408}'), ('\u{10431}',
-        '\u{10409}'), ('\u{10432}', '\u{1040a}'), ('\u{10433}', '\u{1040b}'),
-        ('\u{10434}', '\u{1040c}'), ('\u{10435}', '\u{1040d}'), ('\u{10436}',
-        '\u{1040e}'), ('\u{10437}', '\u{1040f}'), ('\u{10438}', '\u{10410}'),
-        ('\u{10439}', '\u{10411}'), ('\u{1043a}', '\u{10412}'), ('\u{1043b}',
-        '\u{10413}'), ('\u{1043c}', '\u{10414}'), ('\u{1043d}', '\u{10415}'),
-        ('\u{1043e}', '\u{10416}'), ('\u{1043f}', '\u{10417}'), ('\u{10440}',
-        '\u{10418}'), ('\u{10441}', '\u{10419}'), ('\u{10442}', '\u{1041a}'),
-        ('\u{10443}', '\u{1041b}'), ('\u{10444}', '\u{1041c}'), ('\u{10445}',
-        '\u{1041d}'), ('\u{10446}', '\u{1041e}'), ('\u{10447}', '\u{1041f}'),
-        ('\u{10448}', '\u{10420}'), ('\u{10449}', '\u{10421}'), ('\u{1044a}',
-        '\u{10422}'), ('\u{1044b}', '\u{10423}'), ('\u{1044c}', '\u{10424}'),
-        ('\u{1044d}', '\u{10425}'), ('\u{1044e}', '\u{10426}'), ('\u{1044f}',
-        '\u{10427}'), ('\u{10c80}', '\u{10cc0}'), ('\u{10c81}', '\u{10cc1}'),
-        ('\u{10c82}', '\u{10cc2}'), ('\u{10c83}', '\u{10cc3}'), ('\u{10c84}',
-        '\u{10cc4}'), ('\u{10c85}', '\u{10cc5}'), ('\u{10c86}', '\u{10cc6}'),
-        ('\u{10c87}', '\u{10cc7}'), ('\u{10c88}', '\u{10cc8}'), ('\u{10c89}',
-        '\u{10cc9}'), ('\u{10c8a}', '\u{10cca}'), ('\u{10c8b}', '\u{10ccb}'),
-        ('\u{10c8c}', '\u{10ccc}'), ('\u{10c8d}', '\u{10ccd}'), ('\u{10c8e}',
-        '\u{10cce}'), ('\u{10c8f}', '\u{10ccf}'), ('\u{10c90}', '\u{10cd0}'),
-        ('\u{10c91}', '\u{10cd1}'), ('\u{10c92}', '\u{10cd2}'), ('\u{10c93}',
-        '\u{10cd3}'), ('\u{10c94}', '\u{10cd4}'), ('\u{10c95}', '\u{10cd5}'),
-        ('\u{10c96}', '\u{10cd6}'), ('\u{10c97}', '\u{10cd7}'), ('\u{10c98}',
-        '\u{10cd8}'), ('\u{10c99}', '\u{10cd9}'), ('\u{10c9a}', '\u{10cda}'),
-        ('\u{10c9b}', '\u{10cdb}'), ('\u{10c9c}', '\u{10cdc}'), ('\u{10c9d}',
-        '\u{10cdd}'), ('\u{10c9e}', '\u{10cde}'), ('\u{10c9f}', '\u{10cdf}'),
-        ('\u{10ca0}', '\u{10ce0}'), ('\u{10ca1}', '\u{10ce1}'), ('\u{10ca2}',
-        '\u{10ce2}'), ('\u{10ca3}', '\u{10ce3}'), ('\u{10ca4}', '\u{10ce4}'),
-        ('\u{10ca5}', '\u{10ce5}'), ('\u{10ca6}', '\u{10ce6}'), ('\u{10ca7}',
-        '\u{10ce7}'), ('\u{10ca8}', '\u{10ce8}'), ('\u{10ca9}', '\u{10ce9}'),
-        ('\u{10caa}', '\u{10cea}'), ('\u{10cab}', '\u{10ceb}'), ('\u{10cac}',
-        '\u{10cec}'), ('\u{10cad}', '\u{10ced}'), ('\u{10cae}', '\u{10cee}'),
-        ('\u{10caf}', '\u{10cef}'), ('\u{10cb0}', '\u{10cf0}'), ('\u{10cb1}',
-        '\u{10cf1}'), ('\u{10cb2}', '\u{10cf2}'), ('\u{10cc0}', '\u{10c80}'),
-        ('\u{10cc1}', '\u{10c81}'), ('\u{10cc2}', '\u{10c82}'), ('\u{10cc3}',
-        '\u{10c83}'), ('\u{10cc4}', '\u{10c84}'), ('\u{10cc5}', '\u{10c85}'),
-        ('\u{10cc6}', '\u{10c86}'), ('\u{10cc7}', '\u{10c87}'), ('\u{10cc8}',
-        '\u{10c88}'), ('\u{10cc9}', '\u{10c89}'), ('\u{10cca}', '\u{10c8a}'),
-        ('\u{10ccb}', '\u{10c8b}'), ('\u{10ccc}', '\u{10c8c}'), ('\u{10ccd}',
-        '\u{10c8d}'), ('\u{10cce}', '\u{10c8e}'), ('\u{10ccf}', '\u{10c8f}'),
-        ('\u{10cd0}', '\u{10c90}'), ('\u{10cd1}', '\u{10c91}'), ('\u{10cd2}',
-        '\u{10c92}'), ('\u{10cd3}', '\u{10c93}'), ('\u{10cd4}', '\u{10c94}'),
-        ('\u{10cd5}', '\u{10c95}'), ('\u{10cd6}', '\u{10c96}'), ('\u{10cd7}',
-        '\u{10c97}'), ('\u{10cd8}', '\u{10c98}'), ('\u{10cd9}', '\u{10c99}'),
-        ('\u{10cda}', '\u{10c9a}'), ('\u{10cdb}', '\u{10c9b}'), ('\u{10cdc}',
-        '\u{10c9c}'), ('\u{10cdd}', '\u{10c9d}'), ('\u{10cde}', '\u{10c9e}'),
-        ('\u{10cdf}', '\u{10c9f}'), ('\u{10ce0}', '\u{10ca0}'), ('\u{10ce1}',
-        '\u{10ca1}'), ('\u{10ce2}', '\u{10ca2}'), ('\u{10ce3}', '\u{10ca3}'),
-        ('\u{10ce4}', '\u{10ca4}'), ('\u{10ce5}', '\u{10ca5}'), ('\u{10ce6}',
-        '\u{10ca6}'), ('\u{10ce7}', '\u{10ca7}'), ('\u{10ce8}', '\u{10ca8}'),
-        ('\u{10ce9}', '\u{10ca9}'), ('\u{10cea}', '\u{10caa}'), ('\u{10ceb}',
-        '\u{10cab}'), ('\u{10cec}', '\u{10cac}'), ('\u{10ced}', '\u{10cad}'),
-        ('\u{10cee}', '\u{10cae}'), ('\u{10cef}', '\u{10caf}'), ('\u{10cf0}',
-        '\u{10cb0}'), ('\u{10cf1}', '\u{10cb1}'), ('\u{10cf2}', '\u{10cb2}'),
-        ('\u{118a0}', '\u{118c0}'), ('\u{118a1}', '\u{118c1}'), ('\u{118a2}',
-        '\u{118c2}'), ('\u{118a3}', '\u{118c3}'), ('\u{118a4}', '\u{118c4}'),
-        ('\u{118a5}', '\u{118c5}'), ('\u{118a6}', '\u{118c6}'), ('\u{118a7}',
-        '\u{118c7}'), ('\u{118a8}', '\u{118c8}'), ('\u{118a9}', '\u{118c9}'),
-        ('\u{118aa}', '\u{118ca}'), ('\u{118ab}', '\u{118cb}'), ('\u{118ac}',
-        '\u{118cc}'), ('\u{118ad}', '\u{118cd}'), ('\u{118ae}', '\u{118ce}'),
-        ('\u{118af}', '\u{118cf}'), ('\u{118b0}', '\u{118d0}'), ('\u{118b1}',
-        '\u{118d1}'), ('\u{118b2}', '\u{118d2}'), ('\u{118b3}', '\u{118d3}'),
-        ('\u{118b4}', '\u{118d4}'), ('\u{118b5}', '\u{118d5}'), ('\u{118b6}',
-        '\u{118d6}'), ('\u{118b7}', '\u{118d7}'), ('\u{118b8}', '\u{118d8}'),
-        ('\u{118b9}', '\u{118d9}'), ('\u{118ba}', '\u{118da}'), ('\u{118bb}',
-        '\u{118db}'), ('\u{118bc}', '\u{118dc}'), ('\u{118bd}', '\u{118dd}'),
-        ('\u{118be}', '\u{118de}'), ('\u{118bf}', '\u{118df}'), ('\u{118c0}',
-        '\u{118a0}'), ('\u{118c1}', '\u{118a1}'), ('\u{118c2}', '\u{118a2}'),
-        ('\u{118c3}', '\u{118a3}'), ('\u{118c4}', '\u{118a4}'), ('\u{118c5}',
-        '\u{118a5}'), ('\u{118c6}', '\u{118a6}'), ('\u{118c7}', '\u{118a7}'),
-        ('\u{118c8}', '\u{118a8}'), ('\u{118c9}', '\u{118a9}'), ('\u{118ca}',
-        '\u{118aa}'), ('\u{118cb}', '\u{118ab}'), ('\u{118cc}', '\u{118ac}'),
-        ('\u{118cd}', '\u{118ad}'), ('\u{118ce}', '\u{118ae}'), ('\u{118cf}',
-        '\u{118af}'), ('\u{118d0}', '\u{118b0}'), ('\u{118d1}', '\u{118b1}'),
-        ('\u{118d2}', '\u{118b2}'), ('\u{118d3}', '\u{118b3}'), ('\u{118d4}',
-        '\u{118b4}'), ('\u{118d5}', '\u{118b5}'), ('\u{118d6}', '\u{118b6}'),
-        ('\u{118d7}', '\u{118b7}'), ('\u{118d8}', '\u{118b8}'), ('\u{118d9}',
-        '\u{118b9}'), ('\u{118da}', '\u{118ba}'), ('\u{118db}', '\u{118bb}'),
-        ('\u{118dc}', '\u{118bc}'), ('\u{118dd}', '\u{118bd}'), ('\u{118de}',
-        '\u{118be}'), ('\u{118df}', '\u{118bf}')
-    ];
+fn ages(canonical_age: &str) -> Result<AgeIter> {
+    const AGES: &'static [(&'static str, &'static [(char, char)])] = &[
+        ("V1_1", age::V1_1),
+        ("V2_0", age::V2_0),
+        ("V2_1", age::V2_1),
+        ("V3_0", age::V3_0),
+        ("V3_1", age::V3_1),
+        ("V3_2", age::V3_2),
+        ("V4_0", age::V4_0),
+        ("V4_1", age::V4_1),
+        ("V5_0", age::V5_0),
+        ("V5_1", age::V5_1),
+        ("V5_2", age::V5_2),
+        ("V6_0", age::V6_0),
+        ("V6_1", age::V6_1),
+        ("V6_2", age::V6_2),
+        ("V6_3", age::V6_3),
+        ("V7_0", age::V7_0),
+        ("V8_0", age::V8_0),
+        ("V9_0", age::V9_0),
+        ("V10_0", age::V10_0),
+        ("V11_0", age::V11_0),
+    ];
+    assert_eq!(AGES.len(), age::BY_NAME.len(), "ages are out of sync");
+
+    let pos = AGES.iter().position(|&(age, _)| canonical_age == age);
+    match pos {
+        None => Err(Error::PropertyValueNotFound),
+        Some(i) => Ok(AgeIter { ages: &AGES[..i+1] }),
+    }
+}
 
+impl Iterator for AgeIter {
+    type Item = &'static [(char, char)];
+
+    fn next(&mut self) -> Option<&'static [(char, char)]> {
+        if self.ages.is_empty() {
+            None
+        } else {
+            let set = self.ages[0];
+            self.ages = &self.ages[1..];
+            Some(set.1)
+        }
+    }
 }
 
+#[cfg(test)]
+mod tests {
+    use super::{contains_simple_case_mapping, simple_fold};
+
+    #[test]
+    fn simple_fold_k() {
+        let xs: Vec<char> = simple_fold('k').unwrap().collect();
+        assert_eq!(xs, vec!['K', 'K']);
+
+        let xs: Vec<char> = simple_fold('K').unwrap().collect();
+        assert_eq!(xs, vec!['k', 'K']);
+
+        let xs: Vec<char> = simple_fold('K').unwrap().collect();
+        assert_eq!(xs, vec!['K', 'k']);
+    }
+
+    #[test]
+    fn simple_fold_a() {
+        let xs: Vec<char> = simple_fold('a').unwrap().collect();
+        assert_eq!(xs, vec!['A']);
+
+        let xs: Vec<char> = simple_fold('A').unwrap().collect();
+        assert_eq!(xs, vec!['a']);
+    }
+
+    #[test]
+    fn simple_fold_empty() {
+        assert_eq!(Some('A'), simple_fold('?').unwrap_err());
+        assert_eq!(Some('A'), simple_fold('@').unwrap_err());
+        assert_eq!(Some('a'), simple_fold('[').unwrap_err());
+        assert_eq!(Some('Ⰰ'), simple_fold('☃').unwrap_err());
+    }
+
+    #[test]
+    fn simple_fold_max() {
+        assert_eq!(None, simple_fold('\u{10FFFE}').unwrap_err());
+        assert_eq!(None, simple_fold('\u{10FFFF}').unwrap_err());
+    }
+
+    #[test]
+    fn range_contains() {
+        assert!(contains_simple_case_mapping('A', 'A'));
+        assert!(contains_simple_case_mapping('Z', 'Z'));
+        assert!(contains_simple_case_mapping('A', 'Z'));
+        assert!(contains_simple_case_mapping('@', 'A'));
+        assert!(contains_simple_case_mapping('Z', '['));
+        assert!(contains_simple_case_mapping('☃', 'Ⰰ'));
+
+        assert!(!contains_simple_case_mapping('[', '['));
+        assert!(!contains_simple_case_mapping('[', '`'));
+
+        assert!(!contains_simple_case_mapping('☃', '☃'));
+    }
+
+    #[test]
+    fn regression_466() {
+        use super::{CanonicalClassQuery, ClassQuery};
+
+        let q = ClassQuery::OneLetter('C');
+        assert_eq!(
+            q.canonicalize().unwrap(),
+            CanonicalClassQuery::GeneralCategory("Other"));
+    }
+}
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/age.rs b/third_party/rust/regex-syntax/src/unicode_tables/age.rs
new file mode 100644
index 000000000000..8e2cd0a9fb56
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/age.rs
@@ -0,0 +1,455 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate age tmp/ucd-11.0.0/ --chars
+//
+// ucd-generate is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
+  ("V10_0", V10_0), ("V11_0", V11_0), ("V1_1", V1_1), ("V2_0", V2_0),
+  ("V2_1", V2_1), ("V3_0", V3_0), ("V3_1", V3_1), ("V3_2", V3_2),
+  ("V4_0", V4_0), ("V4_1", V4_1), ("V5_0", V5_0), ("V5_1", V5_1),
+  ("V5_2", V5_2), ("V6_0", V6_0), ("V6_1", V6_1), ("V6_2", V6_2),
+  ("V6_3", V6_3), ("V7_0", V7_0), ("V8_0", V8_0), ("V9_0", V9_0),
+];
+
+pub const V10_0: &'static [(char, char)] = &[
+  ('ࡠ', 'ࡪ'), ('ৼ', '৽'), ('ૺ', '૿'), ('ഀ', 'ഀ'),
+  ('഻', '഼'), ('᳷', '᳷'), ('᷶', '᷹'), ('₿', '₿'),
+  ('⏿', '⏿'), ('⯒', '⯒'), ('⹅', '⹉'), ('ㄮ', 'ㄮ'),
+  ('鿖', '鿪'), ('𐌭', '𐌯'), ('𑨀', '𑩇'), ('𑩐', '𑪃'),
+  ('𑪆', '𑪜'), ('𑪞', '𑪢'), ('𑴀', '𑴆'), ('𑴈', '𑴉'),
+  ('𑴋', '𑴶'), ('𑴺', '𑴺'), ('𑴼', '𑴽'), ('𑴿', '𑵇'),
+  ('𑵐', '𑵙'), ('𖿡', '𖿡'), ('𛀂', '𛄞'), ('𛅰', '𛋻'),
+  ('🉠', '🉥'), ('🛓', '🛔'), ('🛷', '🛸'), ('🤀', '🤋'),
+  ('🤟', '🤟'), ('🤨', '🤯'), ('🤱', '🤲'), ('🥌', '🥌'),
+  ('🥟', '🥫'), ('🦒', '🦗'), ('🧐', '🧦'), ('𬺰', '𮯠'),
+];
+
+pub const V11_0: &'static [(char, char)] = &[
+  ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'), ('\u{5ef}', '\u{5ef}'),
+  ('\u{7fd}', '\u{7ff}'), ('\u{8d3}', '\u{8d3}'), ('\u{9fe}', '\u{9fe}'),
+  ('\u{a76}', '\u{a76}'), ('\u{c04}', '\u{c04}'), ('\u{c84}', '\u{c84}'),
+  ('\u{1878}', '\u{1878}'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('\u{2bba}', '\u{2bbc}'),
+  ('\u{2bd3}', '\u{2beb}'), ('\u{2bf0}', '\u{2bfe}'),
+  ('\u{2e4a}', '\u{2e4e}'), ('\u{312f}', '\u{312f}'),
+  ('\u{9feb}', '\u{9fef}'), ('\u{a7af}', '\u{a7af}'),
+  ('\u{a7b8}', '\u{a7b9}'), ('\u{a8fe}', '\u{a8ff}'),
+  ('\u{10a34}', '\u{10a35}'), ('\u{10a48}', '\u{10a48}'),
+  ('\u{10d00}', '\u{10d27}'), ('\u{10d30}', '\u{10d39}'),
+  ('\u{10f00}', '\u{10f27}'), ('\u{10f30}', '\u{10f59}'),
+  ('\u{110cd}', '\u{110cd}'), ('\u{11144}', '\u{11146}'),
+  ('\u{1133b}', '\u{1133b}'), ('\u{1145e}', '\u{1145e}'),
+  ('\u{1171a}', '\u{1171a}'), ('\u{11800}', '\u{1183b}'),
+  ('\u{11a9d}', '\u{11a9d}'), ('\u{11d60}', '\u{11d65}'),
+  ('\u{11d67}', '\u{11d68}'), ('\u{11d6a}', '\u{11d8e}'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d93}', '\u{11d98}'),
+  ('\u{11da0}', '\u{11da9}'), ('\u{11ee0}', '\u{11ef8}'),
+  ('\u{16e40}', '\u{16e9a}'), ('\u{187ed}', '\u{187f1}'),
+  ('\u{1d2e0}', '\u{1d2f3}'), ('\u{1d372}', '\u{1d378}'),
+  ('\u{1ec71}', '\u{1ecb4}'), ('\u{1f12f}', '\u{1f12f}'),
+  ('\u{1f6f9}', '\u{1f6f9}'), ('\u{1f7d5}', '\u{1f7d8}'),
+  ('\u{1f94d}', '\u{1f94f}'), ('\u{1f96c}', '\u{1f970}'),
+  ('\u{1f973}', '\u{1f976}'), ('\u{1f97a}', '\u{1f97a}'),
+  ('\u{1f97c}', '\u{1f97f}'), ('\u{1f998}', '\u{1f9a2}'),
+  ('\u{1f9b0}', '\u{1f9b9}'), ('\u{1f9c1}', '\u{1f9c2}'),
+  ('\u{1f9e7}', '\u{1f9ff}'), ('\u{1fa60}', '\u{1fa6d}'),
+];
+
+pub const V1_1: &'static [(char, char)] = &[
+  ('\u{0}', 'ǵ'), ('Ǻ', 'ȗ'), ('ɐ', 'ʨ'), ('ʰ', '˞'), ('ˠ', '˩'),
+  ('̀', 'ͅ'), ('͠', '͡'), ('ʹ', '͵'), ('ͺ', 'ͺ'), (';', ';'),
+  ('΄', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'), ('Σ', 'ώ'), ('ϐ', 'ϖ'),
+  ('Ϛ', 'Ϛ'), ('Ϝ', 'Ϝ'), ('Ϟ', 'Ϟ'), ('Ϡ', 'Ϡ'), ('Ϣ', 'ϳ'),
+  ('Ё', 'Ќ'), ('Ў', 'я'), ('ё', 'ќ'), ('ў', '҆'), ('Ґ', 'ӄ'),
+  ('Ӈ', 'ӈ'), ('Ӌ', 'ӌ'), ('Ӑ', 'ӫ'), ('Ӯ', 'ӵ'), ('Ӹ', 'ӹ'),
+  ('Ա', 'Ֆ'), ('ՙ', '՟'), ('ա', 'և'), ('։', '։'), ('ְ', 'ֹ'),
+  ('ֻ', '׃'), ('א', 'ת'), ('װ', '״'), ('،', '،'), ('؛', '؛'),
+  ('؟', '؟'), ('ء', 'غ'), ('ـ', 'ْ'), ('٠', '٭'), ('ٰ', 'ڷ'),
+  ('ں', 'ھ'), ('ۀ', 'ێ'), ('ې', 'ۭ'), ('۰', '۹'), ('ँ', 'ः'),
+  ('अ', 'ह'), ('़', '्'), ('ॐ', '॔'), ('क़', '॰'),
+  ('ঁ', 'ঃ'), ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'),
+  ('প', 'র'), ('ল', 'ল'), ('শ', 'হ'), ('়', '়'),
+  ('া', 'ৄ'), ('ে', 'ৈ'), ('ো', '্'), ('ৗ', 'ৗ'),
+  ('ড়', 'ঢ়'), ('য়', 'ৣ'), ('০', '৺'), ('ਂ', 'ਂ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('਼', '਼'),
+  ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('੦', 'ੴ'), ('ઁ', 'ઃ'), ('અ', 'ઋ'),
+  ('ઍ', 'ઍ'), ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'),
+  ('લ', 'ળ'), ('વ', 'હ'), ('઼', 'ૅ'), ('ે', 'ૉ'),
+  ('ો', '્'), ('ૐ', 'ૐ'), ('ૠ', 'ૠ'), ('૦', '૯'),
+  ('ଁ', 'ଃ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'),
+  ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଶ', 'ହ'), ('଼', 'ୃ'),
+  ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୡ'), ('୦', '୰'), ('ஂ', 'ஃ'), ('அ', 'ஊ'),
+  ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'),
+  ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'), ('ம', 'வ'),
+  ('ஷ', 'ஹ'), ('ா', 'ூ'), ('ெ', 'ை'), ('ொ', '்'),
+  ('ௗ', 'ௗ'), ('௧', '௲'), ('ఁ', 'ః'), ('అ', 'ఌ'),
+  ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'ళ'), ('వ', 'హ'),
+  ('ా', 'ౄ'), ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'),
+  ('ౠ', 'ౡ'), ('౦', '౯'), ('ಂ', 'ಃ'), ('ಅ', 'ಌ'),
+  ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'), ('ವ', 'ಹ'),
+  ('ಾ', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', '್'), ('ೕ', 'ೖ'),
+  ('ೞ', 'ೞ'), ('ೠ', 'ೡ'), ('೦', '೯'), ('ം', 'ഃ'),
+  ('അ', 'ഌ'), ('എ', 'ഐ'), ('ഒ', 'ന'), ('പ', 'ഹ'),
+  ('ാ', 'ൃ'), ('െ', 'ൈ'), ('ൊ', '്'), ('ൗ', 'ൗ'),
+  ('ൠ', 'ൡ'), ('൦', '൯'), ('ก', 'ฺ'), ('฿', '๛'),
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ູ'),
+  ('ົ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('່', 'ໍ'),
+  ('໐', '໙'), ('ໜ', 'ໝ'), ('Ⴀ', 'Ⴥ'), ('ა', 'ჶ'),
+  ('჻', '჻'), ('ᄀ', 'ᅙ'), ('ᅟ', 'ᆢ'), ('ᆨ', 'ᇹ'),
+  ('Ḁ', 'ẚ'), ('Ạ', 'ỹ'), ('ἀ', 'ἕ'), ('Ἐ', 'Ἕ'),
+  ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'),
+  ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'),
+  ('ᾶ', 'ῄ'), ('ῆ', 'ΐ'), ('ῖ', 'Ί'), ('῝', '`'),
+  ('ῲ', 'ῴ'), ('ῶ', '῾'), ('\u{2000}', '\u{202e}'), ('‰', '⁆'),
+  ('\u{206a}', '⁰'), ('⁴', '₎'), ('₠', '₪'), ('⃐', '⃡'),
+  ('℀', 'ℸ'), ('⅓', 'ↂ'), ('←', '⇪'), ('∀', '⋱'),
+  ('⌀', '⌀'), ('⌂', '⍺'), ('␀', '␤'), ('⑀', '⑊'),
+  ('①', '⓪'), ('─', '▕'), ('■', '◯'), ('☀', '☓'),
+  ('☚', '♯'), ('✁', '✄'), ('✆', '✉'), ('✌', '✧'),
+  ('✩', '❋'), ('❍', '❍'), ('❏', '❒'), ('❖', '❖'),
+  ('❘', '❞'), ('❡', '❧'), ('❶', '➔'), ('➘', '➯'),
+  ('➱', '➾'), ('\u{3000}', '〷'), ('〿', '〿'), ('ぁ', 'ゔ'),
+  ('゙', 'ゞ'), ('ァ', 'ヾ'), ('ㄅ', 'ㄬ'), ('ㄱ', 'ㆎ'),
+  ('㆐', '㆟'), ('㈀', '㈜'), ('㈠', '㉃'), ('㉠', '㉻'),
+  ('㉿', '㊰'), ('㋀', '㋋'), ('㋐', '㋾'), ('㌀', '㍶'),
+  ('㍻', '㏝'), ('㏠', '㏾'), ('一', '龥'), ('\u{e000}', '鶴'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('ﬞ', 'זּ'), ('טּ', 'לּ'),
+  ('מּ', 'מּ'), ('נּ', 'סּ'), ('ףּ', 'פּ'), ('צּ', 'ﮱ'),
+  ('ﯓ', '﴿'), ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'),
+  ('︠', '︣'), ('︰', '﹄'), ('﹉', '﹒'), ('﹔', '﹦'),
+  ('﹨', '﹫'), ('ﹰ', 'ﹲ'), ('ﹴ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('\u{feff}', '\u{feff}'), ('！', '～'), ('｡', 'ﾾ'), ('ￂ', 'ￇ'),
+  ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('￠', '￦'),
+  ('￨', '￮'), ('�', '\u{ffff}'),
+];
+
+pub const V2_0: &'static [(char, char)] = &[
+  ('֑', '֡'), ('֣', '֯'), ('ׄ', 'ׄ'), ('ༀ', 'ཇ'), ('ཉ', 'ཀྵ'),
+  ('ཱ', 'ྋ'), ('ྐ', 'ྕ'), ('ྗ', 'ྗ'), ('ྙ', 'ྭ'),
+  ('ྱ', 'ྷ'), ('ྐྵ', 'ྐྵ'), ('ẛ', 'ẛ'), ('₫', '₫'),
+  ('가', '힣'), ('\u{1fffe}', '\u{1ffff}'), ('\u{2fffe}', '\u{2ffff}'),
+  ('\u{3fffe}', '\u{3ffff}'), ('\u{4fffe}', '\u{4ffff}'),
+  ('\u{5fffe}', '\u{5ffff}'), ('\u{6fffe}', '\u{6ffff}'),
+  ('\u{7fffe}', '\u{7ffff}'), ('\u{8fffe}', '\u{8ffff}'),
+  ('\u{9fffe}', '\u{9ffff}'), ('\u{afffe}', '\u{affff}'),
+  ('\u{bfffe}', '\u{bffff}'), ('\u{cfffe}', '\u{cffff}'),
+  ('\u{dfffe}', '\u{dffff}'), ('\u{efffe}', '\u{10ffff}'),
+];
+
+pub const V2_1: &'static [(char, char)] = &[
+  ('€', '€'), ('￼', '￼'),
+];
+
+pub const V3_0: &'static [(char, char)] = &[
+  ('Ƕ', 'ǹ'), ('Ș', 'ȟ'), ('Ȣ', 'ȳ'), ('ʩ', 'ʭ'), ('˟', '˟'),
+  ('˪', 'ˮ'), ('͆', '͎'), ('͢', '͢'), ('ϗ', 'ϗ'), ('ϛ', 'ϛ'),
+  ('ϝ', 'ϝ'), ('ϟ', 'ϟ'), ('ϡ', 'ϡ'), ('Ѐ', 'Ѐ'), ('Ѝ', 'Ѝ'),
+  ('ѐ', 'ѐ'), ('ѝ', 'ѝ'), ('҈', '҉'), ('Ҍ', 'ҏ'), ('Ӭ', 'ӭ'),
+  ('֊', '֊'), ('ٓ', 'ٕ'), ('ڸ', 'ڹ'), ('ڿ', 'ڿ'), ('ۏ', 'ۏ'),
+  ('ۺ', '۾'), ('܀', '܍'), ('\u{70f}', 'ܬ'), ('ܰ', '݊'), ('ހ', 'ް'),
+  ('ං', 'ඃ'), ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'),
+  ('ල', 'ල'), ('ව', 'ෆ'), ('්', '්'), ('ා', 'ු'),
+  ('ූ', 'ූ'), ('ෘ', 'ෟ'), ('ෲ', '෴'), ('ཪ', 'ཪ'),
+  ('ྖ', 'ྖ'), ('ྮ', 'ྰ'), ('ྸ', 'ྸ'), ('ྺ', 'ྼ'),
+  ('྾', '࿌'), ('࿏', '࿏'), ('က', 'အ'), ('ဣ', 'ဧ'),
+  ('ဩ', 'ဪ'), ('ာ', 'ဲ'), ('ံ', '္'), ('၀', 'ၙ'),
+  ('ሀ', 'ሆ'), ('ለ', 'ቆ'), ('ቈ', 'ቈ'), ('ቊ', 'ቍ'),
+  ('ቐ', 'ቖ'), ('ቘ', 'ቘ'), ('ቚ', 'ቝ'), ('በ', 'ኆ'),
+  ('ኈ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኮ'), ('ኰ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዎ'), ('ዐ', 'ዖ'), ('ዘ', 'ዮ'), ('ደ', 'ጎ'),
+  ('ጐ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ጞ'), ('ጠ', 'ፆ'),
+  ('ፈ', 'ፚ'), ('፡', '፼'), ('Ꭰ', 'Ᏼ'), ('ᐁ', 'ᙶ'),
+  ('\u{1680}', '᚜'), ('ᚠ', 'ᛰ'), ('ក', 'ៜ'), ('០', '៩'),
+  ('᠀', '\u{180e}'), ('᠐', '᠙'), ('ᠠ', 'ᡷ'), ('ᢀ', 'ᢩ'),
+  ('\u{202f}', '\u{202f}'), ('⁈', '⁍'), ('₭', '₯'), ('⃢', '⃣'),
+  ('ℹ', '℺'), ('Ↄ', 'Ↄ'), ('⇫', '⇳'), ('⌁', '⌁'),
+  ('⍻', '⍻'), ('⍽', '⎚'), ('␥', '␦'), ('◰', '◷'),
+  ('☙', '☙'), ('♰', '♱'), ('⠀', '⣿'), ('⺀', '⺙'),
+  ('⺛', '⻳'), ('⼀', '⿕'), ('⿰', '⿻'), ('〸', '〺'),
+  ('〾', '〾'), ('ㆠ', 'ㆷ'), ('㐀', '䶵'), ('ꀀ', 'ꒌ'),
+  ('꒐', '꒡'), ('꒤', '꒳'), ('꒵', '꓀'), ('꓂', '꓄'),
+  ('꓆', '꓆'), ('יִ', 'יִ'), ('\u{fff9}', '\u{fffb}'),
+];
+
+pub const V3_1: &'static [(char, char)] = &[
+  ('ϴ', 'ϵ'), ('\u{fdd0}', '\u{fdef}'), ('𐌀', '𐌞'), ('𐌠', '𐌣'),
+  ('𐌰', '𐍊'), ('𐐀', '𐐥'), ('𐐨', '𐑍'), ('𝀀', '𝃵'),
+  ('𝄀', '𝄦'), ('𝄪', '𝇝'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓀'), ('𝓂', '𝓃'),
+  ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕒', '𝚣'), ('𝚨', '𝟉'), ('𝟎', '𝟿'),
+  ('𠀀', '𪛖'), ('丽', '𪘀'), ('\u{e0001}', '\u{e0001}'),
+  ('\u{e0020}', '\u{e007f}'),
+];
+
+pub const V3_2: &'static [(char, char)] = &[
+  ('Ƞ', 'Ƞ'), ('͏', '͏'), ('ͣ', 'ͯ'), ('Ϙ', 'ϙ'), ('϶', '϶'),
+  ('Ҋ', 'ҋ'), ('Ӆ', 'ӆ'), ('Ӊ', 'ӊ'), ('Ӎ', 'ӎ'), ('Ԁ', 'ԏ'),
+  ('ٮ', 'ٯ'), ('ޱ', 'ޱ'), ('ჷ', 'ჸ'), ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'),
+  ('ᜠ', '᜶'), ('ᝀ', 'ᝓ'), ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'),
+  ('ᝲ', 'ᝳ'), ('⁇', '⁇'), ('⁎', '⁒'), ('⁗', '⁗'),
+  ('\u{205f}', '\u{2063}'), ('ⁱ', 'ⁱ'), ('₰', '₱'), ('⃤', '⃪'),
+  ('ℽ', '⅋'), ('⇴', '⇿'), ('⋲', '⋿'), ('⍼', '⍼'),
+  ('⎛', '⏎'), ('⓫', '⓾'), ('▖', '▟'), ('◸', '◿'),
+  ('☖', '☗'), ('♲', '♽'), ('⚀', '⚉'), ('❨', '❵'),
+  ('⟐', '⟫'), ('⟰', '⟿'), ('⤀', '⫿'), ('〻', '〽'),
+  ('ゕ', 'ゖ'), ('ゟ', '゠'), ('ヿ', 'ヿ'), ('ㇰ', 'ㇿ'),
+  ('㉑', '㉟'), ('㊱', '㊿'), ('꒢', '꒣'), ('꒴', '꒴'),
+  ('꓁', '꓁'), ('꓅', '꓅'), ('侮', '頻'), ('﷼', '﷼'),
+  ('︀', '️'), ('﹅', '﹆'), ('ﹳ', 'ﹳ'), ('｟', '｠'),
+];
+
+pub const V4_0: &'static [(char, char)] = &[
+  ('ȡ', 'ȡ'), ('ȴ', 'ȶ'), ('ʮ', 'ʯ'), ('˯', '˿'), ('͐', '͗'),
+  ('͝', '͟'), ('Ϸ', 'ϻ'), ('\u{600}', '\u{603}'), ('؍', 'ؕ'),
+  ('ٖ', '٘'), ('ۮ', 'ۯ'), ('ۿ', 'ۿ'), ('ܭ', 'ܯ'), ('ݍ', 'ݏ'),
+  ('ऄ', 'ऄ'), ('ঽ', 'ঽ'), ('ਁ', 'ਁ'), ('ਃ', 'ਃ'),
+  ('ઌ', 'ઌ'), ('ૡ', 'ૣ'), ('૱', '૱'), ('ଵ', 'ଵ'),
+  ('ୱ', 'ୱ'), ('௳', '௺'), ('಼', 'ಽ'), ('៝', '៝'),
+  ('៰', '៹'), ('ᤀ', 'ᤜ'), ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'),
+  ('᥀', '᥀'), ('᥄', 'ᥭ'), ('ᥰ', 'ᥴ'), ('᧠', '᧿'),
+  ('ᴀ', 'ᵫ'), ('⁓', '⁔'), ('℻', '℻'), ('⏏', '⏐'),
+  ('⓿', '⓿'), ('☔', '☕'), ('⚊', '⚑'), ('⚠', '⚡'),
+  ('⬀', '⬍'), ('㈝', '㈞'), ('㉐', '㉐'), ('㉼', '㉽'),
+  ('㋌', '㋏'), ('㍷', '㍺'), ('㏞', '㏟'), ('㏿', '㏿'),
+  ('䷀', '䷿'), ('﷽', '﷽'), ('﹇', '﹈'), ('𐀀', '𐀋'),
+  ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'),
+  ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐄀', '𐄂'), ('𐄇', '𐄳'),
+  ('𐄷', '𐄿'), ('𐎀', '𐎝'), ('𐎟', '𐎟'), ('𐐦', '𐐧'),
+  ('𐑎', '𐒝'), ('𐒠', '𐒩'), ('𐠀', '𐠅'), ('𐠈', '𐠈'),
+  ('𐠊', '𐠵'), ('𐠷', '𐠸'), ('𐠼', '𐠼'), ('𐠿', '𐠿'),
+  ('𝌀', '𝍖'), ('𝓁', '𝓁'), ('󠄀', '󠇯'),
+];
+
+pub const V4_1: &'static [(char, char)] = &[
+  ('ȷ', 'Ɂ'), ('͘', '͜'), ('ϼ', 'Ͽ'), ('Ӷ', 'ӷ'), ('֢', '֢'),
+  ('ׅ', 'ׇ'), ('؋', '؋'), ('؞', '؞'), ('ٙ', 'ٞ'), ('ݐ', 'ݭ'),
+  ('ॽ', 'ॽ'), ('ৎ', 'ৎ'), ('ஶ', 'ஶ'), ('௦', '௦'),
+  ('࿐', '࿑'), ('ჹ', 'ჺ'), ('ჼ', 'ჼ'), ('ሇ', 'ሇ'),
+  ('ቇ', 'ቇ'), ('ኇ', 'ኇ'), ('ኯ', 'ኯ'), ('ዏ', 'ዏ'),
+  ('ዯ', 'ዯ'), ('ጏ', 'ጏ'), ('ጟ', 'ጟ'), ('ፇ', 'ፇ'),
+  ('፟', '፠'), ('ᎀ', '᎙'), ('ᦀ', 'ᦩ'), ('ᦰ', 'ᧉ'),
+  ('᧐', '᧙'), ('᧞', '᧟'), ('ᨀ', 'ᨛ'), ('᨞', '᨟'),
+  ('ᵬ', '᷃'), ('⁕', '⁖'), ('⁘', '⁞'), ('ₐ', 'ₔ'),
+  ('₲', '₵'), ('⃫', '⃫'), ('ℼ', 'ℼ'), ('⅌', '⅌'),
+  ('⏑', '⏛'), ('☘', '☘'), ('♾', '♿'), ('⚒', '⚜'),
+  ('⚢', '⚱'), ('⟀', '⟆'), ('⬎', '⬓'), ('Ⰰ', 'Ⱞ'),
+  ('ⰰ', 'ⱞ'), ('Ⲁ', '⳪'), ('⳹', 'ⴥ'), ('ⴰ', 'ⵥ'),
+  ('ⵯ', 'ⵯ'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'),
+  ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'),
+  ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('⸀', '⸗'), ('⸜', '⸝'),
+  ('㇀', '㇏'), ('㉾', '㉾'), ('龦', '龻'), ('꜀', '꜖'),
+  ('ꠀ', '꠫'), ('並', '龎'), ('︐', '︙'), ('𐅀', '𐆊'),
+  ('𐎠', '𐏃'), ('𐏈', '𐏕'), ('𐨀', '𐨃'), ('𐨅', '𐨆'),
+  ('𐨌', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '𐨳'), ('𐨸', '𐨺'),
+  ('𐨿', '𐩇'), ('𐩐', '𐩘'), ('𝈀', '𝉅'), ('𝚤', '𝚥'),
+];
+
+pub const V5_0: &'static [(char, char)] = &[
+  ('ɂ', 'ɏ'), ('ͻ', 'ͽ'), ('ӏ', 'ӏ'), ('Ӻ', 'ӿ'), ('Ԑ', 'ԓ'),
+  ('ֺ', 'ֺ'), ('߀', 'ߺ'), ('ॻ', 'ॼ'), ('ॾ', 'ॿ'), ('ೢ', 'ೣ'),
+  ('ೱ', 'ೲ'), ('ᬀ', 'ᭋ'), ('᭐', '᭼'), ('᷄', '᷊'),
+  ('᷾', '᷿'), ('⃬', '⃯'), ('⅍', 'ⅎ'), ('ↄ', 'ↄ'),
+  ('⏜', '⏧'), ('⚲', '⚲'), ('⟇', '⟊'), ('⬔', '⬚'),
+  ('⬠', '⬣'), ('Ⱡ', 'ⱬ'), ('ⱴ', 'ⱷ'), ('ꜗ', 'ꜚ'),
+  ('꜠', '꜡'), ('ꡀ', '꡷'), ('𐤀', '𐤙'), ('𐤟', '𐤟'),
+  ('𒀀', '𒍮'), ('𒐀', '𒑢'), ('𒑰', '𒑳'), ('𝍠', '𝍱'),
+  ('𝟊', '𝟋'),
+];
+
+pub const V5_1: &'static [(char, char)] = &[
+  ('Ͱ', 'ͳ'), ('Ͷ', 'ͷ'), ('Ϗ', 'Ϗ'), ('҇', '҇'), ('Ԕ', 'ԣ'),
+  ('؆', '؊'), ('ؖ', 'ؚ'), ('ػ', 'ؿ'), ('ݮ', 'ݿ'), ('ॱ', 'ॲ'),
+  ('ੑ', 'ੑ'), ('ੵ', 'ੵ'), ('ୄ', 'ୄ'), ('ୢ', 'ୣ'),
+  ('ௐ', 'ௐ'), ('ఽ', 'ఽ'), ('ౘ', 'ౙ'), ('ౢ', 'ౣ'),
+  ('౸', '౿'), ('ഽ', 'ഽ'), ('ൄ', 'ൄ'), ('ൢ', 'ൣ'),
+  ('൰', '൵'), ('൹', 'ൿ'), ('ཫ', 'ཬ'), ('࿎', '࿎'),
+  ('࿒', '࿔'), ('ဢ', 'ဢ'), ('ဨ', 'ဨ'), ('ါ', 'ါ'),
+  ('ဳ', 'ဵ'), ('်', 'ဿ'), ('ၚ', '႙'), ('႞', '႟'),
+  ('ᢪ', 'ᢪ'), ('ᮀ', '᮪'), ('ᮮ', '᮹'), ('ᰀ', '᰷'),
+  ('᰻', '᱉'), ('ᱍ', '᱿'), ('᷋', 'ᷦ'), ('ẜ', 'ẟ'),
+  ('Ỻ', 'ỿ'), ('\u{2064}', '\u{2064}'), ('⃰', '⃰'), ('⅏', '⅏'),
+  ('ↅ', 'ↈ'), ('⚝', '⚝'), ('⚳', '⚼'), ('⛀', '⛃'),
+  ('⟌', '⟌'), ('⟬', '⟯'), ('⬛', '⬟'), ('⬤', '⭌'),
+  ('⭐', '⭔'), ('Ɑ', 'Ɐ'), ('ⱱ', 'ⱳ'), ('ⱸ', 'ⱽ'),
+  ('ⷠ', 'ⷿ'), ('⸘', '⸛'), ('⸞', '⸰'), ('ㄭ', 'ㄭ'),
+  ('㇐', '㇣'), ('龼', '鿃'), ('ꔀ', 'ꘫ'), ('Ꙁ', 'ꙟ'),
+  ('Ꙣ', '꙳'), ('꙼', 'ꚗ'), ('ꜛ', 'ꜟ'), ('Ꜣ', 'ꞌ'),
+  ('ꟻ', 'ꟿ'), ('ꢀ', '꣄'), ('꣎', '꣙'), ('꤀', '꥓'),
+  ('꥟', '꥟'), ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'), ('꩐', '꩙'),
+  ('꩜', '꩟'), ('︤', '︦'), ('𐆐', '𐆛'), ('𐇐', '𐇽'),
+  ('𐊀', '𐊜'), ('𐊠', '𐋐'), ('𐤠', '𐤹'), ('𐤿', '𐤿'),
+  ('𝄩', '𝄩'), ('🀀', '🀫'), ('🀰', '🂓'),
+];
+
+pub const V5_2: &'static [(char, char)] = &[
+  ('Ԥ', 'ԥ'), ('ࠀ', '࠭'), ('࠰', '࠾'), ('ऀ', 'ऀ'),
+  ('ॎ', 'ॎ'), ('ॕ', 'ॕ'), ('ॹ', 'ॺ'), ('৻', '৻'),
+  ('࿕', '࿘'), ('ႚ', 'ႝ'), ('ᅚ', 'ᅞ'), ('ᆣ', 'ᆧ'),
+  ('ᇺ', 'ᇿ'), ('᐀', '᐀'), ('ᙷ', 'ᙿ'), ('ᢰ', 'ᣵ'),
+  ('ᦪ', 'ᦫ'), ('᧚', '᧚'), ('ᨠ', 'ᩞ'), ('᩠', '᩼'),
+  ('᩿', '᪉'), ('᪐', '᪙'), ('᪠', '᪭'), ('᳐', 'ᳲ'),
+  ('᷽', '᷽'), ('₶', '₸'), ('⅐', '⅒'), ('↉', '↉'),
+  ('⏨', '⏨'), ('⚞', '⚟'), ('⚽', '⚿'), ('⛄', '⛍'),
+  ('⛏', '⛡'), ('⛣', '⛣'), ('⛨', '⛿'), ('❗', '❗'),
+  ('⭕', '⭙'), ('Ɒ', 'Ɒ'), ('Ȿ', 'Ɀ'), ('Ⳬ', '⳱'),
+  ('⸱', '⸱'), ('㉄', '㉏'), ('鿄', '鿋'), ('ꓐ', '꓿'),
+  ('ꚠ', '꛷'), ('꠰', '꠹'), ('꣠', 'ꣻ'), ('ꥠ', 'ꥼ'),
+  ('ꦀ', '꧍'), ('ꧏ', '꧙'), ('꧞', '꧟'), ('ꩠ', 'ꩻ'),
+  ('ꪀ', 'ꫂ'), ('ꫛ', '꫟'), ('ꯀ', '꯭'), ('꯰', '꯹'),
+  ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('恵', '舘'), ('𐡀', '𐡕'),
+  ('𐡗', '𐡟'), ('𐤚', '𐤛'), ('𐩠', '𐩿'), ('𐬀', '𐬵'),
+  ('𐬹', '𐭕'), ('𐭘', '𐭲'), ('𐭸', '𐭿'), ('𐰀', '𐱈'),
+  ('𐹠', '𐹾'), ('𑂀', '𑃁'), ('𓀀', '𓐮'), ('🄀', '🄊'),
+  ('🄐', '🄮'), ('🄱', '🄱'), ('🄽', '🄽'), ('🄿', '🄿'),
+  ('🅂', '🅂'), ('🅆', '🅆'), ('🅊', '🅎'), ('🅗', '🅗'),
+  ('🅟', '🅟'), ('🅹', '🅹'), ('🅻', '🅼'), ('🅿', '🅿'),
+  ('🆊', '🆍'), ('🆐', '🆐'), ('🈀', '🈀'), ('🈐', '🈱'),
+  ('🉀', '🉈'), ('𪜀', '𫜴'),
+];
+
+pub const V6_0: &'static [(char, char)] = &[
+  ('Ԧ', 'ԧ'), ('ؠ', 'ؠ'), ('ٟ', 'ٟ'), ('ࡀ', '࡛'), ('࡞', '࡞'),
+  ('ऺ', 'ऻ'), ('ॏ', 'ॏ'), ('ॖ', 'ॗ'), ('ॳ', 'ॷ'),
+  ('୲', '୷'), ('ഩ', 'ഩ'), ('ഺ', 'ഺ'), ('ൎ', 'ൎ'),
+  ('ྌ', 'ྏ'), ('࿙', '࿚'), ('፝', '፞'), ('ᯀ', '᯳'),
+  ('᯼', '᯿'), ('᷼', '᷼'), ('ₕ', 'ₜ'), ('₹', '₹'),
+  ('⏩', '⏳'), ('⛎', '⛎'), ('⛢', '⛢'), ('⛤', '⛧'),
+  ('✅', '✅'), ('✊', '✋'), ('✨', '✨'), ('❌', '❌'),
+  ('❎', '❎'), ('❓', '❕'), ('❟', '❠'), ('➕', '➗'),
+  ('➰', '➰'), ('➿', '➿'), ('⟎', '⟏'), ('⵰', '⵰'),
+  ('⵿', '⵿'), ('ㆸ', 'ㆺ'), ('Ꙡ', 'ꙡ'), ('Ɥ', 'ꞎ'),
+  ('Ꞑ', 'ꞑ'), ('Ꞡ', 'ꞩ'), ('ꟺ', 'ꟺ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+  ('﮲', '﯁'), ('𑀀', '𑁍'), ('𑁒', '𑁯'), ('𖠀', '𖨸'),
+  ('𛀀', '𛀁'), ('🂠', '🂮'), ('🂱', '🂾'), ('🃁', '🃏'),
+  ('🃑', '🃟'), ('🄰', '🄰'), ('🄲', '🄼'), ('🄾', '🄾'),
+  ('🅀', '🅁'), ('🅃', '🅅'), ('🅇', '🅉'), ('🅏', '🅖'),
+  ('🅘', '🅞'), ('🅠', '🅩'), ('🅰', '🅸'), ('🅺', '🅺'),
+  ('🅽', '🅾'), ('🆀', '🆉'), ('🆎', '🆏'), ('🆑', '🆚'),
+  ('🇦', '🇿'), ('🈁', '🈂'), ('🈲', '🈺'), ('🉐', '🉑'),
+  ('🌀', '🌠'), ('🌰', '🌵'), ('🌷', '🍼'), ('🎀', '🎓'),
+  ('🎠', '🏄'), ('🏆', '🏊'), ('🏠', '🏰'), ('🐀', '🐾'),
+  ('👀', '👀'), ('👂', '📷'), ('📹', '📼'), ('🔀', '🔽'),
+  ('🕐', '🕧'), ('🗻', '🗿'), ('😁', '😐'), ('😒', '😔'),
+  ('😖', '😖'), ('😘', '😘'), ('😚', '😚'), ('😜', '😞'),
+  ('😠', '😥'), ('😨', '😫'), ('😭', '😭'), ('😰', '😳'),
+  ('😵', '🙀'), ('🙅', '🙏'), ('🚀', '🛅'), ('🜀', '🝳'),
+  ('𫝀', '𫠝'),
+];
+
+pub const V6_1: &'static [(char, char)] = &[
+  ('֏', '֏'), ('\u{604}', '\u{604}'), ('ࢠ', 'ࢠ'), ('ࢢ', 'ࢬ'),
+  ('ࣤ', 'ࣾ'), ('૰', '૰'), ('ໞ', 'ໟ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ჽ', 'ჿ'), ('᮫', 'ᮭ'), ('ᮺ', 'ᮿ'),
+  ('᳀', '᳇'), ('ᳳ', 'ᳶ'), ('⟋', '⟋'), ('⟍', '⟍'),
+  ('Ⳳ', 'ⳳ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ⵦ', 'ⵧ'),
+  ('⸲', '⸻'), ('鿌', '鿌'), ('ꙴ', 'ꙻ'), ('ꚟ', 'ꚟ'),
+  ('Ꞓ', 'ꞓ'), ('Ɦ', 'Ɦ'), ('ꟸ', 'ꟹ'), ('ꫠ', '꫶'),
+  ('郞', '隷'), ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𑃐', '𑃨'),
+  ('𑃰', '𑃹'), ('𑄀', '𑄴'), ('𑄶', '𑅃'), ('𑆀', '𑇈'),
+  ('𑇐', '𑇙'), ('𑚀', '𑚷'), ('𑛀', '𑛉'), ('𖼀', '𖽄'),
+  ('𖽐', '𖽾'), ('𖾏', '𖾟'), ('𞸀', '𞸃'), ('𞸅', '𞸟'),
+  ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'),
+  ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'),
+  ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'),
+  ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'),
+  ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'),
+  ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'),
+  ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'),
+  ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('𞻰', '𞻱'),
+  ('🅪', '🅫'), ('🕀', '🕃'), ('😀', '😀'), ('😑', '😑'),
+  ('😕', '😕'), ('😗', '😗'), ('😙', '😙'), ('😛', '😛'),
+  ('😟', '😟'), ('😦', '😧'), ('😬', '😬'), ('😮', '😯'),
+  ('😴', '😴'),
+];
+
+pub const V6_2: &'static [(char, char)] = &[
+  ('₺', '₺'),
+];
+
+pub const V6_3: &'static [(char, char)] = &[
+  ('\u{61c}', '\u{61c}'), ('\u{2066}', '\u{2069}'),
+];
+
+pub const V7_0: &'static [(char, char)] = &[
+  ('Ϳ', 'Ϳ'), ('Ԩ', 'ԯ'), ('֍', '֎'), ('\u{605}', '\u{605}'),
+  ('ࢡ', 'ࢡ'), ('ࢭ', 'ࢲ'), ('ࣿ', 'ࣿ'), ('ॸ', 'ॸ'),
+  ('ঀ', 'ঀ'), ('ఀ', 'ఀ'), ('ఴ', 'ఴ'), ('ಁ', 'ಁ'),
+  ('ഁ', 'ഁ'), ('෦', '෯'), ('ᛱ', 'ᛸ'), ('ᤝ', 'ᤞ'),
+  ('᪰', '᪾'), ('᳸', '᳹'), ('ᷧ', '᷵'), ('₻', '₽'),
+  ('⏴', '⏺'), ('✀', '✀'), ('⭍', '⭏'), ('⭚', '⭳'),
+  ('⭶', '⮕'), ('⮘', '⮹'), ('⮽', '⯈'), ('⯊', '⯑'),
+  ('⸼', '⹂'), ('Ꚙ', 'ꚝ'), ('ꞔ', 'ꞟ'), ('Ɜ', 'Ɬ'),
+  ('Ʞ', 'Ʇ'), ('ꟷ', 'ꟷ'), ('ꧠ', 'ꧾ'), ('ꩼ', 'ꩿ'),
+  ('ꬰ', 'ꭟ'), ('ꭤ', 'ꭥ'), ('︧', '︭'), ('𐆋', '𐆌'),
+  ('𐆠', '𐆠'), ('𐋠', '𐋻'), ('𐌟', '𐌟'), ('𐍐', '𐍺'),
+  ('𐔀', '𐔧'), ('𐔰', '𐕣'), ('𐕯', '𐕯'), ('𐘀', '𐜶'),
+  ('𐝀', '𐝕'), ('𐝠', '𐝧'), ('𐡠', '𐢞'), ('𐢧', '𐢯'),
+  ('𐪀', '𐪟'), ('𐫀', '𐫦'), ('𐫫', '𐫶'), ('𐮀', '𐮑'),
+  ('𐮙', '𐮜'), ('𐮩', '𐮯'), ('𑁿', '𑁿'), ('𑅐', '𑅶'),
+  ('𑇍', '𑇍'), ('𑇚', '𑇚'), ('𑇡', '𑇴'), ('𑈀', '𑈑'),
+  ('𑈓', '𑈽'), ('𑊰', '𑋪'), ('𑋰', '𑋹'), ('𑌁', '𑌃'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌼', '𑍄'), ('𑍇', '𑍈'),
+  ('𑍋', '𑍍'), ('𑍗', '𑍗'), ('𑍝', '𑍣'), ('𑍦', '𑍬'),
+  ('𑍰', '𑍴'), ('𑒀', '𑓇'), ('𑓐', '𑓙'), ('𑖀', '𑖵'),
+  ('𑖸', '𑗉'), ('𑘀', '𑙄'), ('𑙐', '𑙙'), ('𑢠', '𑣲'),
+  ('𑣿', '𑣿'), ('𑫀', '𑫸'), ('𒍯', '𒎘'), ('𒑣', '𒑮'),
+  ('𒑴', '𒑴'), ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖩮', '𖩯'),
+  ('𖫐', '𖫭'), ('𖫰', '𖫵'), ('𖬀', '𖭅'), ('𖭐', '𖭙'),
+  ('𖭛', '𖭡'), ('𖭣', '𖭷'), ('𖭽', '𖮏'), ('𛰀', '𛱪'),
+  ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲜', '\u{1bca3}'),
+  ('𞠀', '𞣄'), ('𞣇', '𞣖'), ('🂿', '🂿'), ('🃠', '🃵'),
+  ('🄋', '🄌'), ('🌡', '🌬'), ('🌶', '🌶'), ('🍽', '🍽'),
+  ('🎔', '🎟'), ('🏅', '🏅'), ('🏋', '🏎'), ('🏔', '🏟'),
+  ('🏱', '🏷'), ('🐿', '🐿'), ('👁', '👁'), ('📸', '📸'),
+  ('📽', '📾'), ('🔾', '🔿'), ('🕄', '🕊'), ('🕨', '🕹'),
+  ('🕻', '🖣'), ('🖥', '🗺'), ('🙁', '🙂'), ('🙐', '🙿'),
+  ('🛆', '🛏'), ('🛠', '🛬'), ('🛰', '🛳'), ('🞀', '🟔'),
+  ('🠀', '🠋'), ('🠐', '🡇'), ('🡐', '🡙'), ('🡠', '🢇'),
+  ('🢐', '🢭'),
+];
+
+pub const V8_0: &'static [(char, char)] = &[
+  ('ࢳ', 'ࢴ'), ('ࣣ', 'ࣣ'), ('ૹ', 'ૹ'), ('ౚ', 'ౚ'),
+  ('ൟ', 'ൟ'), ('Ᏽ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('₾', '₾'),
+  ('↊', '↋'), ('⯬', '⯯'), ('鿍', '鿕'), ('ꚞ', 'ꚞ'),
+  ('ꞏ', 'ꞏ'), ('Ʝ', 'ꞷ'), ('꣼', 'ꣽ'), ('ꭠ', 'ꭣ'),
+  ('ꭰ', 'ꮿ'), ('︮', '︯'), ('𐣠', '𐣲'), ('𐣴', '𐣵'),
+  ('𐣻', '𐣿'), ('𐦼', '𐦽'), ('𐧀', '𐧏'), ('𐧒', '𐧿'),
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𐳺', '𐳿'), ('𑇉', '𑇌'),
+  ('𑇛', '𑇟'), ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'),
+  ('𑊏', '𑊝'), ('𑊟', '𑊩'), ('𑌀', '𑌀'), ('𑍐', '𑍐'),
+  ('𑗊', '𑗝'), ('𑜀', '𑜙'), ('𑜝', '𑜫'), ('𑜰', '𑜿'),
+  ('𒎙', '𒎙'), ('𒒀', '𒕃'), ('𔐀', '𔙆'), ('𝇞', '𝇨'),
+  ('𝠀', '𝪋'), ('𝪛', '𝪟'), ('𝪡', '𝪯'), ('🌭', '🌯'),
+  ('🍾', '🍿'), ('🏏', '🏓'), ('🏸', '🏿'), ('📿', '📿'),
+  ('🕋', '🕏'), ('🙃', '🙄'), ('🛐', '🛐'), ('🤐', '🤘'),
+  ('🦀', '🦄'), ('🧀', '🧀'), ('𫠠', '𬺡'),
+];
+
+pub const V9_0: &'static [(char, char)] = &[
+  ('ࢶ', 'ࢽ'), ('ࣔ', '\u{8e2}'), ('ಀ', 'ಀ'), ('൏', '൏'),
+  ('ൔ', 'ൖ'), ('൘', '൞'), ('൶', '൸'), ('ᲀ', 'ᲈ'),
+  ('᷻', '᷻'), ('⏻', '⏾'), ('⹃', '⹄'), ('Ɪ', 'Ɪ'),
+  ('ꣅ', 'ꣅ'), ('𐆍', '𐆎'), ('𐒰', '𐓓'), ('𐓘', '𐓻'),
+  ('𑈾', '𑈾'), ('𑐀', '𑑙'), ('𑑛', '𑑛'), ('𑑝', '𑑝'),
+  ('𑙠', '𑙬'), ('𑰀', '𑰈'), ('𑰊', '𑰶'), ('𑰸', '𑱅'),
+  ('𑱐', '𑱬'), ('𑱰', '𑲏'), ('𑲒', '𑲧'), ('𑲩', '𑲶'),
+  ('𖿠', '𖿠'), ('𗀀', '𘟬'), ('𘠀', '𘫲'), ('𞀀', '𞀆'),
+  ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'),
+  ('𞤀', '𞥊'), ('𞥐', '𞥙'), ('𞥞', '𞥟'), ('🆛', '🆬'),
+  ('🈻', '🈻'), ('🕺', '🕺'), ('🖤', '🖤'), ('🛑', '🛒'),
+  ('🛴', '🛶'), ('🤙', '🤞'), ('🤠', '🤧'), ('🤰', '🤰'),
+  ('🤳', '🤾'), ('🥀', '🥋'), ('🥐', '🥞'), ('🦅', '🦑'),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/case_folding_simple.rs b/third_party/rust/regex-syntax/src/unicode_tables/case_folding_simple.rs
new file mode 100644
index 000000000000..bf2f61ec8881
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/case_folding_simple.rs
@@ -0,0 +1,725 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate case-folding-simple tmp/ucd-11.0.0/ --chars --all-pairs
+//
+// ucd-generate is available on crates.io.
+
+pub const CASE_FOLDING_SIMPLE: &'static [(char, &'static [char])] = &[
+  ('A', &['a']), ('B', &['b']), ('C', &['c']), ('D', &['d']), ('E', &['e']),
+  ('F', &['f']), ('G', &['g']), ('H', &['h']), ('I', &['i']), ('J', &['j']),
+  ('K', &['k', 'K', ]), ('L', &['l']), ('M', &['m']), ('N', &['n']), ('O', &[
+  'o']), ('P', &['p']), ('Q', &['q']), ('R', &['r']), ('S', &['s', 'ſ', ]),
+  ('T', &['t']), ('U', &['u']), ('V', &['v']), ('W', &['w']), ('X', &['x']),
+  ('Y', &['y']), ('Z', &['z']), ('a', &['A']), ('b', &['B']), ('c', &['C']),
+  ('d', &['D']), ('e', &['E']), ('f', &['F']), ('g', &['G']), ('h', &['H']),
+  ('i', &['I']), ('j', &['J']), ('k', &['K', 'K', ]), ('l', &['L']), ('m', &[
+  'M']), ('n', &['N']), ('o', &['O']), ('p', &['P']), ('q', &['Q']), ('r', &[
+  'R']), ('s', &['S', 'ſ', ]), ('t', &['T']), ('u', &['U']), ('v', &['V']),
+  ('w', &['W']), ('x', &['X']), ('y', &['Y']), ('z', &['Z']), ('µ', &['Μ',
+  'μ', ]), ('À', &['à']), ('Á', &['á']), ('Â', &['â']), ('Ã', &['ã'
+  ]), ('Ä', &['ä']), ('Å', &['å', 'Å', ]), ('Æ', &['æ']), ('Ç', &['ç'
+  ]), ('È', &['è']), ('É', &['é']), ('Ê', &['ê']), ('Ë', &['ë']),
+  ('Ì', &['ì']), ('Í', &['í']), ('Î', &['î']), ('Ï', &['ï']), ('Ð', &[
+  'ð']), ('Ñ', &['ñ']), ('Ò', &['ò']), ('Ó', &['ó']), ('Ô', &['ô']),
+  ('Õ', &['õ']), ('Ö', &['ö']), ('Ø', &['ø']), ('Ù', &['ù']), ('Ú', &[
+  'ú']), ('Û', &['û']), ('Ü', &['ü']), ('Ý', &['ý']), ('Þ', &['þ']),
+  ('ß', &['ẞ']), ('à', &['À']), ('á', &['Á']), ('â', &['Â']),
+  ('ã', &['Ã']), ('ä', &['Ä']), ('å', &['Å', 'Å', ]), ('æ', &['Æ']),
+  ('ç', &['Ç']), ('è', &['È']), ('é', &['É']), ('ê', &['Ê']), ('ë', &[
+  'Ë']), ('ì', &['Ì']), ('í', &['Í']), ('î', &['Î']), ('ï', &['Ï']),
+  ('ð', &['Ð']), ('ñ', &['Ñ']), ('ò', &['Ò']), ('ó', &['Ó']), ('ô', &[
+  'Ô']), ('õ', &['Õ']), ('ö', &['Ö']), ('ø', &['Ø']), ('ù', &['Ù']),
+  ('ú', &['Ú']), ('û', &['Û']), ('ü', &['Ü']), ('ý', &['Ý']), ('þ', &[
+  'Þ']), ('ÿ', &['Ÿ']), ('Ā', &['ā']), ('ā', &['Ā']), ('Ă', &['ă']),
+  ('ă', &['Ă']), ('Ą', &['ą']), ('ą', &['Ą']), ('Ć', &['ć']), ('ć', &[
+  'Ć']), ('Ĉ', &['ĉ']), ('ĉ', &['Ĉ']), ('Ċ', &['ċ']), ('ċ', &['Ċ']),
+  ('Č', &['č']), ('č', &['Č']), ('Ď', &['ď']), ('ď', &['Ď']), ('Đ', &[
+  'đ']), ('đ', &['Đ']), ('Ē', &['ē']), ('ē', &['Ē']), ('Ĕ', &['ĕ']),
+  ('ĕ', &['Ĕ']), ('Ė', &['ė']), ('ė', &['Ė']), ('Ę', &['ę']), ('ę', &[
+  'Ę']), ('Ě', &['ě']), ('ě', &['Ě']), ('Ĝ', &['ĝ']), ('ĝ', &['Ĝ']),
+  ('Ğ', &['ğ']), ('ğ', &['Ğ']), ('Ġ', &['ġ']), ('ġ', &['Ġ']), ('Ģ', &[
+  'ģ']), ('ģ', &['Ģ']), ('Ĥ', &['ĥ']), ('ĥ', &['Ĥ']), ('Ħ', &['ħ']),
+  ('ħ', &['Ħ']), ('Ĩ', &['ĩ']), ('ĩ', &['Ĩ']), ('Ī', &['ī']), ('ī', &[
+  'Ī']), ('Ĭ', &['ĭ']), ('ĭ', &['Ĭ']), ('Į', &['į']), ('į', &['Į']),
+  ('Ĳ', &['ĳ']), ('ĳ', &['Ĳ']), ('Ĵ', &['ĵ']), ('ĵ', &['Ĵ']), ('Ķ', &[
+  'ķ']), ('ķ', &['Ķ']), ('Ĺ', &['ĺ']), ('ĺ', &['Ĺ']), ('Ļ', &['ļ']),
+  ('ļ', &['Ļ']), ('Ľ', &['ľ']), ('ľ', &['Ľ']), ('Ŀ', &['ŀ']), ('ŀ', &[
+  'Ŀ']), ('Ł', &['ł']), ('ł', &['Ł']), ('Ń', &['ń']), ('ń', &['Ń']),
+  ('Ņ', &['ņ']), ('ņ', &['Ņ']), ('Ň', &['ň']), ('ň', &['Ň']), ('Ŋ', &[
+  'ŋ']), ('ŋ', &['Ŋ']), ('Ō', &['ō']), ('ō', &['Ō']), ('Ŏ', &['ŏ']),
+  ('ŏ', &['Ŏ']), ('Ő', &['ő']), ('ő', &['Ő']), ('Œ', &['œ']), ('œ', &[
+  'Œ']), ('Ŕ', &['ŕ']), ('ŕ', &['Ŕ']), ('Ŗ', &['ŗ']), ('ŗ', &['Ŗ']),
+  ('Ř', &['ř']), ('ř', &['Ř']), ('Ś', &['ś']), ('ś', &['Ś']), ('Ŝ', &[
+  'ŝ']), ('ŝ', &['Ŝ']), ('Ş', &['ş']), ('ş', &['Ş']), ('Š', &['š']),
+  ('š', &['Š']), ('Ţ', &['ţ']), ('ţ', &['Ţ']), ('Ť', &['ť']), ('ť', &[
+  'Ť']), ('Ŧ', &['ŧ']), ('ŧ', &['Ŧ']), ('Ũ', &['ũ']), ('ũ', &['Ũ']),
+  ('Ū', &['ū']), ('ū', &['Ū']), ('Ŭ', &['ŭ']), ('ŭ', &['Ŭ']), ('Ů', &[
+  'ů']), ('ů', &['Ů']), ('Ű', &['ű']), ('ű', &['Ű']), ('Ų', &['ų']),
+  ('ų', &['Ų']), ('Ŵ', &['ŵ']), ('ŵ', &['Ŵ']), ('Ŷ', &['ŷ']), ('ŷ', &[
+  'Ŷ']), ('Ÿ', &['ÿ']), ('Ź', &['ź']), ('ź', &['Ź']), ('Ż', &['ż']),
+  ('ż', &['Ż']), ('Ž', &['ž']), ('ž', &['Ž']), ('ſ', &['S', 's', ]),
+  ('ƀ', &['Ƀ']), ('Ɓ', &['ɓ']), ('Ƃ', &['ƃ']), ('ƃ', &['Ƃ']), ('Ƅ', &[
+  'ƅ']), ('ƅ', &['Ƅ']), ('Ɔ', &['ɔ']), ('Ƈ', &['ƈ']), ('ƈ', &['Ƈ']),
+  ('Ɖ', &['ɖ']), ('Ɗ', &['ɗ']), ('Ƌ', &['ƌ']), ('ƌ', &['Ƌ']), ('Ǝ', &[
+  'ǝ']), ('Ə', &['ə']), ('Ɛ', &['ɛ']), ('Ƒ', &['ƒ']), ('ƒ', &['Ƒ']),
+  ('Ɠ', &['ɠ']), ('Ɣ', &['ɣ']), ('ƕ', &['Ƕ']), ('Ɩ', &['ɩ']), ('Ɨ', &[
+  'ɨ']), ('Ƙ', &['ƙ']), ('ƙ', &['Ƙ']), ('ƚ', &['Ƚ']), ('Ɯ', &['ɯ']),
+  ('Ɲ', &['ɲ']), ('ƞ', &['Ƞ']), ('Ɵ', &['ɵ']), ('Ơ', &['ơ']), ('ơ', &[
+  'Ơ']), ('Ƣ', &['ƣ']), ('ƣ', &['Ƣ']), ('Ƥ', &['ƥ']), ('ƥ', &['Ƥ']),
+  ('Ʀ', &['ʀ']), ('Ƨ', &['ƨ']), ('ƨ', &['Ƨ']), ('Ʃ', &['ʃ']), ('Ƭ', &[
+  'ƭ']), ('ƭ', &['Ƭ']), ('Ʈ', &['ʈ']), ('Ư', &['ư']), ('ư', &['Ư']),
+  ('Ʊ', &['ʊ']), ('Ʋ', &['ʋ']), ('Ƴ', &['ƴ']), ('ƴ', &['Ƴ']), ('Ƶ', &[
+  'ƶ']), ('ƶ', &['Ƶ']), ('Ʒ', &['ʒ']), ('Ƹ', &['ƹ']), ('ƹ', &['Ƹ']),
+  ('Ƽ', &['ƽ']), ('ƽ', &['Ƽ']), ('ƿ', &['Ƿ']), ('Ǆ', &['ǅ', 'ǆ', ]),
+  ('ǅ', &['Ǆ', 'ǆ', ]), ('ǆ', &['Ǆ', 'ǅ', ]), ('Ǉ', &['ǈ', 'ǉ', ]),
+  ('ǈ', &['Ǉ', 'ǉ', ]), ('ǉ', &['Ǉ', 'ǈ', ]), ('Ǌ', &['ǋ', 'ǌ', ]),
+  ('ǋ', &['Ǌ', 'ǌ', ]), ('ǌ', &['Ǌ', 'ǋ', ]), ('Ǎ', &['ǎ']), ('ǎ', &[
+  'Ǎ']), ('Ǐ', &['ǐ']), ('ǐ', &['Ǐ']), ('Ǒ', &['ǒ']), ('ǒ', &['Ǒ']),
+  ('Ǔ', &['ǔ']), ('ǔ', &['Ǔ']), ('Ǖ', &['ǖ']), ('ǖ', &['Ǖ']), ('Ǘ', &[
+  'ǘ']), ('ǘ', &['Ǘ']), ('Ǚ', &['ǚ']), ('ǚ', &['Ǚ']), ('Ǜ', &['ǜ']),
+  ('ǜ', &['Ǜ']), ('ǝ', &['Ǝ']), ('Ǟ', &['ǟ']), ('ǟ', &['Ǟ']), ('Ǡ', &[
+  'ǡ']), ('ǡ', &['Ǡ']), ('Ǣ', &['ǣ']), ('ǣ', &['Ǣ']), ('Ǥ', &['ǥ']),
+  ('ǥ', &['Ǥ']), ('Ǧ', &['ǧ']), ('ǧ', &['Ǧ']), ('Ǩ', &['ǩ']), ('ǩ', &[
+  'Ǩ']), ('Ǫ', &['ǫ']), ('ǫ', &['Ǫ']), ('Ǭ', &['ǭ']), ('ǭ', &['Ǭ']),
+  ('Ǯ', &['ǯ']), ('ǯ', &['Ǯ']), ('Ǳ', &['ǲ', 'ǳ', ]), ('ǲ', &['Ǳ',
+  'ǳ', ]), ('ǳ', &['Ǳ', 'ǲ', ]), ('Ǵ', &['ǵ']), ('ǵ', &['Ǵ']),
+  ('Ƕ', &['ƕ']), ('Ƿ', &['ƿ']), ('Ǹ', &['ǹ']), ('ǹ', &['Ǹ']), ('Ǻ', &[
+  'ǻ']), ('ǻ', &['Ǻ']), ('Ǽ', &['ǽ']), ('ǽ', &['Ǽ']), ('Ǿ', &['ǿ']),
+  ('ǿ', &['Ǿ']), ('Ȁ', &['ȁ']), ('ȁ', &['Ȁ']), ('Ȃ', &['ȃ']), ('ȃ', &[
+  'Ȃ']), ('Ȅ', &['ȅ']), ('ȅ', &['Ȅ']), ('Ȇ', &['ȇ']), ('ȇ', &['Ȇ']),
+  ('Ȉ', &['ȉ']), ('ȉ', &['Ȉ']), ('Ȋ', &['ȋ']), ('ȋ', &['Ȋ']), ('Ȍ', &[
+  'ȍ']), ('ȍ', &['Ȍ']), ('Ȏ', &['ȏ']), ('ȏ', &['Ȏ']), ('Ȑ', &['ȑ']),
+  ('ȑ', &['Ȑ']), ('Ȓ', &['ȓ']), ('ȓ', &['Ȓ']), ('Ȕ', &['ȕ']), ('ȕ', &[
+  'Ȕ']), ('Ȗ', &['ȗ']), ('ȗ', &['Ȗ']), ('Ș', &['ș']), ('ș', &['Ș']),
+  ('Ț', &['ț']), ('ț', &['Ț']), ('Ȝ', &['ȝ']), ('ȝ', &['Ȝ']), ('Ȟ', &[
+  'ȟ']), ('ȟ', &['Ȟ']), ('Ƞ', &['ƞ']), ('Ȣ', &['ȣ']), ('ȣ', &['Ȣ']),
+  ('Ȥ', &['ȥ']), ('ȥ', &['Ȥ']), ('Ȧ', &['ȧ']), ('ȧ', &['Ȧ']), ('Ȩ', &[
+  'ȩ']), ('ȩ', &['Ȩ']), ('Ȫ', &['ȫ']), ('ȫ', &['Ȫ']), ('Ȭ', &['ȭ']),
+  ('ȭ', &['Ȭ']), ('Ȯ', &['ȯ']), ('ȯ', &['Ȯ']), ('Ȱ', &['ȱ']), ('ȱ', &[
+  'Ȱ']), ('Ȳ', &['ȳ']), ('ȳ', &['Ȳ']), ('Ⱥ', &['ⱥ']), ('Ȼ', &['ȼ']),
+  ('ȼ', &['Ȼ']), ('Ƚ', &['ƚ']), ('Ⱦ', &['ⱦ']), ('ȿ', &['Ȿ']),
+  ('ɀ', &['Ɀ']), ('Ɂ', &['ɂ']), ('ɂ', &['Ɂ']), ('Ƀ', &['ƀ']),
+  ('Ʉ', &['ʉ']), ('Ʌ', &['ʌ']), ('Ɇ', &['ɇ']), ('ɇ', &['Ɇ']), ('Ɉ', &[
+  'ɉ']), ('ɉ', &['Ɉ']), ('Ɋ', &['ɋ']), ('ɋ', &['Ɋ']), ('Ɍ', &['ɍ']),
+  ('ɍ', &['Ɍ']), ('Ɏ', &['ɏ']), ('ɏ', &['Ɏ']), ('ɐ', &['Ɐ']),
+  ('ɑ', &['Ɑ']), ('ɒ', &['Ɒ']), ('ɓ', &['Ɓ']), ('ɔ', &['Ɔ']),
+  ('ɖ', &['Ɖ']), ('ɗ', &['Ɗ']), ('ə', &['Ə']), ('ɛ', &['Ɛ']), ('ɜ', &[
+  'Ɜ']), ('ɠ', &['Ɠ']), ('ɡ', &['Ɡ']), ('ɣ', &['Ɣ']), ('ɥ', &['Ɥ'
+  ]), ('ɦ', &['Ɦ']), ('ɨ', &['Ɨ']), ('ɩ', &['Ɩ']), ('ɪ', &['Ɪ']),
+  ('ɫ', &['Ɫ']), ('ɬ', &['Ɬ']), ('ɯ', &['Ɯ']), ('ɱ', &['Ɱ']),
+  ('ɲ', &['Ɲ']), ('ɵ', &['Ɵ']), ('ɽ', &['Ɽ']), ('ʀ', &['Ʀ']),
+  ('ʃ', &['Ʃ']), ('ʇ', &['Ʇ']), ('ʈ', &['Ʈ']), ('ʉ', &['Ʉ']),
+  ('ʊ', &['Ʊ']), ('ʋ', &['Ʋ']), ('ʌ', &['Ʌ']), ('ʒ', &['Ʒ']), ('ʝ', &[
+  'Ʝ']), ('ʞ', &['Ʞ']), ('ͅ', &['Ι', 'ι', 'ι', ]), ('Ͱ', &['ͱ']),
+  ('ͱ', &['Ͱ']), ('Ͳ', &['ͳ']), ('ͳ', &['Ͳ']), ('Ͷ', &['ͷ']), ('ͷ', &[
+  'Ͷ']), ('ͻ', &['Ͻ']), ('ͼ', &['Ͼ']), ('ͽ', &['Ͽ']), ('Ϳ', &['ϳ']),
+  ('Ά', &['ά']), ('Έ', &['έ']), ('Ή', &['ή']), ('Ί', &['ί']), ('Ό', &[
+  'ό']), ('Ύ', &['ύ']), ('Ώ', &['ώ']), ('Α', &['α']), ('Β', &['β',
+  'ϐ', ]), ('Γ', &['γ']), ('Δ', &['δ']), ('Ε', &['ε', 'ϵ', ]),
+  ('Ζ', &['ζ']), ('Η', &['η']), ('Θ', &['θ', 'ϑ', 'ϴ', ]), ('Ι', &[
+  'ͅ', 'ι', 'ι', ]), ('Κ', &['κ', 'ϰ', ]), ('Λ', &['λ']), ('Μ', &[
+  'µ', 'μ', ]), ('Ν', &['ν']), ('Ξ', &['ξ']), ('Ο', &['ο']), ('Π', &[
+  'π', 'ϖ', ]), ('Ρ', &['ρ', 'ϱ', ]), ('Σ', &['ς', 'σ', ]), ('Τ', &[
+  'τ']), ('Υ', &['υ']), ('Φ', &['φ', 'ϕ', ]), ('Χ', &['χ']), ('Ψ', &[
+  'ψ']), ('Ω', &['ω', 'Ω', ]), ('Ϊ', &['ϊ']), ('Ϋ', &['ϋ']), ('ά', &[
+  'Ά']), ('έ', &['Έ']), ('ή', &['Ή']), ('ί', &['Ί']), ('α', &['Α']),
+  ('β', &['Β', 'ϐ', ]), ('γ', &['Γ']), ('δ', &['Δ']), ('ε', &['Ε',
+  'ϵ', ]), ('ζ', &['Ζ']), ('η', &['Η']), ('θ', &['Θ', 'ϑ', 'ϴ', ]),
+  ('ι', &['ͅ', 'Ι', 'ι', ]), ('κ', &['Κ', 'ϰ', ]), ('λ', &['Λ']),
+  ('μ', &['µ', 'Μ', ]), ('ν', &['Ν']), ('ξ', &['Ξ']), ('ο', &['Ο']),
+  ('π', &['Π', 'ϖ', ]), ('ρ', &['Ρ', 'ϱ', ]), ('ς', &['Σ', 'σ', ]),
+  ('σ', &['Σ', 'ς', ]), ('τ', &['Τ']), ('υ', &['Υ']), ('φ', &['Φ',
+  'ϕ', ]), ('χ', &['Χ']), ('ψ', &['Ψ']), ('ω', &['Ω', 'Ω', ]),
+  ('ϊ', &['Ϊ']), ('ϋ', &['Ϋ']), ('ό', &['Ό']), ('ύ', &['Ύ']), ('ώ', &[
+  'Ώ']), ('Ϗ', &['ϗ']), ('ϐ', &['Β', 'β', ]), ('ϑ', &['Θ', 'θ', 'ϴ',
+  ]), ('ϕ', &['Φ', 'φ', ]), ('ϖ', &['Π', 'π', ]), ('ϗ', &['Ϗ']),
+  ('Ϙ', &['ϙ']), ('ϙ', &['Ϙ']), ('Ϛ', &['ϛ']), ('ϛ', &['Ϛ']), ('Ϝ', &[
+  'ϝ']), ('ϝ', &['Ϝ']), ('Ϟ', &['ϟ']), ('ϟ', &['Ϟ']), ('Ϡ', &['ϡ']),
+  ('ϡ', &['Ϡ']), ('Ϣ', &['ϣ']), ('ϣ', &['Ϣ']), ('Ϥ', &['ϥ']), ('ϥ', &[
+  'Ϥ']), ('Ϧ', &['ϧ']), ('ϧ', &['Ϧ']), ('Ϩ', &['ϩ']), ('ϩ', &['Ϩ']),
+  ('Ϫ', &['ϫ']), ('ϫ', &['Ϫ']), ('Ϭ', &['ϭ']), ('ϭ', &['Ϭ']), ('Ϯ', &[
+  'ϯ']), ('ϯ', &['Ϯ']), ('ϰ', &['Κ', 'κ', ]), ('ϱ', &['Ρ', 'ρ', ]),
+  ('ϲ', &['Ϲ']), ('ϳ', &['Ϳ']), ('ϴ', &['Θ', 'θ', 'ϑ', ]), ('ϵ', &[
+  'Ε', 'ε', ]), ('Ϸ', &['ϸ']), ('ϸ', &['Ϸ']), ('Ϲ', &['ϲ']), ('Ϻ', &[
+  'ϻ']), ('ϻ', &['Ϻ']), ('Ͻ', &['ͻ']), ('Ͼ', &['ͼ']), ('Ͽ', &['ͽ']),
+  ('Ѐ', &['ѐ']), ('Ё', &['ё']), ('Ђ', &['ђ']), ('Ѓ', &['ѓ']), ('Є', &[
+  'є']), ('Ѕ', &['ѕ']), ('І', &['і']), ('Ї', &['ї']), ('Ј', &['ј']),
+  ('Љ', &['љ']), ('Њ', &['њ']), ('Ћ', &['ћ']), ('Ќ', &['ќ']), ('Ѝ', &[
+  'ѝ']), ('Ў', &['ў']), ('Џ', &['џ']), ('А', &['а']), ('Б', &['б']),
+  ('В', &['в', 'ᲀ', ]), ('Г', &['г']), ('Д', &['д', 'ᲁ', ]),
+  ('Е', &['е']), ('Ж', &['ж']), ('З', &['з']), ('И', &['и']), ('Й', &[
+  'й']), ('К', &['к']), ('Л', &['л']), ('М', &['м']), ('Н', &['н']),
+  ('О', &['о', 'ᲂ', ]), ('П', &['п']), ('Р', &['р']), ('С', &['с',
+  'ᲃ', ]), ('Т', &['т', 'ᲄ', 'ᲅ', ]), ('У', &['у']), ('Ф', &['ф'
+  ]), ('Х', &['х']), ('Ц', &['ц']), ('Ч', &['ч']), ('Ш', &['ш']),
+  ('Щ', &['щ']), ('Ъ', &['ъ', 'ᲆ', ]), ('Ы', &['ы']), ('Ь', &['ь']),
+  ('Э', &['э']), ('Ю', &['ю']), ('Я', &['я']), ('а', &['А']), ('б', &[
+  'Б']), ('в', &['В', 'ᲀ', ]), ('г', &['Г']), ('д', &['Д', 'ᲁ', ]),
+  ('е', &['Е']), ('ж', &['Ж']), ('з', &['З']), ('и', &['И']), ('й', &[
+  'Й']), ('к', &['К']), ('л', &['Л']), ('м', &['М']), ('н', &['Н']),
+  ('о', &['О', 'ᲂ', ]), ('п', &['П']), ('р', &['Р']), ('с', &['С',
+  'ᲃ', ]), ('т', &['Т', 'ᲄ', 'ᲅ', ]), ('у', &['У']), ('ф', &['Ф'
+  ]), ('х', &['Х']), ('ц', &['Ц']), ('ч', &['Ч']), ('ш', &['Ш']),
+  ('щ', &['Щ']), ('ъ', &['Ъ', 'ᲆ', ]), ('ы', &['Ы']), ('ь', &['Ь']),
+  ('э', &['Э']), ('ю', &['Ю']), ('я', &['Я']), ('ѐ', &['Ѐ']), ('ё', &[
+  'Ё']), ('ђ', &['Ђ']), ('ѓ', &['Ѓ']), ('є', &['Є']), ('ѕ', &['Ѕ']),
+  ('і', &['І']), ('ї', &['Ї']), ('ј', &['Ј']), ('љ', &['Љ']), ('њ', &[
+  'Њ']), ('ћ', &['Ћ']), ('ќ', &['Ќ']), ('ѝ', &['Ѝ']), ('ў', &['Ў']),
+  ('џ', &['Џ']), ('Ѡ', &['ѡ']), ('ѡ', &['Ѡ']), ('Ѣ', &['ѣ', 'ᲇ', ]),
+  ('ѣ', &['Ѣ', 'ᲇ', ]), ('Ѥ', &['ѥ']), ('ѥ', &['Ѥ']), ('Ѧ', &['ѧ']),
+  ('ѧ', &['Ѧ']), ('Ѩ', &['ѩ']), ('ѩ', &['Ѩ']), ('Ѫ', &['ѫ']), ('ѫ', &[
+  'Ѫ']), ('Ѭ', &['ѭ']), ('ѭ', &['Ѭ']), ('Ѯ', &['ѯ']), ('ѯ', &['Ѯ']),
+  ('Ѱ', &['ѱ']), ('ѱ', &['Ѱ']), ('Ѳ', &['ѳ']), ('ѳ', &['Ѳ']), ('Ѵ', &[
+  'ѵ']), ('ѵ', &['Ѵ']), ('Ѷ', &['ѷ']), ('ѷ', &['Ѷ']), ('Ѹ', &['ѹ']),
+  ('ѹ', &['Ѹ']), ('Ѻ', &['ѻ']), ('ѻ', &['Ѻ']), ('Ѽ', &['ѽ']), ('ѽ', &[
+  'Ѽ']), ('Ѿ', &['ѿ']), ('ѿ', &['Ѿ']), ('Ҁ', &['ҁ']), ('ҁ', &['Ҁ']),
+  ('Ҋ', &['ҋ']), ('ҋ', &['Ҋ']), ('Ҍ', &['ҍ']), ('ҍ', &['Ҍ']), ('Ҏ', &[
+  'ҏ']), ('ҏ', &['Ҏ']), ('Ґ', &['ґ']), ('ґ', &['Ґ']), ('Ғ', &['ғ']),
+  ('ғ', &['Ғ']), ('Ҕ', &['ҕ']), ('ҕ', &['Ҕ']), ('Җ', &['җ']), ('җ', &[
+  'Җ']), ('Ҙ', &['ҙ']), ('ҙ', &['Ҙ']), ('Қ', &['қ']), ('қ', &['Қ']),
+  ('Ҝ', &['ҝ']), ('ҝ', &['Ҝ']), ('Ҟ', &['ҟ']), ('ҟ', &['Ҟ']), ('Ҡ', &[
+  'ҡ']), ('ҡ', &['Ҡ']), ('Ң', &['ң']), ('ң', &['Ң']), ('Ҥ', &['ҥ']),
+  ('ҥ', &['Ҥ']), ('Ҧ', &['ҧ']), ('ҧ', &['Ҧ']), ('Ҩ', &['ҩ']), ('ҩ', &[
+  'Ҩ']), ('Ҫ', &['ҫ']), ('ҫ', &['Ҫ']), ('Ҭ', &['ҭ']), ('ҭ', &['Ҭ']),
+  ('Ү', &['ү']), ('ү', &['Ү']), ('Ұ', &['ұ']), ('ұ', &['Ұ']), ('Ҳ', &[
+  'ҳ']), ('ҳ', &['Ҳ']), ('Ҵ', &['ҵ']), ('ҵ', &['Ҵ']), ('Ҷ', &['ҷ']),
+  ('ҷ', &['Ҷ']), ('Ҹ', &['ҹ']), ('ҹ', &['Ҹ']), ('Һ', &['һ']), ('һ', &[
+  'Һ']), ('Ҽ', &['ҽ']), ('ҽ', &['Ҽ']), ('Ҿ', &['ҿ']), ('ҿ', &['Ҿ']),
+  ('Ӏ', &['ӏ']), ('Ӂ', &['ӂ']), ('ӂ', &['Ӂ']), ('Ӄ', &['ӄ']), ('ӄ', &[
+  'Ӄ']), ('Ӆ', &['ӆ']), ('ӆ', &['Ӆ']), ('Ӈ', &['ӈ']), ('ӈ', &['Ӈ']),
+  ('Ӊ', &['ӊ']), ('ӊ', &['Ӊ']), ('Ӌ', &['ӌ']), ('ӌ', &['Ӌ']), ('Ӎ', &[
+  'ӎ']), ('ӎ', &['Ӎ']), ('ӏ', &['Ӏ']), ('Ӑ', &['ӑ']), ('ӑ', &['Ӑ']),
+  ('Ӓ', &['ӓ']), ('ӓ', &['Ӓ']), ('Ӕ', &['ӕ']), ('ӕ', &['Ӕ']), ('Ӗ', &[
+  'ӗ']), ('ӗ', &['Ӗ']), ('Ә', &['ә']), ('ә', &['Ә']), ('Ӛ', &['ӛ']),
+  ('ӛ', &['Ӛ']), ('Ӝ', &['ӝ']), ('ӝ', &['Ӝ']), ('Ӟ', &['ӟ']), ('ӟ', &[
+  'Ӟ']), ('Ӡ', &['ӡ']), ('ӡ', &['Ӡ']), ('Ӣ', &['ӣ']), ('ӣ', &['Ӣ']),
+  ('Ӥ', &['ӥ']), ('ӥ', &['Ӥ']), ('Ӧ', &['ӧ']), ('ӧ', &['Ӧ']), ('Ө', &[
+  'ө']), ('ө', &['Ө']), ('Ӫ', &['ӫ']), ('ӫ', &['Ӫ']), ('Ӭ', &['ӭ']),
+  ('ӭ', &['Ӭ']), ('Ӯ', &['ӯ']), ('ӯ', &['Ӯ']), ('Ӱ', &['ӱ']), ('ӱ', &[
+  'Ӱ']), ('Ӳ', &['ӳ']), ('ӳ', &['Ӳ']), ('Ӵ', &['ӵ']), ('ӵ', &['Ӵ']),
+  ('Ӷ', &['ӷ']), ('ӷ', &['Ӷ']), ('Ӹ', &['ӹ']), ('ӹ', &['Ӹ']), ('Ӻ', &[
+  'ӻ']), ('ӻ', &['Ӻ']), ('Ӽ', &['ӽ']), ('ӽ', &['Ӽ']), ('Ӿ', &['ӿ']),
+  ('ӿ', &['Ӿ']), ('Ԁ', &['ԁ']), ('ԁ', &['Ԁ']), ('Ԃ', &['ԃ']), ('ԃ', &[
+  'Ԃ']), ('Ԅ', &['ԅ']), ('ԅ', &['Ԅ']), ('Ԇ', &['ԇ']), ('ԇ', &['Ԇ']),
+  ('Ԉ', &['ԉ']), ('ԉ', &['Ԉ']), ('Ԋ', &['ԋ']), ('ԋ', &['Ԋ']), ('Ԍ', &[
+  'ԍ']), ('ԍ', &['Ԍ']), ('Ԏ', &['ԏ']), ('ԏ', &['Ԏ']), ('Ԑ', &['ԑ']),
+  ('ԑ', &['Ԑ']), ('Ԓ', &['ԓ']), ('ԓ', &['Ԓ']), ('Ԕ', &['ԕ']), ('ԕ', &[
+  'Ԕ']), ('Ԗ', &['ԗ']), ('ԗ', &['Ԗ']), ('Ԙ', &['ԙ']), ('ԙ', &['Ԙ']),
+  ('Ԛ', &['ԛ']), ('ԛ', &['Ԛ']), ('Ԝ', &['ԝ']), ('ԝ', &['Ԝ']), ('Ԟ', &[
+  'ԟ']), ('ԟ', &['Ԟ']), ('Ԡ', &['ԡ']), ('ԡ', &['Ԡ']), ('Ԣ', &['ԣ']),
+  ('ԣ', &['Ԣ']), ('Ԥ', &['ԥ']), ('ԥ', &['Ԥ']), ('Ԧ', &['ԧ']), ('ԧ', &[
+  'Ԧ']), ('Ԩ', &['ԩ']), ('ԩ', &['Ԩ']), ('Ԫ', &['ԫ']), ('ԫ', &['Ԫ']),
+  ('Ԭ', &['ԭ']), ('ԭ', &['Ԭ']), ('Ԯ', &['ԯ']), ('ԯ', &['Ԯ']), ('Ա', &[
+  'ա']), ('Բ', &['բ']), ('Գ', &['գ']), ('Դ', &['դ']), ('Ե', &['ե']),
+  ('Զ', &['զ']), ('Է', &['է']), ('Ը', &['ը']), ('Թ', &['թ']), ('Ժ', &[
+  'ժ']), ('Ի', &['ի']), ('Լ', &['լ']), ('Խ', &['խ']), ('Ծ', &['ծ']),
+  ('Կ', &['կ']), ('Հ', &['հ']), ('Ձ', &['ձ']), ('Ղ', &['ղ']), ('Ճ', &[
+  'ճ']), ('Մ', &['մ']), ('Յ', &['յ']), ('Ն', &['ն']), ('Շ', &['շ']),
+  ('Ո', &['ո']), ('Չ', &['չ']), ('Պ', &['պ']), ('Ջ', &['ջ']), ('Ռ', &[
+  'ռ']), ('Ս', &['ս']), ('Վ', &['վ']), ('Տ', &['տ']), ('Ր', &['ր']),
+  ('Ց', &['ց']), ('Ւ', &['ւ']), ('Փ', &['փ']), ('Ք', &['ք']), ('Օ', &[
+  'օ']), ('Ֆ', &['ֆ']), ('ա', &['Ա']), ('բ', &['Բ']), ('գ', &['Գ']),
+  ('դ', &['Դ']), ('ե', &['Ե']), ('զ', &['Զ']), ('է', &['Է']), ('ը', &[
+  'Ը']), ('թ', &['Թ']), ('ժ', &['Ժ']), ('ի', &['Ի']), ('լ', &['Լ']),
+  ('խ', &['Խ']), ('ծ', &['Ծ']), ('կ', &['Կ']), ('հ', &['Հ']), ('ձ', &[
+  'Ձ']), ('ղ', &['Ղ']), ('ճ', &['Ճ']), ('մ', &['Մ']), ('յ', &['Յ']),
+  ('ն', &['Ն']), ('շ', &['Շ']), ('ո', &['Ո']), ('չ', &['Չ']), ('պ', &[
+  'Պ']), ('ջ', &['Ջ']), ('ռ', &['Ռ']), ('ս', &['Ս']), ('վ', &['Վ']),
+  ('տ', &['Տ']), ('ր', &['Ր']), ('ց', &['Ց']), ('ւ', &['Ւ']), ('փ', &[
+  'Փ']), ('ք', &['Ք']), ('օ', &['Օ']), ('ֆ', &['Ֆ']), ('Ⴀ', &['ⴀ'
+  ]), ('Ⴁ', &['ⴁ']), ('Ⴂ', &['ⴂ']), ('Ⴃ', &['ⴃ']), ('Ⴄ', &['ⴄ'
+  ]), ('Ⴅ', &['ⴅ']), ('Ⴆ', &['ⴆ']), ('Ⴇ', &['ⴇ']), ('Ⴈ', &['ⴈ'
+  ]), ('Ⴉ', &['ⴉ']), ('Ⴊ', &['ⴊ']), ('Ⴋ', &['ⴋ']), ('Ⴌ', &['ⴌ'
+  ]), ('Ⴍ', &['ⴍ']), ('Ⴎ', &['ⴎ']), ('Ⴏ', &['ⴏ']), ('Ⴐ', &['ⴐ'
+  ]), ('Ⴑ', &['ⴑ']), ('Ⴒ', &['ⴒ']), ('Ⴓ', &['ⴓ']), ('Ⴔ', &['ⴔ'
+  ]), ('Ⴕ', &['ⴕ']), ('Ⴖ', &['ⴖ']), ('Ⴗ', &['ⴗ']), ('Ⴘ', &['ⴘ'
+  ]), ('Ⴙ', &['ⴙ']), ('Ⴚ', &['ⴚ']), ('Ⴛ', &['ⴛ']), ('Ⴜ', &['ⴜ'
+  ]), ('Ⴝ', &['ⴝ']), ('Ⴞ', &['ⴞ']), ('Ⴟ', &['ⴟ']), ('Ⴠ', &['ⴠ'
+  ]), ('Ⴡ', &['ⴡ']), ('Ⴢ', &['ⴢ']), ('Ⴣ', &['ⴣ']), ('Ⴤ', &['ⴤ'
+  ]), ('Ⴥ', &['ⴥ']), ('Ⴧ', &['ⴧ']), ('Ⴭ', &['ⴭ']), ('ა', &[
+  '\u{1c90}']), ('ბ', &['\u{1c91}']), ('გ', &['\u{1c92}']), ('დ', &[
+  '\u{1c93}']), ('ე', &['\u{1c94}']), ('ვ', &['\u{1c95}']), ('ზ', &[
+  '\u{1c96}']), ('თ', &['\u{1c97}']), ('ი', &['\u{1c98}']), ('კ', &[
+  '\u{1c99}']), ('ლ', &['\u{1c9a}']), ('მ', &['\u{1c9b}']), ('ნ', &[
+  '\u{1c9c}']), ('ო', &['\u{1c9d}']), ('პ', &['\u{1c9e}']), ('ჟ', &[
+  '\u{1c9f}']), ('რ', &['\u{1ca0}']), ('ს', &['\u{1ca1}']), ('ტ', &[
+  '\u{1ca2}']), ('უ', &['\u{1ca3}']), ('ფ', &['\u{1ca4}']), ('ქ', &[
+  '\u{1ca5}']), ('ღ', &['\u{1ca6}']), ('ყ', &['\u{1ca7}']), ('შ', &[
+  '\u{1ca8}']), ('ჩ', &['\u{1ca9}']), ('ც', &['\u{1caa}']), ('ძ', &[
+  '\u{1cab}']), ('წ', &['\u{1cac}']), ('ჭ', &['\u{1cad}']), ('ხ', &[
+  '\u{1cae}']), ('ჯ', &['\u{1caf}']), ('ჰ', &['\u{1cb0}']), ('ჱ', &[
+  '\u{1cb1}']), ('ჲ', &['\u{1cb2}']), ('ჳ', &['\u{1cb3}']), ('ჴ', &[
+  '\u{1cb4}']), ('ჵ', &['\u{1cb5}']), ('ჶ', &['\u{1cb6}']), ('ჷ', &[
+  '\u{1cb7}']), ('ჸ', &['\u{1cb8}']), ('ჹ', &['\u{1cb9}']), ('ჺ', &[
+  '\u{1cba}']), ('ჽ', &['\u{1cbd}']), ('ჾ', &['\u{1cbe}']), ('ჿ', &[
+  '\u{1cbf}']), ('Ꭰ', &['ꭰ']), ('Ꭱ', &['ꭱ']), ('Ꭲ', &['ꭲ']),
+  ('Ꭳ', &['ꭳ']), ('Ꭴ', &['ꭴ']), ('Ꭵ', &['ꭵ']), ('Ꭶ', &['ꭶ']),
+  ('Ꭷ', &['ꭷ']), ('Ꭸ', &['ꭸ']), ('Ꭹ', &['ꭹ']), ('Ꭺ', &['ꭺ']),
+  ('Ꭻ', &['ꭻ']), ('Ꭼ', &['ꭼ']), ('Ꭽ', &['ꭽ']), ('Ꭾ', &['ꭾ']),
+  ('Ꭿ', &['ꭿ']), ('Ꮀ', &['ꮀ']), ('Ꮁ', &['ꮁ']), ('Ꮂ', &['ꮂ']),
+  ('Ꮃ', &['ꮃ']), ('Ꮄ', &['ꮄ']), ('Ꮅ', &['ꮅ']), ('Ꮆ', &['ꮆ']),
+  ('Ꮇ', &['ꮇ']), ('Ꮈ', &['ꮈ']), ('Ꮉ', &['ꮉ']), ('Ꮊ', &['ꮊ']),
+  ('Ꮋ', &['ꮋ']), ('Ꮌ', &['ꮌ']), ('Ꮍ', &['ꮍ']), ('Ꮎ', &['ꮎ']),
+  ('Ꮏ', &['ꮏ']), ('Ꮐ', &['ꮐ']), ('Ꮑ', &['ꮑ']), ('Ꮒ', &['ꮒ']),
+  ('Ꮓ', &['ꮓ']), ('Ꮔ', &['ꮔ']), ('Ꮕ', &['ꮕ']), ('Ꮖ', &['ꮖ']),
+  ('Ꮗ', &['ꮗ']), ('Ꮘ', &['ꮘ']), ('Ꮙ', &['ꮙ']), ('Ꮚ', &['ꮚ']),
+  ('Ꮛ', &['ꮛ']), ('Ꮜ', &['ꮜ']), ('Ꮝ', &['ꮝ']), ('Ꮞ', &['ꮞ']),
+  ('Ꮟ', &['ꮟ']), ('Ꮠ', &['ꮠ']), ('Ꮡ', &['ꮡ']), ('Ꮢ', &['ꮢ']),
+  ('Ꮣ', &['ꮣ']), ('Ꮤ', &['ꮤ']), ('Ꮥ', &['ꮥ']), ('Ꮦ', &['ꮦ']),
+  ('Ꮧ', &['ꮧ']), ('Ꮨ', &['ꮨ']), ('Ꮩ', &['ꮩ']), ('Ꮪ', &['ꮪ']),
+  ('Ꮫ', &['ꮫ']), ('Ꮬ', &['ꮬ']), ('Ꮭ', &['ꮭ']), ('Ꮮ', &['ꮮ']),
+  ('Ꮯ', &['ꮯ']), ('Ꮰ', &['ꮰ']), ('Ꮱ', &['ꮱ']), ('Ꮲ', &['ꮲ']),
+  ('Ꮳ', &['ꮳ']), ('Ꮴ', &['ꮴ']), ('Ꮵ', &['ꮵ']), ('Ꮶ', &['ꮶ']),
+  ('Ꮷ', &['ꮷ']), ('Ꮸ', &['ꮸ']), ('Ꮹ', &['ꮹ']), ('Ꮺ', &['ꮺ']),
+  ('Ꮻ', &['ꮻ']), ('Ꮼ', &['ꮼ']), ('Ꮽ', &['ꮽ']), ('Ꮾ', &['ꮾ']),
+  ('Ꮿ', &['ꮿ']), ('Ᏸ', &['ᏸ']), ('Ᏹ', &['ᏹ']), ('Ᏺ', &['ᏺ']),
+  ('Ᏻ', &['ᏻ']), ('Ᏼ', &['ᏼ']), ('Ᏽ', &['ᏽ']), ('ᏸ', &['Ᏸ']),
+  ('ᏹ', &['Ᏹ']), ('ᏺ', &['Ᏺ']), ('ᏻ', &['Ᏻ']), ('ᏼ', &['Ᏼ']),
+  ('ᏽ', &['Ᏽ']), ('ᲀ', &['В', 'в', ]), ('ᲁ', &['Д', 'д', ]),
+  ('ᲂ', &['О', 'о', ]), ('ᲃ', &['С', 'с', ]), ('ᲄ', &['Т', 'т',
+  'ᲅ', ]), ('ᲅ', &['Т', 'т', 'ᲄ', ]), ('ᲆ', &['Ъ', 'ъ', ]),
+  ('ᲇ', &['Ѣ', 'ѣ', ]), ('ᲈ', &['Ꙋ', 'ꙋ', ]), ('\u{1c90}', &['ა'
+  ]), ('\u{1c91}', &['ბ']), ('\u{1c92}', &['გ']), ('\u{1c93}', &['დ']),
+  ('\u{1c94}', &['ე']), ('\u{1c95}', &['ვ']), ('\u{1c96}', &['ზ']),
+  ('\u{1c97}', &['თ']), ('\u{1c98}', &['ი']), ('\u{1c99}', &['კ']),
+  ('\u{1c9a}', &['ლ']), ('\u{1c9b}', &['მ']), ('\u{1c9c}', &['ნ']),
+  ('\u{1c9d}', &['ო']), ('\u{1c9e}', &['პ']), ('\u{1c9f}', &['ჟ']),
+  ('\u{1ca0}', &['რ']), ('\u{1ca1}', &['ს']), ('\u{1ca2}', &['ტ']),
+  ('\u{1ca3}', &['უ']), ('\u{1ca4}', &['ფ']), ('\u{1ca5}', &['ქ']),
+  ('\u{1ca6}', &['ღ']), ('\u{1ca7}', &['ყ']), ('\u{1ca8}', &['შ']),
+  ('\u{1ca9}', &['ჩ']), ('\u{1caa}', &['ც']), ('\u{1cab}', &['ძ']),
+  ('\u{1cac}', &['წ']), ('\u{1cad}', &['ჭ']), ('\u{1cae}', &['ხ']),
+  ('\u{1caf}', &['ჯ']), ('\u{1cb0}', &['ჰ']), ('\u{1cb1}', &['ჱ']),
+  ('\u{1cb2}', &['ჲ']), ('\u{1cb3}', &['ჳ']), ('\u{1cb4}', &['ჴ']),
+  ('\u{1cb5}', &['ჵ']), ('\u{1cb6}', &['ჶ']), ('\u{1cb7}', &['ჷ']),
+  ('\u{1cb8}', &['ჸ']), ('\u{1cb9}', &['ჹ']), ('\u{1cba}', &['ჺ']),
+  ('\u{1cbd}', &['ჽ']), ('\u{1cbe}', &['ჾ']), ('\u{1cbf}', &['ჿ']),
+  ('ᵹ', &['Ᵹ']), ('ᵽ', &['Ᵽ']), ('Ḁ', &['ḁ']), ('ḁ', &['Ḁ']),
+  ('Ḃ', &['ḃ']), ('ḃ', &['Ḃ']), ('Ḅ', &['ḅ']), ('ḅ', &['Ḅ']),
+  ('Ḇ', &['ḇ']), ('ḇ', &['Ḇ']), ('Ḉ', &['ḉ']), ('ḉ', &['Ḉ']),
+  ('Ḋ', &['ḋ']), ('ḋ', &['Ḋ']), ('Ḍ', &['ḍ']), ('ḍ', &['Ḍ']),
+  ('Ḏ', &['ḏ']), ('ḏ', &['Ḏ']), ('Ḑ', &['ḑ']), ('ḑ', &['Ḑ']),
+  ('Ḓ', &['ḓ']), ('ḓ', &['Ḓ']), ('Ḕ', &['ḕ']), ('ḕ', &['Ḕ']),
+  ('Ḗ', &['ḗ']), ('ḗ', &['Ḗ']), ('Ḙ', &['ḙ']), ('ḙ', &['Ḙ']),
+  ('Ḛ', &['ḛ']), ('ḛ', &['Ḛ']), ('Ḝ', &['ḝ']), ('ḝ', &['Ḝ']),
+  ('Ḟ', &['ḟ']), ('ḟ', &['Ḟ']), ('Ḡ', &['ḡ']), ('ḡ', &['Ḡ']),
+  ('Ḣ', &['ḣ']), ('ḣ', &['Ḣ']), ('Ḥ', &['ḥ']), ('ḥ', &['Ḥ']),
+  ('Ḧ', &['ḧ']), ('ḧ', &['Ḧ']), ('Ḩ', &['ḩ']), ('ḩ', &['Ḩ']),
+  ('Ḫ', &['ḫ']), ('ḫ', &['Ḫ']), ('Ḭ', &['ḭ']), ('ḭ', &['Ḭ']),
+  ('Ḯ', &['ḯ']), ('ḯ', &['Ḯ']), ('Ḱ', &['ḱ']), ('ḱ', &['Ḱ']),
+  ('Ḳ', &['ḳ']), ('ḳ', &['Ḳ']), ('Ḵ', &['ḵ']), ('ḵ', &['Ḵ']),
+  ('Ḷ', &['ḷ']), ('ḷ', &['Ḷ']), ('Ḹ', &['ḹ']), ('ḹ', &['Ḹ']),
+  ('Ḻ', &['ḻ']), ('ḻ', &['Ḻ']), ('Ḽ', &['ḽ']), ('ḽ', &['Ḽ']),
+  ('Ḿ', &['ḿ']), ('ḿ', &['Ḿ']), ('Ṁ', &['ṁ']), ('ṁ', &['Ṁ']),
+  ('Ṃ', &['ṃ']), ('ṃ', &['Ṃ']), ('Ṅ', &['ṅ']), ('ṅ', &['Ṅ']),
+  ('Ṇ', &['ṇ']), ('ṇ', &['Ṇ']), ('Ṉ', &['ṉ']), ('ṉ', &['Ṉ']),
+  ('Ṋ', &['ṋ']), ('ṋ', &['Ṋ']), ('Ṍ', &['ṍ']), ('ṍ', &['Ṍ']),
+  ('Ṏ', &['ṏ']), ('ṏ', &['Ṏ']), ('Ṑ', &['ṑ']), ('ṑ', &['Ṑ']),
+  ('Ṓ', &['ṓ']), ('ṓ', &['Ṓ']), ('Ṕ', &['ṕ']), ('ṕ', &['Ṕ']),
+  ('Ṗ', &['ṗ']), ('ṗ', &['Ṗ']), ('Ṙ', &['ṙ']), ('ṙ', &['Ṙ']),
+  ('Ṛ', &['ṛ']), ('ṛ', &['Ṛ']), ('Ṝ', &['ṝ']), ('ṝ', &['Ṝ']),
+  ('Ṟ', &['ṟ']), ('ṟ', &['Ṟ']), ('Ṡ', &['ṡ', 'ẛ', ]), ('ṡ', &[
+  'Ṡ', 'ẛ', ]), ('Ṣ', &['ṣ']), ('ṣ', &['Ṣ']), ('Ṥ', &['ṥ']),
+  ('ṥ', &['Ṥ']), ('Ṧ', &['ṧ']), ('ṧ', &['Ṧ']), ('Ṩ', &['ṩ']),
+  ('ṩ', &['Ṩ']), ('Ṫ', &['ṫ']), ('ṫ', &['Ṫ']), ('Ṭ', &['ṭ']),
+  ('ṭ', &['Ṭ']), ('Ṯ', &['ṯ']), ('ṯ', &['Ṯ']), ('Ṱ', &['ṱ']),
+  ('ṱ', &['Ṱ']), ('Ṳ', &['ṳ']), ('ṳ', &['Ṳ']), ('Ṵ', &['ṵ']),
+  ('ṵ', &['Ṵ']), ('Ṷ', &['ṷ']), ('ṷ', &['Ṷ']), ('Ṹ', &['ṹ']),
+  ('ṹ', &['Ṹ']), ('Ṻ', &['ṻ']), ('ṻ', &['Ṻ']), ('Ṽ', &['ṽ']),
+  ('ṽ', &['Ṽ']), ('Ṿ', &['ṿ']), ('ṿ', &['Ṿ']), ('Ẁ', &['ẁ']),
+  ('ẁ', &['Ẁ']), ('Ẃ', &['ẃ']), ('ẃ', &['Ẃ']), ('Ẅ', &['ẅ']),
+  ('ẅ', &['Ẅ']), ('Ẇ', &['ẇ']), ('ẇ', &['Ẇ']), ('Ẉ', &['ẉ']),
+  ('ẉ', &['Ẉ']), ('Ẋ', &['ẋ']), ('ẋ', &['Ẋ']), ('Ẍ', &['ẍ']),
+  ('ẍ', &['Ẍ']), ('Ẏ', &['ẏ']), ('ẏ', &['Ẏ']), ('Ẑ', &['ẑ']),
+  ('ẑ', &['Ẑ']), ('Ẓ', &['ẓ']), ('ẓ', &['Ẓ']), ('Ẕ', &['ẕ']),
+  ('ẕ', &['Ẕ']), ('ẛ', &['Ṡ', 'ṡ', ]), ('ẞ', &['ß']), ('Ạ', &[
+  'ạ']), ('ạ', &['Ạ']), ('Ả', &['ả']), ('ả', &['Ả']), ('Ấ', &[
+  'ấ']), ('ấ', &['Ấ']), ('Ầ', &['ầ']), ('ầ', &['Ầ']), ('Ẩ', &[
+  'ẩ']), ('ẩ', &['Ẩ']), ('Ẫ', &['ẫ']), ('ẫ', &['Ẫ']), ('Ậ', &[
+  'ậ']), ('ậ', &['Ậ']), ('Ắ', &['ắ']), ('ắ', &['Ắ']), ('Ằ', &[
+  'ằ']), ('ằ', &['Ằ']), ('Ẳ', &['ẳ']), ('ẳ', &['Ẳ']), ('Ẵ', &[
+  'ẵ']), ('ẵ', &['Ẵ']), ('Ặ', &['ặ']), ('ặ', &['Ặ']), ('Ẹ', &[
+  'ẹ']), ('ẹ', &['Ẹ']), ('Ẻ', &['ẻ']), ('ẻ', &['Ẻ']), ('Ẽ', &[
+  'ẽ']), ('ẽ', &['Ẽ']), ('Ế', &['ế']), ('ế', &['Ế']), ('Ề', &[
+  'ề']), ('ề', &['Ề']), ('Ể', &['ể']), ('ể', &['Ể']), ('Ễ', &[
+  'ễ']), ('ễ', &['Ễ']), ('Ệ', &['ệ']), ('ệ', &['Ệ']), ('Ỉ', &[
+  'ỉ']), ('ỉ', &['Ỉ']), ('Ị', &['ị']), ('ị', &['Ị']), ('Ọ', &[
+  'ọ']), ('ọ', &['Ọ']), ('Ỏ', &['ỏ']), ('ỏ', &['Ỏ']), ('Ố', &[
+  'ố']), ('ố', &['Ố']), ('Ồ', &['ồ']), ('ồ', &['Ồ']), ('Ổ', &[
+  'ổ']), ('ổ', &['Ổ']), ('Ỗ', &['ỗ']), ('ỗ', &['Ỗ']), ('Ộ', &[
+  'ộ']), ('ộ', &['Ộ']), ('Ớ', &['ớ']), ('ớ', &['Ớ']), ('Ờ', &[
+  'ờ']), ('ờ', &['Ờ']), ('Ở', &['ở']), ('ở', &['Ở']), ('Ỡ', &[
+  'ỡ']), ('ỡ', &['Ỡ']), ('Ợ', &['ợ']), ('ợ', &['Ợ']), ('Ụ', &[
+  'ụ']), ('ụ', &['Ụ']), ('Ủ', &['ủ']), ('ủ', &['Ủ']), ('Ứ', &[
+  'ứ']), ('ứ', &['Ứ']), ('Ừ', &['ừ']), ('ừ', &['Ừ']), ('Ử', &[
+  'ử']), ('ử', &['Ử']), ('Ữ', &['ữ']), ('ữ', &['Ữ']), ('Ự', &[
+  'ự']), ('ự', &['Ự']), ('Ỳ', &['ỳ']), ('ỳ', &['Ỳ']), ('Ỵ', &[
+  'ỵ']), ('ỵ', &['Ỵ']), ('Ỷ', &['ỷ']), ('ỷ', &['Ỷ']), ('Ỹ', &[
+  'ỹ']), ('ỹ', &['Ỹ']), ('Ỻ', &['ỻ']), ('ỻ', &['Ỻ']), ('Ỽ', &[
+  'ỽ']), ('ỽ', &['Ỽ']), ('Ỿ', &['ỿ']), ('ỿ', &['Ỿ']), ('ἀ', &[
+  'Ἀ']), ('ἁ', &['Ἁ']), ('ἂ', &['Ἂ']), ('ἃ', &['Ἃ']), ('ἄ', &[
+  'Ἄ']), ('ἅ', &['Ἅ']), ('ἆ', &['Ἆ']), ('ἇ', &['Ἇ']), ('Ἀ', &[
+  'ἀ']), ('Ἁ', &['ἁ']), ('Ἂ', &['ἂ']), ('Ἃ', &['ἃ']), ('Ἄ', &[
+  'ἄ']), ('Ἅ', &['ἅ']), ('Ἆ', &['ἆ']), ('Ἇ', &['ἇ']), ('ἐ', &[
+  'Ἐ']), ('ἑ', &['Ἑ']), ('ἒ', &['Ἒ']), ('ἓ', &['Ἓ']), ('ἔ', &[
+  'Ἔ']), ('ἕ', &['Ἕ']), ('Ἐ', &['ἐ']), ('Ἑ', &['ἑ']), ('Ἒ', &[
+  'ἒ']), ('Ἓ', &['ἓ']), ('Ἔ', &['ἔ']), ('Ἕ', &['ἕ']), ('ἠ', &[
+  'Ἠ']), ('ἡ', &['Ἡ']), ('ἢ', &['Ἢ']), ('ἣ', &['Ἣ']), ('ἤ', &[
+  'Ἤ']), ('ἥ', &['Ἥ']), ('ἦ', &['Ἦ']), ('ἧ', &['Ἧ']), ('Ἠ', &[
+  'ἠ']), ('Ἡ', &['ἡ']), ('Ἢ', &['ἢ']), ('Ἣ', &['ἣ']), ('Ἤ', &[
+  'ἤ']), ('Ἥ', &['ἥ']), ('Ἦ', &['ἦ']), ('Ἧ', &['ἧ']), ('ἰ', &[
+  'Ἰ']), ('ἱ', &['Ἱ']), ('ἲ', &['Ἲ']), ('ἳ', &['Ἳ']), ('ἴ', &[
+  'Ἴ']), ('ἵ', &['Ἵ']), ('ἶ', &['Ἶ']), ('ἷ', &['Ἷ']), ('Ἰ', &[
+  'ἰ']), ('Ἱ', &['ἱ']), ('Ἲ', &['ἲ']), ('Ἳ', &['ἳ']), ('Ἴ', &[
+  'ἴ']), ('Ἵ', &['ἵ']), ('Ἶ', &['ἶ']), ('Ἷ', &['ἷ']), ('ὀ', &[
+  'Ὀ']), ('ὁ', &['Ὁ']), ('ὂ', &['Ὂ']), ('ὃ', &['Ὃ']), ('ὄ', &[
+  'Ὄ']), ('ὅ', &['Ὅ']), ('Ὀ', &['ὀ']), ('Ὁ', &['ὁ']), ('Ὂ', &[
+  'ὂ']), ('Ὃ', &['ὃ']), ('Ὄ', &['ὄ']), ('Ὅ', &['ὅ']), ('ὑ', &[
+  'Ὑ']), ('ὓ', &['Ὓ']), ('ὕ', &['Ὕ']), ('ὗ', &['Ὗ']), ('Ὑ', &[
+  'ὑ']), ('Ὓ', &['ὓ']), ('Ὕ', &['ὕ']), ('Ὗ', &['ὗ']), ('ὠ', &[
+  'Ὠ']), ('ὡ', &['Ὡ']), ('ὢ', &['Ὢ']), ('ὣ', &['Ὣ']), ('ὤ', &[
+  'Ὤ']), ('ὥ', &['Ὥ']), ('ὦ', &['Ὦ']), ('ὧ', &['Ὧ']), ('Ὠ', &[
+  'ὠ']), ('Ὡ', &['ὡ']), ('Ὢ', &['ὢ']), ('Ὣ', &['ὣ']), ('Ὤ', &[
+  'ὤ']), ('Ὥ', &['ὥ']), ('Ὦ', &['ὦ']), ('Ὧ', &['ὧ']), ('ὰ', &[
+  'Ὰ']), ('ά', &['Ά']), ('ὲ', &['Ὲ']), ('έ', &['Έ']), ('ὴ', &[
+  'Ὴ']), ('ή', &['Ή']), ('ὶ', &['Ὶ']), ('ί', &['Ί']), ('ὸ', &[
+  'Ὸ']), ('ό', &['Ό']), ('ὺ', &['Ὺ']), ('ύ', &['Ύ']), ('ὼ', &[
+  'Ὼ']), ('ώ', &['Ώ']), ('ᾀ', &['ᾈ']), ('ᾁ', &['ᾉ']), ('ᾂ', &[
+  'ᾊ']), ('ᾃ', &['ᾋ']), ('ᾄ', &['ᾌ']), ('ᾅ', &['ᾍ']), ('ᾆ', &[
+  'ᾎ']), ('ᾇ', &['ᾏ']), ('ᾈ', &['ᾀ']), ('ᾉ', &['ᾁ']), ('ᾊ', &[
+  'ᾂ']), ('ᾋ', &['ᾃ']), ('ᾌ', &['ᾄ']), ('ᾍ', &['ᾅ']), ('ᾎ', &[
+  'ᾆ']), ('ᾏ', &['ᾇ']), ('ᾐ', &['ᾘ']), ('ᾑ', &['ᾙ']), ('ᾒ', &[
+  'ᾚ']), ('ᾓ', &['ᾛ']), ('ᾔ', &['ᾜ']), ('ᾕ', &['ᾝ']), ('ᾖ', &[
+  'ᾞ']), ('ᾗ', &['ᾟ']), ('ᾘ', &['ᾐ']), ('ᾙ', &['ᾑ']), ('ᾚ', &[
+  'ᾒ']), ('ᾛ', &['ᾓ']), ('ᾜ', &['ᾔ']), ('ᾝ', &['ᾕ']), ('ᾞ', &[
+  'ᾖ']), ('ᾟ', &['ᾗ']), ('ᾠ', &['ᾨ']), ('ᾡ', &['ᾩ']), ('ᾢ', &[
+  'ᾪ']), ('ᾣ', &['ᾫ']), ('ᾤ', &['ᾬ']), ('ᾥ', &['ᾭ']), ('ᾦ', &[
+  'ᾮ']), ('ᾧ', &['ᾯ']), ('ᾨ', &['ᾠ']), ('ᾩ', &['ᾡ']), ('ᾪ', &[
+  'ᾢ']), ('ᾫ', &['ᾣ']), ('ᾬ', &['ᾤ']), ('ᾭ', &['ᾥ']), ('ᾮ', &[
+  'ᾦ']), ('ᾯ', &['ᾧ']), ('ᾰ', &['Ᾰ']), ('ᾱ', &['Ᾱ']), ('ᾳ', &[
+  'ᾼ']), ('Ᾰ', &['ᾰ']), ('Ᾱ', &['ᾱ']), ('Ὰ', &['ὰ']), ('Ά', &[
+  'ά']), ('ᾼ', &['ᾳ']), ('ι', &['ͅ', 'Ι', 'ι', ]), ('ῃ', &['ῌ'
+  ]), ('Ὲ', &['ὲ']), ('Έ', &['έ']), ('Ὴ', &['ὴ']), ('Ή', &['ή'
+  ]), ('ῌ', &['ῃ']), ('ῐ', &['Ῐ']), ('ῑ', &['Ῑ']), ('Ῐ', &['ῐ'
+  ]), ('Ῑ', &['ῑ']), ('Ὶ', &['ὶ']), ('Ί', &['ί']), ('ῠ', &['Ῠ'
+  ]), ('ῡ', &['Ῡ']), ('ῥ', &['Ῥ']), ('Ῠ', &['ῠ']), ('Ῡ', &['ῡ'
+  ]), ('Ὺ', &['ὺ']), ('Ύ', &['ύ']), ('Ῥ', &['ῥ']), ('ῳ', &['ῼ'
+  ]), ('Ὸ', &['ὸ']), ('Ό', &['ό']), ('Ὼ', &['ὼ']), ('Ώ', &['ώ'
+  ]), ('ῼ', &['ῳ']), ('Ω', &['Ω', 'ω', ]), ('K', &['K', 'k', ]),
+  ('Å', &['Å', 'å', ]), ('Ⅎ', &['ⅎ']), ('ⅎ', &['Ⅎ']), ('Ⅰ', &[
+  'ⅰ']), ('Ⅱ', &['ⅱ']), ('Ⅲ', &['ⅲ']), ('Ⅳ', &['ⅳ']), ('Ⅴ', &[
+  'ⅴ']), ('Ⅵ', &['ⅵ']), ('Ⅶ', &['ⅶ']), ('Ⅷ', &['ⅷ']), ('Ⅸ', &[
+  'ⅸ']), ('Ⅹ', &['ⅹ']), ('Ⅺ', &['ⅺ']), ('Ⅻ', &['ⅻ']), ('Ⅼ', &[
+  'ⅼ']), ('Ⅽ', &['ⅽ']), ('Ⅾ', &['ⅾ']), ('Ⅿ', &['ⅿ']), ('ⅰ', &[
+  'Ⅰ']), ('ⅱ', &['Ⅱ']), ('ⅲ', &['Ⅲ']), ('ⅳ', &['Ⅳ']), ('ⅴ', &[
+  'Ⅴ']), ('ⅵ', &['Ⅵ']), ('ⅶ', &['Ⅶ']), ('ⅷ', &['Ⅷ']), ('ⅸ', &[
+  'Ⅸ']), ('ⅹ', &['Ⅹ']), ('ⅺ', &['Ⅺ']), ('ⅻ', &['Ⅻ']), ('ⅼ', &[
+  'Ⅼ']), ('ⅽ', &['Ⅽ']), ('ⅾ', &['Ⅾ']), ('ⅿ', &['Ⅿ']), ('Ↄ', &[
+  'ↄ']), ('ↄ', &['Ↄ']), ('Ⓐ', &['ⓐ']), ('Ⓑ', &['ⓑ']), ('Ⓒ', &[
+  'ⓒ']), ('Ⓓ', &['ⓓ']), ('Ⓔ', &['ⓔ']), ('Ⓕ', &['ⓕ']), ('Ⓖ', &[
+  'ⓖ']), ('Ⓗ', &['ⓗ']), ('Ⓘ', &['ⓘ']), ('Ⓙ', &['ⓙ']), ('Ⓚ', &[
+  'ⓚ']), ('Ⓛ', &['ⓛ']), ('Ⓜ', &['ⓜ']), ('Ⓝ', &['ⓝ']), ('Ⓞ', &[
+  'ⓞ']), ('Ⓟ', &['ⓟ']), ('Ⓠ', &['ⓠ']), ('Ⓡ', &['ⓡ']), ('Ⓢ', &[
+  'ⓢ']), ('Ⓣ', &['ⓣ']), ('Ⓤ', &['ⓤ']), ('Ⓥ', &['ⓥ']), ('Ⓦ', &[
+  'ⓦ']), ('Ⓧ', &['ⓧ']), ('Ⓨ', &['ⓨ']), ('Ⓩ', &['ⓩ']), ('ⓐ', &[
+  'Ⓐ']), ('ⓑ', &['Ⓑ']), ('ⓒ', &['Ⓒ']), ('ⓓ', &['Ⓓ']), ('ⓔ', &[
+  'Ⓔ']), ('ⓕ', &['Ⓕ']), ('ⓖ', &['Ⓖ']), ('ⓗ', &['Ⓗ']), ('ⓘ', &[
+  'Ⓘ']), ('ⓙ', &['Ⓙ']), ('ⓚ', &['Ⓚ']), ('ⓛ', &['Ⓛ']), ('ⓜ', &[
+  'Ⓜ']), ('ⓝ', &['Ⓝ']), ('ⓞ', &['Ⓞ']), ('ⓟ', &['Ⓟ']), ('ⓠ', &[
+  'Ⓠ']), ('ⓡ', &['Ⓡ']), ('ⓢ', &['Ⓢ']), ('ⓣ', &['Ⓣ']), ('ⓤ', &[
+  'Ⓤ']), ('ⓥ', &['Ⓥ']), ('ⓦ', &['Ⓦ']), ('ⓧ', &['Ⓧ']), ('ⓨ', &[
+  'Ⓨ']), ('ⓩ', &['Ⓩ']), ('Ⰰ', &['ⰰ']), ('Ⰱ', &['ⰱ']), ('Ⰲ', &[
+  'ⰲ']), ('Ⰳ', &['ⰳ']), ('Ⰴ', &['ⰴ']), ('Ⰵ', &['ⰵ']), ('Ⰶ', &[
+  'ⰶ']), ('Ⰷ', &['ⰷ']), ('Ⰸ', &['ⰸ']), ('Ⰹ', &['ⰹ']), ('Ⰺ', &[
+  'ⰺ']), ('Ⰻ', &['ⰻ']), ('Ⰼ', &['ⰼ']), ('Ⰽ', &['ⰽ']), ('Ⰾ', &[
+  'ⰾ']), ('Ⰿ', &['ⰿ']), ('Ⱀ', &['ⱀ']), ('Ⱁ', &['ⱁ']), ('Ⱂ', &[
+  'ⱂ']), ('Ⱃ', &['ⱃ']), ('Ⱄ', &['ⱄ']), ('Ⱅ', &['ⱅ']), ('Ⱆ', &[
+  'ⱆ']), ('Ⱇ', &['ⱇ']), ('Ⱈ', &['ⱈ']), ('Ⱉ', &['ⱉ']), ('Ⱊ', &[
+  'ⱊ']), ('Ⱋ', &['ⱋ']), ('Ⱌ', &['ⱌ']), ('Ⱍ', &['ⱍ']), ('Ⱎ', &[
+  'ⱎ']), ('Ⱏ', &['ⱏ']), ('Ⱐ', &['ⱐ']), ('Ⱑ', &['ⱑ']), ('Ⱒ', &[
+  'ⱒ']), ('Ⱓ', &['ⱓ']), ('Ⱔ', &['ⱔ']), ('Ⱕ', &['ⱕ']), ('Ⱖ', &[
+  'ⱖ']), ('Ⱗ', &['ⱗ']), ('Ⱘ', &['ⱘ']), ('Ⱙ', &['ⱙ']), ('Ⱚ', &[
+  'ⱚ']), ('Ⱛ', &['ⱛ']), ('Ⱜ', &['ⱜ']), ('Ⱝ', &['ⱝ']), ('Ⱞ', &[
+  'ⱞ']), ('ⰰ', &['Ⰰ']), ('ⰱ', &['Ⰱ']), ('ⰲ', &['Ⰲ']), ('ⰳ', &[
+  'Ⰳ']), ('ⰴ', &['Ⰴ']), ('ⰵ', &['Ⰵ']), ('ⰶ', &['Ⰶ']), ('ⰷ', &[
+  'Ⰷ']), ('ⰸ', &['Ⰸ']), ('ⰹ', &['Ⰹ']), ('ⰺ', &['Ⰺ']), ('ⰻ', &[
+  'Ⰻ']), ('ⰼ', &['Ⰼ']), ('ⰽ', &['Ⰽ']), ('ⰾ', &['Ⰾ']), ('ⰿ', &[
+  'Ⰿ']), ('ⱀ', &['Ⱀ']), ('ⱁ', &['Ⱁ']), ('ⱂ', &['Ⱂ']), ('ⱃ', &[
+  'Ⱃ']), ('ⱄ', &['Ⱄ']), ('ⱅ', &['Ⱅ']), ('ⱆ', &['Ⱆ']), ('ⱇ', &[
+  'Ⱇ']), ('ⱈ', &['Ⱈ']), ('ⱉ', &['Ⱉ']), ('ⱊ', &['Ⱊ']), ('ⱋ', &[
+  'Ⱋ']), ('ⱌ', &['Ⱌ']), ('ⱍ', &['Ⱍ']), ('ⱎ', &['Ⱎ']), ('ⱏ', &[
+  'Ⱏ']), ('ⱐ', &['Ⱐ']), ('ⱑ', &['Ⱑ']), ('ⱒ', &['Ⱒ']), ('ⱓ', &[
+  'Ⱓ']), ('ⱔ', &['Ⱔ']), ('ⱕ', &['Ⱕ']), ('ⱖ', &['Ⱖ']), ('ⱗ', &[
+  'Ⱗ']), ('ⱘ', &['Ⱘ']), ('ⱙ', &['Ⱙ']), ('ⱚ', &['Ⱚ']), ('ⱛ', &[
+  'Ⱛ']), ('ⱜ', &['Ⱜ']), ('ⱝ', &['Ⱝ']), ('ⱞ', &['Ⱞ']), ('Ⱡ', &[
+  'ⱡ']), ('ⱡ', &['Ⱡ']), ('Ɫ', &['ɫ']), ('Ᵽ', &['ᵽ']), ('Ɽ', &[
+  'ɽ']), ('ⱥ', &['Ⱥ']), ('ⱦ', &['Ⱦ']), ('Ⱨ', &['ⱨ']), ('ⱨ', &[
+  'Ⱨ']), ('Ⱪ', &['ⱪ']), ('ⱪ', &['Ⱪ']), ('Ⱬ', &['ⱬ']), ('ⱬ', &[
+  'Ⱬ']), ('Ɑ', &['ɑ']), ('Ɱ', &['ɱ']), ('Ɐ', &['ɐ']), ('Ɒ', &['ɒ'
+  ]), ('Ⱳ', &['ⱳ']), ('ⱳ', &['Ⱳ']), ('Ⱶ', &['ⱶ']), ('ⱶ', &['Ⱶ'
+  ]), ('Ȿ', &['ȿ']), ('Ɀ', &['ɀ']), ('Ⲁ', &['ⲁ']), ('ⲁ', &['Ⲁ'
+  ]), ('Ⲃ', &['ⲃ']), ('ⲃ', &['Ⲃ']), ('Ⲅ', &['ⲅ']), ('ⲅ', &['Ⲅ'
+  ]), ('Ⲇ', &['ⲇ']), ('ⲇ', &['Ⲇ']), ('Ⲉ', &['ⲉ']), ('ⲉ', &['Ⲉ'
+  ]), ('Ⲋ', &['ⲋ']), ('ⲋ', &['Ⲋ']), ('Ⲍ', &['ⲍ']), ('ⲍ', &['Ⲍ'
+  ]), ('Ⲏ', &['ⲏ']), ('ⲏ', &['Ⲏ']), ('Ⲑ', &['ⲑ']), ('ⲑ', &['Ⲑ'
+  ]), ('Ⲓ', &['ⲓ']), ('ⲓ', &['Ⲓ']), ('Ⲕ', &['ⲕ']), ('ⲕ', &['Ⲕ'
+  ]), ('Ⲗ', &['ⲗ']), ('ⲗ', &['Ⲗ']), ('Ⲙ', &['ⲙ']), ('ⲙ', &['Ⲙ'
+  ]), ('Ⲛ', &['ⲛ']), ('ⲛ', &['Ⲛ']), ('Ⲝ', &['ⲝ']), ('ⲝ', &['Ⲝ'
+  ]), ('Ⲟ', &['ⲟ']), ('ⲟ', &['Ⲟ']), ('Ⲡ', &['ⲡ']), ('ⲡ', &['Ⲡ'
+  ]), ('Ⲣ', &['ⲣ']), ('ⲣ', &['Ⲣ']), ('Ⲥ', &['ⲥ']), ('ⲥ', &['Ⲥ'
+  ]), ('Ⲧ', &['ⲧ']), ('ⲧ', &['Ⲧ']), ('Ⲩ', &['ⲩ']), ('ⲩ', &['Ⲩ'
+  ]), ('Ⲫ', &['ⲫ']), ('ⲫ', &['Ⲫ']), ('Ⲭ', &['ⲭ']), ('ⲭ', &['Ⲭ'
+  ]), ('Ⲯ', &['ⲯ']), ('ⲯ', &['Ⲯ']), ('Ⲱ', &['ⲱ']), ('ⲱ', &['Ⲱ'
+  ]), ('Ⲳ', &['ⲳ']), ('ⲳ', &['Ⲳ']), ('Ⲵ', &['ⲵ']), ('ⲵ', &['Ⲵ'
+  ]), ('Ⲷ', &['ⲷ']), ('ⲷ', &['Ⲷ']), ('Ⲹ', &['ⲹ']), ('ⲹ', &['Ⲹ'
+  ]), ('Ⲻ', &['ⲻ']), ('ⲻ', &['Ⲻ']), ('Ⲽ', &['ⲽ']), ('ⲽ', &['Ⲽ'
+  ]), ('Ⲿ', &['ⲿ']), ('ⲿ', &['Ⲿ']), ('Ⳁ', &['ⳁ']), ('ⳁ', &['Ⳁ'
+  ]), ('Ⳃ', &['ⳃ']), ('ⳃ', &['Ⳃ']), ('Ⳅ', &['ⳅ']), ('ⳅ', &['Ⳅ'
+  ]), ('Ⳇ', &['ⳇ']), ('ⳇ', &['Ⳇ']), ('Ⳉ', &['ⳉ']), ('ⳉ', &['Ⳉ'
+  ]), ('Ⳋ', &['ⳋ']), ('ⳋ', &['Ⳋ']), ('Ⳍ', &['ⳍ']), ('ⳍ', &['Ⳍ'
+  ]), ('Ⳏ', &['ⳏ']), ('ⳏ', &['Ⳏ']), ('Ⳑ', &['ⳑ']), ('ⳑ', &['Ⳑ'
+  ]), ('Ⳓ', &['ⳓ']), ('ⳓ', &['Ⳓ']), ('Ⳕ', &['ⳕ']), ('ⳕ', &['Ⳕ'
+  ]), ('Ⳗ', &['ⳗ']), ('ⳗ', &['Ⳗ']), ('Ⳙ', &['ⳙ']), ('ⳙ', &['Ⳙ'
+  ]), ('Ⳛ', &['ⳛ']), ('ⳛ', &['Ⳛ']), ('Ⳝ', &['ⳝ']), ('ⳝ', &['Ⳝ'
+  ]), ('Ⳟ', &['ⳟ']), ('ⳟ', &['Ⳟ']), ('Ⳡ', &['ⳡ']), ('ⳡ', &['Ⳡ'
+  ]), ('Ⳣ', &['ⳣ']), ('ⳣ', &['Ⳣ']), ('Ⳬ', &['ⳬ']), ('ⳬ', &['Ⳬ'
+  ]), ('Ⳮ', &['ⳮ']), ('ⳮ', &['Ⳮ']), ('Ⳳ', &['ⳳ']), ('ⳳ', &['Ⳳ'
+  ]), ('ⴀ', &['Ⴀ']), ('ⴁ', &['Ⴁ']), ('ⴂ', &['Ⴂ']), ('ⴃ', &['Ⴃ'
+  ]), ('ⴄ', &['Ⴄ']), ('ⴅ', &['Ⴅ']), ('ⴆ', &['Ⴆ']), ('ⴇ', &['Ⴇ'
+  ]), ('ⴈ', &['Ⴈ']), ('ⴉ', &['Ⴉ']), ('ⴊ', &['Ⴊ']), ('ⴋ', &['Ⴋ'
+  ]), ('ⴌ', &['Ⴌ']), ('ⴍ', &['Ⴍ']), ('ⴎ', &['Ⴎ']), ('ⴏ', &['Ⴏ'
+  ]), ('ⴐ', &['Ⴐ']), ('ⴑ', &['Ⴑ']), ('ⴒ', &['Ⴒ']), ('ⴓ', &['Ⴓ'
+  ]), ('ⴔ', &['Ⴔ']), ('ⴕ', &['Ⴕ']), ('ⴖ', &['Ⴖ']), ('ⴗ', &['Ⴗ'
+  ]), ('ⴘ', &['Ⴘ']), ('ⴙ', &['Ⴙ']), ('ⴚ', &['Ⴚ']), ('ⴛ', &['Ⴛ'
+  ]), ('ⴜ', &['Ⴜ']), ('ⴝ', &['Ⴝ']), ('ⴞ', &['Ⴞ']), ('ⴟ', &['Ⴟ'
+  ]), ('ⴠ', &['Ⴠ']), ('ⴡ', &['Ⴡ']), ('ⴢ', &['Ⴢ']), ('ⴣ', &['Ⴣ'
+  ]), ('ⴤ', &['Ⴤ']), ('ⴥ', &['Ⴥ']), ('ⴧ', &['Ⴧ']), ('ⴭ', &['Ⴭ'
+  ]), ('Ꙁ', &['ꙁ']), ('ꙁ', &['Ꙁ']), ('Ꙃ', &['ꙃ']), ('ꙃ', &['Ꙃ'
+  ]), ('Ꙅ', &['ꙅ']), ('ꙅ', &['Ꙅ']), ('Ꙇ', &['ꙇ']), ('ꙇ', &['Ꙇ'
+  ]), ('Ꙉ', &['ꙉ']), ('ꙉ', &['Ꙉ']), ('Ꙋ', &['ᲈ', 'ꙋ', ]),
+  ('ꙋ', &['ᲈ', 'Ꙋ', ]), ('Ꙍ', &['ꙍ']), ('ꙍ', &['Ꙍ']), ('Ꙏ', &[
+  'ꙏ']), ('ꙏ', &['Ꙏ']), ('Ꙑ', &['ꙑ']), ('ꙑ', &['Ꙑ']), ('Ꙓ', &[
+  'ꙓ']), ('ꙓ', &['Ꙓ']), ('Ꙕ', &['ꙕ']), ('ꙕ', &['Ꙕ']), ('Ꙗ', &[
+  'ꙗ']), ('ꙗ', &['Ꙗ']), ('Ꙙ', &['ꙙ']), ('ꙙ', &['Ꙙ']), ('Ꙛ', &[
+  'ꙛ']), ('ꙛ', &['Ꙛ']), ('Ꙝ', &['ꙝ']), ('ꙝ', &['Ꙝ']), ('Ꙟ', &[
+  'ꙟ']), ('ꙟ', &['Ꙟ']), ('Ꙡ', &['ꙡ']), ('ꙡ', &['Ꙡ']), ('Ꙣ', &[
+  'ꙣ']), ('ꙣ', &['Ꙣ']), ('Ꙥ', &['ꙥ']), ('ꙥ', &['Ꙥ']), ('Ꙧ', &[
+  'ꙧ']), ('ꙧ', &['Ꙧ']), ('Ꙩ', &['ꙩ']), ('ꙩ', &['Ꙩ']), ('Ꙫ', &[
+  'ꙫ']), ('ꙫ', &['Ꙫ']), ('Ꙭ', &['ꙭ']), ('ꙭ', &['Ꙭ']), ('Ꚁ', &[
+  'ꚁ']), ('ꚁ', &['Ꚁ']), ('Ꚃ', &['ꚃ']), ('ꚃ', &['Ꚃ']), ('Ꚅ', &[
+  'ꚅ']), ('ꚅ', &['Ꚅ']), ('Ꚇ', &['ꚇ']), ('ꚇ', &['Ꚇ']), ('Ꚉ', &[
+  'ꚉ']), ('ꚉ', &['Ꚉ']), ('Ꚋ', &['ꚋ']), ('ꚋ', &['Ꚋ']), ('Ꚍ', &[
+  'ꚍ']), ('ꚍ', &['Ꚍ']), ('Ꚏ', &['ꚏ']), ('ꚏ', &['Ꚏ']), ('Ꚑ', &[
+  'ꚑ']), ('ꚑ', &['Ꚑ']), ('Ꚓ', &['ꚓ']), ('ꚓ', &['Ꚓ']), ('Ꚕ', &[
+  'ꚕ']), ('ꚕ', &['Ꚕ']), ('Ꚗ', &['ꚗ']), ('ꚗ', &['Ꚗ']), ('Ꚙ', &[
+  'ꚙ']), ('ꚙ', &['Ꚙ']), ('Ꚛ', &['ꚛ']), ('ꚛ', &['Ꚛ']), ('Ꜣ', &[
+  'ꜣ']), ('ꜣ', &['Ꜣ']), ('Ꜥ', &['ꜥ']), ('ꜥ', &['Ꜥ']), ('Ꜧ', &[
+  'ꜧ']), ('ꜧ', &['Ꜧ']), ('Ꜩ', &['ꜩ']), ('ꜩ', &['Ꜩ']), ('Ꜫ', &[
+  'ꜫ']), ('ꜫ', &['Ꜫ']), ('Ꜭ', &['ꜭ']), ('ꜭ', &['Ꜭ']), ('Ꜯ', &[
+  'ꜯ']), ('ꜯ', &['Ꜯ']), ('Ꜳ', &['ꜳ']), ('ꜳ', &['Ꜳ']), ('Ꜵ', &[
+  'ꜵ']), ('ꜵ', &['Ꜵ']), ('Ꜷ', &['ꜷ']), ('ꜷ', &['Ꜷ']), ('Ꜹ', &[
+  'ꜹ']), ('ꜹ', &['Ꜹ']), ('Ꜻ', &['ꜻ']), ('ꜻ', &['Ꜻ']), ('Ꜽ', &[
+  'ꜽ']), ('ꜽ', &['Ꜽ']), ('Ꜿ', &['ꜿ']), ('ꜿ', &['Ꜿ']), ('Ꝁ', &[
+  'ꝁ']), ('ꝁ', &['Ꝁ']), ('Ꝃ', &['ꝃ']), ('ꝃ', &['Ꝃ']), ('Ꝅ', &[
+  'ꝅ']), ('ꝅ', &['Ꝅ']), ('Ꝇ', &['ꝇ']), ('ꝇ', &['Ꝇ']), ('Ꝉ', &[
+  'ꝉ']), ('ꝉ', &['Ꝉ']), ('Ꝋ', &['ꝋ']), ('ꝋ', &['Ꝋ']), ('Ꝍ', &[
+  'ꝍ']), ('ꝍ', &['Ꝍ']), ('Ꝏ', &['ꝏ']), ('ꝏ', &['Ꝏ']), ('Ꝑ', &[
+  'ꝑ']), ('ꝑ', &['Ꝑ']), ('Ꝓ', &['ꝓ']), ('ꝓ', &['Ꝓ']), ('Ꝕ', &[
+  'ꝕ']), ('ꝕ', &['Ꝕ']), ('Ꝗ', &['ꝗ']), ('ꝗ', &['Ꝗ']), ('Ꝙ', &[
+  'ꝙ']), ('ꝙ', &['Ꝙ']), ('Ꝛ', &['ꝛ']), ('ꝛ', &['Ꝛ']), ('Ꝝ', &[
+  'ꝝ']), ('ꝝ', &['Ꝝ']), ('Ꝟ', &['ꝟ']), ('ꝟ', &['Ꝟ']), ('Ꝡ', &[
+  'ꝡ']), ('ꝡ', &['Ꝡ']), ('Ꝣ', &['ꝣ']), ('ꝣ', &['Ꝣ']), ('Ꝥ', &[
+  'ꝥ']), ('ꝥ', &['Ꝥ']), ('Ꝧ', &['ꝧ']), ('ꝧ', &['Ꝧ']), ('Ꝩ', &[
+  'ꝩ']), ('ꝩ', &['Ꝩ']), ('Ꝫ', &['ꝫ']), ('ꝫ', &['Ꝫ']), ('Ꝭ', &[
+  'ꝭ']), ('ꝭ', &['Ꝭ']), ('Ꝯ', &['ꝯ']), ('ꝯ', &['Ꝯ']), ('Ꝺ', &[
+  'ꝺ']), ('ꝺ', &['Ꝺ']), ('Ꝼ', &['ꝼ']), ('ꝼ', &['Ꝼ']), ('Ᵹ', &[
+  'ᵹ']), ('Ꝿ', &['ꝿ']), ('ꝿ', &['Ꝿ']), ('Ꞁ', &['ꞁ']), ('ꞁ', &[
+  'Ꞁ']), ('Ꞃ', &['ꞃ']), ('ꞃ', &['Ꞃ']), ('Ꞅ', &['ꞅ']), ('ꞅ', &[
+  'Ꞅ']), ('Ꞇ', &['ꞇ']), ('ꞇ', &['Ꞇ']), ('Ꞌ', &['ꞌ']), ('ꞌ', &[
+  'Ꞌ']), ('Ɥ', &['ɥ']), ('Ꞑ', &['ꞑ']), ('ꞑ', &['Ꞑ']), ('Ꞓ', &[
+  'ꞓ']), ('ꞓ', &['Ꞓ']), ('Ꞗ', &['ꞗ']), ('ꞗ', &['Ꞗ']), ('Ꞙ', &[
+  'ꞙ']), ('ꞙ', &['Ꞙ']), ('Ꞛ', &['ꞛ']), ('ꞛ', &['Ꞛ']), ('Ꞝ', &[
+  'ꞝ']), ('ꞝ', &['Ꞝ']), ('Ꞟ', &['ꞟ']), ('ꞟ', &['Ꞟ']), ('Ꞡ', &[
+  'ꞡ']), ('ꞡ', &['Ꞡ']), ('Ꞣ', &['ꞣ']), ('ꞣ', &['Ꞣ']), ('Ꞥ', &[
+  'ꞥ']), ('ꞥ', &['Ꞥ']), ('Ꞧ', &['ꞧ']), ('ꞧ', &['Ꞧ']), ('Ꞩ', &[
+  'ꞩ']), ('ꞩ', &['Ꞩ']), ('Ɦ', &['ɦ']), ('Ɜ', &['ɜ']), ('Ɡ', &[
+  'ɡ']), ('Ɬ', &['ɬ']), ('Ɪ', &['ɪ']), ('Ʞ', &['ʞ']), ('Ʇ', &['ʇ'
+  ]), ('Ʝ', &['ʝ']), ('Ꭓ', &['ꭓ']), ('Ꞵ', &['ꞵ']), ('ꞵ', &['Ꞵ'
+  ]), ('Ꞷ', &['ꞷ']), ('ꞷ', &['Ꞷ']), ('\u{a7b8}', &['\u{a7b9}']),
+  ('\u{a7b9}', &['\u{a7b8}']), ('ꭓ', &['Ꭓ']), ('ꭰ', &['Ꭰ']), ('ꭱ', &[
+  'Ꭱ']), ('ꭲ', &['Ꭲ']), ('ꭳ', &['Ꭳ']), ('ꭴ', &['Ꭴ']), ('ꭵ', &[
+  'Ꭵ']), ('ꭶ', &['Ꭶ']), ('ꭷ', &['Ꭷ']), ('ꭸ', &['Ꭸ']), ('ꭹ', &[
+  'Ꭹ']), ('ꭺ', &['Ꭺ']), ('ꭻ', &['Ꭻ']), ('ꭼ', &['Ꭼ']), ('ꭽ', &[
+  'Ꭽ']), ('ꭾ', &['Ꭾ']), ('ꭿ', &['Ꭿ']), ('ꮀ', &['Ꮀ']), ('ꮁ', &[
+  'Ꮁ']), ('ꮂ', &['Ꮂ']), ('ꮃ', &['Ꮃ']), ('ꮄ', &['Ꮄ']), ('ꮅ', &[
+  'Ꮅ']), ('ꮆ', &['Ꮆ']), ('ꮇ', &['Ꮇ']), ('ꮈ', &['Ꮈ']), ('ꮉ', &[
+  'Ꮉ']), ('ꮊ', &['Ꮊ']), ('ꮋ', &['Ꮋ']), ('ꮌ', &['Ꮌ']), ('ꮍ', &[
+  'Ꮍ']), ('ꮎ', &['Ꮎ']), ('ꮏ', &['Ꮏ']), ('ꮐ', &['Ꮐ']), ('ꮑ', &[
+  'Ꮑ']), ('ꮒ', &['Ꮒ']), ('ꮓ', &['Ꮓ']), ('ꮔ', &['Ꮔ']), ('ꮕ', &[
+  'Ꮕ']), ('ꮖ', &['Ꮖ']), ('ꮗ', &['Ꮗ']), ('ꮘ', &['Ꮘ']), ('ꮙ', &[
+  'Ꮙ']), ('ꮚ', &['Ꮚ']), ('ꮛ', &['Ꮛ']), ('ꮜ', &['Ꮜ']), ('ꮝ', &[
+  'Ꮝ']), ('ꮞ', &['Ꮞ']), ('ꮟ', &['Ꮟ']), ('ꮠ', &['Ꮠ']), ('ꮡ', &[
+  'Ꮡ']), ('ꮢ', &['Ꮢ']), ('ꮣ', &['Ꮣ']), ('ꮤ', &['Ꮤ']), ('ꮥ', &[
+  'Ꮥ']), ('ꮦ', &['Ꮦ']), ('ꮧ', &['Ꮧ']), ('ꮨ', &['Ꮨ']), ('ꮩ', &[
+  'Ꮩ']), ('ꮪ', &['Ꮪ']), ('ꮫ', &['Ꮫ']), ('ꮬ', &['Ꮬ']), ('ꮭ', &[
+  'Ꮭ']), ('ꮮ', &['Ꮮ']), ('ꮯ', &['Ꮯ']), ('ꮰ', &['Ꮰ']), ('ꮱ', &[
+  'Ꮱ']), ('ꮲ', &['Ꮲ']), ('ꮳ', &['Ꮳ']), ('ꮴ', &['Ꮴ']), ('ꮵ', &[
+  'Ꮵ']), ('ꮶ', &['Ꮶ']), ('ꮷ', &['Ꮷ']), ('ꮸ', &['Ꮸ']), ('ꮹ', &[
+  'Ꮹ']), ('ꮺ', &['Ꮺ']), ('ꮻ', &['Ꮻ']), ('ꮼ', &['Ꮼ']), ('ꮽ', &[
+  'Ꮽ']), ('ꮾ', &['Ꮾ']), ('ꮿ', &['Ꮿ']), ('Ａ', &['ａ']), ('Ｂ', &[
+  'ｂ']), ('Ｃ', &['ｃ']), ('Ｄ', &['ｄ']), ('Ｅ', &['ｅ']), ('Ｆ', &[
+  'ｆ']), ('Ｇ', &['ｇ']), ('Ｈ', &['ｈ']), ('Ｉ', &['ｉ']), ('Ｊ', &[
+  'ｊ']), ('Ｋ', &['ｋ']), ('Ｌ', &['ｌ']), ('Ｍ', &['ｍ']), ('Ｎ', &[
+  'ｎ']), ('Ｏ', &['ｏ']), ('Ｐ', &['ｐ']), ('Ｑ', &['ｑ']), ('Ｒ', &[
+  'ｒ']), ('Ｓ', &['ｓ']), ('Ｔ', &['ｔ']), ('Ｕ', &['ｕ']), ('Ｖ', &[
+  'ｖ']), ('Ｗ', &['ｗ']), ('Ｘ', &['ｘ']), ('Ｙ', &['ｙ']), ('Ｚ', &[
+  'ｚ']), ('ａ', &['Ａ']), ('ｂ', &['Ｂ']), ('ｃ', &['Ｃ']), ('ｄ', &[
+  'Ｄ']), ('ｅ', &['Ｅ']), ('ｆ', &['Ｆ']), ('ｇ', &['Ｇ']), ('ｈ', &[
+  'Ｈ']), ('ｉ', &['Ｉ']), ('ｊ', &['Ｊ']), ('ｋ', &['Ｋ']), ('ｌ', &[
+  'Ｌ']), ('ｍ', &['Ｍ']), ('ｎ', &['Ｎ']), ('ｏ', &['Ｏ']), ('ｐ', &[
+  'Ｐ']), ('ｑ', &['Ｑ']), ('ｒ', &['Ｒ']), ('ｓ', &['Ｓ']), ('ｔ', &[
+  'Ｔ']), ('ｕ', &['Ｕ']), ('ｖ', &['Ｖ']), ('ｗ', &['Ｗ']), ('ｘ', &[
+  'Ｘ']), ('ｙ', &['Ｙ']), ('ｚ', &['Ｚ']), ('𐐀', &['𐐨']),
+  ('𐐁', &['𐐩']), ('𐐂', &['𐐪']), ('𐐃', &['𐐫']), ('𐐄', &[
+  '𐐬']), ('𐐅', &['𐐭']), ('𐐆', &['𐐮']), ('𐐇', &['𐐯']),
+  ('𐐈', &['𐐰']), ('𐐉', &['𐐱']), ('𐐊', &['𐐲']), ('𐐋', &[
+  '𐐳']), ('𐐌', &['𐐴']), ('𐐍', &['𐐵']), ('𐐎', &['𐐶']),
+  ('𐐏', &['𐐷']), ('𐐐', &['𐐸']), ('𐐑', &['𐐹']), ('𐐒', &[
+  '𐐺']), ('𐐓', &['𐐻']), ('𐐔', &['𐐼']), ('𐐕', &['𐐽']),
+  ('𐐖', &['𐐾']), ('𐐗', &['𐐿']), ('𐐘', &['𐑀']), ('𐐙', &[
+  '𐑁']), ('𐐚', &['𐑂']), ('𐐛', &['𐑃']), ('𐐜', &['𐑄']),
+  ('𐐝', &['𐑅']), ('𐐞', &['𐑆']), ('𐐟', &['𐑇']), ('𐐠', &[
+  '𐑈']), ('𐐡', &['𐑉']), ('𐐢', &['𐑊']), ('𐐣', &['𐑋']),
+  ('𐐤', &['𐑌']), ('𐐥', &['𐑍']), ('𐐦', &['𐑎']), ('𐐧', &[
+  '𐑏']), ('𐐨', &['𐐀']), ('𐐩', &['𐐁']), ('𐐪', &['𐐂']),
+  ('𐐫', &['𐐃']), ('𐐬', &['𐐄']), ('𐐭', &['𐐅']), ('𐐮', &[
+  '𐐆']), ('𐐯', &['𐐇']), ('𐐰', &['𐐈']), ('𐐱', &['𐐉']),
+  ('𐐲', &['𐐊']), ('𐐳', &['𐐋']), ('𐐴', &['𐐌']), ('𐐵', &[
+  '𐐍']), ('𐐶', &['𐐎']), ('𐐷', &['𐐏']), ('𐐸', &['𐐐']),
+  ('𐐹', &['𐐑']), ('𐐺', &['𐐒']), ('𐐻', &['𐐓']), ('𐐼', &[
+  '𐐔']), ('𐐽', &['𐐕']), ('𐐾', &['𐐖']), ('𐐿', &['𐐗']),
+  ('𐑀', &['𐐘']), ('𐑁', &['𐐙']), ('𐑂', &['𐐚']), ('𐑃', &[
+  '𐐛']), ('𐑄', &['𐐜']), ('𐑅', &['𐐝']), ('𐑆', &['𐐞']),
+  ('𐑇', &['𐐟']), ('𐑈', &['𐐠']), ('𐑉', &['𐐡']), ('𐑊', &[
+  '𐐢']), ('𐑋', &['𐐣']), ('𐑌', &['𐐤']), ('𐑍', &['𐐥']),
+  ('𐑎', &['𐐦']), ('𐑏', &['𐐧']), ('𐒰', &['𐓘']), ('𐒱', &[
+  '𐓙']), ('𐒲', &['𐓚']), ('𐒳', &['𐓛']), ('𐒴', &['𐓜']),
+  ('𐒵', &['𐓝']), ('𐒶', &['𐓞']), ('𐒷', &['𐓟']), ('𐒸', &[
+  '𐓠']), ('𐒹', &['𐓡']), ('𐒺', &['𐓢']), ('𐒻', &['𐓣']),
+  ('𐒼', &['𐓤']), ('𐒽', &['𐓥']), ('𐒾', &['𐓦']), ('𐒿', &[
+  '𐓧']), ('𐓀', &['𐓨']), ('𐓁', &['𐓩']), ('𐓂', &['𐓪']),
+  ('𐓃', &['𐓫']), ('𐓄', &['𐓬']), ('𐓅', &['𐓭']), ('𐓆', &[
+  '𐓮']), ('𐓇', &['𐓯']), ('𐓈', &['𐓰']), ('𐓉', &['𐓱']),
+  ('𐓊', &['𐓲']), ('𐓋', &['𐓳']), ('𐓌', &['𐓴']), ('𐓍', &[
+  '𐓵']), ('𐓎', &['𐓶']), ('𐓏', &['𐓷']), ('𐓐', &['𐓸']),
+  ('𐓑', &['𐓹']), ('𐓒', &['𐓺']), ('𐓓', &['𐓻']), ('𐓘', &[
+  '𐒰']), ('𐓙', &['𐒱']), ('𐓚', &['𐒲']), ('𐓛', &['𐒳']),
+  ('𐓜', &['𐒴']), ('𐓝', &['𐒵']), ('𐓞', &['𐒶']), ('𐓟', &[
+  '𐒷']), ('𐓠', &['𐒸']), ('𐓡', &['𐒹']), ('𐓢', &['𐒺']),
+  ('𐓣', &['𐒻']), ('𐓤', &['𐒼']), ('𐓥', &['𐒽']), ('𐓦', &[
+  '𐒾']), ('𐓧', &['𐒿']), ('𐓨', &['𐓀']), ('𐓩', &['𐓁']),
+  ('𐓪', &['𐓂']), ('𐓫', &['𐓃']), ('𐓬', &['𐓄']), ('𐓭', &[
+  '𐓅']), ('𐓮', &['𐓆']), ('𐓯', &['𐓇']), ('𐓰', &['𐓈']),
+  ('𐓱', &['𐓉']), ('𐓲', &['𐓊']), ('𐓳', &['𐓋']), ('𐓴', &[
+  '𐓌']), ('𐓵', &['𐓍']), ('𐓶', &['𐓎']), ('𐓷', &['𐓏']),
+  ('𐓸', &['𐓐']), ('𐓹', &['𐓑']), ('𐓺', &['𐓒']), ('𐓻', &[
+  '𐓓']), ('𐲀', &['𐳀']), ('𐲁', &['𐳁']), ('𐲂', &['𐳂']),
+  ('𐲃', &['𐳃']), ('𐲄', &['𐳄']), ('𐲅', &['𐳅']), ('𐲆', &[
+  '𐳆']), ('𐲇', &['𐳇']), ('𐲈', &['𐳈']), ('𐲉', &['𐳉']),
+  ('𐲊', &['𐳊']), ('𐲋', &['𐳋']), ('𐲌', &['𐳌']), ('𐲍', &[
+  '𐳍']), ('𐲎', &['𐳎']), ('𐲏', &['𐳏']), ('𐲐', &['𐳐']),
+  ('𐲑', &['𐳑']), ('𐲒', &['𐳒']), ('𐲓', &['𐳓']), ('𐲔', &[
+  '𐳔']), ('𐲕', &['𐳕']), ('𐲖', &['𐳖']), ('𐲗', &['𐳗']),
+  ('𐲘', &['𐳘']), ('𐲙', &['𐳙']), ('𐲚', &['𐳚']), ('𐲛', &[
+  '𐳛']), ('𐲜', &['𐳜']), ('𐲝', &['𐳝']), ('𐲞', &['𐳞']),
+  ('𐲟', &['𐳟']), ('𐲠', &['𐳠']), ('𐲡', &['𐳡']), ('𐲢', &[
+  '𐳢']), ('𐲣', &['𐳣']), ('𐲤', &['𐳤']), ('𐲥', &['𐳥']),
+  ('𐲦', &['𐳦']), ('𐲧', &['𐳧']), ('𐲨', &['𐳨']), ('𐲩', &[
+  '𐳩']), ('𐲪', &['𐳪']), ('𐲫', &['𐳫']), ('𐲬', &['𐳬']),
+  ('𐲭', &['𐳭']), ('𐲮', &['𐳮']), ('𐲯', &['𐳯']), ('𐲰', &[
+  '𐳰']), ('𐲱', &['𐳱']), ('𐲲', &['𐳲']), ('𐳀', &['𐲀']),
+  ('𐳁', &['𐲁']), ('𐳂', &['𐲂']), ('𐳃', &['𐲃']), ('𐳄', &[
+  '𐲄']), ('𐳅', &['𐲅']), ('𐳆', &['𐲆']), ('𐳇', &['𐲇']),
+  ('𐳈', &['𐲈']), ('𐳉', &['𐲉']), ('𐳊', &['𐲊']), ('𐳋', &[
+  '𐲋']), ('𐳌', &['𐲌']), ('𐳍', &['𐲍']), ('𐳎', &['𐲎']),
+  ('𐳏', &['𐲏']), ('𐳐', &['𐲐']), ('𐳑', &['𐲑']), ('𐳒', &[
+  '𐲒']), ('𐳓', &['𐲓']), ('𐳔', &['𐲔']), ('𐳕', &['𐲕']),
+  ('𐳖', &['𐲖']), ('𐳗', &['𐲗']), ('𐳘', &['𐲘']), ('𐳙', &[
+  '𐲙']), ('𐳚', &['𐲚']), ('𐳛', &['𐲛']), ('𐳜', &['𐲜']),
+  ('𐳝', &['𐲝']), ('𐳞', &['𐲞']), ('𐳟', &['𐲟']), ('𐳠', &[
+  '𐲠']), ('𐳡', &['𐲡']), ('𐳢', &['𐲢']), ('𐳣', &['𐲣']),
+  ('𐳤', &['𐲤']), ('𐳥', &['𐲥']), ('𐳦', &['𐲦']), ('𐳧', &[
+  '𐲧']), ('𐳨', &['𐲨']), ('𐳩', &['𐲩']), ('𐳪', &['𐲪']),
+  ('𐳫', &['𐲫']), ('𐳬', &['𐲬']), ('𐳭', &['𐲭']), ('𐳮', &[
+  '𐲮']), ('𐳯', &['𐲯']), ('𐳰', &['𐲰']), ('𐳱', &['𐲱']),
+  ('𐳲', &['𐲲']), ('𑢠', &['𑣀']), ('𑢡', &['𑣁']), ('𑢢', &[
+  '𑣂']), ('𑢣', &['𑣃']), ('𑢤', &['𑣄']), ('𑢥', &['𑣅']),
+  ('𑢦', &['𑣆']), ('𑢧', &['𑣇']), ('𑢨', &['𑣈']), ('𑢩', &[
+  '𑣉']), ('𑢪', &['𑣊']), ('𑢫', &['𑣋']), ('𑢬', &['𑣌']),
+  ('𑢭', &['𑣍']), ('𑢮', &['𑣎']), ('𑢯', &['𑣏']), ('𑢰', &[
+  '𑣐']), ('𑢱', &['𑣑']), ('𑢲', &['𑣒']), ('𑢳', &['𑣓']),
+  ('𑢴', &['𑣔']), ('𑢵', &['𑣕']), ('𑢶', &['𑣖']), ('𑢷', &[
+  '𑣗']), ('𑢸', &['𑣘']), ('𑢹', &['𑣙']), ('𑢺', &['𑣚']),
+  ('𑢻', &['𑣛']), ('𑢼', &['𑣜']), ('𑢽', &['𑣝']), ('𑢾', &[
+  '𑣞']), ('𑢿', &['𑣟']), ('𑣀', &['𑢠']), ('𑣁', &['𑢡']),
+  ('𑣂', &['𑢢']), ('𑣃', &['𑢣']), ('𑣄', &['𑢤']), ('𑣅', &[
+  '𑢥']), ('𑣆', &['𑢦']), ('𑣇', &['𑢧']), ('𑣈', &['𑢨']),
+  ('𑣉', &['𑢩']), ('𑣊', &['𑢪']), ('𑣋', &['𑢫']), ('𑣌', &[
+  '𑢬']), ('𑣍', &['𑢭']), ('𑣎', &['𑢮']), ('𑣏', &['𑢯']),
+  ('𑣐', &['𑢰']), ('𑣑', &['𑢱']), ('𑣒', &['𑢲']), ('𑣓', &[
+  '𑢳']), ('𑣔', &['𑢴']), ('𑣕', &['𑢵']), ('𑣖', &['𑢶']),
+  ('𑣗', &['𑢷']), ('𑣘', &['𑢸']), ('𑣙', &['𑢹']), ('𑣚', &[
+  '𑢺']), ('𑣛', &['𑢻']), ('𑣜', &['𑢼']), ('𑣝', &['𑢽']),
+  ('𑣞', &['𑢾']), ('𑣟', &['𑢿']), ('\u{16e40}', &['\u{16e60}']),
+  ('\u{16e41}', &['\u{16e61}']), ('\u{16e42}', &['\u{16e62}']),
+  ('\u{16e43}', &['\u{16e63}']), ('\u{16e44}', &['\u{16e64}']),
+  ('\u{16e45}', &['\u{16e65}']), ('\u{16e46}', &['\u{16e66}']),
+  ('\u{16e47}', &['\u{16e67}']), ('\u{16e48}', &['\u{16e68}']),
+  ('\u{16e49}', &['\u{16e69}']), ('\u{16e4a}', &['\u{16e6a}']),
+  ('\u{16e4b}', &['\u{16e6b}']), ('\u{16e4c}', &['\u{16e6c}']),
+  ('\u{16e4d}', &['\u{16e6d}']), ('\u{16e4e}', &['\u{16e6e}']),
+  ('\u{16e4f}', &['\u{16e6f}']), ('\u{16e50}', &['\u{16e70}']),
+  ('\u{16e51}', &['\u{16e71}']), ('\u{16e52}', &['\u{16e72}']),
+  ('\u{16e53}', &['\u{16e73}']), ('\u{16e54}', &['\u{16e74}']),
+  ('\u{16e55}', &['\u{16e75}']), ('\u{16e56}', &['\u{16e76}']),
+  ('\u{16e57}', &['\u{16e77}']), ('\u{16e58}', &['\u{16e78}']),
+  ('\u{16e59}', &['\u{16e79}']), ('\u{16e5a}', &['\u{16e7a}']),
+  ('\u{16e5b}', &['\u{16e7b}']), ('\u{16e5c}', &['\u{16e7c}']),
+  ('\u{16e5d}', &['\u{16e7d}']), ('\u{16e5e}', &['\u{16e7e}']),
+  ('\u{16e5f}', &['\u{16e7f}']), ('\u{16e60}', &['\u{16e40}']),
+  ('\u{16e61}', &['\u{16e41}']), ('\u{16e62}', &['\u{16e42}']),
+  ('\u{16e63}', &['\u{16e43}']), ('\u{16e64}', &['\u{16e44}']),
+  ('\u{16e65}', &['\u{16e45}']), ('\u{16e66}', &['\u{16e46}']),
+  ('\u{16e67}', &['\u{16e47}']), ('\u{16e68}', &['\u{16e48}']),
+  ('\u{16e69}', &['\u{16e49}']), ('\u{16e6a}', &['\u{16e4a}']),
+  ('\u{16e6b}', &['\u{16e4b}']), ('\u{16e6c}', &['\u{16e4c}']),
+  ('\u{16e6d}', &['\u{16e4d}']), ('\u{16e6e}', &['\u{16e4e}']),
+  ('\u{16e6f}', &['\u{16e4f}']), ('\u{16e70}', &['\u{16e50}']),
+  ('\u{16e71}', &['\u{16e51}']), ('\u{16e72}', &['\u{16e52}']),
+  ('\u{16e73}', &['\u{16e53}']), ('\u{16e74}', &['\u{16e54}']),
+  ('\u{16e75}', &['\u{16e55}']), ('\u{16e76}', &['\u{16e56}']),
+  ('\u{16e77}', &['\u{16e57}']), ('\u{16e78}', &['\u{16e58}']),
+  ('\u{16e79}', &['\u{16e59}']), ('\u{16e7a}', &['\u{16e5a}']),
+  ('\u{16e7b}', &['\u{16e5b}']), ('\u{16e7c}', &['\u{16e5c}']),
+  ('\u{16e7d}', &['\u{16e5d}']), ('\u{16e7e}', &['\u{16e5e}']),
+  ('\u{16e7f}', &['\u{16e5f}']), ('𞤀', &['𞤢']), ('𞤁', &['𞤣']),
+  ('𞤂', &['𞤤']), ('𞤃', &['𞤥']), ('𞤄', &['𞤦']), ('𞤅', &[
+  '𞤧']), ('𞤆', &['𞤨']), ('𞤇', &['𞤩']), ('𞤈', &['𞤪']),
+  ('𞤉', &['𞤫']), ('𞤊', &['𞤬']), ('𞤋', &['𞤭']), ('𞤌', &[
+  '𞤮']), ('𞤍', &['𞤯']), ('𞤎', &['𞤰']), ('𞤏', &['𞤱']),
+  ('𞤐', &['𞤲']), ('𞤑', &['𞤳']), ('𞤒', &['𞤴']), ('𞤓', &[
+  '𞤵']), ('𞤔', &['𞤶']), ('𞤕', &['𞤷']), ('𞤖', &['𞤸']),
+  ('𞤗', &['𞤹']), ('𞤘', &['𞤺']), ('𞤙', &['𞤻']), ('𞤚', &[
+  '𞤼']), ('𞤛', &['𞤽']), ('𞤜', &['𞤾']), ('𞤝', &['𞤿']),
+  ('𞤞', &['𞥀']), ('𞤟', &['𞥁']), ('𞤠', &['𞥂']), ('𞤡', &[
+  '𞥃']), ('𞤢', &['𞤀']), ('𞤣', &['𞤁']), ('𞤤', &['𞤂']),
+  ('𞤥', &['𞤃']), ('𞤦', &['𞤄']), ('𞤧', &['𞤅']), ('𞤨', &[
+  '𞤆']), ('𞤩', &['𞤇']), ('𞤪', &['𞤈']), ('𞤫', &['𞤉']),
+  ('𞤬', &['𞤊']), ('𞤭', &['𞤋']), ('𞤮', &['𞤌']), ('𞤯', &[
+  '𞤍']), ('𞤰', &['𞤎']), ('𞤱', &['𞤏']), ('𞤲', &['𞤐']),
+  ('𞤳', &['𞤑']), ('𞤴', &['𞤒']), ('𞤵', &['𞤓']), ('𞤶', &[
+  '𞤔']), ('𞤷', &['𞤕']), ('𞤸', &['𞤖']), ('𞤹', &['𞤗']),
+  ('𞤺', &['𞤘']), ('𞤻', &['𞤙']), ('𞤼', &['𞤚']), ('𞤽', &[
+  '𞤛']), ('𞤾', &['𞤜']), ('𞤿', &['𞤝']), ('𞥀', &['𞤞']),
+  ('𞥁', &['𞤟']), ('𞥂', &['𞤠']), ('𞥃', &['𞤡']),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/general_category.rs b/third_party/rust/regex-syntax/src/unicode_tables/general_category.rs
new file mode 100644
index 000000000000..9a7be2880838
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/general_category.rs
@@ -0,0 +1,1907 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate general-category tmp/ucd-11.0.0/ --chars --exclude surrogate
+//
+// ucd-generate is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
+  ("Cased_Letter", CASED_LETTER), ("Close_Punctuation", CLOSE_PUNCTUATION),
+  ("Connector_Punctuation", CONNECTOR_PUNCTUATION), ("Control", CONTROL),
+  ("Currency_Symbol", CURRENCY_SYMBOL),
+  ("Dash_Punctuation", DASH_PUNCTUATION), ("Decimal_Number", DECIMAL_NUMBER),
+  ("Enclosing_Mark", ENCLOSING_MARK),
+  ("Final_Punctuation", FINAL_PUNCTUATION), ("Format", FORMAT),
+  ("Initial_Punctuation", INITIAL_PUNCTUATION), ("Letter", LETTER),
+  ("Letter_Number", LETTER_NUMBER), ("Line_Separator", LINE_SEPARATOR),
+  ("Lowercase_Letter", LOWERCASE_LETTER), ("Mark", MARK),
+  ("Math_Symbol", MATH_SYMBOL), ("Modifier_Letter", MODIFIER_LETTER),
+  ("Modifier_Symbol", MODIFIER_SYMBOL), ("Nonspacing_Mark", NONSPACING_MARK),
+  ("Number", NUMBER), ("Open_Punctuation", OPEN_PUNCTUATION),
+  ("Other", OTHER), ("Other_Letter", OTHER_LETTER),
+  ("Other_Number", OTHER_NUMBER), ("Other_Punctuation", OTHER_PUNCTUATION),
+  ("Other_Symbol", OTHER_SYMBOL),
+  ("Paragraph_Separator", PARAGRAPH_SEPARATOR), ("Private_Use", PRIVATE_USE),
+  ("Punctuation", PUNCTUATION), ("Separator", SEPARATOR),
+  ("Space_Separator", SPACE_SEPARATOR), ("Spacing_Mark", SPACING_MARK),
+  ("Symbol", SYMBOL), ("Titlecase_Letter", TITLECASE_LETTER),
+  ("Unassigned", UNASSIGNED), ("Uppercase_Letter", UPPERCASE_LETTER),
+];
+
+pub const CASED_LETTER: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('µ', 'µ'), ('À', 'Ö'), ('Ø', 'ö'),
+  ('ø', 'ƺ'), ('Ƽ', 'ƿ'), ('Ǆ', 'ʓ'), ('ʕ', 'ʯ'), ('Ͱ', 'ͳ'),
+  ('Ͷ', 'ͷ'), ('ͻ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'),
+  ('Ό', 'Ό'), ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('\u{560}', '\u{588}'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('Ꭰ', 'Ᏽ'),
+  ('ᏸ', 'ᏽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('ᴀ', 'ᴫ'), ('ᵫ', 'ᵷ'), ('ᵹ', 'ᶚ'),
+  ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'),
+  ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'),
+  ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('ℙ', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℭ'),
+  ('ℯ', 'ℴ'), ('ℹ', 'ℹ'), ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'),
+  ('ⅎ', 'ⅎ'), ('Ↄ', 'ↄ'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'),
+  ('Ⱡ', 'ⱻ'), ('Ȿ', 'ⳤ'), ('Ⳬ', 'ⳮ'), ('Ⳳ', 'ⳳ'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('Ꙁ', 'ꙭ'),
+  ('Ꚁ', 'ꚛ'), ('Ꜣ', 'ꝯ'), ('ꝱ', 'ꞇ'), ('Ꞌ', 'ꞎ'),
+  ('Ꞑ', '\u{a7b9}'), ('ꟺ', 'ꟺ'), ('ꬰ', 'ꭚ'), ('ꭠ', 'ꭥ'),
+  ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('Ａ', 'Ｚ'),
+  ('ａ', 'ｚ'), ('𐐀', '𐑏'), ('𐒰', '𐓓'), ('𐓘', '𐓻'),
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𑢠', '𑣟'),
+  ('\u{16e40}', '\u{16e7f}'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'), ('𝛜', '𝛺'),
+  ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'), ('𝝐', '𝝮'),
+  ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'), ('𝟄', '𝟋'),
+  ('𞤀', '𞥃'),
+];
+
+pub const CLOSE_PUNCTUATION: &'static [(char, char)] = &[
+  (')', ')'), (']', ']'), ('}', '}'), ('༻', '༻'), ('༽', '༽'),
+  ('᚜', '᚜'), ('⁆', '⁆'), ('⁾', '⁾'), ('₎', '₎'),
+  ('⌉', '⌉'), ('⌋', '⌋'), ('〉', '〉'), ('❩', '❩'),
+  ('❫', '❫'), ('❭', '❭'), ('❯', '❯'), ('❱', '❱'),
+  ('❳', '❳'), ('❵', '❵'), ('⟆', '⟆'), ('⟧', '⟧'),
+  ('⟩', '⟩'), ('⟫', '⟫'), ('⟭', '⟭'), ('⟯', '⟯'),
+  ('⦄', '⦄'), ('⦆', '⦆'), ('⦈', '⦈'), ('⦊', '⦊'),
+  ('⦌', '⦌'), ('⦎', '⦎'), ('⦐', '⦐'), ('⦒', '⦒'),
+  ('⦔', '⦔'), ('⦖', '⦖'), ('⦘', '⦘'), ('⧙', '⧙'),
+  ('⧛', '⧛'), ('⧽', '⧽'), ('⸣', '⸣'), ('⸥', '⸥'),
+  ('⸧', '⸧'), ('⸩', '⸩'), ('〉', '〉'), ('》', '》'),
+  ('」', '」'), ('』', '』'), ('】', '】'), ('〕', '〕'),
+  ('〗', '〗'), ('〙', '〙'), ('〛', '〛'), ('〞', '〟'),
+  ('﴾', '﴾'), ('︘', '︘'), ('︶', '︶'), ('︸', '︸'),
+  ('︺', '︺'), ('︼', '︼'), ('︾', '︾'), ('﹀', '﹀'),
+  ('﹂', '﹂'), ('﹄', '﹄'), ('﹈', '﹈'), ('﹚', '﹚'),
+  ('﹜', '﹜'), ('﹞', '﹞'), ('）', '）'), ('］', '］'),
+  ('｝', '｝'), ('｠', '｠'), ('｣', '｣'),
+];
+
+pub const CONNECTOR_PUNCTUATION: &'static [(char, char)] = &[
+  ('_', '_'), ('‿', '⁀'), ('⁔', '⁔'), ('︳', '︴'), ('﹍', '﹏'),
+  ('＿', '＿'),
+];
+
+pub const CONTROL: &'static [(char, char)] = &[
+  ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}'),
+];
+
+pub const CURRENCY_SYMBOL: &'static [(char, char)] = &[
+  ('$', '$'), ('¢', '¥'), ('֏', '֏'), ('؋', '؋'),
+  ('\u{7fe}', '\u{7ff}'), ('৲', '৳'), ('৻', '৻'), ('૱', '૱'),
+  ('௹', '௹'), ('฿', '฿'), ('៛', '៛'), ('₠', '₿'),
+  ('꠸', '꠸'), ('﷼', '﷼'), ('﹩', '﹩'), ('＄', '＄'),
+  ('￠', '￡'), ('￥', '￦'), ('\u{1ecb0}', '\u{1ecb0}'),
+];
+
+pub const DASH_PUNCTUATION: &'static [(char, char)] = &[
+  ('-', '-'), ('֊', '֊'), ('־', '־'), ('᐀', '᐀'), ('᠆', '᠆'),
+  ('‐', '―'), ('⸗', '⸗'), ('⸚', '⸚'), ('⸺', '⸻'),
+  ('⹀', '⹀'), ('〜', '〜'), ('〰', '〰'), ('゠', '゠'),
+  ('︱', '︲'), ('﹘', '﹘'), ('﹣', '﹣'), ('－', '－'),
+];
+
+pub const DECIMAL_NUMBER: &'static [(char, char)] = &[
+  ('0', '9'), ('٠', '٩'), ('۰', '۹'), ('߀', '߉'), ('०', '९'),
+  ('০', '৯'), ('੦', '੯'), ('૦', '૯'), ('୦', '୯'),
+  ('௦', '௯'), ('౦', '౯'), ('೦', '೯'), ('൦', '൯'),
+  ('෦', '෯'), ('๐', '๙'), ('໐', '໙'), ('༠', '༩'),
+  ('၀', '၉'), ('႐', '႙'), ('០', '៩'), ('᠐', '᠙'),
+  ('᥆', '᥏'), ('᧐', '᧙'), ('᪀', '᪉'), ('᪐', '᪙'),
+  ('᭐', '᭙'), ('᮰', '᮹'), ('᱀', '᱉'), ('᱐', '᱙'),
+  ('꘠', '꘩'), ('꣐', '꣙'), ('꤀', '꤉'), ('꧐', '꧙'),
+  ('꧰', '꧹'), ('꩐', '꩙'), ('꯰', '꯹'), ('０', '９'),
+  ('𐒠', '𐒩'), ('\u{10d30}', '\u{10d39}'), ('𑁦', '𑁯'),
+  ('𑃰', '𑃹'), ('𑄶', '𑄿'), ('𑇐', '𑇙'), ('𑋰', '𑋹'),
+  ('𑑐', '𑑙'), ('𑓐', '𑓙'), ('𑙐', '𑙙'), ('𑛀', '𑛉'),
+  ('𑜰', '𑜹'), ('𑣠', '𑣩'), ('𑱐', '𑱙'), ('𑵐', '𑵙'),
+  ('\u{11da0}', '\u{11da9}'), ('𖩠', '𖩩'), ('𖭐', '𖭙'),
+  ('𝟎', '𝟿'), ('𞥐', '𞥙'),
+];
+
+pub const ENCLOSING_MARK: &'static [(char, char)] = &[
+  ('҈', '҉'), ('᪾', '᪾'), ('⃝', '⃠'), ('⃢', '⃤'),
+  ('꙰', '꙲'),
+];
+
+pub const FINAL_PUNCTUATION: &'static [(char, char)] = &[
+  ('»', '»'), ('’', '’'), ('”', '”'), ('›', '›'),
+  ('⸃', '⸃'), ('⸅', '⸅'), ('⸊', '⸊'), ('⸍', '⸍'),
+  ('⸝', '⸝'), ('⸡', '⸡'),
+];
+
+pub const FORMAT: &'static [(char, char)] = &[
+  ('\u{ad}', '\u{ad}'), ('\u{600}', '\u{605}'), ('\u{61c}', '\u{61c}'),
+  ('\u{6dd}', '\u{6dd}'), ('\u{70f}', '\u{70f}'), ('\u{8e2}', '\u{8e2}'),
+  ('\u{180e}', '\u{180e}'), ('\u{200b}', '\u{200f}'),
+  ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{2064}'),
+  ('\u{2066}', '\u{206f}'), ('\u{feff}', '\u{feff}'),
+  ('\u{fff9}', '\u{fffb}'), ('\u{110bd}', '\u{110bd}'),
+  ('\u{110cd}', '\u{110cd}'), ('\u{1bca0}', '\u{1bca3}'),
+  ('\u{1d173}', '\u{1d17a}'), ('\u{e0001}', '\u{e0001}'),
+  ('\u{e0020}', '\u{e007f}'),
+];
+
+pub const INITIAL_PUNCTUATION: &'static [(char, char)] = &[
+  ('«', '«'), ('‘', '‘'), ('‛', '“'), ('‟', '‟'),
+  ('‹', '‹'), ('⸂', '⸂'), ('⸄', '⸄'), ('⸉', '⸉'),
+  ('⸌', '⸌'), ('⸜', '⸜'), ('⸠', '⸠'),
+];
+
+pub const LETTER: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'),
+  ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'), ('ˆ', 'ˑ'), ('ˠ', 'ˤ'),
+  ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('Ͱ', 'ʹ'), ('Ͷ', 'ͷ'), ('ͺ', 'ͽ'),
+  ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'),
+  ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'), ('Ա', 'Ֆ'), ('ՙ', 'ՙ'),
+  ('\u{560}', '\u{588}'), ('א', 'ת'), ('\u{5ef}', 'ײ'), ('ؠ', 'ي'),
+  ('ٮ', 'ٯ'), ('ٱ', 'ۓ'), ('ە', 'ە'), ('ۥ', 'ۦ'), ('ۮ', 'ۯ'),
+  ('ۺ', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', 'ܐ'), ('ܒ', 'ܯ'), ('ݍ', 'ޥ'),
+  ('ޱ', 'ޱ'), ('ߊ', 'ߪ'), ('ߴ', 'ߵ'), ('ߺ', 'ߺ'), ('ࠀ', 'ࠕ'),
+  ('ࠚ', 'ࠚ'), ('ࠤ', 'ࠤ'), ('ࠨ', 'ࠨ'), ('ࡀ', 'ࡘ'),
+  ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'), ('ऄ', 'ह'),
+  ('ऽ', 'ऽ'), ('ॐ', 'ॐ'), ('क़', 'ॡ'), ('ॱ', 'ঀ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('ঽ', 'ঽ'), ('ৎ', 'ৎ'),
+  ('ড়', 'ঢ়'), ('য়', 'ৡ'), ('ৰ', 'ৱ'), ('ৼ', 'ৼ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('ੲ', 'ੴ'), ('અ', 'ઍ'), ('એ', 'ઑ'),
+  ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'), ('વ', 'હ'),
+  ('ઽ', 'ઽ'), ('ૐ', 'ૐ'), ('ૠ', 'ૡ'), ('ૹ', 'ૹ'),
+  ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'),
+  ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('ଽ', 'ଽ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୡ'), ('ୱ', 'ୱ'), ('ஃ', 'ஃ'), ('அ', 'ஊ'),
+  ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'),
+  ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'),
+  ('ௐ', 'ௐ'), ('అ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'),
+  ('ప', 'హ'), ('ఽ', 'ఽ'), ('ౘ', 'ౚ'), ('ౠ', 'ౡ'),
+  ('ಀ', 'ಀ'), ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'),
+  ('ಪ', 'ಳ'), ('ವ', 'ಹ'), ('ಽ', 'ಽ'), ('ೞ', 'ೞ'),
+  ('ೠ', 'ೡ'), ('ೱ', 'ೲ'), ('അ', 'ഌ'), ('എ', 'ഐ'),
+  ('ഒ', 'ഺ'), ('ഽ', 'ഽ'), ('ൎ', 'ൎ'), ('ൔ', 'ൖ'),
+  ('ൟ', 'ൡ'), ('ൺ', 'ൿ'), ('අ', 'ඖ'), ('ක', 'න'),
+  ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'), ('ก', 'ะ'),
+  ('า', 'ำ'), ('เ', 'ๆ'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'),
+  ('ງ', 'ຈ'), ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'),
+  ('ນ', 'ຟ'), ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'),
+  ('ສ', 'ຫ'), ('ອ', 'ະ'), ('າ', 'ຳ'), ('ຽ', 'ຽ'),
+  ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('ໜ', 'ໟ'), ('ༀ', 'ༀ'),
+  ('ཀ', 'ཇ'), ('ཉ', 'ཬ'), ('ྈ', 'ྌ'), ('က', 'ဪ'),
+  ('ဿ', 'ဿ'), ('ၐ', 'ၕ'), ('ၚ', 'ၝ'), ('ၡ', 'ၡ'),
+  ('ၥ', 'ၦ'), ('ၮ', 'ၰ'), ('ၵ', 'ႁ'), ('ႎ', 'ႎ'),
+  ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'),
+  ('ჼ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛱ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', 'ᜑ'), ('ᜠ', 'ᜱ'), ('ᝀ', 'ᝑ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ក', 'ឳ'), ('ៗ', 'ៗ'),
+  ('ៜ', 'ៜ'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢄ'), ('ᢇ', 'ᢨ'),
+  ('ᢪ', 'ᢪ'), ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᥐ', 'ᥭ'),
+  ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('ᨀ', 'ᨖ'),
+  ('ᨠ', 'ᩔ'), ('ᪧ', 'ᪧ'), ('ᬅ', 'ᬳ'), ('ᭅ', 'ᭋ'),
+  ('ᮃ', 'ᮠ'), ('ᮮ', 'ᮯ'), ('ᮺ', 'ᯥ'), ('ᰀ', 'ᰣ'),
+  ('ᱍ', 'ᱏ'), ('ᱚ', 'ᱽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('ᳩ', 'ᳬ'), ('ᳮ', 'ᳱ'), ('ᳵ', 'ᳶ'),
+  ('ᴀ', 'ᶿ'), ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'),
+  ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'),
+  ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'),
+  ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'Ί'), ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('ℙ', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℭ'),
+  ('ℯ', 'ℹ'), ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'),
+  ('Ↄ', 'ↄ'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'),
+  ('Ⳬ', 'ⳮ'), ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'),
+  ('ⴭ', 'ⴭ'), ('ⴰ', 'ⵧ'), ('ⵯ', 'ⵯ'), ('ⶀ', 'ⶖ'),
+  ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'),
+  ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'),
+  ('ⸯ', 'ⸯ'), ('々', '〆'), ('〱', '〵'), ('〻', '〼'),
+  ('ぁ', 'ゖ'), ('ゝ', 'ゟ'), ('ァ', 'ヺ'), ('ー', 'ヿ'),
+  ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'),
+  ('㐀', '䶵'), ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'),
+  ('ꔀ', 'ꘌ'), ('ꘐ', 'ꘟ'), ('ꘪ', 'ꘫ'), ('Ꙁ', 'ꙮ'),
+  ('ꙿ', 'ꚝ'), ('ꚠ', 'ꛥ'), ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'),
+  ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꠁ'), ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'),
+  ('ꠌ', 'ꠢ'), ('ꡀ', 'ꡳ'), ('ꢂ', 'ꢳ'), ('ꣲ', 'ꣷ'),
+  ('ꣻ', 'ꣻ'), ('ꣽ', '\u{a8fe}'), ('ꤊ', 'ꤥ'), ('ꤰ', 'ꥆ'),
+  ('ꥠ', 'ꥼ'), ('ꦄ', 'ꦲ'), ('ꧏ', 'ꧏ'), ('ꧠ', 'ꧤ'),
+  ('ꧦ', 'ꧯ'), ('ꧺ', 'ꧾ'), ('ꨀ', 'ꨨ'), ('ꩀ', 'ꩂ'),
+  ('ꩄ', 'ꩋ'), ('ꩠ', 'ꩶ'), ('ꩺ', 'ꩺ'), ('ꩾ', 'ꪯ'),
+  ('ꪱ', 'ꪱ'), ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪽ'), ('ꫀ', 'ꫀ'),
+  ('ꫂ', 'ꫂ'), ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫪ'), ('ꫲ', 'ꫴ'),
+  ('ꬁ', 'ꬆ'), ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'),
+  ('ꬨ', 'ꬮ'), ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯢ'),
+  ('가', '힣'), ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'),
+  ('並', '龎'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'יִ'),
+  ('ײַ', 'ﬨ'), ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'),
+  ('נּ', 'סּ'), ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'),
+  ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'), ('ﹰ', 'ﹴ'),
+  ('ﹶ', 'ﻼ'), ('Ａ', 'Ｚ'), ('ａ', 'ｚ'), ('ｦ', 'ﾾ'),
+  ('ￂ', 'ￇ'), ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'),
+  ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'),
+  ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐊀', '𐊜'),
+  ('𐊠', '𐋐'), ('𐌀', '𐌟'), ('𐌭', '𐍀'), ('𐍂', '𐍉'),
+  ('𐍐', '𐍵'), ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'),
+  ('𐐀', '𐒝'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'),
+  ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+  ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'),
+  ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'), ('𐢀', '𐢞'),
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'), ('𐤠', '𐤹'),
+  ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨀'), ('𐨐', '𐨓'),
+  ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'), ('𐩠', '𐩼'), ('𐪀', '𐪜'),
+  ('𐫀', '𐫇'), ('𐫉', '𐫤'), ('𐬀', '𐬵'), ('𐭀', '𐭕'),
+  ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'), ('𐲀', '𐲲'),
+  ('𐳀', '𐳲'), ('\u{10d00}', '\u{10d23}'), ('\u{10f00}', '\u{10f1c}'),
+  ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'), ('𑀃', '𑀷'),
+  ('𑂃', '𑂯'), ('𑃐', '𑃨'), ('𑄃', '𑄦'),
+  ('\u{11144}', '\u{11144}'), ('𑅐', '𑅲'), ('𑅶', '𑅶'),
+  ('𑆃', '𑆲'), ('𑇁', '𑇄'), ('𑇚', '𑇚'), ('𑇜', '𑇜'),
+  ('𑈀', '𑈑'), ('𑈓', '𑈫'), ('𑊀', '𑊆'), ('𑊈', '𑊈'),
+  ('𑊊', '𑊍'), ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋞'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑌽'), ('𑍐', '𑍐'),
+  ('𑍝', '𑍡'), ('𑐀', '𑐴'), ('𑑇', '𑑊'), ('𑒀', '𑒯'),
+  ('𑓄', '𑓅'), ('𑓇', '𑓇'), ('𑖀', '𑖮'), ('𑗘', '𑗛'),
+  ('𑘀', '𑘯'), ('𑙄', '𑙄'), ('𑚀', '𑚪'), ('𑜀', '\u{1171a}'),
+  ('\u{11800}', '\u{1182b}'), ('𑢠', '𑣟'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨀'), ('𑨋', '𑨲'), ('𑨺', '𑨺'), ('𑩐', '𑩐'),
+  ('𑩜', '𑪃'), ('𑪆', '𑪉'), ('\u{11a9d}', '\u{11a9d}'),
+  ('𑫀', '𑫸'), ('𑰀', '𑰈'), ('𑰊', '𑰮'), ('𑱀', '𑱀'),
+  ('𑱲', '𑲏'), ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴰'),
+  ('𑵆', '𑵆'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d89}'), ('\u{11d98}', '\u{11d98}'),
+  ('\u{11ee0}', '\u{11ef2}'), ('𒀀', '𒎙'), ('𒒀', '𒕃'),
+  ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'), ('𖩀', '𖩞'),
+  ('𖫐', '𖫭'), ('𖬀', '𖬯'), ('𖭀', '𖭃'), ('𖭣', '𖭷'),
+  ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'), ('𖼀', '𖽄'),
+  ('𖽐', '𖽐'), ('𖾓', '𖾟'), ('𖿠', '𖿡'), ('𗀀', '\u{187f1}'),
+  ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'),
+  ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𝐀', '𝑔'),
+  ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'),
+  ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'),
+  ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'),
+  ('𝛜', '𝛺'), ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'),
+  ('𝝐', '𝝮'), ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'),
+  ('𝟄', '𝟋'), ('𞠀', '𞣄'), ('𞤀', '𞥃'), ('𞸀', '𞸃'),
+  ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'),
+  ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'),
+  ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'),
+  ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'),
+  ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'),
+  ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'),
+  ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'),
+  ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'),
+  ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'), ('𫠠', '𬺡'),
+  ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const LETTER_NUMBER: &'static [(char, char)] = &[
+  ('ᛮ', 'ᛰ'), ('Ⅰ', 'ↂ'), ('ↅ', 'ↈ'), ('〇', '〇'),
+  ('〡', '〩'), ('〸', '〺'), ('ꛦ', 'ꛯ'), ('𐅀', '𐅴'),
+  ('𐍁', '𐍁'), ('𐍊', '𐍊'), ('𐏑', '𐏕'), ('𒐀', '𒑮'),
+];
+
+pub const LINE_SEPARATOR: &'static [(char, char)] = &[
+  ('\u{2028}', '\u{2028}'),
+];
+
+pub const LOWERCASE_LETTER: &'static [(char, char)] = &[
+  ('a', 'z'), ('µ', 'µ'), ('ß', 'ö'), ('ø', 'ÿ'), ('ā', 'ā'),
+  ('ă', 'ă'), ('ą', 'ą'), ('ć', 'ć'), ('ĉ', 'ĉ'), ('ċ', 'ċ'),
+  ('č', 'č'), ('ď', 'ď'), ('đ', 'đ'), ('ē', 'ē'), ('ĕ', 'ĕ'),
+  ('ė', 'ė'), ('ę', 'ę'), ('ě', 'ě'), ('ĝ', 'ĝ'), ('ğ', 'ğ'),
+  ('ġ', 'ġ'), ('ģ', 'ģ'), ('ĥ', 'ĥ'), ('ħ', 'ħ'), ('ĩ', 'ĩ'),
+  ('ī', 'ī'), ('ĭ', 'ĭ'), ('į', 'į'), ('ı', 'ı'), ('ĳ', 'ĳ'),
+  ('ĵ', 'ĵ'), ('ķ', 'ĸ'), ('ĺ', 'ĺ'), ('ļ', 'ļ'), ('ľ', 'ľ'),
+  ('ŀ', 'ŀ'), ('ł', 'ł'), ('ń', 'ń'), ('ņ', 'ņ'), ('ň', 'ŉ'),
+  ('ŋ', 'ŋ'), ('ō', 'ō'), ('ŏ', 'ŏ'), ('ő', 'ő'), ('œ', 'œ'),
+  ('ŕ', 'ŕ'), ('ŗ', 'ŗ'), ('ř', 'ř'), ('ś', 'ś'), ('ŝ', 'ŝ'),
+  ('ş', 'ş'), ('š', 'š'), ('ţ', 'ţ'), ('ť', 'ť'), ('ŧ', 'ŧ'),
+  ('ũ', 'ũ'), ('ū', 'ū'), ('ŭ', 'ŭ'), ('ů', 'ů'), ('ű', 'ű'),
+  ('ų', 'ų'), ('ŵ', 'ŵ'), ('ŷ', 'ŷ'), ('ź', 'ź'), ('ż', 'ż'),
+  ('ž', 'ƀ'), ('ƃ', 'ƃ'), ('ƅ', 'ƅ'), ('ƈ', 'ƈ'), ('ƌ', 'ƍ'),
+  ('ƒ', 'ƒ'), ('ƕ', 'ƕ'), ('ƙ', 'ƛ'), ('ƞ', 'ƞ'), ('ơ', 'ơ'),
+  ('ƣ', 'ƣ'), ('ƥ', 'ƥ'), ('ƨ', 'ƨ'), ('ƪ', 'ƫ'), ('ƭ', 'ƭ'),
+  ('ư', 'ư'), ('ƴ', 'ƴ'), ('ƶ', 'ƶ'), ('ƹ', 'ƺ'), ('ƽ', 'ƿ'),
+  ('ǆ', 'ǆ'), ('ǉ', 'ǉ'), ('ǌ', 'ǌ'), ('ǎ', 'ǎ'), ('ǐ', 'ǐ'),
+  ('ǒ', 'ǒ'), ('ǔ', 'ǔ'), ('ǖ', 'ǖ'), ('ǘ', 'ǘ'), ('ǚ', 'ǚ'),
+  ('ǜ', 'ǝ'), ('ǟ', 'ǟ'), ('ǡ', 'ǡ'), ('ǣ', 'ǣ'), ('ǥ', 'ǥ'),
+  ('ǧ', 'ǧ'), ('ǩ', 'ǩ'), ('ǫ', 'ǫ'), ('ǭ', 'ǭ'), ('ǯ', 'ǰ'),
+  ('ǳ', 'ǳ'), ('ǵ', 'ǵ'), ('ǹ', 'ǹ'), ('ǻ', 'ǻ'), ('ǽ', 'ǽ'),
+  ('ǿ', 'ǿ'), ('ȁ', 'ȁ'), ('ȃ', 'ȃ'), ('ȅ', 'ȅ'), ('ȇ', 'ȇ'),
+  ('ȉ', 'ȉ'), ('ȋ', 'ȋ'), ('ȍ', 'ȍ'), ('ȏ', 'ȏ'), ('ȑ', 'ȑ'),
+  ('ȓ', 'ȓ'), ('ȕ', 'ȕ'), ('ȗ', 'ȗ'), ('ș', 'ș'), ('ț', 'ț'),
+  ('ȝ', 'ȝ'), ('ȟ', 'ȟ'), ('ȡ', 'ȡ'), ('ȣ', 'ȣ'), ('ȥ', 'ȥ'),
+  ('ȧ', 'ȧ'), ('ȩ', 'ȩ'), ('ȫ', 'ȫ'), ('ȭ', 'ȭ'), ('ȯ', 'ȯ'),
+  ('ȱ', 'ȱ'), ('ȳ', 'ȹ'), ('ȼ', 'ȼ'), ('ȿ', 'ɀ'), ('ɂ', 'ɂ'),
+  ('ɇ', 'ɇ'), ('ɉ', 'ɉ'), ('ɋ', 'ɋ'), ('ɍ', 'ɍ'), ('ɏ', 'ʓ'),
+  ('ʕ', 'ʯ'), ('ͱ', 'ͱ'), ('ͳ', 'ͳ'), ('ͷ', 'ͷ'), ('ͻ', 'ͽ'),
+  ('ΐ', 'ΐ'), ('ά', 'ώ'), ('ϐ', 'ϑ'), ('ϕ', 'ϗ'), ('ϙ', 'ϙ'),
+  ('ϛ', 'ϛ'), ('ϝ', 'ϝ'), ('ϟ', 'ϟ'), ('ϡ', 'ϡ'), ('ϣ', 'ϣ'),
+  ('ϥ', 'ϥ'), ('ϧ', 'ϧ'), ('ϩ', 'ϩ'), ('ϫ', 'ϫ'), ('ϭ', 'ϭ'),
+  ('ϯ', 'ϳ'), ('ϵ', 'ϵ'), ('ϸ', 'ϸ'), ('ϻ', 'ϼ'), ('а', 'џ'),
+  ('ѡ', 'ѡ'), ('ѣ', 'ѣ'), ('ѥ', 'ѥ'), ('ѧ', 'ѧ'), ('ѩ', 'ѩ'),
+  ('ѫ', 'ѫ'), ('ѭ', 'ѭ'), ('ѯ', 'ѯ'), ('ѱ', 'ѱ'), ('ѳ', 'ѳ'),
+  ('ѵ', 'ѵ'), ('ѷ', 'ѷ'), ('ѹ', 'ѹ'), ('ѻ', 'ѻ'), ('ѽ', 'ѽ'),
+  ('ѿ', 'ѿ'), ('ҁ', 'ҁ'), ('ҋ', 'ҋ'), ('ҍ', 'ҍ'), ('ҏ', 'ҏ'),
+  ('ґ', 'ґ'), ('ғ', 'ғ'), ('ҕ', 'ҕ'), ('җ', 'җ'), ('ҙ', 'ҙ'),
+  ('қ', 'қ'), ('ҝ', 'ҝ'), ('ҟ', 'ҟ'), ('ҡ', 'ҡ'), ('ң', 'ң'),
+  ('ҥ', 'ҥ'), ('ҧ', 'ҧ'), ('ҩ', 'ҩ'), ('ҫ', 'ҫ'), ('ҭ', 'ҭ'),
+  ('ү', 'ү'), ('ұ', 'ұ'), ('ҳ', 'ҳ'), ('ҵ', 'ҵ'), ('ҷ', 'ҷ'),
+  ('ҹ', 'ҹ'), ('һ', 'һ'), ('ҽ', 'ҽ'), ('ҿ', 'ҿ'), ('ӂ', 'ӂ'),
+  ('ӄ', 'ӄ'), ('ӆ', 'ӆ'), ('ӈ', 'ӈ'), ('ӊ', 'ӊ'), ('ӌ', 'ӌ'),
+  ('ӎ', 'ӏ'), ('ӑ', 'ӑ'), ('ӓ', 'ӓ'), ('ӕ', 'ӕ'), ('ӗ', 'ӗ'),
+  ('ә', 'ә'), ('ӛ', 'ӛ'), ('ӝ', 'ӝ'), ('ӟ', 'ӟ'), ('ӡ', 'ӡ'),
+  ('ӣ', 'ӣ'), ('ӥ', 'ӥ'), ('ӧ', 'ӧ'), ('ө', 'ө'), ('ӫ', 'ӫ'),
+  ('ӭ', 'ӭ'), ('ӯ', 'ӯ'), ('ӱ', 'ӱ'), ('ӳ', 'ӳ'), ('ӵ', 'ӵ'),
+  ('ӷ', 'ӷ'), ('ӹ', 'ӹ'), ('ӻ', 'ӻ'), ('ӽ', 'ӽ'), ('ӿ', 'ӿ'),
+  ('ԁ', 'ԁ'), ('ԃ', 'ԃ'), ('ԅ', 'ԅ'), ('ԇ', 'ԇ'), ('ԉ', 'ԉ'),
+  ('ԋ', 'ԋ'), ('ԍ', 'ԍ'), ('ԏ', 'ԏ'), ('ԑ', 'ԑ'), ('ԓ', 'ԓ'),
+  ('ԕ', 'ԕ'), ('ԗ', 'ԗ'), ('ԙ', 'ԙ'), ('ԛ', 'ԛ'), ('ԝ', 'ԝ'),
+  ('ԟ', 'ԟ'), ('ԡ', 'ԡ'), ('ԣ', 'ԣ'), ('ԥ', 'ԥ'), ('ԧ', 'ԧ'),
+  ('ԩ', 'ԩ'), ('ԫ', 'ԫ'), ('ԭ', 'ԭ'), ('ԯ', 'ԯ'),
+  ('\u{560}', '\u{588}'), ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('ᏸ', 'ᏽ'),
+  ('ᲀ', 'ᲈ'), ('ᴀ', 'ᴫ'), ('ᵫ', 'ᵷ'), ('ᵹ', 'ᶚ'),
+  ('ḁ', 'ḁ'), ('ḃ', 'ḃ'), ('ḅ', 'ḅ'), ('ḇ', 'ḇ'),
+  ('ḉ', 'ḉ'), ('ḋ', 'ḋ'), ('ḍ', 'ḍ'), ('ḏ', 'ḏ'),
+  ('ḑ', 'ḑ'), ('ḓ', 'ḓ'), ('ḕ', 'ḕ'), ('ḗ', 'ḗ'),
+  ('ḙ', 'ḙ'), ('ḛ', 'ḛ'), ('ḝ', 'ḝ'), ('ḟ', 'ḟ'),
+  ('ḡ', 'ḡ'), ('ḣ', 'ḣ'), ('ḥ', 'ḥ'), ('ḧ', 'ḧ'),
+  ('ḩ', 'ḩ'), ('ḫ', 'ḫ'), ('ḭ', 'ḭ'), ('ḯ', 'ḯ'),
+  ('ḱ', 'ḱ'), ('ḳ', 'ḳ'), ('ḵ', 'ḵ'), ('ḷ', 'ḷ'),
+  ('ḹ', 'ḹ'), ('ḻ', 'ḻ'), ('ḽ', 'ḽ'), ('ḿ', 'ḿ'),
+  ('ṁ', 'ṁ'), ('ṃ', 'ṃ'), ('ṅ', 'ṅ'), ('ṇ', 'ṇ'),
+  ('ṉ', 'ṉ'), ('ṋ', 'ṋ'), ('ṍ', 'ṍ'), ('ṏ', 'ṏ'),
+  ('ṑ', 'ṑ'), ('ṓ', 'ṓ'), ('ṕ', 'ṕ'), ('ṗ', 'ṗ'),
+  ('ṙ', 'ṙ'), ('ṛ', 'ṛ'), ('ṝ', 'ṝ'), ('ṟ', 'ṟ'),
+  ('ṡ', 'ṡ'), ('ṣ', 'ṣ'), ('ṥ', 'ṥ'), ('ṧ', 'ṧ'),
+  ('ṩ', 'ṩ'), ('ṫ', 'ṫ'), ('ṭ', 'ṭ'), ('ṯ', 'ṯ'),
+  ('ṱ', 'ṱ'), ('ṳ', 'ṳ'), ('ṵ', 'ṵ'), ('ṷ', 'ṷ'),
+  ('ṹ', 'ṹ'), ('ṻ', 'ṻ'), ('ṽ', 'ṽ'), ('ṿ', 'ṿ'),
+  ('ẁ', 'ẁ'), ('ẃ', 'ẃ'), ('ẅ', 'ẅ'), ('ẇ', 'ẇ'),
+  ('ẉ', 'ẉ'), ('ẋ', 'ẋ'), ('ẍ', 'ẍ'), ('ẏ', 'ẏ'),
+  ('ẑ', 'ẑ'), ('ẓ', 'ẓ'), ('ẕ', 'ẝ'), ('ẟ', 'ẟ'),
+  ('ạ', 'ạ'), ('ả', 'ả'), ('ấ', 'ấ'), ('ầ', 'ầ'),
+  ('ẩ', 'ẩ'), ('ẫ', 'ẫ'), ('ậ', 'ậ'), ('ắ', 'ắ'),
+  ('ằ', 'ằ'), ('ẳ', 'ẳ'), ('ẵ', 'ẵ'), ('ặ', 'ặ'),
+  ('ẹ', 'ẹ'), ('ẻ', 'ẻ'), ('ẽ', 'ẽ'), ('ế', 'ế'),
+  ('ề', 'ề'), ('ể', 'ể'), ('ễ', 'ễ'), ('ệ', 'ệ'),
+  ('ỉ', 'ỉ'), ('ị', 'ị'), ('ọ', 'ọ'), ('ỏ', 'ỏ'),
+  ('ố', 'ố'), ('ồ', 'ồ'), ('ổ', 'ổ'), ('ỗ', 'ỗ'),
+  ('ộ', 'ộ'), ('ớ', 'ớ'), ('ờ', 'ờ'), ('ở', 'ở'),
+  ('ỡ', 'ỡ'), ('ợ', 'ợ'), ('ụ', 'ụ'), ('ủ', 'ủ'),
+  ('ứ', 'ứ'), ('ừ', 'ừ'), ('ử', 'ử'), ('ữ', 'ữ'),
+  ('ự', 'ự'), ('ỳ', 'ỳ'), ('ỵ', 'ỵ'), ('ỷ', 'ỷ'),
+  ('ỹ', 'ỹ'), ('ỻ', 'ỻ'), ('ỽ', 'ỽ'), ('ỿ', 'ἇ'),
+  ('ἐ', 'ἕ'), ('ἠ', 'ἧ'), ('ἰ', 'ἷ'), ('ὀ', 'ὅ'),
+  ('ὐ', 'ὗ'), ('ὠ', 'ὧ'), ('ὰ', 'ώ'), ('ᾀ', 'ᾇ'),
+  ('ᾐ', 'ᾗ'), ('ᾠ', 'ᾧ'), ('ᾰ', 'ᾴ'), ('ᾶ', 'ᾷ'),
+  ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῇ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'ῗ'), ('ῠ', 'ῧ'), ('ῲ', 'ῴ'), ('ῶ', 'ῷ'),
+  ('ℊ', 'ℊ'), ('ℎ', 'ℏ'), ('ℓ', 'ℓ'), ('ℯ', 'ℯ'),
+  ('ℴ', 'ℴ'), ('ℹ', 'ℹ'), ('ℼ', 'ℽ'), ('ⅆ', 'ⅉ'),
+  ('ⅎ', 'ⅎ'), ('ↄ', 'ↄ'), ('ⰰ', 'ⱞ'), ('ⱡ', 'ⱡ'),
+  ('ⱥ', 'ⱦ'), ('ⱨ', 'ⱨ'), ('ⱪ', 'ⱪ'), ('ⱬ', 'ⱬ'),
+  ('ⱱ', 'ⱱ'), ('ⱳ', 'ⱴ'), ('ⱶ', 'ⱻ'), ('ⲁ', 'ⲁ'),
+  ('ⲃ', 'ⲃ'), ('ⲅ', 'ⲅ'), ('ⲇ', 'ⲇ'), ('ⲉ', 'ⲉ'),
+  ('ⲋ', 'ⲋ'), ('ⲍ', 'ⲍ'), ('ⲏ', 'ⲏ'), ('ⲑ', 'ⲑ'),
+  ('ⲓ', 'ⲓ'), ('ⲕ', 'ⲕ'), ('ⲗ', 'ⲗ'), ('ⲙ', 'ⲙ'),
+  ('ⲛ', 'ⲛ'), ('ⲝ', 'ⲝ'), ('ⲟ', 'ⲟ'), ('ⲡ', 'ⲡ'),
+  ('ⲣ', 'ⲣ'), ('ⲥ', 'ⲥ'), ('ⲧ', 'ⲧ'), ('ⲩ', 'ⲩ'),
+  ('ⲫ', 'ⲫ'), ('ⲭ', 'ⲭ'), ('ⲯ', 'ⲯ'), ('ⲱ', 'ⲱ'),
+  ('ⲳ', 'ⲳ'), ('ⲵ', 'ⲵ'), ('ⲷ', 'ⲷ'), ('ⲹ', 'ⲹ'),
+  ('ⲻ', 'ⲻ'), ('ⲽ', 'ⲽ'), ('ⲿ', 'ⲿ'), ('ⳁ', 'ⳁ'),
+  ('ⳃ', 'ⳃ'), ('ⳅ', 'ⳅ'), ('ⳇ', 'ⳇ'), ('ⳉ', 'ⳉ'),
+  ('ⳋ', 'ⳋ'), ('ⳍ', 'ⳍ'), ('ⳏ', 'ⳏ'), ('ⳑ', 'ⳑ'),
+  ('ⳓ', 'ⳓ'), ('ⳕ', 'ⳕ'), ('ⳗ', 'ⳗ'), ('ⳙ', 'ⳙ'),
+  ('ⳛ', 'ⳛ'), ('ⳝ', 'ⳝ'), ('ⳟ', 'ⳟ'), ('ⳡ', 'ⳡ'),
+  ('ⳣ', 'ⳤ'), ('ⳬ', 'ⳬ'), ('ⳮ', 'ⳮ'), ('ⳳ', 'ⳳ'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ꙁ', 'ꙁ'),
+  ('ꙃ', 'ꙃ'), ('ꙅ', 'ꙅ'), ('ꙇ', 'ꙇ'), ('ꙉ', 'ꙉ'),
+  ('ꙋ', 'ꙋ'), ('ꙍ', 'ꙍ'), ('ꙏ', 'ꙏ'), ('ꙑ', 'ꙑ'),
+  ('ꙓ', 'ꙓ'), ('ꙕ', 'ꙕ'), ('ꙗ', 'ꙗ'), ('ꙙ', 'ꙙ'),
+  ('ꙛ', 'ꙛ'), ('ꙝ', 'ꙝ'), ('ꙟ', 'ꙟ'), ('ꙡ', 'ꙡ'),
+  ('ꙣ', 'ꙣ'), ('ꙥ', 'ꙥ'), ('ꙧ', 'ꙧ'), ('ꙩ', 'ꙩ'),
+  ('ꙫ', 'ꙫ'), ('ꙭ', 'ꙭ'), ('ꚁ', 'ꚁ'), ('ꚃ', 'ꚃ'),
+  ('ꚅ', 'ꚅ'), ('ꚇ', 'ꚇ'), ('ꚉ', 'ꚉ'), ('ꚋ', 'ꚋ'),
+  ('ꚍ', 'ꚍ'), ('ꚏ', 'ꚏ'), ('ꚑ', 'ꚑ'), ('ꚓ', 'ꚓ'),
+  ('ꚕ', 'ꚕ'), ('ꚗ', 'ꚗ'), ('ꚙ', 'ꚙ'), ('ꚛ', 'ꚛ'),
+  ('ꜣ', 'ꜣ'), ('ꜥ', 'ꜥ'), ('ꜧ', 'ꜧ'), ('ꜩ', 'ꜩ'),
+  ('ꜫ', 'ꜫ'), ('ꜭ', 'ꜭ'), ('ꜯ', 'ꜱ'), ('ꜳ', 'ꜳ'),
+  ('ꜵ', 'ꜵ'), ('ꜷ', 'ꜷ'), ('ꜹ', 'ꜹ'), ('ꜻ', 'ꜻ'),
+  ('ꜽ', 'ꜽ'), ('ꜿ', 'ꜿ'), ('ꝁ', 'ꝁ'), ('ꝃ', 'ꝃ'),
+  ('ꝅ', 'ꝅ'), ('ꝇ', 'ꝇ'), ('ꝉ', 'ꝉ'), ('ꝋ', 'ꝋ'),
+  ('ꝍ', 'ꝍ'), ('ꝏ', 'ꝏ'), ('ꝑ', 'ꝑ'), ('ꝓ', 'ꝓ'),
+  ('ꝕ', 'ꝕ'), ('ꝗ', 'ꝗ'), ('ꝙ', 'ꝙ'), ('ꝛ', 'ꝛ'),
+  ('ꝝ', 'ꝝ'), ('ꝟ', 'ꝟ'), ('ꝡ', 'ꝡ'), ('ꝣ', 'ꝣ'),
+  ('ꝥ', 'ꝥ'), ('ꝧ', 'ꝧ'), ('ꝩ', 'ꝩ'), ('ꝫ', 'ꝫ'),
+  ('ꝭ', 'ꝭ'), ('ꝯ', 'ꝯ'), ('ꝱ', 'ꝸ'), ('ꝺ', 'ꝺ'),
+  ('ꝼ', 'ꝼ'), ('ꝿ', 'ꝿ'), ('ꞁ', 'ꞁ'), ('ꞃ', 'ꞃ'),
+  ('ꞅ', 'ꞅ'), ('ꞇ', 'ꞇ'), ('ꞌ', 'ꞌ'), ('ꞎ', 'ꞎ'),
+  ('ꞑ', 'ꞑ'), ('ꞓ', 'ꞕ'), ('ꞗ', 'ꞗ'), ('ꞙ', 'ꞙ'),
+  ('ꞛ', 'ꞛ'), ('ꞝ', 'ꞝ'), ('ꞟ', 'ꞟ'), ('ꞡ', 'ꞡ'),
+  ('ꞣ', 'ꞣ'), ('ꞥ', 'ꞥ'), ('ꞧ', 'ꞧ'), ('ꞩ', 'ꞩ'),
+  ('\u{a7af}', '\u{a7af}'), ('ꞵ', 'ꞵ'), ('ꞷ', 'ꞷ'),
+  ('\u{a7b9}', '\u{a7b9}'), ('ꟺ', 'ꟺ'), ('ꬰ', 'ꭚ'), ('ꭠ', 'ꭥ'),
+  ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('ａ', 'ｚ'),
+  ('𐐨', '𐑏'), ('𐓘', '𐓻'), ('𐳀', '𐳲'), ('𑣀', '𑣟'),
+  ('\u{16e60}', '\u{16e7f}'), ('𝐚', '𝐳'), ('𝑎', '𝑔'),
+  ('𝑖', '𝑧'), ('𝒂', '𝒛'), ('𝒶', '𝒹'), ('𝒻', '𝒻'),
+  ('𝒽', '𝓃'), ('𝓅', '𝓏'), ('𝓪', '𝔃'), ('𝔞', '𝔷'),
+  ('𝕒', '𝕫'), ('𝖆', '𝖟'), ('𝖺', '𝗓'), ('𝗮', '𝘇'),
+  ('𝘢', '𝘻'), ('𝙖', '𝙯'), ('𝚊', '𝚥'), ('𝛂', '𝛚'),
+  ('𝛜', '𝛡'), ('𝛼', '𝜔'), ('𝜖', '𝜛'), ('𝜶', '𝝎'),
+  ('𝝐', '𝝕'), ('𝝰', '𝞈'), ('𝞊', '𝞏'), ('𝞪', '𝟂'),
+  ('𝟄', '𝟉'), ('𝟋', '𝟋'), ('𞤢', '𞥃'),
+];
+
+pub const MARK: &'static [(char, char)] = &[
+  ('̀', 'ͯ'), ('҃', '҉'), ('֑', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'),
+  ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('ؐ', 'ؚ'), ('ً', 'ٟ'), ('ٰ', 'ٰ'),
+  ('ۖ', 'ۜ'), ('۟', 'ۤ'), ('ۧ', 'ۨ'), ('۪', 'ۭ'), ('ܑ', 'ܑ'),
+  ('ܰ', '݊'), ('ަ', 'ް'), ('߫', '߳'), ('\u{7fd}', '\u{7fd}'),
+  ('ࠖ', '࠙'), ('ࠛ', 'ࠣ'), ('ࠥ', 'ࠧ'), ('ࠩ', '࠭'),
+  ('࡙', '࡛'), ('\u{8d3}', '࣡'), ('ࣣ', 'ः'), ('ऺ', '़'),
+  ('ा', 'ॏ'), ('॑', 'ॗ'), ('ॢ', 'ॣ'), ('ঁ', 'ঃ'),
+  ('়', '়'), ('া', 'ৄ'), ('ে', 'ৈ'), ('ো', '্'),
+  ('ৗ', 'ৗ'), ('ৢ', 'ৣ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਃ'),
+  ('਼', '਼'), ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'),
+  ('ੑ', 'ੑ'), ('ੰ', 'ੱ'), ('ੵ', 'ੵ'), ('ઁ', 'ઃ'),
+  ('઼', '઼'), ('ા', 'ૅ'), ('ે', 'ૉ'), ('ો', '્'),
+  ('ૢ', 'ૣ'), ('ૺ', '૿'), ('ଁ', 'ଃ'), ('଼', '଼'),
+  ('ା', 'ୄ'), ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'),
+  ('ୢ', 'ୣ'), ('ஂ', 'ஂ'), ('ா', 'ூ'), ('ெ', 'ை'),
+  ('ொ', '்'), ('ௗ', 'ௗ'), ('ఀ', '\u{c04}'), ('ా', 'ౄ'),
+  ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'), ('ౢ', 'ౣ'),
+  ('ಁ', 'ಃ'), ('಼', '಼'), ('ಾ', 'ೄ'), ('ೆ', 'ೈ'),
+  ('ೊ', '್'), ('ೕ', 'ೖ'), ('ೢ', 'ೣ'), ('ഀ', 'ഃ'),
+  ('഻', '഼'), ('ാ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', '്'),
+  ('ൗ', 'ൗ'), ('ൢ', 'ൣ'), ('ං', 'ඃ'), ('්', '්'),
+  ('ා', 'ු'), ('ූ', 'ූ'), ('ෘ', 'ෟ'), ('ෲ', 'ෳ'),
+  ('ั', 'ั'), ('ิ', 'ฺ'), ('็', '๎'), ('ັ', 'ັ'),
+  ('ິ', 'ູ'), ('ົ', 'ຼ'), ('່', 'ໍ'), ('༘', '༙'),
+  ('༵', '༵'), ('༷', '༷'), ('༹', '༹'), ('༾', '༿'),
+  ('ཱ', '྄'), ('྆', '྇'), ('ྍ', 'ྗ'), ('ྙ', 'ྼ'),
+  ('࿆', '࿆'), ('ါ', 'ှ'), ('ၖ', 'ၙ'), ('ၞ', 'ၠ'),
+  ('ၢ', 'ၤ'), ('ၧ', 'ၭ'), ('ၱ', 'ၴ'), ('ႂ', 'ႍ'),
+  ('ႏ', 'ႏ'), ('ႚ', 'ႝ'), ('፝', '፟'), ('ᜒ', '᜔'),
+  ('ᜲ', '᜴'), ('ᝒ', 'ᝓ'), ('ᝲ', 'ᝳ'), ('឴', '៓'),
+  ('៝', '៝'), ('᠋', '᠍'), ('ᢅ', 'ᢆ'), ('ᢩ', 'ᢩ'),
+  ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'), ('ᨗ', 'ᨛ'), ('ᩕ', 'ᩞ'),
+  ('᩠', '᩼'), ('᩿', '᩿'), ('᪰', '᪾'), ('ᬀ', 'ᬄ'),
+  ('᬴', '᭄'), ('᭫', '᭳'), ('ᮀ', 'ᮂ'), ('ᮡ', 'ᮭ'),
+  ('᯦', '᯳'), ('ᰤ', '᰷'), ('᳐', '᳒'), ('᳔', '᳨'),
+  ('᳭', '᳭'), ('ᳲ', '᳴'), ('᳷', '᳹'), ('᷀', '᷹'),
+  ('᷻', '᷿'), ('⃐', '⃰'), ('⳯', '⳱'), ('⵿', '⵿'),
+  ('ⷠ', 'ⷿ'), ('〪', '〯'), ('゙', '゚'), ('꙯', '꙲'),
+  ('ꙴ', '꙽'), ('ꚞ', 'ꚟ'), ('꛰', '꛱'), ('ꠂ', 'ꠂ'),
+  ('꠆', '꠆'), ('ꠋ', 'ꠋ'), ('ꠣ', 'ꠧ'), ('ꢀ', 'ꢁ'),
+  ('ꢴ', 'ꣅ'), ('꣠', '꣱'), ('\u{a8ff}', '\u{a8ff}'), ('ꤦ', '꤭'),
+  ('ꥇ', '꥓'), ('ꦀ', 'ꦃ'), ('꦳', '꧀'), ('ꧥ', 'ꧥ'),
+  ('ꨩ', 'ꨶ'), ('ꩃ', 'ꩃ'), ('ꩌ', 'ꩍ'), ('ꩻ', 'ꩽ'),
+  ('ꪰ', 'ꪰ'), ('ꪲ', 'ꪴ'), ('ꪷ', 'ꪸ'), ('ꪾ', '꪿'),
+  ('꫁', '꫁'), ('ꫫ', 'ꫯ'), ('ꫵ', '꫶'), ('ꯣ', 'ꯪ'),
+  ('꯬', '꯭'), ('ﬞ', 'ﬞ'), ('︀', '️'), ('︠', '︯'),
+  ('𐇽', '𐇽'), ('𐋠', '𐋠'), ('𐍶', '𐍺'), ('𐨁', '𐨃'),
+  ('𐨅', '𐨆'), ('𐨌', '𐨏'), ('𐨸', '𐨺'), ('𐨿', '𐨿'),
+  ('𐫥', '𐫦'), ('\u{10d24}', '\u{10d27}'), ('\u{10f46}', '\u{10f50}'),
+  ('𑀀', '𑀂'), ('𑀸', '𑁆'), ('𑁿', '𑂂'), ('𑂰', '𑂺'),
+  ('𑄀', '𑄂'), ('𑄧', '𑄴'), ('\u{11145}', '\u{11146}'),
+  ('𑅳', '𑅳'), ('𑆀', '𑆂'), ('𑆳', '𑇀'), ('𑇉', '𑇌'),
+  ('𑈬', '𑈷'), ('𑈾', '𑈾'), ('𑋟', '𑋪'), ('𑌀', '𑌃'),
+  ('\u{1133b}', '𑌼'), ('𑌾', '𑍄'), ('𑍇', '𑍈'), ('𑍋', '𑍍'),
+  ('𑍗', '𑍗'), ('𑍢', '𑍣'), ('𑍦', '𑍬'), ('𑍰', '𑍴'),
+  ('𑐵', '𑑆'), ('\u{1145e}', '\u{1145e}'), ('𑒰', '𑓃'),
+  ('𑖯', '𑖵'), ('𑖸', '𑗀'), ('𑗜', '𑗝'), ('𑘰', '𑙀'),
+  ('𑚫', '𑚷'), ('𑜝', '𑜫'), ('\u{1182c}', '\u{1183a}'),
+  ('𑨁', '𑨊'), ('𑨳', '𑨹'), ('𑨻', '𑨾'), ('𑩇', '𑩇'),
+  ('𑩑', '𑩛'), ('𑪊', '𑪙'), ('𑰯', '𑰶'), ('𑰸', '𑰿'),
+  ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴱', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵅'), ('𑵇', '𑵇'),
+  ('\u{11d8a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d97}'), ('\u{11ef3}', '\u{11ef6}'), ('𖫰', '𖫴'),
+  ('𖬰', '𖬶'), ('𖽑', '𖽾'), ('𖾏', '𖾒'), ('𛲝', '𛲞'),
+  ('𝅥', '𝅩'), ('𝅭', '𝅲'), ('𝅻', '𝆂'), ('𝆅', '𝆋'),
+  ('𝆪', '𝆭'), ('𝉂', '𝉄'), ('𝨀', '𝨶'), ('𝨻', '𝩬'),
+  ('𝩵', '𝩵'), ('𝪄', '𝪄'), ('𝪛', '𝪟'), ('𝪡', '𝪯'),
+  ('𞀀', '𞀆'), ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'),
+  ('𞀦', '𞀪'), ('𞣐', '𞣖'), ('𞥄', '𞥊'), ('󠄀', '󠇯'),
+];
+
+pub const MATH_SYMBOL: &'static [(char, char)] = &[
+  ('+', '+'), ('<', '>'), ('|', '|'), ('~', '~'), ('¬', '¬'), ('±', '±'),
+  ('×', '×'), ('÷', '÷'), ('϶', '϶'), ('؆', '؈'), ('⁄', '⁄'),
+  ('⁒', '⁒'), ('⁺', '⁼'), ('₊', '₌'), ('℘', '℘'),
+  ('⅀', '⅄'), ('⅋', '⅋'), ('←', '↔'), ('↚', '↛'),
+  ('↠', '↠'), ('↣', '↣'), ('↦', '↦'), ('↮', '↮'),
+  ('⇎', '⇏'), ('⇒', '⇒'), ('⇔', '⇔'), ('⇴', '⋿'),
+  ('⌠', '⌡'), ('⍼', '⍼'), ('⎛', '⎳'), ('⏜', '⏡'),
+  ('▷', '▷'), ('◁', '◁'), ('◸', '◿'), ('♯', '♯'),
+  ('⟀', '⟄'), ('⟇', '⟥'), ('⟰', '⟿'), ('⤀', '⦂'),
+  ('⦙', '⧗'), ('⧜', '⧻'), ('⧾', '⫿'), ('⬰', '⭄'),
+  ('⭇', '⭌'), ('﬩', '﬩'), ('﹢', '﹢'), ('﹤', '﹦'),
+  ('＋', '＋'), ('＜', '＞'), ('｜', '｜'), ('～', '～'),
+  ('￢', '￢'), ('￩', '￬'), ('𝛁', '𝛁'), ('𝛛', '𝛛'),
+  ('𝛻', '𝛻'), ('𝜕', '𝜕'), ('𝜵', '𝜵'), ('𝝏', '𝝏'),
+  ('𝝯', '𝝯'), ('𝞉', '𝞉'), ('𝞩', '𝞩'), ('𝟃', '𝟃'),
+  ('𞻰', '𞻱'),
+];
+
+pub const MODIFIER_LETTER: &'static [(char, char)] = &[
+  ('ʰ', 'ˁ'), ('ˆ', 'ˑ'), ('ˠ', 'ˤ'), ('ˬ', 'ˬ'), ('ˮ', 'ˮ'),
+  ('ʹ', 'ʹ'), ('ͺ', 'ͺ'), ('ՙ', 'ՙ'), ('ـ', 'ـ'), ('ۥ', 'ۦ'),
+  ('ߴ', 'ߵ'), ('ߺ', 'ߺ'), ('ࠚ', 'ࠚ'), ('ࠤ', 'ࠤ'), ('ࠨ', 'ࠨ'),
+  ('ॱ', 'ॱ'), ('ๆ', 'ๆ'), ('ໆ', 'ໆ'), ('ჼ', 'ჼ'),
+  ('ៗ', 'ៗ'), ('ᡃ', 'ᡃ'), ('ᪧ', 'ᪧ'), ('ᱸ', 'ᱽ'),
+  ('ᴬ', 'ᵪ'), ('ᵸ', 'ᵸ'), ('ᶛ', 'ᶿ'), ('ⁱ', 'ⁱ'),
+  ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ⱼ', 'ⱽ'), ('ⵯ', 'ⵯ'),
+  ('ⸯ', 'ⸯ'), ('々', '々'), ('〱', '〵'), ('〻', '〻'),
+  ('ゝ', 'ゞ'), ('ー', 'ヾ'), ('ꀕ', 'ꀕ'), ('ꓸ', 'ꓽ'),
+  ('ꘌ', 'ꘌ'), ('ꙿ', 'ꙿ'), ('ꚜ', 'ꚝ'), ('ꜗ', 'ꜟ'),
+  ('ꝰ', 'ꝰ'), ('ꞈ', 'ꞈ'), ('ꟸ', 'ꟹ'), ('ꧏ', 'ꧏ'),
+  ('ꧦ', 'ꧦ'), ('ꩰ', 'ꩰ'), ('ꫝ', 'ꫝ'), ('ꫳ', 'ꫴ'),
+  ('ꭜ', 'ꭟ'), ('ｰ', 'ｰ'), ('ﾞ', 'ﾟ'), ('𖭀', '𖭃'),
+  ('𖾓', '𖾟'), ('𖿠', '𖿡'),
+];
+
+pub const MODIFIER_SYMBOL: &'static [(char, char)] = &[
+  ('^', '^'), ('`', '`'), ('¨', '¨'), ('¯', '¯'), ('´', '´'),
+  ('¸', '¸'), ('˂', '˅'), ('˒', '˟'), ('˥', '˫'), ('˭', '˭'),
+  ('˯', '˿'), ('͵', '͵'), ('΄', '΅'), ('᾽', '᾽'), ('᾿', '῁'),
+  ('῍', '῏'), ('῝', '῟'), ('῭', '`'), ('´', '῾'),
+  ('゛', '゜'), ('꜀', '꜖'), ('꜠', '꜡'), ('꞉', '꞊'),
+  ('꭛', '꭛'), ('﮲', '﯁'), ('＾', '＾'), ('｀', '｀'),
+  ('￣', '￣'), ('🏻', '🏿'),
+];
+
+pub const NONSPACING_MARK: &'static [(char, char)] = &[
+  ('̀', 'ͯ'), ('҃', '҇'), ('֑', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'),
+  ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('ؐ', 'ؚ'), ('ً', 'ٟ'), ('ٰ', 'ٰ'),
+  ('ۖ', 'ۜ'), ('۟', 'ۤ'), ('ۧ', 'ۨ'), ('۪', 'ۭ'), ('ܑ', 'ܑ'),
+  ('ܰ', '݊'), ('ަ', 'ް'), ('߫', '߳'), ('\u{7fd}', '\u{7fd}'),
+  ('ࠖ', '࠙'), ('ࠛ', 'ࠣ'), ('ࠥ', 'ࠧ'), ('ࠩ', '࠭'),
+  ('࡙', '࡛'), ('\u{8d3}', '࣡'), ('ࣣ', 'ं'), ('ऺ', 'ऺ'),
+  ('़', '़'), ('ु', 'ै'), ('्', '्'), ('॑', 'ॗ'),
+  ('ॢ', 'ॣ'), ('ঁ', 'ঁ'), ('়', '়'), ('ু', 'ৄ'),
+  ('্', '্'), ('ৢ', 'ৣ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਂ'),
+  ('਼', '਼'), ('ੁ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'),
+  ('ੑ', 'ੑ'), ('ੰ', 'ੱ'), ('ੵ', 'ੵ'), ('ઁ', 'ં'),
+  ('઼', '઼'), ('ુ', 'ૅ'), ('ે', 'ૈ'), ('્', '્'),
+  ('ૢ', 'ૣ'), ('ૺ', '૿'), ('ଁ', 'ଁ'), ('଼', '଼'),
+  ('ି', 'ି'), ('ୁ', 'ୄ'), ('୍', '୍'), ('ୖ', 'ୖ'),
+  ('ୢ', 'ୣ'), ('ஂ', 'ஂ'), ('ீ', 'ீ'), ('்', '்'),
+  ('ఀ', 'ఀ'), ('\u{c04}', '\u{c04}'), ('ా', 'ీ'), ('ె', 'ై'),
+  ('ొ', '్'), ('ౕ', 'ౖ'), ('ౢ', 'ౣ'), ('ಁ', 'ಁ'),
+  ('಼', '಼'), ('ಿ', 'ಿ'), ('ೆ', 'ೆ'), ('ೌ', '್'),
+  ('ೢ', 'ೣ'), ('ഀ', 'ഁ'), ('഻', '഼'), ('ു', 'ൄ'),
+  ('്', '്'), ('ൢ', 'ൣ'), ('්', '්'), ('ි', 'ු'),
+  ('ූ', 'ූ'), ('ั', 'ั'), ('ิ', 'ฺ'), ('็', '๎'),
+  ('ັ', 'ັ'), ('ິ', 'ູ'), ('ົ', 'ຼ'), ('່', 'ໍ'),
+  ('༘', '༙'), ('༵', '༵'), ('༷', '༷'), ('༹', '༹'),
+  ('ཱ', 'ཾ'), ('ྀ', '྄'), ('྆', '྇'), ('ྍ', 'ྗ'),
+  ('ྙ', 'ྼ'), ('࿆', '࿆'), ('ိ', 'ူ'), ('ဲ', '့'),
+  ('္', '်'), ('ွ', 'ှ'), ('ၘ', 'ၙ'), ('ၞ', 'ၠ'),
+  ('ၱ', 'ၴ'), ('ႂ', 'ႂ'), ('ႅ', 'ႆ'), ('ႍ', 'ႍ'),
+  ('ႝ', 'ႝ'), ('፝', '፟'), ('ᜒ', '᜔'), ('ᜲ', '᜴'),
+  ('ᝒ', 'ᝓ'), ('ᝲ', 'ᝳ'), ('឴', '឵'), ('ិ', 'ួ'),
+  ('ំ', 'ំ'), ('៉', '៓'), ('៝', '៝'), ('᠋', '᠍'),
+  ('ᢅ', 'ᢆ'), ('ᢩ', 'ᢩ'), ('ᤠ', 'ᤢ'), ('ᤧ', 'ᤨ'),
+  ('ᤲ', 'ᤲ'), ('᤹', '᤻'), ('ᨗ', 'ᨘ'), ('ᨛ', 'ᨛ'),
+  ('ᩖ', 'ᩖ'), ('ᩘ', 'ᩞ'), ('᩠', '᩠'), ('ᩢ', 'ᩢ'),
+  ('ᩥ', 'ᩬ'), ('ᩳ', '᩼'), ('᩿', '᩿'), ('᪰', '᪽'),
+  ('ᬀ', 'ᬃ'), ('᬴', '᬴'), ('ᬶ', 'ᬺ'), ('ᬼ', 'ᬼ'),
+  ('ᭂ', 'ᭂ'), ('᭫', '᭳'), ('ᮀ', 'ᮁ'), ('ᮢ', 'ᮥ'),
+  ('ᮨ', 'ᮩ'), ('᮫', 'ᮭ'), ('᯦', '᯦'), ('ᯨ', 'ᯩ'),
+  ('ᯭ', 'ᯭ'), ('ᯯ', 'ᯱ'), ('ᰬ', 'ᰳ'), ('ᰶ', '᰷'),
+  ('᳐', '᳒'), ('᳔', '᳠'), ('᳢', '᳨'), ('᳭', '᳭'),
+  ('᳴', '᳴'), ('᳸', '᳹'), ('᷀', '᷹'), ('᷻', '᷿'),
+  ('⃐', '⃜'), ('⃡', '⃡'), ('⃥', '⃰'), ('⳯', '⳱'),
+  ('⵿', '⵿'), ('ⷠ', 'ⷿ'), ('〪', '〭'), ('゙', '゚'),
+  ('꙯', '꙯'), ('ꙴ', '꙽'), ('ꚞ', 'ꚟ'), ('꛰', '꛱'),
+  ('ꠂ', 'ꠂ'), ('꠆', '꠆'), ('ꠋ', 'ꠋ'), ('ꠥ', 'ꠦ'),
+  ('꣄', 'ꣅ'), ('꣠', '꣱'), ('\u{a8ff}', '\u{a8ff}'), ('ꤦ', '꤭'),
+  ('ꥇ', 'ꥑ'), ('ꦀ', 'ꦂ'), ('꦳', '꦳'), ('ꦶ', 'ꦹ'),
+  ('ꦼ', 'ꦼ'), ('ꧥ', 'ꧥ'), ('ꨩ', 'ꨮ'), ('ꨱ', 'ꨲ'),
+  ('ꨵ', 'ꨶ'), ('ꩃ', 'ꩃ'), ('ꩌ', 'ꩌ'), ('ꩼ', 'ꩼ'),
+  ('ꪰ', 'ꪰ'), ('ꪲ', 'ꪴ'), ('ꪷ', 'ꪸ'), ('ꪾ', '꪿'),
+  ('꫁', '꫁'), ('ꫬ', 'ꫭ'), ('꫶', '꫶'), ('ꯥ', 'ꯥ'),
+  ('ꯨ', 'ꯨ'), ('꯭', '꯭'), ('ﬞ', 'ﬞ'), ('︀', '️'),
+  ('︠', '︯'), ('𐇽', '𐇽'), ('𐋠', '𐋠'), ('𐍶', '𐍺'),
+  ('𐨁', '𐨃'), ('𐨅', '𐨆'), ('𐨌', '𐨏'), ('𐨸', '𐨺'),
+  ('𐨿', '𐨿'), ('𐫥', '𐫦'), ('\u{10d24}', '\u{10d27}'),
+  ('\u{10f46}', '\u{10f50}'), ('𑀁', '𑀁'), ('𑀸', '𑁆'),
+  ('𑁿', '𑂁'), ('𑂳', '𑂶'), ('𑂹', '𑂺'), ('𑄀', '𑄂'),
+  ('𑄧', '𑄫'), ('𑄭', '𑄴'), ('𑅳', '𑅳'), ('𑆀', '𑆁'),
+  ('𑆶', '𑆾'), ('𑇉', '𑇌'), ('𑈯', '𑈱'), ('𑈴', '𑈴'),
+  ('𑈶', '𑈷'), ('𑈾', '𑈾'), ('𑋟', '𑋟'), ('𑋣', '𑋪'),
+  ('𑌀', '𑌁'), ('\u{1133b}', '𑌼'), ('𑍀', '𑍀'), ('𑍦', '𑍬'),
+  ('𑍰', '𑍴'), ('𑐸', '𑐿'), ('𑑂', '𑑄'), ('𑑆', '𑑆'),
+  ('\u{1145e}', '\u{1145e}'), ('𑒳', '𑒸'), ('𑒺', '𑒺'),
+  ('𑒿', '𑓀'), ('𑓂', '𑓃'), ('𑖲', '𑖵'), ('𑖼', '𑖽'),
+  ('𑖿', '𑗀'), ('𑗜', '𑗝'), ('𑘳', '𑘺'), ('𑘽', '𑘽'),
+  ('𑘿', '𑙀'), ('𑚫', '𑚫'), ('𑚭', '𑚭'), ('𑚰', '𑚵'),
+  ('𑚷', '𑚷'), ('𑜝', '𑜟'), ('𑜢', '𑜥'), ('𑜧', '𑜫'),
+  ('\u{1182f}', '\u{11837}'), ('\u{11839}', '\u{1183a}'), ('𑨁', '𑨊'),
+  ('𑨳', '𑨸'), ('𑨻', '𑨾'), ('𑩇', '𑩇'), ('𑩑', '𑩖'),
+  ('𑩙', '𑩛'), ('𑪊', '𑪖'), ('𑪘', '𑪙'), ('𑰰', '𑰶'),
+  ('𑰸', '𑰽'), ('𑰿', '𑰿'), ('𑲒', '𑲧'), ('𑲪', '𑲰'),
+  ('𑲲', '𑲳'), ('𑲵', '𑲶'), ('𑴱', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵅'), ('𑵇', '𑵇'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d95}', '\u{11d95}'),
+  ('\u{11d97}', '\u{11d97}'), ('\u{11ef3}', '\u{11ef4}'), ('𖫰', '𖫴'),
+  ('𖬰', '𖬶'), ('𖾏', '𖾒'), ('𛲝', '𛲞'), ('𝅧', '𝅩'),
+  ('𝅻', '𝆂'), ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('𝉂', '𝉄'),
+  ('𝨀', '𝨶'), ('𝨻', '𝩬'), ('𝩵', '𝩵'), ('𝪄', '𝪄'),
+  ('𝪛', '𝪟'), ('𝪡', '𝪯'), ('𞀀', '𞀆'), ('𞀈', '𞀘'),
+  ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'), ('𞣐', '𞣖'),
+  ('𞥄', '𞥊'), ('󠄀', '󠇯'),
+];
+
+pub const NUMBER: &'static [(char, char)] = &[
+  ('0', '9'), ('²', '³'), ('¹', '¹'), ('¼', '¾'), ('٠', '٩'),
+  ('۰', '۹'), ('߀', '߉'), ('०', '९'), ('০', '৯'), ('৴', '৹'),
+  ('੦', '੯'), ('૦', '૯'), ('୦', '୯'), ('୲', '୷'),
+  ('௦', '௲'), ('౦', '౯'), ('౸', '౾'), ('೦', '೯'),
+  ('൘', '൞'), ('൦', '൸'), ('෦', '෯'), ('๐', '๙'),
+  ('໐', '໙'), ('༠', '༳'), ('၀', '၉'), ('႐', '႙'),
+  ('፩', '፼'), ('ᛮ', 'ᛰ'), ('០', '៩'), ('៰', '៹'),
+  ('᠐', '᠙'), ('᥆', '᥏'), ('᧐', '᧚'), ('᪀', '᪉'),
+  ('᪐', '᪙'), ('᭐', '᭙'), ('᮰', '᮹'), ('᱀', '᱉'),
+  ('᱐', '᱙'), ('⁰', '⁰'), ('⁴', '⁹'), ('₀', '₉'),
+  ('⅐', 'ↂ'), ('ↅ', '↉'), ('①', '⒛'), ('⓪', '⓿'),
+  ('❶', '➓'), ('⳽', '⳽'), ('〇', '〇'), ('〡', '〩'),
+  ('〸', '〺'), ('㆒', '㆕'), ('㈠', '㈩'), ('㉈', '㉏'),
+  ('㉑', '㉟'), ('㊀', '㊉'), ('㊱', '㊿'), ('꘠', '꘩'),
+  ('ꛦ', 'ꛯ'), ('꠰', '꠵'), ('꣐', '꣙'), ('꤀', '꤉'),
+  ('꧐', '꧙'), ('꧰', '꧹'), ('꩐', '꩙'), ('꯰', '꯹'),
+  ('０', '９'), ('𐄇', '𐄳'), ('𐅀', '𐅸'), ('𐆊', '𐆋'),
+  ('𐋡', '𐋻'), ('𐌠', '𐌣'), ('𐍁', '𐍁'), ('𐍊', '𐍊'),
+  ('𐏑', '𐏕'), ('𐒠', '𐒩'), ('𐡘', '𐡟'), ('𐡹', '𐡿'),
+  ('𐢧', '𐢯'), ('𐣻', '𐣿'), ('𐤖', '𐤛'), ('𐦼', '𐦽'),
+  ('𐧀', '𐧏'), ('𐧒', '𐧿'), ('𐩀', '\u{10a48}'), ('𐩽', '𐩾'),
+  ('𐪝', '𐪟'), ('𐫫', '𐫯'), ('𐭘', '𐭟'), ('𐭸', '𐭿'),
+  ('𐮩', '𐮯'), ('𐳺', '𐳿'), ('\u{10d30}', '\u{10d39}'),
+  ('𐹠', '𐹾'), ('\u{10f1d}', '\u{10f26}'), ('\u{10f51}', '\u{10f54}'),
+  ('𑁒', '𑁯'), ('𑃰', '𑃹'), ('𑄶', '𑄿'), ('𑇐', '𑇙'),
+  ('𑇡', '𑇴'), ('𑋰', '𑋹'), ('𑑐', '𑑙'), ('𑓐', '𑓙'),
+  ('𑙐', '𑙙'), ('𑛀', '𑛉'), ('𑜰', '𑜻'), ('𑣠', '𑣲'),
+  ('𑱐', '𑱬'), ('𑵐', '𑵙'), ('\u{11da0}', '\u{11da9}'),
+  ('𒐀', '𒑮'), ('𖩠', '𖩩'), ('𖭐', '𖭙'), ('𖭛', '𖭡'),
+  ('\u{16e80}', '\u{16e96}'), ('\u{1d2e0}', '\u{1d2f3}'),
+  ('𝍠', '\u{1d378}'), ('𝟎', '𝟿'), ('𞣇', '𞣏'), ('𞥐', '𞥙'),
+  ('\u{1ec71}', '\u{1ecab}'), ('\u{1ecad}', '\u{1ecaf}'),
+  ('\u{1ecb1}', '\u{1ecb4}'), ('🄀', '🄌'),
+];
+
+pub const OPEN_PUNCTUATION: &'static [(char, char)] = &[
+  ('(', '('), ('[', '['), ('{', '{'), ('༺', '༺'), ('༼', '༼'),
+  ('᚛', '᚛'), ('‚', '‚'), ('„', '„'), ('⁅', '⁅'),
+  ('⁽', '⁽'), ('₍', '₍'), ('⌈', '⌈'), ('⌊', '⌊'),
+  ('〈', '〈'), ('❨', '❨'), ('❪', '❪'), ('❬', '❬'),
+  ('❮', '❮'), ('❰', '❰'), ('❲', '❲'), ('❴', '❴'),
+  ('⟅', '⟅'), ('⟦', '⟦'), ('⟨', '⟨'), ('⟪', '⟪'),
+  ('⟬', '⟬'), ('⟮', '⟮'), ('⦃', '⦃'), ('⦅', '⦅'),
+  ('⦇', '⦇'), ('⦉', '⦉'), ('⦋', '⦋'), ('⦍', '⦍'),
+  ('⦏', '⦏'), ('⦑', '⦑'), ('⦓', '⦓'), ('⦕', '⦕'),
+  ('⦗', '⦗'), ('⧘', '⧘'), ('⧚', '⧚'), ('⧼', '⧼'),
+  ('⸢', '⸢'), ('⸤', '⸤'), ('⸦', '⸦'), ('⸨', '⸨'),
+  ('⹂', '⹂'), ('〈', '〈'), ('《', '《'), ('「', '「'),
+  ('『', '『'), ('【', '【'), ('〔', '〔'), ('〖', '〖'),
+  ('〘', '〘'), ('〚', '〚'), ('〝', '〝'), ('﴿', '﴿'),
+  ('︗', '︗'), ('︵', '︵'), ('︷', '︷'), ('︹', '︹'),
+  ('︻', '︻'), ('︽', '︽'), ('︿', '︿'), ('﹁', '﹁'),
+  ('﹃', '﹃'), ('﹇', '﹇'), ('﹙', '﹙'), ('﹛', '﹛'),
+  ('﹝', '﹝'), ('（', '（'), ('［', '［'), ('｛', '｛'),
+  ('｟', '｟'), ('｢', '｢'),
+];
+
+pub const OTHER: &'static [(char, char)] = &[
+  ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}'), ('\u{ad}', '\u{ad}'),
+  ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
+  ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
+  ('\u{557}', '\u{558}'), ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'),
+  ('\u{5c8}', '\u{5cf}'), ('\u{5eb}', '\u{5ee}'), ('\u{5f5}', '\u{605}'),
+  ('\u{61c}', '\u{61d}'), ('\u{6dd}', '\u{6dd}'), ('\u{70e}', '\u{70f}'),
+  ('\u{74b}', '\u{74c}'), ('\u{7b2}', '\u{7bf}'), ('\u{7fb}', '\u{7fc}'),
+  ('\u{82e}', '\u{82f}'), ('\u{83f}', '\u{83f}'), ('\u{85c}', '\u{85d}'),
+  ('\u{85f}', '\u{85f}'), ('\u{86b}', '\u{89f}'), ('\u{8b5}', '\u{8b5}'),
+  ('\u{8be}', '\u{8d2}'), ('\u{8e2}', '\u{8e2}'), ('\u{984}', '\u{984}'),
+  ('\u{98d}', '\u{98e}'), ('\u{991}', '\u{992}'), ('\u{9a9}', '\u{9a9}'),
+  ('\u{9b1}', '\u{9b1}'), ('\u{9b3}', '\u{9b5}'), ('\u{9ba}', '\u{9bb}'),
+  ('\u{9c5}', '\u{9c6}'), ('\u{9c9}', '\u{9ca}'), ('\u{9cf}', '\u{9d6}'),
+  ('\u{9d8}', '\u{9db}'), ('\u{9de}', '\u{9de}'), ('\u{9e4}', '\u{9e5}'),
+  ('\u{9ff}', '\u{a00}'), ('\u{a04}', '\u{a04}'), ('\u{a0b}', '\u{a0e}'),
+  ('\u{a11}', '\u{a12}'), ('\u{a29}', '\u{a29}'), ('\u{a31}', '\u{a31}'),
+  ('\u{a34}', '\u{a34}'), ('\u{a37}', '\u{a37}'), ('\u{a3a}', '\u{a3b}'),
+  ('\u{a3d}', '\u{a3d}'), ('\u{a43}', '\u{a46}'), ('\u{a49}', '\u{a4a}'),
+  ('\u{a4e}', '\u{a50}'), ('\u{a52}', '\u{a58}'), ('\u{a5d}', '\u{a5d}'),
+  ('\u{a5f}', '\u{a65}'), ('\u{a77}', '\u{a80}'), ('\u{a84}', '\u{a84}'),
+  ('\u{a8e}', '\u{a8e}'), ('\u{a92}', '\u{a92}'), ('\u{aa9}', '\u{aa9}'),
+  ('\u{ab1}', '\u{ab1}'), ('\u{ab4}', '\u{ab4}'), ('\u{aba}', '\u{abb}'),
+  ('\u{ac6}', '\u{ac6}'), ('\u{aca}', '\u{aca}'), ('\u{ace}', '\u{acf}'),
+  ('\u{ad1}', '\u{adf}'), ('\u{ae4}', '\u{ae5}'), ('\u{af2}', '\u{af8}'),
+  ('\u{b00}', '\u{b00}'), ('\u{b04}', '\u{b04}'), ('\u{b0d}', '\u{b0e}'),
+  ('\u{b11}', '\u{b12}'), ('\u{b29}', '\u{b29}'), ('\u{b31}', '\u{b31}'),
+  ('\u{b34}', '\u{b34}'), ('\u{b3a}', '\u{b3b}'), ('\u{b45}', '\u{b46}'),
+  ('\u{b49}', '\u{b4a}'), ('\u{b4e}', '\u{b55}'), ('\u{b58}', '\u{b5b}'),
+  ('\u{b5e}', '\u{b5e}'), ('\u{b64}', '\u{b65}'), ('\u{b78}', '\u{b81}'),
+  ('\u{b84}', '\u{b84}'), ('\u{b8b}', '\u{b8d}'), ('\u{b91}', '\u{b91}'),
+  ('\u{b96}', '\u{b98}'), ('\u{b9b}', '\u{b9b}'), ('\u{b9d}', '\u{b9d}'),
+  ('\u{ba0}', '\u{ba2}'), ('\u{ba5}', '\u{ba7}'), ('\u{bab}', '\u{bad}'),
+  ('\u{bba}', '\u{bbd}'), ('\u{bc3}', '\u{bc5}'), ('\u{bc9}', '\u{bc9}'),
+  ('\u{bce}', '\u{bcf}'), ('\u{bd1}', '\u{bd6}'), ('\u{bd8}', '\u{be5}'),
+  ('\u{bfb}', '\u{bff}'), ('\u{c0d}', '\u{c0d}'), ('\u{c11}', '\u{c11}'),
+  ('\u{c29}', '\u{c29}'), ('\u{c3a}', '\u{c3c}'), ('\u{c45}', '\u{c45}'),
+  ('\u{c49}', '\u{c49}'), ('\u{c4e}', '\u{c54}'), ('\u{c57}', '\u{c57}'),
+  ('\u{c5b}', '\u{c5f}'), ('\u{c64}', '\u{c65}'), ('\u{c70}', '\u{c77}'),
+  ('\u{c8d}', '\u{c8d}'), ('\u{c91}', '\u{c91}'), ('\u{ca9}', '\u{ca9}'),
+  ('\u{cb4}', '\u{cb4}'), ('\u{cba}', '\u{cbb}'), ('\u{cc5}', '\u{cc5}'),
+  ('\u{cc9}', '\u{cc9}'), ('\u{cce}', '\u{cd4}'), ('\u{cd7}', '\u{cdd}'),
+  ('\u{cdf}', '\u{cdf}'), ('\u{ce4}', '\u{ce5}'), ('\u{cf0}', '\u{cf0}'),
+  ('\u{cf3}', '\u{cff}'), ('\u{d04}', '\u{d04}'), ('\u{d0d}', '\u{d0d}'),
+  ('\u{d11}', '\u{d11}'), ('\u{d45}', '\u{d45}'), ('\u{d49}', '\u{d49}'),
+  ('\u{d50}', '\u{d53}'), ('\u{d64}', '\u{d65}'), ('\u{d80}', '\u{d81}'),
+  ('\u{d84}', '\u{d84}'), ('\u{d97}', '\u{d99}'), ('\u{db2}', '\u{db2}'),
+  ('\u{dbc}', '\u{dbc}'), ('\u{dbe}', '\u{dbf}'), ('\u{dc7}', '\u{dc9}'),
+  ('\u{dcb}', '\u{dce}'), ('\u{dd5}', '\u{dd5}'), ('\u{dd7}', '\u{dd7}'),
+  ('\u{de0}', '\u{de5}'), ('\u{df0}', '\u{df1}'), ('\u{df5}', '\u{e00}'),
+  ('\u{e3b}', '\u{e3e}'), ('\u{e5c}', '\u{e80}'), ('\u{e83}', '\u{e83}'),
+  ('\u{e85}', '\u{e86}'), ('\u{e89}', '\u{e89}'), ('\u{e8b}', '\u{e8c}'),
+  ('\u{e8e}', '\u{e93}'), ('\u{e98}', '\u{e98}'), ('\u{ea0}', '\u{ea0}'),
+  ('\u{ea4}', '\u{ea4}'), ('\u{ea6}', '\u{ea6}'), ('\u{ea8}', '\u{ea9}'),
+  ('\u{eac}', '\u{eac}'), ('\u{eba}', '\u{eba}'), ('\u{ebe}', '\u{ebf}'),
+  ('\u{ec5}', '\u{ec5}'), ('\u{ec7}', '\u{ec7}'), ('\u{ece}', '\u{ecf}'),
+  ('\u{eda}', '\u{edb}'), ('\u{ee0}', '\u{eff}'), ('\u{f48}', '\u{f48}'),
+  ('\u{f6d}', '\u{f70}'), ('\u{f98}', '\u{f98}'), ('\u{fbd}', '\u{fbd}'),
+  ('\u{fcd}', '\u{fcd}'), ('\u{fdb}', '\u{fff}'), ('\u{10c6}', '\u{10c6}'),
+  ('\u{10c8}', '\u{10cc}'), ('\u{10ce}', '\u{10cf}'),
+  ('\u{1249}', '\u{1249}'), ('\u{124e}', '\u{124f}'),
+  ('\u{1257}', '\u{1257}'), ('\u{1259}', '\u{1259}'),
+  ('\u{125e}', '\u{125f}'), ('\u{1289}', '\u{1289}'),
+  ('\u{128e}', '\u{128f}'), ('\u{12b1}', '\u{12b1}'),
+  ('\u{12b6}', '\u{12b7}'), ('\u{12bf}', '\u{12bf}'),
+  ('\u{12c1}', '\u{12c1}'), ('\u{12c6}', '\u{12c7}'),
+  ('\u{12d7}', '\u{12d7}'), ('\u{1311}', '\u{1311}'),
+  ('\u{1316}', '\u{1317}'), ('\u{135b}', '\u{135c}'),
+  ('\u{137d}', '\u{137f}'), ('\u{139a}', '\u{139f}'),
+  ('\u{13f6}', '\u{13f7}'), ('\u{13fe}', '\u{13ff}'),
+  ('\u{169d}', '\u{169f}'), ('\u{16f9}', '\u{16ff}'),
+  ('\u{170d}', '\u{170d}'), ('\u{1715}', '\u{171f}'),
+  ('\u{1737}', '\u{173f}'), ('\u{1754}', '\u{175f}'),
+  ('\u{176d}', '\u{176d}'), ('\u{1771}', '\u{1771}'),
+  ('\u{1774}', '\u{177f}'), ('\u{17de}', '\u{17df}'),
+  ('\u{17ea}', '\u{17ef}'), ('\u{17fa}', '\u{17ff}'),
+  ('\u{180e}', '\u{180f}'), ('\u{181a}', '\u{181f}'),
+  ('\u{1879}', '\u{187f}'), ('\u{18ab}', '\u{18af}'),
+  ('\u{18f6}', '\u{18ff}'), ('\u{191f}', '\u{191f}'),
+  ('\u{192c}', '\u{192f}'), ('\u{193c}', '\u{193f}'),
+  ('\u{1941}', '\u{1943}'), ('\u{196e}', '\u{196f}'),
+  ('\u{1975}', '\u{197f}'), ('\u{19ac}', '\u{19af}'),
+  ('\u{19ca}', '\u{19cf}'), ('\u{19db}', '\u{19dd}'),
+  ('\u{1a1c}', '\u{1a1d}'), ('\u{1a5f}', '\u{1a5f}'),
+  ('\u{1a7d}', '\u{1a7e}'), ('\u{1a8a}', '\u{1a8f}'),
+  ('\u{1a9a}', '\u{1a9f}'), ('\u{1aae}', '\u{1aaf}'),
+  ('\u{1abf}', '\u{1aff}'), ('\u{1b4c}', '\u{1b4f}'),
+  ('\u{1b7d}', '\u{1b7f}'), ('\u{1bf4}', '\u{1bfb}'),
+  ('\u{1c38}', '\u{1c3a}'), ('\u{1c4a}', '\u{1c4c}'),
+  ('\u{1c89}', '\u{1c8f}'), ('\u{1cbb}', '\u{1cbc}'),
+  ('\u{1cc8}', '\u{1ccf}'), ('\u{1cfa}', '\u{1cff}'),
+  ('\u{1dfa}', '\u{1dfa}'), ('\u{1f16}', '\u{1f17}'),
+  ('\u{1f1e}', '\u{1f1f}'), ('\u{1f46}', '\u{1f47}'),
+  ('\u{1f4e}', '\u{1f4f}'), ('\u{1f58}', '\u{1f58}'),
+  ('\u{1f5a}', '\u{1f5a}'), ('\u{1f5c}', '\u{1f5c}'),
+  ('\u{1f5e}', '\u{1f5e}'), ('\u{1f7e}', '\u{1f7f}'),
+  ('\u{1fb5}', '\u{1fb5}'), ('\u{1fc5}', '\u{1fc5}'),
+  ('\u{1fd4}', '\u{1fd5}'), ('\u{1fdc}', '\u{1fdc}'),
+  ('\u{1ff0}', '\u{1ff1}'), ('\u{1ff5}', '\u{1ff5}'),
+  ('\u{1fff}', '\u{1fff}'), ('\u{200b}', '\u{200f}'),
+  ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{206f}'),
+  ('\u{2072}', '\u{2073}'), ('\u{208f}', '\u{208f}'),
+  ('\u{209d}', '\u{209f}'), ('\u{20c0}', '\u{20cf}'),
+  ('\u{20f1}', '\u{20ff}'), ('\u{218c}', '\u{218f}'),
+  ('\u{2427}', '\u{243f}'), ('\u{244b}', '\u{245f}'),
+  ('\u{2b74}', '\u{2b75}'), ('\u{2b96}', '\u{2b97}'),
+  ('\u{2bc9}', '\u{2bc9}'), ('\u{2bff}', '\u{2bff}'),
+  ('\u{2c2f}', '\u{2c2f}'), ('\u{2c5f}', '\u{2c5f}'),
+  ('\u{2cf4}', '\u{2cf8}'), ('\u{2d26}', '\u{2d26}'),
+  ('\u{2d28}', '\u{2d2c}'), ('\u{2d2e}', '\u{2d2f}'),
+  ('\u{2d68}', '\u{2d6e}'), ('\u{2d71}', '\u{2d7e}'),
+  ('\u{2d97}', '\u{2d9f}'), ('\u{2da7}', '\u{2da7}'),
+  ('\u{2daf}', '\u{2daf}'), ('\u{2db7}', '\u{2db7}'),
+  ('\u{2dbf}', '\u{2dbf}'), ('\u{2dc7}', '\u{2dc7}'),
+  ('\u{2dcf}', '\u{2dcf}'), ('\u{2dd7}', '\u{2dd7}'),
+  ('\u{2ddf}', '\u{2ddf}'), ('\u{2e4f}', '\u{2e7f}'),
+  ('\u{2e9a}', '\u{2e9a}'), ('\u{2ef4}', '\u{2eff}'),
+  ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}', '\u{2fff}'),
+  ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'),
+  ('\u{3100}', '\u{3104}'), ('\u{3130}', '\u{3130}'),
+  ('\u{318f}', '\u{318f}'), ('\u{31bb}', '\u{31bf}'),
+  ('\u{31e4}', '\u{31ef}'), ('\u{321f}', '\u{321f}'),
+  ('\u{32ff}', '\u{32ff}'), ('\u{4db6}', '\u{4dbf}'),
+  ('\u{9ff0}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'),
+  ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'),
+  ('\u{a6f8}', '\u{a6ff}'), ('\u{a7ba}', '\u{a7f6}'),
+  ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', '\u{a83f}'),
+  ('\u{a878}', '\u{a87f}'), ('\u{a8c6}', '\u{a8cd}'),
+  ('\u{a8da}', '\u{a8df}'), ('\u{a954}', '\u{a95e}'),
+  ('\u{a97d}', '\u{a97f}'), ('\u{a9ce}', '\u{a9ce}'),
+  ('\u{a9da}', '\u{a9dd}'), ('\u{a9ff}', '\u{a9ff}'),
+  ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'),
+  ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'),
+  ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'),
+  ('\u{ab0f}', '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'),
+  ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}', '\u{ab2f}'),
+  ('\u{ab66}', '\u{ab6f}'), ('\u{abee}', '\u{abef}'),
+  ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'),
+  ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', '\u{f8ff}'),
+  ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', '\u{faff}'),
+  ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'),
+  ('\u{fb37}', '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'),
+  ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'),
+  ('\u{fb45}', '\u{fb45}'), ('\u{fbc2}', '\u{fbd2}'),
+  ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'),
+  ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'),
+  ('\u{fe1a}', '\u{fe1f}'), ('\u{fe53}', '\u{fe53}'),
+  ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'),
+  ('\u{fe75}', '\u{fe75}'), ('\u{fefd}', '\u{ff00}'),
+  ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'),
+  ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'),
+  ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'),
+  ('\u{ffef}', '\u{fffb}'), ('\u{fffe}', '\u{ffff}'),
+  ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'),
+  ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'),
+  ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', '\u{1007f}'),
+  ('\u{100fb}', '\u{100ff}'), ('\u{10103}', '\u{10106}'),
+  ('\u{10134}', '\u{10136}'), ('\u{1018f}', '\u{1018f}'),
+  ('\u{1019c}', '\u{1019f}'), ('\u{101a1}', '\u{101cf}'),
+  ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'),
+  ('\u{102d1}', '\u{102df}'), ('\u{102fc}', '\u{102ff}'),
+  ('\u{10324}', '\u{1032c}'), ('\u{1034b}', '\u{1034f}'),
+  ('\u{1037b}', '\u{1037f}'), ('\u{1039e}', '\u{1039e}'),
+  ('\u{103c4}', '\u{103c7}'), ('\u{103d6}', '\u{103ff}'),
+  ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104af}'),
+  ('\u{104d4}', '\u{104d7}'), ('\u{104fc}', '\u{104ff}'),
+  ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'),
+  ('\u{10570}', '\u{105ff}'), ('\u{10737}', '\u{1073f}'),
+  ('\u{10756}', '\u{1075f}'), ('\u{10768}', '\u{107ff}'),
+  ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'),
+  ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'),
+  ('\u{1083d}', '\u{1083e}'), ('\u{10856}', '\u{10856}'),
+  ('\u{1089f}', '\u{108a6}'), ('\u{108b0}', '\u{108df}'),
+  ('\u{108f3}', '\u{108f3}'), ('\u{108f6}', '\u{108fa}'),
+  ('\u{1091c}', '\u{1091e}'), ('\u{1093a}', '\u{1093e}'),
+  ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'),
+  ('\u{109d0}', '\u{109d1}'), ('\u{10a04}', '\u{10a04}'),
+  ('\u{10a07}', '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'),
+  ('\u{10a18}', '\u{10a18}'), ('\u{10a36}', '\u{10a37}'),
+  ('\u{10a3b}', '\u{10a3e}'), ('\u{10a49}', '\u{10a4f}'),
+  ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'),
+  ('\u{10ae7}', '\u{10aea}'), ('\u{10af7}', '\u{10aff}'),
+  ('\u{10b36}', '\u{10b38}'), ('\u{10b56}', '\u{10b57}'),
+  ('\u{10b73}', '\u{10b77}'), ('\u{10b92}', '\u{10b98}'),
+  ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}', '\u{10bff}'),
+  ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'),
+  ('\u{10cf3}', '\u{10cf9}'), ('\u{10d28}', '\u{10d2f}'),
+  ('\u{10d3a}', '\u{10e5f}'), ('\u{10e7f}', '\u{10eff}'),
+  ('\u{10f28}', '\u{10f2f}'), ('\u{10f5a}', '\u{10fff}'),
+  ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'),
+  ('\u{110bd}', '\u{110bd}'), ('\u{110c2}', '\u{110cf}'),
+  ('\u{110e9}', '\u{110ef}'), ('\u{110fa}', '\u{110ff}'),
+  ('\u{11135}', '\u{11135}'), ('\u{11147}', '\u{1114f}'),
+  ('\u{11177}', '\u{1117f}'), ('\u{111ce}', '\u{111cf}'),
+  ('\u{111e0}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'),
+  ('\u{11212}', '\u{11212}'), ('\u{1123f}', '\u{1127f}'),
+  ('\u{11287}', '\u{11287}'), ('\u{11289}', '\u{11289}'),
+  ('\u{1128e}', '\u{1128e}'), ('\u{1129e}', '\u{1129e}'),
+  ('\u{112aa}', '\u{112af}'), ('\u{112eb}', '\u{112ef}'),
+  ('\u{112fa}', '\u{112ff}'), ('\u{11304}', '\u{11304}'),
+  ('\u{1130d}', '\u{1130e}'), ('\u{11311}', '\u{11312}'),
+  ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'),
+  ('\u{11334}', '\u{11334}'), ('\u{1133a}', '\u{1133a}'),
+  ('\u{11345}', '\u{11346}'), ('\u{11349}', '\u{1134a}'),
+  ('\u{1134e}', '\u{1134f}'), ('\u{11351}', '\u{11356}'),
+  ('\u{11358}', '\u{1135c}'), ('\u{11364}', '\u{11365}'),
+  ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{113ff}'),
+  ('\u{1145a}', '\u{1145a}'), ('\u{1145c}', '\u{1145c}'),
+  ('\u{1145f}', '\u{1147f}'), ('\u{114c8}', '\u{114cf}'),
+  ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'),
+  ('\u{115de}', '\u{115ff}'), ('\u{11645}', '\u{1164f}'),
+  ('\u{1165a}', '\u{1165f}'), ('\u{1166d}', '\u{1167f}'),
+  ('\u{116b8}', '\u{116bf}'), ('\u{116ca}', '\u{116ff}'),
+  ('\u{1171b}', '\u{1171c}'), ('\u{1172c}', '\u{1172f}'),
+  ('\u{11740}', '\u{117ff}'), ('\u{1183c}', '\u{1189f}'),
+  ('\u{118f3}', '\u{118fe}'), ('\u{11900}', '\u{119ff}'),
+  ('\u{11a48}', '\u{11a4f}'), ('\u{11a84}', '\u{11a85}'),
+  ('\u{11aa3}', '\u{11abf}'), ('\u{11af9}', '\u{11bff}'),
+  ('\u{11c09}', '\u{11c09}'), ('\u{11c37}', '\u{11c37}'),
+  ('\u{11c46}', '\u{11c4f}'), ('\u{11c6d}', '\u{11c6f}'),
+  ('\u{11c90}', '\u{11c91}'), ('\u{11ca8}', '\u{11ca8}'),
+  ('\u{11cb7}', '\u{11cff}'), ('\u{11d07}', '\u{11d07}'),
+  ('\u{11d0a}', '\u{11d0a}'), ('\u{11d37}', '\u{11d39}'),
+  ('\u{11d3b}', '\u{11d3b}'), ('\u{11d3e}', '\u{11d3e}'),
+  ('\u{11d48}', '\u{11d4f}'), ('\u{11d5a}', '\u{11d5f}'),
+  ('\u{11d66}', '\u{11d66}'), ('\u{11d69}', '\u{11d69}'),
+  ('\u{11d8f}', '\u{11d8f}'), ('\u{11d92}', '\u{11d92}'),
+  ('\u{11d99}', '\u{11d9f}'), ('\u{11daa}', '\u{11edf}'),
+  ('\u{11ef9}', '\u{11fff}'), ('\u{1239a}', '\u{123ff}'),
+  ('\u{1246f}', '\u{1246f}'), ('\u{12475}', '\u{1247f}'),
+  ('\u{12544}', '\u{12fff}'), ('\u{1342f}', '\u{143ff}'),
+  ('\u{14647}', '\u{167ff}'), ('\u{16a39}', '\u{16a3f}'),
+  ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'),
+  ('\u{16a70}', '\u{16acf}'), ('\u{16aee}', '\u{16aef}'),
+  ('\u{16af6}', '\u{16aff}'), ('\u{16b46}', '\u{16b4f}'),
+  ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'),
+  ('\u{16b78}', '\u{16b7c}'), ('\u{16b90}', '\u{16e3f}'),
+  ('\u{16e9b}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'),
+  ('\u{16f7f}', '\u{16f8e}'), ('\u{16fa0}', '\u{16fdf}'),
+  ('\u{16fe2}', '\u{16fff}'), ('\u{187f2}', '\u{187ff}'),
+  ('\u{18af3}', '\u{1afff}'), ('\u{1b11f}', '\u{1b16f}'),
+  ('\u{1b2fc}', '\u{1bbff}'), ('\u{1bc6b}', '\u{1bc6f}'),
+  ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'),
+  ('\u{1bc9a}', '\u{1bc9b}'), ('\u{1bca0}', '\u{1cfff}'),
+  ('\u{1d0f6}', '\u{1d0ff}'), ('\u{1d127}', '\u{1d128}'),
+  ('\u{1d173}', '\u{1d17a}'), ('\u{1d1e9}', '\u{1d1ff}'),
+  ('\u{1d246}', '\u{1d2df}'), ('\u{1d2f4}', '\u{1d2ff}'),
+  ('\u{1d357}', '\u{1d35f}'), ('\u{1d379}', '\u{1d3ff}'),
+  ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}', '\u{1d49d}'),
+  ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'),
+  ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'),
+  ('\u{1d4ba}', '\u{1d4ba}'), ('\u{1d4bc}', '\u{1d4bc}'),
+  ('\u{1d4c4}', '\u{1d4c4}'), ('\u{1d506}', '\u{1d506}'),
+  ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}', '\u{1d515}'),
+  ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', '\u{1d53a}'),
+  ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'),
+  ('\u{1d547}', '\u{1d549}'), ('\u{1d551}', '\u{1d551}'),
+  ('\u{1d6a6}', '\u{1d6a7}'), ('\u{1d7cc}', '\u{1d7cd}'),
+  ('\u{1da8c}', '\u{1da9a}'), ('\u{1daa0}', '\u{1daa0}'),
+  ('\u{1dab0}', '\u{1dfff}'), ('\u{1e007}', '\u{1e007}'),
+  ('\u{1e019}', '\u{1e01a}'), ('\u{1e022}', '\u{1e022}'),
+  ('\u{1e025}', '\u{1e025}'), ('\u{1e02b}', '\u{1e7ff}'),
+  ('\u{1e8c5}', '\u{1e8c6}'), ('\u{1e8d7}', '\u{1e8ff}'),
+  ('\u{1e94b}', '\u{1e94f}'), ('\u{1e95a}', '\u{1e95d}'),
+  ('\u{1e960}', '\u{1ec70}'), ('\u{1ecb5}', '\u{1edff}'),
+  ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}', '\u{1ee20}'),
+  ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'),
+  ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', '\u{1ee33}'),
+  ('\u{1ee38}', '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'),
+  ('\u{1ee3c}', '\u{1ee41}'), ('\u{1ee43}', '\u{1ee46}'),
+  ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}', '\u{1ee4a}'),
+  ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'),
+  ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'),
+  ('\u{1ee58}', '\u{1ee58}'), ('\u{1ee5a}', '\u{1ee5a}'),
+  ('\u{1ee5c}', '\u{1ee5c}'), ('\u{1ee5e}', '\u{1ee5e}'),
+  ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}', '\u{1ee63}'),
+  ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', '\u{1ee6b}'),
+  ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'),
+  ('\u{1ee7d}', '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'),
+  ('\u{1ee8a}', '\u{1ee8a}'), ('\u{1ee9c}', '\u{1eea0}'),
+  ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}', '\u{1eeaa}'),
+  ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'),
+  ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', '\u{1f09f}'),
+  ('\u{1f0af}', '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'),
+  ('\u{1f0d0}', '\u{1f0d0}'), ('\u{1f0f6}', '\u{1f0ff}'),
+  ('\u{1f10d}', '\u{1f10f}'), ('\u{1f16c}', '\u{1f16f}'),
+  ('\u{1f1ad}', '\u{1f1e5}'), ('\u{1f203}', '\u{1f20f}'),
+  ('\u{1f23c}', '\u{1f23f}'), ('\u{1f249}', '\u{1f24f}'),
+  ('\u{1f252}', '\u{1f25f}'), ('\u{1f266}', '\u{1f2ff}'),
+  ('\u{1f6d5}', '\u{1f6df}'), ('\u{1f6ed}', '\u{1f6ef}'),
+  ('\u{1f6fa}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'),
+  ('\u{1f7d9}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'),
+  ('\u{1f848}', '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'),
+  ('\u{1f888}', '\u{1f88f}'), ('\u{1f8ae}', '\u{1f8ff}'),
+  ('\u{1f90c}', '\u{1f90f}'), ('\u{1f93f}', '\u{1f93f}'),
+  ('\u{1f971}', '\u{1f972}'), ('\u{1f977}', '\u{1f979}'),
+  ('\u{1f97b}', '\u{1f97b}'), ('\u{1f9a3}', '\u{1f9af}'),
+  ('\u{1f9ba}', '\u{1f9bf}'), ('\u{1f9c3}', '\u{1f9cf}'),
+  ('\u{1fa00}', '\u{1fa5f}'), ('\u{1fa6e}', '\u{1ffff}'),
+  ('\u{2a6d7}', '\u{2a6ff}'), ('\u{2b735}', '\u{2b73f}'),
+  ('\u{2b81e}', '\u{2b81f}'), ('\u{2cea2}', '\u{2ceaf}'),
+  ('\u{2ebe1}', '\u{2f7ff}'), ('\u{2fa1e}', '\u{e00ff}'),
+  ('\u{e01f0}', '\u{10ffff}'),
+];
+
+pub const OTHER_LETTER: &'static [(char, char)] = &[
+  ('ª', 'ª'), ('º', 'º'), ('ƻ', 'ƻ'), ('ǀ', 'ǃ'), ('ʔ', 'ʔ'),
+  ('א', 'ת'), ('\u{5ef}', 'ײ'), ('ؠ', 'ؿ'), ('ف', 'ي'), ('ٮ', 'ٯ'),
+  ('ٱ', 'ۓ'), ('ە', 'ە'), ('ۮ', 'ۯ'), ('ۺ', 'ۼ'), ('ۿ', 'ۿ'),
+  ('ܐ', 'ܐ'), ('ܒ', 'ܯ'), ('ݍ', 'ޥ'), ('ޱ', 'ޱ'), ('ߊ', 'ߪ'),
+  ('ࠀ', 'ࠕ'), ('ࡀ', 'ࡘ'), ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'),
+  ('ࢶ', 'ࢽ'), ('ऄ', 'ह'), ('ऽ', 'ऽ'), ('ॐ', 'ॐ'),
+  ('क़', 'ॡ'), ('ॲ', 'ঀ'), ('অ', 'ঌ'), ('এ', 'ঐ'),
+  ('ও', 'ন'), ('প', 'র'), ('ল', 'ল'), ('শ', 'হ'),
+  ('ঽ', 'ঽ'), ('ৎ', 'ৎ'), ('ড়', 'ঢ়'), ('য়', 'ৡ'),
+  ('ৰ', 'ৱ'), ('ৼ', 'ৼ'), ('ਅ', 'ਊ'), ('ਏ', 'ਐ'),
+  ('ਓ', 'ਨ'), ('ਪ', 'ਰ'), ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'),
+  ('ਸ', 'ਹ'), ('ਖ਼', 'ੜ'), ('ਫ਼', 'ਫ਼'), ('ੲ', 'ੴ'),
+  ('અ', 'ઍ'), ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'),
+  ('લ', 'ળ'), ('વ', 'હ'), ('ઽ', 'ઽ'), ('ૐ', 'ૐ'),
+  ('ૠ', 'ૡ'), ('ૹ', 'ૹ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'),
+  ('ଓ', 'ନ'), ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଵ', 'ହ'),
+  ('ଽ', 'ଽ'), ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୡ'), ('ୱ', 'ୱ'),
+  ('ஃ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'), ('ஒ', 'க'),
+  ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'), ('ண', 'த'),
+  ('ந', 'ப'), ('ம', 'ஹ'), ('ௐ', 'ௐ'), ('అ', 'ఌ'),
+  ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'హ'), ('ఽ', 'ఽ'),
+  ('ౘ', 'ౚ'), ('ౠ', 'ౡ'), ('ಀ', 'ಀ'), ('ಅ', 'ಌ'),
+  ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'), ('ವ', 'ಹ'),
+  ('ಽ', 'ಽ'), ('ೞ', 'ೞ'), ('ೠ', 'ೡ'), ('ೱ', 'ೲ'),
+  ('അ', 'ഌ'), ('എ', 'ഐ'), ('ഒ', 'ഺ'), ('ഽ', 'ഽ'),
+  ('ൎ', 'ൎ'), ('ൔ', 'ൖ'), ('ൟ', 'ൡ'), ('ൺ', 'ൿ'),
+  ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'),
+  ('ව', 'ෆ'), ('ก', 'ะ'), ('า', 'ำ'), ('เ', 'ๅ'),
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ະ'),
+  ('າ', 'ຳ'), ('ຽ', 'ຽ'), ('ເ', 'ໄ'), ('ໜ', 'ໟ'),
+  ('ༀ', 'ༀ'), ('ཀ', 'ཇ'), ('ཉ', 'ཬ'), ('ྈ', 'ྌ'),
+  ('က', 'ဪ'), ('ဿ', 'ဿ'), ('ၐ', 'ၕ'), ('ၚ', 'ၝ'),
+  ('ၡ', 'ၡ'), ('ၥ', 'ၦ'), ('ၮ', 'ၰ'), ('ၵ', 'ႁ'),
+  ('ႎ', 'ႎ'), ('ᄀ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'),
+  ('ቘ', 'ቘ'), ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'),
+  ('ነ', 'ኰ'), ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'),
+  ('ዂ', 'ዅ'), ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'),
+  ('ጘ', 'ፚ'), ('ᎀ', 'ᎏ'), ('ᐁ', 'ᙬ'), ('ᙯ', 'ᙿ'),
+  ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛱ', 'ᛸ'), ('ᜀ', 'ᜌ'),
+  ('ᜎ', 'ᜑ'), ('ᜠ', 'ᜱ'), ('ᝀ', 'ᝑ'), ('ᝠ', 'ᝬ'),
+  ('ᝮ', 'ᝰ'), ('ក', 'ឳ'), ('ៜ', 'ៜ'), ('ᠠ', 'ᡂ'),
+  ('ᡄ', '\u{1878}'), ('ᢀ', 'ᢄ'), ('ᢇ', 'ᢨ'), ('ᢪ', 'ᢪ'),
+  ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'),
+  ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('ᨀ', 'ᨖ'), ('ᨠ', 'ᩔ'),
+  ('ᬅ', 'ᬳ'), ('ᭅ', 'ᭋ'), ('ᮃ', 'ᮠ'), ('ᮮ', 'ᮯ'),
+  ('ᮺ', 'ᯥ'), ('ᰀ', 'ᰣ'), ('ᱍ', 'ᱏ'), ('ᱚ', 'ᱷ'),
+  ('ᳩ', 'ᳬ'), ('ᳮ', 'ᳱ'), ('ᳵ', 'ᳶ'), ('ℵ', 'ℸ'),
+  ('ⴰ', 'ⵧ'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'),
+  ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'),
+  ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('〆', '〆'), ('〼', '〼'),
+  ('ぁ', 'ゖ'), ('ゟ', 'ゟ'), ('ァ', 'ヺ'), ('ヿ', 'ヿ'),
+  ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'),
+  ('㐀', '䶵'), ('一', '\u{9fef}'), ('ꀀ', 'ꀔ'), ('ꀖ', 'ꒌ'),
+  ('ꓐ', 'ꓷ'), ('ꔀ', 'ꘋ'), ('ꘐ', 'ꘟ'), ('ꘪ', 'ꘫ'),
+  ('ꙮ', 'ꙮ'), ('ꚠ', 'ꛥ'), ('ꞏ', 'ꞏ'), ('ꟷ', 'ꟷ'),
+  ('ꟻ', 'ꠁ'), ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'), ('ꠌ', 'ꠢ'),
+  ('ꡀ', 'ꡳ'), ('ꢂ', 'ꢳ'), ('ꣲ', 'ꣷ'), ('ꣻ', 'ꣻ'),
+  ('ꣽ', '\u{a8fe}'), ('ꤊ', 'ꤥ'), ('ꤰ', 'ꥆ'), ('ꥠ', 'ꥼ'),
+  ('ꦄ', 'ꦲ'), ('ꧠ', 'ꧤ'), ('ꧧ', 'ꧯ'), ('ꧺ', 'ꧾ'),
+  ('ꨀ', 'ꨨ'), ('ꩀ', 'ꩂ'), ('ꩄ', 'ꩋ'), ('ꩠ', 'ꩯ'),
+  ('ꩱ', 'ꩶ'), ('ꩺ', 'ꩺ'), ('ꩾ', 'ꪯ'), ('ꪱ', 'ꪱ'),
+  ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪽ'), ('ꫀ', 'ꫀ'), ('ꫂ', 'ꫂ'),
+  ('ꫛ', 'ꫜ'), ('ꫠ', 'ꫪ'), ('ꫲ', 'ꫲ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+  ('ꯀ', 'ꯢ'), ('가', '힣'), ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'),
+  ('豈', '舘'), ('並', '龎'), ('יִ', 'יִ'), ('ײַ', 'ﬨ'),
+  ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'),
+  ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'), ('ﵐ', 'ﶏ'),
+  ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('ｦ', 'ｯ'), ('ｱ', 'ﾝ'), ('ﾠ', 'ﾾ'), ('ￂ', 'ￇ'),
+  ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('𐀀', '𐀋'),
+  ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'),
+  ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐊀', '𐊜'), ('𐊠', '𐋐'),
+  ('𐌀', '𐌟'), ('𐌭', '𐍀'), ('𐍂', '𐍉'), ('𐍐', '𐍵'),
+  ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐑐', '𐒝'),
+  ('𐔀', '𐔧'), ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'),
+  ('𐝠', '𐝧'), ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'),
+  ('𐠷', '𐠸'), ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'),
+  ('𐢀', '𐢞'), ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'),
+  ('𐤠', '𐤹'), ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨀'),
+  ('𐨐', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'), ('𐩠', '𐩼'),
+  ('𐪀', '𐪜'), ('𐫀', '𐫇'), ('𐫉', '𐫤'), ('𐬀', '𐬵'),
+  ('𐭀', '𐭕'), ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'),
+  ('\u{10d00}', '\u{10d23}'), ('\u{10f00}', '\u{10f1c}'),
+  ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'), ('𑀃', '𑀷'),
+  ('𑂃', '𑂯'), ('𑃐', '𑃨'), ('𑄃', '𑄦'),
+  ('\u{11144}', '\u{11144}'), ('𑅐', '𑅲'), ('𑅶', '𑅶'),
+  ('𑆃', '𑆲'), ('𑇁', '𑇄'), ('𑇚', '𑇚'), ('𑇜', '𑇜'),
+  ('𑈀', '𑈑'), ('𑈓', '𑈫'), ('𑊀', '𑊆'), ('𑊈', '𑊈'),
+  ('𑊊', '𑊍'), ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋞'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑌽'), ('𑍐', '𑍐'),
+  ('𑍝', '𑍡'), ('𑐀', '𑐴'), ('𑑇', '𑑊'), ('𑒀', '𑒯'),
+  ('𑓄', '𑓅'), ('𑓇', '𑓇'), ('𑖀', '𑖮'), ('𑗘', '𑗛'),
+  ('𑘀', '𑘯'), ('𑙄', '𑙄'), ('𑚀', '𑚪'), ('𑜀', '\u{1171a}'),
+  ('\u{11800}', '\u{1182b}'), ('𑣿', '𑣿'), ('𑨀', '𑨀'),
+  ('𑨋', '𑨲'), ('𑨺', '𑨺'), ('𑩐', '𑩐'), ('𑩜', '𑪃'),
+  ('𑪆', '𑪉'), ('\u{11a9d}', '\u{11a9d}'), ('𑫀', '𑫸'),
+  ('𑰀', '𑰈'), ('𑰊', '𑰮'), ('𑱀', '𑱀'), ('𑱲', '𑲏'),
+  ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴰'), ('𑵆', '𑵆'),
+  ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d89}'), ('\u{11d98}', '\u{11d98}'),
+  ('\u{11ee0}', '\u{11ef2}'), ('𒀀', '𒎙'), ('𒒀', '𒕃'),
+  ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'), ('𖩀', '𖩞'),
+  ('𖫐', '𖫭'), ('𖬀', '𖬯'), ('𖭣', '𖭷'), ('𖭽', '𖮏'),
+  ('𖼀', '𖽄'), ('𖽐', '𖽐'), ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'),
+  ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'), ('𛱰', '𛱼'),
+  ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𞠀', '𞣄'), ('𞸀', '𞸃'),
+  ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'),
+  ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'),
+  ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'),
+  ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'),
+  ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'),
+  ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'),
+  ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'),
+  ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'),
+  ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'), ('𫠠', '𬺡'),
+  ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const OTHER_NUMBER: &'static [(char, char)] = &[
+  ('²', '³'), ('¹', '¹'), ('¼', '¾'), ('৴', '৹'), ('୲', '୷'),
+  ('௰', '௲'), ('౸', '౾'), ('൘', '൞'), ('൰', '൸'),
+  ('༪', '༳'), ('፩', '፼'), ('៰', '៹'), ('᧚', '᧚'),
+  ('⁰', '⁰'), ('⁴', '⁹'), ('₀', '₉'), ('⅐', '⅟'),
+  ('↉', '↉'), ('①', '⒛'), ('⓪', '⓿'), ('❶', '➓'),
+  ('⳽', '⳽'), ('㆒', '㆕'), ('㈠', '㈩'), ('㉈', '㉏'),
+  ('㉑', '㉟'), ('㊀', '㊉'), ('㊱', '㊿'), ('꠰', '꠵'),
+  ('𐄇', '𐄳'), ('𐅵', '𐅸'), ('𐆊', '𐆋'), ('𐋡', '𐋻'),
+  ('𐌠', '𐌣'), ('𐡘', '𐡟'), ('𐡹', '𐡿'), ('𐢧', '𐢯'),
+  ('𐣻', '𐣿'), ('𐤖', '𐤛'), ('𐦼', '𐦽'), ('𐧀', '𐧏'),
+  ('𐧒', '𐧿'), ('𐩀', '\u{10a48}'), ('𐩽', '𐩾'), ('𐪝', '𐪟'),
+  ('𐫫', '𐫯'), ('𐭘', '𐭟'), ('𐭸', '𐭿'), ('𐮩', '𐮯'),
+  ('𐳺', '𐳿'), ('𐹠', '𐹾'), ('\u{10f1d}', '\u{10f26}'),
+  ('\u{10f51}', '\u{10f54}'), ('𑁒', '𑁥'), ('𑇡', '𑇴'),
+  ('𑜺', '𑜻'), ('𑣪', '𑣲'), ('𑱚', '𑱬'), ('𖭛', '𖭡'),
+  ('\u{16e80}', '\u{16e96}'), ('\u{1d2e0}', '\u{1d2f3}'),
+  ('𝍠', '\u{1d378}'), ('𞣇', '𞣏'), ('\u{1ec71}', '\u{1ecab}'),
+  ('\u{1ecad}', '\u{1ecaf}'), ('\u{1ecb1}', '\u{1ecb4}'), ('🄀', '🄌'),
+];
+
+pub const OTHER_PUNCTUATION: &'static [(char, char)] = &[
+  ('!', '#'), ('%', '\''), ('*', '*'), (',', ','), ('.', '/'), (':', ';'),
+  ('?', '@'), ('\\', '\\'), ('¡', '¡'), ('§', '§'), ('¶', '·'),
+  ('¿', '¿'), (';', ';'), ('·', '·'), ('՚', '՟'), ('։', '։'),
+  ('׀', '׀'), ('׃', '׃'), ('׆', '׆'), ('׳', '״'), ('؉', '؊'),
+  ('،', '؍'), ('؛', '؛'), ('؞', '؟'), ('٪', '٭'), ('۔', '۔'),
+  ('܀', '܍'), ('߷', '߹'), ('࠰', '࠾'), ('࡞', '࡞'), ('।', '॥'),
+  ('॰', '॰'), ('৽', '৽'), ('\u{a76}', '\u{a76}'), ('૰', '૰'),
+  ('\u{c84}', '\u{c84}'), ('෴', '෴'), ('๏', '๏'), ('๚', '๛'),
+  ('༄', '༒'), ('༔', '༔'), ('྅', '྅'), ('࿐', '࿔'),
+  ('࿙', '࿚'), ('၊', '၏'), ('჻', '჻'), ('፠', '፨'),
+  ('᙭', '᙮'), ('᛫', '᛭'), ('᜵', '᜶'), ('។', '៖'),
+  ('៘', '៚'), ('᠀', '᠅'), ('᠇', '᠊'), ('᥄', '᥅'),
+  ('᨞', '᨟'), ('᪠', '᪦'), ('᪨', '᪭'), ('᭚', '᭠'),
+  ('᯼', '᯿'), ('᰻', '᰿'), ('᱾', '᱿'), ('᳀', '᳇'),
+  ('᳓', '᳓'), ('‖', '‗'), ('†', '‧'), ('‰', '‸'),
+  ('※', '‾'), ('⁁', '⁃'), ('⁇', '⁑'), ('⁓', '⁓'),
+  ('⁕', '⁞'), ('⳹', '⳼'), ('⳾', '⳿'), ('⵰', '⵰'),
+  ('⸀', '⸁'), ('⸆', '⸈'), ('⸋', '⸋'), ('⸎', '⸖'),
+  ('⸘', '⸙'), ('⸛', '⸛'), ('⸞', '⸟'), ('⸪', '⸮'),
+  ('⸰', '⸹'), ('⸼', '⸿'), ('⹁', '⹁'), ('⹃', '\u{2e4e}'),
+  ('、', '〃'), ('〽', '〽'), ('・', '・'), ('꓾', '꓿'),
+  ('꘍', '꘏'), ('꙳', '꙳'), ('꙾', '꙾'), ('꛲', '꛷'),
+  ('꡴', '꡷'), ('꣎', '꣏'), ('꣸', '꣺'), ('꣼', '꣼'),
+  ('꤮', '꤯'), ('꥟', '꥟'), ('꧁', '꧍'), ('꧞', '꧟'),
+  ('꩜', '꩟'), ('꫞', '꫟'), ('꫰', '꫱'), ('꯫', '꯫'),
+  ('︐', '︖'), ('︙', '︙'), ('︰', '︰'), ('﹅', '﹆'),
+  ('﹉', '﹌'), ('﹐', '﹒'), ('﹔', '﹗'), ('﹟', '﹡'),
+  ('﹨', '﹨'), ('﹪', '﹫'), ('！', '＃'), ('％', '＇'),
+  ('＊', '＊'), ('，', '，'), ('．', '／'), ('：', '；'),
+  ('？', '＠'), ('＼', '＼'), ('｡', '｡'), ('､', '･'),
+  ('𐄀', '𐄂'), ('𐎟', '𐎟'), ('𐏐', '𐏐'), ('𐕯', '𐕯'),
+  ('𐡗', '𐡗'), ('𐤟', '𐤟'), ('𐤿', '𐤿'), ('𐩐', '𐩘'),
+  ('𐩿', '𐩿'), ('𐫰', '𐫶'), ('𐬹', '𐬿'), ('𐮙', '𐮜'),
+  ('\u{10f55}', '\u{10f59}'), ('𑁇', '𑁍'), ('𑂻', '𑂼'),
+  ('𑂾', '𑃁'), ('𑅀', '𑅃'), ('𑅴', '𑅵'), ('𑇅', '𑇈'),
+  ('𑇍', '𑇍'), ('𑇛', '𑇛'), ('𑇝', '𑇟'), ('𑈸', '𑈽'),
+  ('𑊩', '𑊩'), ('𑑋', '𑑏'), ('𑑛', '𑑛'), ('𑑝', '𑑝'),
+  ('𑓆', '𑓆'), ('𑗁', '𑗗'), ('𑙁', '𑙃'), ('𑙠', '𑙬'),
+  ('𑜼', '𑜾'), ('\u{1183b}', '\u{1183b}'), ('𑨿', '𑩆'),
+  ('𑪚', '𑪜'), ('𑪞', '𑪢'), ('𑱁', '𑱅'), ('𑱰', '𑱱'),
+  ('\u{11ef7}', '\u{11ef8}'), ('𒑰', '𒑴'), ('𖩮', '𖩯'),
+  ('𖫵', '𖫵'), ('𖬷', '𖬻'), ('𖭄', '𖭄'),
+  ('\u{16e97}', '\u{16e9a}'), ('𛲟', '𛲟'), ('𝪇', '𝪋'),
+  ('𞥞', '𞥟'),
+];
+
+pub const OTHER_SYMBOL: &'static [(char, char)] = &[
+  ('¦', '¦'), ('©', '©'), ('®', '®'), ('°', '°'), ('҂', '҂'),
+  ('֍', '֎'), ('؎', '؏'), ('۞', '۞'), ('۩', '۩'), ('۽', '۾'),
+  ('߶', '߶'), ('৺', '৺'), ('୰', '୰'), ('௳', '௸'),
+  ('௺', '௺'), ('౿', '౿'), ('൏', '൏'), ('൹', '൹'),
+  ('༁', '༃'), ('༓', '༓'), ('༕', '༗'), ('༚', '༟'),
+  ('༴', '༴'), ('༶', '༶'), ('༸', '༸'), ('྾', '࿅'),
+  ('࿇', '࿌'), ('࿎', '࿏'), ('࿕', '࿘'), ('႞', '႟'),
+  ('᎐', '᎙'), ('᥀', '᥀'), ('᧞', '᧿'), ('᭡', '᭪'),
+  ('᭴', '᭼'), ('℀', '℁'), ('℃', '℆'), ('℈', '℉'),
+  ('℔', '℔'), ('№', '℗'), ('℞', '℣'), ('℥', '℥'),
+  ('℧', '℧'), ('℩', '℩'), ('℮', '℮'), ('℺', '℻'),
+  ('⅊', '⅊'), ('⅌', '⅍'), ('⅏', '⅏'), ('↊', '↋'),
+  ('↕', '↙'), ('↜', '↟'), ('↡', '↢'), ('↤', '↥'),
+  ('↧', '↭'), ('↯', '⇍'), ('⇐', '⇑'), ('⇓', '⇓'),
+  ('⇕', '⇳'), ('⌀', '⌇'), ('⌌', '⌟'), ('⌢', '⌨'),
+  ('⌫', '⍻'), ('⍽', '⎚'), ('⎴', '⏛'), ('⏢', '␦'),
+  ('⑀', '⑊'), ('⒜', 'ⓩ'), ('─', '▶'), ('▸', '◀'),
+  ('◂', '◷'), ('☀', '♮'), ('♰', '❧'), ('➔', '➿'),
+  ('⠀', '⣿'), ('⬀', '⬯'), ('⭅', '⭆'), ('⭍', '⭳'),
+  ('⭶', '⮕'), ('⮘', '⯈'), ('⯊', '\u{2bfe}'), ('⳥', '⳪'),
+  ('⺀', '⺙'), ('⺛', '⻳'), ('⼀', '⿕'), ('⿰', '⿻'),
+  ('〄', '〄'), ('〒', '〓'), ('〠', '〠'), ('〶', '〷'),
+  ('〾', '〿'), ('㆐', '㆑'), ('㆖', '㆟'), ('㇀', '㇣'),
+  ('㈀', '㈞'), ('㈪', '㉇'), ('㉐', '㉐'), ('㉠', '㉿'),
+  ('㊊', '㊰'), ('㋀', '㋾'), ('㌀', '㏿'), ('䷀', '䷿'),
+  ('꒐', '꓆'), ('꠨', '꠫'), ('꠶', '꠷'), ('꠹', '꠹'),
+  ('꩷', '꩹'), ('﷽', '﷽'), ('￤', '￤'), ('￨', '￨'),
+  ('￭', '￮'), ('￼', '�'), ('𐄷', '𐄿'), ('𐅹', '𐆉'),
+  ('𐆌', '𐆎'), ('𐆐', '𐆛'), ('𐆠', '𐆠'), ('𐇐', '𐇼'),
+  ('𐡷', '𐡸'), ('𐫈', '𐫈'), ('𑜿', '𑜿'), ('𖬼', '𖬿'),
+  ('𖭅', '𖭅'), ('𛲜', '𛲜'), ('𝀀', '𝃵'), ('𝄀', '𝄦'),
+  ('𝄩', '𝅘𝅥𝅲'), ('𝅪', '𝅬'), ('𝆃', '𝆄'), ('𝆌', '𝆩'),
+  ('𝆮', '𝇨'), ('𝈀', '𝉁'), ('𝉅', '𝉅'), ('𝌀', '𝍖'),
+  ('𝠀', '𝧿'), ('𝨷', '𝨺'), ('𝩭', '𝩴'), ('𝩶', '𝪃'),
+  ('𝪅', '𝪆'), ('\u{1ecac}', '\u{1ecac}'), ('🀀', '🀫'),
+  ('🀰', '🂓'), ('🂠', '🂮'), ('🂱', '🂿'), ('🃁', '🃏'),
+  ('🃑', '🃵'), ('🄐', '🅫'), ('🅰', '🆬'), ('🇦', '🈂'),
+  ('🈐', '🈻'), ('🉀', '🉈'), ('🉐', '🉑'), ('🉠', '🉥'),
+  ('🌀', '🏺'), ('🐀', '🛔'), ('🛠', '🛬'), ('🛰', '\u{1f6f9}'),
+  ('🜀', '🝳'), ('🞀', '\u{1f7d8}'), ('🠀', '🠋'), ('🠐', '🡇'),
+  ('🡐', '🡙'), ('🡠', '🢇'), ('🢐', '🢭'), ('🤀', '🤋'),
+  ('🤐', '🤾'), ('🥀', '\u{1f970}'), ('\u{1f973}', '\u{1f976}'),
+  ('\u{1f97a}', '\u{1f97a}'), ('\u{1f97c}', '\u{1f9a2}'),
+  ('\u{1f9b0}', '\u{1f9b9}'), ('🧀', '\u{1f9c2}'), ('🧐', '\u{1f9ff}'),
+  ('\u{1fa60}', '\u{1fa6d}'),
+];
+
+pub const PARAGRAPH_SEPARATOR: &'static [(char, char)] = &[
+  ('\u{2029}', '\u{2029}'),
+];
+
+pub const PRIVATE_USE: &'static [(char, char)] = &[
+  ('\u{e000}', '\u{f8ff}'), ('\u{f0000}', '\u{ffffd}'),
+  ('\u{100000}', '\u{10fffd}'),
+];
+
+pub const PUNCTUATION: &'static [(char, char)] = &[
+  ('!', '#'), ('%', '*'), (',', '/'), (':', ';'), ('?', '@'), ('[', ']'),
+  ('_', '_'), ('{', '{'), ('}', '}'), ('¡', '¡'), ('§', '§'),
+  ('«', '«'), ('¶', '·'), ('»', '»'), ('¿', '¿'), (';', ';'),
+  ('·', '·'), ('՚', '՟'), ('։', '֊'), ('־', '־'), ('׀', '׀'),
+  ('׃', '׃'), ('׆', '׆'), ('׳', '״'), ('؉', '؊'), ('،', '؍'),
+  ('؛', '؛'), ('؞', '؟'), ('٪', '٭'), ('۔', '۔'), ('܀', '܍'),
+  ('߷', '߹'), ('࠰', '࠾'), ('࡞', '࡞'), ('।', '॥'),
+  ('॰', '॰'), ('৽', '৽'), ('\u{a76}', '\u{a76}'), ('૰', '૰'),
+  ('\u{c84}', '\u{c84}'), ('෴', '෴'), ('๏', '๏'), ('๚', '๛'),
+  ('༄', '༒'), ('༔', '༔'), ('༺', '༽'), ('྅', '྅'),
+  ('࿐', '࿔'), ('࿙', '࿚'), ('၊', '၏'), ('჻', '჻'),
+  ('፠', '፨'), ('᐀', '᐀'), ('᙭', '᙮'), ('᚛', '᚜'),
+  ('᛫', '᛭'), ('᜵', '᜶'), ('។', '៖'), ('៘', '៚'),
+  ('᠀', '᠊'), ('᥄', '᥅'), ('᨞', '᨟'), ('᪠', '᪦'),
+  ('᪨', '᪭'), ('᭚', '᭠'), ('᯼', '᯿'), ('᰻', '᰿'),
+  ('᱾', '᱿'), ('᳀', '᳇'), ('᳓', '᳓'), ('‐', '‧'),
+  ('‰', '⁃'), ('⁅', '⁑'), ('⁓', '⁞'), ('⁽', '⁾'),
+  ('₍', '₎'), ('⌈', '⌋'), ('〈', '〉'), ('❨', '❵'),
+  ('⟅', '⟆'), ('⟦', '⟯'), ('⦃', '⦘'), ('⧘', '⧛'),
+  ('⧼', '⧽'), ('⳹', '⳼'), ('⳾', '⳿'), ('⵰', '⵰'),
+  ('⸀', '⸮'), ('⸰', '\u{2e4e}'), ('、', '〃'), ('〈', '】'),
+  ('〔', '〟'), ('〰', '〰'), ('〽', '〽'), ('゠', '゠'),
+  ('・', '・'), ('꓾', '꓿'), ('꘍', '꘏'), ('꙳', '꙳'),
+  ('꙾', '꙾'), ('꛲', '꛷'), ('꡴', '꡷'), ('꣎', '꣏'),
+  ('꣸', '꣺'), ('꣼', '꣼'), ('꤮', '꤯'), ('꥟', '꥟'),
+  ('꧁', '꧍'), ('꧞', '꧟'), ('꩜', '꩟'), ('꫞', '꫟'),
+  ('꫰', '꫱'), ('꯫', '꯫'), ('﴾', '﴿'), ('︐', '︙'),
+  ('︰', '﹒'), ('﹔', '﹡'), ('﹣', '﹣'), ('﹨', '﹨'),
+  ('﹪', '﹫'), ('！', '＃'), ('％', '＊'), ('，', '／'),
+  ('：', '；'), ('？', '＠'), ('［', '］'), ('＿', '＿'),
+  ('｛', '｛'), ('｝', '｝'), ('｟', '･'), ('𐄀', '𐄂'),
+  ('𐎟', '𐎟'), ('𐏐', '𐏐'), ('𐕯', '𐕯'), ('𐡗', '𐡗'),
+  ('𐤟', '𐤟'), ('𐤿', '𐤿'), ('𐩐', '𐩘'), ('𐩿', '𐩿'),
+  ('𐫰', '𐫶'), ('𐬹', '𐬿'), ('𐮙', '𐮜'),
+  ('\u{10f55}', '\u{10f59}'), ('𑁇', '𑁍'), ('𑂻', '𑂼'),
+  ('𑂾', '𑃁'), ('𑅀', '𑅃'), ('𑅴', '𑅵'), ('𑇅', '𑇈'),
+  ('𑇍', '𑇍'), ('𑇛', '𑇛'), ('𑇝', '𑇟'), ('𑈸', '𑈽'),
+  ('𑊩', '𑊩'), ('𑑋', '𑑏'), ('𑑛', '𑑛'), ('𑑝', '𑑝'),
+  ('𑓆', '𑓆'), ('𑗁', '𑗗'), ('𑙁', '𑙃'), ('𑙠', '𑙬'),
+  ('𑜼', '𑜾'), ('\u{1183b}', '\u{1183b}'), ('𑨿', '𑩆'),
+  ('𑪚', '𑪜'), ('𑪞', '𑪢'), ('𑱁', '𑱅'), ('𑱰', '𑱱'),
+  ('\u{11ef7}', '\u{11ef8}'), ('𒑰', '𒑴'), ('𖩮', '𖩯'),
+  ('𖫵', '𖫵'), ('𖬷', '𖬻'), ('𖭄', '𖭄'),
+  ('\u{16e97}', '\u{16e9a}'), ('𛲟', '𛲟'), ('𝪇', '𝪋'),
+  ('𞥞', '𞥟'),
+];
+
+pub const SEPARATOR: &'static [(char, char)] = &[
+  (' ', ' '), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
+  ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2029}'),
+  ('\u{202f}', '\u{202f}'), ('\u{205f}', '\u{205f}'),
+  ('\u{3000}', '\u{3000}'),
+];
+
+pub const SPACE_SEPARATOR: &'static [(char, char)] = &[
+  (' ', ' '), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'),
+  ('\u{2000}', '\u{200a}'), ('\u{202f}', '\u{202f}'),
+  ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+];
+
+pub const SPACING_MARK: &'static [(char, char)] = &[
+  ('ः', 'ः'), ('ऻ', 'ऻ'), ('ा', 'ी'), ('ॉ', 'ौ'),
+  ('ॎ', 'ॏ'), ('ং', 'ঃ'), ('া', 'ী'), ('ে', 'ৈ'),
+  ('ো', 'ৌ'), ('ৗ', 'ৗ'), ('ਃ', 'ਃ'), ('ਾ', 'ੀ'),
+  ('ઃ', 'ઃ'), ('ા', 'ી'), ('ૉ', 'ૉ'), ('ો', 'ૌ'),
+  ('ଂ', 'ଃ'), ('ା', 'ା'), ('ୀ', 'ୀ'), ('େ', 'ୈ'),
+  ('ୋ', 'ୌ'), ('ୗ', 'ୗ'), ('ா', 'ி'), ('ு', 'ூ'),
+  ('ெ', 'ை'), ('ொ', 'ௌ'), ('ௗ', 'ௗ'), ('ఁ', 'ః'),
+  ('ు', 'ౄ'), ('ಂ', 'ಃ'), ('ಾ', 'ಾ'), ('ೀ', 'ೄ'),
+  ('ೇ', 'ೈ'), ('ೊ', 'ೋ'), ('ೕ', 'ೖ'), ('ം', 'ഃ'),
+  ('ാ', 'ീ'), ('െ', 'ൈ'), ('ൊ', 'ൌ'), ('ൗ', 'ൗ'),
+  ('ං', 'ඃ'), ('ා', 'ෑ'), ('ෘ', 'ෟ'), ('ෲ', 'ෳ'),
+  ('༾', '༿'), ('ཿ', 'ཿ'), ('ါ', 'ာ'), ('ေ', 'ေ'),
+  ('း', 'း'), ('ျ', 'ြ'), ('ၖ', 'ၗ'), ('ၢ', 'ၤ'),
+  ('ၧ', 'ၭ'), ('ႃ', 'ႄ'), ('ႇ', 'ႌ'), ('ႏ', 'ႏ'),
+  ('ႚ', 'ႜ'), ('ា', 'ា'), ('ើ', 'ៅ'), ('ះ', 'ៈ'),
+  ('ᤣ', 'ᤦ'), ('ᤩ', 'ᤫ'), ('ᤰ', 'ᤱ'), ('ᤳ', 'ᤸ'),
+  ('ᨙ', 'ᨚ'), ('ᩕ', 'ᩕ'), ('ᩗ', 'ᩗ'), ('ᩡ', 'ᩡ'),
+  ('ᩣ', 'ᩤ'), ('ᩭ', 'ᩲ'), ('ᬄ', 'ᬄ'), ('ᬵ', 'ᬵ'),
+  ('ᬻ', 'ᬻ'), ('ᬽ', 'ᭁ'), ('ᭃ', '᭄'), ('ᮂ', 'ᮂ'),
+  ('ᮡ', 'ᮡ'), ('ᮦ', 'ᮧ'), ('᮪', '᮪'), ('ᯧ', 'ᯧ'),
+  ('ᯪ', 'ᯬ'), ('ᯮ', 'ᯮ'), ('᯲', '᯳'), ('ᰤ', 'ᰫ'),
+  ('ᰴ', 'ᰵ'), ('᳡', '᳡'), ('ᳲ', 'ᳳ'), ('᳷', '᳷'),
+  ('〮', '〯'), ('ꠣ', 'ꠤ'), ('ꠧ', 'ꠧ'), ('ꢀ', 'ꢁ'),
+  ('ꢴ', 'ꣃ'), ('ꥒ', '꥓'), ('ꦃ', 'ꦃ'), ('ꦴ', 'ꦵ'),
+  ('ꦺ', 'ꦻ'), ('ꦽ', '꧀'), ('ꨯ', 'ꨰ'), ('ꨳ', 'ꨴ'),
+  ('ꩍ', 'ꩍ'), ('ꩻ', 'ꩻ'), ('ꩽ', 'ꩽ'), ('ꫫ', 'ꫫ'),
+  ('ꫮ', 'ꫯ'), ('ꫵ', 'ꫵ'), ('ꯣ', 'ꯤ'), ('ꯦ', 'ꯧ'),
+  ('ꯩ', 'ꯪ'), ('꯬', '꯬'), ('𑀀', '𑀀'), ('𑀂', '𑀂'),
+  ('𑂂', '𑂂'), ('𑂰', '𑂲'), ('𑂷', '𑂸'), ('𑄬', '𑄬'),
+  ('\u{11145}', '\u{11146}'), ('𑆂', '𑆂'), ('𑆳', '𑆵'),
+  ('𑆿', '𑇀'), ('𑈬', '𑈮'), ('𑈲', '𑈳'), ('𑈵', '𑈵'),
+  ('𑋠', '𑋢'), ('𑌂', '𑌃'), ('𑌾', '𑌿'), ('𑍁', '𑍄'),
+  ('𑍇', '𑍈'), ('𑍋', '𑍍'), ('𑍗', '𑍗'), ('𑍢', '𑍣'),
+  ('𑐵', '𑐷'), ('𑑀', '𑑁'), ('𑑅', '𑑅'), ('𑒰', '𑒲'),
+  ('𑒹', '𑒹'), ('𑒻', '𑒾'), ('𑓁', '𑓁'), ('𑖯', '𑖱'),
+  ('𑖸', '𑖻'), ('𑖾', '𑖾'), ('𑘰', '𑘲'), ('𑘻', '𑘼'),
+  ('𑘾', '𑘾'), ('𑚬', '𑚬'), ('𑚮', '𑚯'), ('𑚶', '𑚶'),
+  ('𑜠', '𑜡'), ('𑜦', '𑜦'), ('\u{1182c}', '\u{1182e}'),
+  ('\u{11838}', '\u{11838}'), ('𑨹', '𑨹'), ('𑩗', '𑩘'),
+  ('𑪗', '𑪗'), ('𑰯', '𑰯'), ('𑰾', '𑰾'), ('𑲩', '𑲩'),
+  ('𑲱', '𑲱'), ('𑲴', '𑲴'), ('\u{11d8a}', '\u{11d8e}'),
+  ('\u{11d93}', '\u{11d94}'), ('\u{11d96}', '\u{11d96}'),
+  ('\u{11ef5}', '\u{11ef6}'), ('𖽑', '𖽾'), ('𝅥', '𝅦'),
+  ('𝅭', '𝅲'),
+];
+
+pub const SYMBOL: &'static [(char, char)] = &[
+  ('$', '$'), ('+', '+'), ('<', '>'), ('^', '^'), ('`', '`'), ('|', '|'),
+  ('~', '~'), ('¢', '¦'), ('¨', '©'), ('¬', '¬'), ('®', '±'),
+  ('´', '´'), ('¸', '¸'), ('×', '×'), ('÷', '÷'), ('˂', '˅'),
+  ('˒', '˟'), ('˥', '˫'), ('˭', '˭'), ('˯', '˿'), ('͵', '͵'),
+  ('΄', '΅'), ('϶', '϶'), ('҂', '҂'), ('֍', '֏'), ('؆', '؈'),
+  ('؋', '؋'), ('؎', '؏'), ('۞', '۞'), ('۩', '۩'), ('۽', '۾'),
+  ('߶', '߶'), ('\u{7fe}', '\u{7ff}'), ('৲', '৳'), ('৺', '৻'),
+  ('૱', '૱'), ('୰', '୰'), ('௳', '௺'), ('౿', '౿'),
+  ('൏', '൏'), ('൹', '൹'), ('฿', '฿'), ('༁', '༃'),
+  ('༓', '༓'), ('༕', '༗'), ('༚', '༟'), ('༴', '༴'),
+  ('༶', '༶'), ('༸', '༸'), ('྾', '࿅'), ('࿇', '࿌'),
+  ('࿎', '࿏'), ('࿕', '࿘'), ('႞', '႟'), ('᎐', '᎙'),
+  ('៛', '៛'), ('᥀', '᥀'), ('᧞', '᧿'), ('᭡', '᭪'),
+  ('᭴', '᭼'), ('᾽', '᾽'), ('᾿', '῁'), ('῍', '῏'),
+  ('῝', '῟'), ('῭', '`'), ('´', '῾'), ('⁄', '⁄'),
+  ('⁒', '⁒'), ('⁺', '⁼'), ('₊', '₌'), ('₠', '₿'),
+  ('℀', '℁'), ('℃', '℆'), ('℈', '℉'), ('℔', '℔'),
+  ('№', '℘'), ('℞', '℣'), ('℥', '℥'), ('℧', '℧'),
+  ('℩', '℩'), ('℮', '℮'), ('℺', '℻'), ('⅀', '⅄'),
+  ('⅊', '⅍'), ('⅏', '⅏'), ('↊', '↋'), ('←', '⌇'),
+  ('⌌', '⌨'), ('⌫', '␦'), ('⑀', '⑊'), ('⒜', 'ⓩ'),
+  ('─', '❧'), ('➔', '⟄'), ('⟇', '⟥'), ('⟰', '⦂'),
+  ('⦙', '⧗'), ('⧜', '⧻'), ('⧾', '⭳'), ('⭶', '⮕'),
+  ('⮘', '⯈'), ('⯊', '\u{2bfe}'), ('⳥', '⳪'), ('⺀', '⺙'),
+  ('⺛', '⻳'), ('⼀', '⿕'), ('⿰', '⿻'), ('〄', '〄'),
+  ('〒', '〓'), ('〠', '〠'), ('〶', '〷'), ('〾', '〿'),
+  ('゛', '゜'), ('㆐', '㆑'), ('㆖', '㆟'), ('㇀', '㇣'),
+  ('㈀', '㈞'), ('㈪', '㉇'), ('㉐', '㉐'), ('㉠', '㉿'),
+  ('㊊', '㊰'), ('㋀', '㋾'), ('㌀', '㏿'), ('䷀', '䷿'),
+  ('꒐', '꓆'), ('꜀', '꜖'), ('꜠', '꜡'), ('꞉', '꞊'),
+  ('꠨', '꠫'), ('꠶', '꠹'), ('꩷', '꩹'), ('꭛', '꭛'),
+  ('﬩', '﬩'), ('﮲', '﯁'), ('﷼', '﷽'), ('﹢', '﹢'),
+  ('﹤', '﹦'), ('﹩', '﹩'), ('＄', '＄'), ('＋', '＋'),
+  ('＜', '＞'), ('＾', '＾'), ('｀', '｀'), ('｜', '｜'),
+  ('～', '～'), ('￠', '￦'), ('￨', '￮'), ('￼', '�'),
+  ('𐄷', '𐄿'), ('𐅹', '𐆉'), ('𐆌', '𐆎'), ('𐆐', '𐆛'),
+  ('𐆠', '𐆠'), ('𐇐', '𐇼'), ('𐡷', '𐡸'), ('𐫈', '𐫈'),
+  ('𑜿', '𑜿'), ('𖬼', '𖬿'), ('𖭅', '𖭅'), ('𛲜', '𛲜'),
+  ('𝀀', '𝃵'), ('𝄀', '𝄦'), ('𝄩', '𝅘𝅥𝅲'), ('𝅪', '𝅬'),
+  ('𝆃', '𝆄'), ('𝆌', '𝆩'), ('𝆮', '𝇨'), ('𝈀', '𝉁'),
+  ('𝉅', '𝉅'), ('𝌀', '𝍖'), ('𝛁', '𝛁'), ('𝛛', '𝛛'),
+  ('𝛻', '𝛻'), ('𝜕', '𝜕'), ('𝜵', '𝜵'), ('𝝏', '𝝏'),
+  ('𝝯', '𝝯'), ('𝞉', '𝞉'), ('𝞩', '𝞩'), ('𝟃', '𝟃'),
+  ('𝠀', '𝧿'), ('𝨷', '𝨺'), ('𝩭', '𝩴'), ('𝩶', '𝪃'),
+  ('𝪅', '𝪆'), ('\u{1ecac}', '\u{1ecac}'), ('\u{1ecb0}', '\u{1ecb0}'),
+  ('𞻰', '𞻱'), ('🀀', '🀫'), ('🀰', '🂓'), ('🂠', '🂮'),
+  ('🂱', '🂿'), ('🃁', '🃏'), ('🃑', '🃵'), ('🄐', '🅫'),
+  ('🅰', '🆬'), ('🇦', '🈂'), ('🈐', '🈻'), ('🉀', '🉈'),
+  ('🉐', '🉑'), ('🉠', '🉥'), ('🌀', '🛔'), ('🛠', '🛬'),
+  ('🛰', '\u{1f6f9}'), ('🜀', '🝳'), ('🞀', '\u{1f7d8}'),
+  ('🠀', '🠋'), ('🠐', '🡇'), ('🡐', '🡙'), ('🡠', '🢇'),
+  ('🢐', '🢭'), ('🤀', '🤋'), ('🤐', '🤾'), ('🥀', '\u{1f970}'),
+  ('\u{1f973}', '\u{1f976}'), ('\u{1f97a}', '\u{1f97a}'),
+  ('\u{1f97c}', '\u{1f9a2}'), ('\u{1f9b0}', '\u{1f9b9}'),
+  ('🧀', '\u{1f9c2}'), ('🧐', '\u{1f9ff}'), ('\u{1fa60}', '\u{1fa6d}'),
+];
+
+pub const TITLECASE_LETTER: &'static [(char, char)] = &[
+  ('ǅ', 'ǅ'), ('ǈ', 'ǈ'), ('ǋ', 'ǋ'), ('ǲ', 'ǲ'), ('ᾈ', 'ᾏ'),
+  ('ᾘ', 'ᾟ'), ('ᾨ', 'ᾯ'), ('ᾼ', 'ᾼ'), ('ῌ', 'ῌ'),
+  ('ῼ', 'ῼ'),
+];
+
+pub const UNASSIGNED: &'static [(char, char)] = &[
+  ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'),
+  ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'),
+  ('\u{557}', '\u{558}'), ('\u{58b}', '\u{58c}'), ('\u{590}', '\u{590}'),
+  ('\u{5c8}', '\u{5cf}'), ('\u{5eb}', '\u{5ee}'), ('\u{5f5}', '\u{5ff}'),
+  ('\u{61d}', '\u{61d}'), ('\u{70e}', '\u{70e}'), ('\u{74b}', '\u{74c}'),
+  ('\u{7b2}', '\u{7bf}'), ('\u{7fb}', '\u{7fc}'), ('\u{82e}', '\u{82f}'),
+  ('\u{83f}', '\u{83f}'), ('\u{85c}', '\u{85d}'), ('\u{85f}', '\u{85f}'),
+  ('\u{86b}', '\u{89f}'), ('\u{8b5}', '\u{8b5}'), ('\u{8be}', '\u{8d2}'),
+  ('\u{984}', '\u{984}'), ('\u{98d}', '\u{98e}'), ('\u{991}', '\u{992}'),
+  ('\u{9a9}', '\u{9a9}'), ('\u{9b1}', '\u{9b1}'), ('\u{9b3}', '\u{9b5}'),
+  ('\u{9ba}', '\u{9bb}'), ('\u{9c5}', '\u{9c6}'), ('\u{9c9}', '\u{9ca}'),
+  ('\u{9cf}', '\u{9d6}'), ('\u{9d8}', '\u{9db}'), ('\u{9de}', '\u{9de}'),
+  ('\u{9e4}', '\u{9e5}'), ('\u{9ff}', '\u{a00}'), ('\u{a04}', '\u{a04}'),
+  ('\u{a0b}', '\u{a0e}'), ('\u{a11}', '\u{a12}'), ('\u{a29}', '\u{a29}'),
+  ('\u{a31}', '\u{a31}'), ('\u{a34}', '\u{a34}'), ('\u{a37}', '\u{a37}'),
+  ('\u{a3a}', '\u{a3b}'), ('\u{a3d}', '\u{a3d}'), ('\u{a43}', '\u{a46}'),
+  ('\u{a49}', '\u{a4a}'), ('\u{a4e}', '\u{a50}'), ('\u{a52}', '\u{a58}'),
+  ('\u{a5d}', '\u{a5d}'), ('\u{a5f}', '\u{a65}'), ('\u{a77}', '\u{a80}'),
+  ('\u{a84}', '\u{a84}'), ('\u{a8e}', '\u{a8e}'), ('\u{a92}', '\u{a92}'),
+  ('\u{aa9}', '\u{aa9}'), ('\u{ab1}', '\u{ab1}'), ('\u{ab4}', '\u{ab4}'),
+  ('\u{aba}', '\u{abb}'), ('\u{ac6}', '\u{ac6}'), ('\u{aca}', '\u{aca}'),
+  ('\u{ace}', '\u{acf}'), ('\u{ad1}', '\u{adf}'), ('\u{ae4}', '\u{ae5}'),
+  ('\u{af2}', '\u{af8}'), ('\u{b00}', '\u{b00}'), ('\u{b04}', '\u{b04}'),
+  ('\u{b0d}', '\u{b0e}'), ('\u{b11}', '\u{b12}'), ('\u{b29}', '\u{b29}'),
+  ('\u{b31}', '\u{b31}'), ('\u{b34}', '\u{b34}'), ('\u{b3a}', '\u{b3b}'),
+  ('\u{b45}', '\u{b46}'), ('\u{b49}', '\u{b4a}'), ('\u{b4e}', '\u{b55}'),
+  ('\u{b58}', '\u{b5b}'), ('\u{b5e}', '\u{b5e}'), ('\u{b64}', '\u{b65}'),
+  ('\u{b78}', '\u{b81}'), ('\u{b84}', '\u{b84}'), ('\u{b8b}', '\u{b8d}'),
+  ('\u{b91}', '\u{b91}'), ('\u{b96}', '\u{b98}'), ('\u{b9b}', '\u{b9b}'),
+  ('\u{b9d}', '\u{b9d}'), ('\u{ba0}', '\u{ba2}'), ('\u{ba5}', '\u{ba7}'),
+  ('\u{bab}', '\u{bad}'), ('\u{bba}', '\u{bbd}'), ('\u{bc3}', '\u{bc5}'),
+  ('\u{bc9}', '\u{bc9}'), ('\u{bce}', '\u{bcf}'), ('\u{bd1}', '\u{bd6}'),
+  ('\u{bd8}', '\u{be5}'), ('\u{bfb}', '\u{bff}'), ('\u{c0d}', '\u{c0d}'),
+  ('\u{c11}', '\u{c11}'), ('\u{c29}', '\u{c29}'), ('\u{c3a}', '\u{c3c}'),
+  ('\u{c45}', '\u{c45}'), ('\u{c49}', '\u{c49}'), ('\u{c4e}', '\u{c54}'),
+  ('\u{c57}', '\u{c57}'), ('\u{c5b}', '\u{c5f}'), ('\u{c64}', '\u{c65}'),
+  ('\u{c70}', '\u{c77}'), ('\u{c8d}', '\u{c8d}'), ('\u{c91}', '\u{c91}'),
+  ('\u{ca9}', '\u{ca9}'), ('\u{cb4}', '\u{cb4}'), ('\u{cba}', '\u{cbb}'),
+  ('\u{cc5}', '\u{cc5}'), ('\u{cc9}', '\u{cc9}'), ('\u{cce}', '\u{cd4}'),
+  ('\u{cd7}', '\u{cdd}'), ('\u{cdf}', '\u{cdf}'), ('\u{ce4}', '\u{ce5}'),
+  ('\u{cf0}', '\u{cf0}'), ('\u{cf3}', '\u{cff}'), ('\u{d04}', '\u{d04}'),
+  ('\u{d0d}', '\u{d0d}'), ('\u{d11}', '\u{d11}'), ('\u{d45}', '\u{d45}'),
+  ('\u{d49}', '\u{d49}'), ('\u{d50}', '\u{d53}'), ('\u{d64}', '\u{d65}'),
+  ('\u{d80}', '\u{d81}'), ('\u{d84}', '\u{d84}'), ('\u{d97}', '\u{d99}'),
+  ('\u{db2}', '\u{db2}'), ('\u{dbc}', '\u{dbc}'), ('\u{dbe}', '\u{dbf}'),
+  ('\u{dc7}', '\u{dc9}'), ('\u{dcb}', '\u{dce}'), ('\u{dd5}', '\u{dd5}'),
+  ('\u{dd7}', '\u{dd7}'), ('\u{de0}', '\u{de5}'), ('\u{df0}', '\u{df1}'),
+  ('\u{df5}', '\u{e00}'), ('\u{e3b}', '\u{e3e}'), ('\u{e5c}', '\u{e80}'),
+  ('\u{e83}', '\u{e83}'), ('\u{e85}', '\u{e86}'), ('\u{e89}', '\u{e89}'),
+  ('\u{e8b}', '\u{e8c}'), ('\u{e8e}', '\u{e93}'), ('\u{e98}', '\u{e98}'),
+  ('\u{ea0}', '\u{ea0}'), ('\u{ea4}', '\u{ea4}'), ('\u{ea6}', '\u{ea6}'),
+  ('\u{ea8}', '\u{ea9}'), ('\u{eac}', '\u{eac}'), ('\u{eba}', '\u{eba}'),
+  ('\u{ebe}', '\u{ebf}'), ('\u{ec5}', '\u{ec5}'), ('\u{ec7}', '\u{ec7}'),
+  ('\u{ece}', '\u{ecf}'), ('\u{eda}', '\u{edb}'), ('\u{ee0}', '\u{eff}'),
+  ('\u{f48}', '\u{f48}'), ('\u{f6d}', '\u{f70}'), ('\u{f98}', '\u{f98}'),
+  ('\u{fbd}', '\u{fbd}'), ('\u{fcd}', '\u{fcd}'), ('\u{fdb}', '\u{fff}'),
+  ('\u{10c6}', '\u{10c6}'), ('\u{10c8}', '\u{10cc}'),
+  ('\u{10ce}', '\u{10cf}'), ('\u{1249}', '\u{1249}'),
+  ('\u{124e}', '\u{124f}'), ('\u{1257}', '\u{1257}'),
+  ('\u{1259}', '\u{1259}'), ('\u{125e}', '\u{125f}'),
+  ('\u{1289}', '\u{1289}'), ('\u{128e}', '\u{128f}'),
+  ('\u{12b1}', '\u{12b1}'), ('\u{12b6}', '\u{12b7}'),
+  ('\u{12bf}', '\u{12bf}'), ('\u{12c1}', '\u{12c1}'),
+  ('\u{12c6}', '\u{12c7}'), ('\u{12d7}', '\u{12d7}'),
+  ('\u{1311}', '\u{1311}'), ('\u{1316}', '\u{1317}'),
+  ('\u{135b}', '\u{135c}'), ('\u{137d}', '\u{137f}'),
+  ('\u{139a}', '\u{139f}'), ('\u{13f6}', '\u{13f7}'),
+  ('\u{13fe}', '\u{13ff}'), ('\u{169d}', '\u{169f}'),
+  ('\u{16f9}', '\u{16ff}'), ('\u{170d}', '\u{170d}'),
+  ('\u{1715}', '\u{171f}'), ('\u{1737}', '\u{173f}'),
+  ('\u{1754}', '\u{175f}'), ('\u{176d}', '\u{176d}'),
+  ('\u{1771}', '\u{1771}'), ('\u{1774}', '\u{177f}'),
+  ('\u{17de}', '\u{17df}'), ('\u{17ea}', '\u{17ef}'),
+  ('\u{17fa}', '\u{17ff}'), ('\u{180f}', '\u{180f}'),
+  ('\u{181a}', '\u{181f}'), ('\u{1879}', '\u{187f}'),
+  ('\u{18ab}', '\u{18af}'), ('\u{18f6}', '\u{18ff}'),
+  ('\u{191f}', '\u{191f}'), ('\u{192c}', '\u{192f}'),
+  ('\u{193c}', '\u{193f}'), ('\u{1941}', '\u{1943}'),
+  ('\u{196e}', '\u{196f}'), ('\u{1975}', '\u{197f}'),
+  ('\u{19ac}', '\u{19af}'), ('\u{19ca}', '\u{19cf}'),
+  ('\u{19db}', '\u{19dd}'), ('\u{1a1c}', '\u{1a1d}'),
+  ('\u{1a5f}', '\u{1a5f}'), ('\u{1a7d}', '\u{1a7e}'),
+  ('\u{1a8a}', '\u{1a8f}'), ('\u{1a9a}', '\u{1a9f}'),
+  ('\u{1aae}', '\u{1aaf}'), ('\u{1abf}', '\u{1aff}'),
+  ('\u{1b4c}', '\u{1b4f}'), ('\u{1b7d}', '\u{1b7f}'),
+  ('\u{1bf4}', '\u{1bfb}'), ('\u{1c38}', '\u{1c3a}'),
+  ('\u{1c4a}', '\u{1c4c}'), ('\u{1c89}', '\u{1c8f}'),
+  ('\u{1cbb}', '\u{1cbc}'), ('\u{1cc8}', '\u{1ccf}'),
+  ('\u{1cfa}', '\u{1cff}'), ('\u{1dfa}', '\u{1dfa}'),
+  ('\u{1f16}', '\u{1f17}'), ('\u{1f1e}', '\u{1f1f}'),
+  ('\u{1f46}', '\u{1f47}'), ('\u{1f4e}', '\u{1f4f}'),
+  ('\u{1f58}', '\u{1f58}'), ('\u{1f5a}', '\u{1f5a}'),
+  ('\u{1f5c}', '\u{1f5c}'), ('\u{1f5e}', '\u{1f5e}'),
+  ('\u{1f7e}', '\u{1f7f}'), ('\u{1fb5}', '\u{1fb5}'),
+  ('\u{1fc5}', '\u{1fc5}'), ('\u{1fd4}', '\u{1fd5}'),
+  ('\u{1fdc}', '\u{1fdc}'), ('\u{1ff0}', '\u{1ff1}'),
+  ('\u{1ff5}', '\u{1ff5}'), ('\u{1fff}', '\u{1fff}'),
+  ('\u{2065}', '\u{2065}'), ('\u{2072}', '\u{2073}'),
+  ('\u{208f}', '\u{208f}'), ('\u{209d}', '\u{209f}'),
+  ('\u{20c0}', '\u{20cf}'), ('\u{20f1}', '\u{20ff}'),
+  ('\u{218c}', '\u{218f}'), ('\u{2427}', '\u{243f}'),
+  ('\u{244b}', '\u{245f}'), ('\u{2b74}', '\u{2b75}'),
+  ('\u{2b96}', '\u{2b97}'), ('\u{2bc9}', '\u{2bc9}'),
+  ('\u{2bff}', '\u{2bff}'), ('\u{2c2f}', '\u{2c2f}'),
+  ('\u{2c5f}', '\u{2c5f}'), ('\u{2cf4}', '\u{2cf8}'),
+  ('\u{2d26}', '\u{2d26}'), ('\u{2d28}', '\u{2d2c}'),
+  ('\u{2d2e}', '\u{2d2f}'), ('\u{2d68}', '\u{2d6e}'),
+  ('\u{2d71}', '\u{2d7e}'), ('\u{2d97}', '\u{2d9f}'),
+  ('\u{2da7}', '\u{2da7}'), ('\u{2daf}', '\u{2daf}'),
+  ('\u{2db7}', '\u{2db7}'), ('\u{2dbf}', '\u{2dbf}'),
+  ('\u{2dc7}', '\u{2dc7}'), ('\u{2dcf}', '\u{2dcf}'),
+  ('\u{2dd7}', '\u{2dd7}'), ('\u{2ddf}', '\u{2ddf}'),
+  ('\u{2e4f}', '\u{2e7f}'), ('\u{2e9a}', '\u{2e9a}'),
+  ('\u{2ef4}', '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'),
+  ('\u{2ffc}', '\u{2fff}'), ('\u{3040}', '\u{3040}'),
+  ('\u{3097}', '\u{3098}'), ('\u{3100}', '\u{3104}'),
+  ('\u{3130}', '\u{3130}'), ('\u{318f}', '\u{318f}'),
+  ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'),
+  ('\u{321f}', '\u{321f}'), ('\u{32ff}', '\u{32ff}'),
+  ('\u{4db6}', '\u{4dbf}'), ('\u{9ff0}', '\u{9fff}'),
+  ('\u{a48d}', '\u{a48f}'), ('\u{a4c7}', '\u{a4cf}'),
+  ('\u{a62c}', '\u{a63f}'), ('\u{a6f8}', '\u{a6ff}'),
+  ('\u{a7ba}', '\u{a7f6}'), ('\u{a82c}', '\u{a82f}'),
+  ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'),
+  ('\u{a8c6}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'),
+  ('\u{a954}', '\u{a95e}'), ('\u{a97d}', '\u{a97f}'),
+  ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'),
+  ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'),
+  ('\u{aa4e}', '\u{aa4f}'), ('\u{aa5a}', '\u{aa5b}'),
+  ('\u{aac3}', '\u{aada}'), ('\u{aaf7}', '\u{ab00}'),
+  ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}', '\u{ab10}'),
+  ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'),
+  ('\u{ab2f}', '\u{ab2f}'), ('\u{ab66}', '\u{ab6f}'),
+  ('\u{abee}', '\u{abef}'), ('\u{abfa}', '\u{abff}'),
+  ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}', '\u{d7ca}'),
+  ('\u{d7fc}', '\u{d7ff}'), ('\u{fa6e}', '\u{fa6f}'),
+  ('\u{fada}', '\u{faff}'), ('\u{fb07}', '\u{fb12}'),
+  ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'),
+  ('\u{fb3d}', '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'),
+  ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', '\u{fb45}'),
+  ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'),
+  ('\u{fd90}', '\u{fd91}'), ('\u{fdc8}', '\u{fdef}'),
+  ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'),
+  ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'),
+  ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}', '\u{fe75}'),
+  ('\u{fefd}', '\u{fefe}'), ('\u{ff00}', '\u{ff00}'),
+  ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'),
+  ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'),
+  ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'),
+  ('\u{ffef}', '\u{fff8}'), ('\u{fffe}', '\u{ffff}'),
+  ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'),
+  ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'),
+  ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', '\u{1007f}'),
+  ('\u{100fb}', '\u{100ff}'), ('\u{10103}', '\u{10106}'),
+  ('\u{10134}', '\u{10136}'), ('\u{1018f}', '\u{1018f}'),
+  ('\u{1019c}', '\u{1019f}'), ('\u{101a1}', '\u{101cf}'),
+  ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'),
+  ('\u{102d1}', '\u{102df}'), ('\u{102fc}', '\u{102ff}'),
+  ('\u{10324}', '\u{1032c}'), ('\u{1034b}', '\u{1034f}'),
+  ('\u{1037b}', '\u{1037f}'), ('\u{1039e}', '\u{1039e}'),
+  ('\u{103c4}', '\u{103c7}'), ('\u{103d6}', '\u{103ff}'),
+  ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', '\u{104af}'),
+  ('\u{104d4}', '\u{104d7}'), ('\u{104fc}', '\u{104ff}'),
+  ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'),
+  ('\u{10570}', '\u{105ff}'), ('\u{10737}', '\u{1073f}'),
+  ('\u{10756}', '\u{1075f}'), ('\u{10768}', '\u{107ff}'),
+  ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'),
+  ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'),
+  ('\u{1083d}', '\u{1083e}'), ('\u{10856}', '\u{10856}'),
+  ('\u{1089f}', '\u{108a6}'), ('\u{108b0}', '\u{108df}'),
+  ('\u{108f3}', '\u{108f3}'), ('\u{108f6}', '\u{108fa}'),
+  ('\u{1091c}', '\u{1091e}'), ('\u{1093a}', '\u{1093e}'),
+  ('\u{10940}', '\u{1097f}'), ('\u{109b8}', '\u{109bb}'),
+  ('\u{109d0}', '\u{109d1}'), ('\u{10a04}', '\u{10a04}'),
+  ('\u{10a07}', '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'),
+  ('\u{10a18}', '\u{10a18}'), ('\u{10a36}', '\u{10a37}'),
+  ('\u{10a3b}', '\u{10a3e}'), ('\u{10a49}', '\u{10a4f}'),
+  ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'),
+  ('\u{10ae7}', '\u{10aea}'), ('\u{10af7}', '\u{10aff}'),
+  ('\u{10b36}', '\u{10b38}'), ('\u{10b56}', '\u{10b57}'),
+  ('\u{10b73}', '\u{10b77}'), ('\u{10b92}', '\u{10b98}'),
+  ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}', '\u{10bff}'),
+  ('\u{10c49}', '\u{10c7f}'), ('\u{10cb3}', '\u{10cbf}'),
+  ('\u{10cf3}', '\u{10cf9}'), ('\u{10d28}', '\u{10d2f}'),
+  ('\u{10d3a}', '\u{10e5f}'), ('\u{10e7f}', '\u{10eff}'),
+  ('\u{10f28}', '\u{10f2f}'), ('\u{10f5a}', '\u{10fff}'),
+  ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'),
+  ('\u{110c2}', '\u{110cc}'), ('\u{110ce}', '\u{110cf}'),
+  ('\u{110e9}', '\u{110ef}'), ('\u{110fa}', '\u{110ff}'),
+  ('\u{11135}', '\u{11135}'), ('\u{11147}', '\u{1114f}'),
+  ('\u{11177}', '\u{1117f}'), ('\u{111ce}', '\u{111cf}'),
+  ('\u{111e0}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'),
+  ('\u{11212}', '\u{11212}'), ('\u{1123f}', '\u{1127f}'),
+  ('\u{11287}', '\u{11287}'), ('\u{11289}', '\u{11289}'),
+  ('\u{1128e}', '\u{1128e}'), ('\u{1129e}', '\u{1129e}'),
+  ('\u{112aa}', '\u{112af}'), ('\u{112eb}', '\u{112ef}'),
+  ('\u{112fa}', '\u{112ff}'), ('\u{11304}', '\u{11304}'),
+  ('\u{1130d}', '\u{1130e}'), ('\u{11311}', '\u{11312}'),
+  ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'),
+  ('\u{11334}', '\u{11334}'), ('\u{1133a}', '\u{1133a}'),
+  ('\u{11345}', '\u{11346}'), ('\u{11349}', '\u{1134a}'),
+  ('\u{1134e}', '\u{1134f}'), ('\u{11351}', '\u{11356}'),
+  ('\u{11358}', '\u{1135c}'), ('\u{11364}', '\u{11365}'),
+  ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{113ff}'),
+  ('\u{1145a}', '\u{1145a}'), ('\u{1145c}', '\u{1145c}'),
+  ('\u{1145f}', '\u{1147f}'), ('\u{114c8}', '\u{114cf}'),
+  ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'),
+  ('\u{115de}', '\u{115ff}'), ('\u{11645}', '\u{1164f}'),
+  ('\u{1165a}', '\u{1165f}'), ('\u{1166d}', '\u{1167f}'),
+  ('\u{116b8}', '\u{116bf}'), ('\u{116ca}', '\u{116ff}'),
+  ('\u{1171b}', '\u{1171c}'), ('\u{1172c}', '\u{1172f}'),
+  ('\u{11740}', '\u{117ff}'), ('\u{1183c}', '\u{1189f}'),
+  ('\u{118f3}', '\u{118fe}'), ('\u{11900}', '\u{119ff}'),
+  ('\u{11a48}', '\u{11a4f}'), ('\u{11a84}', '\u{11a85}'),
+  ('\u{11aa3}', '\u{11abf}'), ('\u{11af9}', '\u{11bff}'),
+  ('\u{11c09}', '\u{11c09}'), ('\u{11c37}', '\u{11c37}'),
+  ('\u{11c46}', '\u{11c4f}'), ('\u{11c6d}', '\u{11c6f}'),
+  ('\u{11c90}', '\u{11c91}'), ('\u{11ca8}', '\u{11ca8}'),
+  ('\u{11cb7}', '\u{11cff}'), ('\u{11d07}', '\u{11d07}'),
+  ('\u{11d0a}', '\u{11d0a}'), ('\u{11d37}', '\u{11d39}'),
+  ('\u{11d3b}', '\u{11d3b}'), ('\u{11d3e}', '\u{11d3e}'),
+  ('\u{11d48}', '\u{11d4f}'), ('\u{11d5a}', '\u{11d5f}'),
+  ('\u{11d66}', '\u{11d66}'), ('\u{11d69}', '\u{11d69}'),
+  ('\u{11d8f}', '\u{11d8f}'), ('\u{11d92}', '\u{11d92}'),
+  ('\u{11d99}', '\u{11d9f}'), ('\u{11daa}', '\u{11edf}'),
+  ('\u{11ef9}', '\u{11fff}'), ('\u{1239a}', '\u{123ff}'),
+  ('\u{1246f}', '\u{1246f}'), ('\u{12475}', '\u{1247f}'),
+  ('\u{12544}', '\u{12fff}'), ('\u{1342f}', '\u{143ff}'),
+  ('\u{14647}', '\u{167ff}'), ('\u{16a39}', '\u{16a3f}'),
+  ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'),
+  ('\u{16a70}', '\u{16acf}'), ('\u{16aee}', '\u{16aef}'),
+  ('\u{16af6}', '\u{16aff}'), ('\u{16b46}', '\u{16b4f}'),
+  ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'),
+  ('\u{16b78}', '\u{16b7c}'), ('\u{16b90}', '\u{16e3f}'),
+  ('\u{16e9b}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'),
+  ('\u{16f7f}', '\u{16f8e}'), ('\u{16fa0}', '\u{16fdf}'),
+  ('\u{16fe2}', '\u{16fff}'), ('\u{187f2}', '\u{187ff}'),
+  ('\u{18af3}', '\u{1afff}'), ('\u{1b11f}', '\u{1b16f}'),
+  ('\u{1b2fc}', '\u{1bbff}'), ('\u{1bc6b}', '\u{1bc6f}'),
+  ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'),
+  ('\u{1bc9a}', '\u{1bc9b}'), ('\u{1bca4}', '\u{1cfff}'),
+  ('\u{1d0f6}', '\u{1d0ff}'), ('\u{1d127}', '\u{1d128}'),
+  ('\u{1d1e9}', '\u{1d1ff}'), ('\u{1d246}', '\u{1d2df}'),
+  ('\u{1d2f4}', '\u{1d2ff}'), ('\u{1d357}', '\u{1d35f}'),
+  ('\u{1d379}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'),
+  ('\u{1d49d}', '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'),
+  ('\u{1d4a3}', '\u{1d4a4}'), ('\u{1d4a7}', '\u{1d4a8}'),
+  ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}', '\u{1d4ba}'),
+  ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'),
+  ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', '\u{1d50c}'),
+  ('\u{1d515}', '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'),
+  ('\u{1d53a}', '\u{1d53a}'), ('\u{1d53f}', '\u{1d53f}'),
+  ('\u{1d545}', '\u{1d545}'), ('\u{1d547}', '\u{1d549}'),
+  ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'),
+  ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1da8c}', '\u{1da9a}'),
+  ('\u{1daa0}', '\u{1daa0}'), ('\u{1dab0}', '\u{1dfff}'),
+  ('\u{1e007}', '\u{1e007}'), ('\u{1e019}', '\u{1e01a}'),
+  ('\u{1e022}', '\u{1e022}'), ('\u{1e025}', '\u{1e025}'),
+  ('\u{1e02b}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'),
+  ('\u{1e8d7}', '\u{1e8ff}'), ('\u{1e94b}', '\u{1e94f}'),
+  ('\u{1e95a}', '\u{1e95d}'), ('\u{1e960}', '\u{1ec70}'),
+  ('\u{1ecb5}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'),
+  ('\u{1ee20}', '\u{1ee20}'), ('\u{1ee23}', '\u{1ee23}'),
+  ('\u{1ee25}', '\u{1ee26}'), ('\u{1ee28}', '\u{1ee28}'),
+  ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}', '\u{1ee38}'),
+  ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', '\u{1ee41}'),
+  ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'),
+  ('\u{1ee4a}', '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'),
+  ('\u{1ee50}', '\u{1ee50}'), ('\u{1ee53}', '\u{1ee53}'),
+  ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}', '\u{1ee58}'),
+  ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'),
+  ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', '\u{1ee60}'),
+  ('\u{1ee63}', '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'),
+  ('\u{1ee6b}', '\u{1ee6b}'), ('\u{1ee73}', '\u{1ee73}'),
+  ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}', '\u{1ee7d}'),
+  ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'),
+  ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'),
+  ('\u{1eeaa}', '\u{1eeaa}'), ('\u{1eebc}', '\u{1eeef}'),
+  ('\u{1eef2}', '\u{1efff}'), ('\u{1f02c}', '\u{1f02f}'),
+  ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}', '\u{1f0b0}'),
+  ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', '\u{1f0d0}'),
+  ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'),
+  ('\u{1f16c}', '\u{1f16f}'), ('\u{1f1ad}', '\u{1f1e5}'),
+  ('\u{1f203}', '\u{1f20f}'), ('\u{1f23c}', '\u{1f23f}'),
+  ('\u{1f249}', '\u{1f24f}'), ('\u{1f252}', '\u{1f25f}'),
+  ('\u{1f266}', '\u{1f2ff}'), ('\u{1f6d5}', '\u{1f6df}'),
+  ('\u{1f6ed}', '\u{1f6ef}'), ('\u{1f6fa}', '\u{1f6ff}'),
+  ('\u{1f774}', '\u{1f77f}'), ('\u{1f7d9}', '\u{1f7ff}'),
+  ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}', '\u{1f84f}'),
+  ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', '\u{1f88f}'),
+  ('\u{1f8ae}', '\u{1f8ff}'), ('\u{1f90c}', '\u{1f90f}'),
+  ('\u{1f93f}', '\u{1f93f}'), ('\u{1f971}', '\u{1f972}'),
+  ('\u{1f977}', '\u{1f979}'), ('\u{1f97b}', '\u{1f97b}'),
+  ('\u{1f9a3}', '\u{1f9af}'), ('\u{1f9ba}', '\u{1f9bf}'),
+  ('\u{1f9c3}', '\u{1f9cf}'), ('\u{1fa00}', '\u{1fa5f}'),
+  ('\u{1fa6e}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'),
+  ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2b81f}'),
+  ('\u{2cea2}', '\u{2ceaf}'), ('\u{2ebe1}', '\u{2f7ff}'),
+  ('\u{2fa1e}', '\u{e0000}'), ('\u{e0002}', '\u{e001f}'),
+  ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{effff}'),
+  ('\u{ffffe}', '\u{fffff}'), ('\u{10fffe}', '\u{10ffff}'),
+];
+
+pub const UPPERCASE_LETTER: &'static [(char, char)] = &[
+  ('A', 'Z'), ('À', 'Ö'), ('Ø', 'Þ'), ('Ā', 'Ā'), ('Ă', 'Ă'),
+  ('Ą', 'Ą'), ('Ć', 'Ć'), ('Ĉ', 'Ĉ'), ('Ċ', 'Ċ'), ('Č', 'Č'),
+  ('Ď', 'Ď'), ('Đ', 'Đ'), ('Ē', 'Ē'), ('Ĕ', 'Ĕ'), ('Ė', 'Ė'),
+  ('Ę', 'Ę'), ('Ě', 'Ě'), ('Ĝ', 'Ĝ'), ('Ğ', 'Ğ'), ('Ġ', 'Ġ'),
+  ('Ģ', 'Ģ'), ('Ĥ', 'Ĥ'), ('Ħ', 'Ħ'), ('Ĩ', 'Ĩ'), ('Ī', 'Ī'),
+  ('Ĭ', 'Ĭ'), ('Į', 'Į'), ('İ', 'İ'), ('Ĳ', 'Ĳ'), ('Ĵ', 'Ĵ'),
+  ('Ķ', 'Ķ'), ('Ĺ', 'Ĺ'), ('Ļ', 'Ļ'), ('Ľ', 'Ľ'), ('Ŀ', 'Ŀ'),
+  ('Ł', 'Ł'), ('Ń', 'Ń'), ('Ņ', 'Ņ'), ('Ň', 'Ň'), ('Ŋ', 'Ŋ'),
+  ('Ō', 'Ō'), ('Ŏ', 'Ŏ'), ('Ő', 'Ő'), ('Œ', 'Œ'), ('Ŕ', 'Ŕ'),
+  ('Ŗ', 'Ŗ'), ('Ř', 'Ř'), ('Ś', 'Ś'), ('Ŝ', 'Ŝ'), ('Ş', 'Ş'),
+  ('Š', 'Š'), ('Ţ', 'Ţ'), ('Ť', 'Ť'), ('Ŧ', 'Ŧ'), ('Ũ', 'Ũ'),
+  ('Ū', 'Ū'), ('Ŭ', 'Ŭ'), ('Ů', 'Ů'), ('Ű', 'Ű'), ('Ų', 'Ų'),
+  ('Ŵ', 'Ŵ'), ('Ŷ', 'Ŷ'), ('Ÿ', 'Ź'), ('Ż', 'Ż'), ('Ž', 'Ž'),
+  ('Ɓ', 'Ƃ'), ('Ƅ', 'Ƅ'), ('Ɔ', 'Ƈ'), ('Ɖ', 'Ƌ'), ('Ǝ', 'Ƒ'),
+  ('Ɠ', 'Ɣ'), ('Ɩ', 'Ƙ'), ('Ɯ', 'Ɲ'), ('Ɵ', 'Ơ'), ('Ƣ', 'Ƣ'),
+  ('Ƥ', 'Ƥ'), ('Ʀ', 'Ƨ'), ('Ʃ', 'Ʃ'), ('Ƭ', 'Ƭ'), ('Ʈ', 'Ư'),
+  ('Ʊ', 'Ƴ'), ('Ƶ', 'Ƶ'), ('Ʒ', 'Ƹ'), ('Ƽ', 'Ƽ'), ('Ǆ', 'Ǆ'),
+  ('Ǉ', 'Ǉ'), ('Ǌ', 'Ǌ'), ('Ǎ', 'Ǎ'), ('Ǐ', 'Ǐ'), ('Ǒ', 'Ǒ'),
+  ('Ǔ', 'Ǔ'), ('Ǖ', 'Ǖ'), ('Ǘ', 'Ǘ'), ('Ǚ', 'Ǚ'), ('Ǜ', 'Ǜ'),
+  ('Ǟ', 'Ǟ'), ('Ǡ', 'Ǡ'), ('Ǣ', 'Ǣ'), ('Ǥ', 'Ǥ'), ('Ǧ', 'Ǧ'),
+  ('Ǩ', 'Ǩ'), ('Ǫ', 'Ǫ'), ('Ǭ', 'Ǭ'), ('Ǯ', 'Ǯ'), ('Ǳ', 'Ǳ'),
+  ('Ǵ', 'Ǵ'), ('Ƕ', 'Ǹ'), ('Ǻ', 'Ǻ'), ('Ǽ', 'Ǽ'), ('Ǿ', 'Ǿ'),
+  ('Ȁ', 'Ȁ'), ('Ȃ', 'Ȃ'), ('Ȅ', 'Ȅ'), ('Ȇ', 'Ȇ'), ('Ȉ', 'Ȉ'),
+  ('Ȋ', 'Ȋ'), ('Ȍ', 'Ȍ'), ('Ȏ', 'Ȏ'), ('Ȑ', 'Ȑ'), ('Ȓ', 'Ȓ'),
+  ('Ȕ', 'Ȕ'), ('Ȗ', 'Ȗ'), ('Ș', 'Ș'), ('Ț', 'Ț'), ('Ȝ', 'Ȝ'),
+  ('Ȟ', 'Ȟ'), ('Ƞ', 'Ƞ'), ('Ȣ', 'Ȣ'), ('Ȥ', 'Ȥ'), ('Ȧ', 'Ȧ'),
+  ('Ȩ', 'Ȩ'), ('Ȫ', 'Ȫ'), ('Ȭ', 'Ȭ'), ('Ȯ', 'Ȯ'), ('Ȱ', 'Ȱ'),
+  ('Ȳ', 'Ȳ'), ('Ⱥ', 'Ȼ'), ('Ƚ', 'Ⱦ'), ('Ɂ', 'Ɂ'), ('Ƀ', 'Ɇ'),
+  ('Ɉ', 'Ɉ'), ('Ɋ', 'Ɋ'), ('Ɍ', 'Ɍ'), ('Ɏ', 'Ɏ'), ('Ͱ', 'Ͱ'),
+  ('Ͳ', 'Ͳ'), ('Ͷ', 'Ͷ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'),
+  ('Ό', 'Ό'), ('Ύ', 'Ώ'), ('Α', 'Ρ'), ('Σ', 'Ϋ'), ('Ϗ', 'Ϗ'),
+  ('ϒ', 'ϔ'), ('Ϙ', 'Ϙ'), ('Ϛ', 'Ϛ'), ('Ϝ', 'Ϝ'), ('Ϟ', 'Ϟ'),
+  ('Ϡ', 'Ϡ'), ('Ϣ', 'Ϣ'), ('Ϥ', 'Ϥ'), ('Ϧ', 'Ϧ'), ('Ϩ', 'Ϩ'),
+  ('Ϫ', 'Ϫ'), ('Ϭ', 'Ϭ'), ('Ϯ', 'Ϯ'), ('ϴ', 'ϴ'), ('Ϸ', 'Ϸ'),
+  ('Ϲ', 'Ϻ'), ('Ͻ', 'Я'), ('Ѡ', 'Ѡ'), ('Ѣ', 'Ѣ'), ('Ѥ', 'Ѥ'),
+  ('Ѧ', 'Ѧ'), ('Ѩ', 'Ѩ'), ('Ѫ', 'Ѫ'), ('Ѭ', 'Ѭ'), ('Ѯ', 'Ѯ'),
+  ('Ѱ', 'Ѱ'), ('Ѳ', 'Ѳ'), ('Ѵ', 'Ѵ'), ('Ѷ', 'Ѷ'), ('Ѹ', 'Ѹ'),
+  ('Ѻ', 'Ѻ'), ('Ѽ', 'Ѽ'), ('Ѿ', 'Ѿ'), ('Ҁ', 'Ҁ'), ('Ҋ', 'Ҋ'),
+  ('Ҍ', 'Ҍ'), ('Ҏ', 'Ҏ'), ('Ґ', 'Ґ'), ('Ғ', 'Ғ'), ('Ҕ', 'Ҕ'),
+  ('Җ', 'Җ'), ('Ҙ', 'Ҙ'), ('Қ', 'Қ'), ('Ҝ', 'Ҝ'), ('Ҟ', 'Ҟ'),
+  ('Ҡ', 'Ҡ'), ('Ң', 'Ң'), ('Ҥ', 'Ҥ'), ('Ҧ', 'Ҧ'), ('Ҩ', 'Ҩ'),
+  ('Ҫ', 'Ҫ'), ('Ҭ', 'Ҭ'), ('Ү', 'Ү'), ('Ұ', 'Ұ'), ('Ҳ', 'Ҳ'),
+  ('Ҵ', 'Ҵ'), ('Ҷ', 'Ҷ'), ('Ҹ', 'Ҹ'), ('Һ', 'Һ'), ('Ҽ', 'Ҽ'),
+  ('Ҿ', 'Ҿ'), ('Ӏ', 'Ӂ'), ('Ӄ', 'Ӄ'), ('Ӆ', 'Ӆ'), ('Ӈ', 'Ӈ'),
+  ('Ӊ', 'Ӊ'), ('Ӌ', 'Ӌ'), ('Ӎ', 'Ӎ'), ('Ӑ', 'Ӑ'), ('Ӓ', 'Ӓ'),
+  ('Ӕ', 'Ӕ'), ('Ӗ', 'Ӗ'), ('Ә', 'Ә'), ('Ӛ', 'Ӛ'), ('Ӝ', 'Ӝ'),
+  ('Ӟ', 'Ӟ'), ('Ӡ', 'Ӡ'), ('Ӣ', 'Ӣ'), ('Ӥ', 'Ӥ'), ('Ӧ', 'Ӧ'),
+  ('Ө', 'Ө'), ('Ӫ', 'Ӫ'), ('Ӭ', 'Ӭ'), ('Ӯ', 'Ӯ'), ('Ӱ', 'Ӱ'),
+  ('Ӳ', 'Ӳ'), ('Ӵ', 'Ӵ'), ('Ӷ', 'Ӷ'), ('Ӹ', 'Ӹ'), ('Ӻ', 'Ӻ'),
+  ('Ӽ', 'Ӽ'), ('Ӿ', 'Ӿ'), ('Ԁ', 'Ԁ'), ('Ԃ', 'Ԃ'), ('Ԅ', 'Ԅ'),
+  ('Ԇ', 'Ԇ'), ('Ԉ', 'Ԉ'), ('Ԋ', 'Ԋ'), ('Ԍ', 'Ԍ'), ('Ԏ', 'Ԏ'),
+  ('Ԑ', 'Ԑ'), ('Ԓ', 'Ԓ'), ('Ԕ', 'Ԕ'), ('Ԗ', 'Ԗ'), ('Ԙ', 'Ԙ'),
+  ('Ԛ', 'Ԛ'), ('Ԝ', 'Ԝ'), ('Ԟ', 'Ԟ'), ('Ԡ', 'Ԡ'), ('Ԣ', 'Ԣ'),
+  ('Ԥ', 'Ԥ'), ('Ԧ', 'Ԧ'), ('Ԩ', 'Ԩ'), ('Ԫ', 'Ԫ'), ('Ԭ', 'Ԭ'),
+  ('Ԯ', 'Ԯ'), ('Ա', 'Ֆ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('Ꭰ', 'Ᏽ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('Ḁ', 'Ḁ'), ('Ḃ', 'Ḃ'), ('Ḅ', 'Ḅ'), ('Ḇ', 'Ḇ'),
+  ('Ḉ', 'Ḉ'), ('Ḋ', 'Ḋ'), ('Ḍ', 'Ḍ'), ('Ḏ', 'Ḏ'),
+  ('Ḑ', 'Ḑ'), ('Ḓ', 'Ḓ'), ('Ḕ', 'Ḕ'), ('Ḗ', 'Ḗ'),
+  ('Ḙ', 'Ḙ'), ('Ḛ', 'Ḛ'), ('Ḝ', 'Ḝ'), ('Ḟ', 'Ḟ'),
+  ('Ḡ', 'Ḡ'), ('Ḣ', 'Ḣ'), ('Ḥ', 'Ḥ'), ('Ḧ', 'Ḧ'),
+  ('Ḩ', 'Ḩ'), ('Ḫ', 'Ḫ'), ('Ḭ', 'Ḭ'), ('Ḯ', 'Ḯ'),
+  ('Ḱ', 'Ḱ'), ('Ḳ', 'Ḳ'), ('Ḵ', 'Ḵ'), ('Ḷ', 'Ḷ'),
+  ('Ḹ', 'Ḹ'), ('Ḻ', 'Ḻ'), ('Ḽ', 'Ḽ'), ('Ḿ', 'Ḿ'),
+  ('Ṁ', 'Ṁ'), ('Ṃ', 'Ṃ'), ('Ṅ', 'Ṅ'), ('Ṇ', 'Ṇ'),
+  ('Ṉ', 'Ṉ'), ('Ṋ', 'Ṋ'), ('Ṍ', 'Ṍ'), ('Ṏ', 'Ṏ'),
+  ('Ṑ', 'Ṑ'), ('Ṓ', 'Ṓ'), ('Ṕ', 'Ṕ'), ('Ṗ', 'Ṗ'),
+  ('Ṙ', 'Ṙ'), ('Ṛ', 'Ṛ'), ('Ṝ', 'Ṝ'), ('Ṟ', 'Ṟ'),
+  ('Ṡ', 'Ṡ'), ('Ṣ', 'Ṣ'), ('Ṥ', 'Ṥ'), ('Ṧ', 'Ṧ'),
+  ('Ṩ', 'Ṩ'), ('Ṫ', 'Ṫ'), ('Ṭ', 'Ṭ'), ('Ṯ', 'Ṯ'),
+  ('Ṱ', 'Ṱ'), ('Ṳ', 'Ṳ'), ('Ṵ', 'Ṵ'), ('Ṷ', 'Ṷ'),
+  ('Ṹ', 'Ṹ'), ('Ṻ', 'Ṻ'), ('Ṽ', 'Ṽ'), ('Ṿ', 'Ṿ'),
+  ('Ẁ', 'Ẁ'), ('Ẃ', 'Ẃ'), ('Ẅ', 'Ẅ'), ('Ẇ', 'Ẇ'),
+  ('Ẉ', 'Ẉ'), ('Ẋ', 'Ẋ'), ('Ẍ', 'Ẍ'), ('Ẏ', 'Ẏ'),
+  ('Ẑ', 'Ẑ'), ('Ẓ', 'Ẓ'), ('Ẕ', 'Ẕ'), ('ẞ', 'ẞ'),
+  ('Ạ', 'Ạ'), ('Ả', 'Ả'), ('Ấ', 'Ấ'), ('Ầ', 'Ầ'),
+  ('Ẩ', 'Ẩ'), ('Ẫ', 'Ẫ'), ('Ậ', 'Ậ'), ('Ắ', 'Ắ'),
+  ('Ằ', 'Ằ'), ('Ẳ', 'Ẳ'), ('Ẵ', 'Ẵ'), ('Ặ', 'Ặ'),
+  ('Ẹ', 'Ẹ'), ('Ẻ', 'Ẻ'), ('Ẽ', 'Ẽ'), ('Ế', 'Ế'),
+  ('Ề', 'Ề'), ('Ể', 'Ể'), ('Ễ', 'Ễ'), ('Ệ', 'Ệ'),
+  ('Ỉ', 'Ỉ'), ('Ị', 'Ị'), ('Ọ', 'Ọ'), ('Ỏ', 'Ỏ'),
+  ('Ố', 'Ố'), ('Ồ', 'Ồ'), ('Ổ', 'Ổ'), ('Ỗ', 'Ỗ'),
+  ('Ộ', 'Ộ'), ('Ớ', 'Ớ'), ('Ờ', 'Ờ'), ('Ở', 'Ở'),
+  ('Ỡ', 'Ỡ'), ('Ợ', 'Ợ'), ('Ụ', 'Ụ'), ('Ủ', 'Ủ'),
+  ('Ứ', 'Ứ'), ('Ừ', 'Ừ'), ('Ử', 'Ử'), ('Ữ', 'Ữ'),
+  ('Ự', 'Ự'), ('Ỳ', 'Ỳ'), ('Ỵ', 'Ỵ'), ('Ỷ', 'Ỷ'),
+  ('Ỹ', 'Ỹ'), ('Ỻ', 'Ỻ'), ('Ỽ', 'Ỽ'), ('Ỿ', 'Ỿ'),
+  ('Ἀ', 'Ἇ'), ('Ἐ', 'Ἕ'), ('Ἠ', 'Ἧ'), ('Ἰ', 'Ἷ'),
+  ('Ὀ', 'Ὅ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'Ὗ'), ('Ὠ', 'Ὧ'), ('Ᾰ', 'Ά'), ('Ὲ', 'Ή'),
+  ('Ῐ', 'Ί'), ('Ῠ', 'Ῥ'), ('Ὸ', 'Ώ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℋ', 'ℍ'), ('ℐ', 'ℒ'), ('ℕ', 'ℕ'),
+  ('ℙ', 'ℝ'), ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'),
+  ('K', 'ℭ'), ('ℰ', 'ℳ'), ('ℾ', 'ℿ'), ('ⅅ', 'ⅅ'),
+  ('Ↄ', 'Ↄ'), ('Ⰰ', 'Ⱞ'), ('Ⱡ', 'Ⱡ'), ('Ɫ', 'Ɽ'),
+  ('Ⱨ', 'Ⱨ'), ('Ⱪ', 'Ⱪ'), ('Ⱬ', 'Ⱬ'), ('Ɑ', 'Ɒ'),
+  ('Ⱳ', 'Ⱳ'), ('Ⱶ', 'Ⱶ'), ('Ȿ', 'Ⲁ'), ('Ⲃ', 'Ⲃ'),
+  ('Ⲅ', 'Ⲅ'), ('Ⲇ', 'Ⲇ'), ('Ⲉ', 'Ⲉ'), ('Ⲋ', 'Ⲋ'),
+  ('Ⲍ', 'Ⲍ'), ('Ⲏ', 'Ⲏ'), ('Ⲑ', 'Ⲑ'), ('Ⲓ', 'Ⲓ'),
+  ('Ⲕ', 'Ⲕ'), ('Ⲗ', 'Ⲗ'), ('Ⲙ', 'Ⲙ'), ('Ⲛ', 'Ⲛ'),
+  ('Ⲝ', 'Ⲝ'), ('Ⲟ', 'Ⲟ'), ('Ⲡ', 'Ⲡ'), ('Ⲣ', 'Ⲣ'),
+  ('Ⲥ', 'Ⲥ'), ('Ⲧ', 'Ⲧ'), ('Ⲩ', 'Ⲩ'), ('Ⲫ', 'Ⲫ'),
+  ('Ⲭ', 'Ⲭ'), ('Ⲯ', 'Ⲯ'), ('Ⲱ', 'Ⲱ'), ('Ⲳ', 'Ⲳ'),
+  ('Ⲵ', 'Ⲵ'), ('Ⲷ', 'Ⲷ'), ('Ⲹ', 'Ⲹ'), ('Ⲻ', 'Ⲻ'),
+  ('Ⲽ', 'Ⲽ'), ('Ⲿ', 'Ⲿ'), ('Ⳁ', 'Ⳁ'), ('Ⳃ', 'Ⳃ'),
+  ('Ⳅ', 'Ⳅ'), ('Ⳇ', 'Ⳇ'), ('Ⳉ', 'Ⳉ'), ('Ⳋ', 'Ⳋ'),
+  ('Ⳍ', 'Ⳍ'), ('Ⳏ', 'Ⳏ'), ('Ⳑ', 'Ⳑ'), ('Ⳓ', 'Ⳓ'),
+  ('Ⳕ', 'Ⳕ'), ('Ⳗ', 'Ⳗ'), ('Ⳙ', 'Ⳙ'), ('Ⳛ', 'Ⳛ'),
+  ('Ⳝ', 'Ⳝ'), ('Ⳟ', 'Ⳟ'), ('Ⳡ', 'Ⳡ'), ('Ⳣ', 'Ⳣ'),
+  ('Ⳬ', 'Ⳬ'), ('Ⳮ', 'Ⳮ'), ('Ⳳ', 'Ⳳ'), ('Ꙁ', 'Ꙁ'),
+  ('Ꙃ', 'Ꙃ'), ('Ꙅ', 'Ꙅ'), ('Ꙇ', 'Ꙇ'), ('Ꙉ', 'Ꙉ'),
+  ('Ꙋ', 'Ꙋ'), ('Ꙍ', 'Ꙍ'), ('Ꙏ', 'Ꙏ'), ('Ꙑ', 'Ꙑ'),
+  ('Ꙓ', 'Ꙓ'), ('Ꙕ', 'Ꙕ'), ('Ꙗ', 'Ꙗ'), ('Ꙙ', 'Ꙙ'),
+  ('Ꙛ', 'Ꙛ'), ('Ꙝ', 'Ꙝ'), ('Ꙟ', 'Ꙟ'), ('Ꙡ', 'Ꙡ'),
+  ('Ꙣ', 'Ꙣ'), ('Ꙥ', 'Ꙥ'), ('Ꙧ', 'Ꙧ'), ('Ꙩ', 'Ꙩ'),
+  ('Ꙫ', 'Ꙫ'), ('Ꙭ', 'Ꙭ'), ('Ꚁ', 'Ꚁ'), ('Ꚃ', 'Ꚃ'),
+  ('Ꚅ', 'Ꚅ'), ('Ꚇ', 'Ꚇ'), ('Ꚉ', 'Ꚉ'), ('Ꚋ', 'Ꚋ'),
+  ('Ꚍ', 'Ꚍ'), ('Ꚏ', 'Ꚏ'), ('Ꚑ', 'Ꚑ'), ('Ꚓ', 'Ꚓ'),
+  ('Ꚕ', 'Ꚕ'), ('Ꚗ', 'Ꚗ'), ('Ꚙ', 'Ꚙ'), ('Ꚛ', 'Ꚛ'),
+  ('Ꜣ', 'Ꜣ'), ('Ꜥ', 'Ꜥ'), ('Ꜧ', 'Ꜧ'), ('Ꜩ', 'Ꜩ'),
+  ('Ꜫ', 'Ꜫ'), ('Ꜭ', 'Ꜭ'), ('Ꜯ', 'Ꜯ'), ('Ꜳ', 'Ꜳ'),
+  ('Ꜵ', 'Ꜵ'), ('Ꜷ', 'Ꜷ'), ('Ꜹ', 'Ꜹ'), ('Ꜻ', 'Ꜻ'),
+  ('Ꜽ', 'Ꜽ'), ('Ꜿ', 'Ꜿ'), ('Ꝁ', 'Ꝁ'), ('Ꝃ', 'Ꝃ'),
+  ('Ꝅ', 'Ꝅ'), ('Ꝇ', 'Ꝇ'), ('Ꝉ', 'Ꝉ'), ('Ꝋ', 'Ꝋ'),
+  ('Ꝍ', 'Ꝍ'), ('Ꝏ', 'Ꝏ'), ('Ꝑ', 'Ꝑ'), ('Ꝓ', 'Ꝓ'),
+  ('Ꝕ', 'Ꝕ'), ('Ꝗ', 'Ꝗ'), ('Ꝙ', 'Ꝙ'), ('Ꝛ', 'Ꝛ'),
+  ('Ꝝ', 'Ꝝ'), ('Ꝟ', 'Ꝟ'), ('Ꝡ', 'Ꝡ'), ('Ꝣ', 'Ꝣ'),
+  ('Ꝥ', 'Ꝥ'), ('Ꝧ', 'Ꝧ'), ('Ꝩ', 'Ꝩ'), ('Ꝫ', 'Ꝫ'),
+  ('Ꝭ', 'Ꝭ'), ('Ꝯ', 'Ꝯ'), ('Ꝺ', 'Ꝺ'), ('Ꝼ', 'Ꝼ'),
+  ('Ᵹ', 'Ꝿ'), ('Ꞁ', 'Ꞁ'), ('Ꞃ', 'Ꞃ'), ('Ꞅ', 'Ꞅ'),
+  ('Ꞇ', 'Ꞇ'), ('Ꞌ', 'Ꞌ'), ('Ɥ', 'Ɥ'), ('Ꞑ', 'Ꞑ'),
+  ('Ꞓ', 'Ꞓ'), ('Ꞗ', 'Ꞗ'), ('Ꞙ', 'Ꞙ'), ('Ꞛ', 'Ꞛ'),
+  ('Ꞝ', 'Ꞝ'), ('Ꞟ', 'Ꞟ'), ('Ꞡ', 'Ꞡ'), ('Ꞣ', 'Ꞣ'),
+  ('Ꞥ', 'Ꞥ'), ('Ꞧ', 'Ꞧ'), ('Ꞩ', 'Ꞩ'), ('Ɦ', 'Ɪ'),
+  ('Ʞ', 'Ꞵ'), ('Ꞷ', 'Ꞷ'), ('\u{a7b8}', '\u{a7b8}'), ('Ａ', 'Ｚ'),
+  ('𐐀', '𐐧'), ('𐒰', '𐓓'), ('𐲀', '𐲲'), ('𑢠', '𑢿'),
+  ('\u{16e40}', '\u{16e5f}'), ('𝐀', '𝐙'), ('𝐴', '𝑍'),
+  ('𝑨', '𝒁'), ('𝒜', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'),
+  ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒵'), ('𝓐', '𝓩'),
+  ('𝔄', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔸', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕬', '𝖅'), ('𝖠', '𝖹'), ('𝗔', '𝗭'),
+  ('𝘈', '𝘡'), ('𝘼', '𝙕'), ('𝙰', '𝚉'), ('𝚨', '𝛀'),
+  ('𝛢', '𝛺'), ('𝜜', '𝜴'), ('𝝖', '𝝮'), ('𝞐', '𝞨'),
+  ('𝟊', '𝟊'), ('𞤀', '𞤡'),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/mod.rs b/third_party/rust/regex-syntax/src/unicode_tables/mod.rs
new file mode 100644
index 000000000000..6c2e9e7736eb
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/mod.rs
@@ -0,0 +1,9 @@
+pub mod age;
+pub mod case_folding_simple;
+pub mod general_category;
+pub mod perl_word;
+pub mod property_bool;
+pub mod property_names;
+pub mod property_values;
+pub mod script_extension;
+pub mod script;
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/perl_word.rs b/third_party/rust/regex-syntax/src/unicode_tables/perl_word.rs
new file mode 100644
index 000000000000..336a71702e54
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/perl_word.rs
@@ -0,0 +1,188 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate perl-word tmp/ucd-11.0.0/ --chars
+//
+// ucd-generate is available on crates.io.
+
+pub const PERL_WORD: &'static [(char, char)] = &[
+  ('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'),
+  ('º', 'º'), ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'), ('ˆ', 'ˑ'),
+  ('ˠ', 'ˤ'), ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('̀', 'ʹ'), ('Ͷ', 'ͷ'),
+  ('ͺ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'),
+  ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('҃', 'ԯ'), ('Ա', 'Ֆ'),
+  ('ՙ', 'ՙ'), ('\u{560}', '\u{588}'), ('֑', 'ֽ'), ('ֿ', 'ֿ'),
+  ('ׁ', 'ׂ'), ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('א', 'ת'), ('\u{5ef}', 'ײ'),
+  ('ؐ', 'ؚ'), ('ؠ', '٩'), ('ٮ', 'ۓ'), ('ە', 'ۜ'), ('۟', 'ۨ'),
+  ('۪', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', '݊'), ('ݍ', 'ޱ'), ('߀', 'ߵ'),
+  ('ߺ', 'ߺ'), ('\u{7fd}', '\u{7fd}'), ('ࠀ', '࠭'), ('ࡀ', '࡛'),
+  ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'), ('\u{8d3}', '࣡'),
+  ('ࣣ', 'ॣ'), ('०', '९'), ('ॱ', 'ঃ'), ('অ', 'ঌ'),
+  ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'), ('ল', 'ল'),
+  ('শ', 'হ'), ('়', 'ৄ'), ('ে', 'ৈ'), ('ো', 'ৎ'),
+  ('ৗ', 'ৗ'), ('ড়', 'ঢ়'), ('য়', 'ৣ'), ('০', 'ৱ'),
+  ('ৼ', 'ৼ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਃ'), ('ਅ', 'ਊ'),
+  ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'), ('ਲ', 'ਲ਼'),
+  ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('਼', '਼'), ('ਾ', 'ੂ'),
+  ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ੑ', 'ੑ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('੦', 'ੵ'), ('ઁ', 'ઃ'), ('અ', 'ઍ'),
+  ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'),
+  ('વ', 'હ'), ('઼', 'ૅ'), ('ે', 'ૉ'), ('ો', '્'),
+  ('ૐ', 'ૐ'), ('ૠ', 'ૣ'), ('૦', '૯'), ('ૹ', '૿'),
+  ('ଁ', 'ଃ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'),
+  ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('଼', 'ୄ'),
+  ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୣ'), ('୦', '୯'), ('ୱ', 'ୱ'), ('ஂ', 'ஃ'),
+  ('அ', 'ஊ'), ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'),
+  ('ஜ', 'ஜ'), ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'),
+  ('ம', 'ஹ'), ('ா', 'ூ'), ('ெ', 'ை'), ('ொ', '்'),
+  ('ௐ', 'ௐ'), ('ௗ', 'ௗ'), ('௦', '௯'), ('ఀ', 'ఌ'),
+  ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'హ'), ('ఽ', 'ౄ'),
+  ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'), ('ౘ', 'ౚ'),
+  ('ౠ', 'ౣ'), ('౦', '౯'), ('ಀ', 'ಃ'), ('ಅ', 'ಌ'),
+  ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'), ('ವ', 'ಹ'),
+  ('಼', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', '್'), ('ೕ', 'ೖ'),
+  ('ೞ', 'ೞ'), ('ೠ', 'ೣ'), ('೦', '೯'), ('ೱ', 'ೲ'),
+  ('ഀ', 'ഃ'), ('അ', 'ഌ'), ('എ', 'ഐ'), ('ഒ', 'ൄ'),
+  ('െ', 'ൈ'), ('ൊ', 'ൎ'), ('ൔ', 'ൗ'), ('ൟ', 'ൣ'),
+  ('൦', '൯'), ('ൺ', 'ൿ'), ('ං', 'ඃ'), ('අ', 'ඖ'),
+  ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'),
+  ('්', '්'), ('ා', 'ු'), ('ූ', 'ූ'), ('ෘ', 'ෟ'),
+  ('෦', '෯'), ('ෲ', 'ෳ'), ('ก', 'ฺ'), ('เ', '๎'),
+  ('๐', '๙'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'),
+  ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'),
+  ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'),
+  ('ອ', 'ູ'), ('ົ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'),
+  ('່', 'ໍ'), ('໐', '໙'), ('ໜ', 'ໟ'), ('ༀ', 'ༀ'),
+  ('༘', '༙'), ('༠', '༩'), ('༵', '༵'), ('༷', '༷'),
+  ('༹', '༹'), ('༾', 'ཇ'), ('ཉ', 'ཬ'), ('ཱ', '྄'),
+  ('྆', 'ྗ'), ('ྙ', 'ྼ'), ('࿆', '࿆'), ('က', '၉'),
+  ('ၐ', 'ႝ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('ა', 'ჺ'), ('ჼ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'),
+  ('ቘ', 'ቘ'), ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'),
+  ('ነ', 'ኰ'), ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'),
+  ('ዂ', 'ዅ'), ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'),
+  ('ጘ', 'ፚ'), ('፝', '፟'), ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'),
+  ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'), ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'),
+  ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'), ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'),
+  ('ᜠ', '᜴'), ('ᝀ', 'ᝓ'), ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'),
+  ('ᝲ', 'ᝳ'), ('ក', '៓'), ('ៗ', 'ៗ'), ('ៜ', '៝'),
+  ('០', '៩'), ('᠋', '᠍'), ('᠐', '᠙'), ('ᠠ', '\u{1878}'),
+  ('ᢀ', 'ᢪ'), ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'),
+  ('ᤰ', '᤻'), ('᥆', 'ᥭ'), ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'),
+  ('ᦰ', 'ᧉ'), ('᧐', '᧙'), ('ᨀ', 'ᨛ'), ('ᨠ', 'ᩞ'),
+  ('᩠', '᩼'), ('᩿', '᪉'), ('᪐', '᪙'), ('ᪧ', 'ᪧ'),
+  ('᪰', '᪾'), ('ᬀ', 'ᭋ'), ('᭐', '᭙'), ('᭫', '᭳'),
+  ('ᮀ', '᯳'), ('ᰀ', '᰷'), ('᱀', '᱉'), ('ᱍ', 'ᱽ'),
+  ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('᳐', '᳒'), ('᳔', '᳹'), ('ᴀ', '᷹'), ('᷻', 'ἕ'),
+  ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'),
+  ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'),
+  ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'), ('ῂ', 'ῄ'),
+  ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'), ('ῠ', 'Ῥ'),
+  ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('\u{200c}', '\u{200d}'), ('‿', '⁀'),
+  ('⁔', '⁔'), ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'),
+  ('⃐', '⃰'), ('ℂ', 'ℂ'), ('ℇ', 'ℇ'), ('ℊ', 'ℓ'),
+  ('ℕ', 'ℕ'), ('ℙ', 'ℝ'), ('ℤ', 'ℤ'), ('Ω', 'Ω'),
+  ('ℨ', 'ℨ'), ('K', 'ℭ'), ('ℯ', 'ℹ'), ('ℼ', 'ℿ'),
+  ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'), ('Ⓐ', 'ⓩ'),
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'), ('Ⳬ', 'ⳳ'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ⴰ', 'ⵧ'),
+  ('ⵯ', 'ⵯ'), ('⵿', 'ⶖ'), ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'),
+  ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'),
+  ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('ⷠ', 'ⷿ'), ('ⸯ', 'ⸯ'),
+  ('々', '〇'), ('〡', '〯'), ('〱', '〵'), ('〸', '〼'),
+  ('ぁ', 'ゖ'), ('゙', '゚'), ('ゝ', 'ゟ'), ('ァ', 'ヺ'),
+  ('ー', 'ヿ'), ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'),
+  ('ㇰ', 'ㇿ'), ('㐀', '䶵'), ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'),
+  ('ꓐ', 'ꓽ'), ('ꔀ', 'ꘌ'), ('ꘐ', 'ꘫ'), ('Ꙁ', '꙲'),
+  ('ꙴ', '꙽'), ('ꙿ', '꛱'), ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'),
+  ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꠧ'), ('ꡀ', 'ꡳ'), ('ꢀ', 'ꣅ'),
+  ('꣐', '꣙'), ('꣠', 'ꣷ'), ('ꣻ', 'ꣻ'), ('ꣽ', '꤭'),
+  ('ꤰ', '꥓'), ('ꥠ', 'ꥼ'), ('ꦀ', '꧀'), ('ꧏ', '꧙'),
+  ('ꧠ', 'ꧾ'), ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'), ('꩐', '꩙'),
+  ('ꩠ', 'ꩶ'), ('ꩺ', 'ꫂ'), ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫯ'),
+  ('ꫲ', '꫶'), ('ꬁ', 'ꬆ'), ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'),
+  ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'), ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'),
+  ('ꭰ', 'ꯪ'), ('꯬', '꯭'), ('꯰', '꯹'), ('가', '힣'),
+  ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'), ('並', '龎'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'ﬨ'), ('שׁ', 'זּ'),
+  ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'), ('ףּ', 'פּ'),
+  ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'), ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'),
+  ('ﷰ', 'ﷻ'), ('︀', '️'), ('︠', '︯'), ('︳', '︴'),
+  ('﹍', '﹏'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'), ('０', '９'),
+  ('Ａ', 'Ｚ'), ('＿', '＿'), ('ａ', 'ｚ'), ('ｦ', 'ﾾ'),
+  ('ￂ', 'ￇ'), ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'),
+  ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'),
+  ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐅀', '𐅴'),
+  ('𐇽', '𐇽'), ('𐊀', '𐊜'), ('𐊠', '𐋐'), ('𐋠', '𐋠'),
+  ('𐌀', '𐌟'), ('𐌭', '𐍊'), ('𐍐', '𐍺'), ('𐎀', '𐎝'),
+  ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐏑', '𐏕'), ('𐐀', '𐒝'),
+  ('𐒠', '𐒩'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'),
+  ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+  ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'),
+  ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'), ('𐢀', '𐢞'),
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'), ('𐤠', '𐤹'),
+  ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨃'), ('𐨅', '𐨆'),
+  ('𐨌', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'), ('𐨸', '𐨺'),
+  ('𐨿', '𐨿'), ('𐩠', '𐩼'), ('𐪀', '𐪜'), ('𐫀', '𐫇'),
+  ('𐫉', '𐫦'), ('𐬀', '𐬵'), ('𐭀', '𐭕'), ('𐭠', '𐭲'),
+  ('𐮀', '𐮑'), ('𐰀', '𐱈'), ('𐲀', '𐲲'), ('𐳀', '𐳲'),
+  ('\u{10d00}', '\u{10d27}'), ('\u{10d30}', '\u{10d39}'),
+  ('\u{10f00}', '\u{10f1c}'), ('\u{10f27}', '\u{10f27}'),
+  ('\u{10f30}', '\u{10f50}'), ('𑀀', '𑁆'), ('𑁦', '𑁯'),
+  ('𑁿', '𑂺'), ('𑃐', '𑃨'), ('𑃰', '𑃹'), ('𑄀', '𑄴'),
+  ('𑄶', '𑄿'), ('\u{11144}', '\u{11146}'), ('𑅐', '𑅳'),
+  ('𑅶', '𑅶'), ('𑆀', '𑇄'), ('𑇉', '𑇌'), ('𑇐', '𑇚'),
+  ('𑇜', '𑇜'), ('𑈀', '𑈑'), ('𑈓', '𑈷'), ('𑈾', '𑈾'),
+  ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'), ('𑊏', '𑊝'),
+  ('𑊟', '𑊨'), ('𑊰', '𑋪'), ('𑋰', '𑋹'), ('𑌀', '𑌃'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('\u{1133b}', '𑍄'), ('𑍇', '𑍈'),
+  ('𑍋', '𑍍'), ('𑍐', '𑍐'), ('𑍗', '𑍗'), ('𑍝', '𑍣'),
+  ('𑍦', '𑍬'), ('𑍰', '𑍴'), ('𑐀', '𑑊'), ('𑑐', '𑑙'),
+  ('\u{1145e}', '\u{1145e}'), ('𑒀', '𑓅'), ('𑓇', '𑓇'),
+  ('𑓐', '𑓙'), ('𑖀', '𑖵'), ('𑖸', '𑗀'), ('𑗘', '𑗝'),
+  ('𑘀', '𑙀'), ('𑙄', '𑙄'), ('𑙐', '𑙙'), ('𑚀', '𑚷'),
+  ('𑛀', '𑛉'), ('𑜀', '\u{1171a}'), ('𑜝', '𑜫'), ('𑜰', '𑜹'),
+  ('\u{11800}', '\u{1183a}'), ('𑢠', '𑣩'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨾'), ('𑩇', '𑩇'), ('𑩐', '𑪃'), ('𑪆', '𑪙'),
+  ('\u{11a9d}', '\u{11a9d}'), ('𑫀', '𑫸'), ('𑰀', '𑰈'),
+  ('𑰊', '𑰶'), ('𑰸', '𑱀'), ('𑱐', '𑱙'), ('𑱲', '𑲏'),
+  ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴀', '𑴆'), ('𑴈', '𑴉'),
+  ('𑴋', '𑴶'), ('𑴺', '𑴺'), ('𑴼', '𑴽'), ('𑴿', '𑵇'),
+  ('𑵐', '𑵙'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d98}'), ('\u{11da0}', '\u{11da9}'),
+  ('\u{11ee0}', '\u{11ef6}'), ('𒀀', '𒎙'), ('𒐀', '𒑮'),
+  ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'),
+  ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖫐', '𖫭'), ('𖫰', '𖫴'),
+  ('𖬀', '𖬶'), ('𖭀', '𖭃'), ('𖭐', '𖭙'), ('𖭣', '𖭷'),
+  ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'), ('𖼀', '𖽄'),
+  ('𖽐', '𖽾'), ('𖾏', '𖾟'), ('𖿠', '𖿡'), ('𗀀', '\u{187f1}'),
+  ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'),
+  ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲝', '𛲞'),
+  ('𝅥', '𝅩'), ('𝅭', '𝅲'), ('𝅻', '𝆂'), ('𝆅', '𝆋'),
+  ('𝆪', '𝆭'), ('𝉂', '𝉄'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'), ('𝛜', '𝛺'),
+  ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'), ('𝝐', '𝝮'),
+  ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'), ('𝟄', '𝟋'),
+  ('𝟎', '𝟿'), ('𝨀', '𝨶'), ('𝨻', '𝩬'), ('𝩵', '𝩵'),
+  ('𝪄', '𝪄'), ('𝪛', '𝪟'), ('𝪡', '𝪯'), ('𞀀', '𞀆'),
+  ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'),
+  ('𞠀', '𞣄'), ('𞣐', '𞣖'), ('𞤀', '𞥊'), ('𞥐', '𞥙'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'), ('🄰', '🅉'), ('🅐', '🅩'), ('🅰', '🆉'),
+  ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'), ('𫠠', '𬺡'),
+  ('𬺰', '𮯠'), ('丽', '𪘀'), ('󠄀', '󠇯'),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/property_bool.rs b/third_party/rust/regex-syntax/src/unicode_tables/property_bool.rs
new file mode 100644
index 000000000000..57c8fc88c550
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/property_bool.rs
@@ -0,0 +1,2658 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate property-bool tmp/ucd-11.0.0/ --chars
+//
+// ucd-generate is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
+  ("ASCII_Hex_Digit", ASCII_HEX_DIGIT), ("Alphabetic", ALPHABETIC),
+  ("Bidi_Control", BIDI_CONTROL), ("Case_Ignorable", CASE_IGNORABLE),
+  ("Cased", CASED), ("Changes_When_Casefolded", CHANGES_WHEN_CASEFOLDED),
+  ("Changes_When_Casemapped", CHANGES_WHEN_CASEMAPPED),
+  ("Changes_When_Lowercased", CHANGES_WHEN_LOWERCASED),
+  ("Changes_When_Titlecased", CHANGES_WHEN_TITLECASED),
+  ("Changes_When_Uppercased", CHANGES_WHEN_UPPERCASED), ("Dash", DASH),
+  ("Default_Ignorable_Code_Point", DEFAULT_IGNORABLE_CODE_POINT),
+  ("Deprecated", DEPRECATED), ("Diacritic", DIACRITIC),
+  ("Extender", EXTENDER), ("Grapheme_Base", GRAPHEME_BASE),
+  ("Grapheme_Extend", GRAPHEME_EXTEND), ("Grapheme_Link", GRAPHEME_LINK),
+  ("Hex_Digit", HEX_DIGIT), ("Hyphen", HYPHEN),
+  ("IDS_Binary_Operator", IDS_BINARY_OPERATOR),
+  ("IDS_Trinary_Operator", IDS_TRINARY_OPERATOR),
+  ("ID_Continue", ID_CONTINUE), ("ID_Start", ID_START),
+  ("Ideographic", IDEOGRAPHIC), ("Join_Control", JOIN_CONTROL),
+  ("Logical_Order_Exception", LOGICAL_ORDER_EXCEPTION),
+  ("Lowercase", LOWERCASE), ("Math", MATH),
+  ("Noncharacter_Code_Point", NONCHARACTER_CODE_POINT),
+  ("Other_Alphabetic", OTHER_ALPHABETIC),
+  ("Other_Default_Ignorable_Code_Point", OTHER_DEFAULT_IGNORABLE_CODE_POINT),
+  ("Other_Grapheme_Extend", OTHER_GRAPHEME_EXTEND),
+  ("Other_ID_Continue", OTHER_ID_CONTINUE),
+  ("Other_ID_Start", OTHER_ID_START), ("Other_Lowercase", OTHER_LOWERCASE),
+  ("Other_Math", OTHER_MATH), ("Other_Uppercase", OTHER_UPPERCASE),
+  ("Pattern_Syntax", PATTERN_SYNTAX),
+  ("Pattern_White_Space", PATTERN_WHITE_SPACE),
+  ("Prepended_Concatenation_Mark", PREPENDED_CONCATENATION_MARK),
+  ("Quotation_Mark", QUOTATION_MARK), ("Radical", RADICAL),
+  ("Regional_Indicator", REGIONAL_INDICATOR),
+  ("Sentence_Terminal", SENTENCE_TERMINAL), ("Soft_Dotted", SOFT_DOTTED),
+  ("Terminal_Punctuation", TERMINAL_PUNCTUATION),
+  ("Unified_Ideograph", UNIFIED_IDEOGRAPH), ("Uppercase", UPPERCASE),
+  ("Variation_Selector", VARIATION_SELECTOR), ("White_Space", WHITE_SPACE),
+  ("XID_Continue", XID_CONTINUE), ("XID_Start", XID_START),
+];
+
+pub const ASCII_HEX_DIGIT: &'static [(char, char)] = &[
+  ('0', '9'), ('A', 'F'), ('a', 'f'),
+];
+
+pub const ALPHABETIC: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'),
+  ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'), ('ˆ', 'ˑ'), ('ˠ', 'ˤ'),
+  ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('ͅ', 'ͅ'), ('Ͱ', 'ʹ'), ('Ͷ', 'ͷ'),
+  ('ͺ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'),
+  ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'), ('Ա', 'Ֆ'),
+  ('ՙ', 'ՙ'), ('\u{560}', '\u{588}'), ('ְ', 'ֽ'), ('ֿ', 'ֿ'),
+  ('ׁ', 'ׂ'), ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('א', 'ת'), ('\u{5ef}', 'ײ'),
+  ('ؐ', 'ؚ'), ('ؠ', 'ٗ'), ('ٙ', 'ٟ'), ('ٮ', 'ۓ'), ('ە', 'ۜ'),
+  ('ۡ', 'ۨ'), ('ۭ', 'ۯ'), ('ۺ', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', 'ܿ'),
+  ('ݍ', 'ޱ'), ('ߊ', 'ߪ'), ('ߴ', 'ߵ'), ('ߺ', 'ߺ'), ('ࠀ', 'ࠗ'),
+  ('ࠚ', 'ࠬ'), ('ࡀ', 'ࡘ'), ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'),
+  ('ࢶ', 'ࢽ'), ('ࣔ', 'ࣟ'), ('ࣣ', 'ࣩ'), ('ࣰ', 'ऻ'),
+  ('ऽ', 'ौ'), ('ॎ', 'ॐ'), ('ॕ', 'ॣ'), ('ॱ', 'ঃ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('ঽ', 'ৄ'), ('ে', 'ৈ'),
+  ('ো', 'ৌ'), ('ৎ', 'ৎ'), ('ৗ', 'ৗ'), ('ড়', 'ঢ়'),
+  ('য়', 'ৣ'), ('ৰ', 'ৱ'), ('ৼ', 'ৼ'), ('ਁ', 'ਃ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('ਾ', 'ੂ'),
+  ('ੇ', 'ੈ'), ('ੋ', 'ੌ'), ('ੑ', 'ੑ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('ੰ', 'ੵ'), ('ઁ', 'ઃ'), ('અ', 'ઍ'),
+  ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'),
+  ('વ', 'હ'), ('ઽ', 'ૅ'), ('ે', 'ૉ'), ('ો', 'ૌ'),
+  ('ૐ', 'ૐ'), ('ૠ', 'ૣ'), ('ૹ', 'ૼ'), ('ଁ', 'ଃ'),
+  ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'),
+  ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('ଽ', 'ୄ'), ('େ', 'ୈ'),
+  ('ୋ', 'ୌ'), ('ୖ', 'ୗ'), ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୣ'),
+  ('ୱ', 'ୱ'), ('ஂ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'),
+  ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'),
+  ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'), ('ா', 'ூ'),
+  ('ெ', 'ை'), ('ொ', 'ௌ'), ('ௐ', 'ௐ'), ('ௗ', 'ௗ'),
+  ('ఀ', 'ః'), ('అ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'),
+  ('ప', 'హ'), ('ఽ', 'ౄ'), ('ె', 'ై'), ('ొ', 'ౌ'),
+  ('ౕ', 'ౖ'), ('ౘ', 'ౚ'), ('ౠ', 'ౣ'), ('ಀ', 'ಃ'),
+  ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'),
+  ('ವ', 'ಹ'), ('ಽ', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', 'ೌ'),
+  ('ೕ', 'ೖ'), ('ೞ', 'ೞ'), ('ೠ', 'ೣ'), ('ೱ', 'ೲ'),
+  ('ഀ', 'ഃ'), ('അ', 'ഌ'), ('എ', 'ഐ'), ('ഒ', 'ഺ'),
+  ('ഽ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', 'ൌ'), ('ൎ', 'ൎ'),
+  ('ൔ', 'ൗ'), ('ൟ', 'ൣ'), ('ൺ', 'ൿ'), ('ං', 'ඃ'),
+  ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'),
+  ('ව', 'ෆ'), ('ා', 'ු'), ('ූ', 'ූ'), ('ෘ', 'ෟ'),
+  ('ෲ', 'ෳ'), ('ก', 'ฺ'), ('เ', 'ๆ'), ('ํ', 'ํ'),
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ູ'),
+  ('ົ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('ໍ', 'ໍ'),
+  ('ໜ', 'ໟ'), ('ༀ', 'ༀ'), ('ཀ', 'ཇ'), ('ཉ', 'ཬ'),
+  ('ཱ', 'ཱྀ'), ('ྈ', 'ྗ'), ('ྙ', 'ྼ'), ('က', 'ံ'),
+  ('း', 'း'), ('ျ', 'ဿ'), ('ၐ', 'ၢ'), ('ၥ', 'ၨ'),
+  ('ၮ', 'ႆ'), ('ႎ', 'ႎ'), ('ႜ', 'ႝ'), ('Ⴀ', 'Ⴥ'),
+  ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'), ('ჼ', 'ቈ'),
+  ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'), ('ቚ', 'ቝ'),
+  ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'), ('ኲ', 'ኵ'),
+  ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'), ('ወ', 'ዖ'),
+  ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'), ('፟', '፟'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', 'ᜓ'), ('ᜠ', 'ᜳ'), ('ᝀ', 'ᝓ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ᝲ', 'ᝳ'), ('ក', 'ឳ'),
+  ('ា', 'ៈ'), ('ៗ', 'ៗ'), ('ៜ', 'ៜ'), ('ᠠ', '\u{1878}'),
+  ('ᢀ', 'ᢪ'), ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'),
+  ('ᤰ', 'ᤸ'), ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'),
+  ('ᦰ', 'ᧉ'), ('ᨀ', 'ᨛ'), ('ᨠ', 'ᩞ'), ('ᩡ', 'ᩴ'),
+  ('ᪧ', 'ᪧ'), ('ᬀ', 'ᬳ'), ('ᬵ', 'ᭃ'), ('ᭅ', 'ᭋ'),
+  ('ᮀ', 'ᮩ'), ('ᮬ', 'ᮯ'), ('ᮺ', 'ᯥ'), ('ᯧ', 'ᯱ'),
+  ('ᰀ', 'ᰵ'), ('ᱍ', 'ᱏ'), ('ᱚ', 'ᱽ'), ('ᲀ', 'ᲈ'),
+  ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'), ('ᳩ', 'ᳬ'),
+  ('ᳮ', 'ᳳ'), ('ᳵ', 'ᳶ'), ('ᴀ', 'ᶿ'), ('ᷧ', 'ᷴ'),
+  ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'),
+  ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'),
+  ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('ⁱ', 'ⁱ'),
+  ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ℂ', 'ℂ'), ('ℇ', 'ℇ'),
+  ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('ℙ', 'ℝ'), ('ℤ', 'ℤ'),
+  ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℭ'), ('ℯ', 'ℹ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⓐ', 'ⓩ'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'),
+  ('Ⳬ', 'ⳮ'), ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'),
+  ('ⴭ', 'ⴭ'), ('ⴰ', 'ⵧ'), ('ⵯ', 'ⵯ'), ('ⶀ', 'ⶖ'),
+  ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'),
+  ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'),
+  ('ⷠ', 'ⷿ'), ('ⸯ', 'ⸯ'), ('々', '〇'), ('〡', '〩'),
+  ('〱', '〵'), ('〸', '〼'), ('ぁ', 'ゖ'), ('ゝ', 'ゟ'),
+  ('ァ', 'ヺ'), ('ー', 'ヿ'), ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'),
+  ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'), ('㐀', '䶵'), ('一', '\u{9fef}'),
+  ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'), ('ꔀ', 'ꘌ'), ('ꘐ', 'ꘟ'),
+  ('ꘪ', 'ꘫ'), ('Ꙁ', 'ꙮ'), ('ꙴ', 'ꙻ'), ('ꙿ', 'ꛯ'),
+  ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'), ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꠁ'),
+  ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'), ('ꠌ', 'ꠧ'), ('ꡀ', 'ꡳ'),
+  ('ꢀ', 'ꣃ'), ('ꣅ', 'ꣅ'), ('ꣲ', 'ꣷ'), ('ꣻ', 'ꣻ'),
+  ('ꣽ', '\u{a8fe}'), ('ꤊ', 'ꤪ'), ('ꤰ', 'ꥒ'), ('ꥠ', 'ꥼ'),
+  ('ꦀ', 'ꦲ'), ('ꦴ', 'ꦿ'), ('ꧏ', 'ꧏ'), ('ꧠ', 'ꧤ'),
+  ('ꧦ', 'ꧯ'), ('ꧺ', 'ꧾ'), ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'),
+  ('ꩠ', 'ꩶ'), ('ꩺ', 'ꩺ'), ('ꩾ', 'ꪾ'), ('ꫀ', 'ꫀ'),
+  ('ꫂ', 'ꫂ'), ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫯ'), ('ꫲ', 'ꫵ'),
+  ('ꬁ', 'ꬆ'), ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'),
+  ('ꬨ', 'ꬮ'), ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯪ'),
+  ('가', '힣'), ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'),
+  ('並', '龎'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'ﬨ'),
+  ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'),
+  ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'), ('ﵐ', 'ﶏ'),
+  ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('Ａ', 'Ｚ'), ('ａ', 'ｚ'), ('ｦ', 'ﾾ'), ('ￂ', 'ￇ'),
+  ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('𐀀', '𐀋'),
+  ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'),
+  ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐅀', '𐅴'), ('𐊀', '𐊜'),
+  ('𐊠', '𐋐'), ('𐌀', '𐌟'), ('𐌭', '𐍊'), ('𐍐', '𐍺'),
+  ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐏑', '𐏕'),
+  ('𐐀', '𐒝'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'),
+  ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+  ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'),
+  ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'), ('𐢀', '𐢞'),
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'), ('𐤠', '𐤹'),
+  ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨃'), ('𐨅', '𐨆'),
+  ('𐨌', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'), ('𐩠', '𐩼'),
+  ('𐪀', '𐪜'), ('𐫀', '𐫇'), ('𐫉', '𐫤'), ('𐬀', '𐬵'),
+  ('𐭀', '𐭕'), ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'),
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('\u{10d00}', '\u{10d27}'),
+  ('\u{10f00}', '\u{10f1c}'), ('\u{10f27}', '\u{10f27}'),
+  ('\u{10f30}', '\u{10f45}'), ('𑀀', '𑁅'), ('𑂂', '𑂸'),
+  ('𑃐', '𑃨'), ('𑄀', '𑄲'), ('\u{11144}', '\u{11146}'),
+  ('𑅐', '𑅲'), ('𑅶', '𑅶'), ('𑆀', '𑆿'), ('𑇁', '𑇄'),
+  ('𑇚', '𑇚'), ('𑇜', '𑇜'), ('𑈀', '𑈑'), ('𑈓', '𑈴'),
+  ('𑈷', '𑈷'), ('𑈾', '𑈾'), ('𑊀', '𑊆'), ('𑊈', '𑊈'),
+  ('𑊊', '𑊍'), ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋨'),
+  ('𑌀', '𑌃'), ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'),
+  ('𑌪', '𑌰'), ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑍄'),
+  ('𑍇', '𑍈'), ('𑍋', '𑍌'), ('𑍐', '𑍐'), ('𑍗', '𑍗'),
+  ('𑍝', '𑍣'), ('𑐀', '𑑁'), ('𑑃', '𑑅'), ('𑑇', '𑑊'),
+  ('𑒀', '𑓁'), ('𑓄', '𑓅'), ('𑓇', '𑓇'), ('𑖀', '𑖵'),
+  ('𑖸', '𑖾'), ('𑗘', '𑗝'), ('𑘀', '𑘾'), ('𑙀', '𑙀'),
+  ('𑙄', '𑙄'), ('𑚀', '𑚵'), ('𑜀', '\u{1171a}'), ('𑜝', '𑜪'),
+  ('\u{11800}', '\u{11838}'), ('𑢠', '𑣟'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨲'), ('𑨵', '𑨾'), ('𑩐', '𑪃'), ('𑪆', '𑪗'),
+  ('\u{11a9d}', '\u{11a9d}'), ('𑫀', '𑫸'), ('𑰀', '𑰈'),
+  ('𑰊', '𑰶'), ('𑰸', '𑰾'), ('𑱀', '𑱀'), ('𑱲', '𑲏'),
+  ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴀', '𑴆'), ('𑴈', '𑴉'),
+  ('𑴋', '𑴶'), ('𑴺', '𑴺'), ('𑴼', '𑴽'), ('𑴿', '𑵁'),
+  ('𑵃', '𑵃'), ('𑵆', '𑵇'), ('\u{11d60}', '\u{11d65}'),
+  ('\u{11d67}', '\u{11d68}'), ('\u{11d6a}', '\u{11d8e}'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d93}', '\u{11d96}'),
+  ('\u{11d98}', '\u{11d98}'), ('\u{11ee0}', '\u{11ef6}'), ('𒀀', '𒎙'),
+  ('𒐀', '𒑮'), ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'),
+  ('𖠀', '𖨸'), ('𖩀', '𖩞'), ('𖫐', '𖫭'), ('𖬀', '𖬶'),
+  ('𖭀', '𖭃'), ('𖭣', '𖭷'), ('𖭽', '𖮏'),
+  ('\u{16e40}', '\u{16e7f}'), ('𖼀', '𖽄'), ('𖽐', '𖽾'),
+  ('𖾓', '𖾟'), ('𖿠', '𖿡'), ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'),
+  ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'), ('𛱰', '𛱼'),
+  ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲞', '𛲞'), ('𝐀', '𝑔'),
+  ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'),
+  ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'),
+  ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'),
+  ('𝛜', '𝛺'), ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'),
+  ('𝝐', '𝝮'), ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'),
+  ('𝟄', '𝟋'), ('𞀀', '𞀆'), ('𞀈', '𞀘'), ('𞀛', '𞀡'),
+  ('𞀣', '𞀤'), ('𞀦', '𞀪'), ('𞠀', '𞣄'), ('𞤀', '𞥃'),
+  ('𞥇', '𞥇'), ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'),
+  ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'),
+  ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'),
+  ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'),
+  ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'),
+  ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'),
+  ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'),
+  ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'),
+  ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('🄰', '🅉'), ('🅐', '🅩'),
+  ('🅰', '🆉'), ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'),
+  ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const BIDI_CONTROL: &'static [(char, char)] = &[
+  ('\u{61c}', '\u{61c}'), ('\u{200e}', '\u{200f}'), ('\u{202a}', '\u{202e}'),
+  ('\u{2066}', '\u{2069}'),
+];
+
+pub const CASE_IGNORABLE: &'static [(char, char)] = &[
+  ('\'', '\''), ('.', '.'), (':', ':'), ('^', '^'), ('`', '`'), ('¨', '¨'),
+  ('\u{ad}', '\u{ad}'), ('¯', '¯'), ('´', '´'), ('·', '¸'),
+  ('ʰ', 'ͯ'), ('ʹ', '͵'), ('ͺ', 'ͺ'), ('΄', '΅'), ('·', '·'),
+  ('҃', '҉'), ('ՙ', 'ՙ'), ('֑', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'),
+  ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('״', '״'), ('\u{600}', '\u{605}'),
+  ('ؐ', 'ؚ'), ('\u{61c}', '\u{61c}'), ('ـ', 'ـ'), ('ً', 'ٟ'),
+  ('ٰ', 'ٰ'), ('ۖ', '\u{6dd}'), ('۟', 'ۨ'), ('۪', 'ۭ'),
+  ('\u{70f}', '\u{70f}'), ('ܑ', 'ܑ'), ('ܰ', '݊'), ('ަ', 'ް'),
+  ('߫', 'ߵ'), ('ߺ', 'ߺ'), ('\u{7fd}', '\u{7fd}'), ('ࠖ', '࠭'),
+  ('࡙', '࡛'), ('\u{8d3}', 'ं'), ('ऺ', 'ऺ'), ('़', '़'),
+  ('ु', 'ै'), ('्', '्'), ('॑', 'ॗ'), ('ॢ', 'ॣ'),
+  ('ॱ', 'ॱ'), ('ঁ', 'ঁ'), ('়', '়'), ('ু', 'ৄ'),
+  ('্', '্'), ('ৢ', 'ৣ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਂ'),
+  ('਼', '਼'), ('ੁ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'),
+  ('ੑ', 'ੑ'), ('ੰ', 'ੱ'), ('ੵ', 'ੵ'), ('ઁ', 'ં'),
+  ('઼', '઼'), ('ુ', 'ૅ'), ('ે', 'ૈ'), ('્', '્'),
+  ('ૢ', 'ૣ'), ('ૺ', '૿'), ('ଁ', 'ଁ'), ('଼', '଼'),
+  ('ି', 'ି'), ('ୁ', 'ୄ'), ('୍', '୍'), ('ୖ', 'ୖ'),
+  ('ୢ', 'ୣ'), ('ஂ', 'ஂ'), ('ீ', 'ீ'), ('்', '்'),
+  ('ఀ', 'ఀ'), ('\u{c04}', '\u{c04}'), ('ా', 'ీ'), ('ె', 'ై'),
+  ('ొ', '్'), ('ౕ', 'ౖ'), ('ౢ', 'ౣ'), ('ಁ', 'ಁ'),
+  ('಼', '಼'), ('ಿ', 'ಿ'), ('ೆ', 'ೆ'), ('ೌ', '್'),
+  ('ೢ', 'ೣ'), ('ഀ', 'ഁ'), ('഻', '഼'), ('ു', 'ൄ'),
+  ('്', '്'), ('ൢ', 'ൣ'), ('්', '්'), ('ි', 'ු'),
+  ('ූ', 'ූ'), ('ั', 'ั'), ('ิ', 'ฺ'), ('ๆ', '๎'),
+  ('ັ', 'ັ'), ('ິ', 'ູ'), ('ົ', 'ຼ'), ('ໆ', 'ໆ'),
+  ('່', 'ໍ'), ('༘', '༙'), ('༵', '༵'), ('༷', '༷'),
+  ('༹', '༹'), ('ཱ', 'ཾ'), ('ྀ', '྄'), ('྆', '྇'),
+  ('ྍ', 'ྗ'), ('ྙ', 'ྼ'), ('࿆', '࿆'), ('ိ', 'ူ'),
+  ('ဲ', '့'), ('္', '်'), ('ွ', 'ှ'), ('ၘ', 'ၙ'),
+  ('ၞ', 'ၠ'), ('ၱ', 'ၴ'), ('ႂ', 'ႂ'), ('ႅ', 'ႆ'),
+  ('ႍ', 'ႍ'), ('ႝ', 'ႝ'), ('ჼ', 'ჼ'), ('፝', '፟'),
+  ('ᜒ', '᜔'), ('ᜲ', '᜴'), ('ᝒ', 'ᝓ'), ('ᝲ', 'ᝳ'),
+  ('឴', '឵'), ('ិ', 'ួ'), ('ំ', 'ំ'), ('៉', '៓'),
+  ('ៗ', 'ៗ'), ('៝', '៝'), ('᠋', '\u{180e}'), ('ᡃ', 'ᡃ'),
+  ('ᢅ', 'ᢆ'), ('ᢩ', 'ᢩ'), ('ᤠ', 'ᤢ'), ('ᤧ', 'ᤨ'),
+  ('ᤲ', 'ᤲ'), ('᤹', '᤻'), ('ᨗ', 'ᨘ'), ('ᨛ', 'ᨛ'),
+  ('ᩖ', 'ᩖ'), ('ᩘ', 'ᩞ'), ('᩠', '᩠'), ('ᩢ', 'ᩢ'),
+  ('ᩥ', 'ᩬ'), ('ᩳ', '᩼'), ('᩿', '᩿'), ('ᪧ', 'ᪧ'),
+  ('᪰', '᪾'), ('ᬀ', 'ᬃ'), ('᬴', '᬴'), ('ᬶ', 'ᬺ'),
+  ('ᬼ', 'ᬼ'), ('ᭂ', 'ᭂ'), ('᭫', '᭳'), ('ᮀ', 'ᮁ'),
+  ('ᮢ', 'ᮥ'), ('ᮨ', 'ᮩ'), ('᮫', 'ᮭ'), ('᯦', '᯦'),
+  ('ᯨ', 'ᯩ'), ('ᯭ', 'ᯭ'), ('ᯯ', 'ᯱ'), ('ᰬ', 'ᰳ'),
+  ('ᰶ', '᰷'), ('ᱸ', 'ᱽ'), ('᳐', '᳒'), ('᳔', '᳠'),
+  ('᳢', '᳨'), ('᳭', '᳭'), ('᳴', '᳴'), ('᳸', '᳹'),
+  ('ᴬ', 'ᵪ'), ('ᵸ', 'ᵸ'), ('ᶛ', '᷹'), ('᷻', '᷿'),
+  ('᾽', '᾽'), ('᾿', '῁'), ('῍', '῏'), ('῝', '῟'),
+  ('῭', '`'), ('´', '῾'), ('\u{200b}', '\u{200f}'), ('‘', '’'),
+  ('․', '․'), ('‧', '‧'), ('\u{202a}', '\u{202e}'),
+  ('\u{2060}', '\u{2064}'), ('\u{2066}', '\u{206f}'), ('ⁱ', 'ⁱ'),
+  ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('⃐', '⃰'), ('ⱼ', 'ⱽ'),
+  ('⳯', '⳱'), ('ⵯ', 'ⵯ'), ('⵿', '⵿'), ('ⷠ', 'ⷿ'),
+  ('ⸯ', 'ⸯ'), ('々', '々'), ('〪', '〭'), ('〱', '〵'),
+  ('〻', '〻'), ('゙', 'ゞ'), ('ー', 'ヾ'), ('ꀕ', 'ꀕ'),
+  ('ꓸ', 'ꓽ'), ('ꘌ', 'ꘌ'), ('꙯', '꙲'), ('ꙴ', '꙽'),
+  ('ꙿ', 'ꙿ'), ('ꚜ', 'ꚟ'), ('꛰', '꛱'), ('꜀', '꜡'),
+  ('ꝰ', 'ꝰ'), ('ꞈ', '꞊'), ('ꟸ', 'ꟹ'), ('ꠂ', 'ꠂ'),
+  ('꠆', '꠆'), ('ꠋ', 'ꠋ'), ('ꠥ', 'ꠦ'), ('꣄', 'ꣅ'),
+  ('꣠', '꣱'), ('\u{a8ff}', '\u{a8ff}'), ('ꤦ', '꤭'), ('ꥇ', 'ꥑ'),
+  ('ꦀ', 'ꦂ'), ('꦳', '꦳'), ('ꦶ', 'ꦹ'), ('ꦼ', 'ꦼ'),
+  ('ꧏ', 'ꧏ'), ('ꧥ', 'ꧦ'), ('ꨩ', 'ꨮ'), ('ꨱ', 'ꨲ'),
+  ('ꨵ', 'ꨶ'), ('ꩃ', 'ꩃ'), ('ꩌ', 'ꩌ'), ('ꩰ', 'ꩰ'),
+  ('ꩼ', 'ꩼ'), ('ꪰ', 'ꪰ'), ('ꪲ', 'ꪴ'), ('ꪷ', 'ꪸ'),
+  ('ꪾ', '꪿'), ('꫁', '꫁'), ('ꫝ', 'ꫝ'), ('ꫬ', 'ꫭ'),
+  ('ꫳ', 'ꫴ'), ('꫶', '꫶'), ('꭛', 'ꭟ'), ('ꯥ', 'ꯥ'),
+  ('ꯨ', 'ꯨ'), ('꯭', '꯭'), ('ﬞ', 'ﬞ'), ('﮲', '﯁'),
+  ('︀', '️'), ('︓', '︓'), ('︠', '︯'), ('﹒', '﹒'),
+  ('﹕', '﹕'), ('\u{feff}', '\u{feff}'), ('＇', '＇'), ('．', '．'),
+  ('：', '：'), ('＾', '＾'), ('｀', '｀'), ('ｰ', 'ｰ'),
+  ('ﾞ', 'ﾟ'), ('￣', '￣'), ('\u{fff9}', '\u{fffb}'), ('𐇽', '𐇽'),
+  ('𐋠', '𐋠'), ('𐍶', '𐍺'), ('𐨁', '𐨃'), ('𐨅', '𐨆'),
+  ('𐨌', '𐨏'), ('𐨸', '𐨺'), ('𐨿', '𐨿'), ('𐫥', '𐫦'),
+  ('\u{10d24}', '\u{10d27}'), ('\u{10f46}', '\u{10f50}'), ('𑀁', '𑀁'),
+  ('𑀸', '𑁆'), ('𑁿', '𑂁'), ('𑂳', '𑂶'), ('𑂹', '𑂺'),
+  ('\u{110bd}', '\u{110bd}'), ('\u{110cd}', '\u{110cd}'), ('𑄀', '𑄂'),
+  ('𑄧', '𑄫'), ('𑄭', '𑄴'), ('𑅳', '𑅳'), ('𑆀', '𑆁'),
+  ('𑆶', '𑆾'), ('𑇉', '𑇌'), ('𑈯', '𑈱'), ('𑈴', '𑈴'),
+  ('𑈶', '𑈷'), ('𑈾', '𑈾'), ('𑋟', '𑋟'), ('𑋣', '𑋪'),
+  ('𑌀', '𑌁'), ('\u{1133b}', '𑌼'), ('𑍀', '𑍀'), ('𑍦', '𑍬'),
+  ('𑍰', '𑍴'), ('𑐸', '𑐿'), ('𑑂', '𑑄'), ('𑑆', '𑑆'),
+  ('\u{1145e}', '\u{1145e}'), ('𑒳', '𑒸'), ('𑒺', '𑒺'),
+  ('𑒿', '𑓀'), ('𑓂', '𑓃'), ('𑖲', '𑖵'), ('𑖼', '𑖽'),
+  ('𑖿', '𑗀'), ('𑗜', '𑗝'), ('𑘳', '𑘺'), ('𑘽', '𑘽'),
+  ('𑘿', '𑙀'), ('𑚫', '𑚫'), ('𑚭', '𑚭'), ('𑚰', '𑚵'),
+  ('𑚷', '𑚷'), ('𑜝', '𑜟'), ('𑜢', '𑜥'), ('𑜧', '𑜫'),
+  ('\u{1182f}', '\u{11837}'), ('\u{11839}', '\u{1183a}'), ('𑨁', '𑨊'),
+  ('𑨳', '𑨸'), ('𑨻', '𑨾'), ('𑩇', '𑩇'), ('𑩑', '𑩖'),
+  ('𑩙', '𑩛'), ('𑪊', '𑪖'), ('𑪘', '𑪙'), ('𑰰', '𑰶'),
+  ('𑰸', '𑰽'), ('𑰿', '𑰿'), ('𑲒', '𑲧'), ('𑲪', '𑲰'),
+  ('𑲲', '𑲳'), ('𑲵', '𑲶'), ('𑴱', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵅'), ('𑵇', '𑵇'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d95}', '\u{11d95}'),
+  ('\u{11d97}', '\u{11d97}'), ('\u{11ef3}', '\u{11ef4}'), ('𖫰', '𖫴'),
+  ('𖬰', '𖬶'), ('𖭀', '𖭃'), ('𖾏', '𖾟'), ('𖿠', '𖿡'),
+  ('𛲝', '𛲞'), ('\u{1bca0}', '\u{1bca3}'), ('𝅧', '𝅩'),
+  ('\u{1d173}', '𝆂'), ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('𝉂', '𝉄'),
+  ('𝨀', '𝨶'), ('𝨻', '𝩬'), ('𝩵', '𝩵'), ('𝪄', '𝪄'),
+  ('𝪛', '𝪟'), ('𝪡', '𝪯'), ('𞀀', '𞀆'), ('𞀈', '𞀘'),
+  ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'), ('𞣐', '𞣖'),
+  ('𞥄', '𞥊'), ('🏻', '🏿'), ('\u{e0001}', '\u{e0001}'),
+  ('\u{e0020}', '\u{e007f}'), ('󠄀', '󠇯'),
+];
+
+pub const CASED: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'),
+  ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ƺ'), ('Ƽ', 'ƿ'), ('Ǆ', 'ʓ'),
+  ('ʕ', 'ʸ'), ('ˀ', 'ˁ'), ('ˠ', 'ˤ'), ('ͅ', 'ͅ'), ('Ͱ', 'ͳ'),
+  ('Ͷ', 'ͷ'), ('ͺ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'),
+  ('Ό', 'Ό'), ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('\u{560}', '\u{588}'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('Ꭰ', 'Ᏽ'),
+  ('ᏸ', 'ᏽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('ᴀ', 'ᶿ'), ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'),
+  ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'),
+  ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'),
+  ('ᾶ', 'ᾼ'), ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῌ'),
+  ('ῐ', 'ΐ'), ('ῖ', 'Ί'), ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'),
+  ('ῶ', 'ῼ'), ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'),
+  ('ℂ', 'ℂ'), ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'),
+  ('ℙ', 'ℝ'), ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'),
+  ('K', 'ℭ'), ('ℯ', 'ℴ'), ('ℹ', 'ℹ'), ('ℼ', 'ℿ'),
+  ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ⅿ'), ('Ↄ', 'ↄ'),
+  ('Ⓐ', 'ⓩ'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'),
+  ('Ⳬ', 'ⳮ'), ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'),
+  ('ⴭ', 'ⴭ'), ('Ꙁ', 'ꙭ'), ('Ꚁ', 'ꚝ'), ('Ꜣ', 'ꞇ'),
+  ('Ꞌ', 'ꞎ'), ('Ꞑ', '\u{a7b9}'), ('ꟸ', 'ꟺ'), ('ꬰ', 'ꭚ'),
+  ('ꭜ', 'ꭥ'), ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'),
+  ('Ａ', 'Ｚ'), ('ａ', 'ｚ'), ('𐐀', '𐑏'), ('𐒰', '𐓓'),
+  ('𐓘', '𐓻'), ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𑢠', '𑣟'),
+  ('\u{16e40}', '\u{16e7f}'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'), ('𝛜', '𝛺'),
+  ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'), ('𝝐', '𝝮'),
+  ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'), ('𝟄', '𝟋'),
+  ('𞤀', '𞥃'), ('🄰', '🅉'), ('🅐', '🅩'), ('🅰', '🆉'),
+];
+
+pub const CHANGES_WHEN_CASEFOLDED: &'static [(char, char)] = &[
+  ('A', 'Z'), ('µ', 'µ'), ('À', 'Ö'), ('Ø', 'ß'), ('Ā', 'Ā'),
+  ('Ă', 'Ă'), ('Ą', 'Ą'), ('Ć', 'Ć'), ('Ĉ', 'Ĉ'), ('Ċ', 'Ċ'),
+  ('Č', 'Č'), ('Ď', 'Ď'), ('Đ', 'Đ'), ('Ē', 'Ē'), ('Ĕ', 'Ĕ'),
+  ('Ė', 'Ė'), ('Ę', 'Ę'), ('Ě', 'Ě'), ('Ĝ', 'Ĝ'), ('Ğ', 'Ğ'),
+  ('Ġ', 'Ġ'), ('Ģ', 'Ģ'), ('Ĥ', 'Ĥ'), ('Ħ', 'Ħ'), ('Ĩ', 'Ĩ'),
+  ('Ī', 'Ī'), ('Ĭ', 'Ĭ'), ('Į', 'Į'), ('İ', 'İ'), ('Ĳ', 'Ĳ'),
+  ('Ĵ', 'Ĵ'), ('Ķ', 'Ķ'), ('Ĺ', 'Ĺ'), ('Ļ', 'Ļ'), ('Ľ', 'Ľ'),
+  ('Ŀ', 'Ŀ'), ('Ł', 'Ł'), ('Ń', 'Ń'), ('Ņ', 'Ņ'), ('Ň', 'Ň'),
+  ('ŉ', 'Ŋ'), ('Ō', 'Ō'), ('Ŏ', 'Ŏ'), ('Ő', 'Ő'), ('Œ', 'Œ'),
+  ('Ŕ', 'Ŕ'), ('Ŗ', 'Ŗ'), ('Ř', 'Ř'), ('Ś', 'Ś'), ('Ŝ', 'Ŝ'),
+  ('Ş', 'Ş'), ('Š', 'Š'), ('Ţ', 'Ţ'), ('Ť', 'Ť'), ('Ŧ', 'Ŧ'),
+  ('Ũ', 'Ũ'), ('Ū', 'Ū'), ('Ŭ', 'Ŭ'), ('Ů', 'Ů'), ('Ű', 'Ű'),
+  ('Ų', 'Ų'), ('Ŵ', 'Ŵ'), ('Ŷ', 'Ŷ'), ('Ÿ', 'Ź'), ('Ż', 'Ż'),
+  ('Ž', 'Ž'), ('ſ', 'ſ'), ('Ɓ', 'Ƃ'), ('Ƅ', 'Ƅ'), ('Ɔ', 'Ƈ'),
+  ('Ɖ', 'Ƌ'), ('Ǝ', 'Ƒ'), ('Ɠ', 'Ɣ'), ('Ɩ', 'Ƙ'), ('Ɯ', 'Ɲ'),
+  ('Ɵ', 'Ơ'), ('Ƣ', 'Ƣ'), ('Ƥ', 'Ƥ'), ('Ʀ', 'Ƨ'), ('Ʃ', 'Ʃ'),
+  ('Ƭ', 'Ƭ'), ('Ʈ', 'Ư'), ('Ʊ', 'Ƴ'), ('Ƶ', 'Ƶ'), ('Ʒ', 'Ƹ'),
+  ('Ƽ', 'Ƽ'), ('Ǆ', 'ǅ'), ('Ǉ', 'ǈ'), ('Ǌ', 'ǋ'), ('Ǎ', 'Ǎ'),
+  ('Ǐ', 'Ǐ'), ('Ǒ', 'Ǒ'), ('Ǔ', 'Ǔ'), ('Ǖ', 'Ǖ'), ('Ǘ', 'Ǘ'),
+  ('Ǚ', 'Ǚ'), ('Ǜ', 'Ǜ'), ('Ǟ', 'Ǟ'), ('Ǡ', 'Ǡ'), ('Ǣ', 'Ǣ'),
+  ('Ǥ', 'Ǥ'), ('Ǧ', 'Ǧ'), ('Ǩ', 'Ǩ'), ('Ǫ', 'Ǫ'), ('Ǭ', 'Ǭ'),
+  ('Ǯ', 'Ǯ'), ('Ǳ', 'ǲ'), ('Ǵ', 'Ǵ'), ('Ƕ', 'Ǹ'), ('Ǻ', 'Ǻ'),
+  ('Ǽ', 'Ǽ'), ('Ǿ', 'Ǿ'), ('Ȁ', 'Ȁ'), ('Ȃ', 'Ȃ'), ('Ȅ', 'Ȅ'),
+  ('Ȇ', 'Ȇ'), ('Ȉ', 'Ȉ'), ('Ȋ', 'Ȋ'), ('Ȍ', 'Ȍ'), ('Ȏ', 'Ȏ'),
+  ('Ȑ', 'Ȑ'), ('Ȓ', 'Ȓ'), ('Ȕ', 'Ȕ'), ('Ȗ', 'Ȗ'), ('Ș', 'Ș'),
+  ('Ț', 'Ț'), ('Ȝ', 'Ȝ'), ('Ȟ', 'Ȟ'), ('Ƞ', 'Ƞ'), ('Ȣ', 'Ȣ'),
+  ('Ȥ', 'Ȥ'), ('Ȧ', 'Ȧ'), ('Ȩ', 'Ȩ'), ('Ȫ', 'Ȫ'), ('Ȭ', 'Ȭ'),
+  ('Ȯ', 'Ȯ'), ('Ȱ', 'Ȱ'), ('Ȳ', 'Ȳ'), ('Ⱥ', 'Ȼ'), ('Ƚ', 'Ⱦ'),
+  ('Ɂ', 'Ɂ'), ('Ƀ', 'Ɇ'), ('Ɉ', 'Ɉ'), ('Ɋ', 'Ɋ'), ('Ɍ', 'Ɍ'),
+  ('Ɏ', 'Ɏ'), ('ͅ', 'ͅ'), ('Ͱ', 'Ͱ'), ('Ͳ', 'Ͳ'), ('Ͷ', 'Ͷ'),
+  ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ώ'),
+  ('Α', 'Ρ'), ('Σ', 'Ϋ'), ('ς', 'ς'), ('Ϗ', 'ϑ'), ('ϕ', 'ϖ'),
+  ('Ϙ', 'Ϙ'), ('Ϛ', 'Ϛ'), ('Ϝ', 'Ϝ'), ('Ϟ', 'Ϟ'), ('Ϡ', 'Ϡ'),
+  ('Ϣ', 'Ϣ'), ('Ϥ', 'Ϥ'), ('Ϧ', 'Ϧ'), ('Ϩ', 'Ϩ'), ('Ϫ', 'Ϫ'),
+  ('Ϭ', 'Ϭ'), ('Ϯ', 'Ϯ'), ('ϰ', 'ϱ'), ('ϴ', 'ϵ'), ('Ϸ', 'Ϸ'),
+  ('Ϲ', 'Ϻ'), ('Ͻ', 'Я'), ('Ѡ', 'Ѡ'), ('Ѣ', 'Ѣ'), ('Ѥ', 'Ѥ'),
+  ('Ѧ', 'Ѧ'), ('Ѩ', 'Ѩ'), ('Ѫ', 'Ѫ'), ('Ѭ', 'Ѭ'), ('Ѯ', 'Ѯ'),
+  ('Ѱ', 'Ѱ'), ('Ѳ', 'Ѳ'), ('Ѵ', 'Ѵ'), ('Ѷ', 'Ѷ'), ('Ѹ', 'Ѹ'),
+  ('Ѻ', 'Ѻ'), ('Ѽ', 'Ѽ'), ('Ѿ', 'Ѿ'), ('Ҁ', 'Ҁ'), ('Ҋ', 'Ҋ'),
+  ('Ҍ', 'Ҍ'), ('Ҏ', 'Ҏ'), ('Ґ', 'Ґ'), ('Ғ', 'Ғ'), ('Ҕ', 'Ҕ'),
+  ('Җ', 'Җ'), ('Ҙ', 'Ҙ'), ('Қ', 'Қ'), ('Ҝ', 'Ҝ'), ('Ҟ', 'Ҟ'),
+  ('Ҡ', 'Ҡ'), ('Ң', 'Ң'), ('Ҥ', 'Ҥ'), ('Ҧ', 'Ҧ'), ('Ҩ', 'Ҩ'),
+  ('Ҫ', 'Ҫ'), ('Ҭ', 'Ҭ'), ('Ү', 'Ү'), ('Ұ', 'Ұ'), ('Ҳ', 'Ҳ'),
+  ('Ҵ', 'Ҵ'), ('Ҷ', 'Ҷ'), ('Ҹ', 'Ҹ'), ('Һ', 'Һ'), ('Ҽ', 'Ҽ'),
+  ('Ҿ', 'Ҿ'), ('Ӏ', 'Ӂ'), ('Ӄ', 'Ӄ'), ('Ӆ', 'Ӆ'), ('Ӈ', 'Ӈ'),
+  ('Ӊ', 'Ӊ'), ('Ӌ', 'Ӌ'), ('Ӎ', 'Ӎ'), ('Ӑ', 'Ӑ'), ('Ӓ', 'Ӓ'),
+  ('Ӕ', 'Ӕ'), ('Ӗ', 'Ӗ'), ('Ә', 'Ә'), ('Ӛ', 'Ӛ'), ('Ӝ', 'Ӝ'),
+  ('Ӟ', 'Ӟ'), ('Ӡ', 'Ӡ'), ('Ӣ', 'Ӣ'), ('Ӥ', 'Ӥ'), ('Ӧ', 'Ӧ'),
+  ('Ө', 'Ө'), ('Ӫ', 'Ӫ'), ('Ӭ', 'Ӭ'), ('Ӯ', 'Ӯ'), ('Ӱ', 'Ӱ'),
+  ('Ӳ', 'Ӳ'), ('Ӵ', 'Ӵ'), ('Ӷ', 'Ӷ'), ('Ӹ', 'Ӹ'), ('Ӻ', 'Ӻ'),
+  ('Ӽ', 'Ӽ'), ('Ӿ', 'Ӿ'), ('Ԁ', 'Ԁ'), ('Ԃ', 'Ԃ'), ('Ԅ', 'Ԅ'),
+  ('Ԇ', 'Ԇ'), ('Ԉ', 'Ԉ'), ('Ԋ', 'Ԋ'), ('Ԍ', 'Ԍ'), ('Ԏ', 'Ԏ'),
+  ('Ԑ', 'Ԑ'), ('Ԓ', 'Ԓ'), ('Ԕ', 'Ԕ'), ('Ԗ', 'Ԗ'), ('Ԙ', 'Ԙ'),
+  ('Ԛ', 'Ԛ'), ('Ԝ', 'Ԝ'), ('Ԟ', 'Ԟ'), ('Ԡ', 'Ԡ'), ('Ԣ', 'Ԣ'),
+  ('Ԥ', 'Ԥ'), ('Ԧ', 'Ԧ'), ('Ԩ', 'Ԩ'), ('Ԫ', 'Ԫ'), ('Ԭ', 'Ԭ'),
+  ('Ԯ', 'Ԯ'), ('Ա', 'Ֆ'), ('և', 'և'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ᏸ', 'ᏽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('Ḁ', 'Ḁ'), ('Ḃ', 'Ḃ'), ('Ḅ', 'Ḅ'),
+  ('Ḇ', 'Ḇ'), ('Ḉ', 'Ḉ'), ('Ḋ', 'Ḋ'), ('Ḍ', 'Ḍ'),
+  ('Ḏ', 'Ḏ'), ('Ḑ', 'Ḑ'), ('Ḓ', 'Ḓ'), ('Ḕ', 'Ḕ'),
+  ('Ḗ', 'Ḗ'), ('Ḙ', 'Ḙ'), ('Ḛ', 'Ḛ'), ('Ḝ', 'Ḝ'),
+  ('Ḟ', 'Ḟ'), ('Ḡ', 'Ḡ'), ('Ḣ', 'Ḣ'), ('Ḥ', 'Ḥ'),
+  ('Ḧ', 'Ḧ'), ('Ḩ', 'Ḩ'), ('Ḫ', 'Ḫ'), ('Ḭ', 'Ḭ'),
+  ('Ḯ', 'Ḯ'), ('Ḱ', 'Ḱ'), ('Ḳ', 'Ḳ'), ('Ḵ', 'Ḵ'),
+  ('Ḷ', 'Ḷ'), ('Ḹ', 'Ḹ'), ('Ḻ', 'Ḻ'), ('Ḽ', 'Ḽ'),
+  ('Ḿ', 'Ḿ'), ('Ṁ', 'Ṁ'), ('Ṃ', 'Ṃ'), ('Ṅ', 'Ṅ'),
+  ('Ṇ', 'Ṇ'), ('Ṉ', 'Ṉ'), ('Ṋ', 'Ṋ'), ('Ṍ', 'Ṍ'),
+  ('Ṏ', 'Ṏ'), ('Ṑ', 'Ṑ'), ('Ṓ', 'Ṓ'), ('Ṕ', 'Ṕ'),
+  ('Ṗ', 'Ṗ'), ('Ṙ', 'Ṙ'), ('Ṛ', 'Ṛ'), ('Ṝ', 'Ṝ'),
+  ('Ṟ', 'Ṟ'), ('Ṡ', 'Ṡ'), ('Ṣ', 'Ṣ'), ('Ṥ', 'Ṥ'),
+  ('Ṧ', 'Ṧ'), ('Ṩ', 'Ṩ'), ('Ṫ', 'Ṫ'), ('Ṭ', 'Ṭ'),
+  ('Ṯ', 'Ṯ'), ('Ṱ', 'Ṱ'), ('Ṳ', 'Ṳ'), ('Ṵ', 'Ṵ'),
+  ('Ṷ', 'Ṷ'), ('Ṹ', 'Ṹ'), ('Ṻ', 'Ṻ'), ('Ṽ', 'Ṽ'),
+  ('Ṿ', 'Ṿ'), ('Ẁ', 'Ẁ'), ('Ẃ', 'Ẃ'), ('Ẅ', 'Ẅ'),
+  ('Ẇ', 'Ẇ'), ('Ẉ', 'Ẉ'), ('Ẋ', 'Ẋ'), ('Ẍ', 'Ẍ'),
+  ('Ẏ', 'Ẏ'), ('Ẑ', 'Ẑ'), ('Ẓ', 'Ẓ'), ('Ẕ', 'Ẕ'),
+  ('ẚ', 'ẛ'), ('ẞ', 'ẞ'), ('Ạ', 'Ạ'), ('Ả', 'Ả'),
+  ('Ấ', 'Ấ'), ('Ầ', 'Ầ'), ('Ẩ', 'Ẩ'), ('Ẫ', 'Ẫ'),
+  ('Ậ', 'Ậ'), ('Ắ', 'Ắ'), ('Ằ', 'Ằ'), ('Ẳ', 'Ẳ'),
+  ('Ẵ', 'Ẵ'), ('Ặ', 'Ặ'), ('Ẹ', 'Ẹ'), ('Ẻ', 'Ẻ'),
+  ('Ẽ', 'Ẽ'), ('Ế', 'Ế'), ('Ề', 'Ề'), ('Ể', 'Ể'),
+  ('Ễ', 'Ễ'), ('Ệ', 'Ệ'), ('Ỉ', 'Ỉ'), ('Ị', 'Ị'),
+  ('Ọ', 'Ọ'), ('Ỏ', 'Ỏ'), ('Ố', 'Ố'), ('Ồ', 'Ồ'),
+  ('Ổ', 'Ổ'), ('Ỗ', 'Ỗ'), ('Ộ', 'Ộ'), ('Ớ', 'Ớ'),
+  ('Ờ', 'Ờ'), ('Ở', 'Ở'), ('Ỡ', 'Ỡ'), ('Ợ', 'Ợ'),
+  ('Ụ', 'Ụ'), ('Ủ', 'Ủ'), ('Ứ', 'Ứ'), ('Ừ', 'Ừ'),
+  ('Ử', 'Ử'), ('Ữ', 'Ữ'), ('Ự', 'Ự'), ('Ỳ', 'Ỳ'),
+  ('Ỵ', 'Ỵ'), ('Ỷ', 'Ỷ'), ('Ỹ', 'Ỹ'), ('Ỻ', 'Ỻ'),
+  ('Ỽ', 'Ỽ'), ('Ỿ', 'Ỿ'), ('Ἀ', 'Ἇ'), ('Ἐ', 'Ἕ'),
+  ('Ἠ', 'Ἧ'), ('Ἰ', 'Ἷ'), ('Ὀ', 'Ὅ'), ('Ὑ', 'Ὑ'),
+  ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'Ὗ'), ('Ὠ', 'Ὧ'),
+  ('ᾀ', 'ᾯ'), ('ᾲ', 'ᾴ'), ('ᾷ', 'ᾼ'), ('ῂ', 'ῄ'),
+  ('ῇ', 'ῌ'), ('Ῐ', 'Ί'), ('Ῠ', 'Ῥ'), ('ῲ', 'ῴ'),
+  ('ῷ', 'ῼ'), ('Ω', 'Ω'), ('K', 'Å'), ('Ⅎ', 'Ⅎ'),
+  ('Ⅰ', 'Ⅿ'), ('Ↄ', 'Ↄ'), ('Ⓐ', 'Ⓩ'), ('Ⰰ', 'Ⱞ'),
+  ('Ⱡ', 'Ⱡ'), ('Ɫ', 'Ɽ'), ('Ⱨ', 'Ⱨ'), ('Ⱪ', 'Ⱪ'),
+  ('Ⱬ', 'Ⱬ'), ('Ɑ', 'Ɒ'), ('Ⱳ', 'Ⱳ'), ('Ⱶ', 'Ⱶ'),
+  ('Ȿ', 'Ⲁ'), ('Ⲃ', 'Ⲃ'), ('Ⲅ', 'Ⲅ'), ('Ⲇ', 'Ⲇ'),
+  ('Ⲉ', 'Ⲉ'), ('Ⲋ', 'Ⲋ'), ('Ⲍ', 'Ⲍ'), ('Ⲏ', 'Ⲏ'),
+  ('Ⲑ', 'Ⲑ'), ('Ⲓ', 'Ⲓ'), ('Ⲕ', 'Ⲕ'), ('Ⲗ', 'Ⲗ'),
+  ('Ⲙ', 'Ⲙ'), ('Ⲛ', 'Ⲛ'), ('Ⲝ', 'Ⲝ'), ('Ⲟ', 'Ⲟ'),
+  ('Ⲡ', 'Ⲡ'), ('Ⲣ', 'Ⲣ'), ('Ⲥ', 'Ⲥ'), ('Ⲧ', 'Ⲧ'),
+  ('Ⲩ', 'Ⲩ'), ('Ⲫ', 'Ⲫ'), ('Ⲭ', 'Ⲭ'), ('Ⲯ', 'Ⲯ'),
+  ('Ⲱ', 'Ⲱ'), ('Ⲳ', 'Ⲳ'), ('Ⲵ', 'Ⲵ'), ('Ⲷ', 'Ⲷ'),
+  ('Ⲹ', 'Ⲹ'), ('Ⲻ', 'Ⲻ'), ('Ⲽ', 'Ⲽ'), ('Ⲿ', 'Ⲿ'),
+  ('Ⳁ', 'Ⳁ'), ('Ⳃ', 'Ⳃ'), ('Ⳅ', 'Ⳅ'), ('Ⳇ', 'Ⳇ'),
+  ('Ⳉ', 'Ⳉ'), ('Ⳋ', 'Ⳋ'), ('Ⳍ', 'Ⳍ'), ('Ⳏ', 'Ⳏ'),
+  ('Ⳑ', 'Ⳑ'), ('Ⳓ', 'Ⳓ'), ('Ⳕ', 'Ⳕ'), ('Ⳗ', 'Ⳗ'),
+  ('Ⳙ', 'Ⳙ'), ('Ⳛ', 'Ⳛ'), ('Ⳝ', 'Ⳝ'), ('Ⳟ', 'Ⳟ'),
+  ('Ⳡ', 'Ⳡ'), ('Ⳣ', 'Ⳣ'), ('Ⳬ', 'Ⳬ'), ('Ⳮ', 'Ⳮ'),
+  ('Ⳳ', 'Ⳳ'), ('Ꙁ', 'Ꙁ'), ('Ꙃ', 'Ꙃ'), ('Ꙅ', 'Ꙅ'),
+  ('Ꙇ', 'Ꙇ'), ('Ꙉ', 'Ꙉ'), ('Ꙋ', 'Ꙋ'), ('Ꙍ', 'Ꙍ'),
+  ('Ꙏ', 'Ꙏ'), ('Ꙑ', 'Ꙑ'), ('Ꙓ', 'Ꙓ'), ('Ꙕ', 'Ꙕ'),
+  ('Ꙗ', 'Ꙗ'), ('Ꙙ', 'Ꙙ'), ('Ꙛ', 'Ꙛ'), ('Ꙝ', 'Ꙝ'),
+  ('Ꙟ', 'Ꙟ'), ('Ꙡ', 'Ꙡ'), ('Ꙣ', 'Ꙣ'), ('Ꙥ', 'Ꙥ'),
+  ('Ꙧ', 'Ꙧ'), ('Ꙩ', 'Ꙩ'), ('Ꙫ', 'Ꙫ'), ('Ꙭ', 'Ꙭ'),
+  ('Ꚁ', 'Ꚁ'), ('Ꚃ', 'Ꚃ'), ('Ꚅ', 'Ꚅ'), ('Ꚇ', 'Ꚇ'),
+  ('Ꚉ', 'Ꚉ'), ('Ꚋ', 'Ꚋ'), ('Ꚍ', 'Ꚍ'), ('Ꚏ', 'Ꚏ'),
+  ('Ꚑ', 'Ꚑ'), ('Ꚓ', 'Ꚓ'), ('Ꚕ', 'Ꚕ'), ('Ꚗ', 'Ꚗ'),
+  ('Ꚙ', 'Ꚙ'), ('Ꚛ', 'Ꚛ'), ('Ꜣ', 'Ꜣ'), ('Ꜥ', 'Ꜥ'),
+  ('Ꜧ', 'Ꜧ'), ('Ꜩ', 'Ꜩ'), ('Ꜫ', 'Ꜫ'), ('Ꜭ', 'Ꜭ'),
+  ('Ꜯ', 'Ꜯ'), ('Ꜳ', 'Ꜳ'), ('Ꜵ', 'Ꜵ'), ('Ꜷ', 'Ꜷ'),
+  ('Ꜹ', 'Ꜹ'), ('Ꜻ', 'Ꜻ'), ('Ꜽ', 'Ꜽ'), ('Ꜿ', 'Ꜿ'),
+  ('Ꝁ', 'Ꝁ'), ('Ꝃ', 'Ꝃ'), ('Ꝅ', 'Ꝅ'), ('Ꝇ', 'Ꝇ'),
+  ('Ꝉ', 'Ꝉ'), ('Ꝋ', 'Ꝋ'), ('Ꝍ', 'Ꝍ'), ('Ꝏ', 'Ꝏ'),
+  ('Ꝑ', 'Ꝑ'), ('Ꝓ', 'Ꝓ'), ('Ꝕ', 'Ꝕ'), ('Ꝗ', 'Ꝗ'),
+  ('Ꝙ', 'Ꝙ'), ('Ꝛ', 'Ꝛ'), ('Ꝝ', 'Ꝝ'), ('Ꝟ', 'Ꝟ'),
+  ('Ꝡ', 'Ꝡ'), ('Ꝣ', 'Ꝣ'), ('Ꝥ', 'Ꝥ'), ('Ꝧ', 'Ꝧ'),
+  ('Ꝩ', 'Ꝩ'), ('Ꝫ', 'Ꝫ'), ('Ꝭ', 'Ꝭ'), ('Ꝯ', 'Ꝯ'),
+  ('Ꝺ', 'Ꝺ'), ('Ꝼ', 'Ꝼ'), ('Ᵹ', 'Ꝿ'), ('Ꞁ', 'Ꞁ'),
+  ('Ꞃ', 'Ꞃ'), ('Ꞅ', 'Ꞅ'), ('Ꞇ', 'Ꞇ'), ('Ꞌ', 'Ꞌ'),
+  ('Ɥ', 'Ɥ'), ('Ꞑ', 'Ꞑ'), ('Ꞓ', 'Ꞓ'), ('Ꞗ', 'Ꞗ'),
+  ('Ꞙ', 'Ꞙ'), ('Ꞛ', 'Ꞛ'), ('Ꞝ', 'Ꞝ'), ('Ꞟ', 'Ꞟ'),
+  ('Ꞡ', 'Ꞡ'), ('Ꞣ', 'Ꞣ'), ('Ꞥ', 'Ꞥ'), ('Ꞧ', 'Ꞧ'),
+  ('Ꞩ', 'Ꞩ'), ('Ɦ', 'Ɪ'), ('Ʞ', 'Ꞵ'), ('Ꞷ', 'Ꞷ'),
+  ('\u{a7b8}', '\u{a7b8}'), ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'),
+  ('Ａ', 'Ｚ'), ('𐐀', '𐐧'), ('𐒰', '𐓓'), ('𐲀', '𐲲'),
+  ('𑢠', '𑢿'), ('\u{16e40}', '\u{16e5f}'), ('𞤀', '𞤡'),
+];
+
+pub const CHANGES_WHEN_CASEMAPPED: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('µ', 'µ'), ('À', 'Ö'), ('Ø', 'ö'),
+  ('ø', 'ķ'), ('Ĺ', 'ƌ'), ('Ǝ', 'ƚ'), ('Ɯ', 'Ʃ'), ('Ƭ', 'ƹ'),
+  ('Ƽ', 'ƽ'), ('ƿ', 'ƿ'), ('Ǆ', 'Ƞ'), ('Ȣ', 'ȳ'), ('Ⱥ', 'ɔ'),
+  ('ɖ', 'ɗ'), ('ə', 'ə'), ('ɛ', 'ɜ'), ('ɠ', 'ɡ'), ('ɣ', 'ɣ'),
+  ('ɥ', 'ɦ'), ('ɨ', 'ɬ'), ('ɯ', 'ɯ'), ('ɱ', 'ɲ'), ('ɵ', 'ɵ'),
+  ('ɽ', 'ɽ'), ('ʀ', 'ʀ'), ('ʃ', 'ʃ'), ('ʇ', 'ʌ'), ('ʒ', 'ʒ'),
+  ('ʝ', 'ʞ'), ('ͅ', 'ͅ'), ('Ͱ', 'ͳ'), ('Ͷ', 'ͷ'), ('ͻ', 'ͽ'),
+  ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'),
+  ('Σ', 'ϑ'), ('ϕ', 'ϵ'), ('Ϸ', 'ϻ'), ('Ͻ', 'ҁ'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('ա', 'և'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'),
+  ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('ᵹ', 'ᵹ'), ('ᵽ', 'ᵽ'), ('Ḁ', 'ẛ'), ('ẞ', 'ẞ'),
+  ('Ạ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'),
+  ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'),
+  ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('Ω', 'Ω'),
+  ('K', 'Å'), ('Ⅎ', 'Ⅎ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ⅿ'),
+  ('Ↄ', 'ↄ'), ('Ⓐ', 'ⓩ'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'),
+  ('Ⱡ', 'Ɒ'), ('Ⱳ', 'ⱳ'), ('Ⱶ', 'ⱶ'), ('Ȿ', 'ⳣ'),
+  ('Ⳬ', 'ⳮ'), ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'),
+  ('ⴭ', 'ⴭ'), ('Ꙁ', 'ꙭ'), ('Ꚁ', 'ꚛ'), ('Ꜣ', 'ꜯ'),
+  ('Ꜳ', 'ꝯ'), ('Ꝺ', 'ꞇ'), ('Ꞌ', 'Ɥ'), ('Ꞑ', 'ꞓ'),
+  ('Ꞗ', 'Ɪ'), ('Ʞ', '\u{a7b9}'), ('ꭓ', 'ꭓ'), ('ꭰ', 'ꮿ'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('Ａ', 'Ｚ'), ('ａ', 'ｚ'),
+  ('𐐀', '𐑏'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐲀', '𐲲'),
+  ('𐳀', '𐳲'), ('𑢠', '𑣟'), ('\u{16e40}', '\u{16e7f}'),
+  ('𞤀', '𞥃'),
+];
+
+pub const CHANGES_WHEN_LOWERCASED: &'static [(char, char)] = &[
+  ('A', 'Z'), ('À', 'Ö'), ('Ø', 'Þ'), ('Ā', 'Ā'), ('Ă', 'Ă'),
+  ('Ą', 'Ą'), ('Ć', 'Ć'), ('Ĉ', 'Ĉ'), ('Ċ', 'Ċ'), ('Č', 'Č'),
+  ('Ď', 'Ď'), ('Đ', 'Đ'), ('Ē', 'Ē'), ('Ĕ', 'Ĕ'), ('Ė', 'Ė'),
+  ('Ę', 'Ę'), ('Ě', 'Ě'), ('Ĝ', 'Ĝ'), ('Ğ', 'Ğ'), ('Ġ', 'Ġ'),
+  ('Ģ', 'Ģ'), ('Ĥ', 'Ĥ'), ('Ħ', 'Ħ'), ('Ĩ', 'Ĩ'), ('Ī', 'Ī'),
+  ('Ĭ', 'Ĭ'), ('Į', 'Į'), ('İ', 'İ'), ('Ĳ', 'Ĳ'), ('Ĵ', 'Ĵ'),
+  ('Ķ', 'Ķ'), ('Ĺ', 'Ĺ'), ('Ļ', 'Ļ'), ('Ľ', 'Ľ'), ('Ŀ', 'Ŀ'),
+  ('Ł', 'Ł'), ('Ń', 'Ń'), ('Ņ', 'Ņ'), ('Ň', 'Ň'), ('Ŋ', 'Ŋ'),
+  ('Ō', 'Ō'), ('Ŏ', 'Ŏ'), ('Ő', 'Ő'), ('Œ', 'Œ'), ('Ŕ', 'Ŕ'),
+  ('Ŗ', 'Ŗ'), ('Ř', 'Ř'), ('Ś', 'Ś'), ('Ŝ', 'Ŝ'), ('Ş', 'Ş'),
+  ('Š', 'Š'), ('Ţ', 'Ţ'), ('Ť', 'Ť'), ('Ŧ', 'Ŧ'), ('Ũ', 'Ũ'),
+  ('Ū', 'Ū'), ('Ŭ', 'Ŭ'), ('Ů', 'Ů'), ('Ű', 'Ű'), ('Ų', 'Ų'),
+  ('Ŵ', 'Ŵ'), ('Ŷ', 'Ŷ'), ('Ÿ', 'Ź'), ('Ż', 'Ż'), ('Ž', 'Ž'),
+  ('Ɓ', 'Ƃ'), ('Ƅ', 'Ƅ'), ('Ɔ', 'Ƈ'), ('Ɖ', 'Ƌ'), ('Ǝ', 'Ƒ'),
+  ('Ɠ', 'Ɣ'), ('Ɩ', 'Ƙ'), ('Ɯ', 'Ɲ'), ('Ɵ', 'Ơ'), ('Ƣ', 'Ƣ'),
+  ('Ƥ', 'Ƥ'), ('Ʀ', 'Ƨ'), ('Ʃ', 'Ʃ'), ('Ƭ', 'Ƭ'), ('Ʈ', 'Ư'),
+  ('Ʊ', 'Ƴ'), ('Ƶ', 'Ƶ'), ('Ʒ', 'Ƹ'), ('Ƽ', 'Ƽ'), ('Ǆ', 'ǅ'),
+  ('Ǉ', 'ǈ'), ('Ǌ', 'ǋ'), ('Ǎ', 'Ǎ'), ('Ǐ', 'Ǐ'), ('Ǒ', 'Ǒ'),
+  ('Ǔ', 'Ǔ'), ('Ǖ', 'Ǖ'), ('Ǘ', 'Ǘ'), ('Ǚ', 'Ǚ'), ('Ǜ', 'Ǜ'),
+  ('Ǟ', 'Ǟ'), ('Ǡ', 'Ǡ'), ('Ǣ', 'Ǣ'), ('Ǥ', 'Ǥ'), ('Ǧ', 'Ǧ'),
+  ('Ǩ', 'Ǩ'), ('Ǫ', 'Ǫ'), ('Ǭ', 'Ǭ'), ('Ǯ', 'Ǯ'), ('Ǳ', 'ǲ'),
+  ('Ǵ', 'Ǵ'), ('Ƕ', 'Ǹ'), ('Ǻ', 'Ǻ'), ('Ǽ', 'Ǽ'), ('Ǿ', 'Ǿ'),
+  ('Ȁ', 'Ȁ'), ('Ȃ', 'Ȃ'), ('Ȅ', 'Ȅ'), ('Ȇ', 'Ȇ'), ('Ȉ', 'Ȉ'),
+  ('Ȋ', 'Ȋ'), ('Ȍ', 'Ȍ'), ('Ȏ', 'Ȏ'), ('Ȑ', 'Ȑ'), ('Ȓ', 'Ȓ'),
+  ('Ȕ', 'Ȕ'), ('Ȗ', 'Ȗ'), ('Ș', 'Ș'), ('Ț', 'Ț'), ('Ȝ', 'Ȝ'),
+  ('Ȟ', 'Ȟ'), ('Ƞ', 'Ƞ'), ('Ȣ', 'Ȣ'), ('Ȥ', 'Ȥ'), ('Ȧ', 'Ȧ'),
+  ('Ȩ', 'Ȩ'), ('Ȫ', 'Ȫ'), ('Ȭ', 'Ȭ'), ('Ȯ', 'Ȯ'), ('Ȱ', 'Ȱ'),
+  ('Ȳ', 'Ȳ'), ('Ⱥ', 'Ȼ'), ('Ƚ', 'Ⱦ'), ('Ɂ', 'Ɂ'), ('Ƀ', 'Ɇ'),
+  ('Ɉ', 'Ɉ'), ('Ɋ', 'Ɋ'), ('Ɍ', 'Ɍ'), ('Ɏ', 'Ɏ'), ('Ͱ', 'Ͱ'),
+  ('Ͳ', 'Ͳ'), ('Ͷ', 'Ͷ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'),
+  ('Ό', 'Ό'), ('Ύ', 'Ώ'), ('Α', 'Ρ'), ('Σ', 'Ϋ'), ('Ϗ', 'Ϗ'),
+  ('Ϙ', 'Ϙ'), ('Ϛ', 'Ϛ'), ('Ϝ', 'Ϝ'), ('Ϟ', 'Ϟ'), ('Ϡ', 'Ϡ'),
+  ('Ϣ', 'Ϣ'), ('Ϥ', 'Ϥ'), ('Ϧ', 'Ϧ'), ('Ϩ', 'Ϩ'), ('Ϫ', 'Ϫ'),
+  ('Ϭ', 'Ϭ'), ('Ϯ', 'Ϯ'), ('ϴ', 'ϴ'), ('Ϸ', 'Ϸ'), ('Ϲ', 'Ϻ'),
+  ('Ͻ', 'Я'), ('Ѡ', 'Ѡ'), ('Ѣ', 'Ѣ'), ('Ѥ', 'Ѥ'), ('Ѧ', 'Ѧ'),
+  ('Ѩ', 'Ѩ'), ('Ѫ', 'Ѫ'), ('Ѭ', 'Ѭ'), ('Ѯ', 'Ѯ'), ('Ѱ', 'Ѱ'),
+  ('Ѳ', 'Ѳ'), ('Ѵ', 'Ѵ'), ('Ѷ', 'Ѷ'), ('Ѹ', 'Ѹ'), ('Ѻ', 'Ѻ'),
+  ('Ѽ', 'Ѽ'), ('Ѿ', 'Ѿ'), ('Ҁ', 'Ҁ'), ('Ҋ', 'Ҋ'), ('Ҍ', 'Ҍ'),
+  ('Ҏ', 'Ҏ'), ('Ґ', 'Ґ'), ('Ғ', 'Ғ'), ('Ҕ', 'Ҕ'), ('Җ', 'Җ'),
+  ('Ҙ', 'Ҙ'), ('Қ', 'Қ'), ('Ҝ', 'Ҝ'), ('Ҟ', 'Ҟ'), ('Ҡ', 'Ҡ'),
+  ('Ң', 'Ң'), ('Ҥ', 'Ҥ'), ('Ҧ', 'Ҧ'), ('Ҩ', 'Ҩ'), ('Ҫ', 'Ҫ'),
+  ('Ҭ', 'Ҭ'), ('Ү', 'Ү'), ('Ұ', 'Ұ'), ('Ҳ', 'Ҳ'), ('Ҵ', 'Ҵ'),
+  ('Ҷ', 'Ҷ'), ('Ҹ', 'Ҹ'), ('Һ', 'Һ'), ('Ҽ', 'Ҽ'), ('Ҿ', 'Ҿ'),
+  ('Ӏ', 'Ӂ'), ('Ӄ', 'Ӄ'), ('Ӆ', 'Ӆ'), ('Ӈ', 'Ӈ'), ('Ӊ', 'Ӊ'),
+  ('Ӌ', 'Ӌ'), ('Ӎ', 'Ӎ'), ('Ӑ', 'Ӑ'), ('Ӓ', 'Ӓ'), ('Ӕ', 'Ӕ'),
+  ('Ӗ', 'Ӗ'), ('Ә', 'Ә'), ('Ӛ', 'Ӛ'), ('Ӝ', 'Ӝ'), ('Ӟ', 'Ӟ'),
+  ('Ӡ', 'Ӡ'), ('Ӣ', 'Ӣ'), ('Ӥ', 'Ӥ'), ('Ӧ', 'Ӧ'), ('Ө', 'Ө'),
+  ('Ӫ', 'Ӫ'), ('Ӭ', 'Ӭ'), ('Ӯ', 'Ӯ'), ('Ӱ', 'Ӱ'), ('Ӳ', 'Ӳ'),
+  ('Ӵ', 'Ӵ'), ('Ӷ', 'Ӷ'), ('Ӹ', 'Ӹ'), ('Ӻ', 'Ӻ'), ('Ӽ', 'Ӽ'),
+  ('Ӿ', 'Ӿ'), ('Ԁ', 'Ԁ'), ('Ԃ', 'Ԃ'), ('Ԅ', 'Ԅ'), ('Ԇ', 'Ԇ'),
+  ('Ԉ', 'Ԉ'), ('Ԋ', 'Ԋ'), ('Ԍ', 'Ԍ'), ('Ԏ', 'Ԏ'), ('Ԑ', 'Ԑ'),
+  ('Ԓ', 'Ԓ'), ('Ԕ', 'Ԕ'), ('Ԗ', 'Ԗ'), ('Ԙ', 'Ԙ'), ('Ԛ', 'Ԛ'),
+  ('Ԝ', 'Ԝ'), ('Ԟ', 'Ԟ'), ('Ԡ', 'Ԡ'), ('Ԣ', 'Ԣ'), ('Ԥ', 'Ԥ'),
+  ('Ԧ', 'Ԧ'), ('Ԩ', 'Ԩ'), ('Ԫ', 'Ԫ'), ('Ԭ', 'Ԭ'), ('Ԯ', 'Ԯ'),
+  ('Ա', 'Ֆ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('Ꭰ', 'Ᏽ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('Ḁ', 'Ḁ'), ('Ḃ', 'Ḃ'), ('Ḅ', 'Ḅ'), ('Ḇ', 'Ḇ'),
+  ('Ḉ', 'Ḉ'), ('Ḋ', 'Ḋ'), ('Ḍ', 'Ḍ'), ('Ḏ', 'Ḏ'),
+  ('Ḑ', 'Ḑ'), ('Ḓ', 'Ḓ'), ('Ḕ', 'Ḕ'), ('Ḗ', 'Ḗ'),
+  ('Ḙ', 'Ḙ'), ('Ḛ', 'Ḛ'), ('Ḝ', 'Ḝ'), ('Ḟ', 'Ḟ'),
+  ('Ḡ', 'Ḡ'), ('Ḣ', 'Ḣ'), ('Ḥ', 'Ḥ'), ('Ḧ', 'Ḧ'),
+  ('Ḩ', 'Ḩ'), ('Ḫ', 'Ḫ'), ('Ḭ', 'Ḭ'), ('Ḯ', 'Ḯ'),
+  ('Ḱ', 'Ḱ'), ('Ḳ', 'Ḳ'), ('Ḵ', 'Ḵ'), ('Ḷ', 'Ḷ'),
+  ('Ḹ', 'Ḹ'), ('Ḻ', 'Ḻ'), ('Ḽ', 'Ḽ'), ('Ḿ', 'Ḿ'),
+  ('Ṁ', 'Ṁ'), ('Ṃ', 'Ṃ'), ('Ṅ', 'Ṅ'), ('Ṇ', 'Ṇ'),
+  ('Ṉ', 'Ṉ'), ('Ṋ', 'Ṋ'), ('Ṍ', 'Ṍ'), ('Ṏ', 'Ṏ'),
+  ('Ṑ', 'Ṑ'), ('Ṓ', 'Ṓ'), ('Ṕ', 'Ṕ'), ('Ṗ', 'Ṗ'),
+  ('Ṙ', 'Ṙ'), ('Ṛ', 'Ṛ'), ('Ṝ', 'Ṝ'), ('Ṟ', 'Ṟ'),
+  ('Ṡ', 'Ṡ'), ('Ṣ', 'Ṣ'), ('Ṥ', 'Ṥ'), ('Ṧ', 'Ṧ'),
+  ('Ṩ', 'Ṩ'), ('Ṫ', 'Ṫ'), ('Ṭ', 'Ṭ'), ('Ṯ', 'Ṯ'),
+  ('Ṱ', 'Ṱ'), ('Ṳ', 'Ṳ'), ('Ṵ', 'Ṵ'), ('Ṷ', 'Ṷ'),
+  ('Ṹ', 'Ṹ'), ('Ṻ', 'Ṻ'), ('Ṽ', 'Ṽ'), ('Ṿ', 'Ṿ'),
+  ('Ẁ', 'Ẁ'), ('Ẃ', 'Ẃ'), ('Ẅ', 'Ẅ'), ('Ẇ', 'Ẇ'),
+  ('Ẉ', 'Ẉ'), ('Ẋ', 'Ẋ'), ('Ẍ', 'Ẍ'), ('Ẏ', 'Ẏ'),
+  ('Ẑ', 'Ẑ'), ('Ẓ', 'Ẓ'), ('Ẕ', 'Ẕ'), ('ẞ', 'ẞ'),
+  ('Ạ', 'Ạ'), ('Ả', 'Ả'), ('Ấ', 'Ấ'), ('Ầ', 'Ầ'),
+  ('Ẩ', 'Ẩ'), ('Ẫ', 'Ẫ'), ('Ậ', 'Ậ'), ('Ắ', 'Ắ'),
+  ('Ằ', 'Ằ'), ('Ẳ', 'Ẳ'), ('Ẵ', 'Ẵ'), ('Ặ', 'Ặ'),
+  ('Ẹ', 'Ẹ'), ('Ẻ', 'Ẻ'), ('Ẽ', 'Ẽ'), ('Ế', 'Ế'),
+  ('Ề', 'Ề'), ('Ể', 'Ể'), ('Ễ', 'Ễ'), ('Ệ', 'Ệ'),
+  ('Ỉ', 'Ỉ'), ('Ị', 'Ị'), ('Ọ', 'Ọ'), ('Ỏ', 'Ỏ'),
+  ('Ố', 'Ố'), ('Ồ', 'Ồ'), ('Ổ', 'Ổ'), ('Ỗ', 'Ỗ'),
+  ('Ộ', 'Ộ'), ('Ớ', 'Ớ'), ('Ờ', 'Ờ'), ('Ở', 'Ở'),
+  ('Ỡ', 'Ỡ'), ('Ợ', 'Ợ'), ('Ụ', 'Ụ'), ('Ủ', 'Ủ'),
+  ('Ứ', 'Ứ'), ('Ừ', 'Ừ'), ('Ử', 'Ử'), ('Ữ', 'Ữ'),
+  ('Ự', 'Ự'), ('Ỳ', 'Ỳ'), ('Ỵ', 'Ỵ'), ('Ỷ', 'Ỷ'),
+  ('Ỹ', 'Ỹ'), ('Ỻ', 'Ỻ'), ('Ỽ', 'Ỽ'), ('Ỿ', 'Ỿ'),
+  ('Ἀ', 'Ἇ'), ('Ἐ', 'Ἕ'), ('Ἠ', 'Ἧ'), ('Ἰ', 'Ἷ'),
+  ('Ὀ', 'Ὅ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'Ὗ'), ('Ὠ', 'Ὧ'), ('ᾈ', 'ᾏ'), ('ᾘ', 'ᾟ'),
+  ('ᾨ', 'ᾯ'), ('Ᾰ', 'ᾼ'), ('Ὲ', 'ῌ'), ('Ῐ', 'Ί'),
+  ('Ῠ', 'Ῥ'), ('Ὸ', 'ῼ'), ('Ω', 'Ω'), ('K', 'Å'),
+  ('Ⅎ', 'Ⅎ'), ('Ⅰ', 'Ⅿ'), ('Ↄ', 'Ↄ'), ('Ⓐ', 'Ⓩ'),
+  ('Ⰰ', 'Ⱞ'), ('Ⱡ', 'Ⱡ'), ('Ɫ', 'Ɽ'), ('Ⱨ', 'Ⱨ'),
+  ('Ⱪ', 'Ⱪ'), ('Ⱬ', 'Ⱬ'), ('Ɑ', 'Ɒ'), ('Ⱳ', 'Ⱳ'),
+  ('Ⱶ', 'Ⱶ'), ('Ȿ', 'Ⲁ'), ('Ⲃ', 'Ⲃ'), ('Ⲅ', 'Ⲅ'),
+  ('Ⲇ', 'Ⲇ'), ('Ⲉ', 'Ⲉ'), ('Ⲋ', 'Ⲋ'), ('Ⲍ', 'Ⲍ'),
+  ('Ⲏ', 'Ⲏ'), ('Ⲑ', 'Ⲑ'), ('Ⲓ', 'Ⲓ'), ('Ⲕ', 'Ⲕ'),
+  ('Ⲗ', 'Ⲗ'), ('Ⲙ', 'Ⲙ'), ('Ⲛ', 'Ⲛ'), ('Ⲝ', 'Ⲝ'),
+  ('Ⲟ', 'Ⲟ'), ('Ⲡ', 'Ⲡ'), ('Ⲣ', 'Ⲣ'), ('Ⲥ', 'Ⲥ'),
+  ('Ⲧ', 'Ⲧ'), ('Ⲩ', 'Ⲩ'), ('Ⲫ', 'Ⲫ'), ('Ⲭ', 'Ⲭ'),
+  ('Ⲯ', 'Ⲯ'), ('Ⲱ', 'Ⲱ'), ('Ⲳ', 'Ⲳ'), ('Ⲵ', 'Ⲵ'),
+  ('Ⲷ', 'Ⲷ'), ('Ⲹ', 'Ⲹ'), ('Ⲻ', 'Ⲻ'), ('Ⲽ', 'Ⲽ'),
+  ('Ⲿ', 'Ⲿ'), ('Ⳁ', 'Ⳁ'), ('Ⳃ', 'Ⳃ'), ('Ⳅ', 'Ⳅ'),
+  ('Ⳇ', 'Ⳇ'), ('Ⳉ', 'Ⳉ'), ('Ⳋ', 'Ⳋ'), ('Ⳍ', 'Ⳍ'),
+  ('Ⳏ', 'Ⳏ'), ('Ⳑ', 'Ⳑ'), ('Ⳓ', 'Ⳓ'), ('Ⳕ', 'Ⳕ'),
+  ('Ⳗ', 'Ⳗ'), ('Ⳙ', 'Ⳙ'), ('Ⳛ', 'Ⳛ'), ('Ⳝ', 'Ⳝ'),
+  ('Ⳟ', 'Ⳟ'), ('Ⳡ', 'Ⳡ'), ('Ⳣ', 'Ⳣ'), ('Ⳬ', 'Ⳬ'),
+  ('Ⳮ', 'Ⳮ'), ('Ⳳ', 'Ⳳ'), ('Ꙁ', 'Ꙁ'), ('Ꙃ', 'Ꙃ'),
+  ('Ꙅ', 'Ꙅ'), ('Ꙇ', 'Ꙇ'), ('Ꙉ', 'Ꙉ'), ('Ꙋ', 'Ꙋ'),
+  ('Ꙍ', 'Ꙍ'), ('Ꙏ', 'Ꙏ'), ('Ꙑ', 'Ꙑ'), ('Ꙓ', 'Ꙓ'),
+  ('Ꙕ', 'Ꙕ'), ('Ꙗ', 'Ꙗ'), ('Ꙙ', 'Ꙙ'), ('Ꙛ', 'Ꙛ'),
+  ('Ꙝ', 'Ꙝ'), ('Ꙟ', 'Ꙟ'), ('Ꙡ', 'Ꙡ'), ('Ꙣ', 'Ꙣ'),
+  ('Ꙥ', 'Ꙥ'), ('Ꙧ', 'Ꙧ'), ('Ꙩ', 'Ꙩ'), ('Ꙫ', 'Ꙫ'),
+  ('Ꙭ', 'Ꙭ'), ('Ꚁ', 'Ꚁ'), ('Ꚃ', 'Ꚃ'), ('Ꚅ', 'Ꚅ'),
+  ('Ꚇ', 'Ꚇ'), ('Ꚉ', 'Ꚉ'), ('Ꚋ', 'Ꚋ'), ('Ꚍ', 'Ꚍ'),
+  ('Ꚏ', 'Ꚏ'), ('Ꚑ', 'Ꚑ'), ('Ꚓ', 'Ꚓ'), ('Ꚕ', 'Ꚕ'),
+  ('Ꚗ', 'Ꚗ'), ('Ꚙ', 'Ꚙ'), ('Ꚛ', 'Ꚛ'), ('Ꜣ', 'Ꜣ'),
+  ('Ꜥ', 'Ꜥ'), ('Ꜧ', 'Ꜧ'), ('Ꜩ', 'Ꜩ'), ('Ꜫ', 'Ꜫ'),
+  ('Ꜭ', 'Ꜭ'), ('Ꜯ', 'Ꜯ'), ('Ꜳ', 'Ꜳ'), ('Ꜵ', 'Ꜵ'),
+  ('Ꜷ', 'Ꜷ'), ('Ꜹ', 'Ꜹ'), ('Ꜻ', 'Ꜻ'), ('Ꜽ', 'Ꜽ'),
+  ('Ꜿ', 'Ꜿ'), ('Ꝁ', 'Ꝁ'), ('Ꝃ', 'Ꝃ'), ('Ꝅ', 'Ꝅ'),
+  ('Ꝇ', 'Ꝇ'), ('Ꝉ', 'Ꝉ'), ('Ꝋ', 'Ꝋ'), ('Ꝍ', 'Ꝍ'),
+  ('Ꝏ', 'Ꝏ'), ('Ꝑ', 'Ꝑ'), ('Ꝓ', 'Ꝓ'), ('Ꝕ', 'Ꝕ'),
+  ('Ꝗ', 'Ꝗ'), ('Ꝙ', 'Ꝙ'), ('Ꝛ', 'Ꝛ'), ('Ꝝ', 'Ꝝ'),
+  ('Ꝟ', 'Ꝟ'), ('Ꝡ', 'Ꝡ'), ('Ꝣ', 'Ꝣ'), ('Ꝥ', 'Ꝥ'),
+  ('Ꝧ', 'Ꝧ'), ('Ꝩ', 'Ꝩ'), ('Ꝫ', 'Ꝫ'), ('Ꝭ', 'Ꝭ'),
+  ('Ꝯ', 'Ꝯ'), ('Ꝺ', 'Ꝺ'), ('Ꝼ', 'Ꝼ'), ('Ᵹ', 'Ꝿ'),
+  ('Ꞁ', 'Ꞁ'), ('Ꞃ', 'Ꞃ'), ('Ꞅ', 'Ꞅ'), ('Ꞇ', 'Ꞇ'),
+  ('Ꞌ', 'Ꞌ'), ('Ɥ', 'Ɥ'), ('Ꞑ', 'Ꞑ'), ('Ꞓ', 'Ꞓ'),
+  ('Ꞗ', 'Ꞗ'), ('Ꞙ', 'Ꞙ'), ('Ꞛ', 'Ꞛ'), ('Ꞝ', 'Ꞝ'),
+  ('Ꞟ', 'Ꞟ'), ('Ꞡ', 'Ꞡ'), ('Ꞣ', 'Ꞣ'), ('Ꞥ', 'Ꞥ'),
+  ('Ꞧ', 'Ꞧ'), ('Ꞩ', 'Ꞩ'), ('Ɦ', 'Ɪ'), ('Ʞ', 'Ꞵ'),
+  ('Ꞷ', 'Ꞷ'), ('\u{a7b8}', '\u{a7b8}'), ('Ａ', 'Ｚ'), ('𐐀', '𐐧'),
+  ('𐒰', '𐓓'), ('𐲀', '𐲲'), ('𑢠', '𑢿'),
+  ('\u{16e40}', '\u{16e5f}'), ('𞤀', '𞤡'),
+];
+
+pub const CHANGES_WHEN_TITLECASED: &'static [(char, char)] = &[
+  ('a', 'z'), ('µ', 'µ'), ('ß', 'ö'), ('ø', 'ÿ'), ('ā', 'ā'),
+  ('ă', 'ă'), ('ą', 'ą'), ('ć', 'ć'), ('ĉ', 'ĉ'), ('ċ', 'ċ'),
+  ('č', 'č'), ('ď', 'ď'), ('đ', 'đ'), ('ē', 'ē'), ('ĕ', 'ĕ'),
+  ('ė', 'ė'), ('ę', 'ę'), ('ě', 'ě'), ('ĝ', 'ĝ'), ('ğ', 'ğ'),
+  ('ġ', 'ġ'), ('ģ', 'ģ'), ('ĥ', 'ĥ'), ('ħ', 'ħ'), ('ĩ', 'ĩ'),
+  ('ī', 'ī'), ('ĭ', 'ĭ'), ('į', 'į'), ('ı', 'ı'), ('ĳ', 'ĳ'),
+  ('ĵ', 'ĵ'), ('ķ', 'ķ'), ('ĺ', 'ĺ'), ('ļ', 'ļ'), ('ľ', 'ľ'),
+  ('ŀ', 'ŀ'), ('ł', 'ł'), ('ń', 'ń'), ('ņ', 'ņ'), ('ň', 'ŉ'),
+  ('ŋ', 'ŋ'), ('ō', 'ō'), ('ŏ', 'ŏ'), ('ő', 'ő'), ('œ', 'œ'),
+  ('ŕ', 'ŕ'), ('ŗ', 'ŗ'), ('ř', 'ř'), ('ś', 'ś'), ('ŝ', 'ŝ'),
+  ('ş', 'ş'), ('š', 'š'), ('ţ', 'ţ'), ('ť', 'ť'), ('ŧ', 'ŧ'),
+  ('ũ', 'ũ'), ('ū', 'ū'), ('ŭ', 'ŭ'), ('ů', 'ů'), ('ű', 'ű'),
+  ('ų', 'ų'), ('ŵ', 'ŵ'), ('ŷ', 'ŷ'), ('ź', 'ź'), ('ż', 'ż'),
+  ('ž', 'ƀ'), ('ƃ', 'ƃ'), ('ƅ', 'ƅ'), ('ƈ', 'ƈ'), ('ƌ', 'ƌ'),
+  ('ƒ', 'ƒ'), ('ƕ', 'ƕ'), ('ƙ', 'ƚ'), ('ƞ', 'ƞ'), ('ơ', 'ơ'),
+  ('ƣ', 'ƣ'), ('ƥ', 'ƥ'), ('ƨ', 'ƨ'), ('ƭ', 'ƭ'), ('ư', 'ư'),
+  ('ƴ', 'ƴ'), ('ƶ', 'ƶ'), ('ƹ', 'ƹ'), ('ƽ', 'ƽ'), ('ƿ', 'ƿ'),
+  ('Ǆ', 'Ǆ'), ('ǆ', 'Ǉ'), ('ǉ', 'Ǌ'), ('ǌ', 'ǌ'), ('ǎ', 'ǎ'),
+  ('ǐ', 'ǐ'), ('ǒ', 'ǒ'), ('ǔ', 'ǔ'), ('ǖ', 'ǖ'), ('ǘ', 'ǘ'),
+  ('ǚ', 'ǚ'), ('ǜ', 'ǝ'), ('ǟ', 'ǟ'), ('ǡ', 'ǡ'), ('ǣ', 'ǣ'),
+  ('ǥ', 'ǥ'), ('ǧ', 'ǧ'), ('ǩ', 'ǩ'), ('ǫ', 'ǫ'), ('ǭ', 'ǭ'),
+  ('ǯ', 'Ǳ'), ('ǳ', 'ǳ'), ('ǵ', 'ǵ'), ('ǹ', 'ǹ'), ('ǻ', 'ǻ'),
+  ('ǽ', 'ǽ'), ('ǿ', 'ǿ'), ('ȁ', 'ȁ'), ('ȃ', 'ȃ'), ('ȅ', 'ȅ'),
+  ('ȇ', 'ȇ'), ('ȉ', 'ȉ'), ('ȋ', 'ȋ'), ('ȍ', 'ȍ'), ('ȏ', 'ȏ'),
+  ('ȑ', 'ȑ'), ('ȓ', 'ȓ'), ('ȕ', 'ȕ'), ('ȗ', 'ȗ'), ('ș', 'ș'),
+  ('ț', 'ț'), ('ȝ', 'ȝ'), ('ȟ', 'ȟ'), ('ȣ', 'ȣ'), ('ȥ', 'ȥ'),
+  ('ȧ', 'ȧ'), ('ȩ', 'ȩ'), ('ȫ', 'ȫ'), ('ȭ', 'ȭ'), ('ȯ', 'ȯ'),
+  ('ȱ', 'ȱ'), ('ȳ', 'ȳ'), ('ȼ', 'ȼ'), ('ȿ', 'ɀ'), ('ɂ', 'ɂ'),
+  ('ɇ', 'ɇ'), ('ɉ', 'ɉ'), ('ɋ', 'ɋ'), ('ɍ', 'ɍ'), ('ɏ', 'ɔ'),
+  ('ɖ', 'ɗ'), ('ə', 'ə'), ('ɛ', 'ɜ'), ('ɠ', 'ɡ'), ('ɣ', 'ɣ'),
+  ('ɥ', 'ɦ'), ('ɨ', 'ɬ'), ('ɯ', 'ɯ'), ('ɱ', 'ɲ'), ('ɵ', 'ɵ'),
+  ('ɽ', 'ɽ'), ('ʀ', 'ʀ'), ('ʃ', 'ʃ'), ('ʇ', 'ʌ'), ('ʒ', 'ʒ'),
+  ('ʝ', 'ʞ'), ('ͅ', 'ͅ'), ('ͱ', 'ͱ'), ('ͳ', 'ͳ'), ('ͷ', 'ͷ'),
+  ('ͻ', 'ͽ'), ('ΐ', 'ΐ'), ('ά', 'ώ'), ('ϐ', 'ϑ'), ('ϕ', 'ϗ'),
+  ('ϙ', 'ϙ'), ('ϛ', 'ϛ'), ('ϝ', 'ϝ'), ('ϟ', 'ϟ'), ('ϡ', 'ϡ'),
+  ('ϣ', 'ϣ'), ('ϥ', 'ϥ'), ('ϧ', 'ϧ'), ('ϩ', 'ϩ'), ('ϫ', 'ϫ'),
+  ('ϭ', 'ϭ'), ('ϯ', 'ϳ'), ('ϵ', 'ϵ'), ('ϸ', 'ϸ'), ('ϻ', 'ϻ'),
+  ('а', 'џ'), ('ѡ', 'ѡ'), ('ѣ', 'ѣ'), ('ѥ', 'ѥ'), ('ѧ', 'ѧ'),
+  ('ѩ', 'ѩ'), ('ѫ', 'ѫ'), ('ѭ', 'ѭ'), ('ѯ', 'ѯ'), ('ѱ', 'ѱ'),
+  ('ѳ', 'ѳ'), ('ѵ', 'ѵ'), ('ѷ', 'ѷ'), ('ѹ', 'ѹ'), ('ѻ', 'ѻ'),
+  ('ѽ', 'ѽ'), ('ѿ', 'ѿ'), ('ҁ', 'ҁ'), ('ҋ', 'ҋ'), ('ҍ', 'ҍ'),
+  ('ҏ', 'ҏ'), ('ґ', 'ґ'), ('ғ', 'ғ'), ('ҕ', 'ҕ'), ('җ', 'җ'),
+  ('ҙ', 'ҙ'), ('қ', 'қ'), ('ҝ', 'ҝ'), ('ҟ', 'ҟ'), ('ҡ', 'ҡ'),
+  ('ң', 'ң'), ('ҥ', 'ҥ'), ('ҧ', 'ҧ'), ('ҩ', 'ҩ'), ('ҫ', 'ҫ'),
+  ('ҭ', 'ҭ'), ('ү', 'ү'), ('ұ', 'ұ'), ('ҳ', 'ҳ'), ('ҵ', 'ҵ'),
+  ('ҷ', 'ҷ'), ('ҹ', 'ҹ'), ('һ', 'һ'), ('ҽ', 'ҽ'), ('ҿ', 'ҿ'),
+  ('ӂ', 'ӂ'), ('ӄ', 'ӄ'), ('ӆ', 'ӆ'), ('ӈ', 'ӈ'), ('ӊ', 'ӊ'),
+  ('ӌ', 'ӌ'), ('ӎ', 'ӏ'), ('ӑ', 'ӑ'), ('ӓ', 'ӓ'), ('ӕ', 'ӕ'),
+  ('ӗ', 'ӗ'), ('ә', 'ә'), ('ӛ', 'ӛ'), ('ӝ', 'ӝ'), ('ӟ', 'ӟ'),
+  ('ӡ', 'ӡ'), ('ӣ', 'ӣ'), ('ӥ', 'ӥ'), ('ӧ', 'ӧ'), ('ө', 'ө'),
+  ('ӫ', 'ӫ'), ('ӭ', 'ӭ'), ('ӯ', 'ӯ'), ('ӱ', 'ӱ'), ('ӳ', 'ӳ'),
+  ('ӵ', 'ӵ'), ('ӷ', 'ӷ'), ('ӹ', 'ӹ'), ('ӻ', 'ӻ'), ('ӽ', 'ӽ'),
+  ('ӿ', 'ӿ'), ('ԁ', 'ԁ'), ('ԃ', 'ԃ'), ('ԅ', 'ԅ'), ('ԇ', 'ԇ'),
+  ('ԉ', 'ԉ'), ('ԋ', 'ԋ'), ('ԍ', 'ԍ'), ('ԏ', 'ԏ'), ('ԑ', 'ԑ'),
+  ('ԓ', 'ԓ'), ('ԕ', 'ԕ'), ('ԗ', 'ԗ'), ('ԙ', 'ԙ'), ('ԛ', 'ԛ'),
+  ('ԝ', 'ԝ'), ('ԟ', 'ԟ'), ('ԡ', 'ԡ'), ('ԣ', 'ԣ'), ('ԥ', 'ԥ'),
+  ('ԧ', 'ԧ'), ('ԩ', 'ԩ'), ('ԫ', 'ԫ'), ('ԭ', 'ԭ'), ('ԯ', 'ԯ'),
+  ('ա', 'և'), ('ᏸ', 'ᏽ'), ('ᲀ', 'ᲈ'), ('ᵹ', 'ᵹ'),
+  ('ᵽ', 'ᵽ'), ('ḁ', 'ḁ'), ('ḃ', 'ḃ'), ('ḅ', 'ḅ'),
+  ('ḇ', 'ḇ'), ('ḉ', 'ḉ'), ('ḋ', 'ḋ'), ('ḍ', 'ḍ'),
+  ('ḏ', 'ḏ'), ('ḑ', 'ḑ'), ('ḓ', 'ḓ'), ('ḕ', 'ḕ'),
+  ('ḗ', 'ḗ'), ('ḙ', 'ḙ'), ('ḛ', 'ḛ'), ('ḝ', 'ḝ'),
+  ('ḟ', 'ḟ'), ('ḡ', 'ḡ'), ('ḣ', 'ḣ'), ('ḥ', 'ḥ'),
+  ('ḧ', 'ḧ'), ('ḩ', 'ḩ'), ('ḫ', 'ḫ'), ('ḭ', 'ḭ'),
+  ('ḯ', 'ḯ'), ('ḱ', 'ḱ'), ('ḳ', 'ḳ'), ('ḵ', 'ḵ'),
+  ('ḷ', 'ḷ'), ('ḹ', 'ḹ'), ('ḻ', 'ḻ'), ('ḽ', 'ḽ'),
+  ('ḿ', 'ḿ'), ('ṁ', 'ṁ'), ('ṃ', 'ṃ'), ('ṅ', 'ṅ'),
+  ('ṇ', 'ṇ'), ('ṉ', 'ṉ'), ('ṋ', 'ṋ'), ('ṍ', 'ṍ'),
+  ('ṏ', 'ṏ'), ('ṑ', 'ṑ'), ('ṓ', 'ṓ'), ('ṕ', 'ṕ'),
+  ('ṗ', 'ṗ'), ('ṙ', 'ṙ'), ('ṛ', 'ṛ'), ('ṝ', 'ṝ'),
+  ('ṟ', 'ṟ'), ('ṡ', 'ṡ'), ('ṣ', 'ṣ'), ('ṥ', 'ṥ'),
+  ('ṧ', 'ṧ'), ('ṩ', 'ṩ'), ('ṫ', 'ṫ'), ('ṭ', 'ṭ'),
+  ('ṯ', 'ṯ'), ('ṱ', 'ṱ'), ('ṳ', 'ṳ'), ('ṵ', 'ṵ'),
+  ('ṷ', 'ṷ'), ('ṹ', 'ṹ'), ('ṻ', 'ṻ'), ('ṽ', 'ṽ'),
+  ('ṿ', 'ṿ'), ('ẁ', 'ẁ'), ('ẃ', 'ẃ'), ('ẅ', 'ẅ'),
+  ('ẇ', 'ẇ'), ('ẉ', 'ẉ'), ('ẋ', 'ẋ'), ('ẍ', 'ẍ'),
+  ('ẏ', 'ẏ'), ('ẑ', 'ẑ'), ('ẓ', 'ẓ'), ('ẕ', 'ẛ'),
+  ('ạ', 'ạ'), ('ả', 'ả'), ('ấ', 'ấ'), ('ầ', 'ầ'),
+  ('ẩ', 'ẩ'), ('ẫ', 'ẫ'), ('ậ', 'ậ'), ('ắ', 'ắ'),
+  ('ằ', 'ằ'), ('ẳ', 'ẳ'), ('ẵ', 'ẵ'), ('ặ', 'ặ'),
+  ('ẹ', 'ẹ'), ('ẻ', 'ẻ'), ('ẽ', 'ẽ'), ('ế', 'ế'),
+  ('ề', 'ề'), ('ể', 'ể'), ('ễ', 'ễ'), ('ệ', 'ệ'),
+  ('ỉ', 'ỉ'), ('ị', 'ị'), ('ọ', 'ọ'), ('ỏ', 'ỏ'),
+  ('ố', 'ố'), ('ồ', 'ồ'), ('ổ', 'ổ'), ('ỗ', 'ỗ'),
+  ('ộ', 'ộ'), ('ớ', 'ớ'), ('ờ', 'ờ'), ('ở', 'ở'),
+  ('ỡ', 'ỡ'), ('ợ', 'ợ'), ('ụ', 'ụ'), ('ủ', 'ủ'),
+  ('ứ', 'ứ'), ('ừ', 'ừ'), ('ử', 'ử'), ('ữ', 'ữ'),
+  ('ự', 'ự'), ('ỳ', 'ỳ'), ('ỵ', 'ỵ'), ('ỷ', 'ỷ'),
+  ('ỹ', 'ỹ'), ('ỻ', 'ỻ'), ('ỽ', 'ỽ'), ('ỿ', 'ἇ'),
+  ('ἐ', 'ἕ'), ('ἠ', 'ἧ'), ('ἰ', 'ἷ'), ('ὀ', 'ὅ'),
+  ('ὐ', 'ὗ'), ('ὠ', 'ὧ'), ('ὰ', 'ώ'), ('ᾀ', 'ᾇ'),
+  ('ᾐ', 'ᾗ'), ('ᾠ', 'ᾧ'), ('ᾰ', 'ᾴ'), ('ᾶ', 'ᾷ'),
+  ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῇ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'ῗ'), ('ῠ', 'ῧ'), ('ῲ', 'ῴ'), ('ῶ', 'ῷ'),
+  ('ⅎ', 'ⅎ'), ('ⅰ', 'ⅿ'), ('ↄ', 'ↄ'), ('ⓐ', 'ⓩ'),
+  ('ⰰ', 'ⱞ'), ('ⱡ', 'ⱡ'), ('ⱥ', 'ⱦ'), ('ⱨ', 'ⱨ'),
+  ('ⱪ', 'ⱪ'), ('ⱬ', 'ⱬ'), ('ⱳ', 'ⱳ'), ('ⱶ', 'ⱶ'),
+  ('ⲁ', 'ⲁ'), ('ⲃ', 'ⲃ'), ('ⲅ', 'ⲅ'), ('ⲇ', 'ⲇ'),
+  ('ⲉ', 'ⲉ'), ('ⲋ', 'ⲋ'), ('ⲍ', 'ⲍ'), ('ⲏ', 'ⲏ'),
+  ('ⲑ', 'ⲑ'), ('ⲓ', 'ⲓ'), ('ⲕ', 'ⲕ'), ('ⲗ', 'ⲗ'),
+  ('ⲙ', 'ⲙ'), ('ⲛ', 'ⲛ'), ('ⲝ', 'ⲝ'), ('ⲟ', 'ⲟ'),
+  ('ⲡ', 'ⲡ'), ('ⲣ', 'ⲣ'), ('ⲥ', 'ⲥ'), ('ⲧ', 'ⲧ'),
+  ('ⲩ', 'ⲩ'), ('ⲫ', 'ⲫ'), ('ⲭ', 'ⲭ'), ('ⲯ', 'ⲯ'),
+  ('ⲱ', 'ⲱ'), ('ⲳ', 'ⲳ'), ('ⲵ', 'ⲵ'), ('ⲷ', 'ⲷ'),
+  ('ⲹ', 'ⲹ'), ('ⲻ', 'ⲻ'), ('ⲽ', 'ⲽ'), ('ⲿ', 'ⲿ'),
+  ('ⳁ', 'ⳁ'), ('ⳃ', 'ⳃ'), ('ⳅ', 'ⳅ'), ('ⳇ', 'ⳇ'),
+  ('ⳉ', 'ⳉ'), ('ⳋ', 'ⳋ'), ('ⳍ', 'ⳍ'), ('ⳏ', 'ⳏ'),
+  ('ⳑ', 'ⳑ'), ('ⳓ', 'ⳓ'), ('ⳕ', 'ⳕ'), ('ⳗ', 'ⳗ'),
+  ('ⳙ', 'ⳙ'), ('ⳛ', 'ⳛ'), ('ⳝ', 'ⳝ'), ('ⳟ', 'ⳟ'),
+  ('ⳡ', 'ⳡ'), ('ⳣ', 'ⳣ'), ('ⳬ', 'ⳬ'), ('ⳮ', 'ⳮ'),
+  ('ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+  ('ꙁ', 'ꙁ'), ('ꙃ', 'ꙃ'), ('ꙅ', 'ꙅ'), ('ꙇ', 'ꙇ'),
+  ('ꙉ', 'ꙉ'), ('ꙋ', 'ꙋ'), ('ꙍ', 'ꙍ'), ('ꙏ', 'ꙏ'),
+  ('ꙑ', 'ꙑ'), ('ꙓ', 'ꙓ'), ('ꙕ', 'ꙕ'), ('ꙗ', 'ꙗ'),
+  ('ꙙ', 'ꙙ'), ('ꙛ', 'ꙛ'), ('ꙝ', 'ꙝ'), ('ꙟ', 'ꙟ'),
+  ('ꙡ', 'ꙡ'), ('ꙣ', 'ꙣ'), ('ꙥ', 'ꙥ'), ('ꙧ', 'ꙧ'),
+  ('ꙩ', 'ꙩ'), ('ꙫ', 'ꙫ'), ('ꙭ', 'ꙭ'), ('ꚁ', 'ꚁ'),
+  ('ꚃ', 'ꚃ'), ('ꚅ', 'ꚅ'), ('ꚇ', 'ꚇ'), ('ꚉ', 'ꚉ'),
+  ('ꚋ', 'ꚋ'), ('ꚍ', 'ꚍ'), ('ꚏ', 'ꚏ'), ('ꚑ', 'ꚑ'),
+  ('ꚓ', 'ꚓ'), ('ꚕ', 'ꚕ'), ('ꚗ', 'ꚗ'), ('ꚙ', 'ꚙ'),
+  ('ꚛ', 'ꚛ'), ('ꜣ', 'ꜣ'), ('ꜥ', 'ꜥ'), ('ꜧ', 'ꜧ'),
+  ('ꜩ', 'ꜩ'), ('ꜫ', 'ꜫ'), ('ꜭ', 'ꜭ'), ('ꜯ', 'ꜯ'),
+  ('ꜳ', 'ꜳ'), ('ꜵ', 'ꜵ'), ('ꜷ', 'ꜷ'), ('ꜹ', 'ꜹ'),
+  ('ꜻ', 'ꜻ'), ('ꜽ', 'ꜽ'), ('ꜿ', 'ꜿ'), ('ꝁ', 'ꝁ'),
+  ('ꝃ', 'ꝃ'), ('ꝅ', 'ꝅ'), ('ꝇ', 'ꝇ'), ('ꝉ', 'ꝉ'),
+  ('ꝋ', 'ꝋ'), ('ꝍ', 'ꝍ'), ('ꝏ', 'ꝏ'), ('ꝑ', 'ꝑ'),
+  ('ꝓ', 'ꝓ'), ('ꝕ', 'ꝕ'), ('ꝗ', 'ꝗ'), ('ꝙ', 'ꝙ'),
+  ('ꝛ', 'ꝛ'), ('ꝝ', 'ꝝ'), ('ꝟ', 'ꝟ'), ('ꝡ', 'ꝡ'),
+  ('ꝣ', 'ꝣ'), ('ꝥ', 'ꝥ'), ('ꝧ', 'ꝧ'), ('ꝩ', 'ꝩ'),
+  ('ꝫ', 'ꝫ'), ('ꝭ', 'ꝭ'), ('ꝯ', 'ꝯ'), ('ꝺ', 'ꝺ'),
+  ('ꝼ', 'ꝼ'), ('ꝿ', 'ꝿ'), ('ꞁ', 'ꞁ'), ('ꞃ', 'ꞃ'),
+  ('ꞅ', 'ꞅ'), ('ꞇ', 'ꞇ'), ('ꞌ', 'ꞌ'), ('ꞑ', 'ꞑ'),
+  ('ꞓ', 'ꞓ'), ('ꞗ', 'ꞗ'), ('ꞙ', 'ꞙ'), ('ꞛ', 'ꞛ'),
+  ('ꞝ', 'ꞝ'), ('ꞟ', 'ꞟ'), ('ꞡ', 'ꞡ'), ('ꞣ', 'ꞣ'),
+  ('ꞥ', 'ꞥ'), ('ꞧ', 'ꞧ'), ('ꞩ', 'ꞩ'), ('ꞵ', 'ꞵ'),
+  ('ꞷ', 'ꞷ'), ('\u{a7b9}', '\u{a7b9}'), ('ꭓ', 'ꭓ'), ('ꭰ', 'ꮿ'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('ａ', 'ｚ'), ('𐐨', '𐑏'),
+  ('𐓘', '𐓻'), ('𐳀', '𐳲'), ('𑣀', '𑣟'),
+  ('\u{16e60}', '\u{16e7f}'), ('𞤢', '𞥃'),
+];
+
+pub const CHANGES_WHEN_UPPERCASED: &'static [(char, char)] = &[
+  ('a', 'z'), ('µ', 'µ'), ('ß', 'ö'), ('ø', 'ÿ'), ('ā', 'ā'),
+  ('ă', 'ă'), ('ą', 'ą'), ('ć', 'ć'), ('ĉ', 'ĉ'), ('ċ', 'ċ'),
+  ('č', 'č'), ('ď', 'ď'), ('đ', 'đ'), ('ē', 'ē'), ('ĕ', 'ĕ'),
+  ('ė', 'ė'), ('ę', 'ę'), ('ě', 'ě'), ('ĝ', 'ĝ'), ('ğ', 'ğ'),
+  ('ġ', 'ġ'), ('ģ', 'ģ'), ('ĥ', 'ĥ'), ('ħ', 'ħ'), ('ĩ', 'ĩ'),
+  ('ī', 'ī'), ('ĭ', 'ĭ'), ('į', 'į'), ('ı', 'ı'), ('ĳ', 'ĳ'),
+  ('ĵ', 'ĵ'), ('ķ', 'ķ'), ('ĺ', 'ĺ'), ('ļ', 'ļ'), ('ľ', 'ľ'),
+  ('ŀ', 'ŀ'), ('ł', 'ł'), ('ń', 'ń'), ('ņ', 'ņ'), ('ň', 'ŉ'),
+  ('ŋ', 'ŋ'), ('ō', 'ō'), ('ŏ', 'ŏ'), ('ő', 'ő'), ('œ', 'œ'),
+  ('ŕ', 'ŕ'), ('ŗ', 'ŗ'), ('ř', 'ř'), ('ś', 'ś'), ('ŝ', 'ŝ'),
+  ('ş', 'ş'), ('š', 'š'), ('ţ', 'ţ'), ('ť', 'ť'), ('ŧ', 'ŧ'),
+  ('ũ', 'ũ'), ('ū', 'ū'), ('ŭ', 'ŭ'), ('ů', 'ů'), ('ű', 'ű'),
+  ('ų', 'ų'), ('ŵ', 'ŵ'), ('ŷ', 'ŷ'), ('ź', 'ź'), ('ż', 'ż'),
+  ('ž', 'ƀ'), ('ƃ', 'ƃ'), ('ƅ', 'ƅ'), ('ƈ', 'ƈ'), ('ƌ', 'ƌ'),
+  ('ƒ', 'ƒ'), ('ƕ', 'ƕ'), ('ƙ', 'ƚ'), ('ƞ', 'ƞ'), ('ơ', 'ơ'),
+  ('ƣ', 'ƣ'), ('ƥ', 'ƥ'), ('ƨ', 'ƨ'), ('ƭ', 'ƭ'), ('ư', 'ư'),
+  ('ƴ', 'ƴ'), ('ƶ', 'ƶ'), ('ƹ', 'ƹ'), ('ƽ', 'ƽ'), ('ƿ', 'ƿ'),
+  ('ǅ', 'ǆ'), ('ǈ', 'ǉ'), ('ǋ', 'ǌ'), ('ǎ', 'ǎ'), ('ǐ', 'ǐ'),
+  ('ǒ', 'ǒ'), ('ǔ', 'ǔ'), ('ǖ', 'ǖ'), ('ǘ', 'ǘ'), ('ǚ', 'ǚ'),
+  ('ǜ', 'ǝ'), ('ǟ', 'ǟ'), ('ǡ', 'ǡ'), ('ǣ', 'ǣ'), ('ǥ', 'ǥ'),
+  ('ǧ', 'ǧ'), ('ǩ', 'ǩ'), ('ǫ', 'ǫ'), ('ǭ', 'ǭ'), ('ǯ', 'ǰ'),
+  ('ǲ', 'ǳ'), ('ǵ', 'ǵ'), ('ǹ', 'ǹ'), ('ǻ', 'ǻ'), ('ǽ', 'ǽ'),
+  ('ǿ', 'ǿ'), ('ȁ', 'ȁ'), ('ȃ', 'ȃ'), ('ȅ', 'ȅ'), ('ȇ', 'ȇ'),
+  ('ȉ', 'ȉ'), ('ȋ', 'ȋ'), ('ȍ', 'ȍ'), ('ȏ', 'ȏ'), ('ȑ', 'ȑ'),
+  ('ȓ', 'ȓ'), ('ȕ', 'ȕ'), ('ȗ', 'ȗ'), ('ș', 'ș'), ('ț', 'ț'),
+  ('ȝ', 'ȝ'), ('ȟ', 'ȟ'), ('ȣ', 'ȣ'), ('ȥ', 'ȥ'), ('ȧ', 'ȧ'),
+  ('ȩ', 'ȩ'), ('ȫ', 'ȫ'), ('ȭ', 'ȭ'), ('ȯ', 'ȯ'), ('ȱ', 'ȱ'),
+  ('ȳ', 'ȳ'), ('ȼ', 'ȼ'), ('ȿ', 'ɀ'), ('ɂ', 'ɂ'), ('ɇ', 'ɇ'),
+  ('ɉ', 'ɉ'), ('ɋ', 'ɋ'), ('ɍ', 'ɍ'), ('ɏ', 'ɔ'), ('ɖ', 'ɗ'),
+  ('ə', 'ə'), ('ɛ', 'ɜ'), ('ɠ', 'ɡ'), ('ɣ', 'ɣ'), ('ɥ', 'ɦ'),
+  ('ɨ', 'ɬ'), ('ɯ', 'ɯ'), ('ɱ', 'ɲ'), ('ɵ', 'ɵ'), ('ɽ', 'ɽ'),
+  ('ʀ', 'ʀ'), ('ʃ', 'ʃ'), ('ʇ', 'ʌ'), ('ʒ', 'ʒ'), ('ʝ', 'ʞ'),
+  ('ͅ', 'ͅ'), ('ͱ', 'ͱ'), ('ͳ', 'ͳ'), ('ͷ', 'ͷ'), ('ͻ', 'ͽ'),
+  ('ΐ', 'ΐ'), ('ά', 'ώ'), ('ϐ', 'ϑ'), ('ϕ', 'ϗ'), ('ϙ', 'ϙ'),
+  ('ϛ', 'ϛ'), ('ϝ', 'ϝ'), ('ϟ', 'ϟ'), ('ϡ', 'ϡ'), ('ϣ', 'ϣ'),
+  ('ϥ', 'ϥ'), ('ϧ', 'ϧ'), ('ϩ', 'ϩ'), ('ϫ', 'ϫ'), ('ϭ', 'ϭ'),
+  ('ϯ', 'ϳ'), ('ϵ', 'ϵ'), ('ϸ', 'ϸ'), ('ϻ', 'ϻ'), ('а', 'џ'),
+  ('ѡ', 'ѡ'), ('ѣ', 'ѣ'), ('ѥ', 'ѥ'), ('ѧ', 'ѧ'), ('ѩ', 'ѩ'),
+  ('ѫ', 'ѫ'), ('ѭ', 'ѭ'), ('ѯ', 'ѯ'), ('ѱ', 'ѱ'), ('ѳ', 'ѳ'),
+  ('ѵ', 'ѵ'), ('ѷ', 'ѷ'), ('ѹ', 'ѹ'), ('ѻ', 'ѻ'), ('ѽ', 'ѽ'),
+  ('ѿ', 'ѿ'), ('ҁ', 'ҁ'), ('ҋ', 'ҋ'), ('ҍ', 'ҍ'), ('ҏ', 'ҏ'),
+  ('ґ', 'ґ'), ('ғ', 'ғ'), ('ҕ', 'ҕ'), ('җ', 'җ'), ('ҙ', 'ҙ'),
+  ('қ', 'қ'), ('ҝ', 'ҝ'), ('ҟ', 'ҟ'), ('ҡ', 'ҡ'), ('ң', 'ң'),
+  ('ҥ', 'ҥ'), ('ҧ', 'ҧ'), ('ҩ', 'ҩ'), ('ҫ', 'ҫ'), ('ҭ', 'ҭ'),
+  ('ү', 'ү'), ('ұ', 'ұ'), ('ҳ', 'ҳ'), ('ҵ', 'ҵ'), ('ҷ', 'ҷ'),
+  ('ҹ', 'ҹ'), ('һ', 'һ'), ('ҽ', 'ҽ'), ('ҿ', 'ҿ'), ('ӂ', 'ӂ'),
+  ('ӄ', 'ӄ'), ('ӆ', 'ӆ'), ('ӈ', 'ӈ'), ('ӊ', 'ӊ'), ('ӌ', 'ӌ'),
+  ('ӎ', 'ӏ'), ('ӑ', 'ӑ'), ('ӓ', 'ӓ'), ('ӕ', 'ӕ'), ('ӗ', 'ӗ'),
+  ('ә', 'ә'), ('ӛ', 'ӛ'), ('ӝ', 'ӝ'), ('ӟ', 'ӟ'), ('ӡ', 'ӡ'),
+  ('ӣ', 'ӣ'), ('ӥ', 'ӥ'), ('ӧ', 'ӧ'), ('ө', 'ө'), ('ӫ', 'ӫ'),
+  ('ӭ', 'ӭ'), ('ӯ', 'ӯ'), ('ӱ', 'ӱ'), ('ӳ', 'ӳ'), ('ӵ', 'ӵ'),
+  ('ӷ', 'ӷ'), ('ӹ', 'ӹ'), ('ӻ', 'ӻ'), ('ӽ', 'ӽ'), ('ӿ', 'ӿ'),
+  ('ԁ', 'ԁ'), ('ԃ', 'ԃ'), ('ԅ', 'ԅ'), ('ԇ', 'ԇ'), ('ԉ', 'ԉ'),
+  ('ԋ', 'ԋ'), ('ԍ', 'ԍ'), ('ԏ', 'ԏ'), ('ԑ', 'ԑ'), ('ԓ', 'ԓ'),
+  ('ԕ', 'ԕ'), ('ԗ', 'ԗ'), ('ԙ', 'ԙ'), ('ԛ', 'ԛ'), ('ԝ', 'ԝ'),
+  ('ԟ', 'ԟ'), ('ԡ', 'ԡ'), ('ԣ', 'ԣ'), ('ԥ', 'ԥ'), ('ԧ', 'ԧ'),
+  ('ԩ', 'ԩ'), ('ԫ', 'ԫ'), ('ԭ', 'ԭ'), ('ԯ', 'ԯ'), ('ա', 'և'),
+  ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('ᏸ', 'ᏽ'), ('ᲀ', 'ᲈ'),
+  ('ᵹ', 'ᵹ'), ('ᵽ', 'ᵽ'), ('ḁ', 'ḁ'), ('ḃ', 'ḃ'),
+  ('ḅ', 'ḅ'), ('ḇ', 'ḇ'), ('ḉ', 'ḉ'), ('ḋ', 'ḋ'),
+  ('ḍ', 'ḍ'), ('ḏ', 'ḏ'), ('ḑ', 'ḑ'), ('ḓ', 'ḓ'),
+  ('ḕ', 'ḕ'), ('ḗ', 'ḗ'), ('ḙ', 'ḙ'), ('ḛ', 'ḛ'),
+  ('ḝ', 'ḝ'), ('ḟ', 'ḟ'), ('ḡ', 'ḡ'), ('ḣ', 'ḣ'),
+  ('ḥ', 'ḥ'), ('ḧ', 'ḧ'), ('ḩ', 'ḩ'), ('ḫ', 'ḫ'),
+  ('ḭ', 'ḭ'), ('ḯ', 'ḯ'), ('ḱ', 'ḱ'), ('ḳ', 'ḳ'),
+  ('ḵ', 'ḵ'), ('ḷ', 'ḷ'), ('ḹ', 'ḹ'), ('ḻ', 'ḻ'),
+  ('ḽ', 'ḽ'), ('ḿ', 'ḿ'), ('ṁ', 'ṁ'), ('ṃ', 'ṃ'),
+  ('ṅ', 'ṅ'), ('ṇ', 'ṇ'), ('ṉ', 'ṉ'), ('ṋ', 'ṋ'),
+  ('ṍ', 'ṍ'), ('ṏ', 'ṏ'), ('ṑ', 'ṑ'), ('ṓ', 'ṓ'),
+  ('ṕ', 'ṕ'), ('ṗ', 'ṗ'), ('ṙ', 'ṙ'), ('ṛ', 'ṛ'),
+  ('ṝ', 'ṝ'), ('ṟ', 'ṟ'), ('ṡ', 'ṡ'), ('ṣ', 'ṣ'),
+  ('ṥ', 'ṥ'), ('ṧ', 'ṧ'), ('ṩ', 'ṩ'), ('ṫ', 'ṫ'),
+  ('ṭ', 'ṭ'), ('ṯ', 'ṯ'), ('ṱ', 'ṱ'), ('ṳ', 'ṳ'),
+  ('ṵ', 'ṵ'), ('ṷ', 'ṷ'), ('ṹ', 'ṹ'), ('ṻ', 'ṻ'),
+  ('ṽ', 'ṽ'), ('ṿ', 'ṿ'), ('ẁ', 'ẁ'), ('ẃ', 'ẃ'),
+  ('ẅ', 'ẅ'), ('ẇ', 'ẇ'), ('ẉ', 'ẉ'), ('ẋ', 'ẋ'),
+  ('ẍ', 'ẍ'), ('ẏ', 'ẏ'), ('ẑ', 'ẑ'), ('ẓ', 'ẓ'),
+  ('ẕ', 'ẛ'), ('ạ', 'ạ'), ('ả', 'ả'), ('ấ', 'ấ'),
+  ('ầ', 'ầ'), ('ẩ', 'ẩ'), ('ẫ', 'ẫ'), ('ậ', 'ậ'),
+  ('ắ', 'ắ'), ('ằ', 'ằ'), ('ẳ', 'ẳ'), ('ẵ', 'ẵ'),
+  ('ặ', 'ặ'), ('ẹ', 'ẹ'), ('ẻ', 'ẻ'), ('ẽ', 'ẽ'),
+  ('ế', 'ế'), ('ề', 'ề'), ('ể', 'ể'), ('ễ', 'ễ'),
+  ('ệ', 'ệ'), ('ỉ', 'ỉ'), ('ị', 'ị'), ('ọ', 'ọ'),
+  ('ỏ', 'ỏ'), ('ố', 'ố'), ('ồ', 'ồ'), ('ổ', 'ổ'),
+  ('ỗ', 'ỗ'), ('ộ', 'ộ'), ('ớ', 'ớ'), ('ờ', 'ờ'),
+  ('ở', 'ở'), ('ỡ', 'ỡ'), ('ợ', 'ợ'), ('ụ', 'ụ'),
+  ('ủ', 'ủ'), ('ứ', 'ứ'), ('ừ', 'ừ'), ('ử', 'ử'),
+  ('ữ', 'ữ'), ('ự', 'ự'), ('ỳ', 'ỳ'), ('ỵ', 'ỵ'),
+  ('ỷ', 'ỷ'), ('ỹ', 'ỹ'), ('ỻ', 'ỻ'), ('ỽ', 'ỽ'),
+  ('ỿ', 'ἇ'), ('ἐ', 'ἕ'), ('ἠ', 'ἧ'), ('ἰ', 'ἷ'),
+  ('ὀ', 'ὅ'), ('ὐ', 'ὗ'), ('ὠ', 'ὧ'), ('ὰ', 'ώ'),
+  ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾷ'), ('ᾼ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῇ'), ('ῌ', 'ῌ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'ῗ'), ('ῠ', 'ῧ'), ('ῲ', 'ῴ'), ('ῶ', 'ῷ'),
+  ('ῼ', 'ῼ'), ('ⅎ', 'ⅎ'), ('ⅰ', 'ⅿ'), ('ↄ', 'ↄ'),
+  ('ⓐ', 'ⓩ'), ('ⰰ', 'ⱞ'), ('ⱡ', 'ⱡ'), ('ⱥ', 'ⱦ'),
+  ('ⱨ', 'ⱨ'), ('ⱪ', 'ⱪ'), ('ⱬ', 'ⱬ'), ('ⱳ', 'ⱳ'),
+  ('ⱶ', 'ⱶ'), ('ⲁ', 'ⲁ'), ('ⲃ', 'ⲃ'), ('ⲅ', 'ⲅ'),
+  ('ⲇ', 'ⲇ'), ('ⲉ', 'ⲉ'), ('ⲋ', 'ⲋ'), ('ⲍ', 'ⲍ'),
+  ('ⲏ', 'ⲏ'), ('ⲑ', 'ⲑ'), ('ⲓ', 'ⲓ'), ('ⲕ', 'ⲕ'),
+  ('ⲗ', 'ⲗ'), ('ⲙ', 'ⲙ'), ('ⲛ', 'ⲛ'), ('ⲝ', 'ⲝ'),
+  ('ⲟ', 'ⲟ'), ('ⲡ', 'ⲡ'), ('ⲣ', 'ⲣ'), ('ⲥ', 'ⲥ'),
+  ('ⲧ', 'ⲧ'), ('ⲩ', 'ⲩ'), ('ⲫ', 'ⲫ'), ('ⲭ', 'ⲭ'),
+  ('ⲯ', 'ⲯ'), ('ⲱ', 'ⲱ'), ('ⲳ', 'ⲳ'), ('ⲵ', 'ⲵ'),
+  ('ⲷ', 'ⲷ'), ('ⲹ', 'ⲹ'), ('ⲻ', 'ⲻ'), ('ⲽ', 'ⲽ'),
+  ('ⲿ', 'ⲿ'), ('ⳁ', 'ⳁ'), ('ⳃ', 'ⳃ'), ('ⳅ', 'ⳅ'),
+  ('ⳇ', 'ⳇ'), ('ⳉ', 'ⳉ'), ('ⳋ', 'ⳋ'), ('ⳍ', 'ⳍ'),
+  ('ⳏ', 'ⳏ'), ('ⳑ', 'ⳑ'), ('ⳓ', 'ⳓ'), ('ⳕ', 'ⳕ'),
+  ('ⳗ', 'ⳗ'), ('ⳙ', 'ⳙ'), ('ⳛ', 'ⳛ'), ('ⳝ', 'ⳝ'),
+  ('ⳟ', 'ⳟ'), ('ⳡ', 'ⳡ'), ('ⳣ', 'ⳣ'), ('ⳬ', 'ⳬ'),
+  ('ⳮ', 'ⳮ'), ('ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'),
+  ('ⴭ', 'ⴭ'), ('ꙁ', 'ꙁ'), ('ꙃ', 'ꙃ'), ('ꙅ', 'ꙅ'),
+  ('ꙇ', 'ꙇ'), ('ꙉ', 'ꙉ'), ('ꙋ', 'ꙋ'), ('ꙍ', 'ꙍ'),
+  ('ꙏ', 'ꙏ'), ('ꙑ', 'ꙑ'), ('ꙓ', 'ꙓ'), ('ꙕ', 'ꙕ'),
+  ('ꙗ', 'ꙗ'), ('ꙙ', 'ꙙ'), ('ꙛ', 'ꙛ'), ('ꙝ', 'ꙝ'),
+  ('ꙟ', 'ꙟ'), ('ꙡ', 'ꙡ'), ('ꙣ', 'ꙣ'), ('ꙥ', 'ꙥ'),
+  ('ꙧ', 'ꙧ'), ('ꙩ', 'ꙩ'), ('ꙫ', 'ꙫ'), ('ꙭ', 'ꙭ'),
+  ('ꚁ', 'ꚁ'), ('ꚃ', 'ꚃ'), ('ꚅ', 'ꚅ'), ('ꚇ', 'ꚇ'),
+  ('ꚉ', 'ꚉ'), ('ꚋ', 'ꚋ'), ('ꚍ', 'ꚍ'), ('ꚏ', 'ꚏ'),
+  ('ꚑ', 'ꚑ'), ('ꚓ', 'ꚓ'), ('ꚕ', 'ꚕ'), ('ꚗ', 'ꚗ'),
+  ('ꚙ', 'ꚙ'), ('ꚛ', 'ꚛ'), ('ꜣ', 'ꜣ'), ('ꜥ', 'ꜥ'),
+  ('ꜧ', 'ꜧ'), ('ꜩ', 'ꜩ'), ('ꜫ', 'ꜫ'), ('ꜭ', 'ꜭ'),
+  ('ꜯ', 'ꜯ'), ('ꜳ', 'ꜳ'), ('ꜵ', 'ꜵ'), ('ꜷ', 'ꜷ'),
+  ('ꜹ', 'ꜹ'), ('ꜻ', 'ꜻ'), ('ꜽ', 'ꜽ'), ('ꜿ', 'ꜿ'),
+  ('ꝁ', 'ꝁ'), ('ꝃ', 'ꝃ'), ('ꝅ', 'ꝅ'), ('ꝇ', 'ꝇ'),
+  ('ꝉ', 'ꝉ'), ('ꝋ', 'ꝋ'), ('ꝍ', 'ꝍ'), ('ꝏ', 'ꝏ'),
+  ('ꝑ', 'ꝑ'), ('ꝓ', 'ꝓ'), ('ꝕ', 'ꝕ'), ('ꝗ', 'ꝗ'),
+  ('ꝙ', 'ꝙ'), ('ꝛ', 'ꝛ'), ('ꝝ', 'ꝝ'), ('ꝟ', 'ꝟ'),
+  ('ꝡ', 'ꝡ'), ('ꝣ', 'ꝣ'), ('ꝥ', 'ꝥ'), ('ꝧ', 'ꝧ'),
+  ('ꝩ', 'ꝩ'), ('ꝫ', 'ꝫ'), ('ꝭ', 'ꝭ'), ('ꝯ', 'ꝯ'),
+  ('ꝺ', 'ꝺ'), ('ꝼ', 'ꝼ'), ('ꝿ', 'ꝿ'), ('ꞁ', 'ꞁ'),
+  ('ꞃ', 'ꞃ'), ('ꞅ', 'ꞅ'), ('ꞇ', 'ꞇ'), ('ꞌ', 'ꞌ'),
+  ('ꞑ', 'ꞑ'), ('ꞓ', 'ꞓ'), ('ꞗ', 'ꞗ'), ('ꞙ', 'ꞙ'),
+  ('ꞛ', 'ꞛ'), ('ꞝ', 'ꞝ'), ('ꞟ', 'ꞟ'), ('ꞡ', 'ꞡ'),
+  ('ꞣ', 'ꞣ'), ('ꞥ', 'ꞥ'), ('ꞧ', 'ꞧ'), ('ꞩ', 'ꞩ'),
+  ('ꞵ', 'ꞵ'), ('ꞷ', 'ꞷ'), ('\u{a7b9}', '\u{a7b9}'), ('ꭓ', 'ꭓ'),
+  ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('ａ', 'ｚ'),
+  ('𐐨', '𐑏'), ('𐓘', '𐓻'), ('𐳀', '𐳲'), ('𑣀', '𑣟'),
+  ('\u{16e60}', '\u{16e7f}'), ('𞤢', '𞥃'),
+];
+
+pub const DASH: &'static [(char, char)] = &[
+  ('-', '-'), ('֊', '֊'), ('־', '־'), ('᐀', '᐀'), ('᠆', '᠆'),
+  ('‐', '―'), ('⁓', '⁓'), ('⁻', '⁻'), ('₋', '₋'),
+  ('−', '−'), ('⸗', '⸗'), ('⸚', '⸚'), ('⸺', '⸻'),
+  ('⹀', '⹀'), ('〜', '〜'), ('〰', '〰'), ('゠', '゠'),
+  ('︱', '︲'), ('﹘', '﹘'), ('﹣', '﹣'), ('－', '－'),
+];
+
+pub const DEFAULT_IGNORABLE_CODE_POINT: &'static [(char, char)] = &[
+  ('\u{ad}', '\u{ad}'), ('͏', '͏'), ('\u{61c}', '\u{61c}'), ('ᅟ', 'ᅠ'),
+  ('឴', '឵'), ('᠋', '\u{180e}'), ('\u{200b}', '\u{200f}'),
+  ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{206f}'), ('ㅤ', 'ㅤ'),
+  ('︀', '️'), ('\u{feff}', '\u{feff}'), ('ﾠ', 'ﾠ'),
+  ('\u{fff0}', '\u{fff8}'), ('\u{1bca0}', '\u{1bca3}'),
+  ('\u{1d173}', '\u{1d17a}'), ('\u{e0000}', '\u{e0fff}'),
+];
+
+pub const DEPRECATED: &'static [(char, char)] = &[
+  ('ŉ', 'ŉ'), ('ٳ', 'ٳ'), ('ཷ', 'ཷ'), ('ཹ', 'ཹ'), ('ឣ', 'ឤ'),
+  ('\u{206a}', '\u{206f}'), ('〈', '〉'), ('\u{e0001}', '\u{e0001}'),
+];
+
+pub const DIACRITIC: &'static [(char, char)] = &[
+  ('^', '^'), ('`', '`'), ('¨', '¨'), ('¯', '¯'), ('´', '´'),
+  ('·', '¸'), ('ʰ', '͎'), ('͐', '͗'), ('͝', '͢'), ('ʹ', '͵'),
+  ('ͺ', 'ͺ'), ('΄', '΅'), ('҃', '҇'), ('ՙ', 'ՙ'), ('֑', '֡'),
+  ('֣', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'), ('ׄ', 'ׄ'), ('ً', 'ْ'),
+  ('ٗ', '٘'), ('۟', '۠'), ('ۥ', 'ۦ'), ('۪', '۬'), ('ܰ', '݊'),
+  ('ަ', 'ް'), ('߫', 'ߵ'), ('࠘', '࠙'), ('ࣣ', 'ࣾ'), ('़', '़'),
+  ('्', '्'), ('॑', '॔'), ('ॱ', 'ॱ'), ('়', '়'),
+  ('্', '্'), ('਼', '਼'), ('੍', '੍'), ('઼', '઼'),
+  ('્', '્'), ('૽', '૿'), ('଼', '଼'), ('୍', '୍'),
+  ('்', '்'), ('్', '్'), ('಼', '಼'), ('್', '್'),
+  ('഻', '഼'), ('്', '്'), ('්', '්'), ('็', '์'),
+  ('๎', '๎'), ('່', '໌'), ('༘', '༙'), ('༵', '༵'),
+  ('༷', '༷'), ('༹', '༹'), ('༾', '༿'), ('ྂ', '྄'),
+  ('྆', '྇'), ('࿆', '࿆'), ('့', '့'), ('္', '်'),
+  ('ႇ', 'ႍ'), ('ႏ', 'ႏ'), ('ႚ', 'ႛ'), ('៉', '៓'),
+  ('៝', '៝'), ('᤹', '᤻'), ('᩵', '᩼'), ('᩿', '᩿'),
+  ('᪰', '᪽'), ('᬴', '᬴'), ('᭄', '᭄'), ('᭫', '᭳'),
+  ('᮪', '᮫'), ('ᰶ', '᰷'), ('ᱸ', 'ᱽ'), ('᳐', '᳨'),
+  ('᳭', '᳭'), ('᳴', '᳴'), ('᳷', '᳹'), ('ᴬ', 'ᵪ'),
+  ('᷄', '᷏'), ('᷵', '᷹'), ('᷽', '᷿'), ('᾽', '᾽'),
+  ('᾿', '῁'), ('῍', '῏'), ('῝', '῟'), ('῭', '`'),
+  ('´', '῾'), ('⳯', '⳱'), ('ⸯ', 'ⸯ'), ('〪', '〯'),
+  ('゙', '゜'), ('ー', 'ー'), ('꙯', '꙯'), ('꙼', '꙽'),
+  ('ꙿ', 'ꙿ'), ('ꚜ', 'ꚝ'), ('꛰', '꛱'), ('ꜗ', '꜡'),
+  ('ꞈ', 'ꞈ'), ('ꟸ', 'ꟹ'), ('꣄', '꣄'), ('꣠', '꣱'),
+  ('꤫', '꤮'), ('꥓', '꥓'), ('꦳', '꦳'), ('꧀', '꧀'),
+  ('ꧥ', 'ꧥ'), ('ꩻ', 'ꩽ'), ('꪿', 'ꫂ'), ('꫶', '꫶'),
+  ('꭛', 'ꭟ'), ('꯬', '꯭'), ('ﬞ', 'ﬞ'), ('︠', '︯'),
+  ('＾', '＾'), ('｀', '｀'), ('ｰ', 'ｰ'), ('ﾞ', 'ﾟ'),
+  ('￣', '￣'), ('𐋠', '𐋠'), ('𐫥', '𐫦'),
+  ('\u{10d22}', '\u{10d27}'), ('\u{10f46}', '\u{10f50}'), ('𑂹', '𑂺'),
+  ('𑄳', '𑄴'), ('𑅳', '𑅳'), ('𑇀', '𑇀'), ('𑇊', '𑇌'),
+  ('𑈵', '𑈶'), ('𑋩', '𑋪'), ('𑌼', '𑌼'), ('𑍍', '𑍍'),
+  ('𑍦', '𑍬'), ('𑍰', '𑍴'), ('𑑂', '𑑂'), ('𑑆', '𑑆'),
+  ('𑓂', '𑓃'), ('𑖿', '𑗀'), ('𑘿', '𑘿'), ('𑚶', '𑚷'),
+  ('𑜫', '𑜫'), ('\u{11839}', '\u{1183a}'), ('𑨴', '𑨴'),
+  ('𑩇', '𑩇'), ('𑪙', '𑪙'), ('𑰿', '𑰿'), ('𑵂', '𑵂'),
+  ('𑵄', '𑵅'), ('\u{11d97}', '\u{11d97}'), ('𖫰', '𖫴'),
+  ('𖾏', '𖾟'), ('𝅧', '𝅩'), ('𝅭', '𝅲'), ('𝅻', '𝆂'),
+  ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('𞣐', '𞣖'), ('𞥄', '𞥆'),
+  ('𞥈', '𞥊'),
+];
+
+pub const EXTENDER: &'static [(char, char)] = &[
+  ('·', '·'), ('ː', 'ˑ'), ('ـ', 'ـ'), ('ߺ', 'ߺ'), ('ๆ', 'ๆ'),
+  ('ໆ', 'ໆ'), ('᠊', '᠊'), ('ᡃ', 'ᡃ'), ('ᪧ', 'ᪧ'),
+  ('ᰶ', 'ᰶ'), ('ᱻ', 'ᱻ'), ('々', '々'), ('〱', '〵'),
+  ('ゝ', 'ゞ'), ('ー', 'ヾ'), ('ꀕ', 'ꀕ'), ('ꘌ', 'ꘌ'),
+  ('ꧏ', 'ꧏ'), ('ꧦ', 'ꧦ'), ('ꩰ', 'ꩰ'), ('ꫝ', 'ꫝ'),
+  ('ꫳ', 'ꫴ'), ('ｰ', 'ｰ'), ('𑍝', '𑍝'), ('𑗆', '𑗈'),
+  ('𑪘', '𑪘'), ('𖭂', '𖭃'), ('𖿠', '𖿡'), ('𞥄', '𞥆'),
+];
+
+pub const GRAPHEME_BASE: &'static [(char, char)] = &[
+  (' ', '~'), ('\u{a0}', '¬'), ('®', '˿'), ('Ͱ', 'ͷ'), ('ͺ', 'Ϳ'),
+  ('΄', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'), ('Σ', '҂'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('ՙ', '֊'), ('֍', '֏'), ('־', '־'), ('׀', '׀'),
+  ('׃', '׃'), ('׆', '׆'), ('א', 'ת'), ('\u{5ef}', '״'), ('؆', '؏'),
+  ('؛', '؛'), ('؞', 'ي'), ('٠', 'ٯ'), ('ٱ', 'ە'), ('۞', '۞'),
+  ('ۥ', 'ۦ'), ('۩', '۩'), ('ۮ', '܍'), ('ܐ', 'ܐ'), ('ܒ', 'ܯ'),
+  ('ݍ', 'ޥ'), ('ޱ', 'ޱ'), ('߀', 'ߪ'), ('ߴ', 'ߺ'), ('\u{7fe}', 'ࠕ'),
+  ('ࠚ', 'ࠚ'), ('ࠤ', 'ࠤ'), ('ࠨ', 'ࠨ'), ('࠰', '࠾'),
+  ('ࡀ', 'ࡘ'), ('࡞', '࡞'), ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'),
+  ('ࢶ', 'ࢽ'), ('ः', 'ह'), ('ऻ', 'ऻ'), ('ऽ', 'ी'),
+  ('ॉ', 'ौ'), ('ॎ', 'ॐ'), ('क़', 'ॡ'), ('।', 'ঀ'),
+  ('ং', 'ঃ'), ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'),
+  ('প', 'র'), ('ল', 'ল'), ('শ', 'হ'), ('ঽ', 'ঽ'),
+  ('ি', 'ী'), ('ে', 'ৈ'), ('ো', 'ৌ'), ('ৎ', 'ৎ'),
+  ('ড়', 'ঢ়'), ('য়', 'ৡ'), ('০', '৽'), ('ਃ', 'ਃ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('ਾ', 'ੀ'),
+  ('ਖ਼', 'ੜ'), ('ਫ਼', 'ਫ਼'), ('੦', '੯'), ('ੲ', 'ੴ'),
+  ('\u{a76}', '\u{a76}'), ('ઃ', 'ઃ'), ('અ', 'ઍ'), ('એ', 'ઑ'),
+  ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'), ('વ', 'હ'),
+  ('ઽ', 'ી'), ('ૉ', 'ૉ'), ('ો', 'ૌ'), ('ૐ', 'ૐ'),
+  ('ૠ', 'ૡ'), ('૦', '૱'), ('ૹ', 'ૹ'), ('ଂ', 'ଃ'),
+  ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'),
+  ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('ଽ', 'ଽ'), ('ୀ', 'ୀ'),
+  ('େ', 'ୈ'), ('ୋ', 'ୌ'), ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୡ'),
+  ('୦', '୷'), ('ஃ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'),
+  ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'),
+  ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'), ('ி', 'ி'),
+  ('ு', 'ூ'), ('ெ', 'ை'), ('ொ', 'ௌ'), ('ௐ', 'ௐ'),
+  ('௦', '௺'), ('ఁ', 'ః'), ('అ', 'ఌ'), ('ఎ', 'ఐ'),
+  ('ఒ', 'న'), ('ప', 'హ'), ('ఽ', 'ఽ'), ('ు', 'ౄ'),
+  ('ౘ', 'ౚ'), ('ౠ', 'ౡ'), ('౦', '౯'), ('౸', 'ಀ'),
+  ('ಂ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'),
+  ('ವ', 'ಹ'), ('ಽ', 'ಾ'), ('ೀ', 'ು'), ('ೃ', 'ೄ'),
+  ('ೇ', 'ೈ'), ('ೊ', 'ೋ'), ('ೞ', 'ೞ'), ('ೠ', 'ೡ'),
+  ('೦', '೯'), ('ೱ', 'ೲ'), ('ം', 'ഃ'), ('അ', 'ഌ'),
+  ('എ', 'ഐ'), ('ഒ', 'ഺ'), ('ഽ', 'ഽ'), ('ി', 'ീ'),
+  ('െ', 'ൈ'), ('ൊ', 'ൌ'), ('ൎ', '൏'), ('ൔ', 'ൖ'),
+  ('൘', 'ൡ'), ('൦', 'ൿ'), ('ං', 'ඃ'), ('අ', 'ඖ'),
+  ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'),
+  ('ැ', 'ෑ'), ('ෘ', 'ෞ'), ('෦', '෯'), ('ෲ', '෴'),
+  ('ก', 'ะ'), ('า', 'ำ'), ('฿', 'ๆ'), ('๏', '๛'),
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ະ'),
+  ('າ', 'ຳ'), ('ຽ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'),
+  ('໐', '໙'), ('ໜ', 'ໟ'), ('ༀ', '༗'), ('༚', '༴'),
+  ('༶', '༶'), ('༸', '༸'), ('༺', 'ཇ'), ('ཉ', 'ཬ'),
+  ('ཿ', 'ཿ'), ('྅', '྅'), ('ྈ', 'ྌ'), ('྾', '࿅'),
+  ('࿇', '࿌'), ('࿎', '࿚'), ('က', 'ာ'), ('ေ', 'ေ'),
+  ('း', 'း'), ('ျ', 'ြ'), ('ဿ', 'ၗ'), ('ၚ', 'ၝ'),
+  ('ၡ', 'ၰ'), ('ၵ', 'ႁ'), ('ႃ', 'ႄ'), ('ႇ', 'ႌ'),
+  ('ႎ', 'ႜ'), ('႞', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('ა', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('፠', '፼'), ('ᎀ', '᎙'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'),
+  ('᐀', '᚜'), ('ᚠ', 'ᛸ'), ('ᜀ', 'ᜌ'), ('ᜎ', 'ᜑ'),
+  ('ᜠ', 'ᜱ'), ('᜵', '᜶'), ('ᝀ', 'ᝑ'), ('ᝠ', 'ᝬ'),
+  ('ᝮ', 'ᝰ'), ('ក', 'ឳ'), ('ា', 'ា'), ('ើ', 'ៅ'),
+  ('ះ', 'ៈ'), ('។', 'ៜ'), ('០', '៩'), ('៰', '៹'),
+  ('᠀', '᠊'), ('᠐', '᠙'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢄ'),
+  ('ᢇ', 'ᢨ'), ('ᢪ', 'ᢪ'), ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'),
+  ('ᤣ', 'ᤦ'), ('ᤩ', 'ᤫ'), ('ᤰ', 'ᤱ'), ('ᤳ', 'ᤸ'),
+  ('᥀', '᥀'), ('᥄', 'ᥭ'), ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'),
+  ('ᦰ', 'ᧉ'), ('᧐', '᧚'), ('᧞', 'ᨖ'), ('ᨙ', 'ᨚ'),
+  ('᨞', 'ᩕ'), ('ᩗ', 'ᩗ'), ('ᩡ', 'ᩡ'), ('ᩣ', 'ᩤ'),
+  ('ᩭ', 'ᩲ'), ('᪀', '᪉'), ('᪐', '᪙'), ('᪠', '᪭'),
+  ('ᬄ', 'ᬳ'), ('ᬵ', 'ᬵ'), ('ᬻ', 'ᬻ'), ('ᬽ', 'ᭁ'),
+  ('ᭃ', 'ᭋ'), ('᭐', '᭪'), ('᭴', '᭼'), ('ᮂ', 'ᮡ'),
+  ('ᮦ', 'ᮧ'), ('᮪', '᮪'), ('ᮮ', 'ᯥ'), ('ᯧ', 'ᯧ'),
+  ('ᯪ', 'ᯬ'), ('ᯮ', 'ᯮ'), ('᯲', '᯳'), ('᯼', 'ᰫ'),
+  ('ᰴ', 'ᰵ'), ('᰻', '᱉'), ('ᱍ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '᳇'), ('᳓', '᳓'), ('᳡', '᳡'), ('ᳩ', 'ᳬ'),
+  ('ᳮ', 'ᳳ'), ('ᳵ', '᳷'), ('ᴀ', 'ᶿ'), ('Ḁ', 'ἕ'),
+  ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'),
+  ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'),
+  ('ᾀ', 'ᾴ'), ('ᾶ', 'ῄ'), ('ῆ', 'ΐ'), ('ῖ', 'Ί'),
+  ('῝', '`'), ('ῲ', 'ῴ'), ('ῶ', '῾'), ('\u{2000}', '\u{200a}'),
+  ('‐', '‧'), ('\u{202f}', '\u{205f}'), ('⁰', 'ⁱ'), ('⁴', '₎'),
+  ('ₐ', 'ₜ'), ('₠', '₿'), ('℀', '↋'), ('←', '␦'),
+  ('⑀', '⑊'), ('①', '⭳'), ('⭶', '⮕'), ('⮘', '⯈'),
+  ('⯊', '\u{2bfe}'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳮ'),
+  ('Ⳳ', 'ⳳ'), ('⳹', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+  ('ⴰ', 'ⵧ'), ('ⵯ', '⵰'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'),
+  ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'),
+  ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('⸀', '\u{2e4e}'),
+  ('⺀', '⺙'), ('⺛', '⻳'), ('⼀', '⿕'), ('⿰', '⿻'),
+  ('\u{3000}', '〩'), ('〰', '〿'), ('ぁ', 'ゖ'), ('゛', 'ヿ'),
+  ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'), ('㆐', 'ㆺ'), ('㇀', '㇣'),
+  ('ㇰ', '㈞'), ('㈠', '㋾'), ('㌀', '䶵'), ('䷀', '\u{9fef}'),
+  ('ꀀ', 'ꒌ'), ('꒐', '꓆'), ('ꓐ', 'ꘫ'), ('Ꙁ', 'ꙮ'),
+  ('꙳', '꙳'), ('꙾', 'ꚝ'), ('ꚠ', 'ꛯ'), ('꛲', '꛷'),
+  ('꜀', '\u{a7b9}'), ('ꟷ', 'ꠁ'), ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'),
+  ('ꠌ', 'ꠤ'), ('ꠧ', '꠫'), ('꠰', '꠹'), ('ꡀ', '꡷'),
+  ('ꢀ', 'ꣃ'), ('꣎', '꣙'), ('ꣲ', '\u{a8fe}'), ('꤀', 'ꤥ'),
+  ('꤮', 'ꥆ'), ('ꥒ', '꥓'), ('꥟', 'ꥼ'), ('ꦃ', 'ꦲ'),
+  ('ꦴ', 'ꦵ'), ('ꦺ', 'ꦻ'), ('ꦽ', '꧍'), ('ꧏ', '꧙'),
+  ('꧞', 'ꧤ'), ('ꧦ', 'ꧾ'), ('ꨀ', 'ꨨ'), ('ꨯ', 'ꨰ'),
+  ('ꨳ', 'ꨴ'), ('ꩀ', 'ꩂ'), ('ꩄ', 'ꩋ'), ('ꩍ', 'ꩍ'),
+  ('꩐', '꩙'), ('꩜', 'ꩻ'), ('ꩽ', 'ꪯ'), ('ꪱ', 'ꪱ'),
+  ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪽ'), ('ꫀ', 'ꫀ'), ('ꫂ', 'ꫂ'),
+  ('ꫛ', 'ꫫ'), ('ꫮ', 'ꫵ'), ('ꬁ', 'ꬆ'), ('ꬉ', 'ꬎ'),
+  ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'), ('ꬰ', 'ꭥ'),
+  ('ꭰ', 'ꯤ'), ('ꯦ', 'ꯧ'), ('ꯩ', '꯬'), ('꯰', '꯹'),
+  ('가', '힣'), ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'),
+  ('並', '龎'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'יִ'),
+  ('ײַ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'),
+  ('ףּ', 'פּ'), ('צּ', '﯁'), ('ﯓ', '﴿'), ('ﵐ', 'ﶏ'),
+  ('ﶒ', 'ﷇ'), ('ﷰ', '﷽'), ('︐', '︙'), ('︰', '﹒'),
+  ('﹔', '﹦'), ('﹨', '﹫'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('！', 'ﾝ'), ('ﾠ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'),
+  ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('￠', '￦'), ('￨', '￮'),
+  ('￼', '�'), ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'),
+  ('𐀼', '𐀽'), ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'),
+  ('𐄀', '𐄂'), ('𐄇', '𐄳'), ('𐄷', '𐆎'), ('𐆐', '𐆛'),
+  ('𐆠', '𐆠'), ('𐇐', '𐇼'), ('𐊀', '𐊜'), ('𐊠', '𐋐'),
+  ('𐋡', '𐋻'), ('𐌀', '𐌣'), ('𐌭', '𐍊'), ('𐍐', '𐍵'),
+  ('𐎀', '𐎝'), ('𐎟', '𐏃'), ('𐏈', '𐏕'), ('𐐀', '𐒝'),
+  ('𐒠', '𐒩'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'),
+  ('𐔰', '𐕣'), ('𐕯', '𐕯'), ('𐘀', '𐜶'), ('𐝀', '𐝕'),
+  ('𐝠', '𐝧'), ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'),
+  ('𐠷', '𐠸'), ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡗', '𐢞'),
+  ('𐢧', '𐢯'), ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐣻', '𐤛'),
+  ('𐤟', '𐤹'), ('𐤿', '𐤿'), ('𐦀', '𐦷'), ('𐦼', '𐧏'),
+  ('𐧒', '𐨀'), ('𐨐', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'),
+  ('𐩀', '\u{10a48}'), ('𐩐', '𐩘'), ('𐩠', '𐪟'), ('𐫀', '𐫤'),
+  ('𐫫', '𐫶'), ('𐬀', '𐬵'), ('𐬹', '𐭕'), ('𐭘', '𐭲'),
+  ('𐭸', '𐮑'), ('𐮙', '𐮜'), ('𐮩', '𐮯'), ('𐰀', '𐱈'),
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𐳺', '\u{10d23}'),
+  ('\u{10d30}', '\u{10d39}'), ('𐹠', '𐹾'), ('\u{10f00}', '\u{10f27}'),
+  ('\u{10f30}', '\u{10f45}'), ('\u{10f51}', '\u{10f59}'), ('𑀀', '𑀀'),
+  ('𑀂', '𑀷'), ('𑁇', '𑁍'), ('𑁒', '𑁯'), ('𑂂', '𑂲'),
+  ('𑂷', '𑂸'), ('𑂻', '𑂼'), ('𑂾', '𑃁'), ('𑃐', '𑃨'),
+  ('𑃰', '𑃹'), ('𑄃', '𑄦'), ('𑄬', '𑄬'), ('𑄶', '\u{11146}'),
+  ('𑅐', '𑅲'), ('𑅴', '𑅶'), ('𑆂', '𑆵'), ('𑆿', '𑇈'),
+  ('𑇍', '𑇍'), ('𑇐', '𑇟'), ('𑇡', '𑇴'), ('𑈀', '𑈑'),
+  ('𑈓', '𑈮'), ('𑈲', '𑈳'), ('𑈵', '𑈵'), ('𑈸', '𑈽'),
+  ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'), ('𑊏', '𑊝'),
+  ('𑊟', '𑊩'), ('𑊰', '𑋞'), ('𑋠', '𑋢'), ('𑋰', '𑋹'),
+  ('𑌂', '𑌃'), ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'),
+  ('𑌪', '𑌰'), ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑌽'),
+  ('𑌿', '𑌿'), ('𑍁', '𑍄'), ('𑍇', '𑍈'), ('𑍋', '𑍍'),
+  ('𑍐', '𑍐'), ('𑍝', '𑍣'), ('𑐀', '𑐷'), ('𑑀', '𑑁'),
+  ('𑑅', '𑑅'), ('𑑇', '𑑙'), ('𑑛', '𑑛'), ('𑑝', '𑑝'),
+  ('𑒀', '𑒯'), ('𑒱', '𑒲'), ('𑒹', '𑒹'), ('𑒻', '𑒼'),
+  ('𑒾', '𑒾'), ('𑓁', '𑓁'), ('𑓄', '𑓇'), ('𑓐', '𑓙'),
+  ('𑖀', '𑖮'), ('𑖰', '𑖱'), ('𑖸', '𑖻'), ('𑖾', '𑖾'),
+  ('𑗁', '𑗛'), ('𑘀', '𑘲'), ('𑘻', '𑘼'), ('𑘾', '𑘾'),
+  ('𑙁', '𑙄'), ('𑙐', '𑙙'), ('𑙠', '𑙬'), ('𑚀', '𑚪'),
+  ('𑚬', '𑚬'), ('𑚮', '𑚯'), ('𑚶', '𑚶'), ('𑛀', '𑛉'),
+  ('𑜀', '\u{1171a}'), ('𑜠', '𑜡'), ('𑜦', '𑜦'), ('𑜰', '𑜿'),
+  ('\u{11800}', '\u{1182e}'), ('\u{11838}', '\u{11838}'),
+  ('\u{1183b}', '\u{1183b}'), ('𑢠', '𑣲'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨀'), ('𑨋', '𑨲'), ('𑨹', '𑨺'), ('𑨿', '𑩆'),
+  ('𑩐', '𑩐'), ('𑩗', '𑩘'), ('𑩜', '𑪃'), ('𑪆', '𑪉'),
+  ('𑪗', '𑪗'), ('𑪚', '𑪢'), ('𑫀', '𑫸'), ('𑰀', '𑰈'),
+  ('𑰊', '𑰯'), ('𑰾', '𑰾'), ('𑱀', '𑱅'), ('𑱐', '𑱬'),
+  ('𑱰', '𑲏'), ('𑲩', '𑲩'), ('𑲱', '𑲱'), ('𑲴', '𑲴'),
+  ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴰'), ('𑵆', '𑵆'),
+  ('𑵐', '𑵙'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d8e}'), ('\u{11d93}', '\u{11d94}'),
+  ('\u{11d96}', '\u{11d96}'), ('\u{11d98}', '\u{11d98}'),
+  ('\u{11da0}', '\u{11da9}'), ('\u{11ee0}', '\u{11ef2}'),
+  ('\u{11ef5}', '\u{11ef8}'), ('𒀀', '𒎙'), ('𒐀', '𒑮'),
+  ('𒑰', '𒑴'), ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'),
+  ('𖠀', '𖨸'), ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖩮', '𖩯'),
+  ('𖫐', '𖫭'), ('𖫵', '𖫵'), ('𖬀', '𖬯'), ('𖬷', '𖭅'),
+  ('𖭐', '𖭙'), ('𖭛', '𖭡'), ('𖭣', '𖭷'), ('𖭽', '𖮏'),
+  ('\u{16e40}', '\u{16e9a}'), ('𖼀', '𖽄'), ('𖽐', '𖽾'),
+  ('𖾓', '𖾟'), ('𖿠', '𖿡'), ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'),
+  ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'), ('𛱰', '𛱼'),
+  ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲜', '𛲜'), ('𛲟', '𛲟'),
+  ('𝀀', '𝃵'), ('𝄀', '𝄦'), ('𝄩', '𝅘𝅥𝅲'), ('𝅦', '𝅦'),
+  ('𝅪', '𝅭'), ('𝆃', '𝆄'), ('𝆌', '𝆩'), ('𝆮', '𝇨'),
+  ('𝈀', '𝉁'), ('𝉅', '𝉅'), ('\u{1d2e0}', '\u{1d2f3}'),
+  ('𝌀', '𝍖'), ('𝍠', '\u{1d378}'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝟋'), ('𝟎', '𝧿'), ('𝨷', '𝨺'),
+  ('𝩭', '𝩴'), ('𝩶', '𝪃'), ('𝪅', '𝪋'), ('𞠀', '𞣄'),
+  ('𞣇', '𞣏'), ('𞤀', '𞥃'), ('𞥐', '𞥙'), ('𞥞', '𞥟'),
+  ('\u{1ec71}', '\u{1ecb4}'), ('𞸀', '𞸃'), ('𞸅', '𞸟'),
+  ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'),
+  ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'),
+  ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'),
+  ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'),
+  ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'),
+  ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'),
+  ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'),
+  ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('𞻰', '𞻱'),
+  ('🀀', '🀫'), ('🀰', '🂓'), ('🂠', '🂮'), ('🂱', '🂿'),
+  ('🃁', '🃏'), ('🃑', '🃵'), ('🄀', '🄌'), ('🄐', '🅫'),
+  ('🅰', '🆬'), ('🇦', '🈂'), ('🈐', '🈻'), ('🉀', '🉈'),
+  ('🉐', '🉑'), ('🉠', '🉥'), ('🌀', '🛔'), ('🛠', '🛬'),
+  ('🛰', '\u{1f6f9}'), ('🜀', '🝳'), ('🞀', '\u{1f7d8}'),
+  ('🠀', '🠋'), ('🠐', '🡇'), ('🡐', '🡙'), ('🡠', '🢇'),
+  ('🢐', '🢭'), ('🤀', '🤋'), ('🤐', '🤾'), ('🥀', '\u{1f970}'),
+  ('\u{1f973}', '\u{1f976}'), ('\u{1f97a}', '\u{1f97a}'),
+  ('\u{1f97c}', '\u{1f9a2}'), ('\u{1f9b0}', '\u{1f9b9}'),
+  ('🧀', '\u{1f9c2}'), ('🧐', '\u{1f9ff}'), ('\u{1fa60}', '\u{1fa6d}'),
+  ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'), ('𫠠', '𬺡'),
+  ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
+  ('̀', 'ͯ'), ('҃', '҉'), ('֑', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'),
+  ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('ؐ', 'ؚ'), ('ً', 'ٟ'), ('ٰ', 'ٰ'),
+  ('ۖ', 'ۜ'), ('۟', 'ۤ'), ('ۧ', 'ۨ'), ('۪', 'ۭ'), ('ܑ', 'ܑ'),
+  ('ܰ', '݊'), ('ަ', 'ް'), ('߫', '߳'), ('\u{7fd}', '\u{7fd}'),
+  ('ࠖ', '࠙'), ('ࠛ', 'ࠣ'), ('ࠥ', 'ࠧ'), ('ࠩ', '࠭'),
+  ('࡙', '࡛'), ('\u{8d3}', '࣡'), ('ࣣ', 'ं'), ('ऺ', 'ऺ'),
+  ('़', '़'), ('ु', 'ै'), ('्', '्'), ('॑', 'ॗ'),
+  ('ॢ', 'ॣ'), ('ঁ', 'ঁ'), ('়', '়'), ('া', 'া'),
+  ('ু', 'ৄ'), ('্', '্'), ('ৗ', 'ৗ'), ('ৢ', 'ৣ'),
+  ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਂ'), ('਼', '਼'), ('ੁ', 'ੂ'),
+  ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ੑ', 'ੑ'), ('ੰ', 'ੱ'),
+  ('ੵ', 'ੵ'), ('ઁ', 'ં'), ('઼', '઼'), ('ુ', 'ૅ'),
+  ('ે', 'ૈ'), ('્', '્'), ('ૢ', 'ૣ'), ('ૺ', '૿'),
+  ('ଁ', 'ଁ'), ('଼', '଼'), ('ା', 'ି'), ('ୁ', 'ୄ'),
+  ('୍', '୍'), ('ୖ', 'ୗ'), ('ୢ', 'ୣ'), ('ஂ', 'ஂ'),
+  ('ா', 'ா'), ('ீ', 'ீ'), ('்', '்'), ('ௗ', 'ௗ'),
+  ('ఀ', 'ఀ'), ('\u{c04}', '\u{c04}'), ('ా', 'ీ'), ('ె', 'ై'),
+  ('ొ', '్'), ('ౕ', 'ౖ'), ('ౢ', 'ౣ'), ('ಁ', 'ಁ'),
+  ('಼', '಼'), ('ಿ', 'ಿ'), ('ೂ', 'ೂ'), ('ೆ', 'ೆ'),
+  ('ೌ', '್'), ('ೕ', 'ೖ'), ('ೢ', 'ೣ'), ('ഀ', 'ഁ'),
+  ('഻', '഼'), ('ാ', 'ാ'), ('ു', 'ൄ'), ('്', '്'),
+  ('ൗ', 'ൗ'), ('ൢ', 'ൣ'), ('්', '්'), ('ා', 'ා'),
+  ('ි', 'ු'), ('ූ', 'ූ'), ('ෟ', 'ෟ'), ('ั', 'ั'),
+  ('ิ', 'ฺ'), ('็', '๎'), ('ັ', 'ັ'), ('ິ', 'ູ'),
+  ('ົ', 'ຼ'), ('່', 'ໍ'), ('༘', '༙'), ('༵', '༵'),
+  ('༷', '༷'), ('༹', '༹'), ('ཱ', 'ཾ'), ('ྀ', '྄'),
+  ('྆', '྇'), ('ྍ', 'ྗ'), ('ྙ', 'ྼ'), ('࿆', '࿆'),
+  ('ိ', 'ူ'), ('ဲ', '့'), ('္', '်'), ('ွ', 'ှ'),
+  ('ၘ', 'ၙ'), ('ၞ', 'ၠ'), ('ၱ', 'ၴ'), ('ႂ', 'ႂ'),
+  ('ႅ', 'ႆ'), ('ႍ', 'ႍ'), ('ႝ', 'ႝ'), ('፝', '፟'),
+  ('ᜒ', '᜔'), ('ᜲ', '᜴'), ('ᝒ', 'ᝓ'), ('ᝲ', 'ᝳ'),
+  ('឴', '឵'), ('ិ', 'ួ'), ('ំ', 'ំ'), ('៉', '៓'),
+  ('៝', '៝'), ('᠋', '᠍'), ('ᢅ', 'ᢆ'), ('ᢩ', 'ᢩ'),
+  ('ᤠ', 'ᤢ'), ('ᤧ', 'ᤨ'), ('ᤲ', 'ᤲ'), ('᤹', '᤻'),
+  ('ᨗ', 'ᨘ'), ('ᨛ', 'ᨛ'), ('ᩖ', 'ᩖ'), ('ᩘ', 'ᩞ'),
+  ('᩠', '᩠'), ('ᩢ', 'ᩢ'), ('ᩥ', 'ᩬ'), ('ᩳ', '᩼'),
+  ('᩿', '᩿'), ('᪰', '᪾'), ('ᬀ', 'ᬃ'), ('᬴', '᬴'),
+  ('ᬶ', 'ᬺ'), ('ᬼ', 'ᬼ'), ('ᭂ', 'ᭂ'), ('᭫', '᭳'),
+  ('ᮀ', 'ᮁ'), ('ᮢ', 'ᮥ'), ('ᮨ', 'ᮩ'), ('᮫', 'ᮭ'),
+  ('᯦', '᯦'), ('ᯨ', 'ᯩ'), ('ᯭ', 'ᯭ'), ('ᯯ', 'ᯱ'),
+  ('ᰬ', 'ᰳ'), ('ᰶ', '᰷'), ('᳐', '᳒'), ('᳔', '᳠'),
+  ('᳢', '᳨'), ('᳭', '᳭'), ('᳴', '᳴'), ('᳸', '᳹'),
+  ('᷀', '᷹'), ('᷻', '᷿'), ('\u{200c}', '\u{200c}'), ('⃐', '⃰'),
+  ('⳯', '⳱'), ('⵿', '⵿'), ('ⷠ', 'ⷿ'), ('〪', '〯'),
+  ('゙', '゚'), ('꙯', '꙲'), ('ꙴ', '꙽'), ('ꚞ', 'ꚟ'),
+  ('꛰', '꛱'), ('ꠂ', 'ꠂ'), ('꠆', '꠆'), ('ꠋ', 'ꠋ'),
+  ('ꠥ', 'ꠦ'), ('꣄', 'ꣅ'), ('꣠', '꣱'), ('\u{a8ff}', '\u{a8ff}'),
+  ('ꤦ', '꤭'), ('ꥇ', 'ꥑ'), ('ꦀ', 'ꦂ'), ('꦳', '꦳'),
+  ('ꦶ', 'ꦹ'), ('ꦼ', 'ꦼ'), ('ꧥ', 'ꧥ'), ('ꨩ', 'ꨮ'),
+  ('ꨱ', 'ꨲ'), ('ꨵ', 'ꨶ'), ('ꩃ', 'ꩃ'), ('ꩌ', 'ꩌ'),
+  ('ꩼ', 'ꩼ'), ('ꪰ', 'ꪰ'), ('ꪲ', 'ꪴ'), ('ꪷ', 'ꪸ'),
+  ('ꪾ', '꪿'), ('꫁', '꫁'), ('ꫬ', 'ꫭ'), ('꫶', '꫶'),
+  ('ꯥ', 'ꯥ'), ('ꯨ', 'ꯨ'), ('꯭', '꯭'), ('ﬞ', 'ﬞ'),
+  ('︀', '️'), ('︠', '︯'), ('ﾞ', 'ﾟ'), ('𐇽', '𐇽'),
+  ('𐋠', '𐋠'), ('𐍶', '𐍺'), ('𐨁', '𐨃'), ('𐨅', '𐨆'),
+  ('𐨌', '𐨏'), ('𐨸', '𐨺'), ('𐨿', '𐨿'), ('𐫥', '𐫦'),
+  ('\u{10d24}', '\u{10d27}'), ('\u{10f46}', '\u{10f50}'), ('𑀁', '𑀁'),
+  ('𑀸', '𑁆'), ('𑁿', '𑂁'), ('𑂳', '𑂶'), ('𑂹', '𑂺'),
+  ('𑄀', '𑄂'), ('𑄧', '𑄫'), ('𑄭', '𑄴'), ('𑅳', '𑅳'),
+  ('𑆀', '𑆁'), ('𑆶', '𑆾'), ('𑇉', '𑇌'), ('𑈯', '𑈱'),
+  ('𑈴', '𑈴'), ('𑈶', '𑈷'), ('𑈾', '𑈾'), ('𑋟', '𑋟'),
+  ('𑋣', '𑋪'), ('𑌀', '𑌁'), ('\u{1133b}', '𑌼'), ('𑌾', '𑌾'),
+  ('𑍀', '𑍀'), ('𑍗', '𑍗'), ('𑍦', '𑍬'), ('𑍰', '𑍴'),
+  ('𑐸', '𑐿'), ('𑑂', '𑑄'), ('𑑆', '𑑆'),
+  ('\u{1145e}', '\u{1145e}'), ('𑒰', '𑒰'), ('𑒳', '𑒸'),
+  ('𑒺', '𑒺'), ('𑒽', '𑒽'), ('𑒿', '𑓀'), ('𑓂', '𑓃'),
+  ('𑖯', '𑖯'), ('𑖲', '𑖵'), ('𑖼', '𑖽'), ('𑖿', '𑗀'),
+  ('𑗜', '𑗝'), ('𑘳', '𑘺'), ('𑘽', '𑘽'), ('𑘿', '𑙀'),
+  ('𑚫', '𑚫'), ('𑚭', '𑚭'), ('𑚰', '𑚵'), ('𑚷', '𑚷'),
+  ('𑜝', '𑜟'), ('𑜢', '𑜥'), ('𑜧', '𑜫'),
+  ('\u{1182f}', '\u{11837}'), ('\u{11839}', '\u{1183a}'), ('𑨁', '𑨊'),
+  ('𑨳', '𑨸'), ('𑨻', '𑨾'), ('𑩇', '𑩇'), ('𑩑', '𑩖'),
+  ('𑩙', '𑩛'), ('𑪊', '𑪖'), ('𑪘', '𑪙'), ('𑰰', '𑰶'),
+  ('𑰸', '𑰽'), ('𑰿', '𑰿'), ('𑲒', '𑲧'), ('𑲪', '𑲰'),
+  ('𑲲', '𑲳'), ('𑲵', '𑲶'), ('𑴱', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵅'), ('𑵇', '𑵇'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d95}', '\u{11d95}'),
+  ('\u{11d97}', '\u{11d97}'), ('\u{11ef3}', '\u{11ef4}'), ('𖫰', '𖫴'),
+  ('𖬰', '𖬶'), ('𖾏', '𖾒'), ('𛲝', '𛲞'), ('𝅥', '𝅥'),
+  ('𝅧', '𝅩'), ('𝅮', '𝅲'), ('𝅻', '𝆂'), ('𝆅', '𝆋'),
+  ('𝆪', '𝆭'), ('𝉂', '𝉄'), ('𝨀', '𝨶'), ('𝨻', '𝩬'),
+  ('𝩵', '𝩵'), ('𝪄', '𝪄'), ('𝪛', '𝪟'), ('𝪡', '𝪯'),
+  ('𞀀', '𞀆'), ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'),
+  ('𞀦', '𞀪'), ('𞣐', '𞣖'), ('𞥄', '𞥊'),
+  ('\u{e0020}', '\u{e007f}'), ('󠄀', '󠇯'),
+];
+
+pub const GRAPHEME_LINK: &'static [(char, char)] = &[
+  ('्', '्'), ('্', '্'), ('੍', '੍'), ('્', '્'),
+  ('୍', '୍'), ('்', '்'), ('్', '్'), ('್', '್'),
+  ('഻', '഼'), ('്', '്'), ('්', '්'), ('ฺ', 'ฺ'),
+  ('྄', '྄'), ('္', '်'), ('᜔', '᜔'), ('᜴', '᜴'),
+  ('្', '្'), ('᩠', '᩠'), ('᭄', '᭄'), ('᮪', '᮫'),
+  ('᯲', '᯳'), ('⵿', '⵿'), ('꠆', '꠆'), ('꣄', '꣄'),
+  ('꥓', '꥓'), ('꧀', '꧀'), ('꫶', '꫶'), ('꯭', '꯭'),
+  ('𐨿', '𐨿'), ('𑁆', '𑁆'), ('𑁿', '𑁿'), ('𑂹', '𑂹'),
+  ('𑄳', '𑄴'), ('𑇀', '𑇀'), ('𑈵', '𑈵'), ('𑋪', '𑋪'),
+  ('𑍍', '𑍍'), ('𑑂', '𑑂'), ('𑓂', '𑓂'), ('𑖿', '𑖿'),
+  ('𑘿', '𑘿'), ('𑚶', '𑚶'), ('𑜫', '𑜫'),
+  ('\u{11839}', '\u{11839}'), ('𑨴', '𑨴'), ('𑩇', '𑩇'),
+  ('𑪙', '𑪙'), ('𑰿', '𑰿'), ('𑵄', '𑵅'),
+  ('\u{11d97}', '\u{11d97}'),
+];
+
+pub const HEX_DIGIT: &'static [(char, char)] = &[
+  ('0', '9'), ('A', 'F'), ('a', 'f'), ('０', '９'), ('Ａ', 'Ｆ'),
+  ('ａ', 'ｆ'),
+];
+
+pub const HYPHEN: &'static [(char, char)] = &[
+  ('-', '-'), ('\u{ad}', '\u{ad}'), ('֊', '֊'), ('᠆', '᠆'),
+  ('‐', '‑'), ('⸗', '⸗'), ('・', '・'), ('﹣', '﹣'),
+  ('－', '－'), ('･', '･'),
+];
+
+pub const IDS_BINARY_OPERATOR: &'static [(char, char)] = &[
+  ('⿰', '⿱'), ('⿴', '⿻'),
+];
+
+pub const IDS_TRINARY_OPERATOR: &'static [(char, char)] = &[
+  ('⿲', '⿳'),
+];
+
+pub const ID_CONTINUE: &'static [(char, char)] = &[
+  ('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'),
+  ('·', '·'), ('º', 'º'), ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'),
+  ('ˆ', 'ˑ'), ('ˠ', 'ˤ'), ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('̀', 'ʹ'),
+  ('Ͷ', 'ͷ'), ('ͺ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ί'), ('Ό', 'Ό'),
+  ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('҃', '҇'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('ՙ', 'ՙ'), ('\u{560}', '\u{588}'), ('֑', 'ֽ'),
+  ('ֿ', 'ֿ'), ('ׁ', 'ׂ'), ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('א', 'ת'),
+  ('\u{5ef}', 'ײ'), ('ؐ', 'ؚ'), ('ؠ', '٩'), ('ٮ', 'ۓ'), ('ە', 'ۜ'),
+  ('۟', 'ۨ'), ('۪', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', '݊'), ('ݍ', 'ޱ'),
+  ('߀', 'ߵ'), ('ߺ', 'ߺ'), ('\u{7fd}', '\u{7fd}'), ('ࠀ', '࠭'),
+  ('ࡀ', '࡛'), ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'),
+  ('\u{8d3}', '࣡'), ('ࣣ', 'ॣ'), ('०', '९'), ('ॱ', 'ঃ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('়', 'ৄ'), ('ে', 'ৈ'),
+  ('ো', 'ৎ'), ('ৗ', 'ৗ'), ('ড়', 'ঢ়'), ('য়', 'ৣ'),
+  ('০', 'ৱ'), ('ৼ', 'ৼ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਃ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('਼', '਼'),
+  ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ੑ', 'ੑ'),
+  ('ਖ਼', 'ੜ'), ('ਫ਼', 'ਫ਼'), ('੦', 'ੵ'), ('ઁ', 'ઃ'),
+  ('અ', 'ઍ'), ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'),
+  ('લ', 'ળ'), ('વ', 'હ'), ('઼', 'ૅ'), ('ે', 'ૉ'),
+  ('ો', '્'), ('ૐ', 'ૐ'), ('ૠ', 'ૣ'), ('૦', '૯'),
+  ('ૹ', '૿'), ('ଁ', 'ଃ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'),
+  ('ଓ', 'ନ'), ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଵ', 'ହ'),
+  ('଼', 'ୄ'), ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'),
+  ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୣ'), ('୦', '୯'), ('ୱ', 'ୱ'),
+  ('ஂ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'), ('ஒ', 'க'),
+  ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'), ('ண', 'த'),
+  ('ந', 'ப'), ('ம', 'ஹ'), ('ா', 'ூ'), ('ெ', 'ை'),
+  ('ொ', '்'), ('ௐ', 'ௐ'), ('ௗ', 'ௗ'), ('௦', '௯'),
+  ('ఀ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'హ'),
+  ('ఽ', 'ౄ'), ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'),
+  ('ౘ', 'ౚ'), ('ౠ', 'ౣ'), ('౦', '౯'), ('ಀ', 'ಃ'),
+  ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'),
+  ('ವ', 'ಹ'), ('಼', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', '್'),
+  ('ೕ', 'ೖ'), ('ೞ', 'ೞ'), ('ೠ', 'ೣ'), ('೦', '೯'),
+  ('ೱ', 'ೲ'), ('ഀ', 'ഃ'), ('അ', 'ഌ'), ('എ', 'ഐ'),
+  ('ഒ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', 'ൎ'), ('ൔ', 'ൗ'),
+  ('ൟ', 'ൣ'), ('൦', '൯'), ('ൺ', 'ൿ'), ('ං', 'ඃ'),
+  ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'),
+  ('ව', 'ෆ'), ('්', '්'), ('ා', 'ු'), ('ූ', 'ූ'),
+  ('ෘ', 'ෟ'), ('෦', '෯'), ('ෲ', 'ෳ'), ('ก', 'ฺ'),
+  ('เ', '๎'), ('๐', '๙'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'),
+  ('ງ', 'ຈ'), ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'),
+  ('ນ', 'ຟ'), ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'),
+  ('ສ', 'ຫ'), ('ອ', 'ູ'), ('ົ', 'ຽ'), ('ເ', 'ໄ'),
+  ('ໆ', 'ໆ'), ('່', 'ໍ'), ('໐', '໙'), ('ໜ', 'ໟ'),
+  ('ༀ', 'ༀ'), ('༘', '༙'), ('༠', '༩'), ('༵', '༵'),
+  ('༷', '༷'), ('༹', '༹'), ('༾', 'ཇ'), ('ཉ', 'ཬ'),
+  ('ཱ', '྄'), ('྆', 'ྗ'), ('ྙ', 'ྼ'), ('࿆', '࿆'),
+  ('က', '၉'), ('ၐ', 'ႝ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'), ('ჼ', 'ቈ'), ('ቊ', 'ቍ'),
+  ('ቐ', 'ቖ'), ('ቘ', 'ቘ'), ('ቚ', 'ቝ'), ('በ', 'ኈ'),
+  ('ኊ', 'ኍ'), ('ነ', 'ኰ'), ('ኲ', 'ኵ'), ('ኸ', 'ኾ'),
+  ('ዀ', 'ዀ'), ('ዂ', 'ዅ'), ('ወ', 'ዖ'), ('ዘ', 'ጐ'),
+  ('ጒ', 'ጕ'), ('ጘ', 'ፚ'), ('፝', '፟'), ('፩', '፱'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'), ('ᜠ', '᜴'), ('ᝀ', 'ᝓ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ᝲ', 'ᝳ'), ('ក', '៓'),
+  ('ៗ', 'ៗ'), ('ៜ', '៝'), ('០', '៩'), ('᠋', '᠍'),
+  ('᠐', '᠙'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢪ'), ('ᢰ', 'ᣵ'),
+  ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'), ('᥆', 'ᥭ'),
+  ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('᧐', '᧚'),
+  ('ᨀ', 'ᨛ'), ('ᨠ', 'ᩞ'), ('᩠', '᩼'), ('᩿', '᪉'),
+  ('᪐', '᪙'), ('ᪧ', 'ᪧ'), ('᪰', '᪽'), ('ᬀ', 'ᭋ'),
+  ('᭐', '᭙'), ('᭫', '᭳'), ('ᮀ', '᯳'), ('ᰀ', '᰷'),
+  ('᱀', '᱉'), ('ᱍ', 'ᱽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('᳐', '᳒'), ('᳔', '᳹'), ('ᴀ', '᷹'),
+  ('᷻', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'),
+  ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'),
+  ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('‿', '⁀'),
+  ('⁔', '⁔'), ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'),
+  ('⃐', '⃜'), ('⃡', '⃡'), ('⃥', '⃰'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('℘', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℹ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'), ('Ⳬ', 'ⳳ'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ⴰ', 'ⵧ'),
+  ('ⵯ', 'ⵯ'), ('⵿', 'ⶖ'), ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'),
+  ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'),
+  ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('ⷠ', 'ⷿ'), ('々', '〇'),
+  ('〡', '〯'), ('〱', '〵'), ('〸', '〼'), ('ぁ', 'ゖ'),
+  ('゙', 'ゟ'), ('ァ', 'ヺ'), ('ー', 'ヿ'), ('ㄅ', '\u{312f}'),
+  ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'), ('㐀', '䶵'),
+  ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'), ('ꔀ', 'ꘌ'),
+  ('ꘐ', 'ꘫ'), ('Ꙁ', '꙯'), ('ꙴ', '꙽'), ('ꙿ', '꛱'),
+  ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'), ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꠧ'),
+  ('ꡀ', 'ꡳ'), ('ꢀ', 'ꣅ'), ('꣐', '꣙'), ('꣠', 'ꣷ'),
+  ('ꣻ', 'ꣻ'), ('ꣽ', '꤭'), ('ꤰ', '꥓'), ('ꥠ', 'ꥼ'),
+  ('ꦀ', '꧀'), ('ꧏ', '꧙'), ('ꧠ', 'ꧾ'), ('ꨀ', 'ꨶ'),
+  ('ꩀ', 'ꩍ'), ('꩐', '꩙'), ('ꩠ', 'ꩶ'), ('ꩺ', 'ꫂ'),
+  ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫯ'), ('ꫲ', '꫶'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+  ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯪ'), ('꯬', '꯭'),
+  ('꯰', '꯹'), ('가', '힣'), ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'),
+  ('豈', '舘'), ('並', '龎'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'),
+  ('יִ', 'ﬨ'), ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'),
+  ('נּ', 'סּ'), ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'),
+  ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'), ('︀', '️'),
+  ('︠', '︯'), ('︳', '︴'), ('﹍', '﹏'), ('ﹰ', 'ﹴ'),
+  ('ﹶ', 'ﻼ'), ('０', '９'), ('Ａ', 'Ｚ'), ('＿', '＿'),
+  ('ａ', 'ｚ'), ('ｦ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'),
+  ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('𐀀', '𐀋'), ('𐀍', '𐀦'),
+  ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'), ('𐁐', '𐁝'),
+  ('𐂀', '𐃺'), ('𐅀', '𐅴'), ('𐇽', '𐇽'), ('𐊀', '𐊜'),
+  ('𐊠', '𐋐'), ('𐋠', '𐋠'), ('𐌀', '𐌟'), ('𐌭', '𐍊'),
+  ('𐍐', '𐍺'), ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'),
+  ('𐏑', '𐏕'), ('𐐀', '𐒝'), ('𐒠', '𐒩'), ('𐒰', '𐓓'),
+  ('𐓘', '𐓻'), ('𐔀', '𐔧'), ('𐔰', '𐕣'), ('𐘀', '𐜶'),
+  ('𐝀', '𐝕'), ('𐝠', '𐝧'), ('𐠀', '𐠅'), ('𐠈', '𐠈'),
+  ('𐠊', '𐠵'), ('𐠷', '𐠸'), ('𐠼', '𐠼'), ('𐠿', '𐡕'),
+  ('𐡠', '𐡶'), ('𐢀', '𐢞'), ('𐣠', '𐣲'), ('𐣴', '𐣵'),
+  ('𐤀', '𐤕'), ('𐤠', '𐤹'), ('𐦀', '𐦷'), ('𐦾', '𐦿'),
+  ('𐨀', '𐨃'), ('𐨅', '𐨆'), ('𐨌', '𐨓'), ('𐨕', '𐨗'),
+  ('𐨙', '\u{10a35}'), ('𐨸', '𐨺'), ('𐨿', '𐨿'), ('𐩠', '𐩼'),
+  ('𐪀', '𐪜'), ('𐫀', '𐫇'), ('𐫉', '𐫦'), ('𐬀', '𐬵'),
+  ('𐭀', '𐭕'), ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'),
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('\u{10d00}', '\u{10d27}'),
+  ('\u{10d30}', '\u{10d39}'), ('\u{10f00}', '\u{10f1c}'),
+  ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f50}'), ('𑀀', '𑁆'),
+  ('𑁦', '𑁯'), ('𑁿', '𑂺'), ('𑃐', '𑃨'), ('𑃰', '𑃹'),
+  ('𑄀', '𑄴'), ('𑄶', '𑄿'), ('\u{11144}', '\u{11146}'),
+  ('𑅐', '𑅳'), ('𑅶', '𑅶'), ('𑆀', '𑇄'), ('𑇉', '𑇌'),
+  ('𑇐', '𑇚'), ('𑇜', '𑇜'), ('𑈀', '𑈑'), ('𑈓', '𑈷'),
+  ('𑈾', '𑈾'), ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'),
+  ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋪'), ('𑋰', '𑋹'),
+  ('𑌀', '𑌃'), ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'),
+  ('𑌪', '𑌰'), ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('\u{1133b}', '𑍄'),
+  ('𑍇', '𑍈'), ('𑍋', '𑍍'), ('𑍐', '𑍐'), ('𑍗', '𑍗'),
+  ('𑍝', '𑍣'), ('𑍦', '𑍬'), ('𑍰', '𑍴'), ('𑐀', '𑑊'),
+  ('𑑐', '𑑙'), ('\u{1145e}', '\u{1145e}'), ('𑒀', '𑓅'),
+  ('𑓇', '𑓇'), ('𑓐', '𑓙'), ('𑖀', '𑖵'), ('𑖸', '𑗀'),
+  ('𑗘', '𑗝'), ('𑘀', '𑙀'), ('𑙄', '𑙄'), ('𑙐', '𑙙'),
+  ('𑚀', '𑚷'), ('𑛀', '𑛉'), ('𑜀', '\u{1171a}'), ('𑜝', '𑜫'),
+  ('𑜰', '𑜹'), ('\u{11800}', '\u{1183a}'), ('𑢠', '𑣩'),
+  ('𑣿', '𑣿'), ('𑨀', '𑨾'), ('𑩇', '𑩇'), ('𑩐', '𑪃'),
+  ('𑪆', '𑪙'), ('\u{11a9d}', '\u{11a9d}'), ('𑫀', '𑫸'),
+  ('𑰀', '𑰈'), ('𑰊', '𑰶'), ('𑰸', '𑱀'), ('𑱐', '𑱙'),
+  ('𑱲', '𑲏'), ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴀', '𑴆'),
+  ('𑴈', '𑴉'), ('𑴋', '𑴶'), ('𑴺', '𑴺'), ('𑴼', '𑴽'),
+  ('𑴿', '𑵇'), ('𑵐', '𑵙'), ('\u{11d60}', '\u{11d65}'),
+  ('\u{11d67}', '\u{11d68}'), ('\u{11d6a}', '\u{11d8e}'),
+  ('\u{11d90}', '\u{11d91}'), ('\u{11d93}', '\u{11d98}'),
+  ('\u{11da0}', '\u{11da9}'), ('\u{11ee0}', '\u{11ef6}'), ('𒀀', '𒎙'),
+  ('𒐀', '𒑮'), ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'),
+  ('𖠀', '𖨸'), ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖫐', '𖫭'),
+  ('𖫰', '𖫴'), ('𖬀', '𖬶'), ('𖭀', '𖭃'), ('𖭐', '𖭙'),
+  ('𖭣', '𖭷'), ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'),
+  ('𖼀', '𖽄'), ('𖽐', '𖽾'), ('𖾏', '𖾟'), ('𖿠', '𖿡'),
+  ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'),
+  ('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'),
+  ('𛲝', '𛲞'), ('𝅥', '𝅩'), ('𝅭', '𝅲'), ('𝅻', '𝆂'),
+  ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('𝉂', '𝉄'), ('𝐀', '𝑔'),
+  ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'),
+  ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'),
+  ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'),
+  ('𝛜', '𝛺'), ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'),
+  ('𝝐', '𝝮'), ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'),
+  ('𝟄', '𝟋'), ('𝟎', '𝟿'), ('𝨀', '𝨶'), ('𝨻', '𝩬'),
+  ('𝩵', '𝩵'), ('𝪄', '𝪄'), ('𝪛', '𝪟'), ('𝪡', '𝪯'),
+  ('𞀀', '𞀆'), ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'),
+  ('𞀦', '𞀪'), ('𞠀', '𞣄'), ('𞣐', '𞣖'), ('𞤀', '𞥊'),
+  ('𞥐', '𞥙'), ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'),
+  ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'),
+  ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'),
+  ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'),
+  ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'),
+  ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'),
+  ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'),
+  ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'),
+  ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('𠀀', '𪛖'), ('𪜀', '𫜴'),
+  ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+  ('󠄀', '󠇯'),
+];
+
+pub const ID_START: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'),
+  ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'), ('ˆ', 'ˑ'), ('ˠ', 'ˤ'),
+  ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('Ͱ', 'ʹ'), ('Ͷ', 'ͷ'), ('ͺ', 'ͽ'),
+  ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'),
+  ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'), ('Ա', 'Ֆ'), ('ՙ', 'ՙ'),
+  ('\u{560}', '\u{588}'), ('א', 'ת'), ('\u{5ef}', 'ײ'), ('ؠ', 'ي'),
+  ('ٮ', 'ٯ'), ('ٱ', 'ۓ'), ('ە', 'ە'), ('ۥ', 'ۦ'), ('ۮ', 'ۯ'),
+  ('ۺ', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', 'ܐ'), ('ܒ', 'ܯ'), ('ݍ', 'ޥ'),
+  ('ޱ', 'ޱ'), ('ߊ', 'ߪ'), ('ߴ', 'ߵ'), ('ߺ', 'ߺ'), ('ࠀ', 'ࠕ'),
+  ('ࠚ', 'ࠚ'), ('ࠤ', 'ࠤ'), ('ࠨ', 'ࠨ'), ('ࡀ', 'ࡘ'),
+  ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'), ('ऄ', 'ह'),
+  ('ऽ', 'ऽ'), ('ॐ', 'ॐ'), ('क़', 'ॡ'), ('ॱ', 'ঀ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('ঽ', 'ঽ'), ('ৎ', 'ৎ'),
+  ('ড়', 'ঢ়'), ('য়', 'ৡ'), ('ৰ', 'ৱ'), ('ৼ', 'ৼ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('ੲ', 'ੴ'), ('અ', 'ઍ'), ('એ', 'ઑ'),
+  ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'), ('વ', 'હ'),
+  ('ઽ', 'ઽ'), ('ૐ', 'ૐ'), ('ૠ', 'ૡ'), ('ૹ', 'ૹ'),
+  ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'),
+  ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('ଽ', 'ଽ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୡ'), ('ୱ', 'ୱ'), ('ஃ', 'ஃ'), ('அ', 'ஊ'),
+  ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'),
+  ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'),
+  ('ௐ', 'ௐ'), ('అ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'),
+  ('ప', 'హ'), ('ఽ', 'ఽ'), ('ౘ', 'ౚ'), ('ౠ', 'ౡ'),
+  ('ಀ', 'ಀ'), ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'),
+  ('ಪ', 'ಳ'), ('ವ', 'ಹ'), ('ಽ', 'ಽ'), ('ೞ', 'ೞ'),
+  ('ೠ', 'ೡ'), ('ೱ', 'ೲ'), ('അ', 'ഌ'), ('എ', 'ഐ'),
+  ('ഒ', 'ഺ'), ('ഽ', 'ഽ'), ('ൎ', 'ൎ'), ('ൔ', 'ൖ'),
+  ('ൟ', 'ൡ'), ('ൺ', 'ൿ'), ('අ', 'ඖ'), ('ක', 'න'),
+  ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'), ('ก', 'ะ'),
+  ('า', 'ำ'), ('เ', 'ๆ'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'),
+  ('ງ', 'ຈ'), ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'),
+  ('ນ', 'ຟ'), ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'),
+  ('ສ', 'ຫ'), ('ອ', 'ະ'), ('າ', 'ຳ'), ('ຽ', 'ຽ'),
+  ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('ໜ', 'ໟ'), ('ༀ', 'ༀ'),
+  ('ཀ', 'ཇ'), ('ཉ', 'ཬ'), ('ྈ', 'ྌ'), ('က', 'ဪ'),
+  ('ဿ', 'ဿ'), ('ၐ', 'ၕ'), ('ၚ', 'ၝ'), ('ၡ', 'ၡ'),
+  ('ၥ', 'ၦ'), ('ၮ', 'ၰ'), ('ၵ', 'ႁ'), ('ႎ', 'ႎ'),
+  ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'),
+  ('ჼ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', 'ᜑ'), ('ᜠ', 'ᜱ'), ('ᝀ', 'ᝑ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ក', 'ឳ'), ('ៗ', 'ៗ'),
+  ('ៜ', 'ៜ'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢨ'), ('ᢪ', 'ᢪ'),
+  ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'),
+  ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('ᨀ', 'ᨖ'), ('ᨠ', 'ᩔ'),
+  ('ᪧ', 'ᪧ'), ('ᬅ', 'ᬳ'), ('ᭅ', 'ᭋ'), ('ᮃ', 'ᮠ'),
+  ('ᮮ', 'ᮯ'), ('ᮺ', 'ᯥ'), ('ᰀ', 'ᰣ'), ('ᱍ', 'ᱏ'),
+  ('ᱚ', 'ᱽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('ᳩ', 'ᳬ'), ('ᳮ', 'ᳱ'), ('ᳵ', 'ᳶ'),
+  ('ᴀ', 'ᶿ'), ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'),
+  ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'),
+  ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'),
+  ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'Ί'), ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('℘', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℹ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'), ('Ⳬ', 'ⳮ'),
+  ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+  ('ⴰ', 'ⵧ'), ('ⵯ', 'ⵯ'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'),
+  ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'),
+  ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('々', '〇'),
+  ('〡', '〩'), ('〱', '〵'), ('〸', '〼'), ('ぁ', 'ゖ'),
+  ('゛', 'ゟ'), ('ァ', 'ヺ'), ('ー', 'ヿ'), ('ㄅ', '\u{312f}'),
+  ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'), ('㐀', '䶵'),
+  ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'), ('ꔀ', 'ꘌ'),
+  ('ꘐ', 'ꘟ'), ('ꘪ', 'ꘫ'), ('Ꙁ', 'ꙮ'), ('ꙿ', 'ꚝ'),
+  ('ꚠ', 'ꛯ'), ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'), ('Ꞌ', '\u{a7b9}'),
+  ('ꟷ', 'ꠁ'), ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'), ('ꠌ', 'ꠢ'),
+  ('ꡀ', 'ꡳ'), ('ꢂ', 'ꢳ'), ('ꣲ', 'ꣷ'), ('ꣻ', 'ꣻ'),
+  ('ꣽ', '\u{a8fe}'), ('ꤊ', 'ꤥ'), ('ꤰ', 'ꥆ'), ('ꥠ', 'ꥼ'),
+  ('ꦄ', 'ꦲ'), ('ꧏ', 'ꧏ'), ('ꧠ', 'ꧤ'), ('ꧦ', 'ꧯ'),
+  ('ꧺ', 'ꧾ'), ('ꨀ', 'ꨨ'), ('ꩀ', 'ꩂ'), ('ꩄ', 'ꩋ'),
+  ('ꩠ', 'ꩶ'), ('ꩺ', 'ꩺ'), ('ꩾ', 'ꪯ'), ('ꪱ', 'ꪱ'),
+  ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪽ'), ('ꫀ', 'ꫀ'), ('ꫂ', 'ꫂ'),
+  ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫪ'), ('ꫲ', 'ꫴ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+  ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯢ'), ('가', '힣'),
+  ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'), ('並', '龎'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'יִ'), ('ײַ', 'ﬨ'),
+  ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'),
+  ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﴽ'), ('ﵐ', 'ﶏ'),
+  ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷻ'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('Ａ', 'Ｚ'), ('ａ', 'ｚ'), ('ｦ', 'ﾾ'), ('ￂ', 'ￇ'),
+  ('ￊ', 'ￏ'), ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('𐀀', '𐀋'),
+  ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'),
+  ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐅀', '𐅴'), ('𐊀', '𐊜'),
+  ('𐊠', '𐋐'), ('𐌀', '𐌟'), ('𐌭', '𐍊'), ('𐍐', '𐍵'),
+  ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐏑', '𐏕'),
+  ('𐐀', '𐒝'), ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'),
+  ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+  ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'),
+  ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'), ('𐢀', '𐢞'),
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'), ('𐤠', '𐤹'),
+  ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨀'), ('𐨐', '𐨓'),
+  ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'), ('𐩠', '𐩼'), ('𐪀', '𐪜'),
+  ('𐫀', '𐫇'), ('𐫉', '𐫤'), ('𐬀', '𐬵'), ('𐭀', '𐭕'),
+  ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'), ('𐲀', '𐲲'),
+  ('𐳀', '𐳲'), ('\u{10d00}', '\u{10d23}'), ('\u{10f00}', '\u{10f1c}'),
+  ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'), ('𑀃', '𑀷'),
+  ('𑂃', '𑂯'), ('𑃐', '𑃨'), ('𑄃', '𑄦'),
+  ('\u{11144}', '\u{11144}'), ('𑅐', '𑅲'), ('𑅶', '𑅶'),
+  ('𑆃', '𑆲'), ('𑇁', '𑇄'), ('𑇚', '𑇚'), ('𑇜', '𑇜'),
+  ('𑈀', '𑈑'), ('𑈓', '𑈫'), ('𑊀', '𑊆'), ('𑊈', '𑊈'),
+  ('𑊊', '𑊍'), ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋞'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑌽'), ('𑍐', '𑍐'),
+  ('𑍝', '𑍡'), ('𑐀', '𑐴'), ('𑑇', '𑑊'), ('𑒀', '𑒯'),
+  ('𑓄', '𑓅'), ('𑓇', '𑓇'), ('𑖀', '𑖮'), ('𑗘', '𑗛'),
+  ('𑘀', '𑘯'), ('𑙄', '𑙄'), ('𑚀', '𑚪'), ('𑜀', '\u{1171a}'),
+  ('\u{11800}', '\u{1182b}'), ('𑢠', '𑣟'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨀'), ('𑨋', '𑨲'), ('𑨺', '𑨺'), ('𑩐', '𑩐'),
+  ('𑩜', '𑪃'), ('𑪆', '𑪉'), ('\u{11a9d}', '\u{11a9d}'),
+  ('𑫀', '𑫸'), ('𑰀', '𑰈'), ('𑰊', '𑰮'), ('𑱀', '𑱀'),
+  ('𑱲', '𑲏'), ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴰'),
+  ('𑵆', '𑵆'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d89}'), ('\u{11d98}', '\u{11d98}'),
+  ('\u{11ee0}', '\u{11ef2}'), ('𒀀', '𒎙'), ('𒐀', '𒑮'),
+  ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'),
+  ('𖩀', '𖩞'), ('𖫐', '𖫭'), ('𖬀', '𖬯'), ('𖭀', '𖭃'),
+  ('𖭣', '𖭷'), ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'),
+  ('𖼀', '𖽄'), ('𖽐', '𖽐'), ('𖾓', '𖾟'), ('𖿠', '𖿡'),
+  ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'),
+  ('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'),
+  ('𝐀', '𝑔'), ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'),
+  ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'),
+  ('𝒽', '𝓃'), ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'),
+  ('𝔖', '𝔜'), ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'),
+  ('𝕆', '𝕆'), ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝛀'),
+  ('𝛂', '𝛚'), ('𝛜', '𝛺'), ('𝛼', '𝜔'), ('𝜖', '𝜴'),
+  ('𝜶', '𝝎'), ('𝝐', '𝝮'), ('𝝰', '𝞈'), ('𝞊', '𝞨'),
+  ('𝞪', '𝟂'), ('𝟄', '𝟋'), ('𞠀', '𞣄'), ('𞤀', '𞥃'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'), ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'),
+  ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const IDEOGRAPHIC: &'static [(char, char)] = &[
+  ('〆', '〇'), ('〡', '〩'), ('〸', '〺'), ('㐀', '䶵'),
+  ('一', '\u{9fef}'), ('豈', '舘'), ('並', '龎'), ('𗀀', '\u{187f1}'),
+  ('𘠀', '𘫲'), ('𛅰', '𛋻'), ('𠀀', '𪛖'), ('𪜀', '𫜴'),
+  ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const JOIN_CONTROL: &'static [(char, char)] = &[
+  ('\u{200c}', '\u{200d}'),
+];
+
+pub const LOGICAL_ORDER_EXCEPTION: &'static [(char, char)] = &[
+  ('เ', 'ไ'), ('ເ', 'ໄ'), ('ᦵ', 'ᦷ'), ('ᦺ', 'ᦺ'),
+  ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪹ'), ('ꪻ', 'ꪼ'),
+];
+
+pub const LOWERCASE: &'static [(char, char)] = &[
+  ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'), ('ß', 'ö'),
+  ('ø', 'ÿ'), ('ā', 'ā'), ('ă', 'ă'), ('ą', 'ą'), ('ć', 'ć'),
+  ('ĉ', 'ĉ'), ('ċ', 'ċ'), ('č', 'č'), ('ď', 'ď'), ('đ', 'đ'),
+  ('ē', 'ē'), ('ĕ', 'ĕ'), ('ė', 'ė'), ('ę', 'ę'), ('ě', 'ě'),
+  ('ĝ', 'ĝ'), ('ğ', 'ğ'), ('ġ', 'ġ'), ('ģ', 'ģ'), ('ĥ', 'ĥ'),
+  ('ħ', 'ħ'), ('ĩ', 'ĩ'), ('ī', 'ī'), ('ĭ', 'ĭ'), ('į', 'į'),
+  ('ı', 'ı'), ('ĳ', 'ĳ'), ('ĵ', 'ĵ'), ('ķ', 'ĸ'), ('ĺ', 'ĺ'),
+  ('ļ', 'ļ'), ('ľ', 'ľ'), ('ŀ', 'ŀ'), ('ł', 'ł'), ('ń', 'ń'),
+  ('ņ', 'ņ'), ('ň', 'ŉ'), ('ŋ', 'ŋ'), ('ō', 'ō'), ('ŏ', 'ŏ'),
+  ('ő', 'ő'), ('œ', 'œ'), ('ŕ', 'ŕ'), ('ŗ', 'ŗ'), ('ř', 'ř'),
+  ('ś', 'ś'), ('ŝ', 'ŝ'), ('ş', 'ş'), ('š', 'š'), ('ţ', 'ţ'),
+  ('ť', 'ť'), ('ŧ', 'ŧ'), ('ũ', 'ũ'), ('ū', 'ū'), ('ŭ', 'ŭ'),
+  ('ů', 'ů'), ('ű', 'ű'), ('ų', 'ų'), ('ŵ', 'ŵ'), ('ŷ', 'ŷ'),
+  ('ź', 'ź'), ('ż', 'ż'), ('ž', 'ƀ'), ('ƃ', 'ƃ'), ('ƅ', 'ƅ'),
+  ('ƈ', 'ƈ'), ('ƌ', 'ƍ'), ('ƒ', 'ƒ'), ('ƕ', 'ƕ'), ('ƙ', 'ƛ'),
+  ('ƞ', 'ƞ'), ('ơ', 'ơ'), ('ƣ', 'ƣ'), ('ƥ', 'ƥ'), ('ƨ', 'ƨ'),
+  ('ƪ', 'ƫ'), ('ƭ', 'ƭ'), ('ư', 'ư'), ('ƴ', 'ƴ'), ('ƶ', 'ƶ'),
+  ('ƹ', 'ƺ'), ('ƽ', 'ƿ'), ('ǆ', 'ǆ'), ('ǉ', 'ǉ'), ('ǌ', 'ǌ'),
+  ('ǎ', 'ǎ'), ('ǐ', 'ǐ'), ('ǒ', 'ǒ'), ('ǔ', 'ǔ'), ('ǖ', 'ǖ'),
+  ('ǘ', 'ǘ'), ('ǚ', 'ǚ'), ('ǜ', 'ǝ'), ('ǟ', 'ǟ'), ('ǡ', 'ǡ'),
+  ('ǣ', 'ǣ'), ('ǥ', 'ǥ'), ('ǧ', 'ǧ'), ('ǩ', 'ǩ'), ('ǫ', 'ǫ'),
+  ('ǭ', 'ǭ'), ('ǯ', 'ǰ'), ('ǳ', 'ǳ'), ('ǵ', 'ǵ'), ('ǹ', 'ǹ'),
+  ('ǻ', 'ǻ'), ('ǽ', 'ǽ'), ('ǿ', 'ǿ'), ('ȁ', 'ȁ'), ('ȃ', 'ȃ'),
+  ('ȅ', 'ȅ'), ('ȇ', 'ȇ'), ('ȉ', 'ȉ'), ('ȋ', 'ȋ'), ('ȍ', 'ȍ'),
+  ('ȏ', 'ȏ'), ('ȑ', 'ȑ'), ('ȓ', 'ȓ'), ('ȕ', 'ȕ'), ('ȗ', 'ȗ'),
+  ('ș', 'ș'), ('ț', 'ț'), ('ȝ', 'ȝ'), ('ȟ', 'ȟ'), ('ȡ', 'ȡ'),
+  ('ȣ', 'ȣ'), ('ȥ', 'ȥ'), ('ȧ', 'ȧ'), ('ȩ', 'ȩ'), ('ȫ', 'ȫ'),
+  ('ȭ', 'ȭ'), ('ȯ', 'ȯ'), ('ȱ', 'ȱ'), ('ȳ', 'ȹ'), ('ȼ', 'ȼ'),
+  ('ȿ', 'ɀ'), ('ɂ', 'ɂ'), ('ɇ', 'ɇ'), ('ɉ', 'ɉ'), ('ɋ', 'ɋ'),
+  ('ɍ', 'ɍ'), ('ɏ', 'ʓ'), ('ʕ', 'ʸ'), ('ˀ', 'ˁ'), ('ˠ', 'ˤ'),
+  ('ͅ', 'ͅ'), ('ͱ', 'ͱ'), ('ͳ', 'ͳ'), ('ͷ', 'ͷ'), ('ͺ', 'ͽ'),
+  ('ΐ', 'ΐ'), ('ά', 'ώ'), ('ϐ', 'ϑ'), ('ϕ', 'ϗ'), ('ϙ', 'ϙ'),
+  ('ϛ', 'ϛ'), ('ϝ', 'ϝ'), ('ϟ', 'ϟ'), ('ϡ', 'ϡ'), ('ϣ', 'ϣ'),
+  ('ϥ', 'ϥ'), ('ϧ', 'ϧ'), ('ϩ', 'ϩ'), ('ϫ', 'ϫ'), ('ϭ', 'ϭ'),
+  ('ϯ', 'ϳ'), ('ϵ', 'ϵ'), ('ϸ', 'ϸ'), ('ϻ', 'ϼ'), ('а', 'џ'),
+  ('ѡ', 'ѡ'), ('ѣ', 'ѣ'), ('ѥ', 'ѥ'), ('ѧ', 'ѧ'), ('ѩ', 'ѩ'),
+  ('ѫ', 'ѫ'), ('ѭ', 'ѭ'), ('ѯ', 'ѯ'), ('ѱ', 'ѱ'), ('ѳ', 'ѳ'),
+  ('ѵ', 'ѵ'), ('ѷ', 'ѷ'), ('ѹ', 'ѹ'), ('ѻ', 'ѻ'), ('ѽ', 'ѽ'),
+  ('ѿ', 'ѿ'), ('ҁ', 'ҁ'), ('ҋ', 'ҋ'), ('ҍ', 'ҍ'), ('ҏ', 'ҏ'),
+  ('ґ', 'ґ'), ('ғ', 'ғ'), ('ҕ', 'ҕ'), ('җ', 'җ'), ('ҙ', 'ҙ'),
+  ('қ', 'қ'), ('ҝ', 'ҝ'), ('ҟ', 'ҟ'), ('ҡ', 'ҡ'), ('ң', 'ң'),
+  ('ҥ', 'ҥ'), ('ҧ', 'ҧ'), ('ҩ', 'ҩ'), ('ҫ', 'ҫ'), ('ҭ', 'ҭ'),
+  ('ү', 'ү'), ('ұ', 'ұ'), ('ҳ', 'ҳ'), ('ҵ', 'ҵ'), ('ҷ', 'ҷ'),
+  ('ҹ', 'ҹ'), ('һ', 'һ'), ('ҽ', 'ҽ'), ('ҿ', 'ҿ'), ('ӂ', 'ӂ'),
+  ('ӄ', 'ӄ'), ('ӆ', 'ӆ'), ('ӈ', 'ӈ'), ('ӊ', 'ӊ'), ('ӌ', 'ӌ'),
+  ('ӎ', 'ӏ'), ('ӑ', 'ӑ'), ('ӓ', 'ӓ'), ('ӕ', 'ӕ'), ('ӗ', 'ӗ'),
+  ('ә', 'ә'), ('ӛ', 'ӛ'), ('ӝ', 'ӝ'), ('ӟ', 'ӟ'), ('ӡ', 'ӡ'),
+  ('ӣ', 'ӣ'), ('ӥ', 'ӥ'), ('ӧ', 'ӧ'), ('ө', 'ө'), ('ӫ', 'ӫ'),
+  ('ӭ', 'ӭ'), ('ӯ', 'ӯ'), ('ӱ', 'ӱ'), ('ӳ', 'ӳ'), ('ӵ', 'ӵ'),
+  ('ӷ', 'ӷ'), ('ӹ', 'ӹ'), ('ӻ', 'ӻ'), ('ӽ', 'ӽ'), ('ӿ', 'ӿ'),
+  ('ԁ', 'ԁ'), ('ԃ', 'ԃ'), ('ԅ', 'ԅ'), ('ԇ', 'ԇ'), ('ԉ', 'ԉ'),
+  ('ԋ', 'ԋ'), ('ԍ', 'ԍ'), ('ԏ', 'ԏ'), ('ԑ', 'ԑ'), ('ԓ', 'ԓ'),
+  ('ԕ', 'ԕ'), ('ԗ', 'ԗ'), ('ԙ', 'ԙ'), ('ԛ', 'ԛ'), ('ԝ', 'ԝ'),
+  ('ԟ', 'ԟ'), ('ԡ', 'ԡ'), ('ԣ', 'ԣ'), ('ԥ', 'ԥ'), ('ԧ', 'ԧ'),
+  ('ԩ', 'ԩ'), ('ԫ', 'ԫ'), ('ԭ', 'ԭ'), ('ԯ', 'ԯ'),
+  ('\u{560}', '\u{588}'), ('ა', 'ჺ'), ('ჽ', 'ჿ'), ('ᏸ', 'ᏽ'),
+  ('ᲀ', 'ᲈ'), ('ᴀ', 'ᶿ'), ('ḁ', 'ḁ'), ('ḃ', 'ḃ'),
+  ('ḅ', 'ḅ'), ('ḇ', 'ḇ'), ('ḉ', 'ḉ'), ('ḋ', 'ḋ'),
+  ('ḍ', 'ḍ'), ('ḏ', 'ḏ'), ('ḑ', 'ḑ'), ('ḓ', 'ḓ'),
+  ('ḕ', 'ḕ'), ('ḗ', 'ḗ'), ('ḙ', 'ḙ'), ('ḛ', 'ḛ'),
+  ('ḝ', 'ḝ'), ('ḟ', 'ḟ'), ('ḡ', 'ḡ'), ('ḣ', 'ḣ'),
+  ('ḥ', 'ḥ'), ('ḧ', 'ḧ'), ('ḩ', 'ḩ'), ('ḫ', 'ḫ'),
+  ('ḭ', 'ḭ'), ('ḯ', 'ḯ'), ('ḱ', 'ḱ'), ('ḳ', 'ḳ'),
+  ('ḵ', 'ḵ'), ('ḷ', 'ḷ'), ('ḹ', 'ḹ'), ('ḻ', 'ḻ'),
+  ('ḽ', 'ḽ'), ('ḿ', 'ḿ'), ('ṁ', 'ṁ'), ('ṃ', 'ṃ'),
+  ('ṅ', 'ṅ'), ('ṇ', 'ṇ'), ('ṉ', 'ṉ'), ('ṋ', 'ṋ'),
+  ('ṍ', 'ṍ'), ('ṏ', 'ṏ'), ('ṑ', 'ṑ'), ('ṓ', 'ṓ'),
+  ('ṕ', 'ṕ'), ('ṗ', 'ṗ'), ('ṙ', 'ṙ'), ('ṛ', 'ṛ'),
+  ('ṝ', 'ṝ'), ('ṟ', 'ṟ'), ('ṡ', 'ṡ'), ('ṣ', 'ṣ'),
+  ('ṥ', 'ṥ'), ('ṧ', 'ṧ'), ('ṩ', 'ṩ'), ('ṫ', 'ṫ'),
+  ('ṭ', 'ṭ'), ('ṯ', 'ṯ'), ('ṱ', 'ṱ'), ('ṳ', 'ṳ'),
+  ('ṵ', 'ṵ'), ('ṷ', 'ṷ'), ('ṹ', 'ṹ'), ('ṻ', 'ṻ'),
+  ('ṽ', 'ṽ'), ('ṿ', 'ṿ'), ('ẁ', 'ẁ'), ('ẃ', 'ẃ'),
+  ('ẅ', 'ẅ'), ('ẇ', 'ẇ'), ('ẉ', 'ẉ'), ('ẋ', 'ẋ'),
+  ('ẍ', 'ẍ'), ('ẏ', 'ẏ'), ('ẑ', 'ẑ'), ('ẓ', 'ẓ'),
+  ('ẕ', 'ẝ'), ('ẟ', 'ẟ'), ('ạ', 'ạ'), ('ả', 'ả'),
+  ('ấ', 'ấ'), ('ầ', 'ầ'), ('ẩ', 'ẩ'), ('ẫ', 'ẫ'),
+  ('ậ', 'ậ'), ('ắ', 'ắ'), ('ằ', 'ằ'), ('ẳ', 'ẳ'),
+  ('ẵ', 'ẵ'), ('ặ', 'ặ'), ('ẹ', 'ẹ'), ('ẻ', 'ẻ'),
+  ('ẽ', 'ẽ'), ('ế', 'ế'), ('ề', 'ề'), ('ể', 'ể'),
+  ('ễ', 'ễ'), ('ệ', 'ệ'), ('ỉ', 'ỉ'), ('ị', 'ị'),
+  ('ọ', 'ọ'), ('ỏ', 'ỏ'), ('ố', 'ố'), ('ồ', 'ồ'),
+  ('ổ', 'ổ'), ('ỗ', 'ỗ'), ('ộ', 'ộ'), ('ớ', 'ớ'),
+  ('ờ', 'ờ'), ('ở', 'ở'), ('ỡ', 'ỡ'), ('ợ', 'ợ'),
+  ('ụ', 'ụ'), ('ủ', 'ủ'), ('ứ', 'ứ'), ('ừ', 'ừ'),
+  ('ử', 'ử'), ('ữ', 'ữ'), ('ự', 'ự'), ('ỳ', 'ỳ'),
+  ('ỵ', 'ỵ'), ('ỷ', 'ỷ'), ('ỹ', 'ỹ'), ('ỻ', 'ỻ'),
+  ('ỽ', 'ỽ'), ('ỿ', 'ἇ'), ('ἐ', 'ἕ'), ('ἠ', 'ἧ'),
+  ('ἰ', 'ἷ'), ('ὀ', 'ὅ'), ('ὐ', 'ὗ'), ('ὠ', 'ὧ'),
+  ('ὰ', 'ώ'), ('ᾀ', 'ᾇ'), ('ᾐ', 'ᾗ'), ('ᾠ', 'ᾧ'),
+  ('ᾰ', 'ᾴ'), ('ᾶ', 'ᾷ'), ('ι', 'ι'), ('ῂ', 'ῄ'),
+  ('ῆ', 'ῇ'), ('ῐ', 'ΐ'), ('ῖ', 'ῗ'), ('ῠ', 'ῧ'),
+  ('ῲ', 'ῴ'), ('ῶ', 'ῷ'), ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'),
+  ('ₐ', 'ₜ'), ('ℊ', 'ℊ'), ('ℎ', 'ℏ'), ('ℓ', 'ℓ'),
+  ('ℯ', 'ℯ'), ('ℴ', 'ℴ'), ('ℹ', 'ℹ'), ('ℼ', 'ℽ'),
+  ('ⅆ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('ⅰ', 'ⅿ'), ('ↄ', 'ↄ'),
+  ('ⓐ', 'ⓩ'), ('ⰰ', 'ⱞ'), ('ⱡ', 'ⱡ'), ('ⱥ', 'ⱦ'),
+  ('ⱨ', 'ⱨ'), ('ⱪ', 'ⱪ'), ('ⱬ', 'ⱬ'), ('ⱱ', 'ⱱ'),
+  ('ⱳ', 'ⱴ'), ('ⱶ', 'ⱽ'), ('ⲁ', 'ⲁ'), ('ⲃ', 'ⲃ'),
+  ('ⲅ', 'ⲅ'), ('ⲇ', 'ⲇ'), ('ⲉ', 'ⲉ'), ('ⲋ', 'ⲋ'),
+  ('ⲍ', 'ⲍ'), ('ⲏ', 'ⲏ'), ('ⲑ', 'ⲑ'), ('ⲓ', 'ⲓ'),
+  ('ⲕ', 'ⲕ'), ('ⲗ', 'ⲗ'), ('ⲙ', 'ⲙ'), ('ⲛ', 'ⲛ'),
+  ('ⲝ', 'ⲝ'), ('ⲟ', 'ⲟ'), ('ⲡ', 'ⲡ'), ('ⲣ', 'ⲣ'),
+  ('ⲥ', 'ⲥ'), ('ⲧ', 'ⲧ'), ('ⲩ', 'ⲩ'), ('ⲫ', 'ⲫ'),
+  ('ⲭ', 'ⲭ'), ('ⲯ', 'ⲯ'), ('ⲱ', 'ⲱ'), ('ⲳ', 'ⲳ'),
+  ('ⲵ', 'ⲵ'), ('ⲷ', 'ⲷ'), ('ⲹ', 'ⲹ'), ('ⲻ', 'ⲻ'),
+  ('ⲽ', 'ⲽ'), ('ⲿ', 'ⲿ'), ('ⳁ', 'ⳁ'), ('ⳃ', 'ⳃ'),
+  ('ⳅ', 'ⳅ'), ('ⳇ', 'ⳇ'), ('ⳉ', 'ⳉ'), ('ⳋ', 'ⳋ'),
+  ('ⳍ', 'ⳍ'), ('ⳏ', 'ⳏ'), ('ⳑ', 'ⳑ'), ('ⳓ', 'ⳓ'),
+  ('ⳕ', 'ⳕ'), ('ⳗ', 'ⳗ'), ('ⳙ', 'ⳙ'), ('ⳛ', 'ⳛ'),
+  ('ⳝ', 'ⳝ'), ('ⳟ', 'ⳟ'), ('ⳡ', 'ⳡ'), ('ⳣ', 'ⳤ'),
+  ('ⳬ', 'ⳬ'), ('ⳮ', 'ⳮ'), ('ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'),
+  ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ꙁ', 'ꙁ'), ('ꙃ', 'ꙃ'),
+  ('ꙅ', 'ꙅ'), ('ꙇ', 'ꙇ'), ('ꙉ', 'ꙉ'), ('ꙋ', 'ꙋ'),
+  ('ꙍ', 'ꙍ'), ('ꙏ', 'ꙏ'), ('ꙑ', 'ꙑ'), ('ꙓ', 'ꙓ'),
+  ('ꙕ', 'ꙕ'), ('ꙗ', 'ꙗ'), ('ꙙ', 'ꙙ'), ('ꙛ', 'ꙛ'),
+  ('ꙝ', 'ꙝ'), ('ꙟ', 'ꙟ'), ('ꙡ', 'ꙡ'), ('ꙣ', 'ꙣ'),
+  ('ꙥ', 'ꙥ'), ('ꙧ', 'ꙧ'), ('ꙩ', 'ꙩ'), ('ꙫ', 'ꙫ'),
+  ('ꙭ', 'ꙭ'), ('ꚁ', 'ꚁ'), ('ꚃ', 'ꚃ'), ('ꚅ', 'ꚅ'),
+  ('ꚇ', 'ꚇ'), ('ꚉ', 'ꚉ'), ('ꚋ', 'ꚋ'), ('ꚍ', 'ꚍ'),
+  ('ꚏ', 'ꚏ'), ('ꚑ', 'ꚑ'), ('ꚓ', 'ꚓ'), ('ꚕ', 'ꚕ'),
+  ('ꚗ', 'ꚗ'), ('ꚙ', 'ꚙ'), ('ꚛ', 'ꚝ'), ('ꜣ', 'ꜣ'),
+  ('ꜥ', 'ꜥ'), ('ꜧ', 'ꜧ'), ('ꜩ', 'ꜩ'), ('ꜫ', 'ꜫ'),
+  ('ꜭ', 'ꜭ'), ('ꜯ', 'ꜱ'), ('ꜳ', 'ꜳ'), ('ꜵ', 'ꜵ'),
+  ('ꜷ', 'ꜷ'), ('ꜹ', 'ꜹ'), ('ꜻ', 'ꜻ'), ('ꜽ', 'ꜽ'),
+  ('ꜿ', 'ꜿ'), ('ꝁ', 'ꝁ'), ('ꝃ', 'ꝃ'), ('ꝅ', 'ꝅ'),
+  ('ꝇ', 'ꝇ'), ('ꝉ', 'ꝉ'), ('ꝋ', 'ꝋ'), ('ꝍ', 'ꝍ'),
+  ('ꝏ', 'ꝏ'), ('ꝑ', 'ꝑ'), ('ꝓ', 'ꝓ'), ('ꝕ', 'ꝕ'),
+  ('ꝗ', 'ꝗ'), ('ꝙ', 'ꝙ'), ('ꝛ', 'ꝛ'), ('ꝝ', 'ꝝ'),
+  ('ꝟ', 'ꝟ'), ('ꝡ', 'ꝡ'), ('ꝣ', 'ꝣ'), ('ꝥ', 'ꝥ'),
+  ('ꝧ', 'ꝧ'), ('ꝩ', 'ꝩ'), ('ꝫ', 'ꝫ'), ('ꝭ', 'ꝭ'),
+  ('ꝯ', 'ꝸ'), ('ꝺ', 'ꝺ'), ('ꝼ', 'ꝼ'), ('ꝿ', 'ꝿ'),
+  ('ꞁ', 'ꞁ'), ('ꞃ', 'ꞃ'), ('ꞅ', 'ꞅ'), ('ꞇ', 'ꞇ'),
+  ('ꞌ', 'ꞌ'), ('ꞎ', 'ꞎ'), ('ꞑ', 'ꞑ'), ('ꞓ', 'ꞕ'),
+  ('ꞗ', 'ꞗ'), ('ꞙ', 'ꞙ'), ('ꞛ', 'ꞛ'), ('ꞝ', 'ꞝ'),
+  ('ꞟ', 'ꞟ'), ('ꞡ', 'ꞡ'), ('ꞣ', 'ꞣ'), ('ꞥ', 'ꞥ'),
+  ('ꞧ', 'ꞧ'), ('ꞩ', 'ꞩ'), ('\u{a7af}', '\u{a7af}'), ('ꞵ', 'ꞵ'),
+  ('ꞷ', 'ꞷ'), ('\u{a7b9}', '\u{a7b9}'), ('ꟸ', 'ꟺ'), ('ꬰ', 'ꭚ'),
+  ('ꭜ', 'ꭥ'), ('ꭰ', 'ꮿ'), ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'),
+  ('ａ', 'ｚ'), ('𐐨', '𐑏'), ('𐓘', '𐓻'), ('𐳀', '𐳲'),
+  ('𑣀', '𑣟'), ('\u{16e60}', '\u{16e7f}'), ('𝐚', '𝐳'),
+  ('𝑎', '𝑔'), ('𝑖', '𝑧'), ('𝒂', '𝒛'), ('𝒶', '𝒹'),
+  ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝓏'), ('𝓪', '𝔃'),
+  ('𝔞', '𝔷'), ('𝕒', '𝕫'), ('𝖆', '𝖟'), ('𝖺', '𝗓'),
+  ('𝗮', '𝘇'), ('𝘢', '𝘻'), ('𝙖', '𝙯'), ('𝚊', '𝚥'),
+  ('𝛂', '𝛚'), ('𝛜', '𝛡'), ('𝛼', '𝜔'), ('𝜖', '𝜛'),
+  ('𝜶', '𝝎'), ('𝝐', '𝝕'), ('𝝰', '𝞈'), ('𝞊', '𝞏'),
+  ('𝞪', '𝟂'), ('𝟄', '𝟉'), ('𝟋', '𝟋'), ('𞤢', '𞥃'),
+];
+
+pub const MATH: &'static [(char, char)] = &[
+  ('+', '+'), ('<', '>'), ('^', '^'), ('|', '|'), ('~', '~'), ('¬', '¬'),
+  ('±', '±'), ('×', '×'), ('÷', '÷'), ('ϐ', 'ϒ'), ('ϕ', 'ϕ'),
+  ('ϰ', 'ϱ'), ('ϴ', '϶'), ('؆', '؈'), ('‖', '‖'), ('′', '‴'),
+  ('⁀', '⁀'), ('⁄', '⁄'), ('⁒', '⁒'), ('\u{2061}', '\u{2064}'),
+  ('⁺', '⁾'), ('₊', '₎'), ('⃐', '⃜'), ('⃡', '⃡'),
+  ('⃥', '⃦'), ('⃫', '⃯'), ('ℂ', 'ℂ'), ('ℇ', 'ℇ'),
+  ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('℘', 'ℝ'), ('ℤ', 'ℤ'),
+  ('ℨ', '℩'), ('ℬ', 'ℭ'), ('ℯ', 'ℱ'), ('ℳ', 'ℸ'),
+  ('ℼ', 'ⅉ'), ('⅋', '⅋'), ('←', '↧'), ('↩', '↮'),
+  ('↰', '↱'), ('↶', '↷'), ('↼', '⇛'), ('⇝', '⇝'),
+  ('⇤', '⇥'), ('⇴', '⋿'), ('⌈', '⌋'), ('⌠', '⌡'),
+  ('⍼', '⍼'), ('⎛', '⎵'), ('⎷', '⎷'), ('⏐', '⏐'),
+  ('⏜', '⏢'), ('■', '□'), ('▮', '▷'), ('▼', '◁'),
+  ('◆', '◇'), ('◊', '○'), ('●', '◓'), ('◢', '◢'),
+  ('◤', '◤'), ('◧', '◬'), ('◸', '◿'), ('★', '☆'),
+  ('♀', '♀'), ('♂', '♂'), ('♠', '♣'), ('♭', '♯'),
+  ('⟀', '⟿'), ('⤀', '⫿'), ('⬰', '⭄'), ('⭇', '⭌'),
+  ('﬩', '﬩'), ('﹡', '﹦'), ('﹨', '﹨'), ('＋', '＋'),
+  ('＜', '＞'), ('＼', '＼'), ('＾', '＾'), ('｜', '｜'),
+  ('～', '～'), ('￢', '￢'), ('￩', '￬'), ('𝐀', '𝑔'),
+  ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'),
+  ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'),
+  ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝟋'), ('𝟎', '𝟿'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'), ('𞻰', '𞻱'),
+];
+
+pub const NONCHARACTER_CODE_POINT: &'static [(char, char)] = &[
+  ('\u{fdd0}', '\u{fdef}'), ('\u{fffe}', '\u{ffff}'),
+  ('\u{1fffe}', '\u{1ffff}'), ('\u{2fffe}', '\u{2ffff}'),
+  ('\u{3fffe}', '\u{3ffff}'), ('\u{4fffe}', '\u{4ffff}'),
+  ('\u{5fffe}', '\u{5ffff}'), ('\u{6fffe}', '\u{6ffff}'),
+  ('\u{7fffe}', '\u{7ffff}'), ('\u{8fffe}', '\u{8ffff}'),
+  ('\u{9fffe}', '\u{9ffff}'), ('\u{afffe}', '\u{affff}'),
+  ('\u{bfffe}', '\u{bffff}'), ('\u{cfffe}', '\u{cffff}'),
+  ('\u{dfffe}', '\u{dffff}'), ('\u{efffe}', '\u{effff}'),
+  ('\u{ffffe}', '\u{fffff}'), ('\u{10fffe}', '\u{10ffff}'),
+];
+
+pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
+  ('ͅ', 'ͅ'), ('ְ', 'ֽ'), ('ֿ', 'ֿ'), ('ׁ', 'ׂ'), ('ׄ', 'ׅ'),
+  ('ׇ', 'ׇ'), ('ؐ', 'ؚ'), ('ً', 'ٗ'), ('ٙ', 'ٟ'), ('ٰ', 'ٰ'),
+  ('ۖ', 'ۜ'), ('ۡ', 'ۤ'), ('ۧ', 'ۨ'), ('ۭ', 'ۭ'), ('ܑ', 'ܑ'),
+  ('ܰ', 'ܿ'), ('ަ', 'ް'), ('ࠖ', 'ࠗ'), ('ࠛ', 'ࠣ'), ('ࠥ', 'ࠧ'),
+  ('ࠩ', 'ࠬ'), ('ࣔ', 'ࣟ'), ('ࣣ', 'ࣩ'), ('ࣰ', 'ः'),
+  ('ऺ', 'ऻ'), ('ा', 'ौ'), ('ॎ', 'ॏ'), ('ॕ', 'ॗ'),
+  ('ॢ', 'ॣ'), ('ঁ', 'ঃ'), ('া', 'ৄ'), ('ে', 'ৈ'),
+  ('ো', 'ৌ'), ('ৗ', 'ৗ'), ('ৢ', 'ৣ'), ('ਁ', 'ਃ'),
+  ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', 'ੌ'), ('ੑ', 'ੑ'),
+  ('ੰ', 'ੱ'), ('ੵ', 'ੵ'), ('ઁ', 'ઃ'), ('ા', 'ૅ'),
+  ('ે', 'ૉ'), ('ો', 'ૌ'), ('ૢ', 'ૣ'), ('ૺ', 'ૼ'),
+  ('ଁ', 'ଃ'), ('ା', 'ୄ'), ('େ', 'ୈ'), ('ୋ', 'ୌ'),
+  ('ୖ', 'ୗ'), ('ୢ', 'ୣ'), ('ஂ', 'ஂ'), ('ா', 'ூ'),
+  ('ெ', 'ை'), ('ொ', 'ௌ'), ('ௗ', 'ௗ'), ('ఀ', 'ః'),
+  ('ా', 'ౄ'), ('ె', 'ై'), ('ొ', 'ౌ'), ('ౕ', 'ౖ'),
+  ('ౢ', 'ౣ'), ('ಁ', 'ಃ'), ('ಾ', 'ೄ'), ('ೆ', 'ೈ'),
+  ('ೊ', 'ೌ'), ('ೕ', 'ೖ'), ('ೢ', 'ೣ'), ('ഀ', 'ഃ'),
+  ('ാ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', 'ൌ'), ('ൗ', 'ൗ'),
+  ('ൢ', 'ൣ'), ('ං', 'ඃ'), ('ා', 'ු'), ('ූ', 'ූ'),
+  ('ෘ', 'ෟ'), ('ෲ', 'ෳ'), ('ั', 'ั'), ('ิ', 'ฺ'),
+  ('ํ', 'ํ'), ('ັ', 'ັ'), ('ິ', 'ູ'), ('ົ', 'ຼ'),
+  ('ໍ', 'ໍ'), ('ཱ', 'ཱྀ'), ('ྍ', 'ྗ'), ('ྙ', 'ྼ'),
+  ('ါ', 'ံ'), ('း', 'း'), ('ျ', 'ှ'), ('ၖ', 'ၙ'),
+  ('ၞ', 'ၠ'), ('ၢ', 'ၢ'), ('ၧ', 'ၨ'), ('ၱ', 'ၴ'),
+  ('ႂ', 'ႆ'), ('ႜ', 'ႝ'), ('፟', '፟'), ('ᜒ', 'ᜓ'),
+  ('ᜲ', 'ᜳ'), ('ᝒ', 'ᝓ'), ('ᝲ', 'ᝳ'), ('ា', 'ៈ'),
+  ('ᢅ', 'ᢆ'), ('ᢩ', 'ᢩ'), ('ᤠ', 'ᤫ'), ('ᤰ', 'ᤸ'),
+  ('ᨗ', 'ᨛ'), ('ᩕ', 'ᩞ'), ('ᩡ', 'ᩴ'), ('ᬀ', 'ᬄ'),
+  ('ᬵ', 'ᭃ'), ('ᮀ', 'ᮂ'), ('ᮡ', 'ᮩ'), ('ᮬ', 'ᮭ'),
+  ('ᯧ', 'ᯱ'), ('ᰤ', 'ᰵ'), ('ᳲ', 'ᳳ'), ('ᷧ', 'ᷴ'),
+  ('Ⓐ', 'ⓩ'), ('ⷠ', 'ⷿ'), ('ꙴ', 'ꙻ'), ('ꚞ', 'ꚟ'),
+  ('ꠣ', 'ꠧ'), ('ꢀ', 'ꢁ'), ('ꢴ', 'ꣃ'), ('ꣅ', 'ꣅ'),
+  ('ꤦ', 'ꤪ'), ('ꥇ', 'ꥒ'), ('ꦀ', 'ꦃ'), ('ꦴ', 'ꦿ'),
+  ('ꨩ', 'ꨶ'), ('ꩃ', 'ꩃ'), ('ꩌ', 'ꩍ'), ('ꪰ', 'ꪰ'),
+  ('ꪲ', 'ꪴ'), ('ꪷ', 'ꪸ'), ('ꪾ', 'ꪾ'), ('ꫫ', 'ꫯ'),
+  ('ꫵ', 'ꫵ'), ('ꯣ', 'ꯪ'), ('ﬞ', 'ﬞ'), ('𐍶', '𐍺'),
+  ('𐨁', '𐨃'), ('𐨅', '𐨆'), ('𐨌', '𐨏'),
+  ('\u{10d24}', '\u{10d27}'), ('𑀀', '𑀂'), ('𑀸', '𑁅'),
+  ('𑂂', '𑂂'), ('𑂰', '𑂸'), ('𑄀', '𑄂'), ('𑄧', '𑄲'),
+  ('\u{11145}', '\u{11146}'), ('𑆀', '𑆂'), ('𑆳', '𑆿'),
+  ('𑈬', '𑈴'), ('𑈷', '𑈷'), ('𑈾', '𑈾'), ('𑋟', '𑋨'),
+  ('𑌀', '𑌃'), ('𑌾', '𑍄'), ('𑍇', '𑍈'), ('𑍋', '𑍌'),
+  ('𑍗', '𑍗'), ('𑍢', '𑍣'), ('𑐵', '𑑁'), ('𑑃', '𑑅'),
+  ('𑒰', '𑓁'), ('𑖯', '𑖵'), ('𑖸', '𑖾'), ('𑗜', '𑗝'),
+  ('𑘰', '𑘾'), ('𑙀', '𑙀'), ('𑚫', '𑚵'), ('𑜝', '𑜪'),
+  ('\u{1182c}', '\u{11838}'), ('𑨁', '𑨊'), ('𑨵', '𑨹'),
+  ('𑨻', '𑨾'), ('𑩑', '𑩛'), ('𑪊', '𑪗'), ('𑰯', '𑰶'),
+  ('𑰸', '𑰾'), ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴱', '𑴶'),
+  ('𑴺', '𑴺'), ('𑴼', '𑴽'), ('𑴿', '𑵁'), ('𑵃', '𑵃'),
+  ('𑵇', '𑵇'), ('\u{11d8a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d96}'), ('\u{11ef3}', '\u{11ef6}'), ('𖬰', '𖬶'),
+  ('𖽑', '𖽾'), ('𛲞', '𛲞'), ('𞀀', '𞀆'), ('𞀈', '𞀘'),
+  ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'), ('𞥇', '𞥇'),
+  ('🄰', '🅉'), ('🅐', '🅩'), ('🅰', '🆉'),
+];
+
+pub const OTHER_DEFAULT_IGNORABLE_CODE_POINT: &'static [(char, char)] = &[
+  ('͏', '͏'), ('ᅟ', 'ᅠ'), ('឴', '឵'), ('\u{2065}', '\u{2065}'),
+  ('ㅤ', 'ㅤ'), ('ﾠ', 'ﾠ'), ('\u{fff0}', '\u{fff8}'),
+  ('\u{e0000}', '\u{e0000}'), ('\u{e0002}', '\u{e001f}'),
+  ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{e0fff}'),
+];
+
+pub const OTHER_GRAPHEME_EXTEND: &'static [(char, char)] = &[
+  ('া', 'া'), ('ৗ', 'ৗ'), ('ା', 'ା'), ('ୗ', 'ୗ'),
+  ('ா', 'ா'), ('ௗ', 'ௗ'), ('ೂ', 'ೂ'), ('ೕ', 'ೖ'),
+  ('ാ', 'ാ'), ('ൗ', 'ൗ'), ('ා', 'ා'), ('ෟ', 'ෟ'),
+  ('\u{200c}', '\u{200c}'), ('〮', '〯'), ('ﾞ', 'ﾟ'), ('𑌾', '𑌾'),
+  ('𑍗', '𑍗'), ('𑒰', '𑒰'), ('𑒽', '𑒽'), ('𑖯', '𑖯'),
+  ('𝅥', '𝅥'), ('𝅮', '𝅲'), ('\u{e0020}', '\u{e007f}'),
+];
+
+pub const OTHER_ID_CONTINUE: &'static [(char, char)] = &[
+  ('·', '·'), ('·', '·'), ('፩', '፱'), ('᧚', '᧚'),
+];
+
+pub const OTHER_ID_START: &'static [(char, char)] = &[
+  ('ᢅ', 'ᢆ'), ('℘', '℘'), ('℮', '℮'), ('゛', '゜'),
+];
+
+pub const OTHER_LOWERCASE: &'static [(char, char)] = &[
+  ('ª', 'ª'), ('º', 'º'), ('ʰ', 'ʸ'), ('ˀ', 'ˁ'), ('ˠ', 'ˤ'),
+  ('ͅ', 'ͅ'), ('ͺ', 'ͺ'), ('ᴬ', 'ᵪ'), ('ᵸ', 'ᵸ'), ('ᶛ', 'ᶿ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ⅰ', 'ⅿ'),
+  ('ⓐ', 'ⓩ'), ('ⱼ', 'ⱽ'), ('ꚜ', 'ꚝ'), ('ꝰ', 'ꝰ'),
+  ('ꟸ', 'ꟹ'), ('ꭜ', 'ꭟ'),
+];
+
+pub const OTHER_MATH: &'static [(char, char)] = &[
+  ('^', '^'), ('ϐ', 'ϒ'), ('ϕ', 'ϕ'), ('ϰ', 'ϱ'), ('ϴ', 'ϵ'),
+  ('‖', '‖'), ('′', '‴'), ('⁀', '⁀'), ('\u{2061}', '\u{2064}'),
+  ('⁽', '⁾'), ('₍', '₎'), ('⃐', '⃜'), ('⃡', '⃡'),
+  ('⃥', '⃦'), ('⃫', '⃯'), ('ℂ', 'ℂ'), ('ℇ', 'ℇ'),
+  ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('ℙ', 'ℝ'), ('ℤ', 'ℤ'),
+  ('ℨ', '℩'), ('ℬ', 'ℭ'), ('ℯ', 'ℱ'), ('ℳ', 'ℸ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('↕', '↙'), ('↜', '↟'),
+  ('↡', '↢'), ('↤', '↥'), ('↧', '↧'), ('↩', '↭'),
+  ('↰', '↱'), ('↶', '↷'), ('↼', '⇍'), ('⇐', '⇑'),
+  ('⇓', '⇓'), ('⇕', '⇛'), ('⇝', '⇝'), ('⇤', '⇥'),
+  ('⌈', '⌋'), ('⎴', '⎵'), ('⎷', '⎷'), ('⏐', '⏐'),
+  ('⏢', '⏢'), ('■', '□'), ('▮', '▶'), ('▼', '◀'),
+  ('◆', '◇'), ('◊', '○'), ('●', '◓'), ('◢', '◢'),
+  ('◤', '◤'), ('◧', '◬'), ('★', '☆'), ('♀', '♀'),
+  ('♂', '♂'), ('♠', '♣'), ('♭', '♮'), ('⟅', '⟆'),
+  ('⟦', '⟯'), ('⦃', '⦘'), ('⧘', '⧛'), ('⧼', '⧽'),
+  ('﹡', '﹡'), ('﹣', '﹣'), ('﹨', '﹨'), ('＼', '＼'),
+  ('＾', '＾'), ('𝐀', '𝑔'), ('𝑖', '𝒜'), ('𝒞', '𝒟'),
+  ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒹'),
+  ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'), ('𝔇', '𝔊'),
+  ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'), ('𝔻', '𝔾'),
+  ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'), ('𝕒', '𝚥'),
+  ('𝚨', '𝛀'), ('𝛂', '𝛚'), ('𝛜', '𝛺'), ('𝛼', '𝜔'),
+  ('𝜖', '𝜴'), ('𝜶', '𝝎'), ('𝝐', '𝝮'), ('𝝰', '𝞈'),
+  ('𝞊', '𝞨'), ('𝞪', '𝟂'), ('𝟄', '𝟋'), ('𝟎', '𝟿'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'),
+];
+
+pub const OTHER_UPPERCASE: &'static [(char, char)] = &[
+  ('Ⅰ', 'Ⅿ'), ('Ⓐ', 'Ⓩ'), ('🄰', '🅉'), ('🅐', '🅩'),
+  ('🅰', '🆉'),
+];
+
+pub const PATTERN_SYNTAX: &'static [(char, char)] = &[
+  ('!', '/'), (':', '@'), ('[', '^'), ('`', '`'), ('{', '~'), ('¡', '§'),
+  ('©', '©'), ('«', '¬'), ('®', '®'), ('°', '±'), ('¶', '¶'),
+  ('»', '»'), ('¿', '¿'), ('×', '×'), ('÷', '÷'), ('‐', '‧'),
+  ('‰', '‾'), ('⁁', '⁓'), ('⁕', '⁞'), ('←', '\u{245f}'),
+  ('─', '❵'), ('➔', '\u{2bff}'), ('⸀', '\u{2e7f}'), ('、', '〃'),
+  ('〈', '〠'), ('〰', '〰'), ('﴾', '﴿'), ('﹅', '﹆'),
+];
+
+pub const PATTERN_WHITE_SPACE: &'static [(char, char)] = &[
+  ('\t', '\r'), (' ', ' '), ('\u{85}', '\u{85}'), ('\u{200e}', '\u{200f}'),
+  ('\u{2028}', '\u{2029}'),
+];
+
+pub const PREPENDED_CONCATENATION_MARK: &'static [(char, char)] = &[
+  ('\u{600}', '\u{605}'), ('\u{6dd}', '\u{6dd}'), ('\u{70f}', '\u{70f}'),
+  ('\u{8e2}', '\u{8e2}'), ('\u{110bd}', '\u{110bd}'),
+  ('\u{110cd}', '\u{110cd}'),
+];
+
+pub const QUOTATION_MARK: &'static [(char, char)] = &[
+  ('\"', '\"'), ('\'', '\''), ('«', '«'), ('»', '»'), ('‘', '‟'),
+  ('‹', '›'), ('⹂', '⹂'), ('「', '』'), ('〝', '〟'),
+  ('﹁', '﹄'), ('＂', '＂'), ('＇', '＇'), ('｢', '｣'),
+];
+
+pub const RADICAL: &'static [(char, char)] = &[
+  ('⺀', '⺙'), ('⺛', '⻳'), ('⼀', '⿕'),
+];
+
+pub const REGIONAL_INDICATOR: &'static [(char, char)] = &[
+  ('🇦', '🇿'),
+];
+
+pub const SENTENCE_TERMINAL: &'static [(char, char)] = &[
+  ('!', '!'), ('.', '.'), ('?', '?'), ('։', '։'), ('؞', '؟'),
+  ('۔', '۔'), ('܀', '܂'), ('߹', '߹'), ('࠷', '࠷'), ('࠹', '࠹'),
+  ('࠽', '࠾'), ('।', '॥'), ('၊', '။'), ('።', '።'),
+  ('፧', '፨'), ('᙮', '᙮'), ('᜵', '᜶'), ('᠃', '᠃'),
+  ('᠉', '᠉'), ('᥄', '᥅'), ('᪨', '᪫'), ('᭚', '᭛'),
+  ('᭞', '᭟'), ('᰻', '᰼'), ('᱾', '᱿'), ('‼', '‽'),
+  ('⁇', '⁉'), ('⸮', '⸮'), ('⸼', '⸼'), ('。', '。'),
+  ('꓿', '꓿'), ('꘎', '꘏'), ('꛳', '꛳'), ('꛷', '꛷'),
+  ('꡶', '꡷'), ('꣎', '꣏'), ('꤯', '꤯'), ('꧈', '꧉'),
+  ('꩝', '꩟'), ('꫰', '꫱'), ('꯫', '꯫'), ('﹒', '﹒'),
+  ('﹖', '﹗'), ('！', '！'), ('．', '．'), ('？', '？'),
+  ('｡', '｡'), ('𐩖', '𐩗'), ('\u{10f55}', '\u{10f59}'),
+  ('𑁇', '𑁈'), ('𑂾', '𑃁'), ('𑅁', '𑅃'), ('𑇅', '𑇆'),
+  ('𑇍', '𑇍'), ('𑇞', '𑇟'), ('𑈸', '𑈹'), ('𑈻', '𑈼'),
+  ('𑊩', '𑊩'), ('𑑋', '𑑌'), ('𑗂', '𑗃'), ('𑗉', '𑗗'),
+  ('𑙁', '𑙂'), ('𑜼', '𑜾'), ('𑩂', '𑩃'), ('𑪛', '𑪜'),
+  ('𑱁', '𑱂'), ('\u{11ef7}', '\u{11ef8}'), ('𖩮', '𖩯'),
+  ('𖫵', '𖫵'), ('𖬷', '𖬸'), ('𖭄', '𖭄'),
+  ('\u{16e98}', '\u{16e98}'), ('𛲟', '𛲟'), ('𝪈', '𝪈'),
+];
+
+pub const SOFT_DOTTED: &'static [(char, char)] = &[
+  ('i', 'j'), ('į', 'į'), ('ɉ', 'ɉ'), ('ɨ', 'ɨ'), ('ʝ', 'ʝ'),
+  ('ʲ', 'ʲ'), ('ϳ', 'ϳ'), ('і', 'і'), ('ј', 'ј'), ('ᵢ', 'ᵢ'),
+  ('ᶖ', 'ᶖ'), ('ᶤ', 'ᶤ'), ('ᶨ', 'ᶨ'), ('ḭ', 'ḭ'),
+  ('ị', 'ị'), ('ⁱ', 'ⁱ'), ('ⅈ', 'ⅉ'), ('ⱼ', 'ⱼ'),
+  ('𝐢', '𝐣'), ('𝑖', '𝑗'), ('𝒊', '𝒋'), ('𝒾', '𝒿'),
+  ('𝓲', '𝓳'), ('𝔦', '𝔧'), ('𝕚', '𝕛'), ('𝖎', '𝖏'),
+  ('𝗂', '𝗃'), ('𝗶', '𝗷'), ('𝘪', '𝘫'), ('𝙞', '𝙟'),
+  ('𝚒', '𝚓'),
+];
+
+pub const TERMINAL_PUNCTUATION: &'static [(char, char)] = &[
+  ('!', '!'), (',', ','), ('.', '.'), (':', ';'), ('?', '?'), (';', ';'),
+  ('·', '·'), ('։', '։'), ('׃', '׃'), ('،', '،'), ('؛', '؛'),
+  ('؞', '؟'), ('۔', '۔'), ('܀', '܊'), ('܌', '܌'), ('߸', '߹'),
+  ('࠰', '࠾'), ('࡞', '࡞'), ('।', '॥'), ('๚', '๛'),
+  ('༈', '༈'), ('།', '༒'), ('၊', '။'), ('፡', '፨'),
+  ('᙭', '᙮'), ('᛫', '᛭'), ('᜵', '᜶'), ('។', '៖'),
+  ('៚', '៚'), ('᠂', '᠅'), ('᠈', '᠉'), ('᥄', '᥅'),
+  ('᪨', '᪫'), ('᭚', '᭛'), ('᭝', '᭟'), ('᰻', '᰿'),
+  ('᱾', '᱿'), ('‼', '‽'), ('⁇', '⁉'), ('⸮', '⸮'),
+  ('⸼', '⸼'), ('⹁', '⹁'), ('\u{2e4c}', '\u{2e4c}'),
+  ('\u{2e4e}', '\u{2e4e}'), ('、', '。'), ('꓾', '꓿'), ('꘍', '꘏'),
+  ('꛳', '꛷'), ('꡶', '꡷'), ('꣎', '꣏'), ('꤯', '꤯'),
+  ('꧇', '꧉'), ('꩝', '꩟'), ('꫟', '꫟'), ('꫰', '꫱'),
+  ('꯫', '꯫'), ('﹐', '﹒'), ('﹔', '﹗'), ('！', '！'),
+  ('，', '，'), ('．', '．'), ('：', '；'), ('？', '？'),
+  ('｡', '｡'), ('､', '､'), ('𐎟', '𐎟'), ('𐏐', '𐏐'),
+  ('𐡗', '𐡗'), ('𐤟', '𐤟'), ('𐩖', '𐩗'), ('𐫰', '𐫵'),
+  ('𐬺', '𐬿'), ('𐮙', '𐮜'), ('\u{10f55}', '\u{10f59}'),
+  ('𑁇', '𑁍'), ('𑂾', '𑃁'), ('𑅁', '𑅃'), ('𑇅', '𑇆'),
+  ('𑇍', '𑇍'), ('𑇞', '𑇟'), ('𑈸', '𑈼'), ('𑊩', '𑊩'),
+  ('𑑋', '𑑍'), ('𑑛', '𑑛'), ('𑗂', '𑗅'), ('𑗉', '𑗗'),
+  ('𑙁', '𑙂'), ('𑜼', '𑜾'), ('𑩂', '𑩃'), ('𑪛', '𑪜'),
+  ('𑪡', '𑪢'), ('𑱁', '𑱃'), ('𑱱', '𑱱'),
+  ('\u{11ef7}', '\u{11ef8}'), ('𒑰', '𒑴'), ('𖩮', '𖩯'),
+  ('𖫵', '𖫵'), ('𖬷', '𖬹'), ('𖭄', '𖭄'),
+  ('\u{16e97}', '\u{16e98}'), ('𛲟', '𛲟'), ('𝪇', '𝪊'),
+];
+
+pub const UNIFIED_IDEOGRAPH: &'static [(char, char)] = &[
+  ('㐀', '䶵'), ('一', '\u{9fef}'), ('﨎', '﨏'), ('﨑', '﨑'),
+  ('﨓', '﨔'), ('﨟', '﨟'), ('﨡', '﨡'), ('﨣', '﨤'),
+  ('﨧', '﨩'), ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'),
+  ('𫠠', '𬺡'), ('𬺰', '𮯠'),
+];
+
+pub const UPPERCASE: &'static [(char, char)] = &[
+  ('A', 'Z'), ('À', 'Ö'), ('Ø', 'Þ'), ('Ā', 'Ā'), ('Ă', 'Ă'),
+  ('Ą', 'Ą'), ('Ć', 'Ć'), ('Ĉ', 'Ĉ'), ('Ċ', 'Ċ'), ('Č', 'Č'),
+  ('Ď', 'Ď'), ('Đ', 'Đ'), ('Ē', 'Ē'), ('Ĕ', 'Ĕ'), ('Ė', 'Ė'),
+  ('Ę', 'Ę'), ('Ě', 'Ě'), ('Ĝ', 'Ĝ'), ('Ğ', 'Ğ'), ('Ġ', 'Ġ'),
+  ('Ģ', 'Ģ'), ('Ĥ', 'Ĥ'), ('Ħ', 'Ħ'), ('Ĩ', 'Ĩ'), ('Ī', 'Ī'),
+  ('Ĭ', 'Ĭ'), ('Į', 'Į'), ('İ', 'İ'), ('Ĳ', 'Ĳ'), ('Ĵ', 'Ĵ'),
+  ('Ķ', 'Ķ'), ('Ĺ', 'Ĺ'), ('Ļ', 'Ļ'), ('Ľ', 'Ľ'), ('Ŀ', 'Ŀ'),
+  ('Ł', 'Ł'), ('Ń', 'Ń'), ('Ņ', 'Ņ'), ('Ň', 'Ň'), ('Ŋ', 'Ŋ'),
+  ('Ō', 'Ō'), ('Ŏ', 'Ŏ'), ('Ő', 'Ő'), ('Œ', 'Œ'), ('Ŕ', 'Ŕ'),
+  ('Ŗ', 'Ŗ'), ('Ř', 'Ř'), ('Ś', 'Ś'), ('Ŝ', 'Ŝ'), ('Ş', 'Ş'),
+  ('Š', 'Š'), ('Ţ', 'Ţ'), ('Ť', 'Ť'), ('Ŧ', 'Ŧ'), ('Ũ', 'Ũ'),
+  ('Ū', 'Ū'), ('Ŭ', 'Ŭ'), ('Ů', 'Ů'), ('Ű', 'Ű'), ('Ų', 'Ų'),
+  ('Ŵ', 'Ŵ'), ('Ŷ', 'Ŷ'), ('Ÿ', 'Ź'), ('Ż', 'Ż'), ('Ž', 'Ž'),
+  ('Ɓ', 'Ƃ'), ('Ƅ', 'Ƅ'), ('Ɔ', 'Ƈ'), ('Ɖ', 'Ƌ'), ('Ǝ', 'Ƒ'),
+  ('Ɠ', 'Ɣ'), ('Ɩ', 'Ƙ'), ('Ɯ', 'Ɲ'), ('Ɵ', 'Ơ'), ('Ƣ', 'Ƣ'),
+  ('Ƥ', 'Ƥ'), ('Ʀ', 'Ƨ'), ('Ʃ', 'Ʃ'), ('Ƭ', 'Ƭ'), ('Ʈ', 'Ư'),
+  ('Ʊ', 'Ƴ'), ('Ƶ', 'Ƶ'), ('Ʒ', 'Ƹ'), ('Ƽ', 'Ƽ'), ('Ǆ', 'Ǆ'),
+  ('Ǉ', 'Ǉ'), ('Ǌ', 'Ǌ'), ('Ǎ', 'Ǎ'), ('Ǐ', 'Ǐ'), ('Ǒ', 'Ǒ'),
+  ('Ǔ', 'Ǔ'), ('Ǖ', 'Ǖ'), ('Ǘ', 'Ǘ'), ('Ǚ', 'Ǚ'), ('Ǜ', 'Ǜ'),
+  ('Ǟ', 'Ǟ'), ('Ǡ', 'Ǡ'), ('Ǣ', 'Ǣ'), ('Ǥ', 'Ǥ'), ('Ǧ', 'Ǧ'),
+  ('Ǩ', 'Ǩ'), ('Ǫ', 'Ǫ'), ('Ǭ', 'Ǭ'), ('Ǯ', 'Ǯ'), ('Ǳ', 'Ǳ'),
+  ('Ǵ', 'Ǵ'), ('Ƕ', 'Ǹ'), ('Ǻ', 'Ǻ'), ('Ǽ', 'Ǽ'), ('Ǿ', 'Ǿ'),
+  ('Ȁ', 'Ȁ'), ('Ȃ', 'Ȃ'), ('Ȅ', 'Ȅ'), ('Ȇ', 'Ȇ'), ('Ȉ', 'Ȉ'),
+  ('Ȋ', 'Ȋ'), ('Ȍ', 'Ȍ'), ('Ȏ', 'Ȏ'), ('Ȑ', 'Ȑ'), ('Ȓ', 'Ȓ'),
+  ('Ȕ', 'Ȕ'), ('Ȗ', 'Ȗ'), ('Ș', 'Ș'), ('Ț', 'Ț'), ('Ȝ', 'Ȝ'),
+  ('Ȟ', 'Ȟ'), ('Ƞ', 'Ƞ'), ('Ȣ', 'Ȣ'), ('Ȥ', 'Ȥ'), ('Ȧ', 'Ȧ'),
+  ('Ȩ', 'Ȩ'), ('Ȫ', 'Ȫ'), ('Ȭ', 'Ȭ'), ('Ȯ', 'Ȯ'), ('Ȱ', 'Ȱ'),
+  ('Ȳ', 'Ȳ'), ('Ⱥ', 'Ȼ'), ('Ƚ', 'Ⱦ'), ('Ɂ', 'Ɂ'), ('Ƀ', 'Ɇ'),
+  ('Ɉ', 'Ɉ'), ('Ɋ', 'Ɋ'), ('Ɍ', 'Ɍ'), ('Ɏ', 'Ɏ'), ('Ͱ', 'Ͱ'),
+  ('Ͳ', 'Ͳ'), ('Ͷ', 'Ͷ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'),
+  ('Ό', 'Ό'), ('Ύ', 'Ώ'), ('Α', 'Ρ'), ('Σ', 'Ϋ'), ('Ϗ', 'Ϗ'),
+  ('ϒ', 'ϔ'), ('Ϙ', 'Ϙ'), ('Ϛ', 'Ϛ'), ('Ϝ', 'Ϝ'), ('Ϟ', 'Ϟ'),
+  ('Ϡ', 'Ϡ'), ('Ϣ', 'Ϣ'), ('Ϥ', 'Ϥ'), ('Ϧ', 'Ϧ'), ('Ϩ', 'Ϩ'),
+  ('Ϫ', 'Ϫ'), ('Ϭ', 'Ϭ'), ('Ϯ', 'Ϯ'), ('ϴ', 'ϴ'), ('Ϸ', 'Ϸ'),
+  ('Ϲ', 'Ϻ'), ('Ͻ', 'Я'), ('Ѡ', 'Ѡ'), ('Ѣ', 'Ѣ'), ('Ѥ', 'Ѥ'),
+  ('Ѧ', 'Ѧ'), ('Ѩ', 'Ѩ'), ('Ѫ', 'Ѫ'), ('Ѭ', 'Ѭ'), ('Ѯ', 'Ѯ'),
+  ('Ѱ', 'Ѱ'), ('Ѳ', 'Ѳ'), ('Ѵ', 'Ѵ'), ('Ѷ', 'Ѷ'), ('Ѹ', 'Ѹ'),
+  ('Ѻ', 'Ѻ'), ('Ѽ', 'Ѽ'), ('Ѿ', 'Ѿ'), ('Ҁ', 'Ҁ'), ('Ҋ', 'Ҋ'),
+  ('Ҍ', 'Ҍ'), ('Ҏ', 'Ҏ'), ('Ґ', 'Ґ'), ('Ғ', 'Ғ'), ('Ҕ', 'Ҕ'),
+  ('Җ', 'Җ'), ('Ҙ', 'Ҙ'), ('Қ', 'Қ'), ('Ҝ', 'Ҝ'), ('Ҟ', 'Ҟ'),
+  ('Ҡ', 'Ҡ'), ('Ң', 'Ң'), ('Ҥ', 'Ҥ'), ('Ҧ', 'Ҧ'), ('Ҩ', 'Ҩ'),
+  ('Ҫ', 'Ҫ'), ('Ҭ', 'Ҭ'), ('Ү', 'Ү'), ('Ұ', 'Ұ'), ('Ҳ', 'Ҳ'),
+  ('Ҵ', 'Ҵ'), ('Ҷ', 'Ҷ'), ('Ҹ', 'Ҹ'), ('Һ', 'Һ'), ('Ҽ', 'Ҽ'),
+  ('Ҿ', 'Ҿ'), ('Ӏ', 'Ӂ'), ('Ӄ', 'Ӄ'), ('Ӆ', 'Ӆ'), ('Ӈ', 'Ӈ'),
+  ('Ӊ', 'Ӊ'), ('Ӌ', 'Ӌ'), ('Ӎ', 'Ӎ'), ('Ӑ', 'Ӑ'), ('Ӓ', 'Ӓ'),
+  ('Ӕ', 'Ӕ'), ('Ӗ', 'Ӗ'), ('Ә', 'Ә'), ('Ӛ', 'Ӛ'), ('Ӝ', 'Ӝ'),
+  ('Ӟ', 'Ӟ'), ('Ӡ', 'Ӡ'), ('Ӣ', 'Ӣ'), ('Ӥ', 'Ӥ'), ('Ӧ', 'Ӧ'),
+  ('Ө', 'Ө'), ('Ӫ', 'Ӫ'), ('Ӭ', 'Ӭ'), ('Ӯ', 'Ӯ'), ('Ӱ', 'Ӱ'),
+  ('Ӳ', 'Ӳ'), ('Ӵ', 'Ӵ'), ('Ӷ', 'Ӷ'), ('Ӹ', 'Ӹ'), ('Ӻ', 'Ӻ'),
+  ('Ӽ', 'Ӽ'), ('Ӿ', 'Ӿ'), ('Ԁ', 'Ԁ'), ('Ԃ', 'Ԃ'), ('Ԅ', 'Ԅ'),
+  ('Ԇ', 'Ԇ'), ('Ԉ', 'Ԉ'), ('Ԋ', 'Ԋ'), ('Ԍ', 'Ԍ'), ('Ԏ', 'Ԏ'),
+  ('Ԑ', 'Ԑ'), ('Ԓ', 'Ԓ'), ('Ԕ', 'Ԕ'), ('Ԗ', 'Ԗ'), ('Ԙ', 'Ԙ'),
+  ('Ԛ', 'Ԛ'), ('Ԝ', 'Ԝ'), ('Ԟ', 'Ԟ'), ('Ԡ', 'Ԡ'), ('Ԣ', 'Ԣ'),
+  ('Ԥ', 'Ԥ'), ('Ԧ', 'Ԧ'), ('Ԩ', 'Ԩ'), ('Ԫ', 'Ԫ'), ('Ԭ', 'Ԭ'),
+  ('Ԯ', 'Ԯ'), ('Ա', 'Ֆ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('Ꭰ', 'Ᏽ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('Ḁ', 'Ḁ'), ('Ḃ', 'Ḃ'), ('Ḅ', 'Ḅ'), ('Ḇ', 'Ḇ'),
+  ('Ḉ', 'Ḉ'), ('Ḋ', 'Ḋ'), ('Ḍ', 'Ḍ'), ('Ḏ', 'Ḏ'),
+  ('Ḑ', 'Ḑ'), ('Ḓ', 'Ḓ'), ('Ḕ', 'Ḕ'), ('Ḗ', 'Ḗ'),
+  ('Ḙ', 'Ḙ'), ('Ḛ', 'Ḛ'), ('Ḝ', 'Ḝ'), ('Ḟ', 'Ḟ'),
+  ('Ḡ', 'Ḡ'), ('Ḣ', 'Ḣ'), ('Ḥ', 'Ḥ'), ('Ḧ', 'Ḧ'),
+  ('Ḩ', 'Ḩ'), ('Ḫ', 'Ḫ'), ('Ḭ', 'Ḭ'), ('Ḯ', 'Ḯ'),
+  ('Ḱ', 'Ḱ'), ('Ḳ', 'Ḳ'), ('Ḵ', 'Ḵ'), ('Ḷ', 'Ḷ'),
+  ('Ḹ', 'Ḹ'), ('Ḻ', 'Ḻ'), ('Ḽ', 'Ḽ'), ('Ḿ', 'Ḿ'),
+  ('Ṁ', 'Ṁ'), ('Ṃ', 'Ṃ'), ('Ṅ', 'Ṅ'), ('Ṇ', 'Ṇ'),
+  ('Ṉ', 'Ṉ'), ('Ṋ', 'Ṋ'), ('Ṍ', 'Ṍ'), ('Ṏ', 'Ṏ'),
+  ('Ṑ', 'Ṑ'), ('Ṓ', 'Ṓ'), ('Ṕ', 'Ṕ'), ('Ṗ', 'Ṗ'),
+  ('Ṙ', 'Ṙ'), ('Ṛ', 'Ṛ'), ('Ṝ', 'Ṝ'), ('Ṟ', 'Ṟ'),
+  ('Ṡ', 'Ṡ'), ('Ṣ', 'Ṣ'), ('Ṥ', 'Ṥ'), ('Ṧ', 'Ṧ'),
+  ('Ṩ', 'Ṩ'), ('Ṫ', 'Ṫ'), ('Ṭ', 'Ṭ'), ('Ṯ', 'Ṯ'),
+  ('Ṱ', 'Ṱ'), ('Ṳ', 'Ṳ'), ('Ṵ', 'Ṵ'), ('Ṷ', 'Ṷ'),
+  ('Ṹ', 'Ṹ'), ('Ṻ', 'Ṻ'), ('Ṽ', 'Ṽ'), ('Ṿ', 'Ṿ'),
+  ('Ẁ', 'Ẁ'), ('Ẃ', 'Ẃ'), ('Ẅ', 'Ẅ'), ('Ẇ', 'Ẇ'),
+  ('Ẉ', 'Ẉ'), ('Ẋ', 'Ẋ'), ('Ẍ', 'Ẍ'), ('Ẏ', 'Ẏ'),
+  ('Ẑ', 'Ẑ'), ('Ẓ', 'Ẓ'), ('Ẕ', 'Ẕ'), ('ẞ', 'ẞ'),
+  ('Ạ', 'Ạ'), ('Ả', 'Ả'), ('Ấ', 'Ấ'), ('Ầ', 'Ầ'),
+  ('Ẩ', 'Ẩ'), ('Ẫ', 'Ẫ'), ('Ậ', 'Ậ'), ('Ắ', 'Ắ'),
+  ('Ằ', 'Ằ'), ('Ẳ', 'Ẳ'), ('Ẵ', 'Ẵ'), ('Ặ', 'Ặ'),
+  ('Ẹ', 'Ẹ'), ('Ẻ', 'Ẻ'), ('Ẽ', 'Ẽ'), ('Ế', 'Ế'),
+  ('Ề', 'Ề'), ('Ể', 'Ể'), ('Ễ', 'Ễ'), ('Ệ', 'Ệ'),
+  ('Ỉ', 'Ỉ'), ('Ị', 'Ị'), ('Ọ', 'Ọ'), ('Ỏ', 'Ỏ'),
+  ('Ố', 'Ố'), ('Ồ', 'Ồ'), ('Ổ', 'Ổ'), ('Ỗ', 'Ỗ'),
+  ('Ộ', 'Ộ'), ('Ớ', 'Ớ'), ('Ờ', 'Ờ'), ('Ở', 'Ở'),
+  ('Ỡ', 'Ỡ'), ('Ợ', 'Ợ'), ('Ụ', 'Ụ'), ('Ủ', 'Ủ'),
+  ('Ứ', 'Ứ'), ('Ừ', 'Ừ'), ('Ử', 'Ử'), ('Ữ', 'Ữ'),
+  ('Ự', 'Ự'), ('Ỳ', 'Ỳ'), ('Ỵ', 'Ỵ'), ('Ỷ', 'Ỷ'),
+  ('Ỹ', 'Ỹ'), ('Ỻ', 'Ỻ'), ('Ỽ', 'Ỽ'), ('Ỿ', 'Ỿ'),
+  ('Ἀ', 'Ἇ'), ('Ἐ', 'Ἕ'), ('Ἠ', 'Ἧ'), ('Ἰ', 'Ἷ'),
+  ('Ὀ', 'Ὅ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'Ὗ'), ('Ὠ', 'Ὧ'), ('Ᾰ', 'Ά'), ('Ὲ', 'Ή'),
+  ('Ῐ', 'Ί'), ('Ῠ', 'Ῥ'), ('Ὸ', 'Ώ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℋ', 'ℍ'), ('ℐ', 'ℒ'), ('ℕ', 'ℕ'),
+  ('ℙ', 'ℝ'), ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'),
+  ('K', 'ℭ'), ('ℰ', 'ℳ'), ('ℾ', 'ℿ'), ('ⅅ', 'ⅅ'),
+  ('Ⅰ', 'Ⅿ'), ('Ↄ', 'Ↄ'), ('Ⓐ', 'Ⓩ'), ('Ⰰ', 'Ⱞ'),
+  ('Ⱡ', 'Ⱡ'), ('Ɫ', 'Ɽ'), ('Ⱨ', 'Ⱨ'), ('Ⱪ', 'Ⱪ'),
+  ('Ⱬ', 'Ⱬ'), ('Ɑ', 'Ɒ'), ('Ⱳ', 'Ⱳ'), ('Ⱶ', 'Ⱶ'),
+  ('Ȿ', 'Ⲁ'), ('Ⲃ', 'Ⲃ'), ('Ⲅ', 'Ⲅ'), ('Ⲇ', 'Ⲇ'),
+  ('Ⲉ', 'Ⲉ'), ('Ⲋ', 'Ⲋ'), ('Ⲍ', 'Ⲍ'), ('Ⲏ', 'Ⲏ'),
+  ('Ⲑ', 'Ⲑ'), ('Ⲓ', 'Ⲓ'), ('Ⲕ', 'Ⲕ'), ('Ⲗ', 'Ⲗ'),
+  ('Ⲙ', 'Ⲙ'), ('Ⲛ', 'Ⲛ'), ('Ⲝ', 'Ⲝ'), ('Ⲟ', 'Ⲟ'),
+  ('Ⲡ', 'Ⲡ'), ('Ⲣ', 'Ⲣ'), ('Ⲥ', 'Ⲥ'), ('Ⲧ', 'Ⲧ'),
+  ('Ⲩ', 'Ⲩ'), ('Ⲫ', 'Ⲫ'), ('Ⲭ', 'Ⲭ'), ('Ⲯ', 'Ⲯ'),
+  ('Ⲱ', 'Ⲱ'), ('Ⲳ', 'Ⲳ'), ('Ⲵ', 'Ⲵ'), ('Ⲷ', 'Ⲷ'),
+  ('Ⲹ', 'Ⲹ'), ('Ⲻ', 'Ⲻ'), ('Ⲽ', 'Ⲽ'), ('Ⲿ', 'Ⲿ'),
+  ('Ⳁ', 'Ⳁ'), ('Ⳃ', 'Ⳃ'), ('Ⳅ', 'Ⳅ'), ('Ⳇ', 'Ⳇ'),
+  ('Ⳉ', 'Ⳉ'), ('Ⳋ', 'Ⳋ'), ('Ⳍ', 'Ⳍ'), ('Ⳏ', 'Ⳏ'),
+  ('Ⳑ', 'Ⳑ'), ('Ⳓ', 'Ⳓ'), ('Ⳕ', 'Ⳕ'), ('Ⳗ', 'Ⳗ'),
+  ('Ⳙ', 'Ⳙ'), ('Ⳛ', 'Ⳛ'), ('Ⳝ', 'Ⳝ'), ('Ⳟ', 'Ⳟ'),
+  ('Ⳡ', 'Ⳡ'), ('Ⳣ', 'Ⳣ'), ('Ⳬ', 'Ⳬ'), ('Ⳮ', 'Ⳮ'),
+  ('Ⳳ', 'Ⳳ'), ('Ꙁ', 'Ꙁ'), ('Ꙃ', 'Ꙃ'), ('Ꙅ', 'Ꙅ'),
+  ('Ꙇ', 'Ꙇ'), ('Ꙉ', 'Ꙉ'), ('Ꙋ', 'Ꙋ'), ('Ꙍ', 'Ꙍ'),
+  ('Ꙏ', 'Ꙏ'), ('Ꙑ', 'Ꙑ'), ('Ꙓ', 'Ꙓ'), ('Ꙕ', 'Ꙕ'),
+  ('Ꙗ', 'Ꙗ'), ('Ꙙ', 'Ꙙ'), ('Ꙛ', 'Ꙛ'), ('Ꙝ', 'Ꙝ'),
+  ('Ꙟ', 'Ꙟ'), ('Ꙡ', 'Ꙡ'), ('Ꙣ', 'Ꙣ'), ('Ꙥ', 'Ꙥ'),
+  ('Ꙧ', 'Ꙧ'), ('Ꙩ', 'Ꙩ'), ('Ꙫ', 'Ꙫ'), ('Ꙭ', 'Ꙭ'),
+  ('Ꚁ', 'Ꚁ'), ('Ꚃ', 'Ꚃ'), ('Ꚅ', 'Ꚅ'), ('Ꚇ', 'Ꚇ'),
+  ('Ꚉ', 'Ꚉ'), ('Ꚋ', 'Ꚋ'), ('Ꚍ', 'Ꚍ'), ('Ꚏ', 'Ꚏ'),
+  ('Ꚑ', 'Ꚑ'), ('Ꚓ', 'Ꚓ'), ('Ꚕ', 'Ꚕ'), ('Ꚗ', 'Ꚗ'),
+  ('Ꚙ', 'Ꚙ'), ('Ꚛ', 'Ꚛ'), ('Ꜣ', 'Ꜣ'), ('Ꜥ', 'Ꜥ'),
+  ('Ꜧ', 'Ꜧ'), ('Ꜩ', 'Ꜩ'), ('Ꜫ', 'Ꜫ'), ('Ꜭ', 'Ꜭ'),
+  ('Ꜯ', 'Ꜯ'), ('Ꜳ', 'Ꜳ'), ('Ꜵ', 'Ꜵ'), ('Ꜷ', 'Ꜷ'),
+  ('Ꜹ', 'Ꜹ'), ('Ꜻ', 'Ꜻ'), ('Ꜽ', 'Ꜽ'), ('Ꜿ', 'Ꜿ'),
+  ('Ꝁ', 'Ꝁ'), ('Ꝃ', 'Ꝃ'), ('Ꝅ', 'Ꝅ'), ('Ꝇ', 'Ꝇ'),
+  ('Ꝉ', 'Ꝉ'), ('Ꝋ', 'Ꝋ'), ('Ꝍ', 'Ꝍ'), ('Ꝏ', 'Ꝏ'),
+  ('Ꝑ', 'Ꝑ'), ('Ꝓ', 'Ꝓ'), ('Ꝕ', 'Ꝕ'), ('Ꝗ', 'Ꝗ'),
+  ('Ꝙ', 'Ꝙ'), ('Ꝛ', 'Ꝛ'), ('Ꝝ', 'Ꝝ'), ('Ꝟ', 'Ꝟ'),
+  ('Ꝡ', 'Ꝡ'), ('Ꝣ', 'Ꝣ'), ('Ꝥ', 'Ꝥ'), ('Ꝧ', 'Ꝧ'),
+  ('Ꝩ', 'Ꝩ'), ('Ꝫ', 'Ꝫ'), ('Ꝭ', 'Ꝭ'), ('Ꝯ', 'Ꝯ'),
+  ('Ꝺ', 'Ꝺ'), ('Ꝼ', 'Ꝼ'), ('Ᵹ', 'Ꝿ'), ('Ꞁ', 'Ꞁ'),
+  ('Ꞃ', 'Ꞃ'), ('Ꞅ', 'Ꞅ'), ('Ꞇ', 'Ꞇ'), ('Ꞌ', 'Ꞌ'),
+  ('Ɥ', 'Ɥ'), ('Ꞑ', 'Ꞑ'), ('Ꞓ', 'Ꞓ'), ('Ꞗ', 'Ꞗ'),
+  ('Ꞙ', 'Ꞙ'), ('Ꞛ', 'Ꞛ'), ('Ꞝ', 'Ꞝ'), ('Ꞟ', 'Ꞟ'),
+  ('Ꞡ', 'Ꞡ'), ('Ꞣ', 'Ꞣ'), ('Ꞥ', 'Ꞥ'), ('Ꞧ', 'Ꞧ'),
+  ('Ꞩ', 'Ꞩ'), ('Ɦ', 'Ɪ'), ('Ʞ', 'Ꞵ'), ('Ꞷ', 'Ꞷ'),
+  ('\u{a7b8}', '\u{a7b8}'), ('Ａ', 'Ｚ'), ('𐐀', '𐐧'),
+  ('𐒰', '𐓓'), ('𐲀', '𐲲'), ('𑢠', '𑢿'),
+  ('\u{16e40}', '\u{16e5f}'), ('𝐀', '𝐙'), ('𝐴', '𝑍'),
+  ('𝑨', '𝒁'), ('𝒜', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'),
+  ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒵'), ('𝓐', '𝓩'),
+  ('𝔄', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'),
+  ('𝔸', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'),
+  ('𝕊', '𝕐'), ('𝕬', '𝖅'), ('𝖠', '𝖹'), ('𝗔', '𝗭'),
+  ('𝘈', '𝘡'), ('𝘼', '𝙕'), ('𝙰', '𝚉'), ('𝚨', '𝛀'),
+  ('𝛢', '𝛺'), ('𝜜', '𝜴'), ('𝝖', '𝝮'), ('𝞐', '𝞨'),
+  ('𝟊', '𝟊'), ('𞤀', '𞤡'), ('🄰', '🅉'), ('🅐', '🅩'),
+  ('🅰', '🆉'),
+];
+
+pub const VARIATION_SELECTOR: &'static [(char, char)] = &[
+  ('᠋', '᠍'), ('︀', '️'), ('󠄀', '󠇯'),
+];
+
+pub const WHITE_SPACE: &'static [(char, char)] = &[
+  ('\t', '\r'), (' ', ' '), ('\u{85}', '\u{85}'), ('\u{a0}', '\u{a0}'),
+  ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'),
+  ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'),
+  ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}'),
+];
+
+pub const XID_CONTINUE: &'static [(char, char)] = &[
+  ('0', '9'), ('A', 'Z'), ('_', '_'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'),
+  ('·', '·'), ('º', 'º'), ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'),
+  ('ˆ', 'ˑ'), ('ˠ', 'ˤ'), ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('̀', 'ʹ'),
+  ('Ͷ', 'ͷ'), ('ͻ', 'ͽ'), ('Ϳ', 'Ϳ'), ('Ά', 'Ί'), ('Ό', 'Ό'),
+  ('Ύ', 'Ρ'), ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('҃', '҇'), ('Ҋ', 'ԯ'),
+  ('Ա', 'Ֆ'), ('ՙ', 'ՙ'), ('\u{560}', '\u{588}'), ('֑', 'ֽ'),
+  ('ֿ', 'ֿ'), ('ׁ', 'ׂ'), ('ׄ', 'ׅ'), ('ׇ', 'ׇ'), ('א', 'ת'),
+  ('\u{5ef}', 'ײ'), ('ؐ', 'ؚ'), ('ؠ', '٩'), ('ٮ', 'ۓ'), ('ە', 'ۜ'),
+  ('۟', 'ۨ'), ('۪', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', '݊'), ('ݍ', 'ޱ'),
+  ('߀', 'ߵ'), ('ߺ', 'ߺ'), ('\u{7fd}', '\u{7fd}'), ('ࠀ', '࠭'),
+  ('ࡀ', '࡛'), ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'),
+  ('\u{8d3}', '࣡'), ('ࣣ', 'ॣ'), ('०', '९'), ('ॱ', 'ঃ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('়', 'ৄ'), ('ে', 'ৈ'),
+  ('ো', 'ৎ'), ('ৗ', 'ৗ'), ('ড়', 'ঢ়'), ('য়', 'ৣ'),
+  ('০', 'ৱ'), ('ৼ', 'ৼ'), ('\u{9fe}', '\u{9fe}'), ('ਁ', 'ਃ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('਼', '਼'),
+  ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ੑ', 'ੑ'),
+  ('ਖ਼', 'ੜ'), ('ਫ਼', 'ਫ਼'), ('੦', 'ੵ'), ('ઁ', 'ઃ'),
+  ('અ', 'ઍ'), ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'),
+  ('લ', 'ળ'), ('વ', 'હ'), ('઼', 'ૅ'), ('ે', 'ૉ'),
+  ('ો', '્'), ('ૐ', 'ૐ'), ('ૠ', 'ૣ'), ('૦', '૯'),
+  ('ૹ', '૿'), ('ଁ', 'ଃ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'),
+  ('ଓ', 'ନ'), ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଵ', 'ହ'),
+  ('଼', 'ୄ'), ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'),
+  ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୣ'), ('୦', '୯'), ('ୱ', 'ୱ'),
+  ('ஂ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'), ('ஒ', 'க'),
+  ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'), ('ண', 'த'),
+  ('ந', 'ப'), ('ம', 'ஹ'), ('ா', 'ூ'), ('ெ', 'ை'),
+  ('ொ', '்'), ('ௐ', 'ௐ'), ('ௗ', 'ௗ'), ('௦', '௯'),
+  ('ఀ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'హ'),
+  ('ఽ', 'ౄ'), ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'),
+  ('ౘ', 'ౚ'), ('ౠ', 'ౣ'), ('౦', '౯'), ('ಀ', 'ಃ'),
+  ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'),
+  ('ವ', 'ಹ'), ('಼', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', '್'),
+  ('ೕ', 'ೖ'), ('ೞ', 'ೞ'), ('ೠ', 'ೣ'), ('೦', '೯'),
+  ('ೱ', 'ೲ'), ('ഀ', 'ഃ'), ('അ', 'ഌ'), ('എ', 'ഐ'),
+  ('ഒ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', 'ൎ'), ('ൔ', 'ൗ'),
+  ('ൟ', 'ൣ'), ('൦', '൯'), ('ൺ', 'ൿ'), ('ං', 'ඃ'),
+  ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'), ('ල', 'ල'),
+  ('ව', 'ෆ'), ('්', '්'), ('ා', 'ු'), ('ූ', 'ූ'),
+  ('ෘ', 'ෟ'), ('෦', '෯'), ('ෲ', 'ෳ'), ('ก', 'ฺ'),
+  ('เ', '๎'), ('๐', '๙'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'),
+  ('ງ', 'ຈ'), ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'),
+  ('ນ', 'ຟ'), ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'),
+  ('ສ', 'ຫ'), ('ອ', 'ູ'), ('ົ', 'ຽ'), ('ເ', 'ໄ'),
+  ('ໆ', 'ໆ'), ('່', 'ໍ'), ('໐', '໙'), ('ໜ', 'ໟ'),
+  ('ༀ', 'ༀ'), ('༘', '༙'), ('༠', '༩'), ('༵', '༵'),
+  ('༷', '༷'), ('༹', '༹'), ('༾', 'ཇ'), ('ཉ', 'ཬ'),
+  ('ཱ', '྄'), ('྆', 'ྗ'), ('ྙ', 'ྼ'), ('࿆', '࿆'),
+  ('က', '၉'), ('ၐ', 'ႝ'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'),
+  ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'), ('ჼ', 'ቈ'), ('ቊ', 'ቍ'),
+  ('ቐ', 'ቖ'), ('ቘ', 'ቘ'), ('ቚ', 'ቝ'), ('በ', 'ኈ'),
+  ('ኊ', 'ኍ'), ('ነ', 'ኰ'), ('ኲ', 'ኵ'), ('ኸ', 'ኾ'),
+  ('ዀ', 'ዀ'), ('ዂ', 'ዅ'), ('ወ', 'ዖ'), ('ዘ', 'ጐ'),
+  ('ጒ', 'ጕ'), ('ጘ', 'ፚ'), ('፝', '፟'), ('፩', '፱'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'), ('ᜠ', '᜴'), ('ᝀ', 'ᝓ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ᝲ', 'ᝳ'), ('ក', '៓'),
+  ('ៗ', 'ៗ'), ('ៜ', '៝'), ('០', '៩'), ('᠋', '᠍'),
+  ('᠐', '᠙'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢪ'), ('ᢰ', 'ᣵ'),
+  ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'), ('᥆', 'ᥭ'),
+  ('ᥰ', 'ᥴ'), ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('᧐', '᧚'),
+  ('ᨀ', 'ᨛ'), ('ᨠ', 'ᩞ'), ('᩠', '᩼'), ('᩿', '᪉'),
+  ('᪐', '᪙'), ('ᪧ', 'ᪧ'), ('᪰', '᪽'), ('ᬀ', 'ᭋ'),
+  ('᭐', '᭙'), ('᭫', '᭳'), ('ᮀ', '᯳'), ('ᰀ', '᰷'),
+  ('᱀', '᱉'), ('ᱍ', 'ᱽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('᳐', '᳒'), ('᳔', '᳹'), ('ᴀ', '᷹'),
+  ('᷻', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'),
+  ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'),
+  ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'), ('ι', 'ι'),
+  ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'), ('ῖ', 'Ί'),
+  ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), ('‿', '⁀'),
+  ('⁔', '⁔'), ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'),
+  ('⃐', '⃜'), ('⃡', '⃡'), ('⃥', '⃰'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('℘', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℹ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'), ('Ⳬ', 'ⳳ'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'), ('ⴰ', 'ⵧ'),
+  ('ⵯ', 'ⵯ'), ('⵿', 'ⶖ'), ('ⶠ', 'ⶦ'), ('ⶨ', 'ⶮ'),
+  ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'), ('ⷈ', 'ⷎ'),
+  ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('ⷠ', 'ⷿ'), ('々', '〇'),
+  ('〡', '〯'), ('〱', '〵'), ('〸', '〼'), ('ぁ', 'ゖ'),
+  ('゙', '゚'), ('ゝ', 'ゟ'), ('ァ', 'ヺ'), ('ー', 'ヿ'),
+  ('ㄅ', '\u{312f}'), ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'),
+  ('㐀', '䶵'), ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'),
+  ('ꔀ', 'ꘌ'), ('ꘐ', 'ꘫ'), ('Ꙁ', '꙯'), ('ꙴ', '꙽'),
+  ('ꙿ', '꛱'), ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'), ('Ꞌ', '\u{a7b9}'),
+  ('ꟷ', 'ꠧ'), ('ꡀ', 'ꡳ'), ('ꢀ', 'ꣅ'), ('꣐', '꣙'),
+  ('꣠', 'ꣷ'), ('ꣻ', 'ꣻ'), ('ꣽ', '꤭'), ('ꤰ', '꥓'),
+  ('ꥠ', 'ꥼ'), ('ꦀ', '꧀'), ('ꧏ', '꧙'), ('ꧠ', 'ꧾ'),
+  ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'), ('꩐', '꩙'), ('ꩠ', 'ꩶ'),
+  ('ꩺ', 'ꫂ'), ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫯ'), ('ꫲ', '꫶'),
+  ('ꬁ', 'ꬆ'), ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'),
+  ('ꬨ', 'ꬮ'), ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯪ'),
+  ('꯬', '꯭'), ('꯰', '꯹'), ('가', '힣'), ('ힰ', 'ퟆ'),
+  ('ퟋ', 'ퟻ'), ('豈', '舘'), ('並', '龎'), ('ﬀ', 'ﬆ'),
+  ('ﬓ', 'ﬗ'), ('יִ', 'ﬨ'), ('שׁ', 'זּ'), ('טּ', 'לּ'),
+  ('מּ', 'מּ'), ('נּ', 'סּ'), ('ףּ', 'פּ'), ('צּ', 'ﮱ'),
+  ('ﯓ', 'ﱝ'), ('ﱤ', 'ﴽ'), ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'),
+  ('ﷰ', 'ﷹ'), ('︀', '️'), ('︠', '︯'), ('︳', '︴'),
+  ('﹍', '﹏'), ('ﹱ', 'ﹱ'), ('ﹳ', 'ﹳ'), ('ﹷ', 'ﹷ'),
+  ('ﹹ', 'ﹹ'), ('ﹻ', 'ﹻ'), ('ﹽ', 'ﹽ'), ('ﹿ', 'ﻼ'),
+  ('０', '９'), ('Ａ', 'Ｚ'), ('＿', '＿'), ('ａ', 'ｚ'),
+  ('ｦ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'), ('ￒ', 'ￗ'),
+  ('ￚ', 'ￜ'), ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'),
+  ('𐀼', '𐀽'), ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'),
+  ('𐅀', '𐅴'), ('𐇽', '𐇽'), ('𐊀', '𐊜'), ('𐊠', '𐋐'),
+  ('𐋠', '𐋠'), ('𐌀', '𐌟'), ('𐌭', '𐍊'), ('𐍐', '𐍺'),
+  ('𐎀', '𐎝'), ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐏑', '𐏕'),
+  ('𐐀', '𐒝'), ('𐒠', '𐒩'), ('𐒰', '𐓓'), ('𐓘', '𐓻'),
+  ('𐔀', '𐔧'), ('𐔰', '𐕣'), ('𐘀', '𐜶'), ('𐝀', '𐝕'),
+  ('𐝠', '𐝧'), ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'),
+  ('𐠷', '𐠸'), ('𐠼', '𐠼'), ('𐠿', '𐡕'), ('𐡠', '𐡶'),
+  ('𐢀', '𐢞'), ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐤀', '𐤕'),
+  ('𐤠', '𐤹'), ('𐦀', '𐦷'), ('𐦾', '𐦿'), ('𐨀', '𐨃'),
+  ('𐨅', '𐨆'), ('𐨌', '𐨓'), ('𐨕', '𐨗'), ('𐨙', '\u{10a35}'),
+  ('𐨸', '𐨺'), ('𐨿', '𐨿'), ('𐩠', '𐩼'), ('𐪀', '𐪜'),
+  ('𐫀', '𐫇'), ('𐫉', '𐫦'), ('𐬀', '𐬵'), ('𐭀', '𐭕'),
+  ('𐭠', '𐭲'), ('𐮀', '𐮑'), ('𐰀', '𐱈'), ('𐲀', '𐲲'),
+  ('𐳀', '𐳲'), ('\u{10d00}', '\u{10d27}'), ('\u{10d30}', '\u{10d39}'),
+  ('\u{10f00}', '\u{10f1c}'), ('\u{10f27}', '\u{10f27}'),
+  ('\u{10f30}', '\u{10f50}'), ('𑀀', '𑁆'), ('𑁦', '𑁯'),
+  ('𑁿', '𑂺'), ('𑃐', '𑃨'), ('𑃰', '𑃹'), ('𑄀', '𑄴'),
+  ('𑄶', '𑄿'), ('\u{11144}', '\u{11146}'), ('𑅐', '𑅳'),
+  ('𑅶', '𑅶'), ('𑆀', '𑇄'), ('𑇉', '𑇌'), ('𑇐', '𑇚'),
+  ('𑇜', '𑇜'), ('𑈀', '𑈑'), ('𑈓', '𑈷'), ('𑈾', '𑈾'),
+  ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'), ('𑊏', '𑊝'),
+  ('𑊟', '𑊨'), ('𑊰', '𑋪'), ('𑋰', '𑋹'), ('𑌀', '𑌃'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('\u{1133b}', '𑍄'), ('𑍇', '𑍈'),
+  ('𑍋', '𑍍'), ('𑍐', '𑍐'), ('𑍗', '𑍗'), ('𑍝', '𑍣'),
+  ('𑍦', '𑍬'), ('𑍰', '𑍴'), ('𑐀', '𑑊'), ('𑑐', '𑑙'),
+  ('\u{1145e}', '\u{1145e}'), ('𑒀', '𑓅'), ('𑓇', '𑓇'),
+  ('𑓐', '𑓙'), ('𑖀', '𑖵'), ('𑖸', '𑗀'), ('𑗘', '𑗝'),
+  ('𑘀', '𑙀'), ('𑙄', '𑙄'), ('𑙐', '𑙙'), ('𑚀', '𑚷'),
+  ('𑛀', '𑛉'), ('𑜀', '\u{1171a}'), ('𑜝', '𑜫'), ('𑜰', '𑜹'),
+  ('\u{11800}', '\u{1183a}'), ('𑢠', '𑣩'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨾'), ('𑩇', '𑩇'), ('𑩐', '𑪃'), ('𑪆', '𑪙'),
+  ('\u{11a9d}', '\u{11a9d}'), ('𑫀', '𑫸'), ('𑰀', '𑰈'),
+  ('𑰊', '𑰶'), ('𑰸', '𑱀'), ('𑱐', '𑱙'), ('𑱲', '𑲏'),
+  ('𑲒', '𑲧'), ('𑲩', '𑲶'), ('𑴀', '𑴆'), ('𑴈', '𑴉'),
+  ('𑴋', '𑴶'), ('𑴺', '𑴺'), ('𑴼', '𑴽'), ('𑴿', '𑵇'),
+  ('𑵐', '𑵙'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d98}'), ('\u{11da0}', '\u{11da9}'),
+  ('\u{11ee0}', '\u{11ef6}'), ('𒀀', '𒎙'), ('𒐀', '𒑮'),
+  ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'),
+  ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖫐', '𖫭'), ('𖫰', '𖫴'),
+  ('𖬀', '𖬶'), ('𖭀', '𖭃'), ('𖭐', '𖭙'), ('𖭣', '𖭷'),
+  ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'), ('𖼀', '𖽄'),
+  ('𖽐', '𖽾'), ('𖾏', '𖾟'), ('𖿠', '𖿡'), ('𗀀', '\u{187f1}'),
+  ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'), ('𛰀', '𛱪'),
+  ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲝', '𛲞'),
+  ('𝅥', '𝅩'), ('𝅭', '𝅲'), ('𝅻', '𝆂'), ('𝆅', '𝆋'),
+  ('𝆪', '𝆭'), ('𝉂', '𝉄'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝛀'), ('𝛂', '𝛚'), ('𝛜', '𝛺'),
+  ('𝛼', '𝜔'), ('𝜖', '𝜴'), ('𝜶', '𝝎'), ('𝝐', '𝝮'),
+  ('𝝰', '𝞈'), ('𝞊', '𝞨'), ('𝞪', '𝟂'), ('𝟄', '𝟋'),
+  ('𝟎', '𝟿'), ('𝨀', '𝨶'), ('𝨻', '𝩬'), ('𝩵', '𝩵'),
+  ('𝪄', '𝪄'), ('𝪛', '𝪟'), ('𝪡', '𝪯'), ('𞀀', '𞀆'),
+  ('𞀈', '𞀘'), ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'),
+  ('𞠀', '𞣄'), ('𞣐', '𞣖'), ('𞤀', '𞥊'), ('𞥐', '𞥙'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'), ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'),
+  ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'), ('󠄀', '󠇯'),
+];
+
+pub const XID_START: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('µ', 'µ'), ('º', 'º'),
+  ('À', 'Ö'), ('Ø', 'ö'), ('ø', 'ˁ'), ('ˆ', 'ˑ'), ('ˠ', 'ˤ'),
+  ('ˬ', 'ˬ'), ('ˮ', 'ˮ'), ('Ͱ', 'ʹ'), ('Ͷ', 'ͷ'), ('ͻ', 'ͽ'),
+  ('Ϳ', 'Ϳ'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'),
+  ('Σ', 'ϵ'), ('Ϸ', 'ҁ'), ('Ҋ', 'ԯ'), ('Ա', 'Ֆ'), ('ՙ', 'ՙ'),
+  ('\u{560}', '\u{588}'), ('א', 'ת'), ('\u{5ef}', 'ײ'), ('ؠ', 'ي'),
+  ('ٮ', 'ٯ'), ('ٱ', 'ۓ'), ('ە', 'ە'), ('ۥ', 'ۦ'), ('ۮ', 'ۯ'),
+  ('ۺ', 'ۼ'), ('ۿ', 'ۿ'), ('ܐ', 'ܐ'), ('ܒ', 'ܯ'), ('ݍ', 'ޥ'),
+  ('ޱ', 'ޱ'), ('ߊ', 'ߪ'), ('ߴ', 'ߵ'), ('ߺ', 'ߺ'), ('ࠀ', 'ࠕ'),
+  ('ࠚ', 'ࠚ'), ('ࠤ', 'ࠤ'), ('ࠨ', 'ࠨ'), ('ࡀ', 'ࡘ'),
+  ('ࡠ', 'ࡪ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'), ('ऄ', 'ह'),
+  ('ऽ', 'ऽ'), ('ॐ', 'ॐ'), ('क़', 'ॡ'), ('ॱ', 'ঀ'),
+  ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'),
+  ('ল', 'ল'), ('শ', 'হ'), ('ঽ', 'ঽ'), ('ৎ', 'ৎ'),
+  ('ড়', 'ঢ়'), ('য়', 'ৡ'), ('ৰ', 'ৱ'), ('ৼ', 'ৼ'),
+  ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'),
+  ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('ੲ', 'ੴ'), ('અ', 'ઍ'), ('એ', 'ઑ'),
+  ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'), ('વ', 'હ'),
+  ('ઽ', 'ઽ'), ('ૐ', 'ૐ'), ('ૠ', 'ૡ'), ('ૹ', 'ૹ'),
+  ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'),
+  ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('ଽ', 'ଽ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୡ'), ('ୱ', 'ୱ'), ('ஃ', 'ஃ'), ('அ', 'ஊ'),
+  ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'),
+  ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'),
+  ('ௐ', 'ௐ'), ('అ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'),
+  ('ప', 'హ'), ('ఽ', 'ఽ'), ('ౘ', 'ౚ'), ('ౠ', 'ౡ'),
+  ('ಀ', 'ಀ'), ('ಅ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'),
+  ('ಪ', 'ಳ'), ('ವ', 'ಹ'), ('ಽ', 'ಽ'), ('ೞ', 'ೞ'),
+  ('ೠ', 'ೡ'), ('ೱ', 'ೲ'), ('അ', 'ഌ'), ('എ', 'ഐ'),
+  ('ഒ', 'ഺ'), ('ഽ', 'ഽ'), ('ൎ', 'ൎ'), ('ൔ', 'ൖ'),
+  ('ൟ', 'ൡ'), ('ൺ', 'ൿ'), ('අ', 'ඖ'), ('ක', 'න'),
+  ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'), ('ก', 'ะ'),
+  ('า', 'า'), ('เ', 'ๆ'), ('ກ', 'ຂ'), ('ຄ', 'ຄ'),
+  ('ງ', 'ຈ'), ('ຊ', 'ຊ'), ('ຍ', 'ຍ'), ('ດ', 'ທ'),
+  ('ນ', 'ຟ'), ('ມ', 'ຣ'), ('ລ', 'ລ'), ('ວ', 'ວ'),
+  ('ສ', 'ຫ'), ('ອ', 'ະ'), ('າ', 'າ'), ('ຽ', 'ຽ'),
+  ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('ໜ', 'ໟ'), ('ༀ', 'ༀ'),
+  ('ཀ', 'ཇ'), ('ཉ', 'ཬ'), ('ྈ', 'ྌ'), ('က', 'ဪ'),
+  ('ဿ', 'ဿ'), ('ၐ', 'ၕ'), ('ၚ', 'ၝ'), ('ၡ', 'ၡ'),
+  ('ၥ', 'ၦ'), ('ၮ', 'ၰ'), ('ၵ', 'ႁ'), ('ႎ', 'ႎ'),
+  ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'),
+  ('ჼ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('ᎀ', 'ᎏ'), ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ᐁ', 'ᙬ'),
+  ('ᙯ', 'ᙿ'), ('ᚁ', 'ᚚ'), ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+  ('ᜀ', 'ᜌ'), ('ᜎ', 'ᜑ'), ('ᜠ', 'ᜱ'), ('ᝀ', 'ᝑ'),
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ក', 'ឳ'), ('ៗ', 'ៗ'),
+  ('ៜ', 'ៜ'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢨ'), ('ᢪ', 'ᢪ'),
+  ('ᢰ', 'ᣵ'), ('ᤀ', 'ᤞ'), ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'),
+  ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('ᨀ', 'ᨖ'), ('ᨠ', 'ᩔ'),
+  ('ᪧ', 'ᪧ'), ('ᬅ', 'ᬳ'), ('ᭅ', 'ᭋ'), ('ᮃ', 'ᮠ'),
+  ('ᮮ', 'ᮯ'), ('ᮺ', 'ᯥ'), ('ᰀ', 'ᰣ'), ('ᱍ', 'ᱏ'),
+  ('ᱚ', 'ᱽ'), ('ᲀ', 'ᲈ'), ('\u{1c90}', '\u{1cba}'),
+  ('\u{1cbd}', '\u{1cbf}'), ('ᳩ', 'ᳬ'), ('ᳮ', 'ᳱ'), ('ᳵ', 'ᳶ'),
+  ('ᴀ', 'ᶿ'), ('Ḁ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'),
+  ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'),
+  ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ᾼ'),
+  ('ι', 'ι'), ('ῂ', 'ῄ'), ('ῆ', 'ῌ'), ('ῐ', 'ΐ'),
+  ('ῖ', 'Ί'), ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('ℂ', 'ℂ'),
+  ('ℇ', 'ℇ'), ('ℊ', 'ℓ'), ('ℕ', 'ℕ'), ('℘', 'ℝ'),
+  ('ℤ', 'ℤ'), ('Ω', 'Ω'), ('ℨ', 'ℨ'), ('K', 'ℹ'),
+  ('ℼ', 'ℿ'), ('ⅅ', 'ⅉ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('Ⱡ', 'ⳤ'), ('Ⳬ', 'ⳮ'),
+  ('Ⳳ', 'ⳳ'), ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+  ('ⴰ', 'ⵧ'), ('ⵯ', 'ⵯ'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'),
+  ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'),
+  ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('々', '〇'),
+  ('〡', '〩'), ('〱', '〵'), ('〸', '〼'), ('ぁ', 'ゖ'),
+  ('ゝ', 'ゟ'), ('ァ', 'ヺ'), ('ー', 'ヿ'), ('ㄅ', '\u{312f}'),
+  ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆺ'), ('ㇰ', 'ㇿ'), ('㐀', '䶵'),
+  ('一', '\u{9fef}'), ('ꀀ', 'ꒌ'), ('ꓐ', 'ꓽ'), ('ꔀ', 'ꘌ'),
+  ('ꘐ', 'ꘟ'), ('ꘪ', 'ꘫ'), ('Ꙁ', 'ꙮ'), ('ꙿ', 'ꚝ'),
+  ('ꚠ', 'ꛯ'), ('ꜗ', 'ꜟ'), ('Ꜣ', 'ꞈ'), ('Ꞌ', '\u{a7b9}'),
+  ('ꟷ', 'ꠁ'), ('ꠃ', 'ꠅ'), ('ꠇ', 'ꠊ'), ('ꠌ', 'ꠢ'),
+  ('ꡀ', 'ꡳ'), ('ꢂ', 'ꢳ'), ('ꣲ', 'ꣷ'), ('ꣻ', 'ꣻ'),
+  ('ꣽ', '\u{a8fe}'), ('ꤊ', 'ꤥ'), ('ꤰ', 'ꥆ'), ('ꥠ', 'ꥼ'),
+  ('ꦄ', 'ꦲ'), ('ꧏ', 'ꧏ'), ('ꧠ', 'ꧤ'), ('ꧦ', 'ꧯ'),
+  ('ꧺ', 'ꧾ'), ('ꨀ', 'ꨨ'), ('ꩀ', 'ꩂ'), ('ꩄ', 'ꩋ'),
+  ('ꩠ', 'ꩶ'), ('ꩺ', 'ꩺ'), ('ꩾ', 'ꪯ'), ('ꪱ', 'ꪱ'),
+  ('ꪵ', 'ꪶ'), ('ꪹ', 'ꪽ'), ('ꫀ', 'ꫀ'), ('ꫂ', 'ꫂ'),
+  ('ꫛ', 'ꫝ'), ('ꫠ', 'ꫪ'), ('ꫲ', 'ꫴ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+  ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭥ'), ('ꭰ', 'ꯢ'), ('가', '힣'),
+  ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('豈', '舘'), ('並', '龎'),
+  ('ﬀ', 'ﬆ'), ('ﬓ', 'ﬗ'), ('יִ', 'יִ'), ('ײַ', 'ﬨ'),
+  ('שׁ', 'זּ'), ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'),
+  ('ףּ', 'פּ'), ('צּ', 'ﮱ'), ('ﯓ', 'ﱝ'), ('ﱤ', 'ﴽ'),
+  ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'), ('ﷰ', 'ﷹ'), ('ﹱ', 'ﹱ'),
+  ('ﹳ', 'ﹳ'), ('ﹷ', 'ﹷ'), ('ﹹ', 'ﹹ'), ('ﹻ', 'ﹻ'),
+  ('ﹽ', 'ﹽ'), ('ﹿ', 'ﻼ'), ('Ａ', 'Ｚ'), ('ａ', 'ｚ'),
+  ('ｦ', 'ﾝ'), ('ﾠ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'),
+  ('ￒ', 'ￗ'), ('ￚ', 'ￜ'), ('𐀀', '𐀋'), ('𐀍', '𐀦'),
+  ('𐀨', '𐀺'), ('𐀼', '𐀽'), ('𐀿', '𐁍'), ('𐁐', '𐁝'),
+  ('𐂀', '𐃺'), ('𐅀', '𐅴'), ('𐊀', '𐊜'), ('𐊠', '𐋐'),
+  ('𐌀', '𐌟'), ('𐌭', '𐍊'), ('𐍐', '𐍵'), ('𐎀', '𐎝'),
+  ('𐎠', '𐏃'), ('𐏈', '𐏏'), ('𐏑', '𐏕'), ('𐐀', '𐒝'),
+  ('𐒰', '𐓓'), ('𐓘', '𐓻'), ('𐔀', '𐔧'), ('𐔰', '𐕣'),
+  ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'), ('𐠀', '𐠅'),
+  ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'), ('𐠼', '𐠼'),
+  ('𐠿', '𐡕'), ('𐡠', '𐡶'), ('𐢀', '𐢞'), ('𐣠', '𐣲'),
+  ('𐣴', '𐣵'), ('𐤀', '𐤕'), ('𐤠', '𐤹'), ('𐦀', '𐦷'),
+  ('𐦾', '𐦿'), ('𐨀', '𐨀'), ('𐨐', '𐨓'), ('𐨕', '𐨗'),
+  ('𐨙', '\u{10a35}'), ('𐩠', '𐩼'), ('𐪀', '𐪜'), ('𐫀', '𐫇'),
+  ('𐫉', '𐫤'), ('𐬀', '𐬵'), ('𐭀', '𐭕'), ('𐭠', '𐭲'),
+  ('𐮀', '𐮑'), ('𐰀', '𐱈'), ('𐲀', '𐲲'), ('𐳀', '𐳲'),
+  ('\u{10d00}', '\u{10d23}'), ('\u{10f00}', '\u{10f1c}'),
+  ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'), ('𑀃', '𑀷'),
+  ('𑂃', '𑂯'), ('𑃐', '𑃨'), ('𑄃', '𑄦'),
+  ('\u{11144}', '\u{11144}'), ('𑅐', '𑅲'), ('𑅶', '𑅶'),
+  ('𑆃', '𑆲'), ('𑇁', '𑇄'), ('𑇚', '𑇚'), ('𑇜', '𑇜'),
+  ('𑈀', '𑈑'), ('𑈓', '𑈫'), ('𑊀', '𑊆'), ('𑊈', '𑊈'),
+  ('𑊊', '𑊍'), ('𑊏', '𑊝'), ('𑊟', '𑊨'), ('𑊰', '𑋞'),
+  ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'), ('𑌪', '𑌰'),
+  ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌽', '𑌽'), ('𑍐', '𑍐'),
+  ('𑍝', '𑍡'), ('𑐀', '𑐴'), ('𑑇', '𑑊'), ('𑒀', '𑒯'),
+  ('𑓄', '𑓅'), ('𑓇', '𑓇'), ('𑖀', '𑖮'), ('𑗘', '𑗛'),
+  ('𑘀', '𑘯'), ('𑙄', '𑙄'), ('𑚀', '𑚪'), ('𑜀', '\u{1171a}'),
+  ('\u{11800}', '\u{1182b}'), ('𑢠', '𑣟'), ('𑣿', '𑣿'),
+  ('𑨀', '𑨀'), ('𑨋', '𑨲'), ('𑨺', '𑨺'), ('𑩐', '𑩐'),
+  ('𑩜', '𑪃'), ('𑪆', '𑪉'), ('\u{11a9d}', '\u{11a9d}'),
+  ('𑫀', '𑫸'), ('𑰀', '𑰈'), ('𑰊', '𑰮'), ('𑱀', '𑱀'),
+  ('𑱲', '𑲏'), ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴰'),
+  ('𑵆', '𑵆'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d89}'), ('\u{11d98}', '\u{11d98}'),
+  ('\u{11ee0}', '\u{11ef2}'), ('𒀀', '𒎙'), ('𒐀', '𒑮'),
+  ('𒒀', '𒕃'), ('𓀀', '𓐮'), ('𔐀', '𔙆'), ('𖠀', '𖨸'),
+  ('𖩀', '𖩞'), ('𖫐', '𖫭'), ('𖬀', '𖬯'), ('𖭀', '𖭃'),
+  ('𖭣', '𖭷'), ('𖭽', '𖮏'), ('\u{16e40}', '\u{16e7f}'),
+  ('𖼀', '𖽄'), ('𖽐', '𖽐'), ('𖾓', '𖾟'), ('𖿠', '𖿡'),
+  ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'), ('𛀀', '𛄞'), ('𛅰', '𛋻'),
+  ('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'),
+  ('𝐀', '𝑔'), ('𝑖', '𝒜'), ('𝒞', '𝒟'), ('𝒢', '𝒢'),
+  ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒹'), ('𝒻', '𝒻'),
+  ('𝒽', '𝓃'), ('𝓅', '𝔅'), ('𝔇', '𝔊'), ('𝔍', '𝔔'),
+  ('𝔖', '𝔜'), ('𝔞', '𝔹'), ('𝔻', '𝔾'), ('𝕀', '𝕄'),
+  ('𝕆', '𝕆'), ('𝕊', '𝕐'), ('𝕒', '𝚥'), ('𝚨', '𝛀'),
+  ('𝛂', '𝛚'), ('𝛜', '𝛺'), ('𝛼', '𝜔'), ('𝜖', '𝜴'),
+  ('𝜶', '𝝎'), ('𝝐', '𝝮'), ('𝝰', '𝞈'), ('𝞊', '𝞨'),
+  ('𝞪', '𝟂'), ('𝟄', '𝟋'), ('𞠀', '𞣄'), ('𞤀', '𞥃'),
+  ('𞸀', '𞸃'), ('𞸅', '𞸟'), ('𞸡', '𞸢'), ('𞸤', '𞸤'),
+  ('𞸧', '𞸧'), ('𞸩', '𞸲'), ('𞸴', '𞸷'), ('𞸹', '𞸹'),
+  ('𞸻', '𞸻'), ('𞹂', '𞹂'), ('𞹇', '𞹇'), ('𞹉', '𞹉'),
+  ('𞹋', '𞹋'), ('𞹍', '𞹏'), ('𞹑', '𞹒'), ('𞹔', '𞹔'),
+  ('𞹗', '𞹗'), ('𞹙', '𞹙'), ('𞹛', '𞹛'), ('𞹝', '𞹝'),
+  ('𞹟', '𞹟'), ('𞹡', '𞹢'), ('𞹤', '𞹤'), ('𞹧', '𞹪'),
+  ('𞹬', '𞹲'), ('𞹴', '𞹷'), ('𞹹', '𞹼'), ('𞹾', '𞹾'),
+  ('𞺀', '𞺉'), ('𞺋', '𞺛'), ('𞺡', '𞺣'), ('𞺥', '𞺩'),
+  ('𞺫', '𞺻'), ('𠀀', '𪛖'), ('𪜀', '𫜴'), ('𫝀', '𫠝'),
+  ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/property_names.rs b/third_party/rust/regex-syntax/src/unicode_tables/property_names.rs
new file mode 100644
index 000000000000..aa1d684a7b95
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/property_names.rs
@@ -0,0 +1,147 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate property-names tmp/ucd-11.0.0/
+//
+// ucd-generate is available on crates.io.
+
+pub const PROPERTY_NAMES: &'static [(&'static str, &'static str)] = &[
+  ("age", "Age"), ("ahex", "ASCII_Hex_Digit"), ("alpha", "Alphabetic"),
+  ("alphabetic", "Alphabetic"), ("asciihexdigit", "ASCII_Hex_Digit"),
+  ("bc", "Bidi_Class"), ("bidic", "Bidi_Control"),
+  ("bidiclass", "Bidi_Class"), ("bidicontrol", "Bidi_Control"),
+  ("bidim", "Bidi_Mirrored"), ("bidimirrored", "Bidi_Mirrored"),
+  ("bidimirroringglyph", "Bidi_Mirroring_Glyph"),
+  ("bidipairedbracket", "Bidi_Paired_Bracket"),
+  ("bidipairedbrackettype", "Bidi_Paired_Bracket_Type"), ("blk", "Block"),
+  ("block", "Block"), ("bmg", "Bidi_Mirroring_Glyph"),
+  ("bpb", "Bidi_Paired_Bracket"), ("bpt", "Bidi_Paired_Bracket_Type"),
+  ("canonicalcombiningclass", "Canonical_Combining_Class"),
+  ("cased", "Cased"), ("casefolding", "Case_Folding"),
+  ("caseignorable", "Case_Ignorable"), ("ccc", "Canonical_Combining_Class"),
+  ("ce", "Composition_Exclusion"), ("cf", "Case_Folding"),
+  ("changeswhencasefolded", "Changes_When_Casefolded"),
+  ("changeswhencasemapped", "Changes_When_Casemapped"),
+  ("changeswhenlowercased", "Changes_When_Lowercased"),
+  ("changeswhennfkccasefolded", "Changes_When_NFKC_Casefolded"),
+  ("changeswhentitlecased", "Changes_When_Titlecased"),
+  ("changeswhenuppercased", "Changes_When_Uppercased"),
+  ("ci", "Case_Ignorable"), ("cjkaccountingnumeric", "kAccountingNumeric"),
+  ("cjkcompatibilityvariant", "kCompatibilityVariant"),
+  ("cjkiicore", "kIICore"), ("cjkirggsource", "kIRG_GSource"),
+  ("cjkirghsource", "kIRG_HSource"), ("cjkirgjsource", "kIRG_JSource"),
+  ("cjkirgkpsource", "kIRG_KPSource"), ("cjkirgksource", "kIRG_KSource"),
+  ("cjkirgmsource", "kIRG_MSource"), ("cjkirgtsource", "kIRG_TSource"),
+  ("cjkirgusource", "kIRG_USource"), ("cjkirgvsource", "kIRG_VSource"),
+  ("cjkothernumeric", "kOtherNumeric"),
+  ("cjkprimarynumeric", "kPrimaryNumeric"), ("cjkrsunicode", "kRSUnicode"),
+  ("compex", "Full_Composition_Exclusion"),
+  ("compositionexclusion", "Composition_Exclusion"),
+  ("cwcf", "Changes_When_Casefolded"), ("cwcm", "Changes_When_Casemapped"),
+  ("cwkcf", "Changes_When_NFKC_Casefolded"),
+  ("cwl", "Changes_When_Lowercased"), ("cwt", "Changes_When_Titlecased"),
+  ("cwu", "Changes_When_Uppercased"), ("dash", "Dash"),
+  ("decompositionmapping", "Decomposition_Mapping"),
+  ("decompositiontype", "Decomposition_Type"),
+  ("defaultignorablecodepoint", "Default_Ignorable_Code_Point"),
+  ("dep", "Deprecated"), ("deprecated", "Deprecated"),
+  ("di", "Default_Ignorable_Code_Point"), ("dia", "Diacritic"),
+  ("diacritic", "Diacritic"), ("dm", "Decomposition_Mapping"),
+  ("dt", "Decomposition_Type"), ("ea", "East_Asian_Width"),
+  ("eastasianwidth", "East_Asian_Width"),
+  ("equideo", "Equivalent_Unified_Ideograph"),
+  ("equivalentunifiedideograph", "Equivalent_Unified_Ideograph"),
+  ("expandsonnfc", "Expands_On_NFC"), ("expandsonnfd", "Expands_On_NFD"),
+  ("expandsonnfkc", "Expands_On_NFKC"), ("expandsonnfkd", "Expands_On_NFKD"),
+  ("ext", "Extender"), ("extender", "Extender"),
+  ("fcnfkc", "FC_NFKC_Closure"), ("fcnfkcclosure", "FC_NFKC_Closure"),
+  ("fullcompositionexclusion", "Full_Composition_Exclusion"),
+  ("gc", "General_Category"), ("gcb", "Grapheme_Cluster_Break"),
+  ("generalcategory", "General_Category"), ("graphemebase", "Grapheme_Base"),
+  ("graphemeclusterbreak", "Grapheme_Cluster_Break"),
+  ("graphemeextend", "Grapheme_Extend"), ("graphemelink", "Grapheme_Link"),
+  ("grbase", "Grapheme_Base"), ("grext", "Grapheme_Extend"),
+  ("grlink", "Grapheme_Link"), ("hangulsyllabletype", "Hangul_Syllable_Type"),
+  ("hex", "Hex_Digit"), ("hexdigit", "Hex_Digit"),
+  ("hst", "Hangul_Syllable_Type"), ("hyphen", "Hyphen"),
+  ("idc", "ID_Continue"), ("idcontinue", "ID_Continue"),
+  ("ideo", "Ideographic"), ("ideographic", "Ideographic"),
+  ("ids", "ID_Start"), ("idsb", "IDS_Binary_Operator"),
+  ("idsbinaryoperator", "IDS_Binary_Operator"),
+  ("idst", "IDS_Trinary_Operator"), ("idstart", "ID_Start"),
+  ("idstrinaryoperator", "IDS_Trinary_Operator"),
+  ("indicpositionalcategory", "Indic_Positional_Category"),
+  ("indicsyllabiccategory", "Indic_Syllabic_Category"),
+  ("inpc", "Indic_Positional_Category"), ("insc", "Indic_Syllabic_Category"),
+  ("isc", "ISO_Comment"), ("jamoshortname", "Jamo_Short_Name"),
+  ("jg", "Joining_Group"), ("joinc", "Join_Control"),
+  ("joincontrol", "Join_Control"), ("joininggroup", "Joining_Group"),
+  ("joiningtype", "Joining_Type"), ("jsn", "Jamo_Short_Name"),
+  ("jt", "Joining_Type"), ("kaccountingnumeric", "kAccountingNumeric"),
+  ("kcompatibilityvariant", "kCompatibilityVariant"), ("kiicore", "kIICore"),
+  ("kirggsource", "kIRG_GSource"), ("kirghsource", "kIRG_HSource"),
+  ("kirgjsource", "kIRG_JSource"), ("kirgkpsource", "kIRG_KPSource"),
+  ("kirgksource", "kIRG_KSource"), ("kirgmsource", "kIRG_MSource"),
+  ("kirgtsource", "kIRG_TSource"), ("kirgusource", "kIRG_USource"),
+  ("kirgvsource", "kIRG_VSource"), ("kothernumeric", "kOtherNumeric"),
+  ("kprimarynumeric", "kPrimaryNumeric"), ("krsunicode", "kRSUnicode"),
+  ("lb", "Line_Break"), ("lc", "Lowercase_Mapping"),
+  ("linebreak", "Line_Break"), ("loe", "Logical_Order_Exception"),
+  ("logicalorderexception", "Logical_Order_Exception"),
+  ("lower", "Lowercase"), ("lowercase", "Lowercase"),
+  ("lowercasemapping", "Lowercase_Mapping"), ("math", "Math"), ("na", "Name"),
+  ("na1", "Unicode_1_Name"), ("name", "Name"), ("namealias", "Name_Alias"),
+  ("nchar", "Noncharacter_Code_Point"), ("nfcqc", "NFC_Quick_Check"),
+  ("nfcquickcheck", "NFC_Quick_Check"), ("nfdqc", "NFD_Quick_Check"),
+  ("nfdquickcheck", "NFD_Quick_Check"), ("nfkccasefold", "NFKC_Casefold"),
+  ("nfkccf", "NFKC_Casefold"), ("nfkcqc", "NFKC_Quick_Check"),
+  ("nfkcquickcheck", "NFKC_Quick_Check"), ("nfkdqc", "NFKD_Quick_Check"),
+  ("nfkdquickcheck", "NFKD_Quick_Check"),
+  ("noncharactercodepoint", "Noncharacter_Code_Point"),
+  ("nt", "Numeric_Type"), ("numerictype", "Numeric_Type"),
+  ("numericvalue", "Numeric_Value"), ("nv", "Numeric_Value"),
+  ("oalpha", "Other_Alphabetic"), ("ocomment", "ISO_Comment"),
+  ("odi", "Other_Default_Ignorable_Code_Point"),
+  ("ogrext", "Other_Grapheme_Extend"), ("oidc", "Other_ID_Continue"),
+  ("oids", "Other_ID_Start"), ("olower", "Other_Lowercase"),
+  ("omath", "Other_Math"), ("otheralphabetic", "Other_Alphabetic"),
+  ("otherdefaultignorablecodepoint", "Other_Default_Ignorable_Code_Point"),
+  ("othergraphemeextend", "Other_Grapheme_Extend"),
+  ("otheridcontinue", "Other_ID_Continue"),
+  ("otheridstart", "Other_ID_Start"), ("otherlowercase", "Other_Lowercase"),
+  ("othermath", "Other_Math"), ("otheruppercase", "Other_Uppercase"),
+  ("oupper", "Other_Uppercase"), ("patsyn", "Pattern_Syntax"),
+  ("patternsyntax", "Pattern_Syntax"),
+  ("patternwhitespace", "Pattern_White_Space"),
+  ("patws", "Pattern_White_Space"), ("pcm", "Prepended_Concatenation_Mark"),
+  ("prependedconcatenationmark", "Prepended_Concatenation_Mark"),
+  ("qmark", "Quotation_Mark"), ("quotationmark", "Quotation_Mark"),
+  ("radical", "Radical"), ("regionalindicator", "Regional_Indicator"),
+  ("ri", "Regional_Indicator"), ("sb", "Sentence_Break"), ("sc", "Script"),
+  ("scf", "Simple_Case_Folding"), ("script", "Script"),
+  ("scriptextensions", "Script_Extensions"), ("scx", "Script_Extensions"),
+  ("sd", "Soft_Dotted"), ("sentencebreak", "Sentence_Break"),
+  ("sentenceterminal", "Sentence_Terminal"), ("sfc", "Simple_Case_Folding"),
+  ("simplecasefolding", "Simple_Case_Folding"),
+  ("simplelowercasemapping", "Simple_Lowercase_Mapping"),
+  ("simpletitlecasemapping", "Simple_Titlecase_Mapping"),
+  ("simpleuppercasemapping", "Simple_Uppercase_Mapping"),
+  ("slc", "Simple_Lowercase_Mapping"), ("softdotted", "Soft_Dotted"),
+  ("space", "White_Space"), ("stc", "Simple_Titlecase_Mapping"),
+  ("sterm", "Sentence_Terminal"), ("suc", "Simple_Uppercase_Mapping"),
+  ("tc", "Titlecase_Mapping"), ("term", "Terminal_Punctuation"),
+  ("terminalpunctuation", "Terminal_Punctuation"),
+  ("titlecasemapping", "Titlecase_Mapping"), ("uc", "Uppercase_Mapping"),
+  ("uideo", "Unified_Ideograph"), ("unicode1name", "Unicode_1_Name"),
+  ("unicoderadicalstroke", "kRSUnicode"),
+  ("unifiedideograph", "Unified_Ideograph"), ("upper", "Uppercase"),
+  ("uppercase", "Uppercase"), ("uppercasemapping", "Uppercase_Mapping"),
+  ("urs", "kRSUnicode"), ("variationselector", "Variation_Selector"),
+  ("verticalorientation", "Vertical_Orientation"),
+  ("vo", "Vertical_Orientation"), ("vs", "Variation_Selector"),
+  ("wb", "Word_Break"), ("whitespace", "White_Space"),
+  ("wordbreak", "Word_Break"), ("wspace", "White_Space"),
+  ("xidc", "XID_Continue"), ("xidcontinue", "XID_Continue"),
+  ("xids", "XID_Start"), ("xidstart", "XID_Start"),
+  ("xonfc", "Expands_On_NFC"), ("xonfd", "Expands_On_NFD"),
+  ("xonfkc", "Expands_On_NFKC"), ("xonfkd", "Expands_On_NFKD"),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/property_values.rs b/third_party/rust/regex-syntax/src/unicode_tables/property_values.rs
new file mode 100644
index 000000000000..cc6f8f2185dd
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/property_values.rs
@@ -0,0 +1,289 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate property-values tmp/ucd-11.0.0/ --include gc,script,scx,age
+//
+// ucd-generate is available on crates.io.
+
+pub const PROPERTY_VALUES: &'static [(&'static str, &'static [(&'static str, &'static str)])] = &[
+  ("Age", &[("1.1", "V1_1"), ("10.0", "V10_0"), ("11.0", "V11_0"),
+  ("2.0", "V2_0"), ("2.1", "V2_1"), ("3.0", "V3_0"), ("3.1", "V3_1"),
+  ("3.2", "V3_2"), ("4.0", "V4_0"), ("4.1", "V4_1"), ("5.0", "V5_0"),
+  ("5.1", "V5_1"), ("5.2", "V5_2"), ("6.0", "V6_0"), ("6.1", "V6_1"),
+  ("6.2", "V6_2"), ("6.3", "V6_3"), ("7.0", "V7_0"), ("8.0", "V8_0"),
+  ("9.0", "V9_0"), ("na", "Unassigned"), ("unassigned", "Unassigned"),
+  ("v100", "V10_0"), ("v11", "V1_1"), ("v110", "V11_0"), ("v20", "V2_0"),
+  ("v21", "V2_1"), ("v30", "V3_0"), ("v31", "V3_1"), ("v32", "V3_2"),
+  ("v40", "V4_0"), ("v41", "V4_1"), ("v50", "V5_0"), ("v51", "V5_1"),
+  ("v52", "V5_2"), ("v60", "V6_0"), ("v61", "V6_1"), ("v62", "V6_2"),
+  ("v63", "V6_3"), ("v70", "V7_0"), ("v80", "V8_0"), ("v90", "V9_0"), ]),
+
+  ("General_Category", &[("c", "Other"), ("casedletter", "Cased_Letter"),
+  ("cc", "Control"), ("cf", "Format"),
+  ("closepunctuation", "Close_Punctuation"), ("cn", "Unassigned"),
+  ("cntrl", "Control"), ("co", "Private_Use"), ("combiningmark", "Mark"),
+  ("connectorpunctuation", "Connector_Punctuation"), ("control", "Control"),
+  ("cs", "Surrogate"), ("currencysymbol", "Currency_Symbol"),
+  ("dashpunctuation", "Dash_Punctuation"),
+  ("decimalnumber", "Decimal_Number"), ("digit", "Decimal_Number"),
+  ("enclosingmark", "Enclosing_Mark"),
+  ("finalpunctuation", "Final_Punctuation"), ("format", "Format"),
+  ("initialpunctuation", "Initial_Punctuation"), ("l", "Letter"),
+  ("lc", "Cased_Letter"), ("letter", "Letter"),
+  ("letternumber", "Letter_Number"), ("lineseparator", "Line_Separator"),
+  ("ll", "Lowercase_Letter"), ("lm", "Modifier_Letter"),
+  ("lo", "Other_Letter"), ("lowercaseletter", "Lowercase_Letter"),
+  ("lt", "Titlecase_Letter"), ("lu", "Uppercase_Letter"), ("m", "Mark"),
+  ("mark", "Mark"), ("mathsymbol", "Math_Symbol"), ("mc", "Spacing_Mark"),
+  ("me", "Enclosing_Mark"), ("mn", "Nonspacing_Mark"),
+  ("modifierletter", "Modifier_Letter"),
+  ("modifiersymbol", "Modifier_Symbol"), ("n", "Number"),
+  ("nd", "Decimal_Number"), ("nl", "Letter_Number"), ("no", "Other_Number"),
+  ("nonspacingmark", "Nonspacing_Mark"), ("number", "Number"),
+  ("openpunctuation", "Open_Punctuation"), ("other", "Other"),
+  ("otherletter", "Other_Letter"), ("othernumber", "Other_Number"),
+  ("otherpunctuation", "Other_Punctuation"), ("othersymbol", "Other_Symbol"),
+  ("p", "Punctuation"), ("paragraphseparator", "Paragraph_Separator"),
+  ("pc", "Connector_Punctuation"), ("pd", "Dash_Punctuation"),
+  ("pe", "Close_Punctuation"), ("pf", "Final_Punctuation"),
+  ("pi", "Initial_Punctuation"), ("po", "Other_Punctuation"),
+  ("privateuse", "Private_Use"), ("ps", "Open_Punctuation"),
+  ("punct", "Punctuation"), ("punctuation", "Punctuation"), ("s", "Symbol"),
+  ("sc", "Currency_Symbol"), ("separator", "Separator"),
+  ("sk", "Modifier_Symbol"), ("sm", "Math_Symbol"), ("so", "Other_Symbol"),
+  ("spaceseparator", "Space_Separator"), ("spacingmark", "Spacing_Mark"),
+  ("surrogate", "Surrogate"), ("symbol", "Symbol"),
+  ("titlecaseletter", "Titlecase_Letter"), ("unassigned", "Unassigned"),
+  ("uppercaseletter", "Uppercase_Letter"), ("z", "Separator"),
+  ("zl", "Line_Separator"), ("zp", "Paragraph_Separator"),
+  ("zs", "Space_Separator"), ]),
+
+  ("Script", &[("adlam", "Adlam"), ("adlm", "Adlam"),
+  ("aghb", "Caucasian_Albanian"), ("ahom", "Ahom"),
+  ("anatolianhieroglyphs", "Anatolian_Hieroglyphs"), ("arab", "Arabic"),
+  ("arabic", "Arabic"), ("armenian", "Armenian"),
+  ("armi", "Imperial_Aramaic"), ("armn", "Armenian"), ("avestan", "Avestan"),
+  ("avst", "Avestan"), ("bali", "Balinese"), ("balinese", "Balinese"),
+  ("bamu", "Bamum"), ("bamum", "Bamum"), ("bass", "Bassa_Vah"),
+  ("bassavah", "Bassa_Vah"), ("batak", "Batak"), ("batk", "Batak"),
+  ("beng", "Bengali"), ("bengali", "Bengali"), ("bhaiksuki", "Bhaiksuki"),
+  ("bhks", "Bhaiksuki"), ("bopo", "Bopomofo"), ("bopomofo", "Bopomofo"),
+  ("brah", "Brahmi"), ("brahmi", "Brahmi"), ("brai", "Braille"),
+  ("braille", "Braille"), ("bugi", "Buginese"), ("buginese", "Buginese"),
+  ("buhd", "Buhid"), ("buhid", "Buhid"), ("cakm", "Chakma"),
+  ("canadianaboriginal", "Canadian_Aboriginal"),
+  ("cans", "Canadian_Aboriginal"), ("cari", "Carian"), ("carian", "Carian"),
+  ("caucasianalbanian", "Caucasian_Albanian"), ("chakma", "Chakma"),
+  ("cham", "Cham"), ("cher", "Cherokee"), ("cherokee", "Cherokee"),
+  ("common", "Common"), ("copt", "Coptic"), ("coptic", "Coptic"),
+  ("cprt", "Cypriot"), ("cuneiform", "Cuneiform"), ("cypriot", "Cypriot"),
+  ("cyrillic", "Cyrillic"), ("cyrl", "Cyrillic"), ("deseret", "Deseret"),
+  ("deva", "Devanagari"), ("devanagari", "Devanagari"), ("dogr", "Dogra"),
+  ("dogra", "Dogra"), ("dsrt", "Deseret"), ("dupl", "Duployan"),
+  ("duployan", "Duployan"), ("egyp", "Egyptian_Hieroglyphs"),
+  ("egyptianhieroglyphs", "Egyptian_Hieroglyphs"), ("elba", "Elbasan"),
+  ("elbasan", "Elbasan"), ("ethi", "Ethiopic"), ("ethiopic", "Ethiopic"),
+  ("geor", "Georgian"), ("georgian", "Georgian"), ("glag", "Glagolitic"),
+  ("glagolitic", "Glagolitic"), ("gong", "Gunjala_Gondi"),
+  ("gonm", "Masaram_Gondi"), ("goth", "Gothic"), ("gothic", "Gothic"),
+  ("gran", "Grantha"), ("grantha", "Grantha"), ("greek", "Greek"),
+  ("grek", "Greek"), ("gujarati", "Gujarati"), ("gujr", "Gujarati"),
+  ("gunjalagondi", "Gunjala_Gondi"), ("gurmukhi", "Gurmukhi"),
+  ("guru", "Gurmukhi"), ("han", "Han"), ("hang", "Hangul"),
+  ("hangul", "Hangul"), ("hani", "Han"),
+  ("hanifirohingya", "Hanifi_Rohingya"), ("hano", "Hanunoo"),
+  ("hanunoo", "Hanunoo"), ("hatr", "Hatran"), ("hatran", "Hatran"),
+  ("hebr", "Hebrew"), ("hebrew", "Hebrew"), ("hira", "Hiragana"),
+  ("hiragana", "Hiragana"), ("hluw", "Anatolian_Hieroglyphs"),
+  ("hmng", "Pahawh_Hmong"), ("hrkt", "Katakana_Or_Hiragana"),
+  ("hung", "Old_Hungarian"), ("imperialaramaic", "Imperial_Aramaic"),
+  ("inherited", "Inherited"),
+  ("inscriptionalpahlavi", "Inscriptional_Pahlavi"),
+  ("inscriptionalparthian", "Inscriptional_Parthian"), ("ital", "Old_Italic"),
+  ("java", "Javanese"), ("javanese", "Javanese"), ("kaithi", "Kaithi"),
+  ("kali", "Kayah_Li"), ("kana", "Katakana"), ("kannada", "Kannada"),
+  ("katakana", "Katakana"), ("katakanaorhiragana", "Katakana_Or_Hiragana"),
+  ("kayahli", "Kayah_Li"), ("khar", "Kharoshthi"),
+  ("kharoshthi", "Kharoshthi"), ("khmer", "Khmer"), ("khmr", "Khmer"),
+  ("khoj", "Khojki"), ("khojki", "Khojki"), ("khudawadi", "Khudawadi"),
+  ("knda", "Kannada"), ("kthi", "Kaithi"), ("lana", "Tai_Tham"),
+  ("lao", "Lao"), ("laoo", "Lao"), ("latin", "Latin"), ("latn", "Latin"),
+  ("lepc", "Lepcha"), ("lepcha", "Lepcha"), ("limb", "Limbu"),
+  ("limbu", "Limbu"), ("lina", "Linear_A"), ("linb", "Linear_B"),
+  ("lineara", "Linear_A"), ("linearb", "Linear_B"), ("lisu", "Lisu"),
+  ("lyci", "Lycian"), ("lycian", "Lycian"), ("lydi", "Lydian"),
+  ("lydian", "Lydian"), ("mahajani", "Mahajani"), ("mahj", "Mahajani"),
+  ("maka", "Makasar"), ("makasar", "Makasar"), ("malayalam", "Malayalam"),
+  ("mand", "Mandaic"), ("mandaic", "Mandaic"), ("mani", "Manichaean"),
+  ("manichaean", "Manichaean"), ("marc", "Marchen"), ("marchen", "Marchen"),
+  ("masaramgondi", "Masaram_Gondi"), ("medefaidrin", "Medefaidrin"),
+  ("medf", "Medefaidrin"), ("meeteimayek", "Meetei_Mayek"),
+  ("mend", "Mende_Kikakui"), ("mendekikakui", "Mende_Kikakui"),
+  ("merc", "Meroitic_Cursive"), ("mero", "Meroitic_Hieroglyphs"),
+  ("meroiticcursive", "Meroitic_Cursive"),
+  ("meroitichieroglyphs", "Meroitic_Hieroglyphs"), ("miao", "Miao"),
+  ("mlym", "Malayalam"), ("modi", "Modi"), ("mong", "Mongolian"),
+  ("mongolian", "Mongolian"), ("mro", "Mro"), ("mroo", "Mro"),
+  ("mtei", "Meetei_Mayek"), ("mult", "Multani"), ("multani", "Multani"),
+  ("myanmar", "Myanmar"), ("mymr", "Myanmar"), ("nabataean", "Nabataean"),
+  ("narb", "Old_North_Arabian"), ("nbat", "Nabataean"), ("newa", "Newa"),
+  ("newtailue", "New_Tai_Lue"), ("nko", "Nko"), ("nkoo", "Nko"),
+  ("nshu", "Nushu"), ("nushu", "Nushu"), ("ogam", "Ogham"),
+  ("ogham", "Ogham"), ("olchiki", "Ol_Chiki"), ("olck", "Ol_Chiki"),
+  ("oldhungarian", "Old_Hungarian"), ("olditalic", "Old_Italic"),
+  ("oldnortharabian", "Old_North_Arabian"), ("oldpermic", "Old_Permic"),
+  ("oldpersian", "Old_Persian"), ("oldsogdian", "Old_Sogdian"),
+  ("oldsoutharabian", "Old_South_Arabian"), ("oldturkic", "Old_Turkic"),
+  ("oriya", "Oriya"), ("orkh", "Old_Turkic"), ("orya", "Oriya"),
+  ("osage", "Osage"), ("osge", "Osage"), ("osma", "Osmanya"),
+  ("osmanya", "Osmanya"), ("pahawhhmong", "Pahawh_Hmong"),
+  ("palm", "Palmyrene"), ("palmyrene", "Palmyrene"), ("pauc", "Pau_Cin_Hau"),
+  ("paucinhau", "Pau_Cin_Hau"), ("perm", "Old_Permic"), ("phag", "Phags_Pa"),
+  ("phagspa", "Phags_Pa"), ("phli", "Inscriptional_Pahlavi"),
+  ("phlp", "Psalter_Pahlavi"), ("phnx", "Phoenician"),
+  ("phoenician", "Phoenician"), ("plrd", "Miao"),
+  ("prti", "Inscriptional_Parthian"), ("psalterpahlavi", "Psalter_Pahlavi"),
+  ("qaac", "Coptic"), ("qaai", "Inherited"), ("rejang", "Rejang"),
+  ("rjng", "Rejang"), ("rohg", "Hanifi_Rohingya"), ("runic", "Runic"),
+  ("runr", "Runic"), ("samaritan", "Samaritan"), ("samr", "Samaritan"),
+  ("sarb", "Old_South_Arabian"), ("saur", "Saurashtra"),
+  ("saurashtra", "Saurashtra"), ("sgnw", "SignWriting"),
+  ("sharada", "Sharada"), ("shavian", "Shavian"), ("shaw", "Shavian"),
+  ("shrd", "Sharada"), ("sidd", "Siddham"), ("siddham", "Siddham"),
+  ("signwriting", "SignWriting"), ("sind", "Khudawadi"), ("sinh", "Sinhala"),
+  ("sinhala", "Sinhala"), ("sogd", "Sogdian"), ("sogdian", "Sogdian"),
+  ("sogo", "Old_Sogdian"), ("sora", "Sora_Sompeng"),
+  ("sorasompeng", "Sora_Sompeng"), ("soyo", "Soyombo"),
+  ("soyombo", "Soyombo"), ("sund", "Sundanese"), ("sundanese", "Sundanese"),
+  ("sylo", "Syloti_Nagri"), ("sylotinagri", "Syloti_Nagri"),
+  ("syrc", "Syriac"), ("syriac", "Syriac"), ("tagalog", "Tagalog"),
+  ("tagb", "Tagbanwa"), ("tagbanwa", "Tagbanwa"), ("taile", "Tai_Le"),
+  ("taitham", "Tai_Tham"), ("taiviet", "Tai_Viet"), ("takr", "Takri"),
+  ("takri", "Takri"), ("tale", "Tai_Le"), ("talu", "New_Tai_Lue"),
+  ("tamil", "Tamil"), ("taml", "Tamil"), ("tang", "Tangut"),
+  ("tangut", "Tangut"), ("tavt", "Tai_Viet"), ("telu", "Telugu"),
+  ("telugu", "Telugu"), ("tfng", "Tifinagh"), ("tglg", "Tagalog"),
+  ("thaa", "Thaana"), ("thaana", "Thaana"), ("thai", "Thai"),
+  ("tibetan", "Tibetan"), ("tibt", "Tibetan"), ("tifinagh", "Tifinagh"),
+  ("tirh", "Tirhuta"), ("tirhuta", "Tirhuta"), ("ugar", "Ugaritic"),
+  ("ugaritic", "Ugaritic"), ("unknown", "Unknown"), ("vai", "Vai"),
+  ("vaii", "Vai"), ("wara", "Warang_Citi"), ("warangciti", "Warang_Citi"),
+  ("xpeo", "Old_Persian"), ("xsux", "Cuneiform"), ("yi", "Yi"),
+  ("yiii", "Yi"), ("zanabazarsquare", "Zanabazar_Square"),
+  ("zanb", "Zanabazar_Square"), ("zinh", "Inherited"), ("zyyy", "Common"),
+  ("zzzz", "Unknown"), ]),
+
+  ("Script_Extensions", &[("adlam", "Adlam"), ("adlm", "Adlam"),
+  ("aghb", "Caucasian_Albanian"), ("ahom", "Ahom"),
+  ("anatolianhieroglyphs", "Anatolian_Hieroglyphs"), ("arab", "Arabic"),
+  ("arabic", "Arabic"), ("armenian", "Armenian"),
+  ("armi", "Imperial_Aramaic"), ("armn", "Armenian"), ("avestan", "Avestan"),
+  ("avst", "Avestan"), ("bali", "Balinese"), ("balinese", "Balinese"),
+  ("bamu", "Bamum"), ("bamum", "Bamum"), ("bass", "Bassa_Vah"),
+  ("bassavah", "Bassa_Vah"), ("batak", "Batak"), ("batk", "Batak"),
+  ("beng", "Bengali"), ("bengali", "Bengali"), ("bhaiksuki", "Bhaiksuki"),
+  ("bhks", "Bhaiksuki"), ("bopo", "Bopomofo"), ("bopomofo", "Bopomofo"),
+  ("brah", "Brahmi"), ("brahmi", "Brahmi"), ("brai", "Braille"),
+  ("braille", "Braille"), ("bugi", "Buginese"), ("buginese", "Buginese"),
+  ("buhd", "Buhid"), ("buhid", "Buhid"), ("cakm", "Chakma"),
+  ("canadianaboriginal", "Canadian_Aboriginal"),
+  ("cans", "Canadian_Aboriginal"), ("cari", "Carian"), ("carian", "Carian"),
+  ("caucasianalbanian", "Caucasian_Albanian"), ("chakma", "Chakma"),
+  ("cham", "Cham"), ("cher", "Cherokee"), ("cherokee", "Cherokee"),
+  ("common", "Common"), ("copt", "Coptic"), ("coptic", "Coptic"),
+  ("cprt", "Cypriot"), ("cuneiform", "Cuneiform"), ("cypriot", "Cypriot"),
+  ("cyrillic", "Cyrillic"), ("cyrl", "Cyrillic"), ("deseret", "Deseret"),
+  ("deva", "Devanagari"), ("devanagari", "Devanagari"), ("dogr", "Dogra"),
+  ("dogra", "Dogra"), ("dsrt", "Deseret"), ("dupl", "Duployan"),
+  ("duployan", "Duployan"), ("egyp", "Egyptian_Hieroglyphs"),
+  ("egyptianhieroglyphs", "Egyptian_Hieroglyphs"), ("elba", "Elbasan"),
+  ("elbasan", "Elbasan"), ("ethi", "Ethiopic"), ("ethiopic", "Ethiopic"),
+  ("geor", "Georgian"), ("georgian", "Georgian"), ("glag", "Glagolitic"),
+  ("glagolitic", "Glagolitic"), ("gong", "Gunjala_Gondi"),
+  ("gonm", "Masaram_Gondi"), ("goth", "Gothic"), ("gothic", "Gothic"),
+  ("gran", "Grantha"), ("grantha", "Grantha"), ("greek", "Greek"),
+  ("grek", "Greek"), ("gujarati", "Gujarati"), ("gujr", "Gujarati"),
+  ("gunjalagondi", "Gunjala_Gondi"), ("gurmukhi", "Gurmukhi"),
+  ("guru", "Gurmukhi"), ("han", "Han"), ("hang", "Hangul"),
+  ("hangul", "Hangul"), ("hani", "Han"),
+  ("hanifirohingya", "Hanifi_Rohingya"), ("hano", "Hanunoo"),
+  ("hanunoo", "Hanunoo"), ("hatr", "Hatran"), ("hatran", "Hatran"),
+  ("hebr", "Hebrew"), ("hebrew", "Hebrew"), ("hira", "Hiragana"),
+  ("hiragana", "Hiragana"), ("hluw", "Anatolian_Hieroglyphs"),
+  ("hmng", "Pahawh_Hmong"), ("hrkt", "Katakana_Or_Hiragana"),
+  ("hung", "Old_Hungarian"), ("imperialaramaic", "Imperial_Aramaic"),
+  ("inherited", "Inherited"),
+  ("inscriptionalpahlavi", "Inscriptional_Pahlavi"),
+  ("inscriptionalparthian", "Inscriptional_Parthian"), ("ital", "Old_Italic"),
+  ("java", "Javanese"), ("javanese", "Javanese"), ("kaithi", "Kaithi"),
+  ("kali", "Kayah_Li"), ("kana", "Katakana"), ("kannada", "Kannada"),
+  ("katakana", "Katakana"), ("katakanaorhiragana", "Katakana_Or_Hiragana"),
+  ("kayahli", "Kayah_Li"), ("khar", "Kharoshthi"),
+  ("kharoshthi", "Kharoshthi"), ("khmer", "Khmer"), ("khmr", "Khmer"),
+  ("khoj", "Khojki"), ("khojki", "Khojki"), ("khudawadi", "Khudawadi"),
+  ("knda", "Kannada"), ("kthi", "Kaithi"), ("lana", "Tai_Tham"),
+  ("lao", "Lao"), ("laoo", "Lao"), ("latin", "Latin"), ("latn", "Latin"),
+  ("lepc", "Lepcha"), ("lepcha", "Lepcha"), ("limb", "Limbu"),
+  ("limbu", "Limbu"), ("lina", "Linear_A"), ("linb", "Linear_B"),
+  ("lineara", "Linear_A"), ("linearb", "Linear_B"), ("lisu", "Lisu"),
+  ("lyci", "Lycian"), ("lycian", "Lycian"), ("lydi", "Lydian"),
+  ("lydian", "Lydian"), ("mahajani", "Mahajani"), ("mahj", "Mahajani"),
+  ("maka", "Makasar"), ("makasar", "Makasar"), ("malayalam", "Malayalam"),
+  ("mand", "Mandaic"), ("mandaic", "Mandaic"), ("mani", "Manichaean"),
+  ("manichaean", "Manichaean"), ("marc", "Marchen"), ("marchen", "Marchen"),
+  ("masaramgondi", "Masaram_Gondi"), ("medefaidrin", "Medefaidrin"),
+  ("medf", "Medefaidrin"), ("meeteimayek", "Meetei_Mayek"),
+  ("mend", "Mende_Kikakui"), ("mendekikakui", "Mende_Kikakui"),
+  ("merc", "Meroitic_Cursive"), ("mero", "Meroitic_Hieroglyphs"),
+  ("meroiticcursive", "Meroitic_Cursive"),
+  ("meroitichieroglyphs", "Meroitic_Hieroglyphs"), ("miao", "Miao"),
+  ("mlym", "Malayalam"), ("modi", "Modi"), ("mong", "Mongolian"),
+  ("mongolian", "Mongolian"), ("mro", "Mro"), ("mroo", "Mro"),
+  ("mtei", "Meetei_Mayek"), ("mult", "Multani"), ("multani", "Multani"),
+  ("myanmar", "Myanmar"), ("mymr", "Myanmar"), ("nabataean", "Nabataean"),
+  ("narb", "Old_North_Arabian"), ("nbat", "Nabataean"), ("newa", "Newa"),
+  ("newtailue", "New_Tai_Lue"), ("nko", "Nko"), ("nkoo", "Nko"),
+  ("nshu", "Nushu"), ("nushu", "Nushu"), ("ogam", "Ogham"),
+  ("ogham", "Ogham"), ("olchiki", "Ol_Chiki"), ("olck", "Ol_Chiki"),
+  ("oldhungarian", "Old_Hungarian"), ("olditalic", "Old_Italic"),
+  ("oldnortharabian", "Old_North_Arabian"), ("oldpermic", "Old_Permic"),
+  ("oldpersian", "Old_Persian"), ("oldsogdian", "Old_Sogdian"),
+  ("oldsoutharabian", "Old_South_Arabian"), ("oldturkic", "Old_Turkic"),
+  ("oriya", "Oriya"), ("orkh", "Old_Turkic"), ("orya", "Oriya"),
+  ("osage", "Osage"), ("osge", "Osage"), ("osma", "Osmanya"),
+  ("osmanya", "Osmanya"), ("pahawhhmong", "Pahawh_Hmong"),
+  ("palm", "Palmyrene"), ("palmyrene", "Palmyrene"), ("pauc", "Pau_Cin_Hau"),
+  ("paucinhau", "Pau_Cin_Hau"), ("perm", "Old_Permic"), ("phag", "Phags_Pa"),
+  ("phagspa", "Phags_Pa"), ("phli", "Inscriptional_Pahlavi"),
+  ("phlp", "Psalter_Pahlavi"), ("phnx", "Phoenician"),
+  ("phoenician", "Phoenician"), ("plrd", "Miao"),
+  ("prti", "Inscriptional_Parthian"), ("psalterpahlavi", "Psalter_Pahlavi"),
+  ("qaac", "Coptic"), ("qaai", "Inherited"), ("rejang", "Rejang"),
+  ("rjng", "Rejang"), ("rohg", "Hanifi_Rohingya"), ("runic", "Runic"),
+  ("runr", "Runic"), ("samaritan", "Samaritan"), ("samr", "Samaritan"),
+  ("sarb", "Old_South_Arabian"), ("saur", "Saurashtra"),
+  ("saurashtra", "Saurashtra"), ("sgnw", "SignWriting"),
+  ("sharada", "Sharada"), ("shavian", "Shavian"), ("shaw", "Shavian"),
+  ("shrd", "Sharada"), ("sidd", "Siddham"), ("siddham", "Siddham"),
+  ("signwriting", "SignWriting"), ("sind", "Khudawadi"), ("sinh", "Sinhala"),
+  ("sinhala", "Sinhala"), ("sogd", "Sogdian"), ("sogdian", "Sogdian"),
+  ("sogo", "Old_Sogdian"), ("sora", "Sora_Sompeng"),
+  ("sorasompeng", "Sora_Sompeng"), ("soyo", "Soyombo"),
+  ("soyombo", "Soyombo"), ("sund", "Sundanese"), ("sundanese", "Sundanese"),
+  ("sylo", "Syloti_Nagri"), ("sylotinagri", "Syloti_Nagri"),
+  ("syrc", "Syriac"), ("syriac", "Syriac"), ("tagalog", "Tagalog"),
+  ("tagb", "Tagbanwa"), ("tagbanwa", "Tagbanwa"), ("taile", "Tai_Le"),
+  ("taitham", "Tai_Tham"), ("taiviet", "Tai_Viet"), ("takr", "Takri"),
+  ("takri", "Takri"), ("tale", "Tai_Le"), ("talu", "New_Tai_Lue"),
+  ("tamil", "Tamil"), ("taml", "Tamil"), ("tang", "Tangut"),
+  ("tangut", "Tangut"), ("tavt", "Tai_Viet"), ("telu", "Telugu"),
+  ("telugu", "Telugu"), ("tfng", "Tifinagh"), ("tglg", "Tagalog"),
+  ("thaa", "Thaana"), ("thaana", "Thaana"), ("thai", "Thai"),
+  ("tibetan", "Tibetan"), ("tibt", "Tibetan"), ("tifinagh", "Tifinagh"),
+  ("tirh", "Tirhuta"), ("tirhuta", "Tirhuta"), ("ugar", "Ugaritic"),
+  ("ugaritic", "Ugaritic"), ("unknown", "Unknown"), ("vai", "Vai"),
+  ("vaii", "Vai"), ("wara", "Warang_Citi"), ("warangciti", "Warang_Citi"),
+  ("xpeo", "Old_Persian"), ("xsux", "Cuneiform"), ("yi", "Yi"),
+  ("yiii", "Yi"), ("zanabazarsquare", "Zanabazar_Square"),
+  ("zanb", "Zanabazar_Square"), ("zinh", "Inherited"), ("zyyy", "Common"),
+  ("zzzz", "Unknown"), ]),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/script.rs b/third_party/rust/regex-syntax/src/unicode_tables/script.rs
new file mode 100644
index 000000000000..b9b65b5dd956
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/script.rs
@@ -0,0 +1,801 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate script tmp/ucd-11.0.0/ --chars
+//
+// ucd-generate is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
+  ("Adlam", ADLAM), ("Ahom", AHOM),
+  ("Anatolian_Hieroglyphs", ANATOLIAN_HIEROGLYPHS), ("Arabic", ARABIC),
+  ("Armenian", ARMENIAN), ("Avestan", AVESTAN), ("Balinese", BALINESE),
+  ("Bamum", BAMUM), ("Bassa_Vah", BASSA_VAH), ("Batak", BATAK),
+  ("Bengali", BENGALI), ("Bhaiksuki", BHAIKSUKI), ("Bopomofo", BOPOMOFO),
+  ("Brahmi", BRAHMI), ("Braille", BRAILLE), ("Buginese", BUGINESE),
+  ("Buhid", BUHID), ("Canadian_Aboriginal", CANADIAN_ABORIGINAL),
+  ("Carian", CARIAN), ("Caucasian_Albanian", CAUCASIAN_ALBANIAN),
+  ("Chakma", CHAKMA), ("Cham", CHAM), ("Cherokee", CHEROKEE),
+  ("Common", COMMON), ("Coptic", COPTIC), ("Cuneiform", CUNEIFORM),
+  ("Cypriot", CYPRIOT), ("Cyrillic", CYRILLIC), ("Deseret", DESERET),
+  ("Devanagari", DEVANAGARI), ("Dogra", DOGRA), ("Duployan", DUPLOYAN),
+  ("Egyptian_Hieroglyphs", EGYPTIAN_HIEROGLYPHS), ("Elbasan", ELBASAN),
+  ("Ethiopic", ETHIOPIC), ("Georgian", GEORGIAN), ("Glagolitic", GLAGOLITIC),
+  ("Gothic", GOTHIC), ("Grantha", GRANTHA), ("Greek", GREEK),
+  ("Gujarati", GUJARATI), ("Gunjala_Gondi", GUNJALA_GONDI),
+  ("Gurmukhi", GURMUKHI), ("Han", HAN), ("Hangul", HANGUL),
+  ("Hanifi_Rohingya", HANIFI_ROHINGYA), ("Hanunoo", HANUNOO),
+  ("Hatran", HATRAN), ("Hebrew", HEBREW), ("Hiragana", HIRAGANA),
+  ("Imperial_Aramaic", IMPERIAL_ARAMAIC), ("Inherited", INHERITED),
+  ("Inscriptional_Pahlavi", INSCRIPTIONAL_PAHLAVI),
+  ("Inscriptional_Parthian", INSCRIPTIONAL_PARTHIAN), ("Javanese", JAVANESE),
+  ("Kaithi", KAITHI), ("Kannada", KANNADA), ("Katakana", KATAKANA),
+  ("Kayah_Li", KAYAH_LI), ("Kharoshthi", KHAROSHTHI), ("Khmer", KHMER),
+  ("Khojki", KHOJKI), ("Khudawadi", KHUDAWADI), ("Lao", LAO),
+  ("Latin", LATIN), ("Lepcha", LEPCHA), ("Limbu", LIMBU),
+  ("Linear_A", LINEAR_A), ("Linear_B", LINEAR_B), ("Lisu", LISU),
+  ("Lycian", LYCIAN), ("Lydian", LYDIAN), ("Mahajani", MAHAJANI),
+  ("Makasar", MAKASAR), ("Malayalam", MALAYALAM), ("Mandaic", MANDAIC),
+  ("Manichaean", MANICHAEAN), ("Marchen", MARCHEN),
+  ("Masaram_Gondi", MASARAM_GONDI), ("Medefaidrin", MEDEFAIDRIN),
+  ("Meetei_Mayek", MEETEI_MAYEK), ("Mende_Kikakui", MENDE_KIKAKUI),
+  ("Meroitic_Cursive", MEROITIC_CURSIVE),
+  ("Meroitic_Hieroglyphs", MEROITIC_HIEROGLYPHS), ("Miao", MIAO),
+  ("Modi", MODI), ("Mongolian", MONGOLIAN), ("Mro", MRO),
+  ("Multani", MULTANI), ("Myanmar", MYANMAR), ("Nabataean", NABATAEAN),
+  ("New_Tai_Lue", NEW_TAI_LUE), ("Newa", NEWA), ("Nko", NKO),
+  ("Nushu", NUSHU), ("Ogham", OGHAM), ("Ol_Chiki", OL_CHIKI),
+  ("Old_Hungarian", OLD_HUNGARIAN), ("Old_Italic", OLD_ITALIC),
+  ("Old_North_Arabian", OLD_NORTH_ARABIAN), ("Old_Permic", OLD_PERMIC),
+  ("Old_Persian", OLD_PERSIAN), ("Old_Sogdian", OLD_SOGDIAN),
+  ("Old_South_Arabian", OLD_SOUTH_ARABIAN), ("Old_Turkic", OLD_TURKIC),
+  ("Oriya", ORIYA), ("Osage", OSAGE), ("Osmanya", OSMANYA),
+  ("Pahawh_Hmong", PAHAWH_HMONG), ("Palmyrene", PALMYRENE),
+  ("Pau_Cin_Hau", PAU_CIN_HAU), ("Phags_Pa", PHAGS_PA),
+  ("Phoenician", PHOENICIAN), ("Psalter_Pahlavi", PSALTER_PAHLAVI),
+  ("Rejang", REJANG), ("Runic", RUNIC), ("Samaritan", SAMARITAN),
+  ("Saurashtra", SAURASHTRA), ("Sharada", SHARADA), ("Shavian", SHAVIAN),
+  ("Siddham", SIDDHAM), ("SignWriting", SIGNWRITING), ("Sinhala", SINHALA),
+  ("Sogdian", SOGDIAN), ("Sora_Sompeng", SORA_SOMPENG), ("Soyombo", SOYOMBO),
+  ("Sundanese", SUNDANESE), ("Syloti_Nagri", SYLOTI_NAGRI),
+  ("Syriac", SYRIAC), ("Tagalog", TAGALOG), ("Tagbanwa", TAGBANWA),
+  ("Tai_Le", TAI_LE), ("Tai_Tham", TAI_THAM), ("Tai_Viet", TAI_VIET),
+  ("Takri", TAKRI), ("Tamil", TAMIL), ("Tangut", TANGUT), ("Telugu", TELUGU),
+  ("Thaana", THAANA), ("Thai", THAI), ("Tibetan", TIBETAN),
+  ("Tifinagh", TIFINAGH), ("Tirhuta", TIRHUTA), ("Ugaritic", UGARITIC),
+  ("Vai", VAI), ("Warang_Citi", WARANG_CITI), ("Yi", YI),
+  ("Zanabazar_Square", ZANABAZAR_SQUARE),
+];
+
+pub const ADLAM: &'static [(char, char)] = &[
+  ('𞤀', '𞥊'), ('𞥐', '𞥙'), ('𞥞', '𞥟'),
+];
+
+pub const AHOM: &'static [(char, char)] = &[
+  ('𑜀', '\u{1171a}'), ('𑜝', '𑜫'), ('𑜰', '𑜿'),
+];
+
+pub const ANATOLIAN_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𔐀', '𔙆'),
+];
+
+pub const ARABIC: &'static [(char, char)] = &[
+  ('\u{600}', '\u{604}'), ('؆', '؋'), ('؍', 'ؚ'), ('\u{61c}', '\u{61c}'),
+  ('؞', '؞'), ('ؠ', 'ؿ'), ('ف', 'ي'), ('ٖ', 'ٯ'), ('ٱ', 'ۜ'),
+  ('۞', 'ۿ'), ('ݐ', 'ݿ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'),
+  ('\u{8d3}', '࣡'), ('ࣣ', 'ࣿ'), ('ﭐ', '﯁'), ('ﯓ', 'ﴽ'),
+  ('ﵐ', 'ﶏ'), ('ﶒ', 'ﷇ'), ('ﷰ', '﷽'), ('ﹰ', 'ﹴ'),
+  ('ﹶ', 'ﻼ'), ('𐹠', '𐹾'), ('𞸀', '𞸃'), ('𞸅', '𞸟'),
+  ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'),
+  ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'),
+  ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'),
+  ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'),
+  ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'),
+  ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'),
+  ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'),
+  ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('𞻰', '𞻱'),
+];
+
+pub const ARMENIAN: &'static [(char, char)] = &[
+  ('Ա', 'Ֆ'), ('ՙ', '\u{588}'), ('֊', '֊'), ('֍', '֏'), ('ﬓ', 'ﬗ'),
+];
+
+pub const AVESTAN: &'static [(char, char)] = &[
+  ('𐬀', '𐬵'), ('𐬹', '𐬿'),
+];
+
+pub const BALINESE: &'static [(char, char)] = &[
+  ('ᬀ', 'ᭋ'), ('᭐', '᭼'),
+];
+
+pub const BAMUM: &'static [(char, char)] = &[
+  ('ꚠ', '꛷'), ('𖠀', '𖨸'),
+];
+
+pub const BASSA_VAH: &'static [(char, char)] = &[
+  ('𖫐', '𖫭'), ('𖫰', '𖫵'),
+];
+
+pub const BATAK: &'static [(char, char)] = &[
+  ('ᯀ', '᯳'), ('᯼', '᯿'),
+];
+
+pub const BENGALI: &'static [(char, char)] = &[
+  ('ঀ', 'ঃ'), ('অ', 'ঌ'), ('এ', 'ঐ'), ('ও', 'ন'),
+  ('প', 'র'), ('ল', 'ল'), ('শ', 'হ'), ('়', 'ৄ'),
+  ('ে', 'ৈ'), ('ো', 'ৎ'), ('ৗ', 'ৗ'), ('ড়', 'ঢ়'),
+  ('য়', 'ৣ'), ('০', '\u{9fe}'),
+];
+
+pub const BHAIKSUKI: &'static [(char, char)] = &[
+  ('𑰀', '𑰈'), ('𑰊', '𑰶'), ('𑰸', '𑱅'), ('𑱐', '𑱬'),
+];
+
+pub const BOPOMOFO: &'static [(char, char)] = &[
+  ('˪', '˫'), ('ㄅ', '\u{312f}'), ('ㆠ', 'ㆺ'),
+];
+
+pub const BRAHMI: &'static [(char, char)] = &[
+  ('𑀀', '𑁍'), ('𑁒', '𑁯'), ('𑁿', '𑁿'),
+];
+
+pub const BRAILLE: &'static [(char, char)] = &[
+  ('⠀', '⣿'),
+];
+
+pub const BUGINESE: &'static [(char, char)] = &[
+  ('ᨀ', 'ᨛ'), ('᨞', '᨟'),
+];
+
+pub const BUHID: &'static [(char, char)] = &[
+  ('ᝀ', 'ᝓ'),
+];
+
+pub const CANADIAN_ABORIGINAL: &'static [(char, char)] = &[
+  ('᐀', 'ᙿ'), ('ᢰ', 'ᣵ'),
+];
+
+pub const CARIAN: &'static [(char, char)] = &[
+  ('𐊠', '𐋐'),
+];
+
+pub const CAUCASIAN_ALBANIAN: &'static [(char, char)] = &[
+  ('𐔰', '𐕣'), ('𐕯', '𐕯'),
+];
+
+pub const CHAKMA: &'static [(char, char)] = &[
+  ('𑄀', '𑄴'), ('𑄶', '\u{11146}'),
+];
+
+pub const CHAM: &'static [(char, char)] = &[
+  ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'), ('꩐', '꩙'), ('꩜', '꩟'),
+];
+
+pub const CHEROKEE: &'static [(char, char)] = &[
+  ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ꭰ', 'ꮿ'),
+];
+
+pub const COMMON: &'static [(char, char)] = &[
+  ('\u{0}', '@'), ('[', '`'), ('{', '©'), ('«', '¹'), ('»', '¿'),
+  ('×', '×'), ('÷', '÷'), ('ʹ', '˟'), ('˥', '˩'), ('ˬ', '˿'),
+  ('ʹ', 'ʹ'), (';', ';'), ('΅', '΅'), ('·', '·'), ('։', '։'),
+  ('\u{605}', '\u{605}'), ('،', '،'), ('؛', '؛'), ('؟', '؟'),
+  ('ـ', 'ـ'), ('\u{6dd}', '\u{6dd}'), ('\u{8e2}', '\u{8e2}'),
+  ('।', '॥'), ('฿', '฿'), ('࿕', '࿘'), ('჻', '჻'),
+  ('᛫', '᛭'), ('᜵', '᜶'), ('᠂', '᠃'), ('᠅', '᠅'),
+  ('᳓', '᳓'), ('᳡', '᳡'), ('ᳩ', 'ᳬ'), ('ᳮ', 'ᳳ'),
+  ('ᳵ', '᳷'), ('\u{2000}', '\u{200b}'), ('\u{200e}', '\u{2064}'),
+  ('\u{2066}', '⁰'), ('⁴', '⁾'), ('₀', '₎'), ('₠', '₿'),
+  ('℀', '℥'), ('℧', '℩'), ('ℬ', 'ℱ'), ('ℳ', '⅍'),
+  ('⅏', '⅟'), ('↉', '↋'), ('←', '␦'), ('⑀', '⑊'),
+  ('①', '⟿'), ('⤀', '⭳'), ('⭶', '⮕'), ('⮘', '⯈'),
+  ('⯊', '\u{2bfe}'), ('⸀', '\u{2e4e}'), ('⿰', '⿻'),
+  ('\u{3000}', '〄'), ('〆', '〆'), ('〈', '〠'), ('〰', '〷'),
+  ('〼', '〿'), ('゛', '゜'), ('゠', '゠'), ('・', 'ー'),
+  ('㆐', '㆟'), ('㇀', '㇣'), ('㈠', '㉟'), ('㉿', '㋏'),
+  ('㍘', '㏿'), ('䷀', '䷿'), ('꜀', '꜡'), ('ꞈ', '꞊'),
+  ('꠰', '꠹'), ('꤮', '꤮'), ('ꧏ', 'ꧏ'), ('꭛', '꭛'),
+  ('﴾', '﴿'), ('︐', '︙'), ('︰', '﹒'), ('﹔', '﹦'),
+  ('﹨', '﹫'), ('\u{feff}', '\u{feff}'), ('！', '＠'), ('［', '｀'),
+  ('｛', '･'), ('ｰ', 'ｰ'), ('ﾞ', 'ﾟ'), ('￠', '￦'),
+  ('￨', '￮'), ('\u{fff9}', '�'), ('𐄀', '𐄂'), ('𐄇', '𐄳'),
+  ('𐄷', '𐄿'), ('𐆐', '𐆛'), ('𐇐', '𐇼'), ('𐋡', '𐋻'),
+  ('\u{1bca0}', '\u{1bca3}'), ('𝀀', '𝃵'), ('𝄀', '𝄦'),
+  ('𝄩', '𝅦'), ('𝅪', '\u{1d17a}'), ('𝆃', '𝆄'), ('𝆌', '𝆩'),
+  ('𝆮', '𝇨'), ('\u{1d2e0}', '\u{1d2f3}'), ('𝌀', '𝍖'),
+  ('𝍠', '\u{1d378}'), ('𝐀', '𝑔'), ('𝑖', '𝒜'), ('𝒞', '𝒟'),
+  ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'), ('𝒮', '𝒹'),
+  ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'), ('𝔇', '𝔊'),
+  ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'), ('𝔻', '𝔾'),
+  ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'), ('𝕒', '𝚥'),
+  ('𝚨', '𝟋'), ('𝟎', '𝟿'), ('\u{1ec71}', '\u{1ecb4}'),
+  ('🀀', '🀫'), ('🀰', '🂓'), ('🂠', '🂮'), ('🂱', '🂿'),
+  ('🃁', '🃏'), ('🃑', '🃵'), ('🄀', '🄌'), ('🄐', '🅫'),
+  ('🅰', '🆬'), ('🇦', '🇿'), ('🈁', '🈂'), ('🈐', '🈻'),
+  ('🉀', '🉈'), ('🉐', '🉑'), ('🉠', '🉥'), ('🌀', '🛔'),
+  ('🛠', '🛬'), ('🛰', '\u{1f6f9}'), ('🜀', '🝳'),
+  ('🞀', '\u{1f7d8}'), ('🠀', '🠋'), ('🠐', '🡇'), ('🡐', '🡙'),
+  ('🡠', '🢇'), ('🢐', '🢭'), ('🤀', '🤋'), ('🤐', '🤾'),
+  ('🥀', '\u{1f970}'), ('\u{1f973}', '\u{1f976}'),
+  ('\u{1f97a}', '\u{1f97a}'), ('\u{1f97c}', '\u{1f9a2}'),
+  ('\u{1f9b0}', '\u{1f9b9}'), ('🧀', '\u{1f9c2}'), ('🧐', '\u{1f9ff}'),
+  ('\u{1fa60}', '\u{1fa6d}'), ('\u{e0001}', '\u{e0001}'),
+  ('\u{e0020}', '\u{e007f}'),
+];
+
+pub const COPTIC: &'static [(char, char)] = &[
+  ('Ϣ', 'ϯ'), ('Ⲁ', 'ⳳ'), ('⳹', '⳿'),
+];
+
+pub const CUNEIFORM: &'static [(char, char)] = &[
+  ('𒀀', '𒎙'), ('𒐀', '𒑮'), ('𒑰', '𒑴'), ('𒒀', '𒕃'),
+];
+
+pub const CYPRIOT: &'static [(char, char)] = &[
+  ('𐠀', '𐠅'), ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'),
+  ('𐠼', '𐠼'), ('𐠿', '𐠿'),
+];
+
+pub const CYRILLIC: &'static [(char, char)] = &[
+  ('Ѐ', '҄'), ('҇', 'ԯ'), ('ᲀ', 'ᲈ'), ('ᴫ', 'ᴫ'), ('ᵸ', 'ᵸ'),
+  ('ⷠ', 'ⷿ'), ('Ꙁ', 'ꚟ'), ('︮', '︯'),
+];
+
+pub const DESERET: &'static [(char, char)] = &[
+  ('𐐀', '𐑏'),
+];
+
+pub const DEVANAGARI: &'static [(char, char)] = &[
+  ('ऀ', 'ॐ'), ('॓', 'ॣ'), ('०', 'ॿ'), ('꣠', '\u{a8ff}'),
+];
+
+pub const DOGRA: &'static [(char, char)] = &[
+  ('\u{11800}', '\u{1183b}'),
+];
+
+pub const DUPLOYAN: &'static [(char, char)] = &[
+  ('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'),
+  ('𛲜', '𛲟'),
+];
+
+pub const EGYPTIAN_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𓀀', '𓐮'),
+];
+
+pub const ELBASAN: &'static [(char, char)] = &[
+  ('𐔀', '𐔧'),
+];
+
+pub const ETHIOPIC: &'static [(char, char)] = &[
+  ('ሀ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('፝', '፼'), ('ᎀ', '᎙'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'),
+  ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'),
+  ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+];
+
+pub const GEORGIAN: &'static [(char, char)] = &[
+  ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'), ('ა', 'ჺ'),
+  ('ჼ', 'ჿ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+];
+
+pub const GLAGOLITIC: &'static [(char, char)] = &[
+  ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('𞀀', '𞀆'), ('𞀈', '𞀘'),
+  ('𞀛', '𞀡'), ('𞀣', '𞀤'), ('𞀦', '𞀪'),
+];
+
+pub const GOTHIC: &'static [(char, char)] = &[
+  ('𐌰', '𐍊'),
+];
+
+pub const GRANTHA: &'static [(char, char)] = &[
+  ('𑌀', '𑌃'), ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'),
+  ('𑌪', '𑌰'), ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('𑌼', '𑍄'),
+  ('𑍇', '𑍈'), ('𑍋', '𑍍'), ('𑍐', '𑍐'), ('𑍗', '𑍗'),
+  ('𑍝', '𑍣'), ('𑍦', '𑍬'), ('𑍰', '𑍴'),
+];
+
+pub const GREEK: &'static [(char, char)] = &[
+  ('Ͱ', 'ͳ'), ('͵', 'ͷ'), ('ͺ', 'ͽ'), ('Ϳ', 'Ϳ'), ('΄', '΄'),
+  ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'), ('Ύ', 'Ρ'), ('Σ', 'ϡ'),
+  ('ϰ', 'Ͽ'), ('ᴦ', 'ᴪ'), ('ᵝ', 'ᵡ'), ('ᵦ', 'ᵪ'),
+  ('ᶿ', 'ᶿ'), ('ἀ', 'ἕ'), ('Ἐ', 'Ἕ'), ('ἠ', 'ὅ'),
+  ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'), ('Ὓ', 'Ὓ'),
+  ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'), ('ᾶ', 'ῄ'),
+  ('ῆ', 'ΐ'), ('ῖ', 'Ί'), ('῝', '`'), ('ῲ', 'ῴ'),
+  ('ῶ', '῾'), ('Ω', 'Ω'), ('ꭥ', 'ꭥ'), ('𐅀', '𐆎'),
+  ('𐆠', '𐆠'), ('𝈀', '𝉅'),
+];
+
+pub const GUJARATI: &'static [(char, char)] = &[
+  ('ઁ', 'ઃ'), ('અ', 'ઍ'), ('એ', 'ઑ'), ('ઓ', 'ન'),
+  ('પ', 'ર'), ('લ', 'ળ'), ('વ', 'હ'), ('઼', 'ૅ'),
+  ('ે', 'ૉ'), ('ો', '્'), ('ૐ', 'ૐ'), ('ૠ', 'ૣ'),
+  ('૦', '૱'), ('ૹ', '૿'),
+];
+
+pub const GUNJALA_GONDI: &'static [(char, char)] = &[
+  ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d98}'), ('\u{11da0}', '\u{11da9}'),
+];
+
+pub const GURMUKHI: &'static [(char, char)] = &[
+  ('ਁ', 'ਃ'), ('ਅ', 'ਊ'), ('ਏ', 'ਐ'), ('ਓ', 'ਨ'),
+  ('ਪ', 'ਰ'), ('ਲ', 'ਲ਼'), ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'),
+  ('਼', '਼'), ('ਾ', 'ੂ'), ('ੇ', 'ੈ'), ('ੋ', '੍'),
+  ('ੑ', 'ੑ'), ('ਖ਼', 'ੜ'), ('ਫ਼', 'ਫ਼'), ('੦', '\u{a76}'),
+];
+
+pub const HAN: &'static [(char, char)] = &[
+  ('⺀', '⺙'), ('⺛', '⻳'), ('⼀', '⿕'), ('々', '々'),
+  ('〇', '〇'), ('〡', '〩'), ('〸', '〻'), ('㐀', '䶵'),
+  ('一', '\u{9fef}'), ('豈', '舘'), ('並', '龎'), ('𠀀', '𪛖'),
+  ('𪜀', '𫜴'), ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'),
+  ('丽', '𪘀'),
+];
+
+pub const HANGUL: &'static [(char, char)] = &[
+  ('ᄀ', 'ᇿ'), ('〮', '〯'), ('ㄱ', 'ㆎ'), ('㈀', '㈞'),
+  ('㉠', '㉾'), ('ꥠ', 'ꥼ'), ('가', '힣'), ('ힰ', 'ퟆ'),
+  ('ퟋ', 'ퟻ'), ('ﾠ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'),
+  ('ￒ', 'ￗ'), ('ￚ', 'ￜ'),
+];
+
+pub const HANIFI_ROHINGYA: &'static [(char, char)] = &[
+  ('\u{10d00}', '\u{10d27}'), ('\u{10d30}', '\u{10d39}'),
+];
+
+pub const HANUNOO: &'static [(char, char)] = &[
+  ('ᜠ', '᜴'),
+];
+
+pub const HATRAN: &'static [(char, char)] = &[
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐣻', '𐣿'),
+];
+
+pub const HEBREW: &'static [(char, char)] = &[
+  ('֑', 'ׇ'), ('א', 'ת'), ('\u{5ef}', '״'), ('יִ', 'זּ'),
+  ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'), ('ףּ', 'פּ'),
+  ('צּ', 'ﭏ'),
+];
+
+pub const HIRAGANA: &'static [(char, char)] = &[
+  ('ぁ', 'ゖ'), ('ゝ', 'ゟ'), ('𛀁', '𛄞'), ('🈀', '🈀'),
+];
+
+pub const IMPERIAL_ARAMAIC: &'static [(char, char)] = &[
+  ('𐡀', '𐡕'), ('𐡗', '𐡟'),
+];
+
+pub const INHERITED: &'static [(char, char)] = &[
+  ('̀', 'ͯ'), ('҅', '҆'), ('ً', 'ٕ'), ('ٰ', 'ٰ'), ('॑', '॒'),
+  ('᪰', '᪾'), ('᳐', '᳒'), ('᳔', '᳠'), ('᳢', '᳨'),
+  ('᳭', '᳭'), ('᳴', '᳴'), ('᳸', '᳹'), ('᷀', '᷹'),
+  ('᷻', '᷿'), ('\u{200c}', '\u{200d}'), ('⃐', '⃰'), ('〪', '〭'),
+  ('゙', '゚'), ('︀', '️'), ('︠', '︭'), ('𐇽', '𐇽'),
+  ('𐋠', '𐋠'), ('\u{1133b}', '\u{1133b}'), ('𝅧', '𝅩'),
+  ('𝅻', '𝆂'), ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('󠄀', '󠇯'),
+];
+
+pub const INSCRIPTIONAL_PAHLAVI: &'static [(char, char)] = &[
+  ('𐭠', '𐭲'), ('𐭸', '𐭿'),
+];
+
+pub const INSCRIPTIONAL_PARTHIAN: &'static [(char, char)] = &[
+  ('𐭀', '𐭕'), ('𐭘', '𐭟'),
+];
+
+pub const JAVANESE: &'static [(char, char)] = &[
+  ('ꦀ', '꧍'), ('꧐', '꧙'), ('꧞', '꧟'),
+];
+
+pub const KAITHI: &'static [(char, char)] = &[
+  ('𑂀', '𑃁'), ('\u{110cd}', '\u{110cd}'),
+];
+
+pub const KANNADA: &'static [(char, char)] = &[
+  ('ಀ', 'ಌ'), ('ಎ', 'ಐ'), ('ಒ', 'ನ'), ('ಪ', 'ಳ'),
+  ('ವ', 'ಹ'), ('಼', 'ೄ'), ('ೆ', 'ೈ'), ('ೊ', '್'),
+  ('ೕ', 'ೖ'), ('ೞ', 'ೞ'), ('ೠ', 'ೣ'), ('೦', '೯'),
+  ('ೱ', 'ೲ'),
+];
+
+pub const KATAKANA: &'static [(char, char)] = &[
+  ('ァ', 'ヺ'), ('ヽ', 'ヿ'), ('ㇰ', 'ㇿ'), ('㋐', '㋾'),
+  ('㌀', '㍗'), ('ｦ', 'ｯ'), ('ｱ', 'ﾝ'), ('𛀀', '𛀀'),
+];
+
+pub const KAYAH_LI: &'static [(char, char)] = &[
+  ('꤀', '꤭'), ('꤯', '꤯'),
+];
+
+pub const KHAROSHTHI: &'static [(char, char)] = &[
+  ('𐨀', '𐨃'), ('𐨅', '𐨆'), ('𐨌', '𐨓'), ('𐨕', '𐨗'),
+  ('𐨙', '\u{10a35}'), ('𐨸', '𐨺'), ('𐨿', '\u{10a48}'),
+  ('𐩐', '𐩘'),
+];
+
+pub const KHMER: &'static [(char, char)] = &[
+  ('ក', '៝'), ('០', '៩'), ('៰', '៹'), ('᧠', '᧿'),
+];
+
+pub const KHOJKI: &'static [(char, char)] = &[
+  ('𑈀', '𑈑'), ('𑈓', '𑈾'),
+];
+
+pub const KHUDAWADI: &'static [(char, char)] = &[
+  ('𑊰', '𑋪'), ('𑋰', '𑋹'),
+];
+
+pub const LAO: &'static [(char, char)] = &[
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ູ'),
+  ('ົ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('່', 'ໍ'),
+  ('໐', '໙'), ('ໜ', 'ໟ'),
+];
+
+pub const LATIN: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('º', 'º'), ('À', 'Ö'),
+  ('Ø', 'ö'), ('ø', 'ʸ'), ('ˠ', 'ˤ'), ('ᴀ', 'ᴥ'), ('ᴬ', 'ᵜ'),
+  ('ᵢ', 'ᵥ'), ('ᵫ', 'ᵷ'), ('ᵹ', 'ᶾ'), ('Ḁ', 'ỿ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('K', 'Å'),
+  ('Ⅎ', 'Ⅎ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'), ('Ⱡ', 'Ɀ'),
+  ('Ꜣ', 'ꞇ'), ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꟿ'), ('ꬰ', 'ꭚ'),
+  ('ꭜ', 'ꭤ'), ('ﬀ', 'ﬆ'), ('Ａ', 'Ｚ'), ('ａ', 'ｚ'),
+];
+
+pub const LEPCHA: &'static [(char, char)] = &[
+  ('ᰀ', '᰷'), ('᰻', '᱉'), ('ᱍ', 'ᱏ'),
+];
+
+pub const LIMBU: &'static [(char, char)] = &[
+  ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'), ('᥀', '᥀'),
+  ('᥄', '᥏'),
+];
+
+pub const LINEAR_A: &'static [(char, char)] = &[
+  ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+];
+
+pub const LINEAR_B: &'static [(char, char)] = &[
+  ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'),
+  ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'),
+];
+
+pub const LISU: &'static [(char, char)] = &[
+  ('ꓐ', '꓿'),
+];
+
+pub const LYCIAN: &'static [(char, char)] = &[
+  ('𐊀', '𐊜'),
+];
+
+pub const LYDIAN: &'static [(char, char)] = &[
+  ('𐤠', '𐤹'), ('𐤿', '𐤿'),
+];
+
+pub const MAHAJANI: &'static [(char, char)] = &[
+  ('𑅐', '𑅶'),
+];
+
+pub const MAKASAR: &'static [(char, char)] = &[
+  ('\u{11ee0}', '\u{11ef8}'),
+];
+
+pub const MALAYALAM: &'static [(char, char)] = &[
+  ('ഀ', 'ഃ'), ('അ', 'ഌ'), ('എ', 'ഐ'), ('ഒ', 'ൄ'),
+  ('െ', 'ൈ'), ('ൊ', '൏'), ('ൔ', 'ൣ'), ('൦', 'ൿ'),
+];
+
+pub const MANDAIC: &'static [(char, char)] = &[
+  ('ࡀ', '࡛'), ('࡞', '࡞'),
+];
+
+pub const MANICHAEAN: &'static [(char, char)] = &[
+  ('𐫀', '𐫦'), ('𐫫', '𐫶'),
+];
+
+pub const MARCHEN: &'static [(char, char)] = &[
+  ('𑱰', '𑲏'), ('𑲒', '𑲧'), ('𑲩', '𑲶'),
+];
+
+pub const MASARAM_GONDI: &'static [(char, char)] = &[
+  ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵇'), ('𑵐', '𑵙'),
+];
+
+pub const MEDEFAIDRIN: &'static [(char, char)] = &[
+  ('\u{16e40}', '\u{16e9a}'),
+];
+
+pub const MEETEI_MAYEK: &'static [(char, char)] = &[
+  ('ꫠ', '꫶'), ('ꯀ', '꯭'), ('꯰', '꯹'),
+];
+
+pub const MENDE_KIKAKUI: &'static [(char, char)] = &[
+  ('𞠀', '𞣄'), ('𞣇', '𞣖'),
+];
+
+pub const MEROITIC_CURSIVE: &'static [(char, char)] = &[
+  ('𐦠', '𐦷'), ('𐦼', '𐧏'), ('𐧒', '𐧿'),
+];
+
+pub const MEROITIC_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𐦀', '𐦟'),
+];
+
+pub const MIAO: &'static [(char, char)] = &[
+  ('𖼀', '𖽄'), ('𖽐', '𖽾'), ('𖾏', '𖾟'),
+];
+
+pub const MODI: &'static [(char, char)] = &[
+  ('𑘀', '𑙄'), ('𑙐', '𑙙'),
+];
+
+pub const MONGOLIAN: &'static [(char, char)] = &[
+  ('᠀', '᠁'), ('᠄', '᠄'), ('᠆', '\u{180e}'), ('᠐', '᠙'),
+  ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢪ'), ('𑙠', '𑙬'),
+];
+
+pub const MRO: &'static [(char, char)] = &[
+  ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖩮', '𖩯'),
+];
+
+pub const MULTANI: &'static [(char, char)] = &[
+  ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'), ('𑊏', '𑊝'),
+  ('𑊟', '𑊩'),
+];
+
+pub const MYANMAR: &'static [(char, char)] = &[
+  ('က', '႟'), ('ꧠ', 'ꧾ'), ('ꩠ', 'ꩿ'),
+];
+
+pub const NABATAEAN: &'static [(char, char)] = &[
+  ('𐢀', '𐢞'), ('𐢧', '𐢯'),
+];
+
+pub const NEW_TAI_LUE: &'static [(char, char)] = &[
+  ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('᧐', '᧚'), ('᧞', '᧟'),
+];
+
+pub const NEWA: &'static [(char, char)] = &[
+  ('𑐀', '𑑙'), ('𑑛', '𑑛'), ('𑑝', '\u{1145e}'),
+];
+
+pub const NKO: &'static [(char, char)] = &[
+  ('߀', 'ߺ'), ('\u{7fd}', '\u{7ff}'),
+];
+
+pub const NUSHU: &'static [(char, char)] = &[
+  ('𖿡', '𖿡'), ('𛅰', '𛋻'),
+];
+
+pub const OGHAM: &'static [(char, char)] = &[
+  ('\u{1680}', '᚜'),
+];
+
+pub const OL_CHIKI: &'static [(char, char)] = &[
+  ('᱐', '᱿'),
+];
+
+pub const OLD_HUNGARIAN: &'static [(char, char)] = &[
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𐳺', '𐳿'),
+];
+
+pub const OLD_ITALIC: &'static [(char, char)] = &[
+  ('𐌀', '𐌣'), ('𐌭', '𐌯'),
+];
+
+pub const OLD_NORTH_ARABIAN: &'static [(char, char)] = &[
+  ('𐪀', '𐪟'),
+];
+
+pub const OLD_PERMIC: &'static [(char, char)] = &[
+  ('𐍐', '𐍺'),
+];
+
+pub const OLD_PERSIAN: &'static [(char, char)] = &[
+  ('𐎠', '𐏃'), ('𐏈', '𐏕'),
+];
+
+pub const OLD_SOGDIAN: &'static [(char, char)] = &[
+  ('\u{10f00}', '\u{10f27}'),
+];
+
+pub const OLD_SOUTH_ARABIAN: &'static [(char, char)] = &[
+  ('𐩠', '𐩿'),
+];
+
+pub const OLD_TURKIC: &'static [(char, char)] = &[
+  ('𐰀', '𐱈'),
+];
+
+pub const ORIYA: &'static [(char, char)] = &[
+  ('ଁ', 'ଃ'), ('ଅ', 'ଌ'), ('ଏ', 'ଐ'), ('ଓ', 'ନ'),
+  ('ପ', 'ର'), ('ଲ', 'ଳ'), ('ଵ', 'ହ'), ('଼', 'ୄ'),
+  ('େ', 'ୈ'), ('ୋ', '୍'), ('ୖ', 'ୗ'), ('ଡ଼', 'ଢ଼'),
+  ('ୟ', 'ୣ'), ('୦', '୷'),
+];
+
+pub const OSAGE: &'static [(char, char)] = &[
+  ('𐒰', '𐓓'), ('𐓘', '𐓻'),
+];
+
+pub const OSMANYA: &'static [(char, char)] = &[
+  ('𐒀', '𐒝'), ('𐒠', '𐒩'),
+];
+
+pub const PAHAWH_HMONG: &'static [(char, char)] = &[
+  ('𖬀', '𖭅'), ('𖭐', '𖭙'), ('𖭛', '𖭡'), ('𖭣', '𖭷'),
+  ('𖭽', '𖮏'),
+];
+
+pub const PALMYRENE: &'static [(char, char)] = &[
+  ('𐡠', '𐡿'),
+];
+
+pub const PAU_CIN_HAU: &'static [(char, char)] = &[
+  ('𑫀', '𑫸'),
+];
+
+pub const PHAGS_PA: &'static [(char, char)] = &[
+  ('ꡀ', '꡷'),
+];
+
+pub const PHOENICIAN: &'static [(char, char)] = &[
+  ('𐤀', '𐤛'), ('𐤟', '𐤟'),
+];
+
+pub const PSALTER_PAHLAVI: &'static [(char, char)] = &[
+  ('𐮀', '𐮑'), ('𐮙', '𐮜'), ('𐮩', '𐮯'),
+];
+
+pub const REJANG: &'static [(char, char)] = &[
+  ('ꤰ', '꥓'), ('꥟', '꥟'),
+];
+
+pub const RUNIC: &'static [(char, char)] = &[
+  ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+];
+
+pub const SAMARITAN: &'static [(char, char)] = &[
+  ('ࠀ', '࠭'), ('࠰', '࠾'),
+];
+
+pub const SAURASHTRA: &'static [(char, char)] = &[
+  ('ꢀ', 'ꣅ'), ('꣎', '꣙'),
+];
+
+pub const SHARADA: &'static [(char, char)] = &[
+  ('𑆀', '𑇍'), ('𑇐', '𑇟'),
+];
+
+pub const SHAVIAN: &'static [(char, char)] = &[
+  ('𐑐', '𐑿'),
+];
+
+pub const SIDDHAM: &'static [(char, char)] = &[
+  ('𑖀', '𑖵'), ('𑖸', '𑗝'),
+];
+
+pub const SIGNWRITING: &'static [(char, char)] = &[
+  ('𝠀', '𝪋'), ('𝪛', '𝪟'), ('𝪡', '𝪯'),
+];
+
+pub const SINHALA: &'static [(char, char)] = &[
+  ('ං', 'ඃ'), ('අ', 'ඖ'), ('ක', 'න'), ('ඳ', 'ර'),
+  ('ල', 'ල'), ('ව', 'ෆ'), ('්', '්'), ('ා', 'ු'),
+  ('ූ', 'ූ'), ('ෘ', 'ෟ'), ('෦', '෯'), ('ෲ', '෴'),
+  ('𑇡', '𑇴'),
+];
+
+pub const SOGDIAN: &'static [(char, char)] = &[
+  ('\u{10f30}', '\u{10f59}'),
+];
+
+pub const SORA_SOMPENG: &'static [(char, char)] = &[
+  ('𑃐', '𑃨'), ('𑃰', '𑃹'),
+];
+
+pub const SOYOMBO: &'static [(char, char)] = &[
+  ('𑩐', '𑪃'), ('𑪆', '𑪢'),
+];
+
+pub const SUNDANESE: &'static [(char, char)] = &[
+  ('ᮀ', 'ᮿ'), ('᳀', '᳇'),
+];
+
+pub const SYLOTI_NAGRI: &'static [(char, char)] = &[
+  ('ꠀ', '꠫'),
+];
+
+pub const SYRIAC: &'static [(char, char)] = &[
+  ('܀', '܍'), ('\u{70f}', '݊'), ('ݍ', 'ݏ'), ('ࡠ', 'ࡪ'),
+];
+
+pub const TAGALOG: &'static [(char, char)] = &[
+  ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'),
+];
+
+pub const TAGBANWA: &'static [(char, char)] = &[
+  ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ᝲ', 'ᝳ'),
+];
+
+pub const TAI_LE: &'static [(char, char)] = &[
+  ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'),
+];
+
+pub const TAI_THAM: &'static [(char, char)] = &[
+  ('ᨠ', 'ᩞ'), ('᩠', '᩼'), ('᩿', '᪉'), ('᪐', '᪙'),
+  ('᪠', '᪭'),
+];
+
+pub const TAI_VIET: &'static [(char, char)] = &[
+  ('ꪀ', 'ꫂ'), ('ꫛ', '꫟'),
+];
+
+pub const TAKRI: &'static [(char, char)] = &[
+  ('𑚀', '𑚷'), ('𑛀', '𑛉'),
+];
+
+pub const TAMIL: &'static [(char, char)] = &[
+  ('ஂ', 'ஃ'), ('அ', 'ஊ'), ('எ', 'ஐ'), ('ஒ', 'க'),
+  ('ங', 'ச'), ('ஜ', 'ஜ'), ('ஞ', 'ட'), ('ண', 'த'),
+  ('ந', 'ப'), ('ம', 'ஹ'), ('ா', 'ூ'), ('ெ', 'ை'),
+  ('ொ', '்'), ('ௐ', 'ௐ'), ('ௗ', 'ௗ'), ('௦', '௺'),
+];
+
+pub const TANGUT: &'static [(char, char)] = &[
+  ('𖿠', '𖿠'), ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'),
+];
+
+pub const TELUGU: &'static [(char, char)] = &[
+  ('ఀ', 'ఌ'), ('ఎ', 'ఐ'), ('ఒ', 'న'), ('ప', 'హ'),
+  ('ఽ', 'ౄ'), ('ె', 'ై'), ('ొ', '్'), ('ౕ', 'ౖ'),
+  ('ౘ', 'ౚ'), ('ౠ', 'ౣ'), ('౦', '౯'), ('౸', '౿'),
+];
+
+pub const THAANA: &'static [(char, char)] = &[
+  ('ހ', 'ޱ'),
+];
+
+pub const THAI: &'static [(char, char)] = &[
+  ('ก', 'ฺ'), ('เ', '๛'),
+];
+
+pub const TIBETAN: &'static [(char, char)] = &[
+  ('ༀ', 'ཇ'), ('ཉ', 'ཬ'), ('ཱ', 'ྗ'), ('ྙ', 'ྼ'),
+  ('྾', '࿌'), ('࿎', '࿔'), ('࿙', '࿚'),
+];
+
+pub const TIFINAGH: &'static [(char, char)] = &[
+  ('ⴰ', 'ⵧ'), ('ⵯ', '⵰'), ('⵿', '⵿'),
+];
+
+pub const TIRHUTA: &'static [(char, char)] = &[
+  ('𑒀', '𑓇'), ('𑓐', '𑓙'),
+];
+
+pub const UGARITIC: &'static [(char, char)] = &[
+  ('𐎀', '𐎝'), ('𐎟', '𐎟'),
+];
+
+pub const VAI: &'static [(char, char)] = &[
+  ('ꔀ', 'ꘫ'),
+];
+
+pub const WARANG_CITI: &'static [(char, char)] = &[
+  ('𑢠', '𑣲'), ('𑣿', '𑣿'),
+];
+
+pub const YI: &'static [(char, char)] = &[
+  ('ꀀ', 'ꒌ'), ('꒐', '꓆'),
+];
+
+pub const ZANABAZAR_SQUARE: &'static [(char, char)] = &[
+  ('𑨀', '𑩇'),
+];
diff --git a/third_party/rust/regex-syntax/src/unicode_tables/script_extension.rs b/third_party/rust/regex-syntax/src/unicode_tables/script_extension.rs
new file mode 100644
index 000000000000..13f19dc16820
--- /dev/null
+++ b/third_party/rust/regex-syntax/src/unicode_tables/script_extension.rs
@@ -0,0 +1,829 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate script-extension tmp/ucd-11.0.0/ --chars
+//
+// ucd-generate is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
+  ("Adlam", ADLAM), ("Ahom", AHOM),
+  ("Anatolian_Hieroglyphs", ANATOLIAN_HIEROGLYPHS), ("Arabic", ARABIC),
+  ("Armenian", ARMENIAN), ("Avestan", AVESTAN), ("Balinese", BALINESE),
+  ("Bamum", BAMUM), ("Bassa_Vah", BASSA_VAH), ("Batak", BATAK),
+  ("Bengali", BENGALI), ("Bhaiksuki", BHAIKSUKI), ("Bopomofo", BOPOMOFO),
+  ("Brahmi", BRAHMI), ("Braille", BRAILLE), ("Buginese", BUGINESE),
+  ("Buhid", BUHID), ("Canadian_Aboriginal", CANADIAN_ABORIGINAL),
+  ("Carian", CARIAN), ("Caucasian_Albanian", CAUCASIAN_ALBANIAN),
+  ("Chakma", CHAKMA), ("Cham", CHAM), ("Cherokee", CHEROKEE),
+  ("Common", COMMON), ("Coptic", COPTIC), ("Cuneiform", CUNEIFORM),
+  ("Cypriot", CYPRIOT), ("Cyrillic", CYRILLIC), ("Deseret", DESERET),
+  ("Devanagari", DEVANAGARI), ("Dogra", DOGRA), ("Duployan", DUPLOYAN),
+  ("Egyptian_Hieroglyphs", EGYPTIAN_HIEROGLYPHS), ("Elbasan", ELBASAN),
+  ("Ethiopic", ETHIOPIC), ("Georgian", GEORGIAN), ("Glagolitic", GLAGOLITIC),
+  ("Gothic", GOTHIC), ("Grantha", GRANTHA), ("Greek", GREEK),
+  ("Gujarati", GUJARATI), ("Gunjala_Gondi", GUNJALA_GONDI),
+  ("Gurmukhi", GURMUKHI), ("Han", HAN), ("Hangul", HANGUL),
+  ("Hanifi_Rohingya", HANIFI_ROHINGYA), ("Hanunoo", HANUNOO),
+  ("Hatran", HATRAN), ("Hebrew", HEBREW), ("Hiragana", HIRAGANA),
+  ("Imperial_Aramaic", IMPERIAL_ARAMAIC), ("Inherited", INHERITED),
+  ("Inscriptional_Pahlavi", INSCRIPTIONAL_PAHLAVI),
+  ("Inscriptional_Parthian", INSCRIPTIONAL_PARTHIAN), ("Javanese", JAVANESE),
+  ("Kaithi", KAITHI), ("Kannada", KANNADA), ("Katakana", KATAKANA),
+  ("Kayah_Li", KAYAH_LI), ("Kharoshthi", KHAROSHTHI), ("Khmer", KHMER),
+  ("Khojki", KHOJKI), ("Khudawadi", KHUDAWADI), ("Lao", LAO),
+  ("Latin", LATIN), ("Lepcha", LEPCHA), ("Limbu", LIMBU),
+  ("Linear_A", LINEAR_A), ("Linear_B", LINEAR_B), ("Lisu", LISU),
+  ("Lycian", LYCIAN), ("Lydian", LYDIAN), ("Mahajani", MAHAJANI),
+  ("Makasar", MAKASAR), ("Malayalam", MALAYALAM), ("Mandaic", MANDAIC),
+  ("Manichaean", MANICHAEAN), ("Marchen", MARCHEN),
+  ("Masaram_Gondi", MASARAM_GONDI), ("Medefaidrin", MEDEFAIDRIN),
+  ("Meetei_Mayek", MEETEI_MAYEK), ("Mende_Kikakui", MENDE_KIKAKUI),
+  ("Meroitic_Cursive", MEROITIC_CURSIVE),
+  ("Meroitic_Hieroglyphs", MEROITIC_HIEROGLYPHS), ("Miao", MIAO),
+  ("Modi", MODI), ("Mongolian", MONGOLIAN), ("Mro", MRO),
+  ("Multani", MULTANI), ("Myanmar", MYANMAR), ("Nabataean", NABATAEAN),
+  ("New_Tai_Lue", NEW_TAI_LUE), ("Newa", NEWA), ("Nko", NKO),
+  ("Nushu", NUSHU), ("Ogham", OGHAM), ("Ol_Chiki", OL_CHIKI),
+  ("Old_Hungarian", OLD_HUNGARIAN), ("Old_Italic", OLD_ITALIC),
+  ("Old_North_Arabian", OLD_NORTH_ARABIAN), ("Old_Permic", OLD_PERMIC),
+  ("Old_Persian", OLD_PERSIAN), ("Old_Sogdian", OLD_SOGDIAN),
+  ("Old_South_Arabian", OLD_SOUTH_ARABIAN), ("Old_Turkic", OLD_TURKIC),
+  ("Oriya", ORIYA), ("Osage", OSAGE), ("Osmanya", OSMANYA),
+  ("Pahawh_Hmong", PAHAWH_HMONG), ("Palmyrene", PALMYRENE),
+  ("Pau_Cin_Hau", PAU_CIN_HAU), ("Phags_Pa", PHAGS_PA),
+  ("Phoenician", PHOENICIAN), ("Psalter_Pahlavi", PSALTER_PAHLAVI),
+  ("Rejang", REJANG), ("Runic", RUNIC), ("Samaritan", SAMARITAN),
+  ("Saurashtra", SAURASHTRA), ("Sharada", SHARADA), ("Shavian", SHAVIAN),
+  ("Siddham", SIDDHAM), ("SignWriting", SIGNWRITING), ("Sinhala", SINHALA),
+  ("Sogdian", SOGDIAN), ("Sora_Sompeng", SORA_SOMPENG), ("Soyombo", SOYOMBO),
+  ("Sundanese", SUNDANESE), ("Syloti_Nagri", SYLOTI_NAGRI),
+  ("Syriac", SYRIAC), ("Tagalog", TAGALOG), ("Tagbanwa", TAGBANWA),
+  ("Tai_Le", TAI_LE), ("Tai_Tham", TAI_THAM), ("Tai_Viet", TAI_VIET),
+  ("Takri", TAKRI), ("Tamil", TAMIL), ("Tangut", TANGUT), ("Telugu", TELUGU),
+  ("Thaana", THAANA), ("Thai", THAI), ("Tibetan", TIBETAN),
+  ("Tifinagh", TIFINAGH), ("Tirhuta", TIRHUTA), ("Ugaritic", UGARITIC),
+  ("Vai", VAI), ("Warang_Citi", WARANG_CITI), ("Yi", YI),
+  ("Zanabazar_Square", ZANABAZAR_SQUARE),
+];
+
+pub const ADLAM: &'static [(char, char)] = &[
+  ('ـ', 'ـ'), ('𞤀', '𞥊'), ('𞥐', '𞥙'), ('𞥞', '𞥟'),
+];
+
+pub const AHOM: &'static [(char, char)] = &[
+  ('𑜀', '\u{1171a}'), ('𑜝', '𑜫'), ('𑜰', '𑜿'),
+];
+
+pub const ANATOLIAN_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𔐀', '𔙆'),
+];
+
+pub const ARABIC: &'static [(char, char)] = &[
+  ('\u{600}', '\u{604}'), ('؆', '\u{61c}'), ('؞', 'ۜ'), ('۞', 'ۿ'),
+  ('ݐ', 'ݿ'), ('ࢠ', 'ࢴ'), ('ࢶ', 'ࢽ'), ('\u{8d3}', '࣡'),
+  ('ࣣ', 'ࣿ'), ('ﭐ', '﯁'), ('ﯓ', 'ﴽ'), ('ﵐ', 'ﶏ'),
+  ('ﶒ', 'ﷇ'), ('ﷰ', '﷽'), ('ﹰ', 'ﹴ'), ('ﹶ', 'ﻼ'),
+  ('𐋠', '𐋻'), ('𐹠', '𐹾'), ('𞸀', '𞸃'), ('𞸅', '𞸟'),
+  ('𞸡', '𞸢'), ('𞸤', '𞸤'), ('𞸧', '𞸧'), ('𞸩', '𞸲'),
+  ('𞸴', '𞸷'), ('𞸹', '𞸹'), ('𞸻', '𞸻'), ('𞹂', '𞹂'),
+  ('𞹇', '𞹇'), ('𞹉', '𞹉'), ('𞹋', '𞹋'), ('𞹍', '𞹏'),
+  ('𞹑', '𞹒'), ('𞹔', '𞹔'), ('𞹗', '𞹗'), ('𞹙', '𞹙'),
+  ('𞹛', '𞹛'), ('𞹝', '𞹝'), ('𞹟', '𞹟'), ('𞹡', '𞹢'),
+  ('𞹤', '𞹤'), ('𞹧', '𞹪'), ('𞹬', '𞹲'), ('𞹴', '𞹷'),
+  ('𞹹', '𞹼'), ('𞹾', '𞹾'), ('𞺀', '𞺉'), ('𞺋', '𞺛'),
+  ('𞺡', '𞺣'), ('𞺥', '𞺩'), ('𞺫', '𞺻'), ('𞻰', '𞻱'),
+];
+
+pub const ARMENIAN: &'static [(char, char)] = &[
+  ('Ա', 'Ֆ'), ('ՙ', '֊'), ('֍', '֏'), ('ﬓ', 'ﬗ'),
+];
+
+pub const AVESTAN: &'static [(char, char)] = &[
+  ('𐬀', '𐬵'), ('𐬹', '𐬿'),
+];
+
+pub const BALINESE: &'static [(char, char)] = &[
+  ('ᬀ', 'ᭋ'), ('᭐', '᭼'),
+];
+
+pub const BAMUM: &'static [(char, char)] = &[
+  ('ꚠ', '꛷'), ('𖠀', '𖨸'),
+];
+
+pub const BASSA_VAH: &'static [(char, char)] = &[
+  ('𖫐', '𖫭'), ('𖫰', '𖫵'),
+];
+
+pub const BATAK: &'static [(char, char)] = &[
+  ('ᯀ', '᯳'), ('᯼', '᯿'),
+];
+
+pub const BENGALI: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ঀ', 'ঃ'), ('অ', 'ঌ'),
+  ('এ', 'ঐ'), ('ও', 'ন'), ('প', 'র'), ('ল', 'ল'),
+  ('শ', 'হ'), ('়', 'ৄ'), ('ে', 'ৈ'), ('ো', 'ৎ'),
+  ('ৗ', 'ৗ'), ('ড়', 'ঢ়'), ('য়', 'ৣ'), ('০', '\u{9fe}'),
+  ('᳐', '᳐'), ('᳒', '᳒'), ('᳕', '᳖'), ('᳘', '᳘'),
+  ('᳡', '᳡'), ('ᳪ', 'ᳪ'), ('᳭', '᳭'), ('ᳵ', '᳷'),
+  ('꣱', '꣱'),
+];
+
+pub const BHAIKSUKI: &'static [(char, char)] = &[
+  ('𑰀', '𑰈'), ('𑰊', '𑰶'), ('𑰸', '𑱅'), ('𑱐', '𑱬'),
+];
+
+pub const BOPOMOFO: &'static [(char, char)] = &[
+  ('˪', '˫'), ('、', '〃'), ('〈', '】'), ('〓', '〟'),
+  ('〪', '〭'), ('〰', '〰'), ('〷', '〷'), ('・', '・'),
+  ('ㄅ', '\u{312f}'), ('ㆠ', 'ㆺ'), ('﹅', '﹆'), ('｡', '･'),
+];
+
+pub const BRAHMI: &'static [(char, char)] = &[
+  ('𑀀', '𑁍'), ('𑁒', '𑁯'), ('𑁿', '𑁿'),
+];
+
+pub const BRAILLE: &'static [(char, char)] = &[
+  ('⠀', '⣿'),
+];
+
+pub const BUGINESE: &'static [(char, char)] = &[
+  ('ᨀ', 'ᨛ'), ('᨞', '᨟'), ('ꧏ', 'ꧏ'),
+];
+
+pub const BUHID: &'static [(char, char)] = &[
+  ('᜵', '᜶'), ('ᝀ', 'ᝓ'),
+];
+
+pub const CANADIAN_ABORIGINAL: &'static [(char, char)] = &[
+  ('᐀', 'ᙿ'), ('ᢰ', 'ᣵ'),
+];
+
+pub const CARIAN: &'static [(char, char)] = &[
+  ('𐊠', '𐋐'),
+];
+
+pub const CAUCASIAN_ALBANIAN: &'static [(char, char)] = &[
+  ('𐔰', '𐕣'), ('𐕯', '𐕯'),
+];
+
+pub const CHAKMA: &'static [(char, char)] = &[
+  ('০', '৯'), ('၀', '၉'), ('𑄀', '𑄴'), ('𑄶', '\u{11146}'),
+];
+
+pub const CHAM: &'static [(char, char)] = &[
+  ('ꨀ', 'ꨶ'), ('ꩀ', 'ꩍ'), ('꩐', '꩙'), ('꩜', '꩟'),
+];
+
+pub const CHEROKEE: &'static [(char, char)] = &[
+  ('Ꭰ', 'Ᏽ'), ('ᏸ', 'ᏽ'), ('ꭰ', 'ꮿ'),
+];
+
+pub const COMMON: &'static [(char, char)] = &[
+  ('\u{0}', '@'), ('[', '`'), ('{', '©'), ('«', '¹'), ('»', '¿'),
+  ('×', '×'), ('÷', '÷'), ('ʹ', '˟'), ('˥', '˩'), ('ˬ', '˿'),
+  ('ʹ', 'ʹ'), (';', ';'), ('΅', '΅'), ('·', '·'),
+  ('\u{605}', '\u{605}'), ('\u{6dd}', '\u{6dd}'), ('\u{8e2}', '\u{8e2}'),
+  ('฿', '฿'), ('࿕', '࿘'), ('᛫', '᛭'), ('\u{2000}', '\u{200b}'),
+  ('\u{200e}', '\u{2064}'), ('\u{2066}', '⁰'), ('⁴', '⁾'),
+  ('₀', '₎'), ('₠', '₿'), ('℀', '℥'), ('℧', '℩'),
+  ('ℬ', 'ℱ'), ('ℳ', '⅍'), ('⅏', '⅟'), ('↉', '↋'),
+  ('←', '␦'), ('⑀', '⑊'), ('①', '⟿'), ('⤀', '⭳'),
+  ('⭶', '⮕'), ('⮘', '⯈'), ('⯊', '\u{2bfe}'), ('⸀', '⹂'),
+  ('⹄', '\u{2e4e}'), ('⿰', '⿻'), ('\u{3000}', '\u{3000}'),
+  ('〄', '〄'), ('〒', '〒'), ('〠', '〠'), ('〶', '〶'),
+  ('㉈', '㉟'), ('㉿', '㉿'), ('㊱', '㊿'), ('㋌', '㋏'),
+  ('㍱', '㍺'), ('㎀', '㏟'), ('㏿', '㏿'), ('䷀', '䷿'),
+  ('꜀', '꜡'), ('ꞈ', '꞊'), ('꭛', '꭛'), ('﴾', '﴿'),
+  ('︐', '︙'), ('︰', '﹄'), ('﹇', '﹒'), ('﹔', '﹦'),
+  ('﹨', '﹫'), ('\u{feff}', '\u{feff}'), ('！', '＠'), ('［', '｀'),
+  ('｛', '｠'), ('￠', '￦'), ('￨', '￮'), ('\u{fff9}', '�'),
+  ('𐆐', '𐆛'), ('𐇐', '𐇼'), ('𝀀', '𝃵'), ('𝄀', '𝄦'),
+  ('𝄩', '𝅦'), ('𝅪', '\u{1d17a}'), ('𝆃', '𝆄'), ('𝆌', '𝆩'),
+  ('𝆮', '𝇨'), ('\u{1d2e0}', '\u{1d2f3}'), ('𝌀', '𝍖'),
+  ('\u{1d372}', '\u{1d378}'), ('𝐀', '𝑔'), ('𝑖', '𝒜'),
+  ('𝒞', '𝒟'), ('𝒢', '𝒢'), ('𝒥', '𝒦'), ('𝒩', '𝒬'),
+  ('𝒮', '𝒹'), ('𝒻', '𝒻'), ('𝒽', '𝓃'), ('𝓅', '𝔅'),
+  ('𝔇', '𝔊'), ('𝔍', '𝔔'), ('𝔖', '𝔜'), ('𝔞', '𝔹'),
+  ('𝔻', '𝔾'), ('𝕀', '𝕄'), ('𝕆', '𝕆'), ('𝕊', '𝕐'),
+  ('𝕒', '𝚥'), ('𝚨', '𝟋'), ('𝟎', '𝟿'),
+  ('\u{1ec71}', '\u{1ecb4}'), ('🀀', '🀫'), ('🀰', '🂓'),
+  ('🂠', '🂮'), ('🂱', '🂿'), ('🃁', '🃏'), ('🃑', '🃵'),
+  ('🄀', '🄌'), ('🄐', '🅫'), ('🅰', '🆬'), ('🇦', '🇿'),
+  ('🈁', '🈂'), ('🈐', '🈻'), ('🉀', '🉈'), ('🉠', '🉥'),
+  ('🌀', '🛔'), ('🛠', '🛬'), ('🛰', '\u{1f6f9}'), ('🜀', '🝳'),
+  ('🞀', '\u{1f7d8}'), ('🠀', '🠋'), ('🠐', '🡇'), ('🡐', '🡙'),
+  ('🡠', '🢇'), ('🢐', '🢭'), ('🤀', '🤋'), ('🤐', '🤾'),
+  ('🥀', '\u{1f970}'), ('\u{1f973}', '\u{1f976}'),
+  ('\u{1f97a}', '\u{1f97a}'), ('\u{1f97c}', '\u{1f9a2}'),
+  ('\u{1f9b0}', '\u{1f9b9}'), ('🧀', '\u{1f9c2}'), ('🧐', '\u{1f9ff}'),
+  ('\u{1fa60}', '\u{1fa6d}'), ('\u{e0001}', '\u{e0001}'),
+  ('\u{e0020}', '\u{e007f}'),
+];
+
+pub const COPTIC: &'static [(char, char)] = &[
+  ('Ϣ', 'ϯ'), ('Ⲁ', 'ⳳ'), ('⳹', '⳿'), ('𐋠', '𐋻'),
+];
+
+pub const CUNEIFORM: &'static [(char, char)] = &[
+  ('𒀀', '𒎙'), ('𒐀', '𒑮'), ('𒑰', '𒑴'), ('𒒀', '𒕃'),
+];
+
+pub const CYPRIOT: &'static [(char, char)] = &[
+  ('𐄀', '𐄂'), ('𐄇', '𐄳'), ('𐄷', '𐄿'), ('𐠀', '𐠅'),
+  ('𐠈', '𐠈'), ('𐠊', '𐠵'), ('𐠷', '𐠸'), ('𐠼', '𐠼'),
+  ('𐠿', '𐠿'),
+];
+
+pub const CYRILLIC: &'static [(char, char)] = &[
+  ('Ѐ', 'ԯ'), ('ᲀ', 'ᲈ'), ('ᴫ', 'ᴫ'), ('ᵸ', 'ᵸ'),
+  ('ⷠ', 'ⷿ'), ('⹃', '⹃'), ('Ꙁ', 'ꚟ'), ('︮', '︯'),
+];
+
+pub const DESERET: &'static [(char, char)] = &[
+  ('𐐀', '𐑏'),
+];
+
+pub const DEVANAGARI: &'static [(char, char)] = &[
+  ('ऀ', 'ॿ'), ('᳐', 'ᳶ'), ('᳸', '᳹'), ('⃰', '⃰'),
+  ('꠰', '꠹'), ('꣠', '\u{a8ff}'),
+];
+
+pub const DOGRA: &'static [(char, char)] = &[
+  ('।', '९'), ('꠰', '꠹'), ('\u{11800}', '\u{1183b}'),
+];
+
+pub const DUPLOYAN: &'static [(char, char)] = &[
+  ('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'),
+  ('𛲜', '\u{1bca3}'),
+];
+
+pub const EGYPTIAN_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𓀀', '𓐮'),
+];
+
+pub const ELBASAN: &'static [(char, char)] = &[
+  ('𐔀', '𐔧'),
+];
+
+pub const ETHIOPIC: &'static [(char, char)] = &[
+  ('ሀ', 'ቈ'), ('ቊ', 'ቍ'), ('ቐ', 'ቖ'), ('ቘ', 'ቘ'),
+  ('ቚ', 'ቝ'), ('በ', 'ኈ'), ('ኊ', 'ኍ'), ('ነ', 'ኰ'),
+  ('ኲ', 'ኵ'), ('ኸ', 'ኾ'), ('ዀ', 'ዀ'), ('ዂ', 'ዅ'),
+  ('ወ', 'ዖ'), ('ዘ', 'ጐ'), ('ጒ', 'ጕ'), ('ጘ', 'ፚ'),
+  ('፝', '፼'), ('ᎀ', '᎙'), ('ⶀ', 'ⶖ'), ('ⶠ', 'ⶦ'),
+  ('ⶨ', 'ⶮ'), ('ⶰ', 'ⶶ'), ('ⶸ', 'ⶾ'), ('ⷀ', 'ⷆ'),
+  ('ⷈ', 'ⷎ'), ('ⷐ', 'ⷖ'), ('ⷘ', 'ⷞ'), ('ꬁ', 'ꬆ'),
+  ('ꬉ', 'ꬎ'), ('ꬑ', 'ꬖ'), ('ꬠ', 'ꬦ'), ('ꬨ', 'ꬮ'),
+];
+
+pub const GEORGIAN: &'static [(char, char)] = &[
+  ('։', '։'), ('Ⴀ', 'Ⴥ'), ('Ⴧ', 'Ⴧ'), ('Ⴭ', 'Ⴭ'),
+  ('ა', 'ჿ'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'),
+  ('ⴀ', 'ⴥ'), ('ⴧ', 'ⴧ'), ('ⴭ', 'ⴭ'),
+];
+
+pub const GLAGOLITIC: &'static [(char, char)] = &[
+  ('҄', '҄'), ('҇', '҇'), ('Ⰰ', 'Ⱞ'), ('ⰰ', 'ⱞ'), ('⹃', '⹃'),
+  ('꙯', '꙯'), ('𞀀', '𞀆'), ('𞀈', '𞀘'), ('𞀛', '𞀡'),
+  ('𞀣', '𞀤'), ('𞀦', '𞀪'),
+];
+
+pub const GOTHIC: &'static [(char, char)] = &[
+  ('𐌰', '𐍊'),
+];
+
+pub const GRANTHA: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('௦', '௳'), ('᳐', '᳐'),
+  ('᳒', '᳓'), ('ᳲ', '᳴'), ('᳸', '᳹'), ('⃰', '⃰'),
+  ('𑌀', '𑌃'), ('𑌅', '𑌌'), ('𑌏', '𑌐'), ('𑌓', '𑌨'),
+  ('𑌪', '𑌰'), ('𑌲', '𑌳'), ('𑌵', '𑌹'), ('\u{1133b}', '𑍄'),
+  ('𑍇', '𑍈'), ('𑍋', '𑍍'), ('𑍐', '𑍐'), ('𑍗', '𑍗'),
+  ('𑍝', '𑍣'), ('𑍦', '𑍬'), ('𑍰', '𑍴'),
+];
+
+pub const GREEK: &'static [(char, char)] = &[
+  ('͂', '͂'), ('ͅ', 'ͅ'), ('Ͱ', 'ͳ'), ('͵', 'ͷ'), ('ͺ', 'ͽ'),
+  ('Ϳ', 'Ϳ'), ('΄', '΄'), ('Ά', 'Ά'), ('Έ', 'Ί'), ('Ό', 'Ό'),
+  ('Ύ', 'Ρ'), ('Σ', 'ϡ'), ('ϰ', 'Ͽ'), ('ᴦ', 'ᴪ'), ('ᵝ', 'ᵡ'),
+  ('ᵦ', 'ᵪ'), ('ᶿ', '᷁'), ('ἀ', 'ἕ'), ('Ἐ', 'Ἕ'),
+  ('ἠ', 'ὅ'), ('Ὀ', 'Ὅ'), ('ὐ', 'ὗ'), ('Ὑ', 'Ὑ'),
+  ('Ὓ', 'Ὓ'), ('Ὕ', 'Ὕ'), ('Ὗ', 'ώ'), ('ᾀ', 'ᾴ'),
+  ('ᾶ', 'ῄ'), ('ῆ', 'ΐ'), ('ῖ', 'Ί'), ('῝', '`'),
+  ('ῲ', 'ῴ'), ('ῶ', '῾'), ('Ω', 'Ω'), ('ꭥ', 'ꭥ'),
+  ('𐅀', '𐆎'), ('𐆠', '𐆠'), ('𝈀', '𝉅'),
+];
+
+pub const GUJARATI: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ઁ', 'ઃ'), ('અ', 'ઍ'),
+  ('એ', 'ઑ'), ('ઓ', 'ન'), ('પ', 'ર'), ('લ', 'ળ'),
+  ('વ', 'હ'), ('઼', 'ૅ'), ('ે', 'ૉ'), ('ો', '્'),
+  ('ૐ', 'ૐ'), ('ૠ', 'ૣ'), ('૦', '૱'), ('ૹ', '૿'),
+  ('꠰', '꠹'),
+];
+
+pub const GUNJALA_GONDI: &'static [(char, char)] = &[
+  ('।', '॥'), ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'),
+  ('\u{11d6a}', '\u{11d8e}'), ('\u{11d90}', '\u{11d91}'),
+  ('\u{11d93}', '\u{11d98}'), ('\u{11da0}', '\u{11da9}'),
+];
+
+pub const GURMUKHI: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ਁ', 'ਃ'), ('ਅ', 'ਊ'),
+  ('ਏ', 'ਐ'), ('ਓ', 'ਨ'), ('ਪ', 'ਰ'), ('ਲ', 'ਲ਼'),
+  ('ਵ', 'ਸ਼'), ('ਸ', 'ਹ'), ('਼', '਼'), ('ਾ', 'ੂ'),
+  ('ੇ', 'ੈ'), ('ੋ', '੍'), ('ੑ', 'ੑ'), ('ਖ਼', 'ੜ'),
+  ('ਫ਼', 'ਫ਼'), ('੦', '\u{a76}'), ('꠰', '꠹'),
+];
+
+pub const HAN: &'static [(char, char)] = &[
+  ('⺀', '⺙'), ('⺛', '⻳'), ('⼀', '⿕'), ('、', '〃'),
+  ('々', '】'), ('〓', '〟'), ('〡', '〭'), ('〰', '〰'),
+  ('〷', '〿'), ('・', '・'), ('㆐', '㆟'), ('㇀', '㇣'),
+  ('㈠', '㉇'), ('㊀', '㊰'), ('㋀', '㋋'), ('㍘', '㍰'),
+  ('㍻', '㍿'), ('㏠', '㏾'), ('㐀', '䶵'), ('一', '\u{9fef}'),
+  ('豈', '舘'), ('並', '龎'), ('﹅', '﹆'), ('｡', '･'),
+  ('𝍠', '𝍱'), ('🉐', '🉑'), ('𠀀', '𪛖'), ('𪜀', '𫜴'),
+  ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'), ('丽', '𪘀'),
+];
+
+pub const HANGUL: &'static [(char, char)] = &[
+  ('ᄀ', 'ᇿ'), ('、', '〃'), ('〈', '】'), ('〓', '〟'),
+  ('〮', '〰'), ('〷', '〷'), ('・', '・'), ('ㄱ', 'ㆎ'),
+  ('㈀', '㈞'), ('㉠', '㉾'), ('ꥠ', 'ꥼ'), ('가', '힣'),
+  ('ힰ', 'ퟆ'), ('ퟋ', 'ퟻ'), ('﹅', '﹆'), ('｡', '･'),
+  ('ﾠ', 'ﾾ'), ('ￂ', 'ￇ'), ('ￊ', 'ￏ'), ('ￒ', 'ￗ'),
+  ('ￚ', 'ￜ'),
+];
+
+pub const HANIFI_ROHINGYA: &'static [(char, char)] = &[
+  ('،', '،'), ('؛', '؛'), ('؟', '؟'), ('ـ', 'ـ'), ('۔', '۔'),
+  ('\u{10d00}', '\u{10d27}'), ('\u{10d30}', '\u{10d39}'),
+];
+
+pub const HANUNOO: &'static [(char, char)] = &[
+  ('ᜠ', '᜶'),
+];
+
+pub const HATRAN: &'static [(char, char)] = &[
+  ('𐣠', '𐣲'), ('𐣴', '𐣵'), ('𐣻', '𐣿'),
+];
+
+pub const HEBREW: &'static [(char, char)] = &[
+  ('֑', 'ׇ'), ('א', 'ת'), ('\u{5ef}', '״'), ('יִ', 'זּ'),
+  ('טּ', 'לּ'), ('מּ', 'מּ'), ('נּ', 'סּ'), ('ףּ', 'פּ'),
+  ('צּ', 'ﭏ'),
+];
+
+pub const HIRAGANA: &'static [(char, char)] = &[
+  ('、', '〃'), ('〈', '】'), ('〓', '〟'), ('〰', '〵'),
+  ('〷', '〷'), ('〼', '〽'), ('ぁ', 'ゖ'), ('゙', '゠'),
+  ('・', 'ー'), ('﹅', '﹆'), ('｡', '･'), ('ｰ', 'ｰ'),
+  ('ﾞ', 'ﾟ'), ('𛀁', '𛄞'), ('🈀', '🈀'),
+];
+
+pub const IMPERIAL_ARAMAIC: &'static [(char, char)] = &[
+  ('𐡀', '𐡕'), ('𐡗', '𐡟'),
+];
+
+pub const INHERITED: &'static [(char, char)] = &[
+  ('̀', '́'), ('̓', '̈́'), ('͆', '͢'), ('᪰', '᪾'), ('᷂', '᷹'),
+  ('᷻', '᷿'), ('\u{200c}', '\u{200d}'), ('⃐', '⃯'), ('︀', '️'),
+  ('︠', '︭'), ('𐇽', '𐇽'), ('𝅧', '𝅩'), ('𝅻', '𝆂'),
+  ('𝆅', '𝆋'), ('𝆪', '𝆭'), ('󠄀', '󠇯'),
+];
+
+pub const INSCRIPTIONAL_PAHLAVI: &'static [(char, char)] = &[
+  ('𐭠', '𐭲'), ('𐭸', '𐭿'),
+];
+
+pub const INSCRIPTIONAL_PARTHIAN: &'static [(char, char)] = &[
+  ('𐭀', '𐭕'), ('𐭘', '𐭟'),
+];
+
+pub const JAVANESE: &'static [(char, char)] = &[
+  ('ꦀ', '꧍'), ('ꧏ', '꧙'), ('꧞', '꧟'),
+];
+
+pub const KAITHI: &'static [(char, char)] = &[
+  ('०', '९'), ('꠰', '꠹'), ('𑂀', '𑃁'),
+  ('\u{110cd}', '\u{110cd}'),
+];
+
+pub const KANNADA: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ಀ', 'ಌ'), ('ಎ', 'ಐ'),
+  ('ಒ', 'ನ'), ('ಪ', 'ಳ'), ('ವ', 'ಹ'), ('಼', 'ೄ'),
+  ('ೆ', 'ೈ'), ('ೊ', '್'), ('ೕ', 'ೖ'), ('ೞ', 'ೞ'),
+  ('ೠ', 'ೣ'), ('೦', '೯'), ('ೱ', 'ೲ'), ('᳐', '᳐'),
+  ('᳒', '᳒'), ('᳚', '᳚'), ('᳴', '᳴'), ('꠰', '꠵'),
+];
+
+pub const KATAKANA: &'static [(char, char)] = &[
+  ('、', '〃'), ('〈', '】'), ('〓', '〟'), ('〰', '〵'),
+  ('〷', '〷'), ('〼', '〽'), ('゙', '゜'), ('゠', 'ヿ'),
+  ('ㇰ', 'ㇿ'), ('㋐', '㋾'), ('㌀', '㍗'), ('﹅', '﹆'),
+  ('｡', 'ﾟ'), ('𛀀', '𛀀'),
+];
+
+pub const KAYAH_LI: &'static [(char, char)] = &[
+  ('꤀', '꤯'),
+];
+
+pub const KHAROSHTHI: &'static [(char, char)] = &[
+  ('𐨀', '𐨃'), ('𐨅', '𐨆'), ('𐨌', '𐨓'), ('𐨕', '𐨗'),
+  ('𐨙', '\u{10a35}'), ('𐨸', '𐨺'), ('𐨿', '\u{10a48}'),
+  ('𐩐', '𐩘'),
+];
+
+pub const KHMER: &'static [(char, char)] = &[
+  ('ក', '៝'), ('០', '៩'), ('៰', '៹'), ('᧠', '᧿'),
+];
+
+pub const KHOJKI: &'static [(char, char)] = &[
+  ('૦', '૯'), ('꠰', '꠹'), ('𑈀', '𑈑'), ('𑈓', '𑈾'),
+];
+
+pub const KHUDAWADI: &'static [(char, char)] = &[
+  ('।', '॥'), ('꠰', '꠹'), ('𑊰', '𑋪'), ('𑋰', '𑋹'),
+];
+
+pub const LAO: &'static [(char, char)] = &[
+  ('ກ', 'ຂ'), ('ຄ', 'ຄ'), ('ງ', 'ຈ'), ('ຊ', 'ຊ'),
+  ('ຍ', 'ຍ'), ('ດ', 'ທ'), ('ນ', 'ຟ'), ('ມ', 'ຣ'),
+  ('ລ', 'ລ'), ('ວ', 'ວ'), ('ສ', 'ຫ'), ('ອ', 'ູ'),
+  ('ົ', 'ຽ'), ('ເ', 'ໄ'), ('ໆ', 'ໆ'), ('່', 'ໍ'),
+  ('໐', '໙'), ('ໜ', 'ໟ'),
+];
+
+pub const LATIN: &'static [(char, char)] = &[
+  ('A', 'Z'), ('a', 'z'), ('ª', 'ª'), ('º', 'º'), ('À', 'Ö'),
+  ('Ø', 'ö'), ('ø', 'ʸ'), ('ˠ', 'ˤ'), ('ͣ', 'ͯ'), ('҅', '҆'),
+  ('॑', '॒'), ('჻', '჻'), ('ᴀ', 'ᴥ'), ('ᴬ', 'ᵜ'),
+  ('ᵢ', 'ᵥ'), ('ᵫ', 'ᵷ'), ('ᵹ', 'ᶾ'), ('Ḁ', 'ỿ'),
+  ('ⁱ', 'ⁱ'), ('ⁿ', 'ⁿ'), ('ₐ', 'ₜ'), ('⃰', '⃰'),
+  ('K', 'Å'), ('Ⅎ', 'Ⅎ'), ('ⅎ', 'ⅎ'), ('Ⅰ', 'ↈ'),
+  ('Ⱡ', 'Ɀ'), ('Ꜣ', 'ꞇ'), ('Ꞌ', '\u{a7b9}'), ('ꟷ', 'ꟿ'),
+  ('꤮', '꤮'), ('ꬰ', 'ꭚ'), ('ꭜ', 'ꭤ'), ('ﬀ', 'ﬆ'),
+  ('Ａ', 'Ｚ'), ('ａ', 'ｚ'),
+];
+
+pub const LEPCHA: &'static [(char, char)] = &[
+  ('ᰀ', '᰷'), ('᰻', '᱉'), ('ᱍ', 'ᱏ'),
+];
+
+pub const LIMBU: &'static [(char, char)] = &[
+  ('॥', '॥'), ('ᤀ', 'ᤞ'), ('ᤠ', 'ᤫ'), ('ᤰ', '᤻'),
+  ('᥀', '᥀'), ('᥄', '᥏'),
+];
+
+pub const LINEAR_A: &'static [(char, char)] = &[
+  ('𐄇', '𐄳'), ('𐘀', '𐜶'), ('𐝀', '𐝕'), ('𐝠', '𐝧'),
+];
+
+pub const LINEAR_B: &'static [(char, char)] = &[
+  ('𐀀', '𐀋'), ('𐀍', '𐀦'), ('𐀨', '𐀺'), ('𐀼', '𐀽'),
+  ('𐀿', '𐁍'), ('𐁐', '𐁝'), ('𐂀', '𐃺'), ('𐄀', '𐄂'),
+  ('𐄇', '𐄳'), ('𐄷', '𐄿'),
+];
+
+pub const LISU: &'static [(char, char)] = &[
+  ('ꓐ', '꓿'),
+];
+
+pub const LYCIAN: &'static [(char, char)] = &[
+  ('𐊀', '𐊜'),
+];
+
+pub const LYDIAN: &'static [(char, char)] = &[
+  ('𐤠', '𐤹'), ('𐤿', '𐤿'),
+];
+
+pub const MAHAJANI: &'static [(char, char)] = &[
+  ('।', '९'), ('꠰', '꠹'), ('𑅐', '𑅶'),
+];
+
+pub const MAKASAR: &'static [(char, char)] = &[
+  ('\u{11ee0}', '\u{11ef8}'),
+];
+
+pub const MALAYALAM: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ഀ', 'ഃ'), ('അ', 'ഌ'),
+  ('എ', 'ഐ'), ('ഒ', 'ൄ'), ('െ', 'ൈ'), ('ൊ', '൏'),
+  ('ൔ', 'ൣ'), ('൦', 'ൿ'), ('᳚', '᳚'), ('꠰', '꠲'),
+];
+
+pub const MANDAIC: &'static [(char, char)] = &[
+  ('ـ', 'ـ'), ('ࡀ', '࡛'), ('࡞', '࡞'),
+];
+
+pub const MANICHAEAN: &'static [(char, char)] = &[
+  ('ـ', 'ـ'), ('𐫀', '𐫦'), ('𐫫', '𐫶'),
+];
+
+pub const MARCHEN: &'static [(char, char)] = &[
+  ('𑱰', '𑲏'), ('𑲒', '𑲧'), ('𑲩', '𑲶'),
+];
+
+pub const MASARAM_GONDI: &'static [(char, char)] = &[
+  ('𑴀', '𑴆'), ('𑴈', '𑴉'), ('𑴋', '𑴶'), ('𑴺', '𑴺'),
+  ('𑴼', '𑴽'), ('𑴿', '𑵇'), ('𑵐', '𑵙'),
+];
+
+pub const MEDEFAIDRIN: &'static [(char, char)] = &[
+  ('\u{16e40}', '\u{16e9a}'),
+];
+
+pub const MEETEI_MAYEK: &'static [(char, char)] = &[
+  ('ꫠ', '꫶'), ('ꯀ', '꯭'), ('꯰', '꯹'),
+];
+
+pub const MENDE_KIKAKUI: &'static [(char, char)] = &[
+  ('𞠀', '𞣄'), ('𞣇', '𞣖'),
+];
+
+pub const MEROITIC_CURSIVE: &'static [(char, char)] = &[
+  ('𐦠', '𐦷'), ('𐦼', '𐧏'), ('𐧒', '𐧿'),
+];
+
+pub const MEROITIC_HIEROGLYPHS: &'static [(char, char)] = &[
+  ('𐦀', '𐦟'),
+];
+
+pub const MIAO: &'static [(char, char)] = &[
+  ('𖼀', '𖽄'), ('𖽐', '𖽾'), ('𖾏', '𖾟'),
+];
+
+pub const MODI: &'static [(char, char)] = &[
+  ('꠰', '꠹'), ('𑘀', '𑙄'), ('𑙐', '𑙙'),
+];
+
+pub const MONGOLIAN: &'static [(char, char)] = &[
+  ('᠀', '\u{180e}'), ('᠐', '᠙'), ('ᠠ', '\u{1878}'), ('ᢀ', 'ᢪ'),
+  ('𑙠', '𑙬'),
+];
+
+pub const MRO: &'static [(char, char)] = &[
+  ('𖩀', '𖩞'), ('𖩠', '𖩩'), ('𖩮', '𖩯'),
+];
+
+pub const MULTANI: &'static [(char, char)] = &[
+  ('੦', '੯'), ('𑊀', '𑊆'), ('𑊈', '𑊈'), ('𑊊', '𑊍'),
+  ('𑊏', '𑊝'), ('𑊟', '𑊩'),
+];
+
+pub const MYANMAR: &'static [(char, char)] = &[
+  ('က', '႟'), ('꤮', '꤮'), ('ꧠ', 'ꧾ'), ('ꩠ', 'ꩿ'),
+];
+
+pub const NABATAEAN: &'static [(char, char)] = &[
+  ('𐢀', '𐢞'), ('𐢧', '𐢯'),
+];
+
+pub const NEW_TAI_LUE: &'static [(char, char)] = &[
+  ('ᦀ', 'ᦫ'), ('ᦰ', 'ᧉ'), ('᧐', '᧚'), ('᧞', '᧟'),
+];
+
+pub const NEWA: &'static [(char, char)] = &[
+  ('𑐀', '𑑙'), ('𑑛', '𑑛'), ('𑑝', '\u{1145e}'),
+];
+
+pub const NKO: &'static [(char, char)] = &[
+  ('߀', 'ߺ'), ('\u{7fd}', '\u{7ff}'),
+];
+
+pub const NUSHU: &'static [(char, char)] = &[
+  ('𖿡', '𖿡'), ('𛅰', '𛋻'),
+];
+
+pub const OGHAM: &'static [(char, char)] = &[
+  ('\u{1680}', '᚜'),
+];
+
+pub const OL_CHIKI: &'static [(char, char)] = &[
+  ('᱐', '᱿'),
+];
+
+pub const OLD_HUNGARIAN: &'static [(char, char)] = &[
+  ('𐲀', '𐲲'), ('𐳀', '𐳲'), ('𐳺', '𐳿'),
+];
+
+pub const OLD_ITALIC: &'static [(char, char)] = &[
+  ('𐌀', '𐌣'), ('𐌭', '𐌯'),
+];
+
+pub const OLD_NORTH_ARABIAN: &'static [(char, char)] = &[
+  ('𐪀', '𐪟'),
+];
+
+pub const OLD_PERMIC: &'static [(char, char)] = &[
+  ('҃', '҃'), ('𐍐', '𐍺'),
+];
+
+pub const OLD_PERSIAN: &'static [(char, char)] = &[
+  ('𐎠', '𐏃'), ('𐏈', '𐏕'),
+];
+
+pub const OLD_SOGDIAN: &'static [(char, char)] = &[
+  ('\u{10f00}', '\u{10f27}'),
+];
+
+pub const OLD_SOUTH_ARABIAN: &'static [(char, char)] = &[
+  ('𐩠', '𐩿'),
+];
+
+pub const OLD_TURKIC: &'static [(char, char)] = &[
+  ('𐰀', '𐱈'),
+];
+
+pub const ORIYA: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ଁ', 'ଃ'), ('ଅ', 'ଌ'),
+  ('ଏ', 'ଐ'), ('ଓ', 'ନ'), ('ପ', 'ର'), ('ଲ', 'ଳ'),
+  ('ଵ', 'ହ'), ('଼', 'ୄ'), ('େ', 'ୈ'), ('ୋ', '୍'),
+  ('ୖ', 'ୗ'), ('ଡ଼', 'ଢ଼'), ('ୟ', 'ୣ'), ('୦', '୷'),
+  ('᳚', '᳚'),
+];
+
+pub const OSAGE: &'static [(char, char)] = &[
+  ('𐒰', '𐓓'), ('𐓘', '𐓻'),
+];
+
+pub const OSMANYA: &'static [(char, char)] = &[
+  ('𐒀', '𐒝'), ('𐒠', '𐒩'),
+];
+
+pub const PAHAWH_HMONG: &'static [(char, char)] = &[
+  ('𖬀', '𖭅'), ('𖭐', '𖭙'), ('𖭛', '𖭡'), ('𖭣', '𖭷'),
+  ('𖭽', '𖮏'),
+];
+
+pub const PALMYRENE: &'static [(char, char)] = &[
+  ('𐡠', '𐡿'),
+];
+
+pub const PAU_CIN_HAU: &'static [(char, char)] = &[
+  ('𑫀', '𑫸'),
+];
+
+pub const PHAGS_PA: &'static [(char, char)] = &[
+  ('᠂', '᠃'), ('᠅', '᠅'), ('ꡀ', '꡷'),
+];
+
+pub const PHOENICIAN: &'static [(char, char)] = &[
+  ('𐤀', '𐤛'), ('𐤟', '𐤟'),
+];
+
+pub const PSALTER_PAHLAVI: &'static [(char, char)] = &[
+  ('ـ', 'ـ'), ('𐮀', '𐮑'), ('𐮙', '𐮜'), ('𐮩', '𐮯'),
+];
+
+pub const REJANG: &'static [(char, char)] = &[
+  ('ꤰ', '꥓'), ('꥟', '꥟'),
+];
+
+pub const RUNIC: &'static [(char, char)] = &[
+  ('ᚠ', 'ᛪ'), ('ᛮ', 'ᛸ'),
+];
+
+pub const SAMARITAN: &'static [(char, char)] = &[
+  ('ࠀ', '࠭'), ('࠰', '࠾'),
+];
+
+pub const SAURASHTRA: &'static [(char, char)] = &[
+  ('ꢀ', 'ꣅ'), ('꣎', '꣙'),
+];
+
+pub const SHARADA: &'static [(char, char)] = &[
+  ('॑', '॑'), ('᳗', '᳗'), ('᳙', '᳙'), ('᳜', '᳝'),
+  ('᳠', '᳠'), ('𑆀', '𑇍'), ('𑇐', '𑇟'),
+];
+
+pub const SHAVIAN: &'static [(char, char)] = &[
+  ('𐑐', '𐑿'),
+];
+
+pub const SIDDHAM: &'static [(char, char)] = &[
+  ('𑖀', '𑖵'), ('𑖸', '𑗝'),
+];
+
+pub const SIGNWRITING: &'static [(char, char)] = &[
+  ('𝠀', '𝪋'), ('𝪛', '𝪟'), ('𝪡', '𝪯'),
+];
+
+pub const SINHALA: &'static [(char, char)] = &[
+  ('।', '॥'), ('ං', 'ඃ'), ('අ', 'ඖ'), ('ක', 'න'),
+  ('ඳ', 'ර'), ('ල', 'ල'), ('ව', 'ෆ'), ('්', '්'),
+  ('ා', 'ු'), ('ූ', 'ූ'), ('ෘ', 'ෟ'), ('෦', '෯'),
+  ('ෲ', '෴'), ('𑇡', '𑇴'),
+];
+
+pub const SOGDIAN: &'static [(char, char)] = &[
+  ('ـ', 'ـ'), ('\u{10f30}', '\u{10f59}'),
+];
+
+pub const SORA_SOMPENG: &'static [(char, char)] = &[
+  ('𑃐', '𑃨'), ('𑃰', '𑃹'),
+];
+
+pub const SOYOMBO: &'static [(char, char)] = &[
+  ('𑩐', '𑪃'), ('𑪆', '𑪢'),
+];
+
+pub const SUNDANESE: &'static [(char, char)] = &[
+  ('ᮀ', 'ᮿ'), ('᳀', '᳇'),
+];
+
+pub const SYLOTI_NAGRI: &'static [(char, char)] = &[
+  ('।', '॥'), ('০', '৯'), ('ꠀ', '꠫'),
+];
+
+pub const SYRIAC: &'static [(char, char)] = &[
+  ('،', '،'), ('؛', '\u{61c}'), ('؟', '؟'), ('ـ', 'ـ'), ('ً', 'ٕ'),
+  ('ٰ', 'ٰ'), ('܀', '܍'), ('\u{70f}', '݊'), ('ݍ', 'ݏ'), ('ࡠ', 'ࡪ'),
+];
+
+pub const TAGALOG: &'static [(char, char)] = &[
+  ('ᜀ', 'ᜌ'), ('ᜎ', '᜔'), ('᜵', '᜶'),
+];
+
+pub const TAGBANWA: &'static [(char, char)] = &[
+  ('᜵', '᜶'), ('ᝠ', 'ᝬ'), ('ᝮ', 'ᝰ'), ('ᝲ', 'ᝳ'),
+];
+
+pub const TAI_LE: &'static [(char, char)] = &[
+  ('၀', '၉'), ('ᥐ', 'ᥭ'), ('ᥰ', 'ᥴ'),
+];
+
+pub const TAI_THAM: &'static [(char, char)] = &[
+  ('ᨠ', 'ᩞ'), ('᩠', '᩼'), ('᩿', '᪉'), ('᪐', '᪙'),
+  ('᪠', '᪭'),
+];
+
+pub const TAI_VIET: &'static [(char, char)] = &[
+  ('ꪀ', 'ꫂ'), ('ꫛ', '꫟'),
+];
+
+pub const TAKRI: &'static [(char, char)] = &[
+  ('।', '॥'), ('꠰', '꠹'), ('𑚀', '𑚷'), ('𑛀', '𑛉'),
+];
+
+pub const TAMIL: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ஂ', 'ஃ'), ('அ', 'ஊ'),
+  ('எ', 'ஐ'), ('ஒ', 'க'), ('ங', 'ச'), ('ஜ', 'ஜ'),
+  ('ஞ', 'ட'), ('ண', 'த'), ('ந', 'ப'), ('ம', 'ஹ'),
+  ('ா', 'ூ'), ('ெ', 'ை'), ('ொ', '்'), ('ௐ', 'ௐ'),
+  ('ௗ', 'ௗ'), ('௦', '௺'), ('᳚', '᳚'), ('ꣳ', 'ꣳ'),
+  ('𑌁', '𑌁'), ('𑌃', '𑌃'), ('\u{1133b}', '𑌼'),
+];
+
+pub const TANGUT: &'static [(char, char)] = &[
+  ('𖿠', '𖿠'), ('𗀀', '\u{187f1}'), ('𘠀', '𘫲'),
+];
+
+pub const TELUGU: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('ఀ', 'ఌ'), ('ఎ', 'ఐ'),
+  ('ఒ', 'న'), ('ప', 'హ'), ('ఽ', 'ౄ'), ('ె', 'ై'),
+  ('ొ', '్'), ('ౕ', 'ౖ'), ('ౘ', 'ౚ'), ('ౠ', 'ౣ'),
+  ('౦', '౯'), ('౸', '౿'), ('᳚', '᳚'),
+];
+
+pub const THAANA: &'static [(char, char)] = &[
+  ('،', '،'), ('؛', '\u{61c}'), ('؟', '؟'), ('٠', '٩'), ('ހ', 'ޱ'),
+  ('ﷲ', 'ﷲ'), ('﷽', '﷽'),
+];
+
+pub const THAI: &'static [(char, char)] = &[
+  ('ก', 'ฺ'), ('เ', '๛'),
+];
+
+pub const TIBETAN: &'static [(char, char)] = &[
+  ('ༀ', 'ཇ'), ('ཉ', 'ཬ'), ('ཱ', 'ྗ'), ('ྙ', 'ྼ'),
+  ('྾', '࿌'), ('࿎', '࿔'), ('࿙', '࿚'),
+];
+
+pub const TIFINAGH: &'static [(char, char)] = &[
+  ('ⴰ', 'ⵧ'), ('ⵯ', '⵰'), ('⵿', '⵿'),
+];
+
+pub const TIRHUTA: &'static [(char, char)] = &[
+  ('॑', '॒'), ('।', '॥'), ('꠰', '꠹'), ('𑒀', '𑓇'),
+  ('𑓐', '𑓙'),
+];
+
+pub const UGARITIC: &'static [(char, char)] = &[
+  ('𐎀', '𐎝'), ('𐎟', '𐎟'),
+];
+
+pub const VAI: &'static [(char, char)] = &[
+  ('ꔀ', 'ꘫ'),
+];
+
+pub const WARANG_CITI: &'static [(char, char)] = &[
+  ('𑢠', '𑣲'), ('𑣿', '𑣿'),
+];
+
+pub const YI: &'static [(char, char)] = &[
+  ('、', '。'), ('〈', '】'), ('〔', '〛'), ('・', '・'),
+  ('ꀀ', 'ꒌ'), ('꒐', '꓆'), ('｡', '･'),
+];
+
+pub const ZANABAZAR_SQUARE: &'static [(char, char)] = &[
+  ('𑨀', '𑩇'),
+];
diff --git a/third_party/rust/regex/.cargo-checksum.json b/third_party/rust/regex/.cargo-checksum.json
index 7397ed39ea11..fb04e24b1cea 100644
--- a/third_party/rust/regex/.cargo-checksum.json
+++ b/third_party/rust/regex/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"28fc87d41a27bc03d9a8c6b5f7bc1bca55444dbd0001100b85060acada1449d7","CHANGELOG.md":"1056eb04d324b46354605713b40b76bb68d29e5d6ff7ab8d67a58f24534d1860","Cargo.toml":"db32762fb82d997942d0ccebdfab132e742a3d384b2f3b10b2e1000515bd40e7","HACKING.md":"37ea34650ce307a1d561aa915ada82cc8b44153085f327aa2b342fcf8e7afc62","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"d23d6dbe3791bc0689c5a876922b8264d6d3069b577772440b8caa01867f0cb4","README.md":"e88b7b2f1982115b1bfa8dd1b305ae1315af6f426c919009d80b63007509ed1c","appveyor.yml":"6855c14a64fec423d67c1ddcc47644593ae3ad1f26e8d157cd5c395efee1efc0","ci/after_success.sh":"6c9562098234f7484e2496918386505185c43018c3f3d17f8df95a59457d8f1f","ci/run-kcov":"721a0ebfb72deb34e4b45141279eae5b4a40c22d47159e01b4e6f176ed3bbc22","ci/run-shootout-test":"be7edb66a4a65eaef6a2b7e6036b4b732effa8dcd931bf4cbd591d0ca32b8264","ci/script.sh":"7f640b7a469c2764f6c12dc84a75fa956c24bc1f611cd72f1ae3a53bacd3ee06","examples/bug347.rs":"93fde9707dd78978dffed46b08bde095a515151bc94f892c0159ac3c0060852d","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"3d36b08dd34c51d022e9b3a3dcfbc780bc9dc3d46a601256db5d4d5e2213119c","examples/shootout-regex-dna-cheat.rs":"4b5a590ec88a9ba67cc4a34621cb038a400d45e64a15a354f3e07fdaf41a935b","examples/shootout-regex-dna-replace.rs":"15677e7de356427fe2b983e918de073a7a730337b090d4ab0e815e1e66f74f73","examples/shootout-regex-dna-single-cheat.rs":"5e743b3a6ec968713ce064a289b1fbd11c302add824d1c749a2ffb546c73128e","examples/shootout-regex-dna-single.rs":"021292ec6999be33a9b8e833759bf3509dc0e6b6365fad8e3a882cf3835b0405","examples/shootout-regex-dna.rs":"b892242cea6b6b16f0511ea672c24a49909585224fb69085f0f2fca77ce30aea","examples/shootout-regex-redux-1.rs":"191f47847f5466261a308c8cdc19a3502603a208f40e4e650024dec80241b9e3","examples/shootout-regex-redux-chunked.rs":"6da0b6af66df64dfe45fb2e08532e2b3712cebcf0d3f19ff8d5f87fe712278c9","examples/shootout-regex-redux.rs":"c587bef968feb9c329f5c1896f79ec09e509885dec27091678b28a221a5d40e8","scripts/frequencies.py":"df2cac150bc4ed42d2d97762535a5f260f3fe06d9d516721f68a52671a3b7a3b","scripts/regex-match-tests.py":"f1b3ad870c893510172bd84f8328b66ee99cd7aee7715a95a858468ff3e33635","scripts/unicode.py":"4b1330e733bbc22e677e22855bf8a88ab134aae56a10fda97081320aa12a6228","src/backtrack.rs":"221e12b4afaff096f8a61bb274eade928845e194e1ec37fa75b684b18c126b1b","src/compile.rs":"4c2159961364d001e9191840a878c3c3ca0b641f2356ba2abcc3356581b7b47c","src/dfa.rs":"985b5f880814452edae862347584f2e53c08eaccae0e01ee5c5d8564dd8381ad","src/error.rs":"b4052872f9a7bc48c478fe73e145ac1acf7533140f827999808fadcba09754d3","src/exec.rs":"b696cd65cca692d4ddf55e60bcd29986c5f2fd43a2e32ffea23c0c95548915d9","src/expand.rs":"94d7fb06544639d94338fc426bd15d1883efd4e0204552c9def667b9b415ef63","src/freqs.rs":"e25871eec51d1c02c15abbc04d61dbea71fb2dbc15f370c98279687416c969de","src/input.rs":"c2710458e38398a0eba357c76c38fde42b50c22b6e39764ea68984fab3acfab7","src/lib.rs":"1652707e4c259cd39e5c45011c5c8d001f582944527af8d78637600bfe162b44","src/literals.rs":"7a2efe252c21660794bd27054e997151763c8f0ea68c2be7994e1a36f4811675","src/pattern.rs":"4e820c17a2b983050f47d3fd13282094ce9f27b75fd852fcec438d61f07f0b0b","src/pikevm.rs":"bc9d00bd5aed5463121fc98ce9390381137f842c821da48242b2f6fae1137f22","src/prog.rs":"3b3d472ced5958e140e96d367067ab53edba72804c80009a46131ec904a75f2a","src/re_builder.rs":"d14baf810f1248a030eca31475989115f6254a438acbba1eec14b59ed58d2f12","src/re_bytes.rs":"a5b7afee1460fb1957284a2483e6708f6357acc7c13288dee409b6aa0fa15b74","src/re_plugin.rs":"74999c35abc02cb7c18adb74c1d8ebd08b56141f66f174c67b7157c5c27e2a49","src/re_set.rs":"43f40dba1273b8b359d4010616be62b41f71b1d803f0c6e4b04169dc57cb6318","src/re_trait.rs":"37d791af9cc737e0a144be64ddb7104114222e5034cfc9c948078b0b2c799295","src/re_unicode.rs":"34cff9ae054084d870803f1c8d092847fe32a34c9572e67bfc524da03cbfc905","src/simd_accel/mod.rs":"a3eb2c7fcc296137cfc135da47cdfe745606e8159c3263591bebced2c09fdd54","src/simd_accel/teddy128.rs":"4b913c67f5b7105f75b02fff092c3d76895612425c3f8b3e5ded2c41aae4279c","src/simd_fallback/mod.rs":"4cb8a77e2d3e167e9bfc47cb7e4734179f743c2f727e26838864d9959275239b","src/simd_fallback/teddy128.rs":"502d3bff4c78963f343875aa00b15e3625f3ee2ba1de01f029211292a5721912","src/sparse.rs":"04e70bb0bd006f806e8c9cf19825625e907036304823bc03b6c8f2e5046a38ef","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"75a4516d636566938e896f10687fc16b3ecd8b09de0093015359eb0d11471d5d","tests/api.rs":"803faacd9ac5efc149959ff63a2132f5ca155f75a246b79807c549b464b5c497","tests/api_str.rs":"aef1388c9de8fe9044539745d1975c734e9d268ff02a2dbb1edc5b754cc56d77","tests/bytes.rs":"ae7601bf69307c541b56d85b6f77369051f55096dddfa9d81d470adb54f42a5d","tests/crazy.rs":"bf3a1c3b8620d7d4c9aa72ab5e027fec02ef4bcec45a884e89ad70e82c445a8d","tests/flags.rs":"cd3788760defc667b32adb2732b6657b289372e1051fc240dfd0e435e2835353","tests/fowler.rs":"e0b7420fa5b636301d4c11cd4dfb803ec09fa7b27be47c594d231167de1241e3","tests/macros.rs":"e0329eedbe073e9dca649e651bc869ef2e6030b4b2a2d5959033b58bfddeb858","tests/macros_bytes.rs":"647c42525b8df5151f4f4cab40f515dd2fa5a05246562f5575902e162b0af2c0","tests/macros_str.rs":"124767f6ff33766502e89050ad498d3aba21e975aefeaf64ae76b0abe13b4fdb","tests/misc.rs":"c8cc85ac916980ebd053df2444fe9b795a00f2ac42c5cd828fc3df487f689265","tests/multiline.rs":"4e872a9473bc229d955716c18c77aa3530625a8f3a28ecaefdb70b9aff0f0a8b","tests/noparse.rs":"9c5acf252655f8daba67d5aa15a98f556a8bb5de87de9ecc8e8e3b50614a65c2","tests/plugin.rs":"9a51dfcbdad4e2a19f43598d74e0dd745a862a01b4165fce387a94083e5b588f","tests/regression.rs":"28bd9e3b6df7b8b48b4c2e069f72f4f59d5e64b091ed2559bd3b0516e27f626a","tests/replace.rs":"4a65b863ad012366328062784e323f13c4bbccce89ff709196e4d84d94ef1636","tests/searcher.rs":"124c9909a1e8fcfddee8ecfae3a1fb9d76f9ddac62fda23d9b895744728a0aa8","tests/set.rs":"0cecf5d2acb3d0df2b051e0ab56a4a853bb58c0e922480f5e460b9a05a0d16af","tests/shortest_match.rs":"7ca223e0a61b1a26a1f36465ab49de021475295e18f4d6421497461af1e107be","tests/suffix_reverse.rs":"cd497c1a51246a8fc727062133470e0c6300620ad80333d20d63c0ee4224ef1c","tests/test_backtrack.rs":"b07a114b2eb7f1f17357629be9c8458e31f7952fb2c327d66d9415f08855c624","tests/test_backtrack_bytes.rs":"dd3cec3c630d6f41892c9111bee87227bf47126651b2402672c30b084fa9c28c","tests/test_backtrack_utf8bytes.rs":"b576b933d6be21f8cedb281e456441d4278350b0145a139dbccb1861639a54f9","tests/test_default.rs":"768a1fabafc7eb815bfaf55c22606dc884e1dbb88d7fc40fd561e8faaa61e6d9","tests/test_default_bytes.rs":"c0b66b63abd263f3fc7e5fcacf4a93cb7fc40c17b764edf8700ae9ba1ab950ff","tests/test_nfa.rs":"aad36ca01f3f7eb23633a1207056e9056d686be2ef6e3661fad83805fa482927","tests/test_nfa_bytes.rs":"198f7b58c5c7dd0a05f16ddb3b9b63dab29ef2a56448378ac602c5d087c01e4e","tests/test_nfa_utf8bytes.rs":"854d80114ca1bed14d4ad3f2b3bf292ff0fa44e12d7d3f2ec6dd17cbbaa82175","tests/test_plugin.rs":"84be9cabe1cf8fb208638475436b020a75e9ec3e7f885af39e5404adb6fcae03","tests/unicode.rs":"7bd3095678fa227dc722f2b5f60a072c2b1752a5ac8df234cd023ece34c80d8a","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"ae4ac0689c6b42ff7628a681d6d99a124d254f35eb1b809137859d3a8afe84fc"},"package":"1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"}
\ No newline at end of file
+{"files":{".cargo_vcs_info.json":"370f6a3784ffd7340034b2c8e6fd99e27592f2b4b7922430b51748c20d16c14e",".travis.yml":"45292f4da39459f6b6806cd57f9f89872c5bbb997f5f502c4f2d472f65617512","CHANGELOG.md":"42fc0cade5e708e2d9d8f24d622f460a984608e0f67db09aacaaf141ec6a80a3","Cargo.toml":"6ee51849e9866caf784ee6d1a68197ded11e7b864d895162172ad89c1d8ebcd0","HACKING.md":"33e3e555fbcf70d7c235068a10c0d9c3d53c02d71712eda52d252d0b20f70eb3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"c776b18758b6dc8f2f9d37e9a95261f75c5f744925e8ddf216b83953bf7467b7","README.md":"35e3481785806be3422bf52369249146c80d6a8922bb166650561d9e8bf5d4c7","UNICODE.md":"d7992c142299cb79f524c964ca8d4cf247b5db99fcf4103e4eebaf6c54cf06f6","appveyor.yml":"3cc9496bd76b8ce1cd4be1c369974fd43798352aad595a36d6f4229bdeeb13d7","build.rs":"cebf7813476c332764ab9f26f8e0e7d9b5460ff1468e7ab2703eec812f82bdee","ci/after_success.sh":"9a6089e0a64057e97b11158219921c664a6ac956c0fad20f007da29ef11c19af","ci/run-kcov":"a81cad2c3de4c6d704502cdc4227d7432b7765613c7b8c426db66ab03fe23bfb","ci/run-shootout-test":"be7edb66a4a65eaef6a2b7e6036b4b732effa8dcd931bf4cbd591d0ca32b8264","ci/script.sh":"934fbb49e530161140682fbeab81d68216e849702460735af9d10fba271ad04d","ci/test-regex-capi":"a46d41fd47b817611f8a442971671c999b3be4d3d37fe0fd71c530ae0d633e93","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"f097a923fef2e9bd9a9abd3686eea84830e8050bb750bcab840b6575873227ff","examples/shootout-regex-dna-cheat.rs":"4b5a590ec88a9ba67cc4a34621cb038a400d45e64a15a354f3e07fdaf41a935b","examples/shootout-regex-dna-replace.rs":"15677e7de356427fe2b983e918de073a7a730337b090d4ab0e815e1e66f74f73","examples/shootout-regex-dna-single-cheat.rs":"5e743b3a6ec968713ce064a289b1fbd11c302add824d1c749a2ffb546c73128e","examples/shootout-regex-dna-single.rs":"c86969adb0fb08c5e23f749ec6922a58404da7d0e1925c848957a5144ddc8815","examples/shootout-regex-dna.rs":"e627f1e5e24c1cf4e9c9d52b844b6d971c59b7169b0e8762d8d9d1cb7debc6e6","scripts/frequencies.py":"df2cac150bc4ed42d2d97762535a5f260f3fe06d9d516721f68a52671a3b7a3b","scripts/generate.py":"35e83c13fdf7bc3b068601feb9b1eb2f9cb291944a95e05fe350dea502d7ce51","scripts/regex-match-tests.py":"f1b3ad870c893510172bd84f8328b66ee99cd7aee7715a95a858468ff3e33635","scripts/scrape_crates_io.py":"ba4bcd130708358144a821d577451a72489526a191bf7cc60f8a055010db9b1e","src/backtrack.rs":"0372ada608dca9c8d3e1fabf56e33498f8ff4fbdfd445873c4a4be6657465c68","src/compile.rs":"32667252ac4b687d9ef1c9dd0f055f0616ab49050870daca338809d32616409b","src/dfa.rs":"163aa4ec0dcdb1ffc7dd687debc1d64acffeeca7861cb4bb303d2da0ad33b3a6","src/error.rs":"d26673a95e372665863c7e01558836ef6e957aadf421d5056525720e16a9683d","src/exec.rs":"08c9a2dceb42f88bf8bfabd2628ad98661f9541505d895de027676f1a423ea3c","src/expand.rs":"4333da32d6fbb05ec05bead810eb659c5b012e2d361a9bb9e24bb30e8939fb88","src/freqs.rs":"e25871eec51d1c02c15abbc04d61dbea71fb2dbc15f370c98279687416c969de","src/input.rs":"9b092fe88a66b46dee0dfe0a2e67e4b78b01a32f53b28443b5f382b8514d0cfb","src/lib.rs":"66ab592814fd3349c8e927d4a4377bb8c0e64c9648f98acbc11b32a68d9d1441","src/literal/mod.rs":"c395221efe19f36edd9d92c8f8283e5b30553e0e9b408ccb1430d11f038730f8","src/literal/teddy_avx2/fallback.rs":"f24b70f9dd028eefe2802b7bbc6b2dca97663b03a931058e3a59750f0693a15c","src/literal/teddy_avx2/imp.rs":"b0e4634bc9fbc793e3b0938b97a236df4b8fb17a0ac08040a6394bc73042aa8b","src/literal/teddy_avx2/mod.rs":"b7373cb7bc823e60be4e585b93fe15e7a477c2cb16a45563f66c2e5c0d7e660d","src/literal/teddy_ssse3/fallback.rs":"f24b70f9dd028eefe2802b7bbc6b2dca97663b03a931058e3a59750f0693a15c","src/literal/teddy_ssse3/imp.rs":"be4565c47a3807ab09343f2da4ef0e3297d4776719472efb60dee8e55380c2ec","src/literal/teddy_ssse3/mod.rs":"34dba2fde2ec15c1b37faae164a1475b92227ad5c1010bc619d0c318bc30e332","src/pattern.rs":"4e820c17a2b983050f47d3fd13282094ce9f27b75fd852fcec438d61f07f0b0b","src/pikevm.rs":"9600a8b135075f8cf62683e6b08c73834873a203347d275f1e9ca3a97221dbeb","src/prog.rs":"7fdfa764562867c3b051554921fbf6452d08e6f860ade6657cf021b6a734b899","src/re_builder.rs":"94b348b7b6aa9f8502b01240cebc50434d9f460f4f63bd0aec013cc9f9b3eec1","src/re_bytes.rs":"d3ca160c650a29cb1e09342611187d8c683df0e0f5d8b9e277c7d6d596c14b49","src/re_set.rs":"0b8df90c7a9ce94c4af5962fcdc647958a8e42f50a86c22fcf043292f1d2fe72","src/re_trait.rs":"45b2e81076cce0b87bace2c05e125d44b8e3b71ff8d5c94130a7ae2c915f237d","src/re_unicode.rs":"b7ae7149a651b962087c6e5111c82aa70c237313996a8d7e0e695d429427d40a","src/sparse.rs":"04e70bb0bd006f806e8c9cf19825625e907036304823bc03b6c8f2e5046a38ef","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"3756a5bdd6f387ed34731197fbdaab8521b0ae1726250100ba235756cb42b4b1","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"1a2d7bc43ab139bfc2b2610627efd59a7ead2a959492ba73eebb743d482c7957","src/vector/avx2.rs":"1ef39371a9215144b69bf72df9aa3533ea6be44d7425cdc5c8192de79dfc5e96","src/vector/mod.rs":"fc238d33117c500381f57d2d1fbaba14bd6ab855ba3fe55304c37256b1c0e965","src/vector/ssse3.rs":"f8549244fddfcb73f538761c0ae5a81c535e5ae5e129cebf8e3e6f9db4fa79f4","tests/api.rs":"803faacd9ac5efc149959ff63a2132f5ca155f75a246b79807c549b464b5c497","tests/api_str.rs":"8ccb6c3dfe0220229ad33fcaf9dea420b414aea17c7498d978efd1b8aceaa980","tests/bytes.rs":"3564a933f12f84d65488c220d71067a9902ed9860522a7d9139a713f818a0b1c","tests/consistent.rs":"51b12bfec3ec2b49471b508dec537dbbd50823673a34a16b98e38dc3ae2a0793","tests/crates_regex.rs":"7812e91c25a2aad48ba024bcbeb8b922ffc1cfa3113a33615885d72d8a2cae64","tests/crazy.rs":"b0c593be5022341606ddb15b3d28aa39d2d52977db4b1b72c41c6133a7f7a7e0","tests/flags.rs":"cd3788760defc667b32adb2732b6657b289372e1051fc240dfd0e435e2835353","tests/fowler.rs":"e0b7420fa5b636301d4c11cd4dfb803ec09fa7b27be47c594d231167de1241e3","tests/macros.rs":"f021b62e3ce8d122f6450a5aab36972eccf4c21c62a53c604924d4d01d90c0d8","tests/macros_bytes.rs":"5574c19bff5dfa45802238b65f642605f1a8b8adc6a353660a251c80490ad68e","tests/macros_str.rs":"518bde310ceb9fb689b20294279483454601ba3a3fd7c95a04d07331f05d476d","tests/misc.rs":"c8cc85ac916980ebd053df2444fe9b795a00f2ac42c5cd828fc3df487f689265","tests/multiline.rs":"4e872a9473bc229d955716c18c77aa3530625a8f3a28ecaefdb70b9aff0f0a8b","tests/noparse.rs":"8850d31cb95e413e3a67edecce8590cd158f49779abcc2e5722381113346179c","tests/regression.rs":"c8293a778591a7862de4d526d856843b4e3f105bba0b7ebca0ed7ae5e0346232","tests/replace.rs":"a121da1d86fa39d45b6b29ccd74e4327deaf0c9c1914dc1da46e6358084e4459","tests/searcher.rs":"124c9909a1e8fcfddee8ecfae3a1fb9d76f9ddac62fda23d9b895744728a0aa8","tests/set.rs":"0cecf5d2acb3d0df2b051e0ab56a4a853bb58c0e922480f5e460b9a05a0d16af","tests/shortest_match.rs":"7ca223e0a61b1a26a1f36465ab49de021475295e18f4d6421497461af1e107be","tests/suffix_reverse.rs":"cd497c1a51246a8fc727062133470e0c6300620ad80333d20d63c0ee4224ef1c","tests/test_backtrack.rs":"b07a114b2eb7f1f17357629be9c8458e31f7952fb2c327d66d9415f08855c624","tests/test_backtrack_bytes.rs":"dd3cec3c630d6f41892c9111bee87227bf47126651b2402672c30b084fa9c28c","tests/test_backtrack_utf8bytes.rs":"b576b933d6be21f8cedb281e456441d4278350b0145a139dbccb1861639a54f9","tests/test_crates_regex.rs":"6d7f2cfade28ebab6a831282882b83e4b3d66a5171411730505e2a8bb95074a8","tests/test_default.rs":"dc819a5973dd03a58165afa37da20727e8bf7085f1482414290654483fe20aa1","tests/test_default_bytes.rs":"c5228278e0a1d8fab5157dfd2b52642fd0ec68db346dc133f4c16f178d63e856","tests/test_nfa.rs":"aad36ca01f3f7eb23633a1207056e9056d686be2ef6e3661fad83805fa482927","tests/test_nfa_bytes.rs":"198f7b58c5c7dd0a05f16ddb3b9b63dab29ef2a56448378ac602c5d087c01e4e","tests/test_nfa_utf8bytes.rs":"854d80114ca1bed14d4ad3f2b3bf292ff0fa44e12d7d3f2ec6dd17cbbaa82175","tests/unicode.rs":"cadd620a5d70216d6a3100d18f21598bd3ed6c343023697a7d3c57b7dc45149e","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"75dbcc35d3abc0f9795c2ea99e216dc227b0a5b58e9ca5eef767815ff0513921"},"package":"2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341"}
\ No newline at end of file
diff --git a/third_party/rust/regex/.cargo_vcs_info.json b/third_party/rust/regex/.cargo_vcs_info.json
new file mode 100644
index 000000000000..68ab0d5ac054
--- /dev/null
+++ b/third_party/rust/regex/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "7f29401b017f0dd527ff7c4aa61d53ea8ad21ecd"
+  }
+}
diff --git a/third_party/rust/regex/.travis.yml b/third_party/rust/regex/.travis.yml
index c3d5321e0c50..c49ba699fab7 100644
--- a/third_party/rust/regex/.travis.yml
+++ b/third_party/rust/regex/.travis.yml
@@ -1,13 +1,13 @@
 dist: trusty
-sudo: false
+sudo: required
 language: rust
 rust:
-  - 1.12.0
+  - 1.20.0
   - stable
   - beta
   - nightly
 script: ci/script.sh
 addons:
   apt:
     packages:
       - libcurl4-openssl-dev
@@ -15,14 +15,15 @@ addons:
       - libdw-dev
       - binutils-dev
       - wget
       - clang-3.6
       - cmake
       - python
       - python-virtualenv
 after_success: ci/after_success.sh
-env:
-  global:
-    secure: "GdGE0kFYiJGccVZligur7JlWRCy49eH6uWPl71mrnaaW8jLHmkva0jVb0LB9e5ol3YMaMCgrwM2pcj3Uk2C08YcGIoEKOLlDVho351KaD6XfclZ29CQTAPMz4Xut2IcB4YeuZlDrOnM26guTIOtn2NAjeQgOhpM/ErzVBgkB+wQ="
 notifications:
   email:
     on_success: never
+branches:
+  only:
+    - master
+    - auto
diff --git a/third_party/rust/regex/CHANGELOG.md b/third_party/rust/regex/CHANGELOG.md
index 19492b701004..79710e3b0cf2 100644
--- a/third_party/rust/regex/CHANGELOG.md
+++ b/third_party/rust/regex/CHANGELOG.md
@@ -1,8 +1,256 @@
+1.0.2 (2018-07-18)
+==================
+This release exposes some new lower level APIs on `Regex` that permit
+amortizing allocation and controlling the location at which a search is
+performed in a more granular way. Most users of the regex crate will not
+need or want to use these APIs.
+
+New features:
+
+* [FEATURE #493](https://github.com/rust-lang/regex/pull/493):
+  Add a few lower level APIs for amortizing allocation and more fine grained
+  searching.
+
+Bug fixes:
+
+* [BUG 3981d2ad](https://github.com/rust-lang/regex/commit/3981d2ad):
+  Correct outdated documentation on `RegexBuilder::dot_matches_new_line`.
+* [BUG 7ebe4ae0](https://github.com/rust-lang/regex/commit/7ebe4ae0):
+  Correct outdated documentation on `Parser::allow_invalid_utf8` in the
+  `regex-syntax` crate.
+* [BUG 24c7770b](https://github.com/rust-lang/regex/commit/24c7770b):
+  Fix a bug in the HIR printer where it wouldn't correctly escape meta
+  characters in character classes.
+
+
+1.0.1 (2018-06-19)
+==================
+This release upgrades regex's Unicode tables to Unicode 11, and enables SIMD
+optimizations automatically on Rust stable (1.27 or newer).
+
+New features:
+
+* [FEATURE #486](https://github.com/rust-lang/regex/pull/486):
+  Implement `size_hint` on `RegexSet` match iterators.
+* [FEATURE #488](https://github.com/rust-lang/regex/pull/488):
+  Update Unicode tables for Unicode 11.
+* [FEATURE #490](https://github.com/rust-lang/regex/pull/490):
+  SIMD optimizations are now enabled automatically in Rust stable, for versions
+  1.27 and up. No compilation flags or features need to be set. CPU support
+  SIMD is detected automatically at runtime.
+
+Bug fixes:
+
+* [BUG #482](https://github.com/rust-lang/regex/pull/482):
+  Present a better compilation error when the `use_std` feature isn't used.
+
+
+1.0.0 (2018-05-01)
+==================
+This release marks the 1.0 release of regex.
+
+While this release includes some breaking changes, most users of older versions
+of the regex library should be able to migrate to 1.0 by simply bumping the
+version number. The important changes are as follows:
+
+* We adopt Rust 1.20 as the new minimum supported version of Rust for regex.
+  We also tentativley adopt a policy that permits bumping the minimum supported
+  version of Rust in minor version releases of regex, but no patch releases.
+  That is, with respect to semver, we do not strictly consider bumping the
+  minimum version of Rust to be a breaking change, but adopt a conservative
+  stance as a compromise.
+* Octal syntax in regular expressions has been disabled by default. This
+  permits better error messages that inform users that backreferences aren't
+  available. Octal syntax can be re-enabled via the corresponding option on
+  `RegexBuilder`.
+* `(?-u:\B)` is no longer allowed in Unicode regexes since it can match at
+  invalid UTF-8 code unit boundaries. `(?-u:\b)` is still allowed in Unicode
+  regexes.
+* The `From<regex_syntax::Error>` impl has been removed. This formally removes
+  the public dependency on `regex-syntax`.
+* A new feature, `use_std`, has been added and enabled by default. Disabling
+  the feature will result in a compilation error. In the future, this may
+  permit us to support `no_std` environments (w/ `alloc`) in a backwards
+  compatible way.
+
+For more information and discussion, please see
+[1.0 release tracking issue](https://github.com/rust-lang/regex/issues/457).
+
+
+0.2.11 (2018-05-01)
+===================
+This release primarily contains bug fixes. Some of them resolve bugs where
+the parser could panic.
+
+New features:
+
+* [FEATURE #459](https://github.com/rust-lang/regex/pull/459):
+  Include C++'s standard regex library and Boost's regex library in the
+  benchmark harness. We now include D/libphobos, C++/std, C++/boost, Oniguruma,
+  PCRE1, PCRE2, RE2 and Tcl in the harness.
+
+Bug fixes:
+
+* [BUG #445](https://github.com/rust-lang/regex/issues/445):
+  Clarify order of indices returned by RegexSet match iterator.
+* [BUG #461](https://github.com/rust-lang/regex/issues/461):
+  Improve error messages for invalid regexes like `[\d-a]`.
+* [BUG #464](https://github.com/rust-lang/regex/issues/464):
+  Fix a bug in the error message pretty printer that could cause a panic when
+  a regex contained a literal `\n` character.
+* [BUG #465](https://github.com/rust-lang/regex/issues/465):
+  Fix a panic in the parser that was caused by applying a repetition operator
+  to `(?flags)`.
+* [BUG #466](https://github.com/rust-lang/regex/issues/466):
+  Fix a bug where `\pC` was not recognized as an alias for `\p{Other}`.
+* [BUG #470](https://github.com/rust-lang/regex/pull/470):
+  Fix a bug where literal searches did more work than necessary for anchored
+  regexes.
+
+
+0.2.10 (2018-03-16)
+===================
+This release primarily updates the regex crate to changes made in `std::arch`
+on nightly Rust.
+
+New features:
+
+* [FEATURE #458](https://github.com/rust-lang/regex/pull/458):
+  The `Hir` type in `regex-syntax` now has a printer.
+
+
+0.2.9 (2018-03-12)
+==================
+This release introduces a new nightly only feature, `unstable`, which enables
+SIMD optimizations for certain types of regexes. No additional compile time
+options are necessary, and the regex crate will automatically choose the
+best CPU features at run time. As a result, the `simd` (nightly only) crate
+dependency has been dropped.
+
+New features:
+
+* [FEATURE #456](https://github.com/rust-lang/regex/pull/456):
+  The regex crate now includes AVX2 optimizations in addition to the extant
+  SSSE3 optimization.
+
+Bug fixes:
+
+* [BUG #455](https://github.com/rust-lang/regex/pull/455):
+  Fix a bug where `(?x)[ / - ]` failed to parse.
+
+
+0.2.8 (2018-03-12)
+==================
+Bug gixes:
+
+* [BUG #454](https://github.com/rust-lang/regex/pull/454):
+  Fix a bug in the nest limit checker being too aggressive.
+
+
+0.2.7 (2018-03-07)
+==================
+This release includes a ground-up rewrite of the regex-syntax crate, which has
+been in development for over a year.
+
+New features:
+
+* Error messages for invalid regexes have been greatly improved. You get these
+  automatically; you don't need to do anything. In addition to better
+  formatting, error messages will now explicitly call out the use of look
+  around. When regex 1.0 is released, this will happen for backreferences as
+  well.
+* Full support for intersection, difference and symmetric difference of
+  character classes. These can be used via the `&&`, `--` and `~~` binary
+  operators within classes.
+* A Unicode Level 1 conformat implementation of `\p{..}` character classes.
+  Things like `\p{scx:Hira}`, `\p{age:3.2}` or `\p{Changes_When_Casefolded}`
+  now work. All property name and value aliases are supported, and properties
+  are selected via loose matching. e.g., `\p{Greek}` is the same as
+  `\p{G r E e K}`.
+* A new `UNICODE.md` document has been added to this repository that
+  exhaustively documents support for UTS#18.
+* Empty sub-expressions are now permitted in most places. That is, `()+` is
+  now a valid regex.
+* Almost everything in regex-syntax now uses constant stack space, even when
+  performing anaylsis that requires structural induction. This reduces the risk
+  of a user provided regular expression causing a stack overflow.
+* [FEATURE #174](https://github.com/rust-lang/regex/issues/174):
+  The `Ast` type in `regex-syntax` now contains span information.
+* [FEATURE #424](https://github.com/rust-lang/regex/issues/424):
+  Support `\u`, `\u{...}`, `\U` and `\U{...}` syntax for specifying code points
+  in a regular expression.
+* [FEATURE #449](https://github.com/rust-lang/regex/pull/449):
+  Add a `Replace::by_ref` adapter for use of a replacer without consuming it.
+
+Bug fixes:
+
+* [BUG #446](https://github.com/rust-lang/regex/issues/446):
+  We re-enable the Boyer-Moore literal matcher.
+
+
+0.2.6 (2018-02-08)
+==================
+Bug fixes:
+
+* [BUG #446](https://github.com/rust-lang/regex/issues/446):
+  Fixes a bug in the new Boyer-Moore searcher that results in a match failure.
+  We fix this bug by temporarily disabling Boyer-Moore.
+
+
+0.2.5 (2017-12-30)
+==================
+Bug fixes:
+
+* [BUG #437](https://github.com/rust-lang/regex/issues/437):
+  Fixes a bug in the new Boyer-Moore searcher that results in a panic.
+
+
+0.2.4 (2017-12-30)
+==================
+New features:
+
+* [FEATURE #348](https://github.com/rust-lang/regex/pull/348):
+  Improve performance for capture searches on anchored regex.
+  (Contributed by @ethanpailes. Nice work!)
+* [FEATURE #419](https://github.com/rust-lang/regex/pull/419):
+  Expand literal searching to include Tuned Boyer-Moore in some cases.
+  (Contributed by @ethanpailes. Nice work!)
+
+Bug fixes:
+
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  The regex compiler plugin has been removed.
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  `simd` has been bumped to `0.2.1`, which fixes a Rust nightly build error.
+* [BUG](https://github.com/rust-lang/regex/pull/436):
+  Bring the benchmark harness up to date.
+
+
+0.2.3 (2017-11-30)
+==================
+New features:
+
+* [FEATURE #374](https://github.com/rust-lang/regex/pull/374):
+  Add `impl From<Match> for &str`.
+* [FEATURE #380](https://github.com/rust-lang/regex/pull/380):
+  Derive `Clone` and `PartialEq` on `Error`.
+* [FEATURE #400](https://github.com/rust-lang/regex/pull/400):
+  Update to Unicode 10.
+
+Bug fixes:
+
+* [BUG #375](https://github.com/rust-lang/regex/issues/375):
+  Fix a bug that prevented the bounded backtracker from terminating.
+* [BUG #393](https://github.com/rust-lang/regex/issues/393),
+  [BUG #394](https://github.com/rust-lang/regex/issues/394):
+  Fix bug with `replace` methods for empty matches.
+
+
 0.2.2 (2017-05-21)
 ==================
 New features:
 
 * [FEATURE #341](https://github.com/rust-lang/regex/issues/341):
   Support nested character classes and intersection operation.
   For example, `[\p{Greek}&&\pL]` matches greek letters and
   `[[0-9]&&[^4]]` matches every decimal digit except `4`.
diff --git a/third_party/rust/regex/Cargo.toml b/third_party/rust/regex/Cargo.toml
index 664f34b16d60..b44ba771d3d9 100644
--- a/third_party/rust/regex/Cargo.toml
+++ b/third_party/rust/regex/Cargo.toml
@@ -1,94 +1,105 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
 name = "regex"
-version = "0.2.2"  #:version
+version = "1.0.5"
 authors = ["The Rust Project Developers"]
-license = "MIT/Apache-2.0"
-readme = "README.md"
-repository = "https://github.com/rust-lang/regex"
-documentation = "https://doc.rust-lang.org/regex"
+autotests = false
+description = "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n"
 homepage = "https://github.com/rust-lang/regex"
-description = """
-An implementation of regular expressions for Rust. This implementation uses
-finite automata and guarantees linear time matching on all inputs.
-"""
+documentation = "https://docs.rs/regex"
+readme = "README.md"
 categories = ["text-processing"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/regex"
+[profile.test]
+debug = true
 
-[dependencies]
-# For very fast prefix literal matching.
-aho-corasick = "0.6.0"
-# For skipping along search text quickly when a leading byte is known.
-memchr = "1.0.0"
-# For managing regex caches quickly across multiple threads.
-thread_local = "0.3.2"
-# For parsing regular expressions.
-regex-syntax = { path = "regex-syntax", version = "0.4.1" }
-# For accelerating text search.
-simd = { version = "0.1.1", optional = true }
-# For compiling UTF-8 decoding into automata.
-utf8-ranges = "1.0.0"
-
-[dev-dependencies]
-# For examples.
-lazy_static = "0.2.2"
-# For property based tests.
-quickcheck = { version = "0.4.1", default-features = false }
-# For generating random test data.
-rand = "0.3.15"
+[profile.bench]
+debug = true
 
-[features]
-# Enable to use the unstable pattern traits defined in std.
-pattern = []
-# Enable to use simd acceleration.
-simd-accel = ["simd"]
+[profile.release]
+debug = true
 
 [lib]
-# There are no benchmarks in the library code itself
 bench = false
 
-# Run the test suite on the default behavior of Regex::new.
-# This includes a mish mash of NFAs and DFAs, which are chosen automatically
-# based on the regex. We test both of the NFA implementations by forcing their
-# usage with the test definitions below. (We can't test the DFA implementations
-# in the same way since they can't be used for every regex tested.)
 [[test]]
-path = "tests/test_default.rs"
 name = "default"
+path = "tests/test_default.rs"
 
-# The same as the default tests, but run on bytes::Regex.
 [[test]]
-path = "tests/test_default_bytes.rs"
 name = "default-bytes"
+path = "tests/test_default_bytes.rs"
 
-# Run the test suite on the NFA algorithm over Unicode codepoints.
 [[test]]
-path = "tests/test_nfa.rs"
 name = "nfa"
+path = "tests/test_nfa.rs"
 
-# Run the test suite on the NFA algorithm over bytes that match UTF-8 only.
 [[test]]
-path = "tests/test_nfa_utf8bytes.rs"
 name = "nfa-utf8bytes"
+path = "tests/test_nfa_utf8bytes.rs"
 
-# Run the test suite on the NFA algorithm over arbitrary bytes.
 [[test]]
-path = "tests/test_nfa_bytes.rs"
 name = "nfa-bytes"
+path = "tests/test_nfa_bytes.rs"
 
-# Run the test suite on the backtracking engine over Unicode codepoints.
 [[test]]
-path = "tests/test_backtrack.rs"
 name = "backtrack"
+path = "tests/test_backtrack.rs"
 
-# Run the test suite on the backtracking engine over bytes that match UTF-8
-# only.
 [[test]]
-path = "tests/test_backtrack_utf8bytes.rs"
 name = "backtrack-utf8bytes"
+path = "tests/test_backtrack_utf8bytes.rs"
 
-# Run the test suite on the backtracking engine over arbitrary bytes.
 [[test]]
-path = "tests/test_backtrack_bytes.rs"
 name = "backtrack-bytes"
+path = "tests/test_backtrack_bytes.rs"
 
-[profile.test]
-debug = true
+[[test]]
+name = "crates-regex"
+path = "tests/test_crates_regex.rs"
+[dependencies.aho-corasick]
+version = "0.6.7"
+
+[dependencies.memchr]
+version = "2.0.2"
+
+[dependencies.regex-syntax]
+version = "0.6.2"
+
+[dependencies.thread_local]
+version = "0.3.6"
+
+[dependencies.utf8-ranges]
+version = "1.0.1"
+[dev-dependencies.lazy_static]
+version = "1"
+
+[dev-dependencies.quickcheck]
+version = "0.7"
+default-features = false
+
+[dev-dependencies.rand]
+version = "0.5"
+
+[features]
+default = ["use_std"]
+pattern = []
+unstable = ["pattern"]
+use_std = []
+[badges.appveyor]
+repository = "rust-lang-libs/regex"
+
+[badges.travis-ci]
+repository = "rust-lang/regex"
diff --git a/third_party/rust/regex/HACKING.md b/third_party/rust/regex/HACKING.md
index 28b9fcb5d7a6..160bbc328b49 100644
--- a/third_party/rust/regex/HACKING.md
+++ b/third_party/rust/regex/HACKING.md
@@ -180,47 +180,46 @@ engine. This scratch space is used during search (for example, for the lazy
 DFA, it contains compiled states that are reused on subsequent searches).
 
 ### Programs
 
 A regular expression program is essentially a sequence of opcodes produced by
 the compiler plus various facts about the regular expression (such as whether
 it is anchored, its capture names, etc.).
 
-### The regex! macro (or why `regex::internal` exists)
-
-The `regex!` macro is defined in the `regex_macros` crate as a compiler plugin,
-which is maintained in this repository. The `regex!` macro compiles a regular
-expression at compile time into specialized Rust code.
-
-The `regex!` macro was written when this library was first conceived and
-unfortunately hasn't changed much since then. In particular, it encodes the
-entire Pike VM into stack allocated space (no heap allocation is done). When
-`regex!` was first written, this provided a substantial speed boost over
-so-called "dynamic" regexes compiled at runtime, and in particular had much
-lower overhead per match. This was because the only matching engine at the
-time was the Pike VM. The addition of other matching engines has inverted
-the relationship; the `regex!` macro is almost never faster than the dynamic
-variant. (In fact, it is typically substantially slower.)
-
-In order to build the `regex!` macro this way, it must have access to some
-internals of the regex library, which is in a distinct crate. (Compiler plugins
-must be part of a distinct crate.) Namely, it must be able to compile a regular
-expression and access its opcodes. The necessary internals are exported as part
-of the top-level `internal` module in the regex library, but is hidden from
-public documentation. In order to present a uniform API between programs build
-by the `regex!` macro and their dynamic analoges, the `Regex` type is an enum
-whose variants are hidden from public documentation.
-
-In the future, the `regex!` macro should probably work more like Ragel, but
-it's not clear how hard this is. In particular, the `regex!` macro should be
-able to support all the features of dynamic regexes, which may be hard to do
-with a Ragel-style implementation approach. (Which somewhat suggests that the
-`regex!` macro may also need to grow conditional execution logic like the
-dynamic variants, which seems rather grotesque.)
+### The regex! macro
+
+The `regex!` macro no longer exists. It was developed in a bygone era as a
+compiler plugin during the infancy of the regex crate. Back then, then only
+matching engine in the crate was the Pike VM. The `regex!` macro was, itself,
+also a Pike VM. The only advantages it offered over the dynamic Pike VM that
+was built at runtime were the following:
+
+  1. Syntax checking was done at compile time. Your Rust program wouldn't
+     compile if your regex didn't compile.
+  2. Reduction of overhead that was proportional to the size of the regex.
+     For the most part, this overhead consisted of heap allocation, which
+     was nearly eliminated in the compiler plugin.
+
+The main takeaway here is that the compiler plugin was a marginally faster
+version of a slow regex engine. As the regex crate evolved, it grew other regex
+engines (DFA, bounded backtracker) and sophisticated literal optimizations.
+The regex macro didn't keep pace, and it therefore became (dramatically) slower
+than the dynamic engines. The only reason left to use it was for the compile
+time guarantee that your regex is correct. Fortunately, Clippy (the Rust lint
+tool) has a lint that checks your regular expression validity, which mostly
+replaces that use case.
+
+Additionally, the regex compiler plugin stopped receiving maintenance. Nobody
+complained. At that point, it seemed prudent to just remove it.
+
+Will a compiler plugin be brought back? The future is murky, but there is
+definitely an opportunity there to build something that is faster than the
+dynamic engines in some cases. But it will be challenging! As of now, there
+are no plans to work on this.
 
 
 ## Testing
 
 A key aspect of any mature regex library is its test suite. A subset of the
 tests in this library come from Glenn Fowler's AT&T test suite (its online
 presence seems gone at the time of writing). The source of the test suite is
 located in src/testdata. The scripts/regex-match-tests.py takes the test suite
@@ -231,85 +230,112 @@ tests/tests.rs. Some of these tests were taken from RE2.
 
 The biggest source of complexity in the tests is related to answering this
 question: how can we reuse the tests to check all of our matching engines? One
 approach would have been to encode every test into some kind of format (like
 the AT&T test suite) and code generate tests for each matching engine. The
 approach we use in this library is to create a Cargo.toml entry point for each
 matching engine we want to test. The entry points are:
 
-* `tests/test_plugin.rs` - tests the `regex!` macro
 * `tests/test_default.rs` - tests `Regex::new`
 * `tests/test_default_bytes.rs` - tests `bytes::Regex::new`
 * `tests/test_nfa.rs` - tests `Regex::new`, forced to use the NFA
   algorithm on every regex.
 * `tests/test_nfa_bytes.rs` - tests `Regex::new`, forced to use the NFA
   algorithm on every regex and use *arbitrary* byte based programs.
 * `tests/test_nfa_utf8bytes.rs` - tests `Regex::new`, forced to use the NFA
   algorithm on every regex and use *UTF-8* byte based programs.
 * `tests/test_backtrack.rs` - tests `Regex::new`, forced to use
   backtracking on every regex.
 * `tests/test_backtrack_bytes.rs` - tests `Regex::new`, forced to use
   backtracking on every regex and use *arbitrary* byte based programs.
 * `tests/test_backtrack_utf8bytes.rs` - tests `Regex::new`, forced to use
   backtracking on every regex and use *UTF-8* byte based programs.
+* `tests/test_crates_regex.rs` - tests to make sure that all of the
+  backends behave in the same way against a number of quickcheck
+  generated random inputs. These tests need to be enabled through
+  the `RUST_REGEX_RANDOM_TEST` environment variable (see
+  below).
 
 The lazy DFA and pure literal engines are absent from this list because
 they cannot be used on every regular expression. Instead, we rely on
 `tests/test_dynamic.rs` to test the lazy DFA and literal engines when possible.
 
 Since the tests are repeated several times, and because `cargo test` runs all
 entry points, it can take a while to compile everything. To reduce compile
 times slightly, try using `cargo test --test default`, which will only use the
 `tests/test_default.rs` entry point.
 
-N.B. To run tests for the `regex!` macro, use:
-
-    cargo test --manifest-path regex_macros/Cargo.toml
-
+The random testing takes quite a while, so it is not enabled by default.
+In order to run the random testing you can set the
+`RUST_REGEX_RANDOM_TEST` environment variable to anything before
+invoking `cargo test`. Note that this variable is inspected at compile
+time, so if the tests don't seem to be running, you may need to run
+`cargo clean`.
 
 ## Benchmarking
 
 The benchmarking in this crate is made up of many micro-benchmarks. Currently,
 there are two primary sets of benchmarks: the benchmarks that were adopted
-at this library's inception (in `benches/src/misc.rs`) and a newer set of
+at this library's inception (in `bench/src/misc.rs`) and a newer set of
 benchmarks meant to test various optimizations. Specifically, the latter set
-contain some analysis and are in `benches/src/sherlock.rs`. Also, the latter
+contain some analysis and are in `bench/src/sherlock.rs`. Also, the latter
 set are all executed on the same lengthy input whereas the former benchmarks
 are executed on strings of varying length.
 
 There is also a smattering of benchmarks for parsing and compilation.
 
 Benchmarks are in a separate crate so that its dependencies can be managed
 separately from the main regex crate.
 
 Benchmarking follows a similarly wonky setup as tests. There are multiple entry
 points:
 
-* `bench_rust_plugin.rs` - benchmarks the `regex!` macro
 * `bench_rust.rs` - benchmarks `Regex::new`
 * `bench_rust_bytes.rs` benchmarks `bytes::Regex::new`
 * `bench_pcre.rs` - benchmarks PCRE
 * `bench_onig.rs` - benchmarks Oniguruma
 
 The PCRE and Oniguruma benchmarks exist as a comparison point to a mature
 regular expression library. In general, this regex library compares favorably
 (there are even a few benchmarks that PCRE simply runs too slowly on or
 outright can't execute at all). I would love to add other regular expression
 library benchmarks (especially RE2).
 
 If you're hacking on one of the matching engines and just want to see
 benchmarks, then all you need to run is:
 
-    $ ./run-bench rust
+    $ ./bench/run rust
 
 If you want to compare your results with older benchmarks, then try:
 
-    $ ./run-bench rust | tee old
+    $ ./bench/run rust | tee old
     $ ... make it faster
-    $ ./run-bench rust | tee new
-    $ cargo-benchcmp old new --improvements
+    $ ./bench/run rust | tee new
+    $ cargo benchcmp old new --improvements
 
 The `cargo-benchcmp` utility is available here:
 https://github.com/BurntSushi/cargo-benchcmp
 
-The `run-bench` utility can run benchmarks for PCRE and Oniguruma too. See
-`./run-bench --help`.
+The `./bench/run` utility can run benchmarks for PCRE and Oniguruma too. See
+`./bench/bench --help`.
+
+## Dev Docs
+
+When digging your teeth into the codebase for the first time, the
+crate documentation can be a great resource. By default `rustdoc`
+will strip out all documentation of private crate members in an
+effort to help consumers of the crate focus on the *interface*
+without having to concern themselves with the *implementation*.
+Normally this is a great thing, but if you want to start hacking
+on regex internals it is not what you want. Many of the private members
+of this crate are well documented with rustdoc style comments, and
+it would be a shame to miss out on the opportunity that presents.
+You can generate the private docs with:
+
+```
+$ rustdoc --crate-name docs src/lib.rs -o target/doc -L target/debug/deps --no-defaults --passes collapse-docs --passes unindent-comments
+```
+
+Then just point your browser at `target/doc/regex/index.html`.
+
+See https://github.com/rust-lang/rust/issues/15347 for more info
+about generating developer docs for internal use.
diff --git a/third_party/rust/regex/PERFORMANCE.md b/third_party/rust/regex/PERFORMANCE.md
index 6b143262d409..b4aeb89c1b17 100644
--- a/third_party/rust/regex/PERFORMANCE.md
+++ b/third_party/rust/regex/PERFORMANCE.md
@@ -1,13 +1,13 @@
 Your friendly guide to understanding the performance characteristics of this
 crate.
 
 This guide assumes some familiarity with the public API of this crate, which
-can be found here: http://doc.rust-lang.org/regex/regex/index.html
+can be found here: https://docs.rs/regex
 
 ## Theory vs. Practice
 
 One of the design goals of this crate is to provide worst case linear time
 behavior with respect to the text searched using finite state automata. This
 means that, *in theory*, the performance of this crate is much better than most
 regex implementations, which typically use backtracking which has worst case
 exponential time.
diff --git a/third_party/rust/regex/README.md b/third_party/rust/regex/README.md
index 1384fb55420f..82420bd377cd 100644
--- a/third_party/rust/regex/README.md
+++ b/third_party/rust/regex/README.md
@@ -6,34 +6,35 @@ like look around and backreferences. In exchange, all searches execute in
 linear time with respect to the size of the regular expression and search text.
 Much of the syntax and implementation is inspired
 by [RE2](https://github.com/google/re2).
 
 [![Build Status](https://travis-ci.org/rust-lang/regex.svg?branch=master)](https://travis-ci.org/rust-lang/regex)
 [![Build status](https://ci.appveyor.com/api/projects/status/github/rust-lang/regex?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/regex)
 [![Coverage Status](https://coveralls.io/repos/github/rust-lang/regex/badge.svg?branch=master)](https://coveralls.io/github/rust-lang/regex?branch=master)
 [![](http://meritbadge.herokuapp.com/regex)](https://crates.io/crates/regex)
+[![Rust](https://img.shields.io/badge/rust-1.20%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/regex)
 
 ### Documentation
 
-[Module documentation with examples](https://doc.rust-lang.org/regex).
-The module documentation also include a comprehensive description of the syntax
-supported.
+[Module documentation with examples](https://docs.rs/regex).
+The module documentation also includes a comprehensive description of the
+syntax supported.
 
 Documentation with examples for the various matching functions and iterators
 can be found on the
-[`Regex` type](https://doc.rust-lang.org/regex/regex/struct.Regex.html).
+[`Regex` type](https://docs.rs/regex/*/regex/struct.Regex.html).
 
 ### Usage
 
 Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-regex = "0.2"
+regex = "1"
 ```
 
 and this to your crate root:
 
 ```rust
 extern crate regex;
 ```
 
@@ -183,58 +184,51 @@ let matches: Vec<_> = set.matches("foobar").into_iter().collect();
 assert_eq!(matches, vec![0, 2, 3, 4, 6]);
 
 // You can also test whether a particular regex matched:
 let matches = set.matches("foobar");
 assert!(!matches.matched(5));
 assert!(matches.matched(6));
 ```
 
-### Usage: `regex!` compiler plugin
+### Usage: enable SIMD optimizations
 
-**WARNING**: The `regex!` compiler plugin is orders of magnitude slower than
-the normal `Regex::new(...)` usage. You should not use the compiler plugin
-unless you have a very special reason for doing so. The performance difference
-may be the temporary, but the path forward at this point isn't clear.
+SIMD optimizations are enabled automatically on Rust stable 1.27 and newer.
+For nightly versions of Rust, this requires a recent version with the SIMD
+features stabilized.
 
-The `regex!` compiler plugin will compile your regexes at compile time. **This
-only works with a nightly compiler.**
 
-Here is a small example:
+### Usage: a regular expression parser
 
-```rust
-#![feature(plugin)]
+This repository contains a crate that provides a well tested regular expression
+parser, abstract syntax and a high-level intermediate representation for
+convenient analysis. It provides no facilities for compilation or execution.
+This may be useful if you're implementing your own regex engine or otherwise
+need to do analysis on the syntax of a regular expression. It is otherwise not
+recommended for general use.
 
-#![plugin(regex_macros)]
-extern crate regex;
+[Documentation `regex-syntax`.](https://docs.rs/regex-syntax)
 
-fn main() {
-    let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
-    let caps = re.captures("2010-03-14").unwrap();
 
-    assert_eq!("2010", caps[1]);
-    assert_eq!("03", caps[2]);
-    assert_eq!("14", caps[3]);
-}
-```
+### Minimum Rust version policy
 
-Notice that we never `unwrap` the result of `regex!`. This is because your
-*program* won't compile if the regex doesn't compile. (Try `regex!("(")`.)
+This crate's minimum supported `rustc` version is `1.20.0`.
 
+The current **tentative** policy is that the minimum Rust version required
+to use this crate can be increased in minor version updates. For example, if
+regex 1.0 requires Rust 1.20.0, then regex 1.0.z for all values of `z` will
+also require Rust 1.20.0 or newer. However, regex 1.y for `y > 0` may require a
+newer minimum version of Rust.
 
-### Usage: a regular expression parser
+In general, this crate will be conservative with respect to the minimum
+supported version of Rust.
 
-This repository contains a crate that provides a well tested regular expression
-parser and abstract syntax. It provides no facilities for compilation or
-execution. This may be useful if you're implementing your own regex engine or
-otherwise need to do analysis on the syntax of a regular expression. It is
-otherwise not recommended for general use.
 
-[Documentation for `regex-syntax` with
-examples](https://doc.rust-lang.org/regex/regex_syntax/index.html).
+### License
 
-# License
+This project is licensed under either of
 
-`regex` is primarily distributed under the terms of both the MIT license and
-the Apache License (Version 2.0), with portions covered by various BSD-like
-licenses.
+ * 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)
 
-See LICENSE-APACHE, and LICENSE-MIT for details.
+at your option.
diff --git a/third_party/rust/regex/UNICODE.md b/third_party/rust/regex/UNICODE.md
new file mode 100644
index 000000000000..0a3b783ae42a
--- /dev/null
+++ b/third_party/rust/regex/UNICODE.md
@@ -0,0 +1,250 @@
+# Unicode conformance
+
+This document describes the regex crate's conformance to Unicode's
+[UTS#18](http://unicode.org/reports/tr18/)
+report, which lays out 3 levels of support: Basic, Extended and Tailored.
+
+Full support for Level 1 ("Basic Unicode Support") is provided with two
+exceptions:
+
+1. Line boundaries are not Unicode aware. Namely, only the `\n`
+   (`END OF LINE`) character is recognized as a line boundary.
+2. The compatibility properties specified by
+   [RL1.2a](http://unicode.org/reports/tr18/#RL1.2a)
+   are ASCII-only definitions.
+
+Little to no support is provided for either Level 2 or Level 3. For the most
+part, this is because the features are either complex/hard to implement, or at
+the very least, very difficult to implement without sacrificing performance.
+For example, tackling canonical equivalence such that matching worked as one
+would expect regardless of normalization form would be a significant
+undertaking. This is at least partially a result of the fact that this regex
+engine is based on finite automata, which admits less flexibility normally
+associated with backtracking implementations.
+
+
+## RL1.1 Hex Notation
+
+[UTS#18 RL1.1](https://unicode.org/reports/tr18/#Hex_notation)
+
+Hex Notation refers to the ability to specify a Unicode code point in a regular
+expression via its hexadecimal code point representation. This is useful in
+environments that have poor Unicode font rendering or if you need to express a
+code point that is not normally displayable. All forms of hexadecimal notation
+are supported
+
+    \x7F        hex character code (exactly two digits)
+    \x{10FFFF}  any hex character code corresponding to a Unicode code point
+    \u007F      hex character code (exactly four digits)
+    \u{7F}      any hex character code corresponding to a Unicode code point
+    \U0000007F  hex character code (exactly eight digits)
+    \U{7F}      any hex character code corresponding to a Unicode code point
+
+Briefly, the `\x{...}`, `\u{...}` and `\U{...}` are all exactly equivalent ways
+of expressing hexadecimal code points. Any number of digits can be written
+within the brackets. In contrast, `\xNN`, `\uNNNN`, `\UNNNNNNNN` are all
+fixed-width variants of the same idea.
+
+Note that when Unicode mode is disabled, any non-ASCII Unicode codepoint is
+banned. Additionally, the `\xNN` syntax represents arbitrary bytes when Unicode
+mode is disabled. That is, the regex `\xFF` matches the Unicode codepoint
+U+00FF (encoded as `\xC3\xBF` in UTF-8) while the regex `(?-u)\xFF` matches
+the literal byte `\xFF`.
+
+
+## RL1.2 Properties
+
+[UTS#18 RL1.2](https://unicode.org/reports/tr18/#Categories)
+
+Full support for Unicode property syntax is provided. Unicode properties
+provide a convenient way to construct character classes of groups of code
+points specified by Unicode. The regex crate does not provide exhaustive
+support, but covers a useful subset. In particular:
+
+* [General categories](http://unicode.org/reports/tr18/#General_Category_Property)
+* [Scripts and Script Extensions](http://unicode.org/reports/tr18/#Script_Property)
+* [Age](http://unicode.org/reports/tr18/#Age)
+* A smattering of boolean properties, including all of those specified by
+  [RL1.2](http://unicode.org/reports/tr18/#RL1.2) explicitly.
+
+In all cases, property name and value abbreviations are supported, and all
+names/values are matched loosely without regard for case, whitespace or
+underscores. Property name aliases can be found in Unicode's
+[`PropertyAliases.txt`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt)
+file, while property value aliases can be found in Unicode's
+[`PropertyValueAliases.txt`](http://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt)
+file.
+
+The syntax supported is also consistent with the UTS#18 recommendation:
+
+* `\p{Greek}` selects the `Greek` script. Equivalent expressions follow:
+  `\p{sc:Greek}`, `\p{Script:Greek}`, `\p{Sc=Greek}`, `\p{script=Greek}`,
+  `\P{sc!=Greek}`. Similarly for `General_Category` (or `gc` for short) and
+  `Script_Extensions` (or `scx` for short).
+* `\p{age:3.2}` selects all code points in Unicode 3.2.
+* `\p{Alphabetic}` selects the "alphabetic" property and can be abbreviated
+  via `\p{alpha}` (for example).
+* Single letter variants for properties with single letter abbreviations.
+  For example, `\p{Letter}` can be equivalently written as `\pL`.
+
+The following is a list of all properties supported by the regex crate (starred
+properties correspond to properties required by RL1.2):
+
+* `General_Category` \* (including `Any`, `ASCII` and `Assigned`)
+* `Script` \*
+* `Script_Extensions` \*
+* `Age`
+* `ASCII_Hex_Digit`
+* `Alphabetic` \*
+* `Bidi_Control`
+* `Case_Ignorable`
+* `Cased`
+* `Changes_When_Casefolded`
+* `Changes_When_Casemapped`
+* `Changes_When_Lowercased`
+* `Changes_When_Titlecased`
+* `Changes_When_Uppercased`
+* `Dash`
+* `Default_Ignorable_Code_Point` \*
+* `Deprecated`
+* `Diacritic`
+* `Extender`
+* `Grapheme_Base`
+* `Grapheme_Extend`
+* `Hex_Digit`
+* `IDS_Binary_Operator`
+* `IDS_Trinary_Operator`
+* `ID_Continue`
+* `ID_Start`
+* `Join_Control`
+* `Logical_Order_Exception`
+* `Lowercase` \*
+* `Math`
+* `Noncharacter_Code_Point` \*
+* `Pattern_Syntax`
+* `Pattern_White_Space`
+* `Prepended_Concatenation_Mark`
+* `Quotation_Mark`
+* `Radical`
+* `Regional_Indicator`
+* `Sentence_Terminal`
+* `Soft_Dotted`
+* `Terminal_Punctuation`
+* `Unified_Ideograph`
+* `Uppercase` \*
+* `Variation_Selector`
+* `White_Space` \*
+* `XID_Continue`
+* `XID_Start`
+
+
+## RL1.2a Compatibility Properties
+
+[UTS#18 RL1.2a](http://unicode.org/reports/tr18/#RL1.2a)
+
+The regex crate only provides ASCII definitions of the
+[compatibility properties documented in UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties)
+(sans the `\X` class, for matching grapheme clusters, which isn't provided
+at all). This is because it seems to be consistent with most other regular
+expression engines, and in particular, because these are often referred to as
+"ASCII" or "POSIX" character classes.
+
+Note that the `\w`, `\s` and `\d` character classes **are** Unicode aware.
+Their traditional ASCII definition can be used by disabling Unicode. That is,
+`[[:word:]]` and `(?-u)\w` are equivalent.
+
+
+## RL1.3 Subtraction and Intersection
+
+[UTS#18 RL1.3](http://unicode.org/reports/tr18/#Subtraction_and_Intersection)
+
+The regex crate provides full support for nested character classes, along with
+union, intersection (`&&`), difference (`--`) and symmetric difference (`~~`)
+operations on arbitrary character classes.
+
+For example, to match all non-ASCII letters, you could use either
+`[\p{Letter}--\p{Ascii}]` (difference) or `[\p{Letter}&&[^\p{Ascii}]]`
+(intersecting the negation).
+
+
+## RL1.4 Simple Word Boundaries
+
+[UTS#18 RL1.4](http://unicode.org/reports/tr18/#Simple_Word_Boundaries)
+
+The regex crate provides basic Unicode aware word boundary assertions. A word
+boundary assertion can be written as `\b`, or `\B` as its negation. A word
+boundary negation corresponds to a zero-width match, where its adjacent
+characters correspond to word and non-word, or non-word and word characters.
+
+Conformance in this case chooses to define word character in the same way that
+the `\w` character class is defined: a code point that is a member of one of
+the following classes:
+
+* `\p{Alphabetic}`
+* `\p{Join_Control}`
+* `\p{gc:Mark}`
+* `\p{gc:Decimal_Number}`
+* `\p{gc:Connector_Punctuation}`
+
+In particular, this differs slightly from the
+[prescription given in RL1.4](http://unicode.org/reports/tr18/#Simple_Word_Boundaries)
+but is permissible according to
+[UTS#18 Annex C](http://unicode.org/reports/tr18/#Compatibility_Properties).
+Namely, it is convenient and simpler to have `\w` and `\b` be in sync with
+one another.
+
+Finally, Unicode word boundaries can be disabled, which will cause ASCII word
+boundaries to be used instead. That is, `\b` is a Unicode word boundary while
+`(?-u)\b` is an ASCII-only word boundary. This can occasionally be beneficial
+if performance is important, since the implementation of Unicode word
+boundaries is currently sub-optimal on non-ASCII text.
+
+
+## RL1.5 Simple Loose Matches
+
+[UTS#18 RL1.5](http://unicode.org/reports/tr18/#Simple_Loose_Matches)
+
+The regex crate provides full support for case insensitive matching in
+accordance with RL1.5. That is, it uses the "simple" case folding mapping. The
+"simple" mapping was chosen because of a key convenient property: every
+"simple" mapping is a mapping from exactly one code point to exactly one other
+code point. This makes case insensitive matching of character classes, for
+example, straight-forward to implement.
+
+When case insensitive mode is enabled (e.g., `(?i)[a]` is equivalent to `a|A`),
+then all characters classes are case folded as well.
+
+
+## RL1.6 Line Boundaries
+
+[UTS#18 RL1.6](http://unicode.org/reports/tr18/#Line_Boundaries)
+
+The regex crate only provides support for recognizing the `\n` (`END OF LINE`)
+character as a line boundary. This choice was made mostly for implementation
+convenience, and to avoid performance cliffs that Unicode word boundaries are
+subject to.
+
+Ideally, it would be nice to at least support `\r\n` as a line boundary as
+well, and in theory, this could be done efficiently.
+
+
+## RL1.7 Code Points
+
+[UTS#18 RL1.7](http://unicode.org/reports/tr18/#Supplementary_Characters)
+
+The regex crate provides full support for Unicode code point matching. Namely,
+the fundamental atom of any match is always a single code point.
+
+Given Rust's strong ties to UTF-8, the following guarantees are also provided:
+
+* All matches are reported on valid UTF-8 code unit boundaries. That is, any
+  match range returned by the public regex API is guaranteed to successfully
+  slice the string that was searched.
+* By consequence of the above, it is impossible to match surrogode code points.
+  No support for UTF-16 is provided, so this is never necessary.
+
+Note that when Unicode mode is disabled, the fundamental atom of matching is
+no longer a code point but a single byte. When Unicode mode is disabled, many
+Unicode features are disabled as well. For example, `(?-u)\pL` is not a valid
+regex but `\pL(?-u)\xFF` (matches any Unicode `Letter` followed by the literal
+byte `\xFF`) is, for example.
diff --git a/third_party/rust/regex/appveyor.yml b/third_party/rust/regex/appveyor.yml
index 0933ad8cc3f8..c67ab0efdaca 100644
--- a/third_party/rust/regex/appveyor.yml
+++ b/third_party/rust/regex/appveyor.yml
@@ -5,13 +5,15 @@ environment:
   - TARGET: i686-pc-windows-gnu
 install:
   - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
   - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
   - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
   - SET PATH=%PATH%;C:\MinGW\bin
   - rustc -V
   - cargo -V
-
 build: false
-
 test_script:
   - cargo test --verbose --jobs 4
+branches:
+  only:
+    - master
+    - auto
diff --git a/third_party/rust/regex/build.rs b/third_party/rust/regex/build.rs
new file mode 100644
index 000000000000..9440ab92d734
--- /dev/null
+++ b/third_party/rust/regex/build.rs
@@ -0,0 +1,86 @@
+use std::env;
+use std::ffi::OsString;
+use std::process::Command;
+
+fn main() {
+    let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
+    let output = Command::new(&rustc)
+        .arg("--version")
+        .output()
+        .unwrap()
+        .stdout;
+    let version = String::from_utf8(output).unwrap();
+
+    enable_simd_optimizations(&version);
+}
+
+fn enable_simd_optimizations(version: &str) {
+    // We don't activate SIMD optimizations these if we've explicitly disabled
+    // them. Disabling auto optimizations is intended for use in tests, so that
+    // we can reliably test fallback implementations.
+    if env::var_os("CARGO_CFG_REGEX_DISABLE_AUTO_OPTIMIZATIONS").is_some() {
+        return;
+    }
+    let parsed = match Version::parse(&version) {
+        Ok(parsed) => parsed,
+        Err(err) => {
+            eprintln!("failed to parse `rustc --version`: {}", err);
+            return;
+        }
+    };
+    let minimum = Version { major: 1, minor: 27, patch: 0 };
+    if version.contains("nightly") || parsed >= minimum {
+        println!("cargo:rustc-cfg=regex_runtime_teddy_ssse3");
+        println!("cargo:rustc-cfg=regex_runtime_teddy_avx2");
+    }
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+struct Version {
+    major: u32,
+    minor: u32,
+    patch: u32,
+}
+
+impl Version {
+    fn parse(mut s: &str) -> Result<Version, String> {
+        if !s.starts_with("rustc ") {
+            return Err(format!("unrecognized version string: {}", s));
+        }
+        s = &s["rustc ".len()..];
+
+        let parts: Vec<&str> = s.split(".").collect();
+        if parts.len() < 3 {
+            return Err(format!("not enough version parts: {:?}", parts));
+        }
+
+        let mut num = String::new();
+        for c in parts[0].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let major = num.parse::<u32>().map_err(|e| e.to_string())?;
+
+        num.clear();
+        for c in parts[1].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let minor = num.parse::<u32>().map_err(|e| e.to_string())?;
+
+        num.clear();
+        for c in parts[2].chars() {
+            if !c.is_digit(10) {
+                break;
+            }
+            num.push(c);
+        }
+        let patch = num.parse::<u32>().map_err(|e| e.to_string())?;
+
+        Ok(Version { major, minor, patch })
+    }
+}
diff --git a/third_party/rust/regex/ci/after_success.sh b/third_party/rust/regex/ci/after_success.sh
index 2cf60f16e59f..4e11477e70f4 100755
--- a/third_party/rust/regex/ci/after_success.sh
+++ b/third_party/rust/regex/ci/after_success.sh
@@ -6,25 +6,16 @@
 set -e
 
 if [ "$TRAVIS_RUST_VERSION" != "nightly" ] || [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" != "master" ]; then
   exit 0
 fi
 
 env
 
-# Build and upload docs.
-echo '<meta http-equiv=refresh content=0;url=regex/index.html>' > target/doc/index.html
-ve=$(mktemp -d)
-virtualenv "$ve"
-"$ve"/bin/pip install --upgrade pip
-"$ve"/bin/pip install ghp-import
-"$ve"/bin/ghp-import -n target/doc
-git push -qf https://${TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
-
 # Install kcov.
 tmp=$(mktemp -d)
 pushd "$tmp"
 wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz
 tar zxf master.tar.gz
 mkdir kcov-master/build
 cd kcov-master/build
 cmake ..
diff --git a/third_party/rust/regex/ci/run-kcov b/third_party/rust/regex/ci/run-kcov
index 092123775d10..78f5b96b3a5b 100755
--- a/third_party/rust/regex/ci/run-kcov
+++ b/third_party/rust/regex/ci/run-kcov
@@ -9,45 +9,31 @@ tests=(
   backtrack_utf8bytes
   backtrack_bytes
   nfa
   nfa_utf8bytes
   nfa_bytes
   regex
 )
 tmpdir=$(mktemp -d)
-with_plugin=
 coveralls_id=
 
 while true; do
   case "$1" in
-    --with-plugin)
-      with_plugin=yes
-      shift
-      ;;
     --coveralls-id)
       coveralls_id="$2"
       shift 2
       ;;
     *)
       break
       ;;
   esac
 done
 
-if [ -n "$with_plugin" ]; then
-  cargo test --manifest-path regex_macros/Cargo.toml --no-run --verbose
-  kcov \
-    --verify \
-    --include-pattern '/regex/src/' \
-    "$tmpdir/plugin" \
-    $(ls -t ./regex_macros/target/debug/plugin-* | head -n1)
-fi
-
-cargo test --no-run --verbose --jobs 4
+cargo test --no-run --verbose --jobs 4 --features unstable
 for t in ${tests[@]}; do
   kcov \
     --verify \
     --include-pattern '/regex/src/' \
     "$tmpdir/$t" \
     $(find ./target/debug -executable -wholename "./target/debug/$t-*" | head -n1)
 done
 
diff --git a/third_party/rust/regex/ci/script.sh b/third_party/rust/regex/ci/script.sh
index 2b48aa5d7ff5..edc7ecaae4c8 100755
--- a/third_party/rust/regex/ci/script.sh
+++ b/third_party/rust/regex/ci/script.sh
@@ -1,35 +1,56 @@
 #!/bin/sh
 
 # This is the main CI script for testing the regex crate and its sub-crates.
 
-set -e
+set -ex
 
 # Builds the regex crate and runs tests.
 cargo build --verbose
 cargo doc --verbose
+
+# If we're testing on an older version of Rust, then only check that we
+# can build the crate. This is because the dev dependencies might be updated
+# more frequently, and therefore might require a newer version of Rust.
+#
+# This isn't ideal. It's a compromise.
+if [ "$TRAVIS_RUST_VERSION" = "1.20.0" ]; then
+  exit
+fi
+
+# Run tests. If we have nightly, then enable our nightly features.
+# Right now there are no nightly features, but that may change in the
+# future.
+CARGO_TEST_EXTRA_FLAGS=""
 if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
-  cargo build --verbose --manifest-path regex-debug/Cargo.toml
-  RUSTFLAGS="-C target-feature=+ssse3" cargo test --verbose --features 'simd-accel pattern' --jobs 4
-else
-  cargo test --verbose --jobs 4
+  CARGO_TEST_EXTRA_FLAGS=""
 fi
+cargo test --verbose ${CARGO_TEST_EXTRA_FLAGS}
+
+# Run the random tests in release mode, as this is faster.
+RUST_REGEX_RANDOM_TEST=1 \
+    cargo test --release --verbose \
+    ${CARGO_TEST_EXTRA_FLAGS} --test crates-regex
 
 # Run a test that confirms the shootout benchmarks are correct.
 ci/run-shootout-test
 
 # Run tests on regex-syntax crate.
 cargo test --verbose --manifest-path regex-syntax/Cargo.toml
 cargo doc --verbose --manifest-path regex-syntax/Cargo.toml
 
 # Run tests on regex-capi crate.
-cargo build --verbose --manifest-path regex-capi/Cargo.toml
-(cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../target/debug ./test)
-(cd regex-capi/examples && ./compile && LD_LIBRARY_PATH=../target/debug ./iter)
+ci/test-regex-capi
 
 # Make sure benchmarks compile. Don't run them though because they take a
-# very long time.
+# very long time. Also, check that we can build the regex-debug tool.
 if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
+  cargo build --verbose --manifest-path regex-debug/Cargo.toml
   for x in rust rust-bytes pcre1 onig; do
-    (cd bench && ./run $x --no-run)
+    (cd bench && ./run $x --no-run --verbose)
   done
+
+  # Test minimal versions.
+  cargo +nightly generate-lockfile -Z minimal-versions
+  cargo build --verbose
+  cargo test --verbose
 fi
diff --git a/third_party/rust/regex/ci/test-regex-capi b/third_party/rust/regex/ci/test-regex-capi
new file mode 100755
index 000000000000..f643aad0dde7
--- /dev/null
+++ b/third_party/rust/regex/ci/test-regex-capi
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+
+cargo build --verbose --manifest-path regex-capi/Cargo.toml
+(cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../../target/debug ./test)
+(cd regex-capi/examples && ./compile && LD_LIBRARY_PATH=../../target/debug ./iter)
diff --git a/third_party/rust/regex/examples/shootout-regex-dna-bytes.rs b/third_party/rust/regex/examples/shootout-regex-dna-bytes.rs
index ec57157c8ea4..4010324db742 100644
--- a/third_party/rust/regex/examples/shootout-regex-dna-bytes.rs
+++ b/third_party/rust/regex/examples/shootout-regex-dna-bytes.rs
@@ -50,17 +50,17 @@ fn main() {
         (regex!("N"), &b"(a|c|g|t)"[..]),
         (regex!("R"), &b"(a|g)"[..]),
         (regex!("S"), &b"(c|g)"[..]),
         (regex!("V"), &b"(a|c|g)"[..]),
         (regex!("W"), &b"(a|t)"[..]),
         (regex!("Y"), &b"(c|t)"[..]),
     ];
     let mut seq = seq;
-    for (re, replacement) in substs.into_iter() {
+    for (re, replacement) in substs {
         seq = re.replace_all(&seq, replacement).into_owned();
     }
 
     for (variant, count) in counts {
         println!("{} {}", variant, count.join().unwrap());
     }
     println!("\n{}\n{}\n{}", ilen, clen, seq.len());
 }
diff --git a/third_party/rust/regex/examples/shootout-regex-dna-single.rs b/third_party/rust/regex/examples/shootout-regex-dna-single.rs
index a84bc63c1246..ed48b8b01083 100644
--- a/third_party/rust/regex/examples/shootout-regex-dna-single.rs
+++ b/third_party/rust/regex/examples/shootout-regex-dna-single.rs
@@ -43,13 +43,13 @@ fn main() {
         (regex!("N"), "(a|c|g|t)"),
         (regex!("R"), "(a|g)"),
         (regex!("S"), "(c|g)"),
         (regex!("V"), "(a|c|g)"),
         (regex!("W"), "(a|t)"),
         (regex!("Y"), "(c|t)"),
     ];
     let mut seq = seq;
-    for (re, replacement) in substs.into_iter() {
+    for (re, replacement) in substs {
         seq = re.replace_all(&seq, replacement).into_owned();
     }
     println!("\n{}\n{}\n{}", ilen, clen, seq.len());
 }
diff --git a/third_party/rust/regex/examples/shootout-regex-dna.rs b/third_party/rust/regex/examples/shootout-regex-dna.rs
index ec0060d7f445..2171bb3eab54 100644
--- a/third_party/rust/regex/examples/shootout-regex-dna.rs
+++ b/third_party/rust/regex/examples/shootout-regex-dna.rs
@@ -50,17 +50,17 @@ fn main() {
         (regex!("N"), "(a|c|g|t)"),
         (regex!("R"), "(a|g)"),
         (regex!("S"), "(c|g)"),
         (regex!("V"), "(a|c|g)"),
         (regex!("W"), "(a|t)"),
         (regex!("Y"), "(c|t)"),
     ];
     let mut seq = seq;
-    for (re, replacement) in substs.into_iter() {
+    for (re, replacement) in substs {
         seq = re.replace_all(&seq, replacement).into_owned();
     }
 
     for (variant, count) in counts {
         println!("{} {}", variant, count.join().unwrap());
     }
     println!("\n{}\n{}\n{}", ilen, clen, seq.len());
 }
diff --git a/third_party/rust/regex/scripts/generate.py b/third_party/rust/regex/scripts/generate.py
new file mode 100755
index 000000000000..7dbd065add27
--- /dev/null
+++ b/third_party/rust/regex/scripts/generate.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+# This uses `ucd-generate` to generate all of the internal tables.
+
+import argparse
+import os
+import subprocess
+import sys
+
+
+def eprint(*args, **kwargs):
+    kwargs['file'] = sys.stderr
+    print(*args, **kwargs)
+
+
+def main():
+    p = argparse.ArgumentParser()
+    p.add_argument('ucd', metavar='DIR', nargs=1)
+    args = p.parse_args()
+    ucd = args.ucd[0]
+
+    def generate(subcmd, *args, **kwargs):
+        subprocess.run(("ucd-generate", subcmd, ucd) + args, check=True, **kwargs)
+
+    def generate_file(path, subcmd, *args, filename=None, **kwargs):
+        if filename is None:
+            filename = subcmd.replace('-', '_') + ".rs"
+        eprint('-', filename)
+        with open(os.path.join(path, filename), "w") as f:
+            generate(subcmd, *args, stdout=f, **kwargs)
+
+    eprint('generating regex-syntax tables')
+    path = os.path.join("regex-syntax", "src", "unicode_tables")
+    generate_file(path, "age", "--chars")
+    generate_file(path, "case-folding-simple", "--chars", "--all-pairs")
+    generate_file(path, "general-category", "--chars", "--exclude", "surrogate")
+    generate_file(path, "perl-word", "--chars")
+    generate_file(path, "property-bool", "--chars")
+    generate_file(path, "property-names")
+    generate_file(path, "property-values", "--include", "gc,script,scx,age")
+    generate_file(path, "script", "--chars")
+    generate_file(path, "script-extension", "--chars")
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/rust/regex/scripts/scrape_crates_io.py b/third_party/rust/regex/scripts/scrape_crates_io.py
new file mode 100755
index 000000000000..943fa8c2b4bd
--- /dev/null
+++ b/third_party/rust/regex/scripts/scrape_crates_io.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+
+from subprocess import call
+import argparse
+import datetime
+import glob
+import json
+import os
+import re
+import shutil
+import tempfile
+import time
+import urllib3
+
+CRATES_IO_INDEX_GIT_LOC = "https://github.com/rust-lang/crates.io-index.git"
+RE_REGEX = re.compile(r"Regex::new\((r?\".*?\")\)")
+KNOWN_UNMAINTAINED_CRATES = set(["queryst-prime", "oozz"])
+
+# if only requests was in the standard library...
+urllib3.disable_warnings()
+http = urllib3.PoolManager()
+
+
+def argparser():
+    p = argparse.ArgumentParser("A script to scrape crates.io for regex.")
+    p.add_argument("-c", "--crates-index", metavar="CRATES_INDEX_DIR",
+                   help=("A directory where we can find crates.io-index "
+                         + "(if this isn't set it will be automatically "
+                         + "downloaded)."))
+    p.add_argument("-o", "--output-file", metavar="OUTPUT",
+                   default="crates_regex.rs",
+                   help="The name of the output file to create.")
+    return p
+
+
+PRELUDE = """// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// DO NOT EDIT. Automatically generated by 'scripts/scrape_crates_io.py'
+// on {date}.
+
+
+
+"""
+
+
+def main():
+    args = argparser().parse_args()
+    out = open(os.path.abspath(args.output_file), "w")
+    out.write(PRELUDE.format(date=str(datetime.datetime.now())))
+    if args.crates_index:
+        args.crates_index = os.path.abspath(args.crates_index)
+
+    # enter our scratch directory
+    old_dir = os.getcwd()
+    work_dir = tempfile.mkdtemp(prefix="scrape-crates-io")
+    os.chdir(work_dir)
+
+    crates_index = (args.crates_index
+                    if os.path.join(old_dir, args.crates_index)
+                    else download_crates_index())
+
+    for (name, vers) in iter_crates(crates_index):
+        if name in KNOWN_UNMAINTAINED_CRATES:
+            continue
+
+        with Crate(work_dir, name, vers) as c:
+            i = 0
+            for line in c.iter_lines():
+                for r in RE_REGEX.findall(line):
+                    print((name, vers, r))
+                    if len(r) >= 2 and r[-2] == "\\":
+                        continue
+                    out.write("// {}-{}: {}\n".format(name, vers, r))
+                    out.write("consistent!({}_{}, {});\n\n".format(
+                                name.replace("-", "_"), i, r))
+                    out.flush()
+                    i += 1
+
+    # Leave the scratch directory
+    os.chdir(old_dir)
+    shutil.rmtree(work_dir)
+    out.close()
+
+
+def download_crates_index():
+    if call(["git", "clone", CRATES_IO_INDEX_GIT_LOC]) != 0:
+        print("Error cloning the crates.io index")
+        exit(1)
+    return "crates.io-index"
+
+
+def iter_crates(crates_index):
+    exclude = set(["config.json", ".git"])
+    for crate_index_file in iter_files(crates_index, exclude=exclude):
+        with open(crate_index_file) as f:
+            most_recent = list(f)
+            most_recent = most_recent[len(most_recent) - 1]
+
+            crate_info = json.loads(most_recent)
+            if "regex" not in set(d["name"] for d in crate_info["deps"]):
+                continue
+
+            if crate_info["yanked"]:
+                continue
+            yield (crate_info["name"], crate_info["vers"])
+
+
+def iter_files(d, exclude=set()):
+    for x in os.listdir(d):
+        if x in exclude:
+            continue
+
+        fullfp = os.path.abspath(d + "/" + x)
+        if os.path.isfile(fullfp):
+            yield fullfp
+        elif os.path.isdir(fullfp):
+            for f in iter_files(fullfp, exclude):
+                yield f
+
+
+class Crate(object):
+    def __init__(self, work_dir, name, version):
+        self.name = name
+        self.version = version
+        self.url = ("https://crates.io/api/v1/crates/{name}/{version}/download"
+                    .format(name=self.name, version=self.version))
+        self.filename = "{}/{}-{}.tar.gz".format(
+                            work_dir, self.name, self.version)
+
+    def __enter__(self):
+        max_retries = 1
+        retries = 0
+        while retries < max_retries:
+            retries += 1
+
+            r = http.request("GET", self.url, preload_content=False)
+            try:
+                print("[{}/{}] Downloading {}".format(
+                        retries, max_retries + 1, self.url))
+                with open(self.filename, "wb") as f:
+                    while True:
+                        data = r.read(1024)
+                        if not data:
+                            break
+                        f.write(data)
+            except requests.exceptions.ConnectionError:
+                time.sleep(1)
+                r.release_conn()
+                continue
+
+            r.release_conn()
+            break
+
+        call(["tar", "-xf", self.filename])
+
+        return self
+
+    def __exit__(self, ty, value, tb):
+        # We are going to clean up the whole temp dir anyway, so
+        # we don't really need to do this. Its nice to clean up
+        # after ourselves though.
+        try:
+            shutil.rmtree(self.filename[:-len(".tar.gz")])
+            os.remove(self.filename)
+        except _:
+            pass
+
+    def iter_srcs(self):
+        g = "{crate}/**/*.rs".format(crate=self.filename[:-len(".tar.gz")])
+        for rsrc in glob.iglob(g):
+            yield rsrc
+
+    def iter_lines(self):
+        for src in self.iter_srcs():
+            with open(src) as f:
+                for line in f:
+                    yield line
+
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/rust/regex/src/backtrack.rs b/third_party/rust/regex/src/backtrack.rs
index 78bc39e93e07..6e71e2c2f376 100644
--- a/third_party/rust/regex/src/backtrack.rs
+++ b/third_party/rust/regex/src/backtrack.rs
@@ -95,17 +95,17 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
         prog: &'r Program,
         cache: &ProgramCache,
         matches: &'m mut [bool],
         slots: &'s mut [Slot],
         input: I,
         start: usize,
     ) -> bool {
         let mut cache = cache.borrow_mut();
-        let mut cache = &mut cache.backtrack;
+        let cache = &mut cache.backtrack;
         let start = input.at(start);
         let mut b = Bounded {
             prog: prog,
             input: input,
             matches: matches,
             slots: slots,
             m: cache,
         };
@@ -211,16 +211,19 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
 
     fn step(&mut self, mut ip: InstPtr, mut at: InputAt) -> bool {
         use prog::Inst::*;
         loop {
             // This loop is an optimization to avoid constantly pushing/popping
             // from the stack. Namely, if we're pushing a job only to run it
             // next, avoid the push and just mutate `ip` (and possibly `at`)
             // in place.
+            if self.has_visited(ip, at) {
+                return false;
+            }
             match self.prog[ip] {
                 Match(slot) => {
                     if slot < self.matches.len() {
                         self.matches[slot] = true;
                     }
                     return true;
                 }
                 Save(ref inst) => {
@@ -270,19 +273,16 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
                             ip = inst.goto;
                             at = self.input.at(at.next_pos());
                             continue;
                         }
                     }
                     return false;
                 }
             }
-            if self.has_visited(ip, at) {
-                return false;
-            }
         }
     }
 
     fn has_visited(&mut self, ip: InstPtr, at: InputAt) -> bool {
         let k = ip * (self.input.len() + 1) + at.pos();
         let k1 = k / BIT_SIZE;
         let k2 = usize_to_u32(1 << (k & (BIT_SIZE - 1)));
         if self.m.visited[k1] & k2 == 0 {
diff --git a/third_party/rust/regex/src/compile.rs b/third_party/rust/regex/src/compile.rs
index 0acdebb1128c..6f2321ec05bd 100644
--- a/third_party/rust/regex/src/compile.rs
+++ b/third_party/rust/regex/src/compile.rs
@@ -8,20 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use std::collections::HashMap;
 use std::iter;
 use std::result;
 use std::sync::Arc;
 
-use syntax::{
-    Expr, Repeater, CharClass, ClassRange, ByteClass, ByteRange,
-    is_word_byte,
-};
+use syntax::is_word_byte;
+use syntax::hir::{self, Hir};
 use utf8_ranges::{Utf8Range, Utf8Sequence, Utf8Sequences};
 
 use prog::{
     Program, Inst, InstPtr, EmptyLook,
     InstSave, InstSplit, InstEmptyLook, InstChar, InstRanges, InstBytes,
 };
 
 use Error;
@@ -118,478 +116,526 @@ impl Compiler {
 
     /// Compile a regular expression given its AST.
     ///
     /// The compiler is guaranteed to succeed unless the program exceeds the
     /// specified size limit. If the size limit is exceeded, then compilation
     /// stops and returns an error.
     pub fn compile(
         mut self,
-        exprs: &[Expr],
+        exprs: &[Hir],
     ) -> result::Result<Program, Error> {
         debug_assert!(exprs.len() >= 1);
         self.num_exprs = exprs.len();
         if exprs.len() == 1 {
             self.compile_one(&exprs[0])
         } else {
             self.compile_many(exprs)
         }
     }
 
-    fn compile_one(mut self, expr: &Expr) -> result::Result<Program, Error> {
+    fn compile_one(mut self, expr: &Hir) -> result::Result<Program, Error> {
         // If we're compiling a forward DFA and we aren't anchored, then
         // add a `.*?` before the first capture group.
         // Other matching engines handle this by baking the logic into the
         // matching engine itself.
         let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
         self.compiled.is_anchored_start = expr.is_anchored_start();
         self.compiled.is_anchored_end = expr.is_anchored_end();
         if self.compiled.needs_dotstar() {
-            dotstar_patch = try!(self.c_dotstar());
+            dotstar_patch = self.c_dotstar()?;
             self.compiled.start = dotstar_patch.entry;
         }
         self.compiled.captures = vec![None];
-        let patch = try!(self.c_capture(0, expr));
+        let patch = self.c_capture(0, expr)?;
         if self.compiled.needs_dotstar() {
             self.fill(dotstar_patch.hole, patch.entry);
         } else {
             self.compiled.start = patch.entry;
         }
         self.fill_to_next(patch.hole);
         self.compiled.matches = vec![self.insts.len()];
         self.push_compiled(Inst::Match(0));
         self.compile_finish()
     }
 
     fn compile_many(
         mut self,
-        exprs: &[Expr],
+        exprs: &[Hir],
     ) -> result::Result<Program, Error> {
         debug_assert!(exprs.len() > 1);
 
         self.compiled.is_anchored_start =
             exprs.iter().all(|e| e.is_anchored_start());
         self.compiled.is_anchored_end =
             exprs.iter().all(|e| e.is_anchored_end());
         let mut dotstar_patch = Patch { hole: Hole::None, entry: 0 };
         if self.compiled.needs_dotstar() {
-            dotstar_patch = try!(self.c_dotstar());
+            dotstar_patch = self.c_dotstar()?;
             self.compiled.start = dotstar_patch.entry;
         } else {
             self.compiled.start = 0; // first instruction is always split
         }
         self.fill_to_next(dotstar_patch.hole);
 
         let mut prev_hole = Hole::None;
         for (i, expr) in exprs[0..exprs.len() - 1].iter().enumerate() {
             self.fill_to_next(prev_hole);
             let split = self.push_split_hole();
-            let Patch { hole, entry } = try!(self.c_capture(0, expr));
+            let Patch { hole, entry } = self.c_capture(0, expr)?;
             self.fill_to_next(hole);
             self.compiled.matches.push(self.insts.len());
             self.push_compiled(Inst::Match(i));
             prev_hole = self.fill_split(split, Some(entry), None);
         }
         let i = exprs.len() - 1;
-        let Patch { hole, entry } = try!(self.c_capture(0, &exprs[i]));
+        let Patch { hole, entry } = self.c_capture(0, &exprs[i])?;
         self.fill(prev_hole, entry);
         self.fill_to_next(hole);
         self.compiled.matches.push(self.insts.len());
         self.push_compiled(Inst::Match(i));
         self.compile_finish()
     }
 
     fn compile_finish(mut self) -> result::Result<Program, Error> {
         self.compiled.insts =
             self.insts.into_iter().map(|inst| inst.unwrap()).collect();
         self.compiled.byte_classes = self.byte_classes.byte_classes();
         self.compiled.capture_name_idx = Arc::new(self.capture_name_idx);
         Ok(self.compiled)
     }
 
-    fn c(&mut self, expr: &Expr) -> Result {
+    /// Compile expr into self.insts, returning a patch on success,
+    /// or an error if we run out of memory.
+    ///
+    /// All of the c_* methods of the compiler share the contract outlined
+    /// here.
+    ///
+    /// The main thing that a c_* method does is mutate `self.insts`
+    /// to add a list of mostly compiled instructions required to execute
+    /// the given expression. `self.insts` contains MaybeInsts rather than
+    /// Insts because there is some backpatching required.
+    ///
+    /// The `Patch` value returned by each c_* method provides metadata
+    /// about the compiled instructions emitted to `self.insts`. The
+    /// `entry` member of the patch refers to the first instruction
+    /// (the entry point), while the `hole` member contains zero or
+    /// more offsets to partial instructions that need to be backpatched.
+    /// The c_* routine can't know where its list of instructions are going to
+    /// jump to after execution, so it is up to the caller to patch
+    /// these jumps to point to the right place. So compiling some
+    /// expression, e, we would end up with a situation that looked like:
+    ///
+    /// ```text
+    /// self.insts = [ ..., i1, i2, ..., iexit1, ..., iexitn, ...]
+    ///                     ^              ^             ^
+    ///                     |                \         /
+    ///                   entry                \     /
+    ///                                         hole
+    /// ```
+    ///
+    /// To compile two expressions, e1 and e2, concatinated together we
+    /// would do:
+    ///
+    /// ```ignore
+    /// let patch1 = self.c(e1);
+    /// let patch2 = self.c(e2);
+    /// ```
+    ///
+    /// while leaves us with a situation that looks like
+    ///
+    /// ```text
+    /// self.insts = [ ..., i1, ..., iexit1, ..., i2, ..., iexit2 ]
+    ///                     ^        ^            ^        ^
+    ///                     |        |            |        |
+    ///                entry1        hole1   entry2        hole2
+    /// ```
+    ///
+    /// Then to merge the two patches together into one we would backpatch
+    /// hole1 with entry2 and return a new patch that enters at entry1
+    /// and has hole2 for a hole. In fact, if you look at the c_concat
+    /// method you will see that it does exactly this, though it handles
+    /// a list of expressions rather than just the two that we use for
+    /// an example.
+    fn c(&mut self, expr: &Hir) -> Result {
         use prog;
-        use syntax::Expr::*;
+        use syntax::hir::HirKind::*;
 
-        try!(self.check_size());
-        match *expr {
+        self.check_size()?;
+        match *expr.kind() {
             Empty => Ok(Patch { hole: Hole::None, entry: self.insts.len() }),
-            Literal { ref chars, casei } => self.c_literal(chars, casei),
-            LiteralBytes { ref bytes, casei } => self.c_bytes(bytes, casei),
-            AnyChar => self.c_class(&[ClassRange {
-                start: '\x00',
-                end: '\u{10ffff}',
-            }]),
-            AnyCharNoNL => {
-                self.c_class(&[
-                    ClassRange { start: '\x00', end: '\x09' },
-                    ClassRange { start: '\x0b', end: '\u{10ffff}' },
-                ])
-            }
-            AnyByte => {
-                self.c_class_bytes(&[ByteRange { start: 0, end: 0xFF }])
+            Literal(hir::Literal::Unicode(c)) => {
+                self.c_literal(&[c])
             }
-            AnyByteNoNL => {
-                self.c_class_bytes(&[
-                    ByteRange { start: 0, end: 0x9 },
-                    ByteRange { start: 0xB, end: 0xFF },
-                ])
+            Literal(hir::Literal::Byte(b)) => {
+                assert!(self.compiled.uses_bytes());
+                self.c_bytes(&[b])
             }
-            Class(ref cls) => {
-                self.c_class(cls)
+            Class(hir::Class::Unicode(ref cls)) => {
+                self.c_class(cls.ranges())
             }
-            ClassBytes(ref cls) => {
-                self.c_class_bytes(cls)
+            Class(hir::Class::Bytes(ref cls)) => {
+                if self.compiled.uses_bytes() {
+                    self.c_class_bytes(cls.ranges())
+                } else {
+                    assert!(cls.is_all_ascii());
+                    let mut char_ranges = vec![];
+                    for r in cls.iter() {
+                        let (s, e) = (r.start() as char, r.end() as char);
+                        char_ranges.push(hir::ClassUnicodeRange::new(s, e));
+                    }
+                    self.c_class(&char_ranges)
+                }
             }
-            StartLine if self.compiled.is_reverse => {
+            Anchor(hir::Anchor::StartLine) if self.compiled.is_reverse => {
                 self.byte_classes.set_range(b'\n', b'\n');
                 self.c_empty_look(prog::EmptyLook::EndLine)
             }
-            StartLine => {
+            Anchor(hir::Anchor::StartLine) => {
                 self.byte_classes.set_range(b'\n', b'\n');
                 self.c_empty_look(prog::EmptyLook::StartLine)
             }
-            EndLine if self.compiled.is_reverse => {
+            Anchor(hir::Anchor::EndLine) if self.compiled.is_reverse => {
                 self.byte_classes.set_range(b'\n', b'\n');
                 self.c_empty_look(prog::EmptyLook::StartLine)
             }
-            EndLine => {
+            Anchor(hir::Anchor::EndLine) => {
                 self.byte_classes.set_range(b'\n', b'\n');
                 self.c_empty_look(prog::EmptyLook::EndLine)
             }
-            StartText if self.compiled.is_reverse => {
+            Anchor(hir::Anchor::StartText) if self.compiled.is_reverse => {
                 self.c_empty_look(prog::EmptyLook::EndText)
             }
-            StartText => {
+            Anchor(hir::Anchor::StartText) => {
                 self.c_empty_look(prog::EmptyLook::StartText)
             }
-            EndText if self.compiled.is_reverse => {
+            Anchor(hir::Anchor::EndText) if self.compiled.is_reverse => {
                 self.c_empty_look(prog::EmptyLook::StartText)
             }
-            EndText => {
+            Anchor(hir::Anchor::EndText) => {
                 self.c_empty_look(prog::EmptyLook::EndText)
             }
-            WordBoundary => {
+            WordBoundary(hir::WordBoundary::Unicode) => {
                 self.compiled.has_unicode_word_boundary = true;
                 self.byte_classes.set_word_boundary();
                 self.c_empty_look(prog::EmptyLook::WordBoundary)
             }
-            NotWordBoundary => {
+            WordBoundary(hir::WordBoundary::UnicodeNegate) => {
                 self.compiled.has_unicode_word_boundary = true;
                 self.byte_classes.set_word_boundary();
                 self.c_empty_look(prog::EmptyLook::NotWordBoundary)
             }
-            WordBoundaryAscii => {
+            WordBoundary(hir::WordBoundary::Ascii) => {
                 self.byte_classes.set_word_boundary();
                 self.c_empty_look(prog::EmptyLook::WordBoundaryAscii)
             }
-            NotWordBoundaryAscii => {
+            WordBoundary(hir::WordBoundary::AsciiNegate) => {
                 self.byte_classes.set_word_boundary();
                 self.c_empty_look(prog::EmptyLook::NotWordBoundaryAscii)
             }
-            Group { ref e, i: None, name: None } => self.c(e),
-            Group { ref e, i, ref name } => {
-                // it's impossible to have a named capture without an index
-                let i = i.expect("capture index");
-                if i >= self.compiled.captures.len() {
-                    self.compiled.captures.push(name.clone());
-                    if let Some(ref name) = *name {
-                        self.capture_name_idx.insert(name.to_owned(), i);
+            Group(ref g) => {
+                match g.kind {
+                    hir::GroupKind::NonCapturing => self.c(&g.hir),
+                    hir::GroupKind::CaptureIndex(index) => {
+                        if index as usize >= self.compiled.captures.len() {
+                            self.compiled.captures.push(None);
+                        }
+                        self.c_capture(2 * index as usize, &g.hir)
+                    }
+                    hir::GroupKind::CaptureName { index, ref name } => {
+                        if index as usize >= self.compiled.captures.len() {
+                            let n = name.to_string();
+                            self.compiled.captures.push(Some(n.clone()));
+                            self.capture_name_idx.insert(n, index as usize);
+                        }
+                        self.c_capture(2 * index as usize, &g.hir)
                     }
                 }
-                self.c_capture(2 * i, e)
             }
             Concat(ref es) => {
                 if self.compiled.is_reverse {
                     self.c_concat(es.iter().rev())
                 } else {
                     self.c_concat(es)
                 }
             }
-            Alternate(ref es) => self.c_alternate(&**es),
-            Repeat { ref e, r, greedy } => self.c_repeat(e, r, greedy),
+            Alternation(ref es) => self.c_alternate(&**es),
+            Repetition(ref rep) => self.c_repeat(rep),
         }
     }
 
-    fn c_capture(&mut self, first_slot: usize, expr: &Expr) -> Result {
+    fn c_capture(&mut self, first_slot: usize, expr: &Hir) -> Result {
         if self.num_exprs > 1 || self.compiled.is_dfa {
             // Don't ever compile Save instructions for regex sets because
             // they are never used. They are also never used in DFA programs
             // because DFAs can't handle captures.
             self.c(expr)
         } else {
             let entry = self.insts.len();
             let hole = self.push_hole(InstHole::Save { slot: first_slot });
-            let patch = try!(self.c(expr));
+            let patch = self.c(expr)?;
             self.fill(hole, patch.entry);
             self.fill_to_next(patch.hole);
             let hole = self.push_hole(InstHole::Save { slot: first_slot + 1 });
             Ok(Patch { hole: hole, entry: entry })
         }
     }
 
     fn c_dotstar(&mut self) -> Result {
         Ok(if !self.compiled.only_utf8() {
-            try!(self.c(&Expr::Repeat {
-                e: Box::new(Expr::AnyByte),
-                r: Repeater::ZeroOrMore,
+            self.c(&Hir::repetition(hir::Repetition {
+                kind: hir::RepetitionKind::ZeroOrMore,
                 greedy: false,
-            }))
+                hir: Box::new(Hir::any(true)),
+            }))?
         } else {
-            try!(self.c(&Expr::Repeat {
-                e: Box::new(Expr::AnyChar),
-                r: Repeater::ZeroOrMore,
+            self.c(&Hir::repetition(hir::Repetition {
+                kind: hir::RepetitionKind::ZeroOrMore,
                 greedy: false,
-            }))
+                hir: Box::new(Hir::any(false)),
+            }))?
         })
     }
 
-    fn c_literal(&mut self, chars: &[char], casei: bool) -> Result {
+    fn c_literal(&mut self, chars: &[char]) -> Result {
         debug_assert!(!chars.is_empty());
         let mut chars: Box<Iterator<Item=&char>> =
             if self.compiled.is_reverse {
                 Box::new(chars.iter().rev())
             } else {
                 Box::new(chars.iter())
             };
         let first = *chars.next().expect("non-empty literal");
-        let Patch { mut hole, entry } = try!(self.c_char(first, casei));
+        let Patch { mut hole, entry } = self.c_char(first)?;
         for &c in chars {
-            let p = try!(self.c_char(c, casei));
+            let p = self.c_char(c)?;
             self.fill(hole, p.entry);
             hole = p.hole;
         }
         Ok(Patch { hole: hole, entry: entry })
     }
 
-    fn c_char(&mut self, c: char, casei: bool) -> Result {
-        if casei {
-            self.c_class(&CharClass::new(vec![
-                ClassRange { start: c, end: c },
-            ]).case_fold())
-        } else {
-            self.c_class(&[ClassRange { start: c, end: c }])
-        }
+    fn c_char(&mut self, c: char) -> Result {
+        self.c_class(&[hir::ClassUnicodeRange::new(c, c)])
     }
 
-    fn c_class(&mut self, ranges: &[ClassRange]) -> Result {
+    fn c_class(&mut self, ranges: &[hir::ClassUnicodeRange]) -> Result {
         assert!(!ranges.is_empty());
         if self.compiled.uses_bytes() {
             CompileClass {
                 c: self,
                 ranges: ranges,
             }.compile()
         } else {
             let ranges: Vec<(char, char)> =
-                ranges.iter().map(|r| (r.start, r.end)).collect();
+                ranges.iter().map(|r| (r.start(), r.end())).collect();
             let hole = if ranges.len() == 1 && ranges[0].0 == ranges[0].1 {
                 self.push_hole(InstHole::Char { c: ranges[0].0 })
             } else {
                 self.push_hole(InstHole::Ranges { ranges: ranges })
             };
             Ok(Patch { hole: hole, entry: self.insts.len() - 1 })
         }
     }
 
-    fn c_bytes(&mut self, bytes: &[u8], casei: bool) -> Result {
+    fn c_bytes(&mut self, bytes: &[u8]) -> Result {
         debug_assert!(!bytes.is_empty());
         let mut bytes: Box<Iterator<Item=&u8>> =
             if self.compiled.is_reverse {
                 Box::new(bytes.iter().rev())
             } else {
                 Box::new(bytes.iter())
             };
         let first = *bytes.next().expect("non-empty literal");
-        let Patch { mut hole, entry } = try!(self.c_byte(first, casei));
+        let Patch { mut hole, entry } = self.c_byte(first)?;
         for &b in bytes {
-            let p = try!(self.c_byte(b, casei));
+            let p = self.c_byte(b)?;
             self.fill(hole, p.entry);
             hole = p.hole;
         }
         Ok(Patch { hole: hole, entry: entry })
     }
 
-    fn c_byte(&mut self, b: u8, casei: bool) -> Result {
-        if casei {
-            self.c_class_bytes(&ByteClass::new(vec![
-                ByteRange { start: b, end: b },
-            ]).case_fold())
-        } else {
-            self.c_class_bytes(&[ByteRange { start: b, end: b }])
-        }
+    fn c_byte(&mut self, b: u8) -> Result {
+        self.c_class_bytes(&[hir::ClassBytesRange::new(b, b)])
     }
 
-    fn c_class_bytes(&mut self, ranges: &[ByteRange]) -> Result {
+    fn c_class_bytes(&mut self, ranges: &[hir::ClassBytesRange]) -> Result {
         debug_assert!(!ranges.is_empty());
 
         let first_split_entry = self.insts.len();
         let mut holes = vec![];
         let mut prev_hole = Hole::None;
         for r in &ranges[0..ranges.len() - 1] {
             self.fill_to_next(prev_hole);
             let split = self.push_split_hole();
             let next = self.insts.len();
-            self.byte_classes.set_range(r.start, r.end);
+            self.byte_classes.set_range(r.start(), r.end());
             holes.push(self.push_hole(InstHole::Bytes {
-                start: r.start, end: r.end,
+                start: r.start(), end: r.end(),
             }));
             prev_hole = self.fill_split(split, Some(next), None);
         }
         let next = self.insts.len();
         let r = &ranges[ranges.len() - 1];
-        self.byte_classes.set_range(r.start, r.end);
+        self.byte_classes.set_range(r.start(), r.end());
         holes.push(self.push_hole(InstHole::Bytes {
-            start: r.start, end: r.end,
+            start: r.start(), end: r.end(),
         }));
         self.fill(prev_hole, next);
         Ok(Patch { hole: Hole::Many(holes), entry: first_split_entry })
     }
 
     fn c_empty_look(&mut self, look: EmptyLook) -> Result {
         let hole = self.push_hole(InstHole::EmptyLook { look: look });
         Ok(Patch { hole: hole, entry: self.insts.len() - 1 })
     }
 
     fn c_concat<'a, I>(&mut self, exprs: I) -> Result
-            where I: IntoIterator<Item=&'a Expr> {
+            where I: IntoIterator<Item=&'a Hir> {
         let mut exprs = exprs.into_iter();
         let first = match exprs.next() {
             Some(expr) => expr,
             None => {
                 return Ok(Patch { hole: Hole::None, entry: self.insts.len() })
             }
         };
-        let Patch { mut hole, entry } = try!(self.c(first));
+        let Patch { mut hole, entry } = self.c(first)?;
         for e in exprs {
-            let p = try!(self.c(e));
+            let p = self.c(e)?;
             self.fill(hole, p.entry);
             hole = p.hole;
         }
         Ok(Patch { hole: hole, entry: entry })
     }
 
-    fn c_alternate(&mut self, exprs: &[Expr]) -> Result {
+    fn c_alternate(&mut self, exprs: &[Hir]) -> Result {
         debug_assert!(
             exprs.len() >= 2, "alternates must have at least 2 exprs");
 
         // Initial entry point is always the first split.
         let first_split_entry = self.insts.len();
 
         // Save up all of the holes from each alternate. They will all get
         // patched to point to the same location.
         let mut holes = vec![];
 
         let mut prev_hole = Hole::None;
         for e in &exprs[0..exprs.len() - 1] {
             self.fill_to_next(prev_hole);
             let split = self.push_split_hole();
-            let Patch { hole, entry } = try!(self.c(e));
+            let prev_entry = self.insts.len();
+            let Patch { hole, entry } = self.c(e)?;
+            if prev_entry == self.insts.len() {
+                // TODO(burntsushi): It is kind of silly that we don't support
+                // empty-subexpressions in alternates, but it is supremely
+                // awkward to support them in the existing compiler
+                // infrastructure. This entire compiler needs to be thrown out
+                // anyway, so don't feel too bad.
+                return Err(Error::Syntax(
+                    "alternations cannot currently contain \
+                     empty sub-expressions".to_string()));
+            }
             holes.push(hole);
             prev_hole = self.fill_split(split, Some(entry), None);
         }
-        let Patch { hole, entry } = try!(self.c(&exprs[exprs.len() - 1]));
+        let prev_entry = self.insts.len();
+        let Patch { hole, entry } = self.c(&exprs[exprs.len() - 1])?;
+        if prev_entry == self.insts.len() {
+            // TODO(burntsushi): See TODO above.
+            return Err(Error::Syntax(
+                "alternations cannot currently contain \
+                 empty sub-expressions".to_string()));
+        }
         holes.push(hole);
         self.fill(prev_hole, entry);
         Ok(Patch { hole: Hole::Many(holes), entry: first_split_entry })
     }
 
-    fn c_repeat(
-        &mut self,
-        expr: &Expr,
-        kind: Repeater,
-        greedy: bool,
-    ) -> Result {
-        match kind {
-            Repeater::ZeroOrOne => self.c_repeat_zero_or_one(expr, greedy),
-            Repeater::ZeroOrMore => self.c_repeat_zero_or_more(expr, greedy),
-            Repeater::OneOrMore => self.c_repeat_one_or_more(expr, greedy),
-            Repeater::Range { min, max: None } => {
-                self.c_repeat_range_min_or_more(expr, greedy, min)
+    fn c_repeat(&mut self, rep: &hir::Repetition) -> Result {
+        use syntax::hir::RepetitionKind::*;
+        match rep.kind {
+            ZeroOrOne => self.c_repeat_zero_or_one(&rep.hir, rep.greedy),
+            ZeroOrMore => self.c_repeat_zero_or_more(&rep.hir, rep.greedy),
+            OneOrMore => self.c_repeat_one_or_more(&rep.hir, rep.greedy),
+            Range(hir::RepetitionRange::Exactly(min_max)) => {
+                self.c_repeat_range(&rep.hir, rep.greedy, min_max, min_max)
             }
-            Repeater::Range { min, max: Some(max) } => {
-                self.c_repeat_range(expr, greedy, min, max)
+            Range(hir::RepetitionRange::AtLeast(min)) => {
+                self.c_repeat_range_min_or_more(&rep.hir, rep.greedy, min)
+            }
+            Range(hir::RepetitionRange::Bounded(min, max)) => {
+                self.c_repeat_range(&rep.hir, rep.greedy, min, max)
             }
         }
     }
 
-    fn c_repeat_zero_or_one(
-        &mut self,
-        expr: &Expr,
-        greedy: bool,
-    ) -> Result {
+    fn c_repeat_zero_or_one(&mut self, expr: &Hir, greedy: bool) -> Result {
         let split_entry = self.insts.len();
         let split = self.push_split_hole();
-        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+        let Patch { hole: hole_rep, entry: entry_rep } = self.c(expr)?;
 
         let split_hole = if greedy {
             self.fill_split(split, Some(entry_rep), None)
         } else {
             self.fill_split(split, None, Some(entry_rep))
         };
         let holes = vec![hole_rep, split_hole];
         Ok(Patch { hole: Hole::Many(holes), entry: split_entry })
     }
 
-    fn c_repeat_zero_or_more(
-        &mut self,
-        expr: &Expr,
-        greedy: bool,
-    ) -> Result {
+    fn c_repeat_zero_or_more(&mut self, expr: &Hir, greedy: bool) -> Result {
         let split_entry = self.insts.len();
         let split = self.push_split_hole();
-        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+        let Patch { hole: hole_rep, entry: entry_rep } = self.c(expr)?;
 
         self.fill(hole_rep, split_entry);
         let split_hole = if greedy {
             self.fill_split(split, Some(entry_rep), None)
         } else {
             self.fill_split(split, None, Some(entry_rep))
         };
         Ok(Patch { hole: split_hole, entry: split_entry })
     }
 
-    fn c_repeat_one_or_more(
-        &mut self,
-        expr: &Expr,
-        greedy: bool,
-    ) -> Result {
-        let Patch { hole: hole_rep, entry: entry_rep } = try!(self.c(expr));
+    fn c_repeat_one_or_more(&mut self, expr: &Hir, greedy: bool) -> Result {
+        let Patch { hole: hole_rep, entry: entry_rep } = self.c(expr)?;
         self.fill_to_next(hole_rep);
         let split = self.push_split_hole();
 
         let split_hole = if greedy {
             self.fill_split(split, Some(entry_rep), None)
         } else {
             self.fill_split(split, None, Some(entry_rep))
         };
         Ok(Patch { hole: split_hole, entry: entry_rep })
     }
 
     fn c_repeat_range_min_or_more(
         &mut self,
-        expr: &Expr,
+        expr: &Hir,
         greedy: bool,
         min: u32,
     ) -> Result {
         let min = u32_to_usize(min);
-        let patch_concat = try!(self.c_concat(iter::repeat(expr).take(min)));
-        let patch_rep = try!(self.c_repeat_zero_or_more(expr, greedy));
+        let patch_concat = self.c_concat(iter::repeat(expr).take(min))?;
+        let patch_rep = self.c_repeat_zero_or_more(expr, greedy)?;
         self.fill(patch_concat.hole, patch_rep.entry);
         Ok(Patch { hole: patch_rep.hole, entry: patch_concat.entry })
     }
 
     fn c_repeat_range(
         &mut self,
-        expr: &Expr,
+        expr: &Hir,
         greedy: bool,
         min: u32,
         max: u32,
     ) -> Result {
         let (min, max) = (u32_to_usize(min), u32_to_usize(max));
-        let patch_concat = try!(self.c_concat(iter::repeat(expr).take(min)));
+        let patch_concat = self.c_concat(iter::repeat(expr).take(min))?;
         let initial_entry = patch_concat.entry;
         if min == max {
             return Ok(patch_concat);
         }
         // It is much simpler to compile, e.g., `a{2,5}` as:
         //
         //     aaa?a?a?
         //
@@ -608,17 +654,17 @@ impl Compiler {
         // This is *incredibly* inefficient because the splits end
         // up forming a chain, which has to be resolved everything a
         // transition is followed.
         let mut holes = vec![];
         let mut prev_hole = patch_concat.hole;
         for _ in min..max {
             self.fill_to_next(prev_hole);
             let split = self.push_split_hole();
-            let Patch { hole, entry } = try!(self.c(expr));
+            let Patch { hole, entry } = self.c(expr)?;
             prev_hole = hole;
             if greedy {
                 holes.push(self.fill_split(split, Some(entry), None));
             } else {
                 holes.push(self.fill_split(split, None, Some(entry)));
             }
         }
         holes.push(prev_hole);
@@ -817,51 +863,51 @@ impl InstHole {
                 end: end,
             }),
         }
     }
 }
 
 struct CompileClass<'a, 'b> {
     c: &'a mut Compiler,
-    ranges: &'b [ClassRange],
+    ranges: &'b [hir::ClassUnicodeRange],
 }
 
 impl<'a, 'b> CompileClass<'a, 'b> {
     fn compile(mut self) -> Result {
         let mut holes = vec![];
         let mut initial_entry = None;
         let mut last_split = Hole::None;
         let mut utf8_seqs = self.c.utf8_seqs.take().unwrap();
         self.c.suffix_cache.clear();
 
-        for (i, ref range) in self.ranges.iter().enumerate() {
+        for (i, range) in self.ranges.iter().enumerate() {
             let is_last_range = i + 1 == self.ranges.len();
-            utf8_seqs.reset(range.start, range.end);
+            utf8_seqs.reset(range.start(), range.end());
             let mut it = (&mut utf8_seqs).peekable();
             loop {
                 let utf8_seq = match it.next() {
                     None => break,
                     Some(utf8_seq) => utf8_seq,
                 };
                 if is_last_range && it.peek().is_none() {
-                    let Patch { hole, entry } = try!(self.c_utf8_seq(&utf8_seq));
+                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
                     holes.push(hole);
                     self.c.fill(last_split, entry);
                     last_split = Hole::None;
                     if initial_entry.is_none() {
                         initial_entry = Some(entry);
                     }
                 } else {
                     if initial_entry.is_none() {
                         initial_entry = Some(self.c.insts.len());
                     }
                     self.c.fill_to_next(last_split);
                     last_split = self.c.push_split_hole();
-                    let Patch { hole, entry } = try!(self.c_utf8_seq(&utf8_seq));
+                    let Patch { hole, entry } = self.c_utf8_seq(&utf8_seq)?;
                     holes.push(hole);
                     last_split = self.c.fill_split(last_split, Some(entry), None);
                 }
             }
         }
         self.c.utf8_seqs = Some(utf8_seqs);
         Ok(Patch {
             hole: Hole::Many(holes),
@@ -911,17 +957,17 @@ impl<'a, 'b> CompileClass<'a, 'b> {
             from_inst = self.c.insts.len().checked_sub(1).unwrap();
             debug_assert!(from_inst < ::std::usize::MAX);
         }
         debug_assert!(from_inst < ::std::usize::MAX);
         Ok(Patch { hole: last_hole, entry: from_inst })
     }
 }
 
-/// SuffixCache is a simple bounded hash map for caching suffix entries in
+/// `SuffixCache` is a simple bounded hash map for caching suffix entries in
 /// UTF-8 automata. For example, consider the Unicode range \u{0}-\u{FFFF}.
 /// The set of byte ranges looks like this:
 ///
 /// [0-7F]
 /// [C2-DF][80-BF]
 /// [E0][A0-BF][80-BF]
 /// [E1-EC][80-BF][80-BF]
 /// [ED][80-9F][80-BF]
@@ -1045,16 +1091,19 @@ impl ByteClassSet {
             }
             i += 1;
         }
         byte_classes
     }
 }
 
 fn u32_to_usize(n: u32) -> usize {
+    // In case usize is less than 32 bits, we need to guard against overflow.
+    // On most platforms this compiles to nothing.
+    // TODO Use `std::convert::TryFrom` once it's stable.
     if (n as u64) > (::std::usize::MAX as u64) {
         panic!("BUG: {} is too big to be pointer sized", n)
     }
     n as usize
 }
 
 #[cfg(test)]
 mod tests {
diff --git a/third_party/rust/regex/src/dfa.rs b/third_party/rust/regex/src/dfa.rs
index d3c007c35037..992a45cc6267 100644
--- a/third_party/rust/regex/src/dfa.rs
+++ b/third_party/rust/regex/src/dfa.rs
@@ -53,30 +53,30 @@ use std::mem;
 
 use exec::ProgramCache;
 use prog::{Inst, Program};
 use sparse::SparseSet;
 
 /// Return true if and only if the given program can be executed by a DFA.
 ///
 /// Generally, a DFA is always possible. A pathological case where it is not
-/// possible is if the number of NFA states exceeds u32::MAX, in which case,
+/// possible is if the number of NFA states exceeds `u32::MAX`, in which case,
 /// this function will return false.
 ///
 /// This function will also return false if the given program has any Unicode
 /// instructions (Char or Ranges) since the DFA operates on bytes only.
 pub fn can_exec(insts: &Program) -> bool {
     use prog::Inst::*;
     // If for some reason we manage to allocate a regex program with more
     // than i32::MAX instructions, then we can't execute the DFA because we
     // use 32 bit instruction pointer deltas for memory savings.
     // If i32::MAX is the largest positive delta,
     // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
     // and we are OK to use 32 bits.
-    if insts.len() > ::std::i32::MAX as usize {
+    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
         return false;
     }
     for inst in insts {
         match *inst {
             Char(_) | Ranges(_) => return false,
             EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
         }
     }
@@ -99,17 +99,17 @@ pub struct Cache {
     /// cached DFA states. In particular, the order of the NFA states matters
     /// for leftmost-first style matching. Namely, when computing a cached
     /// state, the set of NFA states stops growing as soon as the first Match
     /// instruction is observed.
     qcur: SparseSet,
     qnext: SparseSet,
 }
 
-/// CacheInner is logically just a part of Cache, but groups together fields
+/// `CacheInner` is logically just a part of Cache, but groups together fields
 /// that aren't passed as function parameters throughout search. (This split
 /// is mostly an artifact of the borrow checker. It is happily paid.)
 #[derive(Clone, Debug)]
 struct CacheInner {
     /// A cache of pre-compiled DFA states, keyed by the set of NFA states
     /// and the set of empty-width flags set at the byte in the input when the
     /// state was observed.
     ///
@@ -157,18 +157,18 @@ struct CacheInner {
     size: usize,
 }
 
 /// The transition table.
 ///
 /// It is laid out in row-major order, with states as rows and byte class
 /// transitions as columns.
 ///
-/// The transition table is responsible for producing valid StatePtrs. A
-/// StatePtr points to the start of a particular row in this table. When
+/// The transition table is responsible for producing valid `StatePtrs`. A
+/// `StatePtr` points to the start of a particular row in this table. When
 /// indexing to find the next state this allows us to avoid a multiplication
 /// when computing an index into the table.
 #[derive(Clone)]
 struct Transitions {
     /// The table.
     table: Vec<StatePtr>,
     /// The stride.
     num_byte_classes: usize,
@@ -247,17 +247,17 @@ impl<T> Result<T> {
     fn set_non_match(self, at: usize) -> Result<T> {
         match self {
             Result::NoMatch(_) => Result::NoMatch(at),
             r => r,
         }
     }
 }
 
-/// State is a DFA state. It contains an ordered set of NFA states (not
+/// `State` is a DFA state. It contains an ordered set of NFA states (not
 /// necessarily complete) and a smattering of flags.
 ///
 /// The flags are packed into the first byte of data.
 ///
 /// States don't carry their transitions. Instead, transitions are stored in
 /// a single row-major table.
 ///
 /// Delta encoding is used to store the instruction pointers.
@@ -266,17 +266,17 @@ impl<T> Result<T> {
 /// to the previous one. If a delta is in the range -127..127,
 /// it is packed into a single byte; Otherwise the byte 128 (-128 as an i8)
 /// is coded as a flag, followed by 4 bytes encoding the delta.
 #[derive(Clone, Eq, Hash, PartialEq)]
 struct State{
     data: Box<[u8]>,
 }
 
-/// InstPtr is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
+/// `InstPtr` is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
 /// an NFA state).
 ///
 /// Throughout this library, this is usually set to `usize`, but we force a
 /// `u32` here for the DFA to save on space.
 type InstPtr = u32;
 
 /// Adds ip to data using delta encoding with respect to prev.
 ///
@@ -317,17 +317,18 @@ impl State {
     fn inst_ptrs(&self) -> InstPtrs {
         InstPtrs {
             base: 0,
             data: &self.data[1..],
         }
     }
 }
 
-/// StatePtr is a 32 bit pointer to the start of a row in the transition table.
+/// `StatePtr` is a 32 bit pointer to the start of a row in the transition
+/// table.
 ///
 /// It has many special values. There are two types of special values:
 /// sentinels and flags.
 ///
 /// Sentinels corresponds to special states that carry some kind of
 /// significance. There are three such states: unknown, dead and quit states.
 ///
 /// Unknown states are states that haven't been computed yet. They indicate
@@ -340,17 +341,18 @@ impl State {
 /// immediately and return the longest match it has found thus far.
 ///
 /// Quit states are states that imply the DFA is not capable of matching the
 /// regex correctly. Currently, this is only used when a Unicode word boundary
 /// exists in the regex *and* a non-ASCII byte is observed.
 ///
 /// The other type of state pointer is a state pointer with special flag bits.
 /// There are two flags: a start flag and a match flag. The lower bits of both
-/// kinds always contain a "valid" StatePtr (indicated by the STATE_MAX mask).
+/// kinds always contain a "valid" `StatePtr` (indicated by the `STATE_MAX`
+/// mask).
 ///
 /// The start flag means that the state is a start state, and therefore may be
 /// subject to special prefix scanning optimizations.
 ///
 /// The match flag means that the state is a match state, and therefore the
 /// current position in the input (while searching) should be recorded.
 ///
 /// The above exists mostly in the service of making the inner loop fast.
@@ -457,17 +459,17 @@ impl<'a> Fsm<'a> {
     pub fn forward(
         prog: &'a Program,
         cache: &ProgramCache,
         quit_after_match: bool,
         text: &[u8],
         at: usize,
     ) -> Result<usize> {
         let mut cache = cache.borrow_mut();
-        let mut cache = &mut cache.dfa;
+        let cache = &mut cache.dfa;
         let mut dfa = Fsm {
             prog: prog,
             start: 0, // filled in below
             at: at,
             quit_after_match: quit_after_match,
             last_match_si: STATE_UNKNOWN,
             last_cache_flush: at,
             cache: &mut cache.inner,
@@ -490,17 +492,17 @@ impl<'a> Fsm<'a> {
     pub fn reverse(
         prog: &'a Program,
         cache: &ProgramCache,
         quit_after_match: bool,
         text: &[u8],
         at: usize,
     ) -> Result<usize> {
         let mut cache = cache.borrow_mut();
-        let mut cache = &mut cache.dfa_reverse;
+        let cache = &mut cache.dfa_reverse;
         let mut dfa = Fsm {
             prog: prog,
             start: 0, // filled in below
             at: at,
             quit_after_match: quit_after_match,
             last_match_si: STATE_UNKNOWN,
             last_cache_flush: at,
             cache: &mut cache.inner,
@@ -524,17 +526,17 @@ impl<'a> Fsm<'a> {
         prog: &'a Program,
         cache: &ProgramCache,
         matches: &mut [bool],
         text: &[u8],
         at: usize,
     ) -> Result<usize> {
         debug_assert!(matches.len() == prog.matches.len());
         let mut cache = cache.borrow_mut();
-        let mut cache = &mut cache.dfa;
+        let cache = &mut cache.dfa;
         let mut dfa = Fsm {
             prog: prog,
             start: 0, // filled in below
             at: at,
             quit_after_match: false,
             last_match_si: STATE_UNKNOWN,
             last_cache_flush: at,
             cache: &mut cache.inner,
@@ -993,26 +995,30 @@ impl<'a> Fsm<'a> {
                 Bytes(ref inst) => {
                     if b.as_byte().map_or(false, |b| inst.matches(b)) {
                         self.follow_epsilons(
                             inst.goto as InstPtr, qnext, empty_flags);
                     }
                 }
             }
         }
-        let mut cache = true;
-        if b.is_eof() && self.prog.matches.len() > 1 {
-            // If we're processing the last byte of the input and we're
-            // matching a regex set, then make the next state contain the
-            // previous states transitions. We do this so that the main
-            // matching loop can extract all of the match instructions.
-            mem::swap(qcur, qnext);
-            // And don't cache this state because it's totally bunk.
-            cache = false;
-        }
+
+        let cache =
+            if b.is_eof() && self.prog.matches.len() > 1 {
+                // If we're processing the last byte of the input and we're
+                // matching a regex set, then make the next state contain the
+                // previous states transitions. We do this so that the main
+                // matching loop can extract all of the match instructions.
+                mem::swap(qcur, qnext);
+                // And don't cache this state because it's totally bunk.
+                false
+            } else {
+                true
+            };
+
         // We've now built up the set of NFA states that ought to comprise the
         // next DFA state, so try to find it in the cache, and if it doesn't
         // exist, cache it.
         //
         // N.B. We pass `&mut si` here because the cache may clear itself if
         // it has gotten too full. When that happens, the location of the
         // current state may change.
         let mut next = match self.cached_state(
@@ -1025,17 +1031,17 @@ impl<'a> Fsm<'a> {
         };
         if (self.start & !STATE_START) == next {
             // Start states can never be match states since all matches are
             // delayed by one byte.
             debug_assert!(!self.state(next).flags().is_match());
             next = self.start_ptr(next);
         }
         if next <= STATE_MAX && self.state(next).flags().is_match() {
-            next = STATE_MATCH | next;
+            next |= STATE_MATCH;
         }
         debug_assert!(next != STATE_UNKNOWN);
         // And now store our state in the current state's next list.
         if cache {
             let cls = self.byte_class(b);
             self.cache.trans.set_next(si, cls, next);
         }
         Some(next)
@@ -1071,62 +1077,72 @@ impl<'a> Fsm<'a> {
         flags: EmptyFlags,
     ) {
         use prog::Inst::*;
         use prog::EmptyLook::*;
 
         // We need to traverse the NFA to follow epsilon transitions, so avoid
         // recursion with an explicit stack.
         self.cache.stack.push(ip);
-        while let Some(ip) = self.cache.stack.pop() {
-            // Don't visit states we've already added.
-            if q.contains(ip as usize) {
-                continue;
-            }
-            q.insert(ip as usize);
-            match self.prog[ip as usize] {
-                Char(_) | Ranges(_) => unreachable!(),
-                Match(_) | Bytes(_) => {}
-                EmptyLook(ref inst) => {
-                    // Only follow empty assertion states if our flags satisfy
-                    // the assertion.
-                    match inst.look {
-                        StartLine if flags.start_line => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        EndLine if flags.end_line => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        StartText if flags.start => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        EndText if flags.end => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        WordBoundaryAscii if flags.word_boundary => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        NotWordBoundaryAscii if flags.not_word_boundary => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        WordBoundary if flags.word_boundary => {
-                            self.cache.stack.push(inst.goto as InstPtr);
-                        }
-                        NotWordBoundary if flags.not_word_boundary => {
-                            self.cache.stack.push(inst.goto as InstPtr);
+        while let Some(mut ip) = self.cache.stack.pop() {
+            // Try to munch through as many states as possible without
+            // pushes/pops to the stack.
+            loop {
+                // Don't visit states we've already added.
+                if q.contains(ip as usize) {
+                    break;
+                }
+                q.insert(ip as usize);
+                match self.prog[ip as usize] {
+                    Char(_) | Ranges(_) => unreachable!(),
+                    Match(_) | Bytes(_) => {
+                        break;
+                    }
+                    EmptyLook(ref inst) => {
+                        // Only follow empty assertion states if our flags
+                        // satisfy the assertion.
+                        match inst.look {
+                            StartLine if flags.start_line => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            EndLine if flags.end_line => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            StartText if flags.start => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            EndText if flags.end => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            WordBoundaryAscii if flags.word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            NotWordBoundaryAscii if flags.not_word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            WordBoundary if flags.word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            NotWordBoundary if flags.not_word_boundary => {
+                                ip = inst.goto as InstPtr;
+                            }
+                            StartLine | EndLine | StartText | EndText
+                            | WordBoundaryAscii | NotWordBoundaryAscii
+                            | WordBoundary | NotWordBoundary => {
+                                break;
+                            }
                         }
-                        StartLine | EndLine | StartText | EndText => {}
-                        WordBoundaryAscii | NotWordBoundaryAscii => {}
-                        WordBoundary | NotWordBoundary => {}
                     }
-                }
-                Save(ref inst) => self.cache.stack.push(inst.goto as InstPtr),
-                Split(ref inst) => {
-                    self.cache.stack.push(inst.goto2 as InstPtr);
-                    self.cache.stack.push(inst.goto1 as InstPtr);
+                    Save(ref inst) => {
+                        ip = inst.goto as InstPtr;
+                    }
+                    Split(ref inst) => {
+                        self.cache.stack.push(inst.goto2 as InstPtr);
+                        ip = inst.goto1 as InstPtr;
+                    }
                 }
             }
         }
     }
 
     /// Find a previously computed state matching the given set of instructions
     /// and is_match bool.
     ///
@@ -1162,22 +1178,22 @@ impl<'a> Fsm<'a> {
             None => return Some(STATE_DEAD),
             Some(v) => v,
         };
         // In the cache? Cool. Done.
         if let Some(&si) = self.cache.compiled.get(&key) {
             return Some(si);
         }
         // If the cache has gotten too big, wipe it.
-        if self.approximate_size() > self.prog.dfa_size_limit {
-            if !self.clear_cache_and_save(current_state) {
+        if self.approximate_size() > self.prog.dfa_size_limit
+            && !self.clear_cache_and_save(current_state)
+            {
                 // Ooops. DFA is giving up.
                 return None;
             }
-        }
         // Allocate room for our state and add it.
         self.add_state(key)
     }
 
     /// Produces a key suitable for describing a state in the DFA cache.
     ///
     /// The key invariant here is that equivalent keys are produced for any two
     /// sets of ordered NFA states (and toggling of whether the previous NFA
@@ -1205,18 +1221,17 @@ impl<'a> Fsm<'a> {
 
         // Reserve 1 byte for flags.
         let mut insts = vec![0];
         let mut prev = 0;
         for &ip in q {
             let ip = usize_to_u32(ip);
             match self.prog[ip as usize] {
                 Char(_) | Ranges(_) => unreachable!(),
-                Save(_) => {}
-                Split(_) => {}
+                Save(_) | Split(_) => {}
                 Bytes(_) => push_inst_ptr(&mut insts, &mut prev, ip),
                 EmptyLook(_) => {
                     state_flags.set_empty();
                     push_inst_ptr(&mut insts, &mut prev, ip)
                 }
                 Match(_) => {
                     push_inst_ptr(&mut insts, &mut prev, ip);
                     if !self.continue_past_first_match() {
@@ -1296,17 +1311,17 @@ impl<'a> Fsm<'a> {
             Some(self.state(self.last_match_si).clone())
         } else {
             None
         };
         self.cache.reset_size();
         self.cache.trans.clear();
         self.cache.states.clear();
         self.cache.compiled.clear();
-        for s in self.cache.start_states.iter_mut() {
+        for s in &mut self.cache.start_states {
             *s = STATE_UNKNOWN;
         }
         // The unwraps are OK because we just cleared the cache and therefore
         // know that the next state pointer won't exceed STATE_MAX.
         let start_ptr = self.restore_state(start).unwrap();
         self.start = self.start_ptr(start_ptr);
         if let Some(last_match) = last_match {
             self.last_match_si = self.restore_state(last_match).unwrap();
@@ -1406,19 +1421,19 @@ impl<'a> Fsm<'a> {
     /// Computes the set of starting flags for the given position in text.
     ///
     /// This should only be used when executing the DFA forwards over the
     /// input.
     fn start_flags(&self, text: &[u8], at: usize) -> (EmptyFlags, StateFlags) {
         let mut empty_flags = EmptyFlags::default();
         let mut state_flags = StateFlags::default();
         empty_flags.start = at == 0;
-        empty_flags.end = text.len() == 0;
+        empty_flags.end = text.is_empty();
         empty_flags.start_line = at == 0 || text[at - 1] == b'\n';
-        empty_flags.end_line = text.len() == 0;
+        empty_flags.end_line = text.is_empty();
 
         let is_word_last = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
         let is_word = at < text.len() && Byte::byte(text[at]).is_ascii_word();
         if is_word_last {
             state_flags.set_word();
         }
         if is_word == is_word_last {
             empty_flags.not_word_boundary = true;
@@ -1435,19 +1450,19 @@ impl<'a> Fsm<'a> {
     fn start_flags_reverse(
         &self,
         text: &[u8],
         at: usize,
     ) -> (EmptyFlags, StateFlags) {
         let mut empty_flags = EmptyFlags::default();
         let mut state_flags = StateFlags::default();
         empty_flags.start = at == text.len();
-        empty_flags.end = text.len() == 0;
+        empty_flags.end = text.is_empty();
         empty_flags.start_line = at == text.len() || text[at] == b'\n';
-        empty_flags.end_line = text.len() == 0;
+        empty_flags.end_line = text.is_empty();
 
         let is_word_last =
             at < text.len() && Byte::byte(text[at]).is_ascii_word();
         let is_word = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
         if is_word_last {
             state_flags.set_word();
         }
         if is_word == is_word_last {
diff --git a/third_party/rust/regex/src/error.rs b/third_party/rust/regex/src/error.rs
index c95d67acddca..fff1969b4707 100644
--- a/third_party/rust/regex/src/error.rs
+++ b/third_party/rust/regex/src/error.rs
@@ -4,21 +4,20 @@
 //
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use std::fmt;
-
-use syntax;
+use std::iter::repeat;
 
 /// An error that occurred during parsing or compiling a regular expression.
-#[derive(Debug)]
+#[derive(Clone, PartialEq)]
 pub enum Error {
     /// A syntax error.
     Syntax(String),
     /// The compiled program exceeded the set size limit.
     /// The argument is the size limit imposed.
     CompiledTooBig(usize),
     /// Hints that destructuring should not be exhaustive.
     ///
@@ -51,13 +50,35 @@ impl fmt::Display for Error {
                 write!(f, "Compiled regex exceeds size limit of {} bytes.",
                        limit)
             }
             Error::__Nonexhaustive => unreachable!(),
         }
     }
 }
 
-impl From<syntax::Error> for Error {
-    fn from(err: syntax::Error) -> Error {
-        Error::Syntax(err.to_string())
+// We implement our own Debug implementation so that we show nicer syntax
+// errors when people use `Regex::new(...).unwrap()`. It's a little weird,
+// but the `Syntax` variant is already storing a `String` anyway, so we might
+// as well format it nicely.
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::Syntax(ref err) => {
+                let hr: String = repeat('~').take(79).collect();
+                writeln!(f, "Syntax(")?;
+                writeln!(f, "{}", hr)?;
+                writeln!(f, "{}", err)?;
+                writeln!(f, "{}", hr)?;
+                write!(f, ")")?;
+                Ok(())
+            }
+            Error::CompiledTooBig(limit) => {
+                f.debug_tuple("CompiledTooBig")
+                    .field(&limit)
+                    .finish()
+            }
+            Error::__Nonexhaustive => {
+                f.debug_tuple("__Nonexhaustive").finish()
+            }
+        }
     }
 }
diff --git a/third_party/rust/regex/src/exec.rs b/third_party/rust/regex/src/exec.rs
index 3192ce792876..578289aa5c0f 100644
--- a/third_party/rust/regex/src/exec.rs
+++ b/third_party/rust/regex/src/exec.rs
@@ -9,60 +9,62 @@
 // except according to those terms.
 
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::cmp;
 use std::sync::Arc;
 
 use thread_local::CachedThreadLocal;
-use syntax::{Expr, ExprBuilder, Literals};
+use syntax::ParserBuilder;
+use syntax::hir::Hir;
+use syntax::hir::literal::Literals;
 
 use backtrack;
 use compile::Compiler;
 use dfa;
 use error::Error;
 use input::{ByteInput, CharInput};
-use literals::LiteralSearcher;
+use literal::LiteralSearcher;
 use pikevm;
 use prog::Program;
 use re_builder::RegexOptions;
 use re_bytes;
 use re_set;
-use re_trait::{RegularExpression, Slot, Locations, as_slots};
+use re_trait::{RegularExpression, Slot, Locations};
 use re_unicode;
 use utf8::next_utf8;
 
-/// Exec manages the execution of a regular expression.
+/// `Exec` manages the execution of a regular expression.
 ///
 /// In particular, this manages the various compiled forms of a single regular
 /// expression and the choice of which matching engine to use to execute a
 /// regular expression.
 pub struct Exec {
     /// All read only state.
     ro: Arc<ExecReadOnly>,
     /// Caches for the various matching engines.
     cache: CachedThreadLocal<ProgramCache>,
 }
 
-/// ExecNoSync is like Exec, except it embeds a reference to a cache. This
+/// `ExecNoSync` is like `Exec`, except it embeds a reference to a cache. This
 /// means it is no longer Sync, but we can now avoid the overhead of
 /// synchronization to fetch the cache.
 #[derive(Debug)]
 pub struct ExecNoSync<'c> {
     /// All read only state.
     ro: &'c Arc<ExecReadOnly>,
     /// Caches for the various matching engines.
     cache: &'c ProgramCache,
 }
 
-/// ExecNoSyncStr is like ExecNoSync, but matches on &str instead of &[u8].
+/// `ExecNoSyncStr` is like `ExecNoSync`, but matches on &str instead of &[u8].
 pub struct ExecNoSyncStr<'c>(ExecNoSync<'c>);
 
-/// ExecReadOnly comprises all read only state for a regex. Namely, all such
+/// `ExecReadOnly` comprises all read only state for a regex. Namely, all such
 /// state is determined at compile time and never changes during search.
 #[derive(Debug)]
 struct ExecReadOnly {
     /// The original regular expressions given by the caller to compile.
     res: Vec<String>,
     /// A compiled program that is used in the NFA simulation and backtracking.
     /// It can be byte-based or Unicode codepoint based.
     ///
@@ -97,17 +99,17 @@ pub struct ExecBuilder {
     match_type: Option<MatchType>,
     bytes: bool,
     only_utf8: bool,
 }
 
 /// Parsed represents a set of parsed regular expressions and their detected
 /// literals.
 struct Parsed {
-    exprs: Vec<Expr>,
+    exprs: Vec<Hir>,
     prefixes: Literals,
     suffixes: Literals,
     bytes: bool,
 }
 
 impl ExecBuilder {
     /// Create a regex execution builder.
     ///
@@ -209,67 +211,72 @@ impl ExecBuilder {
         let mut exprs = Vec::with_capacity(self.options.pats.len());
         let mut prefixes = Some(Literals::empty());
         let mut suffixes = Some(Literals::empty());
         let mut bytes = false;
         let is_set = self.options.pats.len() > 1;
         // If we're compiling a regex set and that set has any anchored
         // expressions, then disable all literal optimizations.
         for pat in &self.options.pats {
-            let parser =
-                ExprBuilder::new()
+            let mut parser =
+                ParserBuilder::new()
+                    .octal(self.options.octal)
                     .case_insensitive(self.options.case_insensitive)
                     .multi_line(self.options.multi_line)
                     .dot_matches_new_line(self.options.dot_matches_new_line)
                     .swap_greed(self.options.swap_greed)
                     .ignore_whitespace(self.options.ignore_whitespace)
                     .unicode(self.options.unicode)
-                    .allow_bytes(!self.only_utf8);
-            let expr = try!(parser.parse(pat));
-            bytes = bytes || expr.has_bytes();
-
-            if !expr.is_anchored_start() && expr.has_anchored_start() {
+                    .allow_invalid_utf8(!self.only_utf8)
+                    .nest_limit(self.options.nest_limit)
+                    .build();
+            let expr = parser
+                .parse(pat)
+                .map_err(|e| Error::Syntax(e.to_string()))?;
+            bytes = bytes || !expr.is_always_utf8();
+
+            if !expr.is_anchored_start() && expr.is_any_anchored_start() {
                 // Partial anchors unfortunately make it hard to use prefixes,
                 // so disable them.
                 prefixes = None;
             } else if is_set && expr.is_anchored_start() {
                 // Regex sets with anchors do not go well with literal
                 // optimizations.
                 prefixes = None;
             }
             prefixes = prefixes.and_then(|mut prefixes| {
                 if !prefixes.union_prefixes(&expr) {
                     None
                 } else {
                     Some(prefixes)
                 }
             });
 
-            if !expr.is_anchored_end() && expr.has_anchored_end() {
+            if !expr.is_anchored_end() && expr.is_any_anchored_end() {
                 // Partial anchors unfortunately make it hard to use suffixes,
                 // so disable them.
                 suffixes = None;
             } else if is_set && expr.is_anchored_end() {
                 // Regex sets with anchors do not go well with literal
                 // optimizations.
-                prefixes = None;
+                suffixes = None;
             }
             suffixes = suffixes.and_then(|mut suffixes| {
                 if !suffixes.union_suffixes(&expr) {
                     None
                 } else {
                     Some(suffixes)
                 }
             });
             exprs.push(expr);
         }
         Ok(Parsed {
             exprs: exprs,
-            prefixes: prefixes.unwrap_or(Literals::empty()),
-            suffixes: suffixes.unwrap_or(Literals::empty()),
+            prefixes: prefixes.unwrap_or_else(Literals::empty),
+            suffixes: suffixes.unwrap_or_else(Literals::empty),
             bytes: bytes,
         })
     }
 
     /// Build an executor that can run a regular expression.
     pub fn build(self) -> Result<Exec, Error> {
         // Special case when we have no patterns to compile.
         // This can happen when compiling a regex set.
@@ -279,36 +286,36 @@ impl ExecBuilder {
                 nfa: Program::new(),
                 dfa: Program::new(),
                 dfa_reverse: Program::new(),
                 suffixes: LiteralSearcher::empty(),
                 match_type: MatchType::Nothing,
             });
             return Ok(Exec { ro: ro, cache: CachedThreadLocal::new() });
         }
-        let parsed = try!(self.parse());
-        let mut nfa = try!(
+        let parsed = self.parse()?;
+        let mut nfa =
             Compiler::new()
                      .size_limit(self.options.size_limit)
                      .bytes(self.bytes || parsed.bytes)
                      .only_utf8(self.only_utf8)
-                     .compile(&parsed.exprs));
-        let mut dfa = try!(
+                     .compile(&parsed.exprs)?;
+        let mut dfa =
             Compiler::new()
                      .size_limit(self.options.size_limit)
                      .dfa(true)
                      .only_utf8(self.only_utf8)
-                     .compile(&parsed.exprs));
-        let mut dfa_reverse = try!(
+                     .compile(&parsed.exprs)?;
+        let mut dfa_reverse =
             Compiler::new()
                      .size_limit(self.options.size_limit)
                      .dfa(true)
                      .only_utf8(self.only_utf8)
                      .reverse(true)
-                     .compile(&parsed.exprs));
+                     .compile(&parsed.exprs)?;
 
         let prefixes = parsed.prefixes.unambiguous_prefixes();
         let suffixes = parsed.suffixes.unambiguous_suffixes();
         nfa.prefixes = LiteralSearcher::prefixes(prefixes);
         dfa.prefixes = nfa.prefixes.clone();
         dfa.dfa_size_limit = self.options.dfa_size_limit;
         dfa_reverse.dfa_size_limit = self.options.dfa_size_limit;
 
@@ -347,23 +354,23 @@ impl<'c> RegularExpression for ExecNoSyncStr<'c> {
     }
 
     #[inline(always)] // reduces constant overhead
     fn find_at(&self, text: &str, start: usize) -> Option<(usize, usize)> {
         self.0.find_at(text.as_bytes(), start)
     }
 
     #[inline(always)] // reduces constant overhead
-    fn read_captures_at(
+    fn captures_read_at(
         &self,
         locs: &mut Locations,
         text: &str,
         start: usize,
     ) -> Option<(usize, usize)> {
-        self.0.read_captures_at(locs, text.as_bytes(), start)
+        self.0.captures_read_at(locs, text.as_bytes(), start)
     }
 }
 
 impl<'c> RegularExpression for ExecNoSync<'c> {
     type Text = [u8];
 
     /// Returns the number of capture slots in the regular expression. (There
     /// are two slots for every capture group, corresponding to possibly empty
@@ -392,17 +399,17 @@ impl<'c> RegularExpression for ExecNoSync<'c> {
                     dfa::Result::Match(end) => Some(end),
                     dfa::Result::NoMatch(_) => None,
                     dfa::Result::Quit => self.shortest_nfa(text, start),
                 }
             }
             MatchType::DfaAnchoredReverse => {
                 match dfa::Fsm::reverse(
                     &self.ro.dfa_reverse,
-                    &self.cache,
+                    self.cache,
                     true,
                     &text[start..],
                     text.len(),
                 ) {
                     dfa::Result::Match(_) => Some(text.len()),
                     dfa::Result::NoMatch(_) => None,
                     dfa::Result::Quit => self.shortest_nfa(text, start),
                 }
@@ -440,17 +447,17 @@ impl<'c> RegularExpression for ExecNoSync<'c> {
                     dfa::Result::Match(_) => true,
                     dfa::Result::NoMatch(_) => false,
                     dfa::Result::Quit => self.match_nfa(text, start),
                 }
             }
             MatchType::DfaAnchoredReverse => {
                 match dfa::Fsm::reverse(
                     &self.ro.dfa_reverse,
-                    &self.cache,
+                    self.cache,
                     true,
                     &text[start..],
                     text.len(),
                 ) {
                     dfa::Result::Match(_) => true,
                     dfa::Result::NoMatch(_) => false,
                     dfa::Result::Quit => self.match_nfa(text, start),
                 }
@@ -516,23 +523,23 @@ impl<'c> RegularExpression for ExecNoSync<'c> {
     /// Finds the start and end location of the leftmost-first match and also
     /// fills in all matching capture groups.
     ///
     /// The number of capture slots given should be equal to the total number
     /// of capture slots in the compiled program.
     ///
     /// Note that the first two slots always correspond to the start and end
     /// locations of the overall match.
-    fn read_captures_at(
+    fn captures_read_at(
         &self,
         locs: &mut Locations,
         text: &[u8],
         start: usize,
     ) -> Option<(usize, usize)> {
-        let slots = as_slots(locs);
+        let slots = locs.as_slots();
         for slot in slots.iter_mut() {
             *slot = None;
         }
         // If the caller unnecessarily uses this, then we try to save them
         // from themselves.
         match slots.len() {
             0 => return self.find_at(text, start),
             2 => {
@@ -549,22 +556,26 @@ impl<'c> RegularExpression for ExecNoSync<'c> {
         }
         match self.ro.match_type {
             MatchType::Literal(ty) => {
                 self.find_literals(ty, text, start).and_then(|(s, e)| {
                     self.captures_nfa_with_match(slots, text, s, e)
                 })
             }
             MatchType::Dfa => {
-                match self.find_dfa_forward(text, start) {
-                    dfa::Result::Match((s, e)) => {
-                        self.captures_nfa_with_match(slots, text, s, e)
+                if self.ro.nfa.is_anchored_start {
+                    self.captures_nfa(slots, text, start)
+                } else {
+                    match self.find_dfa_forward(text, start) {
+                        dfa::Result::Match((s, e)) => {
+                            self.captures_nfa_with_match(slots, text, s, e)
+                        }
+                        dfa::Result::NoMatch(_) => None,
+                        dfa::Result::Quit => self.captures_nfa(slots, text, start),
                     }
-                    dfa::Result::NoMatch(_) => None,
-                    dfa::Result::Quit => self.captures_nfa(slots, text, start),
                 }
             }
             MatchType::DfaAnchoredReverse => {
                 match self.find_dfa_anchored_reverse(text, start) {
                     dfa::Result::Match((s, e)) => {
                         self.captures_nfa_with_match(slots, text, s, e)
                     }
                     dfa::Result::NoMatch(_) => None,
@@ -604,18 +615,23 @@ impl<'c> ExecNoSync<'c> {
         match ty {
             Unanchored => {
                 let lits = &self.ro.nfa.prefixes;
                 lits.find(&text[start..])
                     .map(|(s, e)| (start + s, start + e))
             }
             AnchoredStart => {
                 let lits = &self.ro.nfa.prefixes;
-                lits.find_start(&text[start..])
-                    .map(|(s, e)| (start + s, start + e))
+                if !self.ro.nfa.is_anchored_start
+                    || (self.ro.nfa.is_anchored_start && start == 0) {
+                    lits.find_start(&text[start..])
+                        .map(|(s, e)| (start + s, start + e))
+                } else {
+                    None
+                }
             }
             AnchoredEnd => {
                 let lits = &self.ro.suffixes;
                 lits.find_end(&text[start..])
                     .map(|(s, e)| (start + s, start + e))
             }
         }
     }
@@ -628,30 +644,30 @@ impl<'c> ExecNoSync<'c> {
     fn find_dfa_forward(
         &self,
         text: &[u8],
         start: usize,
     ) -> dfa::Result<(usize, usize)> {
         use dfa::Result::*;
         let end = match dfa::Fsm::forward(
             &self.ro.dfa,
-            &self.cache,
+            self.cache,
             false,
             text,
             start,
         ) {
             NoMatch(i) => return NoMatch(i),
             Quit => return Quit,
             Match(end) if start == end => return Match((start, start)),
             Match(end) => end,
         };
         // Now run the DFA in reverse to find the start of the match.
         match dfa::Fsm::reverse(
             &self.ro.dfa_reverse,
-            &self.cache,
+            self.cache,
             false,
             &text[start..],
             end - start,
         ) {
             Match(s) => Match((start + s, end)),
             NoMatch(i) => NoMatch(i),
             Quit => Quit,
         }
@@ -667,31 +683,31 @@ impl<'c> ExecNoSync<'c> {
     fn find_dfa_anchored_reverse(
         &self,
         text: &[u8],
         start: usize,
     ) -> dfa::Result<(usize, usize)> {
         use dfa::Result::*;
         match dfa::Fsm::reverse(
             &self.ro.dfa_reverse,
-            &self.cache,
+            self.cache,
             false,
             &text[start..],
             text.len() - start,
         ) {
             Match(s) => Match((start + s, text.len())),
             NoMatch(i) => NoMatch(i),
             Quit => Quit,
         }
     }
 
     /// Finds the end of the shortest match using only the DFA.
     #[inline(always)] // reduces constant overhead
     fn shortest_dfa(&self, text: &[u8], start: usize) -> dfa::Result<usize> {
-        dfa::Fsm::forward(&self.ro.dfa, &self.cache, true, text, start)
+        dfa::Fsm::forward(&self.ro.dfa, self.cache, true, text, start)
     }
 
     /// Finds the end of the shortest match using only the DFA by scanning for
     /// suffix literals.
     ///
     #[inline(always)] // reduces constant overhead
     fn shortest_dfa_reverse_suffix(
         &self,
@@ -726,23 +742,23 @@ impl<'c> ExecNoSync<'c> {
         use dfa::Result::*;
 
         let lcs = self.ro.suffixes.lcs();
         debug_assert!(lcs.len() >= 1);
         let mut start = original_start;
         let mut end = start;
         while end <= text.len() {
             start = end;
-            end = end + match lcs.find(&text[end..]) {
+            end += match lcs.find(&text[end..]) {
                 None => return Some(NoMatch(text.len())),
                 Some(start) => start + lcs.len(),
             };
             match dfa::Fsm::reverse(
                 &self.ro.dfa_reverse,
-                &self.cache,
+                self.cache,
                 false,
                 &text[start..end],
                 end - start,
             ) {
                 Match(0) | NoMatch(0) => return None,
                 Match(s) => return Some(Match((s + start, end))),
                 NoMatch(_) => continue,
                 Quit => return Some(Quit),
@@ -773,17 +789,17 @@ impl<'c> ExecNoSync<'c> {
         // without a match is if the DFA gives up (seems unlikely).
         //
         // Now run the DFA forwards to find the proper end of the match.
         // (The suffix literal match can only indicate the earliest
         // possible end location, which may appear before the end of the
         // leftmost-first match.)
         match dfa::Fsm::forward(
             &self.ro.dfa,
-            &self.cache,
+            self.cache,
             false,
             text,
             match_start,
         ) {
             NoMatch(_) => panic!("BUG: reverse match implies forward match"),
             Quit => Quit,
             Match(e) => Match((match_start, e)),
         }
@@ -934,26 +950,26 @@ impl<'c> ExecNoSync<'c> {
         slots: &mut [Slot],
         quit_after_match: bool,
         text: &[u8],
         start: usize,
     ) -> bool {
         if self.ro.nfa.uses_bytes() {
             pikevm::Fsm::exec(
                 &self.ro.nfa,
-                &self.cache,
+                self.cache,
                 matches,
                 slots,
                 quit_after_match,
                 ByteInput::new(text, self.ro.nfa.only_utf8),
                 start)
         } else {
             pikevm::Fsm::exec(
                 &self.ro.nfa,
-                &self.cache,
+                self.cache,
                 matches,
                 slots,
                 quit_after_match,
                 CharInput::new(text),
                 start)
         }
     }
 
@@ -963,25 +979,25 @@ impl<'c> ExecNoSync<'c> {
         matches: &mut [bool],
         slots: &mut [Slot],
         text: &[u8],
         start: usize,
     ) -> bool {
         if self.ro.nfa.uses_bytes() {
             backtrack::Bounded::exec(
                 &self.ro.nfa,
-                &self.cache,
+                self.cache,
                 matches,
                 slots,
                 ByteInput::new(text, self.ro.nfa.only_utf8),
                 start)
         } else {
             backtrack::Bounded::exec(
                 &self.ro.nfa,
-                &self.cache,
+                self.cache,
                 matches,
                 slots,
                 CharInput::new(text),
                 start)
         }
     }
 
     /// Finds which regular expressions match the given text.
@@ -998,24 +1014,24 @@ impl<'c> ExecNoSync<'c> {
         start: usize,
     ) -> bool {
         use self::MatchType::*;
         if !self.is_anchor_end_match(text) {
             return false;
         }
         match self.ro.match_type {
             Literal(ty) => {
-                debug_assert!(matches.len() == 1);
+                debug_assert_eq!(matches.len(), 1);
                 matches[0] = self.find_literals(ty, text, start).is_some();
                 matches[0]
             }
             Dfa | DfaAnchoredReverse | DfaSuffix | DfaMany => {
                 match dfa::Fsm::forward_many(
                     &self.ro.dfa,
-                    &self.cache,
+                    self.cache,
                     matches,
                     text,
                     start,
                 ) {
                     dfa::Result::Match(_) => true,
                     dfa::Result::NoMatch(_) => false,
                     dfa::Result::Quit => {
                         self.exec_nfa(
@@ -1246,17 +1262,17 @@ enum MatchNfaType {
     Backtrack,
     /// The Pike VM.
     ///
     /// (This is only set by tests, since it never makes sense to always want
     /// the Pike VM.)
     PikeVM,
 }
 
-/// ProgramCache maintains reusable allocations for each matching engine
+/// `ProgramCache` maintains reusable allocations for each matching engine
 /// available to a particular program.
 pub type ProgramCache = RefCell<ProgramCacheInner>;
 
 #[derive(Clone, Debug)]
 pub struct ProgramCacheInner {
     pub pikevm: pikevm::Cache,
     pub backtrack: backtrack::Cache,
     pub dfa: dfa::Cache,
@@ -1268,8 +1284,67 @@ impl ProgramCacheInner {
         ProgramCacheInner {
             pikevm: pikevm::Cache::new(&ro.nfa),
             backtrack: backtrack::Cache::new(&ro.nfa),
             dfa: dfa::Cache::new(&ro.dfa),
             dfa_reverse: dfa::Cache::new(&ro.dfa_reverse),
         }
     }
 }
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn uppercut_s_backtracking_bytes_default_bytes_mismatch() {
+        use internal::ExecBuilder;
+
+        let backtrack_bytes_re = ExecBuilder::new("^S")
+            .bounded_backtracking()
+            .only_utf8(false)
+            .build()
+            .map(|exec| exec.into_byte_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let default_bytes_re = ExecBuilder::new("^S")
+            .only_utf8(false)
+            .build()
+            .map(|exec| exec.into_byte_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let input = vec![83, 83];
+
+        let s1 = backtrack_bytes_re.split(&input);
+        let s2 = default_bytes_re.split(&input);
+        for (chunk1, chunk2) in s1.zip(s2) {
+            assert_eq!(chunk1, chunk2);
+        }
+    }
+
+    #[test]
+    fn unicode_lit_star_backtracking_utf8bytes_default_utf8bytes_mismatch() {
+        use internal::ExecBuilder;
+
+        let backtrack_bytes_re = ExecBuilder::new(r"^(?u:\*)")
+            .bounded_backtracking()
+            .bytes(true)
+            .build()
+            .map(|exec| exec.into_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let default_bytes_re = ExecBuilder::new(r"^(?u:\*)")
+            .bytes(true)
+            .build()
+            .map(|exec| exec.into_regex())
+            .map_err(|err| format!("{}", err))
+            .unwrap();
+
+        let input = "**";
+
+        let s1 = backtrack_bytes_re.split(input);
+        let s2 = default_bytes_re.split(input);
+        for (chunk1, chunk2) in s1.zip(s2) {
+            assert_eq!(chunk1, chunk2);
+        }
+    }
+}
diff --git a/third_party/rust/regex/src/expand.rs b/third_party/rust/regex/src/expand.rs
index 55873f88bb96..a5e43b527946 100644
--- a/third_party/rust/regex/src/expand.rs
+++ b/third_party/rust/regex/src/expand.rs
@@ -84,18 +84,18 @@ pub fn expand_bytes(
                 dst.extend(
                     caps.name(name).map(|m| m.as_bytes()).unwrap_or(b""));
             }
         }
     }
     dst.extend(replacement);
 }
 
-/// CaptureRef represents a reference to a capture group inside some text. The
-/// reference is either a capture group name or a number.
+/// `CaptureRef` represents a reference to a capture group inside some text.
+/// The reference is either a capture group name or a number.
 ///
 /// It is also tagged with the position in the text immediately proceding the
 /// capture reference.
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 struct CaptureRef<'a> {
     cap: Ref<'a>,
     end: usize,
 }
@@ -145,17 +145,17 @@ fn find_cap_ref<T: ?Sized + AsRef<[u8]>>(
     }
     if cap_end == i {
         return None;
     }
     // We just verified that the range 0..cap_end is valid ASCII, so it must
     // therefore be valid UTF-8. If we really cared, we could avoid this UTF-8
     // check with either unsafe or by parsing the number straight from &[u8].
     let cap = str::from_utf8(&rep[i..cap_end])
-                  .ok().expect("valid UTF-8 capture name");
+                  .expect("valid UTF-8 capture name");
     if brace {
         if !rep.get(cap_end).map_or(false, |&b| b == b'}') {
             return None;
         }
         cap_end += 1;
     }
     Some(CaptureRef {
         cap: match cap.parse::<u32>() {
diff --git a/third_party/rust/regex/src/input.rs b/third_party/rust/regex/src/input.rs
index afb946342c49..56097bd56255 100644
--- a/third_party/rust/regex/src/input.rs
+++ b/third_party/rust/regex/src/input.rs
@@ -11,17 +11,17 @@
 use std::char;
 use std::cmp::Ordering;
 use std::fmt;
 use std::ops;
 use std::u32;
 
 use syntax;
 
-use literals::LiteralSearcher;
+use literal::LiteralSearcher;
 use prog::InstEmptyLook;
 use utf8::{decode_utf8, decode_last_utf8};
 
 /// Represents a location in the input.
 #[derive(Clone, Copy, Debug)]
 pub struct InputAt {
     pos: usize,
     c: Char,
@@ -53,16 +53,22 @@ impl InputAt {
         self.byte
     }
 
     /// Returns the UTF-8 width of the character at this position.
     pub fn len(&self) -> usize {
         self.len
     }
 
+    /// Returns whether the UTF-8 width of the character at this position
+    /// is zero.
+    pub fn is_empty(&self) -> bool {
+        self.len == 0
+    }
+
     /// Returns the byte offset of this position.
     pub fn pos(&self) -> usize {
         self.pos
     }
 
     /// Returns the byte offset of the next position in the input.
     pub fn next_pos(&self) -> usize {
         self.pos + self.len
@@ -93,16 +99,19 @@ pub trait Input {
         &self,
         prefixes: &LiteralSearcher,
         at: InputAt,
     ) -> Option<InputAt>;
 
     /// The number of bytes in the input.
     fn len(&self) -> usize;
 
+    /// Whether the input is empty.
+    fn is_empty(&self) -> bool { self.len() == 0 }
+
     /// Return the given input as a sequence of bytes.
     fn as_bytes(&self) -> &[u8];
 }
 
 impl<'a, T: Input> Input for &'a T {
     fn at(&self, i: usize) -> InputAt { (**self).at(i) }
 
     fn next_char(&self, at: InputAt) -> Char { (**self).next_char(at) }
@@ -209,20 +218,16 @@ impl<'t> Input for CharInput<'t> {
     }
 
     fn as_bytes(&self) -> &[u8] {
         self.0
     }
 }
 
 /// An input reader over bytes.
-///
-/// N.B. We represent the reader with a string for now, since that gives us
-/// easy access to necessary Unicode decoding (used for word boundary look
-/// ahead/look behind).
 #[derive(Clone, Copy, Debug)]
 pub struct ByteInput<'t> {
     text: &'t [u8],
     only_utf8: bool,
 }
 
 impl<'t> ByteInput<'t> {
     /// Return a new byte-based input reader for the given string.
@@ -242,17 +247,17 @@ impl<'t> ops::Deref for ByteInput<'t> {
     }
 }
 
 impl<'t> Input for ByteInput<'t> {
     fn at(&self, i: usize) -> InputAt {
         InputAt {
             pos: i,
             c: None.into(),
-            byte: self.get(i).map(|&b| b),
+            byte: self.get(i).cloned(),
             len: 1,
         }
     }
 
     fn next_char(&self, at: InputAt) -> Char {
         decode_utf8(&self[at.pos()..]).map(|(c, _)| c).into()
     }
 
@@ -320,17 +325,17 @@ impl<'t> Input for ByteInput<'t> {
         prefixes.find(&self[at.pos()..]).map(|(s, _)| self.at(at.pos() + s))
     }
 
     fn len(&self) -> usize {
         self.text.len()
     }
 
     fn as_bytes(&self) -> &[u8] {
-        &self.text
+        self.text
     }
 }
 
 /// An inline representation of `Option<char>`.
 ///
 /// This eliminates the need to do case analysis on `Option<char>` to determine
 /// ordinality with other characters.
 ///
@@ -361,38 +366,28 @@ impl Char {
     pub fn len_utf8(self) -> usize {
         char::from_u32(self.0).map_or(0, |c| c.len_utf8())
     }
 
     /// Returns true iff the character is a word character.
     ///
     /// If the character is absent, then false is returned.
     pub fn is_word_char(self) -> bool {
-        char::from_u32(self.0).map_or(false, syntax::is_word_char)
+        char::from_u32(self.0).map_or(false, syntax::is_word_character)
     }
 
     /// Returns true iff the byte is a word byte.
     ///
     /// If the byte is absent, then false is returned.
     pub fn is_word_byte(self) -> bool {
         match char::from_u32(self.0) {
-            None => false,
             Some(c) if c <= '\u{7F}' => syntax::is_word_byte(c as u8),
-            Some(_) => false,
+            None | Some(_) => false,
         }
     }
-
-    /// Converts the character to a real primitive `char`.
-    ///
-    /// If the character is absent, then `None` is returned.
-    pub fn as_char(self) -> Option<char> {
-        // This is only used in the `regex!` macro because it expands char
-        // classes into `match` expressions (instead of binary search).
-        char::from_u32(self.0)
-    }
 }
 
 impl From<char> for Char {
     fn from(c: char) -> Char { Char(c as u32) }
 }
 
 impl From<Option<char>> for Char {
     fn from(c: Option<char>) -> Char {
diff --git a/third_party/rust/regex/src/lib.rs b/third_party/rust/regex/src/lib.rs
index 128932e620d8..9ca156084a8d 100644
--- a/third_party/rust/regex/src/lib.rs
+++ b/third_party/rust/regex/src/lib.rs
@@ -24,17 +24,17 @@ documentation for the [`Regex`](struct.Regex.html) type.
 
 # Usage
 
 This crate is [on crates.io](https://crates.io/crates/regex) and can be
 used by adding `regex` to your dependencies in your project's `Cargo.toml`.
 
 ```toml
 [dependencies]
-regex = "0.2"
+regex = "1"
 ```
 
 and this to your crate root:
 
 ```rust
 extern crate regex;
 ```
 
@@ -51,17 +51,17 @@ assert!(re.is_match("2014-01-01"));
 ```
 
 Notice the use of the `^` and `$` anchors. In this crate, every expression
 is executed with an implicit `.*?` at the beginning and end, which allows
 it to match anywhere in the text. Anchors can be used to ensure that the
 full text matches an expression.
 
 This example also demonstrates the utility of
-[raw strings](https://doc.rust-lang.org/stable/reference.html#raw-string-literals)
+[raw strings](https://doc.rust-lang.org/stable/reference/tokens.html#raw-string-literals)
 in Rust, which
 are just like regular strings except they are prefixed with an `r` and do
 not process any escape sequences. For example, `"\\d"` is the same
 expression as `r"\d"`.
 
 # Example: Avoid compiling the same regex in a loop
 
 It is an anti-pattern to compile the same regular expression in a loop
@@ -212,19 +212,18 @@ only need to test if an expression matches a string. (Use `is_match`
 instead.)
 
 # Unicode
 
 This implementation executes regular expressions **only** on valid UTF-8
 while exposing match locations as byte indices into the search string.
 
 Only simple case folding is supported. Namely, when matching
-case-insensitively, the characters are first mapped using the [simple case
-folding](ftp://ftp.unicode.org/Public/UNIDATA/CaseFolding.txt) mapping
-before matching.
+case-insensitively, the characters are first mapped using the "simple" case
+folding rules defined by Unicode.
 
 Regular expressions themselves are **only** interpreted as a sequence of
 Unicode scalar values. This means you can use Unicode characters directly
 in your expression:
 
 ```rust
 # extern crate regex; use regex::Regex;
 # fn main() {
@@ -243,29 +242,35 @@ are some examples:
   of whitespace categorized by Unicode.
 * `\b` matches a Unicode word boundary.
 * Negated character classes like `[^a]` match all Unicode scalar values except
   for `a`.
 * `^` and `$` are **not** Unicode aware in multi-line mode. Namely, they only
   recognize `\n` and not any of the other forms of line terminators defined
   by Unicode.
 
-Finally, Unicode general categories and scripts are available as character
-classes. For example, you can match a sequence of numerals, Greek or
-Cherokee letters:
+Unicode general categories, scripts, script extensions, ages and a smattering
+of boolean properties are available as character classes. For example, you can
+match a sequence of numerals, Greek or Cherokee letters:
 
 ```rust
 # extern crate regex; use regex::Regex;
 # fn main() {
 let re = Regex::new(r"[\pN\p{Greek}\p{Cherokee}]+").unwrap();
 let mat = re.find("abcΔᎠβⅠᏴγδⅡxyz").unwrap();
 assert_eq!((mat.start(), mat.end()), (3, 23));
 # }
 ```
 
+For a more detailed breakdown of Unicode support with respect to
+[UTS#18](http://unicode.org/reports/tr18/),
+please see the
+[UNICODE](https://github.com/rust-lang/regex/blob/master/UNICODE.md)
+document in the root of the regex repository.
+
 # Opt out of Unicode support
 
 The `bytes` sub-module provides a `Regex` type that can be used to match
 on `&[u8]`. By default, text is interpreted as UTF-8 just like it is with
 the main `Regex` type. However, this behavior can be disabled by turning
 off the `u` flag, even if doing so could result in matching invalid UTF-8.
 For example, when the `u` flag is disabled, `.` will match any byte instead
 of any Unicode scalar value.
@@ -277,17 +282,17 @@ example, `(?-u:\w)` is an ASCII-only `\w` character class and is legal in an
 `\xFF`, which is invalid UTF-8 and therefore is illegal in `&str`-based
 regexes.
 
 # Syntax
 
 The syntax supported in this crate is documented below.
 
 Note that the regular expression parser and abstract syntax are exposed in
-a separate crate, [`regex-syntax`](../regex_syntax/index.html).
+a separate crate, [`regex-syntax`](https://docs.rs/regex-syntax).
 
 ## Matching one character
 
 <pre class="rust">
 .             any character except new line (includes new line with s flag)
 \d            digit (\p{Nd})
 \D            not digit
 \pN           One-letter name Unicode character class
@@ -302,16 +307,18 @@ a separate crate, [`regex-syntax`](../regex_syntax/index.html).
 [xyz]         A character class matching either x, y or z (union).
 [^xyz]        A character class matching any character except x, y and z.
 [a-z]         A character class matching any character in range a-z.
 [[:alpha:]]   ASCII character class ([A-Za-z])
 [[:^alpha:]]  Negated ASCII character class ([^A-Za-z])
 [x[^xyz]]     Nested/grouping character class (matching any character except y and z)
 [a-y&&xyz]    Intersection (matching x or y)
 [0-9&&[^4]]   Subtraction using intersection and negation (matching 0-9 except 4)
+[0-9--4]      Direct subtraction (matching 0-9 except 4)
+[a-g~~b-h]    Symmetric difference (matching `a` and `h` only)
 [\[\]]        Escaping in character classes (matching [ or ])
 </pre>
 
 Any named character class may appear inside a bracketed `[...]` character
 class. For example, `[\p{Greek}[:digit:]]` matches any Greek or ASCII
 digit. `[\p{Greek}&&\pL]` matches Greek letters.
 
 Precedence in character classes, from most binding to least:
@@ -369,64 +376,87 @@ $     the end of text (or end-of-line with multi-line mode)
 Flags are each a single character. For example, `(?x)` sets the flag `x`
 and `(?-x)` clears the flag `x`. Multiple flags can be set or cleared at
 the same time: `(?xy)` sets both the `x` and `y` flags and `(?x-y)` sets
 the `x` flag and clears the `y` flag.
 
 All flags are by default disabled unless stated otherwise. They are:
 
 <pre class="rust">
-i     case-insensitive
+i     case-insensitive: letters match both upper and lower case
 m     multi-line mode: ^ and $ match begin/end of line
 s     allow . to match \n
 U     swap the meaning of x* and x*?
 u     Unicode support (enabled by default)
 x     ignore whitespace and allow line comments (starting with `#`)
 </pre>
 
-Here's an example that matches case-insensitively for only part of the
-expression:
+Flags can be toggled within a pattern. Here's an example that matches
+case-insensitively for the first part but case-sensitively for the second part:
 
 ```rust
 # extern crate regex; use regex::Regex;
 # fn main() {
 let re = Regex::new(r"(?i)a+(?-i)b+").unwrap();
 let cap = re.captures("AaAaAbbBBBb").unwrap();
 assert_eq!(&cap[0], "AaAaAbb");
 # }
 ```
 
 Notice that the `a+` matches either `a` or `A`, but the `b+` only matches
 `b`.
 
+Multi-line mode means `^` and `$` no longer match just at the beginning/end of
+the input, but at the beginning/end of lines:
+
+```
+# use regex::Regex;
+let re = Regex::new(r"(?m)^line \d+").unwrap();
+let m = re.find("line one\nline 2\n").unwrap();
+assert_eq!(m.as_str(), "line 2");
+```
+
+Note that `^` matches after new lines, even at the end of input:
+
+```
+# use regex::Regex;
+let re = Regex::new(r"(?m)^").unwrap();
+let m = re.find_iter("test\n").last().unwrap();
+assert_eq!((m.start(), m.end()), (5, 5));
+```
+
 Here is an example that uses an ASCII word boundary instead of a Unicode
 word boundary:
 
 ```rust
 # extern crate regex; use regex::Regex;
 # fn main() {
 let re = Regex::new(r"(?-u:\b).+(?-u:\b)").unwrap();
 let cap = re.captures("$$abc$$").unwrap();
 assert_eq!(&cap[0], "abc");
 # }
 ```
 
 ## Escape sequences
 
 <pre class="rust">
-\*         literal *, works for any punctuation character: \.+*?()|[]{}^$
-\a         bell (\x07)
-\f         form feed (\x0C)
-\t         horizontal tab
-\n         new line
-\r         carriage return
-\v         vertical tab (\x0B)
-\123       octal character code (up to three digits)
-\x7F       hex character code (exactly two digits)
-\x{10FFFF} any hex character code corresponding to a Unicode code point
+\*          literal *, works for any punctuation character: \.+*?()|[]{}^$
+\a          bell (\x07)
+\f          form feed (\x0C)
+\t          horizontal tab
+\n          new line
+\r          carriage return
+\v          vertical tab (\x0B)
+\123        octal character code (up to three digits) (when enabled)
+\x7F        hex character code (exactly two digits)
+\x{10FFFF}  any hex character code corresponding to a Unicode code point
+\u007F      hex character code (exactly four digits)
+\u{7F}      any hex character code corresponding to a Unicode code point
+\U0000007F  hex character code (exactly eight digits)
+\U{7F}      any hex character code corresponding to a Unicode code point
 </pre>
 
 ## Perl character classes (Unicode friendly)
 
 These classes are based on the definitions provided in
 [UTS#18](http://www.unicode.org/reports/tr18/#Compatibility_Properties):
 
 <pre class="rust">
@@ -485,35 +515,44 @@ the limit is reached too frequently, it gives up and hands control off to
 another matching engine with fixed memory requirements.
 (The DFA size limit can also be tweaked. See
 [`RegexBuilder::dfa_size_limit`](struct.RegexBuilder.html#method.dfa_size_limit).)
 */
 
 #![deny(missing_docs)]
 #![cfg_attr(test, deny(warnings))]
 #![cfg_attr(feature = "pattern", feature(pattern))]
-#![cfg_attr(feature = "simd-accel", feature(cfg_target_feature))]
+
+#[cfg(not(feature = "use_std"))]
+compile_error!("`use_std` feature is currently required to build this crate");
 
 extern crate aho_corasick;
 extern crate memchr;
 extern crate thread_local;
-#[cfg(test)] extern crate quickcheck;
+#[cfg(test)]
+#[macro_use]
+extern crate quickcheck;
 extern crate regex_syntax as syntax;
-#[cfg(feature = "simd-accel")] extern crate simd;
 extern crate utf8_ranges;
 
+#[cfg(feature = "use_std")]
 pub use error::Error;
+#[cfg(feature = "use_std")]
 pub use re_builder::unicode::*;
+#[cfg(feature = "use_std")]
 pub use re_builder::set_unicode::*;
+#[cfg(feature = "use_std")]
 pub use re_set::unicode::*;
-pub use re_trait::Locations;
+#[cfg(feature = "use_std")]
+#[cfg(feature = "use_std")]
 pub use re_unicode::{
     Regex, Match, Captures,
     CaptureNames, Matches, CaptureMatches, SubCaptureMatches,
-    Replacer, NoExpand, Split, SplitN,
+    CaptureLocations, Locations,
+    Replacer, ReplacerRef, NoExpand, Split, SplitN,
     escape,
 };
 
 /**
 Match regular expressions on arbitrary bytes.
 
 This module provides a nearly identical API to the one found in the
 top-level of this crate. There are two important differences:
@@ -584,65 +623,61 @@ character classes are allowed.
 3. In ASCII compatible mode, Perl character classes (`\w`, `\d` and `\s`)
 revert to their typical ASCII definition. `\w` maps to `[[:word:]]`, `\d` maps
 to `[[:digit:]]` and `\s` maps to `[[:space:]]`.
 4. In ASCII compatible mode, word boundaries use the ASCII compatible `\w` to
 determine whether a byte is a word byte or not.
 5. Hexadecimal notation can be used to specify arbitrary bytes instead of
 Unicode codepoints. For example, in ASCII compatible mode, `\xFF` matches the
 literal byte `\xFF`, while in Unicode mode, `\xFF` is a Unicode codepoint that
-matches its UTF-8 encoding of `\xC3\xBF`. Similarly for octal notation.
+matches its UTF-8 encoding of `\xC3\xBF`. Similarly for octal notation when
+enabled.
 6. `.` matches any *byte* except for `\n` instead of any Unicode scalar value.
 When the `s` flag is enabled, `.` matches any byte.
 
 # Performance
 
 In general, one should expect performance on `&[u8]` to be roughly similar to
 performance on `&str`.
 */
+#[cfg(feature = "use_std")]
 pub mod bytes {
     pub use re_builder::bytes::*;
     pub use re_builder::set_bytes::*;
     pub use re_bytes::*;
     pub use re_set::bytes::*;
-    pub use re_trait::Locations;
 }
 
 mod backtrack;
 mod utf8;
 mod compile;
 mod dfa;
 mod error;
 mod exec;
 mod expand;
 mod freqs;
 mod input;
-mod literals;
+mod literal;
 #[cfg(feature = "pattern")]
 mod pattern;
 mod pikevm;
 mod prog;
 mod re_builder;
 mod re_bytes;
-mod re_plugin;
 mod re_set;
 mod re_trait;
 mod re_unicode;
-#[cfg(feature = "simd-accel")]
-mod simd_accel;
-#[cfg(not(feature = "simd-accel"))]
-#[path = "simd_fallback/mod.rs"]
-mod simd_accel;
 mod sparse;
+#[cfg(any(regex_runtime_teddy_ssse3, regex_runtime_teddy_avx2))]
+mod vector;
 
-/// The `internal` module exists to support the `regex!` macro and other
-/// suspicious activity, such as testing different matching engines and
-/// supporting the `regex-debug` CLI utility.
+/// The `internal` module exists to support suspicious activity, such as
+/// testing different matching engines and supporting the `regex-debug` CLI
+/// utility.
 #[doc(hidden)]
+#[cfg(feature = "use_std")]
 pub mod internal {
     pub use compile::Compiler;
     pub use exec::{Exec, ExecBuilder};
     pub use input::{Char, Input, CharInput, InputAt};
-    pub use literals::LiteralSearcher;
+    pub use literal::LiteralSearcher;
     pub use prog::{Program, Inst, EmptyLook, InstRanges};
-    pub use re_plugin::Plugin;
-    pub use re_unicode::_Regex;
 }
diff --git a/third_party/rust/regex/src/literal/mod.rs b/third_party/rust/regex/src/literal/mod.rs
new file mode 100644
index 000000000000..de1bd5339bb1
--- /dev/null
+++ b/third_party/rust/regex/src/literal/mod.rs
@@ -0,0 +1,1141 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp;
+use std::mem;
+
+use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
+use memchr::{memchr, memchr2, memchr3};
+use syntax::hir::literal::{Literal, Literals};
+
+use freqs::BYTE_FREQUENCIES;
+use self::teddy_avx2::{Teddy as TeddyAVX2};
+use self::teddy_ssse3::{Teddy as TeddySSSE3};
+
+mod teddy_avx2;
+mod teddy_ssse3;
+
+/// A prefix extracted from a compiled regular expression.
+///
+/// A regex prefix is a set of literal strings that *must* be matched at the
+/// beginning of a regex in order for the entire regex to match. Similarly
+/// for a regex suffix.
+#[derive(Clone, Debug)]
+pub struct LiteralSearcher {
+    complete: bool,
+    lcp: FreqyPacked,
+    lcs: FreqyPacked,
+    matcher: Matcher,
+}
+
+#[derive(Clone, Debug)]
+enum Matcher {
+    /// No literals. (Never advances through the input.)
+    Empty,
+    /// A set of four or more single byte literals.
+    Bytes(SingleByteSet),
+    /// A single substring, find using memchr and frequency analysis.
+    FreqyPacked(FreqyPacked),
+    /// A single substring, find using Boyer-Moore.
+    BoyerMoore(BoyerMooreSearch),
+    /// An Aho-Corasick automaton.
+    AC(FullAcAutomaton<Literal>),
+    /// A simd accelerated multiple string matcher. Used only for a small
+    /// number of small literals.
+    TeddySSSE3(TeddySSSE3),
+    /// A simd accelerated multiple string matcher. Used only for a small
+    /// number of small literals. This uses 256-bit vectors.
+    TeddyAVX2(TeddyAVX2),
+}
+
+impl LiteralSearcher {
+    /// Returns a matcher that never matches and never advances the input.
+    pub fn empty() -> Self {
+        Self::new(Literals::empty(), Matcher::Empty)
+    }
+
+    /// Returns a matcher for literal prefixes from the given set.
+    pub fn prefixes(lits: Literals) -> Self {
+        let matcher = Matcher::prefixes(&lits);
+        Self::new(lits, matcher)
+    }
+
+    /// Returns a matcher for literal suffixes from the given set.
+    pub fn suffixes(lits: Literals) -> Self {
+        let matcher = Matcher::suffixes(&lits);
+        Self::new(lits, matcher)
+    }
+
+    fn new(lits: Literals, matcher: Matcher) -> Self {
+        let complete = lits.all_complete();
+        LiteralSearcher {
+            complete: complete,
+            lcp: FreqyPacked::new(lits.longest_common_prefix().to_vec()),
+            lcs: FreqyPacked::new(lits.longest_common_suffix().to_vec()),
+            matcher: matcher,
+        }
+    }
+
+    /// Returns true if all matches comprise the entire regular expression.
+    ///
+    /// This does not necessarily mean that a literal match implies a match
+    /// of the regular expression. For example, the regular expresison `^a`
+    /// is comprised of a single complete literal `a`, but the regular
+    /// expression demands that it only match at the beginning of a string.
+    pub fn complete(&self) -> bool {
+        self.complete && !self.is_empty()
+    }
+
+    /// Find the position of a literal in `haystack` if it exists.
+    #[inline(always)] // reduces constant overhead
+    pub fn find(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => Some((0, 0)),
+            Bytes(ref sset) => sset.find(haystack).map(|i| (i, i + 1)),
+            FreqyPacked(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
+            BoyerMoore(ref s) => s.find(haystack).map(|i| (i, i + s.len())),
+            AC(ref aut) => aut.find(haystack).next().map(|m| (m.start, m.end)),
+            TeddySSSE3(ref t) => t.find(haystack).map(|m| (m.start, m.end)),
+            TeddyAVX2(ref t) => t.find(haystack).map(|m| (m.start, m.end)),
+        }
+    }
+
+    /// Like find, except matches must start at index `0`.
+    pub fn find_start(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        for lit in self.iter() {
+            if lit.len() > haystack.len() {
+                continue;
+            }
+            if lit == &haystack[0..lit.len()] {
+                return Some((0, lit.len()));
+            }
+        }
+        None
+    }
+
+    /// Like find, except matches must end at index `haystack.len()`.
+    pub fn find_end(&self, haystack: &[u8]) -> Option<(usize, usize)> {
+        for lit in self.iter() {
+            if lit.len() > haystack.len() {
+                continue;
+            }
+            if lit == &haystack[haystack.len() - lit.len()..] {
+                return Some((haystack.len() - lit.len(), haystack.len()));
+            }
+        }
+        None
+    }
+
+    /// Returns an iterator over all literals to be matched.
+    pub fn iter(&self) -> LiteralIter {
+        match self.matcher {
+            Matcher::Empty => LiteralIter::Empty,
+            Matcher::Bytes(ref sset) => LiteralIter::Bytes(&sset.dense),
+            Matcher::FreqyPacked(ref s) => LiteralIter::Single(&s.pat),
+            Matcher::BoyerMoore(ref s) => LiteralIter::Single(&s.pattern),
+            Matcher::AC(ref ac) => LiteralIter::AC(ac.patterns()),
+            Matcher::TeddySSSE3(ref ted) => {
+                LiteralIter::TeddySSSE3(ted.patterns())
+            }
+            Matcher::TeddyAVX2(ref ted) => {
+                LiteralIter::TeddyAVX2(ted.patterns())
+            }
+        }
+    }
+
+    /// Returns a matcher for the longest common prefix of this matcher.
+    pub fn lcp(&self) -> &FreqyPacked {
+        &self.lcp
+    }
+
+    /// Returns a matcher for the longest common suffix of this matcher.
+    pub fn lcs(&self) -> &FreqyPacked {
+        &self.lcs
+    }
+
+    /// Returns true iff this prefix is empty.
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Returns the number of prefixes in this machine.
+    pub fn len(&self) -> usize {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => 0,
+            Bytes(ref sset) => sset.dense.len(),
+            FreqyPacked(_) => 1,
+            BoyerMoore(_) => 1,
+            AC(ref aut) => aut.len(),
+            TeddySSSE3(ref ted) => ted.len(),
+            TeddyAVX2(ref ted) => ted.len(),
+        }
+    }
+
+    /// Return the approximate heap usage of literals in bytes.
+    pub fn approximate_size(&self) -> usize {
+        use self::Matcher::*;
+        match self.matcher {
+            Empty => 0,
+            Bytes(ref sset) => sset.approximate_size(),
+            FreqyPacked(ref single) => single.approximate_size(),
+            BoyerMoore(ref single) => single.approximate_size(),
+            AC(ref aut) => aut.heap_bytes(),
+            TeddySSSE3(ref ted) => ted.approximate_size(),
+            TeddyAVX2(ref ted) => ted.approximate_size(),
+        }
+    }
+}
+
+impl Matcher {
+    fn prefixes(lits: &Literals) -> Self {
+        let sset = SingleByteSet::prefixes(lits);
+        Matcher::new(lits, sset)
+    }
+
+    fn suffixes(lits: &Literals) -> Self {
+        let sset = SingleByteSet::suffixes(lits);
+        Matcher::new(lits, sset)
+    }
+
+    fn new(lits: &Literals, sset: SingleByteSet) -> Self {
+        if lits.literals().is_empty() {
+            return Matcher::Empty;
+        }
+        if sset.dense.len() >= 26 {
+            // Avoid trying to match a large number of single bytes.
+            // This is *very* sensitive to a frequency analysis comparison
+            // between the bytes in sset and the composition of the haystack.
+            // No matter the size of sset, if its members all are rare in the
+            // haystack, then it'd be worth using it. How to tune this... IDK.
+            // ---AG
+            return Matcher::Empty;
+        }
+        if sset.complete {
+            return Matcher::Bytes(sset);
+        }
+        if lits.literals().len() == 1 {
+            let lit = lits.literals()[0].to_vec();
+            if BoyerMooreSearch::should_use(lit.as_slice()) {
+                return Matcher::BoyerMoore(BoyerMooreSearch::new(lit));
+            } else {
+                return Matcher::FreqyPacked(FreqyPacked::new(lit));
+            }
+        }
+        let is_aho_corasick_fast = sset.dense.len() == 1 && sset.all_ascii;
+        if TeddyAVX2::available() && !is_aho_corasick_fast {
+            const MAX_TEDDY_LITERALS: usize = 32;
+            if lits.literals().len() <= MAX_TEDDY_LITERALS {
+                if let Some(ted) = TeddyAVX2::new(lits) {
+                    return Matcher::TeddyAVX2(ted);
+                }
+            }
+        }
+        if TeddySSSE3::available() && !is_aho_corasick_fast {
+            // Only try Teddy if Aho-Corasick can't use memchr on an ASCII
+            // byte. Also, in its current form, Teddy doesn't scale well to
+            // lots of literals.
+            //
+            // We impose the ASCII restriction since an alternation of
+            // non-ASCII string literals in the same language is likely to all
+            // start with the same byte. Even worse, the corpus being searched
+            // probably has a similar composition, which ends up completely
+            // negating the benefit of memchr.
+            const MAX_TEDDY_LITERALS: usize = 32;
+            if lits.literals().len() <= MAX_TEDDY_LITERALS {
+                if let Some(ted) = TeddySSSE3::new(lits) {
+                    return Matcher::TeddySSSE3(ted);
+                }
+            }
+            // Fallthrough to ol' reliable Aho-Corasick...
+        }
+        let pats = lits.literals().to_owned();
+        Matcher::AC(AcAutomaton::new(pats).into_full())
+    }
+}
+
+pub enum LiteralIter<'a> {
+    Empty,
+    Bytes(&'a [u8]),
+    Single(&'a [u8]),
+    AC(&'a [Literal]),
+    TeddySSSE3(&'a [Vec<u8>]),
+    TeddyAVX2(&'a [Vec<u8>]),
+}
+
+impl<'a> Iterator for LiteralIter<'a> {
+    type Item = &'a [u8];
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            LiteralIter::Empty => None,
+            LiteralIter::Bytes(ref mut many) => {
+                if many.is_empty() {
+                    None
+                } else {
+                    let next = &many[0..1];
+                    *many = &many[1..];
+                    Some(next)
+                }
+            }
+            LiteralIter::Single(ref mut one) => {
+                if one.is_empty() {
+                    None
+                } else {
+                    let next = &one[..];
+                    *one = &[];
+                    Some(next)
+                }
+            }
+            LiteralIter::AC(ref mut lits) => {
+                if lits.is_empty() {
+                    None
+                } else {
+                    let next = &lits[0];
+                    *lits = &lits[1..];
+                    Some(&**next)
+                }
+            }
+            LiteralIter::TeddySSSE3(ref mut lits) => {
+                if lits.is_empty() {
+                    None
+                } else {
+                    let next = &lits[0];
+                    *lits = &lits[1..];
+                    Some(&**next)
+                }
+            }
+            LiteralIter::TeddyAVX2(ref mut lits) => {
+                if lits.is_empty() {
+                    None
+                } else {
+                    let next = &lits[0];
+                    *lits = &lits[1..];
+                    Some(&**next)
+                }
+            }
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+struct SingleByteSet {
+    sparse: Vec<bool>,
+    dense: Vec<u8>,
+    complete: bool,
+    all_ascii: bool,
+}
+
+impl SingleByteSet {
+    fn new() -> SingleByteSet {
+        SingleByteSet {
+            sparse: vec![false; 256],
+            dense: vec![],
+            complete: true,
+            all_ascii: true,
+        }
+    }
+
+    fn prefixes(lits: &Literals) -> SingleByteSet {
+        let mut sset = SingleByteSet::new();
+        for lit in lits.literals() {
+            sset.complete = sset.complete && lit.len() == 1;
+            if let Some(&b) = lit.get(0) {
+                if !sset.sparse[b as usize] {
+                    if b > 0x7F {
+                        sset.all_ascii = false;
+                    }
+                    sset.dense.push(b);
+                    sset.sparse[b as usize] = true;
+                }
+            }
+        }
+        sset
+    }
+
+    fn suffixes(lits: &Literals) -> SingleByteSet {
+        let mut sset = SingleByteSet::new();
+        for lit in lits.literals() {
+            sset.complete = sset.complete && lit.len() == 1;
+            if let Some(&b) = lit.get(lit.len().checked_sub(1).unwrap()) {
+                if !sset.sparse[b as usize] {
+                    if b > 0x7F {
+                        sset.all_ascii = false;
+                    }
+                    sset.dense.push(b);
+                    sset.sparse[b as usize] = true;
+                }
+            }
+        }
+        sset
+    }
+
+    /// Faster find that special cases certain sizes to use memchr.
+    #[inline(always)] // reduces constant overhead
+    fn find(&self, text: &[u8]) -> Option<usize> {
+        match self.dense.len() {
+            0 => None,
+            1 => memchr(self.dense[0], text),
+            2 => memchr2(self.dense[0], self.dense[1], text),
+            3 => memchr3(self.dense[0], self.dense[1], self.dense[2], text),
+            _ => self._find(text),
+        }
+    }
+
+    /// Generic find that works on any sized set.
+    fn _find(&self, haystack: &[u8]) -> Option<usize> {
+        for (i, &b) in haystack.iter().enumerate() {
+            if self.sparse[b as usize] {
+                return Some(i);
+            }
+        }
+        None
+    }
+
+    fn approximate_size(&self) -> usize {
+        (self.dense.len() * mem::size_of::<u8>())
+        + (self.sparse.len() * mem::size_of::<bool>())
+    }
+}
+
+/// Provides an implementation of fast subtring search using frequency
+/// analysis.
+///
+/// memchr is so fast that we do everything we can to keep the loop in memchr
+/// for as long as possible. The easiest way to do this is to intelligently
+/// pick the byte to send to memchr. The best byte is the byte that occurs
+/// least frequently in the haystack. Since doing frequency analysis on the
+/// haystack is far too expensive, we compute a set of fixed frequencies up
+/// front and hard code them in src/freqs.rs. Frequency analysis is done via
+/// scripts/frequencies.py.
+#[derive(Clone, Debug)]
+pub struct FreqyPacked {
+    /// The pattern.
+    pat: Vec<u8>,
+    /// The number of Unicode characters in the pattern. This is useful for
+    /// determining the effective length of a pattern when deciding which
+    /// optimizations to perform. A trailing incomplete UTF-8 sequence counts
+    /// as one character.
+    char_len: usize,
+    /// The rarest byte in the pattern, according to pre-computed frequency
+    /// analysis.
+    rare1: u8,
+    /// The offset of the rarest byte in `pat`.
+    rare1i: usize,
+    /// The second rarest byte in the pattern, according to pre-computed
+    /// frequency analysis. (This may be equivalent to the rarest byte.)
+    ///
+    /// The second rarest byte is used as a type of guard for quickly detecting
+    /// a mismatch after memchr locates an instance of the rarest byte. This
+    /// is a hedge against pathological cases where the pre-computed frequency
+    /// analysis may be off. (But of course, does not prevent *all*
+    /// pathological cases.)
+    rare2: u8,
+    /// The offset of the second rarest byte in `pat`.
+    rare2i: usize,
+}
+
+impl FreqyPacked {
+    fn new(pat: Vec<u8>) -> FreqyPacked {
+        if pat.is_empty() {
+            return FreqyPacked::empty();
+        }
+
+        // Find the rarest two bytes. Try to make them distinct (but it's not
+        // required).
+        let mut rare1 = pat[0];
+        let mut rare2 = pat[0];
+        for b in pat[1..].iter().cloned() {
+            if freq_rank(b) < freq_rank(rare1) {
+                rare1 = b;
+            }
+        }
+        for &b in &pat {
+            if rare1 == rare2 {
+                rare2 = b
+            } else if b != rare1 && freq_rank(b) < freq_rank(rare2) {
+                rare2 = b;
+            }
+        }
+
+        // And find the offsets of their last occurrences.
+        let rare1i = pat.iter().rposition(|&b| b == rare1).unwrap();
+        let rare2i = pat.iter().rposition(|&b| b == rare2).unwrap();
+
+        let char_len = char_len_lossy(&pat);
+        FreqyPacked {
+            pat: pat,
+            char_len: char_len,
+            rare1: rare1,
+            rare1i: rare1i,
+            rare2: rare2,
+            rare2i: rare2i,
+        }
+    }
+
+    fn empty() -> FreqyPacked {
+        FreqyPacked {
+            pat: vec![],
+            char_len: 0,
+            rare1: 0,
+            rare1i: 0,
+            rare2: 0,
+            rare2i: 0,
+        }
+    }
+
+    #[inline(always)] // reduces constant overhead
+    pub fn find(&self, haystack: &[u8]) -> Option<usize> {
+        let pat = &*self.pat;
+        if haystack.len() < pat.len() || pat.is_empty() {
+            return None;
+        }
+        let mut i = self.rare1i;
+        while i < haystack.len() {
+            i += match memchr(self.rare1, &haystack[i..]) {
+                None => return None,
+                Some(i) => i,
+            };
+            let start = i - self.rare1i;
+            let end = start + pat.len();
+            if end > haystack.len() {
+                return None;
+            }
+            let aligned = &haystack[start..end];
+            if aligned[self.rare2i] == self.rare2 && aligned == &*self.pat {
+                return Some(start);
+            }
+            i += 1;
+        }
+        None
+    }
+
+    #[inline(always)] // reduces constant overhead
+    pub fn is_suffix(&self, text: &[u8]) -> bool {
+        if text.len() < self.len() {
+            return false;
+        }
+        text[text.len() - self.len()..] == *self.pat
+    }
+
+    pub fn len(&self) -> usize {
+        self.pat.len()
+    }
+
+    pub fn char_len(&self) -> usize {
+        self.char_len
+    }
+
+    fn approximate_size(&self) -> usize {
+        self.pat.len() * mem::size_of::<u8>()
+    }
+}
+
+fn char_len_lossy(bytes: &[u8]) -> usize {
+    String::from_utf8_lossy(bytes).chars().count()
+}
+
+/// An implementation of Tuned Boyer-Moore as laid out by
+/// Andrew Hume and Daniel Sunday in "Fast String Searching".
+/// O(n) in the size of the input.
+///
+/// Fast string searching algorithms come in many variations,
+/// but they can generally be described in terms of three main
+/// components.
+///
+/// The skip loop is where the string searcher wants to spend
+/// as much time as possible. Exactly which character in the
+/// pattern the skip loop examines varies from algorithm to
+/// algorithm, but in the simplest case this loop repeated
+/// looks at the last character in the pattern and jumps
+/// forward in the input if it is not in the pattern.
+/// Robert Boyer and J Moore called this the "fast" loop in
+/// their original paper.
+///
+/// The match loop is responsible for actually examining the
+/// whole potentially matching substring. In order to fail
+/// faster, the match loop sometimes has a guard test attached.
+/// The guard test uses frequency analysis of the different
+/// characters in the pattern to choose the least frequency
+/// occurring character and use it to find match failures
+/// as quickly as possible.
+///
+/// The shift rule governs how the algorithm will shuffle its
+/// test window in the event of a failure during the match loop.
+/// Certain shift rules allow the worst-case run time of the
+/// algorithm to be shown to be O(n) in the size of the input
+/// rather than O(nm) in the size of the input and the size
+/// of the pattern (as naive Boyer-Moore is).
+///
+/// "Fast String Searching", in addition to presenting a tuned
+/// algorithm, provides a comprehensive taxonomy of the many
+/// different flavors of string searchers. Under that taxonomy
+/// TBM, the algorithm implemented here, uses an unrolled fast
+/// skip loop with memchr fallback, a forward match loop with guard,
+/// and the mini Sunday's delta shift rule. To unpack that you'll have to
+/// read the paper.
+#[derive(Clone, Debug)]
+pub struct BoyerMooreSearch {
+    /// The pattern we are going to look for in the haystack.
+    pattern: Vec<u8>,
+
+    /// The skip table for the skip loop.
+    ///
+    /// Maps the character at the end of the input
+    /// to a shift.
+    skip_table: Vec<usize>,
+
+    /// The guard character (least frequently occurring char).
+    guard: u8,
+    /// The reverse-index of the guard character in the pattern.
+    guard_reverse_idx: usize,
+
+    /// Daniel Sunday's mini generalized delta2 shift table.
+    ///
+    /// We use a skip loop, so we only have to provide a shift
+    /// for the skip char (last char). This is why it is a mini
+    /// shift rule.
+    md2_shift: usize,
+}
+
+impl BoyerMooreSearch {
+    /// Create a new string searcher, performing whatever
+    /// compilation steps are required.
+    fn new(pattern: Vec<u8>) -> Self {
+        debug_assert!(pattern.len() > 0);
+
+        let (g, gi) = Self::select_guard(pattern.as_slice());
+        let skip_table = Self::compile_skip_table(pattern.as_slice());
+        let md2_shift = Self::compile_md2_shift(pattern.as_slice());
+        BoyerMooreSearch {
+            pattern: pattern,
+            skip_table: skip_table,
+            guard: g,
+            guard_reverse_idx: gi,
+            md2_shift: md2_shift,
+        }
+    }
+
+    /// Find the pattern in `haystack`, returning the offset
+    /// of the start of the first occurrence of the pattern
+    /// in `haystack`.
+    #[inline]
+    fn find(&self, haystack: &[u8]) -> Option<usize> {
+        if haystack.len() < self.pattern.len() {
+            return None;
+        }
+
+        let mut window_end = self.pattern.len() - 1;
+
+        // Inspired by the grep source. It is a way
+        // to do correct loop unrolling without having to place
+        // a crashpad of terminating charicters at the end in
+        // the way described in the Fast String Searching paper.
+        const NUM_UNROLL: usize = 10;
+        // 1 for the initial position, and 1 for the md2 shift
+        let short_circut = (NUM_UNROLL + 2) * self.pattern.len();
+
+        if haystack.len() > short_circut {
+            // just 1 for the md2 shift
+            let backstop = haystack.len() - ((NUM_UNROLL + 1) * self.pattern.len());
+            loop {
+                window_end = match self.skip_loop(haystack, window_end, backstop) {
+                    Some(i) => i,
+                    None => return None,
+                };
+                if window_end >= backstop {
+                    break;
+                }
+
+                if self.check_match(haystack, window_end) {
+                    return Some(window_end - (self.pattern.len() - 1));
+                } else {
+                    let skip = self.skip_table[haystack[window_end] as usize];
+                    window_end +=
+                        if skip == 0 { self.md2_shift } else { skip };
+                    continue;
+                }
+            }
+        }
+
+        // now process the input after the backstop
+        while window_end < haystack.len() {
+            let mut skip = self.skip_table[haystack[window_end] as usize];
+            if skip == 0 {
+                if self.check_match(haystack, window_end) {
+                    return Some(window_end - (self.pattern.len() - 1));
+                } else {
+                    skip = self.md2_shift;
+                }
+            }
+            window_end += skip;
+        }
+
+        None
+    }
+
+    fn len(&self) -> usize {
+        return self.pattern.len()
+    }
+
+    /// The key heuristic behind which the BoyerMooreSearch lives.
+    ///
+    /// See `rust-lang/regex/issues/408`.
+    ///
+    /// Tuned Boyer-Moore is actually pretty slow! It turns out a handrolled
+    /// platform-specific memchr routine with a bit of frequency
+    /// analysis sprinkled on top actually wins most of the time.
+    /// However, there are a few cases where Tuned Boyer-Moore still
+    /// wins.
+    ///
+    /// If the haystack is random, frequency analysis doesn't help us,
+    /// so Boyer-Moore will win for sufficiently large needles.
+    /// Unfortunately, there is no obvious way to determine this
+    /// ahead of time.
+    ///
+    /// If the pattern itself consists of very common characters,
+    /// frequency analysis won't get us anywhere. The most extreme
+    /// example of this is a pattern like `eeeeeeeeeeeeeeee`. Fortunately,
+    /// this case is wholly determined by the pattern, so we can actually
+    /// implement the heuristic.
+    ///
+    /// A third case is if the pattern is sufficiently long. The idea
+    /// here is that once the pattern gets long enough the Tuned
+    /// Boyer-Moore skip loop will start making strides long enough
+    /// to beat the asm deep magic that is memchr.
+    fn should_use(pattern: &[u8]) -> bool {
+        // The minimum pattern length required to use TBM.
+        const MIN_LEN: usize = 9;
+        // The minimum frequency rank (lower is rarer) that every byte in the
+        // pattern must have in order to use TBM. That is, if the pattern
+        // contains _any_ byte with a lower rank, then TBM won't be used.
+        const MIN_CUTOFF: usize = 150;
+        // The maximum frequency rank for any byte.
+        const MAX_CUTOFF: usize = 255;
+        // The scaling factor used to determine the actual cutoff frequency
+        // to use (keeping in mind that the minimum frequency rank is bounded
+        // by MIN_CUTOFF). This scaling factor is an attempt to make TBM more
+        // likely to be used as the pattern grows longer. That is, longer
+        // patterns permit somewhat less frequent bytes than shorter patterns,
+        // under the assumption that TBM gets better as the pattern gets
+        // longer.
+        const LEN_CUTOFF_PROPORTION: usize = 4;
+
+        let scaled_rank = pattern.len().wrapping_mul(LEN_CUTOFF_PROPORTION);
+        let cutoff = cmp::max(
+            MIN_CUTOFF,
+            MAX_CUTOFF - cmp::min(MAX_CUTOFF, scaled_rank),
+        );
+        // The pattern must be long enough to be worthwhile. e.g., memchr will
+        // be faster on `e` because it is short even though e is quite common.
+        pattern.len() > MIN_LEN
+            // all the bytes must be more common than the cutoff.
+            && pattern.iter().all(|c| freq_rank(*c) >= cutoff)
+    }
+
+    /// Check to see if there is a match at the given position
+    #[inline]
+    fn check_match(&self, haystack: &[u8], window_end: usize) -> bool {
+        // guard test
+        if haystack[window_end - self.guard_reverse_idx] != self.guard {
+            return false;
+        }
+
+        // match loop
+        let window_start = window_end - (self.pattern.len() - 1);
+        for i in 0..self.pattern.len() {
+            if self.pattern[i] != haystack[window_start + i] {
+                return false;
+            }
+        }
+
+        true
+    }
+
+    /// Skip forward according to the shift table.
+    ///
+    /// Returns the offset of the next occurrence
+    /// of the last char in the pattern, or the none
+    /// if it never reappears. If `skip_loop` hits the backstop
+    /// it will leave early.
+    #[inline]
+    fn skip_loop(&self,
+        haystack: &[u8],
+        mut window_end: usize,
+        backstop: usize,
+    ) -> Option<usize> {
+        use std::mem;
+
+        let window_end_snapshot = window_end;
+        let skip_of = |we: usize| -> usize {
+            // Unsafe might make this faster, but the benchmarks
+            // were hard to interpret.
+            self.skip_table[haystack[we] as usize]
+        };
+
+        loop {
+            let mut skip = skip_of(window_end); window_end += skip;
+            skip = skip_of(window_end); window_end += skip;
+            if skip != 0 {
+                skip = skip_of(window_end); window_end += skip;
+                skip = skip_of(window_end); window_end += skip;
+                skip = skip_of(window_end); window_end += skip;
+                if skip != 0 {
+                    skip = skip_of(window_end); window_end += skip;
+                    skip = skip_of(window_end); window_end += skip;
+                    skip = skip_of(window_end); window_end += skip;
+                    if skip != 0 {
+                        skip = skip_of(window_end); window_end += skip;
+                        skip = skip_of(window_end); window_end += skip;
+
+                        // If ten iterations did not make at least 16 words
+                        // worth of progress, we just fall back on memchr.
+                        if window_end - window_end_snapshot >
+                             16 * mem::size_of::<usize>() {
+
+                            // Returning a window_end >= backstop will immediatly
+                            // break us out of the inner loop in `find`.
+                            if window_end >= backstop {
+                                return Some(window_end);
+                            }
+
+                            continue; // we made enough progress
+                        } else {
+                            // In case we are already there, and so that
+                            // we will catch the guard char.
+                            window_end = window_end
+                                .checked_sub(1 + self.guard_reverse_idx)
+                                .unwrap_or(0);
+
+                            match memchr(self.guard, &haystack[window_end..]) {
+                                None => return None,
+                                Some(g_idx) => {
+                                    return Some(window_end + g_idx + self.guard_reverse_idx);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            return Some(window_end);
+        }
+    }
+
+    /// Compute the ufast skip table.
+    fn compile_skip_table(pattern: &[u8]) -> Vec<usize> {
+        let mut tab = vec![pattern.len(); 256];
+
+        // For every char in the pattern, we write a skip
+        // that will line us up with the rightmost occurrence.
+        //
+        // N.B. the sentinel (0) is written by the last
+        // loop iteration.
+        for (i, c) in pattern.iter().enumerate() {
+            tab[*c as usize] = (pattern.len() - 1) - i;
+        }
+
+        tab
+    }
+
+    /// Select the guard character based off of the precomputed
+    /// frequency table.
+    fn select_guard(pattern: &[u8]) -> (u8, usize) {
+        let mut rarest = pattern[0];
+        let mut rarest_rev_idx = pattern.len() - 1;
+        for (i, c) in pattern.iter().enumerate() {
+            if freq_rank(*c) < freq_rank(rarest) {
+                rarest = *c;
+                rarest_rev_idx = (pattern.len() - 1) - i;
+            }
+        }
+
+        (rarest, rarest_rev_idx)
+    }
+
+    /// If there is another occurrence of the skip
+    /// char, shift to it, otherwise just shift to
+    /// the next window.
+    fn compile_md2_shift(pattern: &[u8]) -> usize {
+        let shiftc = *pattern.last().unwrap();
+
+        // For a pattern of length 1 we will never apply the
+        // shift rule, so we use a poison value on the principle
+        // that failing fast is a good thing.
+        if pattern.len() == 1 {
+            return 0xDEADBEAF;
+        }
+
+        let mut i = pattern.len() - 2;
+        while i > 0 {
+            if pattern[i] == shiftc {
+                return (pattern.len() - 1) - i;
+            }
+            i -= 1;
+        }
+
+        // The skip char never re-occurs in the pattern, so
+        // we can just shift the whole window length.
+        pattern.len() - 1
+    }
+
+    fn approximate_size(&self) -> usize {
+        (self.pattern.len() * mem::size_of::<u8>())
+            + (256 * mem::size_of::<usize>()) // skip table
+    }
+}
+
+fn freq_rank(b: u8) -> usize {
+    BYTE_FREQUENCIES[b as usize] as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{BoyerMooreSearch, FreqyPacked};
+
+    //
+    // Unit Tests
+    //
+
+    // The "hello, world" of string searching
+    #[test]
+    fn bm_find_subs() {
+        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
+        let haystack = b"I keep seeing patterns in this text";
+        assert_eq!(14, searcher.find(haystack).unwrap());
+    }
+
+    #[test]
+    fn bm_find_no_subs() {
+        let searcher = BoyerMooreSearch::new(Vec::from(&b"pattern"[..]));
+        let haystack = b"I keep seeing needles in this text";
+        assert_eq!(None, searcher.find(haystack));
+    }
+
+    //
+    // Regression Tests
+    //
+
+    #[test]
+    fn bm_skip_reset_bug() {
+        let haystack = vec![0, 0, 0, 0, 0, 1, 1, 0];
+        let needle = vec![0, 1, 1, 0];
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let offset = searcher.find(haystack.as_slice()).unwrap();
+        assert_eq!(4, offset);
+    }
+
+    #[test]
+    fn bm_backstop_underflow_bug() {
+        let haystack = vec![0, 0];
+        let needle = vec![0, 0];
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let offset = searcher.find(haystack.as_slice()).unwrap();
+        assert_eq!(0, offset);
+    }
+
+    #[test]
+    fn bm_naive_off_by_one_bug() {
+        let haystack = vec![91];
+        let needle = vec![91];
+
+        let naive_offset = naive_find(&needle, &haystack).unwrap();
+        assert_eq!(0, naive_offset);
+    }
+
+    #[test]
+    fn bm_memchr_fallback_indexing_bug() {
+        let mut haystack = vec![
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+        let needle = vec![1, 1, 1, 1, 32, 32, 87];
+        let needle_start = haystack.len();
+        haystack.extend(needle.clone());
+
+        let searcher = BoyerMooreSearch::new(needle);
+        assert_eq!(needle_start, searcher.find(haystack.as_slice()).unwrap());
+    }
+
+    #[test]
+    fn bm_backstop_boundary() {
+        let haystack = b"\
+// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+e_data.clone_created(entity_id, entity_to_add.entity_id);
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+".to_vec();
+        let needle = b"clone_created".to_vec();
+
+        let searcher = BoyerMooreSearch::new(needle);
+        let result = searcher.find(&haystack);
+        assert_eq!(Some(43), result);
+    }
+
+    #[test]
+    fn bm_win_gnu_indexing_bug() {
+        let haystack_raw = vec![
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+        let needle = vec![1, 1, 1, 1, 1, 1, 1];
+        let haystack = haystack_raw.as_slice();
+
+        BoyerMooreSearch::new(needle.clone()).find(haystack);
+    }
+
+    //
+    // QuickCheck Properties
+    //
+
+    use quickcheck::TestResult;
+
+    fn naive_find(needle: &[u8], haystack: &[u8]) -> Option<usize> {
+        assert!(needle.len() <= haystack.len());
+
+        for i in 0..(haystack.len() - (needle.len() - 1)) {
+            if haystack[i] == needle[0]
+                && &haystack[i..(i+needle.len())] == needle {
+                return Some(i)
+            }
+        }
+
+        None
+    }
+
+    quickcheck! {
+        fn qc_bm_equals_nieve_find(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
+            if pile1.len() == 0 || pile2.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let (needle, haystack) = if pile1.len() < pile2.len() {
+                (pile1, pile2.as_slice())
+            } else {
+                (pile2, pile1.as_slice())
+            };
+
+            let searcher = BoyerMooreSearch::new(needle.clone());
+            TestResult::from_bool(
+                searcher.find(haystack) == naive_find(&needle, haystack))
+        }
+
+        fn qc_bm_equals_single(pile1: Vec<u8>, pile2: Vec<u8>) -> TestResult {
+            if pile1.len() == 0 || pile2.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let (needle, haystack) = if pile1.len() < pile2.len() {
+                (pile1, pile2.as_slice())
+            } else {
+                (pile2, pile1.as_slice())
+            };
+
+            let bm_searcher = BoyerMooreSearch::new(needle.clone());
+            let freqy_memchr = FreqyPacked::new(needle);
+            TestResult::from_bool(
+                bm_searcher.find(haystack) == freqy_memchr.find(haystack))
+        }
+
+        fn qc_bm_finds_trailing_needle(
+            haystack_pre: Vec<u8>,
+            needle: Vec<u8>
+        ) -> TestResult {
+            if needle.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let mut haystack = haystack_pre.clone();
+            let searcher = BoyerMooreSearch::new(needle.clone());
+
+            if haystack.len() >= needle.len() &&
+                searcher.find(haystack.as_slice()).is_some() {
+                return TestResult::discard();
+            }
+
+            haystack.extend(needle.clone());
+
+            // What if the the tail of the haystack can start the
+            // needle?
+            let start = haystack_pre.len()
+                .checked_sub(needle.len())
+                .unwrap_or(0);
+            for i in 0..(needle.len() - 1) {
+                if searcher.find(&haystack[(i + start)..]).is_some() {
+                    return TestResult::discard();
+                }
+            }
+
+            TestResult::from_bool(
+                searcher.find(haystack.as_slice())
+                        .map(|x| x == haystack_pre.len())
+                        .unwrap_or(false))
+        }
+
+        // qc_equals_* is only testing the negative case as @burntsushi
+        // pointed out in https://github.com/rust-lang/regex/issues/446.
+        // This quickcheck prop represents an effort to force testing of
+        // the positive case. qc_bm_finds_first and qc_bm_finds_trailing_needle
+        // already check some of the positive cases, but they don't cover
+        // cases where the needle is in the middle of haystack. This prop
+        // fills that hole.
+        fn qc_bm_finds_subslice(
+            haystack: Vec<u8>,
+            needle_start: usize,
+            needle_length: usize
+        ) -> TestResult {
+            if haystack.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let needle_start = needle_start % haystack.len();
+            let needle_length = needle_length % (haystack.len() - needle_start);
+
+            if needle_length == 0 {
+                return TestResult::discard();
+            }
+
+            let needle = &haystack[needle_start..(needle_start + needle_length)];
+
+            let bm_searcher = BoyerMooreSearch::new(needle.to_vec());
+
+            let start = naive_find(&needle, &haystack);
+            match start {
+                None => TestResult::from_bool(false),
+                Some(nf_start) =>
+                    TestResult::from_bool(
+                        nf_start <= needle_start
+                            && bm_searcher.find(&haystack) == start
+                    )
+            }
+        }
+
+        fn qc_bm_finds_first(needle: Vec<u8>) -> TestResult {
+            if needle.len() == 0 {
+                return TestResult::discard();
+            }
+
+            let mut haystack = needle.clone();
+            let searcher = BoyerMooreSearch::new(needle.clone());
+            haystack.extend(needle);
+
+            TestResult::from_bool(
+                searcher.find(haystack.as_slice())
+                        .map(|x| x == 0)
+                        .unwrap_or(false))
+        }
+    }
+}
diff --git a/third_party/rust/regex/src/literal/teddy_avx2/fallback.rs b/third_party/rust/regex/src/literal/teddy_avx2/fallback.rs
new file mode 100644
index 000000000000..20524aabfe4a
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_avx2/fallback.rs
@@ -0,0 +1,20 @@
+use syntax::hir::literal::Literals;
+
+#[derive(Debug, Clone)]
+pub struct Teddy(());
+
+#[derive(Debug, Clone)]
+pub struct Match {
+    pub pat: usize,
+    pub start: usize,
+    pub end: usize,
+}
+
+impl Teddy {
+    pub fn available() -> bool { false }
+    pub fn new(_pats: &Literals) -> Option<Teddy> { None }
+    pub fn patterns(&self) -> &[Vec<u8>] { &[] }
+    pub fn len(&self) -> usize { 0 }
+    pub fn approximate_size(&self) -> usize { 0 }
+    pub fn find(&self, _haystack: &[u8]) -> Option<Match> { None }
+}
diff --git a/third_party/rust/regex/src/literal/teddy_avx2/imp.rs b/third_party/rust/regex/src/literal/teddy_avx2/imp.rs
new file mode 100644
index 000000000000..62015d07d234
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_avx2/imp.rs
@@ -0,0 +1,468 @@
+/*!
+This is the Teddy searcher, but ported to AVX2.
+
+See the module comments in the SSSE3 Teddy searcher for a more in depth
+explanation of how this algorithm works. For the most part, this port is
+basically the same as the SSSE3 version, but using 256-bit vectors instead of
+128-bit vectors, which increases throughput.
+*/
+
+use std::cmp;
+
+use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
+use syntax::hir::literal::Literals;
+
+use vector::avx2::{AVX2VectorBuilder, u8x32};
+
+/// Corresponds to the number of bytes read at a time in the haystack.
+const BLOCK_SIZE: usize = 32;
+
+/// Match reports match information.
+#[derive(Debug, Clone)]
+pub struct Match {
+    /// The index of the pattern that matched. The index is in correspondence
+    /// with the order of the patterns given at construction.
+    pub pat: usize,
+    /// The start byte offset of the match.
+    pub start: usize,
+    /// The end byte offset of the match. This is always `start + pat.len()`.
+    pub end: usize,
+}
+
+/// A SIMD accelerated multi substring searcher.
+#[derive(Debug, Clone)]
+pub struct Teddy {
+    /// A builder for AVX2 empowered vectors.
+    vb: AVX2VectorBuilder,
+    /// A list of substrings to match.
+    pats: Vec<Vec<u8>>,
+    /// An Aho-Corasick automaton of the patterns. We use this when we need to
+    /// search pieces smaller than the Teddy block size.
+    ac: FullAcAutomaton<Vec<u8>>,
+    /// A set of 8 buckets. Each bucket corresponds to a single member of a
+    /// bitset. A bucket contains zero or more substrings. This is useful
+    /// when the number of substrings exceeds 8, since our bitsets cannot have
+    /// more than 8 members.
+    buckets: Vec<Vec<usize>>,
+    /// Our set of masks. There's one mask for each byte in the fingerprint.
+    masks: Masks,
+}
+
+impl Teddy {
+    /// Returns true if and only if Teddy is supported on this platform.
+    ///
+    /// If this returns `false`, then `Teddy::new(...)` is guaranteed to
+    /// return `None`.
+    pub fn available() -> bool {
+        AVX2VectorBuilder::new().is_some()
+    }
+
+    /// Create a new `Teddy` multi substring matcher.
+    ///
+    /// If a `Teddy` matcher could not be created (e.g., `pats` is empty or has
+    /// an empty substring), then `None` is returned.
+    pub fn new(pats: &Literals) -> Option<Teddy> {
+        let vb = match AVX2VectorBuilder::new() {
+            None => return None,
+            Some(vb) => vb,
+        };
+        if !Teddy::available() {
+            return None;
+        }
+
+        let pats: Vec<_> = pats.literals().iter().map(|p|p.to_vec()).collect();
+        let min_len = pats.iter().map(|p| p.len()).min().unwrap_or(0);
+        // Don't allow any empty patterns and require that we have at
+        // least one pattern.
+        if min_len < 1 {
+            return None;
+        }
+        // Pick the largest mask possible, but no larger than 3.
+        let nmasks = cmp::min(3, min_len);
+        let mut masks = Masks::new(vb, nmasks);
+        let mut buckets = vec![vec![]; 8];
+        // Assign a substring to each bucket, and add the bucket's bitfield to
+        // the appropriate position in the mask.
+        for (pati, pat) in pats.iter().enumerate() {
+            let bucket = pati % 8;
+            buckets[bucket].push(pati);
+            masks.add(bucket as u8, pat);
+        }
+        Some(Teddy {
+            vb: vb,
+            pats: pats.to_vec(),
+            ac: AcAutomaton::new(pats.to_vec()).into_full(),
+            buckets: buckets,
+            masks: masks,
+        })
+    }
+
+    /// Returns all of the substrings matched by this `Teddy`.
+    pub fn patterns(&self) -> &[Vec<u8>] {
+        &self.pats
+    }
+
+    /// Returns the number of substrings in this matcher.
+    pub fn len(&self) -> usize {
+        self.pats.len()
+    }
+
+    /// Returns the approximate size on the heap used by this matcher.
+    pub fn approximate_size(&self) -> usize {
+        self.pats.iter().fold(0, |a, b| a + b.len())
+    }
+
+    /// Searches `haystack` for the substrings in this `Teddy`. If a match was
+    /// found, then it is returned. Otherwise, `None` is returned.
+    pub fn find(&self, haystack: &[u8]) -> Option<Match> {
+        // This is safe because the only way we can construct a Teddy type
+        // is if AVX2 is available.
+        unsafe { self.find_impl(haystack) }
+    }
+
+    #[allow(unused_attributes)]
+    #[target_feature(enable = "avx2")]
+    unsafe fn find_impl(&self, haystack: &[u8]) -> Option<Match> {
+        // If our haystack is smaller than the block size, then fall back to
+        // a naive brute force search.
+        if haystack.is_empty() || haystack.len() < (BLOCK_SIZE + 2) {
+            return self.slow(haystack, 0);
+        }
+        match self.masks.len() {
+            0 => None,
+            1 => self.find1(haystack),
+            2 => self.find2(haystack),
+            3 => self.find3(haystack),
+            _ => unreachable!(),
+        }
+    }
+
+    /// `find1` is used when there is only 1 mask. This is the easy case and is
+    /// pretty much as described in the module documentation.
+    #[inline(always)]
+    fn find1(&self, haystack: &[u8]) -> Option<Match> {
+        let mut pos = 0;
+        let zero = self.vb.u8x32_splat(0);
+        let len = haystack.len();
+        debug_assert!(len >= BLOCK_SIZE);
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-32.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x32_load_unchecked_unaligned(p)
+            };
+            // N.B. `res0` is our `C` in the module documentation.
+            let res0 = self.masks.members1(h);
+            // Only do expensive verification if there are any non-zero bits.
+            let bitfield = res0.ne(zero).movemask();
+            if bitfield != 0 {
+                if let Some(m) = self.verify(haystack, pos, res0, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        self.slow(haystack, pos)
+    }
+
+    /// `find2` is used when there are 2 masks, e.g., the fingerprint is 2 bytes
+    /// long.
+    #[inline(always)]
+    fn find2(&self, haystack: &[u8]) -> Option<Match> {
+        // This is an exotic way to right shift a SIMD vector across lanes.
+        // See below at use for more details.
+        let zero = self.vb.u8x32_splat(0);
+        let len = haystack.len();
+        // The previous value of `C` (from the module documentation) for the
+        // *first* byte in the fingerprint. On subsequent iterations, we take
+        // the last bitset from the previous `C` and insert it into the first
+        // position of the current `C`, shifting all other bitsets to the right
+        // one lane. This causes `C` for the first byte to line up with `C` for
+        // the second byte, so that they can be `AND`'d together.
+        let mut prev0 = self.vb.u8x32_splat(0xFF);
+        let mut pos = 1;
+        debug_assert!(len >= BLOCK_SIZE);
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-32.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x32_load_unchecked_unaligned(p)
+            };
+            let (res0, res1) = self.masks.members2(h);
+
+            // Do this:
+            //
+            //     (prev0 << 15) | (res0 >> 1)
+            //
+            // This lets us line up our C values for each byte.
+            let res0prev0 = res0.alignr_15(prev0);
+
+            // `AND`'s our `C` values together.
+            let res = res0prev0.and(res1);
+            prev0 = res0;
+
+            let bitfield = res.ne(zero).movemask();
+            if bitfield != 0 {
+                let pos = pos.checked_sub(1).unwrap();
+                if let Some(m) = self.verify(haystack, pos, res, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        // The windowing above doesn't check the last byte in the last
+        // window, so start the slow search at the last byte of the last
+        // window.
+        self.slow(haystack, pos.checked_sub(1).unwrap())
+    }
+
+    /// `find3` is used when there are 3 masks, e.g., the fingerprint is 3 bytes
+    /// long.
+    ///
+    /// N.B. This is a straight-forward extrapolation of `find2`. The only
+    /// difference is that we need to keep track of two previous values of `C`,
+    /// since we now need to align for three bytes.
+    #[inline(always)]
+    fn find3(&self, haystack: &[u8]) -> Option<Match> {
+        let zero = self.vb.u8x32_splat(0);
+        let len = haystack.len();
+        let mut prev0 = self.vb.u8x32_splat(0xFF);
+        let mut prev1 = self.vb.u8x32_splat(0xFF);
+        let mut pos = 2;
+
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-32.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x32_load_unchecked_unaligned(p)
+            };
+            let (res0, res1, res2) = self.masks.members3(h);
+
+            let res0prev0 = res0.alignr_14(prev0);
+            let res1prev1 = res1.alignr_15(prev1);
+            let res = res0prev0.and(res1prev1).and(res2);
+
+            prev0 = res0;
+            prev1 = res1;
+
+            let bitfield = res.ne(zero).movemask();
+            if bitfield != 0 {
+                let pos = pos.checked_sub(2).unwrap();
+                if let Some(m) = self.verify(haystack, pos, res, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        // The windowing above doesn't check the last two bytes in the last
+        // window, so start the slow search at the penultimate byte of the
+        // last window.
+        // self.slow(haystack, pos.saturating_sub(2))
+        self.slow(haystack, pos.checked_sub(2).unwrap())
+    }
+
+    /// Runs the verification procedure on `res` (i.e., `C` from the module
+    /// documentation), where the haystack block starts at `pos` in
+    /// `haystack`. `bitfield` has ones in the bit positions that `res` has
+    /// non-zero bytes.
+    ///
+    /// If a match exists, it returns the first one.
+    #[inline(always)]
+    fn verify(
+        &self,
+        haystack: &[u8],
+        pos: usize,
+        res: u8x32,
+        mut bitfield: u32,
+    ) -> Option<Match> {
+        while bitfield != 0 {
+            // The next offset, relative to pos, where some fingerprint
+            // matched.
+            let byte_pos = bitfield.trailing_zeros() as usize;
+            bitfield &= !(1 << byte_pos);
+
+            // Offset relative to the beginning of the haystack.
+            let start = pos + byte_pos;
+
+            // The bitfield telling us which patterns had fingerprints that
+            // match at this starting position.
+            let mut patterns = res.extract(byte_pos);
+            while patterns != 0 {
+                let bucket = patterns.trailing_zeros() as usize;
+                patterns &= !(1 << bucket);
+
+                // Actual substring search verification.
+                if let Some(m) = self.verify_bucket(haystack, bucket, start) {
+                    return Some(m);
+                }
+            }
+        }
+
+        None
+    }
+
+    /// Verifies whether any substring in the given bucket matches in haystack
+    /// at the given starting position.
+    #[inline(always)]
+    fn verify_bucket(
+        &self,
+        haystack: &[u8],
+        bucket: usize,
+        start: usize,
+    ) -> Option<Match> {
+        // This cycles through the patterns in the bucket in the order that
+        // the patterns were given. Therefore, we guarantee leftmost-first
+        // semantics.
+        for &pati in &self.buckets[bucket] {
+            let pat = &*self.pats[pati];
+            if start + pat.len() > haystack.len() {
+                continue;
+            }
+            if pat == &haystack[start..start + pat.len()] {
+                return Some(Match {
+                    pat: pati,
+                    start: start,
+                    end: start + pat.len(),
+                });
+            }
+        }
+        None
+    }
+
+    /// Slow substring search through all patterns in this matcher.
+    ///
+    /// This is used when we don't have enough bytes in the haystack for our
+    /// block based approach.
+    #[inline(never)]
+    fn slow(&self, haystack: &[u8], pos: usize) -> Option<Match> {
+        self.ac.find(&haystack[pos..]).next().map(|m| {
+            Match {
+                pat: m.pati,
+                start: pos + m.start,
+                end: pos + m.end,
+            }
+        })
+    }
+}
+
+/// A list of masks. This has length equal to the length of the fingerprint.
+/// The length of the fingerprint is always `min(3, len(smallest_substring))`.
+#[derive(Debug, Clone)]
+struct Masks {
+    vb: AVX2VectorBuilder,
+    masks: [Mask; 3],
+    size: usize,
+}
+
+impl Masks {
+    /// Create a new set of masks of size `n`, where `n` corresponds to the
+    /// number of bytes in a fingerprint.
+    fn new(vb: AVX2VectorBuilder, n: usize) -> Masks {
+        Masks {
+            vb: vb,
+            masks: [Mask::new(vb), Mask::new(vb), Mask::new(vb)],
+            size: n,
+        }
+    }
+
+    /// Returns the number of masks.
+    fn len(&self) -> usize {
+        self.size
+    }
+
+    /// Adds the given pattern to the given bucket. The bucket should be a
+    /// power of `2 <= 2^7`.
+    fn add(&mut self, bucket: u8, pat: &[u8]) {
+        for i in 0..self.len() {
+            self.masks[i].add(bucket, pat[i]);
+        }
+    }
+
+    /// Finds the fingerprints that are in the given haystack block. i.e., this
+    /// returns `C` as described in the module documentation.
+    ///
+    /// More specifically, `for i in 0..16` and `j in 0..8, C[i][j] == 1` if and
+    /// only if `haystack_block[i]` corresponds to a fingerprint that is part
+    /// of a pattern in bucket `j`.
+    #[inline(always)]
+    fn members1(&self, haystack_block: u8x32) -> u8x32 {
+        let masklo = self.vb.u8x32_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi))
+    }
+
+    /// Like members1, but computes C for the first and second bytes in the
+    /// fingerprint.
+    #[inline(always)]
+    fn members2(&self, haystack_block: u8x32) -> (u8x32, u8x32) {
+        let masklo = self.vb.u8x32_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        let res0 =
+            self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi));
+        let res1 =
+            self.masks[1].lo.shuffle(hlo).and(self.masks[1].hi.shuffle(hhi));
+        (res0, res1)
+    }
+
+    /// Like `members1`, but computes `C` for the first, second and third bytes
+    /// in the fingerprint.
+    #[inline(always)]
+    fn members3(&self, haystack_block: u8x32) -> (u8x32, u8x32, u8x32) {
+        let masklo = self.vb.u8x32_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        let res0 =
+            self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi));
+        let res1 =
+            self.masks[1].lo.shuffle(hlo).and(self.masks[1].hi.shuffle(hhi));
+        let res2 =
+            self.masks[2].lo.shuffle(hlo).and(self.masks[2].hi.shuffle(hhi));
+        (res0, res1, res2)
+    }
+}
+
+/// A single mask.
+#[derive(Debug, Clone, Copy)]
+struct Mask {
+    /// Bitsets for the low nybbles in a fingerprint.
+    lo: u8x32,
+    /// Bitsets for the high nybbles in a fingerprint.
+    hi: u8x32,
+}
+
+impl Mask {
+    /// Create a new mask with no members.
+    fn new(vb: AVX2VectorBuilder) -> Mask {
+        Mask {
+            lo: vb.u8x32_splat(0),
+            hi: vb.u8x32_splat(0),
+        }
+    }
+
+    /// Adds the given byte to the given bucket.
+    fn add(&mut self, bucket: u8, byte: u8) {
+        // Split our byte into two nybbles, and add each nybble to our
+        // mask.
+        let byte_lo = (byte & 0xF) as usize;
+        let byte_hi = (byte >> 4) as usize;
+
+        let lo = self.lo.extract(byte_lo) | ((1 << bucket) as u8);
+        self.lo.replace(byte_lo, lo);
+        self.lo.replace(byte_lo + 16, lo);
+
+        let hi = self.hi.extract(byte_hi) | ((1 << bucket) as u8);
+        self.hi.replace(byte_hi, hi);
+        self.hi.replace(byte_hi + 16, hi);
+    }
+}
diff --git a/third_party/rust/regex/src/literal/teddy_avx2/mod.rs b/third_party/rust/regex/src/literal/teddy_avx2/mod.rs
new file mode 100644
index 000000000000..4a268163be73
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_avx2/mod.rs
@@ -0,0 +1,14 @@
+pub use self::imp::*;
+
+#[cfg(all(
+    regex_runtime_teddy_avx2,
+    target_arch = "x86_64",
+))]
+mod imp;
+
+#[cfg(not(all(
+    regex_runtime_teddy_avx2,
+    target_arch = "x86_64",
+)))]
+#[path = "fallback.rs"]
+mod imp;
diff --git a/third_party/rust/regex/src/literal/teddy_ssse3/fallback.rs b/third_party/rust/regex/src/literal/teddy_ssse3/fallback.rs
new file mode 100644
index 000000000000..20524aabfe4a
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_ssse3/fallback.rs
@@ -0,0 +1,20 @@
+use syntax::hir::literal::Literals;
+
+#[derive(Debug, Clone)]
+pub struct Teddy(());
+
+#[derive(Debug, Clone)]
+pub struct Match {
+    pub pat: usize,
+    pub start: usize,
+    pub end: usize,
+}
+
+impl Teddy {
+    pub fn available() -> bool { false }
+    pub fn new(_pats: &Literals) -> Option<Teddy> { None }
+    pub fn patterns(&self) -> &[Vec<u8>] { &[] }
+    pub fn len(&self) -> usize { 0 }
+    pub fn approximate_size(&self) -> usize { 0 }
+    pub fn find(&self, _haystack: &[u8]) -> Option<Match> { None }
+}
diff --git a/third_party/rust/regex/src/literal/teddy_ssse3/imp.rs b/third_party/rust/regex/src/literal/teddy_ssse3/imp.rs
new file mode 100644
index 000000000000..85422b64095a
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_ssse3/imp.rs
@@ -0,0 +1,776 @@
+/*!
+Teddy is a simd accelerated multiple substring matching algorithm. The name
+and the core ideas in the algorithm were learned from the [Hyperscan][1_u]
+project.
+
+
+Background
+----------
+
+The key idea of Teddy is to do *packed* substring matching. In the literature,
+packed substring matching is the idea of examing multiple bytes in a haystack
+at a time to detect matches. Implementations of, for example, memchr (which
+detects matches of a single byte) have been doing this for years. Only
+recently, with the introduction of various SIMD instructions, has this been
+extended to substring matching. The PCMPESTRI instruction (and its relatives),
+for example, implements substring matching in hardware. It is, however, limited
+to substrings of length 16 bytes or fewer, but this restriction is fine in a
+regex engine, since we rarely care about the performance difference between
+searching for a 16 byte literal and a 16 + N literal; 16 is already long
+enough. The key downside of the PCMPESTRI instruction, on current (2016) CPUs
+at least, is its latency and throughput. As a result, it is often faster to do
+substring search with a Boyer-Moore variant and a well placed memchr to quickly
+skip through the haystack.
+
+There are fewer results from the literature on packed substring matching,
+and even fewer for packed multiple substring matching. Ben-Kiki et al. [2]
+describes use of PCMPESTRI for substring matching, but is mostly theoretical
+and hand-waves performance. There is other theoretical work done by Bille [3]
+as well.
+
+The rest of the work in the field, as far as I'm aware, is by Faro and Kulekci
+and is generally focused on multiple pattern search. Their first paper [4a]
+introduces the concept of a fingerprint, which is computed for every block of
+N bytes in every pattern. The haystack is then scanned N bytes at a time and
+a fingerprint is computed in the same way it was computed for blocks in the
+patterns. If the fingerprint corresponds to one that was found in a pattern,
+then a verification step follows to confirm that one of the substrings with the
+corresponding fingerprint actually matches at the current location. Various
+implementation tricks are employed to make sure the fingerprint lookup is fast;
+typically by truncating the fingerprint. (This may, of course, provoke more
+steps in the verification process, so a balance must be struck.)
+
+The main downside of [4a] is that the minimum substring length is 32 bytes,
+presumably because of how the algorithm uses certain SIMD instructions. This
+essentially makes it useless for general purpose regex matching, where a small
+number of short patterns is far more likely.
+
+Faro and Kulekci published another paper [4b] that is conceptually very similar
+to [4a]. The key difference is that it uses the CRC32 instruction (introduced
+as part of SSE 4.2) to compute fingerprint values. This also enables the
+algorithm to work effectively on substrings as short as 7 bytes with 4 byte
+windows. 7 bytes is unfortunately still too long. The window could be
+technically shrunk to 2 bytes, thereby reducing minimum length to 3, but the
+small window size ends up negating most performance benefits—and it's likely
+the common case in a general purpose regex engine.
+
+Faro and Kulekci also published [4c] that appears to be intended as a
+replacement to using PCMPESTRI. In particular, it is specifically motivated by
+the high throughput/latency time of PCMPESTRI and therefore chooses other SIMD
+instructions that are faster. While this approach works for short substrings,
+I personally couldn't see a way to generalize it to multiple substring search.
+
+Faro and Kulekci have another paper [4d] that I haven't been able to read
+because it is behind a paywall.
+
+
+Teddy
+-----
+
+Finally, we get to Teddy. If the above literature review is complete, then it
+appears that Teddy is a novel algorithm. More than that, in my experience, it
+completely blows away the competition for short substrings, which is exactly
+what we want in a general purpose regex engine. Again, the algorithm appears
+to be developed by the authors of [Hyperscan][1_u]. Hyperscan was open sourced
+late 2015, and no earlier history could be found. Therefore, tracking the exact
+provenance of the algorithm with respect to the published literature seems
+difficult.
+
+DISCLAIMER: My understanding of Teddy is limited to reading auto-generated C
+code, its disassembly and observing its runtime behavior.
+
+At a high level, Teddy works somewhat similarly to the fingerprint algorithms
+published by Faro and Kulekci, but Teddy does it in a way that scales a bit
+better. Namely:
+
+1. Teddy's core algorithm scans the haystack in 16 byte chunks. 16 is
+   significant because it corresponds to the number of bytes in a SIMD vector.
+   If one used AVX2 instructions, then we could scan the haystack in 32 byte
+   chunks. Similarly, if one used AVX512 instructions, we could scan the
+   haystack in 64 byte chunks. Hyperscan implements SSE + AVX2, we only
+   implement SSE for the moment.
+2. Bitwise operations are performed on each chunk to discover if any region of
+   it matches a set of precomputed fingerprints from the patterns. If there are
+   matches, then a verification step is performed. In this implementation, our
+   verification step is naive. This can be improved upon.
+
+The details to make this work are quite clever. First, we must choose how to
+pick our fingerprints. In Hyperscan's implementation, I *believe* they use the
+last N bytes of each substring, where N must be at least the minimum length of
+any substring in the set being searched. In this implementation, we use the
+first N bytes of each substring. (The tradeoffs between these choices aren't
+yet clear to me.) We then must figure out how to quickly test whether an
+occurrence of any fingerprint from the set of patterns appears in a 16 byte
+block from the haystack. To keep things simple, let's assume N = 1 and examine
+some examples to motivate the approach. Here are our patterns:
+
+```ignore
+foo
+bar
+baz
+```
+
+The corresponding fingerprints, for N = 1, are `f`, `b` and `b`. Now let's set
+our 16 byte block to:
+
+```ignore
+bat cat foo bump
+xxxxxxxxxxxxxxxx
+```
+
+To cut to the chase, Teddy works by using bitsets. In particular, Teddy creates
+a mask that allows us to quickly compute membership of a fingerprint in a 16
+byte block that also tells which pattern the fingerprint corresponds to. In
+this case, our fingerprint is a single byte, so an appropriate abstraction is
+a map from a single byte to a list of patterns that contain that fingerprint:
+
+```ignore
+f |--> foo
+b |--> bar, baz
+```
+
+Now, all we need to do is figure out how to represent this map in vector space
+and use normal SIMD operations to perform a lookup. The first simplification
+we can make is to represent our patterns as bit fields occupying a single
+byte. This is important, because a single SIMD vector can store 16 bytes.
+
+```ignore
+f |--> 00000001
+b |--> 00000010, 00000100
+```
+
+How do we perform lookup though? It turns out that SSSE3 introduced a very cool
+instruction called PSHUFB. The instruction takes two SIMD vectors, `A` and `B`,
+and returns a third vector `C`. All vectors are treated as 16 8-bit integers.
+`C` is formed by `C[i] = A[B[i]]`. (This is a bit of a simplification, but true
+for the purposes of this algorithm. For full details, see [Intel's Intrinsics
+Guide][5_u].) This essentially lets us use the values in `B` to lookup values
+in `A`.
+
+If we could somehow cause `B` to contain our 16 byte block from the haystack,
+and if `A` could contain our bitmasks, then we'd end up with something like
+this for `A`:
+
+```ignore
+    0x00 0x01 ... 0x62      ... 0x66      ... 0xFF
+A = 0    0        00000110      00000001      0
+```
+
+And if `B` contains our window from our haystack, we could use shuffle to take
+the values from `B` and use them to look up our bitsets in `A`. But of course,
+we can't do this because `A` in the above example contains 256 bytes, which
+is much larger than the size of a SIMD vector.
+
+Nybbles to the rescue! A nybble is 4 bits. Instead of one mask to hold all of
+our bitsets, we can use two masks, where one mask corresponds to the lower four
+bits of our fingerprint and the other mask corresponds to the upper four bits.
+So our map now looks like:
+
+```ignore
+'f' & 0xF = 0x6 |--> 00000001
+'f' >> 4  = 0x6 |--> 00000111
+'b' & 0xF = 0x2 |--> 00000110
+'b' >> 4  = 0x6 |--> 00000111
+```
+
+Notice that the bitsets for each nybble correspond to the union of all
+fingerprints that contain that nybble. For example, both `f` and `b` have the
+same upper 4 bits but differ on the lower 4 bits. Putting this together, we
+have `A0`, `A1` and `B`, where `A0` is our mask for the lower nybble, `A1` is
+our mask for the upper nybble and `B` is our 16 byte block from the haystack:
+
+```ignore
+      0x00 0x01 0x02      0x03 ... 0x06      ... 0xF
+A0 =  0    0    00000110  0        00000001      0
+A1 =  0    0    0         0        00000111      0
+B  =  b    a    t         _        t             p
+B  =  0x62 0x61 0x74      0x20     0x74          0x70
+```
+
+But of course, we can't use `B` with `PSHUFB` yet, since its values are 8 bits,
+and we need indexes that are at most 4 bits (corresponding to one of 16
+values). We can apply the same transformation to split `B` into lower and upper
+nybbles as we did `A`. As before, `B0` corresponds to the lower nybbles and
+`B1` corresponds to the upper nybbles:
+
+```ignore
+     b   a   t   _   c   a   t   _   f   o   o   _   b   u   m   p
+B0 = 0x2 0x1 0x4 0x0 0x3 0x1 0x4 0x0 0x6 0xF 0xF 0x0 0x2 0x5 0xD 0x0
+B1 = 0x6 0x6 0x7 0x2 0x6 0x6 0x7 0x2 0x6 0x6 0x6 0x2 0x6 0x7 0x6 0x7
+```
+
+And now we have a nice correspondence. `B0` can index `A0` and `B1` can index
+`A1`. Here's what we get when we apply `C0 = PSHUFB(A0, B0)`:
+
+```ignore
+     b         a        ... f         o         ... p
+     A0[0x2]   A0[0x1]      A0[0x6]   A0[0xF]       A0[0x0]
+C0 = 00000110  0            00000001  0             0
+```
+
+And `C1 = PSHUFB(A1, B1)`:
+
+```ignore
+     b         a        ... f         o        ... p
+     A1[0x6]   A1[0x6]      A1[0x6]   A1[0x6]      A1[0x7]
+C1 = 00000111  00000111     00000111  00000111     0
+```
+
+Notice how neither one of `C0` or `C1` is guaranteed to report fully correct
+results all on its own. For example, `C1` claims that `b` is a fingerprint for
+the pattern `foo` (since `A1[0x6] = 00000111`), and that `o` is a fingerprint
+for all of our patterns. But if we combined `C0` and `C1` with an `AND`
+operation:
+
+```ignore
+     b         a        ... f         o        ... p
+C  = 00000110  0            00000001  0            0
+```
+
+Then we now have that `C[i]` contains a bitset corresponding to the matching
+fingerprints in a haystack's 16 byte block, where `i` is the `ith` byte in that
+block.
+
+Once we have that, we can look for the position of the least significant bit
+in `C`. That position, modulo `8`, gives us the pattern that the fingerprint
+matches. That position, integer divided by `8`, also gives us the byte offset
+that the fingerprint occurs in inside the 16 byte haystack block. Using those
+two pieces of information, we can run a verification procedure that tries
+to match all substrings containing that fingerprint at that position in the
+haystack.
+
+
+Implementation notes
+--------------------
+
+The problem with the algorithm as described above is that it uses a single byte
+for a fingerprint. This will work well if the fingerprints are rare in the
+haystack (e.g., capital letters or special characters in normal English text),
+but if the fingerprints are common, you'll wind up spending too much time in
+the verification step, which effectively negate the performance benefits of
+scanning 16 bytes at a time. Remember, the key to the performance of this
+algorithm is to do as little work as possible per 16 bytes.
+
+This algorithm can be extrapolated in a relatively straight-forward way to use
+larger fingerprints. That is, instead of a single byte prefix, we might use a
+three byte prefix. The implementation below implements N = {1, 2, 3} and always
+picks the largest N possible. The rationale is that the bigger the fingerprint,
+the fewer verification steps we'll do. Of course, if N is too large, then we'll
+end up doing too much on each step.
+
+The way to extend it is:
+
+1. Add a mask for each byte in the fingerprint. (Remember that each mask is
+   composed of two SIMD vectors.) This results in a value of `C` for each byte
+   in the fingerprint while searching.
+2. When testing each 16 byte block, each value of `C` must be shifted so that
+   they are aligned. Once aligned, they should all be `AND`'d together. This
+   will give you only the bitsets corresponding to the full match of the
+   fingerprint.
+
+The implementation below is commented to fill in the nitty gritty details.
+
+References
+----------
+
+- **[1]** [Hyperscan on GitHub](https://github.com/01org/hyperscan),
+    [webpage](https://01.org/hyperscan)
+- **[2a]** Ben-Kiki, O., Bille, P., Breslauer, D., Gasieniec, L., Grossi, R.,
+    & Weimann, O. (2011).
+    _Optimal packed string matching_.
+    In LIPIcs-Leibniz International Proceedings in Informatics (Vol. 13).
+    Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.
+    DOI: 10.4230/LIPIcs.FSTTCS.2011.423.
+    [PDF](http://drops.dagstuhl.de/opus/volltexte/2011/3355/pdf/37.pdf).
+- **[2b]** Ben-Kiki, O., Bille, P., Breslauer, D., Ga̧sieniec, L., Grossi, R.,
+    & Weimann, O. (2014).
+    _Towards optimal packed string matching_.
+    Theoretical Computer Science, 525, 111-129.
+    DOI: 10.1016/j.tcs.2013.06.013.
+    [PDF](http://www.cs.haifa.ac.il/~oren/Publications/bpsm.pdf).
+- **[3]** Bille, P. (2011).
+    _Fast searching in packed strings_.
+    Journal of Discrete Algorithms, 9(1), 49-56.
+    DOI: 10.1016/j.jda.2010.09.003.
+    [PDF](http://www.sciencedirect.com/science/article/pii/S1570866710000353).
+- **[4a]** Faro, S., & Külekci, M. O. (2012, October).
+    _Fast multiple string matching using streaming SIMD extensions technology_.
+    In String Processing and Information Retrieval (pp. 217-228).
+    Springer Berlin Heidelberg.
+    DOI: 10.1007/978-3-642-34109-0_23.
+    [PDF](http://www.dmi.unict.it/~faro/papers/conference/faro32.pdf).
+- **[4b]** Faro, S., & Külekci, M. O. (2013, September).
+    _Towards a Very Fast Multiple String Matching Algorithm for Short Patterns_.
+    In Stringology (pp. 78-91).
+    [PDF](http://www.dmi.unict.it/~faro/papers/conference/faro36.pdf).
+- **[4c]** Faro, S., & Külekci, M. O. (2013, January).
+    _Fast packed string matching for short patterns_.
+    In Proceedings of the Meeting on Algorithm Engineering & Expermiments
+    (pp. 113-121).
+    Society for Industrial and Applied Mathematics.
+    [PDF](http://arxiv.org/pdf/1209.6449.pdf).
+- **[4d]** Faro, S., & Külekci, M. O. (2014).
+    _Fast and flexible packed string matching_.
+    Journal of Discrete Algorithms, 28, 61-72.
+    DOI: 10.1016/j.jda.2014.07.003.
+
+[1_u]: https://github.com/01org/hyperscan
+[5_u]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
+*/
+
+use std::cmp;
+
+use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
+use syntax::hir::literal::Literals;
+
+use vector::ssse3::{SSSE3VectorBuilder, u8x16};
+
+/// Corresponds to the number of bytes read at a time in the haystack.
+const BLOCK_SIZE: usize = 16;
+
+/// Match reports match information.
+#[derive(Debug, Clone)]
+pub struct Match {
+    /// The index of the pattern that matched. The index is in correspondence
+    /// with the order of the patterns given at construction.
+    pub pat: usize,
+    /// The start byte offset of the match.
+    pub start: usize,
+    /// The end byte offset of the match. This is always `start + pat.len()`.
+    pub end: usize,
+}
+
+/// A SIMD accelerated multi substring searcher.
+#[derive(Debug, Clone)]
+pub struct Teddy {
+    /// A builder for SSSE3 empowered vectors.
+    vb: SSSE3VectorBuilder,
+    /// A list of substrings to match.
+    pats: Vec<Vec<u8>>,
+    /// An Aho-Corasick automaton of the patterns. We use this when we need to
+    /// search pieces smaller than the Teddy block size.
+    ac: FullAcAutomaton<Vec<u8>>,
+    /// A set of 8 buckets. Each bucket corresponds to a single member of a
+    /// bitset. A bucket contains zero or more substrings. This is useful
+    /// when the number of substrings exceeds 8, since our bitsets cannot have
+    /// more than 8 members.
+    buckets: Vec<Vec<usize>>,
+    /// Our set of masks. There's one mask for each byte in the fingerprint.
+    masks: Masks,
+}
+
+impl Teddy {
+    /// Returns true if and only if Teddy is supported on this platform.
+    ///
+    /// If this returns `false`, then `Teddy::new(...)` is guaranteed to
+    /// return `None`.
+    pub fn available() -> bool {
+        SSSE3VectorBuilder::new().is_some()
+    }
+
+    /// Create a new `Teddy` multi substring matcher.
+    ///
+    /// If a `Teddy` matcher could not be created (e.g., `pats` is empty or has
+    /// an empty substring), then `None` is returned.
+    pub fn new(pats: &Literals) -> Option<Teddy> {
+        let vb = match SSSE3VectorBuilder::new() {
+            None => return None,
+            Some(vb) => vb,
+        };
+        if !Teddy::available() {
+            return None;
+        }
+
+        let pats: Vec<_> = pats.literals().iter().map(|p|p.to_vec()).collect();
+        let min_len = pats.iter().map(|p| p.len()).min().unwrap_or(0);
+        // Don't allow any empty patterns and require that we have at
+        // least one pattern.
+        if min_len < 1 {
+            return None;
+        }
+        // Pick the largest mask possible, but no larger than 3.
+        let nmasks = cmp::min(3, min_len);
+        let mut masks = Masks::new(vb, nmasks);
+        let mut buckets = vec![vec![]; 8];
+        // Assign a substring to each bucket, and add the bucket's bitfield to
+        // the appropriate position in the mask.
+        for (pati, pat) in pats.iter().enumerate() {
+            let bucket = pati % 8;
+            buckets[bucket].push(pati);
+            masks.add(bucket as u8, pat);
+        }
+        Some(Teddy {
+            vb: vb,
+            pats: pats.to_vec(),
+            ac: AcAutomaton::new(pats.to_vec()).into_full(),
+            buckets: buckets,
+            masks: masks,
+        })
+    }
+
+    /// Returns all of the substrings matched by this `Teddy`.
+    pub fn patterns(&self) -> &[Vec<u8>] {
+        &self.pats
+    }
+
+    /// Returns the number of substrings in this matcher.
+    pub fn len(&self) -> usize {
+        self.pats.len()
+    }
+
+    /// Returns the approximate size on the heap used by this matcher.
+    pub fn approximate_size(&self) -> usize {
+        self.pats.iter().fold(0, |a, b| a + b.len())
+    }
+
+    /// Searches `haystack` for the substrings in this `Teddy`. If a match was
+    /// found, then it is returned. Otherwise, `None` is returned.
+    pub fn find(&self, haystack: &[u8]) -> Option<Match> {
+        // This is safe because the only way we can construct a Teddy type
+        // is if SSSE3 is available.
+        unsafe { self.find_impl(haystack) }
+    }
+
+    #[allow(unused_attributes)]
+    #[target_feature(enable = "ssse3")]
+    unsafe fn find_impl(&self, haystack: &[u8]) -> Option<Match> {
+        // If our haystack is smaller than the block size, then fall back to
+        // a naive brute force search.
+        if haystack.is_empty() || haystack.len() < (BLOCK_SIZE + 2) {
+            return self.slow(haystack, 0);
+        }
+        match self.masks.len() {
+            0 => None,
+            1 => self.find1(haystack),
+            2 => self.find2(haystack),
+            3 => self.find3(haystack),
+            _ => unreachable!(),
+        }
+    }
+
+    /// `find1` is used when there is only 1 mask. This is the easy case and is
+    /// pretty much as described in the module documentation.
+    #[inline(always)]
+    fn find1(&self, haystack: &[u8]) -> Option<Match> {
+        let mut pos = 0;
+        let zero = self.vb.u8x16_splat(0);
+        let len = haystack.len();
+        debug_assert!(len >= BLOCK_SIZE);
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-16.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x16_load_unchecked_unaligned(p)
+            };
+            // N.B. `res0` is our `C` in the module documentation.
+            let res0 = self.masks.members1(h);
+            // Only do expensive verification if there are any non-zero bits.
+            let bitfield = res0.ne(zero).movemask();
+            if bitfield != 0 {
+                if let Some(m) = self.verify(haystack, pos, res0, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        self.slow(haystack, pos)
+    }
+
+    /// `find2` is used when there are 2 masks, e.g., the fingerprint is 2 bytes
+    /// long.
+    #[inline(always)]
+    fn find2(&self, haystack: &[u8]) -> Option<Match> {
+        // This is an exotic way to right shift a SIMD vector across lanes.
+        // See below at use for more details.
+        let zero = self.vb.u8x16_splat(0);
+        let len = haystack.len();
+        // The previous value of `C` (from the module documentation) for the
+        // *first* byte in the fingerprint. On subsequent iterations, we take
+        // the last bitset from the previous `C` and insert it into the first
+        // position of the current `C`, shifting all other bitsets to the right
+        // one lane. This causes `C` for the first byte to line up with `C` for
+        // the second byte, so that they can be `AND`'d together.
+        let mut prev0 = self.vb.u8x16_splat(0xFF);
+        let mut pos = 1;
+        debug_assert!(len >= BLOCK_SIZE);
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-16.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x16_load_unchecked_unaligned(p)
+            };
+            let (res0, res1) = self.masks.members2(h);
+
+            // Do this:
+            //
+            //     (prev0 << 15) | (res0 >> 1)
+            //
+            // This lets us line up our C values for each byte.
+            let res0prev0 = res0.alignr_15(prev0);
+
+            // `AND`'s our `C` values together.
+            let res = res0prev0.and(res1);
+            prev0 = res0;
+
+            let bitfield = res.ne(zero).movemask();
+            if bitfield != 0 {
+                let pos = pos.checked_sub(1).unwrap();
+                if let Some(m) = self.verify(haystack, pos, res, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        // The windowing above doesn't check the last byte in the last
+        // window, so start the slow search at the last byte of the last
+        // window.
+        self.slow(haystack, pos.checked_sub(1).unwrap())
+    }
+
+    /// `find3` is used when there are 3 masks, e.g., the fingerprint is 3 bytes
+    /// long.
+    ///
+    /// N.B. This is a straight-forward extrapolation of `find2`. The only
+    /// difference is that we need to keep track of two previous values of `C`,
+    /// since we now need to align for three bytes.
+    #[inline(always)]
+    fn find3(&self, haystack: &[u8]) -> Option<Match> {
+        let zero = self.vb.u8x16_splat(0);
+        let len = haystack.len();
+        let mut prev0 = self.vb.u8x16_splat(0xFF);
+        let mut prev1 = self.vb.u8x16_splat(0xFF);
+        let mut pos = 2;
+        while pos <= len - BLOCK_SIZE {
+            let h = unsafe {
+                // I tried and failed to eliminate bounds checks in safe code.
+                // This is safe because of our loop invariant: pos is always
+                // <= len-16.
+                let p = haystack.get_unchecked(pos..);
+                self.vb.u8x16_load_unchecked_unaligned(p)
+            };
+            let (res0, res1, res2) = self.masks.members3(h);
+
+            let res0prev0 = res0.alignr_14(prev0);
+            let res1prev1 = res1.alignr_15(prev1);
+            let res = res0prev0.and(res1prev1).and(res2);
+
+            prev0 = res0;
+            prev1 = res1;
+
+            let bitfield = res.ne(zero).movemask();
+            if bitfield != 0 {
+                let pos = pos.checked_sub(2).unwrap();
+                if let Some(m) = self.verify(haystack, pos, res, bitfield) {
+                    return Some(m);
+                }
+            }
+            pos += BLOCK_SIZE;
+        }
+        // The windowing above doesn't check the last two bytes in the last
+        // window, so start the slow search at the penultimate byte of the
+        // last window.
+        // self.slow(haystack, pos.saturating_sub(2))
+        self.slow(haystack, pos.checked_sub(2).unwrap())
+    }
+
+    /// Runs the verification procedure on `res` (i.e., `C` from the module
+    /// documentation), where the haystack block starts at `pos` in
+    /// `haystack`. `bitfield` has ones in the bit positions that `res` has
+    /// non-zero bytes.
+    ///
+    /// If a match exists, it returns the first one.
+    #[inline(always)]
+    fn verify(
+        &self,
+        haystack: &[u8],
+        pos: usize,
+        res: u8x16,
+        mut bitfield: u32,
+    ) -> Option<Match> {
+        while bitfield != 0 {
+            // The next offset, relative to pos, where some fingerprint
+            // matched.
+            let byte_pos = bitfield.trailing_zeros() as usize;
+            bitfield &= !(1 << byte_pos);
+
+            // Offset relative to the beginning of the haystack.
+            let start = pos + byte_pos;
+
+            // The bitfield telling us which patterns had fingerprints that
+            // match at this starting position.
+            let mut patterns = res.extract(byte_pos);
+            while patterns != 0 {
+                let bucket = patterns.trailing_zeros() as usize;
+                patterns &= !(1 << bucket);
+
+                // Actual substring search verification.
+                if let Some(m) = self.verify_bucket(haystack, bucket, start) {
+                    return Some(m);
+                }
+            }
+        }
+
+        None
+    }
+
+    /// Verifies whether any substring in the given bucket matches in haystack
+    /// at the given starting position.
+    #[inline(always)]
+    fn verify_bucket(
+        &self,
+        haystack: &[u8],
+        bucket: usize,
+        start: usize,
+    ) -> Option<Match> {
+        // This cycles through the patterns in the bucket in the order that
+        // the patterns were given. Therefore, we guarantee leftmost-first
+        // semantics.
+        for &pati in &self.buckets[bucket] {
+            let pat = &*self.pats[pati];
+            if start + pat.len() > haystack.len() {
+                continue;
+            }
+            if pat == &haystack[start..start + pat.len()] {
+                return Some(Match {
+                    pat: pati,
+                    start: start,
+                    end: start + pat.len(),
+                });
+            }
+        }
+        None
+    }
+
+    /// Slow substring search through all patterns in this matcher.
+    ///
+    /// This is used when we don't have enough bytes in the haystack for our
+    /// block based approach.
+    #[inline(never)]
+    fn slow(&self, haystack: &[u8], pos: usize) -> Option<Match> {
+        self.ac.find(&haystack[pos..]).next().map(|m| {
+            Match {
+                pat: m.pati,
+                start: pos + m.start,
+                end: pos + m.end,
+            }
+        })
+    }
+}
+
+/// A list of masks. This has length equal to the length of the fingerprint.
+/// The length of the fingerprint is always `min(3, len(smallest_substring))`.
+#[derive(Debug, Clone)]
+struct Masks {
+    vb: SSSE3VectorBuilder,
+    masks: [Mask; 3],
+    size: usize,
+}
+
+impl Masks {
+    /// Create a new set of masks of size `n`, where `n` corresponds to the
+    /// number of bytes in a fingerprint.
+    fn new(vb: SSSE3VectorBuilder, n: usize) -> Masks {
+        Masks {
+            vb: vb,
+            masks: [Mask::new(vb), Mask::new(vb), Mask::new(vb)],
+            size: n,
+        }
+    }
+
+    /// Returns the number of masks.
+    fn len(&self) -> usize {
+        self.size
+    }
+
+    /// Adds the given pattern to the given bucket. The bucket should be a
+    /// power of `2 <= 2^7`.
+    fn add(&mut self, bucket: u8, pat: &[u8]) {
+        for i in 0..self.len() {
+            self.masks[i].add(bucket, pat[i]);
+        }
+    }
+
+    /// Finds the fingerprints that are in the given haystack block. i.e., this
+    /// returns `C` as described in the module documentation.
+    ///
+    /// More specifically, `for i in 0..16` and `j in 0..8, C[i][j] == 1` if and
+    /// only if `haystack_block[i]` corresponds to a fingerprint that is part
+    /// of a pattern in bucket `j`.
+    #[inline(always)]
+    fn members1(&self, haystack_block: u8x16) -> u8x16 {
+        let masklo = self.vb.u8x16_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi))
+    }
+
+    /// Like members1, but computes C for the first and second bytes in the
+    /// fingerprint.
+    #[inline(always)]
+    fn members2(&self, haystack_block: u8x16) -> (u8x16, u8x16) {
+        let masklo = self.vb.u8x16_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        let res0 =
+            self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi));
+        let res1 =
+            self.masks[1].lo.shuffle(hlo).and(self.masks[1].hi.shuffle(hhi));
+        (res0, res1)
+    }
+
+    /// Like `members1`, but computes `C` for the first, second and third bytes
+    /// in the fingerprint.
+    #[inline(always)]
+    fn members3(&self, haystack_block: u8x16) -> (u8x16, u8x16, u8x16) {
+        let masklo = self.vb.u8x16_splat(0xF);
+        let hlo = haystack_block.and(masklo);
+        let hhi = haystack_block.bit_shift_right_4().and(masklo);
+
+        let res0 =
+            self.masks[0].lo.shuffle(hlo).and(self.masks[0].hi.shuffle(hhi));
+        let res1 =
+            self.masks[1].lo.shuffle(hlo).and(self.masks[1].hi.shuffle(hhi));
+        let res2 =
+            self.masks[2].lo.shuffle(hlo).and(self.masks[2].hi.shuffle(hhi));
+        (res0, res1, res2)
+    }
+}
+
+/// A single mask.
+#[derive(Debug, Clone, Copy)]
+struct Mask {
+    /// Bitsets for the low nybbles in a fingerprint.
+    lo: u8x16,
+    /// Bitsets for the high nybbles in a fingerprint.
+    hi: u8x16,
+}
+
+impl Mask {
+    /// Create a new mask with no members.
+    fn new(vb: SSSE3VectorBuilder) -> Mask {
+        Mask {
+            lo: vb.u8x16_splat(0),
+            hi: vb.u8x16_splat(0),
+        }
+    }
+
+    /// Adds the given byte to the given bucket.
+    fn add(&mut self, bucket: u8, byte: u8) {
+        // Split our byte into two nybbles, and add each nybble to our
+        // mask.
+        let byte_lo = (byte & 0xF) as usize;
+        let byte_hi = (byte >> 4) as usize;
+
+        let lo = self.lo.extract(byte_lo);
+        self.lo.replace(byte_lo, ((1 << bucket) as u8) | lo);
+
+        let hi = self.hi.extract(byte_hi);
+        self.hi.replace(byte_hi, ((1 << bucket) as u8) | hi);
+    }
+}
diff --git a/third_party/rust/regex/src/literal/teddy_ssse3/mod.rs b/third_party/rust/regex/src/literal/teddy_ssse3/mod.rs
new file mode 100644
index 000000000000..8ffaeba57bd8
--- /dev/null
+++ b/third_party/rust/regex/src/literal/teddy_ssse3/mod.rs
@@ -0,0 +1,14 @@
+pub use self::imp::*;
+
+#[cfg(all(
+    regex_runtime_teddy_ssse3,
+    target_arch = "x86_64",
+))]
+mod imp;
+
+#[cfg(not(all(
+    regex_runtime_teddy_ssse3,
+    target_arch = "x86_64",
+)))]
+#[path = "fallback.rs"]
+mod imp;
diff --git a/third_party/rust/regex/src/pikevm.rs b/third_party/rust/regex/src/pikevm.rs
index b96f0e75885a..80d44717aea2 100644
--- a/third_party/rust/regex/src/pikevm.rs
+++ b/third_party/rust/regex/src/pikevm.rs
@@ -104,17 +104,17 @@ impl<'r, I: Input> Fsm<'r, I> {
         cache: &ProgramCache,
         matches: &mut [bool],
         slots: &mut [Slot],
         quit_after_match: bool,
         input: I,
         start: usize,
     ) -> bool {
         let mut cache = cache.borrow_mut();
-        let mut cache = &mut cache.pikevm;
+        let cache = &mut cache.pikevm;
         cache.clist.resize(prog.len(), prog.captures.len());
         cache.nlist.resize(prog.len(), prog.captures.len());
         let at = input.at(start);
         Fsm {
             prog: prog,
             stack: &mut cache.stack,
             input: input,
         }.exec_(
@@ -336,17 +336,17 @@ impl<'r, I: Input> Fsm<'r, I> {
                     }
                     ip = inst.goto;
                 }
                 Split(ref inst) => {
                     self.stack.push(FollowEpsilon::IP(inst.goto2));
                     ip = inst.goto1;
                 }
                 Match(_) | Char(_) | Ranges(_) | Bytes(_) => {
-                    let mut t = &mut nlist.caps(ip);
+                    let t = &mut nlist.caps(ip);
                     for (slot, val) in t.iter_mut().zip(thread_caps.iter()) {
                         *slot = *val;
                     }
                     return;
                 }
             }
         }
     }
diff --git a/third_party/rust/regex/src/prog.rs b/third_party/rust/regex/src/prog.rs
index 36f2aff879d9..198e1f45c4e8 100644
--- a/third_party/rust/regex/src/prog.rs
+++ b/third_party/rust/regex/src/prog.rs
@@ -2,19 +2,19 @@ use std::collections::HashMap;
 use std::cmp::Ordering;
 use std::fmt;
 use std::ops::Deref;
 use std::mem;
 use std::slice;
 use std::sync::Arc;
 
 use input::Char;
-use literals::LiteralSearcher;
+use literal::LiteralSearcher;
 
-/// InstPtr represents the index of an instruction in a regex program.
+/// `InstPtr` represents the index of an instruction in a regex program.
 pub type InstPtr = usize;
 
 /// Program is a sequence of instructions and various facts about thos
 /// instructions.
 #[derive(Clone)]
 pub struct Program {
     /// A sequence of instructions that represents an NFA.
     pub insts: Vec<Inst>,
@@ -182,59 +182,55 @@ impl fmt::Debug for Program {
             use std::ascii::escape_default;
             let escaped = escape_default(b).collect::<Vec<u8>>();
             String::from_utf8_lossy(&escaped).into_owned()
         }
 
         for (pc, inst) in self.iter().enumerate() {
             match *inst {
                 Match(slot) => {
-                    try!(write!(f, "{:04} Match({:?})", pc, slot))
+                    write!(f, "{:04} Match({:?})", pc, slot)?
                 }
                 Save(ref inst) => {
                     let s = format!("{:04} Save({})", pc, inst.slot);
-                    try!(write!(f, "{}", with_goto(pc, inst.goto, s)));
+                    write!(f, "{}", with_goto(pc, inst.goto, s))?;
                 }
                 Split(ref inst) => {
-                    try!(write!(f, "{:04} Split({}, {})",
-                                pc, inst.goto1, inst.goto2));
+                    write!(
+                        f, "{:04} Split({}, {})", pc, inst.goto1, inst.goto2)?;
                 }
                 EmptyLook(ref inst) => {
                     let s = format!("{:?}", inst.look);
-                    try!(write!(f, "{:04} {}",
-                                pc, with_goto(pc, inst.goto, s)));
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                 }
                 Char(ref inst) => {
                     let s = format!("{:?}", inst.c);
-                    try!(write!(f, "{:04} {}",
-                                pc, with_goto(pc, inst.goto, s)));
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                 }
                 Ranges(ref inst) => {
                     let ranges = inst.ranges
                         .iter()
                         .map(|r| format!("{:?}-{:?}", r.0, r.1))
                         .collect::<Vec<String>>()
                         .join(", ");
-                    let s = format!("{}", ranges);
-                    try!(write!(f, "{:04} {}",
-                                pc, with_goto(pc, inst.goto, s)));
+                    write!(
+                        f, "{:04} {}", pc, with_goto(pc, inst.goto, ranges))?;
                 }
                 Bytes(ref inst) => {
                     let s = format!(
                         "Bytes({}, {})",
                         visible_byte(inst.start),
                         visible_byte(inst.end));
-                    try!(write!(f, "{:04} {}",
-                                pc, with_goto(pc, inst.goto, s)));
+                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                 }
             }
             if pc == self.start {
-                try!(write!(f, " (start)"));
+                write!(f, " (start)")?;
             }
-            try!(write!(f, "\n"));
+            write!(f, "\n")?;
         }
         Ok(())
     }
 }
 
 impl<'a> IntoIterator for &'a Program {
     type Item = &'a Inst;
     type IntoIter = slice::Iter<'a, Inst>;
@@ -315,17 +311,17 @@ pub struct InstSplit {
     /// The first instruction to try. A match resulting from following goto1
     /// has precedence over a match resulting from following goto2.
     pub goto1: InstPtr,
     /// The second instruction to try. A match resulting from following goto1
     /// has precedence over a match resulting from following goto2.
     pub goto2: InstPtr,
 }
 
-/// Representation of the EmptyLook instruction.
+/// Representation of the `EmptyLook` instruction.
 #[derive(Clone, Debug)]
 pub struct InstEmptyLook {
     /// The next location to execute in the program if this instruction
     /// succeeds.
     pub goto: InstPtr,
     /// The type of zero-width assertion to check.
     pub look: EmptyLook,
 }
diff --git a/third_party/rust/regex/src/re_builder.rs b/third_party/rust/regex/src/re_builder.rs
index 12b251564927..6f0352687018 100644
--- a/third_party/rust/regex/src/re_builder.rs
+++ b/third_party/rust/regex/src/re_builder.rs
@@ -10,36 +10,40 @@
 
 /// The set of user configurable options for compiling zero or more regexes.
 #[derive(Clone, Debug)]
 #[allow(missing_docs)]
 pub struct RegexOptions {
     pub pats: Vec<String>,
     pub size_limit: usize,
     pub dfa_size_limit: usize,
+    pub nest_limit: u32,
     pub case_insensitive: bool,
     pub multi_line: bool,
     pub dot_matches_new_line: bool,
     pub swap_greed: bool,
     pub ignore_whitespace: bool,
     pub unicode: bool,
+    pub octal: bool,
 }
 
 impl Default for RegexOptions {
     fn default() -> Self {
         RegexOptions {
             pats: vec![],
             size_limit: 10 * (1<<20),
             dfa_size_limit: 2 * (1<<20),
+            nest_limit: 250,
             case_insensitive: false,
             multi_line: false,
             dot_matches_new_line: false,
             swap_greed: false,
             ignore_whitespace: false,
             unicode: true,
+            octal: false,
         }
     }
 }
 
 macro_rules! define_builder {
     ($name:ident, $regex_mod:ident, $only_utf8:expr) => {
         pub mod $name {
             use error::Error;
@@ -54,17 +58,17 @@ macro_rules! define_builder {
 /// setting the default flags (which can be overridden in the expression
 /// itself) or setting various limits.
 pub struct RegexBuilder(RegexOptions);
 
 impl RegexBuilder {
     /// Create a new regular expression builder with the given pattern.
     ///
     /// If the pattern is invalid, then an error will be returned when
-    /// `compile` is called.
+    /// `build` is called.
     pub fn new(pattern: &str) -> RegexBuilder {
         let mut builder = RegexBuilder(RegexOptions::default());
         builder.0.pats.push(pattern.to_owned());
         builder
     }
 
     /// Consume the builder and compile the regular expression.
     ///
@@ -74,57 +78,97 @@ impl RegexBuilder {
     pub fn build(&self) -> Result<Regex, Error> {
         ExecBuilder::new_options(self.0.clone())
             .only_utf8($only_utf8)
             .build()
             .map(Regex::from)
     }
 
     /// Set the value for the case insensitive (`i`) flag.
+    ///
+    /// When enabled, letters in the pattern will match both upper case and
+    /// lower case variants.
     pub fn case_insensitive(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.case_insensitive = yes;
         self
     }
 
     /// Set the value for the multi-line matching (`m`) flag.
+    ///
+    /// When enabled, `^` matches the beginning of lines and `$` matches the
+    /// end of lines.
+    ///
+    /// By default, they match beginning/end of the input.
     pub fn multi_line(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.multi_line = yes;
         self
     }
 
     /// Set the value for the any character (`s`) flag, where in `.` matches
     /// anything when `s` is set and matches anything except for new line when
     /// it is not set (the default).
     ///
-    /// N.B. "matches anything" means "any byte" for `regex::bytes::Regex`
-    /// expressions and means "any Unicode scalar value" for `regex::Regex`
-    /// expressions.
+    /// N.B. "matches anything" means "any byte" when Unicode is disabled and
+    /// means "any valid UTF-8 encoding of any Unicode scalar value" when
+    /// Unicode is enabled.
     pub fn dot_matches_new_line(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.dot_matches_new_line = yes;
         self
     }
 
     /// Set the value for the greedy swap (`U`) flag.
+    ///
+    /// When enabled, a pattern like `a*` is lazy (tries to find shortest
+    /// match) and `a*?` is greedy (tries to find longest match).
+    ///
+    /// By default, `a*` is greedy and `a*?` is lazy.
     pub fn swap_greed(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.swap_greed = yes;
         self
     }
 
     /// Set the value for the ignore whitespace (`x`) flag.
+    ///
+    /// When enabled, whitespace such as new lines and spaces will be ignored
+    /// between expressions of the pattern, and `#` can be used to start a
+    /// comment until the next new line.
     pub fn ignore_whitespace(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.ignore_whitespace = yes;
         self
     }
 
     /// Set the value for the Unicode (`u`) flag.
+    ///
+    /// Enabled by default. When disabled, character classes such as `\w` only
+    /// match ASCII word characters instead of all Unicode word characters.
     pub fn unicode(&mut self, yes: bool) -> &mut RegexBuilder {
         self.0.unicode = yes;
         self
     }
 
+    /// Whether to support octal syntax or not.
+    ///
+    /// Octal syntax is a little-known way of uttering Unicode codepoints in
+    /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+    /// `\141` are all equivalent regular expressions, where the last example
+    /// shows octal syntax.
+    ///
+    /// While supporting octal syntax isn't in and of itself a problem, it does
+    /// make good error messages harder. That is, in PCRE based regex engines,
+    /// syntax like `\0` invokes a backreference, which is explicitly
+    /// unsupported in Rust's regex engine. However, many users expect it to
+    /// be supported. Therefore, when octal support is disabled, the error
+    /// message will explicitly mention that backreferences aren't supported.
+    ///
+    /// Octal syntax is disabled by default.
+    pub fn octal(&mut self, yes: bool) -> &mut RegexBuilder {
+        self.0.octal = yes;
+        self
+    }
+
     /// Set the approximate size limit of the compiled regular expression.
     ///
     /// This roughly corresponds to the number of bytes occupied by a single
     /// compiled program. If the program exceeds this number, then a
     /// compilation error is returned.
     pub fn size_limit(&mut self, limit: usize) -> &mut RegexBuilder {
         self.0.size_limit = limit;
         self
@@ -132,22 +176,52 @@ impl RegexBuilder {
 
     /// Set the approximate size of the cache used by the DFA.
     ///
     /// This roughly corresponds to the number of bytes that the DFA will
     /// use while searching.
     ///
     /// Note that this is a *per thread* limit. There is no way to set a global
     /// limit. In particular, if a regex is used from multiple threads
-    /// simulanteously, then each thread may use up to the number of bytes
+    /// simultaneously, then each thread may use up to the number of bytes
     /// specified here.
     pub fn dfa_size_limit(&mut self, limit: usize) -> &mut RegexBuilder {
         self.0.dfa_size_limit = limit;
         self
     }
+
+    /// Set the nesting limit for this parser.
+    ///
+    /// The nesting limit controls how deep the abstract syntax tree is allowed
+    /// to be. If the AST exceeds the given limit (e.g., with too many nested
+    /// groups), then an error is returned by the parser.
+    ///
+    /// The purpose of this limit is to act as a heuristic to prevent stack
+    /// overflow for consumers that do structural induction on an `Ast` using
+    /// explicit recursion. While this crate never does this (instead using
+    /// constant stack space and moving the call stack to the heap), other
+    /// crates may.
+    ///
+    /// This limit is not checked until the entire Ast is parsed. Therefore,
+    /// if callers want to put a limit on the amount of heap space used, then
+    /// they should impose a limit on the length, in bytes, of the concrete
+    /// pattern string. In particular, this is viable since this parser
+    /// implementation will limit itself to heap space proportional to the
+    /// lenth of the pattern string.
+    ///
+    /// Note that a nest limit of `0` will return a nest limit error for most
+    /// patterns but not all. For example, a nest limit of `0` permits `a` but
+    /// not `ab`, since `ab` requires a concatenation, which results in a nest
+    /// depth of `1`. In general, a nest limit is not something that manifests
+    /// in an obvious way in the concrete syntax, therefore, it should not be
+    /// used in a granular way.
+    pub fn nest_limit(&mut self, limit: u32) -> &mut RegexBuilder {
+        self.0.nest_limit = limit;
+        self
+    }
 }
         }
     }
 }
 
 define_builder!(bytes, re_bytes, false);
 define_builder!(unicode, re_unicode, true);
 
@@ -166,17 +240,17 @@ macro_rules! define_set_builder {
 /// by setting the default flags (which can be overridden in the expression
 /// itself) or setting various limits.
 pub struct RegexSetBuilder(RegexOptions);
 
 impl RegexSetBuilder {
     /// Create a new regular expression builder with the given pattern.
     ///
     /// If the pattern is invalid, then an error will be returned when
-    /// `compile` is called.
+    /// `build` is called.
     pub fn new<I, S>(patterns: I) -> RegexSetBuilder
             where S: AsRef<str>, I: IntoIterator<Item=S> {
         let mut builder = RegexSetBuilder(RegexOptions::default());
         for pat in patterns {
             builder.0.pats.push(pat.as_ref().to_owned());
         }
         builder
     }
@@ -226,16 +300,36 @@ impl RegexSetBuilder {
     }
 
     /// Set the value for the Unicode (`u`) flag.
     pub fn unicode(&mut self, yes: bool) -> &mut RegexSetBuilder {
         self.0.unicode = yes;
         self
     }
 
+    /// Whether to support octal syntax or not.
+    ///
+    /// Octal syntax is a little-known way of uttering Unicode codepoints in
+    /// a regular expression. For example, `a`, `\x61`, `\u0061` and
+    /// `\141` are all equivalent regular expressions, where the last example
+    /// shows octal syntax.
+    ///
+    /// While supporting octal syntax isn't in and of itself a problem, it does
+    /// make good error messages harder. That is, in PCRE based regex engines,
+    /// syntax like `\0` invokes a backreference, which is explicitly
+    /// unsupported in Rust's regex engine. However, many users expect it to
+    /// be supported. Therefore, when octal support is disabled, the error
+    /// message will explicitly mention that backreferences aren't supported.
+    ///
+    /// Octal syntax is disabled by default.
+    pub fn octal(&mut self, yes: bool) -> &mut RegexSetBuilder {
+        self.0.octal = yes;
+        self
+    }
+
     /// Set the approximate size limit of the compiled regular expression.
     ///
     /// This roughly corresponds to the number of bytes occupied by a single
     /// compiled program. If the program exceeds this number, then a
     /// compilation error is returned.
     pub fn size_limit(&mut self, limit: usize) -> &mut RegexSetBuilder {
         self.0.size_limit = limit;
         self
@@ -249,15 +343,46 @@ impl RegexSetBuilder {
     /// Note that this is a *per thread* limit. There is no way to set a global
     /// limit. In particular, if a regex is used from multiple threads
     /// simulanteously, then each thread may use up to the number of bytes
     /// specified here.
     pub fn dfa_size_limit(&mut self, limit: usize) -> &mut RegexSetBuilder {
         self.0.dfa_size_limit = limit;
         self
     }
+
+    /// Set the nesting limit for this parser.
+    ///
+    /// The nesting limit controls how deep the abstract syntax tree is allowed
+    /// to be. If the AST exceeds the given limit (e.g., with too many nested
+    /// groups), then an error is returned by the parser.
+    ///
+    /// The purpose of this limit is to act as a heuristic to prevent stack
+    /// overflow for consumers that do structural induction on an `Ast` using
+    /// explicit recursion. While this crate never does this (instead using
+    /// constant stack space and moving the call stack to the heap), other
+    /// crates may.
+    ///
+    /// This limit is not checked until the entire Ast is parsed. Therefore,
+    /// if callers want to put a limit on the amount of heap space used, then
+    /// they should impose a limit on the length, in bytes, of the concrete
+    /// pattern string. In particular, this is viable since this parser
+    /// implementation will limit itself to heap space proportional to the
+    /// lenth of the pattern string.
+    ///
+    /// Note that a nest limit of `0` will return a nest limit error for most
+    /// patterns but not all. For example, a nest limit of `0` permits `a` but
+    /// not `ab`, since `ab` requires a concatenation, which results in a nest
+    /// depth of `1`. In general, a nest limit is not something that manifests
+    /// in an obvious way in the concrete syntax, therefore, it should not be
+    /// used in a granular way.
+    pub fn nest_limit(&mut self, limit: u32) -> &mut RegexSetBuilder {
+        self.0.nest_limit = limit;
+        self
+    }
+
 }
         }
     }
 }
 
 define_set_builder!(set_bytes, bytes, false);
 define_set_builder!(set_unicode, unicode, true);
diff --git a/third_party/rust/regex/src/re_bytes.rs b/third_party/rust/regex/src/re_bytes.rs
index 8a8550eb6509..8fdb133d4336 100644
--- a/third_party/rust/regex/src/re_bytes.rs
+++ b/third_party/rust/regex/src/re_bytes.rs
@@ -16,17 +16,17 @@ use std::str::FromStr;
 use std::sync::Arc;
 
 use memchr::memchr;
 
 use exec::{Exec, ExecNoSync};
 use expand::expand_bytes;
 use error::Error;
 use re_builder::bytes::RegexBuilder;
-use re_trait::{self, RegularExpression, Locations, SubCapturesPosIter};
+use re_trait::{self, RegularExpression, SubCapturesPosIter};
 
 /// Match represents a single match of a regex in a haystack.
 ///
 /// The lifetime parameter `'t` refers to the lifetime of the matched text.
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub struct Match<'t> {
     text: &'t [u8],
     start: usize,
@@ -204,19 +204,19 @@ impl Regex {
     /// year separately.
     ///
     /// ```rust
     /// # extern crate regex; use regex::bytes::Regex;
     /// # fn main() {
     /// let re = Regex::new(r"'([^']+)'\s+\((\d{4})\)").unwrap();
     /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
     /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(&caps[1], &b"Citizen Kane"[..]);
-    /// assert_eq!(&caps[2], &b"1941"[..]);
-    /// assert_eq!(&caps[0], &b"'Citizen Kane' (1941)"[..]);
+    /// assert_eq!(caps.get(1).unwrap().as_bytes(), &b"Citizen Kane"[..]);
+    /// assert_eq!(caps.get(2).unwrap().as_bytes(), &b"1941"[..]);
+    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
     /// // You can also access the groups by index using the Index notation.
     /// // Note that this will panic on an invalid index.
     /// assert_eq!(&caps[1], b"Citizen Kane");
     /// assert_eq!(&caps[2], b"1941");
     /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
     /// # }
     /// ```
     ///
@@ -227,40 +227,40 @@ impl Regex {
     ///
     /// ```rust
     /// # extern crate regex; use regex::bytes::Regex;
     /// # fn main() {
     /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
     ///                .unwrap();
     /// let text = b"Not my favorite movie: 'Citizen Kane' (1941).";
     /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(&caps["title"], &b"Citizen Kane"[..]);
-    /// assert_eq!(&caps["year"], &b"1941"[..]);
-    /// assert_eq!(&caps[0], &b"'Citizen Kane' (1941)"[..]);
+    /// assert_eq!(caps.name("title").unwrap().as_bytes(), b"Citizen Kane");
+    /// assert_eq!(caps.name("year").unwrap().as_bytes(), b"1941");
+    /// assert_eq!(caps.get(0).unwrap().as_bytes(), &b"'Citizen Kane' (1941)"[..]);
     /// // You can also access the groups by name using the Index notation.
     /// // Note that this will panic on an invalid group name.
     /// assert_eq!(&caps["title"], b"Citizen Kane");
     /// assert_eq!(&caps["year"], b"1941");
     /// assert_eq!(&caps[0], b"'Citizen Kane' (1941)");
     ///
     /// # }
     /// ```
     ///
     /// Here we name the capture groups, which we can access with the `name`
     /// method or the `Index` notation with a `&str`. Note that the named
     /// capture groups are still accessible with `get` or the `Index` notation
     /// with a `usize`.
     ///
     /// The `0`th capture group is always unnamed, so it must always be
-    /// accessed with `at(0)` or `[0]`.
+    /// accessed with `get(0)` or `[0]`.
     pub fn captures<'t>(&self, text: &'t [u8]) -> Option<Captures<'t>> {
-        let mut locs = self.locations();
-        self.read_captures_at(&mut locs, text, 0).map(|_| Captures {
+        let mut locs = self.capture_locations();
+        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
             text: text,
-            locs: locs,
+            locs: locs.0,
             named_groups: self.0.capture_name_idx().clone(),
         })
     }
 
     /// Returns an iterator over all the non-overlapping capture groups matched
     /// in `text`. This is operationally the same as `find_iter`, except it
     /// yields information about capturing group matches.
     ///
@@ -489,29 +489,30 @@ impl Regex {
     /// capturing group matches in the replacement text.
     pub fn replacen<'t, R: Replacer>(
         &self,
         text: &'t [u8],
         limit: usize,
         mut rep: R,
     ) -> Cow<'t, [u8]> {
         if let Some(rep) = rep.no_expansion() {
+            let mut it = self.find_iter(text).enumerate().peekable();
+            if it.peek().is_none() {
+                return Cow::Borrowed(text);
+            }
             let mut new = Vec::with_capacity(text.len());
             let mut last_match = 0;
-            for (i, m) in self.find_iter(text).enumerate() {
+            for (i, m) in it {
                 if limit > 0 && i >= limit {
                     break
                 }
                 new.extend_from_slice(&text[last_match..m.start()]);
                 new.extend_from_slice(&rep);
                 last_match = m.end();
             }
-            if last_match == 0 {
-                return Cow::Borrowed(text);
-            }
             new.extend_from_slice(&text[last_match..]);
             return Cow::Owned(new);
         }
 
         // The slower path, which we use if the replacement needs access to
         // capture groups.
         let mut it = self.captures_iter(text).enumerate().peekable();
         if it.peek().is_none() {
@@ -562,67 +563,98 @@ impl Regex {
     }
 
     /// Returns the same as shortest_match, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn shortest_match_at(
         &self,
         text: &[u8],
         start: usize,
     ) -> Option<usize> {
         self.0.searcher().shortest_match_at(text, start)
     }
 
     /// Returns the same as is_match, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn is_match_at(&self, text: &[u8], start: usize) -> bool {
         self.shortest_match_at(text, start).is_some()
     }
 
     /// Returns the same as find, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn find_at<'t>(
         &self,
         text: &'t [u8],
         start: usize,
     ) -> Option<Match<'t>> {
         self.0.searcher().find_at(text, start)
             .map(|(s, e)| Match::new(text, s, e))
     }
 
-    /// Returns the same as captures, but starts the search at the given
+    /// This is like `captures`, but uses
+    /// [`CaptureLocations`](struct.CaptureLocations.html)
+    /// instead of
+    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
+    ///
+    /// To create a `CaptureLocations` value, use the
+    /// `Regex::capture_locations` method.
+    ///
+    /// This returns the overall match if this was successful, which is always
+    /// equivalence to the `0`th capture group.
+    pub fn captures_read<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t [u8],
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, 0)
+    }
+
+    /// Returns the same as `captures_read`, but starts the search at the given
     /// offset and populates the capture locations given.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
+    pub fn captures_read_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t [u8],
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher()
+            .captures_read_at(&mut locs.0, text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// An undocumented alias for `captures_read_at`.
+    ///
+    /// The `regex-capi` crate previously used this routine, so to avoid
+    /// breaking that crate, we continue to provide the name as an undocumented
+    /// alias.
     #[doc(hidden)]
     pub fn read_captures_at<'t>(
         &self,
-        locs: &mut Locations,
+        locs: &mut CaptureLocations,
         text: &'t [u8],
         start: usize,
     ) -> Option<Match<'t>> {
-        self.0.searcher().read_captures_at(locs, text, start)
-            .map(|(s, e)| Match::new(text, s, e))
+        self.captures_read_at(locs, text, start)
     }
 }
 
 /// Auxiliary methods.
 impl Regex {
     /// Returns the original string of this regex.
     pub fn as_str(&self) -> &str {
         &self.0.regex_strings()[0]
@@ -633,21 +665,29 @@ impl Regex {
         CaptureNames(self.0.capture_names().iter())
     }
 
     /// Returns the number of captures.
     pub fn captures_len(&self) -> usize {
         self.0.capture_names().len()
     }
 
-    /// Returns an empty set of locations that can be reused in multiple calls
-    /// to `read_captures`.
+    /// Returns an empty set of capture locations that can be reused in
+    /// multiple calls to `captures_read` or `captures_read_at`.
+    pub fn capture_locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher().locations())
+    }
+
+    /// An alias for `capture_locations` to preserve backward compatibility.
+    ///
+    /// The `regex-capi` crate uses this method, so to avoid breaking that
+    /// crate, we continue to export it as an undocumented API.
     #[doc(hidden)]
-    pub fn locations(&self) -> Locations {
-        self.0.searcher().locations()
+    pub fn locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher().locations())
     }
 }
 
 /// An iterator over all non-overlapping matches for a particular string.
 ///
 /// The iterator yields a tuple of integers corresponding to the start and end
 /// of the match. The indices are byte offsets. The iterator stops when no more
 /// matches can be found.
@@ -763,30 +803,87 @@ impl<'r> Iterator for CaptureNames<'r> {
             .map(|slot| slot.as_ref().map(|name| name.as_ref()))
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
 }
 
+/// CaptureLocations is a low level representation of the raw offsets of each
+/// submatch.
+///
+/// You can think of this as a lower level
+/// [`Captures`](struct.Captures.html), where this type does not support
+/// named capturing groups directly and it does not borrow the text that these
+/// offsets were matched on.
+///
+/// Primarily, this type is useful when using the lower level `Regex` APIs
+/// such as `read_captures`, which permits amortizing the allocation in which
+/// capture match locations are stored.
+///
+/// In order to build a value of this type, you'll need to call the
+/// `capture_locations` method on the `Regex` being used to execute the search.
+/// The value returned can then be reused in subsequent searches.
+#[derive(Clone, Debug)]
+pub struct CaptureLocations(re_trait::Locations);
+
+/// A type alias for `CaptureLocations` for backwards compatibility.
+///
+/// Previously, we exported `CaptureLocations` as `Locations` in an
+/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
+/// we continue re-exporting the same undocumented API.
+#[doc(hidden)]
+pub type Locations = CaptureLocations;
+
+impl CaptureLocations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    #[inline]
+    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
+        self.0.pos(i)
+    }
+
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    /// An alias for the `get` method for backwards compatibility.
+    ///
+    /// Previously, we exported `get` as `pos` in an undocumented API. To
+    /// prevent breaking that code (e.g., in `regex-capi`), we continue
+    /// re-exporting the same undocumented API.
+    #[doc(hidden)]
+    #[inline]
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        self.get(i)
+    }
+}
+
 /// Captures represents a group of captured byte strings for a single match.
 ///
 /// The 0th capture always corresponds to the entire match. Each subsequent
 /// index corresponds to the next capture group in the regex. If a capture
 /// group is named, then the matched byte string is *also* available via the
 /// `name` method. (Note that the 0th capture is always unnamed and so must be
 /// accessed with the `get` method.)
 ///
 /// Positions returned from a capture group are always byte indices.
 ///
 /// `'t` is the lifetime of the matched text.
 pub struct Captures<'t> {
     text: &'t [u8],
-    locs: Locations,
+    locs: re_trait::Locations,
     named_groups: Arc<HashMap<String, usize>>,
 }
 
 impl<'t> Captures<'t> {
     /// Returns the match associated with the capture group at index `i`. If
     /// `i` does not correspond to a capture group, or if the capture group
     /// did not participate in the match, then `None` is returned.
     ///
@@ -822,18 +919,18 @@ impl<'t> Captures<'t> {
     /// The first match always corresponds to the overall match of the regex.
     pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
         SubCaptureMatches {
             caps: self,
             it: self.locs.iter(),
         }
     }
 
-    /// Expands all instances of `$name` in `text` to the corresponding capture
-    /// group `name`, and writes them to the `dst` buffer given.
+    /// Expands all instances of `$name` in `replacement` to the corresponding
+    /// capture group `name`, and writes them to the `dst` buffer given.
     ///
     /// `name` may be an integer corresponding to the index of the
     /// capture group (counted by order of opening parenthesis where `0` is the
     /// entire match) or it can be a name (consisting of letters, digits or
     /// underscores) corresponding to a named capture group.
     ///
     /// If `name` isn't a valid capture group (whether the name doesn't exist
     /// or isn't a valid index), then it is replaced with the empty string.
@@ -884,17 +981,17 @@ impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
 
         // We'd like to show something nice here, even if it means an
         // allocation to build a reverse index.
         let slot_to_name: HashMap<&usize, &String> =
             self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
         let mut map = f.debug_map();
         for (slot, m) in self.0.locs.iter().enumerate() {
             let m = m.map(|(s, e)| escape_bytes(&self.0.text[s..e]));
-            if let Some(ref name) = slot_to_name.get(&slot) {
+            if let Some(name) = slot_to_name.get(&slot) {
                 map.entry(&name, &m);
             } else {
                 map.entry(&slot, &m);
             }
         }
         map.finish()
     }
 }
@@ -963,17 +1060,18 @@ impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
     }
 }
 
 /// Replacer describes types that can be used to replace matches in a byte
 /// string.
 ///
 /// In general, users of this crate shouldn't need to implement this trait,
 /// since implementations are already provided for `&[u8]` and
-/// `FnMut(&Captures) -> Vec<u8>`, which covers most use cases.
+/// `FnMut(&Captures) -> Vec<u8>` (or any `FnMut(&Captures) -> T`
+/// where `T: AsRef<[u8]>`), which covers most use cases.
 pub trait Replacer {
     /// Appends text to `dst` to replace the current match.
     ///
     /// The current match is represented by `caps`, which is guaranteed to
     /// have a match at capture group `0`.
     ///
     /// For example, a no-op replacement would be
     /// `dst.extend(&caps[0])`.
@@ -984,48 +1082,88 @@ pub trait Replacer {
     /// When doing replacements, if access to `Captures` is not needed (e.g.,
     /// the replacement byte string does not need `$` expansion), then it can
     /// be beneficial to avoid finding sub-captures.
     ///
     /// In general, this is called once for every call to `replacen`.
     fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
         None
     }
+
+    /// Return a `Replacer` that borrows and wraps this `Replacer`.
+    ///
+    /// This is useful when you want to take a generic `Replacer` (which might
+    /// not be cloneable) and use it without consuming it, so it can be used
+    /// more than once.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use regex::bytes::{Regex, Replacer};
+    ///
+    /// fn replace_all_twice<R: Replacer>(
+    ///     re: Regex,
+    ///     src: &[u8],
+    ///     mut rep: R,
+    /// ) -> Vec<u8> {
+    ///     let dst = re.replace_all(src, rep.by_ref());
+    ///     let dst = re.replace_all(&dst, rep.by_ref());
+    ///     dst.into_owned()
+    /// }
+    /// ```
+    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
+        ReplacerRef(self)
+    }
+}
+
+/// By-reference adaptor for a `Replacer`
+///
+/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
+#[derive(Debug)]
+pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
+
+impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
+        self.0.replace_append(caps, dst)
+    }
+    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+        self.0.no_expansion()
+    }
 }
 
 impl<'a> Replacer for &'a [u8] {
     fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
         caps.expand(*self, dst);
     }
 
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
         match memchr(b'$', *self) {
             Some(_) => None,
             None => Some(Cow::Borrowed(*self)),
         }
     }
 }
 
-impl<F> Replacer for F where F: FnMut(&Captures) -> Vec<u8> {
+impl<F, T> Replacer for F where F: FnMut(&Captures) -> T, T: AsRef<[u8]> {
     fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
-        dst.extend_from_slice(&(*self)(caps));
+        dst.extend_from_slice((*self)(caps).as_ref());
     }
 }
 
-/// NoExpand indicates literal byte string replacement.
+/// `NoExpand` indicates literal byte string replacement.
 ///
 /// It can be used with `replace` and `replace_all` to do a literal byte string
 /// replacement without expanding `$name` to their corresponding capture
 /// groups. This can be both convenient (to avoid escaping `$`, for example)
 /// and performant (since capture groups don't need to be found).
 ///
 /// `'t` is the lifetime of the literal text.
 pub struct NoExpand<'t>(pub &'t [u8]);
 
 impl<'t> Replacer for NoExpand<'t> {
     fn replace_append(&mut self, _: &Captures, dst: &mut Vec<u8>) {
         dst.extend_from_slice(self.0);
     }
 
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
+    fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
         Some(Cow::Borrowed(self.0))
     }
 }
diff --git a/third_party/rust/regex/src/re_set.rs b/third_party/rust/regex/src/re_set.rs
index 89a7a8082806..cfca0ea40595 100644
--- a/third_party/rust/regex/src/re_set.rs
+++ b/third_party/rust/regex/src/re_set.rs
@@ -244,16 +244,20 @@ impl SetMatches {
     }
 
     /// The total number of regexes in the set that created these matches.
     pub fn len(&self) -> usize {
         self.matches.len()
     }
 
     /// Returns an iterator over indexes in the regex that matched.
+    ///
+    /// This will always produces matches in ascending order of index, where
+    /// the index corresponds to the index of the regex that matched with
+    /// respect to its position when initially building the set.
     pub fn iter(&self) -> SetMatchesIter {
         SetMatchesIter((&*self.matches).into_iter().enumerate())
     }
 }
 
 impl IntoIterator for SetMatches {
     type IntoIter = SetMatchesIntoIter;
     type Item = usize;
@@ -268,30 +272,38 @@ impl<'a> IntoIterator for &'a SetMatches {
     type Item = usize;
 
     fn into_iter(self) -> Self::IntoIter {
         self.iter()
     }
 }
 
 /// An owned iterator over the set of matches from a regex set.
+///
+/// This will always produces matches in ascending order of index, where the
+/// index corresponds to the index of the regex that matched with respect to
+/// its position when initially building the set.
 pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);
 
 impl Iterator for SetMatchesIntoIter {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
         loop {
             match self.0.next() {
                 None => return None,
                 Some((_, false)) => {}
                 Some((i, true)) => return Some(i),
             }
         }
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint() 
+    }
 }
 
 impl DoubleEndedIterator for SetMatchesIntoIter {
     fn next_back(&mut self) -> Option<usize> {
         loop {
             match self.0.next_back() {
                 None => return None,
                 Some((_, false)) => {}
@@ -299,31 +311,39 @@ impl DoubleEndedIterator for SetMatchesIntoIter {
             }
         }
     }
 }
 
 /// A borrowed iterator over the set of matches from a regex set.
 ///
 /// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
+///
+/// This will always produces matches in ascending order of index, where the
+/// index corresponds to the index of the regex that matched with respect to
+/// its position when initially building the set.
 #[derive(Clone)]
 pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);
 
 impl<'a> Iterator for SetMatchesIter<'a> {
     type Item = usize;
 
     fn next(&mut self) -> Option<usize> {
         loop {
             match self.0.next() {
                 None => return None,
                 Some((_, &false)) => {}
                 Some((i, &true)) => return Some(i),
             }
         }
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint() 
+    }
 }
 
 impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
     fn next_back(&mut self) -> Option<usize> {
         loop {
             match self.0.next_back() {
                 None => return None,
                 Some((_, &false)) => {}
diff --git a/third_party/rust/regex/src/re_trait.rs b/third_party/rust/regex/src/re_trait.rs
index 9f3407c98b08..81a64bb252ce 100644
--- a/third_party/rust/regex/src/re_trait.rs
+++ b/third_party/rust/regex/src/re_trait.rs
@@ -13,16 +13,17 @@
 /// of the capture).
 pub type Slot = Option<usize>;
 
 /// Locations represents the offsets of each capturing group in a regex for
 /// a single match.
 ///
 /// Unlike `Captures`, a `Locations` value only stores offsets.
 #[doc(hidden)]
+#[derive(Clone, Debug)]
 pub struct Locations(Vec<Slot>);
 
 impl Locations {
     /// Returns the start and end positions of the Nth capture group. Returns
     /// `None` if `i` is not a valid capture group or if the capture group did
     /// not match anything. The positions returned are *always* byte indices
     /// with respect to the original string matched.
     pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
@@ -32,32 +33,31 @@ impl Locations {
             _ => None,
         }
     }
 
     /// Creates an iterator of all the capture group positions in order of
     /// appearance in the regular expression. Positions are byte indices
     /// in terms of the original string matched.
     pub fn iter(&self) -> SubCapturesPosIter {
-        SubCapturesPosIter { idx: 0, locs: &self }
+        SubCapturesPosIter { idx: 0, locs: self }
     }
 
     /// Returns the total number of capturing groups.
     ///
     /// This is always at least `1` since every regex has at least `1`
     /// capturing group that corresponds to the entire match.
     pub fn len(&self) -> usize {
         self.0.len() / 2
     }
-}
 
-/// This is a hack to make Locations -> &mut [Slot] be available internally
-/// without exposing it in the public API.
-pub fn as_slots(locs: &mut Locations) -> &mut [Slot] {
-    &mut locs.0
+    /// Return the individual slots as a slice.
+    pub(crate) fn as_slots(&mut self) -> &mut [Slot] {
+        &mut self.0
+    }
 }
 
 /// An iterator over capture group positions for a particular match of a
 /// regular expression.
 ///
 /// Positions are byte indices in terms of the original string matched.
 ///
 /// `'c` is the lifetime of the captures.
@@ -79,17 +79,17 @@ impl<'c> Iterator for SubCapturesPosIter<'c> {
                 Some(Some((s, e)))
             }
         };
         self.idx += 1;
         x
     }
 }
 
-/// RegularExpression describes types that can implement regex searching.
+/// `RegularExpression` describes types that can implement regex searching.
 ///
 /// This trait is my attempt at reducing code duplication and to standardize
 /// the internal API. Specific duplication that is avoided are the `find`
 /// and `capture` iterators, which are slightly tricky.
 ///
 /// It's not clear whether this trait is worth it, and it also isn't
 /// clear whether it's useful as a public trait or not. Methods like
 /// `next_after_empty` reak of bad design, but the rest of the methods seem
@@ -134,43 +134,43 @@ pub trait RegularExpression: Sized {
     fn find_at(
         &self,
         text: &Self::Text,
         start: usize,
     ) -> Option<(usize, usize)>;
 
     /// Returns the leftmost-first match location if one exists, and also
     /// fills in any matching capture slot locations.
-    fn read_captures_at(
+    fn captures_read_at(
         &self,
         locs: &mut Locations,
         text: &Self::Text,
         start: usize,
     ) -> Option<(usize, usize)>;
 
     /// Returns an iterator over all non-overlapping successive leftmost-first
     /// matches.
-    fn find_iter<'t>(
+    fn find_iter (
         self,
-        text: &'t Self::Text,
-    ) -> Matches<'t, Self> {
+        text: &Self::Text,
+    ) -> Matches<Self> {
         Matches {
             re: self,
             text: text,
             last_end: 0,
             last_match: None,
         }
     }
 
     /// Returns an iterator over all non-overlapping successive leftmost-first
     /// matches with captures.
-    fn captures_iter<'t>(
+    fn captures_iter(
         self,
-        text: &'t Self::Text,
-    ) -> CaptureMatches<'t, Self> {
+        text: &Self::Text,
+    ) -> CaptureMatches<Self> {
         CaptureMatches(self.find_iter(text))
     }
 }
 
 /// An iterator over all non-overlapping successive leftmost-first matches.
 pub struct Matches<'t, R> where R: RegularExpression, R::Text: 't {
     re: R,
     text: &'t R::Text,
@@ -201,17 +201,17 @@ impl<'t, R> Iterator for Matches<'t, R>
         let (s, e) = match self.re.find_at(self.text, self.last_end) {
             None => return None,
             Some((s, e)) => (s, e),
         };
         if s == e {
             // This is an empty match. To ensure we make progress, start
             // the next search at the smallest possible starting position
             // of the next match following this one.
-            self.last_end = self.re.next_after_empty(&self.text, e);
+            self.last_end = self.re.next_after_empty(self.text, e);
             // Don't accept empty matches immediately following a match.
             // Just move on to the next match.
             if Some(e) == self.last_match {
                 return self.next();
             }
         } else {
             self.last_end = e;
         }
@@ -241,26 +241,26 @@ impl<'t, R> Iterator for CaptureMatches<'t, R>
         where R: RegularExpression, R::Text: 't + AsRef<[u8]> {
     type Item = Locations;
 
     fn next(&mut self) -> Option<Locations> {
         if self.0.last_end > self.0.text.as_ref().len() {
             return None
         }
         let mut locs = self.0.re.locations();
-        let (s, e) = match self.0.re.read_captures_at(
+        let (s, e) = match self.0.re.captures_read_at(
             &mut locs,
             self.0.text,
             self.0.last_end,
         ) {
             None => return None,
             Some((s, e)) => (s, e),
         };
         if s == e {
-            self.0.last_end = self.0.re.next_after_empty(&self.0.text, e);
+            self.0.last_end = self.0.re.next_after_empty(self.0.text, e);
             if Some(e) == self.0.last_match {
                 return self.next();
             }
         } else {
             self.0.last_end = e;
         }
         self.0.last_match = Some(e);
         Some(locs)
diff --git a/third_party/rust/regex/src/re_unicode.rs b/third_party/rust/regex/src/re_unicode.rs
index d90be4fb1c9f..f71e7f50309f 100644
--- a/third_party/rust/regex/src/re_unicode.rs
+++ b/third_party/rust/regex/src/re_unicode.rs
@@ -17,18 +17,17 @@ use std::sync::Arc;
 
 use memchr::memchr;
 use syntax;
 
 use error::Error;
 use exec::{Exec, ExecNoSyncStr};
 use expand::expand_str;
 use re_builder::unicode::RegexBuilder;
-use re_plugin::Plugin;
-use re_trait::{self, RegularExpression, Locations, SubCapturesPosIter};
+use re_trait::{self, RegularExpression, SubCapturesPosIter};
 
 /// Escapes all regular expression meta characters in `text`.
 ///
 /// The string returned may be safely used as a literal in a regular
 /// expression.
 pub fn escape(text: &str) -> String {
     syntax::escape(text)
 }
@@ -68,16 +67,22 @@ impl<'t> Match<'t> {
         Match {
             text: haystack,
             start: start,
             end: end,
         }
     }
 }
 
+impl<'t> From<Match<'t>> for &'t str {
+    fn from(m: Match<'t>) -> &'t str {
+        m.as_str()
+    }
+}
+
 /// A compiled regular expression for matching Unicode strings.
 ///
 /// It is represented as either a sequence of bytecode instructions (dynamic)
 /// or as a specialized Rust function (native). It can be used to search, split
 /// or replace text. All searching is done with an implicit `.*?` at the
 /// beginning and end of an expression. To force an expression to match the
 /// whole string (or a prefix or a suffix), you must use an anchor like `^` or
 /// `$` (or `\A` and `\z`).
@@ -124,31 +129,17 @@ impl<'t> Match<'t> {
 ///
 /// assert!(haystack.contains(&re));
 /// assert_eq!(haystack.find(&re), Some(1));
 /// assert_eq!(haystack.match_indices(&re).collect::<Vec<_>>(),
 ///            vec![(1, 4), (5, 8)]);
 /// assert_eq!(haystack.split(&re).collect::<Vec<_>>(), vec!["a", "b", "c"]);
 /// ```
 #[derive(Clone)]
-pub struct Regex(#[doc(hidden)] pub _Regex);
-
-#[derive(Clone)]
-#[doc(hidden)]
-pub enum _Regex {
-    // The representation of `Regex` is exported to support the `regex!`
-    // syntax extension. Do not rely on it.
-    //
-    // See the comments for the `internal` module in `lib.rs` for a more
-    // detailed explanation for what `regex!` requires.
-    #[doc(hidden)]
-    Dynamic(Exec),
-    #[doc(hidden)]
-    Plugin(Plugin),
-}
+pub struct Regex(Exec);
 
 impl fmt::Display for Regex {
     /// Shows the original regular expression.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.as_str())
     }
 }
 
@@ -157,17 +148,17 @@ impl fmt::Debug for Regex {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(self, f)
     }
 }
 
 #[doc(hidden)]
 impl From<Exec> for Regex {
     fn from(exec: Exec) -> Regex {
-        Regex(_Regex::Dynamic(exec))
+        Regex(exec)
     }
 }
 
 impl FromStr for Regex {
     type Err = Error;
 
     /// Attempts to parse a string into a regular expression
     fn from_str(s: &str) -> Result<Regex, Error> {
@@ -246,26 +237,17 @@ impl Regex {
     /// # fn main() {
     /// let text = "Retroactively relinquishing remunerations is reprehensible.";
     /// for mat in Regex::new(r"\b\w{13}\b").unwrap().find_iter(text) {
     ///     println!("{:?}", mat);
     /// }
     /// # }
     /// ```
     pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> Matches<'r, 't> {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                let it = exec.searcher_str().find_iter(text);
-                Matches(MatchesInner::Dynamic(it))
-            }
-            _Regex::Plugin(ref plug) => {
-                let it = plug.find_iter(text);
-                Matches(MatchesInner::Plugin(it))
-            }
-        }
+        Matches(self.0.searcher_str().find_iter(text))
     }
 
     /// Returns the capture groups corresponding to the leftmost-first
     /// match in `text`. Capture group `0` always corresponds to the entire
     /// match. If no match is found, then `None` is returned.
     ///
     /// You should only use `captures` if you need access to the location of
     /// capturing group matches. Otherwise, `find` is faster for discovering
@@ -302,41 +284,41 @@ impl Regex {
     ///
     /// ```rust
     /// # extern crate regex; use regex::Regex;
     /// # fn main() {
     /// let re = Regex::new(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)")
     ///                .unwrap();
     /// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
     /// let caps = re.captures(text).unwrap();
-    /// assert_eq!(&caps["title"], "Citizen Kane");
-    /// assert_eq!(&caps["year"], "1941");
+    /// assert_eq!(caps.name("title").unwrap().as_str(), "Citizen Kane");
+    /// assert_eq!(caps.name("year").unwrap().as_str(), "1941");
     /// assert_eq!(caps.get(0).unwrap().as_str(), "'Citizen Kane' (1941)");
     /// // You can also access the groups by name using the Index notation.
     /// // Note that this will panic on an invalid group name.
     /// assert_eq!(&caps["title"], "Citizen Kane");
     /// assert_eq!(&caps["year"], "1941");
     /// assert_eq!(&caps[0], "'Citizen Kane' (1941)");
     ///
     /// # }
     /// ```
     ///
     /// Here we name the capture groups, which we can access with the `name`
     /// method or the `Index` notation with a `&str`. Note that the named
     /// capture groups are still accessible with `get` or the `Index` notation
     /// with a `usize`.
     ///
     /// The `0`th capture group is always unnamed, so it must always be
-    /// accessed with `at(0)` or `[0]`.
+    /// accessed with `get(0)` or `[0]`.
     pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {
-        let mut locs = self.locations();
-        self.read_captures_at(&mut locs, text, 0).map(|_| Captures {
+        let mut locs = self.capture_locations();
+        self.captures_read_at(&mut locs, text, 0).map(move |_| Captures {
             text: text,
-            locs: locs,
-            named_groups: NamedGroups::from_regex(self)
+            locs: locs.0,
+            named_groups: self.0.capture_name_idx().clone(),
         })
     }
 
     /// Returns an iterator over all the non-overlapping capture groups matched
     /// in `text`. This is operationally the same as `find_iter`, except it
     /// yields information about capturing group matches.
     ///
     /// # Example
@@ -359,26 +341,17 @@ impl Regex {
     /// // Movie: The Wizard of Oz, Released: 1939
     /// // Movie: M, Released: 1931
     /// # }
     /// ```
     pub fn captures_iter<'r, 't>(
         &'r self,
         text: &'t str,
     ) -> CaptureMatches<'r, 't> {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                let it = exec.searcher_str().captures_iter(text);
-                CaptureMatches(CaptureMatchesInner::Dynamic(it))
-            }
-            _Regex::Plugin(ref plug) => {
-                let it = plug.captures_iter(text);
-                CaptureMatches(CaptureMatchesInner::Plugin(it))
-            }
-        }
+        CaptureMatches(self.0.searcher_str().captures_iter(text))
     }
 
     /// Returns an iterator of substrings of `text` delimited by a match of the
     /// regular expression. Namely, each element of the iterator corresponds to
     /// text that *isn't* matched by the regular expression.
     ///
     /// This method will *not* copy the text given.
     ///
@@ -572,29 +545,30 @@ impl Regex {
         // difference:
         //
         //   1) We use `find_iter` instead of `captures_iter`. Not asking for
         //      captures generally makes the regex engines faster.
         //   2) We don't need to look up all of the capture groups and do
         //      replacements inside the replacement string. We just push it
         //      at each match and be done with it.
         if let Some(rep) = rep.no_expansion() {
+            let mut it = self.find_iter(text).enumerate().peekable();
+            if it.peek().is_none() {
+                return Cow::Borrowed(text);
+            }
             let mut new = String::with_capacity(text.len());
             let mut last_match = 0;
-            for (i, m) in self.find_iter(text).enumerate() {
+            for (i, m) in it {
                 if limit > 0 && i >= limit {
                     break
                 }
                 new.push_str(&text[last_match..m.start()]);
                 new.push_str(&rep);
                 last_match = m.end();
             }
-            if last_match == 0 {
-                return Cow::Borrowed(text);
-            }
             new.push_str(&text[last_match..]);
             return Cow::Owned(new);
         }
 
         // The slower path, which we use if the replacement needs access to
         // capture groups.
         let mut it = self.captures_iter(text).enumerate().peekable();
         if it.peek().is_none() {
@@ -645,179 +619,172 @@ impl Regex {
     }
 
     /// Returns the same as shortest_match, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn shortest_match_at(
         &self,
         text: &str,
         start: usize,
     ) -> Option<usize> {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                exec.searcher_str().shortest_match_at(text, start)
-            }
-            _Regex::Plugin(ref plug) => plug.shortest_match_at(text, start),
-        }
+        self.0.searcher_str().shortest_match_at(text, start)
     }
 
     /// Returns the same as is_match, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn is_match_at(&self, text: &str, start: usize) -> bool {
         self.shortest_match_at(text, start).is_some()
     }
 
     /// Returns the same as find, but starts the search at the given
     /// offset.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
-    #[doc(hidden)]
     pub fn find_at<'t>(
         &self,
         text: &'t str,
         start: usize,
     ) -> Option<Match<'t>> {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                exec.searcher_str().find_at(text, start).map(|(s, e)| {
-                    Match::new(text, s, e)
-                })
-            }
-            _Regex::Plugin(ref plug) => {
-                plug.find_at(text, start).map(|(s, e)| Match::new(text, s, e))
-            }
-        }
+        self.0.searcher_str().find_at(text, start).map(|(s, e)| {
+            Match::new(text, s, e)
+        })
+    }
+
+    /// This is like `captures`, but uses
+    /// [`CaptureLocations`](struct.CaptureLocations.html)
+    /// instead of
+    /// [`Captures`](struct.Captures.html) in order to amortize allocations.
+    ///
+    /// To create a `CaptureLocations` value, use the
+    /// `Regex::capture_locations` method.
+    ///
+    /// This returns the overall match if this was successful, which is always
+    /// equivalence to the `0`th capture group.
+    pub fn captures_read<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t str,
+    ) -> Option<Match<'t>> {
+        self.captures_read_at(locs, text, 0)
     }
 
     /// Returns the same as captures, but starts the search at the given
     /// offset and populates the capture locations given.
     ///
     /// The significance of the starting point is that it takes the surrounding
     /// context into consideration. For example, the `\A` anchor can only
     /// match when `start == 0`.
+    pub fn captures_read_at<'t>(
+        &self,
+        locs: &mut CaptureLocations,
+        text: &'t str,
+        start: usize,
+    ) -> Option<Match<'t>> {
+        self.0
+            .searcher_str()
+            .captures_read_at(&mut locs.0, text, start)
+            .map(|(s, e)| Match::new(text, s, e))
+    }
+
+    /// An undocumented alias for `captures_read_at`.
+    ///
+    /// The `regex-capi` crate previously used this routine, so to avoid
+    /// breaking that crate, we continue to provide the name as an undocumented
+    /// alias.
     #[doc(hidden)]
     pub fn read_captures_at<'t>(
         &self,
-        locs: &mut Locations,
+        locs: &mut CaptureLocations,
         text: &'t str,
         start: usize,
     ) -> Option<Match<'t>> {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                exec.searcher_str().read_captures_at(locs, text, start)
-                    .map(|(s, e)| Match::new(text, s, e))
-            }
-            _Regex::Plugin(ref plug) => {
-                plug.read_captures_at(locs, text, start)
-                    .map(|(s, e)| Match::new(text, s, e))
-            }
-        }
+        self.captures_read_at(locs, text, start)
     }
 }
 
 /// Auxiliary methods.
 impl Regex {
     /// Returns the original string of this regex.
     pub fn as_str(&self) -> &str {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => &exec.regex_strings()[0],
-            _Regex::Plugin(ref plug) => &plug.original,
-        }
+        &self.0.regex_strings()[0]
     }
 
     /// Returns an iterator over the capture names.
     pub fn capture_names(&self) -> CaptureNames {
-        CaptureNames(match self.0 {
-            _Regex::Plugin(ref n) => _CaptureNames::Plugin(n.names.iter()),
-            _Regex::Dynamic(ref d) => {
-                _CaptureNames::Dynamic(d.capture_names().iter())
-            }
-        })
+        CaptureNames(self.0.capture_names().iter())
     }
 
     /// Returns the number of captures.
     pub fn captures_len(&self) -> usize {
-        match self.0 {
-            _Regex::Plugin(ref n) => n.names.len(),
-            _Regex::Dynamic(ref d) => d.capture_names().len()
-        }
+        self.0.capture_names().len()
     }
 
-    /// Returns an empty set of locations that can be reused in multiple calls
-    /// to `read_captures`.
+    /// Returns an empty set of capture locations that can be reused in
+    /// multiple calls to `captures_read` or `captures_read_at`.
+    pub fn capture_locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher_str().locations())
+    }
+
+    /// An alias for `capture_locations` to preserve backward compatibility.
+    ///
+    /// The `regex-capi` crate uses this method, so to avoid breaking that
+    /// crate, we continue to export it as an undocumented API.
     #[doc(hidden)]
-    pub fn locations(&self) -> Locations {
-        match self.0 {
-            _Regex::Dynamic(ref exec) => {
-                exec.searcher_str().locations()
-            }
-            _Regex::Plugin(ref plug) => plug.locations(),
-        }
+    pub fn locations(&self) -> CaptureLocations {
+        CaptureLocations(self.0.searcher_str().locations())
     }
 }
 
 /// An iterator over the names of all possible captures.
 ///
 /// `None` indicates an unnamed capture; the first element (capture 0, the
 /// whole matched region) is always unnamed.
 ///
 /// `'r` is the lifetime of the compiled regular expression.
-pub struct CaptureNames<'r>(_CaptureNames<'r>);
-
-enum _CaptureNames<'r> {
-    Plugin(::std::slice::Iter<'r, Option<&'static str>>),
-    Dynamic(::std::slice::Iter<'r, Option<String>>)
-}
+pub struct CaptureNames<'r>(::std::slice::Iter<'r, Option<String>>);
 
 impl<'r> Iterator for CaptureNames<'r> {
     type Item = Option<&'r str>;
 
     fn next(&mut self) -> Option<Option<&'r str>> {
-        match self.0 {
-            _CaptureNames::Plugin(ref mut i) => i.next().cloned(),
-            _CaptureNames::Dynamic(ref mut i) => {
-                i.next().as_ref().map(|o| o.as_ref().map(|s| s.as_ref()))
-            }
-        }
+        self.0
+            .next()
+            .as_ref()
+            .map(|slot| slot.as_ref().map(|name| name.as_ref()))
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        match self.0 {
-            _CaptureNames::Plugin(ref i)  => i.size_hint(),
-            _CaptureNames::Dynamic(ref i) => i.size_hint(),
-        }
+        self.0.size_hint()
     }
 }
 
 /// Yields all substrings delimited by a regular expression match.
 ///
 /// `'r` is the lifetime of the compiled regular expression and `'t` is the
 /// lifetime of the string being split.
 pub struct Split<'r, 't> {
     finder: Matches<'r, 't>,
     last: usize,
 }
 
 impl<'r, 't> Iterator for Split<'r, 't> {
     type Item = &'t str;
 
     fn next(&mut self) -> Option<&'t str> {
-        let text = self.finder.text();
+        let text = self.finder.0.text();
         match self.finder.next() {
             None => {
                 if self.last >= text.len() {
                     None
                 } else {
                     let s = &text[self.last..];
                     self.last = text.len();
                     Some(s)
@@ -847,92 +814,96 @@ impl<'r, 't> Iterator for SplitN<'r, 't> {
     type Item = &'t str;
 
     fn next(&mut self) -> Option<&'t str> {
         if self.n == 0 {
             return None
         }
         self.n -= 1;
         if self.n == 0 {
-            let text = self.splits.finder.text();
+            let text = self.splits.finder.0.text();
             Some(&text[self.splits.last..])
         } else {
             self.splits.next()
         }
     }
 }
 
-enum NamedGroups {
-    Plugin(&'static [(&'static str, usize)]),
-    Dynamic(Arc<HashMap<String, usize>>),
-}
+/// CaptureLocations is a low level representation of the raw offsets of each
+/// submatch.
+///
+/// You can think of this as a lower level
+/// [`Captures`](struct.Captures.html), where this type does not support
+/// named capturing groups directly and it does not borrow the text that these
+/// offsets were matched on.
+///
+/// Primarily, this type is useful when using the lower level `Regex` APIs
+/// such as `read_captures`, which permits amortizing the allocation in which
+/// capture match locations are stored.
+///
+/// In order to build a value of this type, you'll need to call the
+/// `capture_locations` method on the `Regex` being used to execute the search.
+/// The value returned can then be reused in subsequent searches.
+#[derive(Clone, Debug)]
+pub struct CaptureLocations(re_trait::Locations);
 
-impl NamedGroups {
-    fn from_regex(regex: &Regex) -> NamedGroups {
-        match regex.0 {
-            _Regex::Plugin(ref plug) => NamedGroups::Plugin(&plug.groups),
-            _Regex::Dynamic(ref exec) => {
-                NamedGroups::Dynamic(exec.capture_name_idx().clone())
-            }
-        }
-    }
+/// A type alias for `CaptureLocations` for backwards compatibility.
+///
+/// Previously, we exported `CaptureLocations` as `Locations` in an
+/// undocumented API. To prevent breaking that code (e.g., in `regex-capi`),
+/// we continue re-exporting the same undocumented API.
+#[doc(hidden)]
+pub type Locations = CaptureLocations;
 
-    fn pos(&self, name: &str) -> Option<usize> {
-        match *self {
-            NamedGroups::Plugin(groups) => {
-                groups.binary_search_by(|&(n, _)| n.cmp(name))
-                      .ok().map(|i| groups[i].1)
-            },
-            NamedGroups::Dynamic(ref groups) => {
-                groups.get(name).map(|i| *i)
-            },
-        }
+impl CaptureLocations {
+    /// Returns the start and end positions of the Nth capture group. Returns
+    /// `None` if `i` is not a valid capture group or if the capture group did
+    /// not match anything. The positions returned are *always* byte indices
+    /// with respect to the original string matched.
+    #[inline]
+    pub fn get(&self, i: usize) -> Option<(usize, usize)> {
+        self.0.pos(i)
     }
 
-    fn iter<'n>(&'n self) -> NamedGroupsIter<'n> {
-        match *self {
-            NamedGroups::Plugin(g) => NamedGroupsIter::Plugin(g.iter()),
-            NamedGroups::Dynamic(ref g) => NamedGroupsIter::Dynamic(g.iter()),
-        }
+    /// Returns the total number of capturing groups.
+    ///
+    /// This is always at least `1` since every regex has at least `1`
+    /// capturing group that corresponds to the entire match.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.0.len()
     }
-}
-
-enum NamedGroupsIter<'n> {
-    Plugin(::std::slice::Iter<'static, (&'static str, usize)>),
-    Dynamic(::std::collections::hash_map::Iter<'n, String, usize>),
-}
-
-impl<'n> Iterator for NamedGroupsIter<'n> {
-    type Item = (&'n str, usize);
 
-    fn next(&mut self) -> Option<Self::Item> {
-        match *self {
-            NamedGroupsIter::Plugin(ref mut it) => it.next().map(|&v| v),
-            NamedGroupsIter::Dynamic(ref mut it) => {
-                it.next().map(|(s, i)| (s.as_ref(), *i))
-            }
-        }
+    /// An alias for the `get` method for backwards compatibility.
+    ///
+    /// Previously, we exported `get` as `pos` in an undocumented API. To
+    /// prevent breaking that code (e.g., in `regex-capi`), we continue
+    /// re-exporting the same undocumented API.
+    #[doc(hidden)]
+    #[inline]
+    pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
+        self.get(i)
     }
 }
 
 /// Captures represents a group of captured strings for a single match.
 ///
 /// The 0th capture always corresponds to the entire match. Each subsequent
 /// index corresponds to the next capture group in the regex. If a capture
 /// group is named, then the matched string is *also* available via the `name`
 /// method. (Note that the 0th capture is always unnamed and so must be
 /// accessed with the `get` method.)
 ///
 /// Positions returned from a capture group are always byte indices.
 ///
 /// `'t` is the lifetime of the matched text.
 pub struct Captures<'t> {
     text: &'t str,
-    locs: Locations,
-    named_groups: NamedGroups,
+    locs: re_trait::Locations,
+    named_groups: Arc<HashMap<String, usize>>,
 }
 
 impl<'t> Captures<'t> {
     /// Returns the match associated with the capture group at index `i`. If
     /// `i` does not correspond to a capture group, or if the capture group
     /// did not participate in the match, then `None` is returned.
     ///
     /// # Examples
@@ -952,33 +923,33 @@ impl<'t> Captures<'t> {
     /// ```
     pub fn get(&self, i: usize) -> Option<Match<'t>> {
         self.locs.pos(i).map(|(s, e)| Match::new(self.text, s, e))
     }
 
     /// Returns the match for the capture group named `name`. If `name` isn't a
     /// valid capture group or didn't match anything, then `None` is returned.
     pub fn name(&self, name: &str) -> Option<Match<'t>> {
-        self.named_groups.pos(name).and_then(|i| self.get(i))
+        self.named_groups.get(name).and_then(|&i| self.get(i))
     }
 
     /// An iterator that yields all capturing matches in the order in which
     /// they appear in the regex. If a particular capture group didn't
     /// participate in the match, then `None` is yielded for that capture.
     ///
     /// The first match always corresponds to the overall match of the regex.
     pub fn iter<'c>(&'c self) -> SubCaptureMatches<'c, 't> {
         SubCaptureMatches {
             caps: self,
             it: self.locs.iter(),
         }
     }
 
-    /// Expands all instances of `$name` in `text` to the corresponding capture
-    /// group `name`, and writes them to the `dst` buffer given.
+    /// Expands all instances of `$name` in `replacement` to the corresponding
+    /// capture group `name`, and writes them to the `dst` buffer given.
     ///
     /// `name` may be an integer corresponding to the index of the
     /// capture group (counted by order of opening parenthesis where `0` is the
     /// entire match) or it can be a name (consisting of letters, digits or
     /// underscores) corresponding to a named capture group.
     ///
     /// If `name` isn't a valid capture group (whether the name doesn't exist
     /// or isn't a valid index), then it is replaced with the empty string.
@@ -1009,22 +980,22 @@ impl<'t> fmt::Debug for Captures<'t> {
 }
 
 struct CapturesDebug<'c, 't: 'c>(&'c Captures<'t>);
 
 impl<'c, 't> fmt::Debug for CapturesDebug<'c, 't> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // We'd like to show something nice here, even if it means an
         // allocation to build a reverse index.
-        let slot_to_name: HashMap<usize, &str> =
+        let slot_to_name: HashMap<&usize, &String> =
             self.0.named_groups.iter().map(|(a, b)| (b, a)).collect();
         let mut map = f.debug_map();
         for (slot, m) in self.0.locs.iter().enumerate() {
             let m = m.map(|(s, e)| &self.0.text[s..e]);
-            if let Some(ref name) = slot_to_name.get(&slot) {
+            if let Some(name) = slot_to_name.get(&slot) {
                 map.entry(&name, &m);
             } else {
                 map.entry(&slot, &m);
             }
         }
         map.finish()
     }
 }
@@ -1095,91 +1066,54 @@ impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> {
 
 /// An iterator that yields all non-overlapping capture groups matching a
 /// particular regular expression.
 ///
 /// The iterator stops when no more matches can be found.
 ///
 /// `'r` is the lifetime of the compiled regular expression and `'t` is the
 /// lifetime of the matched string.
-pub struct CaptureMatches<'r, 't>(CaptureMatchesInner<'r, 't>);
-
-enum CaptureMatchesInner<'r, 't> {
-    Dynamic(re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>),
-    Plugin(re_trait::CaptureMatches<'t, Plugin>),
-}
+pub struct CaptureMatches<'r, 't>(re_trait::CaptureMatches<'t, ExecNoSyncStr<'r>>);
 
 impl<'r, 't> Iterator for CaptureMatches<'r, 't> {
     type Item = Captures<'t>;
 
     fn next(&mut self) -> Option<Captures<'t>> {
-        match self.0 {
-            CaptureMatchesInner::Dynamic(ref mut it) => {
-                let named = it.regex().capture_name_idx().clone();
-                it.next().map(|locs| Captures {
-                    text: it.text(),
-                    locs: locs,
-                    named_groups: NamedGroups::Dynamic(named),
-                })
-            }
-            CaptureMatchesInner::Plugin(ref mut it) => {
-                it.next().map(|locs| Captures {
-                    text: it.text(),
-                    locs: locs,
-                    named_groups: NamedGroups::Plugin(it.regex().groups),
-                })
-            }
-        }
+        self.0.next().map(|locs| Captures {
+            text: self.0.text(),
+            locs: locs,
+            named_groups: self.0.regex().capture_name_idx().clone(),
+        })
     }
 }
 
 /// An iterator over all non-overlapping matches for a particular string.
 ///
 /// The iterator yields a `Match` value. The iterator stops when no more
 /// matches can be found.
 ///
 /// `'r` is the lifetime of the compiled regular expression and `'t` is the
 /// lifetime of the matched string.
-pub struct Matches<'r, 't>(MatchesInner<'r, 't>);
-
-enum MatchesInner<'r, 't> {
-    Dynamic(re_trait::Matches<'t, ExecNoSyncStr<'r>>),
-    Plugin(re_trait::Matches<'t, Plugin>),
-}
-
-impl<'r, 't> Matches<'r, 't> {
-    fn text(&self) -> &'t str {
-        match self.0 {
-            MatchesInner::Dynamic(ref it) => it.text(),
-            MatchesInner::Plugin(ref it) => it.text(),
-        }
-    }
-}
+pub struct Matches<'r, 't>(re_trait::Matches<'t, ExecNoSyncStr<'r>>);
 
 impl<'r, 't> Iterator for Matches<'r, 't> {
     type Item = Match<'t>;
 
     fn next(&mut self) -> Option<Match<'t>> {
-        let text = self.text();
-        match self.0 {
-            MatchesInner::Dynamic(ref mut it) => {
-                it.next().map(|(s, e)| Match::new(text, s, e))
-            }
-            MatchesInner::Plugin(ref mut it) => {
-                it.next().map(|(s, e)| Match::new(text, s, e))
-            }
-        }
+        let text = self.0.text();
+        self.0.next().map(|(s, e)| Match::new(text, s, e))
     }
 }
 
 /// Replacer describes types that can be used to replace matches in a string.
 ///
 /// In general, users of this crate shouldn't need to implement this trait,
 /// since implementations are already provided for `&str` and
-/// `FnMut(&Captures) -> String`, which covers most use cases.
+/// `FnMut(&Captures) -> String` (or any `FnMut(&Captures) -> T`
+/// where `T: AsRef<str>`), which covers most use cases.
 pub trait Replacer {
     /// Appends text to `dst` to replace the current match.
     ///
     /// The current match is represented by `caps`, which is guaranteed to
     /// have a match at capture group `0`.
     ///
     /// For example, a no-op replacement would be
     /// `dst.extend(caps.get(0).unwrap().as_str())`.
@@ -1190,48 +1124,88 @@ pub trait Replacer {
     /// When doing replacements, if access to `Captures` is not needed (e.g.,
     /// the replacement byte string does not need `$` expansion), then it can
     /// be beneficial to avoid finding sub-captures.
     ///
     /// In general, this is called once for every call to `replacen`.
     fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
         None
     }
+
+    /// Return a `Replacer` that borrows and wraps this `Replacer`.
+    ///
+    /// This is useful when you want to take a generic `Replacer` (which might
+    /// not be cloneable) and use it without consuming it, so it can be used
+    /// more than once.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use regex::{Regex, Replacer};
+    ///
+    /// fn replace_all_twice<R: Replacer>(
+    ///     re: Regex,
+    ///     src: &str,
+    ///     mut rep: R,
+    /// ) -> String {
+    ///     let dst = re.replace_all(src, rep.by_ref());
+    ///     let dst = re.replace_all(&dst, rep.by_ref());
+    ///     dst.into_owned()
+    /// }
+    /// ```
+    fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
+        ReplacerRef(self)
+    }
+}
+
+/// By-reference adaptor for a `Replacer`
+///
+/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
+#[derive(Debug)]
+pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
+
+impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
+    fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
+        self.0.replace_append(caps, dst)
+    }
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
+        self.0.no_expansion()
+    }
 }
 
 impl<'a> Replacer for &'a str {
     fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
         caps.expand(*self, dst);
     }
 
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
         match memchr(b'$', self.as_bytes()) {
             Some(_) => None,
             None => Some(Cow::Borrowed(*self)),
         }
     }
 }
 
-impl<F> Replacer for F where F: FnMut(&Captures) -> String {
+impl<F, T> Replacer for F where F: FnMut(&Captures) -> T, T: AsRef<str> {
     fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
-        dst.push_str(&(*self)(caps));
+        dst.push_str((*self)(caps).as_ref());
     }
 }
 
-/// NoExpand indicates literal string replacement.
+/// `NoExpand` indicates literal string replacement.
 ///
 /// It can be used with `replace` and `replace_all` to do a literal string
 /// replacement without expanding `$name` to their corresponding capture
 /// groups. This can be both convenient (to avoid escaping `$`, for example)
 /// and performant (since capture groups don't need to be found).
 ///
 /// `'t` is the lifetime of the literal text.
 pub struct NoExpand<'t>(pub &'t str);
 
 impl<'t> Replacer for NoExpand<'t> {
     fn replace_append(&mut self, _: &Captures, dst: &mut String) {
         dst.push_str(self.0);
     }
 
-    fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
+    fn no_expansion(&mut self) -> Option<Cow<str>> {
         Some(Cow::Borrowed(self.0))
     }
 }
diff --git a/third_party/rust/regex/src/utf8.rs b/third_party/rust/regex/src/utf8.rs
index 8f6ec1a02263..ac38e63502de 100644
--- a/third_party/rust/regex/src/utf8.rs
+++ b/third_party/rust/regex/src/utf8.rs
@@ -33,47 +33,16 @@ pub fn next_utf8(text: &[u8], i: usize) -> usize {
     } else if b <= 0b1110_1111 {
         3
     } else {
         4
     };
     i + inc
 }
 
-/// Encode the given Unicode character to `dst` as a single UTF-8 sequence.
-///
-/// If `dst` is not long enough, then `None` is returned. Otherwise, the number
-/// of bytes written is returned.
-#[allow(dead_code)]
-#[inline]
-pub fn encode_utf8(character: char, dst: &mut [u8]) -> Option<usize> {
-    let code = character as u32;
-    if code <= 0x7F && !dst.is_empty() {
-        dst[0] = code as u8;
-        Some(1)
-    } else if code <= 0x7FF && dst.len() >= 2 {
-        dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO;
-        dst[1] = (code & 0x3F) as u8 | TAG_CONT;
-        Some(2)
-    } else if code <= 0xFFFF && dst.len() >= 3  {
-        dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE;
-        dst[1] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
-        dst[2] = (code & 0x3F) as u8 | TAG_CONT;
-        Some(3)
-    } else if dst.len() >= 4 {
-        dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR;
-        dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
-        dst[2] = (code >>  6 & 0x3F) as u8 | TAG_CONT;
-        dst[3] = (code & 0x3F) as u8 | TAG_CONT;
-        Some(4)
-    } else {
-        None
-    }
-}
-
 /// Decode a single UTF-8 sequence into a single Unicode codepoint from `src`.
 ///
 /// If no valid UTF-8 sequence could be found, then `None` is returned.
 /// Otherwise, the decoded codepoint and the number of bytes read is returned.
 /// The number of bytes read (for a valid UTF-8 sequence) is guaranteed to be
 /// 1, 2, 3 or 4.
 ///
 /// Note that a UTF-8 sequence is invalid if it is incorrect UTF-8, encodes a
@@ -144,18 +113,18 @@ pub fn decode_utf8(src: &[u8]) -> Option<(char, usize)> {
                 0x10000 ... 0x10FFFF => char::from_u32(cp).map(|cp| (cp, 4)),
                 _ => None,
             }
         }
         _ => None,
     }
 }
 
-/// Like decode_utf8, but decodes the last UTF-8 sequence in `src` instead of
-/// the first.
+/// Like `decode_utf8`, but decodes the last UTF-8 sequence in `src` instead
+/// of the first.
 pub fn decode_last_utf8(src: &[u8]) -> Option<(char, usize)> {
     if src.is_empty() {
         return None;
     }
     let mut start = src.len() - 1;
     if src[start] <= 0x7F {
         return Some((src[start] as char, 1));
     }
@@ -179,71 +148,71 @@ fn is_start_byte(b: u8) -> bool {
 #[cfg(test)]
 mod tests {
     use std::str;
 
     use quickcheck::quickcheck;
 
     use super::{
         TAG_CONT, TAG_TWO, TAG_THREE, TAG_FOUR,
-        decode_utf8, decode_last_utf8, encode_utf8,
+        decode_utf8, decode_last_utf8,
     };
 
     #[test]
     fn prop_roundtrip() {
         fn p(given_cp: char) -> bool {
             let mut tmp = [0; 4];
-            let encoded_len = encode_utf8(given_cp, &mut tmp).unwrap();
+            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
             let (got_cp, got_len) = decode_utf8(&tmp[..encoded_len]).unwrap();
             encoded_len == got_len && given_cp == got_cp
         }
         quickcheck(p as fn(char) -> bool)
     }
 
     #[test]
     fn prop_roundtrip_last() {
         fn p(given_cp: char) -> bool {
             let mut tmp = [0; 4];
-            let encoded_len = encode_utf8(given_cp, &mut tmp).unwrap();
+            let encoded_len = given_cp.encode_utf8(&mut tmp).len();
             let (got_cp, got_len) =
                 decode_last_utf8(&tmp[..encoded_len]).unwrap();
             encoded_len == got_len && given_cp == got_cp
         }
         quickcheck(p as fn(char) -> bool)
     }
 
     #[test]
     fn prop_encode_matches_std() {
         fn p(cp: char) -> bool {
             let mut got = [0; 4];
-            let n = encode_utf8(cp, &mut got).unwrap();
+            let n = cp.encode_utf8(&mut got).len();
             let expected = cp.to_string();
             &got[..n] == expected.as_bytes()
         }
         quickcheck(p as fn(char) -> bool)
     }
 
     #[test]
     fn prop_decode_matches_std() {
         fn p(given_cp: char) -> bool {
             let mut tmp = [0; 4];
-            let n = encode_utf8(given_cp, &mut tmp).unwrap();
+            let n = given_cp.encode_utf8(&mut tmp).len();
             let (got_cp, _) = decode_utf8(&tmp[..n]).unwrap();
             let expected_cp =
                 str::from_utf8(&tmp[..n]).unwrap().chars().next().unwrap();
             got_cp == expected_cp
         }
         quickcheck(p as fn(char) -> bool)
     }
 
     #[test]
     fn prop_decode_last_matches_std() {
         fn p(given_cp: char) -> bool {
             let mut tmp = [0; 4];
-            let n = encode_utf8(given_cp, &mut tmp).unwrap();
+            let n = given_cp.encode_utf8(&mut tmp).len();
             let (got_cp, _) = decode_last_utf8(&tmp[..n]).unwrap();
             let expected_cp =
                 str::from_utf8(&tmp[..n]).unwrap()
                     .chars().rev().next().unwrap();
             got_cp == expected_cp
         }
         quickcheck(p as fn(char) -> bool)
     }
diff --git a/third_party/rust/regex/src/vector/avx2.rs b/third_party/rust/regex/src/vector/avx2.rs
new file mode 100644
index 000000000000..db0532c3feee
--- /dev/null
+++ b/third_party/rust/regex/src/vector/avx2.rs
@@ -0,0 +1,187 @@
+#![allow(dead_code)]
+
+use std::arch::x86_64::*;
+use std::fmt;
+
+#[derive(Clone, Copy, Debug)]
+pub struct AVX2VectorBuilder(());
+
+impl AVX2VectorBuilder {
+    pub fn new() -> Option<AVX2VectorBuilder> {
+        if is_x86_feature_detected!("avx2") {
+            Some(AVX2VectorBuilder(()))
+        } else {
+            None
+        }
+    }
+
+    /// Create a new u8x32 AVX2 vector where all of the bytes are set to
+    /// the given value.
+    #[inline]
+    pub fn u8x32_splat(self, n: u8) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe { u8x32::splat(n) }
+    }
+
+    /// Load 32 bytes from the given slice, with bounds checks.
+    #[inline]
+    pub fn u8x32_load_unaligned(self, slice: &[u8]) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe { u8x32::load_unaligned(slice) }
+    }
+
+    /// Load 32 bytes from the given slice, without bounds checks.
+    #[inline]
+    pub unsafe fn u8x32_load_unchecked_unaligned(self, slice: &[u8]) -> u8x32 {
+        // Safe because we know AVX2 is enabled, but still unsafe
+        // because we aren't doing bounds checks.
+        u8x32::load_unchecked_unaligned(slice)
+    }
+
+    /// Load 32 bytes from the given slice, with bound and alignment checks.
+    #[inline]
+    pub fn u8x32_load(self, slice: &[u8]) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe { u8x32::load(slice) }
+    }
+
+    /// Load 32 bytes from the given slice, without bound or alignment checks.
+    #[inline]
+    pub unsafe fn u8x32_load_unchecked(self, slice: &[u8]) -> u8x32 {
+        // Safe because we know AVX2 is enabled, but still unsafe
+        // because we aren't doing bounds checks.
+        u8x32::load_unchecked(slice)
+    }
+}
+
+#[derive(Clone, Copy)]
+#[allow(non_camel_case_types)]
+pub union u8x32 {
+    vector: __m256i,
+    bytes: [u8; 32],
+}
+
+impl u8x32 {
+    #[inline]
+    unsafe fn splat(n: u8) -> u8x32 {
+        u8x32 { vector: _mm256_set1_epi8(n as i8) }
+    }
+
+    #[inline]
+    unsafe fn load_unaligned(slice: &[u8]) -> u8x32 {
+        assert!(slice.len() >= 32);
+        u8x32::load_unchecked_unaligned(slice)
+    }
+
+    #[inline]
+    unsafe fn load_unchecked_unaligned(slice: &[u8]) -> u8x32 {
+        let p = slice.as_ptr() as *const u8 as *const __m256i;
+        u8x32 { vector: _mm256_loadu_si256(p) }
+    }
+
+    #[inline]
+    unsafe fn load(slice: &[u8]) -> u8x32 {
+        assert!(slice.len() >= 32);
+        assert!(slice.as_ptr() as usize % 32 == 0);
+        u8x32::load_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn load_unchecked(slice: &[u8]) -> u8x32 {
+        let p = slice.as_ptr() as *const u8 as *const __m256i;
+        u8x32 { vector: _mm256_load_si256(p) }
+    }
+
+    #[inline]
+    pub fn extract(self, i: usize) -> u8 {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes[i] }
+    }
+
+    #[inline]
+    pub fn replace(&mut self, i: usize, byte: u8) {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes[i] = byte; }
+    }
+
+    #[inline]
+    pub fn shuffle(self, indices: u8x32) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            u8x32 { vector: _mm256_shuffle_epi8(self.vector, indices.vector) }
+        }
+    }
+
+    #[inline]
+    pub fn ne(self, other: u8x32) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            let boolv = _mm256_cmpeq_epi8(self.vector, other.vector);
+            let ones = _mm256_set1_epi8(0xFF as u8 as i8);
+            u8x32 { vector: _mm256_andnot_si256(boolv, ones) }
+        }
+    }
+
+    #[inline]
+    pub fn and(self, other: u8x32) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            u8x32 { vector: _mm256_and_si256(self.vector, other.vector) }
+        }
+    }
+
+    #[inline]
+    pub fn movemask(self) -> u32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            _mm256_movemask_epi8(self.vector) as u32
+        }
+    }
+
+    #[inline]
+    pub fn alignr_14(self, other: u8x32) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            // Credit goes to jneem for figuring this out:
+            // https://github.com/jneem/teddy/blob/9ab5e899ad6ef6911aecd3cf1033f1abe6e1f66c/src/x86/teddy_simd.rs#L145-L184
+            //
+            // TL;DR avx2's PALIGNR instruction is actually just two 128-bit
+            // PALIGNR instructions, which is not what we want, so we need to
+            // do some extra shuffling.
+            let v = _mm256_permute2x128_si256(other.vector, self.vector, 0x21);
+            let v = _mm256_alignr_epi8(self.vector, v, 14);
+            u8x32 { vector: v }
+        }
+    }
+
+    #[inline]
+    pub fn alignr_15(self, other: u8x32) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            // Credit goes to jneem for figuring this out:
+            // https://github.com/jneem/teddy/blob/9ab5e899ad6ef6911aecd3cf1033f1abe6e1f66c/src/x86/teddy_simd.rs#L145-L184
+            //
+            // TL;DR avx2's PALIGNR instruction is actually just two 128-bit
+            // PALIGNR instructions, which is not what we want, so we need to
+            // do some extra shuffling.
+            let v = _mm256_permute2x128_si256(other.vector, self.vector, 0x21);
+            let v = _mm256_alignr_epi8(self.vector, v, 15);
+            u8x32 { vector: v }
+        }
+    }
+
+    #[inline]
+    pub fn bit_shift_right_4(self) -> u8x32 {
+        // Safe because we know AVX2 is enabled.
+        unsafe {
+            u8x32 { vector: _mm256_srli_epi16(self.vector, 4) }
+        }
+    }
+}
+
+impl fmt::Debug for u8x32 {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes.fmt(f) }
+    }
+}
diff --git a/third_party/rust/regex/src/vector/mod.rs b/third_party/rust/regex/src/vector/mod.rs
new file mode 100644
index 000000000000..2956f56db0ec
--- /dev/null
+++ b/third_party/rust/regex/src/vector/mod.rs
@@ -0,0 +1,4 @@
+#[cfg(target_arch = "x86_64")]
+pub mod avx2;
+#[cfg(any(target_arch = "x86_64"))]
+pub mod ssse3;
diff --git a/third_party/rust/regex/src/vector/ssse3.rs b/third_party/rust/regex/src/vector/ssse3.rs
new file mode 100644
index 000000000000..0485657f01ea
--- /dev/null
+++ b/third_party/rust/regex/src/vector/ssse3.rs
@@ -0,0 +1,192 @@
+#![allow(dead_code)]
+
+use std::arch::x86_64::*;
+use std::fmt;
+
+/// A builder for SSSE3 empowered vectors.
+///
+/// This builder represents a receipt that the SSSE3 target feature is enabled
+/// on the currently running CPU. Namely, the only way to get a value of this
+/// type is if the SSSE3 feature is enabled.
+///
+/// This type can then be used to build vector types that use SSSE3 features
+/// safely.
+#[derive(Clone, Copy, Debug)]
+pub struct SSSE3VectorBuilder(());
+
+impl SSSE3VectorBuilder {
+    /// Create a new SSSE3 vector builder.
+    ///
+    /// If the SSSE3 feature is not enabled for the current target, then
+    /// return `None`.
+    pub fn new() -> Option<SSSE3VectorBuilder> {
+        if is_x86_feature_detected!("ssse3") {
+            Some(SSSE3VectorBuilder(()))
+        } else {
+            None
+        }
+    }
+
+    /// Create a new u8x16 SSSE3 vector where all of the bytes are set to
+    /// the given value.
+    #[inline]
+    pub fn u8x16_splat(self, n: u8) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe { u8x16::splat(n) }
+    }
+
+    /// Load 16 bytes from the given slice, with bounds checks.
+    #[inline]
+    pub fn u8x16_load_unaligned(self, slice: &[u8]) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe { u8x16::load_unaligned(slice) }
+    }
+
+    /// Load 16 bytes from the given slice, without bounds checks.
+    #[inline]
+    pub unsafe fn u8x16_load_unchecked_unaligned(self, slice: &[u8]) -> u8x16 {
+        // Safe because we know SSSE3 is enabled, but still unsafe
+        // because we aren't doing bounds checks.
+        u8x16::load_unchecked_unaligned(slice)
+    }
+
+    /// Load 16 bytes from the given slice, with bound and alignment checks.
+    #[inline]
+    pub fn u8x16_load(self, slice: &[u8]) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe { u8x16::load(slice) }
+    }
+
+    /// Load 16 bytes from the given slice, without bound or alignment checks.
+    #[inline]
+    pub unsafe fn u8x16_load_unchecked(self, slice: &[u8]) -> u8x16 {
+        // Safe because we know SSSE3 is enabled, but still unsafe
+        // because we aren't doing bounds checks.
+        u8x16::load_unchecked(slice)
+    }
+}
+
+/// A u8x16 is a 128-bit vector with 16 single-byte lanes.
+///
+/// It provides a safe API that uses only SSE2 or SSSE3 instructions.
+/// The only way for callers to construct a value of this type is
+/// through the SSSE3VectorBuilder type, and the only way to get a
+/// SSSE3VectorBuilder is if the `ssse3` target feature is enabled.
+///
+/// Note that generally speaking, all uses of this type should get
+/// inlined, otherwise you probably have a performance bug.
+#[derive(Clone, Copy)]
+#[allow(non_camel_case_types)]
+pub union u8x16 {
+    vector: __m128i,
+    bytes: [u8; 16],
+}
+
+impl u8x16 {
+    #[inline]
+    unsafe fn splat(n: u8) -> u8x16 {
+        u8x16 { vector: _mm_set1_epi8(n as i8) }
+    }
+
+    #[inline]
+    unsafe fn load_unaligned(slice: &[u8]) -> u8x16 {
+        assert!(slice.len() >= 16);
+        u8x16::load_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn load_unchecked_unaligned(slice: &[u8]) -> u8x16 {
+        let v = _mm_loadu_si128(slice.as_ptr() as *const u8 as *const __m128i);
+        u8x16 { vector: v }
+    }
+
+    #[inline]
+    unsafe fn load(slice: &[u8]) -> u8x16 {
+        assert!(slice.len() >= 16);
+        assert!(slice.as_ptr() as usize % 16 == 0);
+        u8x16::load_unchecked(slice)
+    }
+
+    #[inline]
+    unsafe fn load_unchecked(slice: &[u8]) -> u8x16 {
+        let v = _mm_load_si128(slice.as_ptr() as *const u8 as *const __m128i);
+        u8x16 { vector: v }
+    }
+
+    #[inline]
+    pub fn extract(self, i: usize) -> u8 {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes[i] }
+    }
+
+    #[inline]
+    pub fn replace(&mut self, i: usize, byte: u8) {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes[i] = byte; }
+    }
+
+    #[inline]
+    pub fn shuffle(self, indices: u8x16) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            u8x16 { vector: _mm_shuffle_epi8(self.vector, indices.vector) }
+        }
+    }
+
+    #[inline]
+    pub fn ne(self, other: u8x16) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            let boolv = _mm_cmpeq_epi8(self.vector, other.vector);
+            let ones = _mm_set1_epi8(0xFF as u8 as i8);
+            u8x16 { vector: _mm_andnot_si128(boolv, ones) }
+        }
+    }
+
+    #[inline]
+    pub fn and(self, other: u8x16) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            u8x16 { vector: _mm_and_si128(self.vector, other.vector) }
+        }
+    }
+
+    #[inline]
+    pub fn movemask(self) -> u32 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            _mm_movemask_epi8(self.vector) as u32
+        }
+    }
+
+    #[inline]
+    pub fn alignr_14(self, other: u8x16) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            u8x16 { vector: _mm_alignr_epi8(self.vector, other.vector, 14) }
+        }
+    }
+
+    #[inline]
+    pub fn alignr_15(self, other: u8x16) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            u8x16 { vector: _mm_alignr_epi8(self.vector, other.vector, 15) }
+        }
+    }
+
+    #[inline]
+    pub fn bit_shift_right_4(self) -> u8x16 {
+        // Safe because we know SSSE3 is enabled.
+        unsafe {
+            u8x16 { vector: _mm_srli_epi16(self.vector, 4) }
+        }
+    }
+}
+
+impl fmt::Debug for u8x16 {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Safe because `bytes` is always accessible.
+        unsafe { self.bytes.fmt(f) }
+    }
+}
diff --git a/third_party/rust/regex/tests/api_str.rs b/third_party/rust/regex/tests/api_str.rs
index 5bdca8426a8b..410bd9036af9 100644
--- a/third_party/rust/regex/tests/api_str.rs
+++ b/third_party/rust/regex/tests/api_str.rs
@@ -15,8 +15,17 @@ fn empty_match_unicode_captures_iter() {
     // Same as empty_match_unicode_find_iter, but tests capture iteration.
     let re = regex!(r".*?");
     let ms: Vec<_> = re.captures_iter(text!("Ⅰ1Ⅱ2"))
                        .map(|c| c.get(0).unwrap())
                        .map(|m| (m.start(), m.end()))
                        .collect();
     assert_eq!(vec![(0, 0), (3, 3), (4, 4), (7, 7), (8, 8)], ms);
 }
+
+#[test]
+fn match_as_str() {
+    let re = regex!(r"fo+");
+    let caps = re.captures("barfoobar").unwrap();
+    assert_eq!(caps.get(0).map(|m| m.as_str()), Some("foo"));
+    assert_eq!(caps.get(0).map(From::from), Some("foo"));
+    assert_eq!(caps.get(0).map(Into::into), Some("foo"));
+}
diff --git a/third_party/rust/regex/tests/bytes.rs b/third_party/rust/regex/tests/bytes.rs
index 9d472aa518d7..0b0f008d6e98 100644
--- a/third_party/rust/regex/tests/bytes.rs
+++ b/third_party/rust/regex/tests/bytes.rs
@@ -1,14 +1,14 @@
 // These are tests specifically crafted for regexes that can match arbitrary
 // bytes.
 
 // A silly wrapper to make it possible to write and match raw bytes.
 struct R<'a>(&'a [u8]);
-impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { &self.0 } }
+impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { self.0 } }
 
 mat!(word_boundary, r"(?-u) \b", " δ", None);
 mat!(word_boundary_unicode, r" \b", " δ", Some((0, 1)));
 mat!(word_not_boundary, r"(?-u) \B", " δ", Some((0, 1)));
 mat!(word_not_boundary_unicode, r" \B", " δ", None);
 
 mat!(perl_w_ascii, r"(?-u)\w+", "aδ", Some((0, 1)));
 mat!(perl_w_unicode, r"\w+", "aδ", Some((0, 3)));
@@ -55,8 +55,18 @@ matiter!(invalidutf8_anchor3,
          R(b"\x8d#;\x1a\xa4s3\x05foobarX\\\x0f0t\xe4\x9b\xa4"),
          (0, 0));
 
 // See https://github.com/rust-lang/regex/issues/303
 #[test]
 fn negated_full_byte_range() {
      assert!(::regex::bytes::Regex::new(r#"(?-u)[^\x00-\xff]"#).is_err());
 }
+
+matiter!(word_boundary_ascii1, r"(?-u:\B)x(?-u:\B)", "áxβ");
+matiter!(word_boundary_ascii2, r"(?-u:\B)", "0\u{7EF5E}", (2, 2), (3, 3), (4, 4), (5, 5));
+
+// See: https://github.com/rust-lang/regex/issues/264
+mat!(ascii_boundary_no_capture, r"(?-u)\B", "\u{28f3e}", Some((0, 0)));
+mat!(ascii_boundary_capture, r"(?-u)(\B)", "\u{28f3e}", Some((0, 0)));
+
+// See: https://github.com/rust-lang/regex/issues/271
+mat!(end_not_wb, r"$(?-u:\B)", "\u{5c124}\u{b576c}", Some((8, 8)));
diff --git a/third_party/rust/regex/tests/consistent.rs b/third_party/rust/regex/tests/consistent.rs
new file mode 100644
index 000000000000..b61050e4b1d4
--- /dev/null
+++ b/third_party/rust/regex/tests/consistent.rs
@@ -0,0 +1,213 @@
+use regex::internal::ExecBuilder;
+
+/// Given a regex, check if all of the backends produce the same
+/// results on a number of different inputs.
+///
+/// For now this just throws quickcheck at the problem, which
+/// is not very good because it only really tests half of the
+/// problem space. It is pretty unlikely that a random string
+/// will match any given regex, so this will probably just
+/// be checking that the different backends fail in the same
+/// way. This is still worthwhile to test, but is definitely not
+/// the whole story.
+///
+/// TODO(ethan): In order to cover the other half of the problem
+/// space, we should generate a random matching string by inspecting
+/// the AST of the input regex. The right way to do this probably
+/// involves adding a custom Arbitrary instance around a couple
+/// of newtypes. That way we can respect the quickcheck size hinting
+/// and shrinking and whatnot.
+pub fn backends_are_consistent(re: &str) -> Result<u64, String> {
+    let standard_backends = vec![
+        ("bounded_backtracking_re",
+            ExecBuilder::new(re)
+                    .bounded_backtracking()
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("pikevm_re",
+            ExecBuilder::new(re)
+                    .nfa()
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("default_re",
+            ExecBuilder::new(re)
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+    ];
+
+    let utf8bytes_backends = vec![
+        ("bounded_backtracking_utf8bytes_re",
+            ExecBuilder::new(re)
+                    .bounded_backtracking()
+                    .bytes(true)
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("pikevm_utf8bytes_re",
+            ExecBuilder::new(re)
+                    .nfa()
+                    .bytes(true)
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("default_utf8bytes_re",
+            ExecBuilder::new(re)
+                    .bytes(true)
+                    .build()
+                    .map(|exec| exec.into_regex())
+                    .map_err(|err| format!("{}", err))?),
+    ];
+
+    let bytes_backends = vec![
+        ("bounded_backtracking_bytes_re",
+            ExecBuilder::new(re)
+                    .bounded_backtracking()
+                    .only_utf8(false)
+                    .build()
+                    .map(|exec| exec.into_byte_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("pikevm_bytes_re",
+            ExecBuilder::new(re)
+                    .nfa()
+                    .only_utf8(false)
+                    .build()
+                    .map(|exec| exec.into_byte_regex())
+                    .map_err(|err| format!("{}", err))?),
+
+        ("default_bytes_re",
+            ExecBuilder::new(re)
+                    .only_utf8(false)
+                    .build()
+                    .map(|exec| exec.into_byte_regex())
+                    .map_err(|err| format!("{}", err))?),
+    ];
+
+    Ok(string_checker::check_backends(&standard_backends)?
+       + string_checker::check_backends(&utf8bytes_backends)?
+       + bytes_checker::check_backends(&bytes_backends)?)
+}
+
+//
+// A consistency checker parameterized by the input type (&str or &[u8]).
+//
+
+macro_rules! checker {
+    ($module_name:ident, $regex_type:path, $mk_input:expr) => {
+
+mod $module_name {
+    use quickcheck;
+    use quickcheck::{TestResult, Arbitrary};
+
+    pub fn check_backends(
+        backends: &[(&str, $regex_type)]
+    ) -> Result<u64, String> {
+        let mut total_passed = 0;
+        for regex in backends[1..].iter() {
+            total_passed += quickcheck_regex_eq(&backends[0], regex)?;
+        }
+
+        Ok(total_passed)
+    }
+
+    fn quickcheck_regex_eq(
+        &(name1, ref re1): &(&str, $regex_type),
+        &(name2, ref re2): &(&str, $regex_type),
+    ) -> Result<u64, String> {
+        quickcheck::QuickCheck::new()
+            .quicktest(RegexEqualityTest::new(re1.clone(), re2.clone()))
+            .map_err(|err|
+                format!("{}(/{}/) and {}(/{}/) are inconsistent.\
+                         QuickCheck Err: {:?}",
+                        name1, re1, name2, re2, err))
+    }
+
+    struct RegexEqualityTest {
+        re1: $regex_type,
+        re2: $regex_type,
+    }
+    impl RegexEqualityTest {
+        fn new(re1: $regex_type, re2: $regex_type) -> Self {
+            RegexEqualityTest {
+                re1: re1,
+                re2: re2,
+            }
+        }
+    }
+
+    impl quickcheck::Testable for RegexEqualityTest {
+        fn result<G: quickcheck::Gen>(&self, gen: &mut G) -> TestResult {
+            let input = $mk_input(gen);
+            let input = &input;
+
+            if self.re1.find(&input) != self.re2.find(input) {
+                return TestResult::error(
+                        format!("find mismatch input={:?}", input));
+            }
+
+            let cap1 = self.re1.captures(input);
+            let cap2 = self.re2.captures(input);
+            match (cap1, cap2) {
+                (None, None) => {}
+                (Some(cap1), Some(cap2)) => {
+                    for (c1, c2) in cap1.iter().zip(cap2.iter()) {
+                        if c1 != c2 {
+                            return TestResult::error(
+                                format!("captures mismatch input={:?}", input));
+                        }
+                    }
+                }
+                _ => return TestResult::error(
+                                format!("captures mismatch input={:?}", input)),
+            }
+
+            let fi1 = self.re1.find_iter(input);
+            let fi2 = self.re2.find_iter(input);
+            for (m1, m2) in fi1.zip(fi2) {
+                if m1 != m2 {
+                    return TestResult::error(
+                        format!("find_iter mismatch input={:?}", input));
+                }
+            }
+
+            let ci1 = self.re1.captures_iter(input);
+            let ci2 = self.re2.captures_iter(input);
+            for (cap1, cap2) in ci1.zip(ci2) {
+                for (c1, c2) in cap1.iter().zip(cap2.iter()) {
+                    if c1 != c2 {
+                        return TestResult::error(
+                            format!("captures_iter mismatch input={:?}", input));
+                    }
+                }
+            }
+
+            let s1 = self.re1.split(input);
+            let s2 = self.re2.split(input);
+            for (chunk1, chunk2) in s1.zip(s2) {
+                if chunk1 != chunk2 {
+                    return TestResult::error(
+                        format!("split mismatch input={:?}", input));
+                }
+            }
+
+            TestResult::from_bool(true)
+        }
+    }
+
+} // mod
+} // rule case
+} // macro_rules!
+
+checker!(string_checker,
+    ::regex::Regex,
+    |gen| String::arbitrary(gen));
+checker!(bytes_checker,
+    ::regex::bytes::Regex,
+    |gen| Vec::<u8>::arbitrary(gen));
diff --git a/third_party/rust/regex/tests/crates_regex.rs b/third_party/rust/regex/tests/crates_regex.rs
new file mode 100644
index 000000000000..1ccfe471084b
--- /dev/null
+++ b/third_party/rust/regex/tests/crates_regex.rs
@@ -0,0 +1,3129 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// DO NOT EDIT. Automatically generated by 'scripts/scrape_crates_io.py'
+// on 2018-06-20 09:56:32.820354.
+
+
+
+// autoshutdown-0.1.0: r"\s*(\d+)(\w)\s*"
+consistent!(autoshutdown_0, r"\s*(\d+)(\w)\s*");
+
+// epub-1.1.1: r"/"
+consistent!(epub_0, r"/");
+
+// rpi-info-0.2.0: "^Revision\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_0, "^Revision\t+: ([0-9a-fA-F]+)");
+
+// rpi-info-0.2.0: "Serial\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_1, "Serial\t+: ([0-9a-fA-F]+)");
+
+// pnet_macros-0.21.0: r"^u([0-9]+)(be|le|he)?$"
+consistent!(pnet_macros_0, r"^u([0-9]+)(be|le|he)?$");
+
+// iban_validate-1.0.3: r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$"
+consistent!(iban_validate_0, r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$");
+
+// markifier-0.1.0: r".*\[(?P<percent>.+)%.*\].*"
+consistent!(markifier_0, r".*\[(?P<percent>.+)%.*\].*");
+
+// mallumo-0.3.0: r"(#include) (\S*)(.*)"
+consistent!(mallumo_0, r"(#include) (\S*)(.*)");
+
+// mallumo-0.3.0: r"(ERROR: \d+:)(\d+)(: )(.+)"
+consistent!(mallumo_1, r"(ERROR: \d+:)(\d+)(: )(.+)");
+
+// mallumo-0.3.0: r"(\d+\()(\d+)(?:\) : )(.+)"
+consistent!(mallumo_2, r"(\d+\()(\d+)(?:\) : )(.+)");
+
+// magnet_more-0.0.1: r"(.+?)(\[.*?\])?"
+consistent!(magnet_more_0, r"(.+?)(\[.*?\])?");
+
+// magnet_app-0.0.1: r":(?P<k>[a-zA-Z_]+)"
+consistent!(magnet_app_0, r":(?P<k>[a-zA-Z_]+)");
+
+// yubibomb-0.2.0: r"^\d{6}(?:\s*,\s*\d{6})*$"
+consistent!(yubibomb_0, r"^\d{6}(?:\s*,\s*\d{6})*$");
+
+// multirust-rs-0.0.4: r"[\\/]([^\\/?]+)(\?.*)?$"
+consistent!(multirust_rs_0, r"[\\/]([^\\/?]+)(\?.*)?$");
+
+// hueclient-0.3.2: "\"[a-z]*\":null"
+consistent!(hueclient_0, "\"[a-z]*\":null");
+
+// hueclient-0.3.2: ",+"
+consistent!(hueclient_1, ",+");
+
+// hueclient-0.3.2: ",\\}"
+consistent!(hueclient_2, ",\\}");
+
+// hueclient-0.3.2: "\\{,"
+consistent!(hueclient_3, "\\{,");
+
+// aerial-0.1.0: r"[a-zA-Z_\$][a-zA-Z_0-9]*"
+consistent!(aerial_0, r"[a-zA-Z_\$][a-zA-Z_0-9]*");
+
+// aerial-0.1.0: r"thi[sng]+"
+consistent!(aerial_1, r"thi[sng]+");
+
+// rvue-0.1.0: r"(.+)\s+\((.+?)\)"
+consistent!(rvue_0, r"(.+)\s+\((.+?)\)");
+
+// rvue-0.1.0: r"([\d\.]+)\s*out\s*of\s*([\d\.]+)"
+consistent!(rvue_1, r"([\d\.]+)\s*out\s*of\s*([\d\.]+)");
+
+// rvue-0.1.0: r"^([\d\.]+)\s*(?:\(\))?$"
+consistent!(rvue_2, r"^([\d\.]+)\s*(?:\(\))?$");
+
+// rvue-0.1.0: r"([\d\.]+)\s*Points\s*Possible"
+consistent!(rvue_3, r"([\d\.]+)\s*Points\s*Possible");
+
+// rvue-0.1.0: r"([\d\.]+)\s*/\s*([\d\.]+)"
+consistent!(rvue_4, r"([\d\.]+)\s*/\s*([\d\.]+)");
+
+// rvsim-0.1.0: r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]"
+consistent!(rvsim_0, r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]");
+
+// nereon-0.1.4: "(.*[^\\\\])\\{\\}(.*)"
+consistent!(nereon_0, "(.*[^\\\\])\\{\\}(.*)");
+
+// next_episode-0.3.0: r"((?i)^(.+).s(\d+)e(\d+).*)$"
+consistent!(next_episode_0, r"((?i)^(.+).s(\d+)e(\d+).*)$");
+
+// migrant_lib-0.19.2: r"[^a-z0-9-]+"
+consistent!(migrant_lib_0, r"[^a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"[0-9]{14}_[a-z0-9-]+"
+consistent!(migrant_lib_1, r"[0-9]{14}_[a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"([0-9]{14}_)?[a-z0-9-]+"
+consistent!(migrant_lib_2, r"([0-9]{14}_)?[a-z0-9-]+");
+
+// minipre-0.2.0: "$_"
+consistent!(minipre_0, "$_");
+
+// minifier-0.0.13: r">\s+<"
+consistent!(minifier_0, r">\s+<");
+
+// minifier-0.0.13: r"\s{2,}|[\r\n]"
+consistent!(minifier_1, r"\s{2,}|[\r\n]");
+
+// minifier-0.0.13: r"<(style|script)[\w|\s].*?>"
+consistent!(minifier_2, r"<(style|script)[\w|\s].*?>");
+
+// minifier-0.0.13: "<!--(.|\n)*?-->"
+consistent!(minifier_3, "<!--(.|\n)*?-->");
+
+// minifier-0.0.13: r"<\w.*?>"
+consistent!(minifier_4, r"<\w.*?>");
+
+// minifier-0.0.13: r" \s+|\s +"
+consistent!(minifier_5, r" \s+|\s +");
+
+// minifier-0.0.13: r"\w\s+\w"
+consistent!(minifier_6, r"\w\s+\w");
+
+// minifier-0.0.13: r"'\s+>"
+consistent!(minifier_7, r"'\s+>");
+
+// minifier-0.0.13: r"\d\s+>"
+consistent!(minifier_8, r"\d\s+>");
+
+// ggp-rs-0.1.2: r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)"
+consistent!(ggp_rs_0, r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)");
+
+// ggp-rs-0.1.2: r"\((.*)\)."
+consistent!(ggp_rs_1, r"\((.*)\).");
+
+// poe-superfilter-0.2.0: "[A-Za-z0-9_]"
+consistent!(poe_superfilter_0, "[A-Za-z0-9_]");
+
+// poke-a-mango-0.5.0: r"(\d+)x(\d+)"
+consistent!(poke_a_mango_0, r"(\d+)x(\d+)");
+
+// pop3-rs-0.1.0: r"(?P<nmsg>\d+) (?P<size>\d+)"
+consistent!(pop3_rs_0, r"(?P<nmsg>\d+) (?P<size>\d+)");
+
+// pop3-rs-0.1.0: r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})"
+consistent!(pop3_rs_1, r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})");
+
+// pop3-rs-0.1.0: r"(<.*>)\r\n$"
+consistent!(pop3_rs_2, r"(<.*>)\r\n$");
+
+// pop3-rs-0.1.0: r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)"
+consistent!(pop3_rs_3, r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)");
+
+// pop3-1.0.6: r"^\.\r\n$"
+consistent!(pop3_0, r"^\.\r\n$");
+
+// pop3-1.0.6: r"\+OK(.*)"
+consistent!(pop3_1, r"\+OK(.*)");
+
+// pop3-1.0.6: r"-ERR(.*)"
+consistent!(pop3_2, r"-ERR(.*)");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_3, r"\+OK (\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"(\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_4, r"(\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_5, r"\+OK (\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"(\d+) (\d+)\r\n"
+consistent!(pop3_6, r"(\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_7, r"\+OK (\d+) (\d+)\r\n");
+
+// polk-1.1.3: "github:(\\w+)/?(\\w+)?"
+consistent!(polk_0, "github:(\\w+)/?(\\w+)?");
+
+// geochunk-0.1.5: "^[0-9]{5}"
+consistent!(geochunk_0, "^[0-9]{5}");
+
+// generic-dns-update-1.1.4: r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"
+consistent!(generic_dns_update_0, r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))");
+
+// generic-dns-update-1.1.4: r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))"
+consistent!(generic_dns_update_1, r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))");
+
+// generic-dns-update-1.1.4: r"<value><string>([0-9.]*)</string></value>"
+consistent!(generic_dns_update_2, r"<value><string>([0-9.]*)</string></value>");
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_3, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_4, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<boolean>([0-1]*)</boolean>"
+consistent!(generic_dns_update_5, r"<boolean>([0-1]*)</boolean>");
+
+// generate-nix-pkg-0.3.0: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_0, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// generate-nix-pkg-0.3.0: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_0, r"arch/([a-z0-9_])+/");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_1, r"arch/([a-z0-9_])+/");
+
+// cron_rs-0.1.6: r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
+consistent!(cron_rs_0, r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$");
+
+// systemfd-0.3.0: r"^([a-zA-Z]+)::(.+)$"
+consistent!(systemfd_0, r"^([a-zA-Z]+)::(.+)$");
+
+// symbolic-debuginfo-5.0.2: "__?hidden#\\d+_"
+consistent!(symbolic_debuginfo_0, "__?hidden#\\d+_");
+
+// symbolic-minidump-5.0.2: r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$"
+consistent!(symbolic_minidump_0, r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_0, "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_1, "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*"
+consistent!(graphql_idl_parser_2, "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*");
+
+// graphql-idl-parser-0.1.1: "^(?u:!)"
+consistent!(graphql_idl_parser_3, "^(?u:!)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\()"
+consistent!(graphql_idl_parser_4, "^(?u:\\()");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\))"
+consistent!(graphql_idl_parser_5, "^(?u:\\))");
+
+// graphql-idl-parser-0.1.1: "^(?u:,)"
+consistent!(graphql_idl_parser_6, "^(?u:,)");
+
+// graphql-idl-parser-0.1.1: "^(?u::)"
+consistent!(graphql_idl_parser_7, "^(?u::)");
+
+// graphql-idl-parser-0.1.1: "^(?u:@)"
+consistent!(graphql_idl_parser_8, "^(?u:@)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\[)"
+consistent!(graphql_idl_parser_9, "^(?u:\\[)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\])"
+consistent!(graphql_idl_parser_10, "^(?u:\\])");
+
+// graphql-idl-parser-0.1.1: "^(?u:enum)"
+consistent!(graphql_idl_parser_11, "^(?u:enum)");
+
+// graphql-idl-parser-0.1.1: "^(?u:implements)"
+consistent!(graphql_idl_parser_12, "^(?u:implements)");
+
+// graphql-idl-parser-0.1.1: "^(?u:input)"
+consistent!(graphql_idl_parser_13, "^(?u:input)");
+
+// graphql-idl-parser-0.1.1: "^(?u:interface)"
+consistent!(graphql_idl_parser_14, "^(?u:interface)");
+
+// graphql-idl-parser-0.1.1: "^(?u:scalar)"
+consistent!(graphql_idl_parser_15, "^(?u:scalar)");
+
+// graphql-idl-parser-0.1.1: "^(?u:type)"
+consistent!(graphql_idl_parser_16, "^(?u:type)");
+
+// graphql-idl-parser-0.1.1: "^(?u:union)"
+consistent!(graphql_idl_parser_17, "^(?u:union)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\{)"
+consistent!(graphql_idl_parser_18, "^(?u:\\{)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\})"
+consistent!(graphql_idl_parser_19, "^(?u:\\})");
+
+// grimoire-0.1.0: r"(?s)/\*(?P<config>.*?)\*/"
+consistent!(grimoire_0, r"(?s)/\*(?P<config>.*?)\*/");
+
+// phonenumber-0.2.0+8.9.0: r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?"
+consistent!(phonenumber_0, r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?");
+
+// phonenumber-0.2.0+8.9.0: r"[, \[\]]"
+consistent!(phonenumber_1, r"[, \[\]]");
+
+// phonenumber-0.2.0+8.9.0: r"[\\/] *x"
+consistent!(phonenumber_2, r"[\\/] *x");
+
+// phonenumber-0.2.0+8.9.0: r"[[\P{N}&&\P{L}]&&[^#]]+$"
+consistent!(phonenumber_3, r"[[\P{N}&&\P{L}]&&[^#]]+$");
+
+// phonenumber-0.2.0+8.9.0: r"(?:.*?[A-Za-z]){3}.*"
+consistent!(phonenumber_4, r"(?:.*?[A-Za-z]){3}.*");
+
+// phonenumber-0.2.0+8.9.0: r"(\D+)"
+consistent!(phonenumber_5, r"(\D+)");
+
+// phonenumber-0.2.0+8.9.0: r"(\$\d)"
+consistent!(phonenumber_6, r"(\$\d)");
+
+// phonenumber-0.2.0+8.9.0: r"\(?\$1\)?"
+consistent!(phonenumber_7, r"\(?\$1\)?");
+
+// phone_number-0.1.0: r"\D"
+consistent!(phone_number_0, r"\D");
+
+// phone_number-0.1.0: r"^0+"
+consistent!(phone_number_1, r"^0+");
+
+// phone_number-0.1.0: r"^89"
+consistent!(phone_number_2, r"^89");
+
+// phone_number-0.1.0: r"^8+"
+consistent!(phone_number_3, r"^8+");
+
+// phile-0.1.4: r"^ *(\^_*\^) *$"
+consistent!(phile_0, r"^ *(\^_*\^) *$");
+
+// phile-0.1.4: r"^[_\p{XID_Start}]$"
+consistent!(phile_1, r"^[_\p{XID_Start}]$");
+
+// phile-0.1.4: r"^\p{XID_Continue}$"
+consistent!(phile_2, r"^\p{XID_Continue}$");
+
+// uritemplate-0.1.2: "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])"
+consistent!(uritemplate_0, "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])");
+
+// urdf-rs-0.4.2: "^package://(\\w+)/"
+consistent!(urdf_rs_0, "^package://(\\w+)/");
+
+// url-match-0.1.7: r"(?P<key>[?&.])"
+consistent!(url_match_0, r"(?P<key>[?&.])");
+
+// url-match-0.1.7: r":(?P<key>[a-zA-Z0-9_-]+)"
+consistent!(url_match_1, r":(?P<key>[a-zA-Z0-9_-]+)");
+
+// tsm-sys-0.1.0: r"hello world"
+consistent!(tsm_sys_0, r"hello world");
+
+// deb-version-0.1.0: "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$"
+consistent!(deb_version_0, "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$");
+
+// debcargo-2.1.0: r"^(?i)(a|an|the)\s+"
+consistent!(debcargo_0, r"^(?i)(a|an|the)\s+");
+
+// debcargo-2.1.0: r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
+consistent!(debcargo_1, r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+");
+
+// feaders-0.2.0: r"^.*\.h$"
+consistent!(feaders_0, r"^.*\.h$");
+
+// feaders-0.2.0: r"^.*\.c$"
+consistent!(feaders_1, r"^.*\.c$");
+
+// feaders-0.2.0: r"^.*\.hpp$"
+consistent!(feaders_2, r"^.*\.hpp$");
+
+// feaders-0.2.0: r"^.*\.cc$"
+consistent!(feaders_3, r"^.*\.cc$");
+
+// feaders-0.2.0: r"^.*\.cpp$"
+consistent!(feaders_4, r"^.*\.cpp$");
+
+// hyperscan-0.1.6: r"CPtr\(\w+\)"
+consistent!(hyperscan_0, r"CPtr\(\w+\)");
+
+// hyperscan-0.1.6: r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
+consistent!(hyperscan_1, r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$");
+
+// hyperscan-0.1.6: r"RawDatabase<Block>\{db: \w+\}"
+consistent!(hyperscan_2, r"RawDatabase<Block>\{db: \w+\}");
+
+// hyperscan-0.1.6: r"RawSerializedDatabase\{p: \w+, len: \d+\}"
+consistent!(hyperscan_3, r"RawSerializedDatabase\{p: \w+, len: \d+\}");
+
+// ucd-parse-0.1.1: r"[0-9A-F]+"
+consistent!(ucd_parse_0, r"[0-9A-F]+");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_0, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_1, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_2, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_3, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_4, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_5, r".*");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_6, r"^[a-z]+$");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_7, r"^[a-z]+$");
+
+// tin-summer-1.21.4: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_summer_0, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
+consistent!(tin_drummer_1, r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$");
+
+// tin-drummer-1.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|\.js)$"
+consistent!(tin_drummer_3, r".*?\.(stats|conf|h|out|cache.*|\.js)$");
+
+// tin-drummer-1.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_drummer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_5, r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(ibc)$"
+consistent!(tin_drummer_6, r".*?\.(ibc)$");
+
+// tin-drummer-1.0.1: r"\.stack-work|dist-newstyle"
+consistent!(tin_drummer_7, r"\.stack-work|dist-newstyle");
+
+// timmy-0.3.0: r"_NET_WM_PID\(CARDINAL\) = (\d+)"
+consistent!(timmy_0, r"_NET_WM_PID\(CARDINAL\) = (\d+)");
+
+// timmy-0.3.0: r"today|yesterday|now"
+consistent!(timmy_1, r"today|yesterday|now");
+
+// timmy-0.3.0: r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
+consistent!(timmy_2, r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?");
+
+// timmy-0.3.0: r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)"
+consistent!(timmy_3, r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)");
+
+// timmy-0.3.0: r"(?P<hr>\d{2}):(?P<mins>\d{2})"
+consistent!(timmy_4, r"(?P<hr>\d{2}):(?P<mins>\d{2})");
+
+// tinfo-0.5.0: r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
+consistent!(tinfo_0, r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?");
+
+// tinfo-0.5.0: r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]"
+consistent!(tinfo_1, r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]");
+
+// timespan-0.0.4: r"(?:\\\{start\\\}|\\\{end\\\})"
+consistent!(timespan_0, r"(?:\\\{start\\\}|\\\{end\\\})");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_1, r"(.*)\s+-\s+(.*)");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_2, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_3, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_4, r"(.*)\s+-\s+(.*)");
+
+// titlecase-0.10.0: r"[[:lower:]]"
+consistent!(titlecase_0, r"[[:lower:]]");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_0, r"^\d+ (day|week|month|year)s?$");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_1, r"^\d+ (day|week|month|year)s?$");
+
+// yaml-0.2.1: r"^[-+]?(0|[1-9][0-9_]*)$"
+consistent!(yaml_0, r"^[-+]?(0|[1-9][0-9_]*)$");
+
+// yaml-0.2.1: r"^([-+]?)0o?([0-7_]+)$"
+consistent!(yaml_1, r"^([-+]?)0o?([0-7_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0x([0-9a-fA-F_]+)$"
+consistent!(yaml_2, r"^([-+]?)0x([0-9a-fA-F_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0b([0-1_]+)$"
+consistent!(yaml_3, r"^([-+]?)0b([0-1_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
+consistent!(yaml_4, r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$");
+
+// yaml-0.2.1: r"^[+]?(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_5, r"^[+]?(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^-(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_6, r"^-(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^(\.nan|\.NaN|\.NAN)$"
+consistent!(yaml_7, r"^(\.nan|\.NaN|\.NAN)$");
+
+// yaml-0.2.1: r"^(null|Null|NULL|~)$"
+consistent!(yaml_8, r"^(null|Null|NULL|~)$");
+
+// yaml-0.2.1: r"^(true|True|TRUE|yes|Yes|YES)$"
+consistent!(yaml_9, r"^(true|True|TRUE|yes|Yes|YES)$");
+
+// yaml-0.2.1: r"^(false|False|FALSE|no|No|NO)$"
+consistent!(yaml_10, r"^(false|False|FALSE|no|No|NO)$");
+
+// kefia-0.1.0: r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$"
+consistent!(kefia_0, r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$");
+
+// risp-0.7.0: "^(\\s+|;.*?(\n|$))+"
+consistent!(risp_0, "^(\\s+|;.*?(\n|$))+");
+
+// risp-0.7.0: "^\".*?\""
+consistent!(risp_1, "^\".*?\"");
+
+// risp-0.7.0: r"^[^\s\{\}()\[\]]+"
+consistent!(risp_2, r"^[^\s\{\}()\[\]]+");
+
+// risp-0.7.0: r"^-?\d+"
+consistent!(risp_3, r"^-?\d+");
+
+// ripgrep-0.8.1: "^([0-9]+)([KMG])?$"
+consistent!(ripgrep_0, "^([0-9]+)([KMG])?$");
+
+// riquid-0.0.1: r"^\w+"
+consistent!(riquid_0, r"^\w+");
+
+// riquid-0.0.1: r"^\d+"
+consistent!(riquid_1, r"^\d+");
+
+// recursive_disassembler-2.1.2: r"\A(0x)?([a-fA-F0-9]+)\z"
+consistent!(recursive_disassembler_0, r"\A(0x)?([a-fA-F0-9]+)\z");
+
+// remake-0.1.0: r"^[a-zA-Z_][a-zA-Z0-9_]*"
+consistent!(remake_0, r"^[a-zA-Z_][a-zA-Z0-9_]*");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_0, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_1, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_2, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_3, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_4, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_5, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)"
+consistent!(regex_decode_6, r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_7, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_8, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_9, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_10, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_11, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_12, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_13, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-cache-0.2.0: "[0-9]{3}-[0-9]{3}-[0-9]{4}"
+consistent!(regex_cache_0, "[0-9]{3}-[0-9]{3}-[0-9]{4}");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_1, r"^\d+$");
+
+// regex-cache-0.2.0: r"^[a-z]+$"
+consistent!(regex_cache_2, r"^[a-z]+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_3, r"^\d+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_4, r"^\d+$");
+
+// regex_dfa-0.5.0: r"\d{4}-\d{2}-\d{2}"
+consistent!(regex_dfa_0, r"\d{4}-\d{2}-\d{2}");
+
+// reaper-2.0.0: r"^[0-9\p{L} _\\.]{3,16}$"
+consistent!(reaper_0, r"^[0-9\p{L} _\\.]{3,16}$");
+
+// retdec-0.1.0: r"^attachment; filename=(.+)$"
+consistent!(retdec_0, r"^attachment; filename=(.+)$");
+
+// renvsubst-0.1.2: r"(\\)(?P<head>\$[0-9A-Za-z_{])"
+consistent!(renvsubst_0, r"(\\)(?P<head>\$[0-9A-Za-z_{])");
+
+// renvsubst-0.1.2: r"\$([[:word:]]+)"
+consistent!(renvsubst_1, r"\$([[:word:]]+)");
+
+// renvsubst-0.1.2: r"\$\{([[:word:]]+)\}"
+consistent!(renvsubst_2, r"\$\{([[:word:]]+)\}");
+
+// rexpect-0.3.0: r"'[a-z]+'"
+consistent!(rexpect_0, r"'[a-z]+'");
+
+// rexpect-0.3.0: r"^\d{4}-\d{2}-\d{2}$"
+consistent!(rexpect_1, r"^\d{4}-\d{2}-\d{2}$");
+
+// rexpect-0.3.0: r"-\d{2}-"
+consistent!(rexpect_2, r"-\d{2}-");
+
+// luther-0.1.0: "^a(b|c)c*$"
+consistent!(luther_0, "^a(b|c)c*$");
+
+// little_boxes-1.6.0: r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]"
+consistent!(little_boxes_0, r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]");
+
+// libimagentrytag-0.8.0: "^[a-zA-Z]([a-zA-Z0-9_-]*)$"
+consistent!(libimagentrytag_0, "^[a-zA-Z]([a-zA-Z0-9_-]*)$");
+
+// libimaginteraction-0.8.0: r"^[Yy](\n?)$"
+consistent!(libimaginteraction_0, r"^[Yy](\n?)$");
+
+// libimaginteraction-0.8.0: r"^[Nn](\n?)$"
+consistent!(libimaginteraction_1, r"^[Nn](\n?)$");
+
+// libimagutil-0.8.0: "^(?P<KEY>([^=]*))=(.*)$"
+consistent!(libimagutil_0, "^(?P<KEY>([^=]*))=(.*)$");
+
+// libimagutil-0.8.0: "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$"
+consistent!(libimagutil_1, "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$");
+
+// linux_ip-0.1.0: r"\s+"
+consistent!(linux_ip_0, r"\s+");
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_1, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_2, r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_3, r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$"
+consistent!(linux_ip_4, r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$");
+
+// linux_ip-0.1.0: r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
+consistent!(linux_ip_5, r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$");
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_6, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$"
+consistent!(linux_ip_7, r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$");
+
+// linux_ip-0.1.0: r"\s*link/ether\s+([a-f0-9:]+)\s+.*"
+consistent!(linux_ip_8, r"\s*link/ether\s+([a-f0-9:]+)\s+.*");
+
+// linux_ip-0.1.0: r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*"
+consistent!(linux_ip_9, r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*");
+
+// linky-0.1.4: r"[^\w -]"
+consistent!(linky_0, r"[^\w -]");
+
+// linky-0.1.4: r"^(.*):(\d+): [^ ]* ([^ ]*)$"
+consistent!(linky_1, r"^(.*):(\d+): [^ ]* ([^ ]*)$");
+
+// limonite-0.2.1: r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$"
+consistent!(limonite_0, r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$");
+
+// process-queue-0.1.1: r"^[a-zA-Z]+$"
+consistent!(process_queue_0, r"^[a-zA-Z]+$");
+
+// pronghorn-0.1.2: r"^\{([a-zA-Z_]+)\}$"
+consistent!(pronghorn_0, r"^\{([a-zA-Z_]+)\}$");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3}) (.+)\r$)"
+consistent!(protocol_ftp_client_0, "(?m:^(\\d{3}) (.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "\"(.+)\""
+consistent!(protocol_ftp_client_1, "\"(.+)\"");
+
+// protocol-ftp-client-0.1.1: "(\\w+) [Tt]ype: (\\w+)"
+consistent!(protocol_ftp_client_2, "(\\w+) [Tt]ype: (\\w+)");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3})-.+\r$)"
+consistent!(protocol_ftp_client_3, "(?m:^(\\d{3})-.+\r$)");
+
+// protocol-ftp-client-0.1.1: "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
+consistent!(protocol_ftp_client_4, "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)");
+
+// protocol-ftp-client-0.1.1: "(?m:^(.+)\r$)"
+consistent!(protocol_ftp_client_5, "(?m:^(.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
+consistent!(protocol_ftp_client_6, "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$");
+
+// article-date-extractor-0.1.1: r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})"
+consistent!(article_date_extractor_0, r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})");
+
+// article-date-extractor-0.1.1: r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
+consistent!(article_date_extractor_1, r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date");
+
+// arthas_plugin-0.1.1: r"type\((.*)\)"
+consistent!(arthas_plugin_0, r"type\((.*)\)");
+
+// arthas_plugin-0.1.1: r"Vec<(.*)>"
+consistent!(arthas_plugin_1, r"Vec<(.*)>");
+
+// arthas_plugin-0.1.1: r"Option<(.*)>"
+consistent!(arthas_plugin_2, r"Option<(.*)>");
+
+// arthas_plugin-0.1.1: r"HashMap<[a-z0-9A-Z]+, *(.*)>"
+consistent!(arthas_plugin_3, r"HashMap<[a-z0-9A-Z]+, *(.*)>");
+
+// arthas_derive-0.1.0: "Vec *< *(.*) *>"
+consistent!(arthas_derive_0, "Vec *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"Option *< *(.*) *>"
+consistent!(arthas_derive_1, r"Option *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>"
+consistent!(arthas_derive_2, r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>");
+
+// arpabet-0.2.0: r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$"
+consistent!(arpabet_0, r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$");
+
+// arpabet-0.2.0: r"^;;;\s+"
+consistent!(arpabet_1, r"^;;;\s+");
+
+// glossy_codegen-0.2.0: r"/\*.*?\*/|//.*"
+consistent!(glossy_codegen_0, r"/\*.*?\*/|//.*");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$"
+consistent!(glossy_codegen_1, "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$"
+consistent!(glossy_codegen_2, "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$");
+
+// glossy_codegen-0.2.0: r"^\s*#\s*version\s+(\d+)"
+consistent!(glossy_codegen_3, r"^\s*#\s*version\s+(\d+)");
+
+// glossy_codegen-0.2.0: r"^\s*$"
+consistent!(glossy_codegen_4, r"^\s*$");
+
+// gluster-1.0.1: r"(?P<addr>via \S+)"
+consistent!(gluster_0, r"(?P<addr>via \S+)");
+
+// gluster-1.0.1: r"(?P<src>src \S+)"
+consistent!(gluster_1, r"(?P<src>src \S+)");
+
+// gl_helpers-0.1.7: r"(.*)\[\d+\]"
+consistent!(gl_helpers_0, r"(.*)\[\d+\]");
+
+// gl_helpers-0.1.7: r"(\d+).(\d+)"
+consistent!(gl_helpers_1, r"(\d+).(\d+)");
+
+// glr-parser-0.0.1: r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])"
+consistent!(glr_parser_0, r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])");
+
+// glr-parser-0.0.1: r"^\w+$"
+consistent!(glr_parser_1, r"^\w+$");
+
+// glr-parser-0.0.1: "'[^']+'"
+consistent!(glr_parser_2, "'[^']+'");
+
+// hoodlum-0.5.0: r"(?m)//.*"
+consistent!(hoodlum_0, r"(?m)//.*");
+
+// form-checker-0.2.2: r"^1\d{10}$"
+consistent!(form_checker_0, r"^1\d{10}$");
+
+// form-checker-0.2.2: r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$"
+consistent!(form_checker_1, r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$");
+
+// wikibase-0.2.0: r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)"
+consistent!(wikibase_0, r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)");
+
+// wifiscanner-0.3.6: r"Cell [0-9]{2,} - Address:"
+consistent!(wifiscanner_0, r"Cell [0-9]{2,} - Address:");
+
+// wifiscanner-0.3.6: r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
+consistent!(wifiscanner_1, r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}");
+
+// wifiscanner-0.3.6: r"Signal level=(\d+)/100"
+consistent!(wifiscanner_2, r"Signal level=(\d+)/100");
+
+// bbcode-1.0.2: r"(?s)\[b\](.*?)\[/b\]"
+consistent!(bbcode_0, r"(?s)\[b\](.*?)\[/b\]");
+
+// bbcode-1.0.2: r"(?s)\[i\](.*?)\[/i\]"
+consistent!(bbcode_1, r"(?s)\[i\](.*?)\[/i\]");
+
+// bbcode-1.0.2: r"(?s)\[u\](.*?)\[/u\]"
+consistent!(bbcode_2, r"(?s)\[u\](.*?)\[/u\]");
+
+// bbcode-1.0.2: r"(?s)\[s\](.*?)\[/s\]"
+consistent!(bbcode_3, r"(?s)\[s\](.*?)\[/s\]");
+
+// bbcode-1.0.2: r"(?s)\[size=(\d+)](.*?)\[/size\]"
+consistent!(bbcode_4, r"(?s)\[size=(\d+)](.*?)\[/size\]");
+
+// bbcode-1.0.2: r"(?s)\[color=(.+)](.*?)\[/color\]"
+consistent!(bbcode_5, r"(?s)\[color=(.+)](.*?)\[/color\]");
+
+// bbcode-1.0.2: r"(?s)\[center\](.*?)\[/center\]"
+consistent!(bbcode_6, r"(?s)\[center\](.*?)\[/center\]");
+
+// bbcode-1.0.2: r"(?s)\[left\](.*?)\[/left\]"
+consistent!(bbcode_7, r"(?s)\[left\](.*?)\[/left\]");
+
+// bbcode-1.0.2: r"(?s)\[right\](.*?)\[/right\]"
+consistent!(bbcode_8, r"(?s)\[right\](.*?)\[/right\]");
+
+// bbcode-1.0.2: r"(?s)\[table\](.*?)\[/table\]"
+consistent!(bbcode_9, r"(?s)\[table\](.*?)\[/table\]");
+
+// bbcode-1.0.2: r"(?s)\[td\](.*?)\[/td\]"
+consistent!(bbcode_10, r"(?s)\[td\](.*?)\[/td\]");
+
+// bbcode-1.0.2: r"(?s)\[tr\](.*?)\[/tr\]"
+consistent!(bbcode_11, r"(?s)\[tr\](.*?)\[/tr\]");
+
+// bbcode-1.0.2: r"(?s)\[th\](.*?)\[/th\]"
+consistent!(bbcode_12, r"(?s)\[th\](.*?)\[/th\]");
+
+// bbcode-1.0.2: r"(?s)\[url\](.*?)\[/url\]"
+consistent!(bbcode_13, r"(?s)\[url\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[url=(.+)\](.*?)\[/url\]"
+consistent!(bbcode_14, r"(?s)\[url=(.+)\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[quote\](.*?)\[/quote\]"
+consistent!(bbcode_15, r"(?s)\[quote\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[quote=(.+)\](.*?)\[/quote\]"
+consistent!(bbcode_16, r"(?s)\[quote=(.+)\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_17, r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_18, r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_19, r"(?s)\[img(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[ol\](.*?)\[/ol\]"
+consistent!(bbcode_20, r"(?s)\[ol\](.*?)\[/ol\]");
+
+// bbcode-1.0.2: r"(?s)\[ul\](.*?)\[/ul\]"
+consistent!(bbcode_21, r"(?s)\[ul\](.*?)\[/ul\]");
+
+// bbcode-1.0.2: r"(?s)\[list\](.*?)\[/list\]"
+consistent!(bbcode_22, r"(?s)\[list\](.*?)\[/list\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube\](.*?)\[/youtube\]"
+consistent!(bbcode_23, r"(?s)\[youtube\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]"
+consistent!(bbcode_24, r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[li\](.*?)\[/li\]"
+consistent!(bbcode_25, r"(?s)\[li\](.*?)\[/li\]");
+
+// block-utils-0.5.0: r"loop\d+"
+consistent!(block_utils_0, r"loop\d+");
+
+// block-utils-0.5.0: r"ram\d+"
+consistent!(block_utils_1, r"ram\d+");
+
+// block-utils-0.5.0: r"md\d+"
+consistent!(block_utils_2, r"md\d+");
+
+// kvvliveapi-0.1.0: r"^([1-9]) min$"
+consistent!(kvvliveapi_0, r"^([1-9]) min$");
+
+// rfc822_sanitizer-0.3.3: r"(\d{2}):(\d{2}):(\d{2})"
+consistent!(rfc822_sanitizer_0, r"(\d{2}):(\d{2}):(\d{2})");
+
+// rfc822_sanitizer-0.3.3: r"(\d{1,2}):(\d{1,2}):(\d{1,2})"
+consistent!(rfc822_sanitizer_1, r"(\d{1,2}):(\d{1,2}):(\d{1,2})");
+
+// faker-0.0.4: r"[2-9]"
+consistent!(faker_0, r"[2-9]");
+
+// faker-0.0.4: r"[1-9]"
+consistent!(faker_1, r"[1-9]");
+
+// faker-0.0.4: r"[0-9]"
+consistent!(faker_2, r"[0-9]");
+
+// faker-0.0.4: r"\d{10}"
+consistent!(faker_3, r"\d{10}");
+
+// faker-0.0.4: r"\d{1}"
+consistent!(faker_4, r"\d{1}");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_5, r"^\w+");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_6, r"^\w+");
+
+// faker-0.0.4: r"^(\w+\.? ?){2,3}$"
+consistent!(faker_7, r"^(\w+\.? ?){2,3}$");
+
+// faker-0.0.4: r"^[A-Z][a-z]+\.?$"
+consistent!(faker_8, r"^[A-Z][a-z]+\.?$");
+
+// faker-0.0.4: r"^[A-Z][A-Za-z]*\.?$"
+consistent!(faker_9, r"^[A-Z][A-Za-z]*\.?$");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/\w+"
+consistent!(faker_10, r"http://lorempixel.com/100/100/\w+");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/cats"
+consistent!(faker_11, r"http://lorempixel.com/100/100/cats");
+
+// fancy-regex-0.1.0: "(?i:ß)"
+consistent!(fancy_regex_0, "(?i:ß)");
+
+// fancy-regex-0.1.0: "(?i:\\x{0587})"
+consistent!(fancy_regex_1, "(?i:\\x{0587})");
+
+// fancy-regex-0.1.0: "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})"
+consistent!(fancy_regex_2, "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})");
+
+// fancy-prompt-0.1.5: r"/([^/])[^/]+/"
+consistent!(fancy_prompt_0, r"/([^/])[^/]+/");
+
+// fancy-prompt-0.1.5: r"^([^:]+):.*?(?::([^:]+))?$"
+consistent!(fancy_prompt_1, r"^([^:]+):.*?(?::([^:]+))?$");
+
+// fanta-0.2.0: r"^(/?__\w+__)/(.*)"
+consistent!(fanta_0, r"^(/?__\w+__)/(.*)");
+
+// fanta-cli-0.1.1: r"(.)([A-Z])"
+consistent!(fanta_cli_0, r"(.)([A-Z])");
+
+// fanta-cli-0.1.1: "\\{:[^\\s]+\\}"
+consistent!(fanta_cli_1, "\\{:[^\\s]+\\}");
+
+// amethyst_tools-0.7.1: "(?P<last>[^\r])\n"
+consistent!(amethyst_tools_0, "(?P<last>[^\r])\n");
+
+// amigo-0.3.1: r"^-?\d+(\.\d)?"
+consistent!(amigo_0, r"^-?\d+(\.\d)?");
+
+// amigo-0.3.1: r"^[a-zA-Z_]+[\w-]*[!?_]?"
+consistent!(amigo_1, r"^[a-zA-Z_]+[\w-]*[!?_]?");
+
+// amigo-0.3.1: r"^\("
+consistent!(amigo_2, r"^\(");
+
+// amigo-0.3.1: r"^\)"
+consistent!(amigo_3, r"^\)");
+
+// amigo-0.3.1: r"^\s+"
+consistent!(amigo_4, r"^\s+");
+
+// ethcore-logger-1.12.0: "\x1b\\[[^m]+m"
+consistent!(ethcore_logger_0, "\x1b\\[[^m]+m");
+
+// dash2html-1.0.1: r"__.*?__"
+consistent!(dash2html_0, r"__.*?__");
+
+// dash2html-1.0.1: r"(?i)@(?:time|clipboard|cursor|date)"
+consistent!(dash2html_1, r"(?i)@(?:time|clipboard|cursor|date)");
+
+// os_type-2.0.0: r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$"
+consistent!(os_type_0, r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$");
+
+// os_type-2.0.0: r"ProductName:\s([\w\s]+)\n"
+consistent!(os_type_1, r"ProductName:\s([\w\s]+)\n");
+
+// os_type-2.0.0: r"ProductVersion:\s(\w+\.\w+\.\w+)"
+consistent!(os_type_2, r"ProductVersion:\s(\w+\.\w+\.\w+)");
+
+// os_type-2.0.0: r"BuildVersion:\s(\w+)"
+consistent!(os_type_3, r"BuildVersion:\s(\w+)");
+
+// os_type-2.0.0: r"(\w+) Linux release"
+consistent!(os_type_4, r"(\w+) Linux release");
+
+// os_type-2.0.0: r"release\s([\w\.]+)"
+consistent!(os_type_5, r"release\s([\w\.]+)");
+
+// os_type-2.0.0: r"Distributor ID:\s(\w+)"
+consistent!(os_type_6, r"Distributor ID:\s(\w+)");
+
+// os_type-2.0.0: r"Release:\s([\w\.]+)"
+consistent!(os_type_7, r"Release:\s([\w\.]+)");
+
+// bindgen-0.37.0: r"typename type\-parameter\-\d+\-\d+::.+"
+consistent!(bindgen_0, r"typename type\-parameter\-\d+\-\d+::.+");
+
+// imap-0.8.1: "^+(.*)\r\n"
+consistent!(imap_0, "^+(.*)\r\n");
+
+// image-base64-0.1.0: r"^ffd8ffe0"
+consistent!(image_base64_0, r"^ffd8ffe0");
+
+// image-base64-0.1.0: r"^89504e47"
+consistent!(image_base64_1, r"^89504e47");
+
+// image-base64-0.1.0: r"^47494638"
+consistent!(image_base64_2, r"^47494638");
+
+// json-pointer-0.3.2: "^(/([^/~]|~[01])*)*$"
+consistent!(json_pointer_0, "^(/([^/~]|~[01])*)*$");
+
+// json-pointer-0.3.2: "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$"
+consistent!(json_pointer_1, "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$");
+
+// mysql_common-0.7.0: r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB"
+consistent!(mysql_common_0, r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB");
+
+// mysql_common-0.7.0: r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)"
+consistent!(mysql_common_1, r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)");
+
+// government_id-0.1.0: r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$"
+consistent!(government_id_0, r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$");
+
+// ohmers-0.1.1: r"UniqueIndexViolation: (\w+)"
+consistent!(ohmers_0, r"UniqueIndexViolation: (\w+)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_0, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_1, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_2, r"(.*) you are (.*)");
+
+// chema-0.0.5: "^\\s*\\*"
+consistent!(chema_0, "^\\s*\\*");
+
+// chema-0.0.5: "^\\s*@(\\w+)\\s+(.*)"
+consistent!(chema_1, "^\\s*@(\\w+)\\s+(.*)");
+
+// chord3-0.3.0: r"^\s*#"
+consistent!(chord3_0, r"^\s*#");
+
+// chord3-0.3.0: r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}"
+consistent!(chord3_1, r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}");
+
+// chord3-0.3.0: r"\{(eot|end_of_tab):?\s*"
+consistent!(chord3_2, r"\{(eot|end_of_tab):?\s*");
+
+// chord3-0.3.0: r"([^\[]*)(?:\[([^\]]*)\])?"
+consistent!(chord3_3, r"([^\[]*)(?:\[([^\]]*)\])?");
+
+// checkmail-0.1.1: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
+consistent!(checkmail_0, "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_0, r"\b\w\w+\b");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_1, r"\b\w\w+\b");
+
+// cniguru-0.1.0: r"\(id: (\d+)\)"
+consistent!(cniguru_0, r"\(id: (\d+)\)");
+
+// upm_lib-0.3.0: r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$"
+consistent!(upm_lib_0, r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$");
+
+// avro-0.2.1: r"^\s*(\*+(\s+))?"
+consistent!(avro_0, r"^\s*(\*+(\s+))?");
+
+// avro-0.2.1: r"^\s*(\*+)?"
+consistent!(avro_1, r"^\s*(\*+)?");
+
+// nomi-0.0.2: "[0-9]+"
+consistent!(nomi_0, "[0-9]+");
+
+// nodes-0.1.0: "([0-9]+)@(?:nodes|n)?:([^@]+)?"
+consistent!(nodes_0, "([0-9]+)@(?:nodes|n)?:([^@]+)?");
+
+// not-stakkr-1.0.0: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(not_stakkr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// notetxt-0.0.1: "^([A-Za-z0-9 -_:]+)\n-+\n"
+consistent!(notetxt_0, "^([A-Za-z0-9 -_:]+)\n-+\n");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$"
+consistent!(nail_0, r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+$"
+consistent!(nail_1, r"^-?[0-9]+$");
+
+// askalono-0.2.0: r"[^\w\s\pP]+"
+consistent!(askalono_0, r"[^\w\s\pP]+");
+
+// askalono-0.2.0: r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+"
+consistent!(askalono_1, r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+");
+
+// askalono-0.2.0: r"\p{Pd}+"
+consistent!(askalono_2, r"\p{Pd}+");
+
+// askalono-0.2.0: r"\p{Ps}+"
+consistent!(askalono_3, r"\p{Ps}+");
+
+// askalono-0.2.0: r"\p{Pe}+"
+consistent!(askalono_4, r"\p{Pe}+");
+
+// askalono-0.2.0: r"\p{Pc}+"
+consistent!(askalono_5, r"\p{Pc}+");
+
+// askalono-0.2.0: r"[©Ⓒⓒ]"
+consistent!(askalono_6, r"[©Ⓒⓒ]");
+
+// askalono-0.2.0: r"[\r\n\v\f]"
+consistent!(askalono_7, r"[\r\n\v\f]");
+
+// askalono-0.2.0: r"\n{3,}"
+consistent!(askalono_8, r"\n{3,}");
+
+// askalono-0.2.0: r"[^\w\s]+"
+consistent!(askalono_9, r"[^\w\s]+");
+
+// askalono-0.2.0: r"\s+"
+consistent!(askalono_10, r"\s+");
+
+// assembunny_plus-0.0.3: r"[^0-9a-zA-Z_]"
+consistent!(assembunny_plus_0, r"[^0-9a-zA-Z_]");
+
+// assembunny_plus-0.0.3: r"[0-9]"
+consistent!(assembunny_plus_1, r"[0-9]");
+
+// salt-compressor-0.4.0: r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
+consistent!(salt_compressor_0, r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$");
+
+// sabisabi-0.4.1: r"</?[^>]+?>"
+consistent!(sabisabi_0, r"</?[^>]+?>");
+
+// sabisabi-0.4.1: r"\([^)]*\)"
+consistent!(sabisabi_1, r"\([^)]*\)");
+
+// sassers-0.13.5-h28: "@import \"([^\"]*)\";"
+consistent!(sassers_0, "@import \"([^\"]*)\";");
+
+// shadowsocks-0.6.2: r"[A-Za-z\d-]{1,63}$"
+consistent!(shadowsocks_0, r"[A-Za-z\d-]{1,63}$");
+
+// shkeleton-0.1.5: "[abc]+"
+consistent!(shkeleton_0, "[abc]+");
+
+// shellwords-0.1.0: r"([^A-Za-z0-9_\-.,:/@\n])"
+consistent!(shellwords_0, r"([^A-Za-z0-9_\-.,:/@\n])");
+
+// shellwords-0.1.0: r"\n"
+consistent!(shellwords_1, r"\n");
+
+// shush-0.1.5: "(?P<num>[0-9]+)(?P<units>[dhms])"
+consistent!(shush_0, "(?P<num>[0-9]+)(?P<units>[dhms])");
+
+// woothee-0.8.0: r"(?:Chrome|CrMo|CriOS)/([.0-9]+)"
+consistent!(woothee_0, r"(?:Chrome|CrMo|CriOS)/([.0-9]+)");
+
+// woothee-0.8.0: r"Vivaldi/([.0-9]+)"
+consistent!(woothee_1, r"Vivaldi/([.0-9]+)");
+
+// woothee-0.8.0: r"Firefox/([.0-9]+)"
+consistent!(woothee_2, r"Firefox/([.0-9]+)");
+
+// woothee-0.8.0: r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$"
+consistent!(woothee_3, r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$");
+
+// woothee-0.8.0: r"FxiOS/([.0-9]+)"
+consistent!(woothee_4, r"FxiOS/([.0-9]+)");
+
+// woothee-0.8.0: r"\(([^;)]+);FOMA;"
+consistent!(woothee_5, r"\(([^;)]+);FOMA;");
+
+// woothee-0.8.0: r"jig browser[^;]+; ([^);]+)"
+consistent!(woothee_6, r"jig browser[^;]+; ([^);]+)");
+
+// woothee-0.8.0: r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)"
+consistent!(woothee_7, r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)");
+
+// woothee-0.8.0: r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)"
+consistent!(woothee_8, r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)");
+
+// woothee-0.8.0: r"(?i)(?:feed|web) ?parser"
+consistent!(woothee_9, r"(?i)(?:feed|web) ?parser");
+
+// woothee-0.8.0: r"(?i)watch ?dog"
+consistent!(woothee_10, r"(?i)watch ?dog");
+
+// woothee-0.8.0: r"Edge/([.0-9]+)"
+consistent!(woothee_11, r"Edge/([.0-9]+)");
+
+// woothee-0.8.0: r"MSIE ([.0-9]+);"
+consistent!(woothee_12, r"MSIE ([.0-9]+);");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_13, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"Opera[/ ]([.0-9]+)"
+consistent!(woothee_14, r"Opera[/ ]([.0-9]+)");
+
+// woothee-0.8.0: r"OPR/([.0-9]+)"
+consistent!(woothee_15, r"OPR/([.0-9]+)");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_16, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)"
+consistent!(woothee_17, r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Trident/([.0-9]+);"
+consistent!(woothee_18, r"Trident/([.0-9]+);");
+
+// woothee-0.8.0: r" rv:([.0-9]+)"
+consistent!(woothee_19, r" rv:([.0-9]+)");
+
+// woothee-0.8.0: r"IEMobile/([.0-9]+);"
+consistent!(woothee_20, r"IEMobile/([.0-9]+);");
+
+// woothee-0.8.0: r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)"
+consistent!(woothee_21, r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Windows ([ .a-zA-Z0-9]+)[;\\)]"
+consistent!(woothee_22, r"Windows ([ .a-zA-Z0-9]+)[;\\)]");
+
+// woothee-0.8.0: r"^Phone(?: OS)? ([.0-9]+)"
+consistent!(woothee_23, r"^Phone(?: OS)? ([.0-9]+)");
+
+// woothee-0.8.0: r"iP(hone;|ad;|od) .*like Mac OS X"
+consistent!(woothee_24, r"iP(hone;|ad;|od) .*like Mac OS X");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_25, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"rv:(\d+\.\d+\.\d+)"
+consistent!(woothee_26, r"rv:(\d+\.\d+\.\d+)");
+
+// woothee-0.8.0: r"FreeBSD ([^;\)]+);"
+consistent!(woothee_27, r"FreeBSD ([^;\)]+);");
+
+// woothee-0.8.0: r"CrOS ([^\)]+)\)"
+consistent!(woothee_28, r"CrOS ([^\)]+)\)");
+
+// woothee-0.8.0: r"Android[- ](\d+\.\d+(?:\.\d+)?)"
+consistent!(woothee_29, r"Android[- ](\d+\.\d+(?:\.\d+)?)");
+
+// woothee-0.8.0: r"PSP \(PlayStation Portable\); ([.0-9]+)\)"
+consistent!(woothee_30, r"PSP \(PlayStation Portable\); ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PLAYSTATION 3;? ([.0-9]+)\)"
+consistent!(woothee_31, r"PLAYSTATION 3;? ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation Vita ([.0-9]+)\)"
+consistent!(woothee_32, r"PlayStation Vita ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation 4 ([.0-9]+)\)"
+consistent!(woothee_33, r"PlayStation 4 ([.0-9]+)\)");
+
+// woothee-0.8.0: r"BB10(?:.+)Version/([.0-9]+) "
+consistent!(woothee_34, r"BB10(?:.+)Version/([.0-9]+) ");
+
+// woothee-0.8.0: r"BlackBerry(?:\d+)/([.0-9]+) "
+consistent!(woothee_35, r"BlackBerry(?:\d+)/([.0-9]+) ");
+
+// woothee-0.8.0: r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
+consistent!(woothee_36, r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X");
+
+// woothee-0.8.0: r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)"
+consistent!(woothee_37, r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)");
+
+// woothee-0.8.0: r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
+consistent!(woothee_38, r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)");
+
+// woothee-0.8.0: r"[- ]HttpClient(/|$)"
+consistent!(woothee_39, r"[- ]HttpClient(/|$)");
+
+// woothee-0.8.0: r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
+consistent!(woothee_40, r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)");
+
+// woothee-0.8.0: r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)"
+consistent!(woothee_41, r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)");
+
+// woothee-0.8.0: r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
+consistent!(woothee_42, r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)");
+
+// woothee-0.8.0: r"Sleipnir/([.0-9]+)"
+consistent!(woothee_43, r"Sleipnir/([.0-9]+)");
+
+// word_replace-0.0.3: r"@@[a-z|A-Z|\d]+@@"
+consistent!(word_replace_0, r"@@[a-z|A-Z|\d]+@@");
+
+// wordcount-0.1.0: r"\w+"
+consistent!(wordcount_0, r"\w+");
+
+// just-0.3.12: "^([^=]+)=(.*)$"
+consistent!(just_0, "^([^=]+)=(.*)$");
+
+// emote-0.1.0: r":[a-zA-Z_]+?:"
+consistent!(emote_0, r":[a-zA-Z_]+?:");
+
+// emojicons-1.0.1: r":([a-zA-Z0-9_+-]+):"
+consistent!(emojicons_0, r":([a-zA-Z0-9_+-]+):");
+
+// git2_codecommit-0.1.2: r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
+consistent!(git2_codecommit_0, r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com");
+
+// git-workarea-3.1.2: r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
+consistent!(git_workarea_0, r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$");
+
+// git-shell-enforce-directory-1.0.0: r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
+consistent!(git_shell_enforce_directory_0, r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$");
+
+// git-journal-1.6.3: r"[ \n]:(.*?):"
+consistent!(git_journal_0, r"[ \n]:(.*?):");
+
+// git-find-0.3.2: r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
+consistent!(git_find_0, r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$");
+
+// gitlab-api-0.6.0: r"private_token=\w{20}"
+consistent!(gitlab_api_0, r"private_token=\w{20}");
+
+// td-client-0.7.0: "^(http://|https://)"
+consistent!(td_client_0, "^(http://|https://)");
+
+// karaconv-0.3.0: r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)"
+consistent!(karaconv_0, r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)");
+
+// katana-1.0.2: r"(?P<comp>et al\.)(?:\.)"
+consistent!(katana_0, r"(?P<comp>et al\.)(?:\.)");
+
+// katana-1.0.2: r"\.{3}"
+consistent!(katana_1, r"\.{3}");
+
+// katana-1.0.2: r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)"
+consistent!(katana_2, r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)");
+
+// katana-1.0.2: r"\s\.(?P<nums>[0-9]+)"
+consistent!(katana_3, r"\s\.(?P<nums>[0-9]+)");
+
+// katana-1.0.2: r"(?:[A-Za-z]\.){2,}"
+consistent!(katana_4, r"(?:[A-Za-z]\.){2,}");
+
+// katana-1.0.2: r"(?P<init>[A-Z])(?P<point>\.)"
+consistent!(katana_5, r"(?P<init>[A-Z])(?P<point>\.)");
+
+// katana-1.0.2: r"(?P<title>[A-Z][a-z]{1,3})(\.)"
+consistent!(katana_6, r"(?P<title>[A-Z][a-z]{1,3})(\.)");
+
+// katana-1.0.2: r"&==&(?P<p>[.!?])"
+consistent!(katana_7, r"&==&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\^&(?P<p>[.!?])"
+consistent!(katana_8, r"&\^&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\*\*&(?P<p>[.!?])"
+consistent!(katana_9, r"&\*\*&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&=&(?P<p>[.!?])"
+consistent!(katana_10, r"&=&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&##&(?P<p>[.!?])"
+consistent!(katana_11, r"&##&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\$&(?P<p>[.!?])"
+consistent!(katana_12, r"&\$&(?P<p>[.!?])");
+
+// kailua_syntax-1.1.0: r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)"
+consistent!(kailua_syntax_0, r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)");
+
+// kailua_syntax-1.1.0: r"<(\d+)>"
+consistent!(kailua_syntax_1, r"<(\d+)>");
+
+// ftp-3.0.1: r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)"
+consistent!(ftp_0, r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)");
+
+// ftp-3.0.1: r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b"
+consistent!(ftp_1, r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b");
+
+// ftp-3.0.1: r"\s+(\d+)\s*$"
+consistent!(ftp_2, r"\s+(\d+)\s*$");
+
+// vat-0.1.0: r"<countryCode>(.*?)</countryCode>"
+consistent!(vat_0, r"<countryCode>(.*?)</countryCode>");
+
+// vat-0.1.0: r"<vatNumber>(.*?)</vatNumber>"
+consistent!(vat_1, r"<vatNumber>(.*?)</vatNumber>");
+
+// vat-0.1.0: r"<name>(.*?)</name>"
+consistent!(vat_2, r"<name>(.*?)</name>");
+
+// vat-0.1.0: r"<address>(?s)(.*?)(?-s)</address>"
+consistent!(vat_3, r"<address>(?s)(.*?)(?-s)</address>");
+
+// vat-0.1.0: r"<valid>(true|false)</valid>"
+consistent!(vat_4, r"<valid>(true|false)</valid>");
+
+// vat-0.1.0: r"^ATU\d{8}$"
+consistent!(vat_5, r"^ATU\d{8}$");
+
+// vat-0.1.0: r"^BE0?\d{9, 10}$"
+consistent!(vat_6, r"^BE0?\d{9, 10}$");
+
+// vat-0.1.0: r"^BG\d{9,10}$"
+consistent!(vat_7, r"^BG\d{9,10}$");
+
+// vat-0.1.0: r"^HR\d{11}$"
+consistent!(vat_8, r"^HR\d{11}$");
+
+// vat-0.1.0: r"^CY\d{8}[A-Z]$"
+consistent!(vat_9, r"^CY\d{8}[A-Z]$");
+
+// vat-0.1.0: r"^CZ\d{8,10}$"
+consistent!(vat_10, r"^CZ\d{8,10}$");
+
+// vat-0.1.0: r"^DK\d{8}$"
+consistent!(vat_11, r"^DK\d{8}$");
+
+// vat-0.1.0: r"^EE\d{9}$"
+consistent!(vat_12, r"^EE\d{9}$");
+
+// vat-0.1.0: r"^FI\d{8}$"
+consistent!(vat_13, r"^FI\d{8}$");
+
+// vat-0.1.0: r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$"
+consistent!(vat_14, r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$");
+
+// vat-0.1.0: r"^DE\d{9}$"
+consistent!(vat_15, r"^DE\d{9}$");
+
+// vat-0.1.0: r"^EL\d{9}$"
+consistent!(vat_16, r"^EL\d{9}$");
+
+// vat-0.1.0: r"^HU\d{8}$"
+consistent!(vat_17, r"^HU\d{8}$");
+
+// vat-0.1.0: r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$"
+consistent!(vat_18, r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$");
+
+// vat-0.1.0: r"^IT\d{11}$"
+consistent!(vat_19, r"^IT\d{11}$");
+
+// vat-0.1.0: r"^LV\d{11}$"
+consistent!(vat_20, r"^LV\d{11}$");
+
+// vat-0.1.0: r"^LT(\d{9}|\d{12})$"
+consistent!(vat_21, r"^LT(\d{9}|\d{12})$");
+
+// vat-0.1.0: r"^LU\d{8}$"
+consistent!(vat_22, r"^LU\d{8}$");
+
+// vat-0.1.0: r"^MT\d{8}$"
+consistent!(vat_23, r"^MT\d{8}$");
+
+// vat-0.1.0: r"^NL\d{9}B\d{2}$"
+consistent!(vat_24, r"^NL\d{9}B\d{2}$");
+
+// vat-0.1.0: r"^PL\d{10}$"
+consistent!(vat_25, r"^PL\d{10}$");
+
+// vat-0.1.0: r"^PT\d{9}$"
+consistent!(vat_26, r"^PT\d{9}$");
+
+// vat-0.1.0: r"^RO\d{2,10}$"
+consistent!(vat_27, r"^RO\d{2,10}$");
+
+// vat-0.1.0: r"^SK\d{10}$"
+consistent!(vat_28, r"^SK\d{10}$");
+
+// vat-0.1.0: r"^SI\d{8}$"
+consistent!(vat_29, r"^SI\d{8}$");
+
+// vat-0.1.0: r"^ES[A-Z0-9]\d{7}[A-Z0-9]$"
+consistent!(vat_30, r"^ES[A-Z0-9]\d{7}[A-Z0-9]$");
+
+// vat-0.1.0: r"^SE\d{10}01$"
+consistent!(vat_31, r"^SE\d{10}01$");
+
+// vat-0.1.0: r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$"
+consistent!(vat_32, r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$");
+
+// eve-0.1.1: r"\{\{(.*)\}\}"
+consistent!(eve_0, r"\{\{(.*)\}\}");
+
+// egc-0.1.2: "^mio"
+consistent!(egc_0, "^mio");
+
+// pew-0.2.3: ""
+consistent!(pew_0, "");
+
+// pew-0.2.3: ""
+consistent!(pew_1, "");
+
+// mob-0.4.3: "y"
+consistent!(mob_0, "y");
+
+// lit-0.2.8: "@([a-z]+)"
+consistent!(lit_0, "@([a-z]+)");
+
+// lit-0.2.8: "([A-Z-]+):(.*)"
+consistent!(lit_1, "([A-Z-]+):(.*)");
+
+// lit-0.2.8: "^[a-zA-Z_][a-zA-Z0-9_]*$"
+consistent!(lit_2, "^[a-zA-Z_][a-zA-Z0-9_]*$");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_0, r"\d+\.\d+\.\d+");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_1, r"\d+\.\d+\.\d+");
+
+// orm-0.2.0: r"^Vec<(.+)>$"
+consistent!(orm_0, r"^Vec<(.+)>$");
+
+// sgf-0.1.5: r"\\(\r\n|\n\r|\n|\r)"
+consistent!(sgf_0, r"\\(\r\n|\n\r|\n|\r)");
+
+// sgf-0.1.5: r"\\(.)"
+consistent!(sgf_1, r"\\(.)");
+
+// sgf-0.1.5: r"\r\n|\n\r|\n|\r"
+consistent!(sgf_2, r"\r\n|\n\r|\n|\r");
+
+// sgf-0.1.5: r"([\]\\:])"
+consistent!(sgf_3, r"([\]\\:])");
+
+// dok-0.2.0: "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
+consistent!(dok_0, "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$");
+
+// d20-0.1.0: r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)"
+consistent!(d20_0, r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)");
+
+// dvb-0.3.0: "E"
+consistent!(dvb_0, "E");
+
+// dvb-0.3.0: "^F"
+consistent!(dvb_1, "^F");
+
+// dvb-0.3.0: "^S"
+consistent!(dvb_2, "^S");
+
+// ger-0.2.0: r"Change-Id: (I[a-f0-9]{40})$"
+consistent!(ger_0, r"Change-Id: (I[a-f0-9]{40})$");
+
+// ger-0.2.0: r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
+consistent!(ger_1, r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$");
+
+// n5-0.2.1: r"(\d+)(\.(\d+))?(\.(\d+))?(.*)"
+consistent!(n5_0, r"(\d+)(\.(\d+))?(\.(\d+))?(.*)");
+
+// po-0.1.4: r"[A-Za-z0-9]"
+consistent!(po_0, r"[A-Za-z0-9]");
+
+// carnix-0.8.5: "path is (‘|')?([^’'\n]*)(’|')?"
+consistent!(carnix_0, "path is (‘|')?([^’'\n]*)(’|')?");
+
+// carnix-0.8.5: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?"
+consistent!(carnix_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?");
+
+// carnix-0.8.5: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_2, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// carnix-0.8.5: r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_3, r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// caseless-0.2.1: r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$"
+consistent!(caseless_0, r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$");
+
+// caseless-0.2.1: r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);"
+consistent!(caseless_1, r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);");
+
+// cabot-0.2.0: "\r?\n\r?\n"
+consistent!(cabot_0, "\r?\n\r?\n");
+
+// cabot-0.2.0: "\r?\n"
+consistent!(cabot_1, "\r?\n");
+
+// card-validate-2.2.1: r"^600"
+consistent!(card_validate_0, r"^600");
+
+// card-validate-2.2.1: r"^5019"
+consistent!(card_validate_1, r"^5019");
+
+// card-validate-2.2.1: r"^4"
+consistent!(card_validate_2, r"^4");
+
+// card-validate-2.2.1: r"^(5[1-5]|2[2-7])"
+consistent!(card_validate_3, r"^(5[1-5]|2[2-7])");
+
+// card-validate-2.2.1: r"^3[47]"
+consistent!(card_validate_4, r"^3[47]");
+
+// card-validate-2.2.1: r"^3[0689]"
+consistent!(card_validate_5, r"^3[0689]");
+
+// card-validate-2.2.1: r"^6([045]|22)"
+consistent!(card_validate_6, r"^6([045]|22)");
+
+// card-validate-2.2.1: r"^(62|88)"
+consistent!(card_validate_7, r"^(62|88)");
+
+// card-validate-2.2.1: r"^35"
+consistent!(card_validate_8, r"^35");
+
+// card-validate-2.2.1: r"^[0-9]+$"
+consistent!(card_validate_9, r"^[0-9]+$");
+
+// cargo-testify-0.3.0: r"\d{1,} passed.*filtered out"
+consistent!(cargo_testify_0, r"\d{1,} passed.*filtered out");
+
+// cargo-testify-0.3.0: r"error(:|\[).*"
+consistent!(cargo_testify_1, r"error(:|\[).*");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_0, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_1, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_2, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_3, r"<(.*?)>");
+
+// cargo-incremental-0.1.23: r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
+consistent!(cargo_incremental_0, r"(?m)^incremental: re-using (\d+) out of (\d+) modules$");
+
+// cargo-incremental-0.1.23: "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$"
+consistent!(cargo_incremental_1, "(?m)(warning|error): (.*)\n  --> ([^:]:\\d+:\\d+)$");
+
+// cargo-incremental-0.1.23: r"(?m)^test (.*) \.\.\. (\w+)"
+consistent!(cargo_incremental_2, r"(?m)^test (.*) \.\.\. (\w+)");
+
+// cargo-incremental-0.1.23: r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
+consistent!(cargo_incremental_3, r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured");
+
+// cargo-testjs-0.1.2: r"^[^-]+-[0-9a-f]+\.js$"
+consistent!(cargo_testjs_0, r"^[^-]+-[0-9a-f]+\.js$");
+
+// cargo-tarpaulin-0.6.2: r"\s*//"
+consistent!(cargo_tarpaulin_0, r"\s*//");
+
+// cargo-tarpaulin-0.6.2: r"/\*"
+consistent!(cargo_tarpaulin_1, r"/\*");
+
+// cargo-tarpaulin-0.6.2: r"\*/"
+consistent!(cargo_tarpaulin_2, r"\*/");
+
+// cargo-culture-kit-0.1.0: r"^fo"
+consistent!(cargo_culture_kit_0, r"^fo");
+
+// cargo-screeps-0.1.3: "\\s+"
+consistent!(cargo_screeps_0, "\\s+");
+
+// cargo-brew-0.1.4: r"`(\S+) v([0-9.]+)"
+consistent!(cargo_brew_0, r"`(\S+) v([0-9.]+)");
+
+// cargo-release-0.10.2: "^\\[.+\\]"
+consistent!(cargo_release_0, "^\\[.+\\]");
+
+// cargo-release-0.10.2: "^\\[\\[.+\\]\\]"
+consistent!(cargo_release_1, "^\\[\\[.+\\]\\]");
+
+// cargo-edit-0.3.0-beta.1: r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(cargo_edit_0, r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$");
+
+// cargo-edit-0.3.0-beta.1: r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(cargo_edit_1, r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$");
+
+// cargo-disassemble-0.1.1: ".*"
+consistent!(cargo_disassemble_0, ".*");
+
+// cargo-demangle-0.1.2: r"(?m)(?P<symbol>_ZN[0-9]+.*E)"
+consistent!(cargo_demangle_0, r"(?m)(?P<symbol>_ZN[0-9]+.*E)");
+
+// cargo-coverage-annotations-0.1.5: r"^\s*\}(?:\)*;?|\s*else\s*\{)$"
+consistent!(cargo_coverage_annotations_0, r"^\s*\}(?:\)*;?|\s*else\s*\{)$");
+
+// cargo-urlcrate-1.0.1: "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]"
+consistent!(cargo_urlcrate_0, "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]");
+
+// cargo-script-0.2.8: r"^\s*\*( |$)"
+consistent!(cargo_script_0, r"^\s*\*( |$)");
+
+// cargo-script-0.2.8: r"^(\s+)"
+consistent!(cargo_script_1, r"^(\s+)");
+
+// cargo-script-0.2.8: r"/\*|\*/"
+consistent!(cargo_script_2, r"/\*|\*/");
+
+// cargo-script-0.2.8: r"^\s*//!"
+consistent!(cargo_script_3, r"^\s*//!");
+
+// cargo-script-0.2.8: r"^#![^\[].*?(\r\n|\n)"
+consistent!(cargo_script_4, r"^#![^\[].*?(\r\n|\n)");
+
+// cargo-update-1.5.2: r"cargo-install-update\.exe-v.+"
+consistent!(cargo_update_0, r"cargo-install-update\.exe-v.+");
+
+// canteen-0.4.1: r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
+consistent!(canteen_0, r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$");
+
+// thruster-cli-0.1.3: r"(.)([A-Z])"
+consistent!(thruster_cli_0, r"(.)([A-Z])");
+
+// thieves-cant-0.1.0: "([Z]+)$"
+consistent!(thieves_cant_0, "([Z]+)$");
+
+// codeowners-0.1.3: r"^@\S+/\S+"
+consistent!(codeowners_0, r"^@\S+/\S+");
+
+// codeowners-0.1.3: r"^@\S+"
+consistent!(codeowners_1, r"^@\S+");
+
+// codeowners-0.1.3: r"^\S+@\S+"
+consistent!(codeowners_2, r"^\S+@\S+");
+
+// conserve-0.4.2: r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$"
+consistent!(conserve_0, r"^b0000 {21} complete   20[-0-9T:+]+\s +\d+s\n$");
+
+// commodore-0.3.0: r"(?P<greeting>\S+?) (?P<name>\S+?)$"
+consistent!(commodore_0, r"(?P<greeting>\S+?) (?P<name>\S+?)$");
+
+// corollary-0.3.0: r"([ \t]*)```haskell([\s\S]*?)```"
+consistent!(corollary_0, r"([ \t]*)```haskell([\s\S]*?)```");
+
+// corollary-0.3.0: r"\b((?:a|b|t)\d*)\b"
+consistent!(corollary_1, r"\b((?:a|b|t)\d*)\b");
+
+// colorizex-0.1.3: "NB"
+consistent!(colorizex_0, "NB");
+
+// colorstring-0.0.1: r"(?i)\[[a-z0-9_-]+\]"
+consistent!(colorstring_0, r"(?i)\[[a-z0-9_-]+\]");
+
+// colorstring-0.0.1: r"^(?i)(\[[a-z0-9_-]+\])+"
+consistent!(colorstring_1, r"^(?i)(\[[a-z0-9_-]+\])+");
+
+// cosmogony-0.3.0: "name:(.+)"
+consistent!(cosmogony_0, "name:(.+)");
+
+// cobalt-bin-0.12.1: r"(?m:^ {0,3}\[[^\]]+\]:.+$)"
+consistent!(cobalt_bin_0, r"(?m:^ {0,3}\[[^\]]+\]:.+$)");
+
+// comrak-0.2.12: r"[^\p{L}\p{M}\p{N}\p{Pc} -]"
+consistent!(comrak_0, r"[^\p{L}\p{M}\p{N}\p{Pc} -]");
+
+// content-blocker-0.2.3: ""
+consistent!(content_blocker_0, "");
+
+// content-blocker-0.2.3: "(?i)hi"
+consistent!(content_blocker_1, "(?i)hi");
+
+// content-blocker-0.2.3: "http[s]?://domain.org"
+consistent!(content_blocker_2, "http[s]?://domain.org");
+
+// content-blocker-0.2.3: "(?i)http[s]?://domain.org"
+consistent!(content_blocker_3, "(?i)http[s]?://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_4, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_5, "http://domain.org");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_6, "ad.html");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_7, "ad.html");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_8, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_9, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_10, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/hideme.jpg"
+consistent!(content_blocker_11, "http://domain.org/hideme.jpg");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html"
+consistent!(content_blocker_12, "http://domain.org/ok.html");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html\\?except_this=1"
+consistent!(content_blocker_13, "http://domain.org/ok.html\\?except_this=1");
+
+// victoria-dom-0.1.2: "[A-Za-z0-9=]"
+consistent!(victoria_dom_0, "[A-Za-z0-9=]");
+
+// numbat-1.0.0: r"^nsq://"
+consistent!(numbat_0, r"^nsq://");
+
+// airkorea-0.1.2: r"[\s\t\r\n]"
+consistent!(airkorea_0, r"[\s\t\r\n]");
+
+// airkorea-0.1.2: r"([\{\[,])|([\}\]])"
+consistent!(airkorea_1, r"([\{\[,])|([\}\]])");
+
+// airkorea-0.1.2: r"[^.\d]+$"
+consistent!(airkorea_2, r"[^.\d]+$");
+
+// rofl-0.0.1: r"\b"
+// consistent!(rofl_0, r"\b");
+
+// rogcat-0.2.15: r"--------- beginning of.*"
+consistent!(rogcat_0, r"--------- beginning of.*");
+
+// rogcat-0.2.15: r"a|e|i|o|u"
+consistent!(rogcat_1, r"a|e|i|o|u");
+
+// rogcat-0.2.15: r"^(\d+)([kMG])$"
+consistent!(rogcat_2, r"^(\d+)([kMG])$");
+
+// media_filename-0.1.4: "\\.([A-Za-z0-9]{2,4})$"
+consistent!(media_filename_0, "\\.([A-Za-z0-9]{2,4})$");
+
+// media_filename-0.1.4: "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})"
+consistent!(media_filename_1, "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})");
+
+// media_filename-0.1.4: "(?:^\\[([^]]+)\\]|- ?([^-]+)$)"
+consistent!(media_filename_2, "(?:^\\[([^]]+)\\]|- ?([^-]+)$)");
+
+// media_filename-0.1.4: "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
+consistent!(media_filename_3, "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])");
+
+// media_filename-0.1.4: "[sS]([0-9]{1,2})"
+consistent!(media_filename_4, "[sS]([0-9]{1,2})");
+
+// media_filename-0.1.4: "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)"
+consistent!(media_filename_5, "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)");
+
+// media_filename-0.1.4: "((19[0-9]|20[01])[0-9])"
+consistent!(media_filename_6, "((19[0-9]|20[01])[0-9])");
+
+// media_filename-0.1.4: "((?i)xvid|x264|h\\.?264)"
+consistent!(media_filename_7, "((?i)xvid|x264|h\\.?264)");
+
+// media_filename-0.1.4: "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)"
+consistent!(media_filename_8, "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)");
+
+// media_filename-0.1.4: "\\[([0-9A-F]{8})\\]"
+consistent!(media_filename_9, "\\[([0-9A-F]{8})\\]");
+
+// termimage-0.3.2: r"(\d+)[xX](\d+)"
+consistent!(termimage_0, r"(\d+)[xX](\d+)");
+
+// teensy-0.1.0: r".*(\d{4}-\d{2}-\d{2}).*"
+consistent!(teensy_0, r".*(\d{4}-\d{2}-\d{2}).*");
+
+// telescreen-0.1.3: r"<@(.+)>"
+consistent!(telescreen_0, r"<@(.+)>");
+
+// tempus_fugit-0.4.4: r"^(\d+)"
+consistent!(tempus_fugit_0, r"^(\d+)");
+
+// fselect-0.4.1: "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_0, "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fselect-0.4.1: "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_1, "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fs_eventbridge-0.1.0: r"^([A-Z]+)(?:\s(.+))?\s*"
+consistent!(fs_eventbridge_0, r"^([A-Z]+)(?:\s(.+))?\s*");
+
+// joseki-0.0.1: r"(\w{1,2})\[(.+?)\]"
+consistent!(joseki_0, r"(\w{1,2})\[(.+?)\]");
+
+// tweetr-0.2.1: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(tweetr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+"
+consistent!(bullet_core_0, "^(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+"
+consistent!(bullet_core_1, "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ﬀ-ﬆﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼＡ-Ｚａ-ｚｦ-ﾾￂ-ￇￊ-ￏￒ-ￗￚ-ￜ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+"
+consistent!(bullet_core_2, "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ﬀ-ﬆﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼＡ-Ｚａ-ｚｦ-ﾾￂ-ￇￊ-ￏￒ-ￗￚ-ￜ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+");
+
+// bullet_core-0.1.1: "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ﬀ-ﬆﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼＡ-Ｚａ-ｚｦ-ﾾￂ-ￇￊ-ￏￒ-ￗￚ-ￜ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)"
+consistent!(bullet_core_3, "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ﬀ-ﬆﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼＡ-Ｚａ-ｚｦ-ﾾￂ-ￇￊ-ￏￒ-ￗￚ-ￜ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)");
+
+// bullet_core-0.1.1: "^(?u:\\()"
+consistent!(bullet_core_4, "^(?u:\\()");
+
+// bullet_core-0.1.1: "^(?u:\\))"
+consistent!(bullet_core_5, "^(?u:\\))");
+
+// bullet_core-0.1.1: "^(?u:\\*)"
+consistent!(bullet_core_6, "^(?u:\\*)");
+
+// bullet_core-0.1.1: "^(?u:\\+)"
+consistent!(bullet_core_7, "^(?u:\\+)");
+
+// bullet_core-0.1.1: "^(?u:,)"
+consistent!(bullet_core_8, "^(?u:,)");
+
+// bullet_core-0.1.1: "^(?u:\\-)"
+consistent!(bullet_core_9, "^(?u:\\-)");
+
+// bullet_core-0.1.1: "^(?u:/)"
+consistent!(bullet_core_10, "^(?u:/)");
+
+// bullet_core-0.1.1: "^(?u:\\[)"
+consistent!(bullet_core_11, "^(?u:\\[)");
+
+// bullet_core-0.1.1: "^(?u:\\])"
+consistent!(bullet_core_12, "^(?u:\\])");
+
+// bullet_core-0.1.1: "^(?u:\\^)"
+consistent!(bullet_core_13, "^(?u:\\^)");
+
+// bullet_core-0.1.1: "^(?u:·)"
+consistent!(bullet_core_14, "^(?u:·)");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_0, "//+");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_1, "//+");
+
+// althea_kernel_interface-0.1.0: r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
+consistent!(althea_kernel_interface_0, r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)");
+
+// althea_kernel_interface-0.1.0: r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
+consistent!(althea_kernel_interface_1, r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)");
+
+// alcibiades-0.3.0: r"\buci(?:\s|$)"
+consistent!(alcibiades_0, r"\buci(?:\s|$)");
+
+// ruma-identifiers-0.11.0: r"\A[a-z0-9._=-]+\z"
+consistent!(ruma_identifiers_0, r"\A[a-z0-9._=-]+\z");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$"
+consistent!(rusqbin_0, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$"
+consistent!(rusqbin_1, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$");
+
+// rust-install-0.0.4: r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
+consistent!(rust_install_0, r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$");
+
+// rust_inbox-0.0.5: "^+(.*)\r\n"
+consistent!(rust_inbox_0, "^+(.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* CAPABILITY (.*)\r\n"
+consistent!(rust_inbox_1, r"^\* CAPABILITY (.*)\r\n");
+
+// rust_inbox-0.0.5: r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)"
+consistent!(rust_inbox_2, r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)");
+
+// rust_inbox-0.0.5: r"^\* (\d+) EXISTS\r\n"
+consistent!(rust_inbox_3, r"^\* (\d+) EXISTS\r\n");
+
+// rust_inbox-0.0.5: r"^\* (\d+) RECENT\r\n"
+consistent!(rust_inbox_4, r"^\* (\d+) RECENT\r\n");
+
+// rust_inbox-0.0.5: r"^\* FLAGS (.+)\r\n"
+consistent!(rust_inbox_5, r"^\* FLAGS (.+)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UNSEEN (\d+)\](.*)\r\n"
+consistent!(rust_inbox_6, r"^\* OK \[UNSEEN (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n"
+consistent!(rust_inbox_7, r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n"
+consistent!(rust_inbox_8, r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n"
+consistent!(rust_inbox_9, r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_0, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_1, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_2, r"^[a-z]+ (\d+)$");
+
+// rustfmt-0.10.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)"
+consistent!(rustfmt_core_0, r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)");
+
+// rustfmt-core-0.4.0: r"^## `([^`]+)`"
+consistent!(rustfmt_core_1, r"^## `([^`]+)`");
+
+// rustfmt-core-0.4.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_core_2, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"\s;"
+consistent!(rustfmt_core_3, r"\s;");
+
+// rust-enum-derive-0.4.0: r"^(0x)?([:digit:]+)$"
+consistent!(rust_enum_derive_0, r"^(0x)?([:digit:]+)$");
+
+// rust-enum-derive-0.4.0: r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
+consistent!(rust_enum_derive_1, r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$");
+
+// rust-enum-derive-0.4.0: r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,"
+consistent!(rust_enum_derive_2, r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,");
+
+// rust-enum-derive-0.4.0: r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
+consistent!(rust_enum_derive_3, r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)");
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_0, r"^\s*pub mod (.+);$");
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_1, r"^\s*pub mod (.+);$");
+
+// rustfmt-nightly-0.8.2: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_nightly_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-nightly-0.8.2: r"\s;"
+consistent!(rustfmt_nightly_1, r"\s;");
+
+// rustache-0.1.0: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rustfilt-0.2.0: r"_ZN[\$\._[:alnum:]]*"
+consistent!(rustfilt_0, r"_ZN[\$\._[:alnum:]]*");
+
+// rustache-lists-0.1.2: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_lists_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rural-0.7.3: "(.+)=(.+)"
+consistent!(rural_0, "(.+)=(.+)");
+
+// rural-0.7.3: "(.*):(.+)"
+consistent!(rural_1, "(.*):(.+)");
+
+// rural-0.7.3: "(.+):=(.+)"
+consistent!(rural_2, "(.+):=(.+)");
+
+// rural-0.7.3: "(.*)==(.+)"
+consistent!(rural_3, "(.*)==(.+)");
+
+// rusoto_credential-0.11.0: r"^\[([^\]]+)\]$"
+consistent!(rusoto_credential_0, r"^\[([^\]]+)\]$");
+
+// rumblebars-0.3.0: "([:blank:]*)$"
+consistent!(rumblebars_0, "([:blank:]*)$");
+
+// rumblebars-0.3.0: "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(rumblebars_1, "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
+
+// rumblebars-0.3.0: "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(rumblebars_2, "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
+
+// rumblebars-0.3.0: "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$"
+consistent!(rumblebars_3, "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$");
+
+// rumblebars-0.3.0: "^([:blank:]*\r?\n)(.*)"
+consistent!(rumblebars_4, "^([:blank:]*\r?\n)(.*)");
+
+// diesel_cli-1.3.1: r"(?P<stamp>[\d-]*)_hello"
+consistent!(diesel_cli_0, r"(?P<stamp>[\d-]*)_hello");
+
+// dishub-0.1.1: r"(\d+)s"
+consistent!(dishub_0, r"(\d+)s");
+
+// spreadsheet_textconv-0.1.0: r"\n"
+consistent!(spreadsheet_textconv_0, r"\n");
+
+// spreadsheet_textconv-0.1.0: r"\r"
+consistent!(spreadsheet_textconv_1, r"\r");
+
+// spreadsheet_textconv-0.1.0: r"\t"
+consistent!(spreadsheet_textconv_2, r"\t");
+
+// split_aud-0.1.0: r"DELAY (-?\d+)ms"
+consistent!(split_aud_0, r"DELAY (-?\d+)ms");
+
+// split_aud-0.1.0: r"Trim\((\d+), ?(\d+)\)"
+consistent!(split_aud_1, r"Trim\((\d+), ?(\d+)\)");
+
+// spotrust-0.0.5: r"spotify:[a-z]+:[a-zA-Z0-9]+"
+consistent!(spotrust_0, r"spotify:[a-z]+:[a-zA-Z0-9]+");
+
+// spaceslugs-0.1.0: r"[^\x00-\x7F]"
+consistent!(spaceslugs_0, r"[^\x00-\x7F]");
+
+// spaceslugs-0.1.0: r"[']+"
+consistent!(spaceslugs_1, r"[']+");
+
+// spaceslugs-0.1.0: r"\W+"
+consistent!(spaceslugs_2, r"\W+");
+
+// spaceslugs-0.1.0: r"[ ]+"
+consistent!(spaceslugs_3, r"[ ]+");
+
+// space_email_api-0.1.1: "PHPSESSID=([0-9a-f]+)"
+consistent!(space_email_api_0, "PHPSESSID=([0-9a-f]+)");
+
+// lorikeet-0.7.0: "[^0-9.,]"
+consistent!(lorikeet_0, "[^0-9.,]");
+
+// claude-0.3.0: r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$"
+consistent!(claude_0, r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$");
+
+// clam-0.1.6: r"<%=\s*(.+?)\s*%>"
+consistent!(clam_0, r"<%=\s*(.+?)\s*%>");
+
+// classifier-0.0.3: r"(\s)"
+consistent!(classifier_0, r"(\s)");
+
+// click-0.3.2: r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)"
+consistent!(click_0, r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)");
+
+// click-0.3.2: r"-----BEGIN PRIVATE KEY-----"
+consistent!(click_1, r"-----BEGIN PRIVATE KEY-----");
+
+// ultrastar-txt-0.1.2: r"#([A-Z3a-z]*):(.*)"
+consistent!(ultrastar_txt_0, r"#([A-Z3a-z]*):(.*)");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s*$"
+consistent!(ultrastar_txt_1, "^-\\s?(-?[0-9]+)\\s*$");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)"
+consistent!(ultrastar_txt_2, "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)");
+
+// ultrastar-txt-0.1.2: "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
+consistent!(ultrastar_txt_3, "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)");
+
+// ultrastar-txt-0.1.2: "^P\\s?(-?[0-9]+)"
+consistent!(ultrastar_txt_4, "^P\\s?(-?[0-9]+)");
+
+// db-accelerate-2.0.0: r"^template\.add($|\..+$)"
+consistent!(db_accelerate_0, r"^template\.add($|\..+$)");
+
+// db-accelerate-2.0.0: r"^template\.sub($|\..+$)"
+consistent!(db_accelerate_1, r"^template\.sub($|\..+$)");
+
+// sterling-0.3.0: r"(\d+)([cegps])"
+consistent!(sterling_0, r"(\d+)([cegps])");
+
+// stache-0.2.0: r"[^\w]"
+consistent!(stache_0, r"[^\w]");
+
+// strukt-0.1.0: "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\""
+consistent!(strukt_0, "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\"");
+
+// steamid-ng-0.3.1: r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$"
+consistent!(steamid_ng_0, r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$");
+
+// steamid-ng-0.3.1: r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
+consistent!(steamid_ng_1, r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$");
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_0, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_1, r"^\s+");
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_2, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_3, r"^\s+");
+
+// strscan-0.1.1: r"^(\w+)\s+"
+consistent!(strscan_4, r"^(\w+)\s+");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_0, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_1, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// evalrs-0.0.10: r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?"
+consistent!(evalrs_0, r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?");
+
+// evalrs-0.0.10: r"(?m)^# "
+consistent!(evalrs_1, r"(?m)^# ");
+
+// evalrs-0.0.10: r"(?m)^\s*fn +main *\( *\)"
+consistent!(evalrs_2, r"(?m)^\s*fn +main *\( *\)");
+
+// evalrs-0.0.10: r"(extern\s+crate\s+[a-z0-9_]+\s*;)"
+consistent!(evalrs_3, r"(extern\s+crate\s+[a-z0-9_]+\s*;)");
+
+// gate_build-0.5.0: "(.*)_t([0-9]+)"
+consistent!(gate_build_0, "(.*)_t([0-9]+)");
+
+// rake-0.1.1: r"[^\P{P}-]|\s+-\s+"
+consistent!(rake_0, r"[^\P{P}-]|\s+-\s+");
+
+// rafy-0.2.1: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(rafy_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// raven-0.2.1: r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$"
+consistent!(raven_0, r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$");
+
+// rargs-0.2.0: r"\{[[:space:]]*[^{}]*[[:space:]]*\}"
+consistent!(rargs_0, r"\{[[:space:]]*[^{}]*[[:space:]]*\}");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$"
+consistent!(rargs_1, r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$"
+consistent!(rargs_2, r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
+consistent!(rargs_3, r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$");
+
+// rargs-0.2.0: r"(.*?)[[:space:]]+|(.*?)$"
+consistent!(rargs_4, r"(.*?)[[:space:]]+|(.*?)$");
+
+// indradb-lib-0.15.0: r"[a-zA-Z0-9]{8}"
+consistent!(indradb_lib_0, r"[a-zA-Z0-9]{8}");
+
+// fungi-lang-0.1.50: r"::"
+consistent!(fungi_lang_0, r"::");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_0, "/hello/(?P<name>[a-zA-Z]+)");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_1, "/hello/(?P<name>[a-zA-Z]+)");
+
+// pact_verifier-0.4.0: r"\{(\w+)\}"
+consistent!(pact_verifier_0, r"\{(\w+)\}");
+
+// pact_matching-0.4.1: "application/.*json"
+consistent!(pact_matching_0, "application/.*json");
+
+// pact_matching-0.4.1: "application/json.*"
+consistent!(pact_matching_1, "application/json.*");
+
+// pact_matching-0.4.1: "application/.*xml"
+consistent!(pact_matching_2, "application/.*xml");
+
+// pangu-0.2.0: "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
+consistent!(pangu_0, "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])");
+
+// pangu-0.2.0: "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
+consistent!(pangu_1, "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)");
+
+// parser-haskell-0.2.0: r"\{-[\s\S]*?-\}"
+consistent!(parser_haskell_0, r"\{-[\s\S]*?-\}");
+
+// parser-haskell-0.2.0: r"(?m);+\s*$"
+consistent!(parser_haskell_1, r"(?m);+\s*$");
+
+// parser-haskell-0.2.0: r"(?m)^#(if|ifn?def|endif|else|include|elif).*"
+consistent!(parser_haskell_2, r"(?m)^#(if|ifn?def|endif|else|include|elif).*");
+
+// parser-haskell-0.2.0: r"'([^'\\]|\\[A-Z]{1,3}|\\.)'"
+consistent!(parser_haskell_3, r"'([^'\\]|\\[A-Z]{1,3}|\\.)'");
+
+// parser-haskell-0.2.0: r"forall\s+(.*?)\."
+consistent!(parser_haskell_4, r"forall\s+(.*?)\.");
+
+// html2md-0.2.1: "\\s{2,}"
+consistent!(html2md_0, "\\s{2,}");
+
+// html2md-0.2.1: "\\n{2,}"
+consistent!(html2md_1, "\\n{2,}");
+
+// html2md-0.2.1: "(?m)(\\S) $"
+consistent!(html2md_2, "(?m)(\\S) $");
+
+// html2md-0.2.1: "(?m)^[-*] "
+consistent!(html2md_3, "(?m)^[-*] ");
+
+// ovpnfile-0.1.2: r"#.*$"
+consistent!(ovpnfile_0, r"#.*$");
+
+// ovpnfile-0.1.2: r"^<(\S+)>"
+consistent!(ovpnfile_1, r"^<(\S+)>");
+
+// ovpnfile-0.1.2: r"^</(\S+)>"
+consistent!(ovpnfile_2, r"^</(\S+)>");
+
+// screenruster-saver-fractal-0.1.1: r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
+consistent!(screenruster_saver_fractal_0, r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})");
+
+// scarlet-0.2.2: r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
+consistent!(scarlet_0, r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)");
+
+// cpp_to_rust_generator-0.2.0: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_generator_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust_generator-0.2.0: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_generator_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust_generator-0.2.0: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_generator_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust_generator-0.2.0: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_generator_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_generator_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_generator_5, r"(public|protected|private)\s*:");
+
+// cpp_to_rust-0.5.3: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust-0.5.3: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust-0.5.3: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust-0.5.3: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_5, r"(public|protected|private)\s*:");
+
+// fritzbox_logs-0.2.0: "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
+consistent!(fritzbox_logs_0, "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)");
+
+// fractal-matrix-api-3.29.0: r"mxc://(?P<server>[^/]+)/(?P<media>.+)"
+consistent!(fractal_matrix_api_0, r"mxc://(?P<server>[^/]+)/(?P<media>.+)");
+
+// smtp2go-0.1.4: r"^api-[a-zA-Z0-9]{32}$"
+consistent!(smtp2go_0, r"^api-[a-zA-Z0-9]{32}$");
+
+// pusher-0.3.1: r"^[-a-zA-Z0-9_=@,.;]+$"
+consistent!(pusher_0, r"^[-a-zA-Z0-9_=@,.;]+$");
+
+// pusher-0.3.1: r"\A\d+\.\d+\z"
+consistent!(pusher_1, r"\A\d+\.\d+\z");
+
+// bakervm-0.9.0: r"^\.(.+?) +?(.+)$"
+consistent!(bakervm_0, r"^\.(.+?) +?(.+)$");
+
+// bakervm-0.9.0: r"^\.([^\s]+)$"
+consistent!(bakervm_1, r"^\.([^\s]+)$");
+
+// bakervm-0.9.0: r"^include! +([^\s]+)$"
+consistent!(bakervm_2, r"^include! +([^\s]+)$");
+
+// bakervm-0.9.0: r"^@(\d+)$"
+consistent!(bakervm_3, r"^@(\d+)$");
+
+// bakervm-0.9.0: r"^true|false$"
+consistent!(bakervm_4, r"^true|false$");
+
+// bakervm-0.9.0: r"^(-?\d+)?\.[0-9]+$"
+consistent!(bakervm_5, r"^(-?\d+)?\.[0-9]+$");
+
+// bakervm-0.9.0: r"^(-?\d+)?$"
+consistent!(bakervm_6, r"^(-?\d+)?$");
+
+// bakervm-0.9.0: r"^#([0-9abcdefABCDEF]{6})$"
+consistent!(bakervm_7, r"^#([0-9abcdefABCDEF]{6})$");
+
+// bakervm-0.9.0: r"^'(.)'$"
+consistent!(bakervm_8, r"^'(.)'$");
+
+// bakervm-0.9.0: r"^\$vi\((\d+)\)$"
+consistent!(bakervm_9, r"^\$vi\((\d+)\)$");
+
+// bakervm-0.9.0: r"^\$key\((\d+)\)$"
+consistent!(bakervm_10, r"^\$key\((\d+)\)$");
+
+// banana-0.0.2: "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
+consistent!(banana_0, "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)");
+
+// serial-key-2.0.0: r"[A-F0-9]{8}"
+consistent!(serial_key_0, r"[A-F0-9]{8}");
+
+// serde-hjson-0.8.1: "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_0, "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_1, "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_2, "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-odbc-0.1.0: r"/todos/(?P<id>\d+)"
+consistent!(serde_odbc_0, r"/todos/(?P<id>\d+)");
+
+// sentry-0.6.0: r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)"
+consistent!(sentry_0, r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)");
+
+// sentiment-0.1.1: r"[^a-zA-Z0 -]+"
+consistent!(sentiment_0, r"[^a-zA-Z0 -]+");
+
+// sentiment-0.1.1: r" {2,}"
+consistent!(sentiment_1, r" {2,}");
+
+// verilog-0.0.1: r"(?m)//.*"
+consistent!(verilog_0, r"(?m)//.*");
+
+// verex-0.2.2: "(?P<robot>C3PO)"
+consistent!(verex_0, "(?P<robot>C3PO)");
+
+// handlebars-0.32.4: ">|<|\"|&"
+consistent!(handlebars_0, ">|<|\"|&");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789]{4}$"
+consistent!(haikunator_0, r"^\w+-\w+-[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+@\w+@[0123456789]{4}$"
+consistent!(haikunator_1, r"^\w+@\w+@[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789abcdef]{4}$"
+consistent!(haikunator_2, r"^\w+-\w+-[0123456789abcdef]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$"
+consistent!(haikunator_3, r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$");
+
+// haikunator-0.1.2: r"^\w+-\w+$"
+consistent!(haikunator_4, r"^\w+-\w+$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[foo]{4}$"
+consistent!(haikunator_5, r"^\w+-\w+-[foo]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$"
+consistent!(haikunator_6, r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$");
+
+// bobbin-cli-0.8.3: r"(.*)"
+consistent!(bobbin_cli_0, r"(.*)");
+
+// bobbin-cli-0.8.3: r"rustc (.*)"
+consistent!(bobbin_cli_1, r"rustc (.*)");
+
+// bobbin-cli-0.8.3: r"cargo (.*)"
+consistent!(bobbin_cli_2, r"cargo (.*)");
+
+// bobbin-cli-0.8.3: r"xargo (.*)\n"
+consistent!(bobbin_cli_3, r"xargo (.*)\n");
+
+// bobbin-cli-0.8.3: r"Open On-Chip Debugger (.*)"
+consistent!(bobbin_cli_4, r"Open On-Chip Debugger (.*)");
+
+// bobbin-cli-0.8.3: r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
+consistent!(bobbin_cli_5, r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)");
+
+// bobbin-cli-0.8.3: r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
+consistent!(bobbin_cli_6, r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n");
+
+// bobbin-cli-0.8.3: r"(?m)SEGGER J-Link Commander (.*)\n"
+consistent!(bobbin_cli_7, r"(?m)SEGGER J-Link Commander (.*)\n");
+
+// bobbin-cli-0.8.3: r"(?m)Teensy Loader, Command Line, Version (.*)\n"
+consistent!(bobbin_cli_8, r"(?m)Teensy Loader, Command Line, Version (.*)\n");
+
+// bobbin-cli-0.8.3: r"dfu-util (.*)\n"
+consistent!(bobbin_cli_9, r"dfu-util (.*)\n");
+
+// borsholder-0.9.1: r"^/static/[\w.]+$"
+consistent!(borsholder_0, r"^/static/[\w.]+$");
+
+// borsholder-0.9.1: r"^/timeline/([0-9]+)$"
+consistent!(borsholder_1, r"^/timeline/([0-9]+)$");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_0, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_1, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// toml-query-0.6.0: r"^\[\d+\]$"
+consistent!(toml_query_0, r"^\[\d+\]$");
+
+// todo-txt-1.1.0: r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)"
+consistent!(todo_txt_0, r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)");
+
+// findr-0.1.5: r"\band\b"
+consistent!(findr_0, r"\band\b");
+
+// findr-0.1.5: r"\bor\b"
+consistent!(findr_1, r"\bor\b");
+
+// findr-0.1.5: r"\bnot\b"
+consistent!(findr_2, r"\bnot\b");
+
+// file-sniffer-3.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*|dat|pc|info)$"
+consistent!(file_sniffer_1, r".*?\.(stats|conf|h|cache.*|dat|pc|info)$");
+
+// file-sniffer-3.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*)$"
+consistent!(file_sniffer_3, r".*?\.(stats|conf|h|cache.*)$");
+
+// file-sniffer-3.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(file_sniffer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// file_logger-0.1.0: "test"
+consistent!(file_logger_0, "test");
+
+// file_scanner-0.2.0: r"foo"
+consistent!(file_scanner_0, r"foo");
+
+// file_scanner-0.2.0: r"a+b"
+consistent!(file_scanner_1, r"a+b");
+
+// file_scanner-0.2.0: r"a[ab]*b"
+consistent!(file_scanner_2, r"a[ab]*b");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_3, r"\s+");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_4, r"\s+");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_0, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_1, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+"
+consistent!(aterm_0, r"^[+\-]?[0-9]+");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?"
+consistent!(aterm_1, r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?");
+
+// atarashii_imap-0.3.0: r"^[*] OK"
+consistent!(atarashii_imap_0, r"^[*] OK");
+
+// atarashii_imap-0.3.0: r"FLAGS\s\((.+)\)"
+consistent!(atarashii_imap_1, r"FLAGS\s\((.+)\)");
+
+// atarashii_imap-0.3.0: r"\[PERMANENTFLAGS\s\((.+)\)\]"
+consistent!(atarashii_imap_2, r"\[PERMANENTFLAGS\s\((.+)\)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDVALIDITY\s(\d+)\]"
+consistent!(atarashii_imap_3, r"\[UIDVALIDITY\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"(\d+)\sEXISTS"
+consistent!(atarashii_imap_4, r"(\d+)\sEXISTS");
+
+// atarashii_imap-0.3.0: r"(\d+)\sRECENT"
+consistent!(atarashii_imap_5, r"(\d+)\sRECENT");
+
+// atarashii_imap-0.3.0: r"\[UNSEEN\s(\d+)\]"
+consistent!(atarashii_imap_6, r"\[UNSEEN\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDNEXT\s(\d+)\]"
+consistent!(atarashii_imap_7, r"\[UIDNEXT\s(\d+)\]");
+
+// editorconfig-1.0.0: r"\\(\{|\})"
+consistent!(editorconfig_0, r"\\(\{|\})");
+
+// editorconfig-1.0.0: r"(^|[^\\])\\\|"
+consistent!(editorconfig_1, r"(^|[^\\])\\\|");
+
+// editorconfig-1.0.0: r"\[([^\]]*)$"
+consistent!(editorconfig_2, r"\[([^\]]*)$");
+
+// editorconfig-1.0.0: r"\[(.*/.*)\]"
+consistent!(editorconfig_3, r"\[(.*/.*)\]");
+
+// editorconfig-1.0.0: r"\{(-?\d+\\\.\\\.-?\d+)\}"
+consistent!(editorconfig_4, r"\{(-?\d+\\\.\\\.-?\d+)\}");
+
+// editorconfig-1.0.0: r"\{([^,]+)\}"
+consistent!(editorconfig_5, r"\{([^,]+)\}");
+
+// editorconfig-1.0.0: r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}"
+consistent!(editorconfig_6, r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}");
+
+// editorconfig-1.0.0: r"^/"
+consistent!(editorconfig_7, r"^/");
+
+// editorconfig-1.0.0: r"(^|[^\\])(\{|\})"
+consistent!(editorconfig_8, r"(^|[^\\])(\{|\})");
+
+// edmunge-1.0.0: "^#!.*\n"
+consistent!(edmunge_0, "^#!.*\n");
+
+// unicode_names2_macros-0.2.0: r"\\N\{(.*?)(?:\}|$)"
+consistent!(unicode_names2_macros_0, r"\\N\{(.*?)(?:\}|$)");
+
+// unidiff-0.2.1: r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(unidiff_0, r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?");
+
+// unidiff-0.2.1: r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(unidiff_1, r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?");
+
+// unidiff-0.2.1: r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)"
+consistent!(unidiff_2, r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)");
+
+// unidiff-0.2.1: r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)"
+consistent!(unidiff_3, r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)");
+
+// slippy-map-tiles-0.13.1: "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$"
+consistent!(slippy_map_tiles_0, "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_1, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_2, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// sonos-0.1.2: r"^https?://(.+?):1400/xml"
+consistent!(sonos_0, r"^https?://(.+?):1400/xml");
+
+// validator_derive-0.7.0: r"^[a-z]{2}$"
+consistent!(validator_derive_0, r"^[a-z]{2}$");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_1, r"[a-z]{2}");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_2, r"[a-z]{2}");
+
+// nginx-config-0.8.0: r"one of \d+ options"
+consistent!(nginx_config_0, r"one of \d+ options");
+
+// waltz-0.4.0: r"[\s,]"
+consistent!(waltz_0, r"[\s,]");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_0, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_1, r"^aws_secret_access_key = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_2, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_3, r"^aws_secret_access_key = (.*)");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)"
+consistent!(jieba_rs_0, r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)");
+
+// jieba-rs-0.2.2: r"(\r\n|\s)"
+consistent!(jieba_rs_1, r"(\r\n|\s)");
+
+// jieba-rs-0.2.2: "([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_2, "([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"[^a-zA-Z0-9+#\n]"
+consistent!(jieba_rs_3, r"[^a-zA-Z0-9+#\n]");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_4, r"([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"([a-zA-Z0-9]+(?:.\d+)?%?)"
+consistent!(jieba_rs_5, r"([a-zA-Z0-9]+(?:.\d+)?%?)");
+
+// lalrpop-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_0, r"Span\([0-9 ,]*\)");
+
+// lalrpop-snap-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_snap_0, r"Span\([0-9 ,]*\)");
+
+// nlp-tokenize-0.1.0: r"[\S]+"
+consistent!(nlp_tokenize_0, r"[\S]+");
+
+// kbgpg-0.1.2: "[[:xdigit:]][70]"
+consistent!(kbgpg_0, "[[:xdigit:]][70]");
+
+// cdbd-0.1.1: r"^((?P<address>.*):)?(?P<port>\d+)$"
+consistent!(cdbd_0, r"^((?P<address>.*):)?(?P<port>\d+)$");
+
+// mbutiles-0.1.1: r"[\w\s=+-/]+\((\{(.|\n)*\})\);?"
+consistent!(mbutiles_0, r"[\w\s=+-/]+\((\{(.|\n)*\})\);?");
+
+// extrahop-0.2.5: r"^-\d+(?:ms|s|m|h|d|w|y)?$"
+consistent!(extrahop_0, r"^-\d+(?:ms|s|m|h|d|w|y)?$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_0, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(pippin_1, "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_2, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(pippin_3, "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$");
+
+// pippin-0.1.0: "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$"
+consistent!(pippin_4, "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$");
+
+// pippin-0.1.0: "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
+consistent!(pippin_5, "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$");
+
+// pinyin-0.3.0: r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
+consistent!(pinyin_0, r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]");
+
+// pinyin-0.3.0: r"([aeoiuvnm])([0-4])$"
+consistent!(pinyin_1, r"([aeoiuvnm])([0-4])$");
+
+// duration-parser-0.2.0: r"(?P<value>\d+)(?P<units>[a-z])"
+consistent!(duration_parser_0, r"(?P<value>\d+)(?P<units>[a-z])");
+
+// dutree-0.2.7: r"^\d+\D?$"
+consistent!(dutree_0, r"^\d+\D?$");
+
+// djangohashers-0.3.0: r"^[A-Za-z0-9]*$"
+consistent!(djangohashers_0, r"^[A-Za-z0-9]*$");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}$"
+consistent!(rtag_0, r"^[A-Z][A-Z0-9]{2,}$");
+
+// rtag-0.3.5: r"^http://www\.emusic\.com"
+consistent!(rtag_1, r"^http://www\.emusic\.com");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}"
+consistent!(rtag_2, r"^[A-Z][A-Z0-9]{2,}");
+
+// rtag-0.3.5: r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
+consistent!(rtag_3, r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)");
+
+// rtow-0.1.0: r"(\d+)[xX](\d+)"
+consistent!(rtow_0, r"(\d+)[xX](\d+)");
+
+// pleingres-sql-plugin-0.1.0: r"\$([a-zA-Z0-9_]+)"
+consistent!(pleingres_sql_plugin_0, r"\$([a-zA-Z0-9_]+)");
+
+// dono-2.0.0: "[\\n]+"
+consistent!(dono_0, "[\\n]+");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_1, "(?m)^\\n");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_2, "(?m)^\\n");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.ed25519$"
+consistent!(ssb_common_0, r"^[0-9A-Za-z\+/]{43}=\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{86}==\.ed25519$"
+consistent!(ssb_common_1, r"^[0-9A-Za-z\+/]{86}==\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.sha256$"
+consistent!(ssb_common_2, r"^[0-9A-Za-z\+/]{43}=\.sha256$");
+
+// mozversion-0.1.3: r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$"
+consistent!(mozversion_0, r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$");
+
+// monger-0.5.6: r"^(\d+)\.(\d+)$"
+consistent!(monger_0, r"^(\d+)\.(\d+)$");
+
+// mongo_rub-0.0.2: r"^[rv]2\.6"
+consistent!(mongo_rub_0, r"^[rv]2\.6");
+
+// flow-0.3.5: "body value"
+consistent!(flow_0, "body value");
+
+// flow-0.3.5: "start marker"
+consistent!(flow_1, "start marker");
+
+// flow-0.3.5: "end marker"
+consistent!(flow_2, "end marker");
+
+// flow-0.3.5: "body value"
+consistent!(flow_3, "body value");
+
+// vobsub-0.2.3: "^([A-Za-z/ ]+): (.*)"
+consistent!(vobsub_0, "^([A-Za-z/ ]+): (.*)");
+
+// voidmap-1.1.2: r"#([^\s=]+)*"
+consistent!(voidmap_0, r"#([^\s=]+)*");
+
+// voidmap-1.1.2: r"#(\S+)*"
+consistent!(voidmap_1, r"#(\S+)*");
+
+// voidmap-1.1.2: r"#prio=(\d+)"
+consistent!(voidmap_2, r"#prio=(\d+)");
+
+// voidmap-1.1.2: r"\[(\S+)\]"
+consistent!(voidmap_3, r"\[(\S+)\]");
+
+// voidmap-1.1.2: r"#limit=(\d+)"
+consistent!(voidmap_4, r"#limit=(\d+)");
+
+// voidmap-1.1.2: r"#tagged=(\S+)"
+consistent!(voidmap_5, r"#tagged=(\S+)");
+
+// voidmap-1.1.2: r"#rev\b"
+consistent!(voidmap_6, r"#rev\b");
+
+// voidmap-1.1.2: r"#done\b"
+consistent!(voidmap_7, r"#done\b");
+
+// voidmap-1.1.2: r"#open\b"
+consistent!(voidmap_8, r"#open\b");
+
+// voidmap-1.1.2: r"#since=(\S+)"
+consistent!(voidmap_9, r"#since=(\S+)");
+
+// voidmap-1.1.2: r"#until=(\S+)"
+consistent!(voidmap_10, r"#until=(\S+)");
+
+// voidmap-1.1.2: r"#plot=(\S+)"
+consistent!(voidmap_11, r"#plot=(\S+)");
+
+// voidmap-1.1.2: r"#n=(\d+)"
+consistent!(voidmap_12, r"#n=(\d+)");
+
+// voidmap-1.1.2: r"(\S+)"
+consistent!(voidmap_13, r"(\S+)");
+
+// voidmap-1.1.2: r"(?P<y>\d+)y"
+consistent!(voidmap_14, r"(?P<y>\d+)y");
+
+// voidmap-1.1.2: r"(?P<m>\d+)m"
+consistent!(voidmap_15, r"(?P<m>\d+)m");
+
+// voidmap-1.1.2: r"(?P<w>\d+)w"
+consistent!(voidmap_16, r"(?P<w>\d+)w");
+
+// voidmap-1.1.2: r"(?P<d>\d+)d"
+consistent!(voidmap_17, r"(?P<d>\d+)d");
+
+// voidmap-1.1.2: r"(?P<h>\d+)h"
+consistent!(voidmap_18, r"(?P<h>\d+)h");
+
+// voidmap-1.1.2: r"C-(.)"
+consistent!(voidmap_19, r"C-(.)");
+
+// qt_generator-0.2.0: r"^\.\./qt[^/]+/"
+consistent!(qt_generator_0, r"^\.\./qt[^/]+/");
+
+// qt_generator-0.2.0: "(href|src)=\"([^\"]*)\""
+consistent!(qt_generator_1, "(href|src)=\"([^\"]*)\"");
+
+// kryptos-0.6.1: r"[01]{5}"
+consistent!(kryptos_0, r"[01]{5}");
+
+// cifar_10_loader-0.2.0: "data_batch_[1-5].bin"
+consistent!(cifar_10_loader_0, "data_batch_[1-5].bin");
+
+// cifar_10_loader-0.2.0: "test_batch.bin"
+consistent!(cifar_10_loader_1, "test_batch.bin");
+
+// circadian-0.6.0: r"^\d+.\d+s$"
+consistent!(circadian_0, r"^\d+.\d+s$");
+
+// circadian-0.6.0: r"^\d+:\d+$"
+consistent!(circadian_1, r"^\d+:\d+$");
+
+// circadian-0.6.0: r"^\d+:\d+m$"
+consistent!(circadian_2, r"^\d+:\d+m$");
+
+// cicada-0.8.1: r"!!"
+consistent!(cicada_0, r"!!");
+
+// cicada-0.8.1: r"^([^`]*)`([^`]+)`(.*)$"
+consistent!(cicada_1, r"^([^`]*)`([^`]+)`(.*)$");
+
+// cicada-0.8.1: r"\*+"
+consistent!(cicada_2, r"\*+");
+
+// cicada-0.8.1: r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)"
+consistent!(cicada_3, r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)");
+
+// cicada-0.8.1: r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$"
+consistent!(cicada_4, r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$");
+
+// vterm-sys-0.1.0: r"hi"
+consistent!(vterm_sys_0, r"hi");
+
+// skim-0.5.0: r".*?\t"
+consistent!(skim_0, r".*?\t");
+
+// skim-0.5.0: r".*?[\t ]"
+consistent!(skim_1, r".*?[\t ]");
+
+// skim-0.5.0: r"(\{-?[0-9.,q]*?})"
+consistent!(skim_2, r"(\{-?[0-9.,q]*?})");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_3, r"[ \t\n]+");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_4, r"[ \t\n]+");
+
+// skim-0.5.0: r"([^ |]+( +\| +[^ |]*)+)|( +)"
+consistent!(skim_5, r"([^ |]+( +\| +[^ |]*)+)|( +)");
+
+// skim-0.5.0: r" +\| +"
+consistent!(skim_6, r" +\| +");
+
+// skim-0.5.0: r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$"
+consistent!(skim_7, r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$");
+
+// skim-0.5.0: ","
+consistent!(skim_8, ",");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_9, ".*?,");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_10, ".*?,");
+
+// skim-0.5.0: ","
+consistent!(skim_11, ",");
+
+// skim-0.5.0: r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))"
+consistent!(skim_12, r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))");
+
+// egg-mode-text-1.14.7: r"[-_./]\z"
+consistent!(egg_mode_text_0, r"[-_./]\z");
+
+// java-properties-1.1.1: "^[ \t\r\n\x0c]*[#!]"
+consistent!(java_properties_0, "^[ \t\r\n\x0c]*[#!]");
+
+// java-properties-1.1.1: r"^[ \t\x0c]*[#!][^\r\n]*$"
+consistent!(java_properties_1, r"^[ \t\x0c]*[#!][^\r\n]*$");
+
+// java-properties-1.1.1: r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$"
+consistent!(java_properties_2, r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$");
+
+// ipaddress-0.1.2: r":.+\."
+consistent!(ipaddress_0, r":.+\.");
+
+// ipaddress-0.1.2: r"\."
+consistent!(ipaddress_1, r"\.");
+
+// ipaddress-0.1.2: r":"
+consistent!(ipaddress_2, r":");
+
+// iptables-0.2.2: r"v(\d+)\.(\d+)\.(\d+)"
+consistent!(iptables_0, r"v(\d+)\.(\d+)\.(\d+)");
+
+// rsure-0.8.1: r"^([^-]+)-(.*)\.dat\.gz$"
+consistent!(rsure_0, r"^([^-]+)-(.*)\.dat\.gz$");
+
+// rs-jsonpath-0.1.0: "^(.*?)(<=|<|==|>=|>)(.*?)$"
+consistent!(rs_jsonpath_0, "^(.*?)(<=|<|==|>=|>)(.*?)$");
+
+// oatie-0.3.0: r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))"
+consistent!(oatie_0, r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))");
+
+// weld-0.2.0: "#.*$"
+consistent!(weld_0, "#.*$");
+
+// weld-0.2.0: r"^[A-Za-z$_][A-Za-z0-9$_]*$"
+consistent!(weld_1, r"^[A-Za-z$_][A-Za-z0-9$_]*$");
+
+// weld-0.2.0: r"^[0-9]+[cC]$"
+consistent!(weld_2, r"^[0-9]+[cC]$");
+
+// weld-0.2.0: r"^0b[0-1]+[cC]$"
+consistent!(weld_3, r"^0b[0-1]+[cC]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[cC]$"
+consistent!(weld_4, r"^0x[0-9a-fA-F]+[cC]$");
+
+// weld-0.2.0: r"^[0-9]+$"
+consistent!(weld_5, r"^[0-9]+$");
+
+// weld-0.2.0: r"^0b[0-1]+$"
+consistent!(weld_6, r"^0b[0-1]+$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+$"
+consistent!(weld_7, r"^0x[0-9a-fA-F]+$");
+
+// weld-0.2.0: r"^[0-9]+[lL]$"
+consistent!(weld_8, r"^[0-9]+[lL]$");
+
+// weld-0.2.0: r"^0b[0-1]+[lL]$"
+consistent!(weld_9, r"^0b[0-1]+[lL]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[lL]$"
+consistent!(weld_10, r"^0x[0-9a-fA-F]+[lL]$");
+
+// webgl_generator-0.1.0: "([(, ])enum\\b"
+consistent!(webgl_generator_0, "([(, ])enum\\b");
+
+// webgl_generator-0.1.0: "\\bAcquireResourcesCallback\\b"
+consistent!(webgl_generator_1, "\\bAcquireResourcesCallback\\b");
+
+// weave-0.2.0: r"^(\d+)(,(\d+))?([acd]).*$"
+consistent!(weave_0, r"^(\d+)(,(\d+))?([acd]).*$");
+
+// wemo-0.0.12: r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>"
+consistent!(wemo_0, r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>");
+
+// webscale-0.9.4: r"(http[s]?://[^\s]+)"
+consistent!(webscale_0, r"(http[s]?://[^\s]+)");
+
+// svgrep-1.1.0: r"^\d+.*$"
+consistent!(svgrep_0, r"^\d+.*$");
+
+// ignore-0.4.2: r"^[\pL\pN]+$"
+consistent!(ignore_0, r"^[\pL\pN]+$");
+
+// ommui_string_patterns-0.1.2: r"^([A-Za-z][0-9A-Za-z_]*)?$"
+consistent!(ommui_string_patterns_0, r"^([A-Za-z][0-9A-Za-z_]*)?$");
+
+// ommui_string_patterns-0.1.2: r"^(\S+(?:.*\S)?)?$"
+consistent!(ommui_string_patterns_1, r"^(\S+(?:.*\S)?)?$");
+
+// opcua-types-0.3.0: "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$"
+consistent!(opcua_types_0, "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$");
+
+// opcua-types-0.3.0: r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$"
+consistent!(opcua_types_1, r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$");
+
+// open_read_later-1.1.1: r"^(.+?)\s*:\s*(.+)$"
+consistent!(open_read_later_0, r"^(.+?)\s*:\s*(.+)$");
+
+// youtube-downloader-0.1.0: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(youtube_downloader_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// yobot-0.1.1: "."
+consistent!(yobot_0, ".");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_1, r".");
+
+// yobot-0.1.1: r".+"
+consistent!(yobot_2, r".+");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_3, r".");
+
+// ubiquity-0.1.5: r"foo"
+consistent!(ubiquity_0, r"foo");
+
+// ubiquity-0.1.5: r"/target/"
+consistent!(ubiquity_1, r"/target/");
+
+// ubiquity-0.1.5: r".DS_Store"
+consistent!(ubiquity_2, r".DS_Store");
+
+// qasm-1.0.0: r"//.*"
+consistent!(qasm_0, r"//.*");
+
+// drill-0.3.5: r"\{\{ *([a-z\._]+) *\}\}"
+consistent!(drill_0, r"\{\{ *([a-z\._]+) *\}\}");
+
+// queryst-2.0.0: r"^([^\]\[]+)"
+consistent!(queryst_0, r"^([^\]\[]+)");
+
+// queryst-2.0.0: r"(\[[^\]\[]*\])"
+consistent!(queryst_1, r"(\[[^\]\[]*\])");
+
+// qui-vive-0.1.0: r"^/(\w+)$"
+consistent!(qui_vive_0, r"^/(\w+)$");
+
+// qui-vive-0.1.0: r"^/key$"
+consistent!(qui_vive_1, r"^/key$");
+
+// qui-vive-0.1.0: r"^/key/(\w+)$"
+consistent!(qui_vive_2, r"^/key/(\w+)$");
+
+// qui-vive-0.1.0: r"^/url$"
+consistent!(qui_vive_3, r"^/url$");
+
+// qui-vive-0.1.0: r"^/url/(\w+)$"
+consistent!(qui_vive_4, r"^/url/(\w+)$");
+
+// qui-vive-0.1.0: r"^/inv$"
+consistent!(qui_vive_5, r"^/inv$");
+
+// qui-vive-0.1.0: r"^/inv/(\w+)$"
+consistent!(qui_vive_6, r"^/inv/(\w+)$");
+
+// subdiff-0.1.0: r"\b"
+// consistent!(subdiff_0, r"\b");
+
+// substudy-0.4.5: r"^(\d+)/(\d+)$"
+consistent!(substudy_0, r"^(\d+)/(\d+)$");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_1, r"\s+");
+
+// substudy-0.4.5: r"<[a-z/][^>]*>"
+consistent!(substudy_2, r"<[a-z/][^>]*>");
+
+// substudy-0.4.5: r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)"
+consistent!(substudy_3, r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_4, r"\s+");
+
+// isbnid-0.1.3: r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$"
+consistent!(isbnid_0, r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$");
+
+// isbnid-0.1.3: r"[^0-9X]"
+consistent!(isbnid_1, r"[^0-9X]");
+
+// ispc-0.3.5: r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
+consistent!(ispc_0, r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)");
+
diff --git a/third_party/rust/regex/tests/crazy.rs b/third_party/rust/regex/tests/crazy.rs
index ade839ade134..6fc4980ebc46 100644
--- a/third_party/rust/regex/tests/crazy.rs
+++ b/third_party/rust/regex/tests/crazy.rs
@@ -42,16 +42,43 @@ mat!(negclass_letters, r"[^ac]", "acx", Some((2, 3)));
 mat!(negclass_letter_comma, r"[^a,]", "a,x", Some((2, 3)));
 mat!(negclass_letter_space, r"[^a\s]", "a x", Some((2, 3)));
 mat!(negclass_comma, r"[^,]", ",,x", Some((2, 3)));
 mat!(negclass_space, r"[^\s]", " a", Some((1, 2)));
 mat!(negclass_space_comma, r"[^,\s]", ", a", Some((2, 3)));
 mat!(negclass_comma_space, r"[^\s,]", " ,a", Some((2, 3)));
 mat!(negclass_ascii, r"[^[:alpha:]Z]", "A1", Some((1, 2)));
 
+// Test that repeated empty expressions don't loop forever.
+mat!(lazy_many_many, r"((?:.*)*?)=", "a=b", Some((0, 2)));
+mat!(lazy_many_optional, r"((?:.?)*?)=", "a=b", Some((0, 2)));
+mat!(lazy_one_many_many, r"((?:.*)+?)=", "a=b", Some((0, 2)));
+mat!(lazy_one_many_optional, r"((?:.?)+?)=", "a=b", Some((0, 2)));
+mat!(lazy_range_min_many, r"((?:.*){1,}?)=", "a=b", Some((0, 2)));
+mat!(lazy_range_many, r"((?:.*){1,2}?)=", "a=b", Some((0, 2)));
+mat!(greedy_many_many, r"((?:.*)*)=", "a=b", Some((0, 2)));
+mat!(greedy_many_optional, r"((?:.?)*)=", "a=b", Some((0, 2)));
+mat!(greedy_one_many_many, r"((?:.*)+)=", "a=b", Some((0, 2)));
+mat!(greedy_one_many_optional, r"((?:.?)+)=", "a=b", Some((0, 2)));
+mat!(greedy_range_min_many, r"((?:.*){1,})=", "a=b", Some((0, 2)));
+mat!(greedy_range_many, r"((?:.*){1,2})=", "a=b", Some((0, 2)));
+
+// Test that we handle various flavors of empty expressions.
+matiter!(match_empty1, r"", "", (0, 0));
+matiter!(match_empty2, r"", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty3, r"()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty4, r"()*", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty5, r"()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty6, r"()?", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty7, r"()()", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty8, r"()+|z", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty9, r"z|()+", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty10, r"()+|b", "abc", (0, 0), (1, 1), (2, 2), (3, 3));
+matiter!(match_empty11, r"b|()+", "abc", (0, 0), (1, 2), (3, 3));
+
 // Test that the DFA can handle pathological cases.
 // (This should result in the DFA's cache being flushed too frequently, which
 // should cause it to quit and fall back to the NFA algorithm.)
 #[test]
 fn dfa_handles_pathological_case() {
     fn ones_and_zeroes(count: usize) -> String {
         use rand::{Rng, thread_rng};
 
@@ -71,8 +98,304 @@ fn dfa_handles_pathological_case() {
     let text = {
         let mut pieces = ones_and_zeroes(100_000);
         pieces.push('1');
         pieces.push_str(&ones_and_zeroes(20));
         pieces
     };
     assert!(re.is_match(text!(&*text)));
 }
+
+#[test]
+fn nest_limit_makes_it_parse() {
+    use regex::RegexBuilder;
+
+    RegexBuilder::new(
+        r#"
+        2(?:
+          [45]\d{3}|
+          7(?:
+            1[0-267]|
+            2[0-289]|
+            3[0-29]|
+            4[01]|
+            5[1-3]|
+            6[013]|
+            7[0178]|
+            91
+          )|
+          8(?:
+            0[125]|
+            [139][1-6]|
+            2[0157-9]|
+            41|
+            6[1-35]|
+            7[1-5]|
+            8[1-8]|
+            90
+          )|
+          9(?:
+            0[0-2]|
+            1[0-4]|
+            2[568]|
+            3[3-6]|
+            5[5-7]|
+            6[0167]|
+            7[15]|
+            8[0146-9]
+          )
+        )\d{4}|
+        3(?:
+          12?[5-7]\d{2}|
+          0(?:
+            2(?:
+              [025-79]\d|
+              [348]\d{1,2}
+            )|
+            3(?:
+              [2-4]\d|
+              [56]\d?
+            )
+          )|
+          2(?:
+            1\d{2}|
+            2(?:
+              [12]\d|
+              [35]\d{1,2}|
+              4\d?
+            )
+          )|
+          3(?:
+            1\d{2}|
+            2(?:
+              [2356]\d|
+              4\d{1,2}
+            )
+          )|
+          4(?:
+            1\d{2}|
+            2(?:
+              2\d{1,2}|
+              [47]|
+              5\d{2}
+            )
+          )|
+          5(?:
+            1\d{2}|
+            29
+          )|
+          [67]1\d{2}|
+          8(?:
+            1\d{2}|
+            2(?:
+              2\d{2}|
+              3|
+              4\d
+            )
+          )
+        )\d{3}|
+        4(?:
+          0(?:
+            2(?:
+              [09]\d|
+              7
+            )|
+            33\d{2}
+          )|
+          1\d{3}|
+          2(?:
+            1\d{2}|
+            2(?:
+              [25]\d?|
+              [348]\d|
+              [67]\d{1,2}
+            )
+          )|
+          3(?:
+            1\d{2}(?:
+              \d{2}
+            )?|
+            2(?:
+              [045]\d|
+              [236-9]\d{1,2}
+            )|
+            32\d{2}
+          )|
+          4(?:
+            [18]\d{2}|
+            2(?:
+              [2-46]\d{2}|
+              3
+            )|
+            5[25]\d{2}
+          )|
+          5(?:
+            1\d{2}|
+            2(?:
+              3\d|
+              5
+            )
+          )|
+          6(?:
+            [18]\d{2}|
+            2(?:
+              3(?:
+                \d{2}
+              )?|
+              [46]\d{1,2}|
+              5\d{2}|
+              7\d
+            )|
+            5(?:
+              3\d?|
+              4\d|
+              [57]\d{1,2}|
+              6\d{2}|
+              8
+            )
+          )|
+          71\d{2}|
+          8(?:
+            [18]\d{2}|
+            23\d{2}|
+            54\d{2}
+          )|
+          9(?:
+            [18]\d{2}|
+            2[2-5]\d{2}|
+            53\d{1,2}
+          )
+        )\d{3}|
+        5(?:
+          02[03489]\d{2}|
+          1\d{2}|
+          2(?:
+            1\d{2}|
+            2(?:
+              2(?:
+                \d{2}
+              )?|
+              [457]\d{2}
+            )
+          )|
+          3(?:
+            1\d{2}|
+            2(?:
+              [37](?:
+                \d{2}
+              )?|
+              [569]\d{2}
+            )
+          )|
+          4(?:
+            1\d{2}|
+            2[46]\d{2}
+          )|
+          5(?:
+            1\d{2}|
+            26\d{1,2}
+          )|
+          6(?:
+            [18]\d{2}|
+            2|
+            53\d{2}
+          )|
+          7(?:
+            1|
+            24
+          )\d{2}|
+          8(?:
+            1|
+            26
+          )\d{2}|
+          91\d{2}
+        )\d{3}|
+        6(?:
+          0(?:
+            1\d{2}|
+            2(?:
+              3\d{2}|
+              4\d{1,2}
+            )
+          )|
+          2(?:
+            2[2-5]\d{2}|
+            5(?:
+              [3-5]\d{2}|
+              7
+            )|
+            8\d{2}
+          )|
+          3(?:
+            1|
+            2[3478]
+          )\d{2}|
+          4(?:
+            1|
+            2[34]
+          )\d{2}|
+          5(?:
+            1|
+            2[47]
+          )\d{2}|
+          6(?:
+            [18]\d{2}|
+            6(?:
+              2(?:
+                2\d|
+                [34]\d{2}
+              )|
+              5(?:
+                [24]\d{2}|
+                3\d|
+                5\d{1,2}
+              )
+            )
+          )|
+          72[2-5]\d{2}|
+          8(?:
+            1\d{2}|
+            2[2-5]\d{2}
+          )|
+          9(?:
+            1\d{2}|
+            2[2-6]\d{2}
+          )
+        )\d{3}|
+        7(?:
+          (?:
+            02|
+            [3-589]1|
+            6[12]|
+            72[24]
+          )\d{2}|
+          21\d{3}|
+          32
+        )\d{3}|
+        8(?:
+          (?:
+            4[12]|
+            [5-7]2|
+            1\d?
+          )|
+          (?:
+            0|
+            3[12]|
+            [5-7]1|
+            217
+          )\d
+        )\d{4}|
+        9(?:
+          [35]1|
+          (?:
+            [024]2|
+            81
+          )\d|
+          (?:
+            1|
+            [24]1
+          )\d{2}
+        )\d{3}
+        "#
+    )
+    .build()
+    .unwrap();
+}
diff --git a/third_party/rust/regex/tests/macros.rs b/third_party/rust/regex/tests/macros.rs
index 2cd1463b4e27..3c4b888b2013 100644
--- a/third_party/rust/regex/tests/macros.rs
+++ b/third_party/rust/regex/tests/macros.rs
@@ -9,17 +9,17 @@ macro_rules! findall {
 
 // Macros for automatically producing tests.
 
 macro_rules! ismatch {
     ($name:ident, $re:expr, $text:expr, $ismatch:expr) => {
         #[test]
         fn $name() {
             let re = regex!($re);
-            assert!($ismatch == re.is_match(text!($text)));
+            assert_eq!($ismatch, re.is_match(text!($text)));
         }
     };
 }
 
 macro_rules! mat(
     ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
         #[test]
         fn $name() {
diff --git a/third_party/rust/regex/tests/macros_bytes.rs b/third_party/rust/regex/tests/macros_bytes.rs
index 4a382c78dd9f..7605d69b21be 100644
--- a/third_party/rust/regex/tests/macros_bytes.rs
+++ b/third_party/rust/regex/tests/macros_bytes.rs
@@ -1,17 +1,15 @@
 // Macros for use in writing tests generic over &str/&[u8].
 macro_rules! text { ($text:expr) => { $text.as_bytes() } }
 macro_rules! t { ($re:expr) => { text!($re) } }
 macro_rules! match_text { ($text:expr) => { $text.as_bytes() } }
+macro_rules! use_ { ($($path: tt)*) => { use regex::bytes::$($path)*; } }
 
 macro_rules! bytes { ($text:expr) => { $text } }
-macro_rules! b { ($text:expr) => { bytes!($text) } }
-
-// macro_rules! u { ($re:expr) => { concat!("(?u)", $re) } }
 
 macro_rules! no_expand {
     ($text:expr) => {{
         use regex::bytes::NoExpand;
         NoExpand(text!($text))
     }}
 }
 
diff --git a/third_party/rust/regex/tests/macros_str.rs b/third_party/rust/regex/tests/macros_str.rs
index e5b0e219daa9..fda5814b8ca8 100644
--- a/third_party/rust/regex/tests/macros_str.rs
+++ b/third_party/rust/regex/tests/macros_str.rs
@@ -1,17 +1,13 @@
 // Macros for use in writing tests generic over &str/&[u8].
 macro_rules! text { ($text:expr) => { $text } }
 macro_rules! t { ($text:expr) => { text!($text) } }
 macro_rules! match_text { ($text:expr) => { $text.as_str() } }
-
-macro_rules! bytes { ($text:expr) => { $text.as_bytes() } }
-macro_rules! b { ($text:expr) => { bytes!($text) } }
-
-// macro_rules! u { ($re:expr) => { $re } }
+macro_rules! use_ { ($($path: tt)*) => { use regex::$($path)*; } }
 
 macro_rules! no_expand {
     ($text:expr) => {{
         use regex::NoExpand;
         NoExpand(text!($text))
     }}
 }
 
diff --git a/third_party/rust/regex/tests/noparse.rs b/third_party/rust/regex/tests/noparse.rs
index ce2d369e2065..62eb5be77e28 100644
--- a/third_party/rust/regex/tests/noparse.rs
+++ b/third_party/rust/regex/tests/noparse.rs
@@ -6,43 +6,45 @@ macro_rules! noparse(
             match regex_new!(re) {
                 Err(_) => {},
                 Ok(_) => panic!("Regex '{}' should cause a parse error.", re),
             }
         }
     );
 );
 
-noparse!(fail_double_repeat, "a**");
 noparse!(fail_no_repeat_arg, "*");
 noparse!(fail_incomplete_escape, "\\");
 noparse!(fail_class_incomplete, "[A-");
 noparse!(fail_class_not_closed, "[A");
 noparse!(fail_class_no_begin, r"[\A]");
 noparse!(fail_class_no_end, r"[\z]");
 noparse!(fail_class_no_boundary, r"[\b]");
 noparse!(fail_open_paren, "(");
 noparse!(fail_close_paren, ")");
 noparse!(fail_invalid_range, "[a-Z]");
 noparse!(fail_empty_capture_name, "(?P<>a)");
-noparse!(fail_empty_capture_exp, "(?P<name>)");
 noparse!(fail_bad_capture_name, "(?P<na-me>)");
 noparse!(fail_bad_flag, "(?a)a");
-noparse!(fail_empty_alt_before, "|a");
-noparse!(fail_empty_alt_after, "a|");
 noparse!(fail_too_big, "a{10000000}");
 noparse!(fail_counted_no_close, "a{1001");
 noparse!(fail_unfinished_cap, "(?");
 noparse!(fail_unfinished_escape, "\\");
 noparse!(fail_octal_digit, r"\8");
 noparse!(fail_hex_digit, r"\xG0");
 noparse!(fail_hex_short, r"\xF");
 noparse!(fail_hex_long_digits, r"\x{fffg}");
 noparse!(fail_flag_bad, "(?a)");
 noparse!(fail_flag_empty, "(?)");
 noparse!(fail_double_neg, "(?-i-i)");
 noparse!(fail_neg_empty, "(?i-)");
-noparse!(fail_empty_group, "()");
 noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)");
 noparse!(fail_range_end_no_class, "[a-[:lower:]]");
 noparse!(fail_range_end_no_begin, r"[a-\A]");
 noparse!(fail_range_end_no_end, r"[a-\z]");
 noparse!(fail_range_end_no_boundary, r"[a-\b]");
+noparse!(fail_empty_alt1, r"|z");
+noparse!(fail_empty_alt2, r"z|");
+noparse!(fail_empty_alt3, r"|");
+noparse!(fail_empty_alt4, r"||");
+noparse!(fail_empty_alt5, r"()|z");
+noparse!(fail_empty_alt6, r"z|()");
+noparse!(fail_empty_alt7, r"(|)");
diff --git a/third_party/rust/regex/tests/regression.rs b/third_party/rust/regex/tests/regression.rs
index 7a30b1527f12..a09333e2c3ae 100644
--- a/third_party/rust/regex/tests/regression.rs
+++ b/third_party/rust/regex/tests/regression.rs
@@ -56,37 +56,39 @@ split!(split_on_word_boundary, r"\b", r"Should this (work?)",
        &[t!(""), t!("Should"), t!(" "), t!("this"),
          t!(" ("), t!("work"), t!("?)")]);
 matiter!(word_boundary_dfa, r"\b", "a b c",
          (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
 
 // See: https://github.com/rust-lang/regex/issues/268
 matiter!(partial_anchor, r"^a|b", "ba", (0, 1));
 
-// See: https://github.com/rust-lang/regex/issues/264
-mat!(ascii_boundary_no_capture, r"(?-u)\B", "\u{28f3e}", Some((0, 0)));
-mat!(ascii_boundary_capture, r"(?-u)(\B)", "\u{28f3e}", Some((0, 0)));
-
 // See: https://github.com/rust-lang/regex/issues/280
 ismatch!(partial_anchor_alternate_begin, r"^a|z", "yyyyya", false);
 ismatch!(partial_anchor_alternate_end, r"a$|z", "ayyyyy", false);
 
 // See: https://github.com/rust-lang/regex/issues/289
 mat!(lits_unambiguous1, r"(ABC|CDA|BC)X", "CDAX", Some((0, 4)));
 
 // See: https://github.com/rust-lang/regex/issues/291
 mat!(lits_unambiguous2, r"((IMG|CAM|MG|MB2)_|(DSCN|CIMG))(?P<n>[0-9]+)$",
      "CIMG2341", Some((0, 8)), Some((0, 4)), None, Some((0, 4)), Some((4, 8)));
 
 // See: https://github.com/rust-lang/regex/issues/271
-mat!(end_not_wb, r"$(?-u:\B)", "\u{5c124}\u{b576c}", Some((8, 8)));
 mat!(endl_or_wb, r"(?m:$)|(?-u:\b)", "\u{6084e}", Some((4, 4)));
 mat!(zero_or_end, r"(?i-u:\x00)|$", "\u{e682f}", Some((4, 4)));
 mat!(y_or_endl, r"(?i-u:y)|(?m:$)", "\u{b4331}", Some((4, 4)));
 mat!(wb_start_x, r"(?u:\b)^(?-u:X)", "X", Some((0, 1)));
 
 // See: https://github.com/rust-lang/regex/issues/321
 ismatch!(strange_anchor_non_complete_prefix, r"a^{2}", "", false);
 ismatch!(strange_anchor_non_complete_suffix, r"${2}a", "", false);
 
 // See: https://github.com/rust-lang/regex/issues/334
 mat!(captures_after_dfa_premature_end, r"a(b*(X|$))?", "abcbX",
      Some((0, 1)), None, None);
+
+// See: https://github.com/rust-lang/regex/issues/437
+ismatch!(
+    literal_panic,
+    r"typename type\-parameter\-\d+\-\d+::.+",
+    "test",
+    false);
diff --git a/third_party/rust/regex/tests/replace.rs b/third_party/rust/regex/tests/replace.rs
index 22eb0c5e5791..6d5a5b13b037 100644
--- a/third_party/rust/regex/tests/replace.rs
+++ b/third_party/rust/regex/tests/replace.rs
@@ -28,11 +28,23 @@ replace!(simple_expand, replace_all, r"(\w) (\w)", "a b", t!("$2 $1"), "b a");
 replace!(literal_dollar1, replace_all,
          r"(\w+) (\w+)", "a b", t!("$$1"), "$1");
 replace!(literal_dollar2, replace_all,
          r"(\w+) (\w+)", "a b", t!("$2 $$c $1"), "b $c a");
 replace!(no_expand1, replace,
          r"(\S+)\s+(\S+)", "w1 w2", no_expand!("$2 $1"), "$2 $1");
 replace!(no_expand2, replace,
          r"(\S+)\s+(\S+)", "w1 w2", no_expand!("$$1"), "$$1");
+use_!(Captures);
+replace!(closure_returning_reference, replace, r"(\d+)", "age: 26",
+         | captures: &Captures | &match_text!(captures.get(1).unwrap())[0..1], "age: 2");
+replace!(closure_returning_value, replace, r"\d+", "age: 26",
+         | _captures: &Captures | t!("Z").to_owned(), "age: Z");
+
 
 // See https://github.com/rust-lang/regex/issues/314
 replace!(match_at_start_replace_with_empty, replace_all, r"foo", "foobar", t!(""), "bar");
+
+// See https://github.com/rust-lang/regex/issues/393
+replace!(single_empty_match, replace, r"^", "bar", t!("foo"), "foobar");
+
+// See https://github.com/rust-lang/regex/issues/399
+replace!(capture_longest_possible_name, replace_all, r"(.)", "b", t!("${1}a $1a"), "ba ");
diff --git a/third_party/rust/regex/tests/test_crates_regex.rs b/third_party/rust/regex/tests/test_crates_regex.rs
new file mode 100644
index 000000000000..1f9ce9277abc
--- /dev/null
+++ b/third_party/rust/regex/tests/test_crates_regex.rs
@@ -0,0 +1,57 @@
+extern crate regex;
+extern crate quickcheck;
+
+/*
+ * This test is a minimal version of <rofl_0> and <subdiff_0>
+ *
+ * Once this bug gets fixed, uncomment rofl_0 and subdiff_0
+ * (in `tests/crates_regex.rs`).
+#[test]
+fn word_boundary_backtracking_default_mismatch() {
+    use regex::internal::ExecBuilder;
+
+    let backtrack_re = ExecBuilder::new(r"\b")
+        .bounded_backtracking()
+        .build()
+        .map(|exec| exec.into_regex())
+        .map_err(|err| format!("{}", err))
+        .unwrap();
+
+    let default_re = ExecBuilder::new(r"\b")
+        .build()
+        .map(|exec| exec.into_regex())
+        .map_err(|err| format!("{}", err))
+        .unwrap();
+
+    let input = "䅅\\u{a0}";
+
+    let fi1 = backtrack_re.find_iter(input);
+    let fi2 = default_re.find_iter(input);
+    for (m1, m2) in fi1.zip(fi2) {
+        assert_eq!(m1, m2);
+    }
+}
+*/
+
+mod consistent;
+
+mod crates_regex {
+
+    macro_rules! consistent {
+        ($test_name:ident, $regex_src:expr) => {
+            #[test]
+            fn $test_name() {
+                use super::consistent::backends_are_consistent;
+
+                if option_env!("RUST_REGEX_RANDOM_TEST").is_some() {
+                    match backends_are_consistent($regex_src) {
+                        Ok(_) => {},
+                        Err(err) => panic!("{}", err),
+                    }
+                }
+            }
+        }
+    }
+
+    include!("crates_regex.rs");
+}
diff --git a/third_party/rust/regex/tests/test_default.rs b/third_party/rust/regex/tests/test_default.rs
index e6cf92fa2e66..0f8a0c2dbadc 100644
--- a/third_party/rust/regex/tests/test_default.rs
+++ b/third_party/rust/regex/tests/test_default.rs
@@ -70,8 +70,18 @@ mod word_boundary_unicode;
 
 #[test]
 fn disallow_non_utf8() {
     assert!(regex::Regex::new(r"(?-u)\xFF").is_err());
     assert!(regex::Regex::new(r"(?-u).").is_err());
     assert!(regex::Regex::new(r"(?-u)[\xFF]").is_err());
     assert!(regex::Regex::new(r"(?-u)☃").is_err());
 }
+
+#[test]
+fn disallow_octal() {
+    assert!(regex::Regex::new(r"\0").is_err());
+}
+
+#[test]
+fn allow_octal() {
+    assert!(regex::RegexBuilder::new(r"\0").octal(true).build().is_ok());
+}
diff --git a/third_party/rust/regex/tests/test_default_bytes.rs b/third_party/rust/regex/tests/test_default_bytes.rs
index b049b3d2aaf5..3ac3ce457f5b 100644
--- a/third_party/rust/regex/tests/test_default_bytes.rs
+++ b/third_party/rust/regex/tests/test_default_bytes.rs
@@ -38,17 +38,17 @@ macro_rules! regex_set {
 }
 
 // Must come before other module definitions.
 include!("macros_bytes.rs");
 include!("macros.rs");
 
 // A silly wrapper to make it possible to write and match raw bytes.
 struct R<'a>(&'a [u8]);
-impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { &self.0 } }
+impl<'a> R<'a> { fn as_bytes(&self) -> &'a [u8] { self.0 } }
 
 // See: https://github.com/rust-lang/regex/issues/321
 //
 // These tests are here because they do not have the same behavior in every
 // regex engine.
 mat!(invalid_utf8_nfa1, r".", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), Some((2, 3)));
 mat!(invalid_utf8_nfa2, r"${2}ä", R(b"\xD4\xC2\x65\x2B\x0E\xFE"), None);
 mat!(invalid_utf8_nfa3, r".", R(b"\x0A\xDB\x82\x6E\x33\x01\xDD\x33\xCD"),
diff --git a/third_party/rust/regex/tests/unicode.rs b/third_party/rust/regex/tests/unicode.rs
index 48e9a95aaf41..9b65bc2b5c7f 100644
--- a/third_party/rust/regex/tests/unicode.rs
+++ b/third_party/rust/regex/tests/unicode.rs
@@ -24,8 +24,87 @@ mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
 mat!(uni_perl_s_not, r"\s+", "☃", None);
 mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));
 
 // And do the same for word boundaries.
 mat!(uni_boundary_none, r"\d\b", "6δ", None);
 mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
 mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
 mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);
+
+// Test general categories.
+//
+// We should test more, but there's a lot. Write a script to generate more of
+// these tests.
+mat!(uni_class_gencat_cased_letter,
+     r"\p{Cased_Letter}", "Ａ", Some((0, 3)));
+mat!(uni_class_gencat_close_punctuation,
+     r"\p{Close_Punctuation}", "❯", Some((0, 3)));
+mat!(uni_class_gencat_connector_punctuation,
+     r"\p{Connector_Punctuation}", "⁀", Some((0, 3)));
+mat!(uni_class_gencat_control,
+     r"\p{Control}", "\u{9f}", Some((0, 2)));
+mat!(uni_class_gencat_currency_symbol,
+     r"\p{Currency_Symbol}", "￡", Some((0, 3)));
+mat!(uni_class_gencat_dash_punctuation,
+     r"\p{Dash_Punctuation}", "〰", Some((0, 3)));
+mat!(uni_class_gencat_decimal_numer,
+     r"\p{Decimal_Number}", "𑓙", Some((0, 4)));
+mat!(uni_class_gencat_enclosing_mark,
+     r"\p{Enclosing_Mark}", "\u{A672}", Some((0, 3)));
+mat!(uni_class_gencat_final_punctuation,
+     r"\p{Final_Punctuation}", "⸡", Some((0, 3)));
+mat!(uni_class_gencat_format,
+     r"\p{Format}", "\u{E007F}", Some((0, 4)));
+mat!(uni_class_gencat_initial_punctuation,
+     r"\p{Initial_Punctuation}", "⸜", Some((0, 3)));
+mat!(uni_class_gencat_letter,
+     r"\p{Letter}", "Έ", Some((0, 2)));
+mat!(uni_class_gencat_letter_number,
+     r"\p{Letter_Number}", "ↂ", Some((0, 3)));
+mat!(uni_class_gencat_line_separator,
+     r"\p{Line_Separator}", "\u{2028}", Some((0, 3)));
+mat!(uni_class_gencat_lowercase_letter,
+     r"\p{Lowercase_Letter}", "ϛ", Some((0, 2)));
+mat!(uni_class_gencat_mark,
+     r"\p{Mark}", "\u{E01EF}", Some((0, 4)));
+mat!(uni_class_gencat_math,
+     r"\p{Math}", "⋿", Some((0, 3)));
+mat!(uni_class_gencat_modifier_letter,
+     r"\p{Modifier_Letter}", "𖭃", Some((0, 4)));
+mat!(uni_class_gencat_modifier_symbol,
+     r"\p{Modifier_Symbol}", "🏿", Some((0, 4)));
+mat!(uni_class_gencat_nonspacing_mark,
+     r"\p{Nonspacing_Mark}", "\u{1E94A}", Some((0, 4)));
+mat!(uni_class_gencat_number,
+     r"\p{Number}", "⓿", Some((0, 3)));
+mat!(uni_class_gencat_open_punctuation,
+     r"\p{Open_Punctuation}", "｟", Some((0, 3)));
+mat!(uni_class_gencat_other,
+     r"\p{Other}", "\u{bc9}", Some((0, 3)));
+mat!(uni_class_gencat_other_letter,
+     r"\p{Other_Letter}", "ꓷ", Some((0, 3)));
+mat!(uni_class_gencat_other_number,
+     r"\p{Other_Number}", "㉏", Some((0, 3)));
+mat!(uni_class_gencat_other_punctuation,
+     r"\p{Other_Punctuation}", "𞥞", Some((0, 4)));
+mat!(uni_class_gencat_other_symbol,
+     r"\p{Other_Symbol}", "⅌", Some((0, 3)));
+mat!(uni_class_gencat_paragraph_separator,
+     r"\p{Paragraph_Separator}", "\u{2029}", Some((0, 3)));
+mat!(uni_class_gencat_private_use,
+     r"\p{Private_Use}", "\u{10FFFD}", Some((0, 4)));
+mat!(uni_class_gencat_punctuation,
+     r"\p{Punctuation}", "𑁍", Some((0, 4)));
+mat!(uni_class_gencat_separator,
+     r"\p{Separator}", "\u{3000}", Some((0, 3)));
+mat!(uni_class_gencat_space_separator,
+     r"\p{Space_Separator}", "\u{205F}", Some((0, 3)));
+mat!(uni_class_gencat_spacing_mark,
+     r"\p{Spacing_Mark}", "\u{16F7E}", Some((0, 4)));
+mat!(uni_class_gencat_symbol,
+     r"\p{Symbol}", "⯈", Some((0, 3)));
+mat!(uni_class_gencat_titlecase_letter,
+     r"\p{Titlecase_Letter}", "ῼ", Some((0, 3)));
+mat!(uni_class_gencat_unassigned,
+     r"\p{Unassigned}", "\u{10FFFF}", Some((0, 4)));
+mat!(uni_class_gencat_uppercase_letter,
+     r"\p{Uppercase_Letter}", "Ꝋ", Some((0, 3)));
diff --git a/third_party/rust/regex/tests/word_boundary_unicode.rs b/third_party/rust/regex/tests/word_boundary_unicode.rs
index 43612a91ac68..c41355ffc4b8 100644
--- a/third_party/rust/regex/tests/word_boundary_unicode.rs
+++ b/third_party/rust/regex/tests/word_boundary_unicode.rs
@@ -1,8 +1,6 @@
 // Unicode word boundaries know about Unicode characters.
 // For ASCII word boundaries, the tests are precisely inverted.
 matiter!(unicode1, r"\bx\b", "áxβ");
 matiter!(unicode2, r"\Bx\B", "áxβ", (2, 3));
 
 matiter!(ascii1, r"(?-u:\b)x(?-u:\b)", "áxβ", (2, 3));
-matiter!(ascii2, r"(?-u:\B)x(?-u:\B)", "áxβ");
-matiter!(ascii3, r"(?-u:\B)", "0\u{7EF5E}", (5, 5));
diff --git a/third_party/rust/smallvec/.cargo-checksum.json b/third_party/rust/smallvec/.cargo-checksum.json
index a5768b623054..518caa798e8f 100644
--- a/third_party/rust/smallvec/.cargo-checksum.json
+++ b/third_party/rust/smallvec/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"91edce5ea2a1956399db4b17f580c8b7995af3aa9801c4314865f560c55d6d09","Cargo.toml":"1bbfc40ffd7370696242dd27dd4f0e211d3309aebca8b564029a6ac167e81726","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"1bc64a621160a291c86b8770f3eeaa45a31c31d91c2a071f39981c14fdacb035","benches/bench.rs":"54cf4879d36ba2a9f3423af91bb93227b70849200e5bf74e384a166d6aa09893","lib.rs":"bd237262110649b266c6599d4f8b3d1f7d7c758d6852b65243c8221811d273e8"},"package":"44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"}
\ No newline at end of file
+{"files":{".travis.yml":"106d159f3fbe3ad49ebc631f9707baedf6adb012e5210443919232db5375fa7b","Cargo.toml":"7d0640e384cf1d81593bd049f6bf5b1dcf129db200f4f21b18c06b6bdb5d67a3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"1bc64a621160a291c86b8770f3eeaa45a31c31d91c2a071f39981c14fdacb035","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"513374844e0fc3bc332f5172de3a604acab160e02f576f7d9eaebe64149588a9"},"package":"153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d"}
\ No newline at end of file
diff --git a/third_party/rust/smallvec/.travis.yml b/third_party/rust/smallvec/.travis.yml
index 7123702a79af..b45c7f81be18 100644
--- a/third_party/rust/smallvec/.travis.yml
+++ b/third_party/rust/smallvec/.travis.yml
@@ -1,14 +1,16 @@
 language: rust
 rust:
+  - 1.20.0
   - nightly
   - beta
   - stable
 script: |
   cargo build --verbose &&
-  cargo build --all-features --verbose &&
   cargo test --verbose &&
-  cargo test --all-features --verbose &&
-  ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features) &&
+  cargo test --verbose --features serde &&
+  ([ $TRAVIS_RUST_VERSION != nightly ] || cargo check --verbose --no-default-features) &&
+  ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --features union) &&
+  ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --all-features) &&
   ([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench)
 notifications:
   webhooks: http://build.servo.org:54856/travis
diff --git a/third_party/rust/smallvec/Cargo.toml b/third_party/rust/smallvec/Cargo.toml
index 02191cb84be1..4600cdbd4ebe 100644
--- a/third_party/rust/smallvec/Cargo.toml
+++ b/third_party/rust/smallvec/Cargo.toml
@@ -7,30 +7,34 @@
 #
 # 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 = "smallvec"
-version = "0.6.0"
+version = "0.6.5"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 description = "'Small vector' optimization: store up to a small number of items on the stack"
 documentation = "http://doc.servo.org/smallvec/"
 readme = "README.md"
 keywords = ["small", "vec", "vector", "stack", "no_std"]
 categories = ["data-structures"]
-license = "MPL-2.0"
+license = "MIT/Apache-2.0"
 repository = "https://github.com/servo/rust-smallvec"
 
 [lib]
 name = "smallvec"
 path = "lib.rs"
 [dependencies.serde]
 version = "1"
 optional = true
+
+[dependencies.unreachable]
+version = "1.0.0"
 [dev-dependencies.bincode]
-version = "0.8"
+version = "1.0.1"
 
 [features]
 default = ["std"]
 std = []
+union = []
diff --git a/third_party/rust/smallvec/LICENSE b/third_party/rust/smallvec/LICENSE
deleted file mode 100644
index 398385c9fb9b..000000000000
--- a/third_party/rust/smallvec/LICENSE
+++ /dev/null
@@ -1,374 +0,0 @@
- Mozilla Public License Version 2.0
-==================================
-
-1. Definitions
---------------
-
-1.1. "Contributor"
-means each individual or legal entity that creates, contributes to
-the creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-means the combination of the Contributions of others (if any) used
-by a Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-means Source Code Form to which the initial Contributor has attached
-the notice in Exhibit A, the Executable Form of such Source Code
-Form, and Modifications of such Source Code Form, in each case
-including portions thereof.
-
-1.5. "Incompatible With Secondary Licenses"
-means
-
-(a) that the initial Contributor has attached the notice described
-in Exhibit B to the Covered Software; or
-
-(b) that the Covered Software was made available under the terms of
-version 1.1 or earlier of the License, but not also under the
-terms of a Secondary License.
-
-1.6. "Executable Form"
-means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-means a work that combines Covered Software with other material, in
-a separate file or files, that is not Covered Software.
-
-1.8. "License"
-means this document.
-
-1.9. "Licensable"
-means having the right to grant, to the maximum extent possible,
-whether at the time of the initial grant or subsequently, any and
-all of the rights conveyed by this License.
-
-1.10. "Modifications"
-means any of the following:
-
-(a) any file in Source Code Form that results from an addition to,
-deletion from, or modification of the contents of Covered
-Software; or
-
-(b) any new file in Source Code Form that contains any Covered
-Software.
-
-1.11. "Patent Claims" of a Contributor
-means any patent claim(s), including without limitation, method,
-process, and apparatus claims, in any patent Licensable by such
-Contributor that would be infringed, but for the grant of the
-License, by the making, using, selling, offering for sale, having
-made, import, or transfer of either its Contributions or its
-Contributor Version.
-
-1.12. "Secondary License"
-means either the GNU General Public License, Version 2.0, the GNU
-Lesser General Public License, Version 2.1, the GNU Affero General
-Public License, Version 3.0, or any later versions of those
-licenses.
-
-1.13. "Source Code Form"
-means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-means an individual or a legal entity exercising rights under this
-License. For legal entities, "You" includes any entity that
-controls, is controlled by, or is under common control with You. For
-purposes of this definition, "control" means (a) the power, direct
-or indirect, to cause the direction or management of such entity,
-whether by contract or otherwise, or (b) ownership of more than
-fifty percent (50%) of the outstanding shares or beneficial
-ownership of such entity.
-
-2. License Grants and Conditions
---------------------------------
-
-2.1. Grants
-
-Each Contributor hereby grants You a world-wide, royalty-free,
-non-exclusive license:
-
-(a) under intellectual property rights (other than patent or trademark)
-Licensable by such Contributor to use, reproduce, make available,
-modify, display, perform, distribute, and otherwise exploit its
-Contributions, either on an unmodified basis, with Modifications, or
-as part of a Larger Work; and
-
-(b) under Patent Claims of such Contributor to make, use, sell, offer
-for sale, have made, import, and otherwise transfer either its
-Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-The licenses granted in Section 2.1 with respect to any Contribution
-become effective for each Contribution on the date the Contributor first
-distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-The licenses granted in this Section 2 are the only rights granted under
-this License. No additional rights or licenses will be implied from the
-distribution or licensing of Covered Software under this License.
-Notwithstanding Section 2.1(b) above, no patent license is granted by a
-Contributor:
-
-(a) for any code that a Contributor has removed from Covered Software;
-or
-
-(b) for infringements caused by: (i) Your and any other third party's
-modifications of Covered Software, or (ii) the combination of its
-Contributions with other software (except as part of its Contributor
-Version); or
-
-(c) under Patent Claims infringed by Covered Software in the absence of
-its Contributions.
-
-This License does not grant any rights in the trademarks, service marks,
-or logos of any Contributor (except as may be necessary to comply with
-the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-No Contributor makes additional grants as a result of Your choice to
-distribute the Covered Software under a subsequent version of this
-License (see Section 10.2) or under the terms of a Secondary License (if
-permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-Each Contributor represents that the Contributor believes its
-Contributions are its original creation(s) or it has sufficient rights
-to grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-This License is not intended to limit any rights You have under
-applicable copyright doctrines of fair use, fair dealing, or other
-equivalents.
-
-2.7. Conditions
-
-Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-in Section 2.1.
-
-3. Responsibilities
--------------------
-
-3.1. Distribution of Source Form
-
-All distribution of Covered Software in Source Code Form, including any
-Modifications that You create or to which You contribute, must be under
-the terms of this License. You must inform recipients that the Source
-Code Form of the Covered Software is governed by the terms of this
-License, and how they can obtain a copy of this License. You may not
-attempt to alter or restrict the recipients' rights in the Source Code
-Form.
-
-3.2. Distribution of Executable Form
-
-If You distribute Covered Software in Executable Form then:
-
-(a) such Covered Software must also be made available in Source Code
-Form, as described in Section 3.1, and You must inform recipients of
-the Executable Form how they can obtain a copy of such Source Code
-Form by reasonable means in a timely manner, at a charge no more
-than the cost of distribution to the recipient; and
-
-(b) You may distribute such Executable Form under the terms of this
-License, or sublicense it under different terms, provided that the
-license for the Executable Form does not attempt to limit or alter
-the recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-You may create and distribute a Larger Work under terms of Your choice,
-provided that You also comply with the requirements of this License for
-the Covered Software. If the Larger Work is a combination of Covered
-Software with a work governed by one or more Secondary Licenses, and the
-Covered Software is not Incompatible With Secondary Licenses, this
-License permits You to additionally distribute such Covered Software
-under the terms of such Secondary License(s), so that the recipient of
-the Larger Work may, at their option, further distribute the Covered
-Software under the terms of either this License or such Secondary
-License(s).
-
-3.4. Notices
-
-You may not remove or alter the substance of any license notices
-(including copyright notices, patent notices, disclaimers of warranty,
-or limitations of liability) contained within the Source Code Form of
-the Covered Software, except that You may alter any license notices to
-the extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-You may choose to offer, and to charge a fee for, warranty, support,
-indemnity or liability obligations to one or more recipients of Covered
-Software. However, You may do so only on Your own behalf, and not on
-behalf of any Contributor. You must make it absolutely clear that any
-such warranty, support, indemnity, or liability obligation is offered by
-You alone, and You hereby agree to indemnify every Contributor for any
-liability incurred by such Contributor as a result of warranty, support,
-indemnity or liability terms You offer. You may include additional
-disclaimers of warranty and limitations of liability specific to any
-jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
----------------------------------------------------
-
-If it is impossible for You to comply with any of the terms of this
-License with respect to some or all of the Covered Software due to
-statute, judicial order, or regulation then You must: (a) comply with
-the terms of this License to the maximum extent possible; and (b)
-describe the limitations and the code they affect. Such description must
-be placed in a text file included with all distributions of the Covered
-Software under this License. Except to the extent prohibited by statute
-or regulation, such description must be sufficiently detailed for a
-recipient of ordinary skill to be able to understand it.
-
-5. Termination
---------------
-
-5.1. The rights granted under this License will terminate automatically
-if You fail to comply with any of its terms. However, if You become
-compliant, then the rights granted under this License from a particular
-Contributor are reinstated (a) provisionally, unless and until such
-Contributor explicitly and finally terminates Your grants, and (b) on an
-ongoing basis, if such Contributor fails to notify You of the
-non-compliance by some reasonable means prior to 60 days after You have
-come back into compliance. Moreover, Your grants from a particular
-Contributor are reinstated on an ongoing basis if such Contributor
-notifies You of the non-compliance by some reasonable means, this is the
-first time You have received notice of non-compliance with this License
-from such Contributor, and You become compliant prior to 30 days after
-Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-infringement claim (excluding declaratory judgment actions,
-counter-claims, and cross-claims) alleging that a Contributor Version
-directly or indirectly infringes any patent, then the rights granted to
-You by any and all Contributors for the Covered Software under Section
-2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-end user license agreements (excluding distributors and resellers) which
-have been validly granted by You or Your distributors under this License
-prior to termination shall survive termination.
-
-************************************************************************
-* *
-* 6. Disclaimer of Warranty *
-* ------------------------- *
-* *
-* Covered Software is provided under this License on an "as is" *
-* basis, without warranty of any kind, either expressed, implied, or *
-* statutory, including, without limitation, warranties that the *
-* Covered Software is free of defects, merchantable, fit for a *
-* particular purpose or non-infringing. The entire risk as to the *
-* quality and performance of the Covered Software is with You. *
-* Should any Covered Software prove defective in any respect, You *
-* (not any Contributor) assume the cost of any necessary servicing, *
-* repair, or correction. This disclaimer of warranty constitutes an *
-* essential part of this License. No use of any Covered Software is *
-* authorized under this License except under this disclaimer. *
-* *
-************************************************************************
-
-************************************************************************
-* *
-* 7. Limitation of Liability *
-* -------------------------- *
-* *
-* Under no circumstances and under no legal theory, whether tort *
-* (including negligence), contract, or otherwise, shall any *
-* Contributor, or anyone who distributes Covered Software as *
-* permitted above, be liable to You for any direct, indirect, *
-* special, incidental, or consequential damages of any character *
-* including, without limitation, damages for lost profits, loss of *
-* goodwill, work stoppage, computer failure or malfunction, or any *
-* and all other commercial damages or losses, even if such party *
-* shall have been informed of the possibility of such damages. This *
-* limitation of liability shall not apply to liability for death or *
-* personal injury resulting from such party's negligence to the *
-* extent applicable law prohibits such limitation. Some *
-* jurisdictions do not allow the exclusion or limitation of *
-* incidental or consequential damages, so this exclusion and *
-* limitation may not apply to You. *
-* *
-************************************************************************
-
-8. Litigation
--------------
-
-Any litigation relating to this License may be brought only in the
-courts of a jurisdiction where the defendant maintains its principal
-place of business and such litigation shall be governed by laws of that
-jurisdiction, without reference to its conflict-of-law provisions.
-Nothing in this Section shall prevent a party's ability to bring
-cross-claims or counter-claims.
-
-9. Miscellaneous
-----------------
-
-This License represents the complete agreement concerning the subject
-matter hereof. If any provision of this License is held to be
-unenforceable, such provision shall be reformed only to the extent
-necessary to make it enforceable. Any law or regulation which provides
-that the language of a contract shall be construed against the drafter
-shall not be used to construe this License against a Contributor.
-
-10. Versions of the License
----------------------------
-
-10.1. New Versions
-
-Mozilla Foundation is the license steward. Except as provided in Section
-10.3, no one other than the license steward has the right to modify or
-publish new versions of this License. Each version will be given a
-distinguishing version number.
-
-10.2. Effect of New Versions
-
-You may distribute the Covered Software under the terms of the version
-of the License under which You originally received the Covered Software,
-or under the terms of any subsequent version published by the license
-steward.
-
-10.3. Modified Versions
-
-If you create software not governed by this License, and you want to
-create a new license for such software, you may create and use a
-modified version of this License if you rename the license and remove
-any references to the name of the license steward (except to note that
-such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-Licenses
-
-If You choose to distribute Source Code Form that is Incompatible With
-Secondary Licenses under the terms of this version of the License, the
-notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
--------------------------------------------
-
-This Source Code Form is subject to the terms of the Mozilla Public
-License, v. 2.0. If a copy of the MPL was not distributed with this
-file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular
-file, then You may include the notice in a location (such as a LICENSE
-file in a relevant directory) where a recipient would be likely to look
-for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
----------------------------------------------------------
-
-This Source Code Form is "Incompatible With Secondary Licenses", as
-defined by the Mozilla Public License, v. 2.0.
-
diff --git a/third_party/rust/smallvec/LICENSE-APACHE b/third_party/rust/smallvec/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/smallvec/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/smallvec/LICENSE-MIT b/third_party/rust/smallvec/LICENSE-MIT
new file mode 100644
index 000000000000..9729c1284e1b
--- /dev/null
+++ b/third_party/rust/smallvec/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 The Servo Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/smallvec/benches/bench.rs b/third_party/rust/smallvec/benches/bench.rs
index 3ca112aab971..36cb1333fab7 100644
--- a/third_party/rust/smallvec/benches/bench.rs
+++ b/third_party/rust/smallvec/benches/bench.rs
@@ -1,111 +1,295 @@
 #![feature(test)]
 
+#[macro_use]
 extern crate smallvec;
 extern crate test;
 
-use smallvec::SmallVec;
 use self::test::Bencher;
+use smallvec::{ExtendFromSlice, SmallVec};
 
-#[bench]
-fn bench_push(b: &mut Bencher) {
+const VEC_SIZE: usize = 16;
+const SPILLED_SIZE: usize = 100;
+
+trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<T> {
+    fn new() -> Self;
+    fn push(&mut self, val: T);
+    fn pop(&mut self) -> Option<T>;
+    fn remove(&mut self, p: usize) -> T;
+    fn insert(&mut self, n: usize, val: T);
+    fn from_elem(val: T, n: usize) -> Self;
+    fn from_elems(val: &[T]) -> Self;
+}
+
+impl<T: Copy> Vector<T> for Vec<T> {
+    fn new() -> Self {
+        Self::with_capacity(VEC_SIZE)
+    }
+
+    fn push(&mut self, val: T) {
+        self.push(val)
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        self.pop()
+    }
+
+    fn remove(&mut self, p: usize) -> T {
+        self.remove(p)
+    }
+
+    fn insert(&mut self, n: usize, val: T) {
+        self.insert(n, val)
+    }
+
+    fn from_elem(val: T, n: usize) -> Self {
+        vec![val; n]
+    }
+
+    fn from_elems(val: &[T]) -> Self {
+        val.to_owned()
+    }
+}
+
+impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
+    fn new() -> Self {
+        Self::new()
+    }
+
+    fn push(&mut self, val: T) {
+        self.push(val)
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        self.pop()
+    }
+
+    fn remove(&mut self, p: usize) -> T {
+        self.remove(p)
+    }
+
+    fn insert(&mut self, n: usize, val: T) {
+        self.insert(n, val)
+    }
+
+    fn from_elem(val: T, n: usize) -> Self {
+        smallvec![val; n]
+    }
+
+    fn from_elems(val: &[T]) -> Self {
+        SmallVec::from_slice(val)
+    }
+}
+
+macro_rules! make_benches {
+    ($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => {
+        $(
+            #[bench]
+            fn $b_name(b: &mut Bencher) {
+                $g_name::<$typ>($($args,)* b)
+            }
+        )*
+    }
+}
+
+make_benches! {
+    SmallVec<[u64; VEC_SIZE]> {
+        bench_push => gen_push(SPILLED_SIZE as _),
+        bench_push_small => gen_push(VEC_SIZE as _),
+        bench_insert => gen_insert(SPILLED_SIZE as _),
+        bench_insert_small => gen_insert(VEC_SIZE as _),
+        bench_remove => gen_remove(SPILLED_SIZE as _),
+        bench_remove_small => gen_remove(VEC_SIZE as _),
+        bench_extend => gen_extend(SPILLED_SIZE as _),
+        bench_extend_small => gen_extend(VEC_SIZE as _),
+        bench_from_iter => gen_from_iter(SPILLED_SIZE as _),
+        bench_from_iter_small => gen_from_iter(VEC_SIZE as _),
+        bench_from_slice => gen_from_slice(SPILLED_SIZE as _),
+        bench_from_slice_small => gen_from_slice(VEC_SIZE as _),
+        bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _),
+        bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _),
+        bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _),
+        bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _),
+        bench_pushpop => gen_pushpop(),
+    }
+}
+
+make_benches! {
+    Vec<u64> {
+        bench_push_vec => gen_push(SPILLED_SIZE as _),
+        bench_push_vec_small => gen_push(VEC_SIZE as _),
+        bench_insert_vec => gen_insert(SPILLED_SIZE as _),
+        bench_insert_vec_small => gen_insert(VEC_SIZE as _),
+        bench_remove_vec => gen_remove(SPILLED_SIZE as _),
+        bench_remove_vec_small => gen_remove(VEC_SIZE as _),
+        bench_extend_vec => gen_extend(SPILLED_SIZE as _),
+        bench_extend_vec_small => gen_extend(VEC_SIZE as _),
+        bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _),
+        bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _),
+        bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _),
+        bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _),
+        bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _),
+        bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _),
+        bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _),
+        bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _),
+        bench_pushpop_vec => gen_pushpop(),
+    }
+}
+
+fn gen_push<V: Vector<u64>>(n: u64, b: &mut Bencher) {
     #[inline(never)]
-    fn push_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
-        vec.push(x)
+    fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
+        vec.push(x);
     }
 
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
-        for x in 0..100 {
+        let mut vec = V::new();
+        for x in 0..n {
             push_noinline(&mut vec, x);
         }
         vec
     });
 }
 
-#[bench]
-fn bench_insert(b: &mut Bencher) {
+fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) {
     #[inline(never)]
-    fn insert_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
-        vec.insert(0, x)
+    fn insert_noinline<V: Vector<u64>>(vec: &mut V, p: usize, x: u64) {
+        vec.insert(p, x)
     }
 
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
-        for x in 0..100 {
-            insert_noinline(&mut vec, x);
+        let mut vec = V::new();
+        // Add one element, with each iteration we insert one before the end.
+        // This means that we benchmark the insertion operation and not the
+        // time it takes to `ptr::copy` the data.
+        vec.push(0);
+        for x in 0..n {
+            insert_noinline(&mut vec, x as _, x);
         }
         vec
     });
 }
 
-#[bench]
-fn bench_insert_many(b: &mut Bencher) {
+fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) {
     #[inline(never)]
-    fn insert_many_noinline<I: IntoIterator<Item=u64>>(
-        vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) {
-        vec.insert_many(index, iterable)
+    fn remove_noinline<V: Vector<u64>>(vec: &mut V, p: usize) -> u64 {
+        vec.remove(p)
     }
 
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
-        insert_many_noinline(&mut vec, 0, 0..100);
-        insert_many_noinline(&mut vec, 0, 0..100);
+        let mut vec = V::from_elem(0, n as _);
+
+        for x in (0..n - 1).rev() {
+            remove_noinline(&mut vec, x);
+        }
+    });
+}
+
+fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    b.iter(|| {
+        let mut vec = V::new();
+        vec.extend(0..n);
         vec
     });
 }
 
-#[bench]
-fn bench_extend(b: &mut Bencher) {
+fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
-        vec.extend(0..100);
+        let vec = V::from(&v);
         vec
     });
 }
 
-#[bench]
-fn bench_from_slice(b: &mut Bencher) {
-    let v: Vec<u64> = (0..100).collect();
+fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
     b.iter(|| {
-        let vec: SmallVec<[u64; 16]> = SmallVec::from_slice(&v);
+        let vec = V::from_elems(&v);
         vec
     });
 }
 
-#[bench]
-fn bench_extend_from_slice(b: &mut Bencher) {
-    let v: Vec<u64> = (0..100).collect();
+fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+    let v: Vec<u64> = (0..n).collect();
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
+        let mut vec = V::new();
         vec.extend_from_slice(&v);
         vec
     });
 }
 
+fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) {
+    #[inline(never)]
+    fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) -> Option<u64> {
+        vec.push(x);
+        vec.pop()
+    }
+
+    b.iter(|| {
+        let mut vec = V::new();
+        for x in 0..SPILLED_SIZE as _ {
+            pushpop_noinline(&mut vec, x);
+        }
+        vec
+    });
+}
+
+fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) {
+    b.iter(|| {
+        let vec = V::from_elem(42, n);
+        vec
+    });
+}
+
+#[bench]
+fn bench_insert_many(b: &mut Bencher) {
+    #[inline(never)]
+    fn insert_many_noinline<I: IntoIterator<Item = u64>>(
+        vec: &mut SmallVec<[u64; VEC_SIZE]>,
+        index: usize,
+        iterable: I,
+    ) {
+        vec.insert_many(index, iterable)
+    }
+
+    b.iter(|| {
+        let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
+        insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+        insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+        vec
+    });
+}
+
 #[bench]
 fn bench_insert_from_slice(b: &mut Bencher) {
-    let v: Vec<u64> = (0..100).collect();
+    let v: Vec<u64> = (0..SPILLED_SIZE as _).collect();
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
+        let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
         vec.insert_from_slice(0, &v);
         vec.insert_from_slice(0, &v);
         vec
     });
 }
 
 #[bench]
-fn bench_pushpop(b: &mut Bencher) {
-    #[inline(never)]
-    fn pushpop_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
-        vec.push(x);
-        vec.pop();
-    }
+fn bench_macro_from_list(b: &mut Bencher) {
+    b.iter(|| {
+        let vec: SmallVec<[u64; 16]> = smallvec![
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+            0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+            0x80000, 0x100000,
+        ];
+        vec
+    });
+}
 
+#[bench]
+fn bench_macro_from_list_vec(b: &mut Bencher) {
     b.iter(|| {
-        let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
-        for x in 0..100 {
-            pushpop_noinline(&mut vec, x);
-        }
+        let vec: Vec<u64> = vec![
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+            0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+            0x80000, 0x100000,
+        ];
         vec
     });
 }
diff --git a/third_party/rust/smallvec/lib.rs b/third_party/rust/smallvec/lib.rs
index 09cceab0ecd9..881021e14c27 100644
--- a/third_party/rust/smallvec/lib.rs
+++ b/third_party/rust/smallvec/lib.rs
@@ -1,64 +1,152 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
 
 //! Small vectors in various sizes. These store a certain number of elements inline, and fall back
 //! to the heap for larger allocations.  This can be a useful optimization for improving cache
 //! locality and reducing allocator traffic for workloads that fit within the inline buffer.
 //!
 //! ## no_std support
 //!
 //! By default, `smallvec` depends on `libstd`. However, it can be configured to use the unstable
 //! `liballoc` API instead, for use on platforms that have `liballoc` but not `libstd`.  This
 //! configuration is currently unstable and is not guaranteed to work on all versions of Rust.
 //!
 //! To depend on `smallvec` without `libstd`, use `default-features = false` in the `smallvec`
 //! section of Cargo.toml to disable its `"std"` feature.
+//!
+//! ## `union` feature
+//!
+//! When the `union` feature is enabled `smallvec` will track its state (inline or spilled)
+//! without the use of an enum tag, reducing the size of the `smallvec` by one machine word.
+//! This means that there is potentially no space overhead compared to `Vec`.
+//! Note that `smallvec` can still be larger than `Vec` if the inline buffer is larger than two
+//! machine words.
+//!
+//! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml.
+//! Note that this feature requires a nightly compiler (for now).
 
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(not(feature = "std"), feature(alloc))]
+#![cfg_attr(feature = "union", feature(untagged_unions))]
 #![deny(missing_docs)]
 
 
 #[cfg(not(feature = "std"))]
-#[cfg_attr(test, macro_use)]
+#[macro_use]
 extern crate alloc;
 
 #[cfg(not(feature = "std"))]
-use alloc::Vec;
+use alloc::vec::Vec;
 
 #[cfg(feature = "serde")]
 extern crate serde;
 
+extern crate unreachable;
+use unreachable::UncheckedOptionExt;
+
 #[cfg(not(feature = "std"))]
 mod std {
     pub use core::*;
 }
 
 use std::borrow::{Borrow, BorrowMut};
 use std::cmp;
 use std::fmt;
 use std::hash::{Hash, Hasher};
-use std::iter::{IntoIterator, FromIterator};
+use std::iter::{IntoIterator, FromIterator, repeat};
 use std::mem;
+#[cfg(not(feature = "union"))]
+use std::mem::ManuallyDrop;
 use std::ops;
 use std::ptr;
 use std::slice;
 #[cfg(feature = "std")]
 use std::io;
 #[cfg(feature = "serde")]
 use serde::ser::{Serialize, Serializer, SerializeSeq};
 #[cfg(feature = "serde")]
 use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
 #[cfg(feature = "serde")]
 use std::marker::PhantomData;
 
-use SmallVecData::{Inline, Heap};
+/// Creates a [`SmallVec`] containing the arguments.
+///
+/// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions.
+/// There are two forms of this macro:
+///
+/// - Create a [`SmallVec`] containing a given list of elements:
+///
+/// ```
+/// # #[macro_use] extern crate smallvec;
+/// # use smallvec::SmallVec;
+/// # fn main() {
+/// let v: SmallVec<[_; 128]> = smallvec![1, 2, 3];
+/// assert_eq!(v[0], 1);
+/// assert_eq!(v[1], 2);
+/// assert_eq!(v[2], 3);
+/// # }
+/// ```
+///
+/// - Create a [`SmallVec`] from a given element and size:
+///
+/// ```
+/// # #[macro_use] extern crate smallvec;
+/// # use smallvec::SmallVec;
+/// # fn main() {
+/// let v: SmallVec<[_; 0x8000]> = smallvec![1; 3];
+/// assert_eq!(v, SmallVec::from_buf([1, 1, 1]));
+/// # }
+/// ```
+///
+/// Note that unlike array expressions this syntax supports all elements
+/// which implement [`Clone`] and the number of elements doesn't have to be
+/// a constant.
+///
+/// This will use `clone` to duplicate an expression, so one should be careful
+/// using this with types having a nonstandard `Clone` implementation. For
+/// example, `smallvec![Rc::new(1); 5]` will create a vector of five references
+/// to the same boxed integer value, not five references pointing to independently
+/// boxed integers.
+
+#[macro_export]
+macro_rules! smallvec {
+    // count helper: transform any expression into 1
+    (@one $x:expr) => (1usize);
+    ($elem:expr; $n:expr) => ({
+        $crate::SmallVec::from_elem($elem, $n)
+    });
+    ($($x:expr),*$(,)*) => ({
+        let count = 0usize $(+ smallvec!(@one $x))*;
+        let mut vec = $crate::SmallVec::new();
+        if count <= vec.inline_size() {
+            $(vec.push($x);)*
+            vec
+        } else {
+            $crate::SmallVec::from_vec(vec![$($x,)*])
+        }
+    });
+}
+
+/// `panic!()` in debug builds, optimization hint in release.
+#[cfg(not(feature = "union"))]
+macro_rules! debug_unreachable {
+    () => { debug_unreachable!("entered unreachable code") };
+    ($e:expr) => {
+        if cfg!(not(debug_assertions)) {
+            unreachable::unreachable();
+        } else {
+            panic!($e);
+        }
+    }
+}
 
 /// Common operations implemented by both `Vec` and `SmallVec`.
 ///
 /// This can be used to write generic code that works with both `Vec` and `SmallVec`.
 ///
 /// ## Example
 ///
 /// ```rust
@@ -147,89 +235,134 @@ pub struct Drain<'a, T: 'a> {
     iter: slice::IterMut<'a,T>,
 }
 
 impl<'a, T: 'a> Iterator for Drain<'a,T> {
     type Item = T;
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        match self.iter.next() {
-            None => None,
-            Some(reference) => {
-                unsafe {
-                    Some(ptr::read(reference))
-                }
-            }
-        }
+        self.iter.next().map(|reference| unsafe { ptr::read(reference) })
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
 }
 
 impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
-        match self.iter.next_back() {
-            None => None,
-            Some(reference) => {
-                unsafe {
-                    Some(ptr::read(reference))
-                }
-            }
-        }
+        self.iter.next_back().map(|reference| unsafe { ptr::read(reference) })
     }
 }
 
 impl<'a, T> ExactSizeIterator for Drain<'a, T> { }
 
 impl<'a, T: 'a> Drop for Drain<'a,T> {
     fn drop(&mut self) {
         // Destroy the remaining elements.
         for _ in self.by_ref() {}
     }
 }
 
+#[cfg(feature = "union")]
+#[allow(unions_with_drop_fields)]
+union SmallVecData<A: Array> {
+    inline: A,
+    heap: (*mut A::Item, usize),
+}
+
+#[cfg(feature = "union")]
+impl<A: Array> SmallVecData<A> {
+    #[inline]
+    unsafe fn inline(&self) -> &A {
+        &self.inline
+    }
+    #[inline]
+    unsafe fn inline_mut(&mut self) -> &mut A {
+        &mut self.inline
+    }
+    #[inline]
+    fn from_inline(inline: A) -> SmallVecData<A> {
+        SmallVecData { inline }
+    }
+    #[inline]
+    unsafe fn into_inline(self) -> A { self.inline }
+    #[inline]
+    unsafe fn heap(&self) -> (*mut A::Item, usize) {
+        self.heap
+    }
+    #[inline]
+    unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) {
+        &mut self.heap
+    }
+    #[inline]
+    fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData<A> {
+        SmallVecData { heap: (ptr, len) }
+    }
+}
+
+#[cfg(not(feature = "union"))]
 enum SmallVecData<A: Array> {
-    Inline { array: A },
-    Heap { ptr: *mut A::Item, capacity: usize },
+    Inline(ManuallyDrop<A>),
+    Heap((*mut A::Item, usize)),
 }
 
+#[cfg(not(feature = "union"))]
 impl<A: Array> SmallVecData<A> {
-    fn ptr_mut(&mut self) -> *mut A::Item {
+    #[inline]
+    unsafe fn inline(&self) -> &A {
         match *self {
-            Inline { ref mut array } => array.ptr_mut(),
-            Heap { ptr, .. } => ptr,
+            SmallVecData::Inline(ref a) => a,
+            _ => debug_unreachable!(),
         }
     }
+    #[inline]
+    unsafe fn inline_mut(&mut self) -> &mut A {
+        match *self {
+            SmallVecData::Inline(ref mut a) => a,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    fn from_inline(inline: A) -> SmallVecData<A> {
+        SmallVecData::Inline(ManuallyDrop::new(inline))
+    }
+    #[inline]
+    unsafe fn into_inline(self) -> A {
+        match self {
+            SmallVecData::Inline(a) => ManuallyDrop::into_inner(a),
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    unsafe fn heap(&self) -> (*mut A::Item, usize) {
+        match *self {
+            SmallVecData::Heap(data) => data,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) {
+        match *self {
+            SmallVecData::Heap(ref mut data) => data,
+            _ => debug_unreachable!(),
+        }
+    }
+    #[inline]
+    fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData<A> {
+        SmallVecData::Heap((ptr, len))
+    }
 }
 
 unsafe impl<A: Array + Send> Send for SmallVecData<A> {}
 unsafe impl<A: Array + Sync> Sync for SmallVecData<A> {}
 
-impl<A: Array> Drop for SmallVecData<A> {
-    fn drop(&mut self) {
-        unsafe {
-            match *self {
-                ref mut inline @ Inline { .. } => {
-                    // Inhibit the array destructor.
-                    ptr::write(inline, Heap {
-                        ptr: ptr::null_mut(),
-                        capacity: 0,
-                    });
-                }
-                Heap { ptr, capacity } => deallocate(ptr, capacity),
-            }
-        }
-    }
-}
-
 /// A `Vec`-like container that can store a small number of elements inline.
 ///
 /// `SmallVec` acts like a vector, but can store a limited amount of data inline within the
 /// `Smallvec` struct rather than in a separate allocation.  If the data exceeds this limit, the
 /// `SmallVec` will "spill" its data onto the heap, allocating a new buffer to hold it.
 ///
 /// The amount of data that a `SmallVec` can store inline depends on its backing store. The backing
 /// store can be any type that implements the `Array` trait; usually it is a small fixed-sized
@@ -247,28 +380,31 @@ impl<A: Array> Drop for SmallVecData<A> {
 /// assert!(!v.spilled());
 ///
 /// // Pushing another element will force the buffer to spill:
 /// v.push(4);
 /// assert_eq!(v.len(), 5);
 /// assert!(v.spilled());
 /// ```
 pub struct SmallVec<A: Array> {
-    len: usize,
+    // The capacity field is used to determine which of the storage variants is active:
+    // If capacity <= A::size() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use).
+    // If capacity > A::size() then the heap variant is used and capacity holds the size of the memory allocation.
+    capacity: usize,
     data: SmallVecData<A>,
 }
 
 impl<A: Array> SmallVec<A> {
     /// Construct an empty vector
     #[inline]
     pub fn new() -> SmallVec<A> {
         unsafe {
             SmallVec {
-                len: 0,
-                data: Inline { array: mem::uninitialized() },
+                capacity: 0,
+                data: SmallVecData::from_inline(mem::uninitialized()),
             }
         }
     }
 
     /// Construct an empty vector with enough capacity pre-allocated to store at least `n`
     /// elements.
     ///
     /// Will create a heap allocation only if `n` is larger than the inline capacity.
@@ -283,37 +419,49 @@ impl<A: Array> SmallVec<A> {
     /// ```
     #[inline]
     pub fn with_capacity(n: usize) -> Self {
         let mut v = SmallVec::new();
         v.reserve_exact(n);
         v
     }
 
-    /// Construct a new `SmallVec` from a `Vec<A::Item>` without copying
-    /// elements.
+    /// Construct a new `SmallVec` from a `Vec<A::Item>`.
+    ///
+    /// Elements will be copied to the inline buffer if vec.capacity() <= A::size().
     ///
     /// ```rust
     /// use smallvec::SmallVec;
     ///
     /// let vec = vec![1, 2, 3, 4, 5];
     /// let small_vec: SmallVec<[_; 3]> = SmallVec::from_vec(vec);
     ///
     /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
     /// ```
     #[inline]
     pub fn from_vec(mut vec: Vec<A::Item>) -> SmallVec<A> {
-        let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
-        mem::forget(vec);
+        if vec.capacity() <= A::size() {
+            unsafe {
+                let mut data = SmallVecData::<A>::from_inline(mem::uninitialized());
+                let len = vec.len();
+                vec.set_len(0);
+                ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().ptr_mut(), len);
+
+                SmallVec {
+                    capacity: len,
+                    data,
+                }
+            }
+        } else {
+            let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len());
+            mem::forget(vec);
 
-        SmallVec {
-            len: len,
-            data: SmallVecData::Heap {
-                ptr: ptr,
-                capacity: cap
+            SmallVec {
+                capacity: cap,
+                data: SmallVecData::from_heap(ptr, len),
             }
         }
     }
 
     /// Constructs a new `SmallVec` on the stack from an `A` without
     /// copying elements.
     ///
     /// ```rust
@@ -322,209 +470,279 @@ impl<A: Array> SmallVec<A> {
     /// let buf = [1, 2, 3, 4, 5];
     /// let small_vec: SmallVec<_> = SmallVec::from_buf(buf);
     ///
     /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
     /// ```
     #[inline]
     pub fn from_buf(buf: A) -> SmallVec<A> {
         SmallVec {
-            len: A::size(),
-            data: SmallVecData::Inline { array: buf },
+            capacity: A::size(),
+            data: SmallVecData::from_inline(buf),
+        }
+    }
+
+    /// Constructs a new `SmallVec` on the stack from an `A` without
+    /// copying elements. Also sets the length, which must be less or
+    /// equal to the size of `buf`.
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
+    /// let small_vec: SmallVec<_> = SmallVec::from_buf_and_len(buf, 5);
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> {
+        assert!(len <= A::size());
+        unsafe { SmallVec::from_buf_and_len_unchecked(buf, len) }
+    }
+
+    /// Constructs a new `SmallVec` on the stack from an `A` without
+    /// copying elements. Also sets the length. The user is responsible
+    /// for ensuring that `len <= A::size()`.
+    ///
+    /// ```rust
+    /// use smallvec::SmallVec;
+    ///
+    /// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
+    /// let small_vec: SmallVec<_> = unsafe {
+    ///     SmallVec::from_buf_and_len_unchecked(buf, 5)
+    /// };
+    ///
+    /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
+    /// ```
+    #[inline]
+    pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> SmallVec<A> {
+        SmallVec {
+            capacity: len,
+            data: SmallVecData::from_inline(buf),
         }
     }
 
+
     /// Sets the length of a vector.
     ///
     /// This will explicitly set the size of the vector, without actually
     /// modifying its buffers, so it is up to the caller to ensure that the
     /// vector is actually the specified size.
     pub unsafe fn set_len(&mut self, new_len: usize) {
-        self.len = new_len
+        let (_, len_ptr, _) = self.triple_mut();
+        *len_ptr = new_len;
     }
 
     /// The maximum number of elements this vector can hold inline
     #[inline]
     pub fn inline_size(&self) -> usize {
         A::size()
     }
 
     /// The number of elements stored in the vector
     #[inline]
     pub fn len(&self) -> usize {
-        self.len
+        self.triple().1
     }
 
     /// Returns `true` if the vector is empty
     #[inline]
     pub fn is_empty(&self) -> bool {
-        self.len == 0
+        self.len() == 0
     }
 
     /// The number of items the vector can hold without reallocating
     #[inline]
     pub fn capacity(&self) -> usize {
-        match self.data {
-            Inline { .. } => A::size(),
-            Heap { capacity, .. } => capacity,
+        self.triple().2
+    }
+
+    /// Returns a tuple with (data ptr, len, capacity)
+    /// Useful to get all SmallVec properties with a single check of the current storage variant.
+    #[inline]
+    fn triple(&self) -> (*const A::Item, usize, usize) {
+        unsafe {
+            if self.spilled() {
+                let (ptr, len) = self.data.heap();
+                (ptr, len, self.capacity)
+            } else {
+                (self.data.inline().ptr(), self.capacity, A::size())
+            }
+        }
+    }
+
+    /// Returns a tuple with (data ptr, len ptr, capacity)
+    #[inline]
+    fn triple_mut(&mut self) -> (*mut A::Item, &mut usize, usize) {
+        unsafe {
+            if self.spilled() {
+                let &mut (ptr, ref mut len_ptr) = self.data.heap_mut();
+                (ptr, len_ptr, self.capacity)
+            } else {
+                (self.data.inline_mut().ptr_mut(), &mut self.capacity, A::size())
+            }
         }
     }
 
     /// Returns `true` if the data has spilled into a separate heap-allocated buffer.
     #[inline]
     pub fn spilled(&self) -> bool {
-        match self.data {
-            Inline { .. } => false,
-            Heap { .. } => true,
-        }
+        self.capacity > A::size()
     }
 
     /// Empty the vector and return an iterator over its former contents.
     pub fn drain(&mut self) -> Drain<A::Item> {
         unsafe {
+            let ptr = self.as_mut_ptr();
+
             let current_len = self.len();
             self.set_len(0);
 
-            let ptr = self.data.ptr_mut();
-
             let slice = slice::from_raw_parts_mut(ptr, current_len);
 
             Drain {
                 iter: slice.iter_mut(),
             }
         }
     }
 
     /// Append an item to the vector.
     #[inline]
     pub fn push(&mut self, value: A::Item) {
-        let cap = self.capacity();
-        if self.len == cap {
-            self.grow(cmp::max(cap * 2, 1))
-        }
         unsafe {
-            let end = self.as_mut_ptr().offset(self.len as isize);
-            ptr::write(end, value);
-            let len = self.len;
-            self.set_len(len + 1)
+            let (_, &mut len, cap) = self.triple_mut();
+            if len == cap {
+                self.reserve(1);
+            }
+            let (ptr, len_ptr, _) = self.triple_mut();
+            *len_ptr = len + 1;
+            ptr::write(ptr.offset(len as isize), value);
         }
     }
 
     /// Remove an item from the end of the vector and return it, or None if empty.
     #[inline]
     pub fn pop(&mut self) -> Option<A::Item> {
-        if self.len == 0 {
-            return None
-        }
-        let last_index = self.len - 1;
-        if (last_index as isize) < 0 {
-            panic!("overflow")
-        }
         unsafe {
-            let end_ptr = self.as_ptr().offset(last_index as isize);
-            let value = ptr::read(end_ptr);
-            self.set_len(last_index);
-            Some(value)
+            let (ptr, len_ptr, _) = self.triple_mut();
+            if *len_ptr == 0 {
+                return None;
+            }
+            let last_index = *len_ptr - 1;
+            *len_ptr = last_index;
+            Some(ptr::read(ptr.offset(last_index as isize)))
         }
     }
 
-    /// Re-allocate to set the capacity to `new_cap`.
+    /// Re-allocate to set the capacity to `max(new_cap, inline_size())`.
     ///
     /// Panics if `new_cap` is less than the vector's length.
     pub fn grow(&mut self, new_cap: usize) {
-        assert!(new_cap >= self.len);
-        let mut vec: Vec<A::Item> = Vec::with_capacity(new_cap);
-        let new_alloc = vec.as_mut_ptr();
         unsafe {
-            mem::forget(vec);
-            ptr::copy_nonoverlapping(self.as_ptr(), new_alloc, self.len);
-
-            match self.data {
-                Inline { .. } => {}
-                Heap { ptr, capacity } => deallocate(ptr, capacity),
+            let (ptr, &mut len, cap) = self.triple_mut();
+            let unspilled = !self.spilled();
+            assert!(new_cap >= len);
+            if new_cap <= self.inline_size() {
+                if unspilled {
+                    return;
+                }
+                self.data = SmallVecData::from_inline(mem::uninitialized());
+                ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len);
+            } else if new_cap != cap {
+                let mut vec = Vec::with_capacity(new_cap);
+                let new_alloc = vec.as_mut_ptr();
+                mem::forget(vec);
+                ptr::copy_nonoverlapping(ptr, new_alloc, len);
+                self.data = SmallVecData::from_heap(new_alloc, len);
+                self.capacity = new_cap;
+                if unspilled {
+                    return;
+                }
             }
-            ptr::write(&mut self.data, Heap {
-                ptr: new_alloc,
-                capacity: new_cap,
-            });
+            deallocate(ptr, cap);
         }
     }
 
     /// Reserve capacity for `additional` more elements to be inserted.
     ///
     /// May reserve more space to avoid frequent reallocations.
     ///
     /// If the new capacity would overflow `usize` then it will be set to `usize::max_value()`
     /// instead. (This means that inserting `additional` new elements is not guaranteed to be
     /// possible after calling this function.)
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
-        let len = self.len();
-        if self.capacity() - len < additional {
-            match len.checked_add(additional).and_then(usize::checked_next_power_of_two) {
-                Some(cap) => self.grow(cap),
-                None => self.grow(usize::max_value()),
-            }
+        // prefer triple_mut() even if triple() would work
+        // so that the optimizer removes duplicated calls to it
+        // from callers like insert()
+        let (_, &mut len, cap) = self.triple_mut();
+        if cap - len < additional {
+            let new_cap = len.checked_add(additional).
+                and_then(usize::checked_next_power_of_two).
+                unwrap_or(usize::max_value());
+            self.grow(new_cap);
         }
     }
 
     /// Reserve the minumum capacity for `additional` more elements to be inserted.
     ///
     /// Panics if the new capacity overflows `usize`.
     pub fn reserve_exact(&mut self, additional: usize) {
-        let len = self.len();
-        if self.capacity() - len < additional {
+        let (_, &mut len, cap) = self.triple_mut();
+        if cap - len < additional {
             match len.checked_add(additional) {
                 Some(cap) => self.grow(cap),
                 None => panic!("reserve_exact overflow"),
             }
         }
     }
 
     /// Shrink the capacity of the vector as much as possible.
     ///
     /// When possible, this will move data from an external heap buffer to the vector's inline
     /// storage.
     pub fn shrink_to_fit(&mut self) {
-        let len = self.len;
+        if !self.spilled() {
+            return;
+        }
+        let len = self.len();
         if self.inline_size() >= len {
             unsafe {
-                let (ptr, capacity) = match self.data {
-                    Inline { .. } => return,
-                    Heap { ptr, capacity } => (ptr, capacity),
-                };
-                ptr::write(&mut self.data, Inline { array: mem::uninitialized() });
-                ptr::copy_nonoverlapping(ptr, self.as_mut_ptr(), len);
-                deallocate(ptr, capacity);
+                let (ptr, len) = self.data.heap();
+                self.data = SmallVecData::from_inline(mem::uninitialized());
+                ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len);
+                deallocate(ptr, self.capacity);
+                self.capacity = len;
             }
         } else if self.capacity() > len {
             self.grow(len);
         }
     }
 
     /// Shorten the vector, keeping the first `len` elements and dropping the rest.
     ///
     /// If `len` is greater than or equal to the vector's current length, this has no
     /// effect.
     ///
     /// This does not re-allocate.  If you want the vector's capacity to shrink, call
     /// `shrink_to_fit` after truncating.
     pub fn truncate(&mut self, len: usize) {
-        let end_ptr = self.as_ptr();
-        while len < self.len {
-            unsafe {
-                let last_index = self.len - 1;
-                self.set_len(last_index);
-                ptr::read(end_ptr.offset(last_index as isize));
+        unsafe {
+            let (ptr, len_ptr, _) = self.triple_mut();
+            while len < *len_ptr {
+                let last_index = *len_ptr - 1;
+                *len_ptr = last_index;
+                ptr::drop_in_place(ptr.offset(last_index as isize));
             }
         }
     }
 
     /// Extracts a slice containing the entire vector.
     ///
-    /// Equivalent to `&mut s[..]`.
+    /// Equivalent to `&s[..]`.
     pub fn as_slice(&self) -> &[A::Item] {
         self
     }
 
     /// Extracts a mutable slice of the entire vector.
     ///
     /// Equivalent to `&mut s[..]`.
     pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
@@ -533,137 +751,168 @@ impl<A: Array> SmallVec<A> {
 
     /// Remove the element at position `index`, replacing it with the last element.
     ///
     /// This does not preserve ordering, but is O(1).
     ///
     /// Panics if `index` is out of bounds.
     #[inline]
     pub fn swap_remove(&mut self, index: usize) -> A::Item {
-        let len = self.len;
+        let len = self.len();
         self.swap(len - 1, index);
-        self.pop().unwrap()
+        unsafe { self.pop().unchecked_unwrap() }
     }
 
     /// Remove all elements from the vector.
     #[inline]
     pub fn clear(&mut self) {
         self.truncate(0);
     }
 
     /// Remove and return the element at position `index`, shifting all elements after it to the
     /// left.
     ///
     /// Panics if `index` is out of bounds.
     pub fn remove(&mut self, index: usize) -> A::Item {
-        let len = self.len();
-
-        assert!(index < len);
-
         unsafe {
-            let ptr = self.as_mut_ptr().offset(index as isize);
+            let (mut ptr, len_ptr, _) = self.triple_mut();
+            let len = *len_ptr;
+            assert!(index < len);
+            *len_ptr = len - 1;
+            ptr = ptr.offset(index as isize);
             let item = ptr::read(ptr);
             ptr::copy(ptr.offset(1), ptr, len - index - 1);
-            self.set_len(len - 1);
             item
         }
     }
 
     /// Insert an element at position `index`, shifting all elements after it to the right.
     ///
     /// Panics if `index` is out of bounds.
     pub fn insert(&mut self, index: usize, element: A::Item) {
         self.reserve(1);
 
-        let len = self.len;
-        assert!(index <= len);
-
         unsafe {
-            let ptr = self.as_mut_ptr().offset(index as isize);
+            let (mut ptr, len_ptr, _) = self.triple_mut();
+            let len = *len_ptr;
+            assert!(index <= len);
+            *len_ptr = len + 1;
+            ptr = ptr.offset(index as isize);
             ptr::copy(ptr, ptr.offset(1), len - index);
             ptr::write(ptr, element);
-            self.set_len(len + 1);
         }
     }
 
     /// Insert multiple elements at position `index`, shifting all following elements toward the
     /// back.
     pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
         let iter = iterable.into_iter();
+        if index == self.len() {
+            return self.extend(iter);
+        }
+
         let (lower_size_bound, _) = iter.size_hint();
         assert!(lower_size_bound <= std::isize::MAX as usize);  // Ensure offset is indexable
         assert!(index + lower_size_bound >= index);  // Protect against overflow
         self.reserve(lower_size_bound);
 
         unsafe {
-            let old_len = self.len;
+            let old_len = self.len();
             assert!(index <= old_len);
-            let ptr = self.as_mut_ptr().offset(index as isize);
+            let mut ptr = self.as_mut_ptr().offset(index as isize);
+
+            // Move the trailing elements.
             ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index);
-            for (off, element) in iter.enumerate() {
-                if off < lower_size_bound {
-                    ptr::write(ptr.offset(off as isize), element);
-                    self.len = self.len + 1;
-                } else {
-                    // Iterator provided more elements than the hint.
-                    assert!(index + off >= index);  // Protect against overflow.
-                    self.insert(index + off, element);
+
+            // In case the iterator panics, don't double-drop the items we just copied above.
+            self.set_len(index);
+
+            let mut num_added = 0;
+            for element in iter {
+                let mut cur = ptr.offset(num_added as isize);
+                if num_added >= lower_size_bound {
+                    // Iterator provided more elements than the hint.  Move trailing items again.
+                    self.reserve(1);
+                    ptr = self.as_mut_ptr().offset(index as isize);
+                    cur = ptr.offset(num_added as isize);
+                    ptr::copy(cur, cur.offset(1), old_len - index);
                 }
+                ptr::write(cur, element);
+                num_added += 1;
             }
-            let num_added = self.len - old_len;
             if num_added < lower_size_bound {
                 // Iterator provided fewer elements than the hint
                 ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index);
             }
+
+            self.set_len(old_len + num_added);
         }
     }
 
     /// Convert a SmallVec to a Vec, without reallocating if the SmallVec has already spilled onto
     /// the heap.
     pub fn into_vec(self) -> Vec<A::Item> {
-        match self.data {
-            Inline { .. } => self.into_iter().collect(),
-            Heap { ptr, capacity } => unsafe {
-                let v = Vec::from_raw_parts(ptr, self.len, capacity);
+        if self.spilled() {
+            unsafe {
+                let (ptr, len) = self.data.heap();
+                let v = Vec::from_raw_parts(ptr, len, self.capacity);
                 mem::forget(self);
                 v
             }
+        } else {
+            self.into_iter().collect()
+        }
+    }
+
+    /// Convert the SmallVec into an `A` if possible. Otherwise return `Err(Self)`.
+    ///
+    /// This method returns `Err(Self)` if the SmallVec is too short (and the `A` contains uninitialized elements),
+    /// or if the SmallVec is too long (and all the elements were spilled to the heap).
+    pub fn into_inner(self) -> Result<A, Self> {
+        if self.spilled() || self.len() != A::size() {
+            Err(self)
+        } else {
+            unsafe {
+                let data = ptr::read(&self.data);
+                mem::forget(self);
+                Ok(data.into_inline())
+            }
         }
     }
 
     /// Retains only the elements specified by the predicate.
     ///
     /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
     /// This method operates in place and preserves the order of the retained
     /// elements.
     pub fn retain<F: FnMut(&mut A::Item) -> bool>(&mut self, mut f: F) {
         let mut del = 0;
-        let len = self.len;
+        let len = self.len();
         for i in 0..len {
             if !f(&mut self[i]) {
                 del += 1;
             } else if del > 0 {
                 self.swap(i - del, i);
             }
         }
         self.truncate(len - del);
     }
 
     /// Removes consecutive duplicate elements.
     pub fn dedup(&mut self) where A::Item: PartialEq<A::Item> {
         self.dedup_by(|a, b| a == b);
     }
 
     /// Removes consecutive duplicate elements using the given equality relation.
-    pub fn dedup_by<F>(&mut self, mut same_bucket: F) 
+    pub fn dedup_by<F>(&mut self, mut same_bucket: F)
         where F: FnMut(&mut A::Item, &mut A::Item) -> bool
     {
         // See the implementation of Vec::dedup_by in the
         // standard library for an explanation of this algorithm.
-        let len = self.len;
+        let len = self.len();
         if len <= 1 {
             return;
         }
 
         let ptr = self.as_mut_ptr();
         let mut w: usize = 1;
 
         unsafe {
@@ -679,42 +928,58 @@ impl<A: Array> SmallVec<A> {
                 }
             }
         }
 
         self.truncate(w);
     }
 
     /// Removes consecutive elements that map to the same key.
-    pub fn dedup_by_key<F, K>(&mut self, mut key: F) 
-        where F: FnMut(&mut A::Item) -> K, 
-              K: PartialEq<K> 
+    pub fn dedup_by_key<F, K>(&mut self, mut key: F)
+        where F: FnMut(&mut A::Item) -> K,
+              K: PartialEq<K>
     {
         self.dedup_by(|a, b| key(a) == key(b));
     }
 }
 
 impl<A: Array> SmallVec<A> where A::Item: Copy {
     /// Copy the elements from a slice into a new `SmallVec`.
     ///
     /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`.
     pub fn from_slice(slice: &[A::Item]) -> Self {
-        let mut vec = Self::new();
-        vec.extend_from_slice(slice);
-        vec
+        let len = slice.len();
+        if len <= A::size() {
+            SmallVec {
+                capacity: len,
+                data: SmallVecData::from_inline(unsafe {
+                    let mut data: A = mem::uninitialized();
+                    ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), len);
+                    data
+                })
+            }
+        } else {
+            let mut b = slice.to_vec();
+            let ptr = b.as_mut_ptr();
+            mem::forget(b);
+            SmallVec {
+                capacity: len,
+                data: SmallVecData::from_heap(ptr, len),
+            }
+        }
     }
 
     /// Copy elements from a slice into the vector at position `index`, shifting any following
     /// elements toward the back.
     ///
     /// For slices of `Copy` types, this is more efficient than `insert`.
     pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
         self.reserve(slice.len());
 
-        let len = self.len;
+        let len = self.len();
         assert!(index <= len);
 
         unsafe {
             let slice_ptr = slice.as_ptr();
             let ptr = self.as_mut_ptr().offset(index as isize);
             ptr::copy(ptr, ptr.offset(slice.len() as isize), len - index);
             ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len());
             self.set_len(len + slice.len());
@@ -726,36 +991,76 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
     /// For slices of `Copy` types, this is more efficient than `extend`.
     #[inline]
     pub fn extend_from_slice(&mut self, slice: &[A::Item]) {
         let len = self.len();
         self.insert_from_slice(len, slice);
     }
 }
 
+impl<A: Array> SmallVec<A> where A::Item: Clone {
+    /// Resizes the vector so that its length is equal to `len`.
+    ///
+    /// If `len` is less than the current length, the vector simply truncated.
+    ///
+    /// If `len` is greater than the current length, `value` is appended to the
+    /// vector until its length equals `len`.
+    pub fn resize(&mut self, len: usize, value: A::Item) {
+        let old_len = self.len();
+
+        if len > old_len {
+            self.extend(repeat(value).take(len - old_len));
+        } else {
+            self.truncate(len);
+        }
+    }
+
+    /// Creates a `SmallVec` with `n` copies of `elem`.
+    /// ```
+    /// use smallvec::SmallVec;
+    ///
+    /// let v = SmallVec::<[char; 128]>::from_elem('d', 2);
+    /// assert_eq!(v, SmallVec::from_buf(['d', 'd']));
+    /// ```
+    pub fn from_elem(elem: A::Item, n: usize) -> Self {
+        if n > A::size() {
+            vec![elem; n].into()
+        } else {
+            let mut v = SmallVec::<A>::new();
+            unsafe {
+                let (ptr, len_ptr, _) = v.triple_mut();
+                let mut local_len = SetLenOnDrop::new(len_ptr);
+
+                for i in 0..n as isize {
+                    ::std::ptr::write(ptr.offset(i), elem.clone());
+                    local_len.increment_len(1);
+                }
+            }
+            v
+        }
+    }
+}
+
 impl<A: Array> ops::Deref for SmallVec<A> {
     type Target = [A::Item];
     #[inline]
     fn deref(&self) -> &[A::Item] {
-        let ptr: *const _ = match self.data {
-            Inline { ref array } => array.ptr(),
-            Heap { ptr, .. } => ptr,
-        };
         unsafe {
-            slice::from_raw_parts(ptr, self.len)
+            let (ptr, len, _) = self.triple();
+            slice::from_raw_parts(ptr, len)
         }
     }
 }
 
 impl<A: Array> ops::DerefMut for SmallVec<A> {
     #[inline]
     fn deref_mut(&mut self) -> &mut [A::Item] {
-        let ptr = self.data.ptr_mut();
         unsafe {
-            slice::from_raw_parts_mut(ptr, self.len)
+            let (ptr, &mut len, _) = self.triple_mut();
+            slice::from_raw_parts_mut(ptr, len)
         }
     }
 }
 
 impl<A: Array> AsRef<[A::Item]> for SmallVec<A> {
     #[inline]
     fn as_ref(&self) -> &[A::Item] {
         self
@@ -916,52 +1221,62 @@ impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
         let mut v = SmallVec::new();
         v.extend(iterable);
         v
     }
 }
 
 impl<A: Array> Extend<A::Item> for SmallVec<A> {
     fn extend<I: IntoIterator<Item=A::Item>>(&mut self, iterable: I) {
-        let iter = iterable.into_iter();
+        let mut iter = iterable.into_iter();
         let (lower_size_bound, _) = iter.size_hint();
+        self.reserve(lower_size_bound);
 
-        let target_len = self.len + lower_size_bound;
-
-        if target_len > self.capacity() {
-           self.grow(target_len);
+        unsafe {
+            let len = self.len();
+            let ptr = self.as_mut_ptr().offset(len as isize);
+            let mut count = 0;
+            while count < lower_size_bound {
+                if let Some(out) = iter.next() {
+                    ptr::write(ptr.offset(count as isize), out);
+                    count += 1;
+                } else {
+                    break;
+                }
+            }
+            self.set_len(len + count);
         }
 
         for elem in iter {
             self.push(elem);
         }
     }
 }
 
 impl<A: Array> fmt::Debug for SmallVec<A> where A::Item: fmt::Debug {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{:?}", &**self)
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
 impl<A: Array> Default for SmallVec<A> {
     #[inline]
     fn default() -> SmallVec<A> {
         SmallVec::new()
     }
 }
 
 impl<A: Array> Drop for SmallVec<A> {
     fn drop(&mut self) {
-        // Note on panic safety: dropping an element may panic,
-        // but the inner SmallVecData destructor will still run
         unsafe {
-            let ptr = self.as_ptr();
-            for i in 0 .. self.len {
-                ptr::read(ptr.offset(i as isize));
+            if self.spilled() {
+                let (ptr, len) = self.data.heap();
+                Vec::from_raw_parts(ptr, len, self.capacity);
+            } else {
+                ptr::drop_in_place(&mut self[..]);
             }
         }
     }
 }
 
 impl<A: Array> Clone for SmallVec<A> where A::Item: Clone {
     fn clone(&self) -> SmallVec<A> {
         let mut new_vector = SmallVec::with_capacity(self.len());
@@ -1005,17 +1320,17 @@ impl<A: Array> Hash for SmallVec<A> where A::Item: Hash {
 unsafe impl<A: Array> Send for SmallVec<A> where A::Item: Send {}
 
 /// An iterator that consumes a `SmallVec` and yields its items by value.
 ///
 /// Returned from [`SmallVec::into_iter`][1].
 ///
 /// [1]: struct.SmallVec.html#method.into_iter
 pub struct IntoIter<A: Array> {
-    data: SmallVecData<A>,
+    data: SmallVec<A>,
     current: usize,
     end: usize,
 }
 
 impl<A: Array> Drop for IntoIter<A> {
     fn drop(&mut self) {
         for _ in self { }
     }
@@ -1028,17 +1343,17 @@ impl<A: Array> Iterator for IntoIter<A> {
     fn next(&mut self) -> Option<A::Item> {
         if self.current == self.end {
             None
         }
         else {
             unsafe {
                 let current = self.current as isize;
                 self.current += 1;
-                Some(ptr::read(self.data.ptr_mut().offset(current)))
+                Some(ptr::read(self.data.as_ptr().offset(current)))
             }
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let size = self.end - self.current;
         (size, Some(size))
@@ -1049,35 +1364,34 @@ impl<A: Array> DoubleEndedIterator for IntoIter<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A::Item> {
         if self.current == self.end {
             None
         }
         else {
             unsafe {
                 self.end -= 1;
-                Some(ptr::read(self.data.ptr_mut().offset(self.end as isize)))
+                Some(ptr::read(self.data.as_ptr().offset(self.end as isize)))
             }
         }
     }
 }
 
 impl<A: Array> ExactSizeIterator for IntoIter<A> { }
 
 impl<A: Array> IntoIterator for SmallVec<A> {
     type IntoIter = IntoIter<A>;
     type Item = A::Item;
     fn into_iter(mut self) -> Self::IntoIter {
-        let len = self.len();
         unsafe {
-            // Only grab the `data` field, the `IntoIter` type handles dropping of the elements
-            let data = ptr::read(&mut self.data);
-            mem::forget(self);
+            // Set SmallVec len to zero as `IntoIter` drop handles dropping of the elements
+            let len = self.len();
+            self.set_len(0);
             IntoIter {
-                data: data,
+                data: self,
                 current: 0,
                 end: len,
             }
         }
     }
 }
 
 impl<'a, A: Array> IntoIterator for &'a SmallVec<A> {
@@ -1103,30 +1417,57 @@ pub unsafe trait Array {
     /// Returns the number of items the array can hold.
     fn size() -> usize;
     /// Returns a pointer to the first element of the array.
     fn ptr(&self) -> *const Self::Item;
     /// Returns a mutable pointer to the first element of the array.
     fn ptr_mut(&mut self) -> *mut Self::Item;
 }
 
+/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
+///
+/// Copied from https://github.com/rust-lang/rust/pull/36355
+struct SetLenOnDrop<'a> {
+    len: &'a mut usize,
+    local_len: usize,
+}
+
+impl<'a> SetLenOnDrop<'a> {
+    #[inline]
+    fn new(len: &'a mut usize) -> Self {
+        SetLenOnDrop { local_len: *len, len: len }
+    }
+
+    #[inline]
+    fn increment_len(&mut self, increment: usize) {
+        self.local_len += increment;
+    }
+}
+
+impl<'a> Drop for SetLenOnDrop<'a> {
+    #[inline]
+    fn drop(&mut self) {
+        *self.len = self.local_len;
+    }
+}
+
 macro_rules! impl_array(
     ($($size:expr),+) => {
         $(
             unsafe impl<T> Array for [T; $size] {
                 type Item = T;
                 fn size() -> usize { $size }
-                fn ptr(&self) -> *const T { &self[0] }
-                fn ptr_mut(&mut self) -> *mut T { &mut self[0] }
+                fn ptr(&self) -> *const T { self.as_ptr() }
+                fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() }
             }
         )+
     }
 );
 
-impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
+impl_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
             0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
             0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
 
 #[cfg(test)]
 mod tests {
     use SmallVec;
 
     use std::iter::FromIterator;
@@ -1139,16 +1480,25 @@ mod tests {
     use std::rc::Rc;
     #[cfg(not(feature = "std"))]
     use alloc::rc::Rc;
     #[cfg(not(feature = "std"))]
     use alloc::boxed::Box;
     #[cfg(not(feature = "std"))]
     use alloc::vec::Vec;
 
+    #[test]
+    pub fn test_zero() {
+        let mut v = SmallVec::<[_; 0]>::new();
+        assert!(!v.spilled());
+        v.push(0usize);
+        assert!(v.spilled());
+        assert_eq!(&*v, &[0]);
+    }
+
     // We heap allocate all these strings so that double frees will show up under valgrind.
 
     #[test]
     pub fn test_inline() {
         let mut v = SmallVec::<[_; 16]>::new();
         v.push("hello".to_owned());
         v.push("there".to_owned());
         assert_eq!(&*v, &[
@@ -1402,16 +1752,48 @@ mod tests {
         for x in 0..4 {
             v.push(x);
         }
         assert_eq!(v.len(), 4);
         v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1});
         assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
     }
 
+    #[cfg(feature = "std")]
+    #[test]
+    // https://github.com/servo/rust-smallvec/issues/96
+    fn test_insert_many_panic() {
+        struct PanicOnDoubleDrop {
+            dropped: Box<bool>
+        }
+
+        impl Drop for PanicOnDoubleDrop {
+            fn drop(&mut self) {
+                assert!(!*self.dropped, "already dropped");
+                *self.dropped = true;
+            }
+        }
+
+        struct BadIter;
+        impl Iterator for BadIter {
+            type Item = PanicOnDoubleDrop;
+            fn size_hint(&self) -> (usize, Option<usize>) { (1, None) }
+            fn next(&mut self) -> Option<Self::Item> { panic!() }
+        }
+
+        let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = vec![
+            PanicOnDoubleDrop { dropped: Box::new(false) },
+            PanicOnDoubleDrop { dropped: Box::new(false) },
+        ].into();
+        let result = ::std::panic::catch_unwind(move || {
+            vec.insert_many(0, BadIter);
+        });
+        assert!(result.is_err());
+    }
+
     #[test]
     #[should_panic]
     fn test_invalid_grow() {
         let mut v: SmallVec<[u8; 8]> = SmallVec::new();
         v.extend(0..8);
         v.grow(5);
     }
 
@@ -1641,16 +2023,28 @@ mod tests {
     fn test_into_vec() {
         let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
         assert_eq!(vec.into_vec(), vec![0, 1]);
 
         let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
         assert_eq!(vec.into_vec(), vec![0, 1, 2]);
     }
 
+    #[test]
+    fn test_into_inner() {
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
+        assert_eq!(vec.into_inner(), Ok([0, 1]));
+
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..1);
+        assert_eq!(vec.clone().into_inner(), Err(vec));
+
+        let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
+        assert_eq!(vec.clone().into_inner(), Err(vec));
+    }
+
     #[test]
     fn test_from_vec() {
         let vec = vec![];
         let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
         assert_eq!(&*small_vec, &[]);
         drop(small_vec);
 
         let vec = vec![];
@@ -1728,16 +2122,27 @@ mod tests {
         all_ones.dedup();
         assert_eq!(all_ones.len(), 1);
 
         let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]);
         no_dupes.dedup();
         assert_eq!(no_dupes.len(), 5);
     }
 
+    #[test]
+    fn test_resize() {
+        let mut v: SmallVec<[i32; 8]> = SmallVec::new();
+        v.push(1);
+        v.resize(5, 0);
+        assert_eq!(v[..], [1, 0, 0, 0, 0][..]);
+
+        v.resize(2, -1);
+        assert_eq!(v[..], [1, 0][..]);
+    }
+
     #[cfg(feature = "std")]
     #[test]
     fn test_write() {
         use io::Write;
 
         let data = [1, 2, 3, 4, 5];
 
         let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new();
@@ -1751,24 +2156,24 @@ mod tests {
     }
 
     #[cfg(feature = "serde")]
     extern crate bincode;
 
     #[cfg(feature = "serde")]
     #[test]
     fn test_serde() {
-        use self::bincode::{serialize, deserialize, Bounded};
+        use self::bincode::{config, deserialize};
         let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new();
         small_vec.push(1);
-        let encoded = serialize(&small_vec, Bounded(100)).unwrap();
+        let encoded = config().limit(100).serialize(&small_vec).unwrap();
         let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
         assert_eq!(small_vec, decoded);
         small_vec.push(2);
         // Spill the vec
         small_vec.push(3);
         small_vec.push(4);
         // Check again after spilling.
-        let encoded = serialize(&small_vec, Bounded(100)).unwrap();
+        let encoded = config().limit(100).serialize(&small_vec).unwrap();
         let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
         assert_eq!(small_vec, decoded);
     }
 }
diff --git a/third_party/rust/thread_local/.cargo-checksum.json b/third_party/rust/thread_local/.cargo-checksum.json
index 13a1a41d7abc..7cd990a33122 100644
--- a/third_party/rust/thread_local/.cargo-checksum.json
+++ b/third_party/rust/thread_local/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"c01fcdfc31a1092bfdbdd22a0d88773bdc280550b806ab2ebe23ac4b32d4a5c2","Cargo.toml":"cc42ea81b9749fdd354f433e91f845f656841e904b986ad08c30bf419a26c6d7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"00a29378d5aeb66b7a48b77bee0d463c8b408b8a9cb0abb7674edb10d142aca0","benches/thread_local.rs":"cc8bde81ed6206525feff209598caf1e01e89a83bf21d8b7ccc0dadc8b89d815","src/lib.rs":"e5902751bf1768fb756b88146da66a128920d3f1b166b797fd0a5e1528f2e687","src/thread_id.rs":"0962c130061939557aa272115e4420fbbc63b6bd306783a456a8ffcbf304a447"},"package":"1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"}
\ No newline at end of file
+{"files":{".travis.yml":"cc8fad15d03ad873a99eeceb74a830069c86f28ac53aa43772d44038dc8a61ff","Cargo.toml":"b4f81d513b95fff17f96d5da83768187870df83969fd5e49b030aaf6158ccd58","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"00a29378d5aeb66b7a48b77bee0d463c8b408b8a9cb0abb7674edb10d142aca0","benches/thread_local.rs":"cc8bde81ed6206525feff209598caf1e01e89a83bf21d8b7ccc0dadc8b89d815","src/lib.rs":"d7f875b0c4a8e2229f3510c88c0425342f1628fdf2f2b113c80789b6b90378b7","src/thread_id.rs":"0962c130061939557aa272115e4420fbbc63b6bd306783a456a8ffcbf304a447","src/unreachable.rs":"830d44988f86f4fc6c3c4dd7e9e4e7d0f2cb9c5b024c360b5f7ceae365983367"},"package":"c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"}
\ No newline at end of file
diff --git a/third_party/rust/thread_local/.travis.yml b/third_party/rust/thread_local/.travis.yml
index 9ae5325f2330..1301a4aa17ba 100644
--- a/third_party/rust/thread_local/.travis.yml
+++ b/third_party/rust/thread_local/.travis.yml
@@ -1,16 +1,16 @@
 language: rust
 sudo: false
 
 rust:
 - nightly
 - beta
 - stable
-- 1.9.0
+- 1.21.0
 
 before_script:
 - |
   pip install 'travis-cargo<0.2' --user &&
   export PATH=$HOME/.local/bin:$PATH
 
 script:
 - travis-cargo build
diff --git a/third_party/rust/thread_local/Cargo.toml b/third_party/rust/thread_local/Cargo.toml
index f55e08badbcf..fc7b3c82dd92 100644
--- a/third_party/rust/thread_local/Cargo.toml
+++ b/third_party/rust/thread_local/Cargo.toml
@@ -7,21 +7,20 @@
 #
 # 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 = "thread_local"
-version = "0.3.4"
+version = "0.3.6"
 authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
 description = "Per-object thread-local storage"
 documentation = "https://amanieu.github.io/thread_local-rs/thread_local/index.html"
 readme = "README.md"
 keywords = ["thread_local", "concurrent", "thread"]
 license = "Apache-2.0/MIT"
 repository = "https://github.com/Amanieu/thread_local-rs"
-[dependencies.unreachable]
-version = "1.0"
-
 [dependencies.lazy_static]
-version = "0.2"
+version = "1.0"
+[badges.travis-ci]
+repository = "Amanieu/thread_local-rs"
diff --git a/third_party/rust/thread_local/src/lib.rs b/third_party/rust/thread_local/src/lib.rs
index dde9a15bed1f..2f8e579b5991 100644
--- a/third_party/rust/thread_local/src/lib.rs
+++ b/third_party/rust/thread_local/src/lib.rs
@@ -65,21 +65,21 @@
 //! // sum of all thread-local counter values.
 //! let tls = Arc::try_unwrap(tls).unwrap();
 //! let total = tls.into_iter().fold(0, |x, y| x + y.get());
 //! assert_eq!(total, 5);
 //! ```
 
 #![warn(missing_docs)]
 
-extern crate unreachable;
 #[macro_use]
 extern crate lazy_static;
 
 mod thread_id;
+mod unreachable;
 
 use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 use std::sync::Mutex;
 use std::marker::PhantomData;
 use std::cell::UnsafeCell;
 use std::fmt;
 use std::iter::Chain;
 use std::option::IntoIter as OptionIter;
@@ -153,17 +153,17 @@ impl<T: ?Sized + Send> Clone for TableEntry<T> {
 #[cfg(target_pointer_width = "32")]
 #[inline]
 fn hash(id: usize, bits: usize) -> usize {
     id.wrapping_mul(0x9E3779B9) >> (32 - bits)
 }
 #[cfg(target_pointer_width = "64")]
 #[inline]
 fn hash(id: usize, bits: usize) -> usize {
-    id.wrapping_mul(0x9E3779B97F4A7C15) >> (64 - bits)
+    id.wrapping_mul(0x9E37_79B9_7F4A_7C15) >> (64 - bits)
 }
 
 impl<T: ?Sized + Send> ThreadLocal<T> {
     /// Creates a new empty `ThreadLocal`.
     pub fn new() -> ThreadLocal<T> {
         let entry = TableEntry {
             owner: AtomicUsize::new(0),
             data: UnsafeCell::new(None),
diff --git a/third_party/rust/thread_local/src/unreachable.rs b/third_party/rust/thread_local/src/unreachable.rs
new file mode 100644
index 000000000000..baff76600cac
--- /dev/null
+++ b/third_party/rust/thread_local/src/unreachable.rs
@@ -0,0 +1,74 @@
+// Copyright 2017 Amanieu d'Antras
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! # unreachable
+//! inlined from https://github.com/reem/rust-unreachable/
+//!
+//! An unreachable code optimization hint in stable rust, and some useful
+//! extension traits for `Option` and `Result`.
+//!
+
+/// Hint to the optimizer that any code path which calls this function is
+/// statically unreachable and can be removed.
+///
+/// Calling this function in reachable code invokes undefined behavior. Be
+/// very, very sure this is what you want; often, a simple `panic!` is more
+/// suitable.
+#[inline]
+pub unsafe fn unreachable() -> ! {
+    /// The empty type for cases which can't occur.
+    enum Void { }
+    let x: &Void = ::std::mem::transmute(1usize);
+    match *x {}
+}
+
+/// An extension trait for `Option<T>` providing unchecked unwrapping methods.
+pub trait UncheckedOptionExt<T> {
+    /// Get the value out of this Option without checking for None.
+    unsafe fn unchecked_unwrap(self) -> T;
+
+    /// Assert that this Option is a None to the optimizer.
+    unsafe fn unchecked_unwrap_none(self);
+}
+
+/// An extension trait for `Result<T, E>` providing unchecked unwrapping methods.
+pub trait UncheckedResultExt<T, E> {
+    /// Get the value out of this Result without checking for Err.
+    unsafe fn unchecked_unwrap_ok(self) -> T;
+
+    /// Get the error out of this Result without checking for Ok.
+    unsafe fn unchecked_unwrap_err(self) -> E;
+}
+
+impl<T> UncheckedOptionExt<T> for Option<T> {
+    unsafe fn unchecked_unwrap(self) -> T {
+        match self {
+            Some(x) => x,
+            None => unreachable()
+        }
+    }
+
+    unsafe fn unchecked_unwrap_none(self) {
+        if self.is_some() { unreachable() }
+    }
+}
+
+impl<T, E> UncheckedResultExt<T, E> for Result<T, E> {
+    unsafe fn unchecked_unwrap_ok(self) -> T {
+        match self {
+            Ok(x) => x,
+            Err(_) => unreachable()
+        }
+    }
+
+    unsafe fn unchecked_unwrap_err(self) -> E {
+        match self {
+            Ok(_) => unreachable(),
+            Err(e) => e
+        }
+    }
+}
\ No newline at end of file
diff --git a/third_party/rust/ucd-util/.cargo-checksum.json b/third_party/rust/ucd-util/.cargo-checksum.json
new file mode 100644
index 000000000000..9cbfa1e80e36
--- /dev/null
+++ b/third_party/rust/ucd-util/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"e6e01e3bdb2baed522658098495701ca8020cd0c59a8fdcb63367fe40ac001b0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"147712a0aa07cb69e3635ce7a0e8cee2bc45d35988a7af75d352ee18b4cdf86f","src/hangul.rs":"304c4986a9d9ae2da04a96727294cede38dba412acdb5d70c470ff51627e63ee","src/ideograph.rs":"e14e315a6c800e7962564eeb0c26e1a000f7f90c518aa98b06d7fba3124ec8a7","src/lib.rs":"234fdc5d7d94c4a184fe482ffc28d4f2994905375e4a16a9e011ea7f7df3241c","src/name.rs":"a350733283862ce670d520e15f4d4854fbc3ebcbfeab100e2c364ce250a53c68","src/property.rs":"ff22f15d83bb0d96049d8bd6fef5fdb07d71a612c77cb3fd434f528f01ef953f","src/unicode_tables/jamo_short_name.rs":"65b6319fc199a88aa73302c0f307029f21692d9d93308aefe4a942934de87f1c","src/unicode_tables/mod.rs":"4aad26e2df3b9611dc7906a814e3dc442b7ca3928ccdd6e2a31173d5e7dbf677","src/unicode_tables/property_names.rs":"68689cdabe287bd16d8379250e02d9d0f209114a35daf72f88c4d15bc6d51646","src/unicode_tables/property_values.rs":"89cf36aa70d5d09367f2c6e03f2d48353be2f71c94ae5c769ab834f628f7e680"},"package":"fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"}
\ No newline at end of file
diff --git a/third_party/rust/ucd-util/Cargo.toml b/third_party/rust/ucd-util/Cargo.toml
new file mode 100644
index 000000000000..6b40f6514118
--- /dev/null
+++ b/third_party/rust/ucd-util/Cargo.toml
@@ -0,0 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "ucd-util"
+version = "0.1.1"
+authors = ["Andrew Gallant <jamslam@gmail.com>"]
+description = "A small utility library for working with the Unicode character database.\n"
+homepage = "https://github.com/BurntSushi/rucd"
+documentation = "https://github.com/BurntSushi/rucd"
+readme = "README.md"
+keywords = ["unicode", "database", "character", "property"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/BurntSushi/rucd"
diff --git a/third_party/rust/ucd-util/LICENSE-APACHE b/third_party/rust/ucd-util/LICENSE-APACHE
new file mode 100644
index 000000000000..16fe87b06e80
--- /dev/null
+++ b/third_party/rust/ucd-util/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/ucd-util/LICENSE-MIT b/third_party/rust/ucd-util/LICENSE-MIT
new file mode 100644
index 000000000000..3b0a5dc09c1e
--- /dev/null
+++ b/third_party/rust/ucd-util/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Gallant
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/rust/ucd-util/README.md b/third_party/rust/ucd-util/README.md
new file mode 100644
index 000000000000..32151c70deef
--- /dev/null
+++ b/third_party/rust/ucd-util/README.md
@@ -0,0 +1,23 @@
+ucd-util
+========
+A library for small auxiliary Unicode functions. This includes things like
+symbol or character name canonicalization, ideograph name generation and helper
+functions for searching property name and value tables.
+
+[![Linux build status](https://api.travis-ci.org/BurntSushi/ucd-generate.png)](https://travis-ci.org/BurntSushi/ucd-generate)
+[![](http://meritbadge.herokuapp.com/ucd-generate)](https://crates.io/crates/ucd-util)
+
+
+### Documentation
+
+https://docs.rs/ucd-util
+
+
+### License
+
+This project is 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.
diff --git a/third_party/rust/ucd-util/src/hangul.rs b/third_party/rust/ucd-util/src/hangul.rs
new file mode 100644
index 000000000000..dd3bbc8f5019
--- /dev/null
+++ b/third_party/rust/ucd-util/src/hangul.rs
@@ -0,0 +1,105 @@
+use unicode_tables::jamo_short_name::JAMO_SHORT_NAME;
+
+// This implementation should correspond to the algorithms described in
+// Unicode 3.12.
+
+/// A set of ranges that corresponds to the set of all Hangul syllable
+/// codepoints.
+///
+/// These ranges are defined in Unicode 4.8 Table 4-13.
+pub const RANGE_HANGUL_SYLLABLE: &'static [(u32, u32)] = &[
+    (0xAC00, 0xD7A3),
+];
+
+const S_BASE: u32 = 0xAC00;
+const L_BASE: u32 = 0x1100;
+const V_BASE: u32 = 0x1161;
+const T_BASE: u32 = 0x11A7;
+const T_COUNT: u32 = 28;
+const N_COUNT: u32 = 588;
+
+/// Return the character name of the given precomposed Hangul codepoint.
+///
+/// If the given codepoint does not correspond to a precomposed Hangul
+/// codepoint in the inclusive range `AC00..D7A3`, then this returns `None`.
+///
+/// This implements the algorithms described in Unicode 3.12 and Unicode 4.8.
+pub fn hangul_name(cp: u32) -> Option<String> {
+    let mut name = "HANGUL SYLLABLE ".to_string();
+    let (lpart, vpart, tpart) = match hangul_full_canonical_decomposition(cp) {
+        None => return None,
+        Some(triple) => triple,
+    };
+
+    name.push_str(jamo_short_name(lpart));
+    name.push_str(jamo_short_name(vpart));
+    name.push_str(tpart.map_or("", jamo_short_name));
+    Some(name)
+}
+
+/// Return the full canonical decomposition of the given precomposed Hangul
+/// codepoint.
+///
+/// If the decomposition does not have any trailing consonant, then the third
+/// part of the tuple returned is `None`.
+///
+/// If the given codepoint does not correspond to a precomposed Hangul
+/// codepoint in the inclusive range `AC00..D7A3`, then this returns `None`.
+///
+/// This implements the algorithms described in Unicode 3.12 and Unicode 4.8.
+pub fn hangul_full_canonical_decomposition(
+    cp: u32,
+) -> Option<(u32, u32, Option<u32>)> {
+    if !(0xAC00 <= cp && cp <= 0xD7A3) {
+        return None;
+    }
+
+    let s_index = cp - S_BASE;
+    let l_index = s_index / N_COUNT;
+    let v_index = (s_index % N_COUNT) / T_COUNT;
+    let t_index = s_index % T_COUNT;
+
+    let l_part = L_BASE + l_index;
+    let v_part = V_BASE + v_index;
+    let t_part =
+        if t_index == 0 {
+            None
+        } else {
+            Some(T_BASE + t_index)
+        };
+    Some((l_part, v_part, t_part))
+}
+
+fn jamo_short_name(cp: u32) -> &'static str {
+    let i = JAMO_SHORT_NAME.binary_search_by_key(&cp, |p| p.0).unwrap();
+    JAMO_SHORT_NAME[i].1
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{hangul_name, hangul_full_canonical_decomposition};
+
+    #[test]
+    fn canon_decomp() {
+        assert_eq!(
+            hangul_full_canonical_decomposition(0xD4DB),
+            Some((0x1111, 0x1171, Some(0x11B6))));
+    }
+
+    #[test]
+    fn name() {
+        assert_eq!(hangul_name(0xD4DB).unwrap(), "HANGUL SYLLABLE PWILH");
+    }
+
+    #[test]
+    fn all() {
+        for cp in 0xAC00..(0xD7A3 + 1) {
+            hangul_name(cp).unwrap();
+        }
+    }
+
+    #[test]
+    fn invalid() {
+        assert!(hangul_name(0).is_none());
+    }
+}
diff --git a/third_party/rust/ucd-util/src/ideograph.rs b/third_party/rust/ucd-util/src/ideograph.rs
new file mode 100644
index 000000000000..0502c6ecf2c3
--- /dev/null
+++ b/third_party/rust/ucd-util/src/ideograph.rs
@@ -0,0 +1,83 @@
+/// A set of ranges that corresponds to the set of all ideograph codepoints.
+///
+/// These ranges are defined in Unicode 4.8 Table 4-13.
+pub const RANGE_IDEOGRAPH: &'static [(u32, u32)] = &[
+    (0x3400, 0x4DB5),
+    (0x4E00, 0x9FD5),
+    (0x4E00, 0x9FD5),
+    (0x20000, 0x2A6D6),
+    (0x2A700, 0x2B734),
+    (0x2B740, 0x2B81D),
+    (0x2B820, 0x2CEA1),
+    (0x17000, 0x187EC),
+    (0xF900, 0xFA6D),
+    (0xFA70, 0xFAD9),
+    (0x2F800, 0x2FA1D),
+];
+
+/// Return the character name of the given ideograph codepoint.
+///
+/// This operation is only defined on ideographic codepoints. This includes
+/// precisely the following inclusive ranges:
+///
+/// * `3400..4DB5`
+/// * `4E00..9FD5`
+/// * `20000..2A6D6`
+/// * `2A700..2B734`
+/// * `2B740..2B81D`
+/// * `2B820..2CEA1`
+/// * `17000..187EC`
+/// * `F900..FA6D`
+/// * `FA70..FAD9`
+/// * `2F800..2FA1D`
+///
+/// If the given codepoint is not in any of the above ranges, then `None` is
+/// returned.
+///
+/// This implements the algorithm described in Unicode 4.8.
+pub fn ideograph_name(cp: u32) -> Option<String> {
+    // This match should be in sync with the `RANGE_IDEOGRAPH` constant.
+    match cp {
+        0x3400...0x4DB5
+        | 0x4E00...0x9FD5
+        | 0x20000...0x2A6D6
+        | 0x2A700...0x2B734
+        | 0x2B740...0x2B81D
+        | 0x2B820...0x2CEA1 => {
+            Some(format!("CJK UNIFIED IDEOGRAPH-{:04X}", cp))
+        }
+        0x17000...0x187EC => {
+            Some(format!("TANGUT IDEOGRAPH-{:04X}", cp))
+        }
+        0xF900...0xFA6D | 0xFA70...0xFAD9 | 0x2F800...0x2FA1D => {
+            Some(format!("CJK COMPATIBILITY IDEOGRAPH-{:04X}", cp))
+        }
+        _ => None,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::ideograph_name;
+
+    #[test]
+    fn name() {
+        assert_eq!(
+            ideograph_name(0x4E00).unwrap(),
+            "CJK UNIFIED IDEOGRAPH-4E00");
+        assert_eq!(
+            ideograph_name(0x9FD5).unwrap(),
+            "CJK UNIFIED IDEOGRAPH-9FD5");
+        assert_eq!(
+            ideograph_name(0x17000).unwrap(),
+            "TANGUT IDEOGRAPH-17000");
+        assert_eq!(
+            ideograph_name(0xF900).unwrap(),
+            "CJK COMPATIBILITY IDEOGRAPH-F900");
+    }
+
+    #[test]
+    fn invalid() {
+        assert!(ideograph_name(0).is_none());
+    }
+}
diff --git a/third_party/rust/ucd-util/src/lib.rs b/third_party/rust/ucd-util/src/lib.rs
new file mode 100644
index 000000000000..4dc56063753e
--- /dev/null
+++ b/third_party/rust/ucd-util/src/lib.rs
@@ -0,0 +1,28 @@
+/*!
+The `ucd-util` crate contains a smattering of utility functions that implement
+various algorithms specified by Unicode. There is no specific goal for
+exhaustiveness. Instead, implementations should be added on an as-needed basis.
+
+A *current* design constraint of this crate is that it should not bring in any
+large Unicode tables. For example, to use the various property name and value
+canonicalization functions, you'll need to supply your own table, which can
+be generated using `ucd-generate`.
+*/
+
+#![deny(missing_docs)]
+
+mod hangul;
+mod ideograph;
+mod name;
+mod property;
+mod unicode_tables;
+
+pub use hangul::{
+    RANGE_HANGUL_SYLLABLE, hangul_name, hangul_full_canonical_decomposition,
+};
+pub use ideograph::{RANGE_IDEOGRAPH, ideograph_name};
+pub use name::{character_name_normalize, symbolic_name_normalize};
+pub use property::{
+    PropertyTable, PropertyValueTable, PropertyValues,
+    canonical_property_name, property_values, canonical_property_value,
+};
diff --git a/third_party/rust/ucd-util/src/name.rs b/third_party/rust/ucd-util/src/name.rs
new file mode 100644
index 000000000000..634d2eddfe75
--- /dev/null
+++ b/third_party/rust/ucd-util/src/name.rs
@@ -0,0 +1,180 @@
+/// Normalize the given character name in place according to UAX44-LM2.
+///
+/// See: http://unicode.org/reports/tr44/#UAX44-LM2
+pub fn character_name_normalize(string: &mut String) {
+    let bytes = unsafe {
+        // SAFETY: `character_name_normalize_bytes` guarantees that
+        // `bytes[..len]` is valid UTF-8.
+        string.as_mut_vec()
+    };
+    let len = character_name_normalize_bytes(bytes).len();
+    bytes.truncate(len);
+}
+
+/// Normalize the given character name in place according to UAX44-LM2.
+///
+/// The slice returned is guaranteed to be valid UTF-8 for all possible values
+/// of `slice`.
+///
+/// See: http://unicode.org/reports/tr44/#UAX44-LM2
+fn character_name_normalize_bytes(slice: &mut [u8]) -> &mut [u8] {
+    // According to Unicode 4.8, character names consist only of Latin
+    // capital letters A to Z, ASCII digits, ASCII space or ASCII hypen.
+    // Therefore, we can do very simplistic case folding and operate on the
+    // raw bytes, since everything is ASCII. Note that we don't actually know
+    // whether `slice` is all ASCII or not, so we drop all non-ASCII bytes.
+    let mut next_write = 0;
+    let mut prev_space = true;
+    for i in 0..slice.len() {
+        // SAFETY ARGUMENT: To guarantee that the resulting slice is valid
+        // UTF-8, we ensure that the slice contains only ASCII bytes. In
+        // particular, we drop every non-ASCII byte from the normalized string.
+        let b = slice[i];
+        if b == b' ' {
+            prev_space = true;
+            continue;
+        } else if b == b'_' {
+            // Drop the underscore.
+        } else if b == b'-' {
+            let mut keep_hyphen = prev_space || slice.get(i+1) == Some(&b' ');
+            // We want to keep the hypen only if it isn't medial, which means
+            // it has at least one adjacent space character. However, there
+            // is one exception. We need to keep the hypen in the character
+            // (U+1180) named `HANGUL JUNGSEONG O-E`. So we check for that
+            // here.
+            let rest_e = slice[i+1..] == b"E"[..] || slice[i+1..] == b"e"[..];
+            if !keep_hyphen && rest_e {
+                keep_hyphen = slice[..next_write] == b"hanguljungseongo"[..];
+            }
+            if keep_hyphen {
+                slice[next_write] = b;
+                next_write += 1;
+            }
+        } else if b'A' <= b && b <= b'Z' {
+            slice[next_write] = b + (b'a' - b'A');
+            next_write += 1;
+        } else if b <= 0x7F {
+            slice[next_write] = b;
+            next_write += 1;
+        }
+        prev_space = false;
+    }
+    &mut slice[..next_write]
+}
+
+/// Normalize the given symbolic name in place according to UAX44-LM3.
+///
+/// A "symbolic name" typically corresponds to property names and property
+/// value aliases. Note, though, that it should not be applied to property
+/// string values.
+///
+/// See: http://unicode.org/reports/tr44/#UAX44-LM2
+pub fn symbolic_name_normalize(string: &mut String) {
+    let bytes = unsafe {
+        // SAFETY: `symbolic_name_normalize_bytes` guarantees that
+        // `bytes[..len]` is valid UTF-8.
+        string.as_mut_vec()
+    };
+    let len = symbolic_name_normalize_bytes(bytes).len();
+    bytes.truncate(len);
+}
+
+/// Normalize the given symbolic name in place according to UAX44-LM3.
+///
+/// A "symbolic name" typically corresponds to property names and property
+/// value aliases. Note, though, that it should not be applied to property
+/// string values.
+///
+/// The slice returned is guaranteed to be valid UTF-8 for all possible values
+/// of `slice`.
+///
+/// See: http://unicode.org/reports/tr44/#UAX44-LM3
+fn symbolic_name_normalize_bytes(slice: &mut [u8]) -> &mut [u8] {
+    // I couldn't find a place in the standard that specified that property
+    // names/aliases had a particular structure (unlike character names), but
+    // we assume that it's ASCII only and drop anything that isn't ASCII.
+    let mut start = 0;
+    if slice.len() >= 2 {
+        // Ignore any "is" prefix.
+        let starts_with_is =
+            slice[0..2] == b"is"[..]
+            || slice[0..2] == b"IS"[..]
+            || slice[0..2] == b"iS"[..]
+            || slice[0..2] == b"Is"[..];
+        if starts_with_is {
+            start = 2;
+        }
+    }
+    let mut next_write = 0;
+    for i in start..slice.len() {
+        // SAFETY ARGUMENT: To guarantee that the resulting slice is valid
+        // UTF-8, we ensure that the slice contains only ASCII bytes. In
+        // particular, we drop every non-ASCII byte from the normalized string.
+        let b = slice[i];
+        if b == b' ' || b == b'_' || b == b'-' {
+            continue;
+        } else if b'A' <= b && b <= b'Z' {
+            slice[next_write] = b + (b'a' - b'A');
+            next_write += 1;
+        } else if b <= 0x7F {
+            slice[next_write] = b;
+            next_write += 1;
+        }
+    }
+    &mut slice[..next_write]
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{
+        character_name_normalize, character_name_normalize_bytes,
+        symbolic_name_normalize, symbolic_name_normalize_bytes,
+    };
+
+    fn char_norm(s: &str) -> String {
+        let mut s = s.to_string();
+        character_name_normalize(&mut s);
+        s
+    }
+
+    fn sym_norm(s: &str) -> String {
+        let mut s = s.to_string();
+        symbolic_name_normalize(&mut s);
+        s
+    }
+
+    #[test]
+    fn char_normalize() {
+        assert_eq!(char_norm("HANGUL JUNGSEONG O-E"), "hanguljungseongo-e");
+        assert_eq!(char_norm("zero-width space"), "zerowidthspace");
+        assert_eq!(char_norm("zerowidthspace"), "zerowidthspace");
+        assert_eq!(char_norm("ZERO WIDTH SPACE"), "zerowidthspace");
+        assert_eq!(char_norm("TIBETAN MARK TSA -PHRU"), "tibetanmarktsa-phru");
+    }
+
+    #[test]
+    fn sym_normalize() {
+        assert_eq!(sym_norm("Line_Break"), "linebreak");
+        assert_eq!(sym_norm("Line-break"), "linebreak");
+        assert_eq!(sym_norm("linebreak"), "linebreak");
+        assert_eq!(sym_norm("BA"), "ba");
+        assert_eq!(sym_norm("ba"), "ba");
+        assert_eq!(sym_norm("Greek"), "greek");
+        assert_eq!(sym_norm("isGreek"), "greek");
+        assert_eq!(sym_norm("IS_Greek"), "greek");
+    }
+
+    #[test]
+    fn valid_utf8_character() {
+        let mut x = b"abc\xFFxyz".to_vec();
+        let y = character_name_normalize_bytes(&mut x);
+        assert_eq!(y, b"abcxyz");
+    }
+
+    #[test]
+    fn valid_utf8_symbolic() {
+        let mut x = b"abc\xFFxyz".to_vec();
+        let y = symbolic_name_normalize_bytes(&mut x);
+        assert_eq!(y, b"abcxyz");
+    }
+}
diff --git a/third_party/rust/ucd-util/src/property.rs b/third_party/rust/ucd-util/src/property.rs
new file mode 100644
index 000000000000..7bbe56e96624
--- /dev/null
+++ b/third_party/rust/ucd-util/src/property.rs
@@ -0,0 +1,124 @@
+/// The type of a property name table.
+///
+/// A property name table is a sequence of sorted tuples, where the first
+/// value in each tuple is a normalized property name and the second value of
+/// each tuple is the corresponding canonical property name.
+pub type PropertyTable = &'static [(&'static str, &'static str)];
+
+/// Find the canonical property name for the given normalized property name.
+///
+/// If no such property exists, then `None` is returned.
+///
+/// The normalized property name must have been normalized according to
+/// UAX44 LM3, which can be done using `symbolic_name_normalize`.
+pub fn canonical_property_name(
+    property_table: PropertyTable,
+    normalized_property_name: &str,
+) -> Option<&'static str> {
+    property_table
+        .binary_search_by_key(&normalized_property_name, |&(n, _)| n)
+        .ok()
+        .map(|i| property_table[i].1)
+}
+
+/// Type of a property value table.
+///
+/// A property value table maps property names to a mapping of property values,
+/// where the mapping of property values is represented by a sequence of
+/// tuples. The first element of each tuple is a normalized property value
+/// while the second element of each tuple is the corresponding canonical
+/// property value.
+///
+/// Note that a property value table only includes values for properties that
+/// are catalogs, enumerations or binary properties. Properties that have
+/// string values (such as case or decomposition mappings), numeric values
+/// or are miscellaneous are not represented in this table.
+pub type PropertyValueTable = &'static [(&'static str, PropertyValues)];
+
+/// A mapping of property values for a specific property.
+///
+/// The first element of each tuple is a normalized property value while the
+/// second element of each tuple is the corresponding canonical property
+/// value.
+pub type PropertyValues = &'static [(&'static str, &'static str)];
+
+/// Find the set of possible property values for a given property.
+///
+/// The set returned is a mapping expressed as a sorted list of tuples.
+/// The first element of each tuple is a normalized property value while the
+/// second element of each tuple is the corresponding canonical property
+/// value.
+///
+/// If no such property exists, then `None` is returned.
+///
+/// The given property name must be in its canonical form, which can be
+/// found using `canonical_property_name`.
+pub fn property_values(
+    property_value_table: PropertyValueTable,
+    canonical_property_name: &str,
+) -> Option<PropertyValues> {
+    property_value_table
+        .binary_search_by_key(&canonical_property_name, |&(n, _)| n)
+        .ok()
+        .map(|i| property_value_table[i].1)
+}
+
+/// Find the canonical property value for the given normalized property
+/// value.
+///
+/// The given property values should correspond to the values for the property
+/// under question, which can be found using `property_values`.
+///
+/// If no such property value exists, then `None` is returned.
+///
+/// The normalized property value must have been normalized according to
+/// UAX44 LM3, which can be done using `symbolic_name_normalize`.
+pub fn canonical_property_value(
+    property_values: PropertyValues,
+    normalized_property_value: &str,
+) -> Option<&'static str> {
+    // This is cute. The types line up, so why not?
+    canonical_property_name(property_values, normalized_property_value)
+}
+
+
+#[cfg(test)]
+mod tests {
+    use unicode_tables::property_names::PROPERTY_NAMES;
+    use unicode_tables::property_values::PROPERTY_VALUES;
+
+    use super::{
+        canonical_property_name, property_values, canonical_property_value,
+    };
+
+    #[test]
+    fn canonical_property_name_1() {
+        assert_eq!(
+            canonical_property_name(PROPERTY_NAMES, "gc"),
+            Some("General_Category"));
+        assert_eq!(
+            canonical_property_name(PROPERTY_NAMES, "generalcategory"),
+            Some("General_Category"));
+        assert_eq!(
+            canonical_property_name(PROPERTY_NAMES, "g c"),
+            None);
+    }
+
+    #[test]
+    fn property_values_1() {
+        assert_eq!(
+            property_values(PROPERTY_VALUES, "White_Space"),
+            Some(&[
+                ("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+                ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+            ][..]));
+    }
+
+    #[test]
+    fn canonical_property_value_1() {
+        let values = property_values(PROPERTY_VALUES, "White_Space").unwrap();
+        assert_eq!(canonical_property_value(values, "false"), Some("No"));
+        assert_eq!(canonical_property_value(values, "t"), Some("Yes"));
+        assert_eq!(canonical_property_value(values, "F"), None);
+    }
+}
diff --git a/third_party/rust/ucd-util/src/unicode_tables/jamo_short_name.rs b/third_party/rust/ucd-util/src/unicode_tables/jamo_short_name.rs
new file mode 100644
index 000000000000..c9f2edeaf16c
--- /dev/null
+++ b/third_party/rust/ucd-util/src/unicode_tables/jamo_short_name.rs
@@ -0,0 +1,22 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate jamo-short-name tmp/ucd-10.0.0/
+//
+// ucd-generate is available on crates.io.
+
+pub const JAMO_SHORT_NAME: &'static [(u32, &'static str)] = &[
+  (4352, "G"), (4353, "GG"), (4354, "N"), (4355, "D"), (4356, "DD"),
+  (4357, "R"), (4358, "M"), (4359, "B"), (4360, "BB"), (4361, "S"),
+  (4362, "SS"), (4363, ""), (4364, "J"), (4365, "JJ"), (4366, "C"),
+  (4367, "K"), (4368, "T"), (4369, "P"), (4370, "H"), (4449, "A"),
+  (4450, "AE"), (4451, "YA"), (4452, "YAE"), (4453, "EO"), (4454, "E"),
+  (4455, "YEO"), (4456, "YE"), (4457, "O"), (4458, "WA"), (4459, "WAE"),
+  (4460, "OE"), (4461, "YO"), (4462, "U"), (4463, "WEO"), (4464, "WE"),
+  (4465, "WI"), (4466, "YU"), (4467, "EU"), (4468, "YI"), (4469, "I"),
+  (4520, "G"), (4521, "GG"), (4522, "GS"), (4523, "N"), (4524, "NJ"),
+  (4525, "NH"), (4526, "D"), (4527, "L"), (4528, "LG"), (4529, "LM"),
+  (4530, "LB"), (4531, "LS"), (4532, "LT"), (4533, "LP"), (4534, "LH"),
+  (4535, "M"), (4536, "B"), (4537, "BS"), (4538, "S"), (4539, "SS"),
+  (4540, "NG"), (4541, "J"), (4542, "C"), (4543, "K"), (4544, "T"),
+  (4545, "P"), (4546, "H"),
+];
diff --git a/third_party/rust/ucd-util/src/unicode_tables/mod.rs b/third_party/rust/ucd-util/src/unicode_tables/mod.rs
new file mode 100644
index 000000000000..558177da924a
--- /dev/null
+++ b/third_party/rust/ucd-util/src/unicode_tables/mod.rs
@@ -0,0 +1,5 @@
+pub mod jamo_short_name;
+#[cfg(test)]
+pub mod property_names;
+#[cfg(test)]
+pub mod property_values;
diff --git a/third_party/rust/ucd-util/src/unicode_tables/property_names.rs b/third_party/rust/ucd-util/src/unicode_tables/property_names.rs
new file mode 100644
index 000000000000..1d1032d3370c
--- /dev/null
+++ b/third_party/rust/ucd-util/src/unicode_tables/property_names.rs
@@ -0,0 +1,146 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate property-names tmp/ucd-10.0.0/
+//
+// ucd-generate is available on crates.io.
+
+pub const PROPERTY_NAMES: &'static [(&'static str, &'static str)] = &[
+  ("age", "Age"), ("ahex", "ASCII_Hex_Digit"), ("alpha", "Alphabetic"),
+  ("alphabetic", "Alphabetic"), ("asciihexdigit", "ASCII_Hex_Digit"),
+  ("bc", "Bidi_Class"), ("bidic", "Bidi_Control"),
+  ("bidiclass", "Bidi_Class"), ("bidicontrol", "Bidi_Control"),
+  ("bidim", "Bidi_Mirrored"), ("bidimirrored", "Bidi_Mirrored"),
+  ("bidimirroringglyph", "Bidi_Mirroring_Glyph"),
+  ("bidipairedbracket", "Bidi_Paired_Bracket"),
+  ("bidipairedbrackettype", "Bidi_Paired_Bracket_Type"), ("blk", "Block"),
+  ("block", "Block"), ("bmg", "Bidi_Mirroring_Glyph"),
+  ("bpb", "Bidi_Paired_Bracket"), ("bpt", "Bidi_Paired_Bracket_Type"),
+  ("c", "ISO_Comment"),
+  ("canonicalcombiningclass", "Canonical_Combining_Class"),
+  ("cased", "Cased"), ("casefolding", "Case_Folding"),
+  ("caseignorable", "Case_Ignorable"), ("ccc", "Canonical_Combining_Class"),
+  ("ce", "Composition_Exclusion"), ("cf", "Case_Folding"),
+  ("changeswhencasefolded", "Changes_When_Casefolded"),
+  ("changeswhencasemapped", "Changes_When_Casemapped"),
+  ("changeswhenlowercased", "Changes_When_Lowercased"),
+  ("changeswhennfkccasefolded", "Changes_When_NFKC_Casefolded"),
+  ("changeswhentitlecased", "Changes_When_Titlecased"),
+  ("changeswhenuppercased", "Changes_When_Uppercased"),
+  ("ci", "Case_Ignorable"), ("cjkaccountingnumeric", "kAccountingNumeric"),
+  ("cjkcompatibilityvariant", "kCompatibilityVariant"),
+  ("cjkiicore", "kIICore"), ("cjkirggsource", "kIRG_GSource"),
+  ("cjkirghsource", "kIRG_HSource"), ("cjkirgjsource", "kIRG_JSource"),
+  ("cjkirgkpsource", "kIRG_KPSource"), ("cjkirgksource", "kIRG_KSource"),
+  ("cjkirgmsource", "kIRG_MSource"), ("cjkirgtsource", "kIRG_TSource"),
+  ("cjkirgusource", "kIRG_USource"), ("cjkirgvsource", "kIRG_VSource"),
+  ("cjkothernumeric", "kOtherNumeric"),
+  ("cjkprimarynumeric", "kPrimaryNumeric"), ("cjkrsunicode", "kRSUnicode"),
+  ("compex", "Full_Composition_Exclusion"),
+  ("compositionexclusion", "Composition_Exclusion"),
+  ("cwcf", "Changes_When_Casefolded"), ("cwcm", "Changes_When_Casemapped"),
+  ("cwkcf", "Changes_When_NFKC_Casefolded"),
+  ("cwl", "Changes_When_Lowercased"), ("cwt", "Changes_When_Titlecased"),
+  ("cwu", "Changes_When_Uppercased"), ("dash", "Dash"),
+  ("decompositionmapping", "Decomposition_Mapping"),
+  ("decompositiontype", "Decomposition_Type"),
+  ("defaultignorablecodepoint", "Default_Ignorable_Code_Point"),
+  ("dep", "Deprecated"), ("deprecated", "Deprecated"),
+  ("di", "Default_Ignorable_Code_Point"), ("dia", "Diacritic"),
+  ("diacritic", "Diacritic"), ("dm", "Decomposition_Mapping"),
+  ("dt", "Decomposition_Type"), ("ea", "East_Asian_Width"),
+  ("eastasianwidth", "East_Asian_Width"), ("expandsonnfc", "Expands_On_NFC"),
+  ("expandsonnfd", "Expands_On_NFD"), ("expandsonnfkc", "Expands_On_NFKC"),
+  ("expandsonnfkd", "Expands_On_NFKD"), ("ext", "Extender"),
+  ("extender", "Extender"), ("fcnfkc", "FC_NFKC_Closure"),
+  ("fcnfkcclosure", "FC_NFKC_Closure"),
+  ("fullcompositionexclusion", "Full_Composition_Exclusion"),
+  ("gc", "General_Category"), ("gcb", "Grapheme_Cluster_Break"),
+  ("generalcategory", "General_Category"), ("graphemebase", "Grapheme_Base"),
+  ("graphemeclusterbreak", "Grapheme_Cluster_Break"),
+  ("graphemeextend", "Grapheme_Extend"), ("graphemelink", "Grapheme_Link"),
+  ("grbase", "Grapheme_Base"), ("grext", "Grapheme_Extend"),
+  ("grlink", "Grapheme_Link"), ("hangulsyllabletype", "Hangul_Syllable_Type"),
+  ("hex", "Hex_Digit"), ("hexdigit", "Hex_Digit"),
+  ("hst", "Hangul_Syllable_Type"), ("hyphen", "Hyphen"),
+  ("idc", "ID_Continue"), ("idcontinue", "ID_Continue"),
+  ("ideo", "Ideographic"), ("ideographic", "Ideographic"),
+  ("ids", "ID_Start"), ("idsb", "IDS_Binary_Operator"),
+  ("idsbinaryoperator", "IDS_Binary_Operator"),
+  ("idst", "IDS_Trinary_Operator"), ("idstart", "ID_Start"),
+  ("idstrinaryoperator", "IDS_Trinary_Operator"),
+  ("indicpositionalcategory", "Indic_Positional_Category"),
+  ("indicsyllabiccategory", "Indic_Syllabic_Category"),
+  ("inpc", "Indic_Positional_Category"), ("insc", "Indic_Syllabic_Category"),
+  ("jamoshortname", "Jamo_Short_Name"), ("jg", "Joining_Group"),
+  ("joinc", "Join_Control"), ("joincontrol", "Join_Control"),
+  ("joininggroup", "Joining_Group"), ("joiningtype", "Joining_Type"),
+  ("jsn", "Jamo_Short_Name"), ("jt", "Joining_Type"),
+  ("kaccountingnumeric", "kAccountingNumeric"),
+  ("kcompatibilityvariant", "kCompatibilityVariant"), ("kiicore", "kIICore"),
+  ("kirggsource", "kIRG_GSource"), ("kirghsource", "kIRG_HSource"),
+  ("kirgjsource", "kIRG_JSource"), ("kirgkpsource", "kIRG_KPSource"),
+  ("kirgksource", "kIRG_KSource"), ("kirgmsource", "kIRG_MSource"),
+  ("kirgtsource", "kIRG_TSource"), ("kirgusource", "kIRG_USource"),
+  ("kirgvsource", "kIRG_VSource"), ("kothernumeric", "kOtherNumeric"),
+  ("kprimarynumeric", "kPrimaryNumeric"), ("krsunicode", "kRSUnicode"),
+  ("lb", "Line_Break"), ("lc", "Lowercase_Mapping"),
+  ("linebreak", "Line_Break"), ("loe", "Logical_Order_Exception"),
+  ("logicalorderexception", "Logical_Order_Exception"),
+  ("lower", "Lowercase"), ("lowercase", "Lowercase"),
+  ("lowercasemapping", "Lowercase_Mapping"), ("math", "Math"), ("na", "Name"),
+  ("na1", "Unicode_1_Name"), ("name", "Name"), ("namealias", "Name_Alias"),
+  ("nchar", "Noncharacter_Code_Point"), ("nfcqc", "NFC_Quick_Check"),
+  ("nfcquickcheck", "NFC_Quick_Check"), ("nfdqc", "NFD_Quick_Check"),
+  ("nfdquickcheck", "NFD_Quick_Check"), ("nfkccasefold", "NFKC_Casefold"),
+  ("nfkccf", "NFKC_Casefold"), ("nfkcqc", "NFKC_Quick_Check"),
+  ("nfkcquickcheck", "NFKC_Quick_Check"), ("nfkdqc", "NFKD_Quick_Check"),
+  ("nfkdquickcheck", "NFKD_Quick_Check"),
+  ("noncharactercodepoint", "Noncharacter_Code_Point"),
+  ("nt", "Numeric_Type"), ("numerictype", "Numeric_Type"),
+  ("numericvalue", "Numeric_Value"), ("nv", "Numeric_Value"),
+  ("oalpha", "Other_Alphabetic"), ("ocomment", "ISO_Comment"),
+  ("odi", "Other_Default_Ignorable_Code_Point"),
+  ("ogrext", "Other_Grapheme_Extend"), ("oidc", "Other_ID_Continue"),
+  ("oids", "Other_ID_Start"), ("olower", "Other_Lowercase"),
+  ("omath", "Other_Math"), ("otheralphabetic", "Other_Alphabetic"),
+  ("otherdefaultignorablecodepoint", "Other_Default_Ignorable_Code_Point"),
+  ("othergraphemeextend", "Other_Grapheme_Extend"),
+  ("otheridcontinue", "Other_ID_Continue"),
+  ("otheridstart", "Other_ID_Start"), ("otherlowercase", "Other_Lowercase"),
+  ("othermath", "Other_Math"), ("otheruppercase", "Other_Uppercase"),
+  ("oupper", "Other_Uppercase"), ("patsyn", "Pattern_Syntax"),
+  ("patternsyntax", "Pattern_Syntax"),
+  ("patternwhitespace", "Pattern_White_Space"),
+  ("patws", "Pattern_White_Space"), ("pcm", "Prepended_Concatenation_Mark"),
+  ("prependedconcatenationmark", "Prepended_Concatenation_Mark"),
+  ("qmark", "Quotation_Mark"), ("quotationmark", "Quotation_Mark"),
+  ("radical", "Radical"), ("regionalindicator", "Regional_Indicator"),
+  ("ri", "Regional_Indicator"), ("sb", "Sentence_Break"), ("sc", "Script"),
+  ("scf", "Simple_Case_Folding"), ("script", "Script"),
+  ("scriptextensions", "Script_Extensions"), ("scx", "Script_Extensions"),
+  ("sd", "Soft_Dotted"), ("sentencebreak", "Sentence_Break"),
+  ("sentenceterminal", "Sentence_Terminal"), ("sfc", "Simple_Case_Folding"),
+  ("simplecasefolding", "Simple_Case_Folding"),
+  ("simplelowercasemapping", "Simple_Lowercase_Mapping"),
+  ("simpletitlecasemapping", "Simple_Titlecase_Mapping"),
+  ("simpleuppercasemapping", "Simple_Uppercase_Mapping"),
+  ("slc", "Simple_Lowercase_Mapping"), ("softdotted", "Soft_Dotted"),
+  ("space", "White_Space"), ("stc", "Simple_Titlecase_Mapping"),
+  ("sterm", "Sentence_Terminal"), ("suc", "Simple_Uppercase_Mapping"),
+  ("tc", "Titlecase_Mapping"), ("term", "Terminal_Punctuation"),
+  ("terminalpunctuation", "Terminal_Punctuation"),
+  ("titlecasemapping", "Titlecase_Mapping"), ("uc", "Uppercase_Mapping"),
+  ("uideo", "Unified_Ideograph"), ("unicode1name", "Unicode_1_Name"),
+  ("unicoderadicalstroke", "kRSUnicode"),
+  ("unifiedideograph", "Unified_Ideograph"), ("upper", "Uppercase"),
+  ("uppercase", "Uppercase"), ("uppercasemapping", "Uppercase_Mapping"),
+  ("urs", "kRSUnicode"), ("variationselector", "Variation_Selector"),
+  ("verticalorientation", "Vertical_Orientation"),
+  ("vo", "Vertical_Orientation"), ("vs", "Variation_Selector"),
+  ("wb", "Word_Break"), ("whitespace", "White_Space"),
+  ("wordbreak", "Word_Break"), ("wspace", "White_Space"),
+  ("xidc", "XID_Continue"), ("xidcontinue", "XID_Continue"),
+  ("xids", "XID_Start"), ("xidstart", "XID_Start"),
+  ("xonfc", "Expands_On_NFC"), ("xonfd", "Expands_On_NFD"),
+  ("xonfkc", "Expands_On_NFKC"), ("xonfkd", "Expands_On_NFKD"),
+];
diff --git a/third_party/rust/ucd-util/src/unicode_tables/property_values.rs b/third_party/rust/ucd-util/src/unicode_tables/property_values.rs
new file mode 100644
index 000000000000..5d43a0590645
--- /dev/null
+++ b/third_party/rust/ucd-util/src/unicode_tables/property_values.rs
@@ -0,0 +1,992 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+//  ucd-generate property-values tmp/ucd-10.0.0/
+//
+// ucd-generate is available on crates.io.
+
+pub const PROPERTY_VALUES: &'static [(&'static str, &'static [(&'static str, &'static str)])] = &[
+  ("ASCII_Hex_Digit", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Age", &[("1.1", "V1_1"), ("10.0", "V10_0"), ("2.0", "V2_0"),
+  ("2.1", "V2_1"), ("3.0", "V3_0"), ("3.1", "V3_1"), ("3.2", "V3_2"),
+  ("4.0", "V4_0"), ("4.1", "V4_1"), ("5.0", "V5_0"), ("5.1", "V5_1"),
+  ("5.2", "V5_2"), ("6.0", "V6_0"), ("6.1", "V6_1"), ("6.2", "V6_2"),
+  ("6.3", "V6_3"), ("7.0", "V7_0"), ("8.0", "V8_0"), ("9.0", "V9_0"),
+  ("na", "Unassigned"), ("unassigned", "Unassigned"), ("v100", "V10_0"),
+  ("v11", "V1_1"), ("v20", "V2_0"), ("v21", "V2_1"), ("v30", "V3_0"),
+  ("v31", "V3_1"), ("v32", "V3_2"), ("v40", "V4_0"), ("v41", "V4_1"),
+  ("v50", "V5_0"), ("v51", "V5_1"), ("v52", "V5_2"), ("v60", "V6_0"),
+  ("v61", "V6_1"), ("v62", "V6_2"), ("v63", "V6_3"), ("v70", "V7_0"),
+  ("v80", "V8_0"), ("v90", "V9_0"), ]),
+
+  ("Alphabetic", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Bidi_Class", &[("al", "Arabic_Letter"), ("an", "Arabic_Number"),
+  ("arabicletter", "Arabic_Letter"), ("arabicnumber", "Arabic_Number"),
+  ("b", "Paragraph_Separator"), ("bn", "Boundary_Neutral"),
+  ("boundaryneutral", "Boundary_Neutral"),
+  ("commonseparator", "Common_Separator"), ("cs", "Common_Separator"),
+  ("en", "European_Number"), ("es", "European_Separator"),
+  ("et", "European_Terminator"), ("europeannumber", "European_Number"),
+  ("europeanseparator", "European_Separator"),
+  ("europeanterminator", "European_Terminator"),
+  ("firststrongisolate", "First_Strong_Isolate"),
+  ("fsi", "First_Strong_Isolate"), ("l", "Left_To_Right"),
+  ("lefttoright", "Left_To_Right"),
+  ("lefttorightembedding", "Left_To_Right_Embedding"),
+  ("lefttorightisolate", "Left_To_Right_Isolate"),
+  ("lefttorightoverride", "Left_To_Right_Override"),
+  ("lre", "Left_To_Right_Embedding"), ("lri", "Left_To_Right_Isolate"),
+  ("lro", "Left_To_Right_Override"), ("nonspacingmark", "Nonspacing_Mark"),
+  ("nsm", "Nonspacing_Mark"), ("on", "Other_Neutral"),
+  ("otherneutral", "Other_Neutral"),
+  ("paragraphseparator", "Paragraph_Separator"),
+  ("pdf", "Pop_Directional_Format"), ("pdi", "Pop_Directional_Isolate"),
+  ("popdirectionalformat", "Pop_Directional_Format"),
+  ("popdirectionalisolate", "Pop_Directional_Isolate"),
+  ("r", "Right_To_Left"), ("righttoleft", "Right_To_Left"),
+  ("righttoleftembedding", "Right_To_Left_Embedding"),
+  ("righttoleftisolate", "Right_To_Left_Isolate"),
+  ("righttoleftoverride", "Right_To_Left_Override"),
+  ("rle", "Right_To_Left_Embedding"), ("rli", "Right_To_Left_Isolate"),
+  ("rlo", "Right_To_Left_Override"), ("s", "Segment_Separator"),
+  ("segmentseparator", "Segment_Separator"), ("whitespace", "White_Space"),
+  ("ws", "White_Space"), ]),
+
+  ("Bidi_Control", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Bidi_Mirrored", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Bidi_Paired_Bracket_Type", &[("c", "Close"), ("close", "Close"),
+  ("n", "None"), ("none", "None"), ("o", "Open"), ("open", "Open"), ]),
+
+  ("Block", &[("adlam", "Adlam"), ("aegeannumbers", "Aegean_Numbers"),
+  ("ahom", "Ahom"), ("alchemical", "Alchemical_Symbols"),
+  ("alchemicalsymbols", "Alchemical_Symbols"),
+  ("alphabeticpf", "Alphabetic_Presentation_Forms"),
+  ("alphabeticpresentationforms", "Alphabetic_Presentation_Forms"),
+  ("anatolianhieroglyphs", "Anatolian_Hieroglyphs"),
+  ("ancientgreekmusic", "Ancient_Greek_Musical_Notation"),
+  ("ancientgreekmusicalnotation", "Ancient_Greek_Musical_Notation"),
+  ("ancientgreeknumbers", "Ancient_Greek_Numbers"),
+  ("ancientsymbols", "Ancient_Symbols"), ("arabic", "Arabic"),
+  ("arabicexta", "Arabic_Extended_A"),
+  ("arabicextendeda", "Arabic_Extended_A"),
+  ("arabicmath", "Arabic_Mathematical_Alphabetic_Symbols"),
+  ("arabicmathematicalalphabeticsymbols", "Arabic_Mathematical_Alphabetic_Symbols"),
+  ("arabicpfa", "Arabic_Presentation_Forms_A"),
+  ("arabicpfb", "Arabic_Presentation_Forms_B"),
+  ("arabicpresentationformsa", "Arabic_Presentation_Forms_A"),
+  ("arabicpresentationformsb", "Arabic_Presentation_Forms_B"),
+  ("arabicsup", "Arabic_Supplement"),
+  ("arabicsupplement", "Arabic_Supplement"), ("armenian", "Armenian"),
+  ("arrows", "Arrows"), ("ascii", "Basic_Latin"), ("avestan", "Avestan"),
+  ("balinese", "Balinese"), ("bamum", "Bamum"),
+  ("bamumsup", "Bamum_Supplement"), ("bamumsupplement", "Bamum_Supplement"),
+  ("basiclatin", "Basic_Latin"), ("bassavah", "Bassa_Vah"),
+  ("batak", "Batak"), ("bengali", "Bengali"), ("bhaiksuki", "Bhaiksuki"),
+  ("blockelements", "Block_Elements"), ("bopomofo", "Bopomofo"),
+  ("bopomofoext", "Bopomofo_Extended"),
+  ("bopomofoextended", "Bopomofo_Extended"), ("boxdrawing", "Box_Drawing"),
+  ("brahmi", "Brahmi"), ("braille", "Braille_Patterns"),
+  ("braillepatterns", "Braille_Patterns"), ("buginese", "Buginese"),
+  ("buhid", "Buhid"), ("byzantinemusic", "Byzantine_Musical_Symbols"),
+  ("byzantinemusicalsymbols", "Byzantine_Musical_Symbols"),
+  ("canadiansyllabics", "Unified_Canadian_Aboriginal_Syllabics"),
+  ("carian", "Carian"), ("caucasianalbanian", "Caucasian_Albanian"),
+  ("chakma", "Chakma"), ("cham", "Cham"), ("cherokee", "Cherokee"),
+  ("cherokeesup", "Cherokee_Supplement"),
+  ("cherokeesupplement", "Cherokee_Supplement"),
+  ("cjk", "CJK_Unified_Ideographs"), ("cjkcompat", "CJK_Compatibility"),
+  ("cjkcompatforms", "CJK_Compatibility_Forms"),
+  ("cjkcompatibility", "CJK_Compatibility"),
+  ("cjkcompatibilityforms", "CJK_Compatibility_Forms"),
+  ("cjkcompatibilityideographs", "CJK_Compatibility_Ideographs"),
+  ("cjkcompatibilityideographssupplement", "CJK_Compatibility_Ideographs_Supplement"),
+  ("cjkcompatideographs", "CJK_Compatibility_Ideographs"),
+  ("cjkcompatideographssup", "CJK_Compatibility_Ideographs_Supplement"),
+  ("cjkexta", "CJK_Unified_Ideographs_Extension_A"),
+  ("cjkextb", "CJK_Unified_Ideographs_Extension_B"),
+  ("cjkextc", "CJK_Unified_Ideographs_Extension_C"),
+  ("cjkextd", "CJK_Unified_Ideographs_Extension_D"),
+  ("cjkexte", "CJK_Unified_Ideographs_Extension_E"),
+  ("cjkextf", "CJK_Unified_Ideographs_Extension_F"),
+  ("cjkradicalssup", "CJK_Radicals_Supplement"),
+  ("cjkradicalssupplement", "CJK_Radicals_Supplement"),
+  ("cjkstrokes", "CJK_Strokes"),
+  ("cjksymbols", "CJK_Symbols_And_Punctuation"),
+  ("cjksymbolsandpunctuation", "CJK_Symbols_And_Punctuation"),
+  ("cjkunifiedideographs", "CJK_Unified_Ideographs"),
+  ("cjkunifiedideographsextensiona", "CJK_Unified_Ideographs_Extension_A"),
+  ("cjkunifiedideographsextensionb", "CJK_Unified_Ideographs_Extension_B"),
+  ("cjkunifiedideographsextensionc", "CJK_Unified_Ideographs_Extension_C"),
+  ("cjkunifiedideographsextensiond", "CJK_Unified_Ideographs_Extension_D"),
+  ("cjkunifiedideographsextensione", "CJK_Unified_Ideographs_Extension_E"),
+  ("cjkunifiedideographsextensionf", "CJK_Unified_Ideographs_Extension_F"),
+  ("combiningdiacriticalmarks", "Combining_Diacritical_Marks"),
+  ("combiningdiacriticalmarksextended", "Combining_Diacritical_Marks_Extended"),
+  ("combiningdiacriticalmarksforsymbols", "Combining_Diacritical_Marks_For_Symbols"),
+  ("combiningdiacriticalmarkssupplement", "Combining_Diacritical_Marks_Supplement"),
+  ("combininghalfmarks", "Combining_Half_Marks"),
+  ("combiningmarksforsymbols", "Combining_Diacritical_Marks_For_Symbols"),
+  ("commonindicnumberforms", "Common_Indic_Number_Forms"),
+  ("compatjamo", "Hangul_Compatibility_Jamo"),
+  ("controlpictures", "Control_Pictures"), ("coptic", "Coptic"),
+  ("copticepactnumbers", "Coptic_Epact_Numbers"),
+  ("countingrod", "Counting_Rod_Numerals"),
+  ("countingrodnumerals", "Counting_Rod_Numerals"),
+  ("cuneiform", "Cuneiform"),
+  ("cuneiformnumbers", "Cuneiform_Numbers_And_Punctuation"),
+  ("cuneiformnumbersandpunctuation", "Cuneiform_Numbers_And_Punctuation"),
+  ("currencysymbols", "Currency_Symbols"),
+  ("cypriotsyllabary", "Cypriot_Syllabary"), ("cyrillic", "Cyrillic"),
+  ("cyrillicexta", "Cyrillic_Extended_A"),
+  ("cyrillicextb", "Cyrillic_Extended_B"),
+  ("cyrillicextc", "Cyrillic_Extended_C"),
+  ("cyrillicextendeda", "Cyrillic_Extended_A"),
+  ("cyrillicextendedb", "Cyrillic_Extended_B"),
+  ("cyrillicextendedc", "Cyrillic_Extended_C"),
+  ("cyrillicsup", "Cyrillic_Supplement"),
+  ("cyrillicsupplement", "Cyrillic_Supplement"),
+  ("cyrillicsupplementary", "Cyrillic_Supplement"), ("deseret", "Deseret"),
+  ("devanagari", "Devanagari"), ("devanagariext", "Devanagari_Extended"),
+  ("devanagariextended", "Devanagari_Extended"),
+  ("diacriticals", "Combining_Diacritical_Marks"),
+  ("diacriticalsext", "Combining_Diacritical_Marks_Extended"),
+  ("diacriticalsforsymbols", "Combining_Diacritical_Marks_For_Symbols"),
+  ("diacriticalssup", "Combining_Diacritical_Marks_Supplement"),
+  ("dingbats", "Dingbats"), ("domino", "Domino_Tiles"),
+  ("dominotiles", "Domino_Tiles"), ("duployan", "Duployan"),
+  ("earlydynasticcuneiform", "Early_Dynastic_Cuneiform"),
+  ("egyptianhieroglyphs", "Egyptian_Hieroglyphs"), ("elbasan", "Elbasan"),
+  ("emoticons", "Emoticons"), ("enclosedalphanum", "Enclosed_Alphanumerics"),
+  ("enclosedalphanumerics", "Enclosed_Alphanumerics"),
+  ("enclosedalphanumericsupplement", "Enclosed_Alphanumeric_Supplement"),
+  ("enclosedalphanumsup", "Enclosed_Alphanumeric_Supplement"),
+  ("enclosedcjk", "Enclosed_CJK_Letters_And_Months"),
+  ("enclosedcjklettersandmonths", "Enclosed_CJK_Letters_And_Months"),
+  ("enclosedideographicsup", "Enclosed_Ideographic_Supplement"),
+  ("enclosedideographicsupplement", "Enclosed_Ideographic_Supplement"),
+  ("ethiopic", "Ethiopic"), ("ethiopicext", "Ethiopic_Extended"),
+  ("ethiopicexta", "Ethiopic_Extended_A"),
+  ("ethiopicextended", "Ethiopic_Extended"),
+  ("ethiopicextendeda", "Ethiopic_Extended_A"),
+  ("ethiopicsup", "Ethiopic_Supplement"),
+  ("ethiopicsupplement", "Ethiopic_Supplement"),
+  ("generalpunctuation", "General_Punctuation"),
+  ("geometricshapes", "Geometric_Shapes"),
+  ("geometricshapesext", "Geometric_Shapes_Extended"),
+  ("geometricshapesextended", "Geometric_Shapes_Extended"),
+  ("georgian", "Georgian"), ("georgiansup", "Georgian_Supplement"),
+  ("georgiansupplement", "Georgian_Supplement"), ("glagolitic", "Glagolitic"),
+  ("glagoliticsup", "Glagolitic_Supplement"),
+  ("glagoliticsupplement", "Glagolitic_Supplement"), ("gothic", "Gothic"),
+  ("grantha", "Grantha"), ("greek", "Greek_And_Coptic"),
+  ("greekandcoptic", "Greek_And_Coptic"), ("greekext", "Greek_Extended"),
+  ("greekextended", "Greek_Extended"), ("gujarati", "Gujarati"),
+  ("gurmukhi", "Gurmukhi"),
+  ("halfandfullforms", "Halfwidth_And_Fullwidth_Forms"),
+  ("halfmarks", "Combining_Half_Marks"),
+  ("halfwidthandfullwidthforms", "Halfwidth_And_Fullwidth_Forms"),
+  ("hangul", "Hangul_Syllables"),
+  ("hangulcompatibilityjamo", "Hangul_Compatibility_Jamo"),
+  ("hanguljamo", "Hangul_Jamo"),
+  ("hanguljamoextendeda", "Hangul_Jamo_Extended_A"),
+  ("hanguljamoextendedb", "Hangul_Jamo_Extended_B"),
+  ("hangulsyllables", "Hangul_Syllables"), ("hanunoo", "Hanunoo"),
+  ("hatran", "Hatran"), ("hebrew", "Hebrew"),
+  ("highprivateusesurrogates", "High_Private_Use_Surrogates"),
+  ("highpusurrogates", "High_Private_Use_Surrogates"),
+  ("highsurrogates", "High_Surrogates"), ("hiragana", "Hiragana"),
+  ("idc", "Ideographic_Description_Characters"),
+  ("ideographicdescriptioncharacters", "Ideographic_Description_Characters"),
+  ("ideographicsymbols", "Ideographic_Symbols_And_Punctuation"),
+  ("ideographicsymbolsandpunctuation", "Ideographic_Symbols_And_Punctuation"),
+  ("imperialaramaic", "Imperial_Aramaic"),
+  ("indicnumberforms", "Common_Indic_Number_Forms"),
+  ("inscriptionalpahlavi", "Inscriptional_Pahlavi"),
+  ("inscriptionalparthian", "Inscriptional_Parthian"),
+  ("ipaext", "IPA_Extensions"), ("ipaextensions", "IPA_Extensions"),
+  ("jamo", "Hangul_Jamo"), ("jamoexta", "Hangul_Jamo_Extended_A"),
+  ("jamoextb", "Hangul_Jamo_Extended_B"), ("javanese", "Javanese"),
+  ("kaithi", "Kaithi"), ("kanaexta", "Kana_Extended_A"),
+  ("kanaextendeda", "Kana_Extended_A"), ("kanasup", "Kana_Supplement"),
+  ("kanasupplement", "Kana_Supplement"), ("kanbun", "Kanbun"),
+  ("kangxi", "Kangxi_Radicals"), ("kangxiradicals", "Kangxi_Radicals"),
+  ("kannada", "Kannada"), ("katakana", "Katakana"),
+  ("katakanaext", "Katakana_Phonetic_Extensions"),
+  ("katakanaphoneticextensions", "Katakana_Phonetic_Extensions"),
+  ("kayahli", "Kayah_Li"), ("kharoshthi", "Kharoshthi"), ("khmer", "Khmer"),
+  ("khmersymbols", "Khmer_Symbols"), ("khojki", "Khojki"),
+  ("khudawadi", "Khudawadi"), ("lao", "Lao"),
+  ("latin1", "Latin_1_Supplement"), ("latin1sup", "Latin_1_Supplement"),
+  ("latin1supplement", "Latin_1_Supplement"),
+  ("latinexta", "Latin_Extended_A"),
+  ("latinextadditional", "Latin_Extended_Additional"),
+  ("latinextb", "Latin_Extended_B"), ("latinextc", "Latin_Extended_C"),
+  ("latinextd", "Latin_Extended_D"), ("latinexte", "Latin_Extended_E"),
+  ("latinextendeda", "Latin_Extended_A"),
+  ("latinextendedadditional", "Latin_Extended_Additional"),
+  ("latinextendedb", "Latin_Extended_B"),
+  ("latinextendedc", "Latin_Extended_C"),
+  ("latinextendedd", "Latin_Extended_D"),
+  ("latinextendede", "Latin_Extended_E"), ("lepcha", "Lepcha"),
+  ("letterlikesymbols", "Letterlike_Symbols"), ("limbu", "Limbu"),
+  ("lineara", "Linear_A"), ("linearbideograms", "Linear_B_Ideograms"),
+  ("linearbsyllabary", "Linear_B_Syllabary"), ("lisu", "Lisu"),
+  ("lowsurrogates", "Low_Surrogates"), ("lycian", "Lycian"),
+  ("lydian", "Lydian"), ("mahajani", "Mahajani"),
+  ("mahjong", "Mahjong_Tiles"), ("mahjongtiles", "Mahjong_Tiles"),
+  ("malayalam", "Malayalam"), ("mandaic", "Mandaic"),
+  ("manichaean", "Manichaean"), ("marchen", "Marchen"),
+  ("masaramgondi", "Masaram_Gondi"),
+  ("mathalphanum", "Mathematical_Alphanumeric_Symbols"),
+  ("mathematicalalphanumericsymbols", "Mathematical_Alphanumeric_Symbols"),
+  ("mathematicaloperators", "Mathematical_Operators"),
+  ("mathoperators", "Mathematical_Operators"),
+  ("meeteimayek", "Meetei_Mayek"),
+  ("meeteimayekext", "Meetei_Mayek_Extensions"),
+  ("meeteimayekextensions", "Meetei_Mayek_Extensions"),
+  ("mendekikakui", "Mende_Kikakui"), ("meroiticcursive", "Meroitic_Cursive"),
+  ("meroitichieroglyphs", "Meroitic_Hieroglyphs"), ("miao", "Miao"),
+  ("miscarrows", "Miscellaneous_Symbols_And_Arrows"),
+  ("miscellaneousmathematicalsymbolsa", "Miscellaneous_Mathematical_Symbols_A"),
+  ("miscellaneousmathematicalsymbolsb", "Miscellaneous_Mathematical_Symbols_B"),
+  ("miscellaneoussymbols", "Miscellaneous_Symbols"),
+  ("miscellaneoussymbolsandarrows", "Miscellaneous_Symbols_And_Arrows"),
+  ("miscellaneoussymbolsandpictographs", "Miscellaneous_Symbols_And_Pictographs"),
+  ("miscellaneoustechnical", "Miscellaneous_Technical"),
+  ("miscmathsymbolsa", "Miscellaneous_Mathematical_Symbols_A"),
+  ("miscmathsymbolsb", "Miscellaneous_Mathematical_Symbols_B"),
+  ("miscpictographs", "Miscellaneous_Symbols_And_Pictographs"),
+  ("miscsymbols", "Miscellaneous_Symbols"),
+  ("misctechnical", "Miscellaneous_Technical"), ("modi", "Modi"),
+  ("modifierletters", "Spacing_Modifier_Letters"),
+  ("modifiertoneletters", "Modifier_Tone_Letters"),
+  ("mongolian", "Mongolian"), ("mongoliansup", "Mongolian_Supplement"),
+  ("mongoliansupplement", "Mongolian_Supplement"), ("mro", "Mro"),
+  ("multani", "Multani"), ("music", "Musical_Symbols"),
+  ("musicalsymbols", "Musical_Symbols"), ("myanmar", "Myanmar"),
+  ("myanmarexta", "Myanmar_Extended_A"),
+  ("myanmarextb", "Myanmar_Extended_B"),
+  ("myanmarextendeda", "Myanmar_Extended_A"),
+  ("myanmarextendedb", "Myanmar_Extended_B"), ("nabataean", "Nabataean"),
+  ("nb", "No_Block"), ("newa", "Newa"), ("newtailue", "New_Tai_Lue"),
+  ("nko", "NKo"), ("noblock", "No_Block"), ("numberforms", "Number_Forms"),
+  ("nushu", "Nushu"), ("ocr", "Optical_Character_Recognition"),
+  ("ogham", "Ogham"), ("olchiki", "Ol_Chiki"),
+  ("oldhungarian", "Old_Hungarian"), ("olditalic", "Old_Italic"),
+  ("oldnortharabian", "Old_North_Arabian"), ("oldpermic", "Old_Permic"),
+  ("oldpersian", "Old_Persian"), ("oldsoutharabian", "Old_South_Arabian"),
+  ("oldturkic", "Old_Turkic"),
+  ("opticalcharacterrecognition", "Optical_Character_Recognition"),
+  ("oriya", "Oriya"), ("ornamentaldingbats", "Ornamental_Dingbats"),
+  ("osage", "Osage"), ("osmanya", "Osmanya"), ("pahawhhmong", "Pahawh_Hmong"),
+  ("palmyrene", "Palmyrene"), ("paucinhau", "Pau_Cin_Hau"),
+  ("phagspa", "Phags_Pa"), ("phaistos", "Phaistos_Disc"),
+  ("phaistosdisc", "Phaistos_Disc"), ("phoenician", "Phoenician"),
+  ("phoneticext", "Phonetic_Extensions"),
+  ("phoneticextensions", "Phonetic_Extensions"),
+  ("phoneticextensionssupplement", "Phonetic_Extensions_Supplement"),
+  ("phoneticextsup", "Phonetic_Extensions_Supplement"),
+  ("playingcards", "Playing_Cards"), ("privateuse", "Private_Use_Area"),
+  ("privateusearea", "Private_Use_Area"),
+  ("psalterpahlavi", "Psalter_Pahlavi"), ("pua", "Private_Use_Area"),
+  ("punctuation", "General_Punctuation"), ("rejang", "Rejang"),
+  ("rumi", "Rumi_Numeral_Symbols"),
+  ("ruminumeralsymbols", "Rumi_Numeral_Symbols"), ("runic", "Runic"),
+  ("samaritan", "Samaritan"), ("saurashtra", "Saurashtra"),
+  ("sharada", "Sharada"), ("shavian", "Shavian"),
+  ("shorthandformatcontrols", "Shorthand_Format_Controls"),
+  ("siddham", "Siddham"), ("sinhala", "Sinhala"),
+  ("sinhalaarchaicnumbers", "Sinhala_Archaic_Numbers"),
+  ("smallforms", "Small_Form_Variants"),
+  ("smallformvariants", "Small_Form_Variants"),
+  ("sorasompeng", "Sora_Sompeng"), ("soyombo", "Soyombo"),
+  ("spacingmodifierletters", "Spacing_Modifier_Letters"),
+  ("specials", "Specials"), ("sundanese", "Sundanese"),
+  ("sundanesesup", "Sundanese_Supplement"),
+  ("sundanesesupplement", "Sundanese_Supplement"),
+  ("suparrowsa", "Supplemental_Arrows_A"),
+  ("suparrowsb", "Supplemental_Arrows_B"),
+  ("suparrowsc", "Supplemental_Arrows_C"),
+  ("superandsub", "Superscripts_And_Subscripts"),
+  ("superscriptsandsubscripts", "Superscripts_And_Subscripts"),
+  ("supmathoperators", "Supplemental_Mathematical_Operators"),
+  ("supplementalarrowsa", "Supplemental_Arrows_A"),
+  ("supplementalarrowsb", "Supplemental_Arrows_B"),
+  ("supplementalarrowsc", "Supplemental_Arrows_C"),
+  ("supplementalmathematicaloperators", "Supplemental_Mathematical_Operators"),
+  ("supplementalpunctuation", "Supplemental_Punctuation"),
+  ("supplementalsymbolsandpictographs", "Supplemental_Symbols_And_Pictographs"),
+  ("supplementaryprivateuseareaa", "Supplementary_Private_Use_Area_A"),
+  ("supplementaryprivateuseareab", "Supplementary_Private_Use_Area_B"),
+  ("suppuaa", "Supplementary_Private_Use_Area_A"),
+  ("suppuab", "Supplementary_Private_Use_Area_B"),
+  ("suppunctuation", "Supplemental_Punctuation"),
+  ("supsymbolsandpictographs", "Supplemental_Symbols_And_Pictographs"),
+  ("suttonsignwriting", "Sutton_SignWriting"),
+  ("sylotinagri", "Syloti_Nagri"), ("syriac", "Syriac"),
+  ("syriacsup", "Syriac_Supplement"),
+  ("syriacsupplement", "Syriac_Supplement"), ("tagalog", "Tagalog"),
+  ("tagbanwa", "Tagbanwa"), ("tags", "Tags"), ("taile", "Tai_Le"),
+  ("taitham", "Tai_Tham"), ("taiviet", "Tai_Viet"),
+  ("taixuanjing", "Tai_Xuan_Jing_Symbols"),
+  ("taixuanjingsymbols", "Tai_Xuan_Jing_Symbols"), ("takri", "Takri"),
+  ("tamil", "Tamil"), ("tangut", "Tangut"),
+  ("tangutcomponents", "Tangut_Components"), ("telugu", "Telugu"),
+  ("thaana", "Thaana"), ("thai", "Thai"), ("tibetan", "Tibetan"),
+  ("tifinagh", "Tifinagh"), ("tirhuta", "Tirhuta"),
+  ("transportandmap", "Transport_And_Map_Symbols"),
+  ("transportandmapsymbols", "Transport_And_Map_Symbols"),
+  ("ucas", "Unified_Canadian_Aboriginal_Syllabics"),
+  ("ucasext", "Unified_Canadian_Aboriginal_Syllabics_Extended"),
+  ("ugaritic", "Ugaritic"),
+  ("unifiedcanadianaboriginalsyllabics", "Unified_Canadian_Aboriginal_Syllabics"),
+  ("unifiedcanadianaboriginalsyllabicsextended", "Unified_Canadian_Aboriginal_Syllabics_Extended"),
+  ("vai", "Vai"), ("variationselectors", "Variation_Selectors"),
+  ("variationselectorssupplement", "Variation_Selectors_Supplement"),
+  ("vedicext", "Vedic_Extensions"), ("vedicextensions", "Vedic_Extensions"),
+  ("verticalforms", "Vertical_Forms"), ("vs", "Variation_Selectors"),
+  ("vssup", "Variation_Selectors_Supplement"), ("warangciti", "Warang_Citi"),
+  ("yijing", "Yijing_Hexagram_Symbols"),
+  ("yijinghexagramsymbols", "Yijing_Hexagram_Symbols"),
+  ("yiradicals", "Yi_Radicals"), ("yisyllables", "Yi_Syllables"),
+  ("zanabazarsquare", "Zanabazar_Square"), ]),
+
+  ("Canonical_Combining_Class", &[("", "Iota_Subscript"),
+  ("0", "Not_Reordered"), ("1", "Overlay"), ("10", "CCC10"),
+  ("103", "CCC103"), ("107", "CCC107"), ("11", "CCC11"), ("118", "CCC118"),
+  ("12", "CCC12"), ("122", "CCC122"), ("129", "CCC129"), ("13", "CCC13"),
+  ("130", "CCC130"), ("132", "CCC132"), ("133", "CCC133"), ("14", "CCC14"),
+  ("15", "CCC15"), ("16", "CCC16"), ("17", "CCC17"), ("18", "CCC18"),
+  ("19", "CCC19"), ("20", "CCC20"), ("200", "Attached_Below_Left"),
+  ("202", "Attached_Below"), ("21", "CCC21"), ("214", "Attached_Above"),
+  ("216", "Attached_Above_Right"), ("218", "Below_Left"), ("22", "CCC22"),
+  ("220", "Below"), ("222", "Below_Right"), ("224", "Left"), ("226", "Right"),
+  ("228", "Above_Left"), ("23", "CCC23"), ("230", "Above"),
+  ("232", "Above_Right"), ("233", "Double_Below"), ("234", "Double_Above"),
+  ("24", "CCC24"), ("240", "Iota_Subscript"), ("25", "CCC25"),
+  ("26", "CCC26"), ("27", "CCC27"), ("28", "CCC28"), ("29", "CCC29"),
+  ("30", "CCC30"), ("31", "CCC31"), ("32", "CCC32"), ("33", "CCC33"),
+  ("34", "CCC34"), ("35", "CCC35"), ("36", "CCC36"), ("7", "Nukta"),
+  ("8", "Kana_Voicing"), ("84", "CCC84"), ("9", "Virama"), ("91", "CCC91"),
+  ("a", "Above"), ("above", "Above"), ("aboveleft", "Above_Left"),
+  ("aboveright", "Above_Right"), ("al", "Above_Left"), ("ar", "Above_Right"),
+  ("ata", "Attached_Above"), ("atar", "Attached_Above_Right"),
+  ("atb", "Attached_Below"), ("atbl", "Attached_Below_Left"),
+  ("attachedabove", "Attached_Above"),
+  ("attachedaboveright", "Attached_Above_Right"),
+  ("attachedbelow", "Attached_Below"),
+  ("attachedbelowleft", "Attached_Below_Left"), ("b", "Below"),
+  ("below", "Below"), ("belowleft", "Below_Left"),
+  ("belowright", "Below_Right"), ("bl", "Below_Left"), ("br", "Below_Right"),
+  ("ccc10", "CCC10"), ("ccc103", "CCC103"), ("ccc107", "CCC107"),
+  ("ccc11", "CCC11"), ("ccc118", "CCC118"), ("ccc12", "CCC12"),
+  ("ccc122", "CCC122"), ("ccc129", "CCC129"), ("ccc13", "CCC13"),
+  ("ccc130", "CCC130"), ("ccc132", "CCC132"), ("ccc133", "CCC133"),
+  ("ccc14", "CCC14"), ("ccc15", "CCC15"), ("ccc16", "CCC16"),
+  ("ccc17", "CCC17"), ("ccc18", "CCC18"), ("ccc19", "CCC19"),
+  ("ccc20", "CCC20"), ("ccc21", "CCC21"), ("ccc22", "CCC22"),
+  ("ccc23", "CCC23"), ("ccc24", "CCC24"), ("ccc25", "CCC25"),
+  ("ccc26", "CCC26"), ("ccc27", "CCC27"), ("ccc28", "CCC28"),
+  ("ccc29", "CCC29"), ("ccc30", "CCC30"), ("ccc31", "CCC31"),
+  ("ccc32", "CCC32"), ("ccc33", "CCC33"), ("ccc34", "CCC34"),
+  ("ccc35", "CCC35"), ("ccc36", "CCC36"), ("ccc84", "CCC84"),
+  ("ccc91", "CCC91"), ("da", "Double_Above"), ("db", "Double_Below"),
+  ("doubleabove", "Double_Above"), ("doublebelow", "Double_Below"),
+  ("iotasubscript", "Iota_Subscript"), ("kanavoicing", "Kana_Voicing"),
+  ("kv", "Kana_Voicing"), ("l", "Left"), ("left", "Left"), ("nk", "Nukta"),
+  ("notreordered", "Not_Reordered"), ("nr", "Not_Reordered"),
+  ("nukta", "Nukta"), ("ov", "Overlay"), ("overlay", "Overlay"),
+  ("r", "Right"), ("right", "Right"), ("virama", "Virama"), ("vr", "Virama"),
+  ]),
+
+  ("Case_Ignorable", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Cased", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Changes_When_Casefolded", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Changes_When_Casemapped", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Changes_When_Lowercased", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Changes_When_NFKC_Casefolded", &[("f", "No"), ("false", "No"),
+  ("n", "No"), ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("Changes_When_Titlecased", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Changes_When_Uppercased", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Composition_Exclusion", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Dash", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Decomposition_Type", &[("can", "Canonical"), ("canonical", "Canonical"),
+  ("circle", "Circle"), ("com", "Compat"), ("compat", "Compat"),
+  ("enc", "Circle"), ("fin", "Final"), ("final", "Final"), ("font", "Font"),
+  ("fra", "Fraction"), ("fraction", "Fraction"), ("init", "Initial"),
+  ("initial", "Initial"), ("med", "Medial"), ("medial", "Medial"),
+  ("nar", "Narrow"), ("narrow", "Narrow"), ("nb", "Nobreak"),
+  ("nobreak", "Nobreak"), ("none", "None"), ("o", "Isolated"),
+  ("olated", "Isolated"), ("small", "Small"), ("sml", "Small"),
+  ("sqr", "Square"), ("square", "Square"), ("sub", "Sub"), ("sup", "Super"),
+  ("super", "Super"), ("vert", "Vertical"), ("vertical", "Vertical"),
+  ("wide", "Wide"), ]),
+
+  ("Default_Ignorable_Code_Point", &[("f", "No"), ("false", "No"),
+  ("n", "No"), ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("Deprecated", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Diacritic", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("East_Asian_Width", &[("a", "Ambiguous"), ("ambiguous", "Ambiguous"),
+  ("f", "Fullwidth"), ("fullwidth", "Fullwidth"), ("h", "Halfwidth"),
+  ("halfwidth", "Halfwidth"), ("n", "Neutral"), ("na", "Narrow"),
+  ("narrow", "Narrow"), ("neutral", "Neutral"), ("w", "Wide"),
+  ("wide", "Wide"), ]),
+
+  ("Expands_On_NFC", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Expands_On_NFD", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Expands_On_NFKC", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Expands_On_NFKD", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Extender", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Full_Composition_Exclusion", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("General_Category", &[("c", "Other"), ("casedletter", "Cased_Letter"),
+  ("cc", "Control"), ("cf", "Format"),
+  ("closepunctuation", "Close_Punctuation"), ("cn", "Unassigned"),
+  ("cntrl", "Control"), ("co", "Private_Use"), ("combiningmark", "Mark"),
+  ("connectorpunctuation", "Connector_Punctuation"), ("control", "Control"),
+  ("cs", "Surrogate"), ("currencysymbol", "Currency_Symbol"),
+  ("dashpunctuation", "Dash_Punctuation"),
+  ("decimalnumber", "Decimal_Number"), ("digit", "Decimal_Number"),
+  ("enclosingmark", "Enclosing_Mark"),
+  ("finalpunctuation", "Final_Punctuation"), ("format", "Format"),
+  ("initialpunctuation", "Initial_Punctuation"), ("l", "Letter"),
+  ("lc", "Cased_Letter"), ("letter", "Letter"),
+  ("letternumber", "Letter_Number"), ("lineseparator", "Line_Separator"),
+  ("ll", "Lowercase_Letter"), ("lm", "Modifier_Letter"),
+  ("lo", "Other_Letter"), ("lowercaseletter", "Lowercase_Letter"),
+  ("lt", "Titlecase_Letter"), ("lu", "Uppercase_Letter"), ("m", "Mark"),
+  ("mark", "Mark"), ("mathsymbol", "Math_Symbol"), ("mc", "Spacing_Mark"),
+  ("me", "Enclosing_Mark"), ("mn", "Nonspacing_Mark"),
+  ("modifierletter", "Modifier_Letter"),
+  ("modifiersymbol", "Modifier_Symbol"), ("n", "Number"),
+  ("nd", "Decimal_Number"), ("nl", "Letter_Number"), ("no", "Other_Number"),
+  ("nonspacingmark", "Nonspacing_Mark"), ("number", "Number"),
+  ("openpunctuation", "Open_Punctuation"), ("other", "Other"),
+  ("otherletter", "Other_Letter"), ("othernumber", "Other_Number"),
+  ("otherpunctuation", "Other_Punctuation"), ("othersymbol", "Other_Symbol"),
+  ("p", "Punctuation"), ("paragraphseparator", "Paragraph_Separator"),
+  ("pc", "Connector_Punctuation"), ("pd", "Dash_Punctuation"),
+  ("pe", "Close_Punctuation"), ("pf", "Final_Punctuation"),
+  ("pi", "Initial_Punctuation"), ("po", "Other_Punctuation"),
+  ("privateuse", "Private_Use"), ("ps", "Open_Punctuation"),
+  ("punct", "Punctuation"), ("punctuation", "Punctuation"), ("s", "Symbol"),
+  ("sc", "Currency_Symbol"), ("separator", "Separator"),
+  ("sk", "Modifier_Symbol"), ("sm", "Math_Symbol"), ("so", "Other_Symbol"),
+  ("spaceseparator", "Space_Separator"), ("spacingmark", "Spacing_Mark"),
+  ("surrogate", "Surrogate"), ("symbol", "Symbol"),
+  ("titlecaseletter", "Titlecase_Letter"), ("unassigned", "Unassigned"),
+  ("uppercaseletter", "Uppercase_Letter"), ("z", "Separator"),
+  ("zl", "Line_Separator"), ("zp", "Paragraph_Separator"),
+  ("zs", "Space_Separator"), ]),
+
+  ("Grapheme_Base", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Grapheme_Cluster_Break", &[("cn", "Control"), ("control", "Control"),
+  ("cr", "CR"), ("eb", "E_Base"), ("ebase", "E_Base"),
+  ("ebasegaz", "E_Base_GAZ"), ("ebg", "E_Base_GAZ"), ("em", "E_Modifier"),
+  ("emodifier", "E_Modifier"), ("ex", "Extend"), ("extend", "Extend"),
+  ("gaz", "Glue_After_Zwj"), ("glueafterzwj", "Glue_After_Zwj"), ("l", "L"),
+  ("lf", "LF"), ("lv", "LV"), ("lvt", "LVT"), ("other", "Other"),
+  ("pp", "Prepend"), ("prepend", "Prepend"),
+  ("regionalindicator", "Regional_Indicator"), ("ri", "Regional_Indicator"),
+  ("sm", "SpacingMark"), ("spacingmark", "SpacingMark"), ("t", "T"),
+  ("v", "V"), ("xx", "Other"), ("zwj", "ZWJ"), ]),
+
+  ("Grapheme_Extend", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Grapheme_Link", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Hangul_Syllable_Type", &[("l", "Leading_Jamo"),
+  ("leadingjamo", "Leading_Jamo"), ("lv", "LV_Syllable"),
+  ("lvsyllable", "LV_Syllable"), ("lvt", "LVT_Syllable"),
+  ("lvtsyllable", "LVT_Syllable"), ("na", "Not_Applicable"),
+  ("notapplicable", "Not_Applicable"), ("t", "Trailing_Jamo"),
+  ("trailingjamo", "Trailing_Jamo"), ("v", "Vowel_Jamo"),
+  ("voweljamo", "Vowel_Jamo"), ]),
+
+  ("Hex_Digit", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Hyphen", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("IDS_Binary_Operator", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("IDS_Trinary_Operator", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("ID_Continue", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("ID_Start", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Ideographic", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Indic_Positional_Category", &[("bottom", "Bottom"),
+  ("bottomandleft", "Bottom_And_Left"),
+  ("bottomandright", "Bottom_And_Right"), ("left", "Left"),
+  ("leftandright", "Left_And_Right"), ("na", "NA"),
+  ("overstruck", "Overstruck"), ("right", "Right"), ("top", "Top"),
+  ("topandbottom", "Top_And_Bottom"),
+  ("topandbottomandright", "Top_And_Bottom_And_Right"),
+  ("topandleft", "Top_And_Left"),
+  ("topandleftandright", "Top_And_Left_And_Right"),
+  ("topandright", "Top_And_Right"), ("visualorderleft", "Visual_Order_Left"),
+  ]),
+
+  ("Indic_Syllabic_Category", &[("avagraha", "Avagraha"), ("bindu", "Bindu"),
+  ("brahmijoiningnumber", "Brahmi_Joining_Number"),
+  ("cantillationmark", "Cantillation_Mark"), ("consonant", "Consonant"),
+  ("consonantdead", "Consonant_Dead"), ("consonantfinal", "Consonant_Final"),
+  ("consonantheadletter", "Consonant_Head_Letter"),
+  ("consonantkiller", "Consonant_Killer"),
+  ("consonantmedial", "Consonant_Medial"),
+  ("consonantplaceholder", "Consonant_Placeholder"),
+  ("consonantprecedingrepha", "Consonant_Preceding_Repha"),
+  ("consonantprefixed", "Consonant_Prefixed"),
+  ("consonantsubjoined", "Consonant_Subjoined"),
+  ("consonantsucceedingrepha", "Consonant_Succeeding_Repha"),
+  ("consonantwithstacker", "Consonant_With_Stacker"),
+  ("geminationmark", "Gemination_Mark"),
+  ("invisiblestacker", "Invisible_Stacker"), ("joiner", "Joiner"),
+  ("modifyingletter", "Modifying_Letter"), ("nonjoiner", "Non_Joiner"),
+  ("nukta", "Nukta"), ("number", "Number"), ("numberjoiner", "Number_Joiner"),
+  ("other", "Other"), ("purekiller", "Pure_Killer"),
+  ("registershifter", "Register_Shifter"),
+  ("syllablemodifier", "Syllable_Modifier"), ("toneletter", "Tone_Letter"),
+  ("tonemark", "Tone_Mark"), ("virama", "Virama"), ("visarga", "Visarga"),
+  ("vowel", "Vowel"), ("voweldependent", "Vowel_Dependent"),
+  ("vowelindependent", "Vowel_Independent"), ]),
+
+  ("Jamo_Short_Name", &[("a", "A"), ("ae", "AE"), ("b", "B"), ("bb", "BB"),
+  ("bs", "BS"), ("c", "C"), ("d", "D"), ("dd", "DD"), ("e", "E"),
+  ("eo", "EO"), ("eu", "EU"), ("g", "G"), ("gg", "GG"), ("gs", "GS"),
+  ("h", "H"), ("i", "I"), ("j", "J"), ("jj", "JJ"), ("k", "K"), ("l", "L"),
+  ("lb", "LB"), ("lg", "LG"), ("lh", "LH"), ("lm", "LM"), ("lp", "LP"),
+  ("ls", "LS"), ("lt", "LT"), ("m", "M"), ("n", "N"), ("ng", "NG"),
+  ("nh", "NH"), ("nj", "NJ"), ("o", "O"), ("oe", "OE"), ("p", "P"),
+  ("r", "R"), ("s", "S"), ("ss", "SS"), ("t", "T"), ("u", "U"), ("wa", "WA"),
+  ("wae", "WAE"), ("we", "WE"), ("weo", "WEO"), ("wi", "WI"), ("ya", "YA"),
+  ("yae", "YAE"), ("ye", "YE"), ("yeo", "YEO"), ("yi", "YI"), ("yo", "YO"),
+  ("yu", "YU"), ]),
+
+  ("Join_Control", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Joining_Group", &[("africanfeh", "African_Feh"),
+  ("africannoon", "African_Noon"), ("africanqaf", "African_Qaf"),
+  ("ain", "Ain"), ("alaph", "Alaph"), ("alef", "Alef"), ("beh", "Beh"),
+  ("beth", "Beth"), ("burushaskiyehbarree", "Burushaski_Yeh_Barree"),
+  ("dal", "Dal"), ("dalathrish", "Dalath_Rish"), ("e", "E"),
+  ("farsiyeh", "Farsi_Yeh"), ("fe", "Fe"), ("feh", "Feh"),
+  ("finalsemkath", "Final_Semkath"), ("gaf", "Gaf"), ("gamal", "Gamal"),
+  ("hah", "Hah"), ("hamzaonhehgoal", "Hamza_On_Heh_Goal"), ("he", "He"),
+  ("heh", "Heh"), ("hehgoal", "Heh_Goal"), ("heth", "Heth"), ("kaf", "Kaf"),
+  ("kaph", "Kaph"), ("khaph", "Khaph"), ("knottedheh", "Knotted_Heh"),
+  ("lam", "Lam"), ("lamadh", "Lamadh"), ("malayalambha", "Malayalam_Bha"),
+  ("malayalamja", "Malayalam_Ja"), ("malayalamlla", "Malayalam_Lla"),
+  ("malayalamllla", "Malayalam_Llla"), ("malayalamnga", "Malayalam_Nga"),
+  ("malayalamnna", "Malayalam_Nna"), ("malayalamnnna", "Malayalam_Nnna"),
+  ("malayalamnya", "Malayalam_Nya"), ("malayalamra", "Malayalam_Ra"),
+  ("malayalamssa", "Malayalam_Ssa"), ("malayalamtta", "Malayalam_Tta"),
+  ("manichaeanaleph", "Manichaean_Aleph"),
+  ("manichaeanayin", "Manichaean_Ayin"),
+  ("manichaeanbeth", "Manichaean_Beth"),
+  ("manichaeandaleth", "Manichaean_Daleth"),
+  ("manichaeandhamedh", "Manichaean_Dhamedh"),
+  ("manichaeanfive", "Manichaean_Five"),
+  ("manichaeangimel", "Manichaean_Gimel"),
+  ("manichaeanheth", "Manichaean_Heth"),
+  ("manichaeanhundred", "Manichaean_Hundred"),
+  ("manichaeankaph", "Manichaean_Kaph"),
+  ("manichaeanlamedh", "Manichaean_Lamedh"),
+  ("manichaeanmem", "Manichaean_Mem"), ("manichaeannun", "Manichaean_Nun"),
+  ("manichaeanone", "Manichaean_One"), ("manichaeanpe", "Manichaean_Pe"),
+  ("manichaeanqoph", "Manichaean_Qoph"),
+  ("manichaeanresh", "Manichaean_Resh"),
+  ("manichaeansadhe", "Manichaean_Sadhe"),
+  ("manichaeansamekh", "Manichaean_Samekh"),
+  ("manichaeantaw", "Manichaean_Taw"), ("manichaeanten", "Manichaean_Ten"),
+  ("manichaeanteth", "Manichaean_Teth"),
+  ("manichaeanthamedh", "Manichaean_Thamedh"),
+  ("manichaeantwenty", "Manichaean_Twenty"),
+  ("manichaeanwaw", "Manichaean_Waw"), ("manichaeanyodh", "Manichaean_Yodh"),
+  ("manichaeanzayin", "Manichaean_Zayin"), ("meem", "Meem"), ("mim", "Mim"),
+  ("nojoininggroup", "No_Joining_Group"), ("noon", "Noon"), ("nun", "Nun"),
+  ("nya", "Nya"), ("pe", "Pe"), ("qaf", "Qaf"), ("qaph", "Qaph"),
+  ("reh", "Reh"), ("reversedpe", "Reversed_Pe"),
+  ("rohingyayeh", "Rohingya_Yeh"), ("sad", "Sad"), ("sadhe", "Sadhe"),
+  ("seen", "Seen"), ("semkath", "Semkath"), ("shin", "Shin"),
+  ("straightwaw", "Straight_Waw"), ("swashkaf", "Swash_Kaf"),
+  ("syriacwaw", "Syriac_Waw"), ("tah", "Tah"), ("taw", "Taw"),
+  ("tehmarbuta", "Teh_Marbuta"), ("tehmarbutagoal", "Hamza_On_Heh_Goal"),
+  ("teth", "Teth"), ("waw", "Waw"), ("yeh", "Yeh"),
+  ("yehbarree", "Yeh_Barree"), ("yehwithtail", "Yeh_With_Tail"),
+  ("yudh", "Yudh"), ("yudhhe", "Yudh_He"), ("zain", "Zain"),
+  ("zhain", "Zhain"), ]),
+
+  ("Joining_Type", &[("c", "Join_Causing"), ("d", "Dual_Joining"),
+  ("dualjoining", "Dual_Joining"), ("joincausing", "Join_Causing"),
+  ("l", "Left_Joining"), ("leftjoining", "Left_Joining"),
+  ("nonjoining", "Non_Joining"), ("r", "Right_Joining"),
+  ("rightjoining", "Right_Joining"), ("t", "Transparent"),
+  ("transparent", "Transparent"), ("u", "Non_Joining"), ]),
+
+  ("Line_Break", &[("", "Infix_Numeric"), ("ai", "Ambiguous"),
+  ("al", "Alphabetic"), ("alphabetic", "Alphabetic"),
+  ("ambiguous", "Ambiguous"), ("b2", "Break_Both"), ("ba", "Break_After"),
+  ("bb", "Break_Before"), ("bk", "Mandatory_Break"),
+  ("breakafter", "Break_After"), ("breakbefore", "Break_Before"),
+  ("breakboth", "Break_Both"), ("breaksymbols", "Break_Symbols"),
+  ("carriagereturn", "Carriage_Return"), ("cb", "Contingent_Break"),
+  ("cj", "Conditional_Japanese_Starter"), ("cl", "Close_Punctuation"),
+  ("closeparenthesis", "Close_Parenthesis"),
+  ("closepunctuation", "Close_Punctuation"), ("cm", "Combining_Mark"),
+  ("combiningmark", "Combining_Mark"), ("complexcontext", "Complex_Context"),
+  ("conditionaljapanesestarter", "Conditional_Japanese_Starter"),
+  ("contingentbreak", "Contingent_Break"), ("cp", "Close_Parenthesis"),
+  ("cr", "Carriage_Return"), ("eb", "E_Base"), ("ebase", "E_Base"),
+  ("em", "E_Modifier"), ("emodifier", "E_Modifier"), ("ex", "Exclamation"),
+  ("exclamation", "Exclamation"), ("gl", "Glue"), ("glue", "Glue"),
+  ("h2", "H2"), ("h3", "H3"), ("hebrewletter", "Hebrew_Letter"),
+  ("hl", "Hebrew_Letter"), ("hy", "Hyphen"), ("hyphen", "Hyphen"),
+  ("id", "Ideographic"), ("ideographic", "Ideographic"),
+  ("in", "Inseparable"), ("infixnumeric", "Infix_Numeric"),
+  ("inseparable", "Inseparable"), ("inseperable", "Inseparable"),
+  ("jl", "JL"), ("jt", "JT"), ("jv", "JV"), ("lf", "Line_Feed"),
+  ("linefeed", "Line_Feed"), ("mandatorybreak", "Mandatory_Break"),
+  ("nextline", "Next_Line"), ("nl", "Next_Line"),
+  ("nonstarter", "Nonstarter"), ("ns", "Nonstarter"), ("nu", "Numeric"),
+  ("numeric", "Numeric"), ("op", "Open_Punctuation"),
+  ("openpunctuation", "Open_Punctuation"), ("po", "Postfix_Numeric"),
+  ("postfixnumeric", "Postfix_Numeric"), ("pr", "Prefix_Numeric"),
+  ("prefixnumeric", "Prefix_Numeric"), ("qu", "Quotation"),
+  ("quotation", "Quotation"), ("regionalindicator", "Regional_Indicator"),
+  ("ri", "Regional_Indicator"), ("sa", "Complex_Context"),
+  ("sg", "Surrogate"), ("sp", "Space"), ("space", "Space"),
+  ("surrogate", "Surrogate"), ("sy", "Break_Symbols"), ("unknown", "Unknown"),
+  ("wj", "Word_Joiner"), ("wordjoiner", "Word_Joiner"), ("xx", "Unknown"),
+  ("zw", "ZWSpace"), ("zwj", "ZWJ"), ("zwspace", "ZWSpace"), ]),
+
+  ("Logical_Order_Exception", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Lowercase", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Math", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("NFC_Quick_Check", &[("m", "Maybe"), ("maybe", "Maybe"), ("n", "No"),
+  ("no", "No"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("NFD_Quick_Check", &[("n", "No"), ("no", "No"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("NFKC_Quick_Check", &[("m", "Maybe"), ("maybe", "Maybe"), ("n", "No"),
+  ("no", "No"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("NFKD_Quick_Check", &[("n", "No"), ("no", "No"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("Noncharacter_Code_Point", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Numeric_Type", &[("de", "Decimal"), ("decimal", "Decimal"),
+  ("di", "Digit"), ("digit", "Digit"), ("none", "None"), ("nu", "Numeric"),
+  ("numeric", "Numeric"), ]),
+
+  ("Other_Alphabetic", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Other_Default_Ignorable_Code_Point", &[("f", "No"), ("false", "No"),
+  ("n", "No"), ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("Other_Grapheme_Extend", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Other_ID_Continue", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Other_ID_Start", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Other_Lowercase", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Other_Math", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Other_Uppercase", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Pattern_Syntax", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Pattern_White_Space", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Prepended_Concatenation_Mark", &[("f", "No"), ("false", "No"),
+  ("n", "No"), ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"),
+  ("yes", "Yes"), ]),
+
+  ("Quotation_Mark", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Radical", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Regional_Indicator", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Script", &[("adlam", "Adlam"), ("adlm", "Adlam"),
+  ("aghb", "Caucasian_Albanian"), ("ahom", "Ahom"),
+  ("anatolianhieroglyphs", "Anatolian_Hieroglyphs"), ("arab", "Arabic"),
+  ("arabic", "Arabic"), ("armenian", "Armenian"),
+  ("armi", "Imperial_Aramaic"), ("armn", "Armenian"), ("avestan", "Avestan"),
+  ("avst", "Avestan"), ("bali", "Balinese"), ("balinese", "Balinese"),
+  ("bamu", "Bamum"), ("bamum", "Bamum"), ("bass", "Bassa_Vah"),
+  ("bassavah", "Bassa_Vah"), ("batak", "Batak"), ("batk", "Batak"),
+  ("beng", "Bengali"), ("bengali", "Bengali"), ("bhaiksuki", "Bhaiksuki"),
+  ("bhks", "Bhaiksuki"), ("bopo", "Bopomofo"), ("bopomofo", "Bopomofo"),
+  ("brah", "Brahmi"), ("brahmi", "Brahmi"), ("brai", "Braille"),
+  ("braille", "Braille"), ("bugi", "Buginese"), ("buginese", "Buginese"),
+  ("buhd", "Buhid"), ("buhid", "Buhid"), ("cakm", "Chakma"),
+  ("canadianaboriginal", "Canadian_Aboriginal"),
+  ("cans", "Canadian_Aboriginal"), ("cari", "Carian"), ("carian", "Carian"),
+  ("caucasianalbanian", "Caucasian_Albanian"), ("chakma", "Chakma"),
+  ("cham", "Cham"), ("cher", "Cherokee"), ("cherokee", "Cherokee"),
+  ("common", "Common"), ("copt", "Coptic"), ("coptic", "Coptic"),
+  ("cprt", "Cypriot"), ("cuneiform", "Cuneiform"), ("cypriot", "Cypriot"),
+  ("cyrillic", "Cyrillic"), ("cyrl", "Cyrillic"), ("deseret", "Deseret"),
+  ("deva", "Devanagari"), ("devanagari", "Devanagari"), ("dsrt", "Deseret"),
+  ("dupl", "Duployan"), ("duployan", "Duployan"),
+  ("egyp", "Egyptian_Hieroglyphs"),
+  ("egyptianhieroglyphs", "Egyptian_Hieroglyphs"), ("elba", "Elbasan"),
+  ("elbasan", "Elbasan"), ("ethi", "Ethiopic"), ("ethiopic", "Ethiopic"),
+  ("geor", "Georgian"), ("georgian", "Georgian"), ("glag", "Glagolitic"),
+  ("glagolitic", "Glagolitic"), ("gonm", "Masaram_Gondi"), ("goth", "Gothic"),
+  ("gothic", "Gothic"), ("gran", "Grantha"), ("grantha", "Grantha"),
+  ("greek", "Greek"), ("grek", "Greek"), ("gujarati", "Gujarati"),
+  ("gujr", "Gujarati"), ("gurmukhi", "Gurmukhi"), ("guru", "Gurmukhi"),
+  ("han", "Han"), ("hang", "Hangul"), ("hangul", "Hangul"), ("hani", "Han"),
+  ("hano", "Hanunoo"), ("hanunoo", "Hanunoo"), ("hatr", "Hatran"),
+  ("hatran", "Hatran"), ("hebr", "Hebrew"), ("hebrew", "Hebrew"),
+  ("hira", "Hiragana"), ("hiragana", "Hiragana"),
+  ("hluw", "Anatolian_Hieroglyphs"), ("hmng", "Pahawh_Hmong"),
+  ("hrkt", "Katakana_Or_Hiragana"), ("hung", "Old_Hungarian"),
+  ("imperialaramaic", "Imperial_Aramaic"), ("inherited", "Inherited"),
+  ("inscriptionalpahlavi", "Inscriptional_Pahlavi"),
+  ("inscriptionalparthian", "Inscriptional_Parthian"), ("ital", "Old_Italic"),
+  ("java", "Javanese"), ("javanese", "Javanese"), ("kaithi", "Kaithi"),
+  ("kali", "Kayah_Li"), ("kana", "Katakana"), ("kannada", "Kannada"),
+  ("katakana", "Katakana"), ("katakanaorhiragana", "Katakana_Or_Hiragana"),
+  ("kayahli", "Kayah_Li"), ("khar", "Kharoshthi"),
+  ("kharoshthi", "Kharoshthi"), ("khmer", "Khmer"), ("khmr", "Khmer"),
+  ("khoj", "Khojki"), ("khojki", "Khojki"), ("khudawadi", "Khudawadi"),
+  ("knda", "Kannada"), ("kthi", "Kaithi"), ("lana", "Tai_Tham"),
+  ("lao", "Lao"), ("laoo", "Lao"), ("latin", "Latin"), ("latn", "Latin"),
+  ("lepc", "Lepcha"), ("lepcha", "Lepcha"), ("limb", "Limbu"),
+  ("limbu", "Limbu"), ("lina", "Linear_A"), ("linb", "Linear_B"),
+  ("lineara", "Linear_A"), ("linearb", "Linear_B"), ("lisu", "Lisu"),
+  ("lyci", "Lycian"), ("lycian", "Lycian"), ("lydi", "Lydian"),
+  ("lydian", "Lydian"), ("mahajani", "Mahajani"), ("mahj", "Mahajani"),
+  ("malayalam", "Malayalam"), ("mand", "Mandaic"), ("mandaic", "Mandaic"),
+  ("mani", "Manichaean"), ("manichaean", "Manichaean"), ("marc", "Marchen"),
+  ("marchen", "Marchen"), ("masaramgondi", "Masaram_Gondi"),
+  ("meeteimayek", "Meetei_Mayek"), ("mend", "Mende_Kikakui"),
+  ("mendekikakui", "Mende_Kikakui"), ("merc", "Meroitic_Cursive"),
+  ("mero", "Meroitic_Hieroglyphs"), ("meroiticcursive", "Meroitic_Cursive"),
+  ("meroitichieroglyphs", "Meroitic_Hieroglyphs"), ("miao", "Miao"),
+  ("mlym", "Malayalam"), ("modi", "Modi"), ("mong", "Mongolian"),
+  ("mongolian", "Mongolian"), ("mro", "Mro"), ("mroo", "Mro"),
+  ("mtei", "Meetei_Mayek"), ("mult", "Multani"), ("multani", "Multani"),
+  ("myanmar", "Myanmar"), ("mymr", "Myanmar"), ("nabataean", "Nabataean"),
+  ("narb", "Old_North_Arabian"), ("nbat", "Nabataean"), ("newa", "Newa"),
+  ("newtailue", "New_Tai_Lue"), ("nko", "Nko"), ("nkoo", "Nko"),
+  ("nshu", "Nushu"), ("nushu", "Nushu"), ("ogam", "Ogham"),
+  ("ogham", "Ogham"), ("olchiki", "Ol_Chiki"), ("olck", "Ol_Chiki"),
+  ("oldhungarian", "Old_Hungarian"), ("olditalic", "Old_Italic"),
+  ("oldnortharabian", "Old_North_Arabian"), ("oldpermic", "Old_Permic"),
+  ("oldpersian", "Old_Persian"), ("oldsoutharabian", "Old_South_Arabian"),
+  ("oldturkic", "Old_Turkic"), ("oriya", "Oriya"), ("orkh", "Old_Turkic"),
+  ("orya", "Oriya"), ("osage", "Osage"), ("osge", "Osage"),
+  ("osma", "Osmanya"), ("osmanya", "Osmanya"),
+  ("pahawhhmong", "Pahawh_Hmong"), ("palm", "Palmyrene"),
+  ("palmyrene", "Palmyrene"), ("pauc", "Pau_Cin_Hau"),
+  ("paucinhau", "Pau_Cin_Hau"), ("perm", "Old_Permic"), ("phag", "Phags_Pa"),
+  ("phagspa", "Phags_Pa"), ("phli", "Inscriptional_Pahlavi"),
+  ("phlp", "Psalter_Pahlavi"), ("phnx", "Phoenician"),
+  ("phoenician", "Phoenician"), ("plrd", "Miao"),
+  ("prti", "Inscriptional_Parthian"), ("psalterpahlavi", "Psalter_Pahlavi"),
+  ("qaac", "Coptic"), ("qaai", "Inherited"), ("rejang", "Rejang"),
+  ("rjng", "Rejang"), ("runic", "Runic"), ("runr", "Runic"),
+  ("samaritan", "Samaritan"), ("samr", "Samaritan"),
+  ("sarb", "Old_South_Arabian"), ("saur", "Saurashtra"),
+  ("saurashtra", "Saurashtra"), ("sgnw", "SignWriting"),
+  ("sharada", "Sharada"), ("shavian", "Shavian"), ("shaw", "Shavian"),
+  ("shrd", "Sharada"), ("sidd", "Siddham"), ("siddham", "Siddham"),
+  ("signwriting", "SignWriting"), ("sind", "Khudawadi"), ("sinh", "Sinhala"),
+  ("sinhala", "Sinhala"), ("sora", "Sora_Sompeng"),
+  ("sorasompeng", "Sora_Sompeng"), ("soyo", "Soyombo"),
+  ("soyombo", "Soyombo"), ("sund", "Sundanese"), ("sundanese", "Sundanese"),
+  ("sylo", "Syloti_Nagri"), ("sylotinagri", "Syloti_Nagri"),
+  ("syrc", "Syriac"), ("syriac", "Syriac"), ("tagalog", "Tagalog"),
+  ("tagb", "Tagbanwa"), ("tagbanwa", "Tagbanwa"), ("taile", "Tai_Le"),
+  ("taitham", "Tai_Tham"), ("taiviet", "Tai_Viet"), ("takr", "Takri"),
+  ("takri", "Takri"), ("tale", "Tai_Le"), ("talu", "New_Tai_Lue"),
+  ("tamil", "Tamil"), ("taml", "Tamil"), ("tang", "Tangut"),
+  ("tangut", "Tangut"), ("tavt", "Tai_Viet"), ("telu", "Telugu"),
+  ("telugu", "Telugu"), ("tfng", "Tifinagh"), ("tglg", "Tagalog"),
+  ("thaa", "Thaana"), ("thaana", "Thaana"), ("thai", "Thai"),
+  ("tibetan", "Tibetan"), ("tibt", "Tibetan"), ("tifinagh", "Tifinagh"),
+  ("tirh", "Tirhuta"), ("tirhuta", "Tirhuta"), ("ugar", "Ugaritic"),
+  ("ugaritic", "Ugaritic"), ("unknown", "Unknown"), ("vai", "Vai"),
+  ("vaii", "Vai"), ("wara", "Warang_Citi"), ("warangciti", "Warang_Citi"),
+  ("xpeo", "Old_Persian"), ("xsux", "Cuneiform"), ("yi", "Yi"),
+  ("yiii", "Yi"), ("zanabazarsquare", "Zanabazar_Square"),
+  ("zanb", "Zanabazar_Square"), ("zinh", "Inherited"), ("zyyy", "Common"),
+  ("zzzz", "Unknown"), ]),
+
+  ("Sentence_Break", &[("at", "ATerm"), ("aterm", "ATerm"), ("cl", "Close"),
+  ("close", "Close"), ("cr", "CR"), ("ex", "Extend"), ("extend", "Extend"),
+  ("fo", "Format"), ("format", "Format"), ("le", "OLetter"), ("lf", "LF"),
+  ("lo", "Lower"), ("lower", "Lower"), ("nu", "Numeric"),
+  ("numeric", "Numeric"), ("oletter", "OLetter"), ("other", "Other"),
+  ("sc", "SContinue"), ("scontinue", "SContinue"), ("se", "Sep"),
+  ("sep", "Sep"), ("sp", "Sp"), ("st", "STerm"), ("sterm", "STerm"),
+  ("up", "Upper"), ("upper", "Upper"), ("xx", "Other"), ]),
+
+  ("Sentence_Terminal", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Soft_Dotted", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Terminal_Punctuation", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Unified_Ideograph", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Uppercase", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Variation_Selector", &[("f", "No"), ("false", "No"), ("n", "No"),
+  ("no", "No"), ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"),
+  ]),
+
+  ("Vertical_Orientation", &[("r", "Rotated"), ("rotated", "Rotated"),
+  ("tr", "Transformed_Rotated"),
+  ("transformedrotated", "Transformed_Rotated"),
+  ("transformedupright", "Transformed_Upright"),
+  ("tu", "Transformed_Upright"), ("u", "Upright"), ("upright", "Upright"), ]),
+
+  ("White_Space", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("Word_Break", &[("aletter", "ALetter"), ("cr", "CR"),
+  ("doublequote", "Double_Quote"), ("dq", "Double_Quote"), ("eb", "E_Base"),
+  ("ebase", "E_Base"), ("ebasegaz", "E_Base_GAZ"), ("ebg", "E_Base_GAZ"),
+  ("em", "E_Modifier"), ("emodifier", "E_Modifier"), ("ex", "ExtendNumLet"),
+  ("extend", "Extend"), ("extendnumlet", "ExtendNumLet"), ("fo", "Format"),
+  ("format", "Format"), ("gaz", "Glue_After_Zwj"),
+  ("glueafterzwj", "Glue_After_Zwj"), ("hebrewletter", "Hebrew_Letter"),
+  ("hl", "Hebrew_Letter"), ("ka", "Katakana"), ("katakana", "Katakana"),
+  ("le", "ALetter"), ("lf", "LF"), ("mb", "MidNumLet"),
+  ("midletter", "MidLetter"), ("midnum", "MidNum"),
+  ("midnumlet", "MidNumLet"), ("ml", "MidLetter"), ("mn", "MidNum"),
+  ("newline", "Newline"), ("nl", "Newline"), ("nu", "Numeric"),
+  ("numeric", "Numeric"), ("other", "Other"),
+  ("regionalindicator", "Regional_Indicator"), ("ri", "Regional_Indicator"),
+  ("singlequote", "Single_Quote"), ("sq", "Single_Quote"), ("xx", "Other"),
+  ("zwj", "ZWJ"), ]),
+
+  ("XID_Continue", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+
+  ("XID_Start", &[("f", "No"), ("false", "No"), ("n", "No"), ("no", "No"),
+  ("t", "Yes"), ("true", "Yes"), ("y", "Yes"), ("yes", "Yes"), ]),
+];
diff --git a/third_party/rust/utf8-ranges/.cargo-checksum.json b/third_party/rust/utf8-ranges/.cargo-checksum.json
index 09bd77d893bb..9cbe2cff0426 100644
--- a/third_party/rust/utf8-ranges/.cargo-checksum.json
+++ b/third_party/rust/utf8-ranges/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{".travis.yml":"efb6a811205188b9caafb2500fc6ef00ae4ffae6798adbe316230797be51b168","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"2f28e69bcdd91620ffb72fb8f1bfe840e5c3fdcb2918abe1d73ca852d1f55f1b","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"98c7359c2b09f257411b32553c40254ef1df89d8b19cef6217dbb3c25dd3c6c7","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"584fefa78c1d0041e1eae4f04a7112864ddc4f39a62ce16e4de73c6df6857d66","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/char_utf8.rs":"e8125d4809fb94ac9ebc57bdf67b2dc61c9f356d76dc154576064937095e1915","src/lib.rs":"c1263642becda4bbbeaf2d29bcce6c934fc326d1c85593ab67886eeba392a001"},"package":"662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"}
\ No newline at end of file
+{"files":{".travis.yml":"84e5793f37584e4756d8e7ec5ad3eea9a4102e04dfcb4dac7da63526b819aa8f","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"c3a468466d4f24b2fb320e1c2679752384c61510daf629c03f92264cc91d5cb2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"98c7359c2b09f257411b32553c40254ef1df89d8b19cef6217dbb3c25dd3c6c7","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"584fefa78c1d0041e1eae4f04a7112864ddc4f39a62ce16e4de73c6df6857d66","ci/script.sh":"39091b4b5d9eb1a1380e74dec42bde4ed8d3c9f29203363f396110132f5a5e07","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/char_utf8.rs":"e8125d4809fb94ac9ebc57bdf67b2dc61c9f356d76dc154576064937095e1915","src/lib.rs":"c1263642becda4bbbeaf2d29bcce6c934fc326d1c85593ab67886eeba392a001"},"package":"fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"}
\ No newline at end of file
diff --git a/third_party/rust/utf8-ranges/.travis.yml b/third_party/rust/utf8-ranges/.travis.yml
index 747082b35bfe..6c50f816055c 100644
--- a/third_party/rust/utf8-ranges/.travis.yml
+++ b/third_party/rust/utf8-ranges/.travis.yml
@@ -1,10 +1,10 @@
 language: rust
 rust:
   - 1.12.0
   - stable
   - beta
   - nightly
-script:
-  - cargo build --verbose
-  - cargo test --verbose
-  - cargo doc
+script: ci/script.sh
+branches:
+  only:
+    - master
diff --git a/third_party/rust/utf8-ranges/Cargo.toml b/third_party/rust/utf8-ranges/Cargo.toml
index 750e096baa15..b591e6ef2e20 100644
--- a/third_party/rust/utf8-ranges/Cargo.toml
+++ b/third_party/rust/utf8-ranges/Cargo.toml
@@ -1,14 +1,28 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
 name = "utf8-ranges"
-version = "1.0.0"  #:version
+version = "1.0.1"
 authors = ["Andrew Gallant <jamslam@gmail.com>"]
 description = "Convert ranges of Unicode codepoints to UTF-8 byte ranges."
-documentation = "https://docs.rs/utf8-ranges"
 homepage = "https://github.com/BurntSushi/utf8-ranges"
-repository = "https://github.com/BurntSushi/utf8-ranges"
+documentation = "https://docs.rs/utf8-ranges"
 readme = "README.md"
 keywords = ["codepoint", "utf8", "automaton", "range"]
 license = "Unlicense/MIT"
-
-[dev-dependencies]
-quickcheck = "0.4.1"
+repository = "https://github.com/BurntSushi/utf8-ranges"
+[dev-dependencies.quickcheck]
+version = "0.7"
+default-features = false
+[badges.travis-ci]
+repository = "BurntSushi/utf8-ranges"
diff --git a/third_party/rust/utf8-ranges/ci/script.sh b/third_party/rust/utf8-ranges/ci/script.sh
new file mode 100755
index 000000000000..25a337b92ddd
--- /dev/null
+++ b/third_party/rust/utf8-ranges/ci/script.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+set -ex
+
+cargo build --verbose
+cargo doc --verbose
+
+# If we're testing on an older version of Rust, then only check that we
+# can build the crate. This is because the dev dependencies might be updated
+# more frequently, and therefore might require a newer version of Rust.
+#
+# This isn't ideal. It's a compromise.
+if [ "$TRAVIS_RUST_VERSION" = "1.12.0" ]; then
+  exit
+fi
+
+cargo test --verbose
-- 
2.17.1

