diff --git a/Cargo.lock b/Cargo.lock index 03d05d0cda2b..7a8ed22190c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3884,10 +3884,12 @@ dependencies = [ [[package]] name = "ron" -version = "0.1.7" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" +checksum = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" dependencies = [ + "base64 0.10.1", + "bitflags", "serde", ] diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock index 0401e097e668..2b742a1d201a 100644 --- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -1323,9 +1323,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ron" -version = "0.1.7" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1590,7 +1592,7 @@ name = "tileview" version = "0.1.0" dependencies = [ "euclid 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", "webrender 0.61.0", "webrender_api 0.61.0", @@ -1775,7 +1777,7 @@ dependencies = [ "png 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1933,7 +1935,7 @@ dependencies = [ "mozangle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "osmesa-src 0.1.1 (git+https://github.com/servo/osmesa-src)", "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2157,7 +2159,7 @@ dependencies = [ "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" "checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" -"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" +"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusttype 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5" diff --git a/gfx/wr/tileview/Cargo.toml b/gfx/wr/tileview/Cargo.toml index 5b8d7b701ea6..cb32309424d9 100644 --- a/gfx/wr/tileview/Cargo.toml +++ b/gfx/wr/tileview/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ron = "0.1.7" +ron = "0.5" serde = {version = "1.0.88", features = ["derive"] } webrender = {path = "../webrender", features=["capture","replay","debugger","png","profiler","no_static_freetype", "leak_checks"]} webrender_api = {path = "../webrender_api", features=["serialize","deserialize"]} diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml index d3d7482bcf4e..dcf26d91330a 100644 --- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -43,7 +43,7 @@ num-traits = "0.2" plane-split = "0.15" png = { optional = true, version = "0.16" } rayon = "1" -ron = { optional = true, version = "0.1.7" } +ron = { optional = true, version = "0.5" } serde = { optional = true, version = "1.0", features = ["serde_derive"] } serde_json = { optional = true, version = "1.0" } smallvec = "1" diff --git a/gfx/wr/wrench/Cargo.toml b/gfx/wr/wrench/Cargo.toml index 72bd8e2df497..988e2537aaea 100644 --- a/gfx/wr/wrench/Cargo.toml +++ b/gfx/wr/wrench/Cargo.toml @@ -19,7 +19,7 @@ clap = { version = "2", features = ["yaml"] } log = "0.4" yaml-rust = "0.4" serde_json = "1.0" -ron = "0.1.5" +ron = "0.5" time = "0.1" chrono = "0.2" crossbeam = "0.2" diff --git a/third_party/rust/ron/.cargo-checksum.json b/third_party/rust/ron/.cargo-checksum.json index 3e610ef75670..f9edf2da1a2c 100644 --- a/third_party/rust/ron/.cargo-checksum.json +++ b/third_party/rust/ron/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"3084630437ca5b2ff223cc0aa4e6329250ccc599723cf0711c89979165a52721","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"fa0598d520497731445a5bc89a2b3d47896d95568bd2be255b7bc43d771b9994","README.md":"87cac8cd8c6d9ceb66802f9c810df6583762942567eff7baf71d4ad700df93ec","examples/decode.rs":"70e1eacea082e17dd57ce731c6963c8166aa161445857c1032819d87d89ce067","examples/decode_file.rs":"d046edcee9339855e3fca0d81cb75bf227a0f12a836faa46ee5420f78df14e51","examples/encode.rs":"502f79332a47950bcc172295e50665ff87d57dc68707d497a4dd9ccb5fcd298f","examples/example.ron":"c3355fcb6ee48f32da62ff56040dc69a69730c24f55e7744e235a28aa66a560e","examples/transcode.rs":"5cae0549acf44d522a1f93d41c72901bc52f640a393b55b25bfc735a3395dff4","highlight/RON.sublime-syntax":"3b44ac654381f86a48ecd294a116d645afc8b1b285ac54a98fdfe0ef44922ad8","src/de/error.rs":"354213757a5edadd2bb1cfb524aff4ab519abe126329372947cb5f1cd9042ce9","src/de/id.rs":"52f7890e13c451d3614e14cf1e41ff0006906af57c7a6d0151bfdf1431c6dd7d","src/de/mod.rs":"08b27a38cf0534f8b5831af3913570b1013663bb3d1a1e1dd8ab19d61e251d91","src/de/tests.rs":"319f4a0c04d351d1fc55b92a7b1f08462ac62760258d64a10f098b65cc7cb452","src/de/value.rs":"6195d0ed6db65c7c2c9cdff40502da3514f0510e59f2ad0c0ad0ad8c3bb5b4ff","src/lib.rs":"558446d7acc431ee04bbb1f54e31cd83a5457d04c0e5619dc2cbf47ec97b28d8","src/parse.rs":"168f02b2e3865cb4448c5b9991a65765a9c9c78b7edb1aa238b329715289200a","src/ser/mod.rs":"0b837bceb1f3c4bda47f6217f7abb07c8a39db26f91000adeaf6ed7e1edd56d6","src/ser/pretty.rs":"b1da2210842fae2f69f76e1429fdc91337805ec21f5e46e8d4fbf6b5ba01b3c5","src/ser/value.rs":"b3616892a500a67f1e14bc21d2b80c11e37387de9d58f877f30c443d0a372328","src/value.rs":"5a6102a111358c3c1f7bb55551ff1a1fd352383dc31e973c85ffe01cb06f38f9","tests/big_struct.rs":"04c78b4e5a707cb359ac01607769b3a9ee272a407e4f5c225bb801d432655254","tests/numbers.rs":"70fd0d8718b364e5512ced9ed8beffd3a3ef5a87109cfef7895bd2209be0929b","tests/roundtrip.rs":"d20e3c28c44ad7e6372e5a64afaf24a6d8db190acbdfde77d22f532ac2a7d1eb"},"package":"da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"} \ No newline at end of file +{"files":{"Cargo.toml":"cbff1b8a1ed9f2757045ddfa291ca54050f528caeb28af00275232b73f635ac7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"fa0598d520497731445a5bc89a2b3d47896d95568bd2be255b7bc43d771b9994","README.md":"64b6f569099a35c13f6028d01ac9b9c314b2aa4a40f0309de7e8e580f90754cb","docs/extensions.md":"b5013a854c1fd90fad40dbb37d35a50f1afc8eafe481133f6e36345091c4c3ef","docs/grammar.md":"e7dbfeae7cc705bd7df5f5132675da7703ba412a64b806b12df15ff50cfb35b3","examples/decode.rs":"ebf3348ce23c3b4cca04da745f8cabfd866b087982d459bb589b2f2f26be0d81","examples/decode_file.rs":"b52cc91894fe10ca5b964327ac5cc633a30da6f646846838a6d4c606369bffb5","examples/encode.rs":"8a7c225036bdd3b9e5ccc1668d608990d0b7b830ebcdf03aadea43cd0dffd67b","examples/example.ron":"c3355fcb6ee48f32da62ff56040dc69a69730c24f55e7744e235a28aa66a560e","examples/transcode.rs":"a01ebe61331fcd1935f5c7885b7825e9155053466ace35f81338c628ea1af2ec","rustfmt.toml":"4f90eed39c472a472c46a9e1273f2e77de3071ba674af7fe57a9e29b6b9bb0c2","src/de/error.rs":"f4581524eaa808ea1307a38cca2dfd0c268953d4c6ab296cd776de057f350345","src/de/id.rs":"4deb0d0c5ad83ca7b287a87b76d19247e43228e85698dd5efb6f7c168433aa79","src/de/mod.rs":"cb435e23590b7bba3394d7592dc8e3749297da64bec90f2cdaf6f6dadc2f0393","src/de/tests.rs":"ac17dcd0573b23fe883d3210bda0550f8d4a7d92fd83611ed72c10e1a5b038b9","src/de/value.rs":"80d32104ea7b4370aa0b4bc8fe9f4ad671886b28ceea37d84a75183f225cc800","src/lib.rs":"39a260e4c97d6b305c1c93c27a12569db4533dc6087981400555c3649630ebb6","src/parse.rs":"f35ef5b3328da6cb836fac6222046c865bc20a11a806944a61af1659b467af76","src/ser/mod.rs":"4cda213bb6163c91b3a3cd7fc1dcfa69d34dff6776ede93bc426533ada2de355","src/ser/value.rs":"4ce34d4b405d6279a24500db0bda4b8b2978dc5aaeb4a34d100a5ee41af7bf05","src/value.rs":"d36369ee4907b1ceda9f4117a78d56a2109357e6b16c8acec989511df60b63e6","tests/147_empty_sets_serialisation.rs":"8e9e71b879d6fe834c110c79939db0a010e75eedb4d117a2147adb6b5136faf5","tests/big_struct.rs":"9c7b41233ae7d0c4fec0727aabd4cea1cd95844c85c0beb5e688b3c79eb43c14","tests/comments.rs":"fff605e703449f211f737e36fb33d6f56f2213d18fec85ca72aea5b3032a287e","tests/depth_limit.rs":"ddf6a45137c78dc283d052556b5b719045f40bffe6f4a454f25de13ef8da6f81","tests/escape.rs":"e53c92cd9ea1fbe115ffdbd8778939a481febc451cce7ab64a3dcb126df3a53b","tests/extensions.rs":"3978323185285a7bfb046402400a5ba70147d9c055a03f42e2d4be18d5568254","tests/numbers.rs":"0ac1745b821fd08c759c5e665c00fecceb23077d41f9f237488989f8d89d32a5","tests/roundtrip.rs":"4267fb6286d3c866d2b3fc16bd67da8a740f709bf685e5cc0d06913007d15dda","tests/unicode.rs":"ac3944bf448f8cd5986bad5e7c4eca60302230c13378b213415dafc1d3ae2428","tests/value.rs":"aec359fc3786e3e150a87ede2ec2fd3185602fe469da9c0598ba443517245fd3"},"package":"2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"} \ No newline at end of file diff --git a/third_party/rust/ron/Cargo.toml b/third_party/rust/ron/Cargo.toml index 27732ffaa0da..c877a66bb9a2 100644 --- a/third_party/rust/ron/Cargo.toml +++ b/third_party/rust/ron/Cargo.toml @@ -3,7 +3,7 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies +# to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're @@ -11,13 +11,15 @@ # will likely look very different (and much more reasonable) [package] +edition = "2018" name = "ron" -version = "0.1.7" +version = "0.5.1" authors = ["Dzmitry Malyshau ", "Thomas Schaller "] exclude = ["bors.toml", ".travis.yml"] description = "Rusty Object Notation" homepage = "https://github.com/ron-rs/ron" documentation = "https://docs.rs/ron/" +readme = "README.md" keywords = ["parser", "serde", "serialization"] categories = ["encoding"] license = "MIT/Apache-2.0" @@ -25,8 +27,17 @@ repository = "https://github.com/ron-rs/ron" [lib] name = "ron" +[dependencies.base64] +version = "0.10" + +[dependencies.bitflags] +version = "1" + [dependencies.serde] version = "1" features = ["serde_derive"] +[dev-dependencies.serde_bytes] +version = "0.10" + [dev-dependencies.serde_json] version = "1" diff --git a/third_party/rust/ron/README.md b/third_party/rust/ron/README.md index 1df3b142166d..6e1d0722387a 100644 --- a/third_party/rust/ron/README.md +++ b/third_party/rust/ron/README.md @@ -1,6 +1,6 @@ -## Rusty Object Notation +# Rusty Object Notation -[![Build Status](https://travis-ci.org/ron-rs/ron.png?branch=master)](https://travis-ci.org/ron-rs/ron) +[![Build Status](https://travis-ci.org/ron-rs/ron.svg?branch=master)](https://travis-ci.org/ron-rs/ron) [![Crates.io](https://img.shields.io/crates/v/ron.svg)](https://crates.io/crates/ron) [![Docs](https://docs.rs/ron/badge.svg)](https://docs.rs/ron) [![Gitter](https://badges.gitter.im/ron-rs/ron.svg)](https://gitter.im/ron-rs/ron) @@ -9,6 +9,39 @@ RON is a simple readable data serialization format that looks similar to Rust sy It's designed to support all of [Serde's data model](https://serde.rs/data-model.html), so structs, enums, tuples, arrays, generic maps, and primitive values. +## Example + +``` +GameConfig( // optional struct name + window_size: (800, 600), + window_title: "PAC-MAN", + fullscreen: false, + + mouse_sensitivity: 1.4, + key_bindings: { + "up": Up, + "down": Down, + "left": Left, + "right": Right, + + // Uncomment to enable WASD controls + /* + "W": Up, + "A": Down, + "S": Left, + "D": Right, + */ + }, + + difficulty_options: ( + start_difficulty: Easy, + adaptive: false, + ), +) +``` + +## Why RON? + ### Example in JSON ```json @@ -27,7 +60,7 @@ structs, enums, tuples, arrays, generic maps, and primitive values. "material": "metal" }, { - "name": "moster", + "name": "monster", "material": "plastic" } ] @@ -86,7 +119,8 @@ Here are the general rules to parse the heterogeneous structures: ### Specification There is a very basic, work in progress specification available on -[the wiki page](https://github.com/kvark/ron/wiki/Specification). +[the wiki page](https://github.com/ron-rs/ron/wiki/Specification). +A more formal and complete grammar is available [here](docs/grammar.md). ### Appendix @@ -95,7 +129,7 @@ Why not XML? - unclear how to treat attributes vs contents Why not YAML? - - significant white-space + - significant white-space - specification is too big Why not TOML? @@ -105,6 +139,12 @@ Why not TOML? Why not XXX? - if you know a better format, tell me! +## Tooling + +Sublime Text: https://packagecontrol.io/packages/RON + +Vim: https://github.com/ron-rs/ron.vim + ## License RON is dual-licensed under Apache-2.0 and MIT. diff --git a/third_party/rust/ron/docs/extensions.md b/third_party/rust/ron/docs/extensions.md new file mode 100644 index 000000000000..ae648d778a26 --- /dev/null +++ b/third_party/rust/ron/docs/extensions.md @@ -0,0 +1,67 @@ +## RON extensions + +RON has extensions that can be enabled by adding the following attribute at the top of your RON document: + +`#![enable(...)]` + +# unwrap_newtypes + +You can add this extension by adding the following attribute at the top of your RON document: + +`#![enable(unwrap_newtypes)]` + +This feature enables RON to automatically unwrap simple tuples. + +```rust +struct NewType(u32); +struct Object { + pub new_type: NewType, +} +``` + +Without `unwrap_newtypes`, because the value `5` can not be saved into `NewType(u32)`, your RON document would look like this: + +``` ron +( + new_type: (5), +) +``` + +With the `unwrap_newtypes` extension, this coercion is done automatically. So `5` will be interpreted as `(5)`. + +``` ron +#![enable(unwrap_newtypes)] +( + new_type: 5, +) +``` + +# implicit_some + +You can add this extension by adding the following attribute at the top of your RON document: + +`#![enable(implicit_some)]` + +This feature enables RON to automatically convert any value to `Some(value)` if the deserialized struct requires it. + +```rust +struct Object { + pub value: Option, +} +``` + +Without this feature, you would have to write this RON document. + +```ron +( + value: Some(5), +) +``` + +Enabling the feature would automatically infer `Some(x)` if `x` is given. In this case, RON automatically casts this `5` into a `Some(5)`. + +```ron +( + value: 5, +) +``` diff --git a/third_party/rust/ron/docs/grammar.md b/third_party/rust/ron/docs/grammar.md new file mode 100644 index 000000000000..0f40039dfc75 --- /dev/null +++ b/third_party/rust/ron/docs/grammar.md @@ -0,0 +1,130 @@ +# RON grammar + +This file describes the structure of a RON file in [EBNF notation][ebnf]. +If extensions are enabled, some rules will be replaced. For that, see the +[extensions document][exts] which describes all extensions and what they override. + +[ebnf]: https://en.wikipedia.org/wiki/Extended_Backus–Naur_form +[exts]: ./extensions.md + +## RON file + +```ebnf +RON = [extensions], ws, value, ws; +``` + +## Whitespace and comments + +```ebnf +ws = { ws_single, comment }; +ws_single = "\n" | "\t" | "\r" | " "; +comment = ["//", { no_newline }, "\n"]; +``` + +## Commas + +```ebnf +comma = ws, ",", ws; +``` + +## Extensions + +```ebnf +extensions = { "#", ws, "!", ws, "[", ws, extensions_inner, ws, "]", ws }; +extensions_inner = "enable", ws, "(", extension_name, { comma, extension_name }, [comma], ws, ")"; +``` + +For the extension names see the [`extensions.md`][exts] document. + +## Value + +```ebnf +value = unsigned | signed | float | string | char | bool | option | list | map | tuple | struct | enum_variant; +``` + +## Numbers + +```ebnf +digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; +unsigned = ["0", ("x" | "b" | "o")], digit, { digit | '_' }; +signed = ["+" | "-"], unsigned; +float = float_std | float_frac; +float_std = ["+" | "-"], digit, { digit }, ".", {digit}, [float_exp]; +float_frac = ".", digit, {digit}, [float_exp]; +float_exp = ("e" | "E"), digit, {digit}; +``` + +## String + +```ebnf +string = string_std | string_raw; +string_std = "\"", { no_double_quotation_marks | string_escape }, "\""; +string_escape = "\\", ("\"" | "\\" | "b" | "f" | "n" | "r" | "t" | ("u", unicode_hex)); +string_raw = ("r#", string_raw, "#") | "\"", { unicode_non_greedy }, "\""; +``` + +> Note: Raw strings start with an `r`, followed by n `#` and a quotation mark + `"`. They may contain any characters or escapes (except the end sequence). + A raw string ends with a quotation mark (`"`), followed by n `#`. + Example: + ```rust +r##"This is a "raw string". It can contain quotations or +backslashes (\)!"## + ``` + I don't know any sane way to write this out in EBNF, if you do, let me know. + +## Char + +```ebnf +char = "'", (no_apostrophe | "\\\\" | "\\'"), "'"; +``` + +## Boolean + +```ebnf +bool = "true" | "false"; +``` + +## Optional + +```ebnf +option = "Some", ws, "(", ws, value, ws, ")"; +``` + +## List + +```ebnf +list = "[", [value, { comma, value }, [comma]], "]"; +``` + +## Map + +```ebnf +map = "{", [map_entry, { comma, map_entry }, [comma]], "}"; +map_entry = value, ws, ":", ws, value; +``` + +## Tuple + +```ebnf +tuple = "(", [value, { comma, value }, [comma]], ")"; +``` + +## Struct + +```ebnf +struct = unit_struct | tuple_struct | named_struct; +unit_struct = ident | "()"; +tuple_struct = [ident], ws, tuple; +named_struct = [ident], ws, "(", [named_field, { comma, named_field }, [comma]], ")"; +named_field = ident, ws, ":", value; +``` + +## Enum + +```ebnf +enum_variant = enum_variant_unit | enum_variant_tuple | enum_variant_named; +enum_variant_unit = ident; +enum_variant_tuple = ident, ws, tuple; +enum_variant_named = ident, ws, "(", [named_field, { comma, named_field }, [comma]], ")"; +``` diff --git a/third_party/rust/ron/examples/decode.rs b/third_party/rust/ron/examples/decode.rs index 94aaf0640745..366f69b2ec17 100644 --- a/third_party/rust/ron/examples/decode.rs +++ b/third_party/rust/ron/examples/decode.rs @@ -1,10 +1,6 @@ -extern crate ron; -#[macro_use] -extern crate serde; - -use std::collections::HashMap; - use ron::de::from_str; +use serde::Deserialize; +use std::collections::HashMap; #[derive(Debug, Deserialize)] struct Config { @@ -12,6 +8,7 @@ struct Config { float: f32, map: HashMap, nested: Nested, + option: Option, tuple: (u32, u32), } @@ -21,7 +18,21 @@ struct Nested { b: char, } -const CONFIG: &str = "( +const CONFIG: &str = " +/* + * RON now has multi-line (C-style) block comments! + * They can be freely nested: + * /* This is a nested comment */ + * If you just want a single-line comment, + * do it like here: +// Just put two slashes before the comment and the rest of the line +// can be used freely! +*/ + +// Note that block comments can not be started in a line comment +// (Putting a /* here will have no effect) + +( boolean: true, float: 8.2, map: { @@ -36,7 +47,8 @@ const CONFIG: &str = "( a: \"Decode me!\", b: 'z', ), - tuple: (3, 7), + option: Some(\t \"Weird formatting!\" \n\n ), + tuple: (3 /*(2 + 1)*/, 7 /*(2 * 5 - 3)*/), )"; fn main() { @@ -45,8 +57,8 @@ fn main() { Err(e) => { println!("Failed to load config: {}", e); - ::std::process::exit(1); - }, + std::process::exit(1); + } }; println!("Config: {:?}", &config); diff --git a/third_party/rust/ron/examples/decode_file.rs b/third_party/rust/ron/examples/decode_file.rs index f34e0f5eee87..cd88ffc5a044 100644 --- a/third_party/rust/ron/examples/decode_file.rs +++ b/third_party/rust/ron/examples/decode_file.rs @@ -1,11 +1,6 @@ -extern crate ron; -#[macro_use] -extern crate serde; - -use std::collections::HashMap; -use std::fs::File; - use ron::de::from_reader; +use serde::Deserialize; +use std::{collections::HashMap, fs::File}; #[derive(Debug, Deserialize)] struct Config { @@ -23,16 +18,15 @@ struct Nested { } fn main() { - let input_path = format!("{}/examples/example.ron", - env!("CARGO_MANIFEST_DIR")); + let input_path = format!("{}/examples/example.ron", env!("CARGO_MANIFEST_DIR")); let f = File::open(&input_path).expect("Failed opening file"); let config: Config = match from_reader(f) { Ok(x) => x, Err(e) => { println!("Failed to load config: {}", e); - ::std::process::exit(1); - }, + std::process::exit(1); + } }; println!("Config: {:?}", &config); diff --git a/third_party/rust/ron/examples/encode.rs b/third_party/rust/ron/examples/encode.rs index f9ebc12befbb..101208bb2943 100644 --- a/third_party/rust/ron/examples/encode.rs +++ b/third_party/rust/ron/examples/encode.rs @@ -1,12 +1,6 @@ -extern crate ron; -#[macro_use] -extern crate serde; - -use std::collections::HashMap; -use std::default::Default; -use std::fs::File; - -use ron::ser::{PrettyConfig, to_string_pretty}; +use ron::ser::{to_string_pretty, PrettyConfig}; +use serde::Serialize; +use std::{collections::HashMap, iter::FromIterator}; #[derive(Serialize)] struct Config { @@ -33,11 +27,6 @@ struct Nested { } fn main() { - use std::io::Write; - use std::iter::FromIterator; - - let mut file = File::create("config.ron").expect("Failed to create file"); - let data = Config { float: (2.18, -1.1), tuple: TupleStruct((), false), @@ -51,11 +40,12 @@ fn main() { }; let pretty = PrettyConfig { + depth_limit: 2, separate_tuple_members: true, enumerate_arrays: true, ..PrettyConfig::default() }; let s = to_string_pretty(&data, pretty).expect("Serialization failed"); - file.write(s.as_bytes()).expect("Failed to write data to file"); + println!("{}", s); } diff --git a/third_party/rust/ron/examples/transcode.rs b/third_party/rust/ron/examples/transcode.rs index 9577ec8e898b..401f65128e3f 100644 --- a/third_party/rust/ron/examples/transcode.rs +++ b/third_party/rust/ron/examples/transcode.rs @@ -1,9 +1,5 @@ -extern crate ron; -extern crate serde; -extern crate serde_json; - use ron::value::Value; -use serde::ser::Serialize; +use serde::Serialize; fn main() { let data = r#" diff --git a/third_party/rust/ron/highlight/RON.sublime-syntax b/third_party/rust/ron/highlight/RON.sublime-syntax deleted file mode 100644 index 7a21c086c56c..000000000000 --- a/third_party/rust/ron/highlight/RON.sublime-syntax +++ /dev/null @@ -1,132 +0,0 @@ -%YAML 1.2 ---- -name: RON -file_extensions: - - ron -scope: source.ron -contexts: - main: - - include: value - array: - - match: '\[' - scope: punctuation.section.array.begin.ron - push: - - meta_scope: meta.structure.array.ron - - match: '\]' - scope: punctuation.section.array.end.ron - pop: true - - include: value - - match: ',' - scope: punctuation.separator.array.ron - - match: '[^\s\]]' - scope: invalid.illegal.expected-array-separator.ron - comments: - - match: /\*\*(?!/) - scope: punctuation.definition.comment.ron - push: - - meta_scope: comment.block.documentation.ron - - match: \*/ - pop: true - - match: /\* - scope: punctuation.definition.comment.ron - push: - - meta_scope: comment.block.ron - - match: \*/ - pop: true - - match: (//).*$\n? - scope: comment.line.double-slash.js - captures: - 1: punctuation.definition.comment.ron - constant: - - match: \b(true|false)\b - scope: constant.language.ron - number: - # handles integer and decimal numbers - - match: |- - (?x: # turn on extended mode - -? # an optional minus - (?: - 0 # a zero - | # ...or... - [1-9] # a 1-9 character - \d* # followed by zero or more digits - ) - (?: - (?: - \. # a period - \d+ # followed by one or more digits - )? - (?: - [eE] # an e character - [+-]? # followed by an option +/- - \d+ # followed by one or more digits - )? # make exponent optional - )? # make decimal portion optional - ) - scope: constant.numeric.ron - object: - - match: '[A-Za-z_][A-Za-z_0-9]*' - scope: entity.name.class.ron - - match: '\(' - scope: punctuation.section.dictionary.begin.ron - push: - - meta_scope: meta.structure.entity.ron - - match: '\)' - scope: punctuation.section.dictionary.end.ron - pop: true - - match: '[a-z_][A-Za-z_0-9]*' - scope: entity.name.tag.ron - - match: '\:' - scope: punctuation.separator.dictionary.key-value.ron - - include: value - - match: ',' - scope: punctuation.separator.dictionary.ron - dictionary: - - match: '\{' - scope: punctuation.section.dictionary.begin.ron - push: - - meta_scope: meta.structure.dictionary.ron - - match: '\}' - scope: punctuation.section.dictionary.end.ron - pop: true - - include: value - - match: ':' - scope: punctuation.separator.dictionary.key-value.ron - - include: value - - match: ',' - scope: punctuation.separator.dictionary.ron - string: - - match: '"' - scope: punctuation.definition.string.begin.ron - push: inside-string - inside-string: - - meta_scope: string.quoted.double.ron - - match: '"' - scope: punctuation.definition.string.end.ron - pop: true - - include: string-escape - - match: $\n? - scope: invalid.illegal.unclosed-string.ron - pop: true - string-escape: - - match: |- - (?x: # turn on extended mode - \\ # a literal backslash - (?: # ...followed by... - ["\\/bfnrt] # one of these characters - | # ...or... - u # a u - [0-9a-fA-F]{4} # and four hex digits - ) - ) - scope: constant.character.escape.ron - - match: \\. - scope: invalid.illegal.unrecognized-string-escape.ron - value: - - include: constant - - include: number - - include: string - - include: array - - include: dictionary - - include: object - - include: comments diff --git a/third_party/rust/ron/rustfmt.toml b/third_party/rust/ron/rustfmt.toml new file mode 100644 index 000000000000..d092e7eae9fe --- /dev/null +++ b/third_party/rust/ron/rustfmt.toml @@ -0,0 +1,9 @@ +hard_tabs = false +merge_imports = true +reorder_impl_items = true +use_field_init_shorthand = true +use_try_shorthand = true +format_doc_comments = true +wrap_comments = true +edition = "2018" +version = "Two" diff --git a/third_party/rust/ron/src/de/error.rs b/third_party/rust/ron/src/de/error.rs index 7cf9f02840f3..f27f2029e8ff 100644 --- a/third_party/rust/ron/src/de/error.rs +++ b/third_party/rust/ron/src/de/error.rs @@ -1,15 +1,10 @@ -use std::error::Error as StdError; -use std::fmt; -use std::str::Utf8Error; -use std::io; -use std::string::FromUtf8Error; - use serde::de; +use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; -use parse::Position; +use crate::parse::Position; /// Deserialization result. -pub type Result = ::std::result::Result; +pub type Result = std::result::Result; #[derive(Clone, Debug, PartialEq)] pub enum Error { @@ -20,9 +15,12 @@ pub enum Error { #[derive(Clone, Debug, PartialEq)] pub enum ParseError { + Base64Error(base64::DecodeError), Eof, ExpectedArray, ExpectedArrayEnd, + ExpectedAttribute, + ExpectedAttributeEnd, ExpectedBoolean, ExpectedComma, ExpectedEnum, @@ -42,8 +40,12 @@ pub enum ParseError { ExpectedStringEnd, ExpectedIdentifier, - InvalidEscape, + InvalidEscape(&'static str), + NoSuchExtension(String), + + UnclosedBlockComment, + UnderscoreAtBeginning, UnexpectedByte(char), Utf8Error(Utf8Error), @@ -54,7 +56,7 @@ pub enum ParseError { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Error::IoError(ref s) => write!(f, "{}", s), Error::Message(ref s) => write!(f, "{}", s), @@ -75,9 +77,14 @@ impl StdError for Error { Error::IoError(ref s) => s, Error::Message(ref e) => e, Error::Parser(ref kind, _) => match *kind { + ParseError::Base64Error(ref e) => e.description(), ParseError::Eof => "Unexpected end of file", ParseError::ExpectedArray => "Expected array", ParseError::ExpectedArrayEnd => "Expected end of array", + ParseError::ExpectedAttribute => "Expected an enable attribute", + ParseError::ExpectedAttributeEnd => { + "Expected closing `)` and `]` after the attribute" + } ParseError::ExpectedBoolean => "Expected boolean", ParseError::ExpectedComma => "Expected comma", ParseError::ExpectedEnum => "Expected enum", @@ -94,15 +101,21 @@ impl StdError for Error { ParseError::ExpectedUnit => "Expected unit", ParseError::ExpectedStructName => "Expected struct name", ParseError::ExpectedString => "Expected string", + ParseError::ExpectedStringEnd => "Expected string end", ParseError::ExpectedIdentifier => "Expected identifier", - ParseError::InvalidEscape => "Invalid escape sequence", + ParseError::InvalidEscape(_) => "Invalid escape sequence", + + ParseError::NoSuchExtension(_) => "No such RON extension", ParseError::Utf8Error(ref e) => e.description(), + ParseError::UnclosedBlockComment => "Unclosed block comment", + ParseError::UnderscoreAtBeginning => "Found underscore at the beginning", + ParseError::UnexpectedByte(_) => "Unexpected byte", ParseError::TrailingCharacters => "Non-whitespace trailing characters", - _ => unimplemented!(), - } + ParseError::__NonExhaustive => unimplemented!(), + }, } } } @@ -121,7 +134,7 @@ impl From for ParseError { impl From for Error { fn from(e: Utf8Error) -> Self { - Error::Parser(ParseError::Utf8Error(e), Position { line : 0, col : 0}) + Error::Parser(ParseError::Utf8Error(e), Position { line: 0, col: 0 }) } } @@ -129,4 +142,4 @@ impl From for Error { fn from(e: io::Error) -> Self { Error::IoError(e.description().to_string()) } -} \ No newline at end of file +} diff --git a/third_party/rust/ron/src/de/id.rs b/third_party/rust/ron/src/de/id.rs index f647a219dde7..1ae1d485a8a3 100644 --- a/third_party/rust/ron/src/de/id.rs +++ b/third_party/rust/ron/src/de/id.rs @@ -8,187 +8,191 @@ pub struct IdDeserializer<'a, 'b: 'a> { impl<'a, 'b: 'a> IdDeserializer<'a, 'b> { pub fn new(d: &'a mut Deserializer<'b>) -> Self { - IdDeserializer { - d - } + IdDeserializer { d } } } impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> { type Error = Error; - fn deserialize_identifier( - self, - visitor: V - ) -> Result - where V: Visitor<'b> + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'b>, { self.d.deserialize_identifier(visitor) } fn deserialize_any(self, visitor: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { self.deserialize_identifier(visitor) } fn deserialize_bool(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_i8(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_i16(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_i32(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_i64(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_u8(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_u16(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_u32(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_u64(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_f32(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_f64(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_char(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_str(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_string(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_bytes(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_byte_buf(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_option(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_unit(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } - fn deserialize_unit_struct( - self, - _: &'static str, - _: V - ) -> Result - where V: Visitor<'b> + fn deserialize_unit_struct(self, _: &'static str, _: V) -> Result + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } - fn deserialize_newtype_struct( - self, - _: &'static str, - _: V - ) -> Result - where V: Visitor<'b> + fn deserialize_newtype_struct(self, _: &'static str, _: V) -> Result + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_seq(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } - fn deserialize_tuple( - self, - _: usize, - _: V - ) -> Result - where V: Visitor<'b> + fn deserialize_tuple(self, _: usize, _: V) -> Result + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } - fn deserialize_tuple_struct( - self, - _: &'static str, - _: usize, - _: V - ) -> Result - where V: Visitor<'b> + fn deserialize_tuple_struct(self, _: &'static str, _: usize, _: V) -> Result + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } fn deserialize_map(self, _: V) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } @@ -197,9 +201,10 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> { self, _: &'static str, _: &'static [&'static str], - _: V + _: V, ) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } @@ -208,18 +213,17 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> { self, _: &'static str, _: &'static [&'static str], - _: V + _: V, ) -> Result - where V: Visitor<'b> + where + V: Visitor<'b>, { unimplemented!("IdDeserializer may only be used for identifiers") } - fn deserialize_ignored_any( - self, - visitor: V - ) -> Result - where V: Visitor<'b> + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'b>, { self.deserialize_any(visitor) } diff --git a/third_party/rust/ron/src/de/mod.rs b/third_party/rust/ron/src/de/mod.rs index cd8bc725502e..149a87cf4fe5 100644 --- a/third_party/rust/ron/src/de/mod.rs +++ b/third_party/rust/ron/src/de/mod.rs @@ -1,16 +1,12 @@ /// Deserialization module. -/// - pub use self::error::{Error, ParseError, Result}; +pub use crate::parse::Position; -use std::borrow::Cow; -use std::io; -use std::str; +use serde::de::{self, DeserializeSeed, Deserializer as SerdeError, Visitor}; +use std::{borrow::Cow, io, str}; -use serde::de::{self, Deserializer as Deserializer_, DeserializeSeed, Visitor}; - -use parse::Bytes; use self::id::IdDeserializer; +use crate::parse::{Bytes, Extensions, ParsedStr}; mod error; mod id; @@ -27,41 +23,50 @@ pub struct Deserializer<'de> { } impl<'de> Deserializer<'de> { - pub fn from_str(input: &'de str) -> Self { - Deserializer { - bytes: Bytes::new(input.as_bytes()), - } + pub fn from_str(input: &'de str) -> Result { + Deserializer::from_bytes(input.as_bytes()) } - pub fn from_bytes(input: &'de [u8]) -> Self { - Deserializer { - bytes: Bytes::new(input), - } + pub fn from_bytes(input: &'de [u8]) -> Result { + Ok(Deserializer { + bytes: Bytes::new(input)?, + }) } - pub fn remainder(&self) -> Cow { + pub fn remainder(&self) -> Cow<'_, str> { String::from_utf8_lossy(&self.bytes.bytes()) } } /// A convenience function for reading data from a reader -/// and feeding into a deserializer +/// and feeding into a deserializer. pub fn from_reader(mut rdr: R) -> Result - where R: io::Read, - T: de::DeserializeOwned +where + R: io::Read, + T: de::DeserializeOwned, { let mut bytes = Vec::new(); rdr.read_to_end(&mut bytes)?; - let s = str::from_utf8(&bytes)?; - from_str(s) + + from_bytes(&bytes) } /// A convenience function for building a deserializer -/// and deserializing a value of type `T`. +/// and deserializing a value of type `T` from a string. pub fn from_str<'a, T>(s: &'a str) -> Result - where T: de::Deserialize<'a> +where + T: de::Deserialize<'a>, { - let mut deserializer = Deserializer::from_str(s); + from_bytes(s.as_bytes()) +} + +/// A convenience function for building a deserializer +/// and deserializing a value of type `T` from bytes. +pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result +where + T: de::Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_bytes(s)?; let t = T::deserialize(&mut deserializer)?; deserializer.end()?; @@ -73,7 +78,7 @@ impl<'de> Deserializer<'de> { /// Check if the remaining bytes are whitespace only, /// otherwise return an error. pub fn end(&mut self) -> Result<()> { - self.bytes.skip_ws(); + self.bytes.skip_ws()?; if self.bytes.bytes().is_empty() { Ok(()) @@ -81,13 +86,41 @@ impl<'de> Deserializer<'de> { self.bytes.err(ParseError::TrailingCharacters) } } + + /// Called from `deserialze_any` when a struct was detected. Decides if + /// there is a unit, tuple or usual struct and deserializes it + /// accordingly. + /// + /// This method assumes there is no identifier left. + fn handle_any_struct(&mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // Create a working copy + let mut bytes = self.bytes; + + match bytes.consume("(") { + true => { + bytes.skip_ws()?; + + match bytes.check_tuple_struct()? { + // first argument is technically incorrect, but ignored anyway + true => self.deserialize_tuple(0, visitor), + // first two arguments are technically incorrect, but ignored anyway + false => self.deserialize_struct("", &[], visitor), + } + } + false => visitor.visit_unit(), + } + } } impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { if self.bytes.consume_ident("true") { return visitor.visit_bool(true); @@ -101,100 +134,121 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { return visitor.visit_unit(); } - if self.bytes.identifier().is_ok() { - self.bytes.skip_ws(); + // `identifier` does not change state if it fails + let ident = self.bytes.identifier().ok(); - return self.deserialize_struct("", &[], visitor); + if ident.is_some() { + self.bytes.skip_ws()?; + + return self.handle_any_struct(visitor); } match self.bytes.peek_or_eof()? { - b'(' => self.deserialize_struct("", &[], visitor), + b'(' => self.handle_any_struct(visitor), b'[' => self.deserialize_seq(visitor), b'{' => self.deserialize_map(visitor), - b'0' ... b'9' | b'+' | b'-' | b'.' => self.deserialize_f64(visitor), - b'"' => self.deserialize_string(visitor), + b'0'..=b'9' | b'+' | b'-' => { + if self.bytes.next_bytes_is_float() { + self.deserialize_f64(visitor) + } else { + self.deserialize_i64(visitor) + } + } + b'.' => self.deserialize_f64(visitor), + b'"' | b'r' => self.deserialize_string(visitor), b'\'' => self.deserialize_char(visitor), other => self.bytes.err(ParseError::UnexpectedByte(other as char)), } } fn deserialize_bool(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_bool(self.bytes.bool()?) } fn deserialize_i8(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_i8(self.bytes.signed_integer()?) } fn deserialize_i16(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_i16(self.bytes.signed_integer()?) } fn deserialize_i32(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_i32(self.bytes.signed_integer()?) } fn deserialize_i64(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_i64(self.bytes.signed_integer()?) } fn deserialize_u8(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_u8(self.bytes.unsigned_integer()?) } fn deserialize_u16(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_u16(self.bytes.unsigned_integer()?) } fn deserialize_u32(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_u32(self.bytes.unsigned_integer()?) } fn deserialize_u64(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_u64(self.bytes.unsigned_integer()?) } fn deserialize_f32(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_f32(self.bytes.float()?) } fn deserialize_f64(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_f64(self.bytes.float()?) } fn deserialize_char(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_char(self.bytes.char()?) } fn deserialize_str(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { - use parse::ParsedStr; - match self.bytes.string()? { ParsedStr::Allocated(s) => visitor.visit_string(s), ParsedStr::Slice(s) => visitor.visit_str(s), @@ -202,41 +256,61 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } fn deserialize_string(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { - self.deserialize_seq(visitor) + self.deserialize_byte_buf(visitor) } fn deserialize_byte_buf(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { - self.deserialize_seq(visitor) + let res = { + let string = self.bytes.string()?; + let base64_str = match string { + ParsedStr::Allocated(ref s) => s.as_str(), + ParsedStr::Slice(ref s) => s, + }; + base64::decode(base64_str) + }; + + match res { + Ok(byte_buf) => visitor.visit_byte_buf(byte_buf), + Err(err) => self.bytes.err(ParseError::Base64Error(err)), + } } fn deserialize_option(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { - if self.bytes.consume("Some") && { self.bytes.skip_ws(); self.bytes.consume("(") } { - self.bytes.skip_ws(); + if self.bytes.consume("None") { + visitor.visit_none() + } else if self.bytes.exts.contains(Extensions::IMPLICIT_SOME) { + visitor.visit_some(&mut *self) + } else if self.bytes.consume("Some") && { + self.bytes.skip_ws()?; + self.bytes.consume("(") + } { + self.bytes.skip_ws()?; let v = visitor.visit_some(&mut *self)?; - self.bytes.skip_ws(); + self.bytes.skip_ws()?; if self.bytes.consume(")") { Ok(v) } else { self.bytes.err(ParseError::ExpectedOptionEnd) } - - } else if self.bytes.consume("None") { - visitor.visit_none() } else { self.bytes.err(ParseError::ExpectedOption) } @@ -244,7 +318,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { // In Serde, unit means an anonymous value containing no data. fn deserialize_unit(self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { if self.bytes.consume("()") { visitor.visit_unit() @@ -253,12 +328,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } } - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V - ) -> Result - where V: Visitor<'de> + fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, { if self.bytes.consume(name) { visitor.visit_unit() @@ -267,20 +339,22 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } } - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V - ) -> Result - where V: Visitor<'de> + fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, { + if self.bytes.exts.contains(Extensions::UNWRAP_NEWTYPES) { + return visitor.visit_newtype_struct(&mut *self); + } + self.bytes.consume(name); - self.bytes.skip_ws(); + self.bytes.skip_ws()?; if self.bytes.consume("(") { + self.bytes.skip_ws()?; let value = visitor.visit_newtype_struct(&mut *self)?; - self.bytes.comma(); + self.bytes.comma()?; if self.bytes.consume(")") { Ok(value) @@ -293,11 +367,12 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } fn deserialize_seq(mut self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { if self.bytes.consume("[") { let value = visitor.visit_seq(CommaSeparated::new(b']', &mut self))?; - self.bytes.comma(); + self.bytes.comma()?; if self.bytes.consume("]") { Ok(value) @@ -309,22 +384,13 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } } - // Tuples look just like sequences in JSON. Some formats may be able to - // represent tuples more efficiently. - // - // As indicated by the length parameter, the `Deserialize` implementation - // for a tuple in the Serde data model is required to know the length of the - // tuple before even looking at the input data. - fn deserialize_tuple( - mut self, - _len: usize, - visitor: V - ) -> Result - where V: Visitor<'de> + fn deserialize_tuple(mut self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, { if self.bytes.consume("(") { let value = visitor.visit_seq(CommaSeparated::new(b')', &mut self))?; - self.bytes.comma(); + self.bytes.comma()?; if self.bytes.consume(")") { Ok(value) @@ -340,20 +406,22 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self, name: &'static str, len: usize, - visitor: V + visitor: V, ) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { self.bytes.consume(name); self.deserialize_tuple(len, visitor) } fn deserialize_map(mut self, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { if self.bytes.consume("{") { let value = visitor.visit_map(CommaSeparated::new(b'}', &mut self))?; - self.bytes.comma(); + self.bytes.comma()?; if self.bytes.consume("}") { Ok(value) @@ -369,17 +437,18 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { mut self, name: &'static str, _fields: &'static [&'static str], - visitor: V + visitor: V, ) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { self.bytes.consume(name); - self.bytes.skip_ws(); + self.bytes.skip_ws()?; if self.bytes.consume("(") { let value = visitor.visit_map(CommaSeparated::new(b')', &mut self))?; - self.bytes.comma(); + self.bytes.comma()?; if self.bytes.consume(")") { Ok(value) @@ -395,27 +464,26 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self, _name: &'static str, _variants: &'static [&'static str], - visitor: V + visitor: V, ) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { visitor.visit_enum(Enum::new(self)) } - fn deserialize_identifier( - self, - visitor: V - ) -> Result - where V: Visitor<'de> + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, { - visitor.visit_bytes(self.bytes.identifier()?) + visitor.visit_str( + str::from_utf8(self.bytes.identifier()?).map_err(|e| self.bytes.error(e.into()))?, + ) } - fn deserialize_ignored_any( - self, - visitor: V - ) -> Result - where V: Visitor<'de> + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, { self.deserialize_any(visitor) } @@ -429,7 +497,11 @@ struct CommaSeparated<'a, 'de: 'a> { impl<'a, 'de> CommaSeparated<'a, 'de> { fn new(terminator: u8, de: &'a mut Deserializer<'de>) -> Self { - CommaSeparated { de, terminator, had_comma: true } + CommaSeparated { + de, + terminator, + had_comma: true, + } } fn err(&self, kind: ParseError) -> Result { @@ -437,10 +509,9 @@ impl<'a, 'de> CommaSeparated<'a, 'de> { } fn has_element(&mut self) -> Result { - self.de.bytes.skip_ws(); + self.de.bytes.skip_ws()?; - Ok(self.had_comma && - self.de.bytes.peek_or_eof()? != self.terminator) + Ok(self.had_comma && self.de.bytes.peek_or_eof()? != self.terminator) } } @@ -448,12 +519,13 @@ impl<'de, 'a> de::SeqAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> - where T: DeserializeSeed<'de> + where + T: DeserializeSeed<'de>, { if self.has_element()? { let res = seed.deserialize(&mut *self.de)?; - self.had_comma = self.de.bytes.comma(); + self.had_comma = self.de.bytes.comma()?; Ok(Some(res)) } else { @@ -466,11 +538,13 @@ impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> - where K: DeserializeSeed<'de> + where + K: DeserializeSeed<'de>, { if self.has_element()? { if self.terminator == b')' { - seed.deserialize(&mut IdDeserializer::new(&mut *self.de)).map(Some) + seed.deserialize(&mut IdDeserializer::new(&mut *self.de)) + .map(Some) } else { seed.deserialize(&mut *self.de).map(Some) } @@ -480,16 +554,17 @@ impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> { } fn next_value_seed(&mut self, seed: V) -> Result - where V: DeserializeSeed<'de> + where + V: DeserializeSeed<'de>, { - self.de.bytes.skip_ws(); + self.de.bytes.skip_ws()?; if self.de.bytes.consume(":") { - self.de.bytes.skip_ws(); + self.de.bytes.skip_ws()?; let res = seed.deserialize(&mut *self.de)?; - self.had_comma = self.de.bytes.comma(); + self.had_comma = self.de.bytes.comma()?; Ok(res) } else { @@ -513,8 +588,11 @@ impl<'de, 'a> de::EnumAccess<'de> for Enum<'a, 'de> { type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> - where V: DeserializeSeed<'de> + where + V: DeserializeSeed<'de>, { + self.de.bytes.skip_ws()?; + let value = seed.deserialize(&mut *self.de)?; Ok((value, self)) @@ -529,14 +607,17 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { } fn newtype_variant_seed(self, seed: T) -> Result - where T: DeserializeSeed<'de> + where + T: DeserializeSeed<'de>, { - self.de.bytes.skip_ws(); - + self.de.bytes.skip_ws()?; + if self.de.bytes.consume("(") { + self.de.bytes.skip_ws()?; + let val = seed.deserialize(&mut *self.de)?; - self.de.bytes.comma(); + self.de.bytes.comma()?; if self.de.bytes.consume(")") { Ok(val) @@ -549,21 +630,19 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { } fn tuple_variant(self, len: usize, visitor: V) -> Result - where V: Visitor<'de> + where + V: Visitor<'de>, { - self.de.bytes.skip_ws(); + self.de.bytes.skip_ws()?; self.de.deserialize_tuple(len, visitor) } - fn struct_variant( - self, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where V: Visitor<'de> + fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result + where + V: Visitor<'de>, { - self.de.bytes.skip_ws(); + self.de.bytes.skip_ws()?; self.de.deserialize_struct("", fields, visitor) } diff --git a/third_party/rust/ron/src/de/tests.rs b/third_party/rust/ron/src/de/tests.rs index 887d7e247a83..04be82d3a845 100644 --- a/third_party/rust/ron/src/de/tests.rs +++ b/third_party/rust/ron/src/de/tests.rs @@ -1,3 +1,6 @@ +use serde::Deserialize; +use serde_bytes; + use super::*; #[derive(Debug, PartialEq, Deserialize)] @@ -7,14 +10,24 @@ struct EmptyStruct1; struct EmptyStruct2 {} #[derive(Clone, Copy, Debug, PartialEq, Deserialize)] -struct MyStruct { x: f32, y: f32 } +struct MyStruct { + x: f32, + y: f32, +} #[derive(Clone, Copy, Debug, PartialEq, Deserialize)] enum MyEnum { A, B(bool), C(bool, f32), - D { a: i32, b: i32 } + D { a: i32, b: i32 }, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct BytesStruct { + small: Vec, + #[serde(with = "serde_bytes")] + large: Vec, } #[test] @@ -23,7 +36,6 @@ fn test_empty_struct() { assert_eq!(Ok(EmptyStruct2 {}), from_str("EmptyStruct2()")); } - #[test] fn test_struct() { let my_struct = MyStruct { x: 4.0, y: 7.0 }; @@ -44,7 +56,6 @@ fn test_struct() { assert_eq!(Ok(TupleStruct(3.0, 4.0)), from_str("(3,4)")); } - #[test] fn test_option() { assert_eq!(Ok(Some(1u8)), from_str("Some(1)")); @@ -67,7 +78,7 @@ fn test_array() { assert_eq!(Ok(empty_array), from_str("[]")); assert_eq!(Ok([2, 3, 4i32]), from_str("(2,3,4,)")); - assert_eq!(Ok(([2, 3, 4i32].to_vec())), from_str("[2,3,4,]")); + assert_eq!(Ok([2, 3, 4i32].to_vec()), from_str("[2,3,4,]")); } #[test] @@ -78,17 +89,33 @@ fn test_map() { map.insert((true, false), 4); map.insert((false, false), 123); - assert_eq!(Ok(map), from_str("{ + assert_eq!( + Ok(map), + from_str( + "{ (true,false,):4, (false,false,):123, - }")); + }" + ) + ); } #[test] fn test_string() { let s: String = from_str("\"String\"").unwrap(); - assert_eq!("String", s); + + let raw: String = from_str("r\"String\"").unwrap(); + assert_eq!("String", raw); + + let raw_hashes: String = from_str("r#\"String\"#").unwrap(); + assert_eq!("String", raw_hashes); + + let raw_hashes_multiline: String = from_str("r#\"String with\nmultiple\nlines\n\"#").unwrap(); + assert_eq!("String with\nmultiple\nlines\n", raw_hashes_multiline); + + let raw_hashes_quote: String = from_str("r##\"String with \"#\"##").unwrap(); + assert_eq!("String with \"#", raw_hashes_quote); } #[test] @@ -108,16 +135,22 @@ fn test_escape() { #[test] fn test_comment() { - assert_eq!(MyStruct { x: 1.0, y: 2.0 }, from_str("( + assert_eq!( + MyStruct { x: 1.0, y: 2.0 }, + from_str( + "( x: 1.0, // x is just 1 // There is another comment in the very next line.. // And y is indeed y: 2.0 // 2! - )").unwrap()); + )" + ) + .unwrap() + ); } fn err(kind: ParseError, line: usize, col: usize) -> Result { - use parse::Position; + use crate::parse::Position; Err(Error::Parser(kind, Position { line, col })) } @@ -137,15 +170,22 @@ fn test_err_wrong_value() { assert_eq!(from_str::<(u8, bool)>("'c'"), err(ExpectedArray, 1, 1)); assert_eq!(from_str::("notabool"), err(ExpectedBoolean, 1, 1)); - assert_eq!(from_str::("MyStruct(\n x: true)"), err(ExpectedFloat, 2, 8)); - assert_eq!(from_str::("MyStruct(\n x: 3.5, \n y:)"), - err(ExpectedFloat, 3, 7)); + assert_eq!( + from_str::("MyStruct(\n x: true)"), + err(ExpectedFloat, 2, 8) + ); + assert_eq!( + from_str::("MyStruct(\n x: 3.5, \n y:)"), + err(ExpectedFloat, 3, 7) + ); } #[test] fn test_perm_ws() { - assert_eq!(from_str::("\nMyStruct \t ( \n x : 3.5 , \t y\n: 4.5 \n ) \t\n"), - Ok(MyStruct { x: 3.5, y: 4.5 })); + assert_eq!( + from_str::("\nMyStruct \t ( \n x : 3.5 , \t y\n: 4.5 \n ) \t\n"), + Ok(MyStruct { x: 3.5, y: 4.5 }) + ); } #[test] @@ -158,6 +198,7 @@ fn untagged() { } assert_eq!(from_str::("true").unwrap(), Untagged::Bool(true)); + assert_eq!(from_str::("8").unwrap(), Untagged::U8(8)); } #[test] @@ -169,3 +210,98 @@ fn forgot_apostrophes() { _ => false, }); } + +#[test] +fn expected_attribute() { + let de: Result = from_str("#\"Hello\""); + + assert_eq!(de, err(ParseError::ExpectedAttribute, 1, 2)); +} + +#[test] +fn expected_attribute_end() { + let de: Result = from_str("#![enable(unwrap_newtypes) \"Hello\""); + + assert_eq!(de, err(ParseError::ExpectedAttributeEnd, 1, 28)); +} + +#[test] +fn invalid_attribute() { + let de: Result = from_str("#![enable(invalid)] \"Hello\""); + + assert_eq!( + de, + err(ParseError::NoSuchExtension("invalid".to_string()), 1, 18) + ); +} + +#[test] +fn multiple_attributes() { + #[derive(Debug, Deserialize, PartialEq)] + struct New(String); + let de: Result = + from_str("#![enable(unwrap_newtypes)] #![enable(unwrap_newtypes)] \"Hello\""); + + assert_eq!(de, Ok(New("Hello".to_owned()))); +} + +#[test] +fn uglified_attribute() { + let de: Result<()> = from_str( + "# !\ + // We definitely want to add a comment here + [\t\tenable( // best style ever + unwrap_newtypes ) ] ()", + ); + + assert_eq!(de, Ok(())); +} + +#[test] +fn implicit_some() { + use serde::de::DeserializeOwned; + + fn de(s: &str) -> Option { + let enable = "#![enable(implicit_some)]\n".to_string(); + + from_str::>(&(enable + s)).unwrap() + } + + assert_eq!(de("'c'"), Some('c')); + assert_eq!(de("5"), Some(5)); + assert_eq!(de("\"Hello\""), Some("Hello".to_owned())); + assert_eq!(de("false"), Some(false)); + assert_eq!( + de("MyStruct(x: .4, y: .5)"), + Some(MyStruct { x: 0.4, y: 0.5 }) + ); + + assert_eq!(de::("None"), None); + + // Not concise + assert_eq!(de::>>("None"), None); +} + +#[test] +fn ws_tuple_newtype_variant() { + assert_eq!(Ok(MyEnum::B(true)), from_str("B ( \n true \n ) ")); +} + +#[test] +fn test_byte_stream() { + assert_eq!( + Ok(BytesStruct { + small: vec![1, 2], + large: vec![1, 2, 3, 4] + }), + from_str("BytesStruct( small:[1, 2], large:\"AQIDBA==\" )"), + ); +} + +#[test] +fn test_numbers() { + assert_eq!( + Ok(vec![1234, 12345, 123456, 1234567, 555_555]), + from_str("[1_234, 12_345, 1_2_3_4_5_6, 1_234_567, 5_55_55_5]"), + ); +} diff --git a/third_party/rust/ron/src/de/value.rs b/third_party/rust/ron/src/de/value.rs index ca01f9b01a97..00b3596e9903 100644 --- a/third_party/rust/ron/src/de/value.rs +++ b/third_party/rust/ron/src/de/value.rs @@ -1,22 +1,31 @@ -use std::collections::BTreeMap; -use std::fmt; +use std::{collections::BTreeMap, fmt}; -use serde::de::{Error, MapAccess, SeqAccess, Visitor}; -use serde::{Deserialize, Deserializer}; +use serde::{ + de::{Error, MapAccess, SeqAccess, Visitor}, + Deserialize, Deserializer, +}; -use de; -use value::{Number, Value}; +use crate::{ + de, + value::{Number, Value}, +}; impl Value { /// Creates a value from a string reference. pub fn from_str(s: &str) -> de::Result { - Self::deserialize(&mut super::Deserializer::from_str(s)) + let mut de = super::Deserializer::from_str(s)?; + + let val = Value::deserialize(&mut de)?; + de.end()?; + + Ok(val) } } impl<'de> Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> + where + D: Deserializer<'de>, { deserializer.deserialize_any(ValueVisitor) } @@ -27,91 +36,106 @@ struct ValueVisitor; impl<'de> Visitor<'de> for ValueVisitor { type Value = Value; - fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "A RON value") + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "a RON value") } fn visit_bool(self, v: bool) -> Result - where E: Error + where + E: Error, { Ok(Value::Bool(v)) } fn visit_i64(self, v: i64) -> Result - where E: Error, + where + E: Error, { self.visit_f64(v as f64) } fn visit_u64(self, v: u64) -> Result - where E: Error + where + E: Error, { self.visit_f64(v as f64) } fn visit_f64(self, v: f64) -> Result - where E: Error + where + E: Error, { Ok(Value::Number(Number::new(v))) } fn visit_char(self, v: char) -> Result - where E: Error + where + E: Error, { Ok(Value::Char(v)) } fn visit_str(self, v: &str) -> Result - where E: Error + where + E: Error, { self.visit_string(v.to_owned()) } fn visit_string(self, v: String) -> Result - where E: Error + where + E: Error, { Ok(Value::String(v)) } fn visit_bytes(self, v: &[u8]) -> Result - where E: Error + where + E: Error, { self.visit_byte_buf(v.to_vec()) } fn visit_byte_buf(self, v: Vec) -> Result - where E: Error + where + E: Error, { - self.visit_string(String::from_utf8(v) - .map_err(|e| Error::custom(format!("{}", e)))?) + self.visit_string(String::from_utf8(v).map_err(|e| Error::custom(format!("{}", e)))?) } fn visit_none(self) -> Result - where E: Error + where + E: Error, { Ok(Value::Option(None)) } fn visit_some(self, deserializer: D) -> Result - where D: Deserializer<'de>, + where + D: Deserializer<'de>, { - Ok(Value::Option(Some(Box::new(deserializer.deserialize_any(ValueVisitor)?)))) + Ok(Value::Option(Some(Box::new( + deserializer.deserialize_any(ValueVisitor)?, + )))) } fn visit_unit(self) -> Result - where E: Error + where + E: Error, { Ok(Value::Unit) } fn visit_newtype_struct(self, deserializer: D) -> Result - where D: Deserializer<'de> + where + D: Deserializer<'de>, { deserializer.deserialize_any(ValueVisitor) } fn visit_seq(self, mut seq: A) -> Result - where A: SeqAccess<'de> + where + A: SeqAccess<'de>, { let mut vec = Vec::new(); if let Some(cap) = seq.size_hint() { @@ -126,7 +150,8 @@ impl<'de> Visitor<'de> for ValueVisitor { } fn visit_map(self, mut map: A) -> Result - where A: MapAccess<'de> + where + A: MapAccess<'de>, { let mut res: BTreeMap = BTreeMap::new(); @@ -154,12 +179,52 @@ mod tests { #[test] fn test_some() { assert_eq!(eval("Some(())"), Value::Option(Some(Box::new(Value::Unit)))); - assert_eq!(eval("Some ( () )"), Value::Option(Some(Box::new(Value::Unit)))); + assert_eq!( + eval("Some ( () )"), + Value::Option(Some(Box::new(Value::Unit))) + ); + } + + #[test] + fn test_tuples_basic() { + assert_eq!( + eval("(3, 4, 5)"), + Value::Seq(vec![ + Value::Number(Number::new(3.0)), + Value::Number(Number::new(4.0)), + Value::Number(Number::new(5.0)), + ],), + ); + } + + #[test] + fn test_tuples_ident() { + assert_eq!( + eval("(true, 3, 4, 5)"), + Value::Seq(vec![ + Value::Bool(true), + Value::Number(Number::new(3.0)), + Value::Number(Number::new(4.0)), + Value::Number(Number::new(5.0)), + ]), + ); + } + + #[test] + fn test_tuples_error() { + use crate::de::{Error, ParseError, Position}; + + assert_eq!( + Value::from_str("Foo:").unwrap_err(), + Error::Parser(ParseError::TrailingCharacters, Position { col: 4, line: 1 }), + ); } #[test] fn test_complex() { - assert_eq!(eval("Some([ + assert_eq!( + eval( + "Some([ Room ( width: 20, height: 5, name: \"The Room\" ), ( @@ -172,27 +237,67 @@ mod tests { \"Enemy3\": 7, }, ), -])"), - Value::Option(Some(Box::new(Value::Seq( - vec![ - Value::Map(vec![ - (Value::String("width".to_owned()), Value::Number(Number::new(20.0))), - (Value::String("height".to_owned()), Value::Number(Number::new(5.0))), - (Value::String("name".to_owned()), Value::String("The Room".to_owned())), - ].into_iter().collect()), - Value::Map(vec![ - (Value::String("width".to_owned()), Value::Number(Number::new(10.0))), - (Value::String("height".to_owned()), Value::Number(Number::new(10.0))), - (Value::String("name".to_owned()), Value::String("Another room".to_owned())), - (Value::String("enemy_levels".to_owned()), Value::Map( - vec![ - (Value::String("Enemy1".to_owned()), Value::Number(Number::new(3.0))), - (Value::String("Enemy2".to_owned()), Value::Number(Number::new(5.0))), - (Value::String("Enemy3".to_owned()), Value::Number(Number::new(7.0))), - ].into_iter().collect() - )), - ].into_iter().collect()), - ] - ))))); +])" + ), + Value::Option(Some(Box::new(Value::Seq(vec![ + Value::Map( + vec![ + ( + Value::String("width".to_owned()), + Value::Number(Number::new(20.0)), + ), + ( + Value::String("height".to_owned()), + Value::Number(Number::new(5.0)), + ), + ( + Value::String("name".to_owned()), + Value::String("The Room".to_owned()), + ), + ] + .into_iter() + .collect(), + ), + Value::Map( + vec![ + ( + Value::String("width".to_owned()), + Value::Number(Number::new(10.0)), + ), + ( + Value::String("height".to_owned()), + Value::Number(Number::new(10.0)), + ), + ( + Value::String("name".to_owned()), + Value::String("Another room".to_owned()), + ), + ( + Value::String("enemy_levels".to_owned()), + Value::Map( + vec![ + ( + Value::String("Enemy1".to_owned()), + Value::Number(Number::new(3.0)), + ), + ( + Value::String("Enemy2".to_owned()), + Value::Number(Number::new(5.0)), + ), + ( + Value::String("Enemy3".to_owned()), + Value::Number(Number::new(7.0)), + ), + ] + .into_iter() + .collect(), + ), + ), + ] + .into_iter() + .collect(), + ), + ])))) + ); } } diff --git a/third_party/rust/ron/src/lib.rs b/third_party/rust/ron/src/lib.rs index 070793e9915a..c621801793a5 100644 --- a/third_party/rust/ron/src/lib.rs +++ b/third_party/rust/ron/src/lib.rs @@ -57,11 +57,9 @@ Serializing / Deserializing is as simple as calling `to_string` / `from_str`. !*/ -#[macro_use] -extern crate serde; - pub mod de; pub mod ser; pub mod value; +pub use crate::value::Value; mod parse; diff --git a/third_party/rust/ron/src/parse.rs b/third_party/rust/ron/src/parse.rs index 70d69cbeb1bc..47743f3e7235 100644 --- a/third_party/rust/ron/src/parse.rs +++ b/third_party/rust/ron/src/parse.rs @@ -1,11 +1,15 @@ -use std::fmt::{Display, Formatter, Result as FmtResult}; -use std::ops::Neg; -use std::result::Result as StdResult; -use std::str::{FromStr, from_utf8, from_utf8_unchecked}; +use bitflags::bitflags; +use std::{ + char::from_u32 as char_from_u32, + fmt::{Display, Formatter, Result as FmtResult}, + ops::Neg, + result::Result as StdResult, + str::{from_utf8, from_utf8_unchecked, FromStr}, +}; -use de::{Error, ParseError, Result}; +use crate::de::{Error, ParseError, Result}; -const DIGITS: &[u8] = b"0123456789ABCDEFabcdef"; +const DIGITS: &[u8] = b"0123456789ABCDEFabcdef_"; const FLOAT_CHARS: &[u8] = b"0123456789.+-eE"; const IDENT_FIRST: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; const IDENT_CHAR: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"; @@ -13,22 +17,36 @@ const WHITE_SPACE: &[u8] = b"\n\t\r "; #[derive(Clone, Copy, Debug)] pub struct Bytes<'a> { + /// Bits set according to `Extension` enum. + pub exts: Extensions, bytes: &'a [u8], column: usize, line: usize, } impl<'a> Bytes<'a> { - pub fn new(bytes: &'a [u8]) -> Self { + pub fn new(bytes: &'a [u8]) -> Result { let mut b = Bytes { bytes, column: 1, + exts: Extensions::empty(), line: 1, }; - b.skip_ws(); + b.skip_ws()?; + // Loop over all extensions attributes + loop { + let attribute = b.extensions()?; - b + if attribute.is_empty() { + break; + } + + b.exts |= attribute; + b.skip_ws()?; + } + + Ok(b) } pub fn advance(&mut self, bytes: usize) -> Result<()> { @@ -71,36 +89,52 @@ impl<'a> Bytes<'a> { return self.err(ParseError::ExpectedChar); } - let c = self.eat_byte()?; + let c = self.peek_or_eof()?; let c = if c == b'\\' { - let c = self.eat_byte()?; + let _ = self.advance(1); - if c != b'\\' && c != b'\'' { - return self.err(ParseError::InvalidEscape); + self.parse_escape()? + } else { + // Check where the end of the char (') is and try to + // interpret the rest as UTF-8 + + let max = self.bytes.len().min(5); + let pos: usize = self.bytes[..max] + .iter() + .position(|&x| x == b'\'') + .ok_or_else(|| self.error(ParseError::ExpectedChar))?; + let s = from_utf8(&self.bytes[0..pos]).map_err(|e| self.error(e.into()))?; + let mut chars = s.chars(); + + let first = chars + .next() + .ok_or_else(|| self.error(ParseError::ExpectedChar))?; + if chars.next().is_some() { + return self.err(ParseError::ExpectedChar); } - c - } else { - c + let _ = self.advance(pos); + + first }; if !self.consume("'") { return self.err(ParseError::ExpectedChar); } - Ok(c as char) + Ok(c) } - pub fn comma(&mut self) -> bool { - self.skip_ws(); + pub fn comma(&mut self) -> Result { + self.skip_ws()?; if self.consume(",") { - self.skip_ws(); + self.skip_ws()?; - true + Ok(true) } else { - false + Ok(false) } } @@ -111,7 +145,22 @@ impl<'a> Bytes<'a> { } fn check_ident_char(&self, index: usize) -> bool { - self.bytes.get(index).map(|b| IDENT_CHAR.contains(b)).unwrap_or(false) + self.bytes + .get(index) + .map_or(false, |b| IDENT_CHAR.contains(b)) + } + + /// Should only be used on a working copy + pub fn check_tuple_struct(mut self) -> Result { + if self.identifier().is_err() { + // if there's no field ident, this is a tuple struct + return Ok(true); + } + + self.skip_ws()?; + + // if there is no colon after the ident, this can only be a unit struct + self.eat_byte().map(|c| c != b':') } /// Only returns true if the char after `ident` cannot belong @@ -136,6 +185,20 @@ impl<'a> Bytes<'a> { } } + fn consume_all(&mut self, all: &[&str]) -> Result { + all.iter() + .map(|elem| { + if self.consume(elem) { + self.skip_ws()?; + + Ok(true) + } else { + Ok(false) + } + }) + .fold(Ok(true), |acc, x| acc.and_then(|val| x.map(|x| x && val))) + } + pub fn eat_byte(&mut self) -> Result { let peek = self.peek_or_eof()?; let _ = self.advance_single(); @@ -148,11 +211,71 @@ impl<'a> Bytes<'a> { } pub fn error(&self, kind: ParseError) -> Error { - Error::Parser(kind, Position { line: self.line, col: self.column }) + Error::Parser( + kind, + Position { + line: self.line, + col: self.column, + }, + ) + } + + pub fn expect_byte(&mut self, byte: u8, error: ParseError) -> Result<()> { + self.eat_byte().and_then(|b| match b == byte { + true => Ok(()), + false => self.err(error), + }) + } + + /// Returns the extensions bit mask. + fn extensions(&mut self) -> Result { + if self.peek() != Some(b'#') { + return Ok(Extensions::empty()); + } + + if !self.consume_all(&["#", "!", "[", "enable", "("])? { + return self.err(ParseError::ExpectedAttribute); + } + + self.skip_ws()?; + let mut extensions = Extensions::empty(); + + loop { + let ident = self.identifier()?; + let extension = Extensions::from_ident(ident).ok_or_else(|| { + self.error(ParseError::NoSuchExtension( + from_utf8(ident).unwrap().to_owned(), + )) + })?; + + extensions |= extension; + + let comma = self.comma()?; + + // If we have no comma but another item, return an error + if !comma && self.check_ident_char(0) { + return self.err(ParseError::ExpectedComma); + } + + // If there's no comma, assume the list ended. + // If there is, it might be a trailing one, thus we only + // continue the loop if we get an ident char. + if !comma || !self.check_ident_char(0) { + break; + } + } + + self.skip_ws()?; + + match self.consume_all(&[")", "]"])? { + true => Ok(extensions), + false => Err(self.error(ParseError::ExpectedAttributeEnd)), + } } pub fn float(&mut self) -> Result - where T: FromStr + where + T: FromStr, { let num_bytes = self.next_bytes_contained_in(FLOAT_CHARS); @@ -164,14 +287,32 @@ impl<'a> Bytes<'a> { res } - pub fn identifier(&mut self) -> Result<&[u8]> { - if IDENT_FIRST.contains(&self.peek_or_eof()?) { + pub fn identifier(&mut self) -> Result<&'a [u8]> { + let bytes = self.identifier_len()?; + let ident = &self.bytes[..bytes]; + let _ = self.advance(bytes); + + Ok(ident) + } + + pub fn identifier_len(&self) -> Result { + let next = self.peek_or_eof()?; + if IDENT_FIRST.contains(&next) { + // If the next two bytes signify the start of a raw string literal, + // return an error. + if next == b'r' { + let second = self + .bytes + .get(1) + .ok_or_else(|| self.error(ParseError::Eof))?; + if *second == b'"' || *second == b'#' { + return self.err(ParseError::ExpectedIdentifier); + } + } + let bytes = self.next_bytes_contained_in(IDENT_CHAR); - let ident = &self.bytes[..bytes]; - let _ = self.advance(bytes); - - Ok(ident) + Ok(bytes) } else { self.err(ParseError::ExpectedIdentifier) } @@ -181,29 +322,59 @@ impl<'a> Bytes<'a> { self.bytes .iter() .take_while(|b| allowed.contains(b)) - .fold(0, |acc, _| acc + 1) + .count() } - pub fn skip_ws(&mut self) { - while self.peek().map(|c| WHITE_SPACE.contains(&c)).unwrap_or(false) { + pub fn next_bytes_is_float(&self) -> bool { + if let Some(byte) = self.peek() { + let skip = match byte { + b'+' | b'-' => 1, + _ => 0, + }; + let flen = self + .bytes + .iter() + .skip(skip) + .take_while(|b| FLOAT_CHARS.contains(b)) + .count(); + let ilen = self + .bytes + .iter() + .skip(skip) + .take_while(|b| DIGITS.contains(b)) + .count(); + flen > ilen + } else { + false + } + } + + pub fn skip_ws(&mut self) -> Result<()> { + while self.peek().map_or(false, |c| WHITE_SPACE.contains(&c)) { let _ = self.advance_single(); } - if self.skip_comment() { - self.skip_ws(); + if self.skip_comment()? { + self.skip_ws()?; } + + Ok(()) } pub fn peek(&self) -> Option { - self.bytes.get(0).map(|b| *b) + self.bytes.get(0).cloned() } pub fn peek_or_eof(&self) -> Result { - self.bytes.get(0).map(|b| *b).ok_or(self.error(ParseError::Eof)) + self.bytes + .get(0) + .cloned() + .ok_or_else(|| self.error(ParseError::Eof)) } pub fn signed_integer(&mut self) -> Result - where T: Neg + Num, + where + T: Neg + Num, { match self.peek_or_eof()? { b'+' => { @@ -220,16 +391,25 @@ impl<'a> Bytes<'a> { } } - pub fn string(&mut self) -> Result { - if !self.consume("\"") { - return self.err(ParseError::ExpectedString); + pub fn string(&mut self) -> Result> { + if self.consume("\"") { + self.escaped_string() + } else if self.consume("r") { + self.raw_string() + } else { + self.err(ParseError::ExpectedString) } + } - let (i, end_or_escape) = self.bytes + fn escaped_string(&mut self) -> Result> { + use std::iter::repeat; + + let (i, end_or_escape) = self + .bytes .iter() .enumerate() .find(|&(_, &b)| b == b'\\' || b == b'"') - .ok_or(self.error(ParseError::ExpectedStringEnd))?; + .ok_or_else(|| self.error(ParseError::ExpectedStringEnd))?; if *end_or_escape == b'"' { let s = from_utf8(&self.bytes[..i]).map_err(|e| self.error(e.into()))?; @@ -245,9 +425,18 @@ impl<'a> Bytes<'a> { loop { let _ = self.advance(i + 1); - self.parse_str_escape(&mut s)?; + let character = self.parse_escape()?; + match character.len_utf8() { + 1 => s.push(character as u8), + len => { + let start = s.len(); + s.extend(repeat(0).take(len)); + character.encode_utf8(&mut s[start..]); + } + } - let (new_i, end_or_escape) = self.bytes + let (new_i, end_or_escape) = self + .bytes .iter() .enumerate() .find(|&(_, &b)| b == b'\\' || b == b'"') @@ -260,15 +449,42 @@ impl<'a> Bytes<'a> { if *end_or_escape == b'"' { let _ = self.advance(i + 1); - break Ok(ParsedStr::Allocated(String::from_utf8(s) - .map_err(|e| self.error(e.into()))?)); + let s = String::from_utf8(s).map_err(|e| self.error(e.into()))?; + break Ok(ParsedStr::Allocated(s)); } } } } + fn raw_string(&mut self) -> Result> { + let num_hashes = self.bytes.iter().take_while(|&&b| b == b'#').count(); + let hashes = &self.bytes[..num_hashes]; + let _ = self.advance(num_hashes); + + if !self.consume("\"") { + return self.err(ParseError::ExpectedString); + } + + let ending = [&[b'"'], hashes].concat(); + let i = self + .bytes + .windows(num_hashes + 1) + .position(|window| window == ending.as_slice()) + .ok_or_else(|| self.error(ParseError::ExpectedStringEnd))?; + + let s = from_utf8(&self.bytes[..i]).map_err(|e| self.error(e.into()))?; + + // Advance by the number of bytes of the string + // + `num_hashes` + 1 for the `"`. + let _ = self.advance(i + num_hashes + 1); + + Ok(ParsedStr::Slice(s)) + } + fn test_for(&self, s: &str) -> bool { - s.bytes().enumerate().all(|(i, b)| self.bytes.get(i).map(|t| *t == b).unwrap_or(false)) + s.bytes() + .enumerate() + .all(|(i, b)| self.bytes.get(i).map_or(false, |t| *t == b)) } pub fn unsigned_integer(&mut self) -> Result { @@ -292,110 +508,158 @@ impl<'a> Bytes<'a> { let num_bytes = self.next_bytes_contained_in(DIGITS); if num_bytes == 0 { - return self.err(ParseError::Eof); + return self.err(ParseError::ExpectedInteger); } - let res = Num::from_str(unsafe { from_utf8_unchecked(&self.bytes[0..num_bytes]) }, base) - .map_err(|_| self.error(ParseError::ExpectedInteger)); + let tmp; + let mut s = unsafe { from_utf8_unchecked(&self.bytes[0..num_bytes]) }; + + if s.as_bytes()[0] == b'_' { + return self.err(ParseError::UnderscoreAtBeginning); + } + + if s.contains('_') { + tmp = s.replace('_', ""); + s = &tmp; + } + + let res = Num::from_str(s, base).map_err(|_| self.error(ParseError::ExpectedInteger)); let _ = self.advance(num_bytes); res } - fn decode_hex_escape(&mut self) -> Result { + fn decode_ascii_escape(&mut self) -> Result { let mut n = 0; - for _ in 0..4 { - n = match self.eat_byte()? { - c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)), - b'a' | b'A' => n * 16_u16 + 10_u16, - b'b' | b'B' => n * 16_u16 + 11_u16, - b'c' | b'C' => n * 16_u16 + 12_u16, - b'd' | b'D' => n * 16_u16 + 13_u16, - b'e' | b'E' => n * 16_u16 + 14_u16, - b'f' | b'F' => n * 16_u16 + 15_u16, - _ => { - return self.err(ParseError::InvalidEscape); - } - }; + for _ in 0..2 { + n <<= 4; + let byte = self.eat_byte()?; + let decoded = self.decode_hex(byte)?; + n |= decoded; } Ok(n) } - fn parse_str_escape(&mut self, store: &mut Vec) -> Result<()> { - use std::iter::repeat; - - match self.eat_byte()? { - b'"' => store.push(b'"'), - b'\\' => store.push(b'\\'), - b'b' => store.push(b'\x08'), - b'f' => store.push(b'\x0c'), - b'n' => store.push(b'\n'), - b'r' => store.push(b'\r'), - b't' => store.push(b'\t'), - b'u' => { - let c: char = match self.decode_hex_escape()? { - 0xDC00 ... 0xDFFF => { - return self.err(ParseError::InvalidEscape); - } - - n1 @ 0xD800 ... 0xDBFF => { - if self.eat_byte()? != b'\\' { - return self.err(ParseError::InvalidEscape); - } - - if self.eat_byte()? != b'u' { - return self.err(ParseError::InvalidEscape); - } - - let n2 = self.decode_hex_escape()?; - - if n2 < 0xDC00 || n2 > 0xDFFF { - return self.err(ParseError::InvalidEscape); - } - - let n = (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000; - - match ::std::char::from_u32(n as u32) { - Some(c) => c, - None => { - return self.err(ParseError::InvalidEscape); - } - } - } - - n => { - match ::std::char::from_u32(n as u32) { - Some(c) => c, - None => { - return self.err(ParseError::InvalidEscape); - } - } - } - }; - - let char_start = store.len(); - store.extend(repeat(0).take(c.len_utf8())); - c.encode_utf8(&mut store[char_start..]); - } - _ => { - return self.err(ParseError::InvalidEscape); - } + fn decode_hex(&self, c: u8) -> Result { + match c { + c @ b'0'..=b'9' => Ok(c - b'0'), + c @ b'a'..=b'f' => Ok(10 + c - b'a'), + c @ b'A'..=b'F' => Ok(10 + c - b'A'), + _ => self.err(ParseError::InvalidEscape("Non-hex digit found")), } - - Ok(()) } - fn skip_comment(&mut self) -> bool { - if self.consume("//") { - let bytes = self.bytes.iter().take_while(|&&b| b != b'\n').count(); + fn parse_escape(&mut self) -> Result { + let c = match self.eat_byte()? { + b'\'' => '\'', + b'"' => '"', + b'\\' => '\\', + b'n' => '\n', + b'r' => '\r', + b't' => '\t', + b'x' => self.decode_ascii_escape()? as char, + b'u' => { + self.expect_byte(b'{', ParseError::InvalidEscape("Missing {"))?; - let _ = self.advance(bytes); + let mut bytes: u32 = 0; + let mut num_digits = 0; - true + while num_digits < 6 { + let byte = self.peek_or_eof()?; + + if byte == b'}' { + break; + } else { + self.advance_single()?; + } + + let byte = self.decode_hex(byte)?; + bytes <<= 4; + bytes |= byte as u32; + + num_digits += 1; + } + + if num_digits == 0 { + return self.err(ParseError::InvalidEscape( + "Expected 1-6 digits, got 0 digits", + )); + } + + self.expect_byte(b'}', ParseError::InvalidEscape("No } at the end"))?; + let character = char_from_u32(bytes) + .ok_or_else(|| self.error(ParseError::InvalidEscape("Not a valid char")))?; + character + } + _ => { + return self.err(ParseError::InvalidEscape("Unknown escape character")); + } + }; + + Ok(c) + } + + fn skip_comment(&mut self) -> Result { + if self.consume("/") { + match self.eat_byte()? { + b'/' => { + let bytes = self.bytes.iter().take_while(|&&b| b != b'\n').count(); + + let _ = self.advance(bytes); + } + b'*' => { + let mut level = 1; + + while level > 0 { + let bytes = self + .bytes + .iter() + .take_while(|&&b| b != b'/' && b != b'*') + .count(); + + if self.bytes.is_empty() { + return self.err(ParseError::UnclosedBlockComment); + } + + let _ = self.advance(bytes); + + // check whether / or * and take action + if self.consume("/*") { + level += 1; + } else if self.consume("*/") { + level -= 1; + } else { + self.eat_byte() + .map_err(|_| self.error(ParseError::UnclosedBlockComment))?; + } + } + } + b => return self.err(ParseError::UnexpectedByte(b as char)), + } + + Ok(true) } else { - false + Ok(false) + } + } +} + +bitflags! { + pub struct Extensions: usize { + const UNWRAP_NEWTYPES = 0x1; + const IMPLICIT_SOME = 0x2; + } +} + +impl Extensions { + /// Creates an extension flag from an ident. + pub fn from_ident(ident: &[u8]) -> Option { + match ident { + b"unwrap_newtypes" => Some(Extensions::UNWRAP_NEWTYPES), + b"implicit_some" => Some(Extensions::IMPLICIT_SOME), + _ => None, } } } @@ -432,7 +696,18 @@ pub struct Position { } impl Display for Position { - fn fmt(&self, f: &mut Formatter) -> FmtResult { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!(f, "{}:{}", self.line, self.col) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn decode_x10() { + let mut bytes = Bytes::new(b"10").unwrap(); + assert_eq!(bytes.decode_ascii_escape(), Ok(0x10)); + } +} diff --git a/third_party/rust/ron/src/ser/mod.rs b/third_party/rust/ron/src/ser/mod.rs index 7abd48901cd1..f2297350fbf5 100644 --- a/third_party/rust/ron/src/ser/mod.rs +++ b/third_party/rust/ron/src/ser/mod.rs @@ -1,24 +1,24 @@ -use std::error::Error as StdError; -use std::fmt::{Display, Formatter, Write, Result as FmtResult}; -use std::result::Result as StdResult; +use serde::{ser, Deserialize, Serialize}; +use std::{ + error::Error as StdError, + fmt::{Display, Formatter, Result as FmtResult, Write}, +}; -use serde::ser::{self, Serialize}; - -#[deprecated(since="0.1.4", note="please use `to_string_pretty` with `PrettyConfig::default()` instead")] -pub mod pretty; mod value; /// Serializes `value` and returns it as string. /// /// This function does not generate any newlines or nice formatting; -/// if you want that, you can use `pretty::to_string` instead. +/// if you want that, you can use `to_string_pretty` instead. pub fn to_string(value: &T) -> Result - where T: Serialize +where + T: Serialize, { let mut s = Serializer { output: String::new(), pretty: None, struct_names: false, + is_empty: None, }; value.serialize(&mut s)?; Ok(s.output) @@ -26,19 +26,27 @@ pub fn to_string(value: &T) -> Result /// Serializes `value` in the recommended RON layout in a pretty way. pub fn to_string_pretty(value: &T, config: PrettyConfig) -> Result - where T: Serialize +where + T: Serialize, { let mut s = Serializer { output: String::new(), - pretty: Some((config, Pretty { indent: 0, sequence_index: Vec::new() })), + pretty: Some(( + config, + Pretty { + indent: 0, + sequence_index: Vec::new(), + }, + )), struct_names: false, + is_empty: None, }; value.serialize(&mut s)?; Ok(s.output) } /// Serialization result. -pub type Result = StdResult; +pub type Result = std::result::Result; /// Serialization error. #[derive(Clone, Debug, PartialEq)] @@ -48,7 +56,7 @@ pub enum Error { } impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> FmtResult { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match *self { Error::Message(ref e) => write!(f, "Custom message: {}", e), } @@ -78,6 +86,8 @@ struct Pretty { /// Pretty serializer configuration #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PrettyConfig { + /// Limit the pretty-ness up to the given depth. + pub depth_limit: usize, /// New line string pub new_line: String, /// Indentation string @@ -91,6 +101,7 @@ pub struct PrettyConfig { impl Default for PrettyConfig { fn default() -> Self { PrettyConfig { + depth_limit: !0, #[cfg(not(target_os = "windows"))] new_line: "\n".to_string(), #[cfg(target_os = "windows")] @@ -110,6 +121,7 @@ pub struct Serializer { output: String, pretty: Option<(PrettyConfig, Pretty)>, struct_names: bool, + is_empty: Option, } impl Serializer { @@ -119,8 +131,17 @@ impl Serializer { pub fn new(config: Option, struct_names: bool) -> Self { Serializer { output: String::new(), - pretty: config.map(|conf| (conf, Pretty { indent: 0, sequence_index: Vec::new() })), + pretty: config.map(|conf| { + ( + conf, + Pretty { + indent: 0, + sequence_index: Vec::new(), + }, + ) + }), struct_names, + is_empty: None, } } @@ -129,44 +150,75 @@ impl Serializer { self.output } + fn is_pretty(&self) -> bool { + match self.pretty { + Some((ref config, ref pretty)) => pretty.indent < config.depth_limit, + None => false, + } + } + fn separate_tuple_members(&self) -> bool { - self.pretty.as_ref() - .map(|&(ref config, _)| config.separate_tuple_members) - .unwrap_or(false) + self.pretty + .as_ref() + .map_or(false, |&(ref config, _)| config.separate_tuple_members) } fn start_indent(&mut self) { if let Some((ref config, ref mut pretty)) = self.pretty { pretty.indent += 1; - self.output += &config.new_line; + if pretty.indent < config.depth_limit { + let is_empty = self.is_empty.unwrap_or(false); + + if !is_empty { + self.output += &config.new_line; + } + } } } fn indent(&mut self) { if let Some((ref config, ref pretty)) = self.pretty { - self.output.extend((0..pretty.indent).map(|_| config.indentor.as_str())); + if pretty.indent < config.depth_limit { + self.output + .extend((0..pretty.indent).map(|_| config.indentor.as_str())); + } } } fn end_indent(&mut self) { if let Some((ref config, ref mut pretty)) = self.pretty { + if pretty.indent < config.depth_limit { + let is_empty = self.is_empty.unwrap_or(false); + + if !is_empty { + self.output + .extend((1..pretty.indent).map(|_| config.indentor.as_str())); + } + } pretty.indent -= 1; - self.output.extend((0..pretty.indent).map(|_| config.indentor.as_str())); + + self.is_empty = None; } } + + fn serialize_escaped_str(&mut self, value: &str) { + let value = value.chars().flat_map(|c| c.escape_debug()); + self.output += "\""; + self.output.extend(value); + self.output += "\""; + } } impl<'a> ser::Serializer for &'a mut Serializer { - type Ok = (); type Error = Error; - + type Ok = (); + type SerializeMap = Self; type SerializeSeq = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; type SerializeTuple = Self; type SerializeTupleStruct = Self; type SerializeTupleVariant = Self; - type SerializeMap = Self; - type SerializeStruct = Self; - type SerializeStructVariant = Self; fn serialize_bool(self, v: bool) -> Result<()> { self.output += if v { "true" } else { "false" }; @@ -209,7 +261,8 @@ impl<'a> ser::Serializer for &'a mut Serializer { } fn serialize_f32(self, v: f32) -> Result<()> { - self.serialize_f64(v as f64) + self.output += &v.to_string(); + Ok(()) } fn serialize_f64(self, v: f64) -> Result<()> { @@ -228,25 +281,13 @@ impl<'a> ser::Serializer for &'a mut Serializer { } fn serialize_str(self, v: &str) -> Result<()> { - self.output += "\""; - for char in v.chars() { - if char == '\\' || char == '"' { - self.output.push('\\'); - } - self.output.push(char); - } - self.output += "\""; + self.serialize_escaped_str(v); + Ok(()) } fn serialize_bytes(self, v: &[u8]) -> Result<()> { - use serde::ser::SerializeSeq; - //TODO: shorter version? e.g. base64 encoding in a single line - let mut seq = self.serialize_seq(Some(v.len()))?; - for byte in v { - seq.serialize_element(byte)?; - } - seq.end() + self.serialize_str(base64::encode(v).as_str()) } fn serialize_none(self) -> Result<()> { @@ -256,7 +297,8 @@ impl<'a> ser::Serializer for &'a mut Serializer { } fn serialize_some(self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.output += "Some("; value.serialize(&mut *self)?; @@ -281,19 +323,15 @@ impl<'a> ser::Serializer for &'a mut Serializer { } } - fn serialize_unit_variant( - self, - _: &'static str, - _: u32, - variant: &'static str - ) -> Result<()> { + fn serialize_unit_variant(self, _: &'static str, _: u32, variant: &'static str) -> Result<()> { self.output += variant; Ok(()) } fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { if self.struct_names { self.output += name; @@ -310,9 +348,10 @@ impl<'a> ser::Serializer for &'a mut Serializer { _: &'static str, _: u32, variant: &'static str, - value: &T + value: &T, ) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.output += variant; self.output += "("; @@ -323,9 +362,13 @@ impl<'a> ser::Serializer for &'a mut Serializer { Ok(()) } - fn serialize_seq(self, _: Option) -> Result { + fn serialize_seq(self, len: Option) -> Result { self.output += "["; + if let Some(len) = len { + self.is_empty = Some(len == 0); + } + self.start_indent(); if let Some((_, ref mut pretty)) = self.pretty { @@ -335,10 +378,12 @@ impl<'a> ser::Serializer for &'a mut Serializer { Ok(self) } - fn serialize_tuple(self, _: usize) -> Result { + fn serialize_tuple(self, len: usize) -> Result { self.output += "("; if self.separate_tuple_members() { + self.is_empty = Some(len == 0); + self.start_indent(); } @@ -348,7 +393,7 @@ impl<'a> ser::Serializer for &'a mut Serializer { fn serialize_tuple_struct( self, name: &'static str, - len: usize + len: usize, ) -> Result { if self.struct_names { self.output += name; @@ -362,36 +407,39 @@ impl<'a> ser::Serializer for &'a mut Serializer { _: &'static str, _: u32, variant: &'static str, - _: usize + len: usize, ) -> Result { self.output += variant; self.output += "("; if self.separate_tuple_members() { + self.is_empty = Some(len == 0); + self.start_indent(); } Ok(self) } - fn serialize_map(self, _len: Option) -> Result { + fn serialize_map(self, len: Option) -> Result { self.output += "{"; + if let Some(len) = len { + self.is_empty = Some(len == 0); + } + self.start_indent(); Ok(self) } - fn serialize_struct( - self, - name: &'static str, - _: usize - ) -> Result { + fn serialize_struct(self, name: &'static str, len: usize) -> Result { if self.struct_names { self.output += name; } self.output += "("; + self.is_empty = Some(len == 0); self.start_indent(); Ok(self) @@ -402,11 +450,12 @@ impl<'a> ser::Serializer for &'a mut Serializer { _: &'static str, _: u32, variant: &'static str, - _: usize + len: usize, ) -> Result { self.output += variant; self.output += "("; + self.is_empty = Some(len == 0); self.start_indent(); Ok(self) @@ -414,11 +463,12 @@ impl<'a> ser::Serializer for &'a mut Serializer { } impl<'a> ser::SerializeSeq for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_element(&mut self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.indent(); @@ -426,15 +476,17 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer { self.output += ","; if let Some((ref config, ref mut pretty)) = self.pretty { - if config.enumerate_arrays { - assert!(config.new_line.contains('\n')); - let index = pretty.sequence_index.last_mut().unwrap(); - //TODO: when /**/ comments are supported, prepend the index - // to an element instead of appending it. - write!(self.output, "// [{}]", index).unwrap(); - *index += 1; + if pretty.indent < config.depth_limit { + if config.enumerate_arrays { + assert!(config.new_line.contains('\n')); + let index = pretty.sequence_index.last_mut().unwrap(); + //TODO: when /**/ comments are supported, prepend the index + // to an element instead of appending it. + write!(self.output, "// [{}]", index).unwrap(); + *index += 1; + } + self.output += &config.new_line; } - self.output += &config.new_line; } Ok(()) @@ -453,11 +505,12 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer { } impl<'a> ser::SerializeTuple for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_element(&mut self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { if self.separate_tuple_members() { self.indent(); @@ -466,21 +519,25 @@ impl<'a> ser::SerializeTuple for &'a mut Serializer { value.serialize(&mut **self)?; self.output += ","; - if let Some((ref config, _)) = self.pretty { - self.output += if self.separate_tuple_members() { &config.new_line } else { " " }; + if let Some((ref config, ref pretty)) = self.pretty { + if pretty.indent < config.depth_limit { + self.output += if self.separate_tuple_members() { + &config.new_line + } else { + " " + }; + } } Ok(()) } fn end(self) -> Result<()> { - if self.pretty.is_some() { - if self.separate_tuple_members() { - self.end_indent(); - } else { - self.output.pop(); - self.output.pop(); - } + if self.separate_tuple_members() { + self.end_indent(); + } else if self.is_pretty() { + self.output.pop(); + self.output.pop(); } self.output += ")"; @@ -491,11 +548,12 @@ impl<'a> ser::SerializeTuple for &'a mut Serializer { // Same thing but for tuple structs. impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_field(&mut self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { ser::SerializeTuple::serialize_element(self, value) } @@ -506,11 +564,12 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { } impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_field(&mut self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { ser::SerializeTuple::serialize_element(self, value) } @@ -521,11 +580,12 @@ impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { } impl<'a> ser::SerializeMap for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_key(&mut self, key: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.indent(); @@ -533,19 +593,22 @@ impl<'a> ser::SerializeMap for &'a mut Serializer { } fn serialize_value(&mut self, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.output += ":"; - if self.pretty.is_some() { + if self.is_pretty() { self.output += " "; } value.serialize(&mut **self)?; self.output += ","; - if let Some((ref config, _)) = self.pretty { - self.output += &config.new_line; + if let Some((ref config, ref pretty)) = self.pretty { + if pretty.indent < config.depth_limit { + self.output += &config.new_line; + } } Ok(()) @@ -560,26 +623,29 @@ impl<'a> ser::SerializeMap for &'a mut Serializer { } impl<'a> ser::SerializeStruct for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { self.indent(); self.output += key; self.output += ":"; - if self.pretty.is_some() { + if self.is_pretty() { self.output += " "; } value.serialize(&mut **self)?; self.output += ","; - if let Some((ref config, _)) = self.pretty { - self.output += &config.new_line; + if let Some((ref config, ref pretty)) = self.pretty { + if pretty.indent < config.depth_limit { + self.output += &config.new_line; + } } Ok(()) @@ -594,11 +660,12 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer { } impl<'a> ser::SerializeStructVariant for &'a mut Serializer { - type Ok = (); type Error = Error; + type Ok = (); fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where T: ?Sized + Serialize + where + T: ?Sized + Serialize, { ser::SerializeStruct::serialize_field(self, key, value) } @@ -619,14 +686,17 @@ mod tests { struct EmptyStruct2 {} #[derive(Serialize)] - struct MyStruct { x: f32, y: f32 } + struct MyStruct { + x: f32, + y: f32, + } #[derive(Serialize)] enum MyEnum { A, B(bool), C(bool, f32), - D { a: i32, b: i32 } + D { a: i32, b: i32 }, } #[test] @@ -641,7 +711,6 @@ mod tests { assert_eq!(to_string(&my_struct).unwrap(), "(x:4,y:7,)"); - #[derive(Serialize)] struct NewType(i32); @@ -707,4 +776,25 @@ mod tests { fn test_escape() { assert_eq!(to_string(&r#""Quoted""#).unwrap(), r#""\"Quoted\"""#); } + + #[test] + fn test_byte_stream() { + use serde_bytes; + + let small: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + assert_eq!( + to_string(&small).unwrap(), + "(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,)" + ); + + let large = vec![255u8; 64]; + let large = serde_bytes::Bytes::new(&large); + assert_eq!( + to_string(&large).unwrap(), + concat!( + "\"/////////////////////////////////////////", + "////////////////////////////////////////////w==\"" + ) + ); + } } diff --git a/third_party/rust/ron/src/ser/pretty.rs b/third_party/rust/ron/src/ser/pretty.rs deleted file mode 100644 index b4c273953cb3..000000000000 --- a/third_party/rust/ron/src/ser/pretty.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Provides default pretty serialization with `to_string`. - -use super::{Result, to_string_pretty}; - -use serde::ser::Serialize; -use std::default::Default; - -/// Serializes `value` in the recommended RON layout with -/// default pretty configuration. -pub fn to_string(value: &T) -> Result - where T: Serialize -{ - to_string_pretty(value, Default::default()) -} diff --git a/third_party/rust/ron/src/ser/value.rs b/third_party/rust/ron/src/ser/value.rs index f9aeb0ba9f4a..d3109ec3d037 100644 --- a/third_party/rust/ron/src/ser/value.rs +++ b/third_party/rust/ron/src/ser/value.rs @@ -1,11 +1,11 @@ use serde::ser::{Serialize, Serializer}; -use value::Value; +use crate::value::Value; impl Serialize for Value { fn serialize(&self, serializer: S) -> Result - where - S: Serializer + where + S: Serializer, { match *self { Value::Bool(b) => serializer.serialize_bool(b), diff --git a/third_party/rust/ron/src/value.rs b/third_party/rust/ron/src/value.rs index b2cec0933b1e..cebac85b0b0f 100644 --- a/third_party/rust/ron/src/value.rs +++ b/third_party/rust/ron/src/value.rs @@ -1,12 +1,18 @@ //! Value module. -use std::cmp::{Eq, Ordering}; -use std::collections::BTreeMap; -use std::hash::{Hash, Hasher}; +use serde::{ + de::{ + DeserializeOwned, DeserializeSeed, Deserializer, Error as SerdeError, MapAccess, SeqAccess, Visitor, + }, + forward_to_deserialize_any, +}; +use std::{ + cmp::{Eq, Ordering}, + collections::BTreeMap, + hash::{Hash, Hasher}, +}; -use serde::de::{DeserializeSeed, Deserializer, Error as SerdeErr, MapAccess, SeqAccess, Visitor}; - -use de::{Error as RonError, Result}; +use crate::de::{Error as RonError, Result}; /// A wrapper for `f64` which guarantees that the inner value /// is finite and thus implements `Eq`, `Hash` and `Ord`. @@ -25,7 +31,7 @@ impl Number { } /// Returns the wrapped float. - pub fn get(&self) -> f64 { + pub fn get(self) -> f64 { self.0 } } @@ -56,11 +62,27 @@ pub enum Value { Unit, } +impl Value { + /// Tries to deserialize this `Value` into `T`. + pub fn into_rust(self) -> Result + where + T: DeserializeOwned, + { + T::deserialize(self) + } +} + /// Deserializer implementation for RON `Value`. /// This does not support enums (because `Value` doesn't store them). impl<'de> Deserializer<'de> for Value { type Error = RonError; + forward_to_deserialize_any! { + bool f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } + fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, @@ -78,7 +100,6 @@ impl<'de> Deserializer<'de> for Value { Value::String(s) => visitor.visit_string(s), Value::Seq(mut seq) => { seq.reverse(); - visitor.visit_seq(Seq { seq }) } Value::Unit => visitor.visit_unit(), @@ -146,12 +167,6 @@ impl<'de> Deserializer<'de> for Value { v => Err(RonError::custom(format!("Expected a number, got {:?}", v))), } } - - forward_to_deserialize_any! { - bool f32 f64 char str string bytes - byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } } struct Map { @@ -204,15 +219,15 @@ impl<'de> SeqAccess<'de> for Seq { #[cfg(test)] mod tests { - use std::fmt::Debug; - use serde::Deserialize; use super::*; + use serde::Deserialize; + use std::fmt::Debug; fn assert_same<'de, T>(s: &'de str) where T: Debug + Deserialize<'de> + PartialEq, { - use de::from_str; + use crate::de::from_str; let direct: T = from_str(s).unwrap(); let value: Value = from_str(s).unwrap(); diff --git a/third_party/rust/ron/tests/147_empty_sets_serialisation.rs b/third_party/rust/ron/tests/147_empty_sets_serialisation.rs new file mode 100644 index 000000000000..bf679e56c953 --- /dev/null +++ b/third_party/rust/ron/tests/147_empty_sets_serialisation.rs @@ -0,0 +1,70 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct UnitStruct; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct NewType(f32); + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct TupleStruct(UnitStruct, i8); + +#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +struct Key(u32); + +#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +enum Enum { + Unit, + Bool(bool), + Chars(char, String), +} + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct Struct { + tuple: ((), NewType, TupleStruct), + vec: Vec>, + map: HashMap, + deep_vec: HashMap>, + deep_map: HashMap>, +} + +#[test] +fn empty_sets_arrays() { + let value = Struct { + tuple: ((), NewType(0.5), TupleStruct(UnitStruct, -5)), + vec: vec![], + map: vec![].into_iter().collect(), + deep_vec: vec![(Key(0), vec![])].into_iter().collect(), + deep_map: vec![(Key(0), vec![].into_iter().collect())] + .into_iter() + .collect(), + }; + + let pretty = ron::ser::PrettyConfig { + enumerate_arrays: true, + ..Default::default() + }; + let serial = ron::ser::to_string_pretty(&value, pretty).unwrap(); + + println!("Serialized: {}", serial); + + assert_eq!( + "( + tuple: ((), (0.5), ((), -5)), + vec: [], + map: {}, + deep_vec: { + (0): [], + }, + deep_map: { + (0): {}, + }, +)", + serial + ); + + let deserial = ron::de::from_str(&serial); + + assert_eq!(Ok(value), deserial); +} diff --git a/third_party/rust/ron/tests/big_struct.rs b/third_party/rust/ron/tests/big_struct.rs index 2497bd63d675..40583606f1fa 100644 --- a/third_party/rust/ron/tests/big_struct.rs +++ b/third_party/rust/ron/tests/big_struct.rs @@ -1,6 +1,4 @@ -extern crate ron; -#[macro_use] -extern crate serde; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct ImVec2 { @@ -39,8 +37,12 @@ pub struct ImGuiStyleSave { pub anti_aliased_shapes: bool, pub curve_tessellation_tol: f32, pub colors: ImColorsSave, + pub new_type: NewType, } +#[derive(Serialize, Deserialize)] +pub struct NewType(i32); + const CONFIG: &str = "( alpha: 1.0, window_padding: (x: 8, y: 8), @@ -66,6 +68,7 @@ const CONFIG: &str = "( anti_aliased_shapes: true, curve_tessellation_tol: 1.25, colors: (text: 4), + new_type: NewType( 1 ), ignored_field: \"Totally ignored, not causing a panic. Hopefully.\", )"; diff --git a/third_party/rust/ron/tests/comments.rs b/third_party/rust/ron/tests/comments.rs new file mode 100644 index 000000000000..d49ef73cd2ab --- /dev/null +++ b/third_party/rust/ron/tests/comments.rs @@ -0,0 +1,52 @@ +use ron::de::{from_str, Error as RonErr, ParseError, Position}; + +#[test] +fn test_simple() { + assert_eq!( + from_str( + "/* + * We got a hexadecimal number here! + * + */0x507" + ), + Ok(0x507) + ); +} + +#[test] +fn test_nested() { + assert_eq!( + from_str( + "/* + /* quite * some * nesting * going * on * /* here /* (yeah, maybe a bit too much) */ */ */ + */ + // The actual value comes.. /* + // very soon, these are just checks that */ + // multi-line comments don't trigger in line comments /* +\"THE VALUE\" /* This is the value /* :) */ */ + " + ), + Ok("THE VALUE".to_owned()) + ); +} + +#[test] +fn test_unclosed() { + assert_eq!( + from_str::( + "/* + /* quite * some * nesting * going * on * /* here /* (yeah, maybe a bit too much) */ */ */ + */ + // The actual value comes.. /* + // very soon, these are just checks that */ + // multi-line comments don't trigger in line comments /* +/* Unfortunately, this comment won't get closed :( +\"THE VALUE (which is invalid)\" +" + ), + Err(RonErr::Parser( + ParseError::UnclosedBlockComment, + Position { col: 1, line: 9 } + )) + ); +} diff --git a/third_party/rust/ron/tests/depth_limit.rs b/third_party/rust/ron/tests/depth_limit.rs new file mode 100644 index 000000000000..beacc02e3755 --- /dev/null +++ b/third_party/rust/ron/tests/depth_limit.rs @@ -0,0 +1,60 @@ +use serde::Serialize; +use std::collections::HashMap; + +#[derive(Serialize)] +struct Config { + float: (f32, f64), + tuple: TupleStruct, + map: HashMap, + nested: Nested, + var: Variant, + array: Vec<()>, +} + +#[derive(Serialize)] +struct TupleStruct((), bool); + +#[derive(Serialize)] +enum Variant { + A(u8, &'static str), +} + +#[derive(Serialize)] +struct Nested { + a: String, + b: char, +} + +const EXPECTED: &str = "( + float: (2.18,-1.1,), + tuple: ((),false,), + map: {8:'1',}, + nested: (a:\"a\",b:'b',), + var: A(255,\"\",), + array: [(),(),(),], +)"; + +#[test] +fn depth_limit() { + let data = Config { + float: (2.18, -1.1), + tuple: TupleStruct((), false), + map: vec![(8, '1')].into_iter().collect(), + nested: Nested { + a: "a".to_owned(), + b: 'b', + }, + var: Variant::A(!0, ""), + array: vec![(); 3], + }; + + let pretty = ron::ser::PrettyConfig { + depth_limit: 2, + separate_tuple_members: true, + enumerate_arrays: true, + ..Default::default() + }; + let s = ron::ser::to_string_pretty(&data, pretty); + + assert_eq!(s, Ok(EXPECTED.to_string())); +} diff --git a/third_party/rust/ron/tests/escape.rs b/third_party/rust/ron/tests/escape.rs new file mode 100644 index 000000000000..20cc87ee1eae --- /dev/null +++ b/third_party/rust/ron/tests/escape.rs @@ -0,0 +1,67 @@ +use ron::{de::from_str, ser::to_string}; +use serde::{Deserialize, Serialize}; +use std::{char::from_u32, fmt::Debug}; + +#[test] +fn test_escape_basic() { + assert_eq!(to_string(&"\x07").unwrap(), "\"\\u{7}\""); + + assert_eq!(from_str::("\"\\x07\"").unwrap(), "\x07"); + assert_eq!(from_str::("\"\\u{7}\"").unwrap(), "\x07"); +} + +fn check_same(t: T) +where + T: Debug + for<'a> Deserialize<'a> + PartialEq + Serialize, +{ + let s: String = to_string(&t).unwrap(); + + println!("Serialized: \n\n{}\n\n", s); + + assert_eq!(from_str(&s), Ok(t)); +} + +#[test] +fn test_ascii_10() { + check_same("\u{10}".to_owned()); +} + +#[test] +fn test_ascii_chars() { + (1..128).into_iter().flat_map(from_u32).for_each(check_same) +} + +#[test] +fn test_ascii_string() { + let s: String = (1..128).into_iter().flat_map(from_u32).collect(); + + check_same(s); +} + +#[test] +fn test_non_ascii() { + assert_eq!(to_string(&"♠").unwrap(), "\"♠\""); + assert_eq!(to_string(&"ß").unwrap(), "\"ß\""); + assert_eq!(to_string(&"ä").unwrap(), "\"ä\""); + assert_eq!(to_string(&"ö").unwrap(), "\"ö\""); + assert_eq!(to_string(&"ü").unwrap(), "\"ü\""); +} + +#[test] +fn test_chars() { + assert_eq!(to_string(&'♠').unwrap(), "'♠'"); + assert_eq!(to_string(&'ß').unwrap(), "'ß'"); + assert_eq!(to_string(&'ä').unwrap(), "'ä'"); + assert_eq!(to_string(&'ö').unwrap(), "'ö'"); + assert_eq!(to_string(&'ü').unwrap(), "'ü'"); + assert_eq!(to_string(&'\u{715}').unwrap(), "'\u{715}'"); + assert_eq!( + from_str::("'\u{715}'").unwrap(), + from_str("'\\u{715}'").unwrap() + ); +} + +#[test] +fn test_nul_in_string() { + check_same("Hello\0World!".to_owned()); +} diff --git a/third_party/rust/ron/tests/extensions.rs b/third_party/rust/ron/tests/extensions.rs new file mode 100644 index 000000000000..81157257ab4e --- /dev/null +++ b/third_party/rust/ron/tests/extensions.rs @@ -0,0 +1,81 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct UnitStruct; + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct NewType(f32); + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct TupleStruct(UnitStruct, i8); + +#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +struct Key(u32); + +#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +enum Enum { + Unit, + Bool(bool), + Chars(char, String), +} + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct Struct { + tuple: ((), NewType, TupleStruct), + vec: Vec>, + map: HashMap, +} + +const CONFIG_U_NT: &str = " +#![enable(unwrap_newtypes)] + +( + tuple: ((), 0.5, ((), -5)), + vec: [ + None, + Some(()), + ], + map: { + 7: Bool(true), + 9: Chars('x', \"\"), + 6: Bool(false), + 5: Unit, + }, +) +"; + +#[test] +fn unwrap_newtypes() { + let d: Struct = ron::de::from_str(&CONFIG_U_NT).expect("Failed to deserialize"); + + println!("unwrap_newtypes: {:#?}", d); +} + +const CONFIG_I_S: &str = " +#![enable(implicit_some)] + +( + tuple: ((), (0.5), ((), -5)), + vec: [ + None, + (), + UnitStruct, + None, + (), + ], + map: { + (7): Bool(true), + (9): Chars('x', \"\"), + (6): Bool(false), + (5): Unit, + }, +) +"; + +#[test] +fn implicit_some() { + let d: Struct = ron::de::from_str(&CONFIG_I_S).expect("Failed to deserialize"); + + println!("implicit_some: {:#?}", d); +} diff --git a/third_party/rust/ron/tests/numbers.rs b/third_party/rust/ron/tests/numbers.rs index b19ae9133ffd..26b97a53ded2 100644 --- a/third_party/rust/ron/tests/numbers.rs +++ b/third_party/rust/ron/tests/numbers.rs @@ -1,22 +1,22 @@ -extern crate ron; +use ron::de::from_str; #[test] fn test_hex() { - assert_eq!(ron::de::from_str("0x507"), Ok(0x507)); - assert_eq!(ron::de::from_str("0x1A5"), Ok(0x1A5)); - assert_eq!(ron::de::from_str("0x53C537"), Ok(0x53C537)); + assert_eq!(from_str("0x507"), Ok(0x507)); + assert_eq!(from_str("0x1A5"), Ok(0x1A5)); + assert_eq!(from_str("0x53C537"), Ok(0x53C537)); } #[test] fn test_bin() { - assert_eq!(ron::de::from_str("0b101"), Ok(0b101)); - assert_eq!(ron::de::from_str("0b001"), Ok(0b001)); - assert_eq!(ron::de::from_str("0b100100"), Ok(0b100100)); + assert_eq!(from_str("0b101"), Ok(0b101)); + assert_eq!(from_str("0b001"), Ok(0b001)); + assert_eq!(from_str("0b100100"), Ok(0b100100)); } #[test] fn test_oct() { - assert_eq!(ron::de::from_str("0o1461"), Ok(0o1461)); - assert_eq!(ron::de::from_str("0o051"), Ok(0o051)); - assert_eq!(ron::de::from_str("0o150700"), Ok(0o150700)); + assert_eq!(from_str("0o1461"), Ok(0o1461)); + assert_eq!(from_str("0o051"), Ok(0o051)); + assert_eq!(from_str("0o150700"), Ok(0o150700)); } diff --git a/third_party/rust/ron/tests/roundtrip.rs b/third_party/rust/ron/tests/roundtrip.rs index b1d8ea19302b..de12a5b2aa26 100644 --- a/third_party/rust/ron/tests/roundtrip.rs +++ b/third_party/rust/ron/tests/roundtrip.rs @@ -1,7 +1,4 @@ -extern crate ron; -#[macro_use] -extern crate serde; - +use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Debug, PartialEq, Deserialize, Serialize)] @@ -40,7 +37,9 @@ fn roundtrip() { (Key(6), Enum::Bool(false)), (Key(7), Enum::Bool(true)), (Key(9), Enum::Chars('x', "".to_string())), - ].into_iter().collect() + ] + .into_iter() + .collect(), }; let serial = ron::ser::to_string(&value).unwrap(); @@ -62,13 +61,60 @@ fn roundtrip_pretty() { (Key(6), Enum::Bool(false)), (Key(7), Enum::Bool(true)), (Key(9), Enum::Chars('x', "".to_string())), - ].into_iter() - .collect(), + ] + .into_iter() + .collect(), }; let pretty = ron::ser::PrettyConfig { enumerate_arrays: true, - .. Default::default() + ..Default::default() + }; + let serial = ron::ser::to_string_pretty(&value, pretty).unwrap(); + + println!("Serialized: {}", serial); + + let deserial = ron::de::from_str(&serial); + + assert_eq!(Ok(value), deserial); +} + +#[test] +fn roundtrip_sep_tuple_members() { + #[derive(Debug, Deserialize, PartialEq, Serialize)] + pub enum FileOrMem { + File(String), + Memory, + } + + #[derive(Debug, Deserialize, PartialEq, Serialize)] + struct Both { + a: Struct, + b: FileOrMem, + } + + let a = Struct { + tuple: ((), NewType(0.5), TupleStruct(UnitStruct, -5)), + vec: vec![None, Some(UnitStruct)], + map: vec![ + (Key(5), Enum::Unit), + (Key(6), Enum::Bool(false)), + (Key(7), Enum::Bool(true)), + (Key(9), Enum::Chars('x', "".to_string())), + ] + .into_iter() + .collect(), + }; + let b = FileOrMem::File("foo".to_owned()); + + let value = Both { a, b }; + + let pretty = ron::ser::PrettyConfig { + depth_limit: !0, + new_line: "\n".to_owned(), + indentor: " ".to_owned(), + separate_tuple_members: true, + enumerate_arrays: false, }; let serial = ron::ser::to_string_pretty(&value, pretty).unwrap(); diff --git a/third_party/rust/ron/tests/unicode.rs b/third_party/rust/ron/tests/unicode.rs new file mode 100644 index 000000000000..0617eeed14e9 --- /dev/null +++ b/third_party/rust/ron/tests/unicode.rs @@ -0,0 +1,13 @@ +use ron::de::from_str; + +#[test] +fn test_char() { + let de: char = from_str("'Փ'").unwrap(); + assert_eq!(de, 'Փ'); +} + +#[test] +fn test_string() { + let de: String = from_str("\"My string: ऄ\"").unwrap(); + assert_eq!(de, "My string: ऄ"); +} diff --git a/third_party/rust/ron/tests/value.rs b/third_party/rust/ron/tests/value.rs new file mode 100644 index 000000000000..6787dcbb554e --- /dev/null +++ b/third_party/rust/ron/tests/value.rs @@ -0,0 +1,115 @@ +use ron::value::{Number, Value}; +use serde::Serialize; +use std::collections::BTreeMap; + +#[test] +fn bool() { + assert_eq!(Value::from_str("true"), Ok(Value::Bool(true))); + assert_eq!(Value::from_str("false"), Ok(Value::Bool(false))); +} + +#[test] +fn char() { + assert_eq!(Value::from_str("'a'"), Ok(Value::Char('a'))); +} + +#[test] +fn map() { + let mut map = BTreeMap::new(); + map.insert(Value::Char('a'), Value::Number(Number::new(1f64))); + map.insert(Value::Char('b'), Value::Number(Number::new(2f64))); + assert_eq!(Value::from_str("{ 'a': 1, 'b': 2 }"), Ok(Value::Map(map))); +} + +#[test] +fn number() { + assert_eq!(Value::from_str("42"), Ok(Value::Number(Number::new(42f64)))); + assert_eq!( + Value::from_str("3.1415"), + Ok(Value::Number(Number::new(3.1415f64))) + ); +} + +#[test] +fn option() { + let opt = Some(Box::new(Value::Char('c'))); + assert_eq!(Value::from_str("Some('c')"), Ok(Value::Option(opt))); +} + +#[test] +fn string() { + let normal = "\"String\""; + assert_eq!(Value::from_str(normal), Ok(Value::String("String".into()))); + + let raw = "r\"Raw String\""; + assert_eq!(Value::from_str(raw), Ok(Value::String("Raw String".into()))); + + let raw_hashes = "r#\"Raw String\"#"; + assert_eq!( + Value::from_str(raw_hashes), + Ok(Value::String("Raw String".into())) + ); + + let raw_escaped = "r##\"Contains \"#\"##"; + assert_eq!( + Value::from_str(raw_escaped), + Ok(Value::String("Contains \"#".into())) + ); + + let raw_multi_line = "r\"Multi\nLine\""; + assert_eq!( + Value::from_str(raw_multi_line), + Ok(Value::String("Multi\nLine".into())) + ); +} + +#[test] +fn seq() { + let seq = vec![ + Value::Number(Number::new(1f64)), + Value::Number(Number::new(2f64)), + ]; + assert_eq!(Value::from_str("[1, 2]"), Ok(Value::Seq(seq))); +} + +#[test] +fn unit() { + use ron::de::{Error, ParseError, Position}; + + assert_eq!(Value::from_str("()"), Ok(Value::Unit)); + assert_eq!(Value::from_str("Foo"), Ok(Value::Unit)); + + assert_eq!( + Value::from_str(""), + Err(Error::Parser(ParseError::Eof, Position { col: 1, line: 1 })) + ); +} + +#[derive(Serialize)] +struct Scene(Option<(u32, u32)>); + +#[derive(Serialize)] +struct Scene2 { + foo: Option<(u32, u32)>, +} + +#[test] +fn roundtrip() { + use ron::{de::from_str, ser::to_string}; + + { + let s = to_string(&Scene2 { + foo: Some((122, 13)), + }) + .unwrap(); + println!("{}", s); + let scene: Value = from_str(&s).unwrap(); + println!("{:?}", scene); + } + { + let s = to_string(&Scene(Some((13, 122)))).unwrap(); + println!("{}", s); + let scene: Value = from_str(&s).unwrap(); + println!("{:?}", scene); + } +}