Bug 1437004 - Vendored Rust dependencies;r=froydnj
authorDavid Teller <dteller@mozilla.com>
Wed, 04 Apr 2018 14:14:26 +0200
changeset 412088 a97cccaa866a0fbd5721842ad8d8e862cd26ea65
parent 412087 47406f36e6ab0f69141d3b2f006e494d4c9f03a0
child 412089 3f27c2b65ef409b60ded331682a95e224f77a65c
push id33784
push usernerli@mozilla.com
push dateFri, 06 Apr 2018 21:54:36 +0000
treeherdermozilla-central@0e0ec6c01e25 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1437004
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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]]
@@ -548,16 +634,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"
 
@@ -574,16 +661,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)",
 ]
 
@@ -833,16 +925,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"
@@ -879,16 +979,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"
@@ -936,16 +1091,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]]
@@ -1256,16 +1416,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]]
@@ -1295,16 +1460,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.2"
 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)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2207,39 +2429,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"
@@ -2269,25 +2505,29 @@ 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.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.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "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"
@@ -2299,28 +2539,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"
@@ -2336,21 +2582,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"
@@ -2380,22 +2628,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"
@@ -2416,19 +2668,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