Bug 1336540 part 2 - Vendor toml. r=froydnj draft
authorXidorn Quan <me@upsuper.org>
Thu, 18 May 2017 18:17:19 +1000
changeset 580845 54498689cdcf28c58b6ee1922e057ffc8a50da45
parent 580844 36bcb2c10614c9b9f597f13d302953f9af14f928
child 629399 8caa7339042065caa8fb51274e7eb15ec6f520ea
push id59676
push userxquan@mozilla.com
push dateFri, 19 May 2017 00:58:20 +0000
reviewersfroydnj
bugs1336540
milestone55.0a1
Bug 1336540 part 2 - Vendor toml. r=froydnj MozReview-Commit-ID: LmZgzyxTLwc
third_party/rust/toml/.cargo-checksum.json
third_party/rust/toml/.cargo-ok
third_party/rust/toml/.gitignore
third_party/rust/toml/.travis.yml
third_party/rust/toml/Cargo.toml
third_party/rust/toml/LICENSE-APACHE
third_party/rust/toml/LICENSE-MIT
third_party/rust/toml/README.md
third_party/rust/toml/examples/toml2json.rs
third_party/rust/toml/src/decoder/mod.rs
third_party/rust/toml/src/decoder/rustc_serialize.rs
third_party/rust/toml/src/decoder/serde.rs
third_party/rust/toml/src/display.rs
third_party/rust/toml/src/encoder/mod.rs
third_party/rust/toml/src/encoder/rustc_serialize.rs
third_party/rust/toml/src/encoder/serde.rs
third_party/rust/toml/src/lib.rs
third_party/rust/toml/src/parser.rs
third_party/rust/toml/tests/README.md
third_party/rust/toml/tests/formatting.rs
third_party/rust/toml/tests/invalid-encoder/array-mixed-types-ints-and-floats.json
third_party/rust/toml/tests/invalid.rs
third_party/rust/toml/tests/invalid/array-mixed-types-arrays-and-ints.toml
third_party/rust/toml/tests/invalid/array-mixed-types-ints-and-floats.toml
third_party/rust/toml/tests/invalid/array-mixed-types-strings-and-ints.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-leads.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-secs.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-t.toml
third_party/rust/toml/tests/invalid/datetime-malformed-no-z.toml
third_party/rust/toml/tests/invalid/datetime-malformed-with-milli.toml
third_party/rust/toml/tests/invalid/duplicate-key-table.toml
third_party/rust/toml/tests/invalid/duplicate-keys.toml
third_party/rust/toml/tests/invalid/duplicate-tables.toml
third_party/rust/toml/tests/invalid/empty-implicit-table.toml
third_party/rust/toml/tests/invalid/empty-table.toml
third_party/rust/toml/tests/invalid/float-no-leading-zero.toml
third_party/rust/toml/tests/invalid/float-no-trailing-digits.toml
third_party/rust/toml/tests/invalid/key-after-array.toml
third_party/rust/toml/tests/invalid/key-after-table.toml
third_party/rust/toml/tests/invalid/key-empty.toml
third_party/rust/toml/tests/invalid/key-hash.toml
third_party/rust/toml/tests/invalid/key-newline.toml
third_party/rust/toml/tests/invalid/key-open-bracket.toml
third_party/rust/toml/tests/invalid/key-single-open-bracket.toml
third_party/rust/toml/tests/invalid/key-space.toml
third_party/rust/toml/tests/invalid/key-start-bracket.toml
third_party/rust/toml/tests/invalid/key-two-equals.toml
third_party/rust/toml/tests/invalid/string-bad-byte-escape.toml
third_party/rust/toml/tests/invalid/string-bad-escape.toml
third_party/rust/toml/tests/invalid/string-byte-escapes.toml
third_party/rust/toml/tests/invalid/string-no-close.toml
third_party/rust/toml/tests/invalid/table-array-implicit.toml
third_party/rust/toml/tests/invalid/table-array-malformed-bracket.toml
third_party/rust/toml/tests/invalid/table-array-malformed-empty.toml
third_party/rust/toml/tests/invalid/table-empty.toml
third_party/rust/toml/tests/invalid/table-nested-brackets-close.toml
third_party/rust/toml/tests/invalid/table-nested-brackets-open.toml
third_party/rust/toml/tests/invalid/table-whitespace.toml
third_party/rust/toml/tests/invalid/table-with-pound.toml
third_party/rust/toml/tests/invalid/text-after-array-entries.toml
third_party/rust/toml/tests/invalid/text-after-integer.toml
third_party/rust/toml/tests/invalid/text-after-string.toml
third_party/rust/toml/tests/invalid/text-after-table.toml
third_party/rust/toml/tests/invalid/text-before-array-separator.toml
third_party/rust/toml/tests/invalid/text-in-array.toml
third_party/rust/toml/tests/valid.rs
third_party/rust/toml/tests/valid/array-empty.json
third_party/rust/toml/tests/valid/array-empty.toml
third_party/rust/toml/tests/valid/array-nospaces.json
third_party/rust/toml/tests/valid/array-nospaces.toml
third_party/rust/toml/tests/valid/arrays-hetergeneous.json
third_party/rust/toml/tests/valid/arrays-hetergeneous.toml
third_party/rust/toml/tests/valid/arrays-nested.json
third_party/rust/toml/tests/valid/arrays-nested.toml
third_party/rust/toml/tests/valid/arrays.json
third_party/rust/toml/tests/valid/arrays.toml
third_party/rust/toml/tests/valid/bool.json
third_party/rust/toml/tests/valid/bool.toml
third_party/rust/toml/tests/valid/comments-everywhere.json
third_party/rust/toml/tests/valid/comments-everywhere.toml
third_party/rust/toml/tests/valid/datetime.json
third_party/rust/toml/tests/valid/datetime.toml
third_party/rust/toml/tests/valid/empty.json
third_party/rust/toml/tests/valid/empty.toml
third_party/rust/toml/tests/valid/example-bom.toml
third_party/rust/toml/tests/valid/example-v0.3.0.json
third_party/rust/toml/tests/valid/example-v0.3.0.toml
third_party/rust/toml/tests/valid/example-v0.4.0.json
third_party/rust/toml/tests/valid/example-v0.4.0.toml
third_party/rust/toml/tests/valid/example.json
third_party/rust/toml/tests/valid/example.toml
third_party/rust/toml/tests/valid/example2.json
third_party/rust/toml/tests/valid/example2.toml
third_party/rust/toml/tests/valid/float.json
third_party/rust/toml/tests/valid/float.toml
third_party/rust/toml/tests/valid/hard_example.json
third_party/rust/toml/tests/valid/hard_example.toml
third_party/rust/toml/tests/valid/implicit-and-explicit-after.json
third_party/rust/toml/tests/valid/implicit-and-explicit-after.toml
third_party/rust/toml/tests/valid/implicit-and-explicit-before.json
third_party/rust/toml/tests/valid/implicit-and-explicit-before.toml
third_party/rust/toml/tests/valid/implicit-groups.json
third_party/rust/toml/tests/valid/implicit-groups.toml
third_party/rust/toml/tests/valid/integer.json
third_party/rust/toml/tests/valid/integer.toml
third_party/rust/toml/tests/valid/key-equals-nospace.json
third_party/rust/toml/tests/valid/key-equals-nospace.toml
third_party/rust/toml/tests/valid/key-space.json
third_party/rust/toml/tests/valid/key-space.toml
third_party/rust/toml/tests/valid/key-special-chars.json
third_party/rust/toml/tests/valid/key-special-chars.toml
third_party/rust/toml/tests/valid/key-with-pound.json
third_party/rust/toml/tests/valid/key-with-pound.toml
third_party/rust/toml/tests/valid/long-float.json
third_party/rust/toml/tests/valid/long-float.toml
third_party/rust/toml/tests/valid/long-integer.json
third_party/rust/toml/tests/valid/long-integer.toml
third_party/rust/toml/tests/valid/multiline-string.json
third_party/rust/toml/tests/valid/multiline-string.toml
third_party/rust/toml/tests/valid/raw-multiline-string.json
third_party/rust/toml/tests/valid/raw-multiline-string.toml
third_party/rust/toml/tests/valid/raw-string.json
third_party/rust/toml/tests/valid/raw-string.toml
third_party/rust/toml/tests/valid/string-empty.json
third_party/rust/toml/tests/valid/string-empty.toml
third_party/rust/toml/tests/valid/string-escapes.json
third_party/rust/toml/tests/valid/string-escapes.toml
third_party/rust/toml/tests/valid/string-simple.json
third_party/rust/toml/tests/valid/string-simple.toml
third_party/rust/toml/tests/valid/string-with-pound.json
third_party/rust/toml/tests/valid/string-with-pound.toml
third_party/rust/toml/tests/valid/table-array-implicit.json
third_party/rust/toml/tests/valid/table-array-implicit.toml
third_party/rust/toml/tests/valid/table-array-many.json
third_party/rust/toml/tests/valid/table-array-many.toml
third_party/rust/toml/tests/valid/table-array-nest.json
third_party/rust/toml/tests/valid/table-array-nest.toml
third_party/rust/toml/tests/valid/table-array-one.json
third_party/rust/toml/tests/valid/table-array-one.toml
third_party/rust/toml/tests/valid/table-empty.json
third_party/rust/toml/tests/valid/table-empty.toml
third_party/rust/toml/tests/valid/table-sub-empty.json
third_party/rust/toml/tests/valid/table-sub-empty.toml
third_party/rust/toml/tests/valid/table-whitespace.json
third_party/rust/toml/tests/valid/table-whitespace.toml
third_party/rust/toml/tests/valid/table-with-pound.json
third_party/rust/toml/tests/valid/table-with-pound.toml
third_party/rust/toml/tests/valid/unicode-escape.json
third_party/rust/toml/tests/valid/unicode-escape.toml
third_party/rust/toml/tests/valid/unicode-literal.json
third_party/rust/toml/tests/valid/unicode-literal.toml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"7d917e42244b1d0d0304a11e8ef45bbc34e2a859bf35a752ed6069920a7cc8c5","Cargo.toml":"996f64a3b649cb71b337b03882f63e487de78fbddb97734c67c6fca015976f2c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"a3505a33e4973ac97b3c7189f7b56b3a5f483218f1a23da5f625a718ad9adc16","examples/toml2json.rs":"d1980e1d53e712ea6f9d6b3a36ce156b075bf8c1dd7660c2947e7b81106ea41c","src/decoder/mod.rs":"23c4045e9131b26ea772797f4dc65a57fab4e4a59b340dcceb094db9dd5cc02e","src/decoder/rustc_serialize.rs":"e5fc97516f38a5997c514318c857173cc7ebfc9b06b0b0517127bdc02c18c625","src/decoder/serde.rs":"7cae3e1d2795d53c351f98b7d010dc4d579ac93f9e3e44dc307b9eca2186f2cc","src/display.rs":"2a9fea5f27328412dd3168571a94645711714261fef1f9348e4cab56138a640e","src/encoder/mod.rs":"b7af37d6cab330bb749717274d821cf34599cf210f19daa431fb0fdb0ef3c2b8","src/encoder/rustc_serialize.rs":"d444ea1995d4cba19ab6e17eabc9246070787a58d2b430997b55d6e1a88a5c30","src/encoder/serde.rs":"eb1d0237fa5d1d4367bcf3cff287cb10b9467d05ab817a696d7a6316350cdd11","src/lib.rs":"6c7e98f283e3263587c628c216ea2274375ab81286070937cec7cc79d82eed01","src/parser.rs":"6bb7694a3ad138b1ffafa6d9fc1dec342ea34af0219b2f560f3777014a21481b","tests/README.md":"3e7d07d64c34e117c3d862ee12e4947af8c133fb0b53f6f0de43cc3bfa5057b8","tests/formatting.rs":"bc672504cedbf956de645073baab876baf06c7f2bc120db20d27b1446c8b5f4b","tests/invalid-encoder/array-mixed-types-ints-and-floats.json":"206d2a353153efbcee74e7ee7b0f852e7a948cfb88417f74607b3ad6f020e373","tests/invalid.rs":"ef9b613246634673e43f95b8688f275d22726f41fb9ecb824504217e6f5d5c58","tests/invalid/array-mixed-types-arrays-and-ints.toml":"c1547b686357c7a865e333a7ce7eed1e30743ebc4daac8ea6148bdd84b7e4dc7","tests/invalid/array-mixed-types-ints-and-floats.toml":"baa235fc168869716680955fd5bdafab30b6fa9b3d09185086261a56ef12960e","tests/invalid/array-mixed-types-strings-and-ints.toml":"4440057ed90d4461db0be55cfd71299cad96b601d5faec2140666242f6fde147","tests/invalid/datetime-malformed-no-leads.toml":"1fa6bf72ea0b96be835ac031408f7acfd0b8d18d5f54b4c0fce8136aad27d22e","tests/invalid/datetime-malformed-no-secs.toml":"b9c30b7fa1847c80e381d68cc79834eefbb8813cd0eff465fb7cbe0733df429b","tests/invalid/datetime-malformed-no-t.toml":"490a46d2e707ef4f87987ec12a22afa5a71c97c5eaa0f4201a174c47846c6a4a","tests/invalid/datetime-malformed-no-z.toml":"6ca48b84c444b3ca51a480aa9688dd1044861010aff674a67e5cec34fd2eb489","tests/invalid/datetime-malformed-with-milli.toml":"62bfd0a6645bcb3f78211523e5673a3d1fa726d9e942c1643df243d6fba474c8","tests/invalid/duplicate-key-table.toml":"a896ea2180d16fcdd4f6c30aa27529b5b29e7e195a4e7a9944343028783602e9","tests/invalid/duplicate-keys.toml":"4bb0a65c22e7704893a2a51334eb2518af702850ef59aeecd5226e7b26bc07ec","tests/invalid/duplicate-tables.toml":"23b16ce26e1155ee6bf1fff559701dce86475c6a2878536b61f6b7e68be340de","tests/invalid/empty-implicit-table.toml":"d6026110dc0dee7babd69592218819328caa425f48cc879e895b29e48550c06c","tests/invalid/empty-table.toml":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","tests/invalid/float-no-leading-zero.toml":"159654461094c938574ba2d2d09baa3d3c387dd6ed024fd411530c0573a1ec42","tests/invalid/float-no-trailing-digits.toml":"64e4f336186cd096be2804532dbd694dd50ea551d292a9cdbf0bef2abf227101","tests/invalid/key-after-array.toml":"314af33770170b53bf2ec3be43ea1609d981c81d62c968052499b85ed54ccce8","tests/invalid/key-after-table.toml":"ed0dcf38f003d184dd18d1518702da0115cbfb05a5a28cbcf42de2f9bdee05fa","tests/invalid/key-empty.toml":"4303477abf4c0b920b42e96edd61caecf9c1f2d5d97f56af876854cd725aff3c","tests/invalid/key-hash.toml":"cd2a2eba6032d32c829633d3cd2778aeba81f5ff554e69f62af6557d1dc712f6","tests/invalid/key-newline.toml":"06a313a6bd70c2db6a1f5bda479d854d8f87e037e3cabf18fb5db822466ffcac","tests/invalid/key-open-bracket.toml":"52dea939022949290e3a19f1291d15605429344dce3cd1aa1f1568ecad8ca365","tests/invalid/key-single-open-bracket.toml":"245843abef9e72e7efac30138a994bf6301e7e1d7d7042a33d42e863d2638811","tests/invalid/key-space.toml":"b4e336d07c27fb3d0f0a6e50b733e1546202dfd58aaf2f7956f56fd6f075b0a1","tests/invalid/key-start-bracket.toml":"3bd3748a9df1d25ab2661330a3da187bd4da3958292bbf0e8b59d7963634dd87","tests/invalid/key-two-equals.toml":"3ac0c4e339d47c86e57564e43147b772ae83933b78083dc78d0ef77e231df3f1","tests/invalid/string-bad-byte-escape.toml":"c665dcec7c02f442c4fdc80423698eed2376ce65779cf855371772293bec2927","tests/invalid/string-bad-escape.toml":"eeca691fbba3d270f58ae2953d2d1369a773e619e39d8c11f38d6bf6f8472e82","tests/invalid/string-byte-escapes.toml":"4a4604b32971de3a252cd01d2997b450972c3ec9030cf22a070d49c57f050da4","tests/invalid/string-no-close.toml":"bb2eaf96eb9f83a52bd0772abb313060a06b94f650efeb45edce774622686882","tests/invalid/table-array-implicit.toml":"9b841ea64d68be4deb54f67fc807b05fd235452ee563ffa7de69dbca64b2f7dd","tests/invalid/table-array-malformed-bracket.toml":"164f641b2628bf04f8202d9746a360a4a243faca1408dc2ecd0c0fdd2d1c2c27","tests/invalid/table-array-malformed-empty.toml":"56ca2a15019cf5c3555041a191f983dc72b1678f0de0afd1a7b8f46ed7970420","tests/invalid/table-empty.toml":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","tests/invalid/table-nested-brackets-close.toml":"991e1210f81e24abcd735988f0d960d4ee94d2ec3b133c6fea6e24932d91c507","tests/invalid/table-nested-brackets-open.toml":"8fb569fc90fa606ae94708ee2bf205bff8db8a023624b3e52ef6b2c1a98ba1c6","tests/invalid/table-whitespace.toml":"2c2db1259adc641df0459e896d349d3db60965d5368d5c8ed50aedd3bc88f040","tests/invalid/table-with-pound.toml":"d8070437f07bd115ac8006c61e286401bd3be88728a62264796e757121750ecd","tests/invalid/text-after-array-entries.toml":"2530cace13292313983b90b01d63e4b8ac484809e7ef0ac79904923573eda7ec","tests/invalid/text-after-integer.toml":"6168ed823a135b8914956b04307aeec2347b10eb1aa79008406d7b547cbde682","tests/invalid/text-after-string.toml":"1771987dd679e1cc181cf53406ba313fdc3413a081d17a93da6041bf6ccccf5e","tests/invalid/text-after-table.toml":"f27ae56bb0b42d3af4c813392857afdfeb4bf8ab77ff896cd93ba32cf1a21b26","tests/invalid/text-before-array-separator.toml":"192d28699573abbdc521797576d4885adf756336c3e76971f10270603c957464","tests/invalid/text-in-array.toml":"50d7b16d7a03d470f1a907eebfeb156d0c696e6f9a8c734a5e4caa2365f54654","tests/valid.rs":"d2199e449a1f6b5aab1914f7b739ae0f496657ca249aa3b9bcdd85b89075e4e4","tests/valid/array-empty.json":"4ed46e8aa3586a7ddd9097cda38919699860052f188880de18e12d4acbee5307","tests/valid/array-empty.toml":"769faa42a690b02ad1b573277f0d793a4a38a7ecf30b9db67bf9836fe2b7778c","tests/valid/array-nospaces.json":"7c82b474797871488c2b522e9b852772a78c681a86900f780f7a0be4f901e1ec","tests/valid/array-nospaces.toml":"01fba63551b1051f7e117c9551c488b293bd3cd4745cbeec6b3709c32f2a3a64","tests/valid/arrays-hetergeneous.json":"dac4702412c90d5ddd6b898c3657c71d782d0aca46e5b9ca19cc694d3e226c0f","tests/valid/arrays-hetergeneous.toml":"361ae2e8470b47b12b336eb61eedd09abb20e216fbeb582b46d16a2831adda4d","tests/valid/arrays-nested.json":"34d6f8fd770f0728f38dbf0d686bed2c218bc16da978290c0208d3bf3704bdec","tests/valid/arrays-nested.toml":"a5941a01a2ba2fa179a3885039a5f81ca6c9876b2e8bea7b880563238be9f004","tests/valid/arrays.json":"315fff195a7d4c80e867e1f14c12a23e36dcc666e8de36138249b15e99bdd4dd","tests/valid/arrays.toml":"2d3c91b77d4f6a65a6a5a2c5ad521dbe86cc2f0ff389dfe58e8c34275cdc35c7","tests/valid/bool.json":"bb608b912fe4d89cb2186da957c10951780575bb34b2f43305335c745eff049c","tests/valid/bool.toml":"3c06ad4dce7430326f5f867105b2e9382def90cccb3ecb69f657c0b88974ab04","tests/valid/comments-everywhere.json":"800f8efd86d1bab4f91f0e367da52a2465e1480387df892561ed8948fd1a38c3","tests/valid/comments-everywhere.toml":"8636108c34f50d45244b142d342234b7535e01fba2db2d2ffed3430223009cea","tests/valid/datetime.json":"94f130c3b2a5f30c625a3a3168b9dfe52aa109b470c4e077f352b3dd79382a69","tests/valid/datetime.toml":"4e1b71ba31a1feef80a1e436225aa9c5d291bf780f558e7cfa76998fe2a29e08","tests/valid/empty.json":"ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356","tests/valid/empty.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","tests/valid/example-bom.toml":"50f3607be97de2f894ccd41a29d3a8a1b1f430982e5ab5bf43047874837f6a42","tests/valid/example-v0.3.0.json":"ec02332eb59dab93a50560771e4b01b972a29d93b6dca8954728c0631e1799a0","tests/valid/example-v0.3.0.toml":"aba9349588c1ba6af2a3ad0c1db2c3d311dca66b64f654480340a0823dfd4546","tests/valid/example-v0.4.0.json":"8b967b246ca2383172eaaecf790b2115a18020f63c70d0848d1dc25fc1fed5a9","tests/valid/example-v0.4.0.toml":"47ee4c4cd83637cd09aca6518f88c8ed56acc2b3022e5ea53d9121e5d35335ed","tests/valid/example.json":"c57fabb1be0ae7ed140fe7ae5082051571c85180204b8ae8d8da1e86133278c9","tests/valid/example.toml":"6f02b2a52ea63c70b629e41e06a8eb1eb4aab359ab966a7a397b248e13849c9c","tests/valid/example2.json":"de89432e78f0a074aae54650fedf151ceca3b0ccb148b8a66e18e2ed68024ba2","tests/valid/example2.toml":"c389eeb485fb7cb9445d617a9a0f8ba70049f08d66cf6b6f2a9a986574295de1","tests/valid/float.json":"9676c13fef00a01bc729456bfe27f1b24a1bd059c9a5913bb0b0401e976a0aab","tests/valid/float.toml":"b6784f554aa38bb210f0905c3bafdfae6db723a4f53288fb07febc66451bbc2d","tests/valid/hard_example.json":"8d170e73e156b8b6be559246880e9cb6a79b36f63d14bc97e3bdf2f2091e7a17","tests/valid/hard_example.toml":"cd3b89f8917a44f944b12fe47f69f86bb39f17db85d1a081bf0c134831eb90f9","tests/valid/implicit-and-explicit-after.json":"6dcaeaf8ee3479bf2cd5c14eb58970757175aaefab014bce9acb0b85e7bf9dd0","tests/valid/implicit-and-explicit-after.toml":"0599b16822764cdb1c3d3cf53f71186b97afc9f60f8d58358a4a89fe4d9477c3","tests/valid/implicit-and-explicit-before.json":"6dcaeaf8ee3479bf2cd5c14eb58970757175aaefab014bce9acb0b85e7bf9dd0","tests/valid/implicit-and-explicit-before.toml":"33435dddb68144b652ca5f5e0c4c53e4f7b3ca0166f9b944eda55f8d76ed2871","tests/valid/implicit-groups.json":"fc2bb43ec20c8c9148c8a70490b3a054506932c41687222ea11faae47eafb723","tests/valid/implicit-groups.toml":"248b3e8272ec43ce4af872981acde10628eeae73537ed6763a1f4245f5a9610c","tests/valid/integer.json":"0fc2d0cb1fb46d7805c1007b1fa4c46a65b273e56ae9d751df686e81d3a3354f","tests/valid/integer.toml":"74b964eb9561be6aa7266f6034cee1cd0657bdab8043a5ec9da33d9b184345da","tests/valid/key-equals-nospace.json":"b9878ee3585d1b48710a4bc09f2163b910ea71a2bfdaa8f1da68e599e8b30f47","tests/valid/key-equals-nospace.toml":"24cab0d01b67b184d0a737de3a5b5d47b8b69b36203273296d5ef763f7fdcf68","tests/valid/key-space.json":"30be539b01420be5cedc9078b88c3279bbef7c0bdde36ba8249ed8906112d5c7","tests/valid/key-space.toml":"9e9459b8cfebc404cf93d77c2d4082cadcd57165a2f9ce9cb35d1d12dc94a8c0","tests/valid/key-special-chars.json":"8bbebb20660d93efa73707bdb09e87a43c2b31c18f13df6388c701a1bc7cab8c","tests/valid/key-special-chars.toml":"c6cb0ba12d32f03cda4206097a1edb27cd154215d72e1c5791cc4f8dff2270b3","tests/valid/key-with-pound.json":"ea4dd79d0ad2a824bcce5c4c194d7fae82a7584a2ab7c0d83d6ddaae6130973e","tests/valid/key-with-pound.toml":"c334f676e19c01b96111277248654358cc8222fd0639aecaf429407e63b6a2dc","tests/valid/long-float.json":"7e103f56e490aa1b1fe5a762000ceb1f8c599f7d81aa215c90f5da41ab4ba6db","tests/valid/long-float.toml":"4d23f706f2a0d241840f6ea78657820c9c7b904c0c3c16828f8cc2574d7c8761","tests/valid/long-integer.json":"9ed7976639f0c2cd7f112584e2f5d272e92569be7135ea5bb9ba597abaff0767","tests/valid/long-integer.toml":"309f94be7ff5fd6f6dedbd257a1e6c171cb71aa74409ff3f8babda951f89d687","tests/valid/multiline-string.json":"3d67a8b992b85e9a2e58b77a1b76dc29745a9c2b4a362ad517786fed541948d7","tests/valid/multiline-string.toml":"7d6650009eb31a03d5b40b20712ef0157e9b787d9c966e66c38873a34e3b861c","tests/valid/raw-multiline-string.json":"4c95e34497433168cac25eb4132485c3bd13c35cad9d13d7becf7f90469dacca","tests/valid/raw-multiline-string.toml":"c724151024ccde432e0ec0d4ba60a5320d77841008116324c39516b8cbb94f4d","tests/valid/raw-string.json":"19268797aff8dfa28437d6ed8f9d813035f6eee50aade5fc774ba12b3290216b","tests/valid/raw-string.toml":"16510e05d477a0856ebaf38cacd0e9e18f02ab63ac7bd1a2eabbaa47a54d0e49","tests/valid/string-empty.json":"ece7d01326742a46e37d6404175118c0a91a2494f7ba2290bbc1d6f990ddb65b","tests/valid/string-empty.toml":"251e9e4052ede79f6b2462e71f73e0b7c9f5927484f6f77f0cd8b3c839b0c13b","tests/valid/string-escapes.json":"3d516f03cf94d5b5ee6b0887b8d37fdf21152752f049f5922a24adaacb5b8c35","tests/valid/string-escapes.toml":"86b1569e10fec91301709ad747012f0f42395050a2343b42aca450e001120f7a","tests/valid/string-simple.json":"622676e347676cce9f9733210acbd8056ce77a0588772ffd6efb05bb4e81b571","tests/valid/string-simple.toml":"ae74db09acea3be2ccae7f854f7b6f7c874ace9d4d87bf2f437b059a7d38a464","tests/valid/string-with-pound.json":"458a0add71536c1df5e1ed3ee5483c6eb48578abce0b0ebcdf75ea20d41ed6f4","tests/valid/string-with-pound.toml":"1aee397830d9ad2a93d41ee9c435acdbfef3758d1bb7c48bca7424fbbec89466","tests/valid/table-array-implicit.json":"3f7d3cdb468de67bc183162805d9c753ef5772f6f363ac2a26598387a5d991ea","tests/valid/table-array-implicit.toml":"66bcb030899a95e9a25ec44b7c9291b02f80ecbc324061cf1cd93223a2919f21","tests/valid/table-array-many.json":"3f21243eeb71ca3e5657a43559c806e12e3833e9f74c43c0c12aad9b0c853e4c","tests/valid/table-array-many.toml":"8d8ea546f954a81ca149a02147ae5f4bf075151cfcd530e62dcf05a04d843ffb","tests/valid/table-array-nest.json":"0a987d2bf1d5bc85f5c9433f23d389063600682a68538b6e57938a3c572959e4","tests/valid/table-array-nest.toml":"71b9c753bf773f232ac71cb2469a54ee0110ff137829045421edd7c5a64d6b6a","tests/valid/table-array-one.json":"7dc0ea3f7f843f7dc7443e68af43a1e5130a5fbae8a27fb02d8d92fa2487888e","tests/valid/table-array-one.toml":"4c478aea2dd7dfcfda682503b49e610f0fa4ce85a3b3cd0bc9041d4959e3626a","tests/valid/table-empty.json":"11e43e212d87b3b2547a5f2541f4091a3d2f6ba00b2a2004b07e02734e927ea7","tests/valid/table-empty.toml":"24d4941e67d5965d270eaebdb9816b994311e0f2f0e79ef6bb626f362c52842e","tests/valid/table-sub-empty.json":"85cca6d48a5993c4f207c21ed96652af4f50b6936b0807659c75317c1763b6db","tests/valid/table-sub-empty.toml":"ae92e90a806ffefcbf8cda83cb82acf7448f75efa50dcfb5e2384632d36471b3","tests/valid/table-whitespace.json":"ad84ac49a6d13f7c4a8af0e1e71fd7ff2a446aa16a34c21a809a0850dfa76e73","tests/valid/table-whitespace.toml":"2f15dafb263d2771671db299f6202b4b78d293aec1ded7641ec7eb1cb024b52c","tests/valid/table-with-pound.json":"151e76606efe77500cbb0aa8fcf8ccfadb124d533bb79a9caa62e937b826e676","tests/valid/table-with-pound.toml":"a1f86c2e3789cc89500ec1d5eac2ec0bdb94bf445fddc3cab558b5228f3aba56","tests/valid/unicode-escape.json":"ebbf81930fa92ea5822bb1ed808b798731abe5c97e64f6471e1e86878d79037c","tests/valid/unicode-escape.toml":"aa26e55e5526a0d00ad68eca774d5c43cbcdf24ae753e0219bf3ab31b9e628b8","tests/valid/unicode-literal.json":"1dd42756384b954955815dc3e906db64b4cd2c0c094f9b3c86633d1652d6d79d","tests/valid/unicode-literal.toml":"bffc6c3d4757de31d0cbfd7b8dc591edd2910fe8a4e1c46bbee422dddc841003"},"package":"736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/.gitignore
@@ -0,0 +1,2 @@
+target
+Cargo.lock
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/.travis.yml
@@ -0,0 +1,31 @@
+language: rust
+rust:
+  - stable
+  - beta
+  - nightly
+sudo: false
+before_script:
+  - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
+script:
+  - cargo build --verbose
+  - cargo build --verbose --no-default-features
+  - cargo build --verbose --features serde --no-default-features
+  - cargo test --verbose --features serde
+  - cargo test --verbose --manifest-path serde-tests/Cargo.toml
+  - rustdoc --test README.md -L target
+  - cargo doc --no-deps
+after_success:
+  - travis-cargo --only nightly doc-upload
+  - travis-cargo coveralls --no-sudo
+env:
+  global:
+    secure: LZMkQQJT5LqLQQ8JyakjvHNqqMPy8lm/SyC+H5cKUVI/xk7xRuti4eKY937N8uSmbff2m9ZYlG6cNwIOfk/nWn8YsqxA8Wg/xugubWzqGuqu+NQ4IZVa7INT2Fiqyk5SPCh8B5fo2x7OBJ24SCkWb2p8bEWAuW8XdZZOdmi3H2I=
+notifications:
+  email:
+    on_success: never
+addons:
+  apt:
+    packages:
+      - libcurl4-openssl-dev
+      - libelf-dev
+      - libdw-dev
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+
+name = "toml"
+version = "0.2.1"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+license = "MIT/Apache-2.0"
+readme = "README.md"
+keywords = ["encoding"]
+repository = "https://github.com/alexcrichton/toml-rs"
+homepage = "https://github.com/alexcrichton/toml-rs"
+documentation = "http://alexcrichton.com/toml-rs"
+description = """
+A native Rust encoder and decoder of TOML-formatted files and streams. Provides
+implementations of the standard Encodable/Decodable traits for TOML data to
+facilitate deserializing and serializing Rust structures.
+"""
+
+[dependencies]
+rustc-serialize = { optional = true, version = "0.3.0" }
+serde = { optional = true, version = "0.8" }
+
+[features]
+default = ["rustc-serialize"]
+
+[dev-dependencies]
+rustc-serialize = "0.3"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 Alex Crichton
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/README.md
@@ -0,0 +1,26 @@
+# toml-rs
+
+[![Build Status](https://travis-ci.org/alexcrichton/toml-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/toml-rs)
+[![Coverage Status](https://coveralls.io/repos/alexcrichton/toml-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/alexcrichton/toml-rs?branch=master)
+
+[Documentation](http://alexcrichton.com/toml-rs)
+
+A [TOML][toml] decoder and encoder for Rust. This library is currently compliant with
+the v0.4.0 version of TOML. This library will also likely continue to stay up to
+date with the TOML specification as changes happen.
+
+[toml]: https://github.com/toml-lang/toml
+
+```toml
+# Cargo.toml
+[dependencies]
+toml = "0.2"
+```
+
+# License
+
+`toml-rs` is primarily distributed under the terms of both the MIT license and
+the Apache License (Version 2.0), with portions covered by various BSD-like
+licenses.
+
+See LICENSE-APACHE, and LICENSE-MIT for details.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/examples/toml2json.rs
@@ -0,0 +1,57 @@
+#![deny(warnings)]
+
+extern crate toml;
+extern crate rustc_serialize;
+
+use std::fs::File;
+use std::env;
+use std::io;
+use std::io::prelude::*;
+
+use toml::Value;
+use rustc_serialize::json::Json;
+
+fn main() {
+    let mut args = env::args();
+    let mut input = String::new();
+    let filename = if args.len() > 1 {
+        let name = args.nth(1).unwrap();
+        File::open(&name).and_then(|mut f| {
+            f.read_to_string(&mut input)
+        }).unwrap();
+        name
+    } else {
+        io::stdin().read_to_string(&mut input).unwrap();
+        "<stdin>".to_string()
+    };
+
+    let mut parser = toml::Parser::new(&input);
+    let toml = match parser.parse() {
+        Some(toml) => toml,
+        None => {
+            for err in &parser.errors {
+                let (loline, locol) = parser.to_linecol(err.lo);
+                let (hiline, hicol) = parser.to_linecol(err.hi);
+                println!("{}:{}:{}-{}:{} error: {}",
+                         filename, loline, locol, hiline, hicol, err.desc);
+            }
+            return
+        }
+    };
+    let json = convert(Value::Table(toml));
+    println!("{}", json.pretty());
+}
+
+fn convert(toml: Value) -> Json {
+    match toml {
+        Value::String(s) => Json::String(s),
+        Value::Integer(i) => Json::I64(i),
+        Value::Float(f) => Json::F64(f),
+        Value::Boolean(b) => Json::Boolean(b),
+        Value::Array(arr) => Json::Array(arr.into_iter().map(convert).collect()),
+        Value::Table(table) => Json::Object(table.into_iter().map(|(k, v)| {
+            (k, convert(v))
+        }).collect()),
+        Value::Datetime(dt) => Json::String(dt),
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/decoder/mod.rs
@@ -0,0 +1,240 @@
+use std::error;
+use std::fmt;
+
+use std::collections::{btree_map, BTreeMap};
+use std::iter::Peekable;
+
+use Value;
+use self::DecodeErrorKind::*;
+
+#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
+#[cfg(feature = "serde")] mod serde;
+
+/// A structure to transform TOML values into Rust values.
+///
+/// This decoder implements the serialization `Decoder` interface, allowing
+/// `Decodable` types to be generated by this decoder. The input is any
+/// arbitrary TOML value.
+pub struct Decoder {
+    /// The TOML value left over after decoding. This can be used to inspect
+    /// whether fields were decoded or not.
+    pub toml: Option<Value>,
+    cur_field: Option<String>,
+
+    // These aren't used if serde is in use
+    #[cfg_attr(feature = "serde", allow(dead_code))]
+    cur_map: Peekable<btree_map::IntoIter<String, Value>>,
+    #[cfg_attr(feature = "serde", allow(dead_code))]
+    leftover_map: ::Table,
+}
+
+/// Description for errors which can occur while decoding a type.
+#[derive(PartialEq, Debug)]
+pub struct DecodeError {
+    /// Field that this error applies to.
+    pub field: Option<String>,
+    /// The type of error which occurred while decoding,
+    pub kind: DecodeErrorKind,
+}
+
+/// Enumeration of possible errors which can occur while decoding a structure.
+#[derive(PartialEq, Debug)]
+pub enum DecodeErrorKind {
+    /// An error flagged by the application, e.g. value out of range
+    ApplicationError(String),
+    /// A field was expected, but none was found.
+    ExpectedField(/* type */ Option<&'static str>),
+    /// A field was found, but it was not an expected one.
+    UnknownField,
+    /// A field was found, but it had the wrong type.
+    ExpectedType(/* expected */ &'static str, /* found */ &'static str),
+    /// The nth map key was expected, but none was found.
+    ExpectedMapKey(usize),
+    /// The nth map element was expected, but none was found.
+    ExpectedMapElement(usize),
+    /// An enum decoding was requested, but no variants were supplied
+    NoEnumVariants,
+    /// The unit type was being decoded, but a non-zero length string was found
+    NilTooLong,
+    /// There was an error with the syntactical structure of the TOML.
+    SyntaxError,
+    /// A custom error was generated when decoding.
+    CustomError(String),
+    /// The end of the TOML input was reached too soon
+    EndOfStream,
+    /// Produced by serde ...
+    InvalidType(&'static str),
+}
+
+/// Decodes a TOML value into a decodable type.
+///
+/// This function will consume the given TOML value and attempt to decode it
+/// into the type specified. If decoding fails, `None` will be returned. If a
+/// finer-grained error is desired, then it is recommended to use `Decodable`
+/// directly.
+#[cfg(feature = "rustc-serialize")]
+pub fn decode<T: ::rustc_serialize::Decodable>(toml: Value) -> Option<T> {
+    ::rustc_serialize::Decodable::decode(&mut Decoder::new(toml)).ok()
+}
+
+/// Decodes a TOML value into a decodable type.
+///
+/// This function will consume the given TOML value and attempt to decode it
+/// into the type specified. If decoding fails, `None` will be returned. If a
+/// finer-grained error is desired, then it is recommended to use `Decodable`
+/// directly.
+#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
+pub fn decode<T: ::serde::Deserialize>(toml: Value) -> Option<T> {
+    ::serde::Deserialize::deserialize(&mut Decoder::new(toml)).ok()
+}
+
+/// Decodes a string into a toml-encoded value.
+///
+/// This function will parse the given string into a TOML value, and then parse
+/// the TOML value into the desired type. If any error occurs, `None` is
+/// returned.
+///
+/// If more fine-grained errors are desired, these steps should be driven
+/// manually.
+#[cfg(feature = "rustc-serialize")]
+pub fn decode_str<T: ::rustc_serialize::Decodable>(s: &str) -> Option<T> {
+    ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
+}
+
+/// Decodes a string into a toml-encoded value.
+///
+/// This function will parse the given string into a TOML value, and then parse
+/// the TOML value into the desired type. If any error occurs, `None` is
+/// returned.
+///
+/// If more fine-grained errors are desired, these steps should be driven
+/// manually.
+#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
+pub fn decode_str<T: ::serde::Deserialize>(s: &str) -> Option<T> {
+    ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
+}
+
+impl Decoder {
+    /// Creates a new decoder, consuming the TOML value to decode.
+    ///
+    /// This decoder can be passed to the `Decodable` methods or driven
+    /// manually.
+    pub fn new(toml: Value) -> Decoder {
+        Decoder::new_empty(Some(toml), None)
+    }
+
+    fn sub_decoder(&self, toml: Option<Value>, field: &str) -> Decoder {
+        let cur_field = if field.is_empty() {
+            self.cur_field.clone()
+        } else {
+            match self.cur_field {
+                None => Some(field.to_string()),
+                Some(ref s) => Some(format!("{}.{}", s, field))
+            }
+        };
+        Decoder::new_empty(toml, cur_field)
+    }
+
+    fn new_empty(toml: Option<Value>, cur_field: Option<String>) -> Decoder {
+        Decoder {
+            toml: toml,
+            cur_field: cur_field,
+            leftover_map: BTreeMap::new(),
+            cur_map: BTreeMap::new().into_iter().peekable(),
+        }
+    }
+
+    fn err(&self, kind: DecodeErrorKind) -> DecodeError {
+        DecodeError {
+            field: self.cur_field.clone(),
+            kind: kind,
+        }
+    }
+
+    fn mismatch(&self, expected: &'static str,
+                found: &Option<Value>) -> DecodeError{
+        match *found {
+            Some(ref val) => self.err(ExpectedType(expected, val.type_str())),
+            None => self.err(ExpectedField(Some(expected))),
+        }
+    }
+}
+
+impl fmt::Display for DecodeError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(match self.kind {
+            ApplicationError(ref err) => {
+                write!(f, "{}", err)
+            }
+            ExpectedField(expected_type) => {
+                match expected_type {
+                    Some("table") => write!(f, "expected a section"),
+                    Some(e) => write!(f, "expected a value of type `{}`", e),
+                    None => write!(f, "expected a value"),
+                }
+            }
+            UnknownField => write!(f, "unknown field"),
+            ExpectedType(expected, found) => {
+                fn humanize(s: &str) -> String {
+                    if s == "section" {
+                        "a section".to_string()
+                    } else {
+                        format!("a value of type `{}`", s)
+                    }
+                }
+                write!(f, "expected {}, but found {}",
+                       humanize(expected),
+                       humanize(found))
+            }
+            ExpectedMapKey(idx) => {
+                write!(f, "expected at least {} keys", idx + 1)
+            }
+            ExpectedMapElement(idx) => {
+                write!(f, "expected at least {} elements", idx + 1)
+            }
+            NoEnumVariants => {
+                write!(f, "expected an enum variant to decode to")
+            }
+            NilTooLong => {
+                write!(f, "expected 0-length string")
+            }
+            SyntaxError => {
+                write!(f, "syntax error")
+            }
+            EndOfStream => {
+                write!(f, "end of stream")
+            }
+            InvalidType(s) => {
+                write!(f, "invalid type: {}", s)
+            }
+            CustomError(ref s) => {
+                write!(f, "custom error: {}", s)
+            }
+        });
+        match self.field {
+            Some(ref s) => {
+                write!(f, " for the key `{}`", s)
+            }
+            None => Ok(())
+        }
+    }
+}
+
+impl error::Error for DecodeError {
+    fn description(&self) -> &str {
+        match self.kind {
+            ApplicationError(ref s) => &**s,
+            ExpectedField(..) => "expected a field",
+            UnknownField => "found an unknown field",
+            ExpectedType(..) => "expected a type",
+            ExpectedMapKey(..) => "expected a map key",
+            ExpectedMapElement(..) => "expected a map element",
+            NoEnumVariants => "no enum variants to decode to",
+            NilTooLong => "nonzero length string representing nil",
+            SyntaxError => "syntax error",
+            EndOfStream => "end of stream",
+            InvalidType(..) => "invalid type",
+            CustomError(..) => "custom error",
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/decoder/rustc_serialize.rs
@@ -0,0 +1,371 @@
+use rustc_serialize;
+use std::mem;
+use std::collections::BTreeMap;
+
+use super::{Decoder, DecodeError};
+use super::DecodeErrorKind::*;
+use Value;
+
+impl rustc_serialize::Decoder for Decoder {
+    type Error = DecodeError;
+    fn read_nil(&mut self) -> Result<(), DecodeError> {
+        match self.toml {
+            Some(Value::String(ref s)) if s.is_empty() => {}
+            Some(Value::String(..)) => return Err(self.err(NilTooLong)),
+            ref found => return Err(self.mismatch("string", found)),
+        }
+        self.toml.take();
+        Ok(())
+    }
+    fn read_usize(&mut self) -> Result<usize, DecodeError> {
+        self.read_i64().map(|i| i as usize)
+    }
+    fn read_u64(&mut self) -> Result<u64, DecodeError> {
+        self.read_i64().map(|i| i as u64)
+    }
+    fn read_u32(&mut self) -> Result<u32, DecodeError> {
+        self.read_i64().map(|i| i as u32)
+    }
+    fn read_u16(&mut self) -> Result<u16, DecodeError> {
+        self.read_i64().map(|i| i as u16)
+    }
+    fn read_u8(&mut self) -> Result<u8, DecodeError> {
+        self.read_i64().map(|i| i as u8)
+    }
+    fn read_isize(&mut self) -> Result<isize, DecodeError> {
+        self.read_i64().map(|i| i as isize)
+    }
+    fn read_i64(&mut self) -> Result<i64, DecodeError> {
+        match self.toml {
+            Some(Value::Integer(i)) => { self.toml.take(); Ok(i) }
+            ref found => Err(self.mismatch("integer", found)),
+        }
+    }
+    fn read_i32(&mut self) -> Result<i32, DecodeError> {
+        self.read_i64().map(|i| i as i32)
+    }
+    fn read_i16(&mut self) -> Result<i16, DecodeError> {
+        self.read_i64().map(|i| i as i16)
+    }
+    fn read_i8(&mut self) -> Result<i8, DecodeError> {
+        self.read_i64().map(|i| i as i8)
+    }
+    fn read_bool(&mut self) -> Result<bool, DecodeError> {
+        match self.toml {
+            Some(Value::Boolean(b)) => { self.toml.take(); Ok(b) }
+            ref found => Err(self.mismatch("bool", found)),
+        }
+    }
+    fn read_f64(&mut self) -> Result<f64, DecodeError> {
+        match self.toml {
+            Some(Value::Float(f)) => { self.toml.take(); Ok(f) },
+            ref found => Err(self.mismatch("float", found)),
+        }
+    }
+    fn read_f32(&mut self) -> Result<f32, DecodeError> {
+        self.read_f64().map(|f| f as f32)
+    }
+    fn read_char(&mut self) -> Result<char, DecodeError> {
+        let ch = match self.toml {
+            Some(Value::String(ref s)) if s.chars().count() == 1 =>
+                s.chars().next().unwrap(),
+            ref found => return Err(self.mismatch("string", found)),
+        };
+        self.toml.take();
+        Ok(ch)
+    }
+    fn read_str(&mut self) -> Result<String, DecodeError> {
+        match self.toml.take() {
+            Some(Value::String(s)) => Ok(s),
+            found => {
+                let err = Err(self.mismatch("string", &found));
+                self.toml = found;
+                err
+            }
+        }
+    }
+
+    // Compound types:
+    fn read_enum<T, F>(&mut self, _name: &str, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        f(self)
+    }
+
+    fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F)
+        -> Result<T, DecodeError>
+        where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError>
+    {
+        // When decoding enums, this crate takes the strategy of trying to
+        // decode the current TOML as all of the possible variants, returning
+        // success on the first one that succeeds.
+        //
+        // Note that fidelity of the errors returned here is a little nebulous,
+        // but we try to return the error that had the relevant field as the
+        // longest field. This way we hopefully match an error against what was
+        // most likely being written down without losing too much info.
+        let mut first_error = None::<DecodeError>;
+        for i in 0..names.len() {
+            let mut d = self.sub_decoder(self.toml.clone(), "");
+            match f(&mut d, i) {
+                Ok(t) => {
+                    self.toml = d.toml;
+                    return Ok(t)
+                }
+                Err(e) => {
+                    if let Some(ref first) = first_error {
+                        let my_len = e.field.as_ref().map(|s| s.len());
+                        let first_len = first.field.as_ref().map(|s| s.len());
+                        if my_len <= first_len {
+                            continue
+                        }
+                    }
+                    first_error = Some(e);
+                }
+            }
+        }
+        Err(first_error.unwrap_or_else(|| self.err(NoEnumVariants)))
+    }
+    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        f(self)
+    }
+
+    fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F)
+        -> Result<T, DecodeError>
+        where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError>
+    {
+        panic!()
+    }
+    fn read_enum_struct_variant_field<T, F>(&mut self,
+                                            _f_name: &str,
+                                            _f_idx: usize,
+                                            _f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        panic!()
+    }
+
+    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        match self.toml {
+            Some(Value::Table(..)) => {
+                let ret = try!(f(self));
+                match self.toml {
+                    Some(Value::Table(ref t)) if t.is_empty() => {}
+                    _ => return Ok(ret)
+                }
+                self.toml.take();
+                Ok(ret)
+            }
+            ref found => Err(self.mismatch("table", found)),
+        }
+    }
+    fn read_struct_field<T, F>(&mut self, f_name: &str, _f_idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        let field = f_name.to_string();
+        let toml = match self.toml {
+            Some(Value::Table(ref mut table)) => {
+                table.remove(&field)
+                     .or_else(|| table.remove(&f_name.replace("_", "-")))
+            },
+            ref found => return Err(self.mismatch("table", found)),
+        };
+        let mut d = self.sub_decoder(toml, f_name);
+        let ret = try!(f(&mut d));
+        if let Some(value) = d.toml {
+            if let Some(Value::Table(ref mut table)) = self.toml {
+                table.insert(field, value);
+            }
+        }
+        Ok(ret)
+    }
+
+    fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        self.read_seq(move |d, len| {
+            assert!(len == tuple_len,
+                    "expected tuple of length `{}`, found tuple \
+                         of length `{}`", tuple_len, len);
+            f(d)
+        })
+    }
+    fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        self.read_seq_elt(a_idx, f)
+    }
+
+    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        panic!()
+    }
+    fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        panic!()
+    }
+
+    // Specialized types:
+    fn read_option<T, F>(&mut self, mut f: F)
+        -> Result<T, DecodeError>
+        where F: FnMut(&mut Decoder, bool) -> Result<T, DecodeError>
+    {
+        match self.toml {
+            Some(..) => f(self, true),
+            None => f(self, false),
+        }
+    }
+
+    fn read_seq<T, F>(&mut self, f: F) -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError>
+    {
+        let len = match self.toml {
+            Some(Value::Array(ref arr)) => arr.len(),
+            None => 0,
+            ref found => return Err(self.mismatch("array", found)),
+        };
+        let ret = try!(f(self, len));
+        match self.toml {
+            Some(Value::Array(ref mut arr)) => {
+                arr.retain(|slot| slot.as_integer() != Some(0));
+                if !arr.is_empty() { return Ok(ret) }
+            }
+            _ => return Ok(ret)
+        }
+        self.toml.take();
+        Ok(ret)
+    }
+    fn read_seq_elt<T, F>(&mut self, idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        let toml = match self.toml {
+            Some(Value::Array(ref mut arr)) => {
+                mem::replace(&mut arr[idx], Value::Integer(0))
+            }
+            ref found => return Err(self.mismatch("array", found)),
+        };
+        let mut d = self.sub_decoder(Some(toml), "");
+        let ret = try!(f(&mut d));
+        if let Some(toml) = d.toml {
+            if let Some(Value::Array(ref mut arr)) = self.toml {
+                arr[idx] = toml;
+            }
+        }
+        Ok(ret)
+    }
+
+    fn read_map<T, F>(&mut self, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError>
+    {
+        let map = match self.toml.take() {
+            Some(Value::Table(table)) => table,
+            found => {
+                self.toml = found;
+                return Err(self.mismatch("table", &self.toml))
+            }
+        };
+        let amt = map.len();
+        let prev_iter = mem::replace(&mut self.cur_map,
+                                     map.into_iter().peekable());
+        let prev_map = mem::replace(&mut self.leftover_map, BTreeMap::new());
+        let ret = try!(f(self, amt));
+        let leftover = mem::replace(&mut self.leftover_map, prev_map);
+        self.cur_map = prev_iter;
+        if !leftover.is_empty() {
+            self.toml = Some(Value::Table(leftover));
+        }
+        Ok(ret)
+    }
+    fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        let key = match self.cur_map.peek().map(|p| p.0.clone()) {
+            Some(k) => k,
+            None => return Err(self.err(ExpectedMapKey(idx))),
+        };
+        let val = Value::String(key.clone());
+        f(&mut self.sub_decoder(Some(val), &key))
+    }
+    fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F)
+        -> Result<T, DecodeError>
+        where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
+    {
+        match self.cur_map.next() {
+            Some((key, value)) => {
+                let mut d = self.sub_decoder(Some(value), &key);
+                let ret = f(&mut d);
+                if let Some(toml) = d.toml.take() {
+                    self.leftover_map.insert(key, toml);
+                }
+                ret
+            }
+            None => Err(self.err(ExpectedMapElement(idx))),
+        }
+    }
+
+    fn error(&mut self, err: &str) -> DecodeError {
+        DecodeError {
+            field: self.cur_field.clone(),
+            kind: ApplicationError(err.to_string())
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use rustc_serialize::Decodable;
+    use std::collections::HashMap;
+
+    use {Parser, Decoder, Value};
+
+    #[test]
+    fn bad_enum_chooses_longest_error() {
+        #[derive(RustcDecodable)]
+        #[allow(dead_code)]
+        struct Foo {
+            wut: HashMap<String, Bar>,
+        }
+
+        #[derive(RustcDecodable)]
+        enum Bar {
+            Simple(String),
+            Detailed(Baz),
+        }
+
+        #[derive(RustcDecodable, Debug)]
+        struct Baz {
+            features: Vec<String>,
+        }
+
+        let s = r#"
+            [wut]
+            a = { features = "" }
+        "#;
+        let v = Parser::new(s).parse().unwrap();
+        let mut d = Decoder::new(Value::Table(v));
+        let err = match Foo::decode(&mut d) {
+            Ok(_) => panic!("expected error"),
+            Err(e) => e,
+        };
+        assert_eq!(err.field.as_ref().unwrap(), "wut.a.features");
+
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/decoder/serde.rs
@@ -0,0 +1,773 @@
+use serde::de;
+use Value;
+use super::{Decoder, DecodeError, DecodeErrorKind};
+use std::collections::BTreeMap;
+
+macro_rules! forward_to_deserialize {
+    ($(
+        $name:ident ( $( $arg:ident : $ty:ty ),* );
+    )*) => {
+        $(
+            forward_to_deserialize!{
+                func: $name ( $( $arg: $ty ),* );
+            }
+        )*
+    };
+
+    (func: deserialize_enum ( $( $arg:ident : $ty:ty ),* );) => {
+        fn deserialize_enum<V>(
+            &mut self,
+            $(_: $ty,)*
+            _visitor: V,
+        ) -> ::std::result::Result<V::Value, Self::Error>
+            where V: ::serde::de::EnumVisitor
+        {
+            Err(::serde::de::Error::invalid_type(::serde::de::Type::Enum))
+        }
+    };
+
+    (func: $name:ident ( $( $arg:ident : $ty:ty ),* );) => {
+        #[inline]
+        fn $name<V>(
+            &mut self,
+            $(_: $ty,)*
+            visitor: V,
+        ) -> ::std::result::Result<V::Value, Self::Error>
+            where V: ::serde::de::Visitor
+        {
+            self.deserialize(visitor)
+        }
+    };
+}
+
+impl de::Deserializer for Decoder {
+    type Error = DecodeError;
+
+    fn deserialize<V>(&mut self, mut visitor: V)
+                      -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        match self.toml.take() {
+            Some(Value::String(s)) => visitor.visit_string(s),
+            Some(Value::Integer(i)) => visitor.visit_i64(i),
+            Some(Value::Float(f)) => visitor.visit_f64(f),
+            Some(Value::Boolean(b)) => visitor.visit_bool(b),
+            Some(Value::Datetime(s)) => visitor.visit_string(s),
+            Some(Value::Array(a)) => {
+                let len = a.len();
+                let iter = a.into_iter();
+                visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
+            }
+            Some(Value::Table(t)) => {
+                visitor.visit_map(MapVisitor {
+                    iter: t.into_iter(),
+                    de: self,
+                    key: None,
+                    value: None,
+                })
+            }
+            None => Err(self.err(DecodeErrorKind::EndOfStream)),
+        }
+    }
+
+    fn deserialize_bool<V>(&mut self, mut visitor: V)
+                           -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        match self.toml.take() {
+            Some(Value::Boolean(b)) => visitor.visit_bool(b),
+            ref found => Err(self.mismatch("bool", found)),
+        }
+    }
+
+    fn deserialize_i8<V>(&mut self, visitor: V)
+                         -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_i16<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_i32<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_i64<V>(&mut self, mut visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        match self.toml.take() {
+            Some(Value::Integer(f)) => visitor.visit_i64(f),
+            ref found => Err(self.mismatch("integer", found)),
+        }
+    }
+
+    fn deserialize_isize<V>(&mut self, visitor: V)
+                            -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_u8<V>(&mut self, visitor: V)
+                         -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_u16<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_u32<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_u64<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_usize<V>(&mut self, visitor: V)
+                            -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_i64(visitor)
+    }
+
+    fn deserialize_f32<V>(&mut self, visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        self.deserialize_f64(visitor)
+    }
+
+    fn deserialize_f64<V>(&mut self, mut visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        match self.toml.take() {
+            Some(Value::Float(f)) => visitor.visit_f64(f),
+            ref found => Err(self.mismatch("float", found)),
+        }
+    }
+
+    fn deserialize_str<V>(&mut self, mut visitor: V)
+                          -> Result<V::Value, Self::Error>
+        where V: de::Visitor,
+    {
+        match self.toml.take() {
+            Some(Value::String(s)) => visitor.visit_string(s),
+            ref found => Err(self.mismatch("string", found)),
+        }
+    }
+
+    fn deserialize_string<V>(&mut self, visitor: V)
+                             -> Result<V::Value, Self::Error>
+        where V: de::Visitor,
+    {
+        self.deserialize_str(visitor)
+    }
+
+    fn deserialize_char<V>(&mut self, mut visitor: V)
+                           -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        match self.toml.take() {
+            Some(Value::String(ref s)) if s.chars().count() == 1 => {
+                visitor.visit_char(s.chars().next().unwrap())
+            }
+            ref found => return Err(self.mismatch("string", found)),
+        }
+    }
+
+    fn deserialize_option<V>(&mut self, mut visitor: V)
+                             -> Result<V::Value, DecodeError>
+        where V: de::Visitor
+    {
+        if self.toml.is_none() {
+            visitor.visit_none()
+        } else {
+            visitor.visit_some(self)
+        }
+    }
+
+    fn deserialize_seq<V>(&mut self, mut visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        if self.toml.is_none() {
+            let iter = None::<i32>.into_iter();
+            visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0))
+        } else {
+            self.deserialize(visitor)
+        }
+    }
+
+    fn deserialize_map<V>(&mut self, mut visitor: V)
+                          -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        match self.toml.take() {
+            Some(Value::Table(t)) => {
+                visitor.visit_map(MapVisitor {
+                    iter: t.into_iter(),
+                    de: self,
+                    key: None,
+                    value: None,
+                })
+            }
+            ref found => Err(self.mismatch("table", found)),
+        }
+    }
+
+    fn deserialize_enum<V>(&mut self,
+                           _enum: &str,
+                           variants: &[&str],
+                           mut visitor: V) -> Result<V::Value, DecodeError>
+        where V: de::EnumVisitor,
+    {
+        // When decoding enums, this crate takes the strategy of trying to
+        // decode the current TOML as all of the possible variants, returning
+        // success on the first one that succeeds.
+        //
+        // Note that fidelity of the errors returned here is a little nebulous,
+        // but we try to return the error that had the relevant field as the
+        // longest field. This way we hopefully match an error against what was
+        // most likely being written down without losing too much info.
+        let mut first_error = None::<DecodeError>;
+
+        for variant in 0..variants.len() {
+            let mut de = VariantVisitor {
+                de: self.sub_decoder(self.toml.clone(), ""),
+                variant: variant,
+            };
+
+            match visitor.visit(&mut de) {
+                Ok(value) => {
+                    self.toml = de.de.toml;
+                    return Ok(value);
+                }
+                Err(e) => {
+                    if let Some(ref first) = first_error {
+                        let my_len = e.field.as_ref().map(|s| s.len());
+                        let first_len = first.field.as_ref().map(|s| s.len());
+                        if my_len <= first_len {
+                            continue
+                        }
+                    }
+                    first_error = Some(e);
+                }
+            }
+        }
+
+        Err(first_error.unwrap_or_else(|| self.err(DecodeErrorKind::NoEnumVariants)))
+    }
+
+    // When #[derive(Deserialize)] encounters an unknown struct field it will
+    // call this method (somehow), and we want to preserve all unknown struct
+    // fields to return them upwards (to warn about unused keys), so we override
+    // that here to not tamper with our own internal state.
+    fn deserialize_ignored_any<V>(&mut self, visitor: V)
+                                  -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        use serde::de::value::ValueDeserializer;
+        let mut d = <() as ValueDeserializer<Self::Error>>::into_deserializer(());
+        d.deserialize(visitor)
+    }
+
+    fn deserialize_bytes<V>(&mut self, visitor: V)
+                            -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_seq(visitor)
+    }
+
+    fn deserialize_seq_fixed_size<V>(&mut self, _len: usize, visitor: V)
+                                     -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_seq(visitor)
+    }
+
+    fn deserialize_newtype_struct<V>(&mut self, _name: &'static str, visitor: V)
+                                     -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_seq(visitor)
+    }
+
+    fn deserialize_tuple_struct<V>(&mut self,
+                                   _name: &'static str,
+                                   _len: usize,
+                                   visitor: V)
+                                   -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_seq(visitor)
+    }
+
+    fn deserialize_struct<V>(&mut self,
+                             _name: &'static str,
+                             _fields: &'static [&'static str],
+                             visitor: V)
+                             -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_map(visitor)
+    }
+
+    fn deserialize_tuple<V>(&mut self,
+                            _len: usize,
+                            visitor: V)
+                            -> Result<V::Value, Self::Error>
+        where V: de::Visitor
+    {
+        self.deserialize_seq(visitor)
+    }
+
+    forward_to_deserialize!{
+        deserialize_unit();
+        deserialize_unit_struct(name: &'static str);
+        deserialize_struct_field();
+    }
+}
+
+struct VariantVisitor {
+    de: Decoder,
+    variant: usize,
+}
+
+impl de::VariantVisitor for VariantVisitor {
+    type Error = DecodeError;
+
+    fn visit_variant<V>(&mut self) -> Result<V, DecodeError>
+        where V: de::Deserialize
+    {
+        use serde::de::value::ValueDeserializer;
+
+        let mut de = self.variant.into_deserializer();
+
+        de::Deserialize::deserialize(&mut de)
+    }
+
+    fn visit_unit(&mut self) -> Result<(), DecodeError> {
+        de::Deserialize::deserialize(&mut self.de)
+    }
+
+    fn visit_newtype<T>(&mut self) -> Result<T, DecodeError>
+        where T: de::Deserialize,
+    {
+        de::Deserialize::deserialize(&mut self.de)
+    }
+
+    fn visit_tuple<V>(&mut self,
+                      _len: usize,
+                      visitor: V) -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        de::Deserializer::deserialize(&mut self.de, visitor)
+    }
+
+    fn visit_struct<V>(&mut self,
+                       _fields: &'static [&'static str],
+                       visitor: V) -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        de::Deserializer::deserialize(&mut self.de, visitor)
+    }
+}
+
+struct SeqDeserializer<'a, I> {
+    iter: I,
+    len: usize,
+    toml: &'a mut Option<Value>,
+}
+
+impl<'a, I> SeqDeserializer<'a, I> where I: Iterator<Item=Value> {
+    fn new(iter: I, len: usize, toml: &'a mut Option<Value>) -> Self {
+        SeqDeserializer {
+            iter: iter,
+            len: len,
+            toml: toml,
+        }
+    }
+
+    fn put_value_back(&mut self, v: Value) {
+        *self.toml = self.toml.take().or(Some(Value::Array(Vec::new())));
+        match self.toml.as_mut().unwrap() {
+            &mut Value::Array(ref mut a) => {
+                a.push(v);
+            },
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl<'a, I> de::Deserializer for SeqDeserializer<'a, I>
+    where I: Iterator<Item=Value>,
+{
+    type Error = DecodeError;
+
+    fn deserialize<V>(&mut self, mut visitor: V)
+                      -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        visitor.visit_seq(self)
+    }
+
+    forward_to_deserialize!{
+        deserialize_bool();
+        deserialize_usize();
+        deserialize_u8();
+        deserialize_u16();
+        deserialize_u32();
+        deserialize_u64();
+        deserialize_isize();
+        deserialize_i8();
+        deserialize_i16();
+        deserialize_i32();
+        deserialize_i64();
+        deserialize_f32();
+        deserialize_f64();
+        deserialize_char();
+        deserialize_str();
+        deserialize_string();
+        deserialize_unit();
+        deserialize_option();
+        deserialize_seq();
+        deserialize_seq_fixed_size(len: usize);
+        deserialize_bytes();
+        deserialize_map();
+        deserialize_unit_struct(name: &'static str);
+        deserialize_newtype_struct(name: &'static str);
+        deserialize_tuple_struct(name: &'static str, len: usize);
+        deserialize_struct(name: &'static str, fields: &'static [&'static str]);
+        deserialize_struct_field();
+        deserialize_tuple(len: usize);
+        deserialize_enum(name: &'static str, variants: &'static [&'static str]);
+        deserialize_ignored_any();
+    }
+}
+
+impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I>
+    where I: Iterator<Item=Value>
+{
+    type Error = DecodeError;
+
+    fn visit<V>(&mut self) -> Result<Option<V>, DecodeError>
+        where V: de::Deserialize
+    {
+        match self.iter.next() {
+            Some(value) => {
+                self.len -= 1;
+                let mut de = Decoder::new(value);
+                let v = try!(de::Deserialize::deserialize(&mut de));
+                if let Some(t) = de.toml {
+                    self.put_value_back(t);
+                }
+                Ok(Some(v))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn end(&mut self) -> Result<(), DecodeError> {
+        if self.len == 0 {
+            Ok(())
+        } else {
+            Err(de::Error::end_of_stream())
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.len, Some(self.len))
+    }
+}
+
+impl de::Error for DecodeError {
+    fn custom<T: Into<String>>(msg: T) -> DecodeError {
+        DecodeError {
+            field: None,
+            kind: DecodeErrorKind::CustomError(msg.into()),
+        }
+    }
+    fn end_of_stream() -> DecodeError {
+        DecodeError { field: None, kind: DecodeErrorKind::EndOfStream }
+    }
+    fn missing_field(name: &'static str) -> DecodeError {
+        DecodeError {
+            field: Some(name.to_string()),
+            kind: DecodeErrorKind::ExpectedField(None),
+        }
+    }
+    fn unknown_field(name: &str) -> DecodeError {
+        DecodeError {
+            field: Some(name.to_string()),
+            kind: DecodeErrorKind::UnknownField,
+        }
+    }
+    fn invalid_type(ty: de::Type) -> Self {
+        DecodeError {
+            field: None,
+            kind: DecodeErrorKind::InvalidType(match ty {
+                de::Type::Bool => "bool",
+                de::Type::Usize |
+                de::Type::U8 |
+                de::Type::U16 |
+                de::Type::U32 |
+                de::Type::U64 |
+                de::Type::Isize |
+                de::Type::I8 |
+                de::Type::I16 |
+                de::Type::I32 |
+                de::Type::I64 => "integer",
+                de::Type::F32 |
+                de::Type::F64 => "float",
+                de::Type::Char |
+                de::Type::Str |
+                de::Type::String => "string",
+                de::Type::Seq => "array",
+                de::Type::Struct |
+                de::Type::Map => "table",
+                de::Type::Unit => "Unit",
+                de::Type::Option => "Option",
+                de::Type::UnitStruct => "UnitStruct",
+                de::Type::NewtypeStruct => "NewtypeStruct",
+                de::Type::TupleStruct => "TupleStruct",
+                de::Type::FieldName => "FieldName",
+                de::Type::Tuple => "Tuple",
+                de::Type::Enum => "Enum",
+                de::Type::VariantName => "VariantName",
+                de::Type::StructVariant => "StructVariant",
+                de::Type::TupleVariant => "TupleVariant",
+                de::Type::UnitVariant => "UnitVariant",
+                de::Type::Bytes => "Bytes",
+            })
+        }
+    }
+}
+
+struct MapVisitor<'a, I> {
+    iter: I,
+    de: &'a mut Decoder,
+    key: Option<String>,
+    value: Option<Value>,
+}
+
+impl<'a, I> MapVisitor<'a, I> {
+    fn put_value_back(&mut self, v: Value) {
+        self.de.toml = self.de.toml.take().or_else(|| {
+            Some(Value::Table(BTreeMap::new()))
+        });
+
+        match self.de.toml.as_mut().unwrap() {
+            &mut Value::Table(ref mut t) => {
+                t.insert(self.key.take().unwrap(), v);
+            },
+            _ => unreachable!(),
+        }
+    }
+}
+
+impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
+    where I: Iterator<Item=(String, Value)>
+{
+    type Error = DecodeError;
+
+    fn visit_key<K>(&mut self) -> Result<Option<K>, DecodeError>
+        where K: de::Deserialize
+    {
+        while let Some((k, v)) = self.iter.next() {
+            let mut dec = self.de.sub_decoder(Some(Value::String(k.clone())), &k);
+            self.key = Some(k);
+
+            match de::Deserialize::deserialize(&mut dec) {
+                Ok(val) => {
+                    self.value = Some(v);
+                    return Ok(Some(val))
+                }
+
+                // If this was an unknown field, then we put the toml value
+                // back into the map and keep going.
+                Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => {
+                    self.put_value_back(v);
+                }
+
+                Err(e) => return Err(e),
+            }
+        }
+        Ok(None)
+    }
+
+    fn visit_value<V>(&mut self) -> Result<V, DecodeError>
+        where V: de::Deserialize
+    {
+        match self.value.take() {
+            Some(t) => {
+                let mut dec = {
+                    // Borrowing the key here because Rust doesn't have
+                    // non-lexical borrows yet.
+                    let key = match self.key {
+                        Some(ref key) => &**key,
+                        None => ""
+                    };
+
+                    self.de.sub_decoder(Some(t), key)
+                };
+                let v = try!(de::Deserialize::deserialize(&mut dec));
+                if let Some(t) = dec.toml {
+                    self.put_value_back(t);
+                }
+                Ok(v)
+            },
+            None => Err(de::Error::end_of_stream())
+        }
+    }
+
+    fn end(&mut self) -> Result<(), DecodeError> {
+        if let Some(v) = self.value.take() {
+            self.put_value_back(v);
+        }
+        while let Some((k, v)) = self.iter.next() {
+            self.key = Some(k);
+            self.put_value_back(v);
+        }
+        Ok(())
+    }
+
+    fn missing_field<V>(&mut self, field_name: &'static str)
+                        -> Result<V, DecodeError> where V: de::Deserialize {
+        // See if the type can deserialize from a unit.
+        match de::Deserialize::deserialize(&mut UnitDeserializer) {
+            Err(DecodeError {
+                kind: DecodeErrorKind::InvalidType(..),
+                field,
+            }) => Err(DecodeError {
+                field: field.or(Some(field_name.to_string())),
+                kind: DecodeErrorKind::ExpectedField(None),
+            }),
+            v => v,
+        }
+    }
+}
+
+struct UnitDeserializer;
+
+impl de::Deserializer for UnitDeserializer {
+    type Error = DecodeError;
+
+    fn deserialize<V>(&mut self, mut visitor: V)
+                      -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        visitor.visit_unit()
+    }
+
+    fn deserialize_option<V>(&mut self, mut visitor: V)
+                             -> Result<V::Value, DecodeError>
+        where V: de::Visitor,
+    {
+        visitor.visit_none()
+    }
+
+    forward_to_deserialize!{
+        deserialize_bool();
+        deserialize_usize();
+        deserialize_u8();
+        deserialize_u16();
+        deserialize_u32();
+        deserialize_u64();
+        deserialize_isize();
+        deserialize_i8();
+        deserialize_i16();
+        deserialize_i32();
+        deserialize_i64();
+        deserialize_f32();
+        deserialize_f64();
+        deserialize_char();
+        deserialize_str();
+        deserialize_string();
+        deserialize_unit();
+        deserialize_seq();
+        deserialize_seq_fixed_size(len: usize);
+        deserialize_bytes();
+        deserialize_map();
+        deserialize_unit_struct(name: &'static str);
+        deserialize_newtype_struct(name: &'static str);
+        deserialize_tuple_struct(name: &'static str, len: usize);
+        deserialize_struct(name: &'static str, fields: &'static [&'static str]);
+        deserialize_struct_field();
+        deserialize_tuple(len: usize);
+        deserialize_enum(name: &'static str, variants: &'static [&'static str]);
+        deserialize_ignored_any();
+    }
+}
+
+impl de::Deserialize for Value {
+    fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error>
+        where D: de::Deserializer
+    {
+        struct ValueVisitor;
+
+        impl de::Visitor for ValueVisitor {
+            type Value = Value;
+
+            fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
+                Ok(Value::Boolean(value))
+            }
+
+            fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
+                Ok(Value::Integer(value))
+            }
+
+            fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
+                Ok(Value::Float(value))
+            }
+
+            fn visit_str<E>(&mut self, value: &str) -> Result<Value, E> {
+                Ok(Value::String(value.into()))
+            }
+
+            fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
+                Ok(Value::String(value))
+            }
+
+            fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
+                where V: de::SeqVisitor
+            {
+                let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
+                Ok(Value::Array(values))
+            }
+
+            fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
+                where V: de::MapVisitor
+            {
+                let mut v = de::impls::BTreeMapVisitor::new();
+                let values = try!(v.visit_map(visitor));
+                Ok(Value::Table(values))
+            }
+        }
+
+        deserializer.deserialize(ValueVisitor)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/display.rs
@@ -0,0 +1,209 @@
+use std::fmt;
+
+use Table as TomlTable;
+use Value::{self, String, Integer, Float, Boolean, Datetime, Array, Table};
+
+struct Printer<'a, 'b:'a> {
+    output: &'a mut fmt::Formatter<'b>,
+    stack: Vec<&'a str>,
+}
+
+struct Key<'a>(&'a [&'a str]);
+
+impl fmt::Display for Value {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            String(ref s) => write_str(f, s),
+            Integer(i) => write!(f, "{}", i),
+            Float(fp) => {
+                try!(write!(f, "{}", fp));
+                if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
+                Ok(())
+            }
+            Boolean(b) => write!(f, "{}", b),
+            Datetime(ref s) => write!(f, "{}", s),
+            Table(ref t) => {
+                let mut p = Printer { output: f, stack: Vec::new() };
+                p.print(t)
+            }
+            Array(ref a) => {
+                try!(write!(f, "["));
+                for (i, v) in a.iter().enumerate() {
+                    if i != 0 { try!(write!(f, ", ")); }
+                    try!(write!(f, "{}", v));
+                }
+                write!(f, "]")
+            }
+        }
+    }
+}
+
+fn write_str(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
+    try!(write!(f, "\""));
+    for ch in s.chars() {
+        match ch {
+            '\u{8}' => try!(write!(f, "\\b")),
+            '\u{9}' => try!(write!(f, "\\t")),
+            '\u{a}' => try!(write!(f, "\\n")),
+            '\u{c}' => try!(write!(f, "\\f")),
+            '\u{d}' => try!(write!(f, "\\r")),
+            '\u{22}' => try!(write!(f, "\\\"")),
+            '\u{5c}' => try!(write!(f, "\\\\")),
+            ch => try!(write!(f, "{}", ch)),
+        }
+    }
+    write!(f, "\"")
+}
+
+impl<'a, 'b> Printer<'a, 'b> {
+    fn print(&mut self, table: &'a TomlTable) -> fmt::Result {
+        let mut space_out_first = false;
+        for (k, v) in table.iter() {
+            match *v {
+                Table(..) => continue,
+                Array(ref a) => {
+                    if let Some(&Table(..)) = a.first() {
+                        continue;
+                    }
+                }
+                _ => {}
+            }
+            space_out_first = true;
+            try!(writeln!(self.output, "{} = {}", Key(&[k]), v));
+        }
+        for (i, (k, v)) in table.iter().enumerate() {
+            match *v {
+                Table(ref inner) => {
+                    self.stack.push(k);
+                    if space_out_first || i != 0 {
+                        try!(write!(self.output, "\n"));
+                    }
+                    try!(writeln!(self.output, "[{}]", Key(&self.stack)));
+                    try!(self.print(inner));
+                    self.stack.pop();
+                }
+                Array(ref inner) => {
+                    match inner.first() {
+                        Some(&Table(..)) => {}
+                        _ => continue
+                    }
+                    self.stack.push(k);
+                    for (j, inner) in inner.iter().enumerate() {
+                        if space_out_first || i != 0 || j != 0 {
+                            try!(write!(self.output, "\n"));
+                        }
+                        try!(writeln!(self.output, "[[{}]]", Key(&self.stack)));
+                        match *inner {
+                            Table(ref inner) => try!(self.print(inner)),
+                            _ => panic!("non-heterogeneous toml array"),
+                        }
+                    }
+                    self.stack.pop();
+                }
+                _ => {},
+            }
+        }
+        Ok(())
+    }
+}
+
+impl<'a> fmt::Display for Key<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for (i, part) in self.0.iter().enumerate() {
+            if i != 0 { try!(write!(f, ".")); }
+            let ok = part.chars().all(|c| {
+                match c {
+                    'a' ... 'z' |
+                    'A' ... 'Z' |
+                    '0' ... '9' |
+                    '-' | '_' => true,
+                    _ => false,
+                }
+            });
+            if ok {
+                try!(write!(f, "{}", part));
+            } else {
+                try!(write_str(f, part));
+            }
+        }
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+#[allow(warnings)]
+mod tests {
+    use Value;
+    use Value::{String, Integer, Float, Boolean, Datetime, Array, Table};
+    use std::collections::BTreeMap;
+
+    macro_rules! map( ($($k:expr => $v:expr),*) => ({
+        let mut _m = BTreeMap::new();
+        $(_m.insert($k.to_string(), $v);)*
+        _m
+    }) );
+
+    #[test]
+    fn simple_show() {
+        assert_eq!(String("foo".to_string()).to_string(),
+                   "\"foo\"");
+        assert_eq!(Integer(10).to_string(),
+                   "10");
+        assert_eq!(Float(10.0).to_string(),
+                   "10.0");
+        assert_eq!(Float(2.4).to_string(),
+                   "2.4");
+        assert_eq!(Boolean(true).to_string(),
+                   "true");
+        assert_eq!(Datetime("test".to_string()).to_string(),
+                   "test");
+        assert_eq!(Array(vec![]).to_string(),
+                   "[]");
+        assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string(),
+                   "[1, 2]");
+    }
+
+    #[test]
+    fn table() {
+        assert_eq!(Table(map! { }).to_string(),
+                   "");
+        assert_eq!(Table(map! { "test" => Integer(2) }).to_string(),
+                   "test = 2\n");
+        assert_eq!(Table(map! {
+                        "test" => Integer(2),
+                        "test2" => Table(map! {
+                            "test" => String("wut".to_string())
+                        })
+                   }).to_string(),
+                   "test = 2\n\
+                    \n\
+                    [test2]\n\
+                    test = \"wut\"\n");
+        assert_eq!(Table(map! {
+                        "test" => Integer(2),
+                        "test2" => Table(map! {
+                            "test" => String("wut".to_string())
+                        })
+                   }).to_string(),
+                   "test = 2\n\
+                    \n\
+                    [test2]\n\
+                    test = \"wut\"\n");
+        assert_eq!(Table(map! {
+                        "test" => Integer(2),
+                        "test2" => Array(vec![Table(map! {
+                            "test" => String("wut".to_string())
+                        })])
+                   }).to_string(),
+                   "test = 2\n\
+                    \n\
+                    [[test2]]\n\
+                    test = \"wut\"\n");
+        assert_eq!(Table(map! {
+                        "foo.bar" => Integer(2),
+                        "foo\"bar" => Integer(2)
+                   }).to_string(),
+                   "\"foo\\\"bar\" = 2\n\
+                    \"foo.bar\" = 2\n");
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/encoder/mod.rs
@@ -0,0 +1,203 @@
+use std::collections::BTreeMap;
+use std::error;
+use std::fmt;
+use std::mem;
+
+use {Value, Table};
+
+#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
+#[cfg(feature = "serde")] mod serde;
+
+/// A structure to transform Rust values into TOML values.
+///
+/// This encoder implements the serialization `Encoder` interface, allowing
+/// `Encodable` rust types to be fed into the encoder. The output of this
+/// encoder is a TOML `Table` structure. The resulting TOML can be stringified
+/// if necessary.
+///
+/// # Example
+///
+/// ```
+/// extern crate rustc_serialize;
+/// extern crate toml;
+///
+/// # fn main() {
+/// use toml::{Encoder, Value};
+/// use rustc_serialize::Encodable;
+///
+/// #[derive(RustcEncodable)]
+/// struct MyStruct { foo: isize, bar: String }
+/// let my_struct = MyStruct { foo: 4, bar: "hello!".to_string() };
+///
+/// let mut e = Encoder::new();
+/// my_struct.encode(&mut e).unwrap();
+///
+/// assert_eq!(e.toml.get(&"foo".to_string()), Some(&Value::Integer(4)))
+/// # }
+/// ```
+#[derive(Default, Debug)]
+pub struct Encoder {
+    /// Output TOML that is emitted. The current version of this encoder forces
+    /// the top-level representation of a structure to be a table.
+    ///
+    /// This field can be used to extract the return value after feeding a value
+    /// into this `Encoder`.
+    pub toml: Table,
+    state: State,
+}
+
+/// Enumeration of errors which can occur while encoding a rust value into a
+/// TOML value.
+#[allow(missing_copy_implementations)]
+#[derive(Debug)]
+pub enum Error {
+    /// Indication that a key was needed when a value was emitted, but no key
+    /// was previously emitted.
+    NeedsKey,
+    /// Indication that a key was emitted, but no value was emitted.
+    NoValue,
+    /// Indicates that a map key was attempted to be emitted at an invalid
+    /// location.
+    InvalidMapKeyLocation,
+    /// Indicates that a type other than a string was attempted to be used as a
+    /// map key type.
+    InvalidMapKeyType,
+    /// A custom error type was generated
+    Custom(String),
+}
+
+/// Internal state of the encoder when encoding transitions
+#[derive(Debug)]
+pub struct EncoderState {
+    inner: State,
+}
+
+#[derive(PartialEq, Debug)]
+enum State {
+    Start,
+    NextKey(String),
+    NextArray(Vec<Value>),
+    NextMapKey,
+}
+
+impl Default for State {
+    fn default() -> State { State::Start }
+}
+
+impl Encoder {
+    /// Constructs a new encoder which will emit to the given output stream.
+    pub fn new() -> Encoder {
+        Encoder { state: State::Start, toml: BTreeMap::new() }
+    }
+
+    fn emit_value(&mut self, v: Value) -> Result<(), Error> {
+        match mem::replace(&mut self.state, State::Start) {
+            State::NextKey(key) => { self.toml.insert(key, v); Ok(()) }
+            State::NextArray(mut vec) => {
+                // TODO: validate types
+                vec.push(v);
+                self.state = State::NextArray(vec);
+                Ok(())
+            }
+            State::NextMapKey => {
+                match v {
+                    Value::String(s) => { self.state = State::NextKey(s); Ok(()) }
+                    _ => Err(Error::InvalidMapKeyType)
+                }
+            }
+            _ => Err(Error::NeedsKey)
+        }
+    }
+
+    fn emit_none(&mut self) -> Result<(), Error> {
+        match mem::replace(&mut self.state, State::Start) {
+            State::Start => unreachable!(),
+            State::NextKey(_) => Ok(()),
+            State::NextArray(..) => panic!("how to encode None in an array?"),
+            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
+        }
+    }
+
+    fn seq_begin(&mut self) -> Result<State, Error> {
+        Ok(mem::replace(&mut self.state, State::NextArray(Vec::new())))
+    }
+
+    fn seq_end(&mut self, old: State) -> Result<(), Error> {
+        match mem::replace(&mut self.state, old) {
+            State::NextArray(v) => self.emit_value(Value::Array(v)),
+            _ => unreachable!(),
+        }
+    }
+
+    fn table_key<F>(&mut self, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        match mem::replace(&mut self.state, State::NextMapKey) {
+            State::Start => {}
+            _ => return Err(Error::InvalidMapKeyLocation),
+        }
+        try!(f(self));
+        match self.state {
+            State::NextKey(_) => Ok(()),
+            _ => Err(Error::InvalidMapKeyLocation),
+        }
+    }
+}
+
+/// Encodes an encodable value into a TOML value.
+///
+/// This function expects the type given to represent a TOML table in some form.
+/// If encoding encounters an error, then this function will fail the task.
+#[cfg(feature = "rustc-serialize")]
+pub fn encode<T: ::rustc_serialize::Encodable>(t: &T) -> Value {
+    let mut e = Encoder::new();
+    t.encode(&mut e).unwrap();
+    Value::Table(e.toml)
+}
+
+/// Encodes an encodable value into a TOML value.
+///
+/// This function expects the type given to represent a TOML table in some form.
+/// If encoding encounters an error, then this function will fail the task.
+#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
+pub fn encode<T: ::serde::Serialize>(t: &T) -> Value {
+    let mut e = Encoder::new();
+    t.serialize(&mut e).unwrap();
+    Value::Table(e.toml)
+}
+
+/// Encodes an encodable value into a TOML string.
+///
+/// This function expects the type given to represent a TOML table in some form.
+/// If encoding encounters an error, then this function will fail the task.
+#[cfg(feature = "rustc-serialize")]
+pub fn encode_str<T: ::rustc_serialize::Encodable>(t: &T) -> String {
+    encode(t).to_string()
+}
+
+/// Encodes an encodable value into a TOML string.
+///
+/// This function expects the type given to represent a TOML table in some form.
+/// If encoding encounters an error, then this function will fail the task.
+#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
+pub fn encode_str<T: ::serde::Serialize>(t: &T) -> String {
+    encode(t).to_string()
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::NeedsKey => write!(f, "need a key to encode"),
+            Error::NoValue => write!(f, "no value to emit for a previous key"),
+            Error::InvalidMapKeyLocation => write!(f, "a map cannot be emitted \
+                                                       at this location"),
+            Error::InvalidMapKeyType => write!(f, "only strings can be used as \
+                                                   key types"),
+            Error::Custom(ref s) => write!(f, "custom error: {}", s),
+        }
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str { "TOML encoding error" }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/encoder/rustc_serialize.rs
@@ -0,0 +1,748 @@
+use std::mem;
+
+use rustc_serialize;
+use Value;
+use super::{Encoder, Error, State};
+use super::Error::*;
+
+impl Encoder {
+    fn table<F>(&mut self, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        match mem::replace(&mut self.state, State::Start) {
+            State::NextKey(key) => {
+                let mut nested = Encoder::new();
+                try!(f(&mut nested));
+                self.toml.insert(key, Value::Table(nested.toml));
+                Ok(())
+            }
+            State::NextArray(mut arr) => {
+                let mut nested = Encoder::new();
+                try!(f(&mut nested));
+                arr.push(Value::Table(nested.toml));
+                self.state = State::NextArray(arr);
+                Ok(())
+            }
+            State::Start => f(self),
+            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
+        }
+    }
+
+    fn seq<F>(&mut self, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        let old = try!(self.seq_begin());
+        try!(f(self));
+        self.seq_end(old)
+    }
+}
+
+impl rustc_serialize::Encoder for Encoder {
+    type Error = Error;
+
+    fn emit_nil(&mut self) -> Result<(), Error> { Ok(()) }
+    fn emit_usize(&mut self, v: usize) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_u8(&mut self, v: u8) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_u16(&mut self, v: u16) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_u32(&mut self, v: u32) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_u64(&mut self, v: u64) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_isize(&mut self, v: isize) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_i8(&mut self, v: i8) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_i16(&mut self, v: i16) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_i32(&mut self, v: i32) -> Result<(), Error> {
+        self.emit_i64(v as i64)
+    }
+    fn emit_i64(&mut self, v: i64) -> Result<(), Error> {
+        self.emit_value(Value::Integer(v))
+    }
+    fn emit_bool(&mut self, v: bool) -> Result<(), Error> {
+        self.emit_value(Value::Boolean(v))
+    }
+    fn emit_f32(&mut self, v: f32) -> Result<(), Error> { self.emit_f64(v as f64) }
+    fn emit_f64(&mut self, v: f64) -> Result<(), Error> {
+        self.emit_value(Value::Float(v))
+    }
+    fn emit_char(&mut self, v: char) -> Result<(), Error> {
+        self.emit_str(&v.to_string())
+    }
+    fn emit_str(&mut self, v: &str) -> Result<(), Error> {
+        self.emit_value(Value::String(v.to_string()))
+    }
+    fn emit_enum<F>(&mut self, _name: &str, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_enum_variant<F>(&mut self, _v_name: &str, _v_id: usize,
+                            _len: usize, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_enum_struct_variant<F>(&mut self, _v_name: &str, _v_id: usize,
+                                   _len: usize,
+                                   _f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        panic!()
+    }
+    fn emit_enum_struct_variant_field<F>(&mut self,
+                                         _f_name: &str,
+                                         _f_idx: usize,
+                                         _f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        panic!()
+    }
+    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.table(f)
+    }
+    fn emit_struct_field<F>(&mut self, f_name: &str, _f_idx: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        let old = mem::replace(&mut self.state,
+                               State::NextKey(f_name.to_string()));
+        try!(f(self));
+        if self.state != State::Start {
+            return Err(NoValue)
+        }
+        self.state = old;
+        Ok(())
+    }
+    fn emit_tuple<F>(&mut self, len: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.emit_seq(len, f)
+    }
+    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.emit_seq_elt(idx, f)
+    }
+    fn emit_tuple_struct<F>(&mut self, _name: &str, _len: usize, _f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        unimplemented!()
+    }
+    fn emit_tuple_struct_arg<F>(&mut self, _f_idx: usize, _f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        unimplemented!()
+    }
+    fn emit_option<F>(&mut self, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_option_none(&mut self) -> Result<(), Error> {
+        self.emit_none()
+    }
+    fn emit_option_some<F>(&mut self, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_seq<F>(&mut self, _len: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.seq(f)
+    }
+    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+    fn emit_map<F>(&mut self, len: usize, f: F)
+        -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.emit_struct("foo", len, f)
+    }
+    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        self.table_key(f)
+    }
+    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Error>
+        where F: FnOnce(&mut Encoder) -> Result<(), Error>
+    {
+        f(self)
+    }
+}
+
+impl rustc_serialize::Encodable for Value {
+    fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
+        where E: rustc_serialize::Encoder
+    {
+        match *self {
+            Value::String(ref s) => e.emit_str(s),
+            Value::Integer(i) => e.emit_i64(i),
+            Value::Float(f) => e.emit_f64(f),
+            Value::Boolean(b) => e.emit_bool(b),
+            Value::Datetime(ref s) => e.emit_str(s),
+            Value::Array(ref a) => {
+                e.emit_seq(a.len(), |e| {
+                    for item in a {
+                        try!(item.encode(e));
+                    }
+                    Ok(())
+                })
+            }
+            Value::Table(ref t) => {
+                e.emit_map(t.len(), |e| {
+                    for (i, (key, value)) in t.iter().enumerate() {
+                        try!(e.emit_map_elt_key(i, |e| e.emit_str(key)));
+                        try!(e.emit_map_elt_val(i, |e| value.encode(e)));
+                    }
+                    Ok(())
+                })
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::collections::{BTreeMap, HashSet};
+    use rustc_serialize::{self, Encodable, Decodable};
+
+    use {Encoder, Decoder, DecodeError};
+    use Value;
+    use Value::{Table, Integer, Array, Float};
+
+    macro_rules! encode( ($t:expr) => ({
+        let mut e = Encoder::new();
+        $t.encode(&mut e).unwrap();
+        e.toml
+    }) );
+
+    macro_rules! decode( ($t:expr) => ({
+        let mut d = Decoder::new($t);
+        Decodable::decode(&mut d).unwrap()
+    }) );
+
+    macro_rules! map( ($($k:ident, $v:expr),*) => ({
+        let mut _m = BTreeMap::new();
+        $(_m.insert(stringify!($k).to_string(), $v);)*
+        _m
+    }) );
+
+    #[test]
+    fn smoke() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: isize }
+
+        let v = Foo { a: 2 };
+        assert_eq!(encode!(v), map! { a, Integer(2) });
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn smoke_hyphen() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a_b: isize }
+
+        let v = Foo { a_b: 2 };
+        assert_eq!(encode!(v), map! { a_b, Integer(2) });
+        assert_eq!(v, decode!(Table(encode!(v))));
+
+        let mut m = BTreeMap::new();
+        m.insert("a-b".to_string(), Integer(2));
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn nested() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: isize, b: Bar }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: String }
+
+        let v = Foo { a: 2, b: Bar { a: "test".to_string() } };
+        assert_eq!(encode!(v),
+                   map! {
+                       a, Integer(2),
+                       b, Table(map! {
+                           a, Value::String("test".to_string())
+                       })
+                   });
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn application_decode_error() {
+        #[derive(PartialEq, Debug)]
+        struct Range10(usize);
+        impl Decodable for Range10 {
+             fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Range10, D::Error> {
+                 let x: usize = try!(Decodable::decode(d));
+                 if x > 10 {
+                     Err(d.error("Value out of range!"))
+                 } else {
+                     Ok(Range10(x))
+                 }
+             }
+        }
+        let mut d_good = Decoder::new(Integer(5));
+        let mut d_bad1 = Decoder::new(Value::String("not an isize".to_string()));
+        let mut d_bad2 = Decoder::new(Integer(11));
+
+        assert_eq!(Ok(Range10(5)), Decodable::decode(&mut d_good));
+
+        let err1: Result<Range10, _> = Decodable::decode(&mut d_bad1);
+        assert!(err1.is_err());
+        let err2: Result<Range10, _> = Decodable::decode(&mut d_bad2);
+        assert!(err2.is_err());
+    }
+
+    #[test]
+    fn array() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Vec<isize> }
+
+        let v = Foo { a: vec![1, 2, 3, 4] };
+        assert_eq!(encode!(v),
+                   map! {
+                       a, Array(vec![
+                            Integer(1),
+                            Integer(2),
+                            Integer(3),
+                            Integer(4)
+                       ])
+                   });
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn tuple() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: (isize, isize, isize, isize) }
+
+        let v = Foo { a: (1, 2, 3, 4) };
+        assert_eq!(encode!(v),
+                   map! {
+                       a, Array(vec![
+                            Integer(1),
+                            Integer(2),
+                            Integer(3),
+                            Integer(4)
+                       ])
+                   });
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn inner_structs_with_options() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo {
+            a: Option<Box<Foo>>,
+            b: Bar,
+        }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar {
+            a: String,
+            b: f64,
+        }
+
+        let v = Foo {
+            a: Some(Box::new(Foo {
+                a: None,
+                b: Bar { a: "foo".to_string(), b: 4.5 },
+            })),
+            b: Bar { a: "bar".to_string(), b: 1.0 },
+        };
+        assert_eq!(encode!(v),
+                   map! {
+                       a, Table(map! {
+                           b, Table(map! {
+                               a, Value::String("foo".to_string()),
+                               b, Float(4.5)
+                           })
+                       }),
+                       b, Table(map! {
+                           a, Value::String("bar".to_string()),
+                           b, Float(1.0)
+                       })
+                   });
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn hashmap() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo {
+            map: BTreeMap<String, isize>,
+            set: HashSet<char>,
+        }
+
+        let v = Foo {
+            map: {
+                let mut m = BTreeMap::new();
+                m.insert("foo".to_string(), 10);
+                m.insert("bar".to_string(), 4);
+                m
+            },
+            set: {
+                let mut s = HashSet::new();
+                s.insert('a');
+                s
+            },
+        };
+        assert_eq!(encode!(v),
+            map! {
+                map, Table(map! {
+                    foo, Integer(10),
+                    bar, Integer(4)
+                }),
+                set, Array(vec![Value::String("a".to_string())])
+            }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn tuple_struct() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo(isize, String, f64);
+
+        let v = Foo(1, "foo".to_string(), 4.5);
+        assert_eq!(
+            encode!(v),
+            map! {
+                _field0, Integer(1),
+                _field1, Value::String("foo".to_string()),
+                _field2, Float(4.5)
+            }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn table_array() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Vec<Bar>, }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: isize }
+
+        let v = Foo { a: vec![Bar { a: 1 }, Bar { a: 2 }] };
+        assert_eq!(
+            encode!(v),
+            map! {
+                a, Array(vec![
+                    Table(map!{ a, Integer(1) }),
+                    Table(map!{ a, Integer(2) }),
+                ])
+            }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn type_errors() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { bar: isize }
+
+        let mut d = Decoder::new(Table(map! {
+            bar, Float(1.0)
+        }));
+        let a: Result<Foo, DecodeError> = Decodable::decode(&mut d);
+        match a {
+            Ok(..) => panic!("should not have decoded"),
+            Err(e) => {
+                assert_eq!(e.to_string(),
+                           "expected a value of type `integer`, but \
+                            found a value of type `float` for the key `bar`");
+            }
+        }
+    }
+
+    #[test]
+    fn missing_errors() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { bar: isize }
+
+        let mut d = Decoder::new(Table(map! {
+        }));
+        let a: Result<Foo, DecodeError> = Decodable::decode(&mut d);
+        match a {
+            Ok(..) => panic!("should not have decoded"),
+            Err(e) => {
+                assert_eq!(e.to_string(),
+                           "expected a value of type `integer` for the key `bar`");
+            }
+        }
+    }
+
+    #[test]
+    fn parse_enum() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: E }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        enum E {
+            Bar(isize),
+            Baz(f64),
+            Last(Foo2),
+        }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo2 {
+            test: String,
+        }
+
+        let v = Foo { a: E::Bar(10) };
+        assert_eq!(
+            encode!(v),
+            map! { a, Integer(10) }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+
+        let v = Foo { a: E::Baz(10.2) };
+        assert_eq!(
+            encode!(v),
+            map! { a, Float(10.2) }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+
+        let v = Foo { a: E::Last(Foo2 { test: "test".to_string() }) };
+        assert_eq!(
+            encode!(v),
+            map! { a, Table(map! { test, Value::String("test".to_string()) }) }
+        );
+        assert_eq!(v, decode!(Table(encode!(v))));
+    }
+
+    #[test]
+    fn unused_fields() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: isize }
+
+        let v = Foo { a: 2 };
+        let mut d = Decoder::new(Table(map! {
+            a, Integer(2),
+            b, Integer(5)
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, Some(Table(map! {
+            b, Integer(5)
+        })));
+    }
+
+    #[test]
+    fn unused_fields2() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Bar }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: isize }
+
+        let v = Foo { a: Bar { a: 2 } };
+        let mut d = Decoder::new(Table(map! {
+            a, Table(map! {
+                a, Integer(2),
+                b, Integer(5)
+            })
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, Some(Table(map! {
+            a, Table(map! {
+                b, Integer(5)
+            })
+        })));
+    }
+
+    #[test]
+    fn unused_fields3() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Bar }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: isize }
+
+        let v = Foo { a: Bar { a: 2 } };
+        let mut d = Decoder::new(Table(map! {
+            a, Table(map! {
+                a, Integer(2)
+            })
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, None);
+    }
+
+    #[test]
+    fn unused_fields4() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: BTreeMap<String, String> }
+
+        let v = Foo { a: map! { a, "foo".to_string() } };
+        let mut d = Decoder::new(Table(map! {
+            a, Table(map! {
+                a, Value::String("foo".to_string())
+            })
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, None);
+    }
+
+    #[test]
+    fn unused_fields5() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Vec<String> }
+
+        let v = Foo { a: vec!["a".to_string()] };
+        let mut d = Decoder::new(Table(map! {
+            a, Array(vec![Value::String("a".to_string())])
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, None);
+    }
+
+    #[test]
+    fn unused_fields6() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Option<Vec<String>> }
+
+        let v = Foo { a: Some(vec![]) };
+        let mut d = Decoder::new(Table(map! {
+            a, Array(vec![])
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, None);
+    }
+
+    #[test]
+    fn unused_fields7() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Vec<Bar> }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: isize }
+
+        let v = Foo { a: vec![Bar { a: 1 }] };
+        let mut d = Decoder::new(Table(map! {
+            a, Array(vec![Table(map! {
+                a, Integer(1),
+                b, Integer(2)
+            })])
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, Some(Table(map! {
+            a, Array(vec![Table(map! {
+                b, Integer(2)
+            })])
+        })));
+    }
+
+    #[test]
+    fn unused_fields8() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: BTreeMap<String, Bar> }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar { a: isize }
+
+        let v = Foo { a: map! { a, Bar { a: 2 } } };
+        let mut d = Decoder::new(Table(map! {
+            a, Table(map! {
+                a, Table(map! {
+                    a, Integer(2),
+                    b, Integer(2)
+                })
+            })
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        assert_eq!(d.toml, Some(Table(map! {
+            a, Table(map! {
+                a, Table(map! {
+                    b, Integer(2)
+                })
+            })
+        })));
+    }
+
+    #[test]
+    fn empty_arrays() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Vec<Bar> }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar;
+
+        let v = Foo { a: vec![] };
+        let mut d = Decoder::new(Table(map! {}));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+    }
+
+    #[test]
+    fn empty_arrays2() {
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Foo { a: Option<Vec<Bar>> }
+        #[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+        struct Bar;
+
+        let v = Foo { a: None };
+        let mut d = Decoder::new(Table(map! {}));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+
+        let v = Foo { a: Some(vec![]) };
+        let mut d = Decoder::new(Table(map! {
+            a, Array(vec![])
+        }));
+        assert_eq!(v, Decodable::decode(&mut d).unwrap());
+    }
+
+    #[test]
+    fn round_trip() {
+        let toml = r#"
+              [test]
+              foo = "bar"
+
+              [[values]]
+              foo = "baz"
+
+              [[values]]
+              foo = "qux"
+        "#;
+
+        let value: Value = toml.parse().unwrap();
+        let val2 = ::encode_str(&value).parse().unwrap();
+        assert_eq!(value, val2);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/encoder/serde.rs
@@ -0,0 +1,339 @@
+use std::mem;
+
+use serde::ser;
+use Value;
+use super::{Encoder, Error, EncoderState, State};
+
+impl Encoder {
+    fn table_begin(&mut self) -> Result<Self, Error> {
+        match self.state {
+            State::NextMapKey => Err(Error::InvalidMapKeyLocation),
+            _ => Ok(mem::replace(self, Encoder::new()))
+        }
+    }
+
+    fn table_end(&mut self, mut state: Self) -> Result<(), Error> {
+        match state.state {
+            State::NextKey(key) => {
+                mem::swap(&mut self.toml, &mut state.toml);
+                self.toml.insert(key, Value::Table(state.toml));
+            },
+            State::NextArray(mut arr) => {
+                mem::swap(&mut self.toml, &mut state.toml);
+                arr.push(Value::Table(state.toml));
+                self.state = State::NextArray(arr);
+            },
+            State::Start => {},
+            State::NextMapKey => unreachable!(),
+        }
+        Ok(())
+    }
+}
+
+impl ser::Serializer for Encoder {
+    type Error = Error;
+    type MapState = Self;
+    type StructState = Self;
+    type StructVariantState = Self;
+    type SeqState = EncoderState;
+    type TupleState = EncoderState;
+    type TupleStructState = EncoderState;
+    type TupleVariantState = EncoderState;
+
+    fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
+        self.emit_value(Value::Boolean(v))
+    }
+
+    fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
+        self.emit_value(Value::Integer(v))
+    }
+
+    // TODO: checked casts
+
+    fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
+        self.serialize_i64(v as i64)
+    }
+
+    fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
+        self.serialize_f64(v as f64)
+    }
+
+    fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
+        self.emit_value(Value::Float(v))
+    }
+
+    fn serialize_str(&mut self, value: &str) -> Result<(), Error> {
+        self.emit_value(Value::String(value.to_string()))
+    }
+
+    fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Error> {
+        Ok(())
+    }
+
+    fn serialize_unit(&mut self) -> Result<(), Error> {
+        Ok(())
+    }
+
+    fn serialize_none(&mut self) -> Result<(), Error> {
+        self.emit_none()
+    }
+
+    fn serialize_char(&mut self, c: char) -> Result<(), Error> {
+        self.serialize_str(&c.to_string())
+    }
+
+    fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
+        where V: ser::Serialize
+    {
+        value.serialize(self)
+    }
+
+    fn serialize_bytes(&mut self, v: &[u8]) -> Result<(), Error> {
+        let mut state = try!(self.serialize_seq(Some(v.len())));
+        for c in v {
+            try!(self.serialize_seq_elt(&mut state, c));
+        }
+        self.serialize_seq_end(state)
+    }
+
+    fn serialize_seq_fixed_size(&mut self, len: usize)
+                                -> Result<EncoderState, Error> {
+        self.serialize_seq(Some(len))
+    }
+
+    fn serialize_seq(&mut self, _len: Option<usize>)
+                     -> Result<EncoderState, Error> {
+        self.seq_begin().map(|s| EncoderState { inner: s })
+    }
+
+    fn serialize_seq_elt<T>(&mut self,
+                            _state: &mut EncoderState,
+                            value: T) -> Result<(), Error>
+        where T: ser::Serialize
+    {
+        value.serialize(self)
+    }
+
+    fn serialize_seq_end(&mut self, state: EncoderState) -> Result<(), Error> {
+        self.seq_end(state.inner)
+    }
+
+    fn serialize_tuple(&mut self, len: usize)
+                       -> Result<EncoderState, Error> {
+        self.serialize_seq(Some(len))
+    }
+
+    fn serialize_tuple_elt<T>(&mut self,
+                              state: &mut EncoderState,
+                              value: T) -> Result<(), Error>
+        where T: ser::Serialize
+    {
+        self.serialize_seq_elt(state, value)
+    }
+
+    fn serialize_tuple_end(&mut self, state: EncoderState) -> Result<(), Error> {
+        self.serialize_seq_end(state)
+    }
+
+    fn serialize_tuple_struct(&mut self,
+                              _name: &'static str,
+                              len: usize) -> Result<EncoderState, Error> {
+        self.serialize_seq(Some(len))
+    }
+
+    fn serialize_tuple_struct_elt<T>(&mut self,
+                                     state: &mut EncoderState,
+                                     value: T) -> Result<(), Error>
+        where T: ser::Serialize
+    {
+        self.serialize_seq_elt(state, value)
+    }
+
+    fn serialize_tuple_struct_end(&mut self, state: EncoderState)
+                                  -> Result<(), Error> {
+        self.serialize_seq_end(state)
+    }
+
+    fn serialize_tuple_variant(&mut self,
+                               _name: &'static str,
+                               _id: usize,
+                               _variant: &'static str,
+                               len: usize) -> Result<EncoderState, Error> {
+        self.serialize_seq(Some(len))
+    }
+
+    fn serialize_tuple_variant_elt<T>(&mut self,
+                                      state: &mut EncoderState,
+                                      value: T) -> Result<(), Error>
+        where T: ser::Serialize
+    {
+        self.serialize_seq_elt(state, value)
+    }
+
+    fn serialize_tuple_variant_end(&mut self, state: EncoderState)
+                                   -> Result<(), Error> {
+        self.serialize_seq_end(state)
+    }
+
+    fn serialize_map(&mut self, _len: Option<usize>) -> Result<Self, Error> {
+        self.table_begin()
+    }
+
+    fn serialize_map_key<K>(&mut self,
+                            _state: &mut Encoder,
+                            key: K) -> Result<(), Error>
+        where K: ser::Serialize
+    {
+        self.table_key(|me| key.serialize(me))
+    }
+
+    fn serialize_map_value<V>(&mut self,
+                              _state: &mut Encoder,
+                              value: V) -> Result<(), Error>
+        where V: ser::Serialize
+    {
+        value.serialize(self)
+    }
+
+    fn serialize_map_end(&mut self, state: Self) -> Result<(), Error> {
+        self.table_end(state)
+    }
+
+    fn serialize_struct(&mut self,
+                        _name: &'static str,
+                        len: usize) -> Result<Self, Error> {
+        self.serialize_map(Some(len))
+    }
+
+    fn serialize_struct_elt<V>(&mut self,
+                               state: &mut Encoder,
+                               key: &'static str,
+                               value: V) -> Result<(), Error>
+        where V: ser::Serialize
+    {
+        try!(self.serialize_map_key(state, key));
+        self.serialize_map_value(state, value)
+    }
+
+    fn serialize_struct_end(&mut self, state: Self) -> Result<(), Error> {
+        self.serialize_map_end(state)
+    }
+
+    fn serialize_struct_variant(&mut self,
+                                _name: &'static str,
+                                _id: usize,
+                                _variant: &'static str,
+                                len: usize) -> Result<Self, Error> {
+        self.serialize_map(Some(len))
+    }
+
+    fn serialize_struct_variant_elt<V>(&mut self,
+                                       state: &mut Encoder,
+                                       key: &'static str,
+                                       value: V) -> Result<(), Error>
+        where V: ser::Serialize
+    {
+        try!(self.serialize_map_key(state, key));
+        self.serialize_map_value(state, value)
+    }
+
+    fn serialize_struct_variant_end(&mut self, state: Self) -> Result<(), Error> {
+        self.serialize_map_end(state)
+    }
+
+    fn serialize_newtype_struct<T>(&mut self,
+                                   _name: &'static str,
+                                   value: T) -> Result<(), Self::Error>
+        where T: ser::Serialize,
+    {
+        // Don't serialize the newtype struct in a tuple.
+        value.serialize(self)
+    }
+
+    fn serialize_newtype_variant<T>(&mut self,
+                                    _name: &'static str,
+                                    _variant_index: usize,
+                                    _variant: &'static str,
+                                    value: T) -> Result<(), Self::Error>
+        where T: ser::Serialize,
+    {
+        // Don't serialize the newtype struct variant in a tuple.
+        value.serialize(self)
+    }
+
+    fn serialize_unit_variant(&mut self,
+                               _name: &'static str,
+                               _variant_index: usize,
+                               _variant: &'static str,
+                               ) -> Result<(), Self::Error>
+    {
+        Ok(())
+    }
+}
+
+impl ser::Serialize for Value {
+    fn serialize<E>(&self, e: &mut E) -> Result<(), E::Error>
+        where E: ser::Serializer
+    {
+        match *self {
+            Value::String(ref s) => e.serialize_str(s),
+            Value::Integer(i) => e.serialize_i64(i),
+            Value::Float(f) => e.serialize_f64(f),
+            Value::Boolean(b) => e.serialize_bool(b),
+            Value::Datetime(ref s) => e.serialize_str(s),
+            Value::Array(ref a) => {
+                let mut state = try!(e.serialize_seq(Some(a.len())));
+                for el in a.iter() {
+                    try!(e.serialize_seq_elt(&mut state, el));
+                }
+                e.serialize_seq_end(state)
+            }
+            Value::Table(ref t) => {
+                let mut state = try!(e.serialize_map(Some(t.len())));
+                for (k, v) in t.iter() {
+                    try!(e.serialize_map_key(&mut state, k));
+                    try!(e.serialize_map_value(&mut state, v));
+                }
+                e.serialize_map_end(state)
+            }
+        }
+    }
+}
+
+impl ser::Error for Error {
+    fn custom<T: Into<String>>(msg: T) -> Error {
+        Error::Custom(msg.into())
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/lib.rs
@@ -0,0 +1,492 @@
+//! A TOML-parsing library
+//!
+//! This library is an implementation in Rust of a parser for TOML configuration
+//! files [1]. It is focused around high quality errors including specific spans
+//! and detailed error messages when things go wrong.
+//!
+//! This implementation currently passes the language agnostic [test suite][2].
+//!
+//! # Example
+//!
+//! ```
+//! let toml = r#"
+//!     [test]
+//!     foo = "bar"
+//! "#;
+//!
+//! let value = toml::Parser::new(toml).parse().unwrap();
+//! println!("{:?}", value);
+//! ```
+//!
+//! # Conversions
+//!
+//! This library also supports using the standard `Encodable` and `Decodable`
+//! traits with TOML values. This library provides the following conversion
+//! capabilities:
+//!
+//! * `String` => `toml::Value` - via `Parser`
+//! * `toml::Value` => `String` - via `Display`
+//! * `toml::Value` => rust object - via `Decoder`
+//! * rust object => `toml::Value` - via `Encoder`
+//!
+//! Convenience functions for performing multiple conversions at a time are also
+//! provided.
+//!
+//! [1]: https://github.com/mojombo/toml
+//! [2]: https://github.com/BurntSushi/toml-test
+
+#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+
+#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
+#[cfg(feature = "serde")] extern crate serde;
+
+use std::collections::BTreeMap;
+use std::str::FromStr;
+
+pub use parser::{Parser, ParserError};
+
+#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
+pub use self::encoder::{Encoder, Error, EncoderState, encode, encode_str};
+#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
+pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};
+
+mod parser;
+mod display;
+#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
+mod encoder;
+#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
+mod decoder;
+
+/// Representation of a TOML value.
+#[derive(PartialEq, Clone, Debug)]
+#[allow(missing_docs)]
+pub enum Value {
+    String(String),
+    Integer(i64),
+    Float(f64),
+    Boolean(bool),
+    Datetime(String),
+    Array(Array),
+    Table(Table),
+}
+
+/// Type representing a TOML array, payload of the `Value::Array` variant
+pub type Array = Vec<Value>;
+
+/// Type representing a TOML table, payload of the `Value::Table` variant
+pub type Table = BTreeMap<String, Value>;
+
+impl Value {
+    /// Tests whether this and another value have the same type.
+    pub fn same_type(&self, other: &Value) -> bool {
+        match (self, other) {
+            (&Value::String(..), &Value::String(..)) |
+            (&Value::Integer(..), &Value::Integer(..)) |
+            (&Value::Float(..), &Value::Float(..)) |
+            (&Value::Boolean(..), &Value::Boolean(..)) |
+            (&Value::Datetime(..), &Value::Datetime(..)) |
+            (&Value::Array(..), &Value::Array(..)) |
+            (&Value::Table(..), &Value::Table(..)) => true,
+
+            _ => false,
+        }
+    }
+
+    /// Returns a human-readable representation of the type of this value.
+    pub fn type_str(&self) -> &'static str {
+        match *self {
+            Value::String(..) => "string",
+            Value::Integer(..) => "integer",
+            Value::Float(..) => "float",
+            Value::Boolean(..) => "boolean",
+            Value::Datetime(..) => "datetime",
+            Value::Array(..) => "array",
+            Value::Table(..) => "table",
+        }
+    }
+
+    /// Extracts the string of this value if it is a string.
+    pub fn as_str(&self) -> Option<&str> {
+        match *self { Value::String(ref s) => Some(&**s), _ => None }
+    }
+
+    /// Extracts the integer value if it is an integer.
+    pub fn as_integer(&self) -> Option<i64> {
+        match *self { Value::Integer(i) => Some(i), _ => None }
+    }
+
+    /// Extracts the float value if it is a float.
+    pub fn as_float(&self) -> Option<f64> {
+        match *self { Value::Float(f) => Some(f), _ => None }
+    }
+
+    /// Extracts the boolean value if it is a boolean.
+    pub fn as_bool(&self) -> Option<bool> {
+        match *self { Value::Boolean(b) => Some(b), _ => None }
+    }
+
+    /// Extracts the datetime value if it is a datetime.
+    ///
+    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
+    /// example date is:
+    ///
+    /// ```notrust
+    /// 1979-05-27T07:32:00Z
+    /// ```
+    pub fn as_datetime(&self) -> Option<&str> {
+        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
+    }
+
+    /// Extracts the array value if it is an array.
+    pub fn as_slice(&self) -> Option<&[Value]> {
+        match *self { Value::Array(ref s) => Some(&**s), _ => None }
+    }
+
+    /// Extracts the table value if it is a table.
+    pub fn as_table(&self) -> Option<&Table> {
+        match *self { Value::Table(ref s) => Some(s), _ => None }
+    }
+
+    /// Lookups for value at specified path.
+    ///
+    /// Uses '.' as a path separator.
+    ///
+    /// Note: arrays have zero-based indexes.
+    ///
+    /// Note: empty path returns self.
+    ///
+    /// ```
+    /// # #![allow(unstable)]
+    /// let toml = r#"
+    ///      [test]
+    ///      foo = "bar"
+    ///
+    ///      [[values]]
+    ///      foo = "baz"
+    ///
+    ///      [[values]]
+    ///      foo = "qux"
+    /// "#;
+    /// let value: toml::Value = toml.parse().unwrap();
+    ///
+    /// let foo = value.lookup("test.foo").unwrap();
+    /// assert_eq!(foo.as_str().unwrap(), "bar");
+    ///
+    /// let foo = value.lookup("values.1.foo").unwrap();
+    /// assert_eq!(foo.as_str().unwrap(), "qux");
+    ///
+    /// let no_bar = value.lookup("test.bar");
+    /// assert_eq!(no_bar.is_none(), true);
+    /// ```
+    pub fn lookup(&self, path: &str) -> Option<&Value> {
+        let ref path = match Parser::new(path).lookup() {
+            Some(path) => path,
+            None => return None,
+        };
+        let mut cur_value = self;
+        if path.is_empty() {
+            return Some(cur_value)
+        }
+
+        for key in path {
+            match *cur_value {
+                Value::Table(ref hm) => {
+                    match hm.get(key) {
+                        Some(v) => cur_value = v,
+                        None => return None
+                    }
+                },
+                Value::Array(ref v) => {
+                    match key.parse::<usize>().ok() {
+                        Some(idx) if idx < v.len() => cur_value = &v[idx],
+                        _ => return None
+                    }
+                },
+                _ => return None
+            }
+        };
+
+        Some(cur_value)
+
+    }
+    /// Lookups for mutable value at specified path.
+    ///
+    /// Uses '.' as a path separator.
+    ///
+    /// Note: arrays have zero-based indexes.
+    ///
+    /// Note: empty path returns self.
+    ///
+    /// ```
+    /// # #![allow(unstable)]
+    /// let toml = r#"
+    ///      [test]
+    ///      foo = "bar"
+    ///
+    ///      [[values]]
+    ///      foo = "baz"
+    ///
+    ///      [[values]]
+    ///      foo = "qux"
+    /// "#;
+    /// let mut value: toml::Value = toml.parse().unwrap();
+    /// {
+    ///    let string = value.lookup_mut("test.foo").unwrap();
+    ///    assert_eq!(string, &mut toml::Value::String(String::from("bar")));
+    ///    *string = toml::Value::String(String::from("foo"));
+    /// }
+    /// let result = value.lookup_mut("test.foo").unwrap();
+    /// assert_eq!(result.as_str().unwrap(), "foo");
+    /// ```
+    pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
+       let ref path = match Parser::new(path).lookup() {
+            Some(path) => path,
+            None => return None,
+        };
+
+        let mut cur = self;
+        if path.is_empty() {
+            return Some(cur)
+        }
+
+        for key in path {
+            let tmp = cur;
+            match *tmp {
+                Value::Table(ref mut hm) => {
+                    match hm.get_mut(key) {
+                        Some(v) => cur = v,
+                        None => return None
+                    }
+                }
+                Value::Array(ref mut v) => {
+                    match key.parse::<usize>().ok() {
+                        Some(idx) if idx < v.len() => cur = &mut v[idx],
+                        _ => return None
+                    }
+                }
+                _ => return None
+           }
+        }
+        Some(cur)
+    }
+}
+
+impl FromStr for Value {
+    type Err = Vec<ParserError>;
+    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
+        let mut p = Parser::new(s);
+        match p.parse().map(Value::Table) {
+            Some(n) => Ok(n),
+            None => Err(p.errors),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Value;
+
+    #[test]
+    fn lookup_mut_change() {
+        let toml = r#"
+              [test]
+              foo = "bar"
+
+              [[values]]
+              foo = "baz"
+
+              [[values]]
+              foo = "qux"
+        "#;
+
+        let mut value: Value = toml.parse().unwrap();
+        {
+          let foo = value.lookup_mut("values.0.foo").unwrap();
+          *foo = Value::String(String::from("bar"));
+        }
+        let foo = value.lookup("values.0.foo").unwrap();
+        assert_eq!(foo.as_str().unwrap(), "bar");
+    }
+
+    #[test]
+    fn lookup_mut_valid() {
+        let toml = r#"
+              [test]
+              foo = "bar"
+
+              [[values]]
+              foo = "baz"
+
+              [[values]]
+              foo = "qux"
+        "#;
+
+        let mut value: Value = toml.parse().unwrap();
+
+        {
+            let test_foo = value.lookup_mut("test.foo").unwrap();
+            assert_eq!(test_foo.as_str().unwrap(), "bar");
+        }
+
+        {
+            let foo1 = value.lookup_mut("values.1.foo").unwrap();
+            assert_eq!(foo1.as_str().unwrap(), "qux");
+        }
+
+        assert!(value.lookup_mut("test.bar").is_none());
+        assert!(value.lookup_mut("test.foo.bar").is_none());
+    }
+
+    #[test]
+    fn lookup_mut_invalid_index() {
+        let toml = r#"
+            [[values]]
+            foo = "baz"
+        "#;
+
+        let mut value: Value = toml.parse().unwrap();
+
+        {
+            let foo = value.lookup_mut("test.foo");
+            assert!(foo.is_none());
+        }
+
+        {
+            let foo = value.lookup_mut("values.100.foo");
+            assert!(foo.is_none());
+        }
+
+        {
+            let foo = value.lookup_mut("values.str.foo");
+            assert!(foo.is_none());
+        }
+    }
+
+    #[test]
+    fn lookup_mut_self() {
+        let mut value: Value = r#"foo = "bar""#.parse().unwrap();
+
+        {
+            let foo = value.lookup_mut("foo").unwrap();
+            assert_eq!(foo.as_str().unwrap(), "bar");
+        }
+
+        let foo = value.lookup_mut("").unwrap();
+        assert!(foo.as_table().is_some());
+
+        let baz = foo.lookup_mut("foo").unwrap();
+        assert_eq!(baz.as_str().unwrap(), "bar");
+    }
+
+    #[test]
+    fn lookup_valid() {
+        let toml = r#"
+              [test]
+              foo = "bar"
+
+              [[values]]
+              foo = "baz"
+
+              [[values]]
+              foo = "qux"
+        "#;
+
+        let value: Value = toml.parse().unwrap();
+
+        let test_foo = value.lookup("test.foo").unwrap();
+        assert_eq!(test_foo.as_str().unwrap(), "bar");
+
+        let foo1 = value.lookup("values.1.foo").unwrap();
+        assert_eq!(foo1.as_str().unwrap(), "qux");
+
+        assert!(value.lookup("test.bar").is_none());
+        assert!(value.lookup("test.foo.bar").is_none());
+    }
+
+    #[test]
+    fn lookup_invalid_index() {
+        let toml = r#"
+            [[values]]
+            foo = "baz"
+        "#;
+
+        let value: Value = toml.parse().unwrap();
+
+        let foo = value.lookup("test.foo");
+        assert!(foo.is_none());
+
+        let foo = value.lookup("values.100.foo");
+        assert!(foo.is_none());
+
+        let foo = value.lookup("values.str.foo");
+        assert!(foo.is_none());
+    }
+
+    #[test]
+    fn lookup_self() {
+        let value: Value = r#"foo = "bar""#.parse().unwrap();
+
+        let foo = value.lookup("foo").unwrap();
+        assert_eq!(foo.as_str().unwrap(), "bar");
+
+        let foo = value.lookup("").unwrap();
+        assert!(foo.as_table().is_some());
+
+        let baz = foo.lookup("foo").unwrap();
+        assert_eq!(baz.as_str().unwrap(), "bar");
+    }
+
+    #[test]
+    fn lookup_advanced() {
+        let value: Value = "[table]\n\"value\" = 0".parse().unwrap();
+        let looked = value.lookup("table.\"value\"").unwrap();
+        assert_eq!(*looked, Value::Integer(0));
+    }
+
+    #[test]
+    fn lookup_advanced_table() {
+        let value: Value = "[table.\"name.other\"]\nvalue = \"my value\"".parse().unwrap();
+        let looked = value.lookup(r#"table."name.other".value"#).unwrap();
+        assert_eq!(*looked, Value::String(String::from("my value")));
+    }
+
+    #[test]
+    fn lookup_mut_advanced() {
+        let mut value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        let looked = value.lookup_mut("table.\"value\".1").unwrap();
+        assert_eq!(*looked, Value::Integer(1));
+    }
+
+    #[test]
+    fn single_dot() {
+        let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        assert_eq!(None, value.lookup("."));
+    }
+
+    #[test]
+    fn array_dot() {
+        let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        assert_eq!(None, value.lookup("0."));
+    }
+
+    #[test]
+    fn dot_inside() {
+        let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        assert_eq!(None, value.lookup("table.\"value.0\""));
+    }
+
+    #[test]
+    fn table_with_quotes() {
+        let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        assert_eq!(None, value.lookup("\"table.element\".\"value\".0"));
+    }
+
+    #[test]
+    fn table_with_quotes_2() {
+        let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
+        assert_eq!(Value::Integer(0), *value.lookup("table.\"element\".\"value\".0").unwrap());
+    }
+
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/src/parser.rs
@@ -0,0 +1,1627 @@
+use std::char;
+use std::collections::btree_map::{BTreeMap, Entry};
+use std::error::Error;
+use std::fmt;
+use std::str;
+
+macro_rules! try {
+    ($e:expr) => (match $e { Some(s) => s, None => return None })
+}
+
+// We redefine Value because we need to keep track of encountered table
+// definitions, eg when parsing:
+//
+//      [a]
+//      [a.b]
+//      [a]
+//
+// we have to error out on redefinition of [a]. This bit of data is difficult to
+// track in a side table so we just have a "stripped down" AST to work with
+// which has the relevant metadata fields in it.
+struct TomlTable {
+    values: BTreeMap<String, Value>,
+    defined: bool,
+}
+
+impl TomlTable {
+    fn convert(self) -> super::Table {
+        self.values.into_iter().map(|(k,v)| (k, v.convert())).collect()
+    }
+}
+
+enum Value {
+    String(String),
+    Integer(i64),
+    Float(f64),
+    Boolean(bool),
+    Datetime(String),
+    Array(Vec<Value>),
+    Table(TomlTable),
+}
+
+impl Value {
+    fn type_str(&self) -> &'static str {
+        match *self {
+            Value::String(..) => "string",
+            Value::Integer(..) => "integer",
+            Value::Float(..) => "float",
+            Value::Boolean(..) => "boolean",
+            Value::Datetime(..) => "datetime",
+            Value::Array(..) => "array",
+            Value::Table(..) => "table",
+        }
+    }
+
+    fn same_type(&self, other: &Value) -> bool {
+        match (self, other) {
+            (&Value::String(..), &Value::String(..)) |
+            (&Value::Integer(..), &Value::Integer(..)) |
+            (&Value::Float(..), &Value::Float(..)) |
+            (&Value::Boolean(..), &Value::Boolean(..)) |
+            (&Value::Datetime(..), &Value::Datetime(..)) |
+            (&Value::Array(..), &Value::Array(..)) |
+            (&Value::Table(..), &Value::Table(..)) => true,
+
+            _ => false,
+        }
+    }
+
+    fn convert(self) -> super::Value {
+        match self {
+            Value::String(x) => super::Value::String(x),
+            Value::Integer(x) => super::Value::Integer(x),
+            Value::Float(x) => super::Value::Float(x),
+            Value::Boolean(x) => super::Value::Boolean(x),
+            Value::Datetime(x) => super::Value::Datetime(x),
+            Value::Array(v) =>
+                super::Value::Array(
+                    v.into_iter().map(|x| x.convert()).collect()
+                ),
+            Value::Table(t) => super::Value::Table(t.convert())
+        }
+    }
+}
+
+/// Parser for converting a string to a TOML `Value` instance.
+///
+/// This parser contains the string slice that is being parsed, and exports the
+/// list of errors which have occurred during parsing.
+pub struct Parser<'a> {
+    input: &'a str,
+    cur: str::CharIndices<'a>,
+    require_newline_after_table: bool,
+
+    /// A list of all errors which have occurred during parsing.
+    ///
+    /// Not all parse errors are fatal, so this list is added to as much as
+    /// possible without aborting parsing. If `None` is returned by `parse`, it
+    /// is guaranteed that this list is not empty.
+    pub errors: Vec<ParserError>,
+}
+
+/// A structure representing a parse error.
+///
+/// The data in this structure can be used to trace back to the original cause
+/// of the error in order to provide diagnostics about parse errors.
+#[derive(Debug, Clone)]
+pub struct ParserError {
+    /// The low byte at which this error is pointing at.
+    pub lo: usize,
+    /// One byte beyond the last character at which this error is pointing at.
+    pub hi: usize,
+    /// A human-readable description explaining what the error is.
+    pub desc: String,
+}
+
+impl<'a> Parser<'a> {
+    /// Creates a new parser for a string.
+    ///
+    /// The parser can be executed by invoking the `parse` method.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let toml = r#"
+    ///     [test]
+    ///     foo = "bar"
+    /// "#;
+    ///
+    /// let mut parser = toml::Parser::new(toml);
+    /// match parser.parse() {
+    ///     Some(value) => println!("found toml: {:?}", value),
+    ///     None => {
+    ///         println!("parse errors: {:?}", parser.errors);
+    ///     }
+    /// }
+    /// ```
+    pub fn new(s: &'a str) -> Parser<'a> {
+        Parser {
+            input: s,
+            cur: s.char_indices(),
+            errors: Vec::new(),
+            require_newline_after_table: true,
+        }
+    }
+
+    /// Converts a byte offset from an error message to a (line, column) pair
+    ///
+    /// All indexes are 0-based.
+    pub fn to_linecol(&self, offset: usize) -> (usize, usize) {
+        let mut cur = 0;
+        for (i, line) in self.input.lines().enumerate() {
+            if cur + line.len() + 1 > offset {
+                return (i, offset - cur)
+            }
+            cur += line.len() + 1;
+        }
+        (self.input.lines().count(), 0)
+    }
+
+    /// Historical versions of toml-rs accidentally allowed a newline after a
+    /// table definition, but the TOML spec requires a newline after a table
+    /// definition header.
+    ///
+    /// This option can be set to `false` (the default is `true`) to emulate
+    /// this behavior for backwards compatibility with older toml-rs versions.
+    pub fn set_require_newline_after_table(&mut self, require: bool) {
+        self.require_newline_after_table = require;
+    }
+
+    fn next_pos(&self) -> usize {
+        self.cur.clone().next().map(|p| p.0).unwrap_or(self.input.len())
+    }
+
+    // Returns true and consumes the next character if it matches `ch`,
+    // otherwise do nothing and return false
+    fn eat(&mut self, ch: char) -> bool {
+        match self.peek(0) {
+            Some((_, c)) if c == ch => { self.cur.next(); true }
+            Some(_) | None => false,
+        }
+    }
+
+    // Peeks ahead `n` characters
+    fn peek(&self, n: usize) -> Option<(usize, char)> {
+        self.cur.clone().skip(n).next()
+    }
+
+    fn expect(&mut self, ch: char) -> bool {
+        if self.eat(ch) { return true }
+        let mut it = self.cur.clone();
+        let lo = it.next().map(|p| p.0).unwrap_or(self.input.len());
+        let hi = it.next().map(|p| p.0).unwrap_or(self.input.len());
+        self.errors.push(ParserError {
+            lo: lo,
+            hi: hi,
+            desc: match self.cur.clone().next() {
+                Some((_, c)) => format!("expected `{}`, but found `{}`", ch, c),
+                None => format!("expected `{}`, but found eof", ch)
+            }
+        });
+        false
+    }
+
+    // Consumes a BOM (Byte Order Mark) if one is next
+    fn bom(&mut self) -> bool {
+        match self.peek(0) {
+            Some((_, '\u{feff}')) => { self.cur.next(); true }
+            _ => false
+        }
+    }
+
+    // Consumes whitespace ('\t' and ' ') until another character (or EOF) is
+    // reached. Returns if any whitespace was consumed
+    fn ws(&mut self) -> bool {
+        let mut ret = false;
+        loop {
+            match self.peek(0) {
+                Some((_, '\t')) |
+                Some((_, ' ')) => { self.cur.next(); ret = true; }
+                _ => break,
+            }
+        }
+        ret
+    }
+
+    // Consumes the rest of the line after a comment character
+    fn comment(&mut self) -> bool {
+        if !self.eat('#') { return false }
+        for (_, ch) in self.cur.by_ref() {
+            if ch == '\n' { break }
+        }
+        true
+    }
+
+    // Consumes a newline if one is next
+    fn newline(&mut self) -> bool {
+        match self.peek(0) {
+            Some((_, '\n')) => { self.cur.next(); true }
+            Some((_, '\r')) if self.peek(1).map(|c| c.1) == Some('\n') => {
+                self.cur.next(); self.cur.next(); true
+            }
+            _ => false
+        }
+    }
+
+    // Match EOF
+    fn eof(&self) -> bool {
+        self.peek(0).is_none()
+    }
+
+    /// Executes the parser, parsing the string contained within.
+    ///
+    /// This function will return the `TomlTable` instance if parsing is
+    /// successful, or it will return `None` if any parse error or invalid TOML
+    /// error occurs.
+    ///
+    /// If an error occurs, the `errors` field of this parser can be consulted
+    /// to determine the cause of the parse failure.
+    pub fn parse(&mut self) -> Option<super::Table> {
+        let mut ret = TomlTable { values: BTreeMap::new(), defined: false };
+        self.bom();
+        while self.peek(0).is_some() {
+            self.ws();
+            if self.newline() { continue }
+            if self.comment() { continue }
+            if self.eat('[') {
+                let array = self.eat('[');
+                let start = self.next_pos();
+
+                // Parse the name of the section
+                let mut keys = Vec::new();
+                loop {
+                    self.ws();
+                    if let Some(s) = self.key_name() {
+                        keys.push(s);
+                    }
+                    self.ws();
+                    if self.eat(']') {
+                        if array && !self.expect(']') { return None }
+                        break
+                    }
+                    if !self.expect('.') { return None }
+                }
+                if keys.is_empty() { return None }
+
+                // Build the section table
+                let mut table = TomlTable {
+                    values: BTreeMap::new(),
+                    defined: true,
+                };
+                if self.require_newline_after_table {
+                    self.ws();
+                    if !self.comment() && !self.newline() && !self.eof() {
+                        self.errors.push(ParserError {
+                            lo: start,
+                            hi: start,
+                            desc: "expected a newline after table definition".to_string(),
+                        });
+                        return None
+                    }
+                }
+                if !self.values(&mut table) { return None }
+                if array {
+                    self.insert_array(&mut ret, &keys, Value::Table(table),
+                                      start)
+                } else {
+                    self.insert_table(&mut ret, &keys, table, start)
+                }
+            } else if !self.values(&mut ret) {
+                return None
+            }
+        }
+        if !self.errors.is_empty() {
+            None
+        } else {
+            Some(ret.convert())
+        }
+    }
+
+    // Parse an array index as a natural number
+    fn array_index(&mut self) -> Option<String> {
+        self.integer(0, false, false)
+    }
+
+    /// Parse a path into a vector of paths
+    pub fn lookup(&mut self) -> Option<Vec<String>> {
+        if self.input.is_empty() {
+            return Some(vec![]);
+        }
+        let mut keys = Vec::new();
+        loop {
+            self.ws();
+            if let Some(s) = self.key_name() {
+                keys.push(s);
+            } else if let Some(s) = self.array_index() {
+                keys.push(s);
+            } else {
+                return None
+            }
+            self.ws();
+            if !self.expect('.') { return Some(keys) }
+        }
+    }
+
+    // Parse a single key name starting at `start`
+    fn key_name(&mut self) -> Option<String> {
+        let start = self.next_pos();
+        let key = if self.eat('"') {
+            self.finish_basic_string(start, false)
+        } else if self.eat('\'') {
+            self.finish_literal_string(start, false)
+        } else {
+            let mut ret = String::new();
+            while let Some((_, ch)) = self.cur.clone().next() {
+                match ch {
+                    'a' ... 'z' |
+                    'A' ... 'Z' |
+                    '0' ... '9' |
+                    '_' | '-' => { self.cur.next(); ret.push(ch) }
+                    _ => break,
+                }
+            }
+            Some(ret)
+        };
+        match key {
+            Some(ref name) if name.is_empty() => {
+                self.errors.push(ParserError {
+                    lo: start,
+                    hi: start,
+                    desc: "expected a key but found an empty string".to_string(),
+                });
+                None
+            }
+            Some(name) => Some(name),
+            None => None,
+        }
+    }
+
+    // Parses the values into the given TomlTable. Returns true in case of success
+    // and false in case of error.
+    fn values(&mut self, into: &mut TomlTable) -> bool {
+        loop {
+            self.ws();
+            if self.newline() { continue }
+            if self.comment() { continue }
+            match self.peek(0) {
+                Some((_, '[')) => break,
+                Some(..) => {}
+                None => break,
+            }
+            let key_lo = self.next_pos();
+            let key = match self.key_name() {
+                Some(s) => s,
+                None => return false
+            };
+            if !self.keyval_sep() { return false }
+            let value = match self.value() {
+                Some(value) => value,
+                None => return false,
+            };
+            let end = self.next_pos();
+            self.insert(into, key, value, key_lo);
+            self.ws();
+            if !self.comment() && !self.newline() {
+                if self.peek(0).is_none() {
+                    return true
+                }
+                self.errors.push(ParserError {
+                    lo: key_lo,
+                    hi: end,
+                    desc: "expected a newline after a key".to_string(),
+                });
+                return false
+            }
+        }
+        true
+    }
+
+    fn keyval_sep(&mut self) -> bool {
+        self.ws();
+        if !self.expect('=') { return false }
+        self.ws();
+        true
+    }
+
+    // Parses a value
+    fn value(&mut self) -> Option<Value> {
+        self.ws();
+        match self.cur.clone().next() {
+            Some((pos, '"')) => self.basic_string(pos),
+            Some((pos, '\'')) => self.literal_string(pos),
+            Some((pos, 't')) |
+            Some((pos, 'f')) => self.boolean(pos),
+            Some((pos, '[')) => self.array(pos),
+            Some((pos, '{')) => self.inline_table(pos),
+            Some((pos, '-')) |
+            Some((pos, '+')) => self.number_or_datetime(pos),
+            Some((pos, ch)) if is_digit(ch) => self.number_or_datetime(pos),
+            _ => {
+                let mut it = self.cur.clone();
+                let lo = it.next().map(|p| p.0).unwrap_or(self.input.len());
+                let hi = it.next().map(|p| p.0).unwrap_or(self.input.len());
+                self.errors.push(ParserError {
+                    lo: lo,
+                    hi: hi,
+                    desc: "expected a value".to_string(),
+                });
+                None
+            }
+        }
+    }
+
+    // Parses a single or multi-line string
+    fn basic_string(&mut self, start: usize) -> Option<Value> {
+        if !self.expect('"') { return None }
+        let mut multiline = false;
+
+        // detect multiline literals, but be careful about empty ""
+        // strings
+        if self.eat('"') {
+            if self.eat('"') {
+                multiline = true;
+                self.newline();
+            } else {
+                // empty
+                return Some(Value::String(String::new()))
+            }
+        }
+
+        self.finish_basic_string(start, multiline).map(Value::String)
+    }
+
+    // Finish parsing a basic string after the opening quote has been seen
+    fn finish_basic_string(&mut self,
+                           start: usize,
+                           multiline: bool) -> Option<String> {
+        let mut ret = String::new();
+        loop {
+            while multiline && self.newline() { ret.push('\n') }
+            match self.cur.next() {
+                Some((_, '"')) => {
+                    if multiline {
+                        if !self.eat('"') { ret.push_str("\""); continue }
+                        if !self.eat('"') { ret.push_str("\"\""); continue }
+                    }
+                    return Some(ret)
+                }
+                Some((pos, '\\')) => {
+                    if let Some(c) = escape(self, pos, multiline) {
+                        ret.push(c);
+                    }
+                }
+                Some((pos, ch)) if ch < '\u{1f}' => {
+                    self.errors.push(ParserError {
+                        lo: pos,
+                        hi: pos + 1,
+                        desc: format!("control character `{}` must be escaped",
+                                      ch.escape_default().collect::<String>())
+                    });
+                }
+                Some((_, ch)) => ret.push(ch),
+                None => {
+                    self.errors.push(ParserError {
+                        lo: start,
+                        hi: self.input.len(),
+                        desc: "unterminated string literal".to_string(),
+                    });
+                    return None
+                }
+            }
+        }
+
+        fn escape(me: &mut Parser, pos: usize, multiline: bool) -> Option<char> {
+            if multiline && me.newline() {
+                while me.ws() || me.newline() { /* ... */ }
+                return None
+            }
+            match me.cur.next() {
+                Some((_, 'b')) => Some('\u{8}'),
+                Some((_, 't')) => Some('\u{9}'),
+                Some((_, 'n')) => Some('\u{a}'),
+                Some((_, 'f')) => Some('\u{c}'),
+                Some((_, 'r')) => Some('\u{d}'),
+                Some((_, '"')) => Some('\u{22}'),
+                Some((_, '\\')) => Some('\u{5c}'),
+                Some((pos, c @ 'u')) |
+                Some((pos, c @ 'U')) => {
+                    let len = if c == 'u' {4} else {8};
+                    let num = &me.input[pos+1..];
+                    let num = if num.char_indices().nth(len).map(|(i, _)| i).unwrap_or(0) == len {
+                        &num[..len]
+                    } else {
+                        "invalid"
+                    };
+                    if let Some(n) = u32::from_str_radix(num, 16).ok() {
+                        if let Some(c) = char::from_u32(n) {
+                            me.cur.by_ref().skip(len - 1).next();
+                            return Some(c)
+                        } else {
+                            me.errors.push(ParserError {
+                                lo: pos + 1,
+                                hi: pos + 5,
+                                desc: format!("codepoint `{:x}` is \
+                                               not a valid unicode \
+                                               codepoint", n),
+                            })
+                        }
+                    } else {
+                        me.errors.push(ParserError {
+                            lo: pos,
+                            hi: pos + 1,
+                            desc: format!("expected {} hex digits \
+                                           after a `{}` escape", len, c),
+                        })
+                    }
+                    None
+                }
+                Some((pos, ch)) => {
+                    let next_pos = me.next_pos();
+                    me.errors.push(ParserError {
+                        lo: pos,
+                        hi: next_pos,
+                        desc: format!("unknown string escape: `{}`",
+                                      ch.escape_default().collect::<String>()),
+                    });
+                    None
+                }
+                None => {
+                    me.errors.push(ParserError {
+                        lo: pos,
+                        hi: pos + 1,
+                        desc: "unterminated escape sequence".to_string(),
+                    });
+                    None
+                }
+            }
+        }
+    }
+
+    fn literal_string(&mut self, start: usize) -> Option<Value> {
+        if !self.expect('\'') { return None }
+        let mut multiline = false;
+
+        // detect multiline literals
+        if self.eat('\'') {
+            if self.eat('\'') {
+                multiline = true;
+                self.newline();
+            } else {
+                return Some(Value::String(String::new())) // empty
+            }
+        }
+
+        self.finish_literal_string(start, multiline).map(Value::String)
+    }
+
+    fn finish_literal_string(&mut self, start: usize, multiline: bool)
+                             -> Option<String> {
+        let mut ret = String::new();
+        loop {
+            if !multiline && self.newline() {
+                let next = self.next_pos();
+                self.errors.push(ParserError {
+                    lo: start,
+                    hi: next,
+                    desc: "literal strings cannot contain newlines".to_string(),
+                });
+                return None
+            }
+            match self.cur.next() {
+                Some((_, '\'')) => {
+                    if multiline {
+                        if !self.eat('\'') { ret.push_str("'"); continue }
+                        if !self.eat('\'') { ret.push_str("''"); continue }
+                    }
+                    return Some(ret)
+                }
+                Some((_, ch)) => ret.push(ch),
+                None => {
+                    self.errors.push(ParserError {
+                        lo: start,
+                        hi: self.input.len(),
+                        desc: "unterminated string literal".to_string(),
+                    });
+                    return None
+                }
+            }
+        }
+    }
+
+    fn number_or_datetime(&mut self, start: usize) -> Option<Value> {
+        let mut is_float = false;
+        let prefix = try!(self.integer(start, false, true));
+        let decimal = if self.eat('.') {
+            is_float = true;
+            Some(try!(self.integer(start, true, false)))
+        } else {
+            None
+        };
+        let exponent = if self.eat('e') || self.eat('E') {
+            is_float = true;
+            Some(try!(self.integer(start, false, true)))
+        } else {
+            None
+        };
+        let end = self.next_pos();
+        let input = &self.input[start..end];
+        let ret = if decimal.is_none() &&
+                     exponent.is_none() &&
+                     !input.starts_with('+') &&
+                     !input.starts_with('-') &&
+                     start + 4 == end &&
+                     self.eat('-') {
+            self.datetime(start)
+        } else {
+            let input = match (decimal, exponent) {
+                (None, None) => prefix,
+                (Some(ref d), None) => prefix + "." + d,
+                (None, Some(ref e)) => prefix + "E" + e,
+                (Some(ref d), Some(ref e)) => prefix + "." + d + "E" + e,
+            };
+            let input = input.trim_left_matches('+');
+            if is_float {
+                input.parse().ok().map(Value::Float)
+            } else {
+                input.parse().ok().map(Value::Integer)
+            }
+        };
+        if ret.is_none() {
+            self.errors.push(ParserError {
+                lo: start,
+                hi: end,
+                desc: "invalid numeric literal".to_string(),
+            });
+        }
+        ret
+    }
+
+    fn integer(&mut self,
+               start: usize,
+               allow_leading_zeros: bool,
+               allow_sign: bool) -> Option<String> {
+        let mut s = String::new();
+        if allow_sign {
+            if self.eat('-') { s.push('-'); }
+            else if self.eat('+') { s.push('+'); }
+        }
+        match self.cur.next() {
+            Some((_, '0')) if !allow_leading_zeros => {
+                s.push('0');
+                match self.peek(0) {
+                    Some((pos, c)) if '0' <= c && c <= '9' => {
+                        self.errors.push(ParserError {
+                            lo: start,
+                            hi: pos,
+                            desc: "leading zeroes are not allowed".to_string(),
+                        });
+                        return None
+                    }
+                    _ => {}
+                }
+            }
+            Some((_, ch)) if '0' <= ch && ch <= '9' => {
+                s.push(ch);
+            }
+            _ => {
+                let pos = self.next_pos();
+                self.errors.push(ParserError {
+                    lo: pos,
+                    hi: pos,
+                    desc: "expected start of a numeric literal".to_string(),
+                });
+                return None;
+            }
+        }
+        let mut underscore = false;
+        loop {
+            match self.cur.clone().next() {
+                Some((_, ch)) if '0' <= ch && ch <= '9' => {
+                    s.push(ch);
+                    self.cur.next();
+                    underscore = false;
+                }
+                Some((_, '_')) if !underscore => {
+                    self.cur.next();
+                    underscore = true;
+                }
+                Some(_) | None => break,
+            }
+        }
+        if underscore {
+            let pos = self.next_pos();
+            self.errors.push(ParserError {
+                lo: pos,
+                hi: pos,
+                desc: "numeral cannot end with an underscore".to_string(),
+            });
+            None
+        } else {
+            Some(s)
+        }
+    }
+
+    fn boolean(&mut self, start: usize) -> Option<Value> {
+        let rest = &self.input[start..];
+        if rest.starts_with("true") {
+            for _ in 0..4 {
+                self.cur.next();
+            }
+            Some(Value::Boolean(true))
+        } else if rest.starts_with("false") {
+            for _ in 0..5 {
+                self.cur.next();
+            }
+            Some(Value::Boolean(false))
+        } else {
+            let next = self.next_pos();
+            self.errors.push(ParserError {
+                lo: start,
+                hi: next,
+                desc: format!("unexpected character: `{}`",
+                              rest.chars().next().unwrap()),
+            });
+            None
+        }
+    }
+
+    fn datetime(&mut self, start: usize) -> Option<Value> {
+        // Up to `start` already contains the year, and we've eaten the next
+        // `-`, so we just resume parsing from there.
+
+        let mut valid = true;
+
+        // month
+        valid = valid && digit(self.cur.next());
+        valid = valid && digit(self.cur.next());
+
+        // day
+        valid = valid && self.cur.next().map(|c| c.1) == Some('-');
+        valid = valid && digit(self.cur.next());
+        valid = valid && digit(self.cur.next());
+
+        valid = valid && self.cur.next().map(|c| c.1) == Some('T');
+
+        // hour
+        valid = valid && digit(self.cur.next());
+        valid = valid && digit(self.cur.next());
+
+        // minute
+        valid = valid && self.cur.next().map(|c| c.1) == Some(':');
+        valid = valid && digit(self.cur.next());
+        valid = valid && digit(self.cur.next());
+
+        // second
+        valid = valid && self.cur.next().map(|c| c.1) == Some(':');
+        valid = valid && digit(self.cur.next());
+        valid = valid && digit(self.cur.next());
+
+        // fractional seconds
+        if self.eat('.') {
+            valid = valid && digit(self.cur.next());
+            loop {
+                match self.cur.clone().next() {
+                    Some((_, c)) if is_digit(c) => {
+                        self.cur.next();
+                    }
+                    _ => break,
+                }
+            }
+        }
+
+        // time zone
+        if !self.eat('Z') {
+            valid = valid && (self.eat('+') || self.eat('-'));
+
+            // hour
+            valid = valid && digit(self.cur.next());
+            valid = valid && digit(self.cur.next());
+
+            // minute
+            valid = valid && self.cur.next().map(|c| c.1) == Some(':');
+            valid = valid && digit(self.cur.next());
+            valid = valid && digit(self.cur.next());
+        }
+
+        return if valid {
+            Some(Value::Datetime(self.input[start..self.next_pos()].to_string()))
+        } else {
+            let next = self.next_pos();
+            self.errors.push(ParserError {
+                lo: start,
+                hi: start + next,
+                desc: "malformed date literal".to_string(),
+            });
+            None
+        };
+
+        fn digit(val: Option<(usize, char)>) -> bool {
+            match val {
+                Some((_, c)) => is_digit(c),
+                None => false,
+            }
+        }
+    }
+
+    fn array(&mut self, _start: usize) -> Option<Value> {
+        if !self.expect('[') { return None }
+        let mut ret = Vec::new();
+        fn consume(me: &mut Parser) {
+            loop {
+                me.ws();
+                if !me.newline() && !me.comment() { break }
+            }
+        }
+        let mut type_str = None;
+        loop {
+            // Break out early if we see the closing bracket
+            consume(self);
+            if self.eat(']') { return Some(Value::Array(ret)) }
+
+            // Attempt to parse a value, triggering an error if it's the wrong
+            // type.
+            let start = self.next_pos();
+            let value = try!(self.value());
+            let end = self.next_pos();
+            let expected = type_str.unwrap_or(value.type_str());
+            if value.type_str() != expected {
+                self.errors.push(ParserError {
+                    lo: start,
+                    hi: end,
+                    desc: format!("expected type `{}`, found type `{}`",
+                                  expected, value.type_str()),
+                });
+            } else {
+                type_str = Some(expected);
+                ret.push(value);
+            }
+
+            // Look for a comma. If we don't find one we're done
+            consume(self);
+            if !self.eat(',') { break }
+        }
+        consume(self);
+        if !self.expect(']') { return None }
+        Some(Value::Array(ret))
+    }
+
+    fn inline_table(&mut self, _start: usize) -> Option<Value> {
+        if !self.expect('{') { return None }
+        self.ws();
+        let mut ret = TomlTable { values: BTreeMap::new(), defined: true };
+        if self.eat('}') { return Some(Value::Table(ret)) }
+        loop {
+            let lo = self.next_pos();
+            let key = try!(self.key_name());
+            if !self.keyval_sep() { return None }
+            let value = try!(self.value());
+            self.insert(&mut ret, key, value, lo);
+
+            self.ws();
+            if self.eat('}') { break }
+            if !self.expect(',') { return None }
+            self.ws();
+        }
+        Some(Value::Table(ret))
+    }
+
+    fn insert(&mut self, into: &mut TomlTable, key: String, value: Value,
+              key_lo: usize) {
+        if let Entry::Vacant(entry) = into.values.entry(key.clone()) {
+            entry.insert(value);
+        } else {
+            self.errors.push(ParserError {
+                lo: key_lo,
+                hi: key_lo + key.len(),
+                desc: format!("duplicate key: `{}`", key),
+            });
+        }
+    }
+
+    fn recurse<'b>(&mut self, mut cur: &'b mut TomlTable, keys: &'b [String],
+                   key_lo: usize) -> Option<(&'b mut TomlTable, &'b str)> {
+        let key_hi = keys.iter().fold(0, |a, b| a + b.len());
+        for part in keys[..keys.len() - 1].iter() {
+            let tmp = cur;
+
+            if tmp.values.contains_key(part) {
+                match *tmp.values.get_mut(part).unwrap() {
+                    Value::Table(ref mut table) => cur = table,
+                    Value::Array(ref mut array) => {
+                        match array.last_mut() {
+                            Some(&mut Value::Table(ref mut table)) => cur = table,
+                            _ => {
+                                self.errors.push(ParserError {
+                                    lo: key_lo,
+                                    hi: key_hi,
+                                    desc: format!("array `{}` does not contain \
+                                                   tables", part)
+                                });
+                                return None
+                            }
+                        }
+                    }
+                    _ => {
+                        self.errors.push(ParserError {
+                            lo: key_lo,
+                            hi: key_hi,
+                            desc: format!("key `{}` was not previously a table",
+                                          part)
+                        });
+                        return None
+                    }
+                }
+                continue
+            }
+
+            // Initialize an empty table as part of this sub-key
+            tmp.values.insert(part.clone(), Value::Table(TomlTable {
+                values: BTreeMap::new(),
+                defined: false,
+            }));
+            match *tmp.values.get_mut(part).unwrap() {
+                Value::Table(ref mut inner) => cur = inner,
+                _ => unreachable!(),
+            }
+        }
+        Some((cur, &**keys.last().unwrap()))
+    }
+
+    fn insert_table(&mut self, into: &mut TomlTable, keys: &[String],
+                    table: TomlTable, key_lo: usize) {
+        let (into, key) = match self.recurse(into, keys, key_lo) {
+            Some(pair) => pair,
+            None => return,
+        };
+        if !into.values.contains_key(key) {
+            into.values.insert(key.to_owned(), Value::Table(table));
+            return
+        }
+        if let Value::Table(ref mut into) = *into.values.get_mut(key).unwrap() {
+            if into.defined {
+                self.errors.push(ParserError {
+                    lo: key_lo,
+                    hi: key_lo + key.len(),
+                    desc: format!("redefinition of table `{}`", key),
+                });
+            }
+            for (k, v) in table.values {
+                if into.values.insert(k.clone(), v).is_some() {
+                    self.errors.push(ParserError {
+                        lo: key_lo,
+                        hi: key_lo + key.len(),
+                        desc: format!("duplicate key `{}` in table", k),
+                    });
+                }
+            }
+        } else {
+            self.errors.push(ParserError {
+                lo: key_lo,
+                hi: key_lo + key.len(),
+                desc: format!("duplicate key `{}` in table", key),
+            });
+        }
+    }
+
+    fn insert_array(&mut self, into: &mut TomlTable,
+                    keys: &[String], value: Value, key_lo: usize) {
+        let (into, key) = match self.recurse(into, keys, key_lo) {
+            Some(pair) => pair,
+            None => return,
+        };
+        if !into.values.contains_key(key) {
+            into.values.insert(key.to_owned(), Value::Array(Vec::new()));
+        }
+        match *into.values.get_mut(key).unwrap() {
+            Value::Array(ref mut vec) => {
+                match vec.first() {
+                    Some(ref v) if !v.same_type(&value) => {
+                        self.errors.push(ParserError {
+                            lo: key_lo,
+                            hi: key_lo + key.len(),
+                            desc: format!("expected type `{}`, found type `{}`",
+                                          v.type_str(), value.type_str()),
+                        })
+                    }
+                    Some(..) | None => {}
+                }
+                vec.push(value);
+            }
+            _ => {
+                self.errors.push(ParserError {
+                    lo: key_lo,
+                    hi: key_lo + key.len(),
+                    desc: format!("key `{}` was previously not an array", key),
+                });
+            }
+        }
+    }
+}
+
+impl Error for ParserError {
+    fn description(&self) -> &str { "TOML parse error" }
+}
+
+impl fmt::Display for ParserError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.desc.fmt(f)
+    }
+}
+
+fn is_digit(c: char) -> bool {
+    match c { '0' ... '9' => true, _ => false }
+}
+
+#[cfg(test)]
+mod tests {
+    use Value::Table;
+    use Parser;
+
+    macro_rules! bad {
+        ($s:expr, $msg:expr) => ({
+            let mut p = Parser::new($s);
+            assert!(p.parse().is_none());
+            assert!(p.errors.iter().any(|e| e.desc.contains($msg)),
+                    "errors: {:?}", p.errors);
+        })
+    }
+
+    #[test]
+    fn lookup_internal() {
+        let mut parser = Parser::new(r#"hello."world\t".a.0.'escaped'.value"#);
+        let result = vec![
+          String::from("hello"),
+          String::from("world\t"),
+          String::from("a"),
+          String::from("0"),
+          String::from("escaped"),
+          String::from("value")
+        ];
+
+        assert_eq!(parser.lookup().unwrap(), result);
+    }
+
+    #[test]
+    fn lookup_internal_void() {
+        let mut parser = Parser::new("");
+        assert_eq!(parser.lookup().unwrap(), Vec::<String>::new());
+    }
+
+    #[test]
+    fn lookup_internal_simple() {
+        let mut parser = Parser::new("value");
+        assert_eq!(parser.lookup().unwrap(), vec![String::from("value")]);
+    }
+
+    // This is due to key_name not parsing an empty "" correctly. Disabled for now.
+    #[test]
+    #[ignore]
+    fn lookup_internal_quoted_void() {
+        let mut parser = Parser::new("\"\"");
+        assert_eq!(parser.lookup().unwrap(), vec![String::from("")]);
+    }
+
+
+    #[test]
+    fn crlf() {
+        let mut p = Parser::new("\
+[project]\r\n\
+\r\n\
+name = \"splay\"\r\n\
+version = \"0.1.0\"\r\n\
+authors = [\"alex@crichton.co\"]\r\n\
+\r\n\
+[[lib]]\r\n\
+\r\n\
+path = \"lib.rs\"\r\n\
+name = \"splay\"\r\n\
+description = \"\"\"\
+A Rust implementation of a TAR file reader and writer. This library does not\r\n\
+currently handle compression, but it is abstract over all I/O readers and\r\n\
+writers. Additionally, great lengths are taken to ensure that the entire\r\n\
+contents are never required to be entirely resident in memory all at once.\r\n\
+\"\"\"\
+");
+        assert!(p.parse().is_some());
+    }
+
+    #[test]
+    fn linecol() {
+        let p = Parser::new("ab\ncde\nf");
+        assert_eq!(p.to_linecol(0), (0, 0));
+        assert_eq!(p.to_linecol(1), (0, 1));
+        assert_eq!(p.to_linecol(3), (1, 0));
+        assert_eq!(p.to_linecol(4), (1, 1));
+        assert_eq!(p.to_linecol(7), (2, 0));
+    }
+
+    #[test]
+    fn fun_with_strings() {
+        let mut p = Parser::new(r#"
+bar = "\U00000000"
+key1 = "One\nTwo"
+key2 = """One\nTwo"""
+key3 = """
+One
+Two"""
+
+key4 = "The quick brown fox jumps over the lazy dog."
+key5 = """
+The quick brown \
+
+
+  fox jumps over \
+    the lazy dog."""
+key6 = """\
+       The quick brown \
+       fox jumps over \
+       the lazy dog.\
+       """
+# What you see is what you get.
+winpath  = 'C:\Users\nodejs\templates'
+winpath2 = '\\ServerX\admin$\system32\'
+quoted   = 'Tom "Dubs" Preston-Werner'
+regex    = '<\i\c*\s*>'
+
+regex2 = '''I [dw]on't need \d{2} apples'''
+lines  = '''
+The first newline is
+trimmed in raw strings.
+   All other whitespace
+   is preserved.
+'''
+"#);
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("bar").and_then(|k| k.as_str()), Some("\0"));
+        assert_eq!(table.lookup("key1").and_then(|k| k.as_str()),
+                   Some("One\nTwo"));
+        assert_eq!(table.lookup("key2").and_then(|k| k.as_str()),
+                   Some("One\nTwo"));
+        assert_eq!(table.lookup("key3").and_then(|k| k.as_str()),
+                   Some("One\nTwo"));
+
+        let msg = "The quick brown fox jumps over the lazy dog.";
+        assert_eq!(table.lookup("key4").and_then(|k| k.as_str()), Some(msg));
+        assert_eq!(table.lookup("key5").and_then(|k| k.as_str()), Some(msg));
+        assert_eq!(table.lookup("key6").and_then(|k| k.as_str()), Some(msg));
+
+        assert_eq!(table.lookup("winpath").and_then(|k| k.as_str()),
+                   Some(r"C:\Users\nodejs\templates"));
+        assert_eq!(table.lookup("winpath2").and_then(|k| k.as_str()),
+                   Some(r"\\ServerX\admin$\system32\"));
+        assert_eq!(table.lookup("quoted").and_then(|k| k.as_str()),
+                   Some(r#"Tom "Dubs" Preston-Werner"#));
+        assert_eq!(table.lookup("regex").and_then(|k| k.as_str()),
+                   Some(r"<\i\c*\s*>"));
+        assert_eq!(table.lookup("regex2").and_then(|k| k.as_str()),
+                   Some(r"I [dw]on't need \d{2} apples"));
+        assert_eq!(table.lookup("lines").and_then(|k| k.as_str()),
+                   Some("The first newline is\n\
+                         trimmed in raw strings.\n   \
+                            All other whitespace\n   \
+                            is preserved.\n"));
+    }
+
+    #[test]
+    fn tables_in_arrays() {
+        let mut p = Parser::new(r#"
+[[foo]]
+  #…
+  [foo.bar]
+    #…
+
+[[foo]] # ...
+  #…
+  [foo.bar]
+    #...
+"#);
+        let table = Table(p.parse().unwrap());
+        table.lookup("foo.0.bar").unwrap().as_table().unwrap();
+        table.lookup("foo.1.bar").unwrap().as_table().unwrap();
+    }
+
+    #[test]
+    fn empty_table() {
+        let mut p = Parser::new(r#"
+[foo]"#);
+        let table = Table(p.parse().unwrap());
+        table.lookup("foo").unwrap().as_table().unwrap();
+    }
+
+    #[test]
+    fn fruit() {
+        let mut p = Parser::new(r#"
+[[fruit]]
+  name = "apple"
+
+  [fruit.physical]
+    color = "red"
+    shape = "round"
+
+  [[fruit.variety]]
+    name = "red delicious"
+
+  [[fruit.variety]]
+    name = "granny smith"
+
+[[fruit]]
+  name = "banana"
+
+  [[fruit.variety]]
+    name = "plantain"
+"#);
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("fruit.0.name").and_then(|k| k.as_str()),
+                   Some("apple"));
+        assert_eq!(table.lookup("fruit.0.physical.color").and_then(|k| k.as_str()),
+                   Some("red"));
+        assert_eq!(table.lookup("fruit.0.physical.shape").and_then(|k| k.as_str()),
+                   Some("round"));
+        assert_eq!(table.lookup("fruit.0.variety.0.name").and_then(|k| k.as_str()),
+                   Some("red delicious"));
+        assert_eq!(table.lookup("fruit.0.variety.1.name").and_then(|k| k.as_str()),
+                   Some("granny smith"));
+        assert_eq!(table.lookup("fruit.1.name").and_then(|k| k.as_str()),
+                   Some("banana"));
+        assert_eq!(table.lookup("fruit.1.variety.0.name").and_then(|k| k.as_str()),
+                   Some("plantain"));
+    }
+
+    #[test]
+    fn stray_cr() {
+        assert!(Parser::new("\r").parse().is_none());
+        assert!(Parser::new("a = [ \r ]").parse().is_none());
+        assert!(Parser::new("a = \"\"\"\r\"\"\"").parse().is_none());
+        assert!(Parser::new("a = \"\"\"\\  \r  \"\"\"").parse().is_none());
+
+        let mut p = Parser::new("foo = '''\r'''");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").and_then(|k| k.as_str()), Some("\r"));
+
+        let mut p = Parser::new("foo = '\r'");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").and_then(|k| k.as_str()), Some("\r"));
+    }
+
+    #[test]
+    fn blank_literal_string() {
+        let mut p = Parser::new("foo = ''");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").and_then(|k| k.as_str()), Some(""));
+    }
+
+    #[test]
+    fn many_blank() {
+        let mut p = Parser::new("foo = \"\"\"\n\n\n\"\"\"");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").and_then(|k| k.as_str()), Some("\n\n"));
+    }
+
+    #[test]
+    fn literal_eats_crlf() {
+        let mut p = Parser::new("
+            foo = \"\"\"\\\r\n\"\"\"
+            bar = \"\"\"\\\r\n   \r\n   \r\n   a\"\"\"
+        ");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").and_then(|k| k.as_str()), Some(""));
+        assert_eq!(table.lookup("bar").and_then(|k| k.as_str()), Some("a"));
+    }
+
+    #[test]
+    fn string_no_newline() {
+        assert!(Parser::new("a = \"\n\"").parse().is_none());
+        assert!(Parser::new("a = '\n'").parse().is_none());
+    }
+
+    #[test]
+    fn bad_leading_zeros() {
+        assert!(Parser::new("a = 00").parse().is_none());
+        assert!(Parser::new("a = -00").parse().is_none());
+        assert!(Parser::new("a = +00").parse().is_none());
+        assert!(Parser::new("a = 00.0").parse().is_none());
+        assert!(Parser::new("a = -00.0").parse().is_none());
+        assert!(Parser::new("a = +00.0").parse().is_none());
+        assert!(Parser::new("a = 9223372036854775808").parse().is_none());
+        assert!(Parser::new("a = -9223372036854775809").parse().is_none());
+    }
+
+    #[test]
+    fn bad_floats() {
+        assert!(Parser::new("a = 0.").parse().is_none());
+        assert!(Parser::new("a = 0.e").parse().is_none());
+        assert!(Parser::new("a = 0.E").parse().is_none());
+        assert!(Parser::new("a = 0.0E").parse().is_none());
+        assert!(Parser::new("a = 0.0e").parse().is_none());
+        assert!(Parser::new("a = 0.0e-").parse().is_none());
+        assert!(Parser::new("a = 0.0e+").parse().is_none());
+        assert!(Parser::new("a = 0.0e+00").parse().is_none());
+    }
+
+    #[test]
+    fn floats() {
+        macro_rules! t {
+            ($actual:expr, $expected:expr) => ({
+                let f = format!("foo = {}", $actual);
+                let mut p = Parser::new(&f);
+                let table = Table(p.parse().unwrap());
+                assert_eq!(table.lookup("foo").and_then(|k| k.as_float()),
+                           Some($expected));
+            })
+        }
+
+        t!("1.0", 1.0);
+        t!("1.0e0", 1.0);
+        t!("1.0e+0", 1.0);
+        t!("1.0e-0", 1.0);
+        t!("1.001e-0", 1.001);
+        t!("2e10", 2e10);
+        t!("2e+10", 2e10);
+        t!("2e-10", 2e-10);
+        t!("2_0.0", 20.0);
+        t!("2_0.0_0e0_0", 20.0);
+        t!("2_0.1_0e1_0", 20.1e10);
+    }
+
+    #[test]
+    fn bare_key_names() {
+        let mut p = Parser::new("
+            foo = 3
+            foo_3 = 3
+            foo_-2--3--r23f--4-f2-4 = 3
+            _ = 3
+            - = 3
+            8 = 8
+            \"a\" = 3
+            \"!\" = 3
+            \"a^b\" = 3
+            \"\\\"\" = 3
+            \"character encoding\" = \"value\"
+            'ʎǝʞ' = \"value\"
+        ");
+        let table = Table(p.parse().unwrap());
+        assert!(table.lookup("foo").is_some());
+        assert!(table.lookup("-").is_some());
+        assert!(table.lookup("_").is_some());
+        assert!(table.lookup("8").is_some());
+        assert!(table.lookup("foo_3").is_some());
+        assert!(table.lookup("foo_-2--3--r23f--4-f2-4").is_some());
+        assert!(table.lookup("a").is_some());
+        assert!(table.lookup("\"!\"").is_some());
+        assert!(table.lookup("\"\\\"\"").is_some());
+        assert!(table.lookup("\"character encoding\"").is_some());
+        assert!(table.lookup("'ʎǝʞ'").is_some());
+    }
+
+    #[test]
+    fn bad_keys() {
+        assert!(Parser::new("key\n=3").parse().is_none());
+        assert!(Parser::new("key=\n3").parse().is_none());
+        assert!(Parser::new("key|=3").parse().is_none());
+        assert!(Parser::new("\"\"=3").parse().is_none());
+        assert!(Parser::new("=3").parse().is_none());
+        assert!(Parser::new("\"\"|=3").parse().is_none());
+        assert!(Parser::new("\"\n\"|=3").parse().is_none());
+        assert!(Parser::new("\"\r\"|=3").parse().is_none());
+    }
+
+    #[test]
+    fn bad_table_names() {
+        assert!(Parser::new("[]").parse().is_none());
+        assert!(Parser::new("[.]").parse().is_none());
+        assert!(Parser::new("[\"\".\"\"]").parse().is_none());
+        assert!(Parser::new("[a.]").parse().is_none());
+        assert!(Parser::new("[\"\"]").parse().is_none());
+        assert!(Parser::new("[!]").parse().is_none());
+        assert!(Parser::new("[\"\n\"]").parse().is_none());
+        assert!(Parser::new("[a.b]\n[a.\"b\"]").parse().is_none());
+        assert!(Parser::new("[']").parse().is_none());
+        assert!(Parser::new("[''']").parse().is_none());
+        assert!(Parser::new("['''''']").parse().is_none());
+        assert!(Parser::new("['\n']").parse().is_none());
+        assert!(Parser::new("['\r\n']").parse().is_none());
+    }
+
+    #[test]
+    fn table_names() {
+        let mut p = Parser::new("
+            [a.\"b\"]
+            [\"f f\"]
+            [\"f.f\"]
+            [\"\\\"\"]
+            ['a.a']
+            ['\"\"']
+        ");
+        let table = Table(p.parse().unwrap());
+        assert!(table.lookup("a.b").is_some());
+        assert!(table.lookup("\"f f\"").is_some());
+        assert!(table.lookup("\"\\\"\"").is_some());
+        assert!(table.lookup("'\"\"'").is_some());
+    }
+
+    #[test]
+    fn invalid_bare_numeral() {
+        assert!(Parser::new("4").parse().is_none());
+    }
+
+    #[test]
+    fn inline_tables() {
+        assert!(Parser::new("a = {}").parse().is_some());
+        assert!(Parser::new("a = {b=1}").parse().is_some());
+        assert!(Parser::new("a = {   b   =   1    }").parse().is_some());
+        assert!(Parser::new("a = {a=1,b=2}").parse().is_some());
+        assert!(Parser::new("a = {a=1,b=2,c={}}").parse().is_some());
+        assert!(Parser::new("a = {a=1,}").parse().is_none());
+        assert!(Parser::new("a = {,}").parse().is_none());
+        assert!(Parser::new("a = {a=1,a=1}").parse().is_none());
+        assert!(Parser::new("a = {\n}").parse().is_none());
+        assert!(Parser::new("a = {").parse().is_none());
+        assert!(Parser::new("a = {a=[\n]}").parse().is_some());
+        assert!(Parser::new("a = {\"a\"=[\n]}").parse().is_some());
+        assert!(Parser::new("a = [\n{},\n{},\n]").parse().is_some());
+    }
+
+    #[test]
+    fn number_underscores() {
+        macro_rules! t {
+            ($actual:expr, $expected:expr) => ({
+                let f = format!("foo = {}", $actual);
+                let mut p = Parser::new(&f);
+                let table = Table(p.parse().unwrap());
+                assert_eq!(table.lookup("foo").and_then(|k| k.as_integer()),
+                           Some($expected));
+            })
+        }
+
+        t!("1_0", 10);
+        t!("1_0_0", 100);
+        t!("1_000", 1000);
+        t!("+1_000", 1000);
+        t!("-1_000", -1000);
+    }
+
+    #[test]
+    fn bad_underscores() {
+        assert!(Parser::new("foo = 0_").parse().is_none());
+        assert!(Parser::new("foo = 0__0").parse().is_none());
+        assert!(Parser::new("foo = __0").parse().is_none());
+        assert!(Parser::new("foo = 1_0_").parse().is_none());
+    }
+
+    #[test]
+    fn bad_unicode_codepoint() {
+        bad!("foo = \"\\uD800\"", "not a valid unicode codepoint");
+    }
+
+    #[test]
+    fn bad_strings() {
+        bad!("foo = \"\\uxx\"", "expected 4 hex digits");
+        bad!("foo = \"\\u\"", "expected 4 hex digits");
+        bad!("foo = \"\\", "unterminated");
+        bad!("foo = '", "unterminated");
+    }
+
+    #[test]
+    fn empty_string() {
+        let mut p = Parser::new("foo = \"\"");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").unwrap().as_str(), Some(""));
+    }
+
+    #[test]
+    fn booleans() {
+        let mut p = Parser::new("foo = true");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").unwrap().as_bool(), Some(true));
+
+        let mut p = Parser::new("foo = false");
+        let table = Table(p.parse().unwrap());
+        assert_eq!(table.lookup("foo").unwrap().as_bool(), Some(false));
+
+        assert!(Parser::new("foo = true2").parse().is_none());
+        assert!(Parser::new("foo = false2").parse().is_none());
+        assert!(Parser::new("foo = t1").parse().is_none());
+        assert!(Parser::new("foo = f2").parse().is_none());
+    }
+
+    #[test]
+    fn bad_nesting() {
+        bad!("
+            a = [2]
+            [[a]]
+            b = 5
+        ", "expected type `integer`, found type `table`");
+        bad!("
+            a = 1
+            [a.b]
+        ", "key `a` was not previously a table");
+        bad!("
+            a = []
+            [a.b]
+        ", "array `a` does not contain tables");
+        bad!("
+            a = []
+            [[a.b]]
+        ", "array `a` does not contain tables");
+        bad!("
+            [a]
+            b = { c = 2, d = {} }
+            [a.b]
+            c = 2
+        ", "duplicate key `c` in table");
+    }
+
+    #[test]
+    fn bad_table_redefine() {
+        bad!("
+            [a]
+            foo=\"bar\"
+            [a.b]
+            foo=\"bar\"
+            [a]
+        ", "redefinition of table `a`");
+        bad!("
+            [a]
+            foo=\"bar\"
+            b = { foo = \"bar\" }
+            [a]
+        ", "redefinition of table `a`");
+        bad!("
+            [a]
+            b = {}
+            [a.b]
+        ", "redefinition of table `b`");
+
+        bad!("
+            [a]
+            b = {}
+            [a]
+        ", "redefinition of table `a`");
+    }
+
+    #[test]
+    fn datetimes() {
+        macro_rules! t {
+            ($actual:expr) => ({
+                let f = format!("foo = {}", $actual);
+                let mut p = Parser::new(&f);
+                let table = Table(p.parse().unwrap());
+                assert_eq!(table.lookup("foo").and_then(|k| k.as_datetime()),
+                           Some($actual));
+            })
+        }
+
+        t!("2016-09-09T09:09:09Z");
+        t!("2016-09-09T09:09:09.0Z");
+        t!("2016-09-09T09:09:09.0+10:00");
+        t!("2016-09-09T09:09:09.01234567890-02:00");
+        bad!("foo = 2016-09-09T09:09:09.Z", "malformed date literal");
+        bad!("foo = 2016-9-09T09:09:09Z", "malformed date literal");
+        bad!("foo = 2016-09-09T09:09:09+2:00", "malformed date literal");
+        bad!("foo = 2016-09-09T09:09:09-2:00", "malformed date literal");
+        bad!("foo = 2016-09-09T09:09:09Z-2:00", "expected");
+    }
+
+    #[test]
+    fn require_newline_after_value() {
+        bad!("0=0r=false", "expected a newline");
+        bad!(r#"
+0=""o=""m=""r=""00="0"q="""0"""e="""0"""
+"#, "expected a newline");
+        bad!(r#"
+[[0000l0]]
+0="0"[[0000l0]]
+0="0"[[0000l0]]
+0="0"l="0"
+"#, "expected a newline");
+        bad!(r#"
+0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z]
+"#, "expected a newline");
+        bad!(r#"
+0=0r0=0r=false
+"#, "expected a newline");
+        bad!(r#"
+0=0r0=0r=falsefal=false
+"#, "expected a newline");
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/README.md
@@ -0,0 +1,1 @@
+Tests are from https://github.com/BurntSushi/toml-test
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/formatting.rs
@@ -0,0 +1,52 @@
+extern crate rustc_serialize;
+extern crate toml;
+use toml::encode_str;
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+struct User {
+    pub name: String,
+    pub surname: String,
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+struct Users {
+    pub user: Vec<User>,
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+struct TwoUsers {
+    pub user0: User,
+    pub user1: User,
+}
+
+#[test]
+fn no_unnecessary_newlines_array() {
+    assert!(!encode_str(&Users {
+            user: vec![
+                    User {
+                        name: "John".to_string(),
+                        surname: "Doe".to_string(),
+                    },
+                    User {
+                        name: "Jane".to_string(),
+                        surname: "Dough".to_string(),
+                    },
+                ],
+        })
+        .starts_with("\n"));
+}
+
+#[test]
+fn no_unnecessary_newlines_table() {
+    assert!(!encode_str(&TwoUsers {
+            user0: User {
+                name: "John".to_string(),
+                surname: "Doe".to_string(),
+            },
+            user1: User {
+                name: "Jane".to_string(),
+                surname: "Dough".to_string(),
+            },
+        })
+        .starts_with("\n"));
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid-encoder/array-mixed-types-ints-and-floats.json
@@ -0,0 +1,15 @@
+{
+    "ints-and-floats": {
+        "type": "array",
+        "value": [
+            {
+                "type": "integer",
+                "value": "1"
+            },
+            {
+                "type": "float",
+                "value": "1.1"
+            }
+        ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid.rs
@@ -0,0 +1,108 @@
+extern crate toml;
+
+use toml::{Parser};
+
+fn run(toml: &str) {
+    let mut p = Parser::new(toml);
+    let table = p.parse();
+    assert!(table.is_none());
+    assert!(p.errors.len() > 0);
+
+    // test Parser::to_linecol with the generated error offsets
+    for error in &p.errors {
+      p.to_linecol(error.lo);
+      p.to_linecol(error.hi);
+    }
+}
+
+macro_rules! test( ($name:ident, $toml:expr) => (
+    #[test]
+    fn $name() { run($toml); }
+) );
+
+test!(array_mixed_types_arrays_and_ints,
+      include_str!("invalid/array-mixed-types-arrays-and-ints.toml"));
+test!(array_mixed_types_ints_and_floats,
+      include_str!("invalid/array-mixed-types-ints-and-floats.toml"));
+test!(array_mixed_types_strings_and_ints,
+      include_str!("invalid/array-mixed-types-strings-and-ints.toml"));
+test!(datetime_malformed_no_leads,
+      include_str!("invalid/datetime-malformed-no-leads.toml"));
+test!(datetime_malformed_no_secs,
+      include_str!("invalid/datetime-malformed-no-secs.toml"));
+test!(datetime_malformed_no_t,
+      include_str!("invalid/datetime-malformed-no-t.toml"));
+test!(datetime_malformed_no_z,
+      include_str!("invalid/datetime-malformed-no-z.toml"));
+test!(datetime_malformed_with_milli,
+      include_str!("invalid/datetime-malformed-with-milli.toml"));
+test!(duplicate_keys,
+      include_str!("invalid/duplicate-keys.toml"));
+test!(duplicate_key_table,
+      include_str!("invalid/duplicate-key-table.toml"));
+test!(duplicate_tables,
+      include_str!("invalid/duplicate-tables.toml"));
+test!(empty_implicit_table,
+      include_str!("invalid/empty-implicit-table.toml"));
+test!(empty_table,
+      include_str!("invalid/empty-table.toml"));
+test!(float_no_leading_zero,
+      include_str!("invalid/float-no-leading-zero.toml"));
+test!(float_no_trailing_digits,
+      include_str!("invalid/float-no-trailing-digits.toml"));
+test!(key_after_array,
+      include_str!("invalid/key-after-array.toml"));
+test!(key_after_table,
+      include_str!("invalid/key-after-table.toml"));
+test!(key_empty,
+      include_str!("invalid/key-empty.toml"));
+test!(key_hash,
+      include_str!("invalid/key-hash.toml"));
+test!(key_newline,
+      include_str!("invalid/key-newline.toml"));
+test!(key_open_bracket,
+      include_str!("invalid/key-open-bracket.toml"));
+test!(key_single_open_bracket,
+      include_str!("invalid/key-single-open-bracket.toml"));
+test!(key_space,
+      include_str!("invalid/key-space.toml"));
+test!(key_start_bracket,
+      include_str!("invalid/key-start-bracket.toml"));
+test!(key_two_equals,
+      include_str!("invalid/key-two-equals.toml"));
+test!(string_bad_byte_escape,
+      include_str!("invalid/string-bad-byte-escape.toml"));
+test!(string_bad_escape,
+      include_str!("invalid/string-bad-escape.toml"));
+test!(string_byte_escapes,
+      include_str!("invalid/string-byte-escapes.toml"));
+test!(string_no_close,
+      include_str!("invalid/string-no-close.toml"));
+test!(table_array_implicit,
+      include_str!("invalid/table-array-implicit.toml"));
+test!(table_array_malformed_bracket,
+      include_str!("invalid/table-array-malformed-bracket.toml"));
+test!(table_array_malformed_empty,
+      include_str!("invalid/table-array-malformed-empty.toml"));
+test!(table_empty,
+      include_str!("invalid/table-empty.toml"));
+test!(table_nested_brackets_close,
+      include_str!("invalid/table-nested-brackets-close.toml"));
+test!(table_nested_brackets_open,
+      include_str!("invalid/table-nested-brackets-open.toml"));
+test!(table_whitespace,
+      include_str!("invalid/table-whitespace.toml"));
+test!(table_with_pound,
+      include_str!("invalid/table-with-pound.toml"));
+test!(text_after_array_entries,
+      include_str!("invalid/text-after-array-entries.toml"));
+test!(text_after_integer,
+      include_str!("invalid/text-after-integer.toml"));
+test!(text_after_string,
+      include_str!("invalid/text-after-string.toml"));
+test!(text_after_table,
+      include_str!("invalid/text-after-table.toml"));
+test!(text_before_array_separator,
+      include_str!("invalid/text-before-array-separator.toml"));
+test!(text_in_array,
+      include_str!("invalid/text-in-array.toml"));
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/array-mixed-types-arrays-and-ints.toml
@@ -0,0 +1,1 @@
+arrays-and-ints =  [1, ["Arrays are not integers."]]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/array-mixed-types-ints-and-floats.toml
@@ -0,0 +1,1 @@
+ints-and-floats = [1, 1.1]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/array-mixed-types-strings-and-ints.toml
@@ -0,0 +1,1 @@
+strings-and-ints = ["hi", 42]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/datetime-malformed-no-leads.toml
@@ -0,0 +1,1 @@
+no-leads = 1987-7-05T17:45:00Z
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/datetime-malformed-no-secs.toml
@@ -0,0 +1,1 @@
+no-secs = 1987-07-05T17:45Z
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/datetime-malformed-no-t.toml
@@ -0,0 +1,1 @@
+no-t = 1987-07-0517:45:00Z
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/datetime-malformed-no-z.toml
@@ -0,0 +1,1 @@
+no-z = 1987-07-05T17:45:00
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/datetime-malformed-with-milli.toml
@@ -0,0 +1,1 @@
+with-milli = 1987-07-5T17:45:00.12Z
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/duplicate-key-table.toml
@@ -0,0 +1,5 @@
+[fruit]
+type = "apple"
+
+[fruit.type]
+apple = "yes"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/duplicate-keys.toml
@@ -0,0 +1,2 @@
+dupe = false
+dupe = true
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/duplicate-tables.toml
@@ -0,0 +1,2 @@
+[a]
+[a]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/empty-implicit-table.toml
@@ -0,0 +1,1 @@
+[naughty..naughty]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/empty-table.toml
@@ -0,0 +1,1 @@
+[]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/float-no-leading-zero.toml
@@ -0,0 +1,2 @@
+answer = .12345
+neganswer = -.12345
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/float-no-trailing-digits.toml
@@ -0,0 +1,2 @@
+answer = 1.
+neganswer = -1.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-after-array.toml
@@ -0,0 +1,1 @@
+[[agencies]] owner = "S Cjelli"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-after-table.toml
@@ -0,0 +1,1 @@
+[history] guard = "sleeping"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-empty.toml
@@ -0,0 +1,1 @@
+ = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-hash.toml
@@ -0,0 +1,1 @@
+a# = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-newline.toml
@@ -0,0 +1,2 @@
+a
+= 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-open-bracket.toml
@@ -0,0 +1,1 @@
+[abc = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-single-open-bracket.toml
@@ -0,0 +1,1 @@
+[
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-space.toml
@@ -0,0 +1,1 @@
+a b = 1
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-start-bracket.toml
@@ -0,0 +1,3 @@
+[a]
+[xyz = 5
+[b]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/key-two-equals.toml
@@ -0,0 +1,1 @@
+key= = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/string-bad-byte-escape.toml
@@ -0,0 +1,1 @@
+naughty = "\xAg"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/string-bad-escape.toml
@@ -0,0 +1,1 @@
+invalid-escape = "This string has a bad \a escape character."
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/string-byte-escapes.toml
@@ -0,0 +1,1 @@
+answer = "\x33"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/string-no-close.toml
@@ -0,0 +1,1 @@
+no-ending-quote = "One time, at band camp
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-array-implicit.toml
@@ -0,0 +1,14 @@
+# This test is a bit tricky. It should fail because the first use of
+# `[[albums.songs]]` without first declaring `albums` implies that `albums`
+# must be a table. The alternative would be quite weird. Namely, it wouldn't
+# comply with the TOML spec: "Each double-bracketed sub-table will belong to 
+# the most *recently* defined table element *above* it."
+#
+# This is in contrast to the *valid* test, table-array-implicit where
+# `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared
+# later. (Although, `[albums]` could be.)
+[[albums.songs]]
+name = "Glory Days"
+
+[[albums]]
+name = "Born in the USA"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-array-malformed-bracket.toml
@@ -0,0 +1,2 @@
+[[albums]
+name = "Born to Run"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-array-malformed-empty.toml
@@ -0,0 +1,2 @@
+[[]]
+name = "Born to Run"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-empty.toml
@@ -0,0 +1,1 @@
+[]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-nested-brackets-close.toml
@@ -0,0 +1,2 @@
+[a]b]
+zyx = 42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-nested-brackets-open.toml
@@ -0,0 +1,2 @@
+[a[b]
+zyx = 42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-whitespace.toml
@@ -0,0 +1,1 @@
+[invalid key]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/table-with-pound.toml
@@ -0,0 +1,2 @@
+[key#group]
+answer = 42
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-after-array-entries.toml
@@ -0,0 +1,4 @@
+array = [
+  "Is there life after an array separator?", No
+  "Entry"
+]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-after-integer.toml
@@ -0,0 +1,1 @@
+answer = 42 the ultimate answer?
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-after-string.toml
@@ -0,0 +1,1 @@
+string = "Is there life after strings?" No.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-after-table.toml
@@ -0,0 +1,1 @@
+[error] this shouldn't be here
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-before-array-separator.toml
@@ -0,0 +1,4 @@
+array = [
+  "Is there life before an array separator?" No,
+  "Entry"
+]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/invalid/text-in-array.toml
@@ -0,0 +1,5 @@
+array = [
+  "Entry 1",
+  I don't belong,
+  "Entry 2",
+]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid.rs
@@ -0,0 +1,195 @@
+extern crate rustc_serialize;
+extern crate toml;
+
+use std::collections::BTreeMap;
+use rustc_serialize::json::Json;
+
+use toml::{Parser, Value};
+use toml::Value::{Table, Integer, Float, Boolean, Datetime, Array};
+
+fn to_json(toml: Value) -> Json {
+    fn doit(s: &str, json: Json) -> Json {
+        let mut map = BTreeMap::new();
+        map.insert(format!("{}", "type"), Json::String(format!("{}", s)));
+        map.insert(format!("{}", "value"), json);
+        Json::Object(map)
+    }
+    match toml {
+        Value::String(s) => doit("string", Json::String(s)),
+        Integer(i) => doit("integer", Json::String(format!("{}", i))),
+        Float(f) => doit("float", Json::String({
+            let s = format!("{:.15}", f);
+            let s = format!("{}", s.trim_right_matches('0'));
+            if s.ends_with(".") {format!("{}0", s)} else {s}
+        })),
+        Boolean(b) => doit("bool", Json::String(format!("{}", b))),
+        Datetime(s) => doit("datetime", Json::String(s)),
+        Array(arr) => {
+            let is_table = match arr.first() {
+                Some(&Table(..)) => true,
+                _ => false,
+            };
+            let json = Json::Array(arr.into_iter().map(to_json).collect());
+            if is_table {json} else {doit("array", json)}
+        }
+        Table(table) => Json::Object(table.into_iter().map(|(k, v)| {
+            (k, to_json(v))
+        }).collect()),
+    }
+}
+
+fn run(toml: &str, json: &str) {
+    let mut p = Parser::new(toml);
+    let table = p.parse();
+    assert!(p.errors.len() == 0, "had_errors: {:?}",
+            p.errors.iter().map(|e| {
+                (e.desc.clone(), &toml[e.lo - 5..e.hi + 5])
+            }).collect::<Vec<(String, &str)>>());
+    assert!(table.is_some());
+    let toml = Table(table.unwrap());
+    let toml_string = format!("{}", toml);
+
+    let json = Json::from_str(json).unwrap();
+    let toml_json = to_json(toml.clone());
+    assert!(json == toml_json,
+            "expected\n{}\ngot\n{}\n",
+            json.pretty(),
+            toml_json.pretty());
+
+    let table2 = Parser::new(&toml_string).parse().unwrap();
+    // floats are a little lossy
+    if table2.values().any(|v| v.as_float().is_some()) { return }
+    assert_eq!(toml, Table(table2));
+}
+
+macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
+    #[test]
+    fn $name() { run($toml, $json); }
+) );
+
+test!(array_empty,
+       include_str!("valid/array-empty.toml"),
+       include_str!("valid/array-empty.json"));
+test!(array_nospaces,
+       include_str!("valid/array-nospaces.toml"),
+       include_str!("valid/array-nospaces.json"));
+test!(arrays_hetergeneous,
+       include_str!("valid/arrays-hetergeneous.toml"),
+       include_str!("valid/arrays-hetergeneous.json"));
+test!(arrays,
+       include_str!("valid/arrays.toml"),
+       include_str!("valid/arrays.json"));
+test!(arrays_nested,
+       include_str!("valid/arrays-nested.toml"),
+       include_str!("valid/arrays-nested.json"));
+test!(empty,
+       include_str!("valid/empty.toml"),
+       include_str!("valid/empty.json"));
+test!(bool,
+       include_str!("valid/bool.toml"),
+       include_str!("valid/bool.json"));
+test!(datetime,
+       include_str!("valid/datetime.toml"),
+       include_str!("valid/datetime.json"));
+test!(example,
+       include_str!("valid/example.toml"),
+       include_str!("valid/example.json"));
+test!(float,
+       include_str!("valid/float.toml"),
+       include_str!("valid/float.json"));
+test!(implicit_and_explicit_after,
+       include_str!("valid/implicit-and-explicit-after.toml"),
+       include_str!("valid/implicit-and-explicit-after.json"));
+test!(implicit_and_explicit_before,
+       include_str!("valid/implicit-and-explicit-before.toml"),
+       include_str!("valid/implicit-and-explicit-before.json"));
+test!(implicit_groups,
+       include_str!("valid/implicit-groups.toml"),
+       include_str!("valid/implicit-groups.json"));
+test!(integer,
+       include_str!("valid/integer.toml"),
+       include_str!("valid/integer.json"));
+test!(key_equals_nospace,
+       include_str!("valid/key-equals-nospace.toml"),
+       include_str!("valid/key-equals-nospace.json"));
+test!(key_space,
+       include_str!("valid/key-space.toml"),
+       include_str!("valid/key-space.json"));
+test!(key_special_chars,
+       include_str!("valid/key-special-chars.toml"),
+       include_str!("valid/key-special-chars.json"));
+test!(key_with_pound,
+       include_str!("valid/key-with-pound.toml"),
+       include_str!("valid/key-with-pound.json"));
+test!(long_float,
+       include_str!("valid/long-float.toml"),
+       include_str!("valid/long-float.json"));
+test!(long_integer,
+       include_str!("valid/long-integer.toml"),
+       include_str!("valid/long-integer.json"));
+test!(multiline_string,
+       include_str!("valid/multiline-string.toml"),
+       include_str!("valid/multiline-string.json"));
+test!(raw_multiline_string,
+       include_str!("valid/raw-multiline-string.toml"),
+       include_str!("valid/raw-multiline-string.json"));
+test!(raw_string,
+       include_str!("valid/raw-string.toml"),
+       include_str!("valid/raw-string.json"));
+test!(string_empty,
+       include_str!("valid/string-empty.toml"),
+       include_str!("valid/string-empty.json"));
+test!(string_escapes,
+       include_str!("valid/string-escapes.toml"),
+       include_str!("valid/string-escapes.json"));
+test!(string_simple,
+       include_str!("valid/string-simple.toml"),
+       include_str!("valid/string-simple.json"));
+test!(string_with_pound,
+       include_str!("valid/string-with-pound.toml"),
+       include_str!("valid/string-with-pound.json"));
+test!(table_array_implicit,
+       include_str!("valid/table-array-implicit.toml"),
+       include_str!("valid/table-array-implicit.json"));
+test!(table_array_many,
+       include_str!("valid/table-array-many.toml"),
+       include_str!("valid/table-array-many.json"));
+test!(table_array_nest,
+       include_str!("valid/table-array-nest.toml"),
+       include_str!("valid/table-array-nest.json"));
+test!(table_array_one,
+       include_str!("valid/table-array-one.toml"),
+       include_str!("valid/table-array-one.json"));
+test!(table_empty,
+       include_str!("valid/table-empty.toml"),
+       include_str!("valid/table-empty.json"));
+test!(table_sub_empty,
+       include_str!("valid/table-sub-empty.toml"),
+       include_str!("valid/table-sub-empty.json"));
+test!(table_whitespace,
+       include_str!("valid/table-whitespace.toml"),
+       include_str!("valid/table-whitespace.json"));
+test!(table_with_pound,
+       include_str!("valid/table-with-pound.toml"),
+       include_str!("valid/table-with-pound.json"));
+test!(unicode_escape,
+       include_str!("valid/unicode-escape.toml"),
+       include_str!("valid/unicode-escape.json"));
+test!(unicode_literal,
+       include_str!("valid/unicode-literal.toml"),
+       include_str!("valid/unicode-literal.json"));
+test!(hard_example,
+       include_str!("valid/hard_example.toml"),
+       include_str!("valid/hard_example.json"));
+test!(example2,
+       include_str!("valid/example2.toml"),
+       include_str!("valid/example2.json"));
+test!(example3,
+       include_str!("valid/example-v0.3.0.toml"),
+       include_str!("valid/example-v0.3.0.json"));
+test!(example4,
+       include_str!("valid/example-v0.4.0.toml"),
+       include_str!("valid/example-v0.4.0.json"));
+test!(example_bom,
+       include_str!("valid/example-bom.toml"),
+       include_str!("valid/example.json"));
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/array-empty.json
@@ -0,0 +1,11 @@
+{
+    "thevoid": { "type": "array", "value": [
+        {"type": "array", "value": [
+            {"type": "array", "value": [
+                {"type": "array", "value": [
+                    {"type": "array", "value": []}
+                ]}
+            ]}
+        ]}
+    ]}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/array-empty.toml
@@ -0,0 +1,1 @@
+thevoid = [[[[[]]]]]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/array-nospaces.json
@@ -0,0 +1,10 @@
+{
+    "ints": {
+        "type": "array",
+        "value": [
+            {"type": "integer", "value": "1"},
+            {"type": "integer", "value": "2"},
+            {"type": "integer", "value": "3"}
+        ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/array-nospaces.toml
@@ -0,0 +1,1 @@
+ints = [1,2,3]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays-hetergeneous.json
@@ -0,0 +1,19 @@
+{
+    "mixed": {
+        "type": "array",
+        "value": [
+            {"type": "array", "value": [
+                {"type": "integer", "value": "1"},
+                {"type": "integer", "value": "2"}
+            ]},
+            {"type": "array", "value": [
+                {"type": "string", "value": "a"},
+                {"type": "string", "value": "b"}
+            ]},
+            {"type": "array", "value": [
+                {"type": "float", "value": "1.1"},
+                {"type": "float", "value": "2.1"}
+            ]}
+        ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays-hetergeneous.toml
@@ -0,0 +1,1 @@
+mixed = [[1, 2], ["a", "b"], [1.1, 2.1]]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays-nested.json
@@ -0,0 +1,13 @@
+{
+    "nest": {
+        "type": "array",
+        "value": [
+            {"type": "array", "value": [
+                {"type": "string", "value": "a"}
+            ]},
+            {"type": "array", "value": [
+                {"type": "string", "value": "b"}
+            ]}
+        ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays-nested.toml
@@ -0,0 +1,1 @@
+nest = [["a"], ["b"]]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays.json
@@ -0,0 +1,34 @@
+{
+    "ints": {
+        "type": "array",
+        "value": [
+            {"type": "integer", "value": "1"},
+            {"type": "integer", "value": "2"},
+            {"type": "integer", "value": "3"}
+        ]
+    },
+    "floats": {
+        "type": "array",
+        "value": [
+            {"type": "float", "value": "1.1"},
+            {"type": "float", "value": "2.1"},
+            {"type": "float", "value": "3.1"}
+        ]
+    },
+    "strings": {
+        "type": "array",
+        "value": [
+            {"type": "string", "value": "a"},
+            {"type": "string", "value": "b"},
+            {"type": "string", "value": "c"}
+        ]
+    },
+    "dates": {
+        "type": "array",
+        "value": [
+            {"type": "datetime", "value": "1987-07-05T17:45:00Z"},
+            {"type": "datetime", "value": "1979-05-27T07:32:00Z"},
+            {"type": "datetime", "value": "2006-06-01T11:00:00Z"}
+        ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/arrays.toml
@@ -0,0 +1,8 @@
+ints = [1, 2, 3]
+floats = [1.1, 2.1, 3.1]
+strings = ["a", "b", "c"]
+dates = [
+  1987-07-05T17:45:00Z,
+  1979-05-27T07:32:00Z,
+  2006-06-01T11:00:00Z,
+]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/bool.json
@@ -0,0 +1,4 @@
+{
+    "f": {"type": "bool", "value": "false"},
+    "t": {"type": "bool", "value": "true"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/bool.toml
@@ -0,0 +1,2 @@
+t = true
+f = false
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/comments-everywhere.json
@@ -0,0 +1,12 @@
+{
+    "group": {
+        "answer": {"type": "integer", "value": "42"},
+        "more": {
+            "type": "array",
+            "value": [
+                {"type": "integer", "value": "42"},
+                {"type": "integer", "value": "42"}
+            ]
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/comments-everywhere.toml
@@ -0,0 +1,24 @@
+# Top comment.
+  # Top comment.
+# Top comment.
+
+# [no-extraneous-groups-please]
+
+[group] # Comment
+answer = 42 # Comment
+# no-extraneous-keys-please = 999
+# Inbetween comment.
+more = [ # Comment
+  # What about multiple # comments?
+  # Can you handle it?
+  #
+          # Evil.
+# Evil.
+  42, 42, # Comments within arrays are fun.
+  # What about multiple # comments?
+  # Can you handle it?
+  #
+          # Evil.
+# Evil.
+# ] Did I fool you?
+] # Hopefully not.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/datetime.json
@@ -0,0 +1,3 @@
+{
+    "bestdayever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/datetime.toml
@@ -0,0 +1,1 @@
+bestdayever = 1987-07-05T17:45:00Z
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/empty.json
@@ -0,0 +1,1 @@
+{}
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example-bom.toml
@@ -0,0 +1,5 @@
+best-day-ever = 1987-07-05T17:45:00Z
+
+[numtheory]
+boring = false
+perfection = [6, 28, 496]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example-v0.3.0.json
@@ -0,0 +1,1 @@
+{"Array":{"key1":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key2":{"type":"array","value":[{"type":"string","value":"red"},{"type":"string","value":"yellow"},{"type":"string","value":"green"}]},"key3":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"integer","value":"3"},{"type":"integer","value":"4"},{"type":"integer","value":"5"}]}]},"key4":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"string","value":"a"},{"type":"string","value":"b"},{"type":"string","value":"c"}]}]},"key5":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key6":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}},"Booleans":{"False":{"type":"bool","value":"false"},"True":{"type":"bool","value":"true"}},"Datetime":{"key1":{"type":"datetime","value":"1979-05-27T07:32:00Z"}},"Float":{"both":{},"exponent":{},"fractional":{"key1":{"type":"float","value":"1.0"},"key2":{"type":"float","value":"3.1415"},"key3":{"type":"float","value":"-0.01"}}},"Integer":{"key1":{"type":"integer","value":"99"},"key2":{"type":"integer","value":"42"},"key3":{"type":"integer","value":"0"},"key4":{"type":"integer","value":"-17"}},"String":{"Literal":{"Multiline":{"lines":{"type":"string","value":"The first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n"},"regex2":{"type":"string","value":"I [dw]on't need \\d{2} apples"}},"quoted":{"type":"string","value":"Tom \"Dubs\" Preston-Werner"},"regex":{"type":"string","value":"\u003c\\i\\c*\\s*\u003e"},"winpath":{"type":"string","value":"C:\\Users\\nodejs\\templates"},"winpath2":{"type":"string","value":"\\\\ServerX\\admin$\\system32\\"}},"Multiline":{"key1":{"type":"string","value":"One\nTwo"},"key2":{"type":"string","value":"One\nTwo"},"key3":{"type":"string","value":"One\nTwo"}},"Multilined":{"Singleline":{"key1":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key2":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key3":{"type":"string","value":"The quick brown fox jumps over the lazy dog."}}},"basic":{"type":"string","value":"I'm a string. \"You can quote me\". Name\u0009José\nLocation\u0009SF."}},"Table":{"key":{"type":"string","value":"value"}},"dog":{"tater":{"type":{"type":"string","value":"pug"}}},"fruit":[{"name":{"type":"string","value":"apple"},"physical":{"color":{"type":"string","value":"red"},"shape":{"type":"string","value":"round"}},"variety":[{"name":{"type":"string","value":"red delicious"}},{"name":{"type":"string","value":"granny smith"}}]},{"name":{"type":"string","value":"banana"},"variety":[{"name":{"type":"string","value":"plantain"}}]}],"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"x":{"y":{"z":{"w":{}}}}}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example-v0.3.0.toml
@@ -0,0 +1,182 @@
+# Comment
+# I am a comment. Hear me roar. Roar.
+
+# Table
+# Tables (also known as hash tables or dictionaries) are collections of key/value pairs.
+# They appear in square brackets on a line by themselves.
+
+[Table]
+
+key = "value" # Yeah, you can do this.
+
+# Nested tables are denoted by table names with dots in them. Name your tables whatever crap you please, just don't use #, ., [ or ].
+
+[dog.tater]
+type = "pug"
+
+# You don't need to specify all the super-tables if you don't want to. TOML knows how to do it for you.
+
+# [x] you
+# [x.y] don't
+# [x.y.z] need these
+[x.y.z.w] # for this to work
+
+# String
+# There are four ways to express strings: basic, multi-line basic, literal, and multi-line literal.
+# All strings must contain only valid UTF-8 characters.
+
+[String]
+basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+[String.Multiline]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "One\nTwo"
+key2 = """One\nTwo"""
+key3 = """
+One
+Two"""
+
+[String.Multilined.Singleline]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "The quick brown fox jumps over the lazy dog."
+
+key2 = """
+The quick brown \
+
+
+  fox jumps over \
+    the lazy dog."""
+
+key3 = """\
+       The quick brown \
+       fox jumps over \
+       the lazy dog.\
+       """
+
+[String.Literal]
+
+# What you see is what you get.
+winpath  = 'C:\Users\nodejs\templates'
+winpath2 = '\\ServerX\admin$\system32\'
+quoted   = 'Tom "Dubs" Preston-Werner'
+regex    = '<\i\c*\s*>'
+
+
+[String.Literal.Multiline]
+
+regex2 = '''I [dw]on't need \d{2} apples'''
+lines  = '''
+The first newline is
+trimmed in raw strings.
+   All other whitespace
+   is preserved.
+'''
+
+# Integer
+# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
+# Negative numbers are prefixed with a minus sign.
+
+[Integer]
+key1 = +99
+key2 = 42
+key3 = 0
+key4 = -17
+
+# Float
+# A float consists of an integer part (which may be prefixed with a plus or minus sign)
+# followed by a fractional part and/or an exponent part.
+
+[Float.fractional]
+
+# fractional
+key1 = +1.0
+key2 = 3.1415
+key3 = -0.01
+
+[Float.exponent]
+
+# exponent
+#key1 = 5e+22
+#key2 = 1e6
+#key3 = -2E-2
+
+[Float.both]
+
+# both
+#key = 6.626e-34
+
+# Boolean
+# Booleans are just the tokens you're used to. Always lowercase.
+
+[Booleans]
+True = true
+False = false
+
+# Datetime
+# Datetimes are RFC 3339 dates.
+
+[Datetime]
+key1 = 1979-05-27T07:32:00Z
+#key2 = 1979-05-27T00:32:00-07:00
+#key3 = 1979-05-27T00:32:00.999999-07:00
+
+# Array
+# Arrays are square brackets with other primitives inside. Whitespace is ignored. Elements are separated by commas. Data types may not be mixed.
+
+[Array]
+key1 = [ 1, 2, 3 ]
+key2 = [ "red", "yellow", "green" ]
+key3 = [ [ 1, 2 ], [3, 4, 5] ]
+key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
+
+#Arrays can also be multiline. So in addition to ignoring whitespace, arrays also ignore newlines between the brackets.
+# Terminating commas are ok before the closing bracket.
+
+key5 = [
+  1, 2, 3
+]
+key6 = [
+  1,
+  2, # this is ok
+]
+
+# Array of Tables
+# These can be expressed by using a table name in double brackets.
+# Each table with the same double bracketed name will be an element in the array.
+# The tables are inserted in the order encountered.
+
+[[products]]
+name = "Hammer"
+sku = 738594937
+
+[[products]]
+
+[[products]]
+name = "Nail"
+sku = 284758393
+color = "gray"
+
+
+# You can create nested arrays of tables as well.
+
+[[fruit]]
+  name = "apple"
+
+  [fruit.physical]
+    color = "red"
+    shape = "round"
+
+  [[fruit.variety]]
+    name = "red delicious"
+
+  [[fruit.variety]]
+    name = "granny smith"
+
+[[fruit]]
+  name = "banana"
+
+  [[fruit.variety]]
+    name = "plantain"
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example-v0.4.0.json
@@ -0,0 +1,1 @@
+{"array":{"key1":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key2":{"type":"array","value":[{"type":"string","value":"red"},{"type":"string","value":"yellow"},{"type":"string","value":"green"}]},"key3":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"integer","value":"3"},{"type":"integer","value":"4"},{"type":"integer","value":"5"}]}]},"key4":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"string","value":"a"},{"type":"string","value":"b"},{"type":"string","value":"c"}]}]},"key5":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key6":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}},"boolean":{"False":{"type":"bool","value":"false"},"True":{"type":"bool","value":"true"}},"datetime":{},"float":{"both":{},"exponent":{},"fractional":{"key1":{"type":"float","value":"1.0"},"key2":{"type":"float","value":"3.1415"},"key3":{"type":"float","value":"-0.01"}},"underscores":{}},"fruit":[{"name":{"type":"string","value":"apple"},"physical":{"color":{"type":"string","value":"red"},"shape":{"type":"string","value":"round"}},"variety":[{"name":{"type":"string","value":"red delicious"}},{"name":{"type":"string","value":"granny smith"}}]},{"name":{"type":"string","value":"banana"},"variety":[{"name":{"type":"string","value":"plantain"}}]}],"integer":{"key1":{"type":"integer","value":"99"},"key2":{"type":"integer","value":"42"},"key3":{"type":"integer","value":"0"},"key4":{"type":"integer","value":"-17"},"underscores":{"key1":{"type":"integer","value":"1000"},"key2":{"type":"integer","value":"5349221"},"key3":{"type":"integer","value":"12345"}}},"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"string":{"basic":{"basic":{"type":"string","value":"I'm a string. \"You can quote me\". Name\u0009José\nLocation\u0009SF."}},"literal":{"multiline":{"lines":{"type":"string","value":"The first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n"},"regex2":{"type":"string","value":"I [dw]on't need \\d{2} apples"}},"quoted":{"type":"string","value":"Tom \"Dubs\" Preston-Werner"},"regex":{"type":"string","value":"\u003c\\i\\c*\\s*\u003e"},"winpath":{"type":"string","value":"C:\\Users\\nodejs\\templates"},"winpath2":{"type":"string","value":"\\\\ServerX\\admin$\\system32\\"}},"multiline":{"continued":{"key1":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key2":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key3":{"type":"string","value":"The quick brown fox jumps over the lazy dog."}},"key1":{"type":"string","value":"One\nTwo"},"key2":{"type":"string","value":"One\nTwo"},"key3":{"type":"string","value":"One\nTwo"}}},"table":{"inline":{"name":{"first":{"type":"string","value":"Tom"},"last":{"type":"string","value":"Preston-Werner"}},"point":{"x":{"type":"integer","value":"1"},"y":{"type":"integer","value":"2"}}},"key":{"type":"string","value":"value"},"subtable":{"key":{"type":"string","value":"another value"}}},"x":{"y":{"z":{"w":{}}}}}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example-v0.4.0.toml
@@ -0,0 +1,235 @@
+################################################################################
+## Comment
+
+# Speak your mind with the hash symbol. They go from the symbol to the end of
+# the line.
+
+
+################################################################################
+## Table
+
+# Tables (also known as hash tables or dictionaries) are collections of
+# key/value pairs. They appear in square brackets on a line by themselves.
+
+[table]
+
+key = "value" # Yeah, you can do this.
+
+# Nested tables are denoted by table names with dots in them. Name your tables
+# whatever crap you please, just don't use #, ., [ or ].
+
+[table.subtable]
+
+key = "another value"
+
+# You don't need to specify all the super-tables if you don't want to. TOML
+# knows how to do it for you.
+
+# [x] you
+# [x.y] don't
+# [x.y.z] need these
+[x.y.z.w] # for this to work
+
+
+################################################################################
+## Inline Table
+
+# Inline tables provide a more compact syntax for expressing tables. They are
+# especially useful for grouped data that can otherwise quickly become verbose.
+# Inline tables are enclosed in curly braces `{` and `}`. No newlines are
+# allowed between the curly braces unless they are valid within a value.
+
+[table.inline]
+
+name = { first = "Tom", last = "Preston-Werner" }
+point = { x = 1, y = 2 }
+
+
+################################################################################
+## String
+
+# There are four ways to express strings: basic, multi-line basic, literal, and
+# multi-line literal. All strings must contain only valid UTF-8 characters.
+
+[string.basic]
+
+basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+[string.multiline]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "One\nTwo"
+key2 = """One\nTwo"""
+key3 = """
+One
+Two"""
+
+[string.multiline.continued]
+
+# The following strings are byte-for-byte equivalent:
+key1 = "The quick brown fox jumps over the lazy dog."
+
+key2 = """
+The quick brown \
+
+
+  fox jumps over \
+    the lazy dog."""
+
+key3 = """\
+       The quick brown \
+       fox jumps over \
+       the lazy dog.\
+       """
+
+[string.literal]
+
+# What you see is what you get.
+winpath  = 'C:\Users\nodejs\templates'
+winpath2 = '\\ServerX\admin$\system32\'
+quoted   = 'Tom "Dubs" Preston-Werner'
+regex    = '<\i\c*\s*>'
+
+
+[string.literal.multiline]
+
+regex2 = '''I [dw]on't need \d{2} apples'''
+lines  = '''
+The first newline is
+trimmed in raw strings.
+   All other whitespace
+   is preserved.
+'''
+
+
+################################################################################
+## Integer
+
+# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
+# Negative numbers are prefixed with a minus sign.
+
+[integer]
+
+key1 = +99
+key2 = 42
+key3 = 0
+key4 = -17
+
+[integer.underscores]
+
+# For large numbers, you may use underscores to enhance readability. Each
+# underscore must be surrounded by at least one digit.
+key1 = 1_000
+key2 = 5_349_221
+key3 = 1_2_3_4_5     # valid but inadvisable
+
+
+################################################################################
+## Float
+
+# A float consists of an integer part (which may be prefixed with a plus or
+# minus sign) followed by a fractional part and/or an exponent part.
+
+[float.fractional]
+
+key1 = +1.0
+key2 = 3.1415
+key3 = -0.01
+
+[float.exponent]
+
+[float.both]
+
+[float.underscores]
+
+
+################################################################################
+## Boolean
+
+# Booleans are just the tokens you're used to. Always lowercase.
+
+[boolean]
+
+True = true
+False = false
+
+
+################################################################################
+## Datetime
+
+# Datetimes are RFC 3339 dates.
+
+[datetime]
+
+#key1 = 1979-05-27T07:32:00Z
+#key2 = 1979-05-27T00:32:00-07:00
+#key3 = 1979-05-27T00:32:00.999999-07:00
+
+
+################################################################################
+## Array
+
+# Arrays are square brackets with other primitives inside. Whitespace is
+# ignored. Elements are separated by commas. Data types may not be mixed.
+
+[array]
+
+key1 = [ 1, 2, 3 ]
+key2 = [ "red", "yellow", "green" ]
+key3 = [ [ 1, 2 ], [3, 4, 5] ]
+key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
+
+# Arrays can also be multiline. So in addition to ignoring whitespace, arrays
+# also ignore newlines between the brackets.  Terminating commas are ok before
+# the closing bracket.
+
+key5 = [
+  1, 2, 3
+]
+key6 = [
+  1,
+  2, # this is ok
+]
+
+
+################################################################################
+## Array of Tables
+
+# These can be expressed by using a table name in double brackets. Each table
+# with the same double bracketed name will be an element in the array. The
+# tables are inserted in the order encountered.
+
+[[products]]
+
+name = "Hammer"
+sku = 738594937
+
+[[products]]
+
+[[products]]
+
+name = "Nail"
+sku = 284758393
+color = "gray"
+
+
+# You can create nested arrays of tables as well.
+
+[[fruit]]
+  name = "apple"
+
+  [fruit.physical]
+    color = "red"
+    shape = "round"
+
+  [[fruit.variety]]
+    name = "red delicious"
+
+  [[fruit.variety]]
+    name = "granny smith"
+
+[[fruit]]
+  name = "banana"
+
+  [[fruit.variety]]
+    name = "plantain"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example.json
@@ -0,0 +1,14 @@
+{
+  "best-day-ever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"},
+  "numtheory": {
+    "boring": {"type": "bool", "value": "false"},
+    "perfection": {
+      "type": "array",
+      "value": [
+        {"type": "integer", "value": "6"},
+        {"type": "integer", "value": "28"},
+        {"type": "integer", "value": "496"}
+      ]
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example.toml
@@ -0,0 +1,5 @@
+best-day-ever = 1987-07-05T17:45:00Z
+
+[numtheory]
+boring = false
+perfection = [6, 28, 496]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example2.json
@@ -0,0 +1,1 @@
+{"clients":{"data":{"type":"array","value":[{"type":"array","value":[{"type":"string","value":"gamma"},{"type":"string","value":"delta"}]},{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}]},"hosts":{"type":"array","value":[{"type":"string","value":"alpha"},{"type":"string","value":"omega"}]}},"database":{"connection_max":{"type":"integer","value":"5000"},"enabled":{"type":"bool","value":"true"},"ports":{"type":"array","value":[{"type":"integer","value":"8001"},{"type":"integer","value":"8001"},{"type":"integer","value":"8002"}]},"server":{"type":"string","value":"192.168.1.1"}},"owner":{"bio":{"type":"string","value":"GitHub Cofounder \u0026 CEO\nLikes tater tots and beer."},"dob":{"type":"datetime","value":"1979-05-27T07:32:00Z"},"name":{"type":"string","value":"Tom Preston-Werner"},"organization":{"type":"string","value":"GitHub"}},"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"servers":{"alpha":{"dc":{"type":"string","value":"eqdc10"},"ip":{"type":"string","value":"10.0.0.1"}},"beta":{"country":{"type":"string","value":"中国"},"dc":{"type":"string","value":"eqdc10"},"ip":{"type":"string","value":"10.0.0.2"}}},"title":{"type":"string","value":"TOML Example"}}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/example2.toml
@@ -0,0 +1,47 @@
+# This is a TOML document. Boom.
+
+title = "TOML Example"
+
+[owner]
+name = "Tom Preston-Werner"
+organization = "GitHub"
+bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
+dob = 1979-05-27T07:32:00Z # First class dates? Why not?
+
+[database]
+server = "192.168.1.1"
+ports = [ 8001, 8001, 8002 ]
+connection_max = 5000
+enabled = true
+
+[servers]
+
+  # You can indent as you please. Tabs or spaces. TOML don't care.
+  [servers.alpha]
+  ip = "10.0.0.1"
+  dc = "eqdc10"
+
+  [servers.beta]
+  ip = "10.0.0.2"
+  dc = "eqdc10"
+  country = "中国" # This should be parsed as UTF-8
+
+[clients]
+data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
+
+# Line breaks are OK when inside arrays
+hosts = [
+  "alpha",
+  "omega"
+]
+
+# Products
+
+  [[products]]
+  name = "Hammer"
+  sku = 738594937
+
+  [[products]]
+  name = "Nail"
+  sku = 284758393
+  color = "gray"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/float.json
@@ -0,0 +1,4 @@
+{
+    "pi": {"type": "float", "value": "3.14"},
+    "negpi": {"type": "float", "value": "-3.14"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/float.toml
@@ -0,0 +1,2 @@
+pi = 3.14
+negpi = -3.14
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/hard_example.json
@@ -0,0 +1,1 @@
+{"the":{"hard":{"another_test_string":{"type":"string","value":" Same thing, but with a string #"},"bit#":{"multi_line_array":{"type":"array","value":[{"type":"string","value":"]"}]},"what?":{"type":"string","value":"You don't think some user won't do that?"}},"harder_test_string":{"type":"string","value":" And when \"'s are in the string, along with # \""},"test_array":{"type":"array","value":[{"type":"string","value":"] "},{"type":"string","value":" # "}]},"test_array2":{"type":"array","value":[{"type":"string","value":"Test #11 ]proved that"},{"type":"string","value":"Experiment #9 was a success"}]}},"test_string":{"type":"string","value":"You'll hate me after this - #"}}}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/hard_example.toml
@@ -0,0 +1,33 @@
+# Test file for TOML
+# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate
+# This part you'll really hate
+
+[the]
+test_string = "You'll hate me after this - #"          # " Annoying, isn't it?
+
+    [the.hard]
+    test_array = [ "] ", " # "]      # ] There you go, parse this!
+    test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ]
+    # You didn't think it'd as easy as chucking out the last #, did you?
+    another_test_string = " Same thing, but with a string #"
+    harder_test_string = " And when \"'s are in the string, along with # \""   # "and comments are there too"
+    # Things will get harder
+
+        [the.hard."bit#"]
+        "what?" = "You don't think some user won't do that?"
+        multi_line_array = [
+            "]",
+            # ] Oh yes I did
+            ]
+
+# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test
+
+#[error]   if you didn't catch this, your parser is broken
+#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment"   like this
+#array = [
+#         "This might most likely happen in multiline arrays",
+#         Like here,
+#         "or here,
+#         and here"
+#         ]     End of array comment, forgot the #
+#number = 3.14  pi <--again forgot the #
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-and-explicit-after.json
@@ -0,0 +1,10 @@
+{
+    "a": {
+        "better": {"type": "integer", "value": "43"},
+        "b": {
+            "c": {
+                "answer": {"type": "integer", "value": "42"}
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-and-explicit-after.toml
@@ -0,0 +1,5 @@
+[a.b.c]
+answer = 42
+
+[a]
+better = 43
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-and-explicit-before.json
@@ -0,0 +1,10 @@
+{
+    "a": {
+        "better": {"type": "integer", "value": "43"},
+        "b": {
+            "c": {
+                "answer": {"type": "integer", "value": "42"}
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-and-explicit-before.toml
@@ -0,0 +1,5 @@
+[a]
+better = 43
+
+[a.b.c]
+answer = 42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-groups.json
@@ -0,0 +1,9 @@
+{
+    "a": {
+        "b": {
+            "c": {
+                "answer": {"type": "integer", "value": "42"}
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/implicit-groups.toml
@@ -0,0 +1,2 @@
+[a.b.c]
+answer = 42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/integer.json
@@ -0,0 +1,4 @@
+{
+    "answer": {"type": "integer", "value": "42"},
+    "neganswer": {"type": "integer", "value": "-42"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/integer.toml
@@ -0,0 +1,2 @@
+answer = 42
+neganswer = -42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-equals-nospace.json
@@ -0,0 +1,3 @@
+{
+    "answer": {"type": "integer", "value": "42"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-equals-nospace.toml
@@ -0,0 +1,1 @@
+answer=42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-space.json
@@ -0,0 +1,3 @@
+{
+    "a b": {"type": "integer", "value": "1"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-space.toml
@@ -0,0 +1,1 @@
+"a b" = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-special-chars.json
@@ -0,0 +1,5 @@
+{
+    "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:'": {
+        "type": "integer", "value": "1"
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-special-chars.toml
@@ -0,0 +1,1 @@
+"~!@#$^&*()_+-`1234567890[]\\|/?><.,;:'" = 1
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-with-pound.json
@@ -0,0 +1,3 @@
+{
+    "key#name": {"type": "integer", "value": "5"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/key-with-pound.toml
@@ -0,0 +1,1 @@
+"key#name" = 5
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/long-float.json
@@ -0,0 +1,4 @@
+{
+    "longpi": {"type": "float", "value": "3.141592653589793"},
+    "neglongpi": {"type": "float", "value": "-3.141592653589793"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/long-float.toml
@@ -0,0 +1,2 @@
+longpi = 3.141592653589793
+neglongpi = -3.141592653589793
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/long-integer.json
@@ -0,0 +1,4 @@
+{
+    "answer": {"type": "integer", "value": "9223372036854775807"},
+    "neganswer": {"type": "integer", "value": "-9223372036854775808"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/long-integer.toml
@@ -0,0 +1,2 @@
+answer = 9223372036854775807
+neganswer = -9223372036854775808
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/multiline-string.json
@@ -0,0 +1,30 @@
+{
+    "multiline_empty_one": {
+        "type": "string",
+        "value": ""
+    },
+    "multiline_empty_two": {
+        "type": "string",
+        "value": ""
+    },
+    "multiline_empty_three": {
+        "type": "string",
+        "value": ""
+    },
+    "multiline_empty_four": {
+        "type": "string",
+        "value": ""
+    },
+    "equivalent_one": {
+        "type": "string",
+        "value": "The quick brown fox jumps over the lazy dog."
+    },
+    "equivalent_two": {
+        "type": "string",
+        "value": "The quick brown fox jumps over the lazy dog."
+    },
+    "equivalent_three": {
+        "type": "string",
+        "value": "The quick brown fox jumps over the lazy dog."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/multiline-string.toml
@@ -0,0 +1,23 @@
+multiline_empty_one = """"""
+multiline_empty_two = """
+"""
+multiline_empty_three = """\
+    """
+multiline_empty_four = """\
+   \
+   \
+   """
+
+equivalent_one = "The quick brown fox jumps over the lazy dog."
+equivalent_two = """
+The quick brown \
+
+
+  fox jumps over \
+    the lazy dog."""
+
+equivalent_three = """\
+       The quick brown \
+       fox jumps over \
+       the lazy dog.\
+       """
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/raw-multiline-string.json
@@ -0,0 +1,14 @@
+{
+    "oneline": {
+        "type": "string",
+        "value": "This string has a ' quote character."
+    },
+    "firstnl": {
+        "type": "string",
+        "value": "This string has a ' quote character."
+    },
+    "multiline": {
+        "type": "string",
+        "value": "This string\nhas ' a quote character\nand more than\none newline\nin it."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/raw-multiline-string.toml
@@ -0,0 +1,9 @@
+oneline = '''This string has a ' quote character.'''
+firstnl = '''
+This string has a ' quote character.'''
+multiline = '''
+This string
+has ' a quote character
+and more than
+one newline
+in it.'''
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/raw-string.json
@@ -0,0 +1,30 @@
+{
+    "backspace": {
+        "type": "string",
+        "value": "This string has a \\b backspace character."
+    },
+    "tab": {
+        "type": "string",
+        "value": "This string has a \\t tab character."
+    },
+    "newline": {
+        "type": "string",
+        "value": "This string has a \\n new line character."
+    },
+    "formfeed": {
+        "type": "string",
+        "value": "This string has a \\f form feed character."
+    },
+    "carriage": {
+        "type": "string",
+        "value": "This string has a \\r carriage return character."
+    },
+    "slash": {
+        "type": "string",
+        "value": "This string has a \\/ slash character."
+    },
+    "backslash": {
+        "type": "string",
+        "value": "This string has a \\\\ backslash character."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/raw-string.toml
@@ -0,0 +1,7 @@
+backspace = 'This string has a \b backspace character.'
+tab = 'This string has a \t tab character.'
+newline = 'This string has a \n new line character.'
+formfeed = 'This string has a \f form feed character.'
+carriage = 'This string has a \r carriage return character.'
+slash = 'This string has a \/ slash character.'
+backslash = 'This string has a \\ backslash character.'
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-empty.json
@@ -0,0 +1,6 @@
+{
+    "answer": {
+        "type": "string",
+        "value": ""
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-empty.toml
@@ -0,0 +1,1 @@
+answer = ""
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-escapes.json
@@ -0,0 +1,50 @@
+{
+    "backspace": {
+        "type": "string",
+        "value": "This string has a \u0008 backspace character."
+    },
+    "tab": {
+        "type": "string",
+        "value": "This string has a \u0009 tab character."
+    },
+    "newline": {
+        "type": "string",
+        "value": "This string has a \u000A new line character."
+    },
+    "formfeed": {
+        "type": "string",
+        "value": "This string has a \u000C form feed character."
+    },
+    "carriage": {
+        "type": "string",
+        "value": "This string has a \u000D carriage return character."
+    },
+    "quote": {
+        "type": "string",
+        "value": "This string has a \u0022 quote character."
+    },
+    "slash": {
+        "type": "string",
+        "value": "This string has a \u002F slash character."
+    },
+    "backslash": {
+        "type": "string",
+        "value": "This string has a \u005C backslash character."
+    },
+    "notunicode1": {
+        "type": "string",
+        "value": "This string does not have a unicode \\u escape."
+    },
+    "notunicode2": {
+        "type": "string",
+        "value": "This string does not have a unicode \u005Cu escape."
+    },
+    "notunicode3": {
+        "type": "string",
+        "value": "This string does not have a unicode \\u0075 escape."
+    },
+    "notunicode4": {
+        "type": "string",
+        "value": "This string does not have a unicode \\\u0075 escape."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-escapes.toml
@@ -0,0 +1,12 @@
+backspace = "This string has a \b backspace character."
+tab = "This string has a \t tab character."
+newline = "This string has a \n new line character."
+formfeed = "This string has a \f form feed character."
+carriage = "This string has a \r carriage return character."
+quote = "This string has a \" quote character."
+slash = "This string has a / slash character."
+backslash = "This string has a \\ backslash character."
+notunicode1 = "This string does not have a unicode \\u escape."
+notunicode2 = "This string does not have a unicode \u005Cu escape."
+notunicode3 = "This string does not have a unicode \\u0075 escape."
+notunicode4 = "This string does not have a unicode \\\u0075 escape."
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-simple.json
@@ -0,0 +1,6 @@
+{
+    "answer": {
+        "type": "string",
+        "value": "You are not drinking enough whisky."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-simple.toml
@@ -0,0 +1,1 @@
+answer = "You are not drinking enough whisky."
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-with-pound.json
@@ -0,0 +1,7 @@
+{
+    "pound": {"type": "string", "value": "We see no # comments here."},
+    "poundcomment": {
+        "type": "string",
+        "value": "But there are # some comments here."
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/string-with-pound.toml
@@ -0,0 +1,2 @@
+pound = "We see no # comments here."
+poundcomment = "But there are # some comments here." # Did I # mess you up?
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-implicit.json
@@ -0,0 +1,7 @@
+{
+    "albums": {
+       "songs": [
+           {"name": {"type": "string", "value": "Glory Days"}}
+       ]
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-implicit.toml
@@ -0,0 +1,2 @@
+[[albums.songs]]
+name = "Glory Days"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-many.json
@@ -0,0 +1,16 @@
+{
+    "people": [
+        {
+            "first_name": {"type": "string", "value": "Bruce"},
+            "last_name": {"type": "string", "value": "Springsteen"}
+        },
+        {
+            "first_name": {"type": "string", "value": "Eric"},
+            "last_name": {"type": "string", "value": "Clapton"}
+        },
+        {
+            "first_name": {"type": "string", "value": "Bob"},
+            "last_name": {"type": "string", "value": "Seger"}
+        }
+    ]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-many.toml
@@ -0,0 +1,11 @@
+[[people]]
+first_name = "Bruce"
+last_name = "Springsteen"
+
+[[people]]
+first_name = "Eric"
+last_name = "Clapton"
+
+[[people]]
+first_name = "Bob"
+last_name = "Seger"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-nest.json
@@ -0,0 +1,18 @@
+{
+    "albums": [
+        {
+            "name": {"type": "string", "value": "Born to Run"},
+            "songs": [
+                {"name": {"type": "string", "value": "Jungleland"}},
+                {"name": {"type": "string", "value": "Meeting Across the River"}}
+            ]
+        },
+        {
+            "name": {"type": "string", "value": "Born in the USA"},
+            "songs": [
+                {"name": {"type": "string", "value": "Glory Days"}},
+                {"name": {"type": "string", "value": "Dancing in the Dark"}}
+            ]
+        }
+    ]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-nest.toml
@@ -0,0 +1,17 @@
+[[albums]]
+name = "Born to Run"
+
+  [[albums.songs]]
+  name = "Jungleland"
+
+  [[albums.songs]]
+  name = "Meeting Across the River"
+
+[[albums]]
+name = "Born in the USA"
+  
+  [[albums.songs]]
+  name = "Glory Days"
+
+  [[albums.songs]]
+  name = "Dancing in the Dark"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-one.json
@@ -0,0 +1,8 @@
+{
+    "people": [
+        {
+            "first_name": {"type": "string", "value": "Bruce"},
+            "last_name": {"type": "string", "value": "Springsteen"}
+        }
+    ]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-array-one.toml
@@ -0,0 +1,3 @@
+[[people]]
+first_name = "Bruce"
+last_name = "Springsteen"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-empty.json
@@ -0,0 +1,3 @@
+{
+    "a": {}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-empty.toml
@@ -0,0 +1,1 @@
+[a]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-sub-empty.json
@@ -0,0 +1,3 @@
+{
+    "a": { "b": {} }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-sub-empty.toml
@@ -0,0 +1,2 @@
+[a]
+[a.b]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-whitespace.json
@@ -0,0 +1,3 @@
+{
+    "valid key": {}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-whitespace.toml
@@ -0,0 +1,1 @@
+["valid key"]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-with-pound.json
@@ -0,0 +1,5 @@
+{
+    "key#group": {
+        "answer": {"type": "integer", "value": "42"}
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/table-with-pound.toml
@@ -0,0 +1,2 @@
+["key#group"]
+answer = 42
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/unicode-escape.json
@@ -0,0 +1,4 @@
+{
+    "answer4": {"type": "string", "value": "\u03B4α"},
+    "answer8": {"type": "string", "value": "\u03B4β"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/unicode-escape.toml
@@ -0,0 +1,2 @@
+answer4 = "\u03B4α"
+answer8 = "\U000003B4β"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/unicode-literal.json
@@ -0,0 +1,3 @@
+{
+    "answer": {"type": "string", "value": "δ"}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/toml/tests/valid/unicode-literal.toml
@@ -0,0 +1,1 @@
+answer = "δ"