summaryrefslogtreecommitdiff
path: root/vendor/educe
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/educe
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/educe')
-rw-r--r--vendor/educe/.cargo-checksum.json1
-rw-r--r--vendor/educe/Cargo.toml102
-rw-r--r--vendor/educe/LICENSE21
-rw-r--r--vendor/educe/README.md1689
-rw-r--r--vendor/educe/src/common/bound.rs57
-rw-r--r--vendor/educe/src/common/expr.rs109
-rw-r--r--vendor/educe/src/common/ident_bool.rs161
-rw-r--r--vendor/educe/src/common/ident_index.rs56
-rw-r--r--vendor/educe/src/common/int.rs63
-rw-r--r--vendor/educe/src/common/mod.rs43
-rw-r--r--vendor/educe/src/common/path.rs43
-rw-r--r--vendor/educe/src/common/tools/discriminant_type.rs169
-rw-r--r--vendor/educe/src/common/tools/hash_type.rs100
-rw-r--r--vendor/educe/src/common/tools/mod.rs11
-rw-r--r--vendor/educe/src/common/type.rs51
-rw-r--r--vendor/educe/src/common/unsafe_punctuated_meta.rs35
-rw-r--r--vendor/educe/src/common/where_predicates_bool.rs122
-rw-r--r--vendor/educe/src/lib.rs2135
-rw-r--r--vendor/educe/src/panic.rs130
-rw-r--r--vendor/educe/src/supported_traits.rs88
-rw-r--r--vendor/educe/src/trait_handlers/clone/clone_enum.rs272
-rw-r--r--vendor/educe/src/trait_handlers/clone/clone_struct.rs195
-rw-r--r--vendor/educe/src/trait_handlers/clone/clone_union.rs73
-rw-r--r--vendor/educe/src/trait_handlers/clone/mod.rs36
-rw-r--r--vendor/educe/src/trait_handlers/clone/models/field_attribute.rs125
-rw-r--r--vendor/educe/src/trait_handlers/clone/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/clone/models/type_attribute.rs140
-rw-r--r--vendor/educe/src/trait_handlers/copy/mod.rs94
-rw-r--r--vendor/educe/src/trait_handlers/copy/models/field_attribute.rs57
-rw-r--r--vendor/educe/src/trait_handlers/copy/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/copy/models/type_attribute.rs140
-rw-r--r--vendor/educe/src/trait_handlers/debug/common.rs55
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_enum.rs371
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_struct.rs185
-rw-r--r--vendor/educe/src/trait_handlers/debug/debug_union.rs86
-rw-r--r--vendor/educe/src/trait_handlers/debug/mod.rs38
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/field_attribute.rs224
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/debug/models/type_attribute.rs264
-rw-r--r--vendor/educe/src/trait_handlers/debug/panic.rs43
-rw-r--r--vendor/educe/src/trait_handlers/default/default_enum.rs230
-rw-r--r--vendor/educe/src/trait_handlers/default/default_struct.rs149
-rw-r--r--vendor/educe/src/trait_handlers/default/default_union.rs153
-rw-r--r--vendor/educe/src/trait_handlers/default/mod.rs43
-rw-r--r--vendor/educe/src/trait_handlers/default/models/field_attribute.rs166
-rw-r--r--vendor/educe/src/trait_handlers/default/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/default/models/type_attribute.rs214
-rw-r--r--vendor/educe/src/trait_handlers/default/panic.rs21
-rw-r--r--vendor/educe/src/trait_handlers/deref/deref_enum.rs144
-rw-r--r--vendor/educe/src/trait_handlers/deref/deref_struct.rs103
-rw-r--r--vendor/educe/src/trait_handlers/deref/mod.rs36
-rw-r--r--vendor/educe/src/trait_handlers/deref/models/field_attribute.rs94
-rw-r--r--vendor/educe/src/trait_handlers/deref/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/deref/models/type_attribute.rs87
-rw-r--r--vendor/educe/src/trait_handlers/deref/panic.rs31
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/deref_mut_enum.rs139
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/deref_mut_struct.rs92
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/mod.rs39
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/models/field_attribute.rs94
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/models/type_attribute.rs87
-rw-r--r--vendor/educe/src/trait_handlers/deref_mut/panic.rs31
-rw-r--r--vendor/educe/src/trait_handlers/eq/mod.rs106
-rw-r--r--vendor/educe/src/trait_handlers/eq/models/field_attribute.rs57
-rw-r--r--vendor/educe/src/trait_handlers/eq/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/eq/models/type_attribute.rs140
-rw-r--r--vendor/educe/src/trait_handlers/hash/hash_enum.rs169
-rw-r--r--vendor/educe/src/trait_handlers/hash/hash_struct.rs88
-rw-r--r--vendor/educe/src/trait_handlers/hash/hash_union.rs54
-rw-r--r--vendor/educe/src/trait_handlers/hash/mod.rs34
-rw-r--r--vendor/educe/src/trait_handlers/hash/models/field_attribute.rs172
-rw-r--r--vendor/educe/src/trait_handlers/hash/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/hash/models/type_attribute.rs154
-rw-r--r--vendor/educe/src/trait_handlers/hash/panic.rs22
-rw-r--r--vendor/educe/src/trait_handlers/into/common.rs17
-rw-r--r--vendor/educe/src/trait_handlers/into/into_enum.rs224
-rw-r--r--vendor/educe/src/trait_handlers/into/into_struct.rs168
-rw-r--r--vendor/educe/src/trait_handlers/into/mod.rs34
-rw-r--r--vendor/educe/src/trait_handlers/into/models/field_attribute.rs152
-rw-r--r--vendor/educe/src/trait_handlers/into/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/into/models/type_attribute.rs153
-rw-r--r--vendor/educe/src/trait_handlers/into/panic.rs27
-rw-r--r--vendor/educe/src/trait_handlers/mod.rs48
-rw-r--r--vendor/educe/src/trait_handlers/ord/mod.rs49
-rw-r--r--vendor/educe/src/trait_handlers/ord/models/field_attribute.rs217
-rw-r--r--vendor/educe/src/trait_handlers/ord/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/ord/models/type_attribute.rs149
-rw-r--r--vendor/educe/src/trait_handlers/ord/ord_enum.rs283
-rw-r--r--vendor/educe/src/trait_handlers/ord/ord_struct.rs123
-rw-r--r--vendor/educe/src/trait_handlers/ord/panic.rs6
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/mod.rs43
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/models/field_attribute.rs181
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/models/type_attribute.rs163
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/panic.rs22
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/partial_eq_enum.rs218
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/partial_eq_struct.rs103
-rw-r--r--vendor/educe/src/trait_handlers/partial_eq/partial_eq_union.rs63
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/mod.rs58
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/models/field_attribute.rs208
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/models/mod.rs5
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/models/type_attribute.rs140
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/panic.rs6
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/partial_ord_enum.rs276
-rw-r--r--vendor/educe/src/trait_handlers/partial_ord/partial_ord_struct.rs113
105 files changed, 13837 insertions, 0 deletions
diff --git a/vendor/educe/.cargo-checksum.json b/vendor/educe/.cargo-checksum.json
new file mode 100644
index 00000000..20ab6f7e
--- /dev/null
+++ b/vendor/educe/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"4766eea0979453ffefb7ca933f1e5e4e2d2f474b9c51e6e0103d06db91caf6c6","LICENSE":"dd0741aba702705d02da3e18fca5d3a27538fe6c983e9f09946e82ecfc59acab","README.md":"add20a05719136fcde338674fddd7bf580aad461d5e4029f4c4f05f0b53297d4","src/common/bound.rs":"ebd8cdeb6aeda3582277865bd3243d6e16e6213f4d477b0a7c65ebc274749a8b","src/common/expr.rs":"811dde58930460ff22151db4242c7a6e26d04a192e38bc7b56f05b002f2bbd0e","src/common/ident_bool.rs":"153db51a900ff1d4e0012417be091c486b71dd7078822b70ee1fcbcb3c6cdb66","src/common/ident_index.rs":"2451d8b8f667ea714384c164682849c4e61535c4f3d8f834405c1c6672350012","src/common/int.rs":"aab8c33cd8732ea3320002999e107d9d8a7140eafc8c93469ff02de7b3f6f7cb","src/common/mod.rs":"e11296217337d3c83a5a1c125a134c3ba34599cb5ec051b35f88cccdfd7f1b28","src/common/path.rs":"0f561bdd4401d50824af3792d92277944041da8da1da5e4b2245a49239f3d6b5","src/common/tools/discriminant_type.rs":"7f861cf559dc3f8e0c75c82e84db2c4fc5de9e7517ff380a6313c6b09e0e1284","src/common/tools/hash_type.rs":"9ce3603f8a3e7c416a9133be196e99280257b8256f4e94dc7b313772e8ee6a2b","src/common/tools/mod.rs":"71dfecf1d05ad890adc22e46e135eb4838935db851678ab6c0404d28b4c47c86","src/common/type.rs":"2e912da0f3a526045b5a6c70ab18d4a0e61241e3cb572f9085638e1352f74151","src/common/unsafe_punctuated_meta.rs":"47c3542567d5660490d957ba9ed794ad5c7fd4f78dc0cca38e4337eb32502bc1","src/common/where_predicates_bool.rs":"2b6d09fcafc9d527209ec41e028121abad4acf3389997eb50ca09bbbcf203a90","src/lib.rs":"e513a0ca4c4f044b95f2e1a440c83dbff4faab08e04b0c612348f752e146cce9","src/panic.rs":"65dd8260e84796d1492d5729c4c54d0d052086a83a98966f4b5a5dc44d1eddef","src/supported_traits.rs":"38d7b163bb5ff8b6c41b83e6ce955afae83702d47836a04dc7114d49275b33a4","src/trait_handlers/clone/clone_enum.rs":"9868b26d1af8ecbee21e93db4e640a4620d46c9372a80552743388a655247053","src/trait_handlers/clone/clone_struct.rs":"4ba5be359bc5472aa26f0f7a07c1362d9b6119bd605c459ff1c78678eb711fff","src/trait_handlers/clone/clone_union.rs":"2d1755b731d7e6589855834dc8f30852af2b0cafeb6ed26192c0783386faef7a","src/trait_handlers/clone/mod.rs":"e768a3e43b8ef704d7efbd91e1a56c2a2c3f1fca9ebaffb38263274ca4c3eb67","src/trait_handlers/clone/models/field_attribute.rs":"ccab133469f7a7828083c2080a4aa67f8fe53aeb32a2adb93a68c12878f800af","src/trait_handlers/clone/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/clone/models/type_attribute.rs":"46d07a430081ab3224b1af56c775cee57614237853723593f436c2835d941103","src/trait_handlers/copy/mod.rs":"3c563110af431c36a25e43ac4273478e96dbaab1eb748e3a6935fe0e3b7f6817","src/trait_handlers/copy/models/field_attribute.rs":"5ad968dc63f23fdb0e0e0def721abb3c21229cfe2adfd0017c948bb7cbeebe4d","src/trait_handlers/copy/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/copy/models/type_attribute.rs":"e2e259a95c738934bfaf178d633be743874e20ee737242d2fb236a3b16fe0d24","src/trait_handlers/debug/common.rs":"65c12424ca20dfe6f7ba5446a5d51a3450b7794c15148b78937ebf4c24e93d81","src/trait_handlers/debug/debug_enum.rs":"d051f6373d2a90a8f5667df0306635a065be1b47794b3e67390a53ccda270ba3","src/trait_handlers/debug/debug_struct.rs":"6faa9eea95540b7b5283d8544b0447de5dfa1fb15d5e0565c682ee08cdc40775","src/trait_handlers/debug/debug_union.rs":"ff1a8b7368f36ada030fe4bcee719a138ffaa34fbf480861dbef576d7db2e738","src/trait_handlers/debug/mod.rs":"135b71363732688aa9b83463224594096d7df6dafd527ba8909c20f38cfe3ff1","src/trait_handlers/debug/models/field_attribute.rs":"050186fea74e3c7a2e95ad832971effed8260cc58eac67d3053566a3c83d278b","src/trait_handlers/debug/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/debug/models/type_attribute.rs":"d77efa9e2773fdfdf2fe340f3f84a8d9a34579350ddeca1c2137c428148e4b33","src/trait_handlers/debug/panic.rs":"57fba8afef3c8f1aef268093cd4a2b28a6edc03a1ec10872db05a83c0c91a629","src/trait_handlers/default/default_enum.rs":"7b221914c9b117bec8e27d9774f4b127786270bc815085d8f01bbda071b31357","src/trait_handlers/default/default_struct.rs":"b7d90e940502ff923c37a360197de2bc36dd9538edd6f889c8b658da91acd4b0","src/trait_handlers/default/default_union.rs":"de5ae0ef615556a2e8df48be30e8d1adf95031ed4089cd8d8b4f7f155fa0a4c1","src/trait_handlers/default/mod.rs":"9f81e83e10d7f97507c24a5b2df386ff25a12dc202b67edda8ad8c8df139de3e","src/trait_handlers/default/models/field_attribute.rs":"b83367d493e1a4cb077c5d7025770574ed561ad88cf5aecd9ef6018a5d5bf591","src/trait_handlers/default/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/default/models/type_attribute.rs":"3b6ab4568eed1ba75ded43f500a4c997ba111966443e8b04948eb0e49fb427ea","src/trait_handlers/default/panic.rs":"b010ef9f4453529aa7fd04023a44a54353d5a50b5d35ce08f4a4740ba9c1a589","src/trait_handlers/deref/deref_enum.rs":"67097724ac28c63e969724f0be6181549107e89bed6ea6a7af04bc4f2d06b765","src/trait_handlers/deref/deref_struct.rs":"e8c1b9c7453b535886b4a881916d2a18a777e9eb817d35c2e331962116c9389e","src/trait_handlers/deref/mod.rs":"44f5cdf504e5dfd55547c65100bec58fc74eae6dbb30b353d5022b4c56e17c4c","src/trait_handlers/deref/models/field_attribute.rs":"163fc46106d141723c5b9e6cfe46bf0168feeb8a5f19f1c3f5f988cc4fc5b09a","src/trait_handlers/deref/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/deref/models/type_attribute.rs":"d47b316b9a98aefec2b23b4b0aed0a17f0b58de827f387a38942406c1a095580","src/trait_handlers/deref/panic.rs":"25a91ab6fd9cdd531cf031af8e2030a485ad8ac95408e12c8e977b584b95fefd","src/trait_handlers/deref_mut/deref_mut_enum.rs":"5f86602852b1aaa08d35274d7ba7a1f0fe6a557d2058d690025b170dd1e0244d","src/trait_handlers/deref_mut/deref_mut_struct.rs":"2fd425f6cf6ae6afd59f24f52573f26db151ee0a6dec7376a3f73118870fcead","src/trait_handlers/deref_mut/mod.rs":"834341a6408dfac16107b3d7f7f9c6af280282a8f3260b4170613c946f295351","src/trait_handlers/deref_mut/models/field_attribute.rs":"1020f9386bc61c9dd3981a0f06c0321a6be42efc8df06b7bb9bb4c9bc85adc6d","src/trait_handlers/deref_mut/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/deref_mut/models/type_attribute.rs":"94ea181e5db12b91160a1a9ca79beff368f39b530841dd0d0972e7913c7d8e5c","src/trait_handlers/deref_mut/panic.rs":"0dae99882da33d5e6e240ef34984510bed15879e7819d4a7d71cedbed9aaf2ab","src/trait_handlers/eq/mod.rs":"4a2cf1298b46def30d4b7dc3e19285cf72899de41aee7e49f6343e5f0ba2cc20","src/trait_handlers/eq/models/field_attribute.rs":"3f4cce6e2d70f3cf3fb6052846ec2aa7ce1b7062faf77a91aa4756bf4e0f52a8","src/trait_handlers/eq/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/eq/models/type_attribute.rs":"1fd7711a0d4f1a2e60e37d39c41a852d419e5f65b8f09da6746869403d283486","src/trait_handlers/hash/hash_enum.rs":"514fe5a51fba197cbac20b0c3bb2828c008a5f749362303ccce20951be647047","src/trait_handlers/hash/hash_struct.rs":"f99b96e05b8766c35a6678c2e8650b0cb9d540a41f583127ba63d06353ce3689","src/trait_handlers/hash/hash_union.rs":"b7f9c3f91f7c7274180786dee165029bcd98c7f532f54584faabdfc172c4cfb1","src/trait_handlers/hash/mod.rs":"31b1f3d6234ca55986439ad4f8ca4c02585714542dcffe751ecf59832d2d863f","src/trait_handlers/hash/models/field_attribute.rs":"5c79101520923717bb35def146302cda0349e02f6b4077068f011cd63285d6ba","src/trait_handlers/hash/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/hash/models/type_attribute.rs":"c50faea296196d9e229514fb8ebdd1bc423465910bc7e0f79a198db6e2252ceb","src/trait_handlers/hash/panic.rs":"0196124d6270c2be31362efe96f932eff17c984aab571f4e42384d3daac4fb65","src/trait_handlers/into/common.rs":"7b5c1705a5e31ca08affb04f9b8bf30303ceac91c7caf989f84003c0520064fd","src/trait_handlers/into/into_enum.rs":"5a10c0ceffbd3b09d11fb467da80834eac4d9a5a1f9797ba711ebc084d94ac2a","src/trait_handlers/into/into_struct.rs":"3de55470901a877d63c0fe2060bbfd78904e71b30ffd65bdee08ef043e9f878e","src/trait_handlers/into/mod.rs":"082fb060eb7ad2b8f230a07a76f308434ff4c65402eaff6c652f3e9ea9040f5e","src/trait_handlers/into/models/field_attribute.rs":"247189668e7cb44e1a22d505e65c35938b13fa0857ef29c2f261005c52ac9c94","src/trait_handlers/into/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/into/models/type_attribute.rs":"17b0375615ec60a2896475a1346fcbf0323c9918aab4cc7749e5d47c69996e75","src/trait_handlers/into/panic.rs":"f04509a7b7517318ce790ac2904a2477783ee79bdf14fc85fe41c367a6b12733","src/trait_handlers/mod.rs":"e8ccffa357491f4e5e131068c23c36f26dc6d41ab466d63821f4359c15189c84","src/trait_handlers/ord/mod.rs":"1c2e09467ef66f3ae748fe50efb90a3e04f1bd478430ac3d3a08136a2f7139ba","src/trait_handlers/ord/models/field_attribute.rs":"106cc919bc44e988189019d7feeeeab34d76be669c544540d264cd22b4723610","src/trait_handlers/ord/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/ord/models/type_attribute.rs":"5111e7a5ffa01dbc16f1581bea631f57ded336f2237932cea176e70371eef60a","src/trait_handlers/ord/ord_enum.rs":"1373c789044e26c59d52ab973d623707ba87b98f60381a4bfc8793239e6971ee","src/trait_handlers/ord/ord_struct.rs":"67b677243a1d61e7472200d2b5b5af64cec357e45c4a49cac35dbcba9c611077","src/trait_handlers/ord/panic.rs":"55e35c24c12b37d52adcac88351c1dc15526c598f0e2beb37ea56e8fd8fd95ac","src/trait_handlers/partial_eq/mod.rs":"a2151a1e08fe7b94544ccfe1116ccecb45920a19cb1664c53cc24de8b8667dc6","src/trait_handlers/partial_eq/models/field_attribute.rs":"c5e05a5013f27d3d76ce3234d480ef60d6aa3825c7b7fee003b3f12bf15c1e35","src/trait_handlers/partial_eq/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/partial_eq/models/type_attribute.rs":"ce22f9247f55b74d33ca5f5338f000249830bea3a47a5e2dc9a9ede6eaece657","src/trait_handlers/partial_eq/panic.rs":"01dfb76792d0e011487d5e22842387021cc5ae5c6805bfd298dfdbbbe42fd9e9","src/trait_handlers/partial_eq/partial_eq_enum.rs":"1d54e4ab9254e4b575e9a698c6fcd52f4bb77ba15bd92061dd6aaf795a091f40","src/trait_handlers/partial_eq/partial_eq_struct.rs":"023bcbac35f4f9a007123c79d1ee1b0ab14a9bcb9f7451c1ae141e8c52fbdc6d","src/trait_handlers/partial_eq/partial_eq_union.rs":"5623847e356e45cde1fcbb1c06e45048b3f96af375cb6b86afb184a56fe23e0b","src/trait_handlers/partial_ord/mod.rs":"9b80e49ee029512a8b65d45e559c465b09a58cea89ff2ca0b313f09c3ce3cdbf","src/trait_handlers/partial_ord/models/field_attribute.rs":"7f08dccb0b991e73f83ce79c1890e2e9da6875b91bd4d66b7477a0d2e9e75bae","src/trait_handlers/partial_ord/models/mod.rs":"22b2ef0fc575723df26a2b6d724b92e4a2dedaf51dcc87878308ba0bc3af9dbc","src/trait_handlers/partial_ord/models/type_attribute.rs":"1a5c2c462ea86989f11598f7f4c87856c0f41ae643e935d9404dd51cf521c444","src/trait_handlers/partial_ord/panic.rs":"55e35c24c12b37d52adcac88351c1dc15526c598f0e2beb37ea56e8fd8fd95ac","src/trait_handlers/partial_ord/partial_ord_enum.rs":"b640eab9e5e161f63fc748fcb27125bd289cde4ad9407d4314aede8daef672f6","src/trait_handlers/partial_ord/partial_ord_struct.rs":"6e45ed93f5607fb050136bfd4f4199e5a9781f3af6ec0b642c033a59170b7efe"},"package":"1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417"} \ No newline at end of file
diff --git a/vendor/educe/Cargo.toml b/vendor/educe/Cargo.toml
new file mode 100644
index 00000000..ae93dbc3
--- /dev/null
+++ b/vendor/educe/Cargo.toml
@@ -0,0 +1,102 @@
+# 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 are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.60"
+name = "educe"
+version = "0.6.0"
+authors = ["Magic Len <len@magiclen.org>"]
+include = [
+ "src/**/*",
+ "Cargo.toml",
+ "README.md",
+ "LICENSE",
+]
+description = "This crate offers procedural macros designed to facilitate the swift implementation of Rust's built-in traits."
+homepage = "https://magiclen.org/educe"
+readme = "README.md"
+keywords = [
+ "derive",
+ "macro",
+ "trait",
+ "field",
+ "procedural",
+]
+categories = [
+ "no-std",
+ "rust-patterns",
+]
+license = "MIT"
+repository = "https://github.com/magiclen/educe"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[lib]
+proc-macro = true
+
+[dependencies.enum-ordinalize]
+version = "4.2"
+features = ["derive"]
+default-features = false
+
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "2"
+
+[dev-dependencies.assert-eq-float]
+version = "0.1"
+
+[dev-dependencies.rustversion]
+version = "1"
+
+[dev-dependencies.syn]
+version = "2"
+features = ["full"]
+
+[features]
+Clone = []
+Copy = []
+Debug = []
+Default = []
+Deref = []
+DerefMut = []
+Eq = []
+Hash = []
+Into = []
+Ord = []
+PartialEq = []
+PartialOrd = []
+default = [
+ "Debug",
+ "Clone",
+ "Copy",
+ "PartialEq",
+ "Eq",
+ "PartialOrd",
+ "Ord",
+ "Hash",
+ "Default",
+ "Deref",
+ "DerefMut",
+ "Into",
+]
+full = ["syn/full"]
diff --git a/vendor/educe/LICENSE b/vendor/educe/LICENSE
new file mode 100644
index 00000000..ba1efc6c
--- /dev/null
+++ b/vendor/educe/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 magiclen.org (Ron Li)
+
+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/vendor/educe/README.md b/vendor/educe/README.md
new file mode 100644
index 00000000..5f266ac8
--- /dev/null
+++ b/vendor/educe/README.md
@@ -0,0 +1,1689 @@
+Educe
+====================
+
+[![CI](https://github.com/magiclen/educe/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/educe/actions/workflows/ci.yml)
+
+This crate offers procedural macros designed to facilitate the swift implementation of Rust's built-in traits.
+
+## Features
+
+By default, every trait this crate supports will be enabled. You can disable all of them by turning off the default features and enable only the traits that you want to use by adding them to the `features` explicitly.
+
+For example,
+
+```toml
+[dependencies.educe]
+version = "*"
+features = ["Debug", "Clone", "Copy", "Hash", "Default"]
+default-features = false
+```
+
+## Traits
+
+#### Debug
+
+Use `#[derive(Educe)]` and `#[educe(Debug)]` to implement the `Debug` trait for a struct, enum, or union. This allows you to modify the names of your types, variants, and fields. You can also choose to ignore specific fields or set a method to replace the `Debug` trait. Additionally, you have the option to format a struct as a tuple and vice versa.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Change the Name of a Type, a Variant or a Field
+
+The `name` parameter can rename a type, a variant or a field. If you set it to `false`, the name can be ignored or forced to show otherwise.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(name(Struct2)))]
+struct Struct {
+ #[educe(Debug(name(f)))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug(name = true))]
+enum Enum {
+ #[educe(Debug(name = false))]
+ V1,
+ #[educe(Debug(name(V)))]
+ V2 {
+ #[educe(Debug(name(f)))]
+ f1: u8,
+ },
+ #[educe(Debug(name = false))]
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+struct Struct {
+ #[educe(Debug(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Debug(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Debug(ignore))]
+ u8
+ ),
+}
+```
+
+###### Fake Structs and Tuples
+
+With the `named_field` parameter, structs can be formatted as tuples and tuples can be formatted as structs.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(named_field = false))]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ #[educe(Debug(named_field = false))]
+ V2 {
+ f1: u8,
+ },
+ #[educe(Debug(named_field = true))]
+ V3(
+ u8,
+ #[educe(Debug(name(value)))]
+ i32
+ ),
+}
+```
+
+###### Use Another Method to Handle the Formatting
+
+The `method` parameter can be utilized to replace the implementation of the `Debug` trait for a field, eliminating the need to implement the `Debug` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+use std::fmt::{self, Formatter};
+
+fn fmt<T>(_s: &T, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("Hi")
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum<T> {
+ V1,
+ V2 {
+ #[educe(Debug(method(fmt)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Debug(method(std::fmt::UpperHex::fmt)))]
+ u8,
+ #[educe(Debug(method(fmt)))]
+ T
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `Debug` Trait or Others
+
+Generic parameters will be automatically bound to the `Debug` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+use std::fmt::{self, Formatter};
+
+fn fmt<D>(_s: &D, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("Hi")
+}
+
+#[derive(Educe)]
+#[educe(Debug(bound(T: std::fmt::Debug)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Debug(method(fmt)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+In the above case, `T` is bound to the `Debug` trait, but `K` is not.
+
+Or, you can have `educe` replicate the behaviour of `std`'s `derive`'s, where a bound is produced for *every* generic parameter, without regard to how it's used in the structure:
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(bound(*)))]
+struct Struct<T> {
+ #[educe(Debug(ignore))]
+ f: T,
+}
+```
+
+This can be useful if you don't want to make the trait implementation part of your permanent public API. In this example, `Struct<T>` doesn't implement `Debug` unless `T` does. I.e., it has a `T: Debug` bound even though that's not needed right now. Later we might want to display `f`; we wouldn't then need to make a breaking API change by adding the bound.
+
+This was the behaviour of `Trait(bound)` in educe 0.4.x and earlier.
+
+###### Union
+
+A union will be formatted as a `u8` slice because we don't know its fields at runtime. The fields of a union cannot be ignored, renamed, or formatted with other methods. The implementation is **unsafe** because it may expose uninitialized memory.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32,
+}
+```
+
+#### Clone
+
+Use `#[derive(Educe)]` and `#[educe(Clone)]` to implement the `Clone` trait for a struct, an enum, or a union. You can set a method to replace the `Clone` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Clone)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Use Another Method to Perform Cloning
+
+The `method` parameter can be utilized to replace the implementation of the `Clone` trait for a field, eliminating the need to implement the `Clone` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+fn clone(v: &u8) -> u8 {
+ v + 100
+}
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone2<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Clone(method(clone2)))]
+ T
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `Clone` Trait or Others
+
+Generic parameters will be automatically bound to the `Clone` trait if necessary. If the `#[educe(Copy)]` attribute exists, they will be bound to the `Copy` trait.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone(bound(T: std::clone::Clone)))]
+enum Enum<T, K: A> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+In the above case, `T` is bound to the `Clone` trait, but `K` is not.
+
+Or, you can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone(bound(*)))]
+struct Struct<T: A> {
+ #[educe(Clone(method(clone)))]
+ f: T,
+}
+```
+
+###### Union
+
+Refer to the introduction of the `#[educe(Copy)]` attribute.
+
+#### Copy
+
+Use `#[derive(Educe)]` and `#[educe(Copy)]` to implement the `Copy` trait for a struct, an enum, or a union.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Generic Parameters Bound to the `Copy` Trait or Others
+
+All generic parameters will be automatically bound to the `Copy` trait.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Copy, Clone(bound(T: Copy, K: A + Copy)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Note that utilizing custom cloning methods for a type that implements the `Copy` and `Clone` traits may not be entirely appropriate.
+
+###### Union
+
+The `#[educe(Copy, Clone)]` attribute can be used for a union. The fields of a union cannot be cloned with other methods.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+union Union {
+ f1: u8,
+}
+```
+
+#### PartialEq
+
+Use `#[derive(Educe)]` and `#[educe(PartialEq)]` to implement the `PartialEq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+struct Struct {
+ #[educe(PartialEq(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(PartialEq(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialEq(ignore))]
+ u8
+ ),
+}
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `PartialEq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+fn eq(a: &u8, b: &u8) -> bool {
+ a + 1 == *b
+}
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq2<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(PartialEq(method(eq)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialEq(method(eq2)))]
+ T
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `PartialEq` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialEq` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialEq(method(eq)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+In the above case, `T` is bound to the `PartialEq` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(*)))]
+struct Struct<T> {
+ #[educe(PartialEq(ignore))]
+ f: T,
+}
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe))]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32
+}
+```
+
+#### Eq
+
+Use `#[derive(Educe)]` and `#[educe(Eq)]` to implement the `Eq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+struct Struct {
+ #[educe(Eq(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Eq(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Eq(ignore))]
+ u8
+ ),
+}
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `Eq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+fn eq(a: &u8, b: &u8) -> bool {
+ a + 1 == *b
+}
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq2<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Eq(method(eq)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Eq(method(eq2)))]
+ T
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `PartialEq` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialEq` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)), Eq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Eq(method(eq)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe), Eq)]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe), Eq)]
+union Union {
+ f1: u8,
+ f2: i32
+}
+```
+
+#### PartialOrd
+
+Use `#[derive(Educe)]` and `#[educe(PartialOrd)]` to implement the `PartialOrd` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `PartialOrd` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ #[educe(PartialOrd(ignore))]
+ f1: u8
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(PartialOrd(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialOrd(ignore))]
+ u8
+ ),
+}
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `PartialOrd` trait for a field, eliminating the need to implement the `PartialOrd` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+fn partial_cmp(a: &u8, b: &u8) -> Option<Ordering> {
+ if a > b {
+ Some(Ordering::Less)
+ } else if a < b {
+ Some(Ordering::Greater)
+ } else {
+ Some(Ordering::Equal)
+ }
+}
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn partial_cmp2<T: A>(a: &T, b: &T) -> Option<Ordering> {
+ partial_cmp(&a.value(), &b.value())
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, PartialOrd)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(partial_cmp)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialOrd(method(partial_cmp2)))]
+ T
+ ),
+}
+```
+
+###### Ranking
+
+Each field can add a `#[educe(PartialOrd(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ #[educe(PartialOrd(rank = 1))]
+ f1: u8,
+ #[educe(PartialOrd(rank = 0))]
+ f2: u8,
+}
+```
+
+For variants, the discriminant can be explicitly set for comparison.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+#[repr(u8)]
+enum Enum {
+ Three { f1: u8 } = 3,
+ Two(u8) = 2,
+ One = 1,
+}
+```
+
+###### Generic Parameters Bound to the `PartialOrd` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialOrd` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn partial_cmp<T: A>(a: &T, b: &T) -> Option<Ordering> {
+ a.value().partial_cmp(&b.value())
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd(bound(T: std::cmp::PartialOrd, K: PartialEq + A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(partial_cmp)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+In the above case, `T` is bound to the `PartialOrd` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd(bound(*)))]
+struct Struct<T> {
+ #[educe(PartialOrd(ignore))]
+ f: T,
+}
+```
+
+#### Ord
+
+Use `#[derive(Educe)]` and `#[educe(Ord)]` to implement the `Ord` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `Ord` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ #[educe(Ord(ignore))]
+ f1: u8
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Ord(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Ord(ignore))]
+ u8
+ ),
+}
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `Ord` trait for a field, eliminating the need to implement the `Ord` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+fn cmp(a: &u8, b: &u8) -> Ordering {
+ if a > b {
+ Ordering::Less
+ } else if a < b {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+}
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn cmp2<T: A>(a: &T, b: &T) -> Ordering {
+ cmp(&a.value(), &b.value())
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq, PartialOrd, Ord)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Ord(method(cmp)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Ord(method(cmp2)))]
+ T
+ ),
+}
+```
+
+###### Ranking
+
+Each field can add a `#[educe(Ord(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ #[educe(Ord(rank = 1))]
+ f1: u8,
+ #[educe(Ord(rank = 0))]
+ f2: u8,
+}
+```
+
+For variants, the discriminant can be explicitly set for comparison.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+#[repr(u8)]
+enum Enum {
+ Three { f1: u8 } = 3,
+ Two(u8) = 2,
+ One = 1,
+}
+```
+
+###### Generic Parameters Bound to the `Ord` Trait or Others
+
+Generic parameters will be automatically bound to the `Ord` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn cmp<T: A>(a: &T, b: &T) -> Ordering {
+ a.value().cmp(&b.value())
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord(bound(T: std::cmp::Ord, K: std::cmp::Ord + A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(cmp)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+#### Hash
+
+Use `#[derive(Educe)]` and `#[educe(Hash)]` to implement the `Hash` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.
+
+###### Basic Usage
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+struct Struct {
+ #[educe(Hash(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Hash(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Hash(ignore))]
+ u8
+ ),
+}
+```
+
+###### Use Another Method for Hashing
+
+The `method` parameter can be utilized to replace the implementation of the `Hash` trait for a field, eliminating the need to implement the `Hash` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+use std::hash::{Hash, Hasher};
+
+fn hash<H: Hasher>(_s: &u8, state: &mut H) {
+ Hash::hash(&100, state)
+}
+
+fn hash2<H: Hasher, T>(_s: &T, state: &mut H) {
+ Hash::hash(&100, state)
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum<T> {
+ V1,
+ V2 {
+ #[educe(Hash(method(hash)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Hash(method(hash2)))]
+ T
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `Hash` Trait or Others
+
+Generic parameters will be automatically bound to the `Hash` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+use std::hash::{Hash, Hasher};
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn hash<H: Hasher, T: A>(s: &T, state: &mut H) {
+ Hash::hash(&s.value(), state)
+}
+
+#[derive(Educe)]
+#[educe(Hash(bound(T: std::hash::Hash, K: A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Hash(method(hash)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+```
+
+In the above case, `T` is bound to the `Hash` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash(bound(*)))]
+struct Struct<T> {
+ #[educe(Hash(ignore))]
+ f: T,
+}
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]` attribute can be used for a union. The fields of a union cannot be hashed with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32
+}
+```
+
+#### Default
+
+Use `#[derive(Educe)]` and `#[educe(Default)]` to implement the `Default` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.
+
+###### Basic Usage
+
+For enums and unions, it is necessary to designate a default variant (for enums) and a default field (for unions) unless the enum has only one variant or the union has only one field.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum {
+ V1,
+ #[educe(Default)]
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+union Union {
+ f1: u8,
+ #[educe(Default)]
+ f2: f64,
+}
+```
+
+###### The Default Value for the Entire Type
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(expression = Struct { f1: 1 }))]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Default(expression = Enum::Struct { f1: 1 }))]
+enum Enum {
+ Unit,
+ Struct {
+ f1: u8
+ },
+ Tuple(u8),
+}
+
+#[derive(Educe)]
+#[educe(Default(expression = Union { f1: 1 }))]
+union Union {
+ f1: u8,
+ f2: f64,
+}
+```
+
+You may need to activate the `full` feature to enable support for advanced expressions.
+
+###### The Default Values for Specific Fields
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+struct Struct {
+ #[educe(Default = 1)]
+ f1: u8,
+ #[educe(Default = 11111111111111111111111111111)]
+ f2: i128,
+ #[educe(Default = 1.1)]
+ f3: f64,
+ #[educe(Default = true)]
+ f4: bool,
+ #[educe(Default = "Hi")]
+ f5: &'static str,
+ #[educe(Default = "Hello")]
+ f6: String,
+ #[educe(Default = 'M')]
+ f7: char,
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum {
+ Unit,
+ #[educe(Default)]
+ Tuple(
+ #[educe(Default(expression = 0 + 1))]
+ u8,
+ #[educe(Default(expression = -11111111111111111111111111111 * -1))]
+ i128,
+ #[educe(Default(expression = 1.0 + 0.1))]
+ f64,
+ #[educe(Default(expression = !false))]
+ bool,
+ #[educe(Default(expression = "Hi"))]
+ &'static str,
+ #[educe(Default(expression = String::from("Hello")))]
+ String,
+ #[educe(Default(expression = 'M'))]
+ char,
+ ),
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+union Union {
+ f1: u8,
+ f2: i128,
+ f3: f64,
+ f4: bool,
+ #[educe(Default = "Hi")]
+ f5: &'static str,
+ f6: char,
+}
+```
+
+###### Generic Parameters Bound to the `Default` Trait or Others
+
+Generic parameters will be automatically bound to the `Default` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum<T> {
+ Unit,
+ #[educe(Default)]
+ Struct {
+ f1: T
+ },
+ Tuple(T),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(bound(T: std::default::Default)))]
+enum Enum<T> {
+ Unit,
+ #[educe(Default)]
+ Struct {
+ f1: T
+ },
+ Tuple(T),
+}
+```
+
+###### The `new` Associated Function
+
+With the `#[educe(Default(new))]` attribute, your type will include an additional associated function called `new`. This function can be utilized to invoke the `default` method of the `Default` trait.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(new))]
+struct Struct {
+ f1: u8
+}
+```
+
+#### Deref
+
+Use `#[derive(Educe)]` and `#[educe(Deref)]` to implement the `Deref` trait for a struct or enum.
+
+###### Basic Usage
+
+You must designate a field as the default for obtaining an immutable reference unless the number of fields is exactly one.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Deref)]
+struct Struct {
+ f1: u8,
+ #[educe(Deref)]
+ f2: u8,
+}
+
+#[derive(Educe)]
+#[educe(Deref)]
+enum Enum {
+ Struct {
+ f1: u8
+ },
+ Struct2 {
+ f1: u8,
+ #[educe(Deref)]
+ f2: u8,
+ },
+ Tuple(u8),
+ Tuple2(
+ u8,
+ #[educe(Deref)]
+ u8
+ ),
+}
+```
+
+#### DerefMut
+
+Use `#[derive(Educe)]` and `#[educe(DerefMut)]` to implement the `DerefMut` trait for a struct or enum.
+
+###### Basic Usage
+
+You must designate a field as the default for obtaining an mutable reference unless the number of fields is exactly one.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Deref, DerefMut)]
+struct Struct {
+ f1: u8,
+ #[educe(Deref, DerefMut)]
+ f2: u8,
+}
+
+#[derive(Educe)]
+#[educe(Deref, DerefMut)]
+enum Enum {
+ Struct {
+ f1: u8
+ },
+ Struct2 {
+ f1: u8,
+ #[educe(Deref, DerefMut)]
+ f2: u8,
+ },
+ Tuple(u8),
+ Tuple2(
+ #[educe(DerefMut)]
+ u8,
+ #[educe(Deref)]
+ u8
+ ),
+}
+```
+
+The mutable dereferencing fields do not need to be the same as the immutable dereferencing fields, but their types must be consistent.
+
+#### Into
+
+Use `#[derive(Educe)]` and `#[educe(Into(type))]` to implement the `Into<type>` trait for a struct or enum.
+
+###### Basic Usage
+
+You need to designate a field as the default for `Into<type>` conversion unless the number of fields is exactly one. If you don't, educe will automatically try to find a proper one.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Into(u8), Into(u16))]
+struct Struct {
+ f1: u8,
+ f2: u16,
+}
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum {
+ V1 {
+ f1: u8,
+ #[educe(Into(u8))]
+ f2: u8,
+ },
+ V2 (
+ u8
+ ),
+}
+```
+
+###### Use Another Method to Perform Into Conversion
+
+The `method` parameter can be utilized to replace the implementation of the `Into` trait for a field, eliminating the need to implement the `Into` trait for the type of that field.
+
+```rust
+use educe::Educe;
+
+fn into(v: u16) -> u8 {
+ v as u8
+}
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum {
+ V1 {
+ #[educe(Into(u8, method(into)))]
+ f1: u16,
+ },
+ V2 (
+ u8
+ ),
+}
+```
+
+###### Generic Parameters Bound to the `Into` Trait or Others
+
+Generic parameters will be automatically bound to the `Into<type>` trait if necessary.
+
+```rust
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum<T, K> {
+ V1 {
+ f1: K,
+ },
+ V2 (
+ T
+ ),
+}
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+use educe::Educe;
+
+fn into<T>(_v: T) -> u8 {
+ 0
+}
+
+#[derive(Educe)]
+#[educe(Into(u8, bound(K: Into<u8>)))]
+enum Enum<T, K> {
+ V1 {
+ f1: K,
+ },
+ V2 (
+ #[educe(Into(u8, method(into)))]
+ T
+ ),
+}
+```
+
+## Crates.io
+
+https://crates.io/crates/educe
+
+## Documentation
+
+https://docs.rs/educe
+
+## License
+
+[MIT](LICENSE)
diff --git a/vendor/educe/src/common/bound.rs b/vendor/educe/src/common/bound.rs
new file mode 100644
index 00000000..78f9aed4
--- /dev/null
+++ b/vendor/educe/src/common/bound.rs
@@ -0,0 +1,57 @@
+use syn::{punctuated::Punctuated, token::Comma, GenericParam, Meta, Path, Type, WherePredicate};
+
+use crate::common::where_predicates_bool::{
+ create_where_predicates_from_all_generic_parameters,
+ create_where_predicates_from_generic_parameters_check_types, meta_2_where_predicates,
+ WherePredicates, WherePredicatesOrBool,
+};
+
+pub(crate) enum Bound {
+ Disabled,
+ Auto,
+ Custom(WherePredicates),
+ All,
+}
+
+impl Bound {
+ #[inline]
+ pub(crate) fn from_meta(meta: &Meta) -> syn::Result<Self> {
+ debug_assert!(meta.path().is_ident("bound"));
+
+ Ok(match meta_2_where_predicates(meta)? {
+ WherePredicatesOrBool::WherePredicates(where_predicates) => {
+ Self::Custom(where_predicates)
+ },
+ WherePredicatesOrBool::Bool(b) => {
+ if b {
+ Self::Auto
+ } else {
+ Self::Disabled
+ }
+ },
+ WherePredicatesOrBool::All => Self::All,
+ })
+ }
+}
+
+impl Bound {
+ #[inline]
+ pub(crate) fn into_where_predicates_by_generic_parameters_check_types(
+ self,
+ params: &Punctuated<GenericParam, Comma>,
+ bound_trait: &Path,
+ types: &[&Type],
+ supertraits: &[proc_macro2::TokenStream],
+ ) -> Punctuated<WherePredicate, Comma> {
+ match self {
+ Self::Disabled => Punctuated::new(),
+ Self::Auto => create_where_predicates_from_generic_parameters_check_types(
+ bound_trait,
+ types,
+ supertraits,
+ ),
+ Self::Custom(where_predicates) => where_predicates,
+ Self::All => create_where_predicates_from_all_generic_parameters(params, bound_trait),
+ }
+ }
+}
diff --git a/vendor/educe/src/common/expr.rs b/vendor/educe/src/common/expr.rs
new file mode 100644
index 00000000..ab49d3a0
--- /dev/null
+++ b/vendor/educe/src/common/expr.rs
@@ -0,0 +1,109 @@
+use quote::{quote, ToTokens};
+use syn::{spanned::Spanned, Expr, Lit, Meta, Type};
+
+use super::path::path_to_string;
+
+const INT_TYPES: [&str; 12] =
+ ["u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"];
+
+const FLOAT_TYPES: [&str; 2] = ["f32", "f64"];
+
+#[inline]
+pub(crate) fn meta_2_expr(meta: &Meta) -> syn::Result<Expr> {
+ match &meta {
+ Meta::NameValue(name_value) => Ok(name_value.value.clone()),
+ Meta::List(list) => list.parse_args::<Expr>(),
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!("expected `{path} = Expr` or `{path}(Expr)`", path = path_to_string(path)),
+ )),
+ }
+}
+
+#[inline]
+pub(crate) fn auto_adjust_expr(expr: Expr, ty: Option<&Type>) -> Expr {
+ match &expr {
+ Expr::Lit(lit) => {
+ match &lit.lit {
+ Lit::Int(lit) => {
+ if let Some(Type::Path(ty)) = ty {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if lit.suffix() == ty_string || INT_TYPES.contains(&ty_string.as_str()) {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::Float(lit) => {
+ if let Some(Type::Path(ty)) = ty {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if lit.suffix() == ty_string || FLOAT_TYPES.contains(&ty_string.as_str()) {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::Str(_) => {
+ if let Some(Type::Reference(ty)) = ty {
+ let ty_string = ty.elem.clone().into_token_stream().to_string();
+
+ if ty_string == "str" {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::Bool(_) => {
+ if let Some(Type::Path(ty)) = ty {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if ty_string == "bool" {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::Char(_) => {
+ if let Some(Type::Path(ty)) = ty {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if ty_string == "char" {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::Byte(_) => {
+ if let Some(Type::Path(ty)) = ty {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if ty_string == "u8" {
+ // don't call into
+ return expr;
+ }
+ }
+ },
+ Lit::ByteStr(_) => {
+ if let Some(Type::Reference(ty)) = ty {
+ if let Type::Array(ty) = ty.elem.as_ref() {
+ if let Type::Path(ty) = ty.elem.as_ref() {
+ let ty_string = ty.into_token_stream().to_string();
+
+ if ty_string == "u8" {
+ // don't call into
+ return expr;
+ }
+ }
+ }
+ }
+ },
+ _ => (),
+ }
+
+ syn::parse2(quote!(::core::convert::Into::into(#expr))).unwrap()
+ },
+ _ => expr,
+ }
+}
diff --git a/vendor/educe/src/common/ident_bool.rs b/vendor/educe/src/common/ident_bool.rs
new file mode 100644
index 00000000..89bf2fb9
--- /dev/null
+++ b/vendor/educe/src/common/ident_bool.rs
@@ -0,0 +1,161 @@
+use syn::{
+ parse::{Parse, ParseStream},
+ spanned::Spanned,
+ Expr, Ident, Lit, LitBool, LitStr, Meta, MetaNameValue,
+};
+
+use super::path::path_to_string;
+
+#[derive(Debug)]
+pub(crate) enum IdentOrBool {
+ Ident(Ident),
+ Bool(bool),
+}
+
+impl Parse for IdentOrBool {
+ #[inline]
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ if let Ok(lit) = input.parse::<Lit>() {
+ match lit {
+ Lit::Bool(lit) => return Ok(Self::Bool(lit.value)),
+ Lit::Str(lit) => {
+ return match lit.parse::<Ident>() {
+ Ok(ident) => Ok(Self::Ident(ident)),
+ Err(_) if lit.value().is_empty() => Ok(Self::Bool(false)),
+ Err(error) => Err(error),
+ }
+ },
+ _ => (),
+ }
+ }
+
+ Ok(Self::Ident(input.parse::<Ident>()?))
+ }
+}
+
+#[inline]
+pub(crate) fn meta_name_value_2_ident(name_value: &MetaNameValue) -> syn::Result<Ident> {
+ match &name_value.value {
+ Expr::Lit(lit) => {
+ if let Lit::Str(lit) = &lit.lit {
+ return lit.parse();
+ }
+ },
+ Expr::Path(path) => {
+ if let Some(ident) = path.path.get_ident() {
+ return Ok(ident.clone());
+ }
+ },
+ _ => (),
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!("expected `{path} = Ident`", path = path_to_string(&name_value.path)),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_ident(meta: &Meta) -> syn::Result<Ident> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_ident(name_value),
+ Meta::List(list) => {
+ if let Ok(lit) = list.parse_args::<LitStr>() {
+ lit.parse()
+ } else {
+ list.parse_args()
+ }
+ },
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!("expected `{path} = Ident` or `{path}(Ident)`", path = path_to_string(path)),
+ )),
+ }
+}
+
+#[inline]
+pub(crate) fn meta_name_value_2_bool(name_value: &MetaNameValue) -> syn::Result<bool> {
+ if let Expr::Lit(lit) = &name_value.value {
+ if let Lit::Bool(b) = &lit.lit {
+ return Ok(b.value);
+ }
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!("expected `{path} = false`", path = path_to_string(&name_value.path)),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_bool(meta: &Meta) -> syn::Result<bool> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_bool(name_value),
+ Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value),
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!("expected `{path} = false` or `{path}(false)`", path = path_to_string(path)),
+ )),
+ }
+}
+
+#[inline]
+pub(crate) fn meta_2_bool_allow_path(meta: &Meta) -> syn::Result<bool> {
+ match &meta {
+ Meta::Path(_) => Ok(true),
+ Meta::NameValue(name_value) => meta_name_value_2_bool(name_value),
+ Meta::List(list) => Ok(list.parse_args::<LitBool>()?.value),
+ }
+}
+
+#[inline]
+pub(crate) fn meta_name_value_2_ident_and_bool(
+ name_value: &MetaNameValue,
+) -> syn::Result<IdentOrBool> {
+ match &name_value.value {
+ Expr::Lit(lit) => match &lit.lit {
+ Lit::Str(lit) => match lit.parse::<Ident>() {
+ Ok(ident) => return Ok(IdentOrBool::Ident(ident)),
+ Err(_) if lit.value().is_empty() => {
+ return Ok(IdentOrBool::Bool(false));
+ },
+ Err(error) => {
+ return Err(error);
+ },
+ },
+ Lit::Bool(lit) => {
+ return Ok(IdentOrBool::Bool(lit.value));
+ },
+ _ => (),
+ },
+ Expr::Path(path) => {
+ if let Some(ident) = path.path.get_ident() {
+ return Ok(IdentOrBool::Ident(ident.clone()));
+ }
+ },
+ _ => (),
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!(
+ "expected `{path} = Ident` or `{path} = false`",
+ path = path_to_string(&name_value.path)
+ ),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_ident_and_bool(meta: &Meta) -> syn::Result<IdentOrBool> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_ident_and_bool(name_value),
+ Meta::List(list) => list.parse_args::<IdentOrBool>(),
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!(
+ "expected `{path} = Ident`, `{path}(Ident)`, `{path} = false`, or `{path}(false)`",
+ path = path_to_string(path)
+ ),
+ )),
+ }
+}
diff --git a/vendor/educe/src/common/ident_index.rs b/vendor/educe/src/common/ident_index.rs
new file mode 100644
index 00000000..c0e38d49
--- /dev/null
+++ b/vendor/educe/src/common/ident_index.rs
@@ -0,0 +1,56 @@
+use quote::ToTokens;
+use syn::{Ident, Index};
+
+pub(crate) enum IdentOrIndex {
+ Ident(Ident),
+ Index(Index),
+}
+
+impl From<Ident> for IdentOrIndex {
+ #[inline]
+ fn from(value: Ident) -> Self {
+ Self::Ident(value)
+ }
+}
+
+impl From<Index> for IdentOrIndex {
+ #[inline]
+ fn from(value: Index) -> Self {
+ Self::Index(value)
+ }
+}
+
+impl From<&Ident> for IdentOrIndex {
+ #[inline]
+ fn from(value: &Ident) -> Self {
+ Self::Ident(value.clone())
+ }
+}
+
+impl From<usize> for IdentOrIndex {
+ #[inline]
+ fn from(value: usize) -> Self {
+ Self::Index(Index::from(value))
+ }
+}
+
+impl ToTokens for IdentOrIndex {
+ #[inline]
+ fn to_tokens(&self, token_stream: &mut proc_macro2::TokenStream) {
+ match self {
+ Self::Ident(ident) => ToTokens::to_tokens(ident, token_stream),
+ Self::Index(index) => ToTokens::to_tokens(index, token_stream),
+ }
+ }
+}
+
+impl IdentOrIndex {
+ #[inline]
+ pub(crate) fn from_ident_with_index(ident: Option<&Ident>, index: usize) -> IdentOrIndex {
+ if let Some(ident) = ident {
+ Self::from(ident)
+ } else {
+ Self::from(index)
+ }
+ }
+}
diff --git a/vendor/educe/src/common/int.rs b/vendor/educe/src/common/int.rs
new file mode 100644
index 00000000..ae52b491
--- /dev/null
+++ b/vendor/educe/src/common/int.rs
@@ -0,0 +1,63 @@
+use syn::{spanned::Spanned, Expr, Lit, Meta, MetaNameValue, UnOp};
+
+use super::path::path_to_string;
+
+#[inline]
+pub(crate) fn meta_name_value_2_isize(name_value: &MetaNameValue) -> syn::Result<isize> {
+ match &name_value.value {
+ Expr::Lit(lit) => match &lit.lit {
+ Lit::Str(lit) => {
+ return lit
+ .value()
+ .parse::<isize>()
+ .map_err(|error| syn::Error::new(lit.span(), error))
+ },
+ Lit::Int(lit) => return lit.base10_parse(),
+ _ => (),
+ },
+ Expr::Unary(unary) => {
+ if let UnOp::Neg(_) = unary.op {
+ if let Expr::Lit(lit) = unary.expr.as_ref() {
+ if let Lit::Int(lit) = &lit.lit {
+ let s = format!("-{}", lit.base10_digits());
+
+ return s
+ .parse::<isize>()
+ .map_err(|error| syn::Error::new(lit.span(), error));
+ }
+ }
+ }
+ },
+ _ => (),
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!("expected `{path} = integer`", path = path_to_string(&name_value.path)),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_isize(meta: &Meta) -> syn::Result<isize> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_isize(name_value),
+ Meta::List(list) => {
+ let lit = list.parse_args::<Lit>()?;
+
+ match &lit {
+ Lit::Str(lit) => {
+ lit.value().parse::<isize>().map_err(|error| syn::Error::new(lit.span(), error))
+ },
+ Lit::Int(lit) => lit.base10_parse(),
+ _ => Err(syn::Error::new(lit.span(), "not an integer")),
+ }
+ },
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!(
+ "expected `{path} = integer` or `{path}(integer)`",
+ path = path_to_string(path)
+ ),
+ )),
+ }
+}
diff --git a/vendor/educe/src/common/mod.rs b/vendor/educe/src/common/mod.rs
new file mode 100644
index 00000000..79e10bb9
--- /dev/null
+++ b/vendor/educe/src/common/mod.rs
@@ -0,0 +1,43 @@
+#[allow(dead_code)]
+pub(crate) mod bound;
+#[allow(dead_code)]
+pub(crate) mod path;
+#[allow(dead_code)]
+pub(crate) mod r#type;
+#[allow(dead_code)]
+pub(crate) mod where_predicates_bool;
+
+#[cfg(feature = "Default")]
+#[allow(dead_code)]
+pub(crate) mod expr;
+#[cfg(any(
+ feature = "Debug",
+ feature = "PartialEq",
+ feature = "PartialOrd",
+ feature = "Ord",
+ feature = "Hash",
+ feature = "Default"
+))]
+#[allow(dead_code)]
+pub(crate) mod ident_bool;
+#[cfg(any(
+ feature = "Debug",
+ feature = "PartialEq",
+ feature = "PartialOrd",
+ feature = "Ord",
+ feature = "Hash",
+ feature = "Deref",
+ feature = "DerefMut",
+ feature = "Into"
+))]
+#[allow(dead_code)]
+pub(crate) mod ident_index;
+#[cfg(any(feature = "PartialOrd", feature = "Ord"))]
+#[allow(dead_code)]
+pub(crate) mod int;
+#[cfg(any(feature = "Debug", feature = "PartialEq", feature = "Hash"))]
+#[allow(dead_code)]
+pub(crate) mod unsafe_punctuated_meta;
+
+#[cfg(any(feature = "PartialOrd", feature = "Ord", feature = "Into"))]
+pub(crate) mod tools;
diff --git a/vendor/educe/src/common/path.rs b/vendor/educe/src/common/path.rs
new file mode 100644
index 00000000..18f80b24
--- /dev/null
+++ b/vendor/educe/src/common/path.rs
@@ -0,0 +1,43 @@
+use quote::ToTokens;
+use syn::{spanned::Spanned, Expr, Lit, LitStr, Meta, MetaNameValue, Path};
+
+#[inline]
+pub(crate) fn meta_name_value_2_path(name_value: &MetaNameValue) -> syn::Result<Path> {
+ match &name_value.value {
+ Expr::Lit(lit) => {
+ if let Lit::Str(lit) = &lit.lit {
+ return lit.parse();
+ }
+ },
+ Expr::Path(path) => return Ok(path.path.clone()),
+ _ => (),
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!("expected `{path} = Path`", path = path_to_string(&name_value.path)),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_path(meta: &Meta) -> syn::Result<Path> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_path(name_value),
+ Meta::List(list) => {
+ if let Ok(lit) = list.parse_args::<LitStr>() {
+ lit.parse()
+ } else {
+ list.parse_args()
+ }
+ },
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!("expected `{path} = Path` or `{path}(Path)`", path = path_to_string(path)),
+ )),
+ }
+}
+
+#[inline]
+pub(crate) fn path_to_string(path: &Path) -> String {
+ path.into_token_stream().to_string().replace(' ', "")
+}
diff --git a/vendor/educe/src/common/tools/discriminant_type.rs b/vendor/educe/src/common/tools/discriminant_type.rs
new file mode 100644
index 00000000..5bc0d2f8
--- /dev/null
+++ b/vendor/educe/src/common/tools/discriminant_type.rs
@@ -0,0 +1,169 @@
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::{ToTokens, TokenStreamExt};
+use syn::{
+ punctuated::Punctuated, spanned::Spanned, Data, DeriveInput, Expr, Lit, Meta, Token, UnOp,
+};
+
+#[derive(Debug)]
+pub(crate) enum DiscriminantType {
+ ISize,
+ I8,
+ I16,
+ I32,
+ I64,
+ I128,
+ USize,
+ U8,
+ U16,
+ U32,
+ U64,
+ U128,
+}
+
+impl DiscriminantType {
+ #[inline]
+ pub(crate) fn parse_str<S: AsRef<str>>(s: S) -> Option<Self> {
+ match s.as_ref() {
+ "i8" => Some(Self::I8),
+ "i16" => Some(Self::I16),
+ "i32" => Some(Self::I32),
+ "i64" => Some(Self::I64),
+ "i128" => Some(Self::I128),
+ "isize" => Some(Self::ISize),
+ "u8" => Some(Self::U8),
+ "u16" => Some(Self::U16),
+ "u32" => Some(Self::U32),
+ "u64" => Some(Self::U64),
+ "u128" => Some(Self::U128),
+ "usize" => Some(Self::USize),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub(crate) const fn as_str(&self) -> &'static str {
+ match self {
+ Self::ISize => "isize",
+ Self::I8 => "i8",
+ Self::I16 => "i16",
+ Self::I32 => "i32",
+ Self::I64 => "i64",
+ Self::I128 => "i128",
+ Self::USize => "usize",
+ Self::U8 => "u8",
+ Self::U16 => "u16",
+ Self::U32 => "u32",
+ Self::U64 => "u64",
+ Self::U128 => "u128",
+ }
+ }
+}
+
+impl ToTokens for DiscriminantType {
+ #[inline]
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Ident::new(self.as_str(), Span::call_site()));
+ }
+}
+
+impl DiscriminantType {
+ pub(crate) fn from_ast(ast: &DeriveInput) -> syn::Result<Self> {
+ if let Data::Enum(data) = &ast.data {
+ for attr in ast.attrs.iter() {
+ if attr.path().is_ident("repr") {
+ // #[repr(u8)], #[repr(u16)], ..., etc.
+ if let Meta::List(list) = &attr.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Ident, Token![,]>::parse_terminated)?;
+
+ if let Some(value) = result.into_iter().next() {
+ if let Some(t) = Self::parse_str(value.to_string()) {
+ return Ok(t);
+ }
+ }
+ }
+ }
+ }
+
+ let mut min = i128::MAX;
+ let mut max = i128::MIN;
+ let mut counter = 0i128;
+
+ for variant in data.variants.iter() {
+ if let Some((_, exp)) = variant.discriminant.as_ref() {
+ match exp {
+ Expr::Lit(lit) => {
+ if let Lit::Int(lit) = &lit.lit {
+ counter = lit
+ .base10_parse()
+ .map_err(|error| syn::Error::new(lit.span(), error))?;
+ } else {
+ return Err(syn::Error::new(lit.span(), "not an integer"));
+ }
+ },
+ Expr::Unary(unary) => {
+ if let UnOp::Neg(_) = unary.op {
+ if let Expr::Lit(lit) = unary.expr.as_ref() {
+ if let Lit::Int(lit) = &lit.lit {
+ match lit.base10_parse::<i128>() {
+ Ok(i) => {
+ counter = -i;
+ },
+ Err(error) => {
+ // overflow
+ if lit.base10_digits()
+ == "170141183460469231731687303715884105728"
+ {
+ counter = i128::MIN;
+ } else {
+ return Err(syn::Error::new(lit.span(), error));
+ }
+ },
+ }
+ } else {
+ return Err(syn::Error::new(lit.span(), "not an integer"));
+ }
+ } else {
+ return Err(syn::Error::new(
+ unary.expr.span(),
+ "not a literal",
+ ));
+ }
+ } else {
+ return Err(syn::Error::new(
+ unary.op.span(),
+ "this operation is not allow here",
+ ));
+ }
+ },
+ _ => return Err(syn::Error::new(exp.span(), "not a literal")),
+ }
+ }
+
+ if min > counter {
+ min = counter;
+ }
+
+ if max < counter {
+ max = counter;
+ }
+
+ counter = counter.saturating_add(1);
+ }
+
+ Ok(if min >= i8::MIN as i128 && max <= i8::MAX as i128 {
+ Self::I8
+ } else if min >= i16::MIN as i128 && max <= i16::MAX as i128 {
+ Self::I16
+ } else if min >= i32::MIN as i128 && max <= i32::MAX as i128 {
+ Self::I32
+ } else if min >= i64::MIN as i128 && max <= i64::MAX as i128 {
+ Self::I64
+ } else {
+ Self::I128
+ })
+ } else {
+ Err(syn::Error::new(ast.span(), "not an enum"))
+ }
+ }
+}
diff --git a/vendor/educe/src/common/tools/hash_type.rs b/vendor/educe/src/common/tools/hash_type.rs
new file mode 100644
index 00000000..ece3d03f
--- /dev/null
+++ b/vendor/educe/src/common/tools/hash_type.rs
@@ -0,0 +1,100 @@
+use std::{
+ cmp::Ordering,
+ fmt::{self, Display, Formatter},
+ hash::{Hash, Hasher},
+ str::FromStr,
+};
+
+use proc_macro2::Span;
+use quote::ToTokens;
+use syn::{spanned::Spanned, Path, Type};
+
+#[derive(Debug, Clone)]
+pub(crate) struct HashType(String, Span);
+
+impl PartialEq for HashType {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.0.eq(&other.0)
+ }
+}
+
+impl Eq for HashType {}
+
+impl PartialOrd for HashType {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for HashType {
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+}
+
+impl Hash for HashType {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ Hash::hash(&self.0, state);
+ }
+}
+
+impl Display for HashType {
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ Display::fmt(&self.0.replace("& '", "&'"), f)
+ }
+}
+
+impl From<Type> for HashType {
+ #[inline]
+ fn from(value: Type) -> Self {
+ Self::from(&value)
+ }
+}
+
+impl From<&Type> for HashType {
+ #[inline]
+ fn from(value: &Type) -> Self {
+ Self(value.into_token_stream().to_string(), value.span())
+ }
+}
+
+impl From<Path> for HashType {
+ #[inline]
+ fn from(value: Path) -> Self {
+ Self::from(&value)
+ }
+}
+
+impl From<&Path> for HashType {
+ #[inline]
+ fn from(value: &Path) -> Self {
+ Self(value.into_token_stream().to_string(), value.span())
+ }
+}
+
+#[allow(dead_code)]
+impl HashType {
+ #[inline]
+ pub(crate) fn to_type(&self) -> Type {
+ syn::parse_str(self.0.as_str()).unwrap()
+ }
+
+ #[inline]
+ pub(crate) fn span(&self) -> Span {
+ self.1
+ }
+}
+
+impl ToTokens for HashType {
+ #[inline]
+ fn to_tokens(&self, token_stream: &mut proc_macro2::TokenStream) {
+ let ty = proc_macro2::TokenStream::from_str(self.0.as_str()).unwrap();
+
+ token_stream.extend(ty);
+ }
+}
diff --git a/vendor/educe/src/common/tools/mod.rs b/vendor/educe/src/common/tools/mod.rs
new file mode 100644
index 00000000..23cb4970
--- /dev/null
+++ b/vendor/educe/src/common/tools/mod.rs
@@ -0,0 +1,11 @@
+#[cfg(any(feature = "PartialOrd", feature = "Ord"))]
+mod discriminant_type;
+
+#[cfg(any(feature = "PartialOrd", feature = "Ord"))]
+pub(crate) use discriminant_type::*;
+
+#[cfg(feature = "Into")]
+mod hash_type;
+
+#[cfg(feature = "Into")]
+pub(crate) use hash_type::*;
diff --git a/vendor/educe/src/common/type.rs b/vendor/educe/src/common/type.rs
new file mode 100644
index 00000000..c17ed73b
--- /dev/null
+++ b/vendor/educe/src/common/type.rs
@@ -0,0 +1,51 @@
+use syn::{
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ Meta, Token, Type,
+};
+
+pub(crate) struct TypeWithPunctuatedMeta {
+ pub(crate) ty: Type,
+ pub(crate) list: Punctuated<Meta, Token![,]>,
+}
+
+impl Parse for TypeWithPunctuatedMeta {
+ #[inline]
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let ty = input.parse::<Type>()?;
+
+ if input.is_empty() {
+ return Ok(Self {
+ ty,
+ list: Punctuated::new(),
+ });
+ }
+
+ input.parse::<Token![,]>()?;
+
+ let list = input.parse_terminated(Meta::parse, Token![,])?;
+
+ Ok(Self {
+ ty,
+ list,
+ })
+ }
+}
+
+#[inline]
+pub(crate) fn dereference(ty: &Type) -> &Type {
+ if let Type::Reference(ty) = ty {
+ dereference(ty.elem.as_ref())
+ } else {
+ ty
+ }
+}
+
+#[inline]
+pub(crate) fn dereference_changed(ty: &Type) -> (&Type, bool) {
+ if let Type::Reference(ty) = ty {
+ (dereference(ty.elem.as_ref()), true)
+ } else {
+ (ty, false)
+ }
+}
diff --git a/vendor/educe/src/common/unsafe_punctuated_meta.rs b/vendor/educe/src/common/unsafe_punctuated_meta.rs
new file mode 100644
index 00000000..e8ec103b
--- /dev/null
+++ b/vendor/educe/src/common/unsafe_punctuated_meta.rs
@@ -0,0 +1,35 @@
+use syn::{
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ Meta, Token,
+};
+
+pub(crate) struct UnsafePunctuatedMeta {
+ pub(crate) list: Punctuated<Meta, Token![,]>,
+ pub(crate) has_unsafe: bool,
+}
+
+impl Parse for UnsafePunctuatedMeta {
+ #[inline]
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let has_unsafe = input.parse::<Token![unsafe]>().is_ok();
+
+ if input.is_empty() {
+ return Ok(Self {
+ list: Punctuated::new(),
+ has_unsafe,
+ });
+ }
+
+ if has_unsafe {
+ input.parse::<Token![,]>()?;
+ }
+
+ let list = input.parse_terminated(Meta::parse, Token![,])?;
+
+ Ok(Self {
+ list,
+ has_unsafe,
+ })
+ }
+}
diff --git a/vendor/educe/src/common/where_predicates_bool.rs b/vendor/educe/src/common/where_predicates_bool.rs
new file mode 100644
index 00000000..4aa3695c
--- /dev/null
+++ b/vendor/educe/src/common/where_predicates_bool.rs
@@ -0,0 +1,122 @@
+use quote::{quote, ToTokens};
+use syn::{
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ spanned::Spanned,
+ token::Comma,
+ Expr, GenericParam, Lit, Meta, MetaNameValue, Path, Token, Type, WherePredicate,
+};
+
+use super::path::path_to_string;
+
+pub(crate) type WherePredicates = Punctuated<WherePredicate, Token![,]>;
+
+pub(crate) enum WherePredicatesOrBool {
+ WherePredicates(WherePredicates),
+ Bool(bool),
+ All,
+}
+
+impl WherePredicatesOrBool {
+ fn from_lit(lit: &Lit) -> syn::Result<Self> {
+ Ok(match lit {
+ Lit::Bool(lit) => Self::Bool(lit.value),
+ Lit::Str(lit) => match lit.parse_with(WherePredicates::parse_terminated) {
+ Ok(where_predicates) => Self::WherePredicates(where_predicates),
+ Err(_) if lit.value().is_empty() => Self::Bool(false),
+ Err(error) => return Err(error),
+ },
+ other => {
+ return Err(syn::Error::new(
+ other.span(),
+ "unexpected kind of literal (only boolean or string allowed)",
+ ))
+ },
+ })
+ }
+}
+
+impl Parse for WherePredicatesOrBool {
+ #[inline]
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ if let Ok(lit) = input.parse::<Lit>() {
+ return Self::from_lit(&lit);
+ }
+
+ if let Ok(_star) = input.parse::<Token![*]>() {
+ return Ok(Self::All);
+ }
+
+ Ok(Self::WherePredicates(input.parse_terminated(WherePredicate::parse, Token![,])?))
+ }
+}
+
+#[inline]
+pub(crate) fn meta_name_value_2_where_predicates_bool(
+ name_value: &MetaNameValue,
+) -> syn::Result<WherePredicatesOrBool> {
+ if let Expr::Lit(lit) = &name_value.value {
+ return WherePredicatesOrBool::from_lit(&lit.lit);
+ }
+
+ Err(syn::Error::new(
+ name_value.value.span(),
+ format!(
+ "expected `{path} = \"where_predicates\"` or `{path} = false`",
+ path = path_to_string(&name_value.path)
+ ),
+ ))
+}
+
+#[inline]
+pub(crate) fn meta_2_where_predicates(meta: &Meta) -> syn::Result<WherePredicatesOrBool> {
+ match &meta {
+ Meta::NameValue(name_value) => meta_name_value_2_where_predicates_bool(name_value),
+ Meta::List(list) => list.parse_args::<WherePredicatesOrBool>(),
+ Meta::Path(path) => Err(syn::Error::new(
+ path.span(),
+ format!(
+ "expected `{path} = \"where_predicates\"`, `{path}(where_predicates)`, `{path} = \
+ false`, or `{path}(false)`",
+ path = path.clone().into_token_stream()
+ ),
+ )),
+ }
+}
+
+#[inline]
+pub(crate) fn create_where_predicates_from_all_generic_parameters(
+ params: &Punctuated<GenericParam, Comma>,
+ bound_trait: &Path,
+) -> WherePredicates {
+ let mut where_predicates = Punctuated::new();
+
+ for param in params {
+ if let GenericParam::Type(ty) = param {
+ let ident = &ty.ident;
+
+ where_predicates.push(syn::parse2(quote! { #ident: #bound_trait }).unwrap());
+ }
+ }
+
+ where_predicates
+}
+
+#[inline]
+pub(crate) fn create_where_predicates_from_generic_parameters_check_types(
+ bound_trait: &Path,
+ types: &[&Type],
+ supertraits: &[proc_macro2::TokenStream],
+) -> WherePredicates {
+ let mut where_predicates = Punctuated::new();
+
+ for t in types {
+ where_predicates.push(syn::parse2(quote! { #t: #bound_trait }).unwrap());
+ }
+
+ for supertrait in supertraits {
+ where_predicates.push(syn::parse2(quote! { Self: #supertrait }).unwrap());
+ }
+
+ where_predicates
+}
diff --git a/vendor/educe/src/lib.rs b/vendor/educe/src/lib.rs
new file mode 100644
index 00000000..6b9a26e3
--- /dev/null
+++ b/vendor/educe/src/lib.rs
@@ -0,0 +1,2135 @@
+/*!
+# Educe
+
+This crate offers procedural macros designed to facilitate the swift implementation of Rust's built-in traits.
+
+## Features
+
+By default, every trait this crate supports will be enabled. You can disable all of them by turning off the default features and enable only the traits that you want to use by adding them to the `features` explicitly.
+
+For example,
+
+```toml
+[dependencies.educe]
+version = "*"
+features = ["Debug", "Clone", "Copy", "Hash", "Default"]
+default-features = false
+```
+
+## Traits
+
+#### Debug
+
+Use `#[derive(Educe)]` and `#[educe(Debug)]` to implement the `Debug` trait for a struct, enum, or union. This allows you to modify the names of your types, variants, and fields. You can also choose to ignore specific fields or set a method to replace the `Debug` trait. Additionally, you have the option to format a struct as a tuple and vice versa.
+
+###### Basic Usage
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Change the Name of a Type, a Variant or a Field
+
+The `name` parameter can rename a type, a variant or a field. If you set it to `false`, the name can be ignored or forced to show otherwise.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(name(Struct2)))]
+struct Struct {
+ #[educe(Debug(name(f)))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug(name = true))]
+enum Enum {
+ #[educe(Debug(name = false))]
+ V1,
+ #[educe(Debug(name(V)))]
+ V2 {
+ #[educe(Debug(name(f)))]
+ f1: u8,
+ },
+ #[educe(Debug(name = false))]
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+struct Struct {
+ #[educe(Debug(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Debug(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Debug(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Fake Structs and Tuples
+
+With the `named_field` parameter, structs can be formatted as tuples and tuples can be formatted as structs.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(named_field = false))]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum {
+ V1,
+ #[educe(Debug(named_field = false))]
+ V2 {
+ f1: u8,
+ },
+ #[educe(Debug(named_field = true))]
+ V3(
+ u8,
+ #[educe(Debug(name(value)))]
+ i32
+ ),
+}
+# }
+```
+
+###### Use Another Method to Handle the Formatting
+
+The `method` parameter can be utilized to replace the implementation of the `Debug` trait for a field, eliminating the need to implement the `Debug` trait for the type of that field.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+use std::fmt::{self, Formatter};
+
+fn fmt<T>(_s: &T, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("Hi")
+}
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum<T> {
+ V1,
+ V2 {
+ #[educe(Debug(method(fmt)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Debug(method(std::fmt::UpperHex::fmt)))]
+ u8,
+ #[educe(Debug(method(fmt)))]
+ T
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Debug` Trait or Others
+
+Generic parameters will be automatically bound to the `Debug` trait if necessary.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+use std::fmt::{self, Formatter};
+
+fn fmt<D>(_s: &D, f: &mut Formatter<'_>) -> fmt::Result {
+ f.write_str("Hi")
+}
+
+#[derive(Educe)]
+#[educe(Debug(bound(T: std::fmt::Debug)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Debug(method(fmt)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+In the above case, `T` is bound to the `Debug` trait, but `K` is not.
+
+Or, you can have `educe` replicate the behaviour of `std`'s `derive`'s, where a bound is produced for *every* generic parameter, without regard to how it's used in the structure:
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(bound(*)))]
+struct Struct<T> {
+ #[educe(Debug(ignore))]
+ f: T,
+}
+# }
+```
+
+This can be useful if you don't want to make the trait implementation part of your permanent public API. In this example, `Struct<T>` doesn't implement `Debug` unless `T` does. I.e., it has a `T: Debug` bound even though that's not needed right now. Later we might want to display `f`; we wouldn't then need to make a breaking API change by adding the bound.
+
+This was the behaviour of `Trait(bound)` in educe 0.4.x and earlier.
+
+###### Union
+
+A union will be formatted as a `u8` slice because we don't know its fields at runtime. The fields of a union cannot be ignored, renamed, or formatted with other methods. The implementation is **unsafe** because it may expose uninitialized memory.
+
+```rust
+# #[cfg(feature = "Debug")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Debug(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32,
+}
+# }
+```
+
+#### Clone
+
+Use `#[derive(Educe)]` and `#[educe(Clone)]` to implement the `Clone` trait for a struct, an enum, or a union. You can set a method to replace the `Clone` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(feature = "Clone")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Clone)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Use Another Method to Perform Cloning
+
+The `method` parameter can be utilized to replace the implementation of the `Clone` trait for a field, eliminating the need to implement the `Clone` trait for the type of that field.
+
+```rust
+# #[cfg(feature = "Clone")]
+# {
+use educe::Educe;
+
+fn clone(v: &u8) -> u8 {
+ v + 100
+}
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone2<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Clone(method(clone2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Clone` Trait or Others
+
+Generic parameters will be automatically bound to the `Clone` trait if necessary. If the `#[educe(Copy)]` attribute exists, they will be bound to the `Copy` trait.
+
+```rust
+# #[cfg(feature = "Clone")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Clone)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "Clone")]
+# {
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone(bound(T: std::clone::Clone)))]
+enum Enum<T, K: A> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+In the above case, `T` is bound to the `Clone` trait, but `K` is not.
+
+Or, you can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+# #[cfg(feature = "Clone")]
+# {
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Clone(bound(*)))]
+struct Struct<T: A> {
+ #[educe(Clone(method(clone)))]
+ f: T,
+}
+# }
+```
+
+###### Union
+
+Refer to the introduction of the `#[educe(Copy)]` attribute.
+
+#### Copy
+
+Use `#[derive(Educe)]` and `#[educe(Copy)]` to implement the `Copy` trait for a struct, an enum, or a union.
+
+###### Basic Usage
+
+```rust
+# #[cfg(all(feature = "Clone", feature = "Copy"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Copy` Trait or Others
+
+All generic parameters will be automatically bound to the `Copy` trait.
+
+```rust
+# #[cfg(all(feature = "Clone", feature = "Copy"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(all(feature = "Clone", feature = "Copy"))]
+# {
+use educe::Educe;
+
+trait A {
+ fn add(&self, rhs: u8) -> Self;
+}
+
+fn clone<T: A>(v: &T) -> T {
+ v.add(100)
+}
+
+#[derive(Educe)]
+#[educe(Copy, Clone(bound(T: Copy, K: A + Copy)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Clone(method(clone)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Note that utilizing custom cloning methods for a type that implements the `Copy` and `Clone` traits may not be entirely appropriate.
+
+###### Union
+
+The `#[educe(Copy, Clone)]` attribute can be used for a union. The fields of a union cannot be cloned with other methods.
+
+```rust
+# #[cfg(all(feature = "Clone", feature = "Copy"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Copy, Clone)]
+union Union {
+ f1: u8,
+}
+# }
+```
+
+#### PartialEq
+
+Use `#[derive(Educe)]` and `#[educe(PartialEq)]` to implement the `PartialEq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+struct Struct {
+ #[educe(PartialEq(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(PartialEq(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialEq(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `PartialEq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+fn eq(a: &u8, b: &u8) -> bool {
+ a + 1 == *b
+}
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq2<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(PartialEq(method(eq)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialEq(method(eq2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `PartialEq` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialEq` trait if necessary.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialEq(method(eq)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+In the above case, `T` is bound to the `PartialEq` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(*)))]
+struct Struct<T> {
+ #[educe(PartialEq(ignore))]
+ f: T,
+}
+# }
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe))]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32
+}
+# }
+```
+
+#### Eq
+
+Use `#[derive(Educe)]` and `#[educe(Eq)]` to implement the `Eq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+struct Struct {
+ #[educe(Eq(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Eq(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Eq(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `Eq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+fn eq(a: &u8, b: &u8) -> bool {
+ a + 1 == *b
+}
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq2<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Eq(method(eq)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Eq(method(eq2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `PartialEq` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialEq` trait if necessary.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+trait A {
+ fn is_same(&self, other: &Self) -> bool;
+}
+
+fn eq<T: A>(a: &T, b: &T) -> bool {
+ a.is_same(b)
+}
+
+#[derive(Educe)]
+#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)), Eq)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Eq(method(eq)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe), Eq)]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe), Eq)]
+union Union {
+ f1: u8,
+ f2: i32
+}
+# }
+```
+
+#### PartialOrd
+
+Use `#[derive(Educe)]` and `#[educe(PartialOrd)]` to implement the `PartialOrd` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `PartialOrd` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ #[educe(PartialOrd(ignore))]
+ f1: u8
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(PartialOrd(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialOrd(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `PartialOrd` trait for a field, eliminating the need to implement the `PartialOrd` trait for the type of that field.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "PartialOrd"))]
+# {
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+fn partial_cmp(a: &u8, b: &u8) -> Option<Ordering> {
+ if a > b {
+ Some(Ordering::Less)
+ } else if a < b {
+ Some(Ordering::Greater)
+ } else {
+ Some(Ordering::Equal)
+ }
+}
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn partial_cmp2<T: A>(a: &T, b: &T) -> Option<Ordering> {
+ partial_cmp(&a.value(), &b.value())
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, PartialOrd)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(partial_cmp)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(PartialOrd(method(partial_cmp2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Ranking
+
+Each field can add a `#[educe(PartialOrd(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+struct Struct {
+ #[educe(PartialOrd(rank = 1))]
+ f1: u8,
+ #[educe(PartialOrd(rank = 0))]
+ f2: u8,
+}
+# }
+```
+
+For variants, the discriminant can be explicitly set for comparison.
+
+```rust,ignore
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+#[repr(u8)]
+enum Enum {
+ Three { f1: u8 } = 3,
+ Two(u8) = 2,
+ One = 1,
+}
+# }
+```
+
+###### Generic Parameters Bound to the `PartialOrd` Trait or Others
+
+Generic parameters will be automatically bound to the `PartialOrd` trait if necessary.
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn partial_cmp<T: A>(a: &T, b: &T) -> Option<Ordering> {
+ a.value().partial_cmp(&b.value())
+}
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd(bound(T: std::cmp::PartialOrd, K: PartialEq + A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(partial_cmp)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+In the above case, `T` is bound to the `PartialOrd` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+# #[cfg(feature = "PartialOrd")]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Educe)]
+#[educe(PartialOrd(bound(*)))]
+struct Struct<T> {
+ #[educe(PartialOrd(ignore))]
+ f: T,
+}
+# }
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe))]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+# #[cfg(feature = "PartialEq")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32
+}
+# }
+```
+
+#### Ord
+
+Use `#[derive(Educe)]` and `#[educe(Ord)]` to implement the `Ord` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `Ord` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ #[educe(Ord(ignore))]
+ f1: u8
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Ord(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Ord(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method to Perform Comparison
+
+The `method` parameter can be utilized to replace the implementation of the `Ord` trait for a field, eliminating the need to implement the `Ord` trait for the type of that field.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq", feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+fn cmp(a: &u8, b: &u8) -> Ordering {
+ if a > b {
+ Ordering::Less
+ } else if a < b {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+}
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn cmp2<T: A>(a: &T, b: &T) -> Ordering {
+ cmp(&a.value(), &b.value())
+}
+
+#[derive(Educe)]
+#[educe(PartialEq, Eq, PartialOrd, Ord)]
+enum Enum<T: A> {
+ V1,
+ V2 {
+ #[educe(Ord(method(cmp)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Ord(method(cmp2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Ranking
+
+Each field can add a `#[educe(Ord(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.
+
+```rust
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+struct Struct {
+ #[educe(Ord(rank = 1))]
+ f1: u8,
+ #[educe(Ord(rank = 0))]
+ f2: u8,
+}
+# }
+```
+
+For variants, the discriminant can be explicitly set for comparison.
+
+```rust,ignore
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+#[repr(u8)]
+enum Enum {
+ Three { f1: u8 } = 3,
+ Two(u8) = 2,
+ One = 1,
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Ord` Trait or Others
+
+Generic parameters will be automatically bound to the `Ord` trait if necessary.
+
+```rust
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(all(feature = "PartialOrd", feature = "Ord"))]
+# {
+use educe::Educe;
+
+use std::cmp::Ordering;
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn cmp<T: A>(a: &T, b: &T) -> Ordering {
+ a.value().cmp(&b.value())
+}
+
+#[derive(PartialEq, Eq, Educe)]
+#[educe(PartialOrd, Ord(bound(T: std::cmp::Ord, K: std::cmp::Ord + A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(PartialOrd(method(cmp)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+#### Hash
+
+Use `#[derive(Educe)]` and `#[educe(Hash)]` to implement the `Hash` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.
+
+###### Basic Usage
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum {
+ V1,
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+# }
+```
+
+###### Ignore Fields
+
+The `ignore` parameter can ignore a specific field.
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+struct Struct {
+ #[educe(Hash(ignore))]
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum {
+ V1,
+ V2 {
+ #[educe(Hash(ignore))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Hash(ignore))]
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method for Hashing
+
+The `method` parameter can be utilized to replace the implementation of the `Hash` trait for a field, eliminating the need to implement the `Hash` trait for the type of that field.
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+use std::hash::{Hash, Hasher};
+
+fn hash<H: Hasher>(_s: &u8, state: &mut H) {
+ Hash::hash(&100, state)
+}
+
+fn hash2<H: Hasher, T>(_s: &T, state: &mut H) {
+ Hash::hash(&100, state)
+}
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum<T> {
+ V1,
+ V2 {
+ #[educe(Hash(method(hash)))]
+ f1: u8,
+ },
+ V3(
+ #[educe(Hash(method(hash2)))]
+ T
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Hash` Trait or Others
+
+Generic parameters will be automatically bound to the `Hash` trait if necessary.
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash)]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+use std::hash::{Hash, Hasher};
+
+trait A {
+ fn value(&self) -> u8;
+}
+
+fn hash<H: Hasher, T: A>(s: &T, state: &mut H) {
+ Hash::hash(&s.value(), state)
+}
+
+#[derive(Educe)]
+#[educe(Hash(bound(T: std::hash::Hash, K: A)))]
+enum Enum<T, K> {
+ V1,
+ V2 {
+ #[educe(Hash(method(hash)))]
+ f1: K,
+ },
+ V3(
+ T
+ ),
+}
+# }
+```
+
+In the above case, `T` is bound to the `Hash` trait, but `K` is not.
+
+You can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.
+
+```rust
+# #[cfg(feature = "Hash")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Hash(bound(*)))]
+struct Struct<T> {
+ #[educe(Hash(ignore))]
+ f: T,
+}
+# }
+```
+
+###### Union
+
+The `#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]` attribute can be used for a union. The fields of a union cannot be hashed with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.
+
+```rust
+# #[cfg(all(feature = "PartialEq", feature = "Eq", feature = "Hash"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]
+union Union {
+ f1: u8,
+ f2: i32
+}
+# }
+```
+
+#### Default
+
+Use `#[derive(Educe)]` and `#[educe(Default)]` to implement the `Default` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.
+
+###### Basic Usage
+
+For enums and unions, it is necessary to designate a default variant (for enums) and a default field (for unions) unless the enum has only one variant or the union has only one field.
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum {
+ V1,
+ #[educe(Default)]
+ V2 {
+ f1: u8,
+ },
+ V3(u8),
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+union Union {
+ f1: u8,
+ #[educe(Default)]
+ f2: f64,
+}
+# }
+```
+
+###### The Default Value for the Entire Type
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(expression = Struct { f1: 1 }))]
+struct Struct {
+ f1: u8
+}
+
+#[derive(Educe)]
+#[educe(Default(expression = Enum::Struct { f1: 1 }))]
+enum Enum {
+ Unit,
+ Struct {
+ f1: u8
+ },
+ Tuple(u8),
+}
+
+#[derive(Educe)]
+#[educe(Default(expression = Union { f1: 1 }))]
+union Union {
+ f1: u8,
+ f2: f64,
+}
+# }
+```
+
+You may need to activate the `full` feature to enable support for advanced expressions.
+
+###### The Default Values for Specific Fields
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+struct Struct {
+ #[educe(Default = 1)]
+ f1: u8,
+ #[educe(Default = 11111111111111111111111111111)]
+ f2: i128,
+ #[educe(Default = 1.1)]
+ f3: f64,
+ #[educe(Default = true)]
+ f4: bool,
+ #[educe(Default = "Hi")]
+ f5: &'static str,
+ #[educe(Default = "Hello")]
+ f6: String,
+ #[educe(Default = 'M')]
+ f7: char,
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum {
+ Unit,
+ #[educe(Default)]
+ Tuple(
+ #[educe(Default(expression = 0 + 1))]
+ u8,
+ #[educe(Default(expression = -11111111111111111111111111111 * -1))]
+ i128,
+ #[educe(Default(expression = 1.0 + 0.1))]
+ f64,
+ #[educe(Default(expression = !false))]
+ bool,
+ #[educe(Default(expression = "Hi"))]
+ &'static str,
+ #[educe(Default(expression = String::from("Hello")))]
+ String,
+ #[educe(Default(expression = 'M'))]
+ char,
+ ),
+}
+
+#[derive(Educe)]
+#[educe(Default)]
+union Union {
+ f1: u8,
+ f2: i128,
+ f3: f64,
+ f4: bool,
+ #[educe(Default = "Hi")]
+ f5: &'static str,
+ f6: char,
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Default` Trait or Others
+
+Generic parameters will be automatically bound to the `Default` trait if necessary.
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default)]
+enum Enum<T> {
+ Unit,
+ #[educe(Default)]
+ Struct {
+ f1: T
+ },
+ Tuple(T),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(bound(T: std::default::Default)))]
+enum Enum<T> {
+ Unit,
+ #[educe(Default)]
+ Struct {
+ f1: T
+ },
+ Tuple(T),
+}
+# }
+```
+
+###### The `new` Associated Function
+
+With the `#[educe(Default(new))]` attribute, your type will include an additional associated function called `new`. This function can be utilized to invoke the `default` method of the `Default` trait.
+
+```rust
+# #[cfg(feature = "Default")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Default(new))]
+struct Struct {
+ f1: u8
+}
+# }
+```
+
+#### Deref
+
+Use `#[derive(Educe)]` and `#[educe(Deref)]` to implement the `Deref` trait for a struct or enum.
+
+###### Basic Usage
+
+You must designate a field as the default for obtaining an immutable reference unless the number of fields is exactly one.
+
+```rust
+# #[cfg(feature = "Deref")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Deref)]
+struct Struct {
+ f1: u8,
+ #[educe(Deref)]
+ f2: u8,
+}
+
+#[derive(Educe)]
+#[educe(Deref)]
+enum Enum {
+ Struct {
+ f1: u8
+ },
+ Struct2 {
+ f1: u8,
+ #[educe(Deref)]
+ f2: u8,
+ },
+ Tuple(u8),
+ Tuple2(
+ u8,
+ #[educe(Deref)]
+ u8
+ ),
+}
+# }
+```
+
+#### DerefMut
+
+Use `#[derive(Educe)]` and `#[educe(DerefMut)]` to implement the `DerefMut` trait for a struct or enum.
+
+###### Basic Usage
+
+You must designate a field as the default for obtaining an mutable reference unless the number of fields is exactly one.
+
+```rust
+# #[cfg(all(feature = "Deref", feature = "DerefMut"))]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Deref, DerefMut)]
+struct Struct {
+ f1: u8,
+ #[educe(Deref, DerefMut)]
+ f2: u8,
+}
+
+#[derive(Educe)]
+#[educe(Deref, DerefMut)]
+enum Enum {
+ Struct {
+ f1: u8
+ },
+ Struct2 {
+ f1: u8,
+ #[educe(Deref, DerefMut)]
+ f2: u8,
+ },
+ Tuple(u8),
+ Tuple2(
+ #[educe(DerefMut)]
+ u8,
+ #[educe(Deref)]
+ u8
+ ),
+}
+# }
+```
+
+The mutable dereferencing fields do not need to be the same as the immutable dereferencing fields, but their types must be consistent.
+
+#### Into
+
+Use `#[derive(Educe)]` and `#[educe(Into(type))]` to implement the `Into<type>` trait for a struct or enum.
+
+###### Basic Usage
+
+You need to designate a field as the default for `Into<type>` conversion unless the number of fields is exactly one. If you don't, educe will automatically try to find a proper one.
+
+```rust
+# #[cfg(feature = "Into")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Into(u8), Into(u16))]
+struct Struct {
+ f1: u8,
+ f2: u16,
+}
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum {
+ V1 {
+ f1: u8,
+ #[educe(Into(u8))]
+ f2: u8,
+ },
+ V2 (
+ u8
+ ),
+}
+# }
+```
+
+###### Use Another Method to Perform Into Conversion
+
+The `method` parameter can be utilized to replace the implementation of the `Into` trait for a field, eliminating the need to implement the `Into` trait for the type of that field.
+
+```rust
+# #[cfg(feature = "Into")]
+# {
+use educe::Educe;
+
+fn into(v: u16) -> u8 {
+ v as u8
+}
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum {
+ V1 {
+ #[educe(Into(u8, method(into)))]
+ f1: u16,
+ },
+ V2 (
+ u8
+ ),
+}
+# }
+```
+
+###### Generic Parameters Bound to the `Into` Trait or Others
+
+Generic parameters will be automatically bound to the `Into<type>` trait if necessary.
+
+```rust
+# #[cfg(feature = "Into")]
+# {
+use educe::Educe;
+
+#[derive(Educe)]
+#[educe(Into(u8))]
+enum Enum<T, K> {
+ V1 {
+ f1: K,
+ },
+ V2 (
+ T
+ ),
+}
+# }
+```
+
+Or you can set the where predicates by yourself.
+
+```rust
+# #[cfg(feature = "Into")]
+# {
+use educe::Educe;
+
+fn into<T>(_v: T) -> u8 {
+ 0
+}
+
+#[derive(Educe)]
+#[educe(Into(u8, bound(K: Into<u8>)))]
+enum Enum<T, K> {
+ V1 {
+ f1: K,
+ },
+ V2 (
+ #[educe(Into(u8, method(into)))]
+ T
+ ),
+}
+# }
+```
+
+*/
+
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+mod common;
+#[allow(dead_code)]
+mod panic;
+mod supported_traits;
+mod trait_handlers;
+
+use std::collections::HashMap;
+
+use proc_macro::TokenStream;
+use supported_traits::Trait;
+use syn::{
+ parse::{Parse, ParseStream},
+ parse_macro_input,
+ punctuated::Punctuated,
+ DeriveInput, Meta, Token,
+};
+#[allow(unused)]
+use trait_handlers::{TraitHandler, TraitHandlerMultiple};
+
+fn derive_input_handler(ast: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
+ let mut token_stream = proc_macro2::TokenStream::new();
+ let mut trait_meta_map: HashMap<Trait, Vec<Meta>> = HashMap::new();
+
+ for attr in ast.attrs.iter() {
+ let path = attr.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attr.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if let Some(v_meta) = trait_meta_map.get_mut(&t) {
+ // except for those traits containing generics types
+
+ #[cfg(feature = "Into")]
+ if t == Trait::Into {
+ v_meta.push(meta);
+
+ continue;
+ }
+
+ // avoid unused warnings
+ let _ = v_meta;
+
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ trait_meta_map.insert(t, vec![meta]);
+ }
+ } else {
+ return Err(panic::educe_format_incorrect(path.get_ident().unwrap()));
+ }
+ }
+ }
+
+ let traits: Vec<Trait> = trait_meta_map.keys().copied().collect();
+
+ #[cfg(feature = "Debug")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Debug) {
+ trait_handlers::debug::DebugHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Clone")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Clone) {
+ trait_handlers::clone::CloneHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Copy")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Copy) {
+ trait_handlers::copy::CopyHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "PartialEq")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::PartialEq) {
+ trait_handlers::partial_eq::PartialEqHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Eq")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Eq) {
+ trait_handlers::eq::EqHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "PartialOrd")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::PartialOrd) {
+ trait_handlers::partial_ord::PartialOrdHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Ord")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Ord) {
+ trait_handlers::ord::OrdHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Hash")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Hash) {
+ trait_handlers::hash::HashHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Default")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Default) {
+ trait_handlers::default::DefaultHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Deref")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Deref) {
+ trait_handlers::deref::DerefHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "DerefMut")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::DerefMut) {
+ trait_handlers::deref_mut::DerefMutHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ &meta[0],
+ )?;
+ }
+ }
+
+ #[cfg(feature = "Into")]
+ {
+ if let Some(meta) = trait_meta_map.get(&Trait::Into) {
+ trait_handlers::into::IntoHandler::trait_meta_handler(
+ &ast,
+ &mut token_stream,
+ &traits,
+ meta,
+ )?;
+ }
+ }
+
+ if trait_meta_map.contains_key(&Trait::_Nothing) {
+ // avoid unused warnings
+ let _ = &ast;
+ let _ = &mut token_stream;
+ let _ = traits;
+ unreachable!();
+ }
+
+ if token_stream.is_empty() {
+ return Err(panic::derive_attribute_not_set_up_yet());
+ }
+
+ Ok(token_stream)
+}
+
+#[proc_macro_derive(Educe, attributes(educe))]
+pub fn educe_derive(input: TokenStream) -> TokenStream {
+ struct MyDeriveInput(proc_macro2::TokenStream);
+
+ impl Parse for MyDeriveInput {
+ #[inline]
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let token_stream = derive_input_handler(input.parse::<DeriveInput>()?)?;
+
+ Ok(Self(token_stream))
+ }
+ }
+
+ // Parse the token stream
+ let derive_input = parse_macro_input!(input as MyDeriveInput);
+
+ derive_input.0.into()
+}
diff --git a/vendor/educe/src/panic.rs b/vendor/educe/src/panic.rs
new file mode 100644
index 00000000..eb059ff4
--- /dev/null
+++ b/vendor/educe/src/panic.rs
@@ -0,0 +1,130 @@
+use core::fmt::{self, Display, Formatter};
+
+use proc_macro2::Span;
+use syn::{spanned::Spanned, Ident, Path, Variant};
+
+use crate::{common::path::path_to_string, Trait};
+
+struct DisplayStringSlice<'a>(&'a [&'static str]);
+
+impl<'a> Display for DisplayStringSlice<'a> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ if !self.0.is_empty() {
+ f.write_str(", which should be reformatted as follows:")?;
+
+ for &s in self.0 {
+ f.write_str("\n ")?;
+ f.write_str(s)?;
+ }
+ }
+
+ Ok(())
+ }
+}
+
+struct DisplayTraits;
+
+impl Display for DisplayTraits {
+ #[inline]
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ for t in &Trait::VARIANTS[..Trait::VARIANTS.len() - 1] {
+ f.write_str("\n ")?;
+ f.write_fmt(format_args!("{t:?}"))?;
+ }
+
+ Ok(())
+ }
+}
+
+#[inline]
+pub(crate) fn derive_attribute_not_set_up_yet() -> syn::Error {
+ syn::Error::new(
+ Span::call_site(),
+ "you are using `Educe` in the `derive` attribute, but it has not been set up yet",
+ )
+}
+
+#[inline]
+pub(crate) fn attribute_incorrect_place(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), format!("the `{name}` attribute cannot be placed here"))
+}
+
+#[inline]
+pub(crate) fn attribute_incorrect_format_with_span(
+ name: &Ident,
+ span: Span,
+ correct_usage: &[&'static str],
+) -> syn::Error {
+ if correct_usage.is_empty() {
+ attribute_incorrect_place(name)
+ } else {
+ syn::Error::new(
+ span,
+ format!(
+ "you are using an incorrect format of the `{name}` attribute{}",
+ DisplayStringSlice(correct_usage)
+ ),
+ )
+ }
+}
+
+#[inline]
+pub(crate) fn attribute_incorrect_format(
+ name: &Ident,
+ correct_usage: &[&'static str],
+) -> syn::Error {
+ attribute_incorrect_format_with_span(name, name.span(), correct_usage)
+}
+
+#[inline]
+pub(crate) fn parameter_reset(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), format!("you are trying to reset the `{name}` parameter"))
+}
+
+#[inline]
+pub(crate) fn educe_format_incorrect(name: &Ident) -> syn::Error {
+ attribute_incorrect_format(name, &[stringify!(#[educe(Trait1, Trait2, ..., TraitN)])])
+}
+
+#[inline]
+pub(crate) fn unsupported_trait(name: &Path) -> syn::Error {
+ let span = name.span();
+
+ match name.get_ident() {
+ Some(name) => syn::Error::new(
+ span,
+ format!("unsupported trait `{name}`, available traits:{DisplayTraits}"),
+ ),
+ None => {
+ let name = path_to_string(name);
+
+ syn::Error::new(
+ span,
+ format!("unsupported trait `{name}`, available traits:{DisplayTraits}"),
+ )
+ },
+ }
+}
+
+#[inline]
+pub(crate) fn reuse_a_trait(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), format!("the trait `{name}` is used repeatedly"))
+}
+
+#[inline]
+pub(crate) fn trait_not_used(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), format!("the trait `{name}` is not used"))
+}
+
+#[inline]
+pub(crate) fn trait_not_support_union(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), format!("the trait `{name}` does not support to a union"))
+}
+
+#[inline]
+pub(crate) fn trait_not_support_unit_variant(name: &Ident, variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ variant.span(),
+ format!("the trait `{name}` cannot be implemented for an enum which has unit variants"),
+ )
+}
diff --git a/vendor/educe/src/supported_traits.rs b/vendor/educe/src/supported_traits.rs
new file mode 100644
index 00000000..50f7f302
--- /dev/null
+++ b/vendor/educe/src/supported_traits.rs
@@ -0,0 +1,88 @@
+#[cfg(not(any(
+ feature = "Debug",
+ feature = "Clone",
+ feature = "Copy",
+ feature = "PartialEq",
+ feature = "Eq",
+ feature = "PartialOrd",
+ feature = "Ord",
+ feature = "Hash",
+ feature = "Default",
+ feature = "Deref",
+ feature = "DerefMut",
+ feature = "Into",
+)))]
+compile_error!("at least one of the trait features must be enabled");
+
+use enum_ordinalize::Ordinalize;
+use syn::Path;
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ordinalize)]
+#[ordinalize(impl_trait = false)]
+#[ordinalize(variants(pub(crate) const VARIANTS))]
+pub(crate) enum Trait {
+ #[cfg(feature = "Debug")]
+ Debug,
+ #[cfg(feature = "Clone")]
+ Clone,
+ #[cfg(feature = "Copy")]
+ Copy,
+ #[cfg(feature = "PartialEq")]
+ PartialEq,
+ #[cfg(feature = "Eq")]
+ Eq,
+ #[cfg(feature = "PartialOrd")]
+ PartialOrd,
+ #[cfg(feature = "Ord")]
+ Ord,
+ #[cfg(feature = "Hash")]
+ Hash,
+ #[cfg(feature = "Default")]
+ Default,
+ #[cfg(feature = "Deref")]
+ Deref,
+ #[cfg(feature = "DerefMut")]
+ DerefMut,
+ #[cfg(feature = "Into")]
+ Into,
+
+ _Nothing,
+}
+
+impl Trait {
+ #[inline]
+ pub(crate) fn from_path(path: &Path) -> Option<Self> {
+ let ident_string = match path.get_ident() {
+ Some(ident) => ident.to_string(),
+ None => return None,
+ };
+
+ match ident_string.as_str() {
+ #[cfg(feature = "Debug")]
+ "Debug" => Some(Self::Debug),
+ #[cfg(feature = "Clone")]
+ "Clone" => Some(Self::Clone),
+ #[cfg(feature = "Copy")]
+ "Copy" => Some(Self::Copy),
+ #[cfg(feature = "PartialEq")]
+ "PartialEq" => Some(Self::PartialEq),
+ #[cfg(feature = "Eq")]
+ "Eq" => Some(Self::Eq),
+ #[cfg(feature = "PartialOrd")]
+ "PartialOrd" => Some(Self::PartialOrd),
+ #[cfg(feature = "Ord")]
+ "Ord" => Some(Self::Ord),
+ #[cfg(feature = "Hash")]
+ "Hash" => Some(Self::Hash),
+ #[cfg(feature = "Default")]
+ "Default" => Some(Self::Default),
+ #[cfg(feature = "Deref")]
+ "Deref" => Some(Self::Deref),
+ #[cfg(feature = "DerefMut")]
+ "DerefMut" => Some(Self::DerefMut),
+ #[cfg(feature = "Into")]
+ "Into" => Some(Self::Into),
+ _ => None,
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/clone_enum.rs b/vendor/educe/src/trait_handlers/clone/clone_enum.rs
new file mode 100644
index 00000000..991243ac
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/clone_enum.rs
@@ -0,0 +1,272 @@
+use quote::{format_ident, quote};
+use syn::{punctuated::Punctuated, Data, DeriveInput, Field, Fields, Meta, Type, Variant};
+
+use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder};
+use crate::{
+ common::where_predicates_bool::WherePredicates, supported_traits::Trait, TraitHandler,
+};
+
+pub(crate) struct CloneEnumHandler;
+
+impl TraitHandler for CloneEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_clone_meta(meta)?;
+
+ let mut bound: WherePredicates = Punctuated::new();
+
+ let mut clone_token_stream = proc_macro2::TokenStream::new();
+ let mut clone_from_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ type Variants<'a> = Vec<(&'a Variant, Vec<(&'a Field, FieldAttribute)>)>;
+
+ let mut variants: Variants = Vec::new();
+
+ #[cfg(feature = "Copy")]
+ let mut has_custom_clone_method = false;
+
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false, enable_bound: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let mut variant_fields: Vec<(&Field, FieldAttribute)> = Vec::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_method: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ #[cfg(feature = "Copy")]
+ if field_attribute.method.is_some() {
+ has_custom_clone_method = true;
+ }
+
+ variant_fields.push((field, field_attribute));
+ }
+
+ variants.push((variant, variant_fields));
+ }
+
+ #[cfg(feature = "Copy")]
+ let contains_copy = !has_custom_clone_method && traits.contains(&Trait::Copy);
+
+ #[cfg(not(feature = "Copy"))]
+ let contains_copy = false;
+
+ if contains_copy {
+ clone_token_stream.extend(quote!(*self));
+ }
+
+ let mut clone_types: Vec<&Type> = Vec::new();
+
+ if variants.is_empty() {
+ if !contains_copy {
+ clone_token_stream.extend(quote!(unreachable!()));
+ clone_from_token_stream.extend(quote!(let _ = source;));
+ }
+ } else {
+ let mut clone_variants_token_stream = proc_macro2::TokenStream::new();
+ let mut clone_from_variants_token_stream = proc_macro2::TokenStream::new();
+
+ for (variant, variant_fields) in variants {
+ let variant_ident = &variant.ident;
+
+ match &variant.fields {
+ Fields::Unit => {
+ clone_variants_token_stream.extend(quote! {
+ Self::#variant_ident => Self::#variant_ident,
+ });
+ clone_from_variants_token_stream.extend(quote! {
+ Self::#variant_ident => {
+ if let Self::#variant_ident = source {
+ // same
+ } else {
+ *self = ::core::clone::Clone::clone(source);
+ }
+ },
+ });
+ },
+ Fields::Named(_) => {
+ let mut pattern_src_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern_dst_token_stream = proc_macro2::TokenStream::new();
+ let mut cl_fields_token_stream = proc_macro2::TokenStream::new();
+ let mut cf_body_token_stream = proc_macro2::TokenStream::new();
+
+ for (field, field_attribute) in variant_fields {
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_src = format_ident!("_s_{}", field_name_real);
+ let field_name_dst = format_ident!("_d_{}", field_name_real);
+
+ pattern_src_token_stream
+ .extend(quote!(#field_name_real: #field_name_src,));
+ pattern_dst_token_stream
+ .extend(quote!(#field_name_real: #field_name_dst,));
+
+ if let Some(clone) = field_attribute.method.as_ref() {
+ cl_fields_token_stream.extend(quote! {
+ #field_name_real: #clone(#field_name_src),
+ });
+ cf_body_token_stream.extend(
+ quote!(*#field_name_dst = #clone(#field_name_src);),
+ );
+ } else {
+ clone_types.push(&field.ty);
+
+ cl_fields_token_stream.extend(quote! {
+ #field_name_real: ::core::clone::Clone::clone(#field_name_src),
+ });
+ cf_body_token_stream.extend(
+ quote!( ::core::clone::Clone::clone_from(#field_name_dst, #field_name_src); ),
+ );
+ }
+ }
+
+ clone_variants_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_src_token_stream } => Self::#variant_ident { #cl_fields_token_stream },
+ });
+
+ clone_from_variants_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_dst_token_stream } => {
+ if let Self::#variant_ident { #pattern_src_token_stream } = source {
+ #cf_body_token_stream
+ } else {
+ *self = ::core::clone::Clone::clone(source);
+ }
+ },
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern2_token_stream = proc_macro2::TokenStream::new();
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+ let mut body_token_stream = proc_macro2::TokenStream::new();
+
+ for (index, (field, field_attribute)) in
+ variant_fields.into_iter().enumerate()
+ {
+ let field_name_src = format_ident!("_{}", index);
+
+ pattern_token_stream.extend(quote!(#field_name_src,));
+
+ let field_name_dst = format_ident!("_{}", field_name_src);
+
+ pattern2_token_stream.extend(quote!(#field_name_dst,));
+
+ if let Some(clone) = field_attribute.method.as_ref() {
+ fields_token_stream.extend(quote! (#clone(#field_name_src),));
+ body_token_stream.extend(
+ quote!(*#field_name_src = #clone(#field_name_dst);),
+ );
+ } else {
+ clone_types.push(&field.ty);
+
+ fields_token_stream.extend(
+ quote! ( ::core::clone::Clone::clone(#field_name_src), ),
+ );
+ body_token_stream.extend(
+ quote!( ::core::clone::Clone::clone_from(#field_name_src, #field_name_dst); ),
+ );
+ }
+ }
+
+ clone_variants_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => Self::#variant_ident ( #fields_token_stream ),
+ });
+
+ clone_from_variants_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ if let Self::#variant_ident ( #pattern2_token_stream ) = source {
+ #body_token_stream
+ } else {
+ *self = ::core::clone::Clone::clone(source);
+ }
+ },
+ });
+ },
+ }
+ }
+
+ if !contains_copy {
+ clone_token_stream.extend(quote! {
+ match self {
+ #clone_variants_token_stream
+ }
+ });
+
+ clone_from_token_stream.extend(quote! {
+ match self {
+ #clone_from_variants_token_stream
+ }
+ });
+ }
+ }
+
+ bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(if contains_copy {
+ quote!(::core::marker::Copy)
+ } else {
+ quote!(::core::clone::Clone)
+ })
+ .unwrap(),
+ &clone_types,
+ &[],
+ );
+ }
+
+ let clone_from_fn_token_stream = if clone_from_token_stream.is_empty() {
+ None
+ } else {
+ Some(quote! {
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ #clone_from_token_stream
+ }
+ })
+ };
+
+ let ident = &ast.ident;
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::clone::Clone for #ident #ty_generics #where_clause {
+ #[inline]
+ fn clone(&self) -> Self {
+ #clone_token_stream
+ }
+
+ #clone_from_fn_token_stream
+ }
+ });
+
+ #[cfg(feature = "Copy")]
+ if traits.contains(&Trait::Copy) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/clone_struct.rs b/vendor/educe/src/trait_handlers/clone/clone_struct.rs
new file mode 100644
index 00000000..73aa8faa
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/clone_struct.rs
@@ -0,0 +1,195 @@
+use quote::quote;
+use syn::{punctuated::Punctuated, Data, DeriveInput, Field, Fields, Index, Meta, Type};
+
+use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder};
+use crate::{
+ common::where_predicates_bool::WherePredicates, supported_traits::Trait, TraitHandler,
+};
+
+pub(crate) struct CloneStructHandler;
+
+impl TraitHandler for CloneStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_clone_meta(meta)?;
+
+ let mut bound: WherePredicates = Punctuated::new();
+
+ let mut clone_token_stream = proc_macro2::TokenStream::new();
+ let mut clone_from_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let mut fields: Vec<(&Field, FieldAttribute)> = Vec::new();
+
+ #[cfg(feature = "Copy")]
+ let contains_copy = traits.contains(&Trait::Copy);
+
+ #[cfg(not(feature = "Copy"))]
+ let contains_copy = false;
+
+ if contains_copy {
+ clone_token_stream.extend(quote!(*self));
+ }
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_method: !contains_copy
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ fields.push((field, field_attribute));
+ }
+
+ let mut clone_types: Vec<&Type> = Vec::new();
+
+ match &data.fields {
+ Fields::Unit => {
+ if !contains_copy {
+ clone_token_stream.extend(quote!(Self));
+ clone_from_token_stream.extend(quote!(let _ = source;));
+ }
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+ let mut clone_from_body_token_stream = proc_macro2::TokenStream::new();
+
+ if fields.is_empty() {
+ clone_from_body_token_stream.extend(quote!(let _ = source;));
+ } else {
+ for (field, field_attribute) in fields {
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(clone) = field_attribute.method.as_ref() {
+ fields_token_stream.extend(quote! {
+ #field_name: #clone(&self.#field_name),
+ });
+
+ clone_from_body_token_stream.extend(
+ quote!(self.#field_name = #clone(&source.#field_name);),
+ );
+ } else {
+ clone_types.push(&field.ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: ::core::clone::Clone::clone(&self.#field_name),
+ });
+
+ clone_from_body_token_stream.extend(
+ quote!( ::core::clone::Clone::clone_from(&mut self.#field_name, &source.#field_name); ),
+ );
+ }
+ }
+ }
+
+ if !contains_copy {
+ clone_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+
+ clone_from_token_stream.extend(clone_from_body_token_stream);
+ }
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+ let mut clone_from_body_token_stream = proc_macro2::TokenStream::new();
+
+ if fields.is_empty() {
+ clone_from_body_token_stream.extend(quote!(let _ = source;));
+ } else {
+ for (index, (field, field_attribute)) in fields.into_iter().enumerate() {
+ let field_name = Index::from(index);
+
+ if let Some(clone) = field_attribute.method.as_ref() {
+ fields_token_stream.extend(quote!(#clone(&self.#field_name),));
+
+ clone_from_body_token_stream.extend(
+ quote!(self.#field_name = #clone(&source.#field_name);),
+ );
+ } else {
+ clone_types.push(&field.ty);
+
+ fields_token_stream.extend(
+ quote! ( ::core::clone::Clone::clone(&self.#field_name), ),
+ );
+
+ clone_from_body_token_stream.extend(
+ quote!( ::core::clone::Clone::clone_from(&mut self.#field_name, &source.#field_name); ),
+ );
+ }
+ }
+ }
+
+ if !contains_copy {
+ clone_token_stream.extend(quote!(Self ( #fields_token_stream )));
+ clone_from_token_stream.extend(clone_from_body_token_stream);
+ }
+ },
+ }
+
+ bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(if contains_copy {
+ quote!(::core::marker::Copy)
+ } else {
+ quote!(::core::clone::Clone)
+ })
+ .unwrap(),
+ &clone_types,
+ &[],
+ );
+ }
+
+ let clone_from_fn_token_stream = if clone_from_token_stream.is_empty() {
+ None
+ } else {
+ Some(quote! {
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ #clone_from_token_stream
+ }
+ })
+ };
+
+ let ident = &ast.ident;
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::clone::Clone for #ident #ty_generics #where_clause {
+ #[inline]
+ fn clone(&self) -> Self {
+ #clone_token_stream
+ }
+
+ #clone_from_fn_token_stream
+ }
+ });
+
+ #[cfg(feature = "Copy")]
+ if traits.contains(&Trait::Copy) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/clone_union.rs b/vendor/educe/src/trait_handlers/clone/clone_union.rs
new file mode 100644
index 00000000..dc3c729a
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/clone_union.rs
@@ -0,0 +1,73 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::supported_traits::Trait;
+
+pub(crate) struct CloneUnionHandler;
+
+impl TraitHandler for CloneUnionHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_clone_meta(meta)?;
+
+ let mut field_types = vec![];
+
+ if let Data::Union(data) = &ast.data {
+ for field in data.fields.named.iter() {
+ field_types.push(&field.ty);
+ let _ = FieldAttributeBuilder {
+ enable_method: false
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::marker::Copy)).unwrap(),
+ &field_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::clone::Clone for #ident #ty_generics #where_clause {
+ #[inline]
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ });
+
+ #[cfg(feature = "Copy")]
+ if traits.contains(&Trait::Copy) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/mod.rs b/vendor/educe/src/trait_handlers/clone/mod.rs
new file mode 100644
index 00000000..8c8a929f
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/mod.rs
@@ -0,0 +1,36 @@
+mod clone_enum;
+mod clone_struct;
+mod clone_union;
+mod models;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct CloneHandler;
+
+impl TraitHandler for CloneHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => clone_struct::CloneStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => {
+ clone_enum::CloneEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ clone_union::CloneUnionHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/models/field_attribute.rs b/vendor/educe/src/trait_handlers/clone/models/field_attribute.rs
new file mode 100644
index 00000000..63c7a9c7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/models/field_attribute.rs
@@ -0,0 +1,125 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Path, Token};
+
+use crate::{common::path::meta_2_path, panic, supported_traits::Trait};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) method: Option<Path>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_method: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_clone_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Clone"));
+
+ let mut method = None;
+
+ let correct_usage_for_clone_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(Clone(method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) | Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_clone_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut method_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "method" {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_clone_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ method,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Clone {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_clone_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ method: None
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/clone/models/mod.rs b/vendor/educe/src/trait_handlers/clone/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/clone/models/type_attribute.rs b/vendor/educe/src/trait_handlers/clone/models/type_attribute.rs
new file mode 100644
index 00000000..f657bbfa
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/clone/models/type_attribute.rs
@@ -0,0 +1,140 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{common::bound::Bound, panic, Trait};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_clone_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Clone"));
+
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_clone_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Clone)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Clone(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Clone(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_clone_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_clone_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_clone_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Clone {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_clone_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/copy/mod.rs b/vendor/educe/src/trait_handlers/copy/mod.rs
new file mode 100644
index 00000000..e1ce4016
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/copy/mod.rs
@@ -0,0 +1,94 @@
+mod models;
+
+use models::{FieldAttributeBuilder, TypeAttributeBuilder};
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct CopyHandler;
+
+impl TraitHandler for CopyHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ #[cfg(feature = "Clone")]
+ let contains_clone = traits.contains(&Trait::Clone);
+
+ #[cfg(not(feature = "Clone"))]
+ let contains_clone = false;
+
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_bound: !contains_clone,
+ }
+ .build_from_copy_meta(meta)?;
+
+ let mut field_types = vec![];
+
+ // if `contains_clone` is true, the implementation is handled by the `Clone` attribute, and field attributes is also handled by the `Clone` attribute
+ if !contains_clone {
+ match &ast.data {
+ Data::Struct(data) => {
+ for field in data.fields.iter() {
+ field_types.push(&field.ty);
+ let _ =
+ FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
+ }
+ },
+ Data::Enum(data) => {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false, enable_bound: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ for field in variant.fields.iter() {
+ field_types.push(&field.ty);
+ let _ = FieldAttributeBuilder
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+ }
+ },
+ Data::Union(data) => {
+ for field in data.fields.named.iter() {
+ field_types.push(&field.ty);
+ let _ =
+ FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
+ }
+ },
+ }
+
+ let ident = &ast.ident;
+
+ let bound =
+ type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::marker::Copy)).unwrap(),
+ &field_types,
+ &[quote! {::core::clone::Clone}],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/copy/models/field_attribute.rs b/vendor/educe/src/trait_handlers/copy/models/field_attribute.rs
new file mode 100644
index 00000000..e03c02d7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/copy/models/field_attribute.rs
@@ -0,0 +1,57 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{panic, supported_traits::Trait};
+
+pub(crate) struct FieldAttribute;
+
+pub(crate) struct FieldAttributeBuilder;
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_copy_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Copy"));
+
+ return Err(panic::attribute_incorrect_place(meta.path().get_ident().unwrap()));
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Copy {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_copy_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/copy/models/mod.rs b/vendor/educe/src/trait_handlers/copy/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/copy/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/copy/models/type_attribute.rs b/vendor/educe/src/trait_handlers/copy/models/type_attribute.rs
new file mode 100644
index 00000000..457acef7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/copy/models/type_attribute.rs
@@ -0,0 +1,140 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{common::bound::Bound, panic, Trait};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_copy_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Copy"));
+
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_copy_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Copy)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Copy(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Copy(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Copy {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_copy_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/common.rs b/vendor/educe/src/trait_handlers/debug/common.rs
new file mode 100644
index 00000000..e2c59a9d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/common.rs
@@ -0,0 +1,55 @@
+use quote::quote;
+use syn::{DeriveInput, Path, Type};
+
+#[inline]
+pub(crate) fn create_debug_map_builder() -> proc_macro2::TokenStream {
+ quote!(
+ #[allow(non_camel_case_types)] // We're using __ to help avoid clashes.
+ struct Educe__RawString(&'static str);
+
+ impl ::core::fmt::Debug for Educe__RawString {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ f.write_str(self.0)
+ }
+ }
+
+ let mut builder = f.debug_map();
+ )
+}
+
+#[inline]
+pub(crate) fn create_format_arg(
+ ast: &DeriveInput,
+ field_ty: &Type,
+ format_method: &Path,
+ field_expr: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let ty_ident = &ast.ident;
+
+ // We use the complete original generics, not filtered by field,
+ // and include a PhantomData<Self> in our wrapper struct to use the generics.
+ //
+ // This avoids having to try to calculate the right *subset* of the generics
+ // relevant for this field, which is nontrivial and maybe impossible.
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ quote!(
+ let arg = {
+ #[allow(non_camel_case_types)] // We're using __ to help avoid clashes.
+ struct Educe__DebugField<V, M>(V, ::core::marker::PhantomData<M>);
+
+ impl #impl_generics ::core::fmt::Debug
+ for Educe__DebugField<&#field_ty, #ty_ident #ty_generics>
+ #where_clause
+ {
+ #[inline]
+ fn fmt(&self, educe__f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ #format_method(self.0, educe__f)
+ }
+ }
+
+ Educe__DebugField(#field_expr, ::core::marker::PhantomData::<Self>)
+ };
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_enum.rs b/vendor/educe/src/trait_handlers/debug/debug_enum.rs
new file mode 100644
index 00000000..1e423818
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_enum.rs
@@ -0,0 +1,371 @@
+use quote::{format_ident, quote, ToTokens};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName};
+use crate::{common::path::path_to_string, supported_traits::Trait, trait_handlers::TraitHandler};
+
+pub(crate) struct DebugEnumHandler;
+
+impl TraitHandler for DebugEnumHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: false,
+ enable_bound: true,
+ name: TypeName::Disable,
+ named_field: false,
+ }
+ .build_from_debug_meta(meta)?;
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut debug_types: Vec<&Type> = Vec::new();
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ for variant in data.variants.iter() {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: true,
+ enable_bound: false,
+ name: TypeName::Default,
+ named_field: matches!(&variant.fields, Fields::Named(_)),
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ let variant_name = type_attribute.name.to_ident_by_ident(variant_ident);
+
+ let named_field = type_attribute.named_field;
+
+ let name_string = if let Some(name) = name {
+ if let Some(variant_name) = variant_name {
+ Some(path_to_string(&syn::parse2(quote!(#name::#variant_name)).unwrap()))
+ } else {
+ Some(name.into_token_stream().to_string())
+ }
+ } else {
+ variant_name.map(|variant_name| variant_name.into_token_stream().to_string())
+ };
+
+ match &variant.fields {
+ Fields::Unit => {
+ if name_string.is_none() {
+ return Err(super::panic::unit_variant_need_name(variant));
+ }
+
+ arms_token_stream
+ .extend(quote!( Self::#variant_ident => f.write_str(#name_string), ));
+ },
+ Fields::Named(fields) => {
+ let mut has_fields = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ if named_field {
+ block_token_stream
+ .extend(create_named_field_builder(name_string.as_deref()));
+
+ for field in fields.named.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var = format_ident!("_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ let key = match field_attribute.name {
+ FieldName::Custom(name) => name,
+ FieldName::Default => field_name_real.clone(),
+ };
+
+ pattern_token_stream
+ .extend(quote!(#field_name_real: #field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), #field_name_var);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), #field_name_var);)
+ });
+ }
+
+ has_fields = true;
+ }
+ } else {
+ block_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(#name_string);));
+
+ for field in fields.named.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var = format_ident!("_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_token_stream
+ .extend(quote!(#field_name_real: #field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream
+ .extend(quote! (builder.field(#field_name_var);));
+ }
+
+ has_fields = true;
+ }
+ }
+
+ if !has_fields && name_string.is_none() {
+ return Err(super::panic::unit_struct_need_name(variant_ident));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_token_stream } => {
+ #block_token_stream
+
+ builder.finish()
+ },
+ });
+ },
+ Fields::Unnamed(fields) => {
+ let mut has_fields = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ if named_field {
+ block_token_stream
+ .extend(create_named_field_builder(name_string.as_deref()));
+
+ for (index, field) in fields.unnamed.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var = format_ident!("_{}", index);
+
+ let key = match field_attribute.name {
+ FieldName::Custom(name) => name,
+ FieldName::Default => field_name_var.clone(),
+ };
+
+ pattern_token_stream.extend(quote!(#field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream.extend(if name_string.is_some() {
+ quote! (builder.field(stringify!(#key), #field_name_var);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), #field_name_var);)
+ });
+ }
+
+ has_fields = true;
+ }
+ } else {
+ block_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(#name_string);));
+
+ for (index, field) in fields.unnamed.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var = format_ident!("_{}", index);
+
+ pattern_token_stream.extend(quote!(#field_name_var,));
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(#field_name_var),
+ ));
+
+ block_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ block_token_stream
+ .extend(quote! (builder.field(#field_name_var);));
+ }
+
+ has_fields = true;
+ }
+ }
+
+ if !has_fields && name_string.is_none() {
+ return Err(super::panic::unit_struct_need_name(variant_ident));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ #block_token_stream
+
+ builder.finish()
+ },
+ });
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ if arms_token_stream.is_empty() {
+ if let Some(ident) = name {
+ builder_token_stream.extend(quote! {
+ f.write_str(stringify!(#ident))
+ });
+ } else {
+ return Err(super::panic::unit_enum_need_name(ident));
+ }
+ } else {
+ builder_token_stream.extend(quote! {
+ match self {
+ #arms_token_stream
+ }
+ });
+ }
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::fmt::Debug)).unwrap(),
+ &debug_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #builder_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
+
+#[inline]
+fn create_named_field_builder(name_string: Option<&str>) -> proc_macro2::TokenStream {
+ if let Some(name_string) = name_string {
+ quote!(let mut builder = f.debug_struct(#name_string);)
+ } else {
+ super::common::create_debug_map_builder()
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_struct.rs b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
new file mode 100644
index 00000000..6430480b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_struct.rs
@@ -0,0 +1,185 @@
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub struct DebugStructHandler;
+
+impl TraitHandler for DebugStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let is_tuple = {
+ if let Data::Struct(data) = &ast.data {
+ matches!(data.fields, Fields::Unnamed(_))
+ } else {
+ true
+ }
+ };
+
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_unsafe: false,
+ enable_name: true,
+ enable_named_field: true,
+ enable_bound: true,
+ name: TypeName::Default,
+ named_field: !is_tuple,
+ }
+ .build_from_debug_meta(meta)?;
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut debug_types: Vec<&Type> = Vec::new();
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+ let mut has_fields = false;
+
+ if type_attribute.named_field {
+ builder_token_stream.extend(if let Some(name) = name {
+ quote!(let mut builder = f.debug_struct(stringify!(#name));)
+ } else {
+ super::common::create_debug_map_builder()
+ });
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: true,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let (key, field_name) = match field_attribute.name {
+ FieldName::Custom(name) => {
+ (name, IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index))
+ },
+ FieldName::Default => {
+ if let Some(ident) = field.ident.as_ref() {
+ (ident.clone(), IdentOrIndex::from(ident))
+ } else {
+ (format_ident!("_{}", index), IdentOrIndex::from(index))
+ }
+ },
+ };
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &arg);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &arg);)
+ });
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(if name.is_some() {
+ quote! (builder.field(stringify!(#key), &self.#field_name);)
+ } else {
+ quote! (builder.entry(&Educe__RawString(stringify!(#key)), &self.#field_name);)
+ });
+ }
+
+ has_fields = true;
+ }
+ }
+ } else {
+ builder_token_stream
+ .extend(quote!(let mut builder = f.debug_tuple(stringify!(#name));));
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: true,
+ enable_method: true,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let field_name =
+ IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ let ty = &field.ty;
+
+ if let Some(method) = field_attribute.method {
+ builder_token_stream.extend(super::common::create_format_arg(
+ ast,
+ ty,
+ &method,
+ quote!(&self.#field_name),
+ ));
+
+ builder_token_stream.extend(quote! (builder.field(&arg);));
+ } else {
+ debug_types.push(ty);
+
+ builder_token_stream.extend(quote! (builder.field(&self.#field_name);));
+ }
+
+ has_fields = true;
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ if !has_fields && name.is_none() {
+ return Err(super::panic::unit_struct_need_name(ident));
+ }
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::fmt::Debug)).unwrap(),
+ &debug_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ #builder_token_stream
+
+ builder.finish()
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/debug_union.rs b/vendor/educe/src/trait_handlers/debug/debug_union.rs
new file mode 100644
index 00000000..096ea776
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/debug_union.rs
@@ -0,0 +1,86 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::{
+ models::{FieldAttributeBuilder, FieldName, TypeAttributeBuilder, TypeName},
+ TraitHandler,
+};
+use crate::supported_traits::Trait;
+
+pub(crate) struct DebugUnionHandler;
+
+impl TraitHandler for DebugUnionHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_unsafe: true,
+ enable_name: true,
+ enable_named_field: false,
+ enable_bound: false,
+ name: TypeName::Default,
+ named_field: false,
+ }
+ .build_from_debug_meta(meta)?;
+
+ if !type_attribute.has_unsafe {
+ return Err(super::panic::union_without_unsafe(meta));
+ }
+
+ let name = type_attribute.name.to_ident_by_ident(&ast.ident);
+
+ let mut builder_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Union(data) = &ast.data {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_name: false,
+ enable_ignore: false,
+ enable_method: false,
+ name: FieldName::Default,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+
+ if let Some(name) = name {
+ builder_token_stream.extend(quote!(
+ let mut builder = f.debug_tuple(stringify!(#name));
+
+ let size = ::core::mem::size_of::<Self>();
+
+ let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+
+ builder.field(&data);
+
+ builder.finish()
+ ));
+ } else {
+ builder_token_stream.extend(quote!(
+ let size = ::core::mem::size_of::<Self>();
+ let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+
+ ::core::fmt::Debug::fmt(data, f)
+ ));
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::fmt::Debug for #ident #ty_generics #where_clause {
+ #[inline]
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ #builder_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/mod.rs b/vendor/educe/src/trait_handlers/debug/mod.rs
new file mode 100644
index 00000000..367ddb71
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/mod.rs
@@ -0,0 +1,38 @@
+mod common;
+mod debug_enum;
+mod debug_struct;
+mod debug_union;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DebugHandler;
+
+impl TraitHandler for DebugHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => debug_struct::DebugStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => {
+ debug_enum::DebugEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ debug_union::DebugUnionHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs b/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs
new file mode 100644
index 00000000..f2cd3e28
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/models/field_attribute.rs
@@ -0,0 +1,224 @@
+use syn::{punctuated::Punctuated, Attribute, Ident, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{
+ meta_2_bool_allow_path, meta_2_ident, meta_name_value_2_bool, meta_name_value_2_ident,
+ meta_name_value_2_ident_and_bool, IdentOrBool,
+ },
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+#[derive(Debug, Clone)]
+pub(crate) enum FieldName {
+ Default,
+ Custom(Ident),
+}
+
+pub(crate) struct FieldAttribute {
+ pub(crate) name: FieldName,
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_name: bool,
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+ pub(crate) name: FieldName,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_debug_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Debug"));
+
+ let mut name = self.name.clone();
+ let mut ignore = false;
+ let mut method = None;
+
+ let correct_usage_for_debug_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_name {
+ usage.push(stringify!(#[educe(Debug = NewName)]));
+ usage.push(stringify!(#[educe(Debug(name(NewName)))]));
+ }
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(Debug = false)]));
+ usage.push(stringify!(#[educe(Debug(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(Debug(method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_name {
+ if self.enable_ignore {
+ match meta_name_value_2_ident_and_bool(name_value)? {
+ IdentOrBool::Ident(ident) => {
+ name = FieldName::Custom(ident);
+ },
+ IdentOrBool::Bool(b) => {
+ ignore = !b;
+ },
+ }
+ } else {
+ name = FieldName::Custom(meta_name_value_2_ident(name_value)?);
+ }
+ } else if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut name_is_set = false;
+ let mut ignore_is_set = false;
+ let mut method_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "name" | "rename" => {
+ if !self.enable_name {
+ return Ok(false);
+ }
+
+ let v = meta_2_ident(&meta)?;
+
+ if name_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ name_is_set = true;
+
+ name = FieldName::Custom(v);
+
+ return Ok(true);
+ },
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ name,
+ ignore,
+ method,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Debug {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_debug_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ name: self.name.clone(),
+ ignore: false,
+ method: None,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/models/mod.rs b/vendor/educe/src/trait_handlers/debug/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/debug/models/type_attribute.rs b/vendor/educe/src/trait_handlers/debug/models/type_attribute.rs
new file mode 100644
index 00000000..ed84ddf3
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/models/type_attribute.rs
@@ -0,0 +1,264 @@
+use proc_macro2::Ident;
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{
+ common::{
+ bound::Bound,
+ ident_bool::{meta_2_bool, meta_2_ident_and_bool, meta_name_value_2_ident, IdentOrBool},
+ unsafe_punctuated_meta::UnsafePunctuatedMeta,
+ },
+ panic, Trait,
+};
+
+#[derive(Debug, Clone)]
+pub(crate) enum TypeName {
+ Disable,
+ Default,
+ Custom(Ident),
+}
+
+impl TypeName {
+ #[inline]
+ pub(crate) fn to_ident_by_ident<'a, 'b: 'a>(&'a self, ident: &'b Ident) -> Option<&'a Ident> {
+ match self {
+ Self::Disable => None,
+ Self::Default => Some(ident),
+ Self::Custom(ident) => Some(ident),
+ }
+ }
+}
+
+pub(crate) struct TypeAttribute {
+ pub(crate) has_unsafe: bool,
+ pub(crate) name: TypeName,
+ pub(crate) named_field: bool,
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_unsafe: bool,
+ pub(crate) enable_name: bool,
+ pub(crate) enable_named_field: bool,
+ pub(crate) enable_bound: bool,
+ pub(crate) name: TypeName,
+ pub(crate) named_field: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_debug_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Debug"));
+
+ let mut has_unsafe = false;
+ let mut name = self.name.clone();
+ let mut named_field = self.named_field;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_debug_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Debug)]));
+ }
+
+ if self.enable_name {
+ if !self.enable_unsafe {
+ usage.push(stringify!(#[educe(Debug = NewName)]));
+ }
+
+ usage.push(stringify!(#[educe(Debug(name(NewName)))]));
+
+ if let TypeName::Disable = &name {
+ usage.push(stringify!(#[educe(Debug(name = true))]));
+ } else {
+ usage.push(stringify!(#[educe(Debug(name = false))]));
+ }
+ }
+
+ if self.enable_named_field {
+ if !self.named_field {
+ usage.push(stringify!(#[educe(Debug(named_field = true))]));
+ } else {
+ usage.push(stringify!(#[educe(Debug(named_field = false))]));
+ }
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Debug(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Debug(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(name_value) => {
+ if !self.enable_name {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+
+ name = TypeName::Custom(meta_name_value_2_ident(name_value)?);
+ },
+ Meta::List(list) => {
+ let result = if self.enable_unsafe {
+ let result: UnsafePunctuatedMeta = list.parse_args()?;
+
+ has_unsafe = result.has_unsafe;
+
+ result.list
+ } else {
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?
+ };
+
+ let mut name_is_set = false;
+ let mut named_field_is_set = false;
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "name" | "rename" => {
+ if !self.enable_name {
+ return Ok(false);
+ }
+
+ let v = meta_2_ident_and_bool(&meta)?;
+
+ if name_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ name_is_set = true;
+
+ name = match v {
+ IdentOrBool::Ident(ident) => TypeName::Custom(ident),
+ IdentOrBool::Bool(b) => {
+ if b {
+ TypeName::Default
+ } else {
+ TypeName::Disable
+ }
+ },
+ };
+
+ return Ok(true);
+ },
+ "named_field" => {
+ if !self.enable_named_field {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool(&meta)?;
+
+ if named_field_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ named_field_is_set = true;
+
+ named_field = v;
+
+ return Ok(true);
+ },
+ "bound" => {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_debug_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ has_unsafe,
+ name,
+ named_field,
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Debug {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_debug_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ has_unsafe: false,
+ name: self.name.clone(),
+ named_field: self.named_field,
+ bound: Bound::Auto,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/debug/panic.rs b/vendor/educe/src/trait_handlers/debug/panic.rs
new file mode 100644
index 00000000..a29646a7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/debug/panic.rs
@@ -0,0 +1,43 @@
+use quote::ToTokens;
+use syn::{spanned::Spanned, Ident, Meta, Variant};
+
+#[inline]
+pub(crate) fn unit_struct_need_name(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), "a unit struct needs to have a name")
+}
+
+#[inline]
+pub(crate) fn unit_variant_need_name(variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ variant.span(),
+ "a unit variant which doesn't use an enum name needs to have a name",
+ )
+}
+
+#[inline]
+pub(crate) fn unit_enum_need_name(name: &Ident) -> syn::Error {
+ syn::Error::new(name.span(), "a unit enum needs to have a name")
+}
+
+#[inline]
+pub(crate) fn union_without_unsafe(meta: &Meta) -> syn::Error {
+ let mut s = meta.into_token_stream().to_string().replace(" , ", ", ");
+
+ match s.len() {
+ 5 => s.push_str("(unsafe)"),
+ 7 => s.insert_str(6, "unsafe"),
+ _ => s.insert_str(6, "unsafe, "),
+ }
+
+ syn::Error::new(
+ meta.span(),
+ format!(
+ "a union's `Debug` implementation may expose uninitialized memory\n* It is \
+ recommended that, for a union where `Debug` is implemented, types that allow \
+ uninitialized memory should not be used in it.\n* If you can ensure that the union \
+ uses no such types, use `#[educe({s})]` to implement the `Debug` trait for it.\n* \
+ The `unsafe` keyword should be placed as the first parameter of the `Debug` \
+ attribute."
+ ),
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/default/default_enum.rs b/vendor/educe/src/trait_handlers/default/default_enum.rs
new file mode 100644
index 00000000..8aa4ec6e
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_enum.rs
@@ -0,0 +1,230 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Fields, Meta, Type, Variant};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultEnumHandler;
+
+impl TraitHandler for DefaultEnumHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ ensure_fields_no_attribute(&variant.fields, traits)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ let variant = {
+ let variants = &data.variants;
+
+ if variants.len() == 1 {
+ let variant = &variants[0];
+
+ let _ = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ variant
+ } else {
+ let mut default_variant: Option<&Variant> = None;
+
+ for variant in variants {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: false,
+ enable_expression: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ if type_attribute.flag {
+ if default_variant.is_some() {
+ return Err(super::panic::multiple_default_variants(
+ type_attribute.span,
+ ));
+ }
+
+ default_variant = Some(variant);
+ } else {
+ ensure_fields_no_attribute(&variant.fields, traits)?;
+ }
+ }
+
+ if let Some(default_variant) = default_variant {
+ default_variant
+ } else {
+ return Err(super::panic::no_default_variant(meta.span()));
+ }
+ }
+ };
+
+ let variant_ident = &variant.ident;
+
+ match &variant.fields {
+ Fields::Unit => {
+ default_token_stream.extend(quote!(Self::#variant_ident));
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+ }
+
+ default_token_stream.extend(quote! {
+ Self::#variant_ident {
+ #fields_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote!(#expression,));
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream
+ .extend(quote!(<#ty as ::core::default::Default>::default(),));
+ }
+ }
+
+ default_token_stream
+ .extend(quote!(Self::#variant_ident ( #fields_token_stream )));
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
+
+fn ensure_fields_no_attribute(fields: &Fields, traits: &[Trait]) -> syn::Result<()> {
+ match fields {
+ Fields::Unit => (),
+ Fields::Named(fields) => {
+ for field in fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+ },
+ Fields::Unnamed(fields) => {
+ for field in fields.unnamed.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+ },
+ }
+
+ Ok(())
+}
diff --git a/vendor/educe/src/trait_handlers/default/default_struct.rs b/vendor/educe/src/trait_handlers/default/default_struct.rs
new file mode 100644
index 00000000..ea25b565
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_struct.rs
@@ -0,0 +1,149 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultStructHandler;
+
+impl TraitHandler for DefaultStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for field in data.fields.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ match &data.fields {
+ Fields::Unit => {
+ default_token_stream.extend(quote!(Self));
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+ }
+
+ default_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote!(#expression,));
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream
+ .extend(quote!(<#ty as ::core::default::Default>::default(),));
+ }
+ }
+
+ default_token_stream.extend(quote!(Self ( #fields_token_stream )));
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/default_union.rs b/vendor/educe/src/trait_handlers/default/default_union.rs
new file mode 100644
index 00000000..a535c011
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_union.rs
@@ -0,0 +1,153 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultUnionHandler;
+
+impl TraitHandler for DefaultUnionHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Union(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ let (field, field_attribute) =
+ {
+ let fields = &data.fields.named;
+
+ if fields.len() == 1 {
+ let field = &fields[0];
+
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ (field, field_attribute)
+ } else {
+ let mut default_field: Option<(&Field, FieldAttribute)> = None;
+
+ for field in fields {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if field_attribute.flag || field_attribute.expression.is_some() {
+ if default_field.is_some() {
+ return Err(super::panic::multiple_default_fields(
+ field_attribute.span,
+ ));
+ }
+
+ default_field = Some((field, field_attribute));
+ }
+ }
+
+ if let Some(default_field) = default_field {
+ default_field
+ } else {
+ return Err(super::panic::no_default_field(meta.span()));
+ }
+ }
+ };
+
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+
+ default_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/mod.rs b/vendor/educe/src/trait_handlers/default/mod.rs
new file mode 100644
index 00000000..5c1eeb8d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/mod.rs
@@ -0,0 +1,43 @@
+mod default_enum;
+mod default_struct;
+mod default_union;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DefaultHandler;
+
+impl TraitHandler for DefaultHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => default_struct::DefaultStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => default_enum::DefaultEnumHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Union(_) => default_union::DefaultUnionHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/models/field_attribute.rs b/vendor/educe/src/trait_handlers/default/models/field_attribute.rs
new file mode 100644
index 00000000..6c82940d
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/field_attribute.rs
@@ -0,0 +1,166 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Expr, Meta, Token, Type};
+
+use crate::{
+ common::expr::{auto_adjust_expr, meta_2_expr},
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) flag: bool,
+ pub(crate) expression: Option<Expr>,
+ pub(crate) span: Span,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_expression: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_default_meta(
+ &self,
+ meta: &Meta,
+ ty: &Type,
+ ) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Default"));
+
+ let mut flag = false;
+ let mut expression = None;
+
+ let correct_usage_for_default_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Default)]));
+ }
+
+ if self.enable_expression {
+ usage.push(stringify!(#[educe(Default = expr)]));
+
+ usage.push(stringify!(#[educe(Default(expression = expr))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ flag = true;
+ },
+ Meta::NameValue(name_value) => {
+ if !self.enable_expression {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ expression = Some(auto_adjust_expr(name_value.value.clone(), Some(ty)));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut expression_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "expression" | "expr" => {
+ if !self.enable_expression {
+ return Ok(false);
+ }
+
+ let v = meta_2_expr(&meta)?;
+
+ if expression_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ expression_is_set = true;
+
+ expression = Some(auto_adjust_expr(v, Some(ty)));
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ flag,
+ expression,
+ span: meta.span(),
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ty: &Type,
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Default {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_default_meta(&meta, ty)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ flag: false,
+ expression: None,
+ span: Span::call_site(),
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/models/mod.rs b/vendor/educe/src/trait_handlers/default/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/default/models/type_attribute.rs b/vendor/educe/src/trait_handlers/default/models/type_attribute.rs
new file mode 100644
index 00000000..ee0b901b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/models/type_attribute.rs
@@ -0,0 +1,214 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Expr, Meta, Token};
+
+use crate::{
+ common::{
+ bound::Bound,
+ expr::{auto_adjust_expr, meta_2_expr},
+ ident_bool::meta_2_bool_allow_path,
+ },
+ panic, Trait,
+};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) flag: bool,
+ pub(crate) new: bool,
+ pub(crate) expression: Option<Expr>,
+ pub(crate) bound: Bound,
+ pub(crate) span: Span,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_new: bool,
+ pub(crate) enable_expression: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_default_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Default"));
+
+ let mut flag = false;
+ let mut new = false;
+ let mut expression = None;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_default_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Default)]));
+ }
+
+ if self.enable_new {
+ usage.push(stringify!(#[educe(Default(new))]));
+ }
+
+ if self.enable_expression {
+ usage.push(stringify!(#[educe(Default(expression = expr))]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Default(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Default(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+
+ flag = true;
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut new_is_set = false;
+ let mut expression_is_set = false;
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "new" => {
+ if !self.enable_new {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if new_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ new_is_set = true;
+
+ new = v;
+
+ return Ok(true);
+ },
+ "expression" | "expr" => {
+ if !self.enable_expression {
+ return Ok(false);
+ }
+
+ let v = meta_2_expr(&meta)?;
+
+ if expression_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ expression_is_set = true;
+
+ expression = Some(auto_adjust_expr(v, None));
+
+ return Ok(true);
+ },
+ "bound" => {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_default_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ flag,
+ new,
+ expression,
+ bound,
+ span: meta.span(),
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Default {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_default_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ flag: false,
+ new: false,
+ expression: None,
+ bound: Bound::Auto,
+ span: Span::call_site(),
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/default/panic.rs b/vendor/educe/src/trait_handlers/default/panic.rs
new file mode 100644
index 00000000..9f3598ea
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/panic.rs
@@ -0,0 +1,21 @@
+use proc_macro2::Span;
+
+#[inline]
+pub(crate) fn multiple_default_fields(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple default fields are set")
+}
+
+#[inline]
+pub(crate) fn no_default_field(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no field set as default")
+}
+
+#[inline]
+pub(crate) fn multiple_default_variants(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple default variants are set")
+}
+
+#[inline]
+pub(crate) fn no_default_variant(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no variant set as default")
+}
diff --git a/vendor/educe/src/trait_handlers/deref/deref_enum.rs b/vendor/educe/src/trait_handlers/deref/deref_enum.rs
new file mode 100644
index 00000000..1c478cc9
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/deref_enum.rs
@@ -0,0 +1,144 @@
+use quote::{format_ident, quote};
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Fields, Ident, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::r#type::dereference, panic, supported_traits::Trait};
+
+pub(crate) struct DerefEnumHandler;
+
+impl TraitHandler for DerefEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let _ = TypeAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_deref_meta(meta)?;
+
+ let mut target_token_stream = proc_macro2::TokenStream::new();
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ type Variants<'a> = Vec<(&'a Ident, bool, usize, Ident, &'a Type)>;
+
+ let mut variants: Variants = Vec::new();
+
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ if let Fields::Unit = &variant.fields {
+ return Err(panic::trait_not_support_unit_variant(
+ meta.path().get_ident().unwrap(),
+ variant,
+ ));
+ }
+
+ let fields = &variant.fields;
+
+ let (index, field) = if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let _ = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ (0usize, field)
+ } else {
+ let mut deref_field: Option<(usize, &Field)> = None;
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.flag {
+ if deref_field.is_some() {
+ return Err(super::panic::multiple_deref_fields_of_variant(
+ field_attribute.span,
+ variant,
+ ));
+ }
+
+ deref_field = Some((index, field));
+ }
+ }
+
+ if let Some(deref_field) = deref_field {
+ deref_field
+ } else {
+ return Err(super::panic::no_deref_field_of_variant(meta.span(), variant));
+ }
+ };
+
+ let (field_name, is_tuple): (Ident, bool) = match field.ident.as_ref() {
+ Some(ident) => (ident.clone(), false),
+ None => (format_ident!("_{}", index), true),
+ };
+
+ variants.push((&variant.ident, is_tuple, index, field_name, &field.ty));
+ }
+
+ if variants.is_empty() {
+ return Err(super::panic::no_deref_field(meta.span()));
+ }
+
+ let ty = variants[0].4;
+ let dereference_ty = dereference(ty);
+
+ target_token_stream.extend(quote!(#dereference_ty));
+
+ for (variant_ident, is_tuple, index, field_name, _) in variants {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+
+ if is_tuple {
+ for _ in 0..index {
+ pattern_token_stream.extend(quote!(_,));
+ }
+
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident ( #pattern_token_stream ) => #field_name, ),
+ );
+ } else {
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident { #pattern_token_stream } => #field_name, ),
+ );
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::ops::Deref for #ident #ty_generics #where_clause {
+ type Target = #target_token_stream;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ match self {
+ #arms_token_stream
+ }
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref/deref_struct.rs b/vendor/educe/src/trait_handlers/deref/deref_struct.rs
new file mode 100644
index 00000000..8c971308
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/deref_struct.rs
@@ -0,0 +1,103 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{
+ common::{ident_index::IdentOrIndex, r#type::dereference_changed},
+ Trait,
+};
+
+pub(crate) struct DerefStructHandler;
+
+impl TraitHandler for DerefStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let _ = TypeAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_deref_meta(meta)?;
+
+ let mut target_token_stream = proc_macro2::TokenStream::new();
+ let mut deref_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let (index, field) = {
+ let fields = &data.fields;
+
+ if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let _ = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ (0usize, field)
+ } else {
+ let mut deref_field: Option<(usize, &Field)> = None;
+
+ for (index, field) in fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.flag {
+ if deref_field.is_some() {
+ return Err(super::panic::multiple_deref_fields(
+ field_attribute.span,
+ ));
+ }
+
+ deref_field = Some((index, field));
+ }
+ }
+
+ if let Some(deref_field) = deref_field {
+ deref_field
+ } else {
+ return Err(super::panic::no_deref_field(meta.span()));
+ }
+ }
+ };
+
+ let ty = &field.ty;
+ let (dereference_ty, is_ref) = dereference_changed(ty);
+
+ target_token_stream.extend(quote!(#dereference_ty));
+
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ deref_token_stream.extend(if is_ref {
+ quote! (self.#field_name)
+ } else {
+ quote! (&self.#field_name)
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::ops::Deref for #ident #ty_generics #where_clause {
+ type Target = #target_token_stream;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ #deref_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref/mod.rs b/vendor/educe/src/trait_handlers/deref/mod.rs
new file mode 100644
index 00000000..1a3263cd
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/mod.rs
@@ -0,0 +1,36 @@
+mod deref_enum;
+mod deref_struct;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DerefHandler;
+
+impl TraitHandler for DerefHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => deref_struct::DerefStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => {
+ deref_enum::DerefEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ Err(crate::panic::trait_not_support_union(meta.path().get_ident().unwrap()))
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref/models/field_attribute.rs b/vendor/educe/src/trait_handlers/deref/models/field_attribute.rs
new file mode 100644
index 00000000..5f3d3fba
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/models/field_attribute.rs
@@ -0,0 +1,94 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Meta, Token};
+
+use crate::{panic, supported_traits::Trait};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) flag: bool,
+ pub(crate) span: Span,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_flag: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_deref_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Deref"));
+
+ let correct_usage_for_deref_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Deref)]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) | Meta::List(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_attribute,
+ ));
+ },
+ }
+
+ Ok(FieldAttribute {
+ flag: true, span: meta.span()
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Deref {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_deref_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ flag: false, span: Span::call_site()
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref/models/mod.rs b/vendor/educe/src/trait_handlers/deref/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/deref/models/type_attribute.rs b/vendor/educe/src/trait_handlers/deref/models/type_attribute.rs
new file mode 100644
index 00000000..01b9e5e9
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/models/type_attribute.rs
@@ -0,0 +1,87 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{panic, Trait};
+
+pub(crate) struct TypeAttribute;
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_deref_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Deref"));
+
+ let correct_usage_for_deref_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Deref)]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) | Meta::List(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_attribute,
+ ));
+ },
+ }
+
+ Ok(TypeAttribute)
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Deref {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_deref_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref/panic.rs b/vendor/educe/src/trait_handlers/deref/panic.rs
new file mode 100644
index 00000000..508b6235
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref/panic.rs
@@ -0,0 +1,31 @@
+use proc_macro2::Span;
+use syn::Variant;
+
+#[inline]
+pub(crate) fn multiple_deref_fields(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple fields are set for `Deref`")
+}
+
+#[inline]
+pub(crate) fn multiple_deref_fields_of_variant(span: Span, variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ span,
+ format!("multiple fields of the `{}` variant are set for `Deref`", variant.ident),
+ )
+}
+
+#[inline]
+pub(crate) fn no_deref_field(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no field which is assigned for `Deref`")
+}
+
+#[inline]
+pub(crate) fn no_deref_field_of_variant(span: Span, variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ span,
+ format!(
+ "there is no field for the `{}` variant which is assigned for `Deref`",
+ variant.ident
+ ),
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/deref_mut_enum.rs b/vendor/educe/src/trait_handlers/deref_mut/deref_mut_enum.rs
new file mode 100644
index 00000000..6ba2f2ed
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/deref_mut_enum.rs
@@ -0,0 +1,139 @@
+use quote::{format_ident, quote};
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Fields, Ident, Meta};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{panic, supported_traits::Trait};
+
+pub(crate) struct DerefMutEnumHandler;
+
+impl TraitHandler for DerefMutEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let _ = TypeAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_deref_mut_meta(meta)?;
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ type Variants<'a> = Vec<(&'a Ident, bool, usize, Ident)>;
+
+ let mut variants: Variants = Vec::new();
+
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ if let Fields::Unit = &variant.fields {
+ return Err(panic::trait_not_support_unit_variant(
+ meta.path().get_ident().unwrap(),
+ variant,
+ ));
+ }
+
+ let fields = &variant.fields;
+
+ let (index, field) = if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let _ = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ (0usize, field)
+ } else {
+ let mut deref_field: Option<(usize, &Field)> = None;
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.flag {
+ if deref_field.is_some() {
+ return Err(super::panic::multiple_deref_mut_fields_of_variant(
+ field_attribute.span,
+ variant,
+ ));
+ }
+
+ deref_field = Some((index, field));
+ }
+ }
+
+ if let Some(deref_field) = deref_field {
+ deref_field
+ } else {
+ return Err(super::panic::no_deref_mut_field_of_variant(
+ meta.span(),
+ variant,
+ ));
+ }
+ };
+
+ let (field_name, is_tuple): (Ident, bool) = match field.ident.as_ref() {
+ Some(ident) => (ident.clone(), false),
+ None => (format_ident!("_{}", index), true),
+ };
+
+ variants.push((&variant.ident, is_tuple, index, field_name));
+ }
+
+ if variants.is_empty() {
+ return Err(super::panic::no_deref_mut_field(meta.span()));
+ }
+
+ for (variant_ident, is_tuple, index, field_name) in variants {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+
+ if is_tuple {
+ for _ in 0..index {
+ pattern_token_stream.extend(quote!(_,));
+ }
+
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident ( #pattern_token_stream ) => #field_name, ),
+ );
+ } else {
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident { #pattern_token_stream } => #field_name, ),
+ );
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::ops::DerefMut for #ident #ty_generics #where_clause {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ match self {
+ #arms_token_stream
+ }
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/deref_mut_struct.rs b/vendor/educe/src/trait_handlers/deref_mut/deref_mut_struct.rs
new file mode 100644
index 00000000..deb58880
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/deref_mut_struct.rs
@@ -0,0 +1,92 @@
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct DerefMutStructHandler;
+
+impl TraitHandler for DerefMutStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let _ = TypeAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_deref_mut_meta(meta)?;
+
+ let mut deref_mut_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let (index, field) = {
+ let fields = &data.fields;
+
+ if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let _ = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ (0usize, field)
+ } else {
+ let mut deref_field: Option<(usize, &Field)> = None;
+
+ for (index, field) in fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.flag {
+ if deref_field.is_some() {
+ return Err(super::panic::multiple_deref_mut_fields(
+ field_attribute.span,
+ ));
+ }
+
+ deref_field = Some((index, field));
+ }
+ }
+
+ if let Some(deref_field) = deref_field {
+ deref_field
+ } else {
+ return Err(super::panic::no_deref_mut_field(meta.span()));
+ }
+ }
+ };
+
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ deref_mut_token_stream.extend(if let Type::Reference(_) = &field.ty {
+ quote! (self.#field_name)
+ } else {
+ quote! (&mut self.#field_name)
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::ops::DerefMut for #ident #ty_generics #where_clause {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ #deref_mut_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/mod.rs b/vendor/educe/src/trait_handlers/deref_mut/mod.rs
new file mode 100644
index 00000000..01f09912
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/mod.rs
@@ -0,0 +1,39 @@
+mod deref_mut_enum;
+mod deref_mut_struct;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct DerefMutHandler;
+
+impl TraitHandler for DerefMutHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => deref_mut_struct::DerefMutStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => deref_mut_enum::DerefMutEnumHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Union(_) => {
+ Err(crate::panic::trait_not_support_union(meta.path().get_ident().unwrap()))
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/models/field_attribute.rs b/vendor/educe/src/trait_handlers/deref_mut/models/field_attribute.rs
new file mode 100644
index 00000000..e04543e4
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/models/field_attribute.rs
@@ -0,0 +1,94 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Meta, Token};
+
+use crate::{panic, supported_traits::Trait};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) flag: bool,
+ pub(crate) span: Span,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_flag: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_deref_mut_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("DerefMut"));
+
+ let correct_usage_for_deref_mut_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(DerefMut)]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_mut_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) | Meta::List(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_mut_attribute,
+ ));
+ },
+ }
+
+ Ok(FieldAttribute {
+ flag: true, span: meta.span()
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::DerefMut {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_deref_mut_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ flag: false, span: Span::call_site()
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/models/mod.rs b/vendor/educe/src/trait_handlers/deref_mut/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/deref_mut/models/type_attribute.rs b/vendor/educe/src/trait_handlers/deref_mut/models/type_attribute.rs
new file mode 100644
index 00000000..782d1361
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/models/type_attribute.rs
@@ -0,0 +1,87 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{panic, Trait};
+
+pub(crate) struct TypeAttribute;
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_deref_mut_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("DerefMut"));
+
+ let correct_usage_for_deref_mut_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(DerefMut)]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_mut_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) | Meta::List(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_deref_mut_attribute,
+ ));
+ },
+ }
+
+ Ok(TypeAttribute)
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::DerefMut {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_deref_mut_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/deref_mut/panic.rs b/vendor/educe/src/trait_handlers/deref_mut/panic.rs
new file mode 100644
index 00000000..d7b14660
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/deref_mut/panic.rs
@@ -0,0 +1,31 @@
+use proc_macro2::Span;
+use syn::Variant;
+
+#[inline]
+pub(crate) fn multiple_deref_mut_fields(span: Span) -> syn::Error {
+ syn::Error::new(span, "multiple fields are set for `DerefMut`")
+}
+
+#[inline]
+pub(crate) fn multiple_deref_mut_fields_of_variant(span: Span, variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ span,
+ format!("multiple fields of the `{}` variant are set for `DerefMut`", variant.ident),
+ )
+}
+
+#[inline]
+pub(crate) fn no_deref_mut_field(span: Span) -> syn::Error {
+ syn::Error::new(span, "there is no field which is assigned for `DerefMut`")
+}
+
+#[inline]
+pub(crate) fn no_deref_mut_field_of_variant(span: Span, variant: &Variant) -> syn::Error {
+ syn::Error::new(
+ span,
+ format!(
+ "there is no field for the `{}` variant which is assigned for `DerefMut`",
+ variant.ident
+ ),
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/eq/mod.rs b/vendor/educe/src/trait_handlers/eq/mod.rs
new file mode 100644
index 00000000..bff020d7
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/eq/mod.rs
@@ -0,0 +1,106 @@
+mod models;
+
+use models::{FieldAttributeBuilder, TypeAttributeBuilder};
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct EqHandler;
+
+impl TraitHandler for EqHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ #[cfg(feature = "PartialEq")]
+ let contains_partial_eq = traits.contains(&Trait::PartialEq);
+
+ #[cfg(not(feature = "PartialEq"))]
+ let contains_partial_eq = false;
+
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_bound: !contains_partial_eq,
+ }
+ .build_from_eq_meta(meta)?;
+
+ let mut field_types = vec![];
+
+ // if `contains_partial_eq` is true, the implementation is handled by the `PartialEq` attribute, and field attributes is also handled by the `PartialEq` attribute
+ if !contains_partial_eq {
+ match &ast.data {
+ Data::Struct(data) => {
+ for field in data.fields.iter() {
+ field_types.push(&field.ty);
+ let _ =
+ FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
+ }
+ },
+ Data::Enum(data) => {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false, enable_bound: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ for field in variant.fields.iter() {
+ field_types.push(&field.ty);
+ let _ = FieldAttributeBuilder
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+ }
+ },
+ Data::Union(data) => {
+ for field in data.fields.named.iter() {
+ field_types.push(&field.ty);
+ let _ =
+ FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
+ }
+ },
+ }
+
+ let ident = &ast.ident;
+
+ /*
+ #[derive(PartialEq)]
+ struct B<T> {
+ f1: PhantomData<T>,
+ }
+
+ impl<T> Eq for B<T> {
+
+ }
+
+ // The above code will throw a compile error because T have to be bound to `PartialEq`. However, it seems not to be necessary logically.
+ */
+ let bound =
+ type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::PartialEq)).unwrap(),
+ &field_types,
+ &[quote! {::core::cmp::PartialEq}],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/eq/models/field_attribute.rs b/vendor/educe/src/trait_handlers/eq/models/field_attribute.rs
new file mode 100644
index 00000000..ce78d6b8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/eq/models/field_attribute.rs
@@ -0,0 +1,57 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{panic, supported_traits::Trait};
+
+pub(crate) struct FieldAttribute;
+
+pub(crate) struct FieldAttributeBuilder;
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_eq_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Eq"));
+
+ return Err(panic::attribute_incorrect_place(meta.path().get_ident().unwrap()));
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Eq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_eq_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/eq/models/mod.rs b/vendor/educe/src/trait_handlers/eq/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/eq/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/eq/models/type_attribute.rs b/vendor/educe/src/trait_handlers/eq/models/type_attribute.rs
new file mode 100644
index 00000000..5c537080
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/eq/models/type_attribute.rs
@@ -0,0 +1,140 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{common::bound::Bound, panic, Trait};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_eq_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Eq"));
+
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_copy_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Eq)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Eq(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Eq(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_copy_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Eq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_eq_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/hash_enum.rs b/vendor/educe/src/trait_handlers/hash/hash_enum.rs
new file mode 100644
index 00000000..01337029
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/hash_enum.rs
@@ -0,0 +1,169 @@
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct HashEnumHandler;
+
+impl TraitHandler for HashEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: false, enable_bound: true
+ }
+ .build_from_hash_meta(meta)?;
+
+ let mut hash_types: Vec<&Type> = Vec::new();
+
+ let mut hash_token_stream = proc_macro2::TokenStream::new();
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ for (variant_index, variant) in data.variants.iter().enumerate() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_unsafe: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ let built_in_hash: Path = syn::parse2(quote!(::core::hash::Hash::hash)).unwrap();
+
+ match &variant.fields {
+ Fields::Unit => {
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident => {
+ ::core::hash::Hash::hash(&#variant_index, state);
+ }
+ });
+ },
+ Fields::Named(_) => {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var = format_ident!("v_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_token_stream.extend(quote!(#field_name_real: #field_name_var,));
+
+ let hash = field_attribute.method.as_ref().unwrap_or_else(|| {
+ hash_types.push(&field.ty);
+ &built_in_hash
+ });
+
+ block_token_stream.extend(quote!( #hash(#field_name_var, state); ));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_token_stream } => {
+ ::core::hash::Hash::hash(&#variant_index, state);
+
+ #block_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_var = format_ident!("_{}", index);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ pattern_token_stream.extend(quote!(#field_name_var,));
+
+ let hash = field_attribute.method.as_ref().unwrap_or_else(|| {
+ hash_types.push(&field.ty);
+ &built_in_hash
+ });
+
+ block_token_stream.extend(quote!( #hash(#field_name_var, state); ));
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ ::core::hash::Hash::hash(&#variant_index, state);
+
+ #block_token_stream
+ }
+ });
+ },
+ }
+ }
+ }
+
+ if !arms_token_stream.is_empty() {
+ hash_token_stream.extend(quote! {
+ match self {
+ #arms_token_stream
+ }
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::hash::Hash)).unwrap(),
+ &hash_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::hash::Hash for #ident #ty_generics #where_clause {
+ #[inline]
+ fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
+ #hash_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/hash_struct.rs b/vendor/educe/src/trait_handlers/hash/hash_struct.rs
new file mode 100644
index 00000000..0444e4b0
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/hash_struct.rs
@@ -0,0 +1,88 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct HashStructHandler;
+
+impl TraitHandler for HashStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: false, enable_bound: true
+ }
+ .build_from_hash_meta(meta)?;
+
+ let mut hash_types: Vec<&Type> = Vec::new();
+
+ let mut hash_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let built_in_hash: Path = syn::parse2(quote!(::core::hash::Hash::hash)).unwrap();
+
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let field_name = if let Some(ident) = field.ident.as_ref() {
+ IdentOrIndex::from(ident)
+ } else {
+ IdentOrIndex::from(index)
+ };
+
+ let hash = field_attribute.method.as_ref().unwrap_or_else(|| {
+ hash_types.push(&field.ty);
+ &built_in_hash
+ });
+
+ hash_token_stream.extend(quote!( #hash(&self.#field_name, state); ));
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::hash::Hash)).unwrap(),
+ &hash_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::hash::Hash for #ident #ty_generics #where_clause {
+ #[inline]
+ fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
+ #hash_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/hash_union.rs b/vendor/educe/src/trait_handlers/hash/hash_union.rs
new file mode 100644
index 00000000..f430c658
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/hash_union.rs
@@ -0,0 +1,54 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::models::{FieldAttributeBuilder, TypeAttributeBuilder};
+use crate::{supported_traits::Trait, trait_handlers::TraitHandler};
+
+pub(crate) struct HashUnionHandler;
+
+impl TraitHandler for HashUnionHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: true, enable_bound: false
+ }
+ .build_from_hash_meta(meta)?;
+
+ if !type_attribute.has_unsafe {
+ return Err(super::panic::union_without_unsafe(meta));
+ }
+
+ if let Data::Union(data) = &ast.data {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_ignore: false, enable_method: false
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::hash::Hash for #ident #ty_generics #where_clause {
+ #[inline]
+ fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
+ let size = ::core::mem::size_of::<Self>();
+ let data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+
+ ::core::hash::Hash::hash(data, state)
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/mod.rs b/vendor/educe/src/trait_handlers/hash/mod.rs
new file mode 100644
index 00000000..c4b07d98
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/mod.rs
@@ -0,0 +1,34 @@
+mod hash_enum;
+mod hash_struct;
+mod hash_union;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct HashHandler;
+
+impl TraitHandler for HashHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => {
+ hash_struct::HashStructHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Enum(_) => {
+ hash_enum::HashEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ hash_union::HashUnionHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/models/field_attribute.rs b/vendor/educe/src/trait_handlers/hash/models/field_attribute.rs
new file mode 100644
index 00000000..d6e34b66
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/models/field_attribute.rs
@@ -0,0 +1,172 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{meta_2_bool_allow_path, meta_name_value_2_bool},
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_hash_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Hash"));
+
+ let mut ignore = false;
+ let mut method = None;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(Hash = false)]));
+ usage.push(stringify!(#[educe(Hash(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(Hash(method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut ignore_is_set = false;
+ let mut method_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ ignore,
+ method,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Hash {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_hash_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ ignore: false, method: None
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/models/mod.rs b/vendor/educe/src/trait_handlers/hash/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/hash/models/type_attribute.rs b/vendor/educe/src/trait_handlers/hash/models/type_attribute.rs
new file mode 100644
index 00000000..33b99994
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/models/type_attribute.rs
@@ -0,0 +1,154 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{
+ common::{bound::Bound, unsafe_punctuated_meta::UnsafePunctuatedMeta},
+ panic, Trait,
+};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) has_unsafe: bool,
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_unsafe: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_hash_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Hash"));
+
+ let mut has_unsafe = false;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_hash_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Hash)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Hash(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Hash(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_hash_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_hash_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result = if self.enable_unsafe {
+ let result: UnsafePunctuatedMeta = list.parse_args()?;
+
+ has_unsafe = result.has_unsafe;
+
+ result.list
+ } else {
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?
+ };
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_hash_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ has_unsafe,
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Hash {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_hash_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ has_unsafe: false, bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/hash/panic.rs b/vendor/educe/src/trait_handlers/hash/panic.rs
new file mode 100644
index 00000000..6e293571
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/hash/panic.rs
@@ -0,0 +1,22 @@
+use quote::ToTokens;
+use syn::{spanned::Spanned, Meta};
+
+#[inline]
+pub(crate) fn union_without_unsafe(meta: &Meta) -> syn::Error {
+ let mut s = meta.into_token_stream().to_string();
+
+ match s.len() {
+ 4 => s.push_str("(unsafe)"),
+ 6 => s.insert_str(10, "unsafe"),
+ _ => unreachable!(),
+ }
+
+ syn::Error::new(
+ meta.span(),
+ format!(
+ "a union's `Hash` implementation is not precise, because it ignores the type of \
+ fields\n* If your union doesn't care about that, use `#[educe({s})]` to implement \
+ the `Hash` trait for it."
+ ),
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/into/common.rs b/vendor/educe/src/trait_handlers/into/common.rs
new file mode 100644
index 00000000..2eba04a1
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/common.rs
@@ -0,0 +1,17 @@
+use quote::quote_spanned;
+use syn::{spanned::Spanned, Type};
+
+use crate::common::{r#type::dereference_changed, tools::HashType};
+
+#[inline]
+pub(crate) fn to_hash_type(ty: &Type) -> HashType {
+ let (ty, is_ref) = dereference_changed(ty);
+
+ let ty = if is_ref {
+ syn::parse2(quote_spanned!( ty.span() => &'static #ty )).unwrap()
+ } else {
+ ty.clone()
+ };
+
+ HashType::from(ty)
+}
diff --git a/vendor/educe/src/trait_handlers/into/into_enum.rs b/vendor/educe/src/trait_handlers/into/into_enum.rs
new file mode 100644
index 00000000..dd4b1988
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/into_enum.rs
@@ -0,0 +1,224 @@
+use std::collections::HashMap;
+
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Field, Fields, Ident, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandlerMultiple,
+};
+use crate::{panic, Trait};
+
+pub(crate) struct IntoEnumHandler;
+
+impl TraitHandlerMultiple for IntoEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &[Meta],
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_types: true
+ }
+ .build_from_into_meta(meta)?;
+
+ if let Data::Enum(data) = &ast.data {
+ let field_attributes: Vec<HashMap<usize, FieldAttribute>> = {
+ let mut map = Vec::new();
+
+ for variant in data.variants.iter() {
+ let mut field_map = HashMap::new();
+
+ let _ = TypeAttributeBuilder {
+ enable_types: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_types: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ for ty in field_attribute.types.keys() {
+ if !type_attribute.types.contains_key(ty) {
+ return Err(super::panic::no_into_impl(ty));
+ }
+ }
+
+ field_map.insert(index, field_attribute);
+ }
+
+ map.push(field_map);
+ }
+
+ map
+ };
+
+ for (target_ty, bound) in type_attribute.types {
+ let mut into_types: Vec<&Type> = Vec::new();
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ type Variants<'a> =
+ Vec<(&'a Ident, bool, usize, Ident, &'a Type, Option<&'a Path>)>;
+
+ let mut variants: Variants = Vec::new();
+
+ for (variant, field_attributes) in data.variants.iter().zip(field_attributes.iter())
+ {
+ if let Fields::Unit = &variant.fields {
+ return Err(panic::trait_not_support_unit_variant(
+ meta[0].path().get_ident().unwrap(),
+ variant,
+ ));
+ }
+
+ let (index, field, method) = {
+ let fields = &variant.fields;
+
+ if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let method = if let Some(field_attribute) = field_attributes.get(&0) {
+ if let Some(method) = field_attribute.types.get(&target_ty) {
+ method.as_ref()
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ (0usize, field, method)
+ } else {
+ let mut into_field: Option<(usize, &Field, Option<&Path>)> = None;
+
+ for (index, field) in fields.iter().enumerate() {
+ if let Some(field_attribute) = field_attributes.get(&index) {
+ if let Some((key, method)) =
+ field_attribute.types.get_key_value(&target_ty)
+ {
+ if into_field.is_some() {
+ return Err(super::panic::multiple_into_fields(key));
+ }
+
+ into_field = Some((index, field, method.as_ref()));
+ }
+ }
+ }
+
+ if into_field.is_none() {
+ // search the same type
+ for (index, field) in fields.iter().enumerate() {
+ let field_ty = super::common::to_hash_type(&field.ty);
+
+ if target_ty.eq(&field_ty) {
+ if into_field.is_some() {
+ // multiple candidates
+ into_field = None;
+
+ break;
+ }
+
+ into_field = Some((index, field, None));
+ }
+ }
+ }
+
+ if let Some(into_field) = into_field {
+ into_field
+ } else {
+ return Err(super::panic::no_into_field(&target_ty));
+ }
+ }
+ };
+
+ let (field_name, is_tuple): (Ident, bool) = match field.ident.as_ref() {
+ Some(ident) => (ident.clone(), false),
+ None => (format_ident!("_{}", index), true),
+ };
+
+ variants.push((&variant.ident, is_tuple, index, field_name, &field.ty, method));
+ }
+
+ if variants.is_empty() {
+ return Err(super::panic::no_into_field(&target_ty));
+ }
+
+ for (variant_ident, is_tuple, index, field_name, ty, method) in variants {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut body_token_stream = proc_macro2::TokenStream::new();
+
+ if let Some(method) = method {
+ body_token_stream.extend(quote!( #method(#field_name) ));
+ } else {
+ let field_ty = super::common::to_hash_type(ty);
+
+ if target_ty.eq(&field_ty) {
+ body_token_stream.extend(quote!( #field_name ));
+ } else {
+ into_types.push(ty);
+
+ body_token_stream
+ .extend(quote!( ::core::convert::Into::into(#field_name) ));
+ }
+ }
+
+ if is_tuple {
+ for _ in 0..index {
+ pattern_token_stream.extend(quote!(_,));
+ }
+
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident ( #pattern_token_stream ) => #body_token_stream, ),
+ );
+ } else {
+ pattern_token_stream.extend(quote!( #field_name, .. ));
+
+ arms_token_stream.extend(
+ quote!( Self::#variant_ident { #pattern_token_stream } => #body_token_stream, ),
+ );
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::convert::Into<#target_ty>)).unwrap(),
+ &into_types,
+ &[],
+ );
+
+ // clone generics in order to not to affect other Into<T> implementations
+ let mut generics = ast.generics.clone();
+
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, _) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::convert::Into<#target_ty> for #ident #ty_generics #where_clause {
+ #[inline]
+ fn into(self) -> #target_ty {
+ match self {
+ #arms_token_stream
+ }
+ }
+ }
+ });
+ }
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/into/into_struct.rs b/vendor/educe/src/trait_handlers/into/into_struct.rs
new file mode 100644
index 00000000..ea139485
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/into_struct.rs
@@ -0,0 +1,168 @@
+use std::collections::HashMap;
+
+use quote::quote;
+use syn::{Data, DeriveInput, Field, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandlerMultiple,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct IntoStructHandler;
+
+impl TraitHandlerMultiple for IntoStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &[Meta],
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_types: true
+ }
+ .build_from_into_meta(meta)?;
+
+ if let Data::Struct(data) = &ast.data {
+ let fields = &data.fields;
+
+ let field_attributes: HashMap<usize, FieldAttribute> = {
+ let mut map = HashMap::new();
+
+ for (index, field) in fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_types: true
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ for ty in field_attribute.types.keys() {
+ if !type_attribute.types.contains_key(ty) {
+ return Err(super::panic::no_into_impl(ty));
+ }
+ }
+
+ map.insert(index, field_attribute);
+ }
+
+ map
+ };
+
+ for (target_ty, bound) in type_attribute.types {
+ let mut into_types: Vec<&Type> = Vec::new();
+
+ let mut into_token_stream = proc_macro2::TokenStream::new();
+
+ let (index, field, method) = {
+ let fields = &data.fields;
+
+ if fields.len() == 1 {
+ let field = fields.into_iter().next().unwrap();
+
+ let method = if let Some(field_attribute) = field_attributes.get(&0) {
+ if let Some(method) = field_attribute.types.get(&target_ty) {
+ method.as_ref()
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ (0usize, field, method)
+ } else {
+ let mut into_field: Option<(usize, &Field, Option<&Path>)> = None;
+
+ for (index, field) in fields.iter().enumerate() {
+ if let Some(field_attribute) = field_attributes.get(&index) {
+ if let Some((key, method)) =
+ field_attribute.types.get_key_value(&target_ty)
+ {
+ if into_field.is_some() {
+ return Err(super::panic::multiple_into_fields(key));
+ }
+
+ into_field = Some((index, field, method.as_ref()));
+ }
+ }
+ }
+
+ if into_field.is_none() {
+ // search the same type
+ for (index, field) in fields.iter().enumerate() {
+ let field_ty = super::common::to_hash_type(&field.ty);
+
+ if target_ty.eq(&field_ty) {
+ if into_field.is_some() {
+ // multiple candidates
+ into_field = None;
+
+ break;
+ }
+
+ into_field = Some((index, field, None));
+ }
+ }
+ }
+
+ if let Some(into_field) = into_field {
+ into_field
+ } else {
+ return Err(super::panic::no_into_field(&target_ty));
+ }
+ }
+ };
+
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ if let Some(method) = method {
+ into_token_stream.extend(quote!( #method(self.#field_name) ));
+ } else {
+ let ty = &field.ty;
+
+ let field_ty = super::common::to_hash_type(ty);
+
+ if target_ty.eq(&field_ty) {
+ into_token_stream.extend(quote!( self.#field_name ));
+ } else {
+ into_types.push(ty);
+
+ into_token_stream
+ .extend(quote!( ::core::convert::Into::into(self.#field_name) ));
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::convert::Into<#target_ty>)).unwrap(),
+ &into_types,
+ &[],
+ );
+
+ // clone generics in order to not to affect other Into<T> implementations
+ let mut generics = ast.generics.clone();
+
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, _) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::convert::Into<#target_ty> for #ident #ty_generics #where_clause {
+ #[inline]
+ fn into(self) -> #target_ty {
+ #into_token_stream
+ }
+ }
+ });
+ }
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/into/mod.rs b/vendor/educe/src/trait_handlers/into/mod.rs
new file mode 100644
index 00000000..1f91777f
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/mod.rs
@@ -0,0 +1,34 @@
+mod common;
+mod into_enum;
+mod into_struct;
+mod models;
+mod panic;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandlerMultiple;
+use crate::Trait;
+
+pub(crate) struct IntoHandler;
+
+impl TraitHandlerMultiple for IntoHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &[Meta],
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => {
+ into_struct::IntoStructHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Enum(_) => {
+ into_enum::IntoEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ Err(crate::panic::trait_not_support_union(meta[0].path().get_ident().unwrap()))
+ },
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/into/models/field_attribute.rs b/vendor/educe/src/trait_handlers/into/models/field_attribute.rs
new file mode 100644
index 00000000..44a7def8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/models/field_attribute.rs
@@ -0,0 +1,152 @@
+use std::collections::HashMap;
+
+use syn::{punctuated::Punctuated, Attribute, Meta, Path, Token};
+
+use crate::{
+ common::{path::meta_2_path, r#type::TypeWithPunctuatedMeta, tools::HashType},
+ panic, Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) types: HashMap<HashType, Option<Path>>,
+}
+
+#[derive(Debug)]
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_types: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_into_meta(&self, meta: &[Meta]) -> syn::Result<FieldAttribute> {
+ debug_assert!(!meta.is_empty());
+
+ let mut types = HashMap::new();
+
+ for meta in meta {
+ debug_assert!(meta.path().is_ident("Into"));
+
+ let correct_usage_for_into_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_types {
+ usage.push(stringify!(#[educe(Into(type))]));
+ usage.push(stringify!(#[educe(Into(type, method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) | Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ if !self.enable_types {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ }
+
+ let TypeWithPunctuatedMeta {
+ ty,
+ list: result,
+ } = list.parse_args()?;
+
+ let ty = super::super::common::to_hash_type(&ty);
+
+ let mut method = None;
+ let mut method_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "method" {
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ }
+ }
+
+ if types.contains_key(&ty) {
+ return Err(super::super::panic::reset_a_type(&ty));
+ }
+
+ types.insert(ty, method);
+ },
+ }
+ }
+
+ Ok(FieldAttribute {
+ types,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output: Option<FieldAttribute> = None;
+
+ let mut v_meta = Vec::new();
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Into {
+ v_meta.push(meta);
+ }
+ }
+ }
+ }
+ }
+
+ if !v_meta.is_empty() {
+ output = Some(self.build_from_into_meta(&v_meta)?);
+ }
+
+ Ok(output.unwrap_or_else(|| FieldAttribute {
+ types: HashMap::new()
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/into/models/mod.rs b/vendor/educe/src/trait_handlers/into/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/into/models/type_attribute.rs b/vendor/educe/src/trait_handlers/into/models/type_attribute.rs
new file mode 100644
index 00000000..526e31e0
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/models/type_attribute.rs
@@ -0,0 +1,153 @@
+use std::collections::HashMap;
+
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{
+ common::{bound::Bound, r#type::TypeWithPunctuatedMeta, tools::HashType},
+ panic, Trait,
+};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) types: HashMap<HashType, Bound>,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_types: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_into_meta(&self, meta: &[Meta]) -> syn::Result<TypeAttribute> {
+ debug_assert!(!meta.is_empty());
+
+ let mut types = HashMap::new();
+
+ for meta in meta {
+ debug_assert!(meta.path().is_ident("Into"));
+
+ let correct_usage_for_into_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_types {
+ usage.push(stringify!(#[educe(Into(type))]));
+ usage.push(stringify!(#[educe(Into(type, bound = false))]));
+ usage.push(stringify!(#[educe(Into(type, bound(where_predicates)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) | Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ if !self.enable_types {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ }
+
+ let TypeWithPunctuatedMeta {
+ ty,
+ list: result,
+ } = list.parse_args()?;
+
+ let ty = super::super::common::to_hash_type(&ty);
+
+ let mut bound = Bound::Auto;
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_into_attribute,
+ ));
+ }
+ }
+
+ if types.contains_key(&ty) {
+ return Err(super::super::panic::reset_a_type(&ty));
+ }
+
+ types.insert(ty, bound);
+ },
+ }
+ }
+
+ Ok(TypeAttribute {
+ types,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output: Option<TypeAttribute> = None;
+
+ let mut v_meta = Vec::new();
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Into {
+ v_meta.push(meta);
+ }
+ }
+ }
+ }
+ }
+
+ if !v_meta.is_empty() {
+ output = Some(self.build_from_into_meta(&v_meta)?);
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ types: HashMap::new()
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/into/panic.rs b/vendor/educe/src/trait_handlers/into/panic.rs
new file mode 100644
index 00000000..95947fcd
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/into/panic.rs
@@ -0,0 +1,27 @@
+use crate::common::tools::HashType;
+
+#[inline]
+pub(crate) fn reset_a_type(ty: &HashType) -> syn::Error {
+ syn::Error::new(ty.span(), format!("the type `{ty}` is repeatedly set"))
+}
+
+#[inline]
+pub(crate) fn no_into_field(ty: &HashType) -> syn::Error {
+ syn::Error::new(ty.span(), format!("there is no field which is assigned for `Into<{ty}>`"))
+}
+
+#[inline]
+pub(crate) fn no_into_impl(ty: &HashType) -> syn::Error {
+ syn::Error::new(
+ ty.span(),
+ format!(
+ "if you want to impl `Into<{ty}>` for this type, you should write \
+ `#[educe(Into({ty}))]` outside"
+ ),
+ )
+}
+
+#[inline]
+pub(crate) fn multiple_into_fields(ty: &HashType) -> syn::Error {
+ syn::Error::new(ty.span(), format!("multiple fields are set for `Into<{ty}>`"))
+}
diff --git a/vendor/educe/src/trait_handlers/mod.rs b/vendor/educe/src/trait_handlers/mod.rs
new file mode 100644
index 00000000..d82242b1
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/mod.rs
@@ -0,0 +1,48 @@
+use syn::{DeriveInput, Meta};
+
+use crate::Trait;
+
+#[cfg(feature = "Clone")]
+pub(crate) mod clone;
+#[cfg(feature = "Copy")]
+pub(crate) mod copy;
+#[cfg(feature = "Debug")]
+pub(crate) mod debug;
+#[cfg(feature = "Default")]
+pub(crate) mod default;
+#[cfg(feature = "Deref")]
+pub(crate) mod deref;
+#[cfg(feature = "DerefMut")]
+pub(crate) mod deref_mut;
+#[cfg(feature = "Eq")]
+pub(crate) mod eq;
+#[cfg(feature = "Hash")]
+pub(crate) mod hash;
+#[cfg(feature = "Into")]
+pub(crate) mod into;
+#[cfg(feature = "Ord")]
+pub(crate) mod ord;
+#[cfg(feature = "PartialEq")]
+pub(crate) mod partial_eq;
+#[cfg(feature = "PartialOrd")]
+pub(crate) mod partial_ord;
+
+pub(crate) trait TraitHandler {
+ #[allow(dead_code)]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()>;
+}
+
+pub(crate) trait TraitHandlerMultiple {
+ #[allow(dead_code)]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &[Meta],
+ ) -> syn::Result<()>;
+}
diff --git a/vendor/educe/src/trait_handlers/ord/mod.rs b/vendor/educe/src/trait_handlers/ord/mod.rs
new file mode 100644
index 00000000..89b2e15f
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/mod.rs
@@ -0,0 +1,49 @@
+mod models;
+mod ord_enum;
+mod ord_struct;
+mod panic;
+
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct OrdHandler;
+
+impl TraitHandler for OrdHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => {
+ ord_struct::OrdStructHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Enum(_) => {
+ ord_enum::OrdEnumHandler::trait_meta_handler(ast, token_stream, traits, meta)
+ },
+ Data::Union(_) => {
+ Err(crate::panic::trait_not_support_union(meta.path().get_ident().unwrap()))
+ },
+ }
+ }
+}
+
+fn supertraits(#[allow(unused_variables)] traits: &[Trait]) -> Vec<proc_macro2::TokenStream> {
+ let mut supertraits = vec![];
+ supertraits.push(quote! {::core::cmp::Eq});
+
+ // We mustn't add the PartialOrd bound to the educed PartialOrd impl.
+ // When we're educing PartialOrd we can leave it off the Ord impl too,
+ // since we *know* Self is going to be PartialOrd.
+ #[cfg(feature = "PartialOrd")]
+ if !traits.contains(&Trait::PartialOrd) {
+ supertraits.push(quote! {::core::cmp::PartialOrd});
+ };
+
+ supertraits
+}
diff --git a/vendor/educe/src/trait_handlers/ord/models/field_attribute.rs b/vendor/educe/src/trait_handlers/ord/models/field_attribute.rs
new file mode 100644
index 00000000..7b2dd969
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/models/field_attribute.rs
@@ -0,0 +1,217 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{meta_2_bool_allow_path, meta_name_value_2_bool},
+ int::meta_2_isize,
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+ pub(crate) rank: isize,
+ pub(crate) rank_span: Option<Span>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+ pub(crate) enable_rank: bool,
+ pub(crate) rank: isize,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_ord_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("Ord") || meta.path().is_ident("PartialOrd"));
+
+ let mut ignore = false;
+ let mut method = None;
+ let mut rank = self.rank;
+ let mut rank_span = None;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(Ord = false)]));
+ usage.push(stringify!(#[educe(Ord(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(Ord(method(path_to_method)))]));
+ }
+
+ if self.enable_rank {
+ usage.push(stringify!(#[educe(Ord(rank = integer))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut ignore_is_set = false;
+ let mut method_is_set = false;
+ let mut rank_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ },
+ "rank" => {
+ if !self.enable_rank {
+ return Ok(false);
+ }
+
+ let v = meta_2_isize(&meta)?;
+
+ if rank_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ rank_is_set = true;
+
+ rank = v;
+ rank_span = Some(meta.span());
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ ignore,
+ method,
+ rank,
+ rank_span,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Ord {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_ord_meta(&meta)?);
+ }
+
+ #[cfg(feature = "PartialOrd")]
+ if traits.contains(&Trait::PartialOrd) && t == Trait::PartialOrd {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_ord_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ ignore: false,
+ method: None,
+ rank: self.rank,
+ rank_span: None,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/ord/models/mod.rs b/vendor/educe/src/trait_handlers/ord/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/ord/models/type_attribute.rs b/vendor/educe/src/trait_handlers/ord/models/type_attribute.rs
new file mode 100644
index 00000000..55054297
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/models/type_attribute.rs
@@ -0,0 +1,149 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{common::bound::Bound, panic, Trait};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_ord_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("Ord") || meta.path().is_ident("PartialOrd"));
+
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(Ord)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(Ord(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(Ord(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::Ord {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_ord_meta(&meta)?);
+ }
+
+ #[cfg(feature = "PartialOrd")]
+ if traits.contains(&Trait::PartialOrd) && t == Trait::PartialOrd {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_ord_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/ord/ord_enum.rs b/vendor/educe/src/trait_handlers/ord/ord_enum.rs
new file mode 100644
index 00000000..0edcb89c
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/ord_enum.rs
@@ -0,0 +1,283 @@
+use std::collections::BTreeMap;
+
+use quote::{format_ident, quote};
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Fields, Ident, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::tools::DiscriminantType, Trait};
+
+pub(crate) struct OrdEnumHandler;
+
+impl TraitHandler for OrdEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_ord_meta(meta)?;
+
+ let mut ord_types: Vec<&Type> = Vec::new();
+
+ let mut cmp_token_stream = proc_macro2::TokenStream::new();
+
+ let discriminant_type = DiscriminantType::from_ast(ast)?;
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ let mut all_unit = true;
+
+ if let Data::Enum(data) = &ast.data {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false, enable_bound: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ let built_in_cmp: Path = syn::parse2(quote!(::core::cmp::Ord::cmp)).unwrap();
+
+ match &variant.fields {
+ Fields::Unit => {
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident => {
+ return ::core::cmp::Ordering::Equal;
+ }
+ });
+ },
+ Fields::Named(_) => {
+ all_unit = false;
+
+ let mut pattern_self_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern_other_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ let mut fields: BTreeMap<isize, (&Field, Ident, Ident, FieldAttribute)> =
+ BTreeMap::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var_self = format_ident!("_s_{}", field_name_real);
+ let field_name_var_other = format_ident!("_o_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_self_token_stream.extend(quote!(#field_name_real: _,));
+ pattern_other_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_self_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_self,));
+ pattern_other_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_other,));
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(
+ rank,
+ (field, field_name_var_self, field_name_var_other, field_attribute),
+ );
+ }
+
+ for (field, field_name_var_self, field_name_var_other, field_attribute) in
+ fields.values()
+ {
+ let cmp = field_attribute.method.as_ref().unwrap_or_else(|| {
+ ord_types.push(&field.ty);
+
+ &built_in_cmp
+ });
+
+ block_token_stream.extend(quote! {
+ match #cmp(#field_name_var_self, #field_name_var_other) {
+ ::core::cmp::Ordering::Equal => (),
+ ::core::cmp::Ordering::Greater => return ::core::cmp::Ordering::Greater,
+ ::core::cmp::Ordering::Less => return ::core::cmp::Ordering::Less,
+ }
+ });
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_self_token_stream } => {
+ if let Self::#variant_ident { #pattern_other_token_stream } = other {
+ #block_token_stream
+ }
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ all_unit = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern2_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ let mut fields: BTreeMap<isize, (&Field, Ident, Ident, FieldAttribute)> =
+ BTreeMap::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_var_self = format_ident!("_{}", index);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+ pattern2_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var_other = format_ident!("_{}", field_name_var_self);
+
+ pattern_token_stream.extend(quote!(#field_name_var_self,));
+ pattern2_token_stream.extend(quote!(#field_name_var_other,));
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(
+ rank,
+ (field, field_name_var_self, field_name_var_other, field_attribute),
+ );
+ }
+
+ for (field, field_name, field_name2, field_attribute) in fields.values() {
+ let cmp = field_attribute.method.as_ref().unwrap_or_else(|| {
+ ord_types.push(&field.ty);
+
+ &built_in_cmp
+ });
+
+ block_token_stream.extend(quote! {
+ match #cmp(#field_name, #field_name2) {
+ ::core::cmp::Ordering::Equal => (),
+ ::core::cmp::Ordering::Greater => return ::core::cmp::Ordering::Greater,
+ ::core::cmp::Ordering::Less => return ::core::cmp::Ordering::Less,
+ }
+ });
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ if let Self::#variant_ident ( #pattern2_token_stream ) = other {
+ #block_token_stream
+ }
+ }
+ });
+ },
+ }
+ }
+ }
+
+ if arms_token_stream.is_empty() {
+ cmp_token_stream.extend(quote!(::core::cmp::Ordering::Equal));
+ } else {
+ let discriminant_cmp = quote! {
+ unsafe {
+ ::core::cmp::Ord::cmp(&*<*const _>::from(self).cast::<#discriminant_type>(), &*<*const _>::from(other).cast::<#discriminant_type>())
+ }
+ };
+
+ cmp_token_stream.extend(if all_unit {
+ quote! {
+ match #discriminant_cmp {
+ ::core::cmp::Ordering::Equal => ::core::cmp::Ordering::Equal,
+ ::core::cmp::Ordering::Greater => ::core::cmp::Ordering::Greater,
+ ::core::cmp::Ordering::Less => ::core::cmp::Ordering::Less,
+ }
+ }
+ } else {
+ quote! {
+ match #discriminant_cmp {
+ ::core::cmp::Ordering::Equal => {
+ match self {
+ #arms_token_stream
+ }
+
+ ::core::cmp::Ordering::Equal
+ },
+ ::core::cmp::Ordering::Greater => ::core::cmp::Ordering::Greater,
+ ::core::cmp::Ordering::Less => ::core::cmp::Ordering::Less,
+ }
+ }
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::Ord)).unwrap(),
+ &ord_types,
+ &crate::trait_handlers::ord::supertraits(traits),
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Ord for #ident #ty_generics #where_clause {
+ #[inline]
+ fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
+ #cmp_token_stream
+ }
+ }
+ });
+
+ #[cfg(feature = "PartialOrd")]
+ if traits.contains(&Trait::PartialOrd) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialOrd for #ident #ty_generics #where_clause {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
+ Some(::core::cmp::Ord::cmp(self, other))
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/ord/ord_struct.rs b/vendor/educe/src/trait_handlers/ord/ord_struct.rs
new file mode 100644
index 00000000..fc6c170a
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/ord_struct.rs
@@ -0,0 +1,123 @@
+use std::collections::BTreeMap;
+
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct OrdStructHandler;
+
+impl TraitHandler for OrdStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_ord_meta(meta)?;
+
+ let mut ord_types: Vec<&Type> = Vec::new();
+
+ let mut cmp_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let mut fields: BTreeMap<isize, (usize, &Field, FieldAttribute)> = BTreeMap::new();
+
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(rank, (index, field, field_attribute));
+ }
+
+ let built_in_cmp: Path = syn::parse2(quote!(::core::cmp::Ord::cmp)).unwrap();
+
+ for (index, field, field_attribute) in fields.values() {
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), *index);
+
+ let cmp = field_attribute.method.as_ref().unwrap_or_else(|| {
+ ord_types.push(&field.ty);
+
+ &built_in_cmp
+ });
+
+ cmp_token_stream.extend(quote! {
+ match #cmp(&self.#field_name, &other.#field_name) {
+ ::core::cmp::Ordering::Equal => (),
+ ::core::cmp::Ordering::Greater => return ::core::cmp::Ordering::Greater,
+ ::core::cmp::Ordering::Less => return ::core::cmp::Ordering::Less,
+ }
+ });
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::Ord)).unwrap(),
+ &ord_types,
+ &crate::trait_handlers::ord::supertraits(traits),
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Ord for #ident #ty_generics #where_clause {
+ #[inline]
+ fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
+ #cmp_token_stream
+
+ ::core::cmp::Ordering::Equal
+ }
+ }
+ });
+
+ #[cfg(feature = "PartialOrd")]
+ if traits.contains(&Trait::PartialOrd) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialOrd for #ident #ty_generics #where_clause {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
+ Some(::core::cmp::Ord::cmp(self, other))
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/ord/panic.rs b/vendor/educe/src/trait_handlers/ord/panic.rs
new file mode 100644
index 00000000..839f3e88
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/ord/panic.rs
@@ -0,0 +1,6 @@
+use proc_macro2::Span;
+
+#[inline]
+pub(crate) fn reuse_a_rank(span: Span, rank: isize) -> syn::Error {
+ syn::Error::new(span, format!("the rank `{rank}` is repeatedly used"))
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/mod.rs b/vendor/educe/src/trait_handlers/partial_eq/mod.rs
new file mode 100644
index 00000000..2bf7c727
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/mod.rs
@@ -0,0 +1,43 @@
+mod models;
+mod panic;
+mod partial_eq_enum;
+mod partial_eq_struct;
+mod partial_eq_union;
+
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct PartialEqHandler;
+
+impl TraitHandler for PartialEqHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ match ast.data {
+ Data::Struct(_) => partial_eq_struct::PartialEqStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => partial_eq_enum::PartialEqEnumHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Union(_) => partial_eq_union::PartialEqUnionHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/models/field_attribute.rs b/vendor/educe/src/trait_handlers/partial_eq/models/field_attribute.rs
new file mode 100644
index 00000000..4b67aba5
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/models/field_attribute.rs
@@ -0,0 +1,181 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{meta_2_bool_allow_path, meta_name_value_2_bool},
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_partial_eq_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("PartialEq") || meta.path().is_ident("Eq"));
+
+ let mut ignore = false;
+ let mut method = None;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(PartialEq = false)]));
+ usage.push(stringify!(#[educe(PartialEq(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(PartialEq(method(path_to_method)))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut ignore_is_set = false;
+ let mut method_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ ignore,
+ method,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::PartialEq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_eq_meta(&meta)?);
+ }
+
+ #[cfg(feature = "Eq")]
+ if traits.contains(&Trait::Eq) && t == Trait::Eq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_eq_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ ignore: false, method: None
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/models/mod.rs b/vendor/educe/src/trait_handlers/partial_eq/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/partial_eq/models/type_attribute.rs b/vendor/educe/src/trait_handlers/partial_eq/models/type_attribute.rs
new file mode 100644
index 00000000..83779975
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/models/type_attribute.rs
@@ -0,0 +1,163 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{
+ common::{bound::Bound, unsafe_punctuated_meta::UnsafePunctuatedMeta},
+ panic, Trait,
+};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) has_unsafe: bool,
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_unsafe: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_partial_eq_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("PartialEq") || meta.path().is_ident("Eq"));
+
+ let mut has_unsafe = false;
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(PartialEq)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(PartialEq(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(PartialEq(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result = if self.enable_unsafe {
+ let result: UnsafePunctuatedMeta = list.parse_args()?;
+
+ has_unsafe = result.has_unsafe;
+
+ result.list
+ } else {
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?
+ };
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ has_unsafe,
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::PartialEq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_eq_meta(&meta)?);
+ }
+
+ #[cfg(feature = "Eq")]
+ if traits.contains(&Trait::Eq) && t == Trait::Eq {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_eq_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ has_unsafe: false, bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/panic.rs b/vendor/educe/src/trait_handlers/partial_eq/panic.rs
new file mode 100644
index 00000000..69d001be
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/panic.rs
@@ -0,0 +1,22 @@
+use quote::ToTokens;
+use syn::{spanned::Spanned, Meta};
+
+#[inline]
+pub(crate) fn union_without_unsafe(meta: &Meta) -> syn::Error {
+ let mut s = meta.into_token_stream().to_string();
+
+ match s.len() {
+ 9 => s.push_str("(unsafe)"),
+ 11 => s.insert_str(10, "unsafe"),
+ _ => unreachable!(),
+ }
+
+ syn::Error::new(
+ meta.span(),
+ format!(
+ "a union's `PartialEq` implementation is not precise, because it ignores the type of \
+ fields\n* If your union doesn't care about that, use `#[educe({s})]` to implement \
+ the `PartialEq` trait for it."
+ ),
+ )
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/partial_eq_enum.rs b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_enum.rs
new file mode 100644
index 00000000..d000f35c
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_enum.rs
@@ -0,0 +1,218 @@
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct PartialEqEnumHandler;
+
+impl TraitHandler for PartialEqEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: false, enable_bound: true
+ }
+ .build_from_partial_eq_meta(meta)?;
+
+ let mut partial_eq_types: Vec<&Type> = Vec::new();
+
+ let mut eq_token_stream = proc_macro2::TokenStream::new();
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Enum(data) = &ast.data {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false,
+ enable_unsafe: false,
+ enable_bound: false,
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ match &variant.fields {
+ Fields::Unit => {
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident => {
+ if let Self::#variant_ident = other {
+ // same
+ } else {
+ return false;
+ }
+ }
+ });
+ },
+ Fields::Named(_) => {
+ let mut pattern_self_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern_other_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ for field in variant.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var_self = format_ident!("_s_{}", field_name_real);
+ let field_name_var_other = format_ident!("_o_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_self_token_stream.extend(quote!(#field_name_real: _,));
+ pattern_other_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_self_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_self,));
+ pattern_other_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_other,));
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(quote! {
+ if !#method(#field_name_var_self, #field_name_var_other) {
+ return false;
+ }
+ });
+ } else {
+ let ty = &field.ty;
+
+ partial_eq_types.push(ty);
+
+ block_token_stream.extend(quote! {
+ if ::core::cmp::PartialEq::ne(#field_name_var_self, #field_name_var_other) {
+ return false;
+ }
+ });
+ }
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_self_token_stream } => {
+ if let Self::#variant_ident { #pattern_other_token_stream } = other {
+ #block_token_stream
+ } else {
+ return false;
+ }
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern2_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+ pattern2_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var_self = format_ident!("_{}", index);
+
+ let field_name_var_other = format_ident!("_{}", field_name_var_self);
+
+ pattern_token_stream.extend(quote!(#field_name_var_self,));
+ pattern2_token_stream.extend(quote!(#field_name_var_other,));
+
+ if let Some(method) = field_attribute.method {
+ block_token_stream.extend(quote! {
+ if !#method(#field_name_var_self, #field_name_var_other) {
+ return false;
+ }
+ });
+ } else {
+ let ty = &field.ty;
+
+ partial_eq_types.push(ty);
+
+ block_token_stream.extend(quote! {
+ if ::core::cmp::PartialEq::ne(#field_name_var_self, #field_name_var_other) {
+ return false;
+ }
+ });
+ }
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ if let Self::#variant_ident ( #pattern2_token_stream ) = other {
+ #block_token_stream
+ } else {
+ return false;
+ }
+ }
+ });
+ },
+ }
+ }
+ }
+
+ if !arms_token_stream.is_empty() {
+ eq_token_stream.extend(quote! {
+ match self {
+ #arms_token_stream
+ }
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::PartialEq)).unwrap(),
+ &partial_eq_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialEq for #ident #ty_generics #where_clause {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ #eq_token_stream
+
+ true
+ }
+ }
+ });
+
+ #[cfg(feature = "Eq")]
+ if traits.contains(&Trait::Eq) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/partial_eq_struct.rs b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_struct.rs
new file mode 100644
index 00000000..7394b8b1
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_struct.rs
@@ -0,0 +1,103 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct PartialEqStructHandler;
+
+impl TraitHandler for PartialEqStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: false, enable_bound: true
+ }
+ .build_from_partial_eq_meta(meta)?;
+
+ let mut partial_eq_types: Vec<&Type> = Vec::new();
+
+ let mut eq_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index);
+
+ if let Some(method) = field_attribute.method {
+ eq_token_stream.extend(quote! {
+ if !#method(&self.#field_name, &other.#field_name) {
+ return false;
+ }
+ });
+ } else {
+ let ty = &field.ty;
+
+ partial_eq_types.push(ty);
+
+ eq_token_stream.extend(quote! {
+ if ::core::cmp::PartialEq::ne(&self.#field_name, &other.#field_name) {
+ return false;
+ }
+ });
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::PartialEq)).unwrap(),
+ &partial_eq_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialEq for #ident #ty_generics #where_clause {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ #eq_token_stream
+
+ true
+ }
+ }
+ });
+
+ #[cfg(feature = "Eq")]
+ if traits.contains(&Trait::Eq) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_eq/partial_eq_union.rs b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_union.rs
new file mode 100644
index 00000000..80ac2b73
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_eq/partial_eq_union.rs
@@ -0,0 +1,63 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Meta};
+
+use super::models::{FieldAttributeBuilder, TypeAttributeBuilder};
+use crate::{supported_traits::Trait, trait_handlers::TraitHandler};
+
+pub(crate) struct PartialEqUnionHandler;
+
+impl TraitHandler for PartialEqUnionHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute =
+ TypeAttributeBuilder {
+ enable_flag: true, enable_unsafe: true, enable_bound: false
+ }
+ .build_from_partial_eq_meta(meta)?;
+
+ if !type_attribute.has_unsafe {
+ return Err(super::panic::union_without_unsafe(meta));
+ }
+
+ if let Data::Union(data) = &ast.data {
+ for field in data.fields.named.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_ignore: false, enable_method: false
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialEq for #ident #ty_generics #where_clause {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ let size = ::core::mem::size_of::<Self>();
+ let self_data = unsafe { ::core::slice::from_raw_parts(self as *const Self as *const u8, size) };
+ let other_data = unsafe { ::core::slice::from_raw_parts(other as *const Self as *const u8, size) };
+
+ ::core::cmp::PartialEq::eq(self_data, other_data)
+ }
+ }
+ });
+
+ #[cfg(feature = "Eq")]
+ if traits.contains(&Trait::Eq) {
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause {
+ }
+ });
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/mod.rs b/vendor/educe/src/trait_handlers/partial_ord/mod.rs
new file mode 100644
index 00000000..c69ff200
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/mod.rs
@@ -0,0 +1,58 @@
+mod models;
+mod panic;
+mod partial_ord_enum;
+mod partial_ord_struct;
+
+use models::TypeAttributeBuilder;
+use syn::{Data, DeriveInput, Meta};
+
+use super::TraitHandler;
+use crate::Trait;
+
+pub(crate) struct PartialOrdHandler;
+
+impl TraitHandler for PartialOrdHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ #[cfg(feature = "Ord")]
+ let contains_ord = traits.contains(&Trait::Ord);
+
+ #[cfg(not(feature = "Ord"))]
+ let contains_ord = false;
+
+ // if `contains_ord` is true, the implementation is handled by the `Ord` attribute
+ if contains_ord {
+ let _ = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: false
+ }
+ .build_from_partial_ord_meta(meta)?;
+
+ // field attributes is also handled by the `Ord` attribute
+
+ Ok(())
+ } else {
+ match ast.data {
+ Data::Struct(_) => partial_ord_struct::PartialOrdStructHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Enum(_) => partial_ord_enum::PartialOrdEnumHandler::trait_meta_handler(
+ ast,
+ token_stream,
+ traits,
+ meta,
+ ),
+ Data::Union(_) => {
+ Err(crate::panic::trait_not_support_union(meta.path().get_ident().unwrap()))
+ },
+ }
+ }
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/models/field_attribute.rs b/vendor/educe/src/trait_handlers/partial_ord/models/field_attribute.rs
new file mode 100644
index 00000000..be455ba1
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/models/field_attribute.rs
@@ -0,0 +1,208 @@
+use proc_macro2::Span;
+use syn::{punctuated::Punctuated, spanned::Spanned, Attribute, Meta, Path, Token};
+
+use crate::{
+ common::{
+ ident_bool::{meta_2_bool_allow_path, meta_name_value_2_bool},
+ int::meta_2_isize,
+ path::meta_2_path,
+ },
+ panic,
+ supported_traits::Trait,
+};
+
+pub(crate) struct FieldAttribute {
+ pub(crate) ignore: bool,
+ pub(crate) method: Option<Path>,
+ pub(crate) rank: isize,
+ pub(crate) rank_span: Option<Span>,
+}
+
+pub(crate) struct FieldAttributeBuilder {
+ pub(crate) enable_ignore: bool,
+ pub(crate) enable_method: bool,
+ pub(crate) enable_rank: bool,
+ pub(crate) rank: isize,
+}
+
+impl FieldAttributeBuilder {
+ pub(crate) fn build_from_partial_ord_meta(&self, meta: &Meta) -> syn::Result<FieldAttribute> {
+ debug_assert!(meta.path().is_ident("PartialOrd"));
+
+ let mut ignore = false;
+ let mut method = None;
+ let mut rank = self.rank;
+ let mut rank_span = None;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_ignore {
+ usage.push(stringify!(#[educe(PartialOrd = false)]));
+ usage.push(stringify!(#[educe(PartialOrd(ignore))]));
+ }
+
+ if self.enable_method {
+ usage.push(stringify!(#[educe(PartialOrd(method(path_to_method)))]));
+ }
+
+ if self.enable_rank {
+ usage.push(stringify!(#[educe(PartialOrd(rank = integer))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::NameValue(name_value) => {
+ if self.enable_ignore {
+ ignore = !meta_name_value_2_bool(name_value)?;
+ } else {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut ignore_is_set = false;
+ let mut method_is_set = false;
+ let mut rank_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ match ident.to_string().as_str() {
+ "ignore" => {
+ if !self.enable_ignore {
+ return Ok(false);
+ }
+
+ let v = meta_2_bool_allow_path(&meta)?;
+
+ if ignore_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ ignore_is_set = true;
+
+ ignore = v;
+
+ return Ok(true);
+ },
+ "method" => {
+ if !self.enable_method {
+ return Ok(false);
+ }
+
+ let v = meta_2_path(&meta)?;
+
+ if method_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ method_is_set = true;
+
+ method = Some(v);
+
+ return Ok(true);
+ },
+ "rank" => {
+ if !self.enable_rank {
+ return Ok(false);
+ }
+
+ let v = meta_2_isize(&meta)?;
+
+ if rank_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ rank_is_set = true;
+
+ rank = v;
+ rank_span = Some(meta.span());
+
+ return Ok(true);
+ },
+ _ => (),
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(FieldAttribute {
+ ignore,
+ method,
+ rank,
+ rank_span,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<FieldAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::PartialOrd {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_ord_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(FieldAttribute {
+ ignore: false,
+ method: None,
+ rank: self.rank,
+ rank_span: None,
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/models/mod.rs b/vendor/educe/src/trait_handlers/partial_ord/models/mod.rs
new file mode 100644
index 00000000..1e4681f8
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/models/mod.rs
@@ -0,0 +1,5 @@
+mod field_attribute;
+mod type_attribute;
+
+pub(crate) use field_attribute::*;
+pub(crate) use type_attribute::*;
diff --git a/vendor/educe/src/trait_handlers/partial_ord/models/type_attribute.rs b/vendor/educe/src/trait_handlers/partial_ord/models/type_attribute.rs
new file mode 100644
index 00000000..5c318c4b
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/models/type_attribute.rs
@@ -0,0 +1,140 @@
+use syn::{punctuated::Punctuated, Attribute, Meta, Token};
+
+use crate::{common::bound::Bound, panic, Trait};
+
+pub(crate) struct TypeAttribute {
+ pub(crate) bound: Bound,
+}
+
+#[derive(Debug)]
+pub(crate) struct TypeAttributeBuilder {
+ pub(crate) enable_flag: bool,
+ pub(crate) enable_bound: bool,
+}
+
+impl TypeAttributeBuilder {
+ pub(crate) fn build_from_partial_ord_meta(&self, meta: &Meta) -> syn::Result<TypeAttribute> {
+ debug_assert!(meta.path().is_ident("PartialOrd"));
+
+ let mut bound = Bound::Auto;
+
+ let correct_usage_for_partial_eq_attribute = {
+ let mut usage = vec![];
+
+ if self.enable_flag {
+ usage.push(stringify!(#[educe(PartialOrd)]));
+ }
+
+ if self.enable_bound {
+ usage.push(stringify!(#[educe(PartialOrd(bound(where_predicates)))]));
+ usage.push(stringify!(#[educe(PartialOrd(bound = false))]));
+ }
+
+ usage
+ };
+
+ match meta {
+ Meta::Path(_) => {
+ if !self.enable_flag {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ },
+ Meta::NameValue(_) => {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ },
+ Meta::List(list) => {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ let mut bound_is_set = false;
+
+ let mut handler = |meta: Meta| -> syn::Result<bool> {
+ if let Some(ident) = meta.path().get_ident() {
+ if ident == "bound" {
+ if !self.enable_bound {
+ return Ok(false);
+ }
+
+ let v = Bound::from_meta(&meta)?;
+
+ if bound_is_set {
+ return Err(panic::parameter_reset(ident));
+ }
+
+ bound_is_set = true;
+
+ bound = v;
+
+ return Ok(true);
+ }
+ }
+
+ Ok(false)
+ };
+
+ for p in result {
+ if !handler(p)? {
+ return Err(panic::attribute_incorrect_format(
+ meta.path().get_ident().unwrap(),
+ &correct_usage_for_partial_eq_attribute,
+ ));
+ }
+ }
+ },
+ }
+
+ Ok(TypeAttribute {
+ bound,
+ })
+ }
+
+ pub(crate) fn build_from_attributes(
+ &self,
+ attributes: &[Attribute],
+ traits: &[Trait],
+ ) -> syn::Result<TypeAttribute> {
+ let mut output = None;
+
+ for attribute in attributes.iter() {
+ let path = attribute.path();
+
+ if path.is_ident("educe") {
+ if let Meta::List(list) = &attribute.meta {
+ let result =
+ list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
+
+ for meta in result {
+ let path = meta.path();
+
+ let t = match Trait::from_path(path) {
+ Some(t) => t,
+ None => return Err(panic::unsupported_trait(meta.path())),
+ };
+
+ if !traits.contains(&t) {
+ return Err(panic::trait_not_used(path.get_ident().unwrap()));
+ }
+
+ if t == Trait::PartialOrd {
+ if output.is_some() {
+ return Err(panic::reuse_a_trait(path.get_ident().unwrap()));
+ }
+
+ output = Some(self.build_from_partial_ord_meta(&meta)?);
+ }
+ }
+ }
+ }
+ }
+
+ Ok(output.unwrap_or(TypeAttribute {
+ bound: Bound::Auto
+ }))
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/panic.rs b/vendor/educe/src/trait_handlers/partial_ord/panic.rs
new file mode 100644
index 00000000..839f3e88
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/panic.rs
@@ -0,0 +1,6 @@
+use proc_macro2::Span;
+
+#[inline]
+pub(crate) fn reuse_a_rank(span: Span, rank: isize) -> syn::Error {
+ syn::Error::new(span, format!("the rank `{rank}` is repeatedly used"))
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/partial_ord_enum.rs b/vendor/educe/src/trait_handlers/partial_ord/partial_ord_enum.rs
new file mode 100644
index 00000000..c41036ff
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/partial_ord_enum.rs
@@ -0,0 +1,276 @@
+use std::collections::BTreeMap;
+
+use quote::{format_ident, quote};
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Fields, Ident, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::tools::DiscriminantType, Trait};
+
+pub(crate) struct PartialOrdEnumHandler;
+
+impl TraitHandler for PartialOrdEnumHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_partial_ord_meta(meta)?;
+
+ let mut partial_ord_types: Vec<&Type> = Vec::new();
+
+ let mut partial_cmp_token_stream = proc_macro2::TokenStream::new();
+
+ let discriminant_type = DiscriminantType::from_ast(ast)?;
+
+ let mut arms_token_stream = proc_macro2::TokenStream::new();
+
+ let mut all_unit = true;
+
+ if let Data::Enum(data) = &ast.data {
+ for variant in data.variants.iter() {
+ let _ = TypeAttributeBuilder {
+ enable_flag: false, enable_bound: false
+ }
+ .build_from_attributes(&variant.attrs, traits)?;
+
+ let variant_ident = &variant.ident;
+
+ let built_in_partial_cmp: Path =
+ syn::parse2(quote!(::core::cmp::PartialOrd::partial_cmp)).unwrap();
+
+ match &variant.fields {
+ Fields::Unit => {
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident => {
+ return Some(::core::cmp::Ordering::Equal);
+ }
+ });
+ },
+ Fields::Named(_) => {
+ all_unit = false;
+
+ let mut pattern_self_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern_other_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ let mut fields: BTreeMap<isize, (&Field, Ident, Ident, FieldAttribute)> =
+ BTreeMap::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_real = field.ident.as_ref().unwrap();
+ let field_name_var_self = format_ident!("_s_{}", field_name_real);
+ let field_name_var_other = format_ident!("_o_{}", field_name_real);
+
+ if field_attribute.ignore {
+ pattern_self_token_stream.extend(quote!(#field_name_real: _,));
+ pattern_other_token_stream.extend(quote!(#field_name_real: _,));
+
+ continue;
+ }
+
+ pattern_self_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_self,));
+ pattern_other_token_stream
+ .extend(quote!(#field_name_real: #field_name_var_other,));
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(
+ rank,
+ (field, field_name_var_self, field_name_var_other, field_attribute),
+ );
+ }
+
+ for (field, field_name_var_self, field_name_var_other, field_attribute) in
+ fields.values()
+ {
+ let partial_cmp =
+ field_attribute.method.as_ref().unwrap_or_else(|| {
+ partial_ord_types.push(&field.ty);
+
+ &built_in_partial_cmp
+ });
+
+ block_token_stream.extend(quote! {
+ match #partial_cmp(#field_name_var_self, #field_name_var_other) {
+ Some(::core::cmp::Ordering::Equal) => (),
+ Some(::core::cmp::Ordering::Greater) => return Some(::core::cmp::Ordering::Greater),
+ Some(::core::cmp::Ordering::Less) => return Some(::core::cmp::Ordering::Less),
+ None => return None,
+ }
+ });
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident { #pattern_self_token_stream } => {
+ if let Self::#variant_ident { #pattern_other_token_stream } = other {
+ #block_token_stream
+ }
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ all_unit = false;
+
+ let mut pattern_token_stream = proc_macro2::TokenStream::new();
+ let mut pattern2_token_stream = proc_macro2::TokenStream::new();
+ let mut block_token_stream = proc_macro2::TokenStream::new();
+
+ let mut fields: BTreeMap<isize, (&Field, Ident, Ident, FieldAttribute)> =
+ BTreeMap::new();
+
+ for (index, field) in variant.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ let field_name_var_self = format_ident!("_{}", index);
+
+ if field_attribute.ignore {
+ pattern_token_stream.extend(quote!(_,));
+ pattern2_token_stream.extend(quote!(_,));
+
+ continue;
+ }
+
+ let field_name_var_other = format_ident!("_{}", field_name_var_self);
+
+ pattern_token_stream.extend(quote!(#field_name_var_self,));
+ pattern2_token_stream.extend(quote!(#field_name_var_other,));
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(
+ rank,
+ (field, field_name_var_self, field_name_var_other, field_attribute),
+ );
+ }
+
+ for (field, field_name, field_name2, field_attribute) in fields.values() {
+ let partial_cmp =
+ field_attribute.method.as_ref().unwrap_or_else(|| {
+ partial_ord_types.push(&field.ty);
+
+ &built_in_partial_cmp
+ });
+
+ block_token_stream.extend(quote! {
+ match #partial_cmp(#field_name, #field_name2) {
+ Some(::core::cmp::Ordering::Equal) => (),
+ Some(::core::cmp::Ordering::Greater) => return Some(::core::cmp::Ordering::Greater),
+ Some(::core::cmp::Ordering::Less) => return Some(::core::cmp::Ordering::Less),
+ None => return None,
+ }
+ });
+ }
+
+ arms_token_stream.extend(quote! {
+ Self::#variant_ident ( #pattern_token_stream ) => {
+ if let Self::#variant_ident ( #pattern2_token_stream ) = other {
+ #block_token_stream
+ }
+ }
+ });
+ },
+ }
+ }
+ }
+
+ if arms_token_stream.is_empty() {
+ partial_cmp_token_stream.extend(quote!(Some(::core::cmp::Ordering::Equal)));
+ } else {
+ let discriminant_cmp = quote! {
+ unsafe {
+ ::core::cmp::Ord::cmp(&*<*const _>::from(self).cast::<#discriminant_type>(), &*<*const _>::from(other).cast::<#discriminant_type>())
+ }
+ };
+
+ partial_cmp_token_stream.extend(if all_unit {
+ quote! {
+ match #discriminant_cmp {
+ ::core::cmp::Ordering::Equal => Some(::core::cmp::Ordering::Equal),
+ ::core::cmp::Ordering::Greater => Some(::core::cmp::Ordering::Greater),
+ ::core::cmp::Ordering::Less => Some(::core::cmp::Ordering::Less),
+ }
+ }
+ } else {
+ quote! {
+ match #discriminant_cmp {
+ ::core::cmp::Ordering::Equal => {
+ match self {
+ #arms_token_stream
+ }
+
+ Some(::core::cmp::Ordering::Equal)
+ },
+ ::core::cmp::Ordering::Greater => Some(::core::cmp::Ordering::Greater),
+ ::core::cmp::Ordering::Less => Some(::core::cmp::Ordering::Less),
+ }
+ }
+ });
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::PartialOrd)).unwrap(),
+ &partial_ord_types,
+ &[quote! {::core::cmp::PartialEq}],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialOrd for #ident #ty_generics #where_clause {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
+ #partial_cmp_token_stream
+ }
+ }
+ });
+
+ Ok(())
+ }
+}
diff --git a/vendor/educe/src/trait_handlers/partial_ord/partial_ord_struct.rs b/vendor/educe/src/trait_handlers/partial_ord/partial_ord_struct.rs
new file mode 100644
index 00000000..7b666447
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/partial_ord/partial_ord_struct.rs
@@ -0,0 +1,113 @@
+use std::collections::BTreeMap;
+
+use quote::quote;
+use syn::{spanned::Spanned, Data, DeriveInput, Field, Meta, Path, Type};
+
+use super::{
+ models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::{common::ident_index::IdentOrIndex, Trait};
+
+pub(crate) struct PartialOrdStructHandler;
+
+impl TraitHandler for PartialOrdStructHandler {
+ #[inline]
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true, enable_bound: true
+ }
+ .build_from_partial_ord_meta(meta)?;
+
+ let mut partial_ord_types: Vec<&Type> = Vec::new();
+
+ let mut partial_cmp_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ let mut fields: BTreeMap<isize, (usize, &Field, FieldAttribute)> = BTreeMap::new();
+
+ for (index, field) in data.fields.iter().enumerate() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_ignore: true,
+ enable_method: true,
+ enable_rank: true,
+ rank: isize::MIN + index as isize,
+ }
+ .build_from_attributes(&field.attrs, traits)?;
+
+ if field_attribute.ignore {
+ continue;
+ }
+
+ let rank = field_attribute.rank;
+
+ if fields.contains_key(&rank) {
+ return Err(super::panic::reuse_a_rank(
+ field_attribute.rank_span.unwrap_or_else(|| field.span()),
+ rank,
+ ));
+ }
+
+ fields.insert(rank, (index, field, field_attribute));
+ }
+
+ let built_in_partial_cmp: Path =
+ syn::parse2(quote!(::core::cmp::PartialOrd::partial_cmp)).unwrap();
+
+ for (index, field, field_attribute) in fields.values() {
+ let field_name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), *index);
+
+ let partial_cmp = field_attribute.method.as_ref().unwrap_or_else(|| {
+ partial_ord_types.push(&field.ty);
+
+ &built_in_partial_cmp
+ });
+
+ partial_cmp_token_stream.extend(quote! {
+ match #partial_cmp(&self.#field_name, &other.#field_name) {
+ Some(::core::cmp::Ordering::Equal) => (),
+ Some(::core::cmp::Ordering::Greater) => return Some(::core::cmp::Ordering::Greater),
+ Some(::core::cmp::Ordering::Less) => return Some(::core::cmp::Ordering::Less),
+ None => return None,
+ }
+ });
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::cmp::PartialOrd)).unwrap(),
+ &partial_ord_types,
+ &[quote! {::core::cmp::PartialEq}],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::cmp::PartialOrd for #ident #ty_generics #where_clause {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
+ #partial_cmp_token_stream
+
+ Some(::core::cmp::Ordering::Equal)
+ }
+ }
+ });
+
+ Ok(())
+ }
+}