Bug 1437004 - Vendored Rust dependencies;r?froydnj draft
authorDavid Teller <dteller@mozilla.com>
Wed, 04 Apr 2018 14:14:26 +0200
changeset 777850 6a5a780276eea8db4592e846b1dace4dd9a927e3
parent 777744 6826688772807b9903c278a5d6b50c32f1561b32
child 777851 057da8c4199f92c52d4e950d9142a18a2a83d54b
push id105306
push userdteller@mozilla.com
push dateThu, 05 Apr 2018 12:07:57 +0000
reviewersfroydnj
bugs1437004
milestone61.0a1
Bug 1437004 - Vendored Rust dependencies;r?froydnj MozReview-Commit-ID: Grf1bKIx2iT
Cargo.lock
Cargo.toml
third_party/rust/Inflector/.cargo-checksum.json
third_party/rust/Inflector/CHANGELOG.md
third_party/rust/Inflector/CONTRIBUTING.md
third_party/rust/Inflector/Cargo.toml
third_party/rust/Inflector/LICENSE.md
third_party/rust/Inflector/PULL_REQUEST_TEMPLATE.md
third_party/rust/Inflector/README.md
third_party/rust/Inflector/benchmark
third_party/rust/Inflector/src/cases/camelcase/mod.rs
third_party/rust/Inflector/src/cases/case/mod.rs
third_party/rust/Inflector/src/cases/classcase/mod.rs
third_party/rust/Inflector/src/cases/kebabcase/mod.rs
third_party/rust/Inflector/src/cases/mod.rs
third_party/rust/Inflector/src/cases/pascalcase/mod.rs
third_party/rust/Inflector/src/cases/screamingsnakecase/mod.rs
third_party/rust/Inflector/src/cases/sentencecase/mod.rs
third_party/rust/Inflector/src/cases/snakecase/mod.rs
third_party/rust/Inflector/src/cases/tablecase/mod.rs
third_party/rust/Inflector/src/cases/titlecase/mod.rs
third_party/rust/Inflector/src/cases/traincase/mod.rs
third_party/rust/Inflector/src/lib.rs
third_party/rust/Inflector/src/numbers/deordinalize/mod.rs
third_party/rust/Inflector/src/numbers/mod.rs
third_party/rust/Inflector/src/numbers/ordinalize/mod.rs
third_party/rust/Inflector/src/string/constants/mod.rs
third_party/rust/Inflector/src/string/deconstantize/mod.rs
third_party/rust/Inflector/src/string/demodulize/mod.rs
third_party/rust/Inflector/src/string/mod.rs
third_party/rust/Inflector/src/string/pluralize/mod.rs
third_party/rust/Inflector/src/string/singularize/mod.rs
third_party/rust/Inflector/src/suffix/foreignkey/mod.rs
third_party/rust/Inflector/src/suffix/mod.rs
third_party/rust/Inflector/tests/lib.rs
third_party/rust/Inflector/travis-after-success.sh
third_party/rust/ascii-canvas/.cargo-checksum.json
third_party/rust/ascii-canvas/Cargo.toml
third_party/rust/ascii-canvas/LICENSE-APACHE
third_party/rust/ascii-canvas/LICENSE-MIT
third_party/rust/ascii-canvas/README.md
third_party/rust/ascii-canvas/src/lib.rs
third_party/rust/ascii-canvas/src/row.rs
third_party/rust/ascii-canvas/src/style.rs
third_party/rust/ascii-canvas/src/test.rs
third_party/rust/atty-0.1.2/.cargo-checksum.json
third_party/rust/atty-0.1.2/.travis.yml
third_party/rust/atty-0.1.2/CHANGELOG.md
third_party/rust/atty-0.1.2/Cargo.toml
third_party/rust/atty-0.1.2/LICENSE
third_party/rust/atty-0.1.2/README.md
third_party/rust/atty-0.1.2/appveyor.yml
third_party/rust/atty-0.1.2/src/lib.rs
third_party/rust/binjs_meta/.cargo-checksum.json
third_party/rust/binjs_meta/Cargo.toml
third_party/rust/binjs_meta/README.md
third_party/rust/binjs_meta/examples/generate_spidermonkey.rs
third_party/rust/binjs_meta/src/export.rs
third_party/rust/binjs_meta/src/import.rs
third_party/rust/binjs_meta/src/lib.rs
third_party/rust/binjs_meta/src/spec.rs
third_party/rust/binjs_meta/src/util.rs
third_party/rust/bit-set/.cargo-checksum.json
third_party/rust/bit-set/.travis.yml
third_party/rust/bit-set/Cargo.toml
third_party/rust/bit-set/LICENSE-APACHE
third_party/rust/bit-set/LICENSE-MIT
third_party/rust/bit-set/README.md
third_party/rust/bit-set/deploy-docs.sh
third_party/rust/bit-set/src/lib.rs
third_party/rust/bit-vec/.cargo-checksum.json
third_party/rust/bit-vec/.travis.yml
third_party/rust/bit-vec/Cargo.toml
third_party/rust/bit-vec/LICENSE-APACHE
third_party/rust/bit-vec/LICENSE-MIT
third_party/rust/bit-vec/README.md
third_party/rust/bit-vec/benches/extern.rs
third_party/rust/bit-vec/crusader.sh
third_party/rust/bit-vec/deploy-docs.sh
third_party/rust/bit-vec/src/bench.rs
third_party/rust/bit-vec/src/lib.rs
third_party/rust/diff/.cargo-checksum.json
third_party/rust/diff/.travis.yml
third_party/rust/diff/Cargo.toml
third_party/rust/diff/LICENSE-APACHE
third_party/rust/diff/LICENSE-MIT
third_party/rust/diff/README.md
third_party/rust/diff/benches/benches.rs
third_party/rust/diff/examples/simple.rs
third_party/rust/diff/src/lib.rs
third_party/rust/diff/tests/tests.rs
third_party/rust/docopt/.cargo-checksum.json
third_party/rust/docopt/.travis.yml
third_party/rust/docopt/COPYING
third_party/rust/docopt/Cargo.toml
third_party/rust/docopt/LICENSE-MIT
third_party/rust/docopt/Makefile
third_party/rust/docopt/README.md
third_party/rust/docopt/UNLICENSE
third_party/rust/docopt/completions/docopt-wordlist.bash
third_party/rust/docopt/ctags.rust
third_party/rust/docopt/examples/cargo.rs
third_party/rust/docopt/examples/cp.rs
third_party/rust/docopt/examples/decode.rs
third_party/rust/docopt/examples/hashmap.rs
third_party/rust/docopt/examples/optional_command.rs
third_party/rust/docopt/examples/verbose_multiple.rs
third_party/rust/docopt/scripts/mk-testcases
third_party/rust/docopt/session.vim
third_party/rust/docopt/src/dopt.rs
third_party/rust/docopt/src/lib.rs
third_party/rust/docopt/src/parse.rs
third_party/rust/docopt/src/synonym.rs
third_party/rust/docopt/src/test/mod.rs
third_party/rust/docopt/src/test/suggestions.rs
third_party/rust/docopt/src/test/testcases.docopt
third_party/rust/docopt/src/test/testcases.rs
third_party/rust/docopt/src/wordlist.rs
third_party/rust/ena/.cargo-checksum.json
third_party/rust/ena/.travis.yml
third_party/rust/ena/Cargo.toml
third_party/rust/ena/LICENSE-APACHE
third_party/rust/ena/LICENSE-MIT
third_party/rust/ena/README.md
third_party/rust/ena/measurements.txt
third_party/rust/ena/src/bitvec.rs
third_party/rust/ena/src/cc/mod.rs
third_party/rust/ena/src/cc/test.rs
third_party/rust/ena/src/constraint/mod.rs
third_party/rust/ena/src/constraint/test.rs
third_party/rust/ena/src/debug.rs
third_party/rust/ena/src/graph/mod.rs
third_party/rust/ena/src/graph/tests.rs
third_party/rust/ena/src/lib.rs
third_party/rust/ena/src/snapshot_vec.rs
third_party/rust/ena/src/unify/mod.rs
third_party/rust/ena/src/unify/tests.rs
third_party/rust/fixedbitset/.cargo-checksum.json
third_party/rust/fixedbitset/.travis.yml
third_party/rust/fixedbitset/Cargo.toml
third_party/rust/fixedbitset/LICENSE-APACHE
third_party/rust/fixedbitset/LICENSE-MIT
third_party/rust/fixedbitset/README.rst
third_party/rust/fixedbitset/benches/benches.rs
third_party/rust/fixedbitset/src/lib.rs
third_party/rust/fixedbitset/src/range.rs
third_party/rust/itertools-0.6.5/.cargo-checksum.json
third_party/rust/itertools-0.6.5/.travis.yml
third_party/rust/itertools-0.6.5/Cargo.toml
third_party/rust/itertools-0.6.5/LICENSE-APACHE
third_party/rust/itertools-0.6.5/LICENSE-MIT
third_party/rust/itertools-0.6.5/Makefile
third_party/rust/itertools-0.6.5/README.rst
third_party/rust/itertools-0.6.5/benches/bench1.rs
third_party/rust/itertools-0.6.5/benches/extra/mod.rs
third_party/rust/itertools-0.6.5/benches/extra/zipslices.rs
third_party/rust/itertools-0.6.5/benches/tuple_combinations.rs
third_party/rust/itertools-0.6.5/benches/tuples.rs
third_party/rust/itertools-0.6.5/custom.css
third_party/rust/itertools-0.6.5/examples/iris.data
third_party/rust/itertools-0.6.5/examples/iris.rs
third_party/rust/itertools-0.6.5/src/adaptors/mod.rs
third_party/rust/itertools-0.6.5/src/adaptors/multipeek.rs
third_party/rust/itertools-0.6.5/src/concat_impl.rs
third_party/rust/itertools-0.6.5/src/cons_tuples_impl.rs
third_party/rust/itertools-0.6.5/src/diff.rs
third_party/rust/itertools-0.6.5/src/format.rs
third_party/rust/itertools-0.6.5/src/free.rs
third_party/rust/itertools-0.6.5/src/groupbylazy.rs
third_party/rust/itertools-0.6.5/src/impl_macros.rs
third_party/rust/itertools-0.6.5/src/intersperse.rs
third_party/rust/itertools-0.6.5/src/kmerge_impl.rs
third_party/rust/itertools-0.6.5/src/lib.rs
third_party/rust/itertools-0.6.5/src/minmax.rs
third_party/rust/itertools-0.6.5/src/pad_tail.rs
third_party/rust/itertools-0.6.5/src/peeking_take_while.rs
third_party/rust/itertools-0.6.5/src/process_results_impl.rs
third_party/rust/itertools-0.6.5/src/rciter_impl.rs
third_party/rust/itertools-0.6.5/src/repeatn.rs
third_party/rust/itertools-0.6.5/src/size_hint.rs
third_party/rust/itertools-0.6.5/src/sources.rs
third_party/rust/itertools-0.6.5/src/tee.rs
third_party/rust/itertools-0.6.5/src/tuple_impl.rs
third_party/rust/itertools-0.6.5/src/with_position.rs
third_party/rust/itertools-0.6.5/src/zip_eq_impl.rs
third_party/rust/itertools-0.6.5/src/zip_longest.rs
third_party/rust/itertools-0.6.5/src/ziptuple.rs
third_party/rust/itertools-0.6.5/tests/peeking_take_while.rs
third_party/rust/itertools-0.6.5/tests/quick.rs
third_party/rust/itertools-0.6.5/tests/tests.rs
third_party/rust/itertools-0.6.5/tests/tuples.rs
third_party/rust/itertools-0.6.5/tests/zip.rs
third_party/rust/lalrpop-intern/.cargo-checksum.json
third_party/rust/lalrpop-intern/Cargo.toml
third_party/rust/lalrpop-intern/src/lib.rs
third_party/rust/lalrpop-intern/src/test.rs
third_party/rust/lalrpop-snap/.cargo-checksum.json
third_party/rust/lalrpop-snap/Cargo.toml
third_party/rust/lalrpop-snap/src/api/mod.rs
third_party/rust/lalrpop-snap/src/build/action.rs
third_party/rust/lalrpop-snap/src/build/fake_term.rs
third_party/rust/lalrpop-snap/src/build/mod.rs
third_party/rust/lalrpop-snap/src/collections/map.rs
third_party/rust/lalrpop-snap/src/collections/mod.rs
third_party/rust/lalrpop-snap/src/collections/multimap.rs
third_party/rust/lalrpop-snap/src/collections/set.rs
third_party/rust/lalrpop-snap/src/file_text.rs
third_party/rust/lalrpop-snap/src/generate.rs
third_party/rust/lalrpop-snap/src/grammar/consts.rs
third_party/rust/lalrpop-snap/src/grammar/mod.rs
third_party/rust/lalrpop-snap/src/grammar/parse_tree.rs
third_party/rust/lalrpop-snap/src/grammar/pattern.rs
third_party/rust/lalrpop-snap/src/grammar/repr.rs
third_party/rust/lalrpop-snap/src/grammar/token/mod.rs
third_party/rust/lalrpop-snap/src/grammar/token/test.rs
third_party/rust/lalrpop-snap/src/kernel_set.rs
third_party/rust/lalrpop-snap/src/lexer/dfa/interpret.rs
third_party/rust/lalrpop-snap/src/lexer/dfa/mod.rs
third_party/rust/lalrpop-snap/src/lexer/dfa/overlap.rs
third_party/rust/lalrpop-snap/src/lexer/dfa/test.rs
third_party/rust/lalrpop-snap/src/lexer/intern_token/mod.rs
third_party/rust/lalrpop-snap/src/lexer/mod.rs
third_party/rust/lalrpop-snap/src/lexer/nfa/interpret.rs
third_party/rust/lalrpop-snap/src/lexer/nfa/mod.rs
third_party/rust/lalrpop-snap/src/lexer/nfa/test.rs
third_party/rust/lalrpop-snap/src/lexer/re/mod.rs
third_party/rust/lalrpop-snap/src/lexer/re/test.rs
third_party/rust/lalrpop-snap/src/lib.rs
third_party/rust/lalrpop-snap/src/log.rs
third_party/rust/lalrpop-snap/src/lr1/build/mod.rs
third_party/rust/lalrpop-snap/src/lr1/build/test.rs
third_party/rust/lalrpop-snap/src/lr1/build_lalr/mod.rs
third_party/rust/lalrpop-snap/src/lr1/build_lalr/test.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/ascent.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/base.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/mod.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/parse_table.rs
third_party/rust/lalrpop-snap/src/lr1/codegen/test_all.rs
third_party/rust/lalrpop-snap/src/lr1/core/mod.rs
third_party/rust/lalrpop-snap/src/lr1/error/mod.rs
third_party/rust/lalrpop-snap/src/lr1/error/test.rs
third_party/rust/lalrpop-snap/src/lr1/example/mod.rs
third_party/rust/lalrpop-snap/src/lr1/example/test.rs
third_party/rust/lalrpop-snap/src/lr1/first/mod.rs
third_party/rust/lalrpop-snap/src/lr1/first/test.rs
third_party/rust/lalrpop-snap/src/lr1/interpret.rs
third_party/rust/lalrpop-snap/src/lr1/item.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/README.md
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/merge.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/construct/state_set.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/lane/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/table/context_set/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/table/context_set/test.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/table/mod.rs
third_party/rust/lalrpop-snap/src/lr1/lane_table/test.rs
third_party/rust/lalrpop-snap/src/lr1/lookahead.rs
third_party/rust/lalrpop-snap/src/lr1/mod.rs
third_party/rust/lalrpop-snap/src/lr1/report/mod.rs
third_party/rust/lalrpop-snap/src/lr1/state_graph.rs
third_party/rust/lalrpop-snap/src/lr1/tls.rs
third_party/rust/lalrpop-snap/src/lr1/trace/mod.rs
third_party/rust/lalrpop-snap/src/lr1/trace/reduce/mod.rs
third_party/rust/lalrpop-snap/src/lr1/trace/reduce/test.rs
third_party/rust/lalrpop-snap/src/lr1/trace/shift/mod.rs
third_party/rust/lalrpop-snap/src/lr1/trace/shift/test.rs
third_party/rust/lalrpop-snap/src/lr1/trace/trace_graph/mod.rs
third_party/rust/lalrpop-snap/src/lr1/trace/trace_graph/test.rs
third_party/rust/lalrpop-snap/src/message/builder.rs
third_party/rust/lalrpop-snap/src/message/horiz.rs
third_party/rust/lalrpop-snap/src/message/indent.rs
third_party/rust/lalrpop-snap/src/message/message.rs
third_party/rust/lalrpop-snap/src/message/mod.rs
third_party/rust/lalrpop-snap/src/message/styled.rs
third_party/rust/lalrpop-snap/src/message/test.rs
third_party/rust/lalrpop-snap/src/message/text.rs
third_party/rust/lalrpop-snap/src/message/vert.rs
third_party/rust/lalrpop-snap/src/message/wrap.rs
third_party/rust/lalrpop-snap/src/normalize/inline/graph/mod.rs
third_party/rust/lalrpop-snap/src/normalize/inline/graph/test.rs
third_party/rust/lalrpop-snap/src/normalize/inline/mod.rs
third_party/rust/lalrpop-snap/src/normalize/inline/test.rs
third_party/rust/lalrpop-snap/src/normalize/lower/mod.rs
third_party/rust/lalrpop-snap/src/normalize/macro_expand/mod.rs
third_party/rust/lalrpop-snap/src/normalize/macro_expand/test.rs
third_party/rust/lalrpop-snap/src/normalize/mod.rs
third_party/rust/lalrpop-snap/src/normalize/norm_util.rs
third_party/rust/lalrpop-snap/src/normalize/prevalidate/mod.rs
third_party/rust/lalrpop-snap/src/normalize/prevalidate/test.rs
third_party/rust/lalrpop-snap/src/normalize/resolve/mod.rs
third_party/rust/lalrpop-snap/src/normalize/resolve/test.rs
third_party/rust/lalrpop-snap/src/normalize/token_check/mod.rs
third_party/rust/lalrpop-snap/src/normalize/token_check/test.rs
third_party/rust/lalrpop-snap/src/normalize/tyinfer/mod.rs
third_party/rust/lalrpop-snap/src/normalize/tyinfer/test.rs
third_party/rust/lalrpop-snap/src/parser/lrgrammar.rs
third_party/rust/lalrpop-snap/src/parser/mod.rs
third_party/rust/lalrpop-snap/src/parser/test.rs
third_party/rust/lalrpop-snap/src/rust/mod.rs
third_party/rust/lalrpop-snap/src/session.rs
third_party/rust/lalrpop-snap/src/test_util.rs
third_party/rust/lalrpop-snap/src/tls/mod.rs
third_party/rust/lalrpop-snap/src/tok/mod.rs
third_party/rust/lalrpop-snap/src/tok/test.rs
third_party/rust/lalrpop-snap/src/util.rs
third_party/rust/lalrpop-util/.cargo-checksum.json
third_party/rust/lalrpop-util/Cargo.toml
third_party/rust/lalrpop-util/src/lib.rs
third_party/rust/lalrpop/.cargo-checksum.json
third_party/rust/lalrpop/Cargo.toml
third_party/rust/lalrpop/build.rs
third_party/rust/lalrpop/src/api/mod.rs
third_party/rust/lalrpop/src/build/action.rs
third_party/rust/lalrpop/src/build/fake_term.rs
third_party/rust/lalrpop/src/build/mod.rs
third_party/rust/lalrpop/src/collections/map.rs
third_party/rust/lalrpop/src/collections/mod.rs
third_party/rust/lalrpop/src/collections/multimap.rs
third_party/rust/lalrpop/src/collections/set.rs
third_party/rust/lalrpop/src/file_text.rs
third_party/rust/lalrpop/src/generate.rs
third_party/rust/lalrpop/src/grammar/consts.rs
third_party/rust/lalrpop/src/grammar/mod.rs
third_party/rust/lalrpop/src/grammar/parse_tree.rs
third_party/rust/lalrpop/src/grammar/pattern.rs
third_party/rust/lalrpop/src/grammar/repr.rs
third_party/rust/lalrpop/src/grammar/token/mod.rs
third_party/rust/lalrpop/src/grammar/token/test.rs
third_party/rust/lalrpop/src/kernel_set.rs
third_party/rust/lalrpop/src/lexer/dfa/interpret.rs
third_party/rust/lalrpop/src/lexer/dfa/mod.rs
third_party/rust/lalrpop/src/lexer/dfa/overlap.rs
third_party/rust/lalrpop/src/lexer/dfa/test.rs
third_party/rust/lalrpop/src/lexer/intern_token/mod.rs
third_party/rust/lalrpop/src/lexer/mod.rs
third_party/rust/lalrpop/src/lexer/nfa/interpret.rs
third_party/rust/lalrpop/src/lexer/nfa/mod.rs
third_party/rust/lalrpop/src/lexer/nfa/test.rs
third_party/rust/lalrpop/src/lexer/re/mod.rs
third_party/rust/lalrpop/src/lexer/re/test.rs
third_party/rust/lalrpop/src/lib.rs
third_party/rust/lalrpop/src/log.rs
third_party/rust/lalrpop/src/lr1/build/mod.rs
third_party/rust/lalrpop/src/lr1/build/test.rs
third_party/rust/lalrpop/src/lr1/build_lalr/mod.rs
third_party/rust/lalrpop/src/lr1/build_lalr/test.rs
third_party/rust/lalrpop/src/lr1/codegen/ascent.rs
third_party/rust/lalrpop/src/lr1/codegen/base.rs
third_party/rust/lalrpop/src/lr1/codegen/mod.rs
third_party/rust/lalrpop/src/lr1/codegen/parse_table.rs
third_party/rust/lalrpop/src/lr1/codegen/test_all.rs
third_party/rust/lalrpop/src/lr1/core/mod.rs
third_party/rust/lalrpop/src/lr1/error/mod.rs
third_party/rust/lalrpop/src/lr1/error/test.rs
third_party/rust/lalrpop/src/lr1/example/mod.rs
third_party/rust/lalrpop/src/lr1/example/test.rs
third_party/rust/lalrpop/src/lr1/first/mod.rs
third_party/rust/lalrpop/src/lr1/first/test.rs
third_party/rust/lalrpop/src/lr1/interpret.rs
third_party/rust/lalrpop/src/lr1/item.rs
third_party/rust/lalrpop/src/lr1/lane_table/README.md
third_party/rust/lalrpop/src/lr1/lane_table/construct/merge.rs
third_party/rust/lalrpop/src/lr1/lane_table/construct/mod.rs
third_party/rust/lalrpop/src/lr1/lane_table/construct/state_set.rs
third_party/rust/lalrpop/src/lr1/lane_table/lane/mod.rs
third_party/rust/lalrpop/src/lr1/lane_table/mod.rs
third_party/rust/lalrpop/src/lr1/lane_table/table/context_set/mod.rs
third_party/rust/lalrpop/src/lr1/lane_table/table/context_set/test.rs
third_party/rust/lalrpop/src/lr1/lane_table/table/mod.rs
third_party/rust/lalrpop/src/lr1/lane_table/test.rs
third_party/rust/lalrpop/src/lr1/lookahead.rs
third_party/rust/lalrpop/src/lr1/mod.rs
third_party/rust/lalrpop/src/lr1/report/mod.rs
third_party/rust/lalrpop/src/lr1/state_graph.rs
third_party/rust/lalrpop/src/lr1/tls.rs
third_party/rust/lalrpop/src/lr1/trace/mod.rs
third_party/rust/lalrpop/src/lr1/trace/reduce/mod.rs
third_party/rust/lalrpop/src/lr1/trace/reduce/test.rs
third_party/rust/lalrpop/src/lr1/trace/shift/mod.rs
third_party/rust/lalrpop/src/lr1/trace/shift/test.rs
third_party/rust/lalrpop/src/lr1/trace/trace_graph/mod.rs
third_party/rust/lalrpop/src/lr1/trace/trace_graph/test.rs
third_party/rust/lalrpop/src/main.rs
third_party/rust/lalrpop/src/message/builder.rs
third_party/rust/lalrpop/src/message/horiz.rs
third_party/rust/lalrpop/src/message/indent.rs
third_party/rust/lalrpop/src/message/message.rs
third_party/rust/lalrpop/src/message/mod.rs
third_party/rust/lalrpop/src/message/styled.rs
third_party/rust/lalrpop/src/message/test.rs
third_party/rust/lalrpop/src/message/text.rs
third_party/rust/lalrpop/src/message/vert.rs
third_party/rust/lalrpop/src/message/wrap.rs
third_party/rust/lalrpop/src/normalize/inline/graph/mod.rs
third_party/rust/lalrpop/src/normalize/inline/graph/test.rs
third_party/rust/lalrpop/src/normalize/inline/mod.rs
third_party/rust/lalrpop/src/normalize/inline/test.rs
third_party/rust/lalrpop/src/normalize/lower/mod.rs
third_party/rust/lalrpop/src/normalize/macro_expand/mod.rs
third_party/rust/lalrpop/src/normalize/macro_expand/test.rs
third_party/rust/lalrpop/src/normalize/mod.rs
third_party/rust/lalrpop/src/normalize/norm_util.rs
third_party/rust/lalrpop/src/normalize/prevalidate/mod.rs
third_party/rust/lalrpop/src/normalize/prevalidate/test.rs
third_party/rust/lalrpop/src/normalize/resolve/mod.rs
third_party/rust/lalrpop/src/normalize/resolve/test.rs
third_party/rust/lalrpop/src/normalize/token_check/mod.rs
third_party/rust/lalrpop/src/normalize/token_check/test.rs
third_party/rust/lalrpop/src/normalize/tyinfer/mod.rs
third_party/rust/lalrpop/src/normalize/tyinfer/test.rs
third_party/rust/lalrpop/src/parser/lrgrammar.lalrpop
third_party/rust/lalrpop/src/parser/lrgrammar.rs
third_party/rust/lalrpop/src/parser/mod.rs
third_party/rust/lalrpop/src/parser/test.rs
third_party/rust/lalrpop/src/rust/mod.rs
third_party/rust/lalrpop/src/session.rs
third_party/rust/lalrpop/src/test_util.rs
third_party/rust/lalrpop/src/tls/mod.rs
third_party/rust/lalrpop/src/tok/mod.rs
third_party/rust/lalrpop/src/tok/test.rs
third_party/rust/lalrpop/src/util.rs
third_party/rust/linked-hash-map/.cargo-checksum.json
third_party/rust/linked-hash-map/.travis.yml
third_party/rust/linked-hash-map/Cargo.toml
third_party/rust/linked-hash-map/LICENSE-APACHE
third_party/rust/linked-hash-map/LICENSE-MIT
third_party/rust/linked-hash-map/README.md
third_party/rust/linked-hash-map/deploy-docs.sh
third_party/rust/linked-hash-map/src/heapsize.rs
third_party/rust/linked-hash-map/src/lib.rs
third_party/rust/linked-hash-map/src/serde.rs
third_party/rust/linked-hash-map/tests/heapsize.rs
third_party/rust/linked-hash-map/tests/serde.rs
third_party/rust/linked-hash-map/tests/test.rs
third_party/rust/ordermap/.cargo-checksum.json
third_party/rust/ordermap/.travis.yml
third_party/rust/ordermap/Cargo.toml
third_party/rust/ordermap/LICENSE-APACHE
third_party/rust/ordermap/LICENSE-MIT
third_party/rust/ordermap/README.rst
third_party/rust/ordermap/benches/bench.rs
third_party/rust/ordermap/benches/faststring.rs
third_party/rust/ordermap/src/equivalent.rs
third_party/rust/ordermap/src/lib.rs
third_party/rust/ordermap/src/macros.rs
third_party/rust/ordermap/src/mutable_keys.rs
third_party/rust/ordermap/src/serde.rs
third_party/rust/ordermap/src/set.rs
third_party/rust/ordermap/src/util.rs
third_party/rust/ordermap/tests/equivalent_trait.rs
third_party/rust/ordermap/tests/quick.rs
third_party/rust/ordermap/tests/serde.rs
third_party/rust/ordermap/tests/tests.rs
third_party/rust/petgraph/.cargo-checksum.json
third_party/rust/petgraph/.travis.yml
third_party/rust/petgraph/Cargo.toml
third_party/rust/petgraph/LICENSE-APACHE
third_party/rust/petgraph/LICENSE-MIT
third_party/rust/petgraph/Makefile
third_party/rust/petgraph/README.rst
third_party/rust/petgraph/benches/iso.rs
third_party/rust/petgraph/benches/ograph.rs
third_party/rust/petgraph/benches/stable_graph.rs
third_party/rust/petgraph/custom.css
third_party/rust/petgraph/graph-example.dot
third_party/rust/petgraph/src/algo/dominators.rs
third_party/rust/petgraph/src/algo/mod.rs
third_party/rust/petgraph/src/astar.rs
third_party/rust/petgraph/src/csr.rs
third_party/rust/petgraph/src/data.rs
third_party/rust/petgraph/src/dijkstra.rs
third_party/rust/petgraph/src/dot.rs
third_party/rust/petgraph/src/generate.rs
third_party/rust/petgraph/src/graph_impl/frozen.rs
third_party/rust/petgraph/src/graph_impl/mod.rs
third_party/rust/petgraph/src/graph_impl/serialization.rs
third_party/rust/petgraph/src/graph_impl/stable_graph/mod.rs
third_party/rust/petgraph/src/graph_impl/stable_graph/serialization.rs
third_party/rust/petgraph/src/graphmap.rs
third_party/rust/petgraph/src/isomorphism.rs
third_party/rust/petgraph/src/iter_format.rs
third_party/rust/petgraph/src/iter_utils.rs
third_party/rust/petgraph/src/lib.rs
third_party/rust/petgraph/src/macros.rs
third_party/rust/petgraph/src/prelude.rs
third_party/rust/petgraph/src/quickcheck.rs
third_party/rust/petgraph/src/scored.rs
third_party/rust/petgraph/src/serde_utils.rs
third_party/rust/petgraph/src/traits_graph.rs
third_party/rust/petgraph/src/unionfind.rs
third_party/rust/petgraph/src/util.rs
third_party/rust/petgraph/src/visit/dfsvisit.rs
third_party/rust/petgraph/src/visit/filter.rs
third_party/rust/petgraph/src/visit/macros.rs
third_party/rust/petgraph/src/visit/mod.rs
third_party/rust/petgraph/src/visit/reversed.rs
third_party/rust/petgraph/src/visit/traversal.rs
third_party/rust/petgraph/tests/graph.rs
third_party/rust/petgraph/tests/graphmap.rs
third_party/rust/petgraph/tests/iso.rs
third_party/rust/petgraph/tests/quickcheck.rs
third_party/rust/petgraph/tests/stable_graph.rs
third_party/rust/petgraph/tests/unionfind.rs
third_party/rust/petgraph/tests/utils/mod.rs
third_party/rust/petgraph/tests/utils/qc.rs
third_party/rust/string_cache/.cargo-checksum.json
third_party/rust/string_cache/.travis.yml
third_party/rust/string_cache/Cargo.toml
third_party/rust/string_cache/LICENSE-APACHE
third_party/rust/string_cache/LICENSE-MIT
third_party/rust/string_cache/README.md
third_party/rust/string_cache/build.rs
third_party/rust/string_cache/src/atom.rs
third_party/rust/string_cache/src/bench.rs
third_party/rust/string_cache/src/event.rs
third_party/rust/string_cache/src/lib.rs
third_party/rust/string_cache_codegen/.cargo-checksum.json
third_party/rust/string_cache_codegen/Cargo.toml
third_party/rust/string_cache_codegen/lib.rs
third_party/rust/string_cache_shared/.cargo-checksum.json
third_party/rust/string_cache_shared/Cargo.toml
third_party/rust/string_cache_shared/lib.rs
third_party/rust/term/.cargo-checksum.json
third_party/rust/term/.travis.yml
third_party/rust/term/Cargo.toml
third_party/rust/term/LICENSE-APACHE
third_party/rust/term/LICENSE-MIT
third_party/rust/term/README.md
third_party/rust/term/appveyor.yml
third_party/rust/term/rustfmt.toml
third_party/rust/term/scripts/id_rsa.enc
third_party/rust/term/scripts/travis-doc-upload.cfg
third_party/rust/term/src/lib.rs
third_party/rust/term/src/terminfo/mod.rs
third_party/rust/term/src/terminfo/parm.rs
third_party/rust/term/src/terminfo/parser/compiled.rs
third_party/rust/term/src/terminfo/parser/names.rs
third_party/rust/term/src/terminfo/searcher.rs
third_party/rust/term/src/win.rs
third_party/rust/term/tests/data/dumb
third_party/rust/term/tests/data/linux
third_party/rust/term/tests/data/linux-16color
third_party/rust/term/tests/data/linux-basic
third_party/rust/term/tests/data/linux-c
third_party/rust/term/tests/data/linux-c-nc
third_party/rust/term/tests/data/linux-koi8
third_party/rust/term/tests/data/linux-koi8r
third_party/rust/term/tests/data/linux-lat
third_party/rust/term/tests/data/linux-m
third_party/rust/term/tests/data/linux-nic
third_party/rust/term/tests/data/linux-vt
third_party/rust/term/tests/data/linux2.2
third_party/rust/term/tests/data/linux2.6
third_party/rust/term/tests/data/linux2.6.26
third_party/rust/term/tests/data/linux3.0
third_party/rust/term/tests/data/rxvt
third_party/rust/term/tests/data/rxvt-16color
third_party/rust/term/tests/data/rxvt-256color
third_party/rust/term/tests/data/rxvt-88color
third_party/rust/term/tests/data/rxvt-basic
third_party/rust/term/tests/data/rxvt-color
third_party/rust/term/tests/data/rxvt-cygwin
third_party/rust/term/tests/data/rxvt-cygwin-native
third_party/rust/term/tests/data/rxvt-xpm
third_party/rust/term/tests/data/screen
third_party/rust/term/tests/data/screen-256color
third_party/rust/term/tests/data/xterm
third_party/rust/term/tests/data/xterm-256color
third_party/rust/term/tests/terminfo.rs
third_party/rust/webidl/.cargo-checksum.json
third_party/rust/webidl/.travis.yml
third_party/rust/webidl/Cargo.toml
third_party/rust/webidl/LICENSE
third_party/rust/webidl/README.md
third_party/rust/webidl/RELEASES.md
third_party/rust/webidl/build.rs
third_party/rust/webidl/clippy.toml
third_party/rust/webidl/src/lexer/mod.rs
third_party/rust/webidl/src/lexer/token.rs
third_party/rust/webidl/src/lib.rs
third_party/rust/webidl/src/parser/ast.rs
third_party/rust/webidl/src/parser/grammar.lalrpop
third_party/rust/webidl/src/parser/mod.rs
third_party/rust/webidl/src/parser/visitor/mod.rs
third_party/rust/webidl/src/parser/visitor/pretty_print.rs
third_party/rust/webidl/tests/parse_test.rs
third_party/rust/webidl/tests/pretty_print_test.rs
third_party/rust/yaml-rust/.cargo-checksum.json
third_party/rust/yaml-rust/.travis.yml
third_party/rust/yaml-rust/Cargo.toml
third_party/rust/yaml-rust/LICENSE-APACHE
third_party/rust/yaml-rust/LICENSE-MIT
third_party/rust/yaml-rust/README.md
third_party/rust/yaml-rust/appveyor.yml
third_party/rust/yaml-rust/examples/dump_yaml.rs
third_party/rust/yaml-rust/src/emitter.rs
third_party/rust/yaml-rust/src/lib.rs
third_party/rust/yaml-rust/src/parser.rs
third_party/rust/yaml-rust/src/scanner.rs
third_party/rust/yaml-rust/src/yaml.rs
third_party/rust/yaml-rust/tests/quickcheck.rs
third_party/rust/yaml-rust/tests/spec_test.rs
third_party/rust/yaml-rust/tests/spec_test.rs.inc
third_party/rust/yaml-rust/tests/specexamples.rs.inc
third_party/rust/yaml-rust/tests/specs/cpp2rust.rb
third_party/rust/yaml-rust/tests/specs/handler_spec_test.cpp
third_party/rust/yaml-rust/tests/specs/libyaml_fail-01.yaml
third_party/rust/yaml-rust/tests/specs/libyaml_fail-02.yaml
third_party/rust/yaml-rust/tests/specs/libyaml_fail-03.yaml
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,8 +1,17 @@
+[[package]]
+name = "Inflector"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[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"
@@ -29,22 +38,40 @@ dependencies = [
 name = "arrayvec"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "ascii-canvas"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "atomic_refcell"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "atty"
+version = "0.1.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.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (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.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -136,16 +163,53 @@ dependencies = [
  "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)",
  "which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "binjs_meta"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "binsource"
+version = "0.1.0"
+dependencies = [
+ "binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.4.4"
+source = "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"
 
 [[package]]
 name = "bitflags"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -483,16 +547,33 @@ dependencies = [
 name = "debug_unreachable"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "diff"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "docopt"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "dtoa"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "dtoa-short"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -515,16 +596,21 @@ dependencies = [
 ]
 
 [[package]]
 name = "either"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "ena"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "encoding_c"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -556,16 +642,17 @@ dependencies = [
 [[package]]
 name = "env_logger"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "error-chain"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -582,16 +669,21 @@ dependencies = [
 name = "fallible"
 version = "0.0.1"
 dependencies = [
  "hashglobe 0.1.0",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "fixedbitset"
+version = "0.1.8"
+source = "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.39 (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)",
 ]
 
@@ -841,16 +933,24 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.39 (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.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.1.0 (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 = [
  "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "itoa"
@@ -887,16 +987,71 @@ dependencies = [
 ]
 
 [[package]]
 name = "khronos_api"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "lalrpop"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lalrpop-snap 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
+ "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lalrpop-intern"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lalrpop-snap"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lalrpop-util"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "language-tags"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lazy_static"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -944,16 +1099,21 @@ source = "registry+https://github.com/ru
 dependencies = [
  "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (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 = "linked-hash-map"
+version = "0.5.1"
+source = "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"
 dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1264,16 +1424,21 @@ name = "ordered-float"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "ordermap"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "owning_ref"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1303,16 +1468,25 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "percent-encoding"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "petgraph"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "phf"
 version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1638,16 +1812,46 @@ version = "0.6.0"
 source = "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 = "string_cache"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 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)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "string_cache_codegen"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "string_cache_shared"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "strsim"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "style"
 version = "0.0.1"
 dependencies = [
@@ -1785,16 +1989,25 @@ dependencies = [
 name = "tempdir"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "term"
+version = "0.4.6"
+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)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[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.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2044,16 +2257,25 @@ dependencies = [
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "webidl"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lalrpop 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "webrender"
 version = "0.57.0"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2205,39 +2427,53 @@ name = "xpcom_macros"
 version = "0.1.0"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "yaml-rust"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "zip"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "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 Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1b33cd9b653730fc539c53c7b3c672d2f47108fa20c6df571fa5817178f5a14c"
 "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 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 ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
+"checksum atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0fd4c0631f06448cc45a6bbb3b710ebb7ff8ccb96a0800c994afe23a70d5df2"
 "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 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
 "checksum bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e"
+"checksum binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcfc86eecb125147e907529a5f1ac7978f6f26d20a52b82a7e053da5faefbc3"
+"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
+"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
 "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"
@@ -2267,26 +2503,30 @@ dependencies = [
 "checksum cubeb 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a3502aafa1bf95c524f65d2ba46d8741700c6a8a9543ea52c6da3d8b69a2896"
 "checksum cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138"
 "checksum cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37f7b20f757a4e4b6aa28863236551bff77682dc6db192eba15af615492b5445"
 "checksum cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "653b9e245d35dbe2a2da7c4586275cee75ff656ddeb02d4a73b4afdfa6d67502"
 "checksum darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3effd06d4057f275cb7858889f4952920bab78dd8ff0f6e7dfe0c8d2e67ed89"
 "checksum darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "167dd3e235c2f1da16a635c282630452cdf49191eb05711de1bcd1d3d5068c00"
 "checksum darling_macro 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c53edaba455f6073a10c27c72440860eb3f60444f8c8660a391032eeae744d82"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
+"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
+"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b26e30aaa6bf31ec830db15fec14ed04f0f2ecfcc486ecfce88c55d3389b237f"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
+"checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
 "checksum encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93ec52324ca72f423237a413ca0e1c60654c8b3d0934fcd5fd888508dfcc4ba7"
 "checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "adfe67a9343519c1449d208da5998c6de582de698f7a39c4ac82ffba23d131a5"
+"checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "398b8a11884898184d55aca9806f002b3cf68f0e860e0cbb4586f834ee39b0e7"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
 "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7"
@@ -2298,28 +2538,34 @@ dependencies = [
 "checksum gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "959c818d9bbe9f7b7db55dce0bc44673c4da4f4ee122536c40550f984c3b8017"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
 "checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
+"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
 "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 itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
 "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 lalrpop 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88035943c3cfbb897a499a556212b2b053574f32b4238b71b61625bc470f80aa"
+"checksum lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4fd87be4a815fd373e02773983940f0d75fb26fde8c098e9e45f7af03154c0"
+"checksum lalrpop-snap 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f244285324e4e33d486910b66fd3b7cb37e2072c5bf63319f506fe99ed72650"
+"checksum lalrpop-util 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de408fd50dea8ad7a77107144983a25c7fdabf5f8faf707a6e020d68874ed06c"
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "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.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
 "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 linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
 "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 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"
@@ -2335,21 +2581,23 @@ dependencies = [
 "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
 "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
 "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
 "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
 "checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
 "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
 "checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"
+"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
 "checksum parking_lot_core 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6c677d78851950b3aec390e681a411f78cc250cba277d4f578758a377f727970"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
+"checksum petgraph 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7e5234c228fbfa874c86a77f685886127f82e0aef602ad1d48333fcac6ad61"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "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"
@@ -2378,22 +2626,26 @@ dependencies = [
 "checksum serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)" = "<none>"
 "checksum serde_derive_internals 0.22.1 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)" = "<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 stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
+"checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"
+"checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
+"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "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 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "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"
@@ -2414,19 +2666,21 @@ dependencies = [
 "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 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 webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc14e4b71f94b5bb4c6d696e3b3be4d2e9ee6750a60870ecae09ff7138a131a7"
 "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"
 "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
 "checksum winreg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9338067aba07889a38beaad4dbb77fa2e62e87c423b770824b3bdf412874bd2c"
 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2"
+"checksum yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57ab38ee1a4a266ed033496cf9af1828d8d6e6c1cfa5f643a2809effcae4d628"
 "checksum zip 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10931e278527cea65682696481e6d840371d581079df529ebfee186e0eaad719"
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,16 +2,17 @@
 
 # These are the "root" crates, which we build and test as top-level targets.
 # Their transitive dependencies and dev-dependencies are included automatically
 # and do not need to be listed here. Their external dependencies are vendored
 # into `third_party/rust` by `mach vendor rust`.
 members = [
   "js/src",
   "js/rust",
+  "js/src/frontend/binsource", # Code generator.
   "testing/geckodriver",
   "toolkit/library/gtest/rust",
   "toolkit/library/rust/",
 ]
 
 # Excluded crates may be built as dependencies, but won't be considered members
 # of the workspace and their dev-dependencies won't be included.
 exclude = [
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"CHANGELOG.md":"e9a48682ad06315c67acdf9d9519ec60e483f487cfabcafebf30c18ecd553c19","CONTRIBUTING.md":"99a4db96609e44c91d9be8385e34cd213dc091e302d58d155056539045d17a8b","Cargo.toml":"1ba1b81c80a1b15f9bac208e924262b69962bf5d05452332fb32b301360f6693","LICENSE.md":"03d1bd5bfbee8d44651e7f57faf9e5b4eda4233f0d4eda36a716f2f0533d230b","PULL_REQUEST_TEMPLATE.md":"88b1581d41bbbfda51ac309ad7c3a735f65798f5b5148f1e6201a246719913c7","README.md":"d2e81724a70e14b60a2e8b680e9024838385ff51e302bb3f0879c526a6ae97f1","benchmark":"87cfbb14d1f7a3a38a9b02579199d04d87b15b078d3cf2094fd750aeb95c820a","src/cases/camelcase/mod.rs":"8e65fca78ea88acb32c0f214cafde39b849aef253253c3681e316f2559b26977","src/cases/case/mod.rs":"f3e1795f402cdfdecf3b255c3f7e42a9a6a8a0044802501574044e4a35d6081d","src/cases/classcase/mod.rs":"5b6b74530a2a693bf1ac89342f1b25f58f39336b1ee3242547c3d6ef468a878f","src/cases/kebabcase/mod.rs":"b317ebd42f22daab4b23bb4b83ce85f053d7088680d3a32eecbd13bd5331587a","src/cases/mod.rs":"e272853bcc1c5f6eb02594038febb9dcebb6eca8eac744d6e503db5082e585c6","src/cases/pascalcase/mod.rs":"a44feed6d8877fd8a31160076befe826960aa001d859587aef2dddc1aedc397b","src/cases/screamingsnakecase/mod.rs":"21582eb1ec2170d379bf3536c6ffb39b8bdc096efe2d493674458ee27b86e985","src/cases/sentencecase/mod.rs":"eb21d7d5bf0b23e1325d429dfdc149081d233a8b950c1fdfe04b4bebcc2c0ddb","src/cases/snakecase/mod.rs":"369739e37e700c028022f308aa78504873c10a5e88768f05249c1c8481b30c9d","src/cases/tablecase/mod.rs":"a6a50a397059d775a517d5dce6ba612b107919e209a9eb56871a5c1d42314664","src/cases/titlecase/mod.rs":"3f0dac5e5b434da9234d6c389f67bb2d3c8f138dc521fa29dbe3791f8eaf5341","src/cases/traincase/mod.rs":"4e2493d6594d3c505de293c69390b3f672c0fd4d35603ae1a1aae48166bc18c2","src/lib.rs":"6c5cf60f5c2f8778a3ad7638f37064527b8a86f164117d867b8b6532e2cc655e","src/numbers/deordinalize/mod.rs":"a6e0c00ab9c50f997b215762670ef1e7ac4cbdaa1380113fd625b8d59940e61c","src/numbers/mod.rs":"fed4e090f8b64a34ae64ddcb68d899cfa4dd8e8422a060be01a70dbdb71b85e0","src/numbers/ordinalize/mod.rs":"ce0d88977efaa50792e7311c0e0a73a3115928f9f7be77f914824c3d80eab66c","src/string/constants/mod.rs":"38de3d5060a5d224d28d184eab8af02203c65d74c1d380720c3260ea205f3e05","src/string/deconstantize/mod.rs":"c79f2170dc41bd6abb89a6e74fbdd87bf011f62cfe1f34d8886fda0724ade6fa","src/string/demodulize/mod.rs":"bbcb5314473e4ca02feee4903e31a332caaa912ed2cbca0f49c2fe411a826215","src/string/mod.rs":"570f7ea4dd646f2d633ddd67079db922cc2cadf916719fa19c2f59b4d522ee89","src/string/pluralize/mod.rs":"5f07fab8b5f4e7af546f1e907426724714b9b27af1ecb59a91e57dccd0833a6e","src/string/singularize/mod.rs":"9c2d833cbcdc1489013642de22578d51f558a31e8d2fea4536a27f8fa1114169","src/suffix/foreignkey/mod.rs":"e7ad9a9a0a21fcb53becb36306a15eedf67958e2da18ae928ae592177e70e7a3","src/suffix/mod.rs":"f6f99ce6fc8794d5411d91533b67be5d4a2bc5994317d32f405b2fa3c5ec660d","tests/lib.rs":"e1cfcea8a146291396ff72b0a2e84c2b9ddaa0103717442c4921c165a2ab470d","travis-after-success.sh":"ae0dfa332c9af427c728c42761a9813c9c6cb1748cc528a5bd38774a04850375"},"package":"1b33cd9b653730fc539c53c7b3c672d2f47108fa20c6df571fa5817178f5a14c"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/CHANGELOG.md
@@ -0,0 +1,392 @@
+# 0.11.2
+
+## Non-breaking changes:
+- Added class_cases and removed -- Thanks @Yoric
+  - Use pascal case
+- Updated lazy_static to 1.0.0
+
+# 0.11.1
+
+## Non-breaking changes:
+- Fixed an issue where words ending in e.g. "-ches", such as "witches"; that
+  would be singularized as "wit" instead of the expected "witch". -- Thanks nbaksalyar
+- Will be removing ascii import when current nightly goes stable.
+
+# 0.11.0
+
+## Breaking changes:
+- Made snake case deal correctly with special characters. Behaviour now follows
+  rails infector
+- Made camel case deal correctly with special characters. Behaviour now follows
+  rails infector
+
+## Non-breaking changes:
+- Removed magic macros for testing.
+- Added explicit tests for all cases.
+
+# 0.10.1
+
+## Non-breaking changes:
+- Added flags for unused macros. Any current macros with this flag with either
+  be moved or removed.
+
+# 0.10.0
+
+## Non-breaking changes:
+- Changed from `fold` to `for in` which resulted in a average 10-20% boost in
+  performance for all castings using the case module.
+
+## Fixes:
+- Fixed issue with snake case like strings where numbers were incorrectly
+  permitted to be next to a string e.g. `string1` was considered valid when it
+  should have been `string_1`. This has been corrected as part of the above
+  change.
+
+## Why is this not 0.9.1?
+- The change in this case are all on private API. This normally wouldn't cause a
+  breaking change as there are extensive tests wrapping all methods. This
+  however doesn't preclude an edge case that hasn't been considered. I've
+  deemed it safer to call this a 0.x.0 release for that reason.
+
+# 0.9.0
+
+## Breaking changes:
+- Changed type signature for all casting methods to use `&str`. This gives the
+  crate a >10% increase in performance in a majority of conversions. Although
+  most users only use:
+     `"my_string".to_camel_case()`
+  or
+    `"myString".to_string().to_snake_case()`
+  For those using the `to_camel_case("something".to_string())` this will be a
+  breaking change as the new syntax demands `to_camel_case("something")`.
+
+
+# 0.8.1
+
+## Fixes:
+
+- Fixed singularize issues with `/ies/`. Thanks @mthjones
+- Fixed issue with feature gates which may have caused downstream api
+  incompatibilities.
+
+# 0.8.0
+
+## New features:
+
+- Feature gated pluralize, singularize, class_case, table_case, demodulize, and
+  deconstantize. This can be activated by passing --features=lightweight. See
+  README
+
+
+## Possible breaking change:
+
+- Feature gated items are on by default, meaning that you'll get the full
+  version of the crate if you install as normal. See README if you want to use
+  the lightweight version.
+- Although the application still passes all tests, substantial portions of the
+  core of the conversion code have been method extracted and may have caused a
+  change for some people. Please file an issue if this is a problem for you.
+
+# 0.7.0
+
+## New features:
+
+- Added traits for various number types on ordinalize.
+
+## Possible breaking change:
+
+- Fixed issue with Boxes to Box which may cause breakages for some people
+
+## Non-breaking change:
+
+- Updated dependencies on `regex` and `lazy_static` to be the current latest
+- Changed the way that traits are implemented to use macros. Thus reducing
+  duplication issues seen previously for each type that wanted to implement
+  Inflector
+- More tests for conversion between different string formats
+- Better documentation for new users
+- Cleaned up documentation
+
+## Notes:
+- This is a pre-release for 1.0.0
+
+# 0.6.0
+
+## Breaking changes:
+
+- Removed lower and upper case. -- Use the built in [Rust implementations](https://doc.rust-lang.org/std/string/struct.String.html#method.to_uppercase)
+
+## Non-breaking change:
+
+- Removed lib definitions. -- Thanks @kanerogers
+
+# 0.5.1
+
+## Non-breaking change:
+
+- Refactored Title, Pascal, Train and Camel cases to be unified.
+
+# 0.5.0
+
+## New features:
+
+- Adds Train-Case thanks to @stpettersens
+
+## Fixes:
+
+- Fixes performance issues with Title Case
+
+# 0.4.0
+
+## Fixes:
+
+- Fixes issue where strings like `HTTPParty` becomes `h_t_t_p_party` instead of `http_party` as it should -- Thanks @cmsd2
+
+## New features:
+
+- Adds PascalCase
+
+## Benchmarks:
+```shell
+test cases::camelcase::tests::bench_camel0                      ... bench:         142 ns/iter (+/- 28)
+test cases::camelcase::tests::bench_camel1                      ... bench:         143 ns/iter (+/- 30)
+test cases::camelcase::tests::bench_camel2                      ... bench:         138 ns/iter (+/- 80)
+test cases::camelcase::tests::bench_is_camel                    ... bench:         171 ns/iter (+/- 103)
+test cases::classcase::tests::bench_class_case                  ... bench:       2,369 ns/iter (+/- 658)
+test cases::classcase::tests::bench_class_from_snake            ... bench:       2,378 ns/iter (+/- 914)
+test cases::classcase::tests::bench_is_class                    ... bench:       2,541 ns/iter (+/- 294)
+test cases::kebabcase::tests::bench_is_kebab                    ... bench:         180 ns/iter (+/- 35)
+test cases::kebabcase::tests::bench_kebab                       ... bench:         156 ns/iter (+/- 91)
+test cases::kebabcase::tests::bench_kebab_from_snake            ... bench:         248 ns/iter (+/- 143)
+test cases::lowercase::tests::bench_is_lower                    ... bench:         340 ns/iter (+/- 91)
+test cases::lowercase::tests::bench_lower                       ... bench:         301 ns/iter (+/- 124)
+test cases::pascalcase::tests::bench_is_pascal                  ... bench:         163 ns/iter (+/- 65)
+test cases::pascalcase::tests::bench_pascal0                    ... bench:         140 ns/iter (+/- 78)
+test cases::pascalcase::tests::bench_pascal1                    ... bench:         140 ns/iter (+/- 40)
+test cases::pascalcase::tests::bench_pascal2                    ... bench:         138 ns/iter (+/- 105)
+test cases::screamingsnakecase::tests::bench_is_screaming_snake ... bench:         193 ns/iter (+/- 27)
+test cases::screamingsnakecase::tests::bench_screaming_snake    ... bench:         161 ns/iter (+/- 84)
+test cases::sentencecase::tests::bench_is_sentence              ... bench:         394 ns/iter (+/- 85)
+test cases::sentencecase::tests::bench_sentence                 ... bench:         365 ns/iter (+/- 186)
+test cases::sentencecase::tests::bench_sentence_from_snake      ... bench:         333 ns/iter (+/- 178)
+test cases::snakecase::tests::bench_is_snake                    ... bench:         190 ns/iter (+/- 74)
+test cases::snakecase::tests::bench_snake_from_camel            ... bench:         155 ns/iter (+/- 44)
+test cases::snakecase::tests::bench_snake_from_snake            ... bench:         280 ns/iter (+/- 161)
+test cases::snakecase::tests::bench_snake_from_title            ... bench:         156 ns/iter (+/- 31)
+test cases::tablecase::tests::bench_is_table_case               ... bench:       2,388 ns/iter (+/- 431)
+test cases::tablecase::tests::bench_table_case                  ... bench:       2,240 ns/iter (+/- 446)
+test cases::titlecase::tests::bench_is_title                    ... bench:         786 ns/iter (+/- 135)
+test cases::titlecase::tests::bench_title                       ... bench:         826 ns/iter (+/- 278)
+test cases::titlecase::tests::bench_title_from_snake            ... bench:         723 ns/iter (+/- 256)
+test cases::uppercase::tests::bench_is_upper                    ... bench:         351 ns/iter (+/- 85)
+test cases::uppercase::tests::bench_upper                       ... bench:         332 ns/iter (+/- 48)
+```
+
+# 0.3.3
+
+## Fixes:
+
+- Fixes issue where camel case tests were not run
+- Fixes issue with camel case with numbers
+
+# 0.3.2
+
+## Fixes:
+
+- Fixes issue https://github.com/whatisinternet/inflector/issues/18
+- Fixes performance issues overall
+
+## Benchmarks:
+```shell
+test cases::camelcase::tests::bench_camel0                      ... bench:         139 ns/iter (+/- 40)
+test cases::camelcase::tests::bench_camel1                      ... bench:         138 ns/iter (+/- 31)
+test cases::camelcase::tests::bench_camel2                      ... bench:         138 ns/iter (+/- 41)
+test cases::camelcase::tests::bench_is_camel                    ... bench:         184 ns/iter (+/- 90)
+test cases::classcase::tests::bench_class_case                  ... bench:       2,383 ns/iter (+/- 557)
+test cases::classcase::tests::bench_class_from_snake            ... bench:       2,393 ns/iter (+/- 1,120)
+test cases::classcase::tests::bench_is_class                    ... bench:       2,443 ns/iter (+/- 1,060)
+test cases::kebabcase::tests::bench_is_kebab                    ... bench:         182 ns/iter (+/- 60)
+test cases::kebabcase::tests::bench_kebab                       ... bench:         161 ns/iter (+/- 98)
+test cases::kebabcase::tests::bench_kebab_from_snake            ... bench:         264 ns/iter (+/- 144)
+test cases::lowercase::tests::bench_is_lower                    ... bench:         358 ns/iter (+/- 154)
+test cases::lowercase::tests::bench_lower                       ... bench:         347 ns/iter (+/- 220)
+test cases::screamingsnakecase::tests::bench_is_screaming_snake ... bench:         194 ns/iter (+/- 35)
+test cases::screamingsnakecase::tests::bench_screaming_snake    ... bench:         173 ns/iter (+/- 97)
+test cases::sentencecase::tests::bench_is_sentence              ... bench:         377 ns/iter (+/- 83)
+test cases::sentencecase::tests::bench_sentence                 ... bench:         337 ns/iter (+/- 155)
+test cases::sentencecase::tests::bench_sentence_from_snake      ... bench:         370 ns/iter (+/- 176)
+test cases::snakecase::tests::bench_is_snake                    ... bench:         191 ns/iter (+/- 98)
+test cases::snakecase::tests::bench_snake_from_camel            ... bench:         156 ns/iter (+/- 25)
+test cases::snakecase::tests::bench_snake_from_snake            ... bench:         289 ns/iter (+/- 136)
+test cases::snakecase::tests::bench_snake_from_title            ... bench:         157 ns/iter (+/- 68)
+test cases::tablecase::tests::bench_is_table_case               ... bench:       2,253 ns/iter (+/- 978)
+test cases::tablecase::tests::bench_table_case                  ... bench:       2,227 ns/iter (+/- 704)
+test cases::titlecase::tests::bench_is_title                    ... bench:         787 ns/iter (+/- 362)
+test cases::titlecase::tests::bench_title                       ... bench:         826 ns/iter (+/- 317)
+test cases::titlecase::tests::bench_title_from_snake            ... bench:         747 ns/iter (+/- 230)
+test cases::uppercase::tests::bench_is_upper                    ... bench:         347 ns/iter (+/- 111)
+test cases::uppercase::tests::bench_upper                       ... bench:         328 ns/iter (+/- 42)
+```
+
+## OLD Benchmarks:
+```shell
+test cases::camelcase::tests::bench_camel                                         ... bench:       1,825 ns/iter (+/- 346)
+test cases::camelcase::tests::bench_camel_from_sname                              ... bench:       1,223 ns/iter (+/- 289)
+test cases::camelcase::tests::bench_is_camel                                      ... bench:      49,416 ns/iter (+/- 593)
+test cases::classcase::tests::bench_class_case                                    ... bench: 160,985,376 ns/iter (+/- 5,173,751)
+test cases::classcase::tests::bench_class_from_snake                              ... bench: 161,533,425 ns/iter (+/- 4,167,305)
+test cases::classcase::tests::bench_is_class                                      ... bench: 161,352,118 ns/iter (+/- 3,793,478)
+test cases::kebabcase::tests::bench_is_kebab                                      ... bench:         793 ns/iter (+/- 400)
+test cases::kebabcase::tests::bench_kebab                                         ... bench:         752 ns/iter (+/- 310)
+test cases::kebabcase::tests::bench_kebab_from_snake                              ... bench:         210 ns/iter (+/- 32)
+test cases::lowercase::tests::bench_is_lower                                      ... bench:         340 ns/iter (+/- 86)
+test cases::lowercase::tests::bench_lower                                         ... bench:         306 ns/iter (+/- 173)
+test cases::screamingsnakecase::tests::bench_is_screaming_snake                   ... bench:         635 ns/iter (+/- 210)
+test cases::screamingsnakecase::tests::bench_screaming_snake                      ... bench:         610 ns/iter (+/- 87)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_camel           ... bench:         961 ns/iter (+/- 579)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_class           ... bench:         894 ns/iter (+/- 352)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_kebab           ... bench:         877 ns/iter (+/- 571)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_screaming_snake ... bench:         584 ns/iter (+/- 304)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_sentence        ... bench:       1,123 ns/iter (+/- 630)
+test cases::screamingsnakecase::tests::bench_screaming_snake_from_upper_kebab     ... bench:         914 ns/iter (+/- 435)
+test cases::sentencecase::tests::bench_is_sentence                                ... bench:       2,714 ns/iter (+/- 796)
+test cases::sentencecase::tests::bench_sentence                                   ... bench:       2,678 ns/iter (+/- 1,357)
+test cases::sentencecase::tests::bench_sentence_from_snake                        ... bench:       2,100 ns/iter (+/- 1,046)
+test cases::snakecase::tests::bench_is_snake                                      ... bench:         626 ns/iter (+/- 191)
+test cases::snakecase::tests::bench_snake                                         ... bench:         581 ns/iter (+/- 298)
+test cases::snakecase::tests::bench_snake_from_camel                              ... bench:         882 ns/iter (+/- 328)
+test cases::snakecase::tests::bench_snake_from_class                              ... bench:         883 ns/iter (+/- 193)
+test cases::snakecase::tests::bench_snake_from_kebab                              ... bench:         922 ns/iter (+/- 360)
+test cases::snakecase::tests::bench_snake_from_sentence                           ... bench:       1,209 ns/iter (+/- 539)
+test cases::snakecase::tests::bench_snake_from_snake                              ... bench:         637 ns/iter (+/- 386)
+test cases::snakecase::tests::bench_snake_from_upper_kebab                        ... bench:         876 ns/iter (+/- 488)
+test cases::tablecase::tests::bench_is_table_case                                 ... bench:       5,784 ns/iter (+/- 1,129)
+test cases::tablecase::tests::bench_table_case                                    ... bench:       5,754 ns/iter (+/- 1,460)
+test cases::titlecase::tests::bench_is_title                                      ... bench:       2,847 ns/iter (+/- 1,553)
+test cases::titlecase::tests::bench_title                                         ... bench:       2,799 ns/iter (+/- 1,309)
+test cases::titlecase::tests::bench_title_from_snake                              ... bench:       2,202 ns/iter (+/- 697)
+test cases::uppercase::tests::bench_is_upper                                      ... bench:         357 ns/iter (+/- 55)
+test cases::uppercase::tests::bench_upper                                         ... bench:         311 ns/iter (+/- 135)
+```
+
+# 0.3.1
+
+## Fixes:
+
+- Fixes issue https://github.com/rust-lang/rust/pull/34660
+- Updates Regex to 0.1.73 for latest fixes
+
+# 0.3.0
+
+## Fixes:
+
+- Resolves issues with pluralize not always correctly pluralizing strings.
+  Thanks, @weiznich!
+- Resolves issues with silently failing test on table case
+- Replaces complex code used for is_*_case checks with simple conversion and
+  check equality.
+
+## Breaking changes:
+
+- Dropping support for Rust versions below stable
+
+# 0.2.1
+
+## Features:
+
+- Replaced custom implementation of lower and uppercase with Rust default
+
+## Breaking changes:
+
+- Rust 1.2 or greater required
+
+# 0.2.0
+
+## Features:
+
+- Added Pluralize
+- Added Singularize
+- Added Table case
+
+## Fixes:
+
+- Fixed doc tests to properly run as rust auto wraps doc tests in a function and
+  never ran the inner function that was defined.
+- Fixed documentation for kebab case
+- Fixed several failed tests for various cases which were mainly typos
+
+## Breaking changes:
+
+- Class case now singularizes strings and verifies that strings are
+  singularized. Those wishing for the old behaviour should remain on the 0.1.6
+  release.
+
+
+# 0.1.6
+
+## Features:
+
+- Added screaming snake case
+
+# 0.1.5
+
+## Fixes:
+
+- Refactored tests into doc tests.
+
+
+# 0.1.4
+
+## Features:
+
+- Significant performance improvement for casting strings between different case
+  types see #13.
+
+## Fixes:
+
+- Fixed performance issues with string casting.
+- Removed heavy reliance on Regex
+
+
+# 0.1.3
+
+## Fixes:
+
+- Refactored code to mostly pass through snake case then be converted to lower
+  the number of moving parts and reduce the complexity for adding a new casting
+  as only snake case would need to be modified to convert to most other cases.
+
+## Breaking changes:
+
+- This release is slow in contrast to other crates
+
+
+# 0.1.2
+
+## Fixes:
+
+- Documentation fixes
+- Added uppercase
+- Added lowercase
+- Added foreign key
+- Added sentence case
+- Added title case
+
+
+# 0.1.1
+
+## Features:
+- Adds support for foreign key
+- Adds demodulize
+- Adds deconstantize
+- Adds trait based usage
+
+
+# 0.1.0
+
+## Features:
+
+- Added support for camel case
+- Added support for class case
+- Added support for kebab case
+- Added support for snake case
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/CONTRIBUTING.md
@@ -0,0 +1,77 @@
+# Thank you! :heart:
+
+This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
+
+## Getting started
+- If you don't have rust installed: Install [rustup](https://www.rustup.rs/)
+- For normal development on `master` run on stable
+  - `rustup toolchain install stable`
+  - `rustup default stable`
+
+- For development with benchmarks run nightly
+  - `rustup toolchain install nightly`
+  - `rustup default nightly`
+
+## Git/GitHub steps
+1. Fork it ( https://github.com/whatisinternet/inflector/fork )
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Add test for the new feature (conversions to all different casts MUST also
+   pass)
+4. Write some code to pass the tests
+5. Commit your changes (`git commit -am 'Add some feature'`)
+6. Push to the branch (`git push origin my-new-feature`)
+7. Create a new Pull Request
+
+### Running the tests
+- `cargo test`
+
+### Running the benchmarks
+- `cargo bench --features=unstable`
+
+## Is this an issues?
+
+- Please ensure you fill out an [issue](https://github.com/whatisinternet/inflector/issues)
+- Be available for questions.
+
+## Are you submitting documentation?
+
+- Awesome!
+- Has everything been run through spell check?
+
+## Are you submitting code?
+
+- Have you added doc tests and do they pass?
+- Do all other tests pass?
+- Have you added trait tests? (If applicable)
+- Have you filled out the pull request template?
+
+
+## Adding a trait
+Traits are now both easy to add and easy to test. Just follow the next steps:
+
+### Adding the trait
+- `src/lib.rs`
+- Add the function signature to the Inflector trait
+```rust
+//...
+use string::singularize::to_singular;
+//...
+pub trait Inflector { // Or InflectorNumbers
+    //...
+    fn your_trait(&self) -> [return_type];
+    //...
+}
+```
+- Add the function name an return type to either `implement_string_for` or
+   `implement_number_for`
+```rust
+  your_trait => [return_type]
+```
+- Add a benchmark following the current convention
+
+### Add the trait tests
+- `tests/lib.rs`
+- Add your trait following the current convention and the test will be
+   automatically generated
+
+Thank you for your help! :heart:
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/Cargo.toml
@@ -0,0 +1,42 @@
+# 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 = "Inflector"
+version = "0.11.2"
+authors = ["Josh Teeter<joshteeter@gmail.com>"]
+exclude = [".travis.yml", ".gitignore"]
+description = "Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title and table cases as well as ordinalize, deordinalize, demodulize, foreign key, and pluralize/singularize are supported as both traits and pure functions acting on String types.\n"
+homepage = "https://github.com/whatisinternet/inflector"
+documentation = "https://docs.rs/Inflector"
+readme = "README.md"
+keywords = ["pluralize", "Inflector", "camel", "snake", "inflection"]
+categories = ["text-processing", "value-formatting"]
+license = "BSD-2-Clause"
+repository = "https://github.com/whatisinternet/inflector"
+
+[lib]
+name = "inflector"
+[dependencies.lazy_static]
+version = "1.0.0"
+optional = true
+
+[dependencies.regex]
+version = "0.2"
+optional = true
+
+[features]
+default = ["heavyweight"]
+heavyweight = ["regex", "lazy_static"]
+unstable = []
+[badges.travis-ci]
+repository = "whatisinternet/Inflector"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/LICENSE.md
@@ -0,0 +1,22 @@
+Copyright 2017 Josh Teeter
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+# What it does:
+
+
+# Why it does it:
+
+
+# Related issues:
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/README.md
@@ -0,0 +1,136 @@
+# Rust Inflector
+
+
+[![Build Status](https://travis-ci.org/whatisinternet/inflector.svg?branch=master)](https://travis-ci.org/whatisinternet/Inflector) [![codecov](https://codecov.io/gh/whatisinternet/Inflector/branch/master/graph/badge.svg)](https://codecov.io/gh/whatisinternet/inflector) [![Crates.io](https://img.shields.io/crates/v/inflector.svg)](https://crates.io/crates/inflector)
+
+
+Adds String based inflections for Rust. Snake, kebab, train, camel,
+sentence, class, and title cases as well as ordinalize,
+deordinalize, demodulize, deconstantize, foreign key, table case, and pluralize/singularize are supported as both traits and pure functions
+acting on &str and String types.
+
+-----
+## Documentation:
+
+Documentation can be found here at the README or via rust docs below.
+
+[Rust docs with examples](https://docs.rs/Inflector)
+
+-----
+
+## Installation:
+
+### As a [crate](http://crates.io)
+
+```toml
+[dependencies]
+Inflector = "*"
+```
+
+### Compile yourself:
+
+1. Install [Rust and cargo](http://doc.crates.io/)
+2. git clone https://github.com/whatisinternet/Inflector
+3. Library: cd inflector && cargo build --release --lib
+4. You can find the library in target/release
+
+## Usage / Example:
+
+```rust
+...
+// to use methods like String.to_lower_case();
+extern crate inflector;
+use inflector::Inflector;
+...
+fn main() {
+...
+  let camel_case_string: String = "some_string".to_camel_case();
+...
+}
+
+```
+
+Or
+
+```rust
+...
+// to use methods like to_snake_case(&str);
+extern crate inflector;
+
+// use inflector::cases::classcase::to_class_case;
+// use inflector::cases::classcase::is_class_case;
+
+// use inflector::cases::camelcase::to_camel_case;
+// use inflector::cases::camelcase::is_camel_case;
+
+// use inflector::cases::pascalcase::to_pascal_case;
+// use inflector::cases::pascalcase::is_pascal_case;
+
+// use inflector::cases::screamingsnakecase::to_screamingsnake_case;
+// use inflector::cases::screamingsnakecase::is_screamingsnake_case;
+
+// use inflector::cases::snakecase::to_snake_case;
+// use inflector::cases::snakecase::is_snake_case;
+
+// use inflector::cases::kebabcase::to_kebab_case;
+// use inflector::cases::kebabcase::is_kebab_case;
+
+// use inflector::cases::traincase::to_train_case;
+// use inflector::cases::traincase::is_train_case;
+
+// use inflector::cases::sentencecase::to_sentence_case;
+// use inflector::cases::sentencecase::is_sentence_case;
+
+// use inflector::cases::titlecase::to_title_case;
+// use inflector::cases::titlecase::is_title_case;
+
+// use inflector::cases::tablecase::to_table_case;
+// use inflector::cases::tablecase::is_table_case;
+
+// use inflector::numbers::ordinalize::ordinalize;
+// use inflector::numbers::deordinalize::deordinalize;
+
+// use inflector::suffix::foreignkey::to_foreign_key;
+// use inflector::suffix::foreignkey::is_foreign_key;
+
+// use inflector::string::demodulize::demodulize;
+// use inflector::string::deconstantize::deconstantize;
+
+// use inflector::string::pluralize::to_plural;
+// use inflector::string::singularize::to_singular;
+...
+fn main() {
+...
+  let camel_case_string: String = to_camel_case("some_string");
+...
+}
+
+```
+
+## Advanced installation and usage:
+
+If the project doesn't require singularize, pluralize, class, table, demodulize,
+deconstantize. Then in your `cargo.toml` you may wish to specify:
+
+```toml
+[dependencies.Inflector]
+version = "*"
+default-features = false
+```
+
+Or
+
+```toml
+Inflector = {version="*", default-features=false}
+
+```
+
+To test this crate locally with features off try:
+
+```shell
+cargo test --no-default-features
+```
+
+## [Contributing](CONTRIBUTING.md)
+
+This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
new file mode 100755
--- /dev/null
+++ b/third_party/rust/Inflector/benchmark
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
+
+cargo clean && \
+cargo bench --features=unstable>variable &&\
+git stash && \
+git checkout master && \
+cargo clean && \
+cargo bench --features=unstable>control &&\
+cargo benchcmp control variable --variance --threshold 10 &&\
+git checkout $branch &&\
+git stash apply
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/camelcase/mod.rs
@@ -0,0 +1,370 @@
+#![deny(warnings)]
+use cases::case::*;
+
+/// Converts a `&str` to camelCase `String`
+///
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "foo-bar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "FooBar3";
+///     let expected_string: String = "fooBar3".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::to_camel_case;
+///     let mock_string: &str = "Foo-Bar";
+///     let expected_string: String = "fooBar".to_string();
+///     let asserted_string: String = to_camel_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_camel_case(non_camelized_string: &str) -> String {
+    let options = CamelOptions {
+        new_word: false,
+        last_char: ' ',
+        first_word: false,
+        injectable_char: ' ',
+        has_seperator: false,
+        inverted: false,
+    };
+    to_case_camel_like(&non_camelized_string, options)
+}
+
+/// Determines if a `&str` is camelCase bool``
+///
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "Foo";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "foo";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "fooBarIsAReallyReally3LongString";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::camelcase::is_camel_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_camel_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+pub fn is_camel_case(test_string: &str) -> bool {
+    to_camel_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_camel0(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "Foo bar";
+            super::to_camel_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_camel1(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "foo_bar";
+            super::to_camel_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_camel2(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "fooBar";
+            super::to_camel_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_is_camel(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string: &str = "Foo bar";
+            super::is_camel_case(test_string)
+        });
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_camel_case;
+    use ::is_camel_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_case_with_loads_of_space() {
+        let convertable_string: String = "foo           bar".to_owned();
+        let expected: String = "fooBar".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn a_name_with_a_dot() {
+        let convertable_string: String = "Robert C. Martin".to_owned();
+        let expected: String = "robertCMartin".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn random_text_with_bad_chars() {
+        let convertable_string: String = "Random text with *(bad) chars".to_owned();
+        let expected: String = "randomTextWithBadChars".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn trailing_bad_chars() {
+        let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+        let expected: String = "trailingBadChars".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn leading_bad_chars() {
+        let convertable_string: String = "-!#$%leading bad chars".to_owned();
+        let expected: String = "leadingBadChars".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn wrapped_in_bad_chars() {
+        let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+        let expected: String = "wrappedInBadChars".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn has_a_sign() {
+        let convertable_string: String = "has a + sign".to_owned();
+        let expected: String = "hasASign".to_owned();
+        assert_eq!(to_camel_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_camel_case(&convertable_string), false)
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/case/mod.rs
@@ -0,0 +1,303 @@
+#![deny(warnings)]
+#[allow(unknown_lints)]
+#[allow(unused_imports)]
+use std::ascii::*;
+
+pub struct CamelOptions {
+    pub new_word: bool,
+    pub last_char: char,
+    pub first_word: bool,
+    pub injectable_char: char,
+    pub has_seperator: bool,
+    pub inverted: bool,
+}
+
+pub fn to_case_snake_like(convertable_string: &str, replace_with: &str, case: &str) -> String {
+    let mut first_character: bool = true;
+    let mut result: String = String::with_capacity(convertable_string.len() * 2);
+    for char_with_index in trim_right(convertable_string).char_indices() {
+        if char_is_seperator(&char_with_index.1) {
+            if !first_character {
+                first_character = true;
+                result.push(replace_with.chars().nth(0).unwrap_or('_'));
+            }
+        } else if requires_seperator(char_with_index, first_character, &convertable_string) {
+            first_character = false;
+            result = snake_like_with_seperator(result, replace_with, &char_with_index.1, case)
+        } else {
+            first_character = false;
+            result = snake_like_no_seperator(result, &char_with_index.1, case)
+        }
+    }
+    result
+}
+
+pub fn to_case_camel_like(convertable_string: &str, camel_options: CamelOptions) -> String {
+    let mut new_word: bool = camel_options.new_word;
+    let mut first_word: bool = camel_options.first_word;
+    let mut last_char: char = camel_options.last_char;
+    let mut found_real_char: bool = false;
+    let mut result: String = String::with_capacity(convertable_string.len() * 2);
+    for character in trim_right(convertable_string).chars() {
+        if char_is_seperator(&character) && found_real_char {
+            new_word = true;
+        } else if !found_real_char && is_not_alphanumeric(character) {
+            continue;
+        } else if character.is_numeric() {
+            found_real_char = true;
+            new_word = true;
+            result.push(character);
+        } else if last_char_lower_current_is_upper_or_new_word(new_word, last_char, character) {
+            found_real_char = true;
+            new_word = false;
+            result = append_on_new_word(result, first_word, character, &camel_options);
+            first_word = false;
+        } else {
+            found_real_char = true;
+            last_char = character;
+            result.push(character.to_ascii_lowercase());
+        }
+    }
+    result
+}
+
+#[inline]
+fn append_on_new_word(mut result: String, first_word: bool, character: char, camel_options: &CamelOptions) -> String {
+    if not_first_word_and_has_seperator(first_word, camel_options.has_seperator) {
+        result.push(camel_options.injectable_char);
+    }
+    if first_word_or_not_inverted(first_word, camel_options.inverted) {
+        result.push(character.to_ascii_uppercase());
+    } else {
+        result.push(character.to_ascii_lowercase());
+    }
+    result
+}
+
+fn not_first_word_and_has_seperator(first_word: bool, has_seperator: bool) -> bool {
+    has_seperator && !first_word
+}
+
+fn first_word_or_not_inverted(first_word: bool, inverted: bool) -> bool {
+    !inverted || first_word
+}
+
+
+fn last_char_lower_current_is_upper_or_new_word(new_word: bool, last_char: char, character: char) -> bool{
+    new_word ||
+        ((last_char.is_lowercase() && character.is_uppercase()) &&
+         (last_char != ' '))
+}
+
+fn char_is_seperator(character: &char) -> bool {
+    is_not_alphanumeric(*character)
+}
+
+fn trim_right(convertable_string: &str) -> &str {
+    convertable_string.trim_right_matches(is_not_alphanumeric)
+}
+
+fn is_not_alphanumeric(character: char) -> bool {
+    !character.is_alphanumeric()
+}
+
+#[inline]
+fn requires_seperator(char_with_index: (usize, char), first_character: bool, convertable_string: &str) -> bool {
+    !first_character &&
+        char_is_uppercase(char_with_index.1) &&
+            next_or_previous_char_is_lowercase(convertable_string, char_with_index.0)
+}
+
+#[inline]
+fn snake_like_no_seperator(mut accumlator: String, current_char: &char, case: &str) -> String {
+    if case == "lower" {
+        accumlator.push(current_char.to_ascii_lowercase());
+        accumlator
+    } else {
+        accumlator.push(current_char.to_ascii_uppercase());
+        accumlator
+    }
+}
+
+#[inline]
+fn snake_like_with_seperator(mut accumlator: String, replace_with: &str, current_char: &char, case: &str) -> String {
+    if case == "lower" {
+        accumlator.push(replace_with.chars().nth(0).unwrap_or('_'));
+        accumlator.push(current_char.to_ascii_lowercase());
+        accumlator
+    } else {
+        accumlator.push(replace_with.chars().nth(0).unwrap_or('_'));
+        accumlator.push(current_char.to_ascii_uppercase());
+        accumlator
+    }
+}
+
+fn next_or_previous_char_is_lowercase(convertable_string: &str, char_with_index: usize) -> bool {
+    convertable_string.chars().nth(char_with_index + 1).unwrap_or('A').is_lowercase() ||
+        convertable_string.chars().nth(char_with_index - 1).unwrap_or('A').is_lowercase()
+}
+
+fn char_is_uppercase(test_char: char) -> bool {
+    test_char == test_char.to_ascii_uppercase()
+}
+
+#[test]
+fn test_trim_bad_chars() {
+    assert_eq!("abc", trim_right("abc----^"))
+}
+
+#[test]
+fn test_trim_bad_chars_when_none_are_bad() {
+    assert_eq!("abc", trim_right("abc"))
+}
+
+#[test]
+fn test_is_not_alphanumeric_on_is_alphanumeric() {
+    assert!(!is_not_alphanumeric('a'))
+}
+
+#[test]
+fn test_is_not_alphanumeric_on_is_not_alphanumeric() {
+    assert!(is_not_alphanumeric('_'))
+}
+
+
+#[test]
+fn test_char_is_uppercase_when_it_is() {
+    assert_eq!(char_is_uppercase('A'), true)
+}
+
+#[test]
+fn test_char_is_uppercase_when_it_is_not() {
+    assert_eq!(char_is_uppercase('a'), false)
+}
+
+#[test]
+fn test_next_or_previous_char_is_lowercase_true() {
+    assert_eq!(next_or_previous_char_is_lowercase("TestWWW", 3), true)
+}
+
+#[test]
+fn test_next_or_previous_char_is_lowercase_false() {
+    assert_eq!(next_or_previous_char_is_lowercase("TestWWW", 5), false)
+}
+
+#[test]
+fn snake_like_with_seperator_lowers() {
+    assert_eq!(snake_like_with_seperator("".to_owned(), "^", &'c', "lower"), "^c".to_string())
+}
+
+#[test]
+fn snake_like_with_seperator_upper() {
+    assert_eq!(snake_like_with_seperator("".to_owned(), "^", &'c', "upper"), "^C".to_string())
+}
+
+#[test]
+fn snake_like_no_seperator_lower() {
+    assert_eq!(snake_like_no_seperator("".to_owned(), &'C', "lower"), "c".to_string())
+}
+
+#[test]
+fn snake_like_no_seperator_upper() {
+    assert_eq!(snake_like_no_seperator("".to_owned(), &'c', "upper"), "C".to_string())
+}
+
+#[test]
+fn requires_seperator_upper_not_first_wrap_is_safe_current_upper() {
+    assert_eq!(requires_seperator((2, 'C'), false, "test"), true)
+}
+
+#[test]
+fn requires_seperator_upper_not_first_wrap_is_safe_current_lower() {
+    assert_eq!(requires_seperator((2, 'c'), false, "test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_upper() {
+    assert_eq!(requires_seperator((0, 'T'), true, "Test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_lower() {
+    assert_eq!(requires_seperator((0, 't'), true, "Test"), false)
+}
+
+#[test]
+fn requires_seperator_upper_first_wrap_is_safe_current_lower_next_is_too() {
+    assert_eq!(requires_seperator((0, 't'), true, "test"), false)
+}
+
+#[test]
+fn test_char_is_seperator_dash() {
+    assert_eq!(char_is_seperator(&'-'), true)
+}
+
+#[test]
+fn test_char_is_seperator_underscore() {
+    assert_eq!(char_is_seperator(&'_'), true)
+}
+
+#[test]
+fn test_char_is_seperator_space() {
+    assert_eq!(char_is_seperator(&' '), true)
+}
+
+#[test]
+fn test_char_is_seperator_when_not() {
+    assert_eq!(char_is_seperator(&'A'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_with_new_word() {
+    assert_eq!(last_char_lower_current_is_upper_or_new_word(true, ' ', '-'), true)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_space() {
+    assert_eq!(last_char_lower_current_is_upper_or_new_word(false, ' ', '-'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_lower_current_upper() {
+    assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'a', 'A'), true)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_upper_current_upper() {
+    assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'A', 'A'), false)
+}
+
+#[test]
+fn test_last_char_lower_current_is_upper_or_new_word_last_char_upper_current_lower() {
+    assert_eq!(last_char_lower_current_is_upper_or_new_word(false, 'A', 'a'), false)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_with_first_word() {
+    assert_eq!(first_word_or_not_inverted(true, false), true)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_not_first_word_not_inverted() {
+    assert_eq!(first_word_or_not_inverted(false, false), true)
+}
+
+#[test]
+fn test_first_word_or_not_inverted_not_first_word_is_inverted() {
+    assert_eq!(first_word_or_not_inverted(false, true), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_is_first_and_not_seperator() {
+    assert_eq!(not_first_word_and_has_seperator(true, false), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_not_first_and_not_seperator() {
+    assert_eq!(not_first_word_and_has_seperator(false, false), false)
+}
+
+#[test]
+fn test_not_first_word_and_has_seperator_not_first_and_has_seperator() {
+    assert_eq!(not_first_word_and_has_seperator(false, true), true)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/classcase/mod.rs
@@ -0,0 +1,393 @@
+#![deny(warnings)]
+use cases::case::*;
+#[cfg(feature = "heavyweight")]
+use string::singularize::to_singular;
+#[cfg(feature = "heavyweight")]
+/// Converts a `&str` to `ClassCase` `String`
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "FooBars";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "foo-bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "foo_bars";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::to_class_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_class_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_class_case(non_class_case_string: &str) -> String {
+    let options = CamelOptions {
+        new_word: true,
+        last_char: ' ',
+        first_word: false,
+        injectable_char: ' ',
+        has_seperator: false,
+        inverted: false,
+    };
+    let class_plural = to_case_camel_like(non_class_case_string, options);
+    let split: (&str, &str) =
+        class_plural.split_at(class_plural.rfind(char::is_uppercase).unwrap_or(0));
+    format!("{}{}", split.0, to_singular(split.1))
+}
+
+#[cfg(feature = "heavyweight")]
+/// Determines if a `&str` is `ClassCase` `bool`
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "Foo";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "foo";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongStrings";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "foo_bar_is_a_really_really_long_strings";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::classcase::is_class_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_class_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+pub fn is_class_case(test_string: &str) -> bool {
+    to_class_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+#[cfg(feature = "heavyweight")]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_class_case(b: &mut Bencher) {
+        b.iter(|| super::to_class_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_is_class(b: &mut Bencher) {
+        b.iter(|| super::is_class_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_class_from_snake(b: &mut Bencher) {
+        b.iter(|| super::to_class_case("foo_bar"));
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "heavyweight")]
+mod tests {
+    use ::to_class_case;
+    use ::is_class_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_class_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_table_case() {
+        let convertable_string: String = "foo_bars".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_case_with_loads_of_space() {
+        let convertable_string: String = "foo           bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn a_name_with_a_dot() {
+        let convertable_string: String = "Robert C. Martin".to_owned();
+        let expected: String = "RobertCMartin".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn random_text_with_bad_chars() {
+        let convertable_string: String = "Random text with *(bad) chars".to_owned();
+        let expected: String = "RandomTextWithBadChar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn trailing_bad_chars() {
+        let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+        let expected: String = "TrailingBadChar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn leading_bad_chars() {
+        let convertable_string: String = "-!#$%leading bad chars".to_owned();
+        let expected: String = "LeadingBadChar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn wrapped_in_bad_chars() {
+        let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+        let expected: String = "WrappedInBadChar".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn has_a_sign() {
+        let convertable_string: String = "has a + sign".to_owned();
+        let expected: String = "HasASign".to_owned();
+        assert_eq!(to_class_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_class_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_table_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_class_case(&convertable_string), true)
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/kebabcase/mod.rs
@@ -0,0 +1,262 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Determines if a `&str` is `kebab-case`
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::is_kebab_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_kebab_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+pub fn is_kebab_case(test_string: &str) -> bool {
+    test_string == to_kebab_case(test_string.clone())
+}
+
+/// Converts a `&str` to `kebab-case` `String`
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "foo-bar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+///
+/// ```
+///     use inflector::cases::kebabcase::to_kebab_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "foo-bar".to_string();
+///     let asserted_string: String = to_kebab_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_kebab_case(non_kebab_case_string: &str) -> String {
+    to_case_snake_like(non_kebab_case_string, "-", "lower")
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_kebab(b: &mut Bencher) {
+        b.iter(|| super::to_kebab_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_is_kebab(b: &mut Bencher) {
+        b.iter(|| super::is_kebab_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_kebab_from_snake(b: &mut Bencher) {
+        b.iter(|| super::to_kebab_case("test_test_test"));
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_kebab_case;
+    use ::is_kebab_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "foo-bar".to_owned();
+        assert_eq!(to_kebab_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_kebab_case(&convertable_string), false)
+    }
+}
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/mod.rs
@@ -0,0 +1,52 @@
+mod case;
+/// Provides conversion to and detection of class case strings.
+///
+/// This version singularizes strings.
+///
+/// Example string `ClassCase`
+pub mod classcase;
+
+/// Provides conversion to and detection of camel case strings.
+///
+/// Example string `camelCase`
+pub mod camelcase;
+
+/// Provides conversion to and detection of snake case strings.
+///
+/// Example string `snake_case`
+pub mod snakecase;
+
+/// Provides conversion to and detection of screaming snake case strings.
+///
+/// Example string `SCREAMING_SNAKE_CASE`
+pub mod screamingsnakecase;
+
+/// Provides conversion to and detection of kebab case strings.
+///
+/// Example string `kebab-case`
+pub mod kebabcase;
+
+/// Provides conversion to and detection of train case strings.
+///
+/// Example string `Train-Case`
+pub mod traincase;
+
+/// Provides conversion to and detection of sentence case strings.
+///
+/// Example string `Sentence case`
+pub mod sentencecase;
+
+/// Provides conversion to and detection of title case strings.
+///
+/// Example string `Title Case`
+pub mod titlecase;
+
+/// Provides conversion to and detection of table case strings.
+///
+/// Example string `table_cases`
+pub mod tablecase;
+
+/// Provides conversion to pascal case strings.
+///
+/// Example string `PascalCase`
+pub mod pascalcase;
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/pascalcase/mod.rs
@@ -0,0 +1,360 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to pascalCase `String`
+///
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "foo-bar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "FooBar".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::to_pascal_case;
+///     let mock_string: &str = "FooBar3";
+///     let expected_string: String = "FooBar3".to_string();
+///     let asserted_string: String = to_pascal_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_pascal_case(non_pascalized_string: &str) -> String {
+    let options = CamelOptions {
+        new_word: true,
+        last_char: ' ',
+        first_word: false,
+        injectable_char: ' ',
+        has_seperator: false,
+        inverted: false,
+    };
+    to_case_camel_like(non_pascalized_string, options)
+}
+
+/// Determines if a `&str` is pascalCase bool``
+///
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "Foo";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "foo";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "FooBarIsAReallyReally3LongString";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+///
+/// ```
+/// ```
+///     use inflector::cases::pascalcase::is_pascal_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_pascal_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+pub fn is_pascal_case(test_string: &str) -> bool {
+    to_pascal_case(test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_pascal0(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "Foo bar";
+            super::to_pascal_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_pascal1(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "foo_bar";
+            super::to_pascal_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_pascal2(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string = "fooBar";
+            super::to_pascal_case(test_string)
+        });
+    }
+
+    #[bench]
+    fn bench_is_pascal(b: &mut Bencher) {
+        b.iter(|| {
+            let test_string: &str = "Foo bar";
+            super::is_pascal_case(test_string)
+        });
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_pascal_case;
+    use ::is_pascal_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_case_with_loads_of_space() {
+        let convertable_string: String = "foo           bar".to_owned();
+        let expected: String = "FooBar".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn a_name_with_a_dot() {
+        let convertable_string: String = "Robert C. Martin".to_owned();
+        let expected: String = "RobertCMartin".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn random_text_with_bad_chars() {
+        let convertable_string: String = "Random text with *(bad) chars".to_owned();
+        let expected: String = "RandomTextWithBadChars".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn trailing_bad_chars() {
+        let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+        let expected: String = "TrailingBadChars".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn leading_bad_chars() {
+        let convertable_string: String = "-!#$%leading bad chars".to_owned();
+        let expected: String = "LeadingBadChars".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn wrapped_in_bad_chars() {
+        let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+        let expected: String = "WrappedInBadChars".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn has_a_sign() {
+        let convertable_string: String = "has a + sign".to_owned();
+        let expected: String = "HasASign".to_owned();
+        assert_eq!(to_pascal_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_pascal_case(&convertable_string), false)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/screamingsnakecase/mod.rs
@@ -0,0 +1,253 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `SCREAMING_SNAKE_CASE` `String`
+///
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "HTTP Foo bar";
+///     let expected_string: String = "HTTP_FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "FOO_BAR".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::to_screaming_snake_case;
+///     let mock_string: &str = "fooBar3";
+///     let expected_string: String = "FOO_BAR_3".to_string();
+///     let asserted_string: String = to_screaming_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_screaming_snake_case(non_snake_case_string: &str) -> String {
+    to_case_snake_like(non_snake_case_string, "_", "upper")
+}
+
+/// Determines of a `&str` is `SCREAMING_SNAKE_CASE`
+///
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "FOO_BAR1_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+///     use inflector::cases::screamingsnakecase::is_screaming_snake_case;
+///     let mock_string: &str = "FOO_BAR_1_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_screaming_snake_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_screaming_snake_case(test_string: &str) -> bool {
+    test_string == to_screaming_snake_case(test_string.clone())
+}
+
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_screaming_snake(b: &mut Bencher) {
+        b.iter(|| super::to_screaming_snake_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_is_screaming_snake(b: &mut Bencher) {
+        b.iter(|| super::is_screaming_snake_case("Foo bar"));
+    }
+
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_screaming_snake_case;
+    use ::is_screaming_snake_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "FOO_BAR".to_owned();
+        assert_eq!(to_screaming_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_screaming_snake_case(&convertable_string), false)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/sentencecase/mod.rs
@@ -0,0 +1,313 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `Sentence case` `String`
+///
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::to_sentence_case;
+///     let mock_string: &str = "foo-bar";
+///     let expected_string: String = "Foo bar".to_string();
+///     let asserted_string: String = to_sentence_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_sentence_case(non_sentence_case_string: &str) -> String {
+    let options = CamelOptions {
+        new_word: true,
+        last_char: ' ',
+        first_word: true,
+        injectable_char: ' ',
+        has_seperator: true,
+        inverted: true,
+    };
+    to_case_camel_like(non_sentence_case_string, options)
+}
+/// Determines of a `&str` is `Sentence case`
+///
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "Foo";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "foo";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::sentencecase::is_sentence_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_sentence_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_sentence_case(test_string: &str) -> bool {
+    test_string == to_sentence_case(test_string.clone())
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_sentence(b: &mut Bencher) {
+        b.iter(|| super::to_sentence_case("Foo BAR"));
+    }
+
+    #[bench]
+    fn bench_is_sentence(b: &mut Bencher) {
+        b.iter(|| super::is_sentence_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_sentence_from_snake(b: &mut Bencher) {
+        b.iter(|| super::to_sentence_case("foo_bar"));
+    }
+
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_sentence_case;
+    use ::is_sentence_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_case_with_loads_of_space() {
+        let convertable_string: String = "foo           bar".to_owned();
+        let expected: String = "Foo bar".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn a_name_with_a_dot() {
+        let convertable_string: String = "Robert C. Martin".to_owned();
+        let expected: String = "Robert c martin".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn random_text_with_bad_chars() {
+        let convertable_string: String = "Random text with *(bad) chars".to_owned();
+        let expected: String = "Random text with bad chars".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn trailing_bad_chars() {
+        let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+        let expected: String = "Trailing bad chars".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn leading_bad_chars() {
+        let convertable_string: String = "-!#$%leading bad chars".to_owned();
+        let expected: String = "Leading bad chars".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn wrapped_in_bad_chars() {
+        let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+        let expected: String = "Wrapped in bad chars".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn has_a_sign() {
+        let convertable_string: String = "has a + sign".to_owned();
+        let expected: String = "Has a sign".to_owned();
+        assert_eq!(to_sentence_case(&convertable_string), expected)
+    }
+
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), true)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_sentence_case(&convertable_string), false)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/snakecase/mod.rs
@@ -0,0 +1,334 @@
+#![deny(warnings)]
+use cases::case::*;
+/// Converts a `&str` to `snake_case` `String`
+///
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "foo_bar";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "HTTP Foo bar";
+///     let expected_string: String = "http_foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "HTTPFooBar";
+///     let expected_string: String = "http_foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "Foo bar";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "Foo Bar";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "FooBar";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "FOO_BAR";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "fooBar";
+///     let expected_string: String = "foo_bar".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::to_snake_case;
+///     let mock_string: &str = "fooBar3";
+///     let expected_string: String = "foo_bar_3".to_string();
+///     let asserted_string: String = to_snake_case(mock_string);
+///     assert!(asserted_string == expected_string);
+///
+/// ```
+pub fn to_snake_case(non_snake_case_string: &str) -> String {
+    to_case_snake_like(non_snake_case_string, "_", "lower")
+}
+
+/// Determines of a `&str` is `snake_case`
+///
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "FOO_BAR_IS_A_REALLY_REALLY_LONG_STRING";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "foo_bar1_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == false);
+///
+/// ```
+/// ```
+///     use inflector::cases::snakecase::is_snake_case;
+///     let mock_string: &str = "foo_bar_1_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_snake_case(mock_string);
+///     assert!(asserted_bool == true);
+///
+/// ```
+pub fn is_snake_case(test_string: &str) -> bool {
+    test_string == to_snake_case(test_string.clone())
+}
+
+#[cfg(all(feature = "unstable", test))]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_snake_from_title(b: &mut Bencher) {
+        b.iter(|| super::to_snake_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_snake_from_camel(b: &mut Bencher) {
+        b.iter(|| super::to_snake_case("fooBar"));
+    }
+
+    #[bench]
+    fn bench_snake_from_snake(b: &mut Bencher) {
+        b.iter(|| super::to_snake_case("foo_bar_bar_bar"));
+    }
+
+    #[bench]
+    fn bench_is_snake(b: &mut Bencher) {
+        b.iter(|| super::is_snake_case("Foo bar"));
+    }
+
+}
+
+#[cfg(test)]
+mod tests {
+    use ::to_snake_case;
+    use ::is_snake_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_case_with_loads_of_space() {
+        let convertable_string: String = "foo           bar".to_owned();
+        let expected: String = "foo_bar".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn a_name_with_a_dot() {
+        let convertable_string: String = "Robert C. Martin".to_owned();
+        let expected: String = "robert_c_martin".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn random_text_with_bad_chars() {
+        let convertable_string: String = "Random text with *(bad) chars".to_owned();
+        let expected: String = "random_text_with_bad_chars".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn trailing_bad_chars() {
+        let convertable_string: String = "trailing bad_chars*(()())".to_owned();
+        let expected: String = "trailing_bad_chars".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn leading_bad_chars() {
+        let convertable_string: String = "-!#$%leading bad chars".to_owned();
+        let expected: String = "leading_bad_chars".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn wrapped_in_bad_chars() {
+        let convertable_string: String = "-!#$%wrapped in bad chars&*^*&(&*^&(<><?>><?><>))".to_owned();
+        let expected: String = "wrapped_in_bad_chars".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn has_a_sign() {
+        let convertable_string: String = "has a + sign".to_owned();
+        let expected: String = "has_a_sign".to_owned();
+        assert_eq!(to_snake_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        assert_eq!(is_snake_case(&convertable_string), true)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/Inflector/src/cases/tablecase/mod.rs
@@ -0,0 +1,271 @@
+#![deny(warnings)]
+#[cfg(feature = "heavyweight")]
+use string::pluralize::to_plural;
+#[cfg(feature = "heavyweight")]
+use cases::case::*;
+#[cfg(feature = "heavyweight")]
+/// Converts a `&str` to `table-case` `String`
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "foo-bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "FOO_BAR";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "foo_bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "Foo Bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "Foo bar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "FooBar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+///
+/// ```
+/// use inflector::cases::tablecase::to_table_case;
+/// let mock_string: &str = "fooBar";
+/// let expected_string: String = "foo_bars".to_string();
+/// let asserted_string: String = to_table_case(mock_string);
+/// assert!(asserted_string == expected_string);
+/// ```
+pub fn to_table_case(non_table_case_string: &str) -> String {
+    let snaked: String = to_case_snake_like(non_table_case_string, "_", "lower");
+    let split: (&str, &str) = snaked.split_at(snaked.rfind('_').unwrap_or(0));
+    format!("{}{}", split.0, to_plural(split.1))
+}
+
+#[cfg(feature = "heavyweight")]
+/// Determines if a `&str` is `table-case`
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "foo_bar_strings";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == true);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "foo-bar-string-that-is-really-really-long";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "FooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "fooBarIsAReallyReallyLongString";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "FOO_BAR_STRING_THAT_IS_REALLY_REALLY_LONG";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "foo_bar_string_that_is_really_really_long";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "Foo bar string that is really really long";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+///
+/// ```
+///     use inflector::cases::tablecase::is_table_case;
+///     let mock_string: &str = "Foo Bar Is A Really Really Long String";
+///     let asserted_bool: bool = is_table_case(mock_string);
+///     assert!(asserted_bool == false);
+/// ```
+pub fn is_table_case(test_string: &str) -> bool {
+     to_table_case(&test_string.clone()) == test_string
+}
+
+#[cfg(all(feature = "unstable", test))]
+#[cfg(feature = "heavyweight")]
+mod benchmarks {
+    extern crate test;
+    use self::test::Bencher;
+
+    #[bench]
+    fn bench_table_case(b: &mut Bencher) {
+        b.iter(|| super::to_table_case("Foo bar"));
+    }
+
+    #[bench]
+    fn bench_is_table_case(b: &mut Bencher) {
+        b.iter(|| super::is_table_case("Foo bar"));
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "heavyweight")]
+mod tests {
+    use ::to_table_case;
+    use ::is_table_case;
+
+    #[test]
+    fn from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_snake_case() {
+        let convertable_string: String = "foo_bar".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn from_table_case() {
+        let convertable_string: String = "foo_bars".to_owned();
+        let expected: String = "foo_bars".to_owned();
+        assert_eq!(to_table_case(&convertable_string), expected)
+    }
+
+    #[test]
+    fn is_correct_from_camel_case() {
+        let convertable_string: String = "fooBar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_pascal_case() {
+        let convertable_string: String = "FooBar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_kebab_case() {
+        let convertable_string: String = "foo-bar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_sentence_case() {
+        let convertable_string: String = "Foo bar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_title_case() {
+        let convertable_string: String = "Foo Bar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_train_case() {
+        let convertable_string: String = "Foo-Bar".to_owned();
+        assert_eq!(is_table_case(&convertable_string), false)
+    }
+
+    #[test]
+    fn is_correct_from_screaming_snake_case() {
+        let convertable_string: String = "FOO_BAR".to_owned();