summaryrefslogtreecommitdiffstats
path: root/third_party/rust/derive_more
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/derive_more
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/derive_more')
-rw-r--r--third_party/rust/derive_more/.cargo-checksum.json1
-rw-r--r--third_party/rust/derive_more/CHANGELOG.md188
-rw-r--r--third_party/rust/derive_more/Cargo.lock63
-rw-r--r--third_party/rust/derive_more/Cargo.toml190
-rw-r--r--third_party/rust/derive_more/LICENSE21
-rw-r--r--third_party/rust/derive_more/README.md173
-rw-r--r--third_party/rust/derive_more/src/add_assign_like.rs41
-rw-r--r--third_party/rust/derive_more/src/add_helpers.rs28
-rw-r--r--third_party/rust/derive_more/src/add_like.rs146
-rw-r--r--third_party/rust/derive_more/src/as_mut.rs79
-rw-r--r--third_party/rust/derive_more/src/as_ref.rs79
-rw-r--r--third_party/rust/derive_more/src/constructor.rs49
-rw-r--r--third_party/rust/derive_more/src/deref.rs46
-rw-r--r--third_party/rust/derive_more/src/deref_mut.rs40
-rw-r--r--third_party/rust/derive_more/src/display.rs932
-rw-r--r--third_party/rust/derive_more/src/from.rs129
-rw-r--r--third_party/rust/derive_more/src/from_str.rs52
-rw-r--r--third_party/rust/derive_more/src/index.rs50
-rw-r--r--third_party/rust/derive_more/src/index_mut.rs49
-rw-r--r--third_party/rust/derive_more/src/into.rs58
-rw-r--r--third_party/rust/derive_more/src/into_iterator.rs59
-rw-r--r--third_party/rust/derive_more/src/lib.rs396
-rw-r--r--third_party/rust/derive_more/src/mul_assign_like.rs65
-rw-r--r--third_party/rust/derive_more/src/mul_helpers.rs36
-rw-r--r--third_party/rust/derive_more/src/mul_like.rs62
-rw-r--r--third_party/rust/derive_more/src/not_like.rs170
-rw-r--r--third_party/rust/derive_more/src/parsing.rs970
-rw-r--r--third_party/rust/derive_more/src/sum_like.rs60
-rw-r--r--third_party/rust/derive_more/src/try_into.rs120
-rw-r--r--third_party/rust/derive_more/src/utils.rs929
30 files changed, 5281 insertions, 0 deletions
diff --git a/third_party/rust/derive_more/.cargo-checksum.json b/third_party/rust/derive_more/.cargo-checksum.json
new file mode 100644
index 0000000000..a1075a1d19
--- /dev/null
+++ b/third_party/rust/derive_more/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"d2567aaf31209eed254c6245f9dbb7b1c8dbe96dc7c4eefc4e5e4e30f3fef16f","Cargo.lock":"524047afe2b1422b2841449d75d16d715e52a437b6ec8a0a5b6b0c340bf9ec79","Cargo.toml":"5a906a9bd1c9350f0af97c65936d2128f01d5640afab607e1c43629b75455ffc","LICENSE":"8a35369f3ca263b3c62fbb5032947e53b6bfebc6c8a4d1bb982de1c069f6fba5","README.md":"618e76cc65717577a15fa156f8ec4aba1c751b2098b61f42aac404eaf4e3ad29","src/add_assign_like.rs":"d71056331208161cfc985ca66425cb0b162381d64edbfaec39efeae77f5b5731","src/add_helpers.rs":"bbd4544b57091ac40bf0a6920fc85e0c90ce750bc4fc2bae3b7656808bc31324","src/add_like.rs":"130adfe79da699c10cc1c480036e84360eaac2aea1bd5667a2be51757803e14f","src/as_mut.rs":"1467c45a4e04c3c1138adcb04412a1e8e56615c9f8eea3ee5be28006f3bec598","src/as_ref.rs":"a018ce133009c19626d5913db947b913e3c834737c0242e2551f8de6be915929","src/constructor.rs":"c34f5eeaf51a3990fa783826ff1b2669a47e1876ce47eed6891a359db684d37d","src/deref.rs":"872145c99fa2850f4adc25169d455ee4e4cffab9e7bdec1495b0eb65c405504a","src/deref_mut.rs":"0272b00dcc59685673b79013ea4b50aa76291b95920987e5f445ac04825e5552","src/display.rs":"ff8502782100d3e3bc4c2dab718084a04457e101d8799e9e1f84f29ecc95ff6c","src/from.rs":"41e7cbbd908277bdb8586809c8f2cb740560e1c7b9a2bb2314d6ef43f0700190","src/from_str.rs":"077a09809bcb466ff801e1a6e75b034b8c46562e3b1665f068a313e1d2dabe95","src/index.rs":"64bdb5f51034b0e7d0962a6c4e7781453d08767d693adb7f474f638e2b9c6179","src/index_mut.rs":"035095e24b7a7c11fb6c4951e5fbb094e045435bbfe9fe36ebc78fe28e6cc802","src/into.rs":"89848fc814ace46b2f65649171e8aaedd805ec0d68150cc04eec811d095cbea3","src/into_iterator.rs":"1a89f60f635ed1f0dda2f740631ca564391cbc9cc20789d0be0f6181d80aaee5","src/lib.rs":"e032f313fd5e42d8cbd077bf38229b9015b3dc7e4e9a9fea8ee11eb5fd34ca2f","src/mul_assign_like.rs":"7f91514b34885304c846c9d41ce7b6519702ee3a6dfa3b0590069c3b1150e292","src/mul_helpers.rs":"7bb577b8866a87bafb8f79843d54416fb0e6eca6bbe22b1523c9eb7347f84b30","src/mul_like.rs":"25fdf3a26909a5f88ec392f00bcf7eeec247dd05a9c6307426383fac133a5e69","src/not_like.rs":"484a7d300a6a3306cb6423d706b570c4c9ca1bcdf26852556a6e7bbcfd51ad09","src/parsing.rs":"53190b5cd3302777b0f7cf4f9bdccb26e4b552598502c98109e5692c34cc21b8","src/sum_like.rs":"c566c6d94d92efb46396ac8673cceeb074e3dc7c1a234a388d40c0946567a2ef","src/try_into.rs":"23fd745717e7d3b60ba23ea985eefe2c460a3ff9ddd74f11ef752a4eaf52ed7c","src/utils.rs":"e044b9bc93245a6c3d4fc0b5663abb23c924d2ef1f8c823ae15364c145664077"},"package":"2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8"} \ No newline at end of file
diff --git a/third_party/rust/derive_more/CHANGELOG.md b/third_party/rust/derive_more/CHANGELOG.md
new file mode 100644
index 0000000000..8dd88f5098
--- /dev/null
+++ b/third_party/rust/derive_more/CHANGELOG.md
@@ -0,0 +1,188 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+## 0.99.2 - 2019-11-17
+
+### Fixes
+
+- Hotfix for a regression in allowed `Display` derives using `#` flag, such as
+ `{:#b}` ([#107](https://github.com/JelteF/derive_more/issues/105))
+
+## 0.99.1 - 2019-11-12
+
+### Fixes
+
+- Hotfix for a regression in allowed `From` derives
+ ([#105](https://github.com/JelteF/derive_more/issues/105))
+
+## 0.99.0 - 2019-11-11
+
+This release is a huge milestone for this library.
+Lot's of new derives are implemented and a ton of attributes are added for
+configuration purposes.
+These attributes will allow future releases to add features/options without
+breaking backwards compatibility.
+This is why the next release with breaking changes is planned to be 1.0.0.
+
+### Breaking changes
+
+- Requires Rust 1.36+
+- When using in a Rust 2015 crate, you should add `extern crate core` to your
+ code.
+- `no_std` feature is removed, the library now supports `no_std` without having
+ to configure any features.
+- `Deref` derives now dereference to the type in the newtype. So if you have
+ `MyBox(Box<i32>)`, dereferencing it will result in a `Box<i32>` not an `i32`.
+ To get the old behaviour of forwarding the dereference you can add the
+ `#[deref(forward)]` attribute on the struct or field.
+
+### New features
+
+- Derives for `AsRef`, `AsMut`, `Sum`, `Product`, `IntoIterator`.
+- Choosing the field of a struct for which to derive the newtype derive.
+- Ignoring variants of enums when deriving `From`, by using `#[from(ignore)]`.
+- Add `#[from(forward)]` attribute for `From` derives. This forwards the `from`
+ calls to the fields themselves. So if your field is an `i64` you can call from
+ on an `i32` and it will work.
+- Add `#[mul(forward)]` and `#[mul_assign(forward)]`, which implement `Mul` and
+ `MulAssign` with the semantics as if they were `Add`/`AddAssign`.
+- You can use features to cut down compile time of the crate by only compiling
+ the code needed for the derives that you use. (see Cargo.toml for the
+ features, by default they are all on)
+- Add `#[into(owned, ref, ref_mut)]` and `#[try_into(owned, ref, ref_mut)]`
+ attributes. These cause the `Into` and `TryInto` derives to also implement
+ derives that return references to the inner fields.
+- Make `no_std` work out of the box
+- Allow `#[display(fmt="some shared display text for all enum variants {}")]`
+ attribute on enum.
+- Better bounds inference of `Display` trait.
+
+### Other things
+
+- Remove dependency on `regex` to cut down compile time.
+- Use `syn` 1.0
+
+## 0.15.0 - 2019-06-08
+
+- Automatic detection of traits needed for `Display` format strings
+
+## 0.14.0 - 2019-02-02
+
+- Added `no_std` support
+- Suppress `unused_variables` warnings in derives
+
+## 0.13.0 - 2018-10-19
+
+- Updated to `syn` v0.15
+- Extended Display-like derives to support custom formats
+
+## 0.12.0 - 2018-09-19
+
+### Changed
+
+- Updated to `syn` v0.14, `quote` v0.6 and `proc-macro2` v0.4
+
+## 0.11.0 - 2018-05-12
+
+### Changed
+
+- Updated to latest version of `syn` and `quote`
+
+### Fixed
+
+- Changed some URLs in the docs so they were correct on crates.io and docs.rs
+- The `Result` type is now referenced in the derives using its absolute path
+ (`::std::result::Result`) to make sure that the derives don't accidentally use
+ another `Result` type that is in scope.
+
+## 0.10.0 - 2018-03-29
+
+### Added
+
+- Allow deriving of `TryInto`
+- Allow deriving of `Deref`
+- Allow deriving of `DerefMut`
+
+## 0.9.0 - 2018-03-18
+
+### Added
+
+- Allow deriving of `Display`, `Binary`, `Octal`, `LowerHex`, `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
+- Allow deriving of `Index`
+- Allow deriving of `IndexMut`
+
+### Fixed
+
+- Allow cross crate inlining of derived methods
+
+### Internal changes
+
+- Fix most `clippy` warnings
+
+## 0.8.0 - 2018-03-10
+
+### Added
+
+- Allow deriving of `FromStr`
+
+### Changed
+
+- Updated to latest version of `syn` and `quote`
+
+## 0.7.1 - 2018-01-25
+
+### Fixed
+
+- Add `#[allow(missing_docs)]` to the Constructor definition
+
+### Internal changes
+
+- Run `rustfmt` on the code
+
+## 0.7.0 - 2017-07-25
+
+### Changed
+
+- Changed code to work with newer version of the `syn` library.
+
+## 0.6.2 - 2017-04-23
+
+### Changed
+
+- Deriving `From`, `Into` and `Constructor` now works for empty structs.
+
+## 0.6.1 - 2017-03-08
+
+### Changed
+
+- The `new()` method that is created when deriving `Constructor` is now public.
+ This makes it a lot more useful.
+
+## 0.6.0 - 2017-02-20
+
+### Added
+
+- Derives for `Into`, `Constructor` and `MulAssign`-like
+
+### Changed
+
+- `From` is now derived for enum variants with multiple fields.
+
+### Fixed
+
+- Derivations now support generics.
+
+## 0.5.0 - 2017-02-02
+
+### Added
+
+- Lots of docs.
+- Derives for `Neg`-like and `AddAssign`-like.
+
+### Changed
+
+- `From` can now be derived for structs with multiple fields.
diff --git a/third_party/rust/derive_more/Cargo.lock b/third_party/rust/derive_more/Cargo.lock
new file mode 100644
index 0000000000..a6fcb562cd
--- /dev/null
+++ b/third_party/rust/derive_more/Cargo.lock
@@ -0,0 +1,63 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "derive_more"
+version = "0.99.2"
+dependencies = [
+ "peg 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "peg"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "quote"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum peg 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "40df12dde1d836ed2a4c3bfc2799797e3abaf807d97520d28d6e3f3bf41a5f85"
+"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum quote 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49d77c41ca8767f2f41394c11a4eebccab83da25e7cc035387a3125f02be90a3"
+"checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
diff --git a/third_party/rust/derive_more/Cargo.toml b/third_party/rust/derive_more/Cargo.toml
new file mode 100644
index 0000000000..1b9e5b4358
--- /dev/null
+++ b/third_party/rust/derive_more/Cargo.toml
@@ -0,0 +1,190 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "derive_more"
+version = "0.99.2"
+authors = ["Jelte Fennema <github-tech@jeltef.nl>"]
+include = ["src/**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md", "test/**/*.rs"]
+autotests = true
+description = "Adds #[derive(x)] macros for more traits"
+documentation = "https://jeltef.github.io/derive_more/derive_more/"
+readme = "README.md"
+keywords = ["derive", "Add", "From", "Display", "IntoIterator"]
+categories = ["development-tools", "development-tools::procedural-macro-helpers", "no-std"]
+license = "MIT"
+repository = "https://github.com/JelteF/derive_more"
+
+[lib]
+name = "derive_more"
+proc-macro = true
+
+[[example]]
+name = "deny_missing_docs"
+path = "examples/deny_missing_docs.rs"
+required-features = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "mul_assign", "mul", "not", "try_into"]
+
+[[test]]
+name = "add_assign"
+path = "tests/add_assign.rs"
+required-features = ["add_assign"]
+
+[[test]]
+name = "add"
+path = "tests/add.rs"
+required-features = ["add"]
+
+[[test]]
+name = "as_mut"
+path = "tests/as_mut.rs"
+required-features = ["as_mut"]
+
+[[test]]
+name = "as_ref"
+path = "tests/as_ref.rs"
+required-features = ["as_ref"]
+
+[[test]]
+name = "boats_display_derive"
+path = "tests/boats_display_derive.rs"
+required-features = ["display"]
+
+[[test]]
+name = "constructor"
+path = "tests/constructor.rs"
+required-features = ["constructor"]
+
+[[test]]
+name = "deref"
+path = "tests/deref.rs"
+required-features = ["deref"]
+
+[[test]]
+name = "deref_mut"
+path = "tests/deref_mut.rs"
+required-features = ["deref_mut"]
+
+[[test]]
+name = "display"
+path = "tests/display.rs"
+required-features = ["display"]
+
+[[test]]
+name = "from"
+path = "tests/from.rs"
+required-features = ["from"]
+
+[[test]]
+name = "from_str"
+path = "tests/from_str.rs"
+required-features = ["from_str"]
+
+[[test]]
+name = "index_mut"
+path = "tests/index_mut.rs"
+required-features = ["index_mut"]
+
+[[test]]
+name = "index"
+path = "tests/index.rs"
+required-features = ["index"]
+
+[[test]]
+name = "into"
+path = "tests/into.rs"
+required-features = ["into"]
+
+[[test]]
+name = "into_iterator"
+path = "tests/into_iterator.rs"
+required-features = ["into_iterator"]
+
+[[test]]
+name = "mul_assign"
+path = "tests/mul_assign.rs"
+required-features = ["mul_assign"]
+
+[[test]]
+name = "mul"
+path = "tests/mul.rs"
+required-features = ["mul"]
+
+[[test]]
+name = "not"
+path = "tests/not.rs"
+required-features = ["not"]
+
+[[test]]
+name = "sum"
+path = "tests/sum.rs"
+required-features = ["sum"]
+
+[[test]]
+name = "try_into"
+path = "tests/try_into.rs"
+required-features = ["try_into"]
+
+[[test]]
+name = "no_std"
+path = "tests/no_std.rs"
+required-features = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "mul_assign", "mul", "not", "sum", "try_into"]
+
+[[test]]
+name = "generics"
+path = "tests/generics.rs"
+required-features = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "mul_assign", "mul", "not", "try_into"]
+
+[[test]]
+name = "lib"
+path = "tests/lib.rs"
+required-features = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "mul_assign", "mul", "not", "try_into"]
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
+features = ["extra-traits"]
+[build-dependencies.peg]
+version = "0.5"
+optional = true
+
+[features]
+add = []
+add_assign = []
+as_mut = []
+as_ref = []
+constructor = []
+default = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "into_iterator", "iterator", "mul_assign", "mul", "not", "sum", "try_into"]
+deref = []
+deref_mut = []
+display = []
+from = []
+from_str = []
+generate-parsing-rs = ["peg"]
+index = []
+index_mut = []
+into = []
+into_iterator = []
+iterator = []
+mul = []
+mul_assign = []
+nightly = []
+not = []
+sum = []
+try_into = []
+[badges.github]
+repository = "JelteF/derive_more"
+workflow = "CI"
diff --git a/third_party/rust/derive_more/LICENSE b/third_party/rust/derive_more/LICENSE
new file mode 100644
index 0000000000..602cf050e2
--- /dev/null
+++ b/third_party/rust/derive_more/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Jelte Fennema
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust/derive_more/README.md b/third_party/rust/derive_more/README.md
new file mode 100644
index 0000000000..106f07cd7d
--- /dev/null
+++ b/third_party/rust/derive_more/README.md
@@ -0,0 +1,173 @@
+# `derive_more`
+
+[![Build Status](https://github.com/JelteF/derive_more/workflows/CI/badge.svg)](https://github.com/JelteF/derive_more/actions)
+[![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/)
+[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE)
+[![Rust 1.36+](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html)
+
+Rust has lots of builtin traits that are implemented for its basic types, such
+as `Add`, `Not`, `From` or `Display`.
+However, when wrapping these types inside your own structs or enums you lose the
+implementations of these traits and are required to recreate them.
+This is especially annoying when your own structures are very simple, such as
+when using the commonly advised newtype pattern (e.g. `MyInt(i32)`).
+
+This library tries to remove these annoyances and the corresponding boilerplate code.
+It does this by allowing you to derive lots of commonly used traits for both structs and enums.
+
+## Example code
+
+By using this library the following code just works:
+
+```rust
+extern crate derive_more;
+use derive_more::{Add, Display, From, Into};
+
+#[derive(PartialEq, From, Add)]
+struct MyInt(i32);
+
+#[derive(PartialEq, From, Into)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+
+#[derive(PartialEq, From, Add, Display)]
+enum MyEnum {
+ #[display(fmt = "int: {}", _0)]
+ Int(i32),
+ Uint(u32),
+ #[display(fmt = "nothing")]
+ Nothing,
+}
+
+assert!(MyInt(11) == MyInt(5) + 6.into());
+assert!((5, 6) == Point2D { x: 5, y: 6 }.into());
+assert!(MyEnum::Int(15) == (MyEnum::Int(8) + 7.into()).unwrap());
+assert!(MyEnum::Int(15).to_string() == "int: 15");
+assert!(MyEnum::Uint(42).to_string() == "42");
+assert!(MyEnum::Nothing.to_string() == "nothing");
+```
+
+## The derivable traits
+
+Below are all the traits that you can derive using this library.
+Some trait derivations are so similar that the further documentation will only show a single one
+of them.
+You can recognize these by the "-like" suffix in their name.
+The trait name before that will be the only one that is used throughout the further
+documentation.
+
+It is important to understand what code gets generated when using one of the
+derives from this crate.
+That is why the links below explain what code gets generated for a trait for
+each group from before.
+
+You can use the [`cargo-expand`] utility to see the exact code that is generated
+for your specific type.
+This will show you your code with all macros and derives expanded.
+
+**NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
+automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
+
+### Conversion traits
+
+These are traits that are used to convert automatically between types.
+
+1. [`From`]
+2. [`Into`]
+3. [`FromStr`]
+4. [`TryInto`]
+5. [`IntoIterator`]
+6. [`AsRef`]
+7. [`AsMut`]
+
+### Formatting traits
+
+These traits are used for converting a struct to a string in different ways.
+
+1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`,
+ `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
+
+### Operators
+
+These are traits that can be used for operator overloading.
+
+1. [`Index`]
+2. [`Deref`]
+3. [`Not`-like], contains `Not` and `Neg`
+4. [`Add`-like], contains `Add`, `Sub`, `BitAnd`, `BitOr`, `BitXor`, `MulSelf`,
+ `DivSelf`, `RemSelf`, `ShrSelf` and `ShlSelf`
+5. [`Mul`-like], contains `Mul`, `Div`, `Rem`, `Shr` and `Shl`
+3. [`Sum`-like], contains `Sum` and `Product`
+6. [`IndexMut`]
+7. [`DerefMut`]
+8. [`AddAssign`-like], contains `AddAssign`, `SubAssign`, `BitAndAssign`,
+ `BitOrAssign` and `BitXorAssign`
+9. [`MulAssign`-like], contains `MulAssign`, `DivAssign`, `RemAssign`,
+ `ShrAssign` and `ShlAssign`
+
+### Static methods
+
+These don't derive traits, but derive static methods instead.
+
+1. [`Constructor`], this derives a `new` method that can be used as a constructor.
+ This is very basic if you need more customization for your constructor, check
+ out the [`derive-new`] crate.
+
+## Generated code
+
+## Installation
+
+This library requires Rust 1.36 or higher and it supports `no_std` out of the box.
+Then add the following to `Cargo.toml`:
+
+```toml
+[dependencies]
+derive_more = "0.99.0"
+# You can specifiy the types of derives that you need for less time spent
+# compiling. For the full list of features see this crate its Cargo.toml.
+default-features = false
+features = ["from", "add", "iterator"]
+```
+
+And this to the top of your Rust file for Rust 2018:
+
+```rust
+extern crate derive_more;
+// use the derives that you want in the file
+use derive_more::{Add, Display, From};
+```
+If you're still using Rust 2015 you should add this instead:
+```rust
+extern crate core;
+#[macro_use]
+extern crate derive_more;
+```
+
+[`cargo-expand`]: https://github.com/dtolnay/cargo-expand
+[`derive-new`]: https://github.com/nrc/derive-new
+
+[`From`]: https://jeltef.github.io/derive_more/derive_more/from.html
+[`Into`]: https://jeltef.github.io/derive_more/derive_more/into.html
+[`FromStr`]: https://jeltef.github.io/derive_more/derive_more/from_str.html
+[`TryInto`]: https://jeltef.github.io/derive_more/derive_more/try_into.html
+[`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html
+[`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html
+[`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html
+
+[`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html
+
+[`Index`]: https://jeltef.github.io/derive_more/derive_more/index_op.html
+[`Deref`]: https://jeltef.github.io/derive_more/derive_more/deref.html
+[`Not`-like]: https://jeltef.github.io/derive_more/derive_more/not.html
+[`Add`-like]: https://jeltef.github.io/derive_more/derive_more/add.html
+[`Mul`-like]: https://jeltef.github.io/derive_more/derive_more/mul.html
+[`Sum`-like]: https://jeltef.github.io/derive_more/derive_more/sum.html
+[`IndexMut`]: https://jeltef.github.io/derive_more/derive_more/index_mut.html
+[`DerefMut`]: https://jeltef.github.io/derive_more/derive_more/deref_mut.html
+[`AddAssign`-like]: https://jeltef.github.io/derive_more/derive_more/add_assign.html
+[`MulAssign`-like]: https://jeltef.github.io/derive_more/derive_more/mul_assign.html
+
+[`Constructor`]: https://jeltef.github.io/derive_more/derive_more/constructor.html
diff --git a/third_party/rust/derive_more/src/add_assign_like.rs b/third_party/rust/derive_more/src/add_assign_like.rs
new file mode 100644
index 0000000000..e779fd8550
--- /dev/null
+++ b/third_party/rust/derive_more/src/add_assign_like.rs
@@ -0,0 +1,41 @@
+use crate::add_helpers::{struct_exprs, tuple_exprs};
+use crate::utils::{add_extra_ty_param_bound_op, named_to_vec, unnamed_to_vec};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{Data, DeriveInput, Fields, Ident};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_ident = Ident::new(trait_name, Span::call_site());
+ let method_name = trait_name.to_string();
+ let method_name = method_name.trim_end_matches("Assign");
+ let method_name = method_name.to_lowercase();
+ let method_ident = Ident::new(&(method_name + "_assign"), Span::call_site());
+ let input_type = &input.ident;
+
+ let generics = add_extra_ty_param_bound_op(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let exprs = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ tuple_exprs(&unnamed_to_vec(fields), &method_ident)
+ }
+ Fields::Named(ref fields) => {
+ struct_exprs(&named_to_vec(fields), &method_ident)
+ }
+ _ => panic!(format!("Unit structs cannot use derive({})", trait_name)),
+ },
+
+ _ => panic!(format!("Only structs can use derive({})", trait_name)),
+ };
+
+ quote!(
+ impl#impl_generics ::core::ops::#trait_ident for #input_type#ty_generics #where_clause {
+ #[inline]
+ fn #method_ident(&mut self, rhs: #input_type#ty_generics) {
+ #(#exprs;
+ )*
+ }
+ }
+ )
+}
diff --git a/third_party/rust/derive_more/src/add_helpers.rs b/third_party/rust/derive_more/src/add_helpers.rs
new file mode 100644
index 0000000000..34f3d2ad5d
--- /dev/null
+++ b/third_party/rust/derive_more/src/add_helpers.rs
@@ -0,0 +1,28 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Field, Ident, Index};
+
+pub fn tuple_exprs(fields: &[&Field], method_ident: &Ident) -> Vec<TokenStream> {
+ let mut exprs = vec![];
+
+ for i in 0..fields.len() {
+ let i = Index::from(i);
+ // generates `self.0.add(rhs.0)`
+ let expr = quote!(self.#i.#method_ident(rhs.#i));
+ exprs.push(expr);
+ }
+ exprs
+}
+
+pub fn struct_exprs(fields: &[&Field], method_ident: &Ident) -> Vec<TokenStream> {
+ let mut exprs = vec![];
+
+ for field in fields {
+ // It's safe to unwrap because struct fields always have an identifier
+ let field_id = field.ident.as_ref().unwrap();
+ // generates `x: self.x.add(rhs.x)`
+ let expr = quote!(self.#field_id.#method_ident(rhs.#field_id));
+ exprs.push(expr)
+ }
+ exprs
+}
diff --git a/third_party/rust/derive_more/src/add_like.rs b/third_party/rust/derive_more/src/add_like.rs
new file mode 100644
index 0000000000..8dd827de27
--- /dev/null
+++ b/third_party/rust/derive_more/src/add_like.rs
@@ -0,0 +1,146 @@
+use crate::add_helpers::{struct_exprs, tuple_exprs};
+use crate::utils::{
+ add_extra_type_param_bound_op_output, field_idents, named_to_vec, numbered_vars,
+ unnamed_to_vec,
+};
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, ToTokens};
+use std::iter;
+use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_name = trait_name.trim_end_matches("Self");
+ let trait_ident = Ident::new(trait_name, Span::call_site());
+ let method_name = trait_name.to_lowercase();
+ let method_ident = Ident::new(&method_name, Span::call_site());
+ let input_type = &input.ident;
+
+ let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let (output_type, block) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => (
+ quote!(#input_type#ty_generics),
+ tuple_content(input_type, &unnamed_to_vec(fields), &method_ident),
+ ),
+ Fields::Named(ref fields) => (
+ quote!(#input_type#ty_generics),
+ struct_content(input_type, &named_to_vec(fields), &method_ident),
+ ),
+ _ => panic!(format!("Unit structs cannot use derive({})", trait_name)),
+ },
+ Data::Enum(ref data_enum) => (
+ quote!(::core::result::Result<#input_type#ty_generics, &'static str>),
+ enum_content(input_type, data_enum, &method_ident),
+ ),
+
+ _ => panic!(format!(
+ "Only structs and enums can use derive({})",
+ trait_name
+ )),
+ };
+
+ quote!(
+ impl#impl_generics ::core::ops::#trait_ident for #input_type#ty_generics #where_clause {
+ type Output = #output_type;
+ #[inline]
+ fn #method_ident(self, rhs: #input_type#ty_generics) -> #output_type {
+ #block
+ }
+ }
+ )
+}
+
+fn tuple_content<T: ToTokens>(
+ input_type: &T,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let exprs = tuple_exprs(fields, method_ident);
+ quote!(#input_type(#(#exprs),*))
+}
+
+fn struct_content(
+ input_type: &Ident,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ // It's safe to unwrap because struct fields always have an identifier
+ let exprs = struct_exprs(fields, method_ident);
+ let field_names = field_idents(fields);
+
+ quote!(#input_type{#(#field_names: #exprs),*})
+}
+
+#[allow(clippy::cognitive_complexity)]
+fn enum_content(
+ input_type: &Ident,
+ data_enum: &DataEnum,
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut matches = vec![];
+ let mut method_iter = iter::repeat(method_ident);
+
+ for variant in &data_enum.variants {
+ let subtype = &variant.ident;
+ let subtype = quote!(#input_type::#subtype);
+
+ match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ // The patern that is outputted should look like this:
+ // (Subtype(left_vars), TypePath(right_vars)) => Ok(TypePath(exprs))
+ let size = unnamed_to_vec(fields).len();
+ let l_vars = &numbered_vars(size, "l_");
+ let r_vars = &numbered_vars(size, "r_");
+ let method_iter = method_iter.by_ref();
+ let matcher = quote! {
+ (#subtype(#(#l_vars),*),
+ #subtype(#(#r_vars),*)) => {
+ ::core::result::Result::Ok(#subtype(#(#l_vars.#method_iter(#r_vars)),*))
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Named(ref fields) => {
+ // The patern that is outputted should look like this:
+ // (Subtype{a: __l_a, ...}, Subtype{a: __r_a, ...} => {
+ // Ok(Subtype{a: __l_a.add(__r_a), ...})
+ // }
+ let field_vec = named_to_vec(fields);
+ let size = field_vec.len();
+ let field_names = &field_idents(&field_vec);
+ let l_vars = &numbered_vars(size, "l_");
+ let r_vars = &numbered_vars(size, "r_");
+ let method_iter = method_iter.by_ref();
+ let matcher = quote! {
+ (#subtype{#(#field_names: #l_vars),*},
+ #subtype{#(#field_names: #r_vars),*}) => {
+ ::core::result::Result::Ok(#subtype{#(#field_names: #l_vars.#method_iter(#r_vars)),*})
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Unit => {
+ let message =
+ format!("Cannot {}() unit variants", method_ident.to_string());
+ matches.push(quote!((#subtype, #subtype) => ::core::result::Result::Err(#message)));
+ }
+ }
+ }
+
+ if data_enum.variants.len() > 1 {
+ // In the strange case where there's only one enum variant this is would be an unreachable
+ // match.
+ let message = format!(
+ "Trying to {} mismatched enum variants",
+ method_ident.to_string()
+ );
+ matches.push(quote!(_ => ::core::result::Result::Err(#message)));
+ }
+ quote!(
+ match (self, rhs) {
+ #(#matches),*
+ }
+ )
+}
diff --git a/third_party/rust/derive_more/src/as_mut.rs b/third_party/rust/derive_more/src/as_mut.rs
new file mode 100644
index 0000000000..544407aef8
--- /dev/null
+++ b/third_party/rust/derive_more/src/as_mut.rs
@@ -0,0 +1,79 @@
+use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{parse::Result, DeriveInput, Ident};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let as_mut_type = &Ident::new("__AsMutT", Span::call_site());
+ let state = State::with_field_ignore_and_forward(
+ input,
+ trait_name,
+ quote!(::core::convert),
+ String::from("as_mut"),
+ )?;
+ let MultiFieldData {
+ fields,
+ input_type,
+ members,
+ infos,
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = state.enabled_fields_data();
+ let sub_items: Vec<_> = infos
+ .iter()
+ .zip(members.iter())
+ .zip(fields)
+ .map(|((info, member), field)| {
+ let field_type = &field.ty;
+ if info.forward {
+ let trait_path = quote!(#trait_path<#as_mut_type>);
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path
+ };
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ as_mut_type,
+ type_where_clauses,
+ false,
+ );
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let casted_trait = quote!(<#field_type as #trait_path>);
+ (
+ quote!(#casted_trait::as_mut(&mut #member)),
+ quote!(#impl_generics),
+ quote!(#where_clause),
+ quote!(#trait_path),
+ quote!(#as_mut_type),
+ )
+ } else {
+ (
+ quote!(&mut #member),
+ quote!(#impl_generics),
+ quote!(#where_clause),
+ quote!(#trait_path<#field_type>),
+ quote!(#field_type),
+ )
+ }
+ })
+ .collect();
+ let bodies = sub_items.iter().map(|i| &i.0);
+ let impl_genericses = sub_items.iter().map(|i| &i.1);
+ let where_clauses = sub_items.iter().map(|i| &i.2);
+ let trait_paths = sub_items.iter().map(|i| &i.3);
+ let return_types = sub_items.iter().map(|i| &i.4);
+
+ Ok(quote! {#(
+ impl#impl_genericses #trait_paths for #input_type#ty_generics
+ #where_clauses
+ {
+ #[inline]
+ fn as_mut(&mut self) -> &mut #return_types {
+ #bodies
+ }
+ }
+ )*})
+}
diff --git a/third_party/rust/derive_more/src/as_ref.rs b/third_party/rust/derive_more/src/as_ref.rs
new file mode 100644
index 0000000000..ed5bb34eea
--- /dev/null
+++ b/third_party/rust/derive_more/src/as_ref.rs
@@ -0,0 +1,79 @@
+use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{parse::Result, DeriveInput, Ident};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let as_ref_type = &Ident::new("__AsRefT", Span::call_site());
+ let state = State::with_field_ignore_and_forward(
+ input,
+ trait_name,
+ quote!(::core::convert),
+ String::from("as_ref"),
+ )?;
+ let MultiFieldData {
+ fields,
+ input_type,
+ members,
+ infos,
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = state.enabled_fields_data();
+ let sub_items: Vec<_> = infos
+ .iter()
+ .zip(members.iter())
+ .zip(fields)
+ .map(|((info, member), field)| {
+ let field_type = &field.ty;
+ if info.forward {
+ let trait_path = quote!(#trait_path<#as_ref_type>);
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path
+ };
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ as_ref_type,
+ type_where_clauses,
+ false,
+ );
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let casted_trait = quote!(<#field_type as #trait_path>);
+ (
+ quote!(#casted_trait::as_ref(&#member)),
+ quote!(#impl_generics),
+ quote!(#where_clause),
+ quote!(#trait_path),
+ quote!(#as_ref_type),
+ )
+ } else {
+ (
+ quote!(&#member),
+ quote!(#impl_generics),
+ quote!(#where_clause),
+ quote!(#trait_path<#field_type>),
+ quote!(#field_type),
+ )
+ }
+ })
+ .collect();
+ let bodies = sub_items.iter().map(|i| &i.0);
+ let impl_genericses = sub_items.iter().map(|i| &i.1);
+ let where_clauses = sub_items.iter().map(|i| &i.2);
+ let trait_paths = sub_items.iter().map(|i| &i.3);
+ let return_types = sub_items.iter().map(|i| &i.4);
+
+ Ok(quote! {#(
+ impl#impl_genericses #trait_paths for #input_type#ty_generics
+ #where_clauses
+ {
+ #[inline]
+ fn as_ref(&self) -> &#return_types {
+ #bodies
+ }
+ }
+ )*})
+}
diff --git a/third_party/rust/derive_more/src/constructor.rs b/third_party/rust/derive_more/src/constructor.rs
new file mode 100644
index 0000000000..14d488bfd4
--- /dev/null
+++ b/third_party/rust/derive_more/src/constructor.rs
@@ -0,0 +1,49 @@
+use crate::utils::{
+ field_idents, get_field_types, named_to_vec, numbered_vars, unnamed_to_vec,
+};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Data, DeriveInput, Field, Fields, Ident};
+
+/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor`
+pub fn expand(input: &DeriveInput, _: &str) -> TokenStream {
+ let input_type = &input.ident;
+ let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+ let ((body, vars), fields) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ let field_vec = unnamed_to_vec(fields);
+ (tuple_body(input_type, &field_vec), field_vec)
+ }
+ Fields::Named(ref fields) => {
+ let field_vec = named_to_vec(fields);
+ (struct_body(input_type, &field_vec), field_vec)
+ }
+ Fields::Unit => (struct_body(input_type, &[]), vec![]),
+ },
+ _ => panic!("Only structs can derive a constructor"),
+ };
+ let original_types = &get_field_types(&fields);
+ quote! {
+ #[allow(missing_docs)]
+ impl#impl_generics #input_type#ty_generics #where_clause {
+ #[inline]
+ pub fn new(#(#vars: #original_types),*) -> #input_type#ty_generics {
+ #body
+ }
+ }
+ }
+}
+
+fn tuple_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
+ let vars = &numbered_vars(fields.len(), "");
+ (quote!(#return_type(#(#vars),*)), vars.clone())
+}
+
+fn struct_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
+ let field_names: &Vec<Ident> =
+ &field_idents(fields).iter().map(|f| (**f).clone()).collect();
+ let vars = field_names;
+ let ret_vars = field_names.clone();
+ (quote!(#return_type{#(#field_names: #vars),*}), ret_vars)
+}
diff --git a/third_party/rust/derive_more/src/deref.rs b/third_party/rust/derive_more/src/deref.rs
new file mode 100644
index 0000000000..c7a8008cbd
--- /dev/null
+++ b/third_party/rust/derive_more/src/deref.rs
@@ -0,0 +1,46 @@
+use crate::utils::{SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(Deref)]` into an implementation of `Deref`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_field_ignore_and_forward(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ trait_name.to_lowercase(),
+ )?;
+ let SingleFieldData {
+ input_type,
+ field_type,
+ trait_path,
+ casted_trait,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ member,
+ info,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let (target, body) = if info.forward {
+ (
+ quote!(#casted_trait::Target),
+ quote!(#casted_trait::deref(&#member)),
+ )
+ } else {
+ (quote!(#field_type), quote!(&#member))
+ };
+
+ Ok(quote! {
+ impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
+ {
+ type Target = #target;
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ #body
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more/src/deref_mut.rs b/third_party/rust/derive_more/src/deref_mut.rs
new file mode 100644
index 0000000000..a64af3818f
--- /dev/null
+++ b/third_party/rust/derive_more/src/deref_mut.rs
@@ -0,0 +1,40 @@
+use crate::utils::{SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(DerefMut)]` into an implementation of `DerefMut`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_field_ignore_and_forward(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ String::from("deref_mut"),
+ )?;
+ let SingleFieldData {
+ input_type,
+ trait_path,
+ casted_trait,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ member,
+ info,
+ ..
+ } = state.assert_single_enabled_field();
+ let body = if info.forward {
+ quote!(#casted_trait::deref_mut(&mut #member))
+ } else {
+ quote!(&mut #member)
+ };
+
+ Ok(quote! {
+ impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
+ {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ #body
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more/src/display.rs b/third_party/rust/derive_more/src/display.rs
new file mode 100644
index 0000000000..d7f65b1a18
--- /dev/null
+++ b/third_party/rust/derive_more/src/display.rs
@@ -0,0 +1,932 @@
+use std::{
+ collections::{HashMap, HashSet},
+ fmt::Display,
+ iter::FromIterator as _,
+ ops::Deref as _,
+ str::FromStr as _,
+};
+
+use crate::utils::add_extra_where_clauses;
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::{quote, quote_spanned};
+use syn::{
+ parse::{Error, Parser as _, Result},
+ punctuated::Punctuated,
+ spanned::Spanned as _,
+};
+
+/// Provides the hook to expand `#[derive(Display)]` into an implementation of `Display`
+pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> Result<TokenStream> {
+ let trait_name = trait_name.trim_end_matches("Custom");
+ let trait_ident = syn::Ident::new(trait_name, Span::call_site());
+ let trait_path = &quote!(::core::fmt::#trait_ident);
+ let trait_attr = trait_name_to_attribute_name(trait_name);
+ let type_params = input
+ .generics
+ .type_params()
+ .map(|t| t.ident.clone())
+ .collect();
+
+ let ParseResult {
+ arms,
+ bounds,
+ requires_helper,
+ } = State {
+ trait_path,
+ trait_attr,
+ input,
+ type_params,
+ }
+ .get_match_arms_and_extra_bounds()?;
+
+ let generics = if !bounds.is_empty() {
+ let bounds: Vec<_> = bounds
+ .into_iter()
+ .map(|(ty, trait_names)| {
+ let bounds: Vec<_> = trait_names
+ .into_iter()
+ .map(|bound| quote!(#bound))
+ .collect();
+ quote!(#ty: #(#bounds)+*)
+ })
+ .collect();
+ let where_clause = quote_spanned!(input.span()=> where #(#bounds),*);
+ add_extra_where_clauses(&input.generics, where_clause)
+ } else {
+ input.generics.clone()
+ };
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let name = &input.ident;
+
+ let helper_struct = if requires_helper {
+ display_as_helper_struct()
+ } else {
+ TokenStream::new()
+ };
+
+ Ok(quote! {
+ impl #impl_generics #trait_path for #name #ty_generics #where_clause
+ {
+ #[allow(unused_variables)]
+ #[inline]
+ fn fmt(&self, _derive_more_display_formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #helper_struct
+
+ match self {
+ #arms
+ _ => Ok(()) // This is needed for empty enums
+ }
+ }
+ }
+ })
+}
+
+fn trait_name_to_attribute_name(trait_name: &str) -> &'static str {
+ match trait_name {
+ "Display" => "display",
+ "Binary" => "binary",
+ "Octal" => "octal",
+ "LowerHex" => "lower_hex",
+ "UpperHex" => "upper_hex",
+ "LowerExp" => "lower_exp",
+ "UpperExp" => "upper_exp",
+ "Pointer" => "pointer",
+ "Debug" => "debug",
+ _ => unimplemented!(),
+ }
+}
+
+fn attribute_name_to_trait_name(attribute_name: &str) -> &'static str {
+ match attribute_name {
+ "display" => "Display",
+ "binary" => "Binary",
+ "octal" => "Octal",
+ "lower_hex" => "LowerHex",
+ "upper_hex" => "UpperHex",
+ "lower_exp" => "LowerExp",
+ "upper_exp" => "UpperExp",
+ "pointer" => "Pointer",
+ _ => unreachable!(),
+ }
+}
+
+fn trait_name_to_trait_bound(trait_name: &str) -> syn::TraitBound {
+ let path_segments_iterator = vec!["core", "fmt", trait_name]
+ .into_iter()
+ .map(|segment| syn::PathSegment::from(Ident::new(segment, Span::call_site())));
+
+ syn::TraitBound {
+ lifetimes: None,
+ modifier: syn::TraitBoundModifier::None,
+ paren_token: None,
+ path: syn::Path {
+ leading_colon: Some(syn::Token![::](Span::call_site())),
+ segments: syn::punctuated::Punctuated::from_iter(path_segments_iterator),
+ },
+ }
+}
+
+/// Create a helper struct that is required by some `Display` impls.
+///
+/// The struct is necessary in cases where `Display` is derived for an enum
+/// with an outer `#[display(fmt = "...")]` attribute and if that outer
+/// format-string contains a single placeholder. In that case, we have to
+/// format twice:
+///
+/// - we need to format each variant according to its own, optional
+/// format-string,
+/// - we then need to insert this formatted variant into the outer
+/// format-string.
+///
+/// This helper struct solves this as follows:
+/// - formatting the whole object inserts the helper struct into the outer
+/// format string,
+/// - upon being formatted, the helper struct calls an inner closure to produce
+/// its formatted result,
+/// - the closure in turn uses the inner, optional format-string to produce its
+/// result. If there is no inner format-string, it falls back to plain
+/// `$trait::fmt()`.
+fn display_as_helper_struct() -> TokenStream {
+ quote! {
+ struct _derive_more_DisplayAs<F>(F)
+ where
+ F: ::core::ops::Fn(&mut ::core::fmt::Formatter) -> ::core::fmt::Result;
+
+ const _derive_more_DisplayAs_impl: () = {
+ impl<F> ::core::fmt::Display for _derive_more_DisplayAs<F>
+ where
+ F: ::core::ops::Fn(&mut ::core::fmt::Formatter) -> ::core::fmt::Result
+ {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ (self.0)(f)
+ }
+ }
+ };
+ }
+}
+
+/// Result type of `State::get_match_arms_and_extra_bounds()`.
+#[derive(Default)]
+struct ParseResult {
+ /// The match arms destructuring `self`.
+ arms: TokenStream,
+ /// Any trait bounds that may be required.
+ bounds: HashMap<syn::Type, HashSet<syn::TraitBound>>,
+ /// `true` if the Display impl requires the `DisplayAs` helper struct.
+ requires_helper: bool,
+}
+
+struct State<'a, 'b> {
+ trait_path: &'b TokenStream,
+ trait_attr: &'static str,
+ input: &'a syn::DeriveInput,
+ type_params: HashSet<Ident>,
+}
+
+impl<'a, 'b> State<'a, 'b> {
+ fn get_proper_fmt_syntax(&self) -> impl Display {
+ format!(
+ r#"Proper syntax: #[{}(fmt = "My format", "arg1", "arg2")]"#,
+ self.trait_attr
+ )
+ }
+ fn get_proper_bound_syntax(&self) -> impl Display {
+ format!(
+ "Proper syntax: #[{}(bound = \"T, U: Trait1 + Trait2, V: Trait3\")]",
+ self.trait_attr
+ )
+ }
+
+ fn get_matcher(&self, fields: &syn::Fields) -> TokenStream {
+ match fields {
+ syn::Fields::Unit => TokenStream::new(),
+ syn::Fields::Unnamed(fields) => {
+ let fields: TokenStream = (0..fields.unnamed.len())
+ .map(|n| {
+ let i = Ident::new(&format!("_{}", n), Span::call_site());
+ quote!(#i,)
+ })
+ .collect();
+ quote!((#fields))
+ }
+ syn::Fields::Named(fields) => {
+ let fields: TokenStream = fields
+ .named
+ .iter()
+ .map(|f| {
+ let i = f.ident.as_ref().unwrap();
+ quote!(#i,)
+ })
+ .collect();
+ quote!({#fields})
+ }
+ }
+ }
+ fn find_meta(
+ &self,
+ attrs: &[syn::Attribute],
+ meta_key: &str,
+ ) -> Result<Option<syn::Meta>> {
+ let mut iterator = attrs
+ .iter()
+ .filter_map(|attr| attr.parse_meta().ok())
+ .filter(|meta| {
+ let meta = match meta {
+ syn::Meta::List(meta) => meta,
+ _ => return false,
+ };
+
+ if !meta.path.is_ident(self.trait_attr) || meta.nested.is_empty() {
+ return false;
+ }
+
+ let meta = match &meta.nested[0] {
+ syn::NestedMeta::Meta(meta) => meta,
+ _ => return false,
+ };
+
+ let meta = match meta {
+ syn::Meta::NameValue(meta) => meta,
+ _ => return false,
+ };
+
+ meta.path.is_ident(meta_key)
+ });
+
+ let meta = iterator.next();
+ if iterator.next().is_none() {
+ Ok(meta)
+ } else {
+ Err(Error::new(meta.span(), "Too many attributes specified"))
+ }
+ }
+ fn parse_meta_bounds(
+ &self,
+ bounds: &syn::LitStr,
+ ) -> Result<HashMap<syn::Type, HashSet<syn::TraitBound>>> {
+ let span = bounds.span();
+
+ let input = bounds.value();
+ let tokens = TokenStream::from_str(&input)?;
+ let parser = Punctuated::<syn::GenericParam, syn::Token![,]>::parse_terminated;
+
+ let generic_params = parser
+ .parse2(tokens)
+ .map_err(|error| Error::new(span, error.to_string()))?;
+
+ if generic_params.is_empty() {
+ return Err(Error::new(span, "No bounds specified"));
+ }
+
+ let mut bounds = HashMap::new();
+
+ for generic_param in generic_params {
+ let type_param = match generic_param {
+ syn::GenericParam::Type(type_param) => type_param,
+ _ => return Err(Error::new(span, "Only trait bounds allowed")),
+ };
+
+ if !self.type_params.contains(&type_param.ident) {
+ return Err(Error::new(
+ span,
+ "Unknown generic type argument specified",
+ ));
+ } else if !type_param.attrs.is_empty() {
+ return Err(Error::new(span, "Attributes aren't allowed"));
+ } else if type_param.eq_token.is_some() || type_param.default.is_some() {
+ return Err(Error::new(span, "Default type parameters aren't allowed"));
+ }
+
+ let ident = type_param.ident.to_string();
+
+ let ty = syn::Type::Path(syn::TypePath {
+ qself: None,
+ path: type_param.ident.into(),
+ });
+ let bounds = bounds.entry(ty).or_insert_with(HashSet::new);
+
+ for bound in type_param.bounds {
+ let bound = match bound {
+ syn::TypeParamBound::Trait(bound) => bound,
+ _ => return Err(Error::new(span, "Only trait bounds allowed")),
+ };
+
+ if bound.lifetimes.is_some() {
+ return Err(Error::new(
+ span,
+ "Higher-rank trait bounds aren't allowed",
+ ));
+ }
+
+ bounds.insert(bound);
+ }
+
+ if bounds.is_empty() {
+ return Err(Error::new(
+ span,
+ format!("No bounds specified for type parameter {}", ident),
+ ));
+ }
+ }
+
+ Ok(bounds)
+ }
+ fn parse_meta_fmt(
+ &self,
+ meta: &syn::Meta,
+ outer_enum: bool,
+ ) -> Result<(TokenStream, bool)> {
+ let list = match meta {
+ syn::Meta::List(list) => list,
+ _ => {
+ return Err(Error::new(meta.span(), self.get_proper_fmt_syntax()));
+ }
+ };
+
+ match &list.nested[0] {
+ syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
+ path,
+ lit: syn::Lit::Str(fmt),
+ ..
+ })) => match path {
+ op if op.segments.first().expect("path shouldn't be empty").ident
+ == "fmt" =>
+ {
+ if outer_enum {
+ if list.nested.iter().skip(1).count() != 0 {
+ return Err(Error::new(
+ list.nested[1].span(),
+ "`fmt` formatting requires a single `fmt` argument",
+ ));
+ }
+ // TODO: Check for a single `Display` group?
+ let fmt_string = match &list.nested[0] {
+ syn::NestedMeta::Meta(syn::Meta::NameValue(
+ syn::MetaNameValue {
+ path,
+ lit: syn::Lit::Str(s),
+ ..
+ },
+ )) if path
+ .segments
+ .first()
+ .expect("path shouldn't be empty")
+ .ident
+ == "fmt" =>
+ {
+ s.value()
+ }
+ // This one has been checked already in get_meta_fmt() method.
+ _ => unreachable!(),
+ };
+
+ let num_placeholders =
+ Placeholder::parse_fmt_string(&fmt_string).len();
+ if num_placeholders > 1 {
+ return Err(Error::new(
+ list.nested[1].span(),
+ "fmt string for enum should have at at most 1 placeholder",
+ ));
+ }
+ if num_placeholders == 1 {
+ return Ok((quote_spanned!(fmt.span()=> #fmt), true));
+ }
+ }
+ let args = list
+ .nested
+ .iter()
+ .skip(1) // skip fmt = "..."
+ .try_fold(TokenStream::new(), |args, arg| {
+ let arg = match arg {
+ syn::NestedMeta::Lit(syn::Lit::Str(s)) => s,
+ syn::NestedMeta::Meta(syn::Meta::Path(i)) => {
+ return Ok(quote_spanned!(list.span()=> #args #i,));
+ }
+ _ => {
+ return Err(Error::new(
+ arg.span(),
+ self.get_proper_fmt_syntax(),
+ ))
+ }
+ };
+ let arg: TokenStream =
+ arg.parse().map_err(|e| Error::new(arg.span(), e))?;
+ Ok(quote_spanned!(list.span()=> #args #arg,))
+ })?;
+
+ Ok((
+ quote_spanned!(meta.span()=> write!(_derive_more_display_formatter, #fmt, #args)),
+ false,
+ ))
+ }
+ _ => Err(Error::new(
+ list.nested[0].span(),
+ self.get_proper_fmt_syntax(),
+ )),
+ },
+ _ => Err(Error::new(
+ list.nested[0].span(),
+ self.get_proper_fmt_syntax(),
+ )),
+ }
+ }
+ fn infer_fmt(&self, fields: &syn::Fields, name: &Ident) -> Result<TokenStream> {
+ let fields = match fields {
+ syn::Fields::Unit => {
+ return Ok(quote!(
+ _derive_more_display_formatter.write_str(stringify!(#name))
+ ))
+ }
+ syn::Fields::Named(fields) => &fields.named,
+ syn::Fields::Unnamed(fields) => &fields.unnamed,
+ };
+ if fields.is_empty() {
+ return Ok(quote!(
+ _derive_more_display_formatter.write_str(stringify!(#name))
+ ));
+ } else if fields.len() > 1 {
+ return Err(Error::new(
+ fields.span(),
+ "Can not automatically infer format for types with more than 1 field",
+ ));
+ }
+
+ let trait_path = self.trait_path;
+ if let Some(ident) = &fields.iter().next().as_ref().unwrap().ident {
+ Ok(quote!(#trait_path::fmt(#ident, _derive_more_display_formatter)))
+ } else {
+ Ok(quote!(#trait_path::fmt(_0, _derive_more_display_formatter)))
+ }
+ }
+ fn get_match_arms_and_extra_bounds(&self) -> Result<ParseResult> {
+ let result: Result<_> = match &self.input.data {
+ syn::Data::Enum(e) => {
+ match self
+ .find_meta(&self.input.attrs, "fmt")
+ .and_then(|m| m.map(|m| self.parse_meta_fmt(&m, true)).transpose())?
+ {
+ // #[display(fmt = "no placeholder")] on whole enum.
+ Some((fmt, false)) => {
+ e.variants.iter().try_for_each(|v| {
+ if let Some(meta) = self.find_meta(&v.attrs, "fmt")? {
+ Err(Error::new(
+ meta.span(),
+ "`fmt` cannot be used on variant when the whole enum has a format string without a placeholder, maybe you want to add a placeholder?",
+ ))
+ } else {
+ Ok(())
+ }
+ })?;
+
+ Ok(ParseResult {
+ arms: quote_spanned!(self.input.span()=> _ => #fmt,),
+ bounds: HashMap::new(),
+ requires_helper: false,
+ })
+ }
+ // #[display(fmt = "one placeholder: {}")] on whole enum.
+ Some((outer_fmt, true)) => {
+ let fmt: Result<TokenStream> = e.variants.iter().try_fold(TokenStream::new(), |arms, v| {
+ let matcher = self.get_matcher(&v.fields);
+ let fmt = if let Some(meta) = self.find_meta(&v.attrs, "fmt")? {
+ self.parse_meta_fmt(&meta, false)?.0
+ } else {
+ self.infer_fmt(&v.fields, &v.ident)?
+ };
+ let name = &self.input.ident;
+ let v_name = &v.ident;
+ Ok(quote_spanned!(fmt.span()=> #arms #name::#v_name #matcher => write!(
+ _derive_more_display_formatter,
+ #outer_fmt,
+ _derive_more_DisplayAs(|_derive_more_display_formatter| #fmt)
+ ),))
+ });
+ let fmt = fmt?;
+ Ok(ParseResult {
+ arms: quote_spanned!(self.input.span()=> #fmt),
+ bounds: HashMap::new(),
+ requires_helper: true,
+ })
+ }
+ // No format attribute on whole enum.
+ None => e.variants.iter().try_fold(ParseResult::default(), |result, v| {
+ let ParseResult{ arms, mut bounds, requires_helper } = result;
+ let matcher = self.get_matcher(&v.fields);
+ let name = &self.input.ident;
+ let v_name = &v.ident;
+ let fmt: TokenStream;
+ let these_bounds: HashMap<_, _>;
+
+ if let Some(meta) = self.find_meta(&v.attrs, "fmt")? {
+ fmt = self.parse_meta_fmt(&meta, false)?.0;
+ these_bounds = self.get_used_type_params_bounds(&v.fields, &meta);
+ } else {
+ fmt = self.infer_fmt(&v.fields, v_name)?;
+ these_bounds = self.infer_type_params_bounds(&v.fields);
+ };
+ these_bounds.into_iter().for_each(|(ty, trait_names)| {
+ bounds.entry(ty).or_default().extend(trait_names)
+ });
+ let arms = quote_spanned!(self.input.span()=> #arms #name::#v_name #matcher => #fmt,);
+
+ Ok(ParseResult{ arms, bounds, requires_helper })
+ }),
+ }
+ }
+ syn::Data::Struct(s) => {
+ let matcher = self.get_matcher(&s.fields);
+ let name = &self.input.ident;
+ let fmt: TokenStream;
+ let bounds: HashMap<_, _>;
+
+ if let Some(meta) = self.find_meta(&self.input.attrs, "fmt")? {
+ fmt = self.parse_meta_fmt(&meta, false)?.0;
+ bounds = self.get_used_type_params_bounds(&s.fields, &meta);
+ } else {
+ fmt = self.infer_fmt(&s.fields, name)?;
+ bounds = self.infer_type_params_bounds(&s.fields);
+ }
+
+ Ok(ParseResult {
+ arms: quote_spanned!(self.input.span()=> #name #matcher => #fmt,),
+ bounds,
+ requires_helper: false,
+ })
+ }
+ syn::Data::Union(_) => {
+ let meta =
+ self.find_meta(&self.input.attrs, "fmt")?.ok_or_else(|| {
+ Error::new(
+ self.input.span(),
+ "Can not automatically infer format for unions",
+ )
+ })?;
+ let fmt = self.parse_meta_fmt(&meta, false)?.0;
+
+ Ok(ParseResult {
+ arms: quote_spanned!(self.input.span()=> _ => #fmt,),
+ bounds: HashMap::new(),
+ requires_helper: false,
+ })
+ }
+ };
+
+ let mut result = result?;
+
+ let meta = match self.find_meta(&self.input.attrs, "bound")? {
+ Some(meta) => meta,
+ _ => return Ok(result),
+ };
+
+ let span = meta.span();
+
+ let meta = match meta {
+ syn::Meta::List(meta) => meta.nested,
+ _ => return Err(Error::new(span, self.get_proper_bound_syntax())),
+ };
+
+ if meta.len() != 1 {
+ return Err(Error::new(span, self.get_proper_bound_syntax()));
+ }
+
+ let meta = match &meta[0] {
+ syn::NestedMeta::Meta(syn::Meta::NameValue(meta)) => meta,
+ _ => return Err(Error::new(span, self.get_proper_bound_syntax())),
+ };
+
+ let extra_bounds = match &meta.lit {
+ syn::Lit::Str(extra_bounds) => extra_bounds,
+ _ => return Err(Error::new(span, self.get_proper_bound_syntax())),
+ };
+
+ let extra_bounds = self.parse_meta_bounds(extra_bounds)?;
+
+ extra_bounds.into_iter().for_each(|(ty, trait_names)| {
+ result.bounds.entry(ty).or_default().extend(trait_names)
+ });
+
+ Ok(result)
+ }
+ fn get_used_type_params_bounds(
+ &self,
+ fields: &syn::Fields,
+ meta: &syn::Meta,
+ ) -> HashMap<syn::Type, HashSet<syn::TraitBound>> {
+ if self.type_params.is_empty() {
+ return HashMap::new();
+ }
+
+ let fields_type_params: HashMap<syn::Path, _> = fields
+ .iter()
+ .enumerate()
+ .filter_map(|(i, field)| {
+ self.get_type_param(&field.ty).map(|ty| {
+ (
+ field
+ .ident
+ .clone()
+ .unwrap_or_else(|| {
+ Ident::new(&format!("_{}", i), Span::call_site())
+ })
+ .into(),
+ ty,
+ )
+ })
+ })
+ .collect();
+ if fields_type_params.is_empty() {
+ return HashMap::new();
+ }
+
+ let list = match meta {
+ syn::Meta::List(list) => list,
+ // This one has been checked already in get_meta_fmt() method.
+ _ => unreachable!(),
+ };
+ let fmt_args: HashMap<_, _> = list
+ .nested
+ .iter()
+ .skip(1) // skip fmt = "..."
+ .enumerate()
+ .filter_map(|(i, arg)| match arg {
+ syn::NestedMeta::Lit(syn::Lit::Str(ref s)) => {
+ syn::parse_str(&s.value()).ok().map(|id| (i, id))
+ }
+ syn::NestedMeta::Meta(syn::Meta::Path(ref id)) => Some((i, id.clone())),
+ // This one has been checked already in get_meta_fmt() method.
+ _ => unreachable!(),
+ })
+ .collect();
+ if fmt_args.is_empty() {
+ return HashMap::new();
+ }
+ let fmt_string = match &list.nested[0] {
+ syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
+ path,
+ lit: syn::Lit::Str(s),
+ ..
+ })) if path
+ .segments
+ .first()
+ .expect("path shouldn't be empty")
+ .ident
+ == "fmt" =>
+ {
+ s.value()
+ }
+ // This one has been checked already in get_meta_fmt() method.
+ _ => unreachable!(),
+ };
+
+ Placeholder::parse_fmt_string(&fmt_string).into_iter().fold(
+ HashMap::new(),
+ |mut bounds, pl| {
+ if let Some(arg) = fmt_args.get(&pl.position) {
+ if fields_type_params.contains_key(arg) {
+ bounds
+ .entry(fields_type_params[arg].clone())
+ .or_insert_with(HashSet::new)
+ .insert(trait_name_to_trait_bound(pl.trait_name));
+ }
+ }
+ bounds
+ },
+ )
+ }
+ fn infer_type_params_bounds(
+ &self,
+ fields: &syn::Fields,
+ ) -> HashMap<syn::Type, HashSet<syn::TraitBound>> {
+ if self.type_params.is_empty() {
+ return HashMap::new();
+ }
+ if let syn::Fields::Unit = fields {
+ return HashMap::new();
+ }
+ // infer_fmt() uses only first field.
+ fields
+ .iter()
+ .take(1)
+ .filter_map(|field| {
+ self.get_type_param(&field.ty).map(|ty| {
+ (
+ ty,
+ [trait_name_to_trait_bound(attribute_name_to_trait_name(
+ self.trait_attr,
+ ))]
+ .iter()
+ .cloned()
+ .collect(),
+ )
+ })
+ })
+ .collect()
+ }
+ fn get_type_param(&self, ty: &syn::Type) -> Option<syn::Type> {
+ if self.has_type_param_in(ty) {
+ match ty {
+ syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => {
+ Some(ty.deref().clone())
+ }
+ ty => Some(ty.clone()),
+ }
+ } else {
+ None
+ }
+ }
+ fn has_type_param_in(&self, ty: &syn::Type) -> bool {
+ match ty {
+ syn::Type::Path(ty) => {
+ if let Some(qself) = &ty.qself {
+ if self.has_type_param_in(&qself.ty) {
+ return true;
+ }
+ }
+
+ if let Some(segment) = ty.path.segments.first() {
+ if self.type_params.contains(&segment.ident) {
+ return true;
+ }
+ }
+
+ ty.path.segments.iter().any(|segment| {
+ if let syn::PathArguments::AngleBracketed(arguments) =
+ &segment.arguments
+ {
+ arguments.args.iter().any(|argument| match argument {
+ syn::GenericArgument::Type(ty) => {
+ self.has_type_param_in(ty)
+ }
+ syn::GenericArgument::Constraint(constraint) => {
+ self.type_params.contains(&constraint.ident)
+ }
+ _ => false,
+ })
+ } else {
+ false
+ }
+ })
+ }
+
+ syn::Type::Reference(ty) => self.has_type_param_in(&ty.elem),
+
+ _ => false,
+ }
+ }
+}
+
+/// Representation of formatting placeholder.
+#[derive(Debug, PartialEq)]
+struct Placeholder {
+ /// Position of formatting argument to be used for this placeholder.
+ position: usize,
+ /// Name of [`std::fmt`] trait to be used for rendering this placeholder.
+ trait_name: &'static str,
+}
+
+impl Placeholder {
+ /// Parses [`Placeholder`]s from a given formatting string.
+ fn parse_fmt_string(s: &str) -> Vec<Placeholder> {
+ let mut n = 0;
+ crate::parsing::all_placeholders(s)
+ .into_iter()
+ .flatten()
+ .map(|m| {
+ let (maybe_arg, maybe_typ) = crate::parsing::format(m).unwrap();
+ let position = maybe_arg.unwrap_or_else(|| {
+ // Assign "the next argument".
+ // https://doc.rust-lang.org/stable/std/fmt/index.html#positional-parameters
+ n += 1;
+ n - 1
+ });
+ let typ = maybe_typ.unwrap_or_default();
+ let trait_name = match typ {
+ "" => "Display",
+ "?" | "x?" | "X?" => "Debug",
+ "o" => "Octal",
+ "x" => "LowerHex",
+ "X" => "UpperHex",
+ "p" => "Pointer",
+ "b" => "Binary",
+ "e" => "LowerExp",
+ "E" => "UpperExp",
+ _ => unreachable!(),
+ };
+ Placeholder {
+ position,
+ trait_name,
+ }
+ })
+ .collect()
+ }
+}
+
+#[cfg(test)]
+mod regex_maybe_placeholder_spec {
+
+ #[test]
+ fn parses_placeholders_and_omits_escaped() {
+ let fmt_string = "{}, {:?}, {{}}, {{{1:0$}}}";
+ let placeholders: Vec<_> = crate::parsing::all_placeholders(&fmt_string)
+ .into_iter()
+ .flat_map(|x| x)
+ .collect();
+ assert_eq!(placeholders, vec!["{}", "{:?}", "{1:0$}"]);
+ }
+}
+
+#[cfg(test)]
+mod regex_placeholder_format_spec {
+
+ #[test]
+ fn detects_type() {
+ for (p, expected) in vec![
+ ("{}", ""),
+ ("{:?}", "?"),
+ ("{:x?}", "x?"),
+ ("{:X?}", "X?"),
+ ("{:o}", "o"),
+ ("{:x}", "x"),
+ ("{:X}", "X"),
+ ("{:p}", "p"),
+ ("{:b}", "b"),
+ ("{:e}", "e"),
+ ("{:E}", "E"),
+ ("{:.*}", ""),
+ ("{8}", ""),
+ ("{:04}", ""),
+ ("{1:0$}", ""),
+ ("{:width$}", ""),
+ ("{9:>8.*}", ""),
+ ("{2:.1$x}", "x"),
+ ] {
+ let typ = crate::parsing::format(p).unwrap().1.unwrap_or_default();
+ assert_eq!(typ, expected);
+ }
+ }
+
+ #[test]
+ fn detects_arg() {
+ for (p, expected) in vec![
+ ("{}", ""),
+ ("{0:?}", "0"),
+ ("{12:x?}", "12"),
+ ("{3:X?}", "3"),
+ ("{5:o}", "5"),
+ ("{6:x}", "6"),
+ ("{:X}", ""),
+ ("{8}", "8"),
+ ("{:04}", ""),
+ ("{1:0$}", "1"),
+ ("{:width$}", ""),
+ ("{9:>8.*}", "9"),
+ ("{2:.1$x}", "2"),
+ ] {
+ let arg = crate::parsing::format(p)
+ .unwrap()
+ .0
+ .map(|s| s.to_string())
+ .unwrap_or_default();
+ assert_eq!(arg, String::from(expected));
+ }
+ }
+}
+
+#[cfg(test)]
+mod placeholder_parse_fmt_string_spec {
+ use super::*;
+
+ #[test]
+ fn indicates_position_and_trait_name_for_each_fmt_placeholder() {
+ let fmt_string = "{},{:?},{{}},{{{1:0$}}}-{2:.1$x}{0:#?}{:width$}";
+ assert_eq!(
+ Placeholder::parse_fmt_string(&fmt_string),
+ vec![
+ Placeholder {
+ position: 0,
+ trait_name: "Display",
+ },
+ Placeholder {
+ position: 1,
+ trait_name: "Debug",
+ },
+ Placeholder {
+ position: 1,
+ trait_name: "Display",
+ },
+ Placeholder {
+ position: 2,
+ trait_name: "LowerHex",
+ },
+ Placeholder {
+ position: 0,
+ trait_name: "Debug",
+ },
+ Placeholder {
+ position: 2,
+ trait_name: "Display",
+ },
+ ],
+ )
+ }
+}
diff --git a/third_party/rust/derive_more/src/from.rs b/third_party/rust/derive_more/src/from.rs
new file mode 100644
index 0000000000..84cf619e3d
--- /dev/null
+++ b/third_party/rust/derive_more/src/from.rs
@@ -0,0 +1,129 @@
+use crate::utils::{
+ add_where_clauses_for_new_ident, AttrParams, DeriveType, MultiFieldData, State,
+};
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, ToTokens};
+use std::collections::HashMap;
+use syn::{parse::Result, DeriveInput, Ident, Index};
+
+/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ quote!(::core::convert),
+ trait_name.to_lowercase(),
+ AttrParams {
+ enum_: vec!["forward", "ignore"],
+ variant: vec!["forward", "ignore"],
+ struct_: vec!["forward"],
+ field: vec!["forward"],
+ },
+ )?;
+ if state.derive_type == DeriveType::Enum {
+ Ok(enum_from(input, state))
+ } else {
+ Ok(struct_from(input, &state))
+ }
+}
+
+pub fn struct_from(input: &DeriveInput, state: &State) -> TokenStream {
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ fields,
+ infos,
+ input_type,
+ trait_path,
+ ..
+ } = multi_field_data.clone();
+
+ let mut new_generics = input.generics.clone();
+ let sub_items: Vec<_> = infos
+ .iter()
+ .zip(fields.iter())
+ .enumerate()
+ .map(|(i, (info, field))| {
+ let field_type = &field.ty;
+ let variable = if fields.len() == 1 {
+ quote!(original)
+ } else {
+ let tuple_index = Index::from(i);
+ quote!(original.#tuple_index)
+ };
+ if info.forward {
+ let type_param =
+ &Ident::new(&format!("__FromT{}", i), Span::call_site());
+ let sub_trait_path = quote!(#trait_path<#type_param>);
+ let type_where_clauses = quote! {
+ where #field_type: #sub_trait_path
+ };
+ new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ type_param,
+ type_where_clauses,
+ true,
+ );
+ let casted_trait = quote!(<#field_type as #sub_trait_path>);
+ (quote!(#casted_trait::from(#variable)), quote!(#type_param))
+ } else {
+ (variable, quote!(#field_type))
+ }
+ })
+ .collect();
+ let initializers: Vec<_> = sub_items.iter().map(|i| &i.0).collect();
+ let from_types: Vec<_> = sub_items.iter().map(|i| &i.1).collect();
+
+ let body = multi_field_data.initializer(&initializers);
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+
+ quote! {
+ impl#impl_generics #trait_path<(#(#from_types),*)> for
+ #input_type#ty_generics #where_clause {
+
+ #[allow(unused_variables)]
+ #[inline]
+ fn from(original: (#(#from_types),*)) -> #input_type#ty_generics {
+ #body
+ }
+ }
+ }
+}
+
+fn enum_from(input: &DeriveInput, state: State) -> TokenStream {
+ let mut tokens = TokenStream::new();
+
+ let mut variants_per_types = HashMap::new();
+ for variant_state in state.enabled_variant_data().variant_states {
+ let multi_field_data = variant_state.enabled_fields_data();
+ let MultiFieldData { field_types, .. } = multi_field_data.clone();
+ variants_per_types
+ .entry(field_types.clone())
+ .or_insert_with(Vec::new)
+ .push(variant_state);
+ }
+ for (ref field_types, ref variant_states) in variants_per_types {
+ for variant_state in variant_states {
+ let multi_field_data = variant_state.enabled_fields_data();
+ let MultiFieldData {
+ variant_info,
+ infos,
+ ..
+ } = multi_field_data.clone();
+ // If there would be a conflict on a empty tuple derive, ignore the
+ // variants that are not explicitely enabled or have explicitely enabled
+ // or disabled fields
+ if field_types.is_empty()
+ && variant_states.len() > 1
+ && !std::iter::once(variant_info)
+ .chain(infos)
+ .any(|info| info.info.enabled.is_some())
+ {
+ continue;
+ }
+ struct_from(input, variant_state).to_tokens(&mut tokens);
+ }
+ }
+ tokens
+}
diff --git a/third_party/rust/derive_more/src/from_str.rs b/third_party/rust/derive_more/src/from_str.rs
new file mode 100644
index 0000000000..84236cd7be
--- /dev/null
+++ b/third_party/rust/derive_more/src/from_str.rs
@@ -0,0 +1,52 @@
+use crate::utils::{SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(FromStr)]` into an implementation of `FromStr`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::new(
+ input,
+ trait_name,
+ quote!(::core::str),
+ trait_name.to_lowercase(),
+ )?;
+
+ // We cannot set defaults for fields, once we do we can remove this check
+ if state.fields.len() != 1 || state.enabled_fields().len() != 1 {
+ panic_one_field(trait_name);
+ }
+
+ let single_field_data = state.assert_single_enabled_field();
+ let SingleFieldData {
+ input_type,
+ field_type,
+ trait_path,
+ casted_trait,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = single_field_data.clone();
+
+ let initializers = [quote!(#casted_trait::from_str(src)?)];
+ let body = single_field_data.initializer(&initializers);
+
+ Ok(quote! {
+ impl#impl_generics #trait_path for #input_type#ty_generics #where_clause
+ {
+ type Err = <#field_type as #trait_path>::Err;
+ #[inline]
+ fn from_str(src: &str) -> ::core::result::Result<Self, Self::Err> {
+ Ok(#body)
+ }
+ }
+ })
+}
+
+fn panic_one_field(trait_name: &str) -> ! {
+ panic!(format!(
+ "Only structs with one field can derive({})",
+ trait_name
+ ))
+}
diff --git a/third_party/rust/derive_more/src/index.rs b/third_party/rust/derive_more/src/index.rs
new file mode 100644
index 0000000000..5aea597693
--- /dev/null
+++ b/third_party/rust/derive_more/src/index.rs
@@ -0,0 +1,50 @@
+use crate::utils::{add_where_clauses_for_new_ident, SingleFieldData, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{parse::Result, DeriveInput, Ident};
+
+/// Provides the hook to expand `#[derive(Index)]` into an implementation of `Index`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let index_type = &Ident::new("__IdxT", Span::call_site());
+ let mut state = State::with_field_ignore(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ trait_name.to_lowercase(),
+ )?;
+ state.add_trait_path_type_param(quote!(#index_type));
+ let SingleFieldData {
+ field,
+ field_type,
+ input_type,
+ trait_path_with_params,
+ casted_trait,
+ member,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path_with_params
+ };
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ index_type,
+ type_where_clauses,
+ true,
+ );
+
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ Ok(quote! {
+ impl#impl_generics #trait_path_with_params for #input_type#ty_generics #where_clause
+ {
+ type Output = #casted_trait::Output;
+ #[inline]
+ fn index(&self, idx: #index_type) -> &Self::Output {
+ #casted_trait::index(&#member, idx)
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more/src/index_mut.rs b/third_party/rust/derive_more/src/index_mut.rs
new file mode 100644
index 0000000000..d2c3688051
--- /dev/null
+++ b/third_party/rust/derive_more/src/index_mut.rs
@@ -0,0 +1,49 @@
+use crate::utils::{add_where_clauses_for_new_ident, SingleFieldData, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{parse::Result, DeriveInput, Ident};
+
+/// Provides the hook to expand `#[derive(IndexMut)]` into an implementation of `IndexMut`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let index_type = &Ident::new("__IdxT", Span::call_site());
+ let mut state = State::with_field_ignore(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ String::from("index_mut"),
+ )?;
+ state.add_trait_path_type_param(quote!(#index_type));
+ let SingleFieldData {
+ field,
+ field_type,
+ input_type,
+ trait_path_with_params,
+ casted_trait,
+ member,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path_with_params
+ };
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ index_type,
+ type_where_clauses,
+ true,
+ );
+
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ Ok(quote! {
+ impl#impl_generics #trait_path_with_params for #input_type#ty_generics #where_clause
+ {
+ #[inline]
+ fn index_mut(&mut self, idx: #index_type) -> &mut Self::Output {
+ #casted_trait::index_mut(&mut #member, idx)
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more/src/into.rs b/third_party/rust/derive_more/src/into.rs
new file mode 100644
index 0000000000..bb77e2336a
--- /dev/null
+++ b/third_party/rust/derive_more/src/into.rs
@@ -0,0 +1,58 @@
+use crate::utils::{add_extra_generic_param, AttrParams, MultiFieldData, State};
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(Into)]` into an implementation of `Into`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ quote!(::core::convert),
+ trait_name.to_lowercase(),
+ AttrParams {
+ enum_: vec!["ignore", "owned", "ref", "ref_mut"],
+ variant: vec!["ignore", "owned", "ref", "ref_mut"],
+ struct_: vec!["ignore", "owned", "ref", "ref_mut"],
+ field: vec!["ignore"],
+ },
+ )?;
+ let MultiFieldData {
+ variant_info,
+ field_types,
+ field_idents,
+ input_type,
+ ..
+ } = state.enabled_fields_data();
+
+ let mut tokens = TokenStream::new();
+
+ for ref_type in variant_info.ref_types() {
+ let reference = ref_type.reference();
+ let lifetime = ref_type.lifetime();
+ let reference_with_lifetime = ref_type.reference_with_lifetime();
+
+ let generics_impl;
+ let (_, ty_generics, where_clause) = input.generics.split_for_impl();
+ let (impl_generics, _, _) = if ref_type.is_ref() {
+ generics_impl = add_extra_generic_param(&input.generics, lifetime);
+ generics_impl.split_for_impl()
+ } else {
+ input.generics.split_for_impl()
+ };
+
+ let into = quote! {
+ impl#impl_generics ::core::convert::From<#reference_with_lifetime #input_type#ty_generics> for
+ (#(#reference_with_lifetime #field_types),*) #where_clause {
+
+ #[allow(unused_variables)]
+ #[inline]
+ fn from(original: #reference_with_lifetime #input_type#ty_generics) -> (#(#reference_with_lifetime #field_types),*) {
+ (#(#reference original.#field_idents),*)
+ }
+ }
+ };
+ into.to_tokens(&mut tokens);
+ }
+ Ok(tokens)
+}
diff --git a/third_party/rust/derive_more/src/into_iterator.rs b/third_party/rust/derive_more/src/into_iterator.rs
new file mode 100644
index 0000000000..45183d4588
--- /dev/null
+++ b/third_party/rust/derive_more/src/into_iterator.rs
@@ -0,0 +1,59 @@
+use crate::utils::{
+ add_extra_generic_param, add_extra_ty_param_bound_ref, SingleFieldData, State,
+};
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(IntoIterator)]` into an implementation of `IntoIterator`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_field_ignore_and_refs(
+ input,
+ trait_name,
+ quote!(::core::iter),
+ String::from("into_iterator"),
+ )?;
+ let SingleFieldData {
+ input_type,
+ info,
+ field_type,
+ member,
+ trait_path,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let mut tokens = TokenStream::new();
+
+ for ref_type in info.ref_types() {
+ let reference = ref_type.reference();
+ let lifetime = ref_type.lifetime();
+ let reference_with_lifetime = ref_type.reference_with_lifetime();
+
+ let generics_impl;
+ let generics =
+ add_extra_ty_param_bound_ref(&input.generics, trait_path, ref_type);
+ let (_, ty_generics, where_clause) = generics.split_for_impl();
+ let (impl_generics, _, _) = if ref_type.is_ref() {
+ generics_impl = add_extra_generic_param(&generics, lifetime.clone());
+ generics_impl.split_for_impl()
+ } else {
+ generics.split_for_impl()
+ };
+ // let generics = add_extra_ty_param_bound(&input.generics, trait_path);
+ let casted_trait =
+ &quote!(<#reference_with_lifetime #field_type as #trait_path>);
+ let into_iterator = quote! {
+ impl#impl_generics #trait_path for #reference_with_lifetime #input_type#ty_generics #where_clause
+ {
+ type Item = #casted_trait::Item;
+ type IntoIter = #casted_trait::IntoIter;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ #casted_trait::into_iter(#reference #member)
+ }
+ }
+ };
+ into_iterator.to_tokens(&mut tokens);
+ }
+ Ok(tokens)
+}
diff --git a/third_party/rust/derive_more/src/lib.rs b/third_party/rust/derive_more/src/lib.rs
new file mode 100644
index 0000000000..8ea93aa406
--- /dev/null
+++ b/third_party/rust/derive_more/src/lib.rs
@@ -0,0 +1,396 @@
+//! # `derive_more`
+//!
+//! [![Build Status](https://github.com/JelteF/derive_more/workflows/CI/badge.svg)](https://github.com/JelteF/derive_more/actions)
+//! [![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more)
+//! [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/)
+//! [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE)
+//! [![Rust 1.36+](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html)
+//!
+//! Rust has lots of builtin traits that are implemented for its basic types, such
+//! as `Add`, `Not`, `From` or `Display`.
+//! However, when wrapping these types inside your own structs or enums you lose the
+//! implementations of these traits and are required to recreate them.
+//! This is especially annoying when your own structures are very simple, such as
+//! when using the commonly advised newtype pattern (e.g. `MyInt(i32)`).
+//!
+//! This library tries to remove these annoyances and the corresponding boilerplate code.
+//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
+//!
+//! ## Example code
+//!
+//! By using this library the following code just works:
+//!
+//! ```rust
+//! extern crate derive_more;
+//! use derive_more::{Add, Display, From, Into};
+//!
+//! #[derive(PartialEq, From, Add)]
+//! struct MyInt(i32);
+//!
+//! #[derive(PartialEq, From, Into)]
+//! struct Point2D {
+//! x: i32,
+//! y: i32,
+//! }
+//!
+//! #[derive(PartialEq, From, Add, Display)]
+//! enum MyEnum {
+//! #[display(fmt = "int: {}", _0)]
+//! Int(i32),
+//! Uint(u32),
+//! #[display(fmt = "nothing")]
+//! Nothing,
+//! }
+//!
+//! assert!(MyInt(11) == MyInt(5) + 6.into());
+//! assert!((5, 6) == Point2D { x: 5, y: 6 }.into());
+//! assert!(MyEnum::Int(15) == (MyEnum::Int(8) + 7.into()).unwrap());
+//! assert!(MyEnum::Int(15).to_string() == "int: 15");
+//! assert!(MyEnum::Uint(42).to_string() == "42");
+//! assert!(MyEnum::Nothing.to_string() == "nothing");
+//! ```
+//!
+//! ## The derivable traits
+//!
+//! Below are all the traits that you can derive using this library.
+//! Some trait derivations are so similar that the further documentation will only show a single one
+//! of them.
+//! You can recognize these by the "-like" suffix in their name.
+//! The trait name before that will be the only one that is used throughout the further
+//! documentation.
+//!
+//! It is important to understand what code gets generated when using one of the
+//! derives from this crate.
+//! That is why the links below explain what code gets generated for a trait for
+//! each group from before.
+//!
+//! You can use the [`cargo-expand`] utility to see the exact code that is generated
+//! for your specific type.
+//! This will show you your code with all macros and derives expanded.
+//!
+//! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
+//! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
+//!
+//! ### Conversion traits
+//!
+//! These are traits that are used to convert automatically between types.
+//!
+//! 1. [`From`]
+//! 2. [`Into`]
+//! 3. [`FromStr`]
+//! 4. [`TryInto`]
+//! 5. [`IntoIterator`]
+//! 6. [`AsRef`]
+//! 7. [`AsMut`]
+//!
+//! ### Formatting traits
+//!
+//! These traits are used for converting a struct to a string in different ways.
+//!
+//! 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`,
+//! `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
+//!
+//! ### Operators
+//!
+//! These are traits that can be used for operator overloading.
+//!
+//! 1. [`Index`]
+//! 2. [`Deref`]
+//! 3. [`Not`-like], contains `Not` and `Neg`
+//! 4. [`Add`-like], contains `Add`, `Sub`, `BitAnd`, `BitOr`, `BitXor`, `MulSelf`,
+//! `DivSelf`, `RemSelf`, `ShrSelf` and `ShlSelf`
+//! 5. [`Mul`-like], contains `Mul`, `Div`, `Rem`, `Shr` and `Shl`
+//! 3. [`Sum`-like], contains `Sum` and `Product`
+//! 6. [`IndexMut`]
+//! 7. [`DerefMut`]
+//! 8. [`AddAssign`-like], contains `AddAssign`, `SubAssign`, `BitAndAssign`,
+//! `BitOrAssign` and `BitXorAssign`
+//! 9. [`MulAssign`-like], contains `MulAssign`, `DivAssign`, `RemAssign`,
+//! `ShrAssign` and `ShlAssign`
+//!
+//! ### Static methods
+//!
+//! These don't derive traits, but derive static methods instead.
+//!
+//! 1. [`Constructor`], this derives a `new` method that can be used as a constructor.
+//! This is very basic if you need more customization for your constructor, check
+//! out the [`derive-new`] crate.
+//!
+//! ## Generated code
+//!
+//! ## Installation
+//!
+//! This library requires Rust 1.36 or higher and it supports `no_std` out of the box.
+//! Then add the following to `Cargo.toml`:
+//!
+//! ```toml
+//! [dependencies]
+//! derive_more = "0.99.0"
+//! # You can specifiy the types of derives that you need for less time spent
+//! # compiling. For the full list of features see this crate its Cargo.toml.
+//! default-features = false
+//! features = ["from", "add", "iterator"]
+//! ```
+//!
+//! And this to the top of your Rust file for Rust 2018:
+//!
+//! ```rust
+//! extern crate derive_more;
+//! // use the derives that you want in the file
+//! use derive_more::{Add, Display, From};
+//! ```
+//! If you're still using Rust 2015 you should add this instead:
+//! ```rust
+//! extern crate core;
+//! #[macro_use]
+//! extern crate derive_more;
+//! # fn main(){}
+//! ```
+//!
+//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
+//! [`derive-new`]: https://github.com/nrc/derive-new
+//!
+//! [`From`]: https://jeltef.github.io/derive_more/derive_more/from.html
+//! [`Into`]: https://jeltef.github.io/derive_more/derive_more/into.html
+//! [`FromStr`]: https://jeltef.github.io/derive_more/derive_more/from_str.html
+//! [`TryInto`]: https://jeltef.github.io/derive_more/derive_more/try_into.html
+//! [`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html
+//! [`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html
+//! [`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html
+//!
+//! [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html
+//!
+//! [`Index`]: https://jeltef.github.io/derive_more/derive_more/index_op.html
+//! [`Deref`]: https://jeltef.github.io/derive_more/derive_more/deref.html
+//! [`Not`-like]: https://jeltef.github.io/derive_more/derive_more/not.html
+//! [`Add`-like]: https://jeltef.github.io/derive_more/derive_more/add.html
+//! [`Mul`-like]: https://jeltef.github.io/derive_more/derive_more/mul.html
+//! [`Sum`-like]: https://jeltef.github.io/derive_more/derive_more/sum.html
+//! [`IndexMut`]: https://jeltef.github.io/derive_more/derive_more/index_mut.html
+//! [`DerefMut`]: https://jeltef.github.io/derive_more/derive_more/deref_mut.html
+//! [`AddAssign`-like]: https://jeltef.github.io/derive_more/derive_more/add_assign.html
+//! [`MulAssign`-like]: https://jeltef.github.io/derive_more/derive_more/mul_assign.html
+//!
+//! [`Constructor`]: https://jeltef.github.io/derive_more/derive_more/constructor.html
+
+#![recursion_limit = "128"]
+
+extern crate proc_macro;
+use proc_macro2;
+use syn;
+
+use proc_macro::TokenStream;
+use syn::parse::Error as ParseError;
+
+mod utils;
+
+#[cfg(any(feature = "add_assign", feature = "mul_assign"))]
+mod add_assign_like;
+#[cfg(any(
+ feature = "add",
+ feature = "add_assign",
+ feature = "mul",
+ feature = "mul_assign",
+))]
+mod add_helpers;
+#[cfg(any(feature = "add", feature = "mul"))]
+mod add_like;
+#[cfg(feature = "as_mut")]
+mod as_mut;
+#[cfg(feature = "as_ref")]
+mod as_ref;
+#[cfg(feature = "constructor")]
+mod constructor;
+#[cfg(feature = "deref")]
+mod deref;
+#[cfg(feature = "deref_mut")]
+mod deref_mut;
+#[cfg(feature = "display")]
+mod display;
+#[cfg(feature = "from")]
+mod from;
+#[cfg(feature = "from_str")]
+mod from_str;
+#[cfg(feature = "index")]
+mod index;
+#[cfg(feature = "index_mut")]
+mod index_mut;
+#[cfg(feature = "into")]
+mod into;
+#[cfg(feature = "into_iterator")]
+mod into_iterator;
+#[cfg(feature = "mul_assign")]
+mod mul_assign_like;
+#[cfg(any(feature = "mul", feature = "mul_assign"))]
+mod mul_helpers;
+#[cfg(feature = "mul")]
+mod mul_like;
+#[cfg(feature = "not")]
+mod not_like;
+#[cfg(feature = "display")]
+#[allow(ellipsis_inclusive_range_patterns)]
+#[allow(clippy::all)]
+mod parsing;
+#[cfg(feature = "sum")]
+mod sum_like;
+#[cfg(feature = "try_into")]
+mod try_into;
+
+// This trait describes the possible return types of
+// the derives. A derive can generally be infallible and
+// return a TokenStream, or it can be fallible and return
+// a Result<TokenStream, syn::parse::Error>.
+trait Output {
+ fn process(self) -> TokenStream;
+}
+
+impl Output for proc_macro2::TokenStream {
+ fn process(self) -> TokenStream {
+ self.into()
+ }
+}
+
+impl Output for Result<proc_macro2::TokenStream, ParseError> {
+ fn process(self) -> TokenStream {
+ match self {
+ Ok(ts) => ts.into(),
+ Err(e) => e.to_compile_error().into(),
+ }
+ }
+}
+
+macro_rules! create_derive(
+ ($feature:literal, $mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => {
+ #[cfg(feature = $feature)]
+ #[proc_macro_derive($trait_, attributes($($attribute),*))]
+ #[doc(hidden)]
+ pub fn $fn_name(input: TokenStream) -> TokenStream {
+ let ast = syn::parse(input).unwrap();
+ Output::process($mod_::expand(&ast, stringify!($trait_)))
+ }
+ }
+);
+
+create_derive!("from", from, From, from_derive, from);
+
+create_derive!("into", into, Into, into_derive, into);
+
+create_derive!("constructor", constructor, Constructor, constructor_derive);
+
+create_derive!("not", not_like, Not, not_derive);
+create_derive!("not", not_like, Neg, neg_derive);
+
+create_derive!("add", add_like, Add, add_derive);
+create_derive!("add", add_like, Sub, sub_derive);
+create_derive!("add", add_like, BitAnd, bit_and_derive);
+create_derive!("add", add_like, BitOr, bit_or_derive);
+create_derive!("add", add_like, BitXor, bit_xor_derive);
+
+create_derive!("mul", mul_like, Mul, mul_derive, mul);
+create_derive!("mul", mul_like, Div, div_derive, div);
+create_derive!("mul", mul_like, Rem, rem_derive, rem);
+create_derive!("mul", mul_like, Shr, shr_derive, shr);
+create_derive!("mul", mul_like, Shl, shl_derive, shl);
+
+create_derive!("add_assign", add_assign_like, AddAssign, add_assign_derive,);
+create_derive!("add_assign", add_assign_like, SubAssign, sub_assign_derive,);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitAndAssign,
+ bit_and_assign_derive,
+);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitOrAssign,
+ bit_or_assign_derive,
+);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitXorAssign,
+ bit_xor_assign_derive,
+);
+
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ MulAssign,
+ mul_assign_derive,
+ mul_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ DivAssign,
+ div_assign_derive,
+ div_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ RemAssign,
+ rem_assign_derive,
+ rem_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ ShrAssign,
+ shr_assign_derive,
+ shr_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ ShlAssign,
+ shl_assign_derive,
+ shl_assign,
+);
+
+create_derive!("sum", sum_like, Sum, sum_derive);
+create_derive!("sum", sum_like, Product, product_derive);
+
+create_derive!("from_str", from_str, FromStr, from_str_derive);
+
+create_derive!("display", display, Display, display_derive, display);
+create_derive!("display", display, Binary, binary_derive, binary);
+create_derive!("display", display, Octal, octal_derive, octal);
+create_derive!("display", display, LowerHex, lower_hex_derive, lower_hex);
+create_derive!("display", display, UpperHex, upper_hex_derive, upper_hex);
+create_derive!("display", display, LowerExp, lower_exp_derive, lower_exp);
+create_derive!("display", display, UpperExp, upper_exp_derive, upper_exp);
+create_derive!("display", display, Pointer, pointer_derive, pointer);
+create_derive!("display", display, DebugCustom, debug_custom_derive, debug);
+
+create_derive!("index", index, Index, index_derive, index);
+create_derive!(
+ "index_mut",
+ index_mut,
+ IndexMut,
+ index_mut_derive,
+ index_mut,
+);
+
+create_derive!(
+ "into_iterator",
+ into_iterator,
+ IntoIterator,
+ into_iterator_derive,
+ into_iterator,
+);
+
+create_derive!("try_into", try_into, TryInto, try_into_derive, try_into);
+
+create_derive!("deref", deref, Deref, deref_derive, deref);
+create_derive!(
+ "deref_mut",
+ deref_mut,
+ DerefMut,
+ deref_mut_derive,
+ deref_mut,
+);
+
+create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref);
+create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut);
diff --git a/third_party/rust/derive_more/src/mul_assign_like.rs b/third_party/rust/derive_more/src/mul_assign_like.rs
new file mode 100644
index 0000000000..544e4b7526
--- /dev/null
+++ b/third_party/rust/derive_more/src/mul_assign_like.rs
@@ -0,0 +1,65 @@
+use crate::add_assign_like;
+use crate::mul_helpers::generics_and_exprs;
+use crate::utils::{AttrParams, MultiFieldData, RefType, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use std::collections::HashSet;
+use std::iter;
+use syn::{DeriveInput, Ident, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let method_name = trait_name
+ .to_lowercase()
+ .trim_end_matches("assign")
+ .to_string()
+ + "_assign";
+
+ let mut state = State::with_attr_params(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ method_name,
+ AttrParams::struct_(vec!["forward"]),
+ )?;
+ if state.default_info.forward {
+ return Ok(add_assign_like::expand(input, trait_name));
+ }
+ let scalar_ident = &Ident::new("__RhsT", Span::call_site());
+ state.add_trait_path_type_param(quote!(#scalar_ident));
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ ty_generics,
+ trait_path,
+ trait_path_with_params,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let tys = field_types.iter().collect::<HashSet<_>>();
+ let tys = tys.iter();
+ let trait_path_iter = iter::repeat(trait_path_with_params);
+
+ let type_where_clauses = quote! {
+ where #(#tys: #trait_path_iter),*
+ };
+
+ let (generics, exprs) = generics_and_exprs(
+ multi_field_data.clone(),
+ scalar_ident,
+ type_where_clauses,
+ RefType::Mut,
+ );
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+
+ Ok(quote!(
+ impl#impl_generics #trait_path<#scalar_ident> for #input_type#ty_generics #where_clause{
+ #[inline]
+ fn #method_ident(&mut self, rhs: #scalar_ident#ty_generics) {
+ #(#exprs;
+ )*
+ }
+ }
+ ))
+}
diff --git a/third_party/rust/derive_more/src/mul_helpers.rs b/third_party/rust/derive_more/src/mul_helpers.rs
new file mode 100644
index 0000000000..985d64fe8c
--- /dev/null
+++ b/third_party/rust/derive_more/src/mul_helpers.rs
@@ -0,0 +1,36 @@
+use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, RefType};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Generics, Ident};
+
+pub fn generics_and_exprs(
+ multi_field_data: MultiFieldData,
+ scalar_ident: &Ident,
+ type_where_clauses: TokenStream,
+ ref_type: RefType,
+) -> (Generics, Vec<TokenStream>) {
+ let MultiFieldData {
+ fields,
+ casted_traits,
+ members,
+ method_ident,
+ ..
+ } = multi_field_data;
+ let reference = ref_type.reference();
+ let exprs: Vec<_> = casted_traits
+ .iter()
+ .zip(members)
+ .map(
+ |(casted_trait, member)| quote!(#casted_trait::#method_ident(#reference #member, rhs)),
+ )
+ .collect();
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &multi_field_data.state.input.generics,
+ &fields,
+ scalar_ident,
+ type_where_clauses,
+ true,
+ );
+ (new_generics, exprs)
+}
diff --git a/third_party/rust/derive_more/src/mul_like.rs b/third_party/rust/derive_more/src/mul_like.rs
new file mode 100644
index 0000000000..734dc0f117
--- /dev/null
+++ b/third_party/rust/derive_more/src/mul_like.rs
@@ -0,0 +1,62 @@
+use crate::add_like;
+use crate::mul_helpers::generics_and_exprs;
+use crate::utils::{AttrParams, MultiFieldData, RefType, State};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use std::collections::HashSet;
+use std::iter;
+use syn::{DeriveInput, Ident, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let mut state = State::with_attr_params(
+ input,
+ trait_name,
+ quote!(::core::ops),
+ trait_name.to_lowercase(),
+ AttrParams::struct_(vec!["forward"]),
+ )?;
+ if state.default_info.forward {
+ return Ok(add_like::expand(input, trait_name));
+ }
+
+ let scalar_ident = &Ident::new("__RhsT", Span::call_site());
+ state.add_trait_path_type_param(quote!(#scalar_ident));
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ ty_generics,
+ trait_path,
+ trait_path_with_params,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let tys = field_types.iter().collect::<HashSet<_>>();
+ let tys = tys.iter();
+ let scalar_iter = iter::repeat(scalar_ident);
+ let trait_path_iter = iter::repeat(trait_path);
+
+ let type_where_clauses = quote! {
+ where #(#tys: #trait_path_iter<#scalar_iter, Output=#tys>),*
+ };
+
+ let (generics, initializers) = generics_and_exprs(
+ multi_field_data.clone(),
+ scalar_ident,
+ type_where_clauses,
+ RefType::No,
+ );
+ let body = multi_field_data.initializer(&initializers);
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+ Ok(quote!(
+ impl#impl_generics #trait_path_with_params for #input_type#ty_generics #where_clause {
+ type Output = #input_type#ty_generics;
+ #[inline]
+ fn #method_ident(self, rhs: #scalar_ident) -> #input_type#ty_generics {
+ #body
+ }
+ }
+
+ ))
+}
diff --git a/third_party/rust/derive_more/src/not_like.rs b/third_party/rust/derive_more/src/not_like.rs
new file mode 100644
index 0000000000..e4ffcdfb39
--- /dev/null
+++ b/third_party/rust/derive_more/src/not_like.rs
@@ -0,0 +1,170 @@
+use crate::utils::{
+ add_extra_type_param_bound_op_output, named_to_vec, unnamed_to_vec,
+};
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, ToTokens};
+use std::iter;
+use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident, Index};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_ident = Ident::new(trait_name, Span::call_site());
+ let method_name = trait_name.to_lowercase();
+ let method_ident = &Ident::new(&method_name, Span::call_site());
+ let input_type = &input.ident;
+
+ let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let (output_type, block) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => (
+ quote!(#input_type#ty_generics),
+ tuple_content(input_type, &unnamed_to_vec(fields), method_ident),
+ ),
+ Fields::Named(ref fields) => (
+ quote!(#input_type#ty_generics),
+ struct_content(input_type, &named_to_vec(fields), method_ident),
+ ),
+ _ => panic!(format!("Unit structs cannot use derive({})", trait_name)),
+ },
+ Data::Enum(ref data_enum) => {
+ enum_output_type_and_content(input, data_enum, method_ident)
+ }
+
+ _ => panic!(format!(
+ "Only structs and enums can use derive({})",
+ trait_name
+ )),
+ };
+
+ quote!(
+ impl#impl_generics ::core::ops::#trait_ident for #input_type#ty_generics #where_clause {
+ type Output = #output_type;
+ #[inline]
+ fn #method_ident(self) -> #output_type {
+ #block
+ }
+ }
+ )
+}
+
+fn tuple_content<T: ToTokens>(
+ input_type: &T,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut exprs = vec![];
+
+ for i in 0..fields.len() {
+ let i = Index::from(i);
+ // generates `self.0.add()`
+ let expr = quote!(self.#i.#method_ident());
+ exprs.push(expr);
+ }
+
+ quote!(#input_type(#(#exprs),*))
+}
+
+fn struct_content(
+ input_type: &Ident,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut exprs = vec![];
+
+ for field in fields {
+ // It's safe to unwrap because struct fields always have an identifier
+ let field_id = field.ident.as_ref();
+ // generates `x: self.x.not()`
+ let expr = quote!(#field_id: self.#field_id.#method_ident());
+ exprs.push(expr)
+ }
+
+ quote!(#input_type{#(#exprs),*})
+}
+
+fn enum_output_type_and_content(
+ input: &DeriveInput,
+ data_enum: &DataEnum,
+ method_ident: &Ident,
+) -> (TokenStream, TokenStream) {
+ let input_type = &input.ident;
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ let mut matches = vec![];
+ let mut method_iter = iter::repeat(method_ident);
+ // If the enum contains unit types that means it can error.
+ let has_unit_type = data_enum.variants.iter().any(|v| v.fields == Fields::Unit);
+
+ for variant in &data_enum.variants {
+ let subtype = &variant.ident;
+ let subtype = quote!(#input_type::#subtype);
+
+ match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ // The patern that is outputted should look like this:
+ // (Subtype(vars)) => Ok(TypePath(exprs))
+ let size = unnamed_to_vec(fields).len();
+ let vars: &Vec<_> = &(0..size)
+ .map(|i| Ident::new(&format!("__{}", i), Span::call_site()))
+ .collect();
+ let method_iter = method_iter.by_ref();
+ let mut body = quote!(#subtype(#(#vars.#method_iter()),*));
+ if has_unit_type {
+ body = quote!(::core::result::Result::Ok(#body))
+ }
+ let matcher = quote! {
+ #subtype(#(#vars),*) => {
+ #body
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Named(ref fields) => {
+ // The patern that is outputted should look like this:
+ // (Subtype{a: __l_a, ...} => {
+ // Ok(Subtype{a: __l_a.neg(__r_a), ...})
+ // }
+ let field_vec = named_to_vec(fields);
+ let size = field_vec.len();
+ let field_names: &Vec<_> = &field_vec
+ .iter()
+ .map(|f| f.ident.as_ref().unwrap())
+ .collect();
+ let vars: &Vec<_> = &(0..size)
+ .map(|i| Ident::new(&format!("__{}", i), Span::call_site()))
+ .collect();
+ let method_iter = method_iter.by_ref();
+ let mut body =
+ quote!(#subtype{#(#field_names: #vars.#method_iter()),*});
+ if has_unit_type {
+ body = quote!(::core::result::Result::Ok(#body))
+ }
+ let matcher = quote! {
+ #subtype{#(#field_names: #vars),*} => {
+ #body
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Unit => {
+ let message =
+ format!("Cannot {}() unit variants", method_ident.to_string());
+ matches.push(quote!(#subtype => ::core::result::Result::Err(#message)));
+ }
+ }
+ }
+
+ let body = quote!(
+ match self {
+ #(#matches),*
+ }
+ );
+
+ let output_type = if has_unit_type {
+ quote!(::core::result::Result<#input_type#ty_generics, &'static str>)
+ } else {
+ quote!(#input_type#ty_generics)
+ };
+
+ (output_type, body)
+}
diff --git a/third_party/rust/derive_more/src/parsing.rs b/third_party/rust/derive_more/src/parsing.rs
new file mode 100644
index 0000000000..c3d09d1624
--- /dev/null
+++ b/third_party/rust/derive_more/src/parsing.rs
@@ -0,0 +1,970 @@
+use self::RuleResult::{Failed, Matched};
+fn escape_default(s: &str) -> String {
+ s.chars().flat_map(|c| c.escape_default()).collect()
+}
+fn char_range_at(s: &str, pos: usize) -> (char, usize) {
+ let c = &s[pos..].chars().next().unwrap();
+ let next_pos = pos + c.len_utf8();
+ (*c, next_pos)
+}
+#[derive(Clone)]
+enum RuleResult<T> {
+ Matched(usize, T),
+ Failed,
+}
+#[derive(PartialEq, Eq, Debug, Clone)]
+pub struct ParseError {
+ pub line: usize,
+ pub column: usize,
+ pub offset: usize,
+ pub expected: ::std::collections::HashSet<&'static str>,
+}
+pub type ParseResult<T> = Result<T, ParseError>;
+impl ::std::fmt::Display for ParseError {
+ fn fmt(
+ &self,
+ fmt: &mut ::std::fmt::Formatter<'_>,
+ ) -> ::std::result::Result<(), ::std::fmt::Error> {
+ write!(fmt, "error at {}:{}: expected ", self.line, self.column)?;
+ if self.expected.len() == 0 {
+ write!(fmt, "EOF")?;
+ } else if self.expected.len() == 1 {
+ write!(
+ fmt,
+ "`{}`",
+ escape_default(self.expected.iter().next().unwrap())
+ )?;
+ } else {
+ let mut iter = self.expected.iter();
+ write!(fmt, "one of `{}`", escape_default(iter.next().unwrap()))?;
+ for elem in iter {
+ write!(fmt, ", `{}`", escape_default(elem))?;
+ }
+ }
+ Ok(())
+ }
+}
+impl ::std::error::Error for ParseError {
+ fn description(&self) -> &str {
+ "parse error"
+ }
+}
+fn slice_eq(
+ input: &str,
+ state: &mut ParseState<'_>,
+ pos: usize,
+ m: &'static str,
+) -> RuleResult<()> {
+ #![inline]
+ #![allow(dead_code)]
+ let l = m.len();
+ if input.len() >= pos + l && &input.as_bytes()[pos..pos + l] == m.as_bytes() {
+ Matched(pos + l, ())
+ } else {
+ state.mark_failure(pos, m)
+ }
+}
+fn slice_eq_case_insensitive(
+ input: &str,
+ state: &mut ParseState<'_>,
+ pos: usize,
+ m: &'static str,
+) -> RuleResult<()> {
+ #![inline]
+ #![allow(dead_code)]
+ let mut used = 0usize;
+ let mut input_iter = input[pos..].chars().flat_map(|x| x.to_uppercase());
+ for m_char_upper in m.chars().flat_map(|x| x.to_uppercase()) {
+ used += m_char_upper.len_utf8();
+ let input_char_result = input_iter.next();
+ if input_char_result.is_none() || input_char_result.unwrap() != m_char_upper {
+ return state.mark_failure(pos, m);
+ }
+ }
+ Matched(pos + used, ())
+}
+fn any_char(input: &str, state: &mut ParseState<'_>, pos: usize) -> RuleResult<()> {
+ #![inline]
+ #![allow(dead_code)]
+ if input.len() > pos {
+ let (_, next) = char_range_at(input, pos);
+ Matched(next, ())
+ } else {
+ state.mark_failure(pos, "<character>")
+ }
+}
+fn pos_to_line(input: &str, pos: usize) -> (usize, usize) {
+ let before = &input[..pos];
+ let line = before.as_bytes().iter().filter(|&&c| c == b'\n').count() + 1;
+ let col = before.chars().rev().take_while(|&c| c != '\n').count() + 1;
+ (line, col)
+}
+impl<'input> ParseState<'input> {
+ fn mark_failure(&mut self, pos: usize, expected: &'static str) -> RuleResult<()> {
+ if self.suppress_fail == 0 {
+ if pos > self.max_err_pos {
+ self.max_err_pos = pos;
+ self.expected.clear();
+ }
+ if pos == self.max_err_pos {
+ self.expected.insert(expected);
+ }
+ }
+ Failed
+ }
+}
+struct ParseState<'input> {
+ max_err_pos: usize,
+ suppress_fail: usize,
+ expected: ::std::collections::HashSet<&'static str>,
+ _phantom: ::std::marker::PhantomData<&'input ()>,
+}
+impl<'input> ParseState<'input> {
+ fn new() -> ParseState<'input> {
+ ParseState {
+ max_err_pos: 0,
+ suppress_fail: 0,
+ expected: ::std::collections::HashSet::new(),
+ _phantom: ::std::marker::PhantomData,
+ }
+ }
+}
+
+fn __parse_discard_doubles<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<Option<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = {
+ let __choice_res = {
+ let __seq_res = slice_eq(__input, __state, __pos, "{");
+ match __seq_res {
+ Matched(__pos, _) => slice_eq(__input, __state, __pos, "{"),
+ Failed => Failed,
+ }
+ };
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => {
+ let __seq_res = slice_eq(__input, __state, __pos, "}");
+ match __seq_res {
+ Matched(__pos, _) => slice_eq(__input, __state, __pos, "}"),
+ Failed => Failed,
+ }
+ }
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => Matched(__pos, { None }),
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_placeholder_inner<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<Option<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = {
+ let str_start = __pos;
+ match {
+ let __seq_res = if __input.len() > __pos {
+ let (__ch, __next) = char_range_at(__input, __pos);
+ match __ch {
+ '{' => Matched(__next, ()),
+ _ => __state.mark_failure(__pos, "[{]"),
+ }
+ } else {
+ __state.mark_failure(__pos, "[{]")
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = {
+ let mut __repeat_pos = __pos;
+ loop {
+ let __pos = __repeat_pos;
+ let __step_res = {
+ let __seq_res = {
+ __state.suppress_fail += 1;
+ let __assert_res = if __input.len() > __pos {
+ let (__ch, __next) =
+ char_range_at(__input, __pos);
+ match __ch {
+ '{' | '}' => Matched(__next, ()),
+ _ => {
+ __state.mark_failure(__pos, "[{}]")
+ }
+ }
+ } else {
+ __state.mark_failure(__pos, "[{}]")
+ };
+ __state.suppress_fail -= 1;
+ match __assert_res {
+ Failed => Matched(__pos, ()),
+ Matched(..) => Failed,
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ any_char(__input, __state, __pos)
+ }
+ Failed => Failed,
+ }
+ };
+ match __step_res {
+ Matched(__newpos, __value) => {
+ __repeat_pos = __newpos;
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ Matched(__repeat_pos, ())
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ if __input.len() > __pos {
+ let (__ch, __next) = char_range_at(__input, __pos);
+ match __ch {
+ '}' => Matched(__next, ()),
+ _ => __state.mark_failure(__pos, "[}]"),
+ }
+ } else {
+ __state.mark_failure(__pos, "[}]")
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ } {
+ Matched(__newpos, _) => {
+ Matched(__newpos, &__input[str_start..__newpos])
+ }
+ Failed => Failed,
+ }
+ };
+ match __seq_res {
+ Matched(__pos, n) => Matched(__pos, { Some(n) }),
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_discard_any<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<Option<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = any_char(__input, __state, __pos);
+ match __seq_res {
+ Matched(__pos, _) => Matched(__pos, { None }),
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_arg<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<usize> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = {
+ let str_start = __pos;
+ match {
+ let mut __repeat_pos = __pos;
+ let mut __repeat_value = vec![];
+ loop {
+ let __pos = __repeat_pos;
+ let __step_res = if __input.len() > __pos {
+ let (__ch, __next) = char_range_at(__input, __pos);
+ match __ch {
+ '0'...'9' => Matched(__next, ()),
+ _ => __state.mark_failure(__pos, "[0-9]"),
+ }
+ } else {
+ __state.mark_failure(__pos, "[0-9]")
+ };
+ match __step_res {
+ Matched(__newpos, __value) => {
+ __repeat_pos = __newpos;
+ __repeat_value.push(__value);
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ if __repeat_value.len() >= 1 {
+ Matched(__repeat_pos, ())
+ } else {
+ Failed
+ }
+ } {
+ Matched(__newpos, _) => {
+ Matched(__newpos, &__input[str_start..__newpos])
+ }
+ Failed => Failed,
+ }
+ };
+ match __seq_res {
+ Matched(__pos, n) => Matched(__pos, { n.parse().unwrap() }),
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_ty<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<&'input str> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = {
+ let str_start = __pos;
+ match {
+ let __choice_res = {
+ let __choice_res = slice_eq(__input, __state, __pos, "x?");
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => slice_eq(__input, __state, __pos, "X?"),
+ }
+ };
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => {
+ let __choice_res = slice_eq(__input, __state, __pos, "o");
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => {
+ let __choice_res =
+ slice_eq(__input, __state, __pos, "x");
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => {
+ let __choice_res =
+ slice_eq(__input, __state, __pos, "X");
+ match __choice_res {
+ Matched(__pos, __value) => {
+ Matched(__pos, __value)
+ }
+ Failed => {
+ let __choice_res = slice_eq(
+ __input, __state, __pos, "p",
+ );
+ match __choice_res {
+ Matched(__pos, __value) => {
+ Matched(__pos, __value)
+ }
+ Failed => {
+ let __choice_res = slice_eq(
+ __input, __state, __pos,
+ "b",
+ );
+ match __choice_res {
+ Matched(__pos, __value) => {
+ Matched(__pos, __value)
+ }
+ Failed => {
+ let __choice_res =
+ slice_eq(
+ __input,
+ __state, __pos,
+ "e",
+ );
+ match __choice_res {
+ Matched(
+ __pos,
+ __value,
+ ) => Matched(
+ __pos, __value,
+ ),
+ Failed => {
+ let __choice_res =
+ slice_eq(
+ __input,
+ __state,
+ __pos,
+ "E",
+ );
+ match __choice_res {
+ Matched(
+ __pos,
+ __value,
+ ) => Matched(
+ __pos, __value,
+ ),
+ Failed => slice_eq(
+ __input, __state,
+ __pos, "?",
+ ),
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } {
+ Matched(__newpos, _) => {
+ Matched(__newpos, &__input[str_start..__newpos])
+ }
+ Failed => Failed,
+ }
+ };
+ match __seq_res {
+ Matched(__pos, n) => Matched(__pos, { n }),
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_format_spec<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<Option<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = slice_eq(__input, __state, __pos, ":");
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match {
+ let __seq_res = match {
+ let __seq_res = {
+ __state.suppress_fail += 1;
+ let __assert_res = if __input.len() > __pos {
+ let (__ch, __next) = char_range_at(__input, __pos);
+ match __ch {
+ '<' | '^' | '>' => Matched(__next, ()),
+ _ => __state.mark_failure(__pos, "[<^>]"),
+ }
+ } else {
+ __state.mark_failure(__pos, "[<^>]")
+ };
+ __state.suppress_fail -= 1;
+ match __assert_res {
+ Failed => Matched(__pos, ()),
+ Matched(..) => Failed,
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => any_char(__input, __state, __pos),
+ Failed => Failed,
+ }
+ } {
+ Matched(__newpos, _) => Matched(__newpos, ()),
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ if __input.len() > __pos {
+ let (__ch, __next) = char_range_at(__input, __pos);
+ match __ch {
+ '<' | '^' | '>' => Matched(__next, ()),
+ _ => __state.mark_failure(__pos, "[<^>]"),
+ }
+ } else {
+ __state.mark_failure(__pos, "[<^>]")
+ }
+ }
+ Failed => Failed,
+ }
+ } {
+ Matched(__newpos, _) => Matched(__newpos, ()),
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match {
+ let __choice_res = slice_eq(__input, __state, __pos, "+");
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => slice_eq(__input, __state, __pos, "-"),
+ }
+ } {
+ Matched(__newpos, _) => Matched(__newpos, ()),
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res =
+ match slice_eq(__input, __state, __pos, "#") {
+ Matched(__newpos, _) => Matched(__newpos, ()),
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match {
+ let __choice_res = {
+ let __seq_res = {
+ let mut __repeat_pos = __pos;
+ let mut __repeat_value = vec![];
+ loop {
+ let __pos = __repeat_pos;
+ let __step_res =
+ if __input.len() > __pos {
+ let (__ch, __next) =
+ char_range_at(
+ __input, __pos,
+ );
+ match __ch {
+ 'A'...'Z'
+ | 'a'...'z'
+ | '0'...'9'
+ | '_' => Matched(
+ __next,
+ (),
+ ),
+ _ => __state
+ .mark_failure(
+ __pos,
+ "[A-Za-z0-9_]",
+ ),
+ }
+ } else {
+ __state.mark_failure(
+ __pos,
+ "[A-Za-z0-9_]",
+ )
+ };
+ match __step_res {
+ Matched(
+ __newpos,
+ __value,
+ ) => {
+ __repeat_pos = __newpos;
+ __repeat_value
+ .push(__value);
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ if __repeat_value.len() >= 1 {
+ Matched(__repeat_pos, ())
+ } else {
+ Failed
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => slice_eq(
+ __input, __state, __pos, "$",
+ ),
+ Failed => Failed,
+ }
+ };
+ match __choice_res {
+ Matched(__pos, __value) => {
+ Matched(__pos, __value)
+ }
+ Failed => {
+ let mut __repeat_pos = __pos;
+ let mut __repeat_value = vec![];
+ loop {
+ let __pos = __repeat_pos;
+ let __step_res = if __input
+ .len()
+ > __pos
+ {
+ let (__ch, __next) =
+ char_range_at(
+ __input, __pos,
+ );
+ match __ch {
+ '0'...'9' => {
+ Matched(__next, ())
+ }
+ _ => __state
+ .mark_failure(
+ __pos, "[0-9]",
+ ),
+ }
+ } else {
+ __state.mark_failure(
+ __pos, "[0-9]",
+ )
+ };
+ match __step_res {
+ Matched(
+ __newpos,
+ __value,
+ ) => {
+ __repeat_pos = __newpos;
+ __repeat_value
+ .push(__value);
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ if __repeat_value.len() >= 1 {
+ Matched(__repeat_pos, ())
+ } else {
+ Failed
+ }
+ }
+ }
+ } {
+ Matched(__newpos, _) => {
+ Matched(__newpos, ())
+ }
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match slice_eq(
+ __input, __state, __pos, "0",
+ ) {
+ Matched(__newpos, _) => {
+ Matched(__newpos, ())
+ }
+ Failed => Matched(__pos, ()),
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match {
+ let __seq_res = slice_eq(
+ __input, __state,
+ __pos, ".",
+ );
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __choice_res = {
+ let __seq_res = {
+ let mut __repeat_pos =
+ __pos;
+ let mut __repeat_value =
+ vec![];
+ loop {
+ let __pos =
+ __repeat_pos;
+ let __step_res =
+ if __input.len()
+ > __pos
+ {
+ let ( __ch , __next ) = char_range_at ( __input , __pos ) ;
+ match __ch { 'A' ... 'Z' | 'a' ... 'z' | '0' ... '9' | '_' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[A-Za-z0-9_]" ) , }
+ } else {
+ __state . mark_failure ( __pos , "[A-Za-z0-9_]" )
+ };
+ match __step_res {
+ Matched(
+ __newpos,
+ __value,
+ ) => {
+ __repeat_pos = __newpos ;
+ __repeat_value . push ( __value ) ;
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ if __repeat_value.len()
+ >= 1
+ {
+ Matched(
+ __repeat_pos,
+ (),
+ )
+ } else {
+ Failed
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ slice_eq(
+ __input,
+ __state, __pos,
+ "$",
+ )
+ }
+ Failed => Failed,
+ }
+ };
+ match __choice_res {
+ Matched(
+ __pos,
+ __value,
+ ) => Matched(
+ __pos,
+ __value,
+ ),
+ Failed => {
+ let __choice_res = {
+ let mut __repeat_pos =
+ __pos;
+ let mut __repeat_value = vec![];
+ loop {
+ let __pos = __repeat_pos ;
+ let __step_res =
+ if __input
+ .len()
+ > __pos
+ {
+ let ( __ch , __next ) = char_range_at ( __input , __pos ) ;
+ match __ch { '0' ... '9' => Matched ( __next , ( ) ) , _ => __state . mark_failure ( __pos , "[0-9]" ) , }
+ } else {
+ __state . mark_failure ( __pos , "[0-9]" )
+ };
+ match __step_res
+ {
+ Matched(
+ __newpos,
+ __value,
+ ) => {
+ __repeat_pos = __newpos ;
+ __repeat_value . push ( __value ) ;
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ if __repeat_value
+ .len()
+ >= 1
+ {
+ Matched ( __repeat_pos , ( ) )
+ } else {
+ Failed
+ }
+ };
+ match __choice_res {
+ Matched(
+ __pos,
+ __value,
+ ) => Matched(
+ __pos, __value,
+ ),
+ Failed => slice_eq(
+ __input,
+ __state, __pos,
+ "*",
+ ),
+ }
+ }
+ }
+ }
+ Failed => Failed,
+ }
+ } {
+ Matched(__newpos, _) => {
+ Matched(__newpos, ())
+ }
+ Failed => {
+ Matched(__pos, ())
+ }
+ };
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res =
+ match __parse_ty(
+ __input,
+ __state, __pos,
+ ) {
+ Matched(
+ __newpos,
+ __value,
+ ) => Matched(
+ __newpos,
+ Some(
+ __value,
+ ),
+ ),
+ Failed => {
+ Matched(
+ __pos,
+ None,
+ )
+ }
+ };
+ match __seq_res {
+ Matched(
+ __pos,
+ n,
+ ) => Matched(
+ __pos,
+ { n },
+ ),
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_all_placeholders<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<Vec<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = {
+ let mut __repeat_pos = __pos;
+ let mut __repeat_value = vec![];
+ loop {
+ let __pos = __repeat_pos;
+ let __step_res = {
+ let __choice_res = __parse_discard_doubles(__input, __state, __pos);
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => {
+ let __choice_res =
+ __parse_placeholder_inner(__input, __state, __pos);
+ match __choice_res {
+ Matched(__pos, __value) => Matched(__pos, __value),
+ Failed => __parse_discard_any(__input, __state, __pos),
+ }
+ }
+ }
+ };
+ match __step_res {
+ Matched(__newpos, __value) => {
+ __repeat_pos = __newpos;
+ __repeat_value.push(__value);
+ }
+ Failed => {
+ break;
+ }
+ }
+ }
+ Matched(__repeat_pos, __repeat_value)
+ };
+ match __seq_res {
+ Matched(__pos, x) => {
+ Matched(__pos, { x.into_iter().flat_map(|x| x).collect() })
+ }
+ Failed => Failed,
+ }
+ }
+}
+
+fn __parse_format<'input>(
+ __input: &'input str,
+ __state: &mut ParseState<'input>,
+ __pos: usize,
+) -> RuleResult<(Option<usize>, Option<&'input str>)> {
+ #![allow(non_snake_case, unused)]
+ {
+ let __seq_res = slice_eq(__input, __state, __pos, "{");
+ match __seq_res {
+ Matched(__pos, _) => {
+ let __seq_res = match __parse_arg(__input, __state, __pos) {
+ Matched(__newpos, __value) => Matched(__newpos, Some(__value)),
+ Failed => Matched(__pos, None),
+ };
+ match __seq_res {
+ Matched(__pos, n) => {
+ let __seq_res =
+ match __parse_format_spec(__input, __state, __pos) {
+ Matched(__newpos, __value) => {
+ Matched(__newpos, Some(__value))
+ }
+ Failed => Matched(__pos, None),
+ };
+ match __seq_res {
+ Matched(__pos, o) => {
+ let __seq_res = slice_eq(__input, __state, __pos, "}");
+ match __seq_res {
+ Matched(__pos, _) => {
+ Matched(__pos, { (n, o.and_then(|x| x)) })
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+ Failed => Failed,
+ }
+ }
+}
+
+pub fn all_placeholders<'input>(__input: &'input str) -> ParseResult<Vec<&'input str>> {
+ #![allow(non_snake_case, unused)]
+ let mut __state = ParseState::new();
+ match __parse_all_placeholders(__input, &mut __state, 0) {
+ Matched(__pos, __value) => {
+ if __pos == __input.len() {
+ return Ok(__value);
+ }
+ }
+ _ => {}
+ }
+ let (__line, __col) = pos_to_line(__input, __state.max_err_pos);
+ Err(ParseError {
+ line: __line,
+ column: __col,
+ offset: __state.max_err_pos,
+ expected: __state.expected,
+ })
+}
+
+pub fn format<'input>(
+ __input: &'input str,
+) -> ParseResult<(Option<usize>, Option<&'input str>)> {
+ #![allow(non_snake_case, unused)]
+ let mut __state = ParseState::new();
+ match __parse_format(__input, &mut __state, 0) {
+ Matched(__pos, __value) => {
+ if __pos == __input.len() {
+ return Ok(__value);
+ }
+ }
+ _ => {}
+ }
+ let (__line, __col) = pos_to_line(__input, __state.max_err_pos);
+ Err(ParseError {
+ line: __line,
+ column: __col,
+ offset: __state.max_err_pos,
+ expected: __state.expected,
+ })
+}
diff --git a/third_party/rust/derive_more/src/sum_like.rs b/third_party/rust/derive_more/src/sum_like.rs
new file mode 100644
index 0000000000..19c05dbe4c
--- /dev/null
+++ b/third_party/rust/derive_more/src/sum_like.rs
@@ -0,0 +1,60 @@
+use crate::utils::{
+ add_extra_ty_param_bound, add_extra_where_clauses, MultiFieldData, State,
+};
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{DeriveInput, Ident, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::new(
+ input,
+ trait_name,
+ quote!(::core::iter),
+ trait_name.to_lowercase(),
+ )?;
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ trait_path,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let op_trait_name = if trait_name == "Sum" { "Add" } else { "Mul" };
+ let op_trait_ident = Ident::new(op_trait_name, Span::call_site());
+ let op_path = quote!(::core::ops::#op_trait_ident);
+ let op_method_ident =
+ Ident::new(&(op_trait_name.to_lowercase()), Span::call_site());
+ let type_params: Vec<_> = input
+ .generics
+ .type_params()
+ .map(|t| t.ident.clone())
+ .collect();
+ let generics = if type_params.is_empty() {
+ input.generics.clone()
+ } else {
+ let generic_type = quote!(<#(#type_params),*>);
+ let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
+ let operator_where_clause = quote! {
+ where #input_type#generic_type: #op_path<Output=#input_type#generic_type>
+ };
+ add_extra_where_clauses(&generics, operator_where_clause)
+ };
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let initializers: Vec<_> = field_types
+ .iter()
+ .map(|field_type| quote!(#trait_path::#method_ident(::core::iter::empty::<#field_type>())))
+ .collect();
+ let identity = multi_field_data.initializer(&initializers);
+
+ Ok(quote!(
+ impl#impl_generics #trait_path for #input_type#ty_generics #where_clause {
+ #[inline]
+ fn #method_ident<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
+ iter.fold(#identity, #op_path::#op_method_ident)
+ }
+ }
+ ))
+}
diff --git a/third_party/rust/derive_more/src/try_into.rs b/third_party/rust/derive_more/src/try_into.rs
new file mode 100644
index 0000000000..66ff7a26e6
--- /dev/null
+++ b/third_party/rust/derive_more/src/try_into.rs
@@ -0,0 +1,120 @@
+use crate::utils::{
+ add_extra_generic_param, numbered_vars, AttrParams, DeriveType, MultiFieldData,
+ State,
+};
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use std::collections::HashMap;
+use syn::{DeriveInput, Result};
+
+/// Provides the hook to expand `#[derive(TryInto)]` into an implementation of `TryInto`
+#[allow(clippy::cognitive_complexity)]
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ quote!(::core::convert),
+ String::from("try_into"),
+ AttrParams {
+ enum_: vec!["ignore", "owned", "ref", "ref_mut"],
+ variant: vec!["ignore", "owned", "ref", "ref_mut"],
+ struct_: vec!["ignore", "owned", "ref", "ref_mut"],
+ field: vec!["ignore"],
+ },
+ )?;
+ if state.derive_type != DeriveType::Enum {
+ panic!("Only enums can derive TryInto");
+ }
+
+ let mut variants_per_types = HashMap::new();
+
+ for variant_state in state.enabled_variant_data().variant_states {
+ let multi_field_data = variant_state.enabled_fields_data();
+ let MultiFieldData {
+ variant_info,
+ field_types,
+ ..
+ } = multi_field_data.clone();
+ for ref_type in variant_info.ref_types() {
+ variants_per_types
+ .entry((ref_type, field_types.clone()))
+ .or_insert_with(Vec::new)
+ .push(multi_field_data.clone());
+ }
+ }
+
+ let mut tokens = TokenStream::new();
+
+ for ((ref_type, ref original_types), ref multi_field_datas) in variants_per_types {
+ let input_type = &input.ident;
+
+ let pattern_ref = ref_type.pattern_ref();
+ let lifetime = ref_type.lifetime();
+ let reference_with_lifetime = ref_type.reference_with_lifetime();
+
+ let mut matchers = vec![];
+ let vars = &numbered_vars(original_types.len(), "");
+ for multi_field_data in multi_field_datas {
+ let patterns: Vec<_> =
+ vars.iter().map(|var| quote!(#pattern_ref #var)).collect();
+ matchers.push(
+ multi_field_data.matcher(&multi_field_data.field_indexes, &patterns),
+ );
+ }
+
+ let vars = if vars.len() == 1 {
+ quote!(#(#vars)*)
+ } else {
+ quote!((#(#vars),*))
+ };
+
+ let output_type = if original_types.len() == 1 {
+ format!("{}", quote!(#(#original_types)*))
+ } else {
+ let types = original_types
+ .iter()
+ .map(|t| format!("{}", quote!(#t)))
+ .collect::<Vec<_>>();
+ format!("({})", types.join(", "))
+ };
+ let variant_names = multi_field_datas
+ .iter()
+ .map(|d| {
+ format!(
+ "{}",
+ d.variant_name.expect("Somehow there was no variant name")
+ )
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+ let message =
+ format!("Only {} can be converted to {}", variant_names, output_type);
+
+ let generics_impl;
+ let (_, ty_generics, where_clause) = input.generics.split_for_impl();
+ let (impl_generics, _, _) = if ref_type.is_ref() {
+ generics_impl = add_extra_generic_param(&input.generics, lifetime.clone());
+ generics_impl.split_for_impl()
+ } else {
+ input.generics.split_for_impl()
+ };
+
+ let try_from = quote! {
+ impl#impl_generics ::core::convert::TryFrom<#reference_with_lifetime #input_type#ty_generics> for
+ (#(#reference_with_lifetime #original_types),*) #where_clause {
+ type Error = &'static str;
+
+ #[allow(unused_variables)]
+ #[inline]
+ fn try_from(value: #reference_with_lifetime #input_type#ty_generics) -> ::core::result::Result<Self, Self::Error> {
+ match value {
+ #(#matchers)|* => ::core::result::Result::Ok(#vars),
+ _ => ::core::result::Result::Err(#message),
+ }
+ }
+ }
+ };
+ try_from.to_tokens(&mut tokens)
+ }
+ Ok(tokens)
+}
diff --git a/third_party/rust/derive_more/src/utils.rs b/third_party/rust/derive_more/src/utils.rs
new file mode 100644
index 0000000000..2e9b8873fa
--- /dev/null
+++ b/third_party/rust/derive_more/src/utils.rs
@@ -0,0 +1,929 @@
+#![cfg_attr(not(feature = "default"), allow(dead_code))]
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, ToTokens};
+use syn::{
+ parse::{Error, Result},
+ parse_str,
+ spanned::Spanned,
+ Attribute, Data, DeriveInput, Field, Fields, FieldsNamed, FieldsUnnamed,
+ GenericParam, Generics, Ident, ImplGenerics, Index, Meta, NestedMeta, Type,
+ TypeGenerics, TypeParamBound, Variant, WhereClause,
+};
+
+#[derive(Clone, Copy, Eq, PartialEq, Hash)]
+pub enum RefType {
+ No,
+ Ref,
+ Mut,
+}
+
+impl RefType {
+ pub fn lifetime(self) -> TokenStream {
+ match self {
+ RefType::No => quote!(),
+ _ => quote!('__deriveMoreLifetime),
+ }
+ }
+
+ pub fn reference(self) -> TokenStream {
+ match self {
+ RefType::No => quote!(),
+ RefType::Ref => quote!(&),
+ RefType::Mut => quote!(&mut),
+ }
+ }
+
+ pub fn mutability(self) -> TokenStream {
+ match self {
+ RefType::Mut => quote!(mut),
+ _ => quote!(),
+ }
+ }
+
+ pub fn pattern_ref(self) -> TokenStream {
+ match self {
+ RefType::Ref => quote!(ref),
+ RefType::Mut => quote!(ref mut),
+ RefType::No => quote!(),
+ }
+ }
+
+ pub fn reference_with_lifetime(self) -> TokenStream {
+ if !self.is_ref() {
+ return quote!();
+ }
+ let lifetime = self.lifetime();
+ let mutability = self.mutability();
+ quote!(&#lifetime #mutability)
+ }
+
+ pub fn is_ref(self) -> bool {
+ match self {
+ RefType::No => false,
+ _ => true,
+ }
+ }
+}
+
+pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
+ (0..count)
+ .map(|i| Ident::new(&format!("__{}{}", prefix, i), Span::call_site()))
+ .collect()
+}
+
+pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
+ fields
+ .iter()
+ .map(|f| {
+ f.ident
+ .as_ref()
+ .expect("Tried to get field names of a tuple struct")
+ })
+ .collect()
+}
+
+pub fn get_field_types_iter<'a>(
+ fields: &'a [&'a Field],
+) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
+ Box::new(fields.iter().map(|f| &f.ty))
+}
+
+pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
+ get_field_types_iter(fields).collect()
+}
+
+pub fn add_extra_type_param_bound_op_output<'a>(
+ generics: &'a Generics,
+ trait_ident: &'a Ident,
+) -> Generics {
+ let mut generics = generics.clone();
+ for type_param in &mut generics.type_params_mut() {
+ let type_ident = &type_param.ident;
+ let bound: TypeParamBound = parse_str(
+ &quote!(::core::ops::#trait_ident<Output=#type_ident>).to_string(),
+ )
+ .unwrap();
+ type_param.bounds.push(bound)
+ }
+
+ generics
+}
+
+pub fn add_extra_ty_param_bound_op<'a>(
+ generics: &'a Generics,
+ trait_ident: &'a Ident,
+) -> Generics {
+ add_extra_ty_param_bound(generics, &quote!(::core::ops::#trait_ident))
+}
+
+pub fn add_extra_ty_param_bound<'a>(
+ generics: &'a Generics,
+ bound: &'a TokenStream,
+) -> Generics {
+ let mut generics = generics.clone();
+ let bound: TypeParamBound = parse_str(&bound.to_string()).unwrap();
+ for type_param in &mut generics.type_params_mut() {
+ type_param.bounds.push(bound.clone())
+ }
+
+ generics
+}
+
+pub fn add_extra_ty_param_bound_ref<'a>(
+ generics: &'a Generics,
+ bound: &'a TokenStream,
+ ref_type: RefType,
+) -> Generics {
+ match ref_type {
+ RefType::No => add_extra_ty_param_bound(generics, bound),
+ _ => {
+ let generics = generics.clone();
+ let idents = generics.type_params().map(|x| &x.ident);
+ let ref_with_lifetime = ref_type.reference_with_lifetime();
+ add_extra_where_clauses(
+ &generics,
+ quote!(
+ where #(#ref_with_lifetime #idents: #bound),*
+ ),
+ )
+ }
+ }
+}
+
+pub fn add_extra_generic_param(
+ generics: &Generics,
+ generic_param: TokenStream,
+) -> Generics {
+ let generic_param: GenericParam = parse_str(&generic_param.to_string()).unwrap();
+ let mut generics = generics.clone();
+ generics.params.push(generic_param);
+
+ generics
+}
+
+pub fn add_extra_where_clauses(
+ generics: &Generics,
+ type_where_clauses: TokenStream,
+) -> Generics {
+ let mut type_where_clauses: WhereClause =
+ parse_str(&type_where_clauses.to_string()).unwrap();
+ let mut new_generics = generics.clone();
+ if let Some(old_where) = new_generics.where_clause {
+ type_where_clauses.predicates.extend(old_where.predicates)
+ }
+ new_generics.where_clause = Some(type_where_clauses);
+
+ new_generics
+}
+
+pub fn add_where_clauses_for_new_ident<'a>(
+ generics: &'a Generics,
+ fields: &[&'a Field],
+ type_ident: &Ident,
+ type_where_clauses: TokenStream,
+ sized: bool,
+) -> Generics {
+ let generic_param = if fields.len() > 1 {
+ quote!(#type_ident: ::core::marker::Copy)
+ } else if sized {
+ quote!(#type_ident)
+ } else {
+ quote!(#type_ident: ?::core::marker::Sized)
+ };
+
+ let generics = add_extra_where_clauses(generics, type_where_clauses);
+ add_extra_generic_param(&generics, generic_param)
+}
+
+pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
+ fields.unnamed.iter().collect()
+}
+
+pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
+ fields.named.iter().collect()
+}
+
+fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
+ panic!(format!(
+ "derive({}) only works when forwarding to a single field. Try putting #[{}] or #[{}(ignore)] on the fields in the struct",
+ trait_name, trait_attr, trait_attr,
+ ))
+}
+
+#[derive(PartialEq, Eq)]
+pub enum DeriveType {
+ Unnamed,
+ Named,
+ Enum,
+}
+
+pub struct State<'input> {
+ pub input: &'input DeriveInput,
+ pub trait_name: &'static str,
+ pub trait_ident: Ident,
+ pub method_ident: Ident,
+ pub trait_module: TokenStream,
+ pub trait_path: TokenStream,
+ pub trait_path_params: Vec<TokenStream>,
+ pub trait_attr: String,
+ pub derive_type: DeriveType,
+ pub fields: Vec<&'input Field>,
+ pub variants: Vec<&'input Variant>,
+ pub variant_states: Vec<State<'input>>,
+ pub variant: Option<&'input Variant>,
+ pub generics: Generics,
+ pub default_info: FullMetaInfo,
+ full_meta_infos: Vec<FullMetaInfo>,
+}
+
+#[derive(Default, Clone)]
+pub struct AttrParams {
+ pub enum_: Vec<&'static str>,
+ pub variant: Vec<&'static str>,
+ pub struct_: Vec<&'static str>,
+ pub field: Vec<&'static str>,
+}
+
+impl AttrParams {
+ pub fn new(params: Vec<&'static str>) -> AttrParams {
+ AttrParams {
+ enum_: params.clone(),
+ struct_: params.clone(),
+ variant: params.clone(),
+ field: params,
+ }
+ }
+ pub fn struct_(params: Vec<&'static str>) -> AttrParams {
+ AttrParams {
+ enum_: vec![],
+ struct_: params,
+ variant: vec![],
+ field: vec![],
+ }
+ }
+}
+
+impl<'input> State<'input> {
+ pub fn new<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::with_attr_params(
+ input,
+ trait_name,
+ trait_module,
+ trait_attr,
+ AttrParams::default(),
+ )
+ }
+
+ pub fn with_field_ignore<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::with_attr_params(
+ input,
+ trait_name,
+ trait_module,
+ trait_attr,
+ AttrParams::new(vec!["ignore"]),
+ )
+ }
+
+ pub fn with_field_ignore_and_forward<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::with_attr_params(
+ input,
+ trait_name,
+ trait_module,
+ trait_attr,
+ AttrParams::new(vec!["ignore", "forward"]),
+ )
+ }
+
+ pub fn with_field_ignore_and_refs<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::with_attr_params(
+ input,
+ trait_name,
+ trait_module,
+ trait_attr,
+ AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]),
+ )
+ }
+
+ pub fn with_attr_params<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ ) -> Result<State<'arg_input>> {
+ let trait_name = trait_name.trim_end_matches("ToInner");
+ let trait_ident = Ident::new(trait_name, Span::call_site());
+ let method_ident = Ident::new(&trait_attr, Span::call_site());
+ let trait_path = quote!(#trait_module::#trait_ident);
+ let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ (DeriveType::Unnamed, unnamed_to_vec(fields), vec![])
+ }
+
+ Fields::Named(ref fields) => {
+ (DeriveType::Named, named_to_vec(fields), vec![])
+ }
+ Fields::Unit => (DeriveType::Named, vec![], vec![]),
+ },
+ Data::Enum(ref data_enum) => (
+ DeriveType::Enum,
+ vec![],
+ data_enum.variants.iter().collect(),
+ ),
+ Data::Union(_) => {
+ panic!(format!("can not derive({}) for union", trait_name))
+ }
+ };
+ let attrs: Vec<_> = if derive_type == DeriveType::Enum {
+ variants.iter().map(|v| &v.attrs).collect()
+ } else {
+ fields.iter().map(|f| &f.attrs).collect()
+ };
+
+ let (allowed_attr_params_outer, allowed_attr_params_inner) =
+ if derive_type == DeriveType::Enum {
+ (&allowed_attr_params.enum_, &allowed_attr_params.variant)
+ } else {
+ (&allowed_attr_params.struct_, &allowed_attr_params.field)
+ };
+
+ let struct_meta_info =
+ get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?;
+ let meta_infos: Result<Vec<_>> = attrs
+ .iter()
+ .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner))
+ .collect();
+ let meta_infos = meta_infos?;
+ let first_match = meta_infos
+ .iter()
+ .filter_map(|info| info.enabled.map(|_| info))
+ .next();
+
+ let defaults = struct_meta_info.to_full(FullMetaInfo {
+ // Default to enabled true, except when first attribute has explicit
+ // enabling
+ enabled: first_match.map_or(true, |info| !info.enabled.unwrap()),
+ forward: false,
+ // Default to owned true, except when first attribute has one of owned,
+ // ref or ref_mut
+ // - not a single attibute means default true
+ // - an attribute, but non of owned, ref or ref_mut means default true
+ // - an attribute, and owned, ref or ref_mut means default false
+ owned: first_match.map_or(true, |info| {
+ info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none()
+ }),
+ ref_: false,
+ ref_mut: false,
+ info: MetaInfo::default(),
+ });
+
+ let full_meta_infos: Vec<_> = meta_infos
+ .iter()
+ .map(|info| info.to_full(defaults))
+ .collect();
+
+ let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum {
+ variants
+ .iter()
+ .zip(full_meta_infos.iter().copied())
+ .map(|(variant, info)| {
+ State::from_variant(
+ input,
+ trait_name,
+ trait_module.clone(),
+ trait_attr.clone(),
+ allowed_attr_params.clone(),
+ variant,
+ info,
+ )
+ })
+ .collect()
+ } else {
+ Ok(vec![])
+ };
+ let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
+
+ Ok(State {
+ input,
+ trait_name,
+ trait_ident,
+ method_ident,
+ trait_module,
+ trait_path,
+ trait_path_params: vec![],
+ trait_attr,
+ // input,
+ fields,
+ variants,
+ variant_states: variant_states?,
+ variant: None,
+ derive_type,
+ generics,
+ full_meta_infos,
+ default_info: defaults,
+ })
+ }
+
+ pub fn from_variant<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_module: TokenStream,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ variant: &'arg_input Variant,
+ default_info: FullMetaInfo,
+ ) -> Result<State<'arg_input>> {
+ let trait_name = trait_name.trim_end_matches("ToInner");
+ let trait_ident = Ident::new(trait_name, Span::call_site());
+ let method_ident = Ident::new(&trait_attr, Span::call_site());
+ let trait_path = quote!(#trait_module::#trait_ident);
+ let (derive_type, fields): (_, Vec<_>) = match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ (DeriveType::Unnamed, unnamed_to_vec(fields))
+ }
+
+ Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
+ Fields::Unit => (DeriveType::Named, vec![]),
+ };
+
+ let meta_infos: Result<Vec<_>> = fields
+ .iter()
+ .map(|f| &f.attrs)
+ .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
+ .collect();
+ let meta_infos = meta_infos?;
+ let full_meta_infos: Vec<_> = meta_infos
+ .iter()
+ .map(|info| info.to_full(default_info))
+ .collect();
+
+ let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
+
+ Ok(State {
+ input,
+ trait_name,
+ trait_module,
+ trait_path,
+ trait_path_params: vec![],
+ trait_attr,
+ trait_ident,
+ method_ident,
+ // input,
+ fields,
+ variants: vec![],
+ variant_states: vec![],
+ variant: Some(variant),
+ derive_type,
+ generics,
+ full_meta_infos,
+ default_info,
+ })
+ }
+ pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
+ self.trait_path_params.push(param);
+ }
+
+ pub fn assert_single_enabled_field<'state>(
+ &'state self,
+ ) -> SingleFieldData<'input, 'state> {
+ if self.derive_type == DeriveType::Enum {
+ panic_one_field(self.trait_name, &self.trait_attr);
+ }
+ let data = self.enabled_fields_data();
+ if data.fields.len() != 1 {
+ panic_one_field(self.trait_name, &self.trait_attr);
+ };
+ SingleFieldData {
+ input_type: data.input_type,
+ field: data.fields[0],
+ field_type: data.field_types[0],
+ member: data.members[0].clone(),
+ info: data.infos[0],
+ field_ident: data.field_idents[0].clone(),
+ trait_path: data.trait_path,
+ trait_path_with_params: data.trait_path_with_params.clone(),
+ casted_trait: data.casted_traits[0].clone(),
+ impl_generics: data.impl_generics.clone(),
+ ty_generics: data.ty_generics.clone(),
+ where_clause: data.where_clause,
+ multi_field_data: data,
+ }
+ }
+
+ pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
+ if self.derive_type == DeriveType::Enum {
+ panic!(format!("can not derive({}) for enum", self.trait_name))
+ }
+ let fields = self.enabled_fields();
+ let field_idents = self.enabled_fields_idents();
+ let field_indexes = self.enabled_fields_indexes();
+ let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
+ let members: Vec<_> = field_idents
+ .iter()
+ .map(|ident| quote!(self.#ident))
+ .collect();
+ let trait_path = &self.trait_path;
+ let trait_path_with_params = if !self.trait_path_params.is_empty() {
+ let params = self.trait_path_params.iter();
+ quote!(#trait_path<#(#params),*>)
+ } else {
+ self.trait_path.clone()
+ };
+
+ let casted_traits: Vec<_> = field_types
+ .iter()
+ .map(|field_type| quote!(<#field_type as #trait_path_with_params>))
+ .collect();
+ let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
+ let input_type = &self.input.ident;
+ let (variant_name, variant_type) = self.variant.map_or_else(
+ || (None, quote!(#input_type)),
+ |v| {
+ let variant_name = &v.ident;
+ (Some(variant_name), quote!(#input_type::#variant_name))
+ },
+ );
+ MultiFieldData {
+ input_type,
+ variant_type,
+ variant_name,
+ variant_info: self.default_info,
+ fields,
+ field_types,
+ field_indexes,
+ members,
+ infos: self.enabled_infos(),
+ field_idents,
+ method_ident: &self.method_ident,
+ trait_path,
+ trait_path_with_params,
+ casted_traits,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ state: self,
+ }
+ }
+
+ pub fn enabled_variant_data<'state>(
+ &'state self,
+ ) -> MultiVariantData<'input, 'state> {
+ if self.derive_type != DeriveType::Enum {
+ panic!(format!("can only derive({}) for enum", self.trait_name))
+ }
+ let variants = self.enabled_variants();
+ let trait_path = &self.trait_path;
+ let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
+ MultiVariantData {
+ input_type: &self.input.ident,
+ variants,
+ variant_states: self.enabled_variant_states(),
+ infos: self.enabled_infos(),
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ }
+ }
+
+ fn enabled_variants(&self) -> Vec<&'input Variant> {
+ self.variants
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(v, _)| *v)
+ .collect()
+ }
+
+ fn enabled_variant_states(&self) -> Vec<&State<'input>> {
+ self.variant_states
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(v, _)| v)
+ .collect()
+ }
+
+ pub fn enabled_fields(&self) -> Vec<&'input Field> {
+ self.fields
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(f, _)| *f)
+ .collect()
+ }
+
+ fn field_idents(&self) -> Vec<TokenStream> {
+ if self.derive_type == DeriveType::Named {
+ self.fields
+ .iter()
+ .map(|f| {
+ f.ident
+ .as_ref()
+ .expect("Tried to get field names of a tuple struct")
+ .to_token_stream()
+ })
+ .collect()
+ } else {
+ let count = self.fields.len();
+ (0..count)
+ .map(|i| Index::from(i).to_token_stream())
+ .collect()
+ }
+ }
+
+ fn enabled_fields_idents(&self) -> Vec<TokenStream> {
+ self.field_idents()
+ .into_iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(f, _)| f)
+ .collect()
+ }
+
+ fn enabled_fields_indexes(&self) -> Vec<usize> {
+ self.full_meta_infos
+ .iter()
+ .map(|info| info.enabled)
+ .enumerate()
+ .filter(|(_, ig)| *ig)
+ .map(|(i, _)| i)
+ .collect()
+ }
+ fn enabled_infos(&self) -> Vec<FullMetaInfo> {
+ self.full_meta_infos
+ .iter()
+ .filter(|info| info.enabled)
+ .copied()
+ .collect()
+ }
+}
+
+#[derive(Clone)]
+pub struct SingleFieldData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub field: &'input Field,
+ pub field_type: &'input Type,
+ pub field_ident: TokenStream,
+ pub member: TokenStream,
+ pub info: FullMetaInfo,
+ pub trait_path: &'state TokenStream,
+ pub trait_path_with_params: TokenStream,
+ pub casted_trait: TokenStream,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+ multi_field_data: MultiFieldData<'input, 'state>,
+}
+
+#[derive(Clone)]
+pub struct MultiFieldData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub variant_type: TokenStream,
+ pub variant_name: Option<&'input Ident>,
+ pub variant_info: FullMetaInfo,
+ pub fields: Vec<&'input Field>,
+ pub field_types: Vec<&'input Type>,
+ pub field_idents: Vec<TokenStream>,
+ pub field_indexes: Vec<usize>,
+ pub members: Vec<TokenStream>,
+ pub infos: Vec<FullMetaInfo>,
+ pub method_ident: &'state Ident,
+ pub trait_path: &'state TokenStream,
+ pub trait_path_with_params: TokenStream,
+ pub casted_traits: Vec<TokenStream>,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+ pub state: &'state State<'input>,
+}
+
+pub struct MultiVariantData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub variants: Vec<&'input Variant>,
+ pub variant_states: Vec<&'state State<'input>>,
+ pub infos: Vec<FullMetaInfo>,
+ pub trait_path: &'state TokenStream,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+}
+
+impl<'input, 'state> MultiFieldData<'input, 'state> {
+ pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
+ let MultiFieldData {
+ variant_type,
+ field_idents,
+ ..
+ } = self;
+ if self.state.derive_type == DeriveType::Named {
+ quote!(#variant_type{#(#field_idents: #initializers),*})
+ } else {
+ quote!(#variant_type(#(#initializers),*))
+ }
+ }
+ pub fn matcher<T: ToTokens>(
+ &self,
+ indexes: &[usize],
+ bindings: &[T],
+ ) -> TokenStream {
+ let MultiFieldData { variant_type, .. } = self;
+ let full_bindings = (0..self.state.fields.len()).map(|i| {
+ indexes.iter().position(|index| i == *index).map_or_else(
+ || quote!(_),
+ |found_index| bindings[found_index].to_token_stream(),
+ )
+ });
+ if self.state.derive_type == DeriveType::Named {
+ let field_idents = self.state.field_idents();
+ quote!(#variant_type{#(#field_idents: #full_bindings),*})
+ } else {
+ quote!(#variant_type(#(#full_bindings),*))
+ }
+ }
+}
+
+impl<'input, 'state> SingleFieldData<'input, 'state> {
+ pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
+ self.multi_field_data.initializer(initializers)
+ }
+}
+
+fn get_meta_info(
+ trait_attr: &str,
+ attrs: &[Attribute],
+ allowed_attr_params: &[&'static str],
+) -> Result<MetaInfo> {
+ let mut it = attrs
+ .iter()
+ .filter_map(|m| m.parse_meta().ok())
+ .filter(|m| {
+ if let Some(ident) = m.path().segments.first().map(|p| &p.ident) {
+ ident == trait_attr
+ } else {
+ false
+ }
+ });
+ let mut info = MetaInfo {
+ enabled: None,
+ forward: None,
+ owned: None,
+ ref_: None,
+ ref_mut: None,
+ };
+
+ let meta = if let Some(meta) = it.next() {
+ meta
+ } else {
+ return Ok(info);
+ };
+
+ if allowed_attr_params.is_empty() {
+ return Err(Error::new(meta.span(), "Attribute is not allowed here"));
+ }
+
+ info.enabled = Some(true);
+
+ if let Some(meta2) = it.next() {
+ return Err(Error::new(
+ meta2.span(),
+ "Only a single attribute is allowed",
+ ));
+ }
+ let list = match meta.clone() {
+ Meta::Path(_) => {
+ if allowed_attr_params.contains(&"ignore") {
+ return Ok(info);
+ } else {
+ return Err(Error::new(meta.span(), format!("Empty attribute is not allowed, add one of the following parameters: {}",
+ allowed_attr_params.join(", ")
+ )));
+ }
+ }
+ Meta::List(list) => list,
+ _ => {
+ return Err(Error::new(meta.span(), "Attribute format not supported1"));
+ }
+ };
+ for element in list.nested.into_iter() {
+ let nested_meta = if let NestedMeta::Meta(meta) = element {
+ meta
+ } else {
+ return Err(Error::new(meta.span(), "Attribute format not supported3"));
+ };
+ if let Meta::Path(_) = nested_meta {
+ } else {
+ return Err(Error::new(meta.span(), "Attribute format not supported4"));
+ }
+ let ident = if let Some(ident) =
+ nested_meta.path().segments.first().map(|p| &p.ident)
+ {
+ ident
+ } else {
+ return Err(Error::new(meta.span(), "Attribute format not supported5"));
+ };
+
+ let str_ident: &str = &ident.to_string();
+ if !allowed_attr_params.contains(&str_ident) {
+ return Err(Error::new(
+ ident.span(),
+ format!(
+ "Attribute parameter not supported. Supported attribute parameters are: {}",
+ allowed_attr_params.join(", ")
+ ),
+ ));
+ }
+
+ match str_ident {
+ "ignore" => {
+ info.enabled = Some(false);
+ }
+ "forward" => {
+ info.forward = Some(true);
+ }
+ "owned" => {
+ info.owned = Some(true);
+ }
+ "ref" => {
+ info.ref_ = Some(true);
+ }
+ "ref_mut" => {
+ info.ref_mut = Some(true);
+ }
+ _ => {
+ return Err(Error::new(meta.span(), "Attribute format not supported7"));
+ }
+ }
+ }
+ Ok(info)
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FullMetaInfo {
+ pub enabled: bool,
+ pub forward: bool,
+ pub owned: bool,
+ pub ref_: bool,
+ pub ref_mut: bool,
+ pub info: MetaInfo,
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+pub struct MetaInfo {
+ pub enabled: Option<bool>,
+ pub forward: Option<bool>,
+ pub owned: Option<bool>,
+ pub ref_: Option<bool>,
+ pub ref_mut: Option<bool>,
+}
+
+impl MetaInfo {
+ fn to_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
+ let info = self;
+ FullMetaInfo {
+ enabled: self.enabled.unwrap_or(defaults.enabled),
+ forward: self.forward.unwrap_or(defaults.forward),
+ owned: self.owned.unwrap_or(defaults.owned),
+ ref_: self.ref_.unwrap_or(defaults.ref_),
+ ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
+ info,
+ }
+ }
+}
+
+impl FullMetaInfo {
+ pub fn ref_types(self) -> Vec<RefType> {
+ let mut ref_types = vec![];
+ if self.owned {
+ ref_types.push(RefType::No);
+ }
+ if self.ref_ {
+ ref_types.push(RefType::Ref);
+ }
+ if self.ref_mut {
+ ref_types.push(RefType::Mut);
+ }
+ ref_types
+ }
+}