mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-24 00:38:00 +00:00
Compare commits
1006 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d17902059e | |||
| a27948e209 | |||
| 576e2ef9d8 | |||
| dd0eb0f2ca | |||
| f7fc3e0d67 | |||
| 1c396d223b | |||
| e42684f9a7 | |||
| 56c29b3c5d | |||
| 5a44519a9a | |||
| fae23fea97 | |||
| d656b4dd6a | |||
| b517ec9fd7 | |||
| 086353c581 | |||
| 4e278703c6 | |||
| 9f9a1ea35e | |||
| a866b336f1 | |||
| 5adc9e816c | |||
| ab581789f4 | |||
| 415d9fc560 | |||
| 7c58427e12 | |||
| 9d3410e3f4 | |||
| 2fb6748bf1 | |||
| f8137c79a2 | |||
| b7dbf7e3cb | |||
| 7c836915fc | |||
| aa2d9b208a | |||
| 3a7c11c82c | |||
| 11ce4402bd | |||
| 8047570160 | |||
| b395215875 | |||
| a437ff6bf7 | |||
| 20fc31c78a | |||
| ad2b064b0a | |||
| dec153b8fa | |||
| e219a0d4b7 | |||
| c78f7d2e30 | |||
| 502a065a4c | |||
| 027112eccb | |||
| 8c3445efe4 | |||
| 88b6a9abf4 | |||
| fa298c9df4 | |||
| c4a07ed4e8 | |||
| c4986f10b9 | |||
| 2d607de146 | |||
| 19956e6b8e | |||
| ec13eb4ed6 | |||
| ae00c4acb7 | |||
| 85d0b9ccd8 | |||
| e60f62a289 | |||
| e04f0ba2de | |||
| c8184be238 | |||
| 896d91f0bb | |||
| 915686d0ec | |||
| 3a682c951b | |||
| ca79f61d0f | |||
| ddb7c4b30f | |||
| 4855fb467f | |||
| 6dffc0b1c8 | |||
| 15be2a600a | |||
| 1799547846 | |||
| 2dbeefb11b | |||
| 8a3c29ff19 | |||
| defc24d361 | |||
| 2316610760 | |||
| c09e2bd690 | |||
| fe7dcc4cd8 | |||
| a20e66e131 | |||
| 1c1a5d95cd | |||
| ee3c2372fb | |||
| bfb020d975 | |||
| 6805bba308 | |||
| 2659b94a62 | |||
| c451415d9f | |||
| 553a9ff15f | |||
| 6f5eb7d207 | |||
| 55615e8f8e | |||
| 1d7899d671 | |||
| 97168d3a24 | |||
| 373b11dda7 | |||
| 69072f2423 | |||
| 5b37e8a531 | |||
| b47f4dfa96 | |||
| cbe98a9888 | |||
| 957996f5fb | |||
| 169988206a | |||
| 840f6ec9b8 | |||
| bf9ebea392 | |||
| 6c316d7cb5 | |||
| a4ac0c2bc6 | |||
| ed76364f87 | |||
| 57e21a1afa | |||
| bb58726133 | |||
| 3f6925125b | |||
| fd4decf2fe | |||
| 00b1b6b2b5 | |||
| cf141aa8c7 | |||
| ff3aee490a | |||
| 10bcfc0047 | |||
| 2f03899197 | |||
| 3bea3b6989 | |||
| 85bf29c446 | |||
| 900c922f41 | |||
| 9cf3f2ed7d | |||
| 1ffbeb9516 | |||
| 1051c5e6b7 | |||
| be255d62c8 | |||
| 263a1dbdd7 | |||
| 23dea60e1a | |||
| 690785f129 | |||
| 69aa109fd3 | |||
| 6bea2e04e4 | |||
| a1a82c3c55 | |||
| 7987ad700e | |||
| 0990d97a77 | |||
| a9150aad74 | |||
| 5ac3d84d99 | |||
| f916ec6baa | |||
| 7f831225a9 | |||
| a16893429b | |||
| 260511d149 | |||
| 7659fb686d | |||
| f669f16127 | |||
| 93f43cedaa | |||
| b6c7ce8ec3 | |||
| 35c963101b | |||
| 8909fc0c60 | |||
| 3c747e4585 | |||
| 1b89ff50a9 | |||
| c069b5c640 | |||
| 79f3484ab8 | |||
| ac8b7ea052 | |||
| c1b2f43917 | |||
| 51f8b0c52d | |||
| 6c4cae6b09 | |||
| 4da055a286 | |||
| 66c5d2b153 | |||
| 4bddf1b953 | |||
| 908f32175a | |||
| 3e1cf11060 | |||
| 723fcacad7 | |||
| 94acfe19e6 | |||
| b4677fde9d | |||
| c85e4240be | |||
| 363deb84cc | |||
| 106da4905f | |||
| f9baf39dc3 | |||
| 3deb08946e | |||
| 43f5eb5c69 | |||
| 5fcfbed3ea | |||
| f3869307cc | |||
| babafa54d2 | |||
| ad6c548573 | |||
| 80b2f5f9e1 | |||
| 2130ba5788 | |||
| a1ddb18c92 | |||
| ae38b27aee | |||
| da3998acfb | |||
| b9de3658ad | |||
| 16af2d9ce7 | |||
| b426ff81e3 | |||
| b0e87aeecd | |||
| a685dcf680 | |||
| 88da17ca21 | |||
| d91f8ba950 | |||
| aa5aa611d4 | |||
| da0b473d60 | |||
| 49d098debd | |||
| 40f1d19dbe | |||
| 514848b584 | |||
| 168b6cf789 | |||
| 8b0e95b6de | |||
| e3a4165363 | |||
| 6ac8049b92 | |||
| 13a33b3c33 | |||
| a8bdd17333 | |||
| 1c9601358b | |||
| f0d1ae08f3 | |||
| e3eaa6a3dd | |||
| 6a630cf283 | |||
| 7bfd518dd4 | |||
| 723a9491e2 | |||
| 2b44efb085 | |||
| 03dc0fc137 | |||
| 85cb0c478e | |||
| abe7194480 | |||
| aaccac7413 | |||
| 7cd4d84cac | |||
| 04ff3e8f95 | |||
| dc3031b614 | |||
| 1e2f931d0c | |||
| 930401b0dd | |||
| cb6eaea151 | |||
| b6f339ca36 | |||
| 2a5caea1a8 | |||
| b9f93f99aa | |||
| eb5cd476ba | |||
| 8478a3b7dd | |||
| dbb909136e | |||
| ad8dd4148b | |||
| f91d2ed9ae | |||
| 9497463718 | |||
| 46e9ecfcdd | |||
| e9c399c822 | |||
| b9dbfcb4ac | |||
| c270e27a4d | |||
| 0307f604ea | |||
| 8939af48fe | |||
| fa5d58cd00 | |||
| 1a3cf4b3c1 | |||
| 7d96352e96 | |||
| 111ecc5d8c | |||
| edd6fe954b | |||
| a20e9249c5 | |||
| b1353a99cd | |||
| c59e876bb3 | |||
| 7f1e697c0d | |||
| 373edcd055 | |||
| f0b5c4f857 | |||
| 3035d4fa34 | |||
| 60ac737439 | |||
| a95b0d301e | |||
| 951ca5ace0 | |||
| adf05a5bf6 | |||
| 418062165f | |||
| 210373b3b6 | |||
| 5f9fffa53e | |||
| 9cda015733 | |||
| 58a8d22931 | |||
| ef0ed22593 | |||
| 79925ac394 | |||
| b60e4092ec | |||
| fdc36e5c06 | |||
| 49e11ce1ba | |||
| 7ae1b5f8f3 | |||
| 1ac054b34a | |||
| 1e36ef551d | |||
| 0058c7226e | |||
| 29d4f3e887 | |||
| 1b8310d98a | |||
| af4c388dff | |||
| 09f6d9361d | |||
| 1f9eb8300f | |||
| c6a5be7f6a | |||
| 0a06af8d21 | |||
| 3393ad6760 | |||
| 830309fcb5 | |||
| ab4f3f3111 | |||
| 00460b8dee | |||
| d4486be2b9 | |||
| 991e344804 | |||
| 6a7de26e5a | |||
| 5382ef3b0b | |||
| a8cbc9184e | |||
| 966e9ccf0c | |||
| 53ade10137 | |||
| 422c719352 | |||
| 3415619bfd | |||
| 04bb76bc00 | |||
| 8b0f482666 | |||
| 4b3178b053 | |||
| 8e1ae68569 | |||
| 31000e1874 | |||
| 4487cb26c7 | |||
| aba4e18553 | |||
| c82f2580b4 | |||
| 1d7b009aec | |||
| 89c4b02bf3 | |||
| eeb8e44cda | |||
| 785c2d9605 | |||
| d549f048e1 | |||
| 4c0dd63011 | |||
| 26fb134165 | |||
| 07e614b52b | |||
| b1f899fbe8 | |||
| b4f860e627 | |||
| d940fe1b49 | |||
| f2899a9e06 | |||
| 3aca38d2d3 | |||
| 30752ac4ff | |||
| b84e6ca4f5 | |||
| 87a2fb0f1a | |||
| 9eaf7b9824 | |||
| 7bde100237 | |||
| da7fc795ee | |||
| 4c5fec1363 | |||
| 6588b0ad37 | |||
| 0093f74cfe | |||
| 171c6da57a | |||
| 2dddc7796d | |||
| 8514f4119a | |||
| 98fb7d94aa | |||
| 31ca16d9bc | |||
| 9f72ce695e | |||
| c383e4f953 | |||
| a94d8750fb | |||
| b0d651be40 | |||
| d5a9c11b5c | |||
| 6bfe1c435a | |||
| a02da49b87 | |||
| 29dc6c3367 | |||
| a7f0bab078 | |||
| 3dc6829303 | |||
| 42e63ff942 | |||
| df07751e6f | |||
| 5445f1741b | |||
| 9d0f811221 | |||
| 36b9a859c4 | |||
| 59628d1712 | |||
| bee7470715 | |||
| 5a359e10f4 | |||
| 5e37ade519 | |||
| 1a9ffdbd0c | |||
| 2adb0e99b0 | |||
| 71ed1f2f12 | |||
| 47954502af | |||
| 4987fd15f7 | |||
| 8bfe0d0ac0 | |||
| 7c0e6bd18f | |||
| 41b9c33c2b | |||
| 28a775db22 | |||
| e999600f8f | |||
| d3492d8d36 | |||
| 48de0c51b0 | |||
| 93bda5f1dc | |||
| 2d75ef6b30 | |||
| f97160f715 | |||
| eb59c776ca | |||
| 9128201c78 | |||
| 2cbfd37072 | |||
| 0939214c51 | |||
| 8c60f5aea7 | |||
| da0ed4021d | |||
| 99f905403b | |||
| aa0654332d | |||
| af376c22c3 | |||
| 477eb7b70e | |||
| 026e91a68c | |||
| bfbedac919 | |||
| 4036ff88ed | |||
| 1b4da41f97 | |||
| f61d452814 | |||
| f9866097a0 | |||
| 8b769fcc20 | |||
| 9c954264f4 | |||
| 77a6a9d4e1 | |||
| 547d843cca | |||
| 005cb84593 | |||
| fd5b5e9aa5 | |||
| 0647a7c1fe | |||
| 85c73ef8de | |||
| 5ba1796a7e | |||
| e52b7b380f | |||
| 84c7419652 | |||
| 536221b1f9 | |||
| fc55ac70d3 | |||
| 2afe5b4ef9 | |||
| b4ec2595c9 | |||
| c3ac7b675a | |||
| 24614e44bf | |||
| 9b868ef831 | |||
| c3eaf76430 | |||
| 32958dec3b | |||
| d64a97ba1e | |||
| c3df3372a1 | |||
| 8764353fe2 | |||
| e08c5de5dd | |||
| 74b538b8ec | |||
| 291ec50d98 | |||
| bc5af506bd | |||
| 21c7fd1bd5 | |||
| 28a092261b | |||
| 18dcae0a77 | |||
| 58c307f9cc | |||
| 8cc4809414 | |||
| 1179158def | |||
| 91aa40e749 | |||
| 595019e979 | |||
| b0d7917f88 | |||
| 8e6637a1e4 | |||
| 694fe05953 | |||
| f3dfd2a237 | |||
| 9e6158e9e6 | |||
| d577c4a2ce | |||
| fee0b82a40 | |||
| 7aafa26314 | |||
| d5bc546ca5 | |||
| 45ae217728 | |||
| b7b97dda73 | |||
| 5d3c563d46 | |||
| 376185458b | |||
| a8f14840ab | |||
| 9e32a40b1c | |||
| 87f635e54d | |||
| d4b2dfbde2 | |||
| f6ab0bc56f | |||
| 48cc2a6327 | |||
| 3202a6858a | |||
| b4f1bc16ff | |||
| 029ab46f71 | |||
| 220ca0ca9d | |||
| 20306f493a | |||
| cc865ac523 | |||
| 2d973c1805 | |||
| 6ca499b2dd | |||
| 1477028717 | |||
| 789740be0d | |||
| 8fe7539bb2 | |||
| f6623a3654 | |||
| c4fb923335 | |||
| 65b7eea775 | |||
| 01cd696fd1 | |||
| c13b3f7e68 | |||
| a6571ee0da | |||
| 6e38afff49 | |||
| 3d1b19ed90 | |||
| 5b24f88e73 | |||
| 74d06708dd | |||
| 3bfab6ef7f | |||
| 364cd8d8f7 | |||
| 9f8c579bf5 | |||
| eae7c2d684 | |||
| 3f43fca90d | |||
| 76449488ca | |||
| 00c4b0cef8 | |||
| 89139e2c11 | |||
| c9cab490f7 | |||
| 5fa711d75d | |||
| f5d8ae423a | |||
| 1d54973b92 | |||
| b8fafefd85 | |||
| c42ebb8839 | |||
| 9e680620b5 | |||
| 846f865de2 | |||
| ede9762a58 | |||
| d438c2d67b | |||
| bef110b92a | |||
| b971ef11d1 | |||
| 29d9f69399 | |||
| aecb4083bd | |||
| 1c675ab3a3 | |||
| dd619630a3 | |||
| 111803ab07 | |||
| 0024f74f34 | |||
| 03eec42c33 | |||
| 196f311ae2 | |||
| 38d9e0b209 | |||
| 6502b31316 | |||
| 6f1a8c3115 | |||
| d883c94cc9 | |||
| 961fa59a74 | |||
| 8bc71def55 | |||
| 7c65a9dc0e | |||
| d2d977a6c6 | |||
| a9a6ee9d7f | |||
| 28c5d215c1 | |||
| 3d6a789562 | |||
| a0e68698e3 | |||
| 44613c7d01 | |||
| c706281df3 | |||
| 65d75b8fe3 | |||
| 332b0cba40 | |||
| 8c4af41296 | |||
| 24a78f071b | |||
| c91c33436d | |||
| 2083f43a28 | |||
| 4676abdc9e | |||
| 35700eb23e | |||
| 59892e7b58 | |||
| 97dd07a7d1 | |||
| c8bc97c81b | |||
| 9dacfbbd69 | |||
| 05c2509d07 | |||
| 64f949b37b | |||
| 3f339de36a | |||
| 215c2b71ef | |||
| ce8fef7e0b | |||
| 0726b2c479 | |||
| 589549d7e6 | |||
| edb1a586d8 | |||
| 11c2917040 | |||
| 6ba9c12ff6 | |||
| d2fcc346b9 | |||
| a091a07aa2 | |||
| bb4135cae8 | |||
| 8de84b7ca3 | |||
| 9cdf332029 | |||
| e94fc65f01 | |||
| b908487476 | |||
| 2a7c7faeb4 | |||
| e302e15eea | |||
| 1cbea892cf | |||
| 37a32857a2 | |||
| 8c4aad3a59 | |||
| 1774794b19 | |||
| 1af23f1f2d | |||
| 94fbc3d388 | |||
| 8da2058e2a | |||
| 09993a904a | |||
| 5d1403461c | |||
| ddc1ee564b | |||
| 00a54b848a | |||
| dad15b9fd0 | |||
| d89c19f903 | |||
| 146dc0fad5 | |||
| d26852deef | |||
| e1c27243b2 | |||
| dbbfe7abe2 | |||
| dc24d12ce0 | |||
| 4e7533e872 | |||
| 5d036515ed | |||
| a741293886 | |||
| f8d0b26d2f | |||
| 7007c1bea5 | |||
| 0d8ebac7e1 | |||
| 212c42c74f | |||
| 919f6be887 | |||
| c0f70428ba | |||
| e797c90ebd | |||
| fc04d1219a | |||
| df4ad5884d | |||
| 3c7dd6fc1e | |||
| 8b196ea1c8 | |||
| 1f8c8ad5a3 | |||
| 870925d503 | |||
| d593215ef7 | |||
| 110af31b48 | |||
| 360606b9a6 | |||
| 151b45ae36 | |||
| 2ea7e1300f | |||
| 4617c957b9 | |||
| 2547ed83ca | |||
| bfcd44704f | |||
| 7b548db91e | |||
| d39dea85ad | |||
| 5e56c9fba8 | |||
| 8d3a03288b | |||
| cb490ec16d | |||
| 45271c3676 | |||
| 6a097eca93 | |||
| 84d1c5385d | |||
| 05a5b7e3c6 | |||
| 3bff326fb3 | |||
| aaadd93878 | |||
| 9c864f0b02 | |||
| 070cce0d9c | |||
| b58e8bac12 | |||
| ada50b077e | |||
| 5e313a7330 | |||
| 2a36d11238 | |||
| b6685cf9dd | |||
| fc273c6763 | |||
| bd7b0e257e | |||
| 73931692b2 | |||
| 4d93e9f44c | |||
| da55ed7e8d | |||
| e3617e1f28 | |||
| 431636af0d | |||
| 891ced598a | |||
| 57dc0ee769 | |||
| 5e102c4da1 | |||
| 5c33931422 | |||
| 4aa54222f4 | |||
| ef4f860384 | |||
| 9bd52ec5c1 | |||
| 5cdd82d41e | |||
| 110bf10481 | |||
| 43035f6f37 | |||
| 83b1a3d5dc | |||
| 878110a4bc | |||
| 59ec8b7db2 | |||
| cae1b43829 | |||
| 99fde4ee3e | |||
| afe3872810 | |||
| 3a3e6bf103 | |||
| 935f0bd70f | |||
| 5c18bfeda6 | |||
| 957ef206d1 | |||
| 0c367838cc | |||
| 2023cf345f | |||
| 033d05f70b | |||
| fe4e3fd3b0 | |||
| 8a8a8a70ee | |||
| 339dca828d | |||
| 0d7349fa4e | |||
| 830528d5b1 | |||
| ab90fbc7c9 | |||
| 3eec111e8f | |||
| 9388433642 | |||
| ba12070665 | |||
| a57a324d72 | |||
| 92e91b3557 | |||
| 4dcf791706 | |||
| e77900fb94 | |||
| 1b14cadf20 | |||
| 4f59cd217a | |||
| 27c8b2d66a | |||
| 89976c2712 | |||
| c91737fef1 | |||
| a100719bc6 | |||
| 9a0e149225 | |||
| 9350927903 | |||
| 677c13a4ec | |||
| ee8e1ee7ff | |||
| f969080b9f | |||
| c2b16bfbb0 | |||
| e7df53701c | |||
| 02c34e490b | |||
| 427c839b3d | |||
| 48aa054f53 | |||
| 3616860203 | |||
| 861b0dfea2 | |||
| 8b3d71ae2d | |||
| ff5442cd9e | |||
| 92d686f9a5 | |||
| 7b09cccd77 | |||
| 6f1f38d046 | |||
| db8f06467b | |||
| 91ec1c290f | |||
| 0676673ca5 | |||
| 7a4335d664 | |||
| 31a0e73489 | |||
| 74fe70855f | |||
| e74925bc43 | |||
| 56be1c203e | |||
| 2f9bf4d3eb | |||
| ad94aed753 | |||
| 30db83fc44 | |||
| b0f7b00e1f | |||
| 7255e192d8 | |||
| 2102e1aa42 | |||
| 85d5c1fd38 | |||
| b789286bc3 | |||
| a6a8a334f7 | |||
| 78a11a27b6 | |||
| d2d7bad04a | |||
| b978854258 | |||
| 0fb672a1ef | |||
| dd9913675d | |||
| 11677ad926 | |||
| 25a53f10db | |||
| 26e2ef001c | |||
| 30f79b3b2e | |||
| 89f84c2915 | |||
| 6882285be0 | |||
| 3260bc5896 | |||
| 6140b6f527 | |||
| 4cabc9f293 | |||
| aa7c6345a4 | |||
| f709fc05b0 | |||
| 089aae1292 | |||
| 855acaf112 | |||
| 7ca7720262 | |||
| 78fea3aa4a | |||
| 1efb8b6a53 | |||
| bc1960b106 | |||
| 967023b755 | |||
| bb51e68f16 | |||
| 27414c90a8 | |||
| 50e2f4b213 | |||
| 22be673beb | |||
| 166c89fabf | |||
| 6e0b13eedb | |||
| 7e8f978ca9 | |||
| 6c0e838a7c | |||
| d3da41927a | |||
| 425a4b7a74 | |||
| 63c65ef742 | |||
| e838b0bd81 | |||
| 041e99c78a | |||
| 07dcc4f7fe | |||
| b88052d875 | |||
| a28292764c | |||
| 2027088741 | |||
| e2d8589976 | |||
| c8a9f99d14 | |||
| 645d04012d | |||
| 100ddada2f | |||
| 2ef1cd4b35 | |||
| be9c3fd69d | |||
| ef522e1d16 | |||
| 1ddb6c2fdb | |||
| eb3f2329af | |||
| 9e8f14816b | |||
| 4e5e55bf1c | |||
| 4513a9e6a7 | |||
| 4f922e4e5b | |||
| 993966600e | |||
| 5b96cf1bde | |||
| f3d50e5209 | |||
| ab21d4d017 | |||
| f7c5d93e6a | |||
| 52a7d40e6e | |||
| 348bc6b257 | |||
| 03da66c805 | |||
| f75426f47e | |||
| 662fc3861c | |||
| 28c10020b9 | |||
| 89c8d85de9 | |||
| 6502838f27 | |||
| c93a0f335a | |||
| 8264e002a7 | |||
| 117ef22142 | |||
| 3fb5e71c33 | |||
| 296db177e2 | |||
| e4a4389177 | |||
| 7aa0453c3b | |||
| 09b78b24e9 | |||
| a622b8a74a | |||
| 399ef081ec | |||
| 3686277e14 | |||
| 807bd20a64 | |||
| ed9a140348 | |||
| 2de7c2bea2 | |||
| e6a4a3772e | |||
| 0fca04e1a6 | |||
| 92bfc8d3af | |||
| fa0312ac45 | |||
| 1920b694aa | |||
| 3bfd41d624 | |||
| 290449f19b | |||
| 3a1f387e69 | |||
| 541603ac94 | |||
| 0666fbfa20 | |||
| ea071ae1d4 | |||
| 992a01bad2 | |||
| d640b5624f | |||
| 48479e4bae | |||
| dfaf48bc09 | |||
| dcbc3e0162 | |||
| 0289d31724 | |||
| 015e39776f | |||
| 6a9a21f178 | |||
| 81ac54b20d | |||
| 6b4e75520a | |||
| b053b4f492 | |||
| 4cf1fec575 | |||
| ee7d77defa | |||
| d0dfc4577e | |||
| bbbd1d24c9 | |||
| fb3a9e0d7c | |||
| 5ffebeb6ef | |||
| 75db73066b | |||
| 2796833c82 | |||
| 95730dc7f7 | |||
| 795261919f | |||
| 3783a30ae7 | |||
| b61ec84886 | |||
| 780a461d92 | |||
| c0ba323166 | |||
| 20a48c9580 | |||
| 09938803af | |||
| 6d0b43a220 | |||
| c604bdbfe4 | |||
| 9fef892f6d | |||
| b1c7db47b8 | |||
| e76e87a430 | |||
| 8a4dfa7231 | |||
| 107018c628 | |||
| a398237930 | |||
| b63c65d7f5 | |||
| f60324e883 | |||
| 361c23a09a | |||
| 43b23c7ea0 | |||
| 6081497506 | |||
| 48e5753e76 | |||
| bbba632ab3 | |||
| e77db40b8d | |||
| 2c1f62d4b4 | |||
| 1aebdc2760 | |||
| 705e58be8c | |||
| 7c2c12aa43 | |||
| a0f850f15b | |||
| fccb9499bc | |||
| a139ab2572 | |||
| 1d910a484c | |||
| ee9166ec97 | |||
| b5a9eff32e | |||
| 9441a29663 | |||
| ab6588ef74 | |||
| 1d11f03449 | |||
| e11d01fe1d | |||
| a901f50850 | |||
| c399e9c368 | |||
| 25381be0c9 | |||
| ef2a7c753f | |||
| 99f165b45a | |||
| 2fb5560746 | |||
| bd653ab30c | |||
| b5d68aedaa | |||
| 624879c4c6 | |||
| bd9e9abf35 | |||
| 3e4a23cbd0 | |||
| 6326ceec3f | |||
| 8f4d37c7ec | |||
| 1b8290b318 | |||
| 48193fbccd | |||
| 51799dd654 | |||
| 732ac49321 | |||
| ac8ea72d88 | |||
| f583401284 | |||
| 2d88228b7d | |||
| 0c6a2bbf79 | |||
| a80d830f27 | |||
| 5f3fd9994e | |||
| d6de911855 | |||
| 04af32230e | |||
| 4cb8d079f8 | |||
| 6ab55a1e52 | |||
| acfd19cb46 | |||
| e3058105f0 | |||
| dc200a6450 | |||
| 2c0999a0b9 | |||
| dd460f82a1 | |||
| c3d637f397 | |||
| 479a00a215 | |||
| c42e7c8012 | |||
| 5b8e0657d4 | |||
| 9fc0d13e2c | |||
| bc22641359 | |||
| 05098105a8 | |||
| 5b23634dc6 | |||
| 32f0d00ff9 | |||
| 9d87851f0c | |||
| c0296ee11b | |||
| 54671259aa | |||
| 994f7c7924 | |||
| 7a8e4977e2 | |||
| fb7b6ea7ea | |||
| 063dd5b93f | |||
| a38aa31ade | |||
| f42b2581da | |||
| 2ba406726f | |||
| 7e9826e17b | |||
| f4dcc5c918 | |||
| 8b1887c440 | |||
| bbfb1d3504 | |||
| e106feb5ec | |||
| 696f6f56db | |||
| b7b636a23f | |||
| 183b91775e | |||
| 0e70f59021 | |||
| 4d9b76db73 | |||
| 9af132f594 | |||
| 6c063569c0 | |||
| 7e9b98401d | |||
| f301e09e02 | |||
| b80e722f81 | |||
| 1714c262c4 | |||
| a42cdafdcd | |||
| eb4c3f16f7 | |||
| ce86f351d6 | |||
| 0b90f6c96a | |||
| 2198463218 | |||
| be57a5e00a | |||
| b1b09eba60 | |||
| eb1e8c140d | |||
| 43da87939d | |||
| 06d99a13a6 | |||
| 49a911d7de | |||
| 27d6628785 | |||
| e4e2956e79 | |||
| ea2f7b81d9 | |||
| f0dfdb5247 | |||
| 6a5da85fcd | |||
| 0750eee4ff | |||
| ef551a517c | |||
| 1c5ea24f76 | |||
| 88d73e5250 | |||
| 1ff2a972c6 | |||
| bb72fe2726 | |||
| e50b14afee | |||
| cbd1cbef07 | |||
| 01da3f79c9 | |||
| f5e0fbcb14 | |||
| 38c130a303 | |||
| c7393614ff | |||
| a13c6382b6 | |||
| a803ec1c1f | |||
| f7636428ed | |||
| f85c4f2fa9 | |||
| a9a9903107 | |||
| bd4a0981ba | |||
| 35e5cf3e15 | |||
| 07fc9f689e | |||
| 14b0e18c57 | |||
| dd27ec8703 | |||
| db3f00c3b3 | |||
| adcb11ca18 | |||
| b7be637e8c | |||
| 30c4aa2cf4 | |||
| a649190a4d | |||
| d81f0ef652 | |||
| 1a3a49ce7c | |||
| 6b948111ca | |||
| 6adfdc56e5 | |||
| 61531ddd9e | |||
| ccf9c6fc07 | |||
| b25d0ea7f9 | |||
| 4f4557fd05 | |||
| bf400d6799 | |||
| 4d2e36d19b | |||
| df6310e5f5 | |||
| 938ab5ddec | |||
| ef5a0de384 | |||
| 5d186c77a6 | |||
| 44bf3633af | |||
| f261184416 | |||
| df40f80fcf | |||
| e7060ba83d | |||
| d98f0eea3d | |||
| 4f157a8b81 | |||
| d493649f52 | |||
| 0e947e6c3b | |||
| 9249dab54c | |||
| 7440e56c53 | |||
| 0d79306285 | |||
| 37faaf295e | |||
| 650358fa00 | |||
| 6159ead404 | |||
| 692ac99c69 | |||
| 86161ce15f | |||
| 5361c790bb | |||
| 126730edc8 | |||
| 3aec2a96a8 | |||
| 227d039b1e | |||
| 0353354d61 | |||
| 34ae0422f4 | |||
| cc128feb4c | |||
| 7766103174 | |||
| 30f7c7110d | |||
| 50354c2d0b | |||
| c4f67e679f | |||
| 0daafe423f | |||
| 37021910c9 | |||
| 7328b34810 | |||
| fabbd2b097 | |||
| 6814f978d7 | |||
| 4ea403c54a | |||
| f4f6b5af3a | |||
| 2062a3c16d | |||
| 9a53bd9125 | |||
| 4873b48b02 | |||
| e19844c659 | |||
| 93bb9e147c | |||
| ab230e6e44 | |||
| 51ea34b217 | |||
| 1050f6b808 | |||
| 15ec95a98d | |||
| 072145e0e9 | |||
| 92957f17f2 | |||
| 667db558b6 | |||
| f41509261e | |||
| 6d009711a2 | |||
| 354b48fd40 | |||
| 3fd8e52f0c | |||
| 142dce0d3d | |||
| 6aed101630 | |||
| e2ccfd9ea7 | |||
| a07d794f74 | |||
| 90d28fc314 | |||
| 55cf0ac51a | |||
| 07696c1674 | |||
| f803b290f3 | |||
| d96e181150 | |||
| 3ffb86fc70 | |||
| 649a72a587 | |||
| b2676348eb | |||
| 8c036ee5a3 | |||
| d99009f3c6 | |||
| be3c37eb8b | |||
| f0346ae054 | |||
| fa6ce42056 | |||
| a9320db6f9 | |||
| d208762c81 | |||
| 5386897d24 | |||
| 68eb59df0c | |||
| a7f4551669 | |||
| 983347484e | |||
| f52d134c14 | |||
| 6660676b0d | |||
| 1d42d3571a | |||
| ebd06eebdb | |||
| f1985823a3 | |||
| 60e4092b8e | |||
| 3d0251666e | |||
| 7770da4929 | |||
| a5fd85a9ef | |||
| abb2a8494d | |||
| a31d0be191 | |||
| d786e750d7 | |||
| 10e4839f83 | |||
| 85e72653c8 | |||
| c9cc8a8924 | |||
| a925ce4119 | |||
| c5f6338ce2 | |||
| 5185487d73 | |||
| efaafd4458 | |||
| a0eb83a5d4 | |||
| 7cc6f7fbb0 | |||
| 44b9496c91 | |||
| 7e1486d0da | |||
| 8170ffef2e | |||
| 4b622f6bbf | |||
| 0ee71c70af | |||
| 6c098e497e | |||
| 41ffa6df7e |
@@ -1 +0,0 @@
|
|||||||
test_suite/tests/expand/*.expanded.rs linguist-generated
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
github: dtolnay
|
||||||
+70
-83
@@ -3,8 +3,12 @@ name: CI
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
schedule: [cron: "40 1 * * *"]
|
schedule: [cron: "40 1 * * *"]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RUSTFLAGS: -Dwarnings
|
RUSTFLAGS: -Dwarnings
|
||||||
|
|
||||||
@@ -12,20 +16,24 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
name: Test suite
|
name: Test suite
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd test_suite && cargo test --features unstable
|
- run: cd test_suite && cargo test --features unstable
|
||||||
- uses: dtolnay/install@cargo-expand
|
- uses: actions/upload-artifact@v6
|
||||||
if: github.event_name != 'pull_request'
|
if: always()
|
||||||
- run: cd test_suite && cargo test --features expandtest --test expandtest -- --include-ignored
|
with:
|
||||||
if: github.event_name != 'pull_request'
|
name: Cargo.lock
|
||||||
|
path: Cargo.lock
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
name: Test suite (windows)
|
name: Test suite (windows)
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||||
|
|
||||||
@@ -36,31 +44,33 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
rust: [stable, beta]
|
rust: [stable, beta]
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@master
|
- uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{matrix.rust}}
|
toolchain: ${{matrix.rust}}
|
||||||
- run: cd serde && cargo build --features rc
|
- run: cd serde && cargo build --features rc
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde_test && cargo build
|
- run: cd test_suite/no_std && cargo build
|
||||||
- run: cd serde_test && cargo test --features serde/derive,serde/rc
|
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
name: Rust nightly${{matrix.os == 'windows' && ' (windows)' || ''}}
|
||||||
runs-on: ${{matrix.os}}-latest
|
runs-on: ${{matrix.os}}-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu, windows]
|
os: [ubuntu, windows]
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd serde && cargo build
|
- run: cd serde && cargo build
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde && cargo build --no-default-features --features alloc
|
- run: cd serde && cargo build --no-default-features --features alloc
|
||||||
- run: cd serde && cargo build --no-default-features --features rc,alloc
|
- run: cd serde && cargo build --no-default-features --features rc,alloc
|
||||||
- run: cd serde && cargo test --features derive,rc,unstable
|
- run: cd serde && cargo build --no-default-features --features unstable
|
||||||
|
- run: cd serde_core && cargo test --features rc,unstable
|
||||||
- run: cd test_suite/no_std && cargo build
|
- run: cd test_suite/no_std && cargo build
|
||||||
if: matrix.os != 'windows'
|
if: matrix.os != 'windows'
|
||||||
- run: cd serde_derive && cargo check --tests
|
- run: cd serde_derive && cargo check --tests
|
||||||
@@ -68,116 +78,91 @@ jobs:
|
|||||||
RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}}
|
RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}}
|
||||||
if: matrix.os != 'windows'
|
if: matrix.os != 'windows'
|
||||||
|
|
||||||
msrv:
|
|
||||||
name: Rust 1.13.0
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@1.13.0
|
|
||||||
- name: Get timestamp for cache
|
|
||||||
id: date
|
|
||||||
run: echo ::set-output name=yearmo::$(date +%Y%m)
|
|
||||||
- uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.cargo/registry/index
|
|
||||||
key: cargo-registry-index-${{steps.date.outputs.yearmo}}
|
|
||||||
- run: cd serde && cargo build --features rc
|
|
||||||
- run: cd serde && cargo build --no-default-features
|
|
||||||
- run: cd serde_test && cargo build
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Rust ${{matrix.rust}}
|
name: Rust ${{matrix.rust}}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
|
rust: [1.56.0, 1.60.0]
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@master
|
- uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{matrix.rust}}
|
toolchain: ${{matrix.rust}}
|
||||||
|
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||||
|
- run: cd serde && cargo build --features rc
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde && cargo build
|
- run: cd serde && cargo build --no-default-features --features alloc
|
||||||
|
|
||||||
more:
|
|
||||||
name: Rust ${{matrix.rust}}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
rust: [1.27.0, 1.28.0]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@master
|
|
||||||
with:
|
|
||||||
toolchain: ${{matrix.rust}}
|
|
||||||
# Work around failing to parse manifest because editions are unstable.
|
|
||||||
- run: sed -i /test_suite/d Cargo.toml
|
|
||||||
- run: cd serde && cargo build --no-default-features
|
|
||||||
- run: cd serde && cargo build
|
- run: cd serde && cargo build
|
||||||
|
|
||||||
derive:
|
derive:
|
||||||
name: Rust 1.31.0
|
name: Rust 1.68.0
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@1.31.0
|
- uses: dtolnay/rust-toolchain@1.68.0
|
||||||
|
- run: |
|
||||||
|
sed -i 's/proc-macro2 = { workspace = true/proc-macro2 = { version = "1"/' serde_derive*/Cargo.toml
|
||||||
|
sed -i 's/quote = { workspace = true/quote = { version = "1"/' serde_derive*/Cargo.toml
|
||||||
|
sed -i 's/syn = { workspace = true/syn = { version = "2"/' serde_derive*/Cargo.toml
|
||||||
- run: cd serde && cargo check --no-default-features
|
- run: cd serde && cargo check --no-default-features
|
||||||
- run: cd serde && cargo check
|
- run: cd serde && cargo check
|
||||||
- run: cd serde_derive && cargo check
|
- run: cd serde_derive && cargo check
|
||||||
|
|
||||||
alloc:
|
minimal:
|
||||||
name: Rust 1.36.0
|
name: Minimal versions
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@1.36.0
|
|
||||||
- run: cd serde && cargo build --no-default-features --features alloc
|
|
||||||
|
|
||||||
emscripten:
|
|
||||||
name: Emscripten
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- uses: actions/setup-node@v1
|
- run: cargo generate-lockfile -Z minimal-versions
|
||||||
with:
|
- run: cargo check --locked --workspace
|
||||||
node-version: 9
|
|
||||||
- name: Install cargo-web
|
doc:
|
||||||
run: |
|
name: Documentation
|
||||||
CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest)
|
runs-on: ubuntu-latest
|
||||||
CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name)
|
timeout-minutes: 45
|
||||||
CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
|
env:
|
||||||
mkdir -p ~/.cargo/bin
|
RUSTDOCFLAGS: -Dwarnings
|
||||||
curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
|
steps:
|
||||||
chmod +x ~/.cargo/bin/cargo-web
|
- uses: actions/checkout@v6
|
||||||
- run: cd test_suite && cargo web test --target=asmjs-unknown-emscripten --nodejs
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
continue-on-error: true
|
- uses: dtolnay/install@cargo-docs-rs
|
||||||
- run: cd test_suite && cargo web test --target=wasm32-unknown-emscripten --nodejs
|
- run: cargo docs-rs -p serde
|
||||||
continue-on-error: true
|
- run: cargo docs-rs -p serde_core
|
||||||
|
- run: cargo docs-rs -p serde_derive
|
||||||
|
- run: cargo docs-rs -p serde_derive_internals
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
name: Clippy
|
name: Clippy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@clippy
|
- uses: dtolnay/rust-toolchain@clippy
|
||||||
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
||||||
|
- run: cd serde_core && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
|
||||||
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
|
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
|
|
||||||
miri:
|
miri:
|
||||||
name: Miri
|
name: Miri
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: dtolnay/rust-toolchain@miri
|
- uses: dtolnay/rust-toolchain@miri
|
||||||
- run: cd serde && cargo miri test --features derive,rc,unstable
|
with:
|
||||||
|
toolchain: nightly-2025-05-16 # https://github.com/rust-lang/miri/issues/4323
|
||||||
|
- run: cargo miri setup
|
||||||
|
- run: cd serde_core && cargo miri test --features rc,unstable
|
||||||
env:
|
env:
|
||||||
MIRIFLAGS: -Zmiri-strict-provenance
|
MIRIFLAGS: -Zmiri-strict-provenance
|
||||||
- run: cd test_suite && cargo miri test --features unstable
|
- run: cd test_suite && cargo miri test --features unstable
|
||||||
@@ -188,7 +173,9 @@ jobs:
|
|||||||
name: Outdated
|
name: Outdated
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- uses: dtolnay/install@cargo-outdated
|
- uses: dtolnay/install@cargo-outdated
|
||||||
- run: cargo outdated --workspace --exclude macrotest,prettyplease --exit-code 1
|
- run: cargo outdated --workspace --exit-code 1
|
||||||
|
|||||||
+2
-4
@@ -1,4 +1,2 @@
|
|||||||
target/
|
/target/
|
||||||
**/*.rs.bk
|
/Cargo.lock
|
||||||
*.sw[po]
|
|
||||||
Cargo.lock
|
|
||||||
|
|||||||
+3
-3
@@ -27,11 +27,11 @@ pull request with your changes. If anything does not pass, typically it will be
|
|||||||
easier to iterate and fix it locally than waiting for the CI servers to run
|
easier to iterate and fix it locally than waiting for the CI servers to run
|
||||||
tests for you.
|
tests for you.
|
||||||
|
|
||||||
##### In the [`serde`] directory
|
##### In the [`serde_core`] directory
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Test all the example code in Serde documentation
|
# Test all the example code in Serde documentation
|
||||||
cargo test --features derive
|
cargo test
|
||||||
```
|
```
|
||||||
|
|
||||||
##### In the [`test_suite`] directory
|
##### In the [`test_suite`] directory
|
||||||
@@ -43,7 +43,7 @@ cargo +nightly test --features unstable
|
|||||||
|
|
||||||
Note that this test suite currently only supports running on a nightly compiler.
|
Note that this test suite currently only supports running on a nightly compiler.
|
||||||
|
|
||||||
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
|
[`serde_core`]: https://github.com/serde-rs/serde/tree/master/serde_core
|
||||||
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
|
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
|
||||||
|
|
||||||
## Conduct
|
## Conduct
|
||||||
|
|||||||
+12
-1
@@ -1,8 +1,19 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_derive_internals",
|
"serde_derive_internals",
|
||||||
"serde_test",
|
|
||||||
"test_suite",
|
"test_suite",
|
||||||
]
|
]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
serde = { path = "serde" }
|
||||||
|
serde_core = { path = "serde_core" }
|
||||||
|
serde_derive = { path = "serde_derive" }
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
proc-macro2 = { version = "1.0.74", default-features = false }
|
||||||
|
quote = { version = "1.0.35", default-features = false }
|
||||||
|
syn = { version = "2.0.81", default-features = false }
|
||||||
|
|||||||
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|||||||
of your accepting any such warranty or additional liability.
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
|
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.56] [![serde_derive msrv]][Rust 1.68]
|
||||||
|
|
||||||
[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master
|
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
|
||||||
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
|
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
|
||||||
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
||||||
[crates.io]: https://crates.io/crates/serde
|
[crates.io]: https://crates.io/crates/serde
|
||||||
[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
|
[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray
|
||||||
[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
|
[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray
|
||||||
[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
|
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0/
|
||||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
[Rust 1.68]: https://blog.rust-lang.org/2023/03/09/Rust-1.68.0/
|
||||||
|
|
||||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||||
|
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
|
|
||||||
You may be looking for:
|
You may be looking for:
|
||||||
|
|
||||||
- [An overview of Serde](https://serde.rs/)
|
- [An overview of Serde](https://serde.rs)
|
||||||
- [Data formats supported by Serde](https://serde.rs/#data-formats)
|
- [Data formats supported by Serde](https://serde.rs/#data-formats)
|
||||||
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
|
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
|
||||||
- [Examples](https://serde.rs/examples.html)
|
- [Examples](https://serde.rs/examples.html)
|
||||||
- [API documentation](https://docs.serde.rs/serde/)
|
- [API documentation](https://docs.rs/serde)
|
||||||
- [Release notes](https://github.com/serde-rs/serde/releases)
|
- [Release notes](https://github.com/serde-rs/serde/releases)
|
||||||
|
|
||||||
## Serde in action
|
## Serde in action
|
||||||
@@ -27,7 +27,7 @@ You may be looking for:
|
|||||||
<details>
|
<details>
|
||||||
<summary>
|
<summary>
|
||||||
Click to show Cargo.toml.
|
Click to show Cargo.toml.
|
||||||
<a href="https://play.rust-lang.org/?edition=2018&gist=72755f28f99afc95e01d63174b28c1f5" target="_blank">Run this code in the playground.</a>
|
<a href="https://play.rust-lang.org/?edition=2021&gist=72755f28f99afc95e01d63174b28c1f5" target="_blank">Run this code in the playground.</a>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@@ -48,7 +48,7 @@ serde_json = "1.0"
|
|||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct Point {
|
struct Point {
|
||||||
|
|||||||
+5
-5
@@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
You may be looking for:
|
You may be looking for:
|
||||||
|
|
||||||
- [An overview of Serde](https://serde.rs/)
|
- [An overview of Serde](https://serde.rs)
|
||||||
- [Data formats supported by Serde](https://serde.rs/#data-formats)
|
- [Data formats supported by Serde](https://serde.rs/#data-formats)
|
||||||
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
|
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
|
||||||
- [Examples](https://serde.rs/examples.html)
|
- [Examples](https://serde.rs/examples.html)
|
||||||
- [API documentation](https://docs.serde.rs/serde/)
|
- [API documentation](https://docs.rs/serde)
|
||||||
- [Release notes](https://github.com/serde-rs/serde/releases)
|
- [Release notes](https://github.com/serde-rs/serde/releases)
|
||||||
|
|
||||||
## Serde in action
|
## Serde in action
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct Point {
|
struct Point {
|
||||||
@@ -46,8 +46,8 @@ fn main() {
|
|||||||
Serde is one of the most widely used Rust libraries so any place that Rustaceans
|
Serde is one of the most widely used Rust libraries so any place that Rustaceans
|
||||||
congregate will be able to help you out. For chat, consider trying the
|
congregate will be able to help you out. For chat, consider trying the
|
||||||
[#rust-questions] or [#rust-beginners] channels of the unofficial community
|
[#rust-questions] or [#rust-beginners] channels of the unofficial community
|
||||||
Discord (invite: <https://discord.gg/rust-lang-community>, the [#rust-usage] or
|
Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage]
|
||||||
[#beginners] channels of the official Rust Project Discord (invite:
|
or [#beginners] channels of the official Rust Project Discord (invite:
|
||||||
<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
|
<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
|
||||||
asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
|
asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
|
||||||
[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
|
[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
msrv = "1.13.0"
|
|
||||||
+25
-19
@@ -1,30 +1,36 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.137" # remember to update html_root_url and serde_derive dependency
|
version = "1.0.228"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
rust-version = "1.13"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
description = "A generic serialization/deserialization framework"
|
|
||||||
homepage = "https://serde.rs"
|
|
||||||
repository = "https://github.com/serde-rs/serde"
|
|
||||||
documentation = "https://docs.serde.rs/serde/"
|
|
||||||
keywords = ["serde", "serialization", "no_std"]
|
|
||||||
categories = ["encoding"]
|
|
||||||
readme = "crates-io.md"
|
|
||||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||||
|
description = "A generic serialization/deserialization framework"
|
||||||
|
documentation = "https://docs.rs/serde"
|
||||||
|
edition = "2021"
|
||||||
|
homepage = "https://serde.rs"
|
||||||
|
keywords = ["serde", "serialization", "no_std"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
readme = "crates-io.md"
|
||||||
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
rust-version = "1.56"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_derive = { version = "=1.0.137", optional = true, path = "../serde_derive" }
|
serde_core = { version = "=1.0.228", path = "../serde_core", default-features = false, features = ["result"] }
|
||||||
|
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||||
[dev-dependencies]
|
|
||||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
|
||||||
|
|
||||||
[package.metadata.playground]
|
[package.metadata.playground]
|
||||||
features = ["derive", "rc"]
|
features = ["derive", "rc"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
features = ["derive", "rc", "unstable"]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
rustdoc-args = [
|
||||||
|
"--generate-link-to-definition",
|
||||||
|
"--generate-macro-expansion",
|
||||||
|
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
### FEATURES #################################################################
|
### FEATURES #################################################################
|
||||||
@@ -37,20 +43,20 @@ derive = ["serde_derive"]
|
|||||||
|
|
||||||
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
|
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
|
||||||
# Requires a dependency on the Rust standard library.
|
# Requires a dependency on the Rust standard library.
|
||||||
std = []
|
std = ["serde_core/std"]
|
||||||
|
|
||||||
# Provide impls for types that require unstable functionality. For tracking and
|
# Provide impls for types that require unstable functionality. For tracking and
|
||||||
# discussion of unstable functionality please refer to this issue:
|
# discussion of unstable functionality please refer to this issue:
|
||||||
#
|
#
|
||||||
# https://github.com/serde-rs/serde/issues/812
|
# https://github.com/serde-rs/serde/issues/812
|
||||||
unstable = []
|
unstable = ["serde_core/unstable"]
|
||||||
|
|
||||||
# Provide impls for types in the Rust core allocation and collections library
|
# Provide impls for types in the Rust core allocation and collections library
|
||||||
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
|
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
|
||||||
# be enabled without depending on all of std.
|
# be enabled without depending on all of std.
|
||||||
alloc = []
|
alloc = ["serde_core/alloc"]
|
||||||
|
|
||||||
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
|
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
|
||||||
# does not preserve identity and may result in multiple copies of the same data.
|
# does not preserve identity and may result in multiple copies of the same data.
|
||||||
# Be sure that this is what you want before enabling this feature.
|
# Be sure that this is what you want before enabling this feature.
|
||||||
rc = []
|
rc = ["serde_core/rc"]
|
||||||
|
|||||||
+43
-114
@@ -1,140 +1,69 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::str::{self, FromStr};
|
use std::str;
|
||||||
|
|
||||||
|
const PRIVATE: &str = "\
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod __private$$ {
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::private::*;
|
||||||
|
}
|
||||||
|
use serde_core::__private$$ as serde_core_private;
|
||||||
|
";
|
||||||
|
|
||||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
// The rustc-cfg strings below are *not* public API. Please let us know by
|
||||||
// opening a GitHub issue if your build environment requires some way to enable
|
// opening a GitHub issue if your build environment requires some way to enable
|
||||||
// these cfgs other than by executing our build script.
|
// these cfgs other than by executing our build script.
|
||||||
fn main() {
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
println!("cargo:rustc-cfg=if_docsrs_then_no_serde_core");
|
||||||
|
|
||||||
|
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap();
|
||||||
|
let module = PRIVATE.replace("$$", &patch_version);
|
||||||
|
fs::write(out_dir.join("private.rs"), module).unwrap();
|
||||||
|
|
||||||
let minor = match rustc_minor_version() {
|
let minor = match rustc_minor_version() {
|
||||||
Some(minor) => minor,
|
Some(minor) => minor,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = env::var("TARGET").unwrap();
|
if minor >= 77 {
|
||||||
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
|
println!("cargo:rustc-check-cfg=cfg(feature, values(\"result\"))");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(if_docsrs_then_no_serde_core)");
|
||||||
// std::collections::Bound was stabilized in Rust 1.17
|
println!("cargo:rustc-check-cfg=cfg(no_core_cstr)");
|
||||||
// but it was moved to core::ops later in Rust 1.26:
|
println!("cargo:rustc-check-cfg=cfg(no_core_error)");
|
||||||
// https://doc.rust-lang.org/core/ops/enum.Bound.html
|
println!("cargo:rustc-check-cfg=cfg(no_core_net)");
|
||||||
if minor < 26 {
|
println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)");
|
||||||
println!("cargo:rustc-cfg=no_ops_bound");
|
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
|
||||||
if minor < 17 {
|
println!("cargo:rustc-check-cfg=cfg(no_serde_derive)");
|
||||||
println!("cargo:rustc-cfg=no_collections_bound");
|
println!("cargo:rustc-check-cfg=cfg(no_std_atomic)");
|
||||||
}
|
println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// core::cmp::Reverse stabilized in Rust 1.19:
|
// Current minimum supported version of serde_derive crate is Rust 1.68.
|
||||||
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
|
if minor < 68 {
|
||||||
if minor < 19 {
|
|
||||||
println!("cargo:rustc-cfg=no_core_reverse");
|
|
||||||
}
|
|
||||||
|
|
||||||
// CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20:
|
|
||||||
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
|
|
||||||
// https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path
|
|
||||||
if minor < 20 {
|
|
||||||
println!("cargo:rustc-cfg=no_de_boxed_c_str");
|
|
||||||
println!("cargo:rustc-cfg=no_de_boxed_path");
|
|
||||||
}
|
|
||||||
|
|
||||||
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
|
|
||||||
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
|
|
||||||
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
|
|
||||||
if minor < 21 {
|
|
||||||
println!("cargo:rustc-cfg=no_de_rc_dst");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duration available in core since Rust 1.25:
|
|
||||||
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
|
|
||||||
if minor < 25 {
|
|
||||||
println!("cargo:rustc-cfg=no_core_duration");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 128-bit integers stabilized in Rust 1.26:
|
|
||||||
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
|
|
||||||
//
|
|
||||||
// Disabled on Emscripten targets before Rust 1.40 since
|
|
||||||
// Emscripten did not support 128-bit integers until Rust 1.40
|
|
||||||
// (https://github.com/rust-lang/rust/pull/65251)
|
|
||||||
if minor < 26 || emscripten && minor < 40 {
|
|
||||||
println!("cargo:rustc-cfg=no_integer128");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inclusive ranges methods stabilized in Rust 1.27:
|
|
||||||
// https://github.com/rust-lang/rust/pull/50758
|
|
||||||
// Also Iterator::try_for_each:
|
|
||||||
// https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations
|
|
||||||
if minor < 27 {
|
|
||||||
println!("cargo:rustc-cfg=no_range_inclusive");
|
|
||||||
println!("cargo:rustc-cfg=no_iterator_try_fold");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-zero integers stabilized in Rust 1.28:
|
|
||||||
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
|
|
||||||
if minor < 28 {
|
|
||||||
println!("cargo:rustc-cfg=no_num_nonzero");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current minimum supported version of serde_derive crate is Rust 1.31.
|
|
||||||
if minor < 31 {
|
|
||||||
println!("cargo:rustc-cfg=no_serde_derive");
|
println!("cargo:rustc-cfg=no_serde_derive");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
|
// Support for the `#[diagnostic]` tool attribute namespace
|
||||||
// stabilized in Rust 1.34:
|
// https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes
|
||||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
|
if minor < 78 {
|
||||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
|
println!("cargo:rustc-cfg=no_diagnostic_namespace");
|
||||||
if minor < 34 {
|
|
||||||
println!("cargo:rustc-cfg=no_core_try_from");
|
|
||||||
println!("cargo:rustc-cfg=no_num_nonzero_signed");
|
|
||||||
println!("cargo:rustc-cfg=no_systemtime_checked_add");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whitelist of archs that support std::sync::atomic module. Ideally we
|
|
||||||
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
|
|
||||||
// Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs.
|
|
||||||
let has_atomic64 = target.starts_with("x86_64")
|
|
||||||
|| target.starts_with("i686")
|
|
||||||
|| target.starts_with("aarch64")
|
|
||||||
|| target.starts_with("powerpc64")
|
|
||||||
|| target.starts_with("sparc64")
|
|
||||||
|| target.starts_with("mips64el")
|
|
||||||
|| target.starts_with("riscv64");
|
|
||||||
let has_atomic32 = has_atomic64 || emscripten;
|
|
||||||
if minor < 34 || !has_atomic64 {
|
|
||||||
println!("cargo:rustc-cfg=no_std_atomic64");
|
|
||||||
}
|
|
||||||
if minor < 34 || !has_atomic32 {
|
|
||||||
println!("cargo:rustc-cfg=no_std_atomic");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustc_minor_version() -> Option<u32> {
|
fn rustc_minor_version() -> Option<u32> {
|
||||||
let rustc = match env::var_os("RUSTC") {
|
let rustc = env::var_os("RUSTC")?;
|
||||||
Some(rustc) => rustc,
|
let output = Command::new(rustc).arg("--version").output().ok()?;
|
||||||
None => return None,
|
let version = str::from_utf8(&output.stdout).ok()?;
|
||||||
};
|
|
||||||
|
|
||||||
let output = match Command::new(rustc).arg("--version").output() {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let version = match str::from_utf8(&output.stdout) {
|
|
||||||
Ok(version) => version,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pieces = version.split('.');
|
let mut pieces = version.split('.');
|
||||||
if pieces.next() != Some("rustc 1") {
|
if pieces.next() != Some("rustc 1") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
pieces.next()?.parse().ok()
|
||||||
let next = match pieces.next() {
|
|
||||||
Some(next) => next,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32::from_str(next).ok()
|
|
||||||
}
|
}
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../serde_core/src
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
use lib::*;
|
|
||||||
|
|
||||||
const TAG_CONT: u8 = 0b1000_0000;
|
|
||||||
const TAG_TWO_B: u8 = 0b1100_0000;
|
|
||||||
const TAG_THREE_B: u8 = 0b1110_0000;
|
|
||||||
const TAG_FOUR_B: u8 = 0b1111_0000;
|
|
||||||
const MAX_ONE_B: u32 = 0x80;
|
|
||||||
const MAX_TWO_B: u32 = 0x800;
|
|
||||||
const MAX_THREE_B: u32 = 0x10000;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn encode(c: char) -> Encode {
|
|
||||||
let code = c as u32;
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
let pos = if code < MAX_ONE_B {
|
|
||||||
buf[3] = code as u8;
|
|
||||||
3
|
|
||||||
} else if code < MAX_TWO_B {
|
|
||||||
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
2
|
|
||||||
} else if code < MAX_THREE_B {
|
|
||||||
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
|
|
||||||
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
|
|
||||||
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
0
|
|
||||||
};
|
|
||||||
Encode { buf: buf, pos: pos }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Encode {
|
|
||||||
buf: [u8; 4],
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encode {
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
str::from_utf8(&self.buf[self.pos..]).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-76
@@ -1,82 +1,14 @@
|
|||||||
/// Conditional compilation depending on whether Serde is built with support for
|
|
||||||
/// 128-bit integers.
|
|
||||||
///
|
|
||||||
/// Data formats that wish to support Rust compiler versions older than 1.26
|
|
||||||
/// (or targets that lack 128-bit integers) may place the i128 / u128 methods
|
|
||||||
/// of their Serializer and Deserializer behind this macro.
|
|
||||||
///
|
|
||||||
/// Data formats that require a minimum Rust compiler version of at least 1.26,
|
|
||||||
/// or do not target platforms that lack 128-bit integers, do not need to
|
|
||||||
/// bother with this macro and may assume support for 128-bit integers.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::__private::doc::Error;
|
|
||||||
/// #
|
|
||||||
/// # struct MySerializer;
|
|
||||||
/// #
|
|
||||||
/// use serde::{serde_if_integer128, Serializer};
|
|
||||||
///
|
|
||||||
/// impl Serializer for MySerializer {
|
|
||||||
/// type Ok = ();
|
|
||||||
/// type Error = Error;
|
|
||||||
///
|
|
||||||
/// fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
/// /* ... */
|
|
||||||
/// # unimplemented!()
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// /* ... */
|
|
||||||
///
|
|
||||||
/// serde_if_integer128! {
|
|
||||||
/// fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
|
||||||
/// /* ... */
|
|
||||||
/// # unimplemented!()
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
|
||||||
/// /* ... */
|
|
||||||
/// # unimplemented!()
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// #
|
|
||||||
/// # serde::__serialize_unimplemented! {
|
|
||||||
/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some
|
|
||||||
/// # unit unit_struct unit_variant newtype_struct newtype_variant seq
|
|
||||||
/// # tuple tuple_struct tuple_variant map struct struct_variant
|
|
||||||
/// # }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// When Serde is built with support for 128-bit integers, this macro expands
|
|
||||||
/// transparently into just the input tokens.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// macro_rules! serde_if_integer128 {
|
|
||||||
/// ($($tt:tt)*) => {
|
|
||||||
/// $($tt)*
|
|
||||||
/// };
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// When built without support for 128-bit integers, this macro expands to
|
|
||||||
/// nothing.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// macro_rules! serde_if_integer128 {
|
|
||||||
/// ($($tt:tt)*) => {};
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[cfg(not(no_integer128))]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[deprecated = "
|
||||||
|
This macro has no effect on any version of Serde released in the past 2 years.
|
||||||
|
It was used long ago in crates that needed to support Rustc older than 1.26.0,
|
||||||
|
or Emscripten targets older than 1.40.0, which did not yet have 128-bit integer
|
||||||
|
support. These days Serde requires a Rust compiler newer than that so 128-bit
|
||||||
|
integers are always supported.
|
||||||
|
"]
|
||||||
|
#[doc(hidden)]
|
||||||
macro_rules! serde_if_integer128 {
|
macro_rules! serde_if_integer128 {
|
||||||
($($tt:tt)*) => {
|
($($tt:tt)*) => {
|
||||||
$($tt)*
|
$($tt)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(no_integer128)]
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! serde_if_integer128 {
|
|
||||||
($($tt:tt)*) => {};
|
|
||||||
}
|
|
||||||
|
|||||||
+178
-194
@@ -9,7 +9,7 @@
|
|||||||
//! these two groups interact with each other, allowing any supported data
|
//! these two groups interact with each other, allowing any supported data
|
||||||
//! structure to be serialized and deserialized using any supported data format.
|
//! structure to be serialized and deserialized using any supported data format.
|
||||||
//!
|
//!
|
||||||
//! See the Serde website <https://serde.rs/> for additional documentation and
|
//! See the Serde website <https://serde.rs> for additional documentation and
|
||||||
//! usage examples.
|
//! usage examples.
|
||||||
//!
|
//!
|
||||||
//! ## Design
|
//! ## Design
|
||||||
@@ -31,8 +31,7 @@
|
|||||||
//! for Serde by the community.
|
//! for Serde by the community.
|
||||||
//!
|
//!
|
||||||
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
|
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
|
||||||
//! - [Bincode], a compact binary format
|
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
||||||
//! used for IPC within the Servo rendering engine.
|
|
||||||
//! - [CBOR], a Concise Binary Object Representation designed for small message
|
//! - [CBOR], a Concise Binary Object Representation designed for small message
|
||||||
//! size without the need for version negotiation.
|
//! size without the need for version negotiation.
|
||||||
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
|
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
|
||||||
@@ -45,8 +44,9 @@
|
|||||||
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
|
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
|
||||||
//! definition.
|
//! definition.
|
||||||
//! - [JSON5], a superset of JSON including some productions from ES5.
|
//! - [JSON5], a superset of JSON including some productions from ES5.
|
||||||
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
|
||||||
//! - [URL] query strings, in the x-www-form-urlencoded format.
|
//! - [URL] query strings, in the x-www-form-urlencoded format.
|
||||||
|
//! - [Starlark], the format used for describing build targets by the Bazel and
|
||||||
|
//! Buck build systems. *(serialization only)*
|
||||||
//! - [Envy], a way to deserialize environment variables into Rust structs.
|
//! - [Envy], a way to deserialize environment variables into Rust structs.
|
||||||
//! *(deserialization only)*
|
//! *(deserialization only)*
|
||||||
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
|
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
|
||||||
@@ -54,23 +54,30 @@
|
|||||||
//! - [S-expressions], the textual representation of code and data used by the
|
//! - [S-expressions], the textual representation of code and data used by the
|
||||||
//! Lisp language family.
|
//! Lisp language family.
|
||||||
//! - [D-Bus]'s binary wire format.
|
//! - [D-Bus]'s binary wire format.
|
||||||
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
|
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy
|
||||||
|
//! serialization format.
|
||||||
|
//! - [Bencode], a simple binary format used in the BitTorrent protocol.
|
||||||
|
//! - [Token streams], for processing Rust procedural macro input.
|
||||||
|
//! *(deserialization only)*
|
||||||
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
|
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
|
||||||
//! and from DynamoDB.
|
//! and from DynamoDB.
|
||||||
|
//! - [Hjson], a syntax extension to JSON designed around human reading and
|
||||||
|
//! editing. *(deserialization only)*
|
||||||
|
//! - [CSV], Comma-separated values is a tabular text file format.
|
||||||
//!
|
//!
|
||||||
//! [JSON]: https://github.com/serde-rs/json
|
//! [JSON]: https://github.com/serde-rs/json
|
||||||
//! [Bincode]: https://github.com/bincode-org/bincode
|
//! [Postcard]: https://github.com/jamesmunns/postcard
|
||||||
//! [CBOR]: https://github.com/enarx/ciborium
|
//! [CBOR]: https://github.com/enarx/ciborium
|
||||||
//! [YAML]: https://github.com/dtolnay/serde-yaml
|
//! [YAML]: https://github.com/dtolnay/serde-yaml
|
||||||
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
|
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
|
||||||
//! [TOML]: https://github.com/alexcrichton/toml-rs
|
//! [TOML]: https://docs.rs/toml
|
||||||
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
|
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
|
||||||
//! [RON]: https://github.com/ron-rs/ron
|
//! [RON]: https://github.com/ron-rs/ron
|
||||||
//! [BSON]: https://github.com/mongodb/bson-rust
|
//! [BSON]: https://github.com/mongodb/bson-rust
|
||||||
//! [Avro]: https://github.com/flavray/avro-rs
|
//! [Avro]: https://docs.rs/apache-avro
|
||||||
//! [JSON5]: https://github.com/callum-oakley/json5-rs
|
//! [JSON5]: https://github.com/callum-oakley/json5-rs
|
||||||
//! [Postcard]: https://github.com/jamesmunns/postcard
|
|
||||||
//! [URL]: https://docs.rs/serde_qs
|
//! [URL]: https://docs.rs/serde_qs
|
||||||
|
//! [Starlark]: https://github.com/dtolnay/serde-starlark
|
||||||
//! [Envy]: https://github.com/softprops/envy
|
//! [Envy]: https://github.com/softprops/envy
|
||||||
//! [Envy Store]: https://github.com/softprops/envy-store
|
//! [Envy Store]: https://github.com/softprops/envy-store
|
||||||
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
|
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -78,66 +85,81 @@
|
|||||||
//! [S-expressions]: https://github.com/rotty/lexpr-rs
|
//! [S-expressions]: https://github.com/rotty/lexpr-rs
|
||||||
//! [D-Bus]: https://docs.rs/zvariant
|
//! [D-Bus]: https://docs.rs/zvariant
|
||||||
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
|
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
|
||||||
|
//! [Bencode]: https://github.com/P3KI/bendy
|
||||||
|
//! [Token streams]: https://github.com/oxidecomputer/serde_tokenstream
|
||||||
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
|
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
|
||||||
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
|
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
|
||||||
|
//! [Hjson]: https://github.com/Canop/deser-hjson
|
||||||
|
//! [CSV]: https://docs.rs/csv
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.137")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.228")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))]
|
||||||
|
#![cfg_attr(docsrs, allow(internal_features))]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
// discussion of these features please refer to this issue:
|
// discussion of these features please refer to this issue:
|
||||||
//
|
//
|
||||||
// https://github.com/serde-rs/serde/issues/812
|
// https://github.com/serde-rs/serde/issues/812
|
||||||
#![cfg_attr(feature = "unstable", feature(never_type))]
|
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||||
#![allow(unknown_lints, bare_trait_objects, deprecated)]
|
#![allow(
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
unknown_lints,
|
||||||
// Ignored clippy and clippy_pedantic lints
|
bare_trait_objects,
|
||||||
#![cfg_attr(
|
deprecated,
|
||||||
feature = "cargo-clippy",
|
mismatched_lifetime_syntaxes
|
||||||
allow(
|
|
||||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
|
|
||||||
unnested_or_patterns,
|
|
||||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
|
|
||||||
semicolon_if_nothing_returned,
|
|
||||||
// not available in our oldest supported compiler
|
|
||||||
empty_enum,
|
|
||||||
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
|
|
||||||
// integer and float ser/de requires these sorts of casts
|
|
||||||
cast_possible_truncation,
|
|
||||||
cast_possible_wrap,
|
|
||||||
cast_sign_loss,
|
|
||||||
// things are often more readable this way
|
|
||||||
cast_lossless,
|
|
||||||
module_name_repetitions,
|
|
||||||
option_if_let_else,
|
|
||||||
single_match_else,
|
|
||||||
type_complexity,
|
|
||||||
use_self,
|
|
||||||
zero_prefixed_literal,
|
|
||||||
// correctly used
|
|
||||||
derive_partial_eq_without_eq,
|
|
||||||
enum_glob_use,
|
|
||||||
let_underscore_drop,
|
|
||||||
map_err_ignore,
|
|
||||||
result_unit_err,
|
|
||||||
wildcard_imports,
|
|
||||||
// not practical
|
|
||||||
needless_pass_by_value,
|
|
||||||
similar_names,
|
|
||||||
too_many_lines,
|
|
||||||
// preference
|
|
||||||
doc_markdown,
|
|
||||||
unseparated_literal_suffix,
|
|
||||||
// false positive
|
|
||||||
needless_doctest_main,
|
|
||||||
// noisy
|
|
||||||
missing_errors_doc,
|
|
||||||
must_use_candidate,
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
|
// Ignored clippy and clippy_pedantic lints
|
||||||
|
#![allow(
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
|
||||||
|
clippy::unnested_or_patterns,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
|
||||||
|
clippy::semicolon_if_nothing_returned,
|
||||||
|
// not available in our oldest supported compiler
|
||||||
|
clippy::empty_enums,
|
||||||
|
clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
|
||||||
|
// integer and float ser/de requires these sorts of casts
|
||||||
|
clippy::cast_possible_truncation,
|
||||||
|
clippy::cast_possible_wrap,
|
||||||
|
clippy::cast_precision_loss,
|
||||||
|
clippy::cast_sign_loss,
|
||||||
|
// things are often more readable this way
|
||||||
|
clippy::cast_lossless,
|
||||||
|
clippy::module_name_repetitions,
|
||||||
|
clippy::single_match_else,
|
||||||
|
clippy::type_complexity,
|
||||||
|
clippy::use_self,
|
||||||
|
clippy::zero_prefixed_literal,
|
||||||
|
// correctly used
|
||||||
|
clippy::derive_partial_eq_without_eq,
|
||||||
|
clippy::enum_glob_use,
|
||||||
|
clippy::explicit_auto_deref,
|
||||||
|
clippy::incompatible_msrv,
|
||||||
|
clippy::let_underscore_untyped,
|
||||||
|
clippy::map_err_ignore,
|
||||||
|
clippy::new_without_default,
|
||||||
|
clippy::result_unit_err,
|
||||||
|
clippy::wildcard_imports,
|
||||||
|
// not practical
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::similar_names,
|
||||||
|
clippy::too_many_lines,
|
||||||
|
// preference
|
||||||
|
clippy::doc_markdown,
|
||||||
|
clippy::elidable_lifetime_names,
|
||||||
|
clippy::needless_lifetimes,
|
||||||
|
clippy::unseparated_literal_suffix,
|
||||||
|
// false positive
|
||||||
|
clippy::needless_doctest_main,
|
||||||
|
// noisy
|
||||||
|
clippy::missing_errors_doc,
|
||||||
|
clippy::must_use_candidate,
|
||||||
|
)]
|
||||||
|
// Restrictions
|
||||||
|
#![deny(clippy::question_mark_used)]
|
||||||
// Rustc lints.
|
// Rustc lints.
|
||||||
#![deny(missing_docs, unused_imports)]
|
#![deny(missing_docs, unused_imports)]
|
||||||
|
|
||||||
@@ -146,156 +168,118 @@
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
/// A facade around all the types we need from the `std`, `core`, and `alloc`
|
// Rustdoc has a lot of shortcomings related to cross-crate re-exports that make
|
||||||
/// crates. This avoids elaborate import wrangling having to happen in every
|
// the rendered documentation of serde_core traits in serde more challenging to
|
||||||
/// module.
|
// understand than the equivalent documentation of the same items in serde_core.
|
||||||
mod lib {
|
// https://github.com/rust-lang/rust/labels/A-cross-crate-reexports
|
||||||
mod core {
|
// So, just for the purpose of docs.rs documentation, we inline the contents of
|
||||||
#[cfg(not(feature = "std"))]
|
// serde_core into serde. This sidesteps all the cross-crate rustdoc bugs.
|
||||||
pub use core::*;
|
#[cfg(docsrs)]
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
|
|
||||||
pub use self::core::{f32, f64};
|
|
||||||
pub use self::core::{i16, i32, i64, i8, isize};
|
|
||||||
pub use self::core::{u16, u32, u64, u8, usize};
|
|
||||||
|
|
||||||
pub use self::core::cell::{Cell, RefCell};
|
|
||||||
pub use self::core::clone::{self, Clone};
|
|
||||||
pub use self::core::convert::{self, From, Into};
|
|
||||||
pub use self::core::default::{self, Default};
|
|
||||||
pub use self::core::fmt::{self, Debug, Display};
|
|
||||||
pub use self::core::marker::{self, PhantomData};
|
|
||||||
pub use self::core::num::Wrapping;
|
|
||||||
pub use self::core::ops::Range;
|
|
||||||
pub use self::core::option::{self, Option};
|
|
||||||
pub use self::core::result::{self, Result};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::borrow::{Cow, ToOwned};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::borrow::{Cow, ToOwned};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::string::{String, ToString};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::string::{String, ToString};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::vec::Vec;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::vec::Vec;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::boxed::Box;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::boxed::Box;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::rc::{Rc, Weak as RcWeak};
|
|
||||||
#[cfg(all(feature = "rc", feature = "std"))]
|
|
||||||
pub use std::rc::{Rc, Weak as RcWeak};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::sync::{Arc, Weak as ArcWeak};
|
|
||||||
#[cfg(all(feature = "rc", feature = "std"))]
|
|
||||||
pub use std::sync::{Arc, Weak as ArcWeak};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::{error, net};
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::collections::{HashMap, HashSet};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::ffi::{CStr, CString, OsStr, OsString};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::hash::{BuildHasher, Hash};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::io::Write;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::path::{Path, PathBuf};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::sync::{Mutex, RwLock};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::time::{SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
|
|
||||||
pub use std::collections::Bound;
|
|
||||||
|
|
||||||
#[cfg(not(no_core_reverse))]
|
|
||||||
pub use self::core::cmp::Reverse;
|
|
||||||
|
|
||||||
#[cfg(not(no_ops_bound))]
|
|
||||||
pub use self::core::ops::Bound;
|
|
||||||
|
|
||||||
#[cfg(not(no_range_inclusive))]
|
|
||||||
pub use self::core::ops::RangeInclusive;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
|
||||||
pub use std::sync::atomic::{
|
|
||||||
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
|
|
||||||
AtomicUsize, Ordering,
|
|
||||||
};
|
|
||||||
#[cfg(all(feature = "std", not(no_std_atomic64)))]
|
|
||||||
pub use std::sync::atomic::{AtomicI64, AtomicU64};
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
|
||||||
pub use self::core::time::Duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
#[path = "core/crate_root.rs"]
|
||||||
|
mod crate_root;
|
||||||
|
|
||||||
|
#[cfg(docsrs)]
|
||||||
|
#[macro_use]
|
||||||
|
#[path = "core/macros.rs"]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
#[macro_use]
|
#[cfg(not(docsrs))]
|
||||||
|
macro_rules! crate_root {
|
||||||
|
() => {
|
||||||
|
/// A facade around all the types we need from the `std`, `core`, and `alloc`
|
||||||
|
/// crates. This avoids elaborate import wrangling having to happen in every
|
||||||
|
/// module.
|
||||||
|
mod lib {
|
||||||
|
mod core {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
pub use core::*;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::core::{f32, f64};
|
||||||
|
pub use self::core::{ptr, str};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
pub use self::core::slice;
|
||||||
|
|
||||||
|
pub use self::core::clone;
|
||||||
|
pub use self::core::convert;
|
||||||
|
pub use self::core::default;
|
||||||
|
pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite};
|
||||||
|
pub use self::core::marker::{self, PhantomData};
|
||||||
|
pub use self::core::option;
|
||||||
|
pub use self::core::result;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::borrow::{Cow, ToOwned};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::string::{String, ToString};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::string::{String, ToString};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::vec::Vec;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::vec::Vec;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::boxed::Box;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::boxed::Box;
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of this crate's error handling needs the `From::from` error conversion
|
||||||
|
// performed implicitly by the `?` operator or the standard library's `try!`
|
||||||
|
// macro. This simplified macro gives a 5.5% improvement in compile time
|
||||||
|
// compared to standard `try!`, and 9% improvement compared to `?`.
|
||||||
|
#[cfg(not(no_serde_derive))]
|
||||||
|
macro_rules! tri {
|
||||||
|
($expr:expr) => {
|
||||||
|
match $expr {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub use serde_core::{
|
||||||
|
de, forward_to_deserialize_any, ser, Deserialize, Deserializer, Serialize, Serializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by generated code and doc tests. Not public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod private;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/private.rs"));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
crate_root!();
|
||||||
|
|
||||||
mod integer128;
|
mod integer128;
|
||||||
|
|
||||||
pub mod de;
|
|
||||||
pub mod ser;
|
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use de::{Deserialize, Deserializer};
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use ser::{Serialize, Serializer};
|
|
||||||
|
|
||||||
// Used by generated code and doc tests. Not public API.
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[path = "private/mod.rs"]
|
|
||||||
pub mod __private;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use self::__private as export;
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use self::__private as private;
|
|
||||||
|
|
||||||
#[path = "de/seed.rs"]
|
|
||||||
mod seed;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
mod std_error;
|
|
||||||
|
|
||||||
// Re-export #[derive(Serialize, Deserialize)].
|
// Re-export #[derive(Serialize, Deserialize)].
|
||||||
//
|
//
|
||||||
// The reason re-exporting is not enabled by default is that disabling it would
|
// The reason re-exporting is not enabled by default is that disabling it would
|
||||||
// be annoying for crates that provide handwritten impls or data formats. They
|
// be annoying for crates that provide handwritten impls or data formats. They
|
||||||
// would need to disable default features and then explicitly re-enable std.
|
// would need to disable default features and then explicitly re-enable std.
|
||||||
#[cfg(feature = "serde_derive")]
|
#[cfg(feature = "serde_derive")]
|
||||||
#[allow(unused_imports)]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
#[cfg(feature = "serde_derive")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub use serde_derive::*;
|
|
||||||
|
|
||||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
/// Derive macro available if serde is built with `features = ["derive"]`.
|
||||||
mod actually_private {
|
#[cfg(feature = "serde_derive")]
|
||||||
pub struct T;
|
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
|
||||||
|
pub use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __require_serde_not_serde_core {
|
||||||
|
() => {};
|
||||||
}
|
}
|
||||||
|
|||||||
+1125
-608
File diff suppressed because it is too large
Load Diff
+10
-42
@@ -3,48 +3,16 @@ pub mod de;
|
|||||||
#[cfg(not(no_serde_derive))]
|
#[cfg(not(no_serde_derive))]
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
|
||||||
pub mod size_hint;
|
pub use crate::lib::clone::Clone;
|
||||||
|
pub use crate::lib::convert::{From, Into, TryFrom};
|
||||||
|
pub use crate::lib::default::Default;
|
||||||
|
pub use crate::lib::fmt::{self, Formatter};
|
||||||
|
pub use crate::lib::marker::PhantomData;
|
||||||
|
pub use crate::lib::option::Option::{self, None, Some};
|
||||||
|
pub use crate::lib::ptr;
|
||||||
|
pub use crate::lib::result::Result::{self, Err, Ok};
|
||||||
|
|
||||||
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
|
pub use crate::serde_core_private::string::from_utf8_lossy;
|
||||||
pub mod doc;
|
|
||||||
|
|
||||||
pub use lib::clone::Clone;
|
|
||||||
pub use lib::convert::{From, Into};
|
|
||||||
pub use lib::default::Default;
|
|
||||||
pub use lib::fmt::{self, Formatter};
|
|
||||||
pub use lib::marker::PhantomData;
|
|
||||||
pub use lib::option::Option::{self, None, Some};
|
|
||||||
pub use lib::ptr;
|
|
||||||
pub use lib::result::Result::{self, Err, Ok};
|
|
||||||
|
|
||||||
pub use self::string::from_utf8_lossy;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub use lib::{ToString, Vec};
|
pub use crate::lib::{ToString, Vec};
|
||||||
|
|
||||||
#[cfg(not(no_core_try_from))]
|
|
||||||
pub use lib::convert::TryFrom;
|
|
||||||
|
|
||||||
mod string {
|
|
||||||
use lib::*;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
|
|
||||||
String::from_utf8_lossy(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The generated code calls this like:
|
|
||||||
//
|
|
||||||
// let value = &_serde::__private::from_utf8_lossy(bytes);
|
|
||||||
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
|
|
||||||
//
|
|
||||||
// so it is okay for the return type to be different from the std case as long
|
|
||||||
// as the above works.
|
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
|
||||||
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
|
|
||||||
// Three unicode replacement characters if it fails. They look like a
|
|
||||||
// white-on-black question mark. The user will recognize it as invalid
|
|
||||||
// UTF-8.
|
|
||||||
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+240
-168
@@ -1,6 +1,6 @@
|
|||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use self::content::{
|
use self::content::{
|
||||||
@@ -27,10 +27,10 @@ where
|
|||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(TaggedSerializer {
|
value.serialize(TaggedSerializer {
|
||||||
type_ident: type_ident,
|
type_ident,
|
||||||
variant_ident: variant_ident,
|
variant_ident,
|
||||||
tag: tag,
|
tag,
|
||||||
variant_name: variant_name,
|
variant_name,
|
||||||
delegate: serializer,
|
delegate: serializer,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -51,15 +51,14 @@ enum Unsupported {
|
|||||||
String,
|
String,
|
||||||
ByteArray,
|
ByteArray,
|
||||||
Optional,
|
Optional,
|
||||||
Unit,
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
UnitStruct,
|
|
||||||
Sequence,
|
Sequence,
|
||||||
Tuple,
|
Tuple,
|
||||||
TupleStruct,
|
TupleStruct,
|
||||||
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
Enum,
|
Enum,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl Display for Unsupported {
|
impl Display for Unsupported {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
@@ -70,12 +69,10 @@ impl Display for Unsupported {
|
|||||||
Unsupported::String => formatter.write_str("a string"),
|
Unsupported::String => formatter.write_str("a string"),
|
||||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||||
Unsupported::Optional => formatter.write_str("an optional"),
|
Unsupported::Optional => formatter.write_str("an optional"),
|
||||||
Unsupported::Unit => formatter.write_str("unit"),
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
Unsupported::UnitStruct => formatter.write_str("unit struct"),
|
|
||||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||||
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
Unsupported::Enum => formatter.write_str("an enum"),
|
Unsupported::Enum => formatter.write_str("an enum"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,6 +90,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<S> Serializer for TaggedSerializer<S>
|
impl<S> Serializer for TaggedSerializer<S>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
@@ -176,20 +174,22 @@ where
|
|||||||
Err(self.bad_type(Unsupported::Optional))
|
Err(self.bad_type(Unsupported::Optional))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Err(self.bad_type(Unsupported::Optional))
|
Err(self.bad_type(Unsupported::Optional))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||||
Err(self.bad_type(Unsupported::Unit))
|
let mut map = tri!(self.delegate.serialize_map(Some(1)));
|
||||||
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
|
map.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||||
let mut map = try!(self.delegate.serialize_map(Some(1)));
|
let mut map = tri!(self.delegate.serialize_map(Some(1)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,24 +199,24 @@ where
|
|||||||
_: u32,
|
_: u32,
|
||||||
inner_variant: &'static str,
|
inner_variant: &'static str,
|
||||||
) -> Result<Self::Ok, Self::Error> {
|
) -> Result<Self::Ok, Self::Error> {
|
||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_entry(inner_variant, &()));
|
tri!(map.serialize_entry(inner_variant, &()));
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
fn serialize_newtype_struct<T>(
|
||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
value: &T,
|
value: &T,
|
||||||
) -> Result<Self::Ok, Self::Error>
|
) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
fn serialize_newtype_variant<T>(
|
||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
@@ -224,11 +224,11 @@ where
|
|||||||
inner_value: &T,
|
inner_value: &T,
|
||||||
) -> Result<Self::Ok, Self::Error>
|
) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_entry(inner_variant, inner_value));
|
tri!(map.serialize_entry(inner_variant, inner_value));
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,9 +269,9 @@ where
|
|||||||
inner_variant: &'static str,
|
inner_variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_key(inner_variant));
|
tri!(map.serialize_key(inner_variant));
|
||||||
Ok(SerializeTupleVariantAsMapValue::new(
|
Ok(SerializeTupleVariantAsMapValue::new(
|
||||||
map,
|
map,
|
||||||
inner_variant,
|
inner_variant,
|
||||||
@@ -280,8 +280,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||||
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,8 +290,8 @@ where
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||||
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
|
let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
|
||||||
try!(state.serialize_field(self.tag, self.variant_name));
|
tri!(state.serialize_field(self.tag, self.variant_name));
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,9 +316,9 @@ where
|
|||||||
inner_variant: &'static str,
|
inner_variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_key(inner_variant));
|
tri!(map.serialize_key(inner_variant));
|
||||||
Ok(SerializeStructVariantAsMapValue::new(
|
Ok(SerializeStructVariantAsMapValue::new(
|
||||||
map,
|
map,
|
||||||
inner_variant,
|
inner_variant,
|
||||||
@@ -327,9 +327,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
fn collect_str<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Display,
|
T: ?Sized + Display,
|
||||||
{
|
{
|
||||||
Err(self.bad_type(Unsupported::String))
|
Err(self.bad_type(Unsupported::String))
|
||||||
}
|
}
|
||||||
@@ -337,9 +337,9 @@ where
|
|||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
mod content {
|
mod content {
|
||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use ser::{self, Serialize, Serializer};
|
use crate::ser::{self, Serialize, Serializer};
|
||||||
|
|
||||||
pub struct SerializeTupleVariantAsMapValue<M> {
|
pub struct SerializeTupleVariantAsMapValue<M> {
|
||||||
map: M,
|
map: M,
|
||||||
@@ -350,13 +350,14 @@ mod content {
|
|||||||
impl<M> SerializeTupleVariantAsMapValue<M> {
|
impl<M> SerializeTupleVariantAsMapValue<M> {
|
||||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||||
SerializeTupleVariantAsMapValue {
|
SerializeTupleVariantAsMapValue {
|
||||||
map: map,
|
map,
|
||||||
name: name,
|
name,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
|
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
|
||||||
where
|
where
|
||||||
M: ser::SerializeMap,
|
M: ser::SerializeMap,
|
||||||
@@ -364,17 +365,17 @@ mod content {
|
|||||||
type Ok = M::Ok;
|
type Ok = M::Ok;
|
||||||
type Error = M::Error;
|
type Error = M::Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), M::Error>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), M::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||||
self.fields.push(value);
|
self.fields.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||||
try!(self
|
tri!(self
|
||||||
.map
|
.map
|
||||||
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
||||||
self.map.end()
|
self.map.end()
|
||||||
@@ -390,13 +391,14 @@ mod content {
|
|||||||
impl<M> SerializeStructVariantAsMapValue<M> {
|
impl<M> SerializeStructVariantAsMapValue<M> {
|
||||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||||
SerializeStructVariantAsMapValue {
|
SerializeStructVariantAsMapValue {
|
||||||
map: map,
|
map,
|
||||||
name: name,
|
name,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
|
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
|
||||||
where
|
where
|
||||||
M: ser::SerializeMap,
|
M: ser::SerializeMap,
|
||||||
@@ -404,21 +406,17 @@ mod content {
|
|||||||
type Ok = M::Ok;
|
type Ok = M::Ok;
|
||||||
type Error = M::Error;
|
type Error = M::Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), M::Error>
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), M::Error>
|
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||||
self.fields.push((key, value));
|
self.fields.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||||
try!(self
|
tri!(self
|
||||||
.map
|
.map
|
||||||
.serialize_value(&Content::Struct(self.name, self.fields)));
|
.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||||
self.map.end()
|
self.map.end()
|
||||||
@@ -468,6 +466,7 @@ mod content {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl Serialize for Content {
|
impl Serialize for Content {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -499,50 +498,50 @@ mod content {
|
|||||||
}
|
}
|
||||||
Content::Seq(ref elements) => elements.serialize(serializer),
|
Content::Seq(ref elements) => elements.serialize(serializer),
|
||||||
Content::Tuple(ref elements) => {
|
Content::Tuple(ref elements) => {
|
||||||
use ser::SerializeTuple;
|
use crate::ser::SerializeTuple;
|
||||||
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
|
let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
|
||||||
for e in elements {
|
for e in elements {
|
||||||
try!(tuple.serialize_element(e));
|
tri!(tuple.serialize_element(e));
|
||||||
}
|
}
|
||||||
tuple.end()
|
tuple.end()
|
||||||
}
|
}
|
||||||
Content::TupleStruct(n, ref fields) => {
|
Content::TupleStruct(n, ref fields) => {
|
||||||
use ser::SerializeTupleStruct;
|
use crate::ser::SerializeTupleStruct;
|
||||||
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
|
let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||||
for f in fields {
|
for f in fields {
|
||||||
try!(ts.serialize_field(f));
|
tri!(ts.serialize_field(f));
|
||||||
}
|
}
|
||||||
ts.end()
|
ts.end()
|
||||||
}
|
}
|
||||||
Content::TupleVariant(n, i, v, ref fields) => {
|
Content::TupleVariant(n, i, v, ref fields) => {
|
||||||
use ser::SerializeTupleVariant;
|
use crate::ser::SerializeTupleVariant;
|
||||||
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||||
for f in fields {
|
for f in fields {
|
||||||
try!(tv.serialize_field(f));
|
tri!(tv.serialize_field(f));
|
||||||
}
|
}
|
||||||
tv.end()
|
tv.end()
|
||||||
}
|
}
|
||||||
Content::Map(ref entries) => {
|
Content::Map(ref entries) => {
|
||||||
use ser::SerializeMap;
|
use crate::ser::SerializeMap;
|
||||||
let mut map = try!(serializer.serialize_map(Some(entries.len())));
|
let mut map = tri!(serializer.serialize_map(Some(entries.len())));
|
||||||
for &(ref k, ref v) in entries {
|
for (k, v) in entries {
|
||||||
try!(map.serialize_entry(k, v));
|
tri!(map.serialize_entry(k, v));
|
||||||
}
|
}
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
Content::Struct(n, ref fields) => {
|
Content::Struct(n, ref fields) => {
|
||||||
use ser::SerializeStruct;
|
use crate::ser::SerializeStruct;
|
||||||
let mut s = try!(serializer.serialize_struct(n, fields.len()));
|
let mut s = tri!(serializer.serialize_struct(n, fields.len()));
|
||||||
for &(k, ref v) in fields {
|
for &(k, ref v) in fields {
|
||||||
try!(s.serialize_field(k, v));
|
tri!(s.serialize_field(k, v));
|
||||||
}
|
}
|
||||||
s.end()
|
s.end()
|
||||||
}
|
}
|
||||||
Content::StructVariant(n, i, v, ref fields) => {
|
Content::StructVariant(n, i, v, ref fields) => {
|
||||||
use ser::SerializeStructVariant;
|
use crate::ser::SerializeStructVariant;
|
||||||
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||||
for &(k, ref v) in fields {
|
for &(k, ref v) in fields {
|
||||||
try!(sv.serialize_field(k, v));
|
tri!(sv.serialize_field(k, v));
|
||||||
}
|
}
|
||||||
sv.end()
|
sv.end()
|
||||||
}
|
}
|
||||||
@@ -560,6 +559,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> Serializer for ContentSerializer<E>
|
impl<E> Serializer for ContentSerializer<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -635,11 +635,11 @@ mod content {
|
|||||||
Ok(Content::None)
|
Ok(Content::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E>
|
fn serialize_some<T>(self, value: &T) -> Result<Content, E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
|
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<Content, E> {
|
fn serialize_unit(self) -> Result<Content, E> {
|
||||||
@@ -659,21 +659,17 @@ mod content {
|
|||||||
Ok(Content::UnitVariant(name, variant_index, variant))
|
Ok(Content::UnitVariant(name, variant_index, variant))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Content, E>
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<Content, E>
|
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Ok(Content::NewtypeStruct(
|
Ok(Content::NewtypeStruct(
|
||||||
name,
|
name,
|
||||||
Box::new(try!(value.serialize(self))),
|
Box::new(tri!(value.serialize(self))),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
fn serialize_newtype_variant<T>(
|
||||||
self,
|
self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
@@ -681,13 +677,13 @@ mod content {
|
|||||||
value: &T,
|
value: &T,
|
||||||
) -> Result<Content, E>
|
) -> Result<Content, E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Ok(Content::NewtypeVariant(
|
Ok(Content::NewtypeVariant(
|
||||||
name,
|
name,
|
||||||
variant_index,
|
variant_index,
|
||||||
variant,
|
variant,
|
||||||
Box::new(try!(value.serialize(self))),
|
Box::new(tri!(value.serialize(self))),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,7 +707,7 @@ mod content {
|
|||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleStruct, E> {
|
) -> Result<Self::SerializeTupleStruct, E> {
|
||||||
Ok(SerializeTupleStruct {
|
Ok(SerializeTupleStruct {
|
||||||
name: name,
|
name,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
error: PhantomData,
|
error: PhantomData,
|
||||||
})
|
})
|
||||||
@@ -725,9 +721,9 @@ mod content {
|
|||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant, E> {
|
) -> Result<Self::SerializeTupleVariant, E> {
|
||||||
Ok(SerializeTupleVariant {
|
Ok(SerializeTupleVariant {
|
||||||
name: name,
|
name,
|
||||||
variant_index: variant_index,
|
variant_index,
|
||||||
variant: variant,
|
variant,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
error: PhantomData,
|
error: PhantomData,
|
||||||
})
|
})
|
||||||
@@ -747,7 +743,7 @@ mod content {
|
|||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStruct, E> {
|
) -> Result<Self::SerializeStruct, E> {
|
||||||
Ok(SerializeStruct {
|
Ok(SerializeStruct {
|
||||||
name: name,
|
name,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
error: PhantomData,
|
error: PhantomData,
|
||||||
})
|
})
|
||||||
@@ -761,9 +757,9 @@ mod content {
|
|||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, E> {
|
) -> Result<Self::SerializeStructVariant, E> {
|
||||||
Ok(SerializeStructVariant {
|
Ok(SerializeStructVariant {
|
||||||
name: name,
|
name,
|
||||||
variant_index: variant_index,
|
variant_index,
|
||||||
variant: variant,
|
variant,
|
||||||
fields: Vec::with_capacity(len),
|
fields: Vec::with_capacity(len),
|
||||||
error: PhantomData,
|
error: PhantomData,
|
||||||
})
|
})
|
||||||
@@ -775,6 +771,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeSeq for SerializeSeq<E>
|
impl<E> ser::SerializeSeq for SerializeSeq<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -782,11 +779,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.elements.push(value);
|
self.elements.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -801,6 +798,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeTuple for SerializeTuple<E>
|
impl<E> ser::SerializeTuple for SerializeTuple<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -808,11 +806,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.elements.push(value);
|
self.elements.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -828,6 +826,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
|
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -835,11 +834,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.fields.push(value);
|
self.fields.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -857,6 +856,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
|
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -864,11 +864,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.fields.push(value);
|
self.fields.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -889,6 +889,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeMap for SerializeMap<E>
|
impl<E> ser::SerializeMap for SerializeMap<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -896,24 +897,24 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E>
|
fn serialize_key<T>(&mut self, key: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||||
self.key = Some(key);
|
self.key = Some(key);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
fn serialize_value<T>(&mut self, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let key = self
|
let key = self
|
||||||
.key
|
.key
|
||||||
.take()
|
.take()
|
||||||
.expect("serialize_value called before serialize_key");
|
.expect("serialize_value called before serialize_key");
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.entries.push((key, value));
|
self.entries.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -922,13 +923,13 @@ mod content {
|
|||||||
Ok(Content::Map(self.entries))
|
Ok(Content::Map(self.entries))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
|
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), E>
|
||||||
where
|
where
|
||||||
K: Serialize,
|
K: ?Sized + Serialize,
|
||||||
V: Serialize,
|
V: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.entries.push((key, value));
|
self.entries.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -940,6 +941,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeStruct for SerializeStruct<E>
|
impl<E> ser::SerializeStruct for SerializeStruct<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -947,11 +949,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.fields.push((key, value));
|
self.fields.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -969,6 +971,7 @@ mod content {
|
|||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
|
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
|
||||||
where
|
where
|
||||||
E: ser::Error,
|
E: ser::Error,
|
||||||
@@ -976,11 +979,11 @@ mod content {
|
|||||||
type Ok = Content;
|
type Ok = Content;
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||||
self.fields.push((key, value));
|
self.fields.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1013,6 +1016,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
||||||
where
|
where
|
||||||
M: SerializeMap + 'a,
|
M: SerializeMap + 'a,
|
||||||
@@ -1025,7 +1029,7 @@ where
|
|||||||
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
||||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
|
||||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
||||||
|
|
||||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||||
@@ -1088,9 +1092,9 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
@@ -1100,30 +1104,30 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||||
Err(Self::bad_type(Unsupported::UnitStruct))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
fn serialize_unit_variant(
|
||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
_: &'static str,
|
variant: &'static str,
|
||||||
) -> Result<Self::Ok, Self::Error> {
|
) -> Result<Self::Ok, Self::Error> {
|
||||||
Err(Self::bad_type(Unsupported::Enum))
|
self.0.serialize_entry(variant, &())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
fn serialize_newtype_struct<T>(
|
||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
value: &T,
|
value: &T,
|
||||||
) -> Result<Self::Ok, Self::Error>
|
) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
fn serialize_newtype_variant<T>(
|
||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
@@ -1131,10 +1135,9 @@ where
|
|||||||
value: &T,
|
value: &T,
|
||||||
) -> Result<Self::Ok, Self::Error>
|
) -> Result<Self::Ok, Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
try!(self.0.serialize_key(variant));
|
self.0.serialize_entry(variant, value)
|
||||||
self.0.serialize_value(value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||||
@@ -1157,10 +1160,11 @@ where
|
|||||||
self,
|
self,
|
||||||
_: &'static str,
|
_: &'static str,
|
||||||
_: u32,
|
_: u32,
|
||||||
_: &'static str,
|
variant: &'static str,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||||
Err(Self::bad_type(Unsupported::Enum))
|
tri!(self.0.serialize_key(variant));
|
||||||
|
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||||
@@ -1182,7 +1186,7 @@ where
|
|||||||
inner_variant: &'static str,
|
inner_variant: &'static str,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||||
try!(self.0.serialize_key(inner_variant));
|
tri!(self.0.serialize_key(inner_variant));
|
||||||
Ok(FlatMapSerializeStructVariantAsMapValue::new(
|
Ok(FlatMapSerializeStructVariantAsMapValue::new(
|
||||||
self.0,
|
self.0,
|
||||||
inner_variant,
|
inner_variant,
|
||||||
@@ -1194,6 +1198,7 @@ where
|
|||||||
pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M);
|
pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M>
|
impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M>
|
||||||
where
|
where
|
||||||
M: SerializeMap + 'a,
|
M: SerializeMap + 'a,
|
||||||
@@ -1201,28 +1206,24 @@ where
|
|||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = M::Error;
|
type Error = M::Error;
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
self.0.serialize_key(key)
|
self.0.serialize_key(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
self.0.serialize_value(value)
|
self.0.serialize_value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
|
||||||
&mut self,
|
|
||||||
key: &K,
|
|
||||||
value: &V,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
where
|
||||||
K: Serialize,
|
K: ?Sized + Serialize,
|
||||||
V: Serialize,
|
V: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
self.0.serialize_entry(key, value)
|
self.0.serialize_entry(key, value)
|
||||||
}
|
}
|
||||||
@@ -1236,6 +1237,7 @@ where
|
|||||||
pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M);
|
pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
|
impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
|
||||||
where
|
where
|
||||||
M: SerializeMap + 'a,
|
M: SerializeMap + 'a,
|
||||||
@@ -1243,13 +1245,9 @@ where
|
|||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = M::Error;
|
type Error = M::Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
self.0.serialize_entry(key, value)
|
self.0.serialize_entry(key, value)
|
||||||
}
|
}
|
||||||
@@ -1259,6 +1257,53 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
|
||||||
|
map: &'a mut M,
|
||||||
|
fields: Vec<Content>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M>
|
||||||
|
where
|
||||||
|
M: SerializeMap + 'a,
|
||||||
|
{
|
||||||
|
fn new(map: &'a mut M) -> Self {
|
||||||
|
FlatMapSerializeTupleVariantAsMapValue {
|
||||||
|
map,
|
||||||
|
fields: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
|
impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M>
|
||||||
|
where
|
||||||
|
M: SerializeMap + 'a,
|
||||||
|
{
|
||||||
|
type Ok = ();
|
||||||
|
type Error = M::Error;
|
||||||
|
|
||||||
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: ?Sized + Serialize,
|
||||||
|
{
|
||||||
|
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||||
|
self.fields.push(value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end(self) -> Result<(), Self::Error> {
|
||||||
|
tri!(self.map.serialize_value(&Content::Seq(self.fields)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
||||||
map: &'a mut M,
|
map: &'a mut M,
|
||||||
@@ -1273,14 +1318,15 @@ where
|
|||||||
{
|
{
|
||||||
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
|
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
|
||||||
FlatMapSerializeStructVariantAsMapValue {
|
FlatMapSerializeStructVariantAsMapValue {
|
||||||
map: map,
|
map,
|
||||||
name: name,
|
name,
|
||||||
fields: Vec::new(),
|
fields: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
|
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
|
||||||
where
|
where
|
||||||
M: SerializeMap + 'a,
|
M: SerializeMap + 'a,
|
||||||
@@ -1288,23 +1334,49 @@ where
|
|||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = M::Error;
|
type Error = M::Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||||
self.fields.push((key, value));
|
self.fields.push((key, value));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
fn end(self) -> Result<(), Self::Error> {
|
||||||
try!(self
|
tri!(self
|
||||||
.map
|
.map
|
||||||
.serialize_value(&Content::Struct(self.name, self.fields)));
|
.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AdjacentlyTaggedEnumVariant {
|
||||||
|
pub enum_name: &'static str,
|
||||||
|
pub variant_index: u32,
|
||||||
|
pub variant_name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
|
impl Serialize for AdjacentlyTaggedEnumVariant {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error when Serialize for a non_exhaustive remote enum encounters a variant
|
||||||
|
// that is not recognized.
|
||||||
|
pub struct CannotSerializeVariant<T>(pub T);
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
|
impl<T> Display for CannotSerializeVariant<T>
|
||||||
|
where
|
||||||
|
T: Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "enum variant cannot be serialized: {:?}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
use lib::*;
|
|
||||||
|
|
||||||
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
{
|
|
||||||
helper(iter.size_hint())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
#[inline]
|
|
||||||
pub fn cautious(hint: Option<usize>) -> usize {
|
|
||||||
cmp::min(hint.unwrap_or(0), 4096)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
|
|
||||||
match bounds {
|
|
||||||
(lower, Some(upper)) if lower == upper => Some(upper),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
[package]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||||
|
description = "Serde traits only, with no support for derive -- use the `serde` crate instead"
|
||||||
|
documentation = "https://docs.rs/serde_core"
|
||||||
|
edition = "2021"
|
||||||
|
homepage = "https://serde.rs"
|
||||||
|
keywords = ["serde", "serialization", "no_std"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
rust-version = "1.56"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde = { version = "1", path = "../serde" }
|
||||||
|
serde_derive = { version = "1", path = "../serde_derive" }
|
||||||
|
|
||||||
|
[package.metadata.playground]
|
||||||
|
features = ["rc", "result"]
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = ["rc", "result", "unstable"]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
rustdoc-args = [
|
||||||
|
"--generate-link-to-definition",
|
||||||
|
"--generate-macro-expansion",
|
||||||
|
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||||
|
]
|
||||||
|
|
||||||
|
# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's
|
||||||
|
# version in lockstep with serde's, even if someone depends on the two crates
|
||||||
|
# separately with serde's "derive" feature disabled. Every serde_derive release
|
||||||
|
# is compatible with exactly one serde release because the generated code
|
||||||
|
# involves nonpublic APIs which are not bound by semver.
|
||||||
|
[target.'cfg(any())'.dependencies]
|
||||||
|
serde_derive = { version = "=1.0.228", path = "../serde_derive" }
|
||||||
|
|
||||||
|
|
||||||
|
### FEATURES #################################################################
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std", "result"]
|
||||||
|
|
||||||
|
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
|
||||||
|
# Requires a dependency on the Rust standard library.
|
||||||
|
std = []
|
||||||
|
|
||||||
|
# Provide impls for types that require unstable functionality. For tracking and
|
||||||
|
# discussion of unstable functionality please refer to this issue:
|
||||||
|
#
|
||||||
|
# https://github.com/serde-rs/serde/issues/812
|
||||||
|
unstable = []
|
||||||
|
|
||||||
|
# Provide impls for types in the Rust core allocation and collections library
|
||||||
|
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
|
||||||
|
# be enabled without depending on all of std.
|
||||||
|
alloc = []
|
||||||
|
|
||||||
|
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
|
||||||
|
# does not preserve identity and may result in multiple copies of the same data.
|
||||||
|
# Be sure that this is what you want before enabling this feature.
|
||||||
|
rc = []
|
||||||
|
|
||||||
|
# Provide impls for Result<T, E>. Convenient in some contexts but can lead to
|
||||||
|
# confusion if ? or unwrap are used incautiously.
|
||||||
|
result = []
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
The `serde_core` crate contains Serde's trait definitions with **no support for
|
||||||
|
#\[derive()\]**.
|
||||||
|
|
||||||
|
In crates that derive an implementation of `Serialize` or `Deserialize`, you
|
||||||
|
must depend on the [`serde`] crate, not `serde_core`.
|
||||||
|
|
||||||
|
[`serde`]: https://crates.io/crates/serde
|
||||||
|
|
||||||
|
In crates that handwrite implementations of Serde traits, or only use them as
|
||||||
|
trait bounds, depending on `serde_core` is permitted. But `serde` re-exports all
|
||||||
|
of these traits and can be used for this use case too. If in doubt, disregard
|
||||||
|
`serde_core` and always use `serde`.
|
||||||
|
|
||||||
|
Crates that depend on `serde_core` instead of `serde` are able to compile in
|
||||||
|
parallel with `serde_derive` even when `serde`'s "derive" feature is turned on,
|
||||||
|
as shown in the following build timings.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
| When `serde_json` depends on `serde` |
|
||||||
|
|---|
|
||||||
|
| <img src="https://github.com/user-attachments/assets/78dc179c-6ab1-4059-928c-1474b0d9d0bb"> |
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
| When `serde_json` depends on `serde_core` |
|
||||||
|
|---|
|
||||||
|
| <img src="https://github.com/user-attachments/assets/6b6cff5e-3e45-4ac7-9db1-d99ee8b9f5f7"> |
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
const PRIVATE: &str = "\
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod __private$$ {
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::private::*;
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|
||||||
|
// The rustc-cfg strings below are *not* public API. Please let us know by
|
||||||
|
// opening a GitHub issue if your build environment requires some way to enable
|
||||||
|
// these cfgs other than by executing our build script.
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap();
|
||||||
|
let module = PRIVATE.replace("$$", &patch_version);
|
||||||
|
fs::write(out_dir.join("private.rs"), module).unwrap();
|
||||||
|
|
||||||
|
let minor = match rustc_minor_version() {
|
||||||
|
Some(minor) => minor,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if minor >= 77 {
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(if_docsrs_then_no_serde_core)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_core_cstr)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_core_error)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_core_net)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_serde_derive)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_std_atomic)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)");
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = env::var("TARGET").unwrap();
|
||||||
|
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
|
||||||
|
|
||||||
|
// Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60.
|
||||||
|
if minor < 60 {
|
||||||
|
println!("cargo:rustc-cfg=no_target_has_atomic");
|
||||||
|
// Allowlist of archs that support std::sync::atomic module. This is
|
||||||
|
// based on rustc's compiler/rustc_target/src/spec/*.rs.
|
||||||
|
let has_atomic64 = target.starts_with("x86_64")
|
||||||
|
|| target.starts_with("i686")
|
||||||
|
|| target.starts_with("aarch64")
|
||||||
|
|| target.starts_with("powerpc64")
|
||||||
|
|| target.starts_with("sparc64")
|
||||||
|
|| target.starts_with("mips64el")
|
||||||
|
|| target.starts_with("riscv64");
|
||||||
|
let has_atomic32 = has_atomic64 || emscripten;
|
||||||
|
if minor < 34 || !has_atomic64 {
|
||||||
|
println!("cargo:rustc-cfg=no_std_atomic64");
|
||||||
|
}
|
||||||
|
if minor < 34 || !has_atomic32 {
|
||||||
|
println!("cargo:rustc-cfg=no_std_atomic");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64.
|
||||||
|
// https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc
|
||||||
|
if minor < 64 {
|
||||||
|
println!("cargo:rustc-cfg=no_core_cstr");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current minimum supported version of serde_derive crate is Rust 1.68.
|
||||||
|
if minor < 68 {
|
||||||
|
println!("cargo:rustc-cfg=no_serde_derive");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74
|
||||||
|
// https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis
|
||||||
|
if minor < 74 {
|
||||||
|
println!("cargo:rustc-cfg=no_core_num_saturating");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for core::net stabilized in Rust 1.77.
|
||||||
|
// https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html
|
||||||
|
if minor < 77 {
|
||||||
|
println!("cargo:rustc-cfg=no_core_net");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for the `#[diagnostic]` tool attribute namespace
|
||||||
|
// https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes
|
||||||
|
if minor < 78 {
|
||||||
|
println!("cargo:rustc-cfg=no_diagnostic_namespace");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Error trait became available in core in 1.81.
|
||||||
|
// https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror
|
||||||
|
if minor < 81 {
|
||||||
|
println!("cargo:rustc-cfg=no_core_error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rustc_minor_version() -> Option<u32> {
|
||||||
|
let rustc = env::var_os("RUSTC")?;
|
||||||
|
let output = Command::new(rustc).arg("--version").output().ok()?;
|
||||||
|
let version = str::from_utf8(&output.stdout).ok()?;
|
||||||
|
let mut pieces = version.split('.');
|
||||||
|
if pieces.next() != Some("rustc 1") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
pieces.next()?.parse().ok()
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
macro_rules! crate_root {
|
||||||
|
() => {
|
||||||
|
/// A facade around all the types we need from the `std`, `core`, and `alloc`
|
||||||
|
/// crates. This avoids elaborate import wrangling having to happen in every
|
||||||
|
/// module.
|
||||||
|
mod lib {
|
||||||
|
mod core {
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
pub use core::*;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::core::{f32, f64};
|
||||||
|
pub use self::core::{iter, num, str};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
pub use self::core::{cmp, mem};
|
||||||
|
|
||||||
|
pub use self::core::cell::{Cell, RefCell};
|
||||||
|
pub use self::core::cmp::Reverse;
|
||||||
|
pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite};
|
||||||
|
pub use self::core::marker::PhantomData;
|
||||||
|
pub use self::core::num::Wrapping;
|
||||||
|
pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
|
||||||
|
pub use self::core::result;
|
||||||
|
pub use self::core::time::Duration;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::borrow::{Cow, ToOwned};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::string::{String, ToString};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::string::{String, ToString};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::vec::Vec;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::vec::Vec;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::boxed::Box;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::boxed::Box;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::rc::{Rc, Weak as RcWeak};
|
||||||
|
#[cfg(all(feature = "rc", feature = "std"))]
|
||||||
|
pub use std::rc::{Rc, Weak as RcWeak};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::sync::{Arc, Weak as ArcWeak};
|
||||||
|
#[cfg(all(feature = "rc", feature = "std"))]
|
||||||
|
pub use std::sync::{Arc, Weak as ArcWeak};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||||
|
|
||||||
|
#[cfg(all(not(no_core_cstr), not(feature = "std")))]
|
||||||
|
pub use self::core::ffi::CStr;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::ffi::CStr;
|
||||||
|
|
||||||
|
#[cfg(all(not(no_core_cstr), feature = "alloc", not(feature = "std")))]
|
||||||
|
pub use alloc::ffi::CString;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::ffi::CString;
|
||||||
|
|
||||||
|
#[cfg(all(not(no_core_net), not(feature = "std")))]
|
||||||
|
pub use self::core::net;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::net;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::error;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::collections::{HashMap, HashSet};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::ffi::{OsStr, OsString};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::hash::{BuildHasher, Hash};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::io::Write;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::path::{Path, PathBuf};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::sync::{Mutex, RwLock};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
|
||||||
|
pub use std::sync::atomic::{
|
||||||
|
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
|
||||||
|
AtomicU8, AtomicUsize, Ordering,
|
||||||
|
};
|
||||||
|
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))]
|
||||||
|
pub use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic)))]
|
||||||
|
pub use std::sync::atomic::Ordering;
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "8"))]
|
||||||
|
pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8};
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "16"))]
|
||||||
|
pub use std::sync::atomic::{AtomicI16, AtomicU16};
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "32"))]
|
||||||
|
pub use std::sync::atomic::{AtomicI32, AtomicU32};
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "64"))]
|
||||||
|
pub use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||||
|
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
|
||||||
|
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
|
||||||
|
|
||||||
|
#[cfg(not(no_core_num_saturating))]
|
||||||
|
pub use self::core::num::Saturating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of this crate's error handling needs the `From::from` error conversion
|
||||||
|
// performed implicitly by the `?` operator or the standard library's `try!`
|
||||||
|
// macro. This simplified macro gives a 5.5% improvement in compile time
|
||||||
|
// compared to standard `try!`, and 9% improvement compared to `?`.
|
||||||
|
macro_rules! tri {
|
||||||
|
($expr:expr) => {
|
||||||
|
match $expr {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/de/mod.rs")]
|
||||||
|
pub mod de;
|
||||||
|
#[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/ser/mod.rs")]
|
||||||
|
pub mod ser;
|
||||||
|
|
||||||
|
#[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/format.rs")]
|
||||||
|
mod format;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use crate::de::{Deserialize, Deserializer};
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use crate::ser::{Serialize, Serializer};
|
||||||
|
|
||||||
|
// Used by generated code. Not public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg_attr(
|
||||||
|
all(docsrs, if_docsrs_then_no_serde_core),
|
||||||
|
path = "core/private/mod.rs"
|
||||||
|
)]
|
||||||
|
mod private;
|
||||||
|
|
||||||
|
// Used by declarative macro generated code. Not public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod __private {
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::private::doc;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use core::result::Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/private.rs"));
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||||
|
#[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/std_error.rs")]
|
||||||
|
mod std_error;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use de::{
|
use crate::de::{
|
||||||
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
|
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -10,13 +10,12 @@ use de::{
|
|||||||
/// any type, except that it does not store any information about the data that
|
/// any type, except that it does not store any information about the data that
|
||||||
/// gets deserialized.
|
/// gets deserialized.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// use std::fmt;
|
|
||||||
/// use std::marker::PhantomData;
|
|
||||||
///
|
|
||||||
/// use serde::de::{
|
/// use serde::de::{
|
||||||
/// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
|
/// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
|
||||||
/// };
|
/// };
|
||||||
|
/// use std::fmt;
|
||||||
|
/// use std::marker::PhantomData;
|
||||||
///
|
///
|
||||||
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
|
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
|
||||||
/// /// while efficiently discarding elements of any type before or after index `n`.
|
/// /// while efficiently discarding elements of any type before or after index `n`.
|
||||||
@@ -108,7 +107,7 @@ use de::{
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||||
pub struct IgnoredAny;
|
pub struct IgnoredAny;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for IgnoredAny {
|
impl<'de> Visitor<'de> for IgnoredAny {
|
||||||
@@ -130,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
#[inline]
|
||||||
#[inline]
|
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
let _ = x;
|
||||||
let _ = x;
|
Ok(IgnoredAny)
|
||||||
Ok(IgnoredAny)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -144,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
#[inline]
|
||||||
#[inline]
|
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
let _ = x;
|
||||||
let _ = x;
|
Ok(IgnoredAny)
|
||||||
Ok(IgnoredAny)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -198,7 +193,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
where
|
where
|
||||||
A: SeqAccess<'de>,
|
A: SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
while let Some(IgnoredAny) = try!(seq.next_element()) {
|
while let Some(IgnoredAny) = tri!(seq.next_element()) {
|
||||||
// Gobble
|
// Gobble
|
||||||
}
|
}
|
||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
@@ -209,7 +204,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
where
|
where
|
||||||
A: MapAccess<'de>,
|
A: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
|
while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
|
||||||
// Gobble
|
// Gobble
|
||||||
}
|
}
|
||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
@@ -228,7 +223,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
where
|
where
|
||||||
A: EnumAccess<'de>,
|
A: EnumAccess<'de>,
|
||||||
{
|
{
|
||||||
data.variant::<IgnoredAny>()?.1.newtype_variant()
|
tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@
|
|||||||
//! # The Deserializer trait
|
//! # The Deserializer trait
|
||||||
//!
|
//!
|
||||||
//! [`Deserializer`] implementations are provided by third-party crates, for
|
//! [`Deserializer`] implementations are provided by third-party crates, for
|
||||||
//! example [`serde_json`], [`serde_yaml`] and [`bincode`].
|
//! example [`serde_json`], [`serde_yaml`] and [`postcard`].
|
||||||
//!
|
//!
|
||||||
//! A partial list of well-maintained formats is given on the [Serde
|
//! A partial list of well-maintained formats is given on the [Serde
|
||||||
//! website][data formats].
|
//! website][data formats].
|
||||||
@@ -64,8 +64,8 @@
|
|||||||
//! - RefCell\<T\>
|
//! - RefCell\<T\>
|
||||||
//! - Mutex\<T\>
|
//! - Mutex\<T\>
|
||||||
//! - RwLock\<T\>
|
//! - RwLock\<T\>
|
||||||
//! - Rc\<T\> *(if* features = ["rc"] *is enabled)*
|
//! - Rc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||||
//! - Arc\<T\> *(if* features = ["rc"] *is enabled)*
|
//! - Arc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||||
//! - **Collection types**:
|
//! - **Collection types**:
|
||||||
//! - BTreeMap\<K, V\>
|
//! - BTreeMap\<K, V\>
|
||||||
//! - BTreeSet\<T\>
|
//! - BTreeSet\<T\>
|
||||||
@@ -101,10 +101,10 @@
|
|||||||
//! - SocketAddrV6
|
//! - SocketAddrV6
|
||||||
//!
|
//!
|
||||||
//! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html
|
//! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html
|
||||||
//! [`Deserialize`]: ../trait.Deserialize.html
|
//! [`Deserialize`]: crate::Deserialize
|
||||||
//! [`Deserializer`]: ../trait.Deserializer.html
|
//! [`Deserializer`]: crate::Deserializer
|
||||||
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
||||||
//! [`bincode`]: https://github.com/bincode-org/bincode
|
//! [`postcard`]: https://github.com/jamesmunns/postcard
|
||||||
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
||||||
//! [`serde_derive`]: https://crates.io/crates/serde_derive
|
//! [`serde_derive`]: https://crates.io/crates/serde_derive
|
||||||
//! [`serde_json`]: https://github.com/serde-rs/json
|
//! [`serde_json`]: https://github.com/serde-rs/json
|
||||||
@@ -112,26 +112,25 @@
|
|||||||
//! [derive section of the manual]: https://serde.rs/derive.html
|
//! [derive section of the manual]: https://serde.rs/derive.html
|
||||||
//! [data formats]: https://serde.rs/#data-formats
|
//! [data formats]: https://serde.rs/#data-formats
|
||||||
|
|
||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
#[cfg(not(no_integer128))]
|
|
||||||
mod format;
|
|
||||||
mod ignored_any;
|
mod ignored_any;
|
||||||
mod impls;
|
mod impls;
|
||||||
mod utf8;
|
|
||||||
|
|
||||||
pub use self::ignored_any::IgnoredAny;
|
pub use self::ignored_any::IgnoredAny;
|
||||||
|
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||||
|
#[doc(no_inline)]
|
||||||
|
pub use crate::std_error::Error as StdError;
|
||||||
|
#[cfg(not(any(feature = "std", no_core_error)))]
|
||||||
|
#[doc(no_inline)]
|
||||||
|
pub use core::error::Error as StdError;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use std::error::Error as StdError;
|
pub use std::error::Error as StdError;
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
#[doc(no_inline)]
|
|
||||||
pub use std_error::Error as StdError;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -157,12 +156,18 @@ macro_rules! declare_error_trait {
|
|||||||
/// type appropriate for a basic JSON data format.
|
/// type appropriate for a basic JSON data format.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::Error` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait Error: Sized $(+ $($supertrait)::+)* {
|
pub trait Error: Sized $(+ $($supertrait)::+)* {
|
||||||
/// Raised when there is general error when deserializing a type.
|
/// Raised when there is general error when deserializing a type.
|
||||||
///
|
///
|
||||||
/// The message should not be capitalized and should not end with a period.
|
/// The message should not be capitalized and should not end with a period.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::str::FromStr;
|
/// # use std::str::FromStr;
|
||||||
/// #
|
/// #
|
||||||
/// # struct IpAddr;
|
/// # struct IpAddr;
|
||||||
@@ -205,7 +210,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// containing an integer, the unexpected type is the integer and the
|
/// containing an integer, the unexpected type is the integer and the
|
||||||
/// expected type is the string.
|
/// expected type is the string.
|
||||||
#[cold]
|
#[cold]
|
||||||
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_type(unexp: Unexpected, exp: &dyn Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +228,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
||||||
/// expected value is a string.
|
/// expected value is a string.
|
||||||
#[cold]
|
#[cold]
|
||||||
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_value(unexp: Unexpected, exp: &dyn Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +242,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// expected. For example `exp` might say that a tuple of size 6 was
|
/// expected. For example `exp` might say that a tuple of size 6 was
|
||||||
/// expected.
|
/// expected.
|
||||||
#[cold]
|
#[cold]
|
||||||
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
fn invalid_length(len: usize, exp: &dyn Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +312,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
|
|||||||
/// This is used as an argument to the `invalid_type`, `invalid_value`, and
|
/// This is used as an argument to the `invalid_type`, `invalid_value`, and
|
||||||
/// `invalid_length` methods of the `Error` trait to build error messages.
|
/// `invalid_length` methods of the `Error` trait to build error messages.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// #
|
/// #
|
||||||
/// # use serde::de::{self, Unexpected, Visitor};
|
/// # use serde::de::{self, Unexpected, Visitor};
|
||||||
@@ -400,20 +405,20 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
|||||||
Bool(b) => write!(formatter, "boolean `{}`", b),
|
Bool(b) => write!(formatter, "boolean `{}`", b),
|
||||||
Unsigned(i) => write!(formatter, "integer `{}`", i),
|
Unsigned(i) => write!(formatter, "integer `{}`", i),
|
||||||
Signed(i) => write!(formatter, "integer `{}`", i),
|
Signed(i) => write!(formatter, "integer `{}`", i),
|
||||||
Float(f) => write!(formatter, "floating point `{}`", f),
|
Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)),
|
||||||
Char(c) => write!(formatter, "character `{}`", c),
|
Char(c) => write!(formatter, "character `{}`", c),
|
||||||
Str(s) => write!(formatter, "string {:?}", s),
|
Str(s) => write!(formatter, "string {:?}", s),
|
||||||
Bytes(_) => write!(formatter, "byte array"),
|
Bytes(_) => formatter.write_str("byte array"),
|
||||||
Unit => write!(formatter, "unit value"),
|
Unit => formatter.write_str("unit value"),
|
||||||
Option => write!(formatter, "Option value"),
|
Option => formatter.write_str("Option value"),
|
||||||
NewtypeStruct => write!(formatter, "newtype struct"),
|
NewtypeStruct => formatter.write_str("newtype struct"),
|
||||||
Seq => write!(formatter, "sequence"),
|
Seq => formatter.write_str("sequence"),
|
||||||
Map => write!(formatter, "map"),
|
Map => formatter.write_str("map"),
|
||||||
Enum => write!(formatter, "enum"),
|
Enum => formatter.write_str("enum"),
|
||||||
UnitVariant => write!(formatter, "unit variant"),
|
UnitVariant => formatter.write_str("unit variant"),
|
||||||
NewtypeVariant => write!(formatter, "newtype variant"),
|
NewtypeVariant => formatter.write_str("newtype variant"),
|
||||||
TupleVariant => write!(formatter, "tuple variant"),
|
TupleVariant => formatter.write_str("tuple variant"),
|
||||||
StructVariant => write!(formatter, "struct variant"),
|
StructVariant => formatter.write_str("struct variant"),
|
||||||
Other(other) => formatter.write_str(other),
|
Other(other) => formatter.write_str(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,10 +437,9 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
|||||||
/// Within the context of a `Visitor` implementation, the `Visitor` itself
|
/// Within the context of a `Visitor` implementation, the `Visitor` itself
|
||||||
/// (`&self`) is an implementation of this trait.
|
/// (`&self`) is an implementation of this trait.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::fmt;
|
|
||||||
/// #
|
|
||||||
/// # use serde::de::{self, Unexpected, Visitor};
|
/// # use serde::de::{self, Unexpected, Visitor};
|
||||||
|
/// # use std::fmt;
|
||||||
/// #
|
/// #
|
||||||
/// # struct Example;
|
/// # struct Example;
|
||||||
/// #
|
/// #
|
||||||
@@ -457,7 +461,7 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
|||||||
///
|
///
|
||||||
/// Outside of a `Visitor`, `&"..."` can be used.
|
/// Outside of a `Visitor`, `&"..."` can be used.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{self, Unexpected};
|
/// # use serde::de::{self, Unexpected};
|
||||||
/// #
|
/// #
|
||||||
/// # fn example<E>() -> Result<(), E>
|
/// # fn example<E>() -> Result<(), E>
|
||||||
@@ -465,9 +469,18 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
|||||||
/// # E: de::Error,
|
/// # E: de::Error,
|
||||||
/// # {
|
/// # {
|
||||||
/// # let v = true;
|
/// # let v = true;
|
||||||
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
|
/// return Err(de::Error::invalid_type(
|
||||||
|
/// Unexpected::Bool(v),
|
||||||
|
/// &"a negative integer",
|
||||||
|
/// ));
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::Expected` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait Expected {
|
pub trait Expected {
|
||||||
/// Format an explanation of what data was being expected. Same signature as
|
/// Format an explanation of what data was being expected. Same signature as
|
||||||
/// the `Display` and `Debug` traits.
|
/// the `Display` and `Debug` traits.
|
||||||
@@ -483,13 +496,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Expected for &'a str {
|
impl Expected for &str {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.write_str(self)
|
formatter.write_str(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Display for Expected + 'a {
|
impl Display for dyn Expected + '_ {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
Expected::fmt(self, formatter)
|
Expected::fmt(self, formatter)
|
||||||
}
|
}
|
||||||
@@ -501,8 +514,8 @@ impl<'a> Display for Expected + 'a {
|
|||||||
/// by Serde.
|
/// by Serde.
|
||||||
///
|
///
|
||||||
/// Serde provides `Deserialize` implementations for many Rust primitive and
|
/// Serde provides `Deserialize` implementations for many Rust primitive and
|
||||||
/// standard library types. The complete list is [here][de]. All of these can
|
/// standard library types. The complete list is [here][crate::de]. All of these
|
||||||
/// be deserialized using Serde out of the box.
|
/// can be deserialized using Serde out of the box.
|
||||||
///
|
///
|
||||||
/// Additionally, Serde provides a procedural macro called `serde_derive` to
|
/// Additionally, Serde provides a procedural macro called `serde_derive` to
|
||||||
/// automatically generate `Deserialize` implementations for structs and enums
|
/// automatically generate `Deserialize` implementations for structs and enums
|
||||||
@@ -518,7 +531,6 @@ impl<'a> Display for Expected + 'a {
|
|||||||
/// `LinkedHashMap<K, V>` type that is deserializable by Serde because the crate
|
/// `LinkedHashMap<K, V>` type that is deserializable by Serde because the crate
|
||||||
/// provides an implementation of `Deserialize` for it.
|
/// provides an implementation of `Deserialize` for it.
|
||||||
///
|
///
|
||||||
/// [de]: https://docs.serde.rs/serde/de/index.html
|
|
||||||
/// [derive]: https://serde.rs/derive.html
|
/// [derive]: https://serde.rs/derive.html
|
||||||
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
|
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
|
||||||
///
|
///
|
||||||
@@ -529,6 +541,16 @@ impl<'a> Display for Expected + 'a {
|
|||||||
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
|
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
|
||||||
///
|
///
|
||||||
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
// Prevents `serde_core::de::Deserialize` appearing in the error message
|
||||||
|
// in projects with no direct dependency on serde_core.
|
||||||
|
message = "the trait bound `{Self}: serde::Deserialize<'de>` is not satisfied",
|
||||||
|
note = "for local types consider adding `#[derive(serde::Deserialize)]` to your `{Self}` type",
|
||||||
|
note = "for types from other crates check whether the crate offers a `serde` feature flag",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait Deserialize<'de>: Sized {
|
pub trait Deserialize<'de>: Sized {
|
||||||
/// Deserialize this value from the given Serde deserializer.
|
/// Deserialize this value from the given Serde deserializer.
|
||||||
///
|
///
|
||||||
@@ -565,7 +587,7 @@ pub trait Deserialize<'de>: Sized {
|
|||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
// Default implementation just delegates to `deserialize` impl.
|
// Default implementation just delegates to `deserialize` impl.
|
||||||
*place = Deserialize::deserialize(deserializer)?;
|
*place = tri!(Deserialize::deserialize(deserializer));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,7 +600,7 @@ pub trait Deserialize<'de>: Sized {
|
|||||||
/// from the input string, but a `from_reader` function may only deserialize
|
/// from the input string, but a `from_reader` function may only deserialize
|
||||||
/// owned data.
|
/// owned data.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{Deserialize, DeserializeOwned};
|
/// # use serde::de::{Deserialize, DeserializeOwned};
|
||||||
/// # use std::io::{Read, Result};
|
/// # use std::io::{Read, Result};
|
||||||
/// #
|
/// #
|
||||||
@@ -601,6 +623,12 @@ pub trait Deserialize<'de>: Sized {
|
|||||||
/// lifetimes].
|
/// lifetimes].
|
||||||
///
|
///
|
||||||
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::DeserializeOwned` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
|
pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
|
||||||
impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
||||||
|
|
||||||
@@ -617,7 +645,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
|||||||
///
|
///
|
||||||
/// The canonical API for stateless deserialization looks like this:
|
/// The canonical API for stateless deserialization looks like this:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::Deserialize;
|
/// # use serde::Deserialize;
|
||||||
/// #
|
/// #
|
||||||
/// # enum Error {}
|
/// # enum Error {}
|
||||||
@@ -631,7 +659,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
|||||||
/// Adjusting an API like this to support stateful deserialization is a matter
|
/// Adjusting an API like this to support stateful deserialization is a matter
|
||||||
/// of accepting a seed as input:
|
/// of accepting a seed as input:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::DeserializeSeed;
|
/// # use serde::de::DeserializeSeed;
|
||||||
/// #
|
/// #
|
||||||
/// # enum Error {}
|
/// # enum Error {}
|
||||||
@@ -664,12 +692,11 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
|||||||
/// into it. This requires stateful deserialization using the `DeserializeSeed`
|
/// into it. This requires stateful deserialization using the `DeserializeSeed`
|
||||||
/// trait.
|
/// trait.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
|
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
||||||
/// use std::fmt;
|
/// use std::fmt;
|
||||||
/// use std::marker::PhantomData;
|
/// use std::marker::PhantomData;
|
||||||
///
|
///
|
||||||
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
|
||||||
///
|
|
||||||
/// // A DeserializeSeed implementation that uses stateful deserialization to
|
/// // A DeserializeSeed implementation that uses stateful deserialization to
|
||||||
/// // append array elements onto the end of an existing vector. The preexisting
|
/// // append array elements onto the end of an existing vector. The preexisting
|
||||||
/// // state ("seed") in this case is the Vec<T>. The `deserialize` method of
|
/// // state ("seed") in this case is the Vec<T>. The `deserialize` method of
|
||||||
@@ -708,6 +735,11 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
|||||||
/// where
|
/// where
|
||||||
/// A: SeqAccess<'de>,
|
/// A: SeqAccess<'de>,
|
||||||
/// {
|
/// {
|
||||||
|
/// // Decrease the number of reallocations if there are many elements
|
||||||
|
/// if let Some(size_hint) = seq.size_hint() {
|
||||||
|
/// self.0.reserve(size_hint);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
/// // Visit each element in the inner array and push it onto
|
/// // Visit each element in the inner array and push it onto
|
||||||
/// // the existing vector.
|
/// // the existing vector.
|
||||||
/// while let Some(elem) = seq.next_element()? {
|
/// while let Some(elem) = seq.next_element()? {
|
||||||
@@ -762,6 +794,12 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::DeserializeSeed<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait DeserializeSeed<'de>: Sized {
|
pub trait DeserializeSeed<'de>: Sized {
|
||||||
/// The type produced by using this seed.
|
/// The type produced by using this seed.
|
||||||
type Value;
|
type Value;
|
||||||
@@ -857,10 +895,10 @@ where
|
|||||||
/// The `Deserializer` trait supports two entry point styles which enables
|
/// The `Deserializer` trait supports two entry point styles which enables
|
||||||
/// different kinds of deserialization.
|
/// different kinds of deserialization.
|
||||||
///
|
///
|
||||||
/// 1. The `deserialize` method. Self-describing data formats like JSON are able
|
/// 1. The `deserialize_any` method. Self-describing data formats like JSON are
|
||||||
/// to look at the serialized data and tell what it represents. For example
|
/// able to look at the serialized data and tell what it represents. For
|
||||||
/// the JSON deserializer may see an opening curly brace (`{`) and know that
|
/// example the JSON deserializer may see an opening curly brace (`{`) and
|
||||||
/// it is seeing a map. If the data format supports
|
/// know that it is seeing a map. If the data format supports
|
||||||
/// `Deserializer::deserialize_any`, it will drive the Visitor using whatever
|
/// `Deserializer::deserialize_any`, it will drive the Visitor using whatever
|
||||||
/// type it sees in the input. JSON uses this approach when deserializing
|
/// type it sees in the input. JSON uses this approach when deserializing
|
||||||
/// `serde_json::Value` which is an enum that can represent any JSON
|
/// `serde_json::Value` which is an enum that can represent any JSON
|
||||||
@@ -869,7 +907,7 @@ where
|
|||||||
/// `Deserializer::deserialize_any`.
|
/// `Deserializer::deserialize_any`.
|
||||||
///
|
///
|
||||||
/// 2. The various `deserialize_*` methods. Non-self-describing formats like
|
/// 2. The various `deserialize_*` methods. Non-self-describing formats like
|
||||||
/// Bincode need to be told what is in the input in order to deserialize it.
|
/// Postcard need to be told what is in the input in order to deserialize it.
|
||||||
/// The `deserialize_*` methods are hints to the deserializer for how to
|
/// The `deserialize_*` methods are hints to the deserializer for how to
|
||||||
/// interpret the next piece of input. Non-self-describing formats are not
|
/// interpret the next piece of input. Non-self-describing formats are not
|
||||||
/// able to deserialize something like `serde_json::Value` which relies on
|
/// able to deserialize something like `serde_json::Value` which relies on
|
||||||
@@ -879,7 +917,7 @@ where
|
|||||||
/// `Deserializer::deserialize_any` unless you need to be told by the
|
/// `Deserializer::deserialize_any` unless you need to be told by the
|
||||||
/// Deserializer what type is in the input. Know that relying on
|
/// Deserializer what type is in the input. Know that relying on
|
||||||
/// `Deserializer::deserialize_any` means your data type will be able to
|
/// `Deserializer::deserialize_any` means your data type will be able to
|
||||||
/// deserialize from self-describing formats only, ruling out Bincode and many
|
/// deserialize from self-describing formats only, ruling out Postcard and many
|
||||||
/// others.
|
/// others.
|
||||||
///
|
///
|
||||||
/// [Serde data model]: https://serde.rs/data-model.html
|
/// [Serde data model]: https://serde.rs/data-model.html
|
||||||
@@ -898,6 +936,12 @@ where
|
|||||||
/// a basic JSON `Deserializer`.
|
/// a basic JSON `Deserializer`.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::Deserializer<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait Deserializer<'de>: Sized {
|
pub trait Deserializer<'de>: Sized {
|
||||||
/// The error type that can be returned if some error occurs during
|
/// The error type that can be returned if some error occurs during
|
||||||
/// deserialization.
|
/// deserialization.
|
||||||
@@ -910,7 +954,7 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
/// `Deserializer::deserialize_any` unless you need to be told by the
|
/// `Deserializer::deserialize_any` unless you need to be told by the
|
||||||
/// Deserializer what type is in the input. Know that relying on
|
/// Deserializer what type is in the input. Know that relying on
|
||||||
/// `Deserializer::deserialize_any` means your data type will be able to
|
/// `Deserializer::deserialize_any` means your data type will be able to
|
||||||
/// deserialize from self-describing formats only, ruling out Bincode and
|
/// deserialize from self-describing formats only, ruling out Postcard and
|
||||||
/// many others.
|
/// many others.
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
@@ -941,18 +985,15 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>;
|
V: Visitor<'de>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
/// default behavior unconditionally returns an error.
|
where
|
||||||
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
V: Visitor<'de>,
|
||||||
where
|
{
|
||||||
V: Visitor<'de>
|
let _ = visitor;
|
||||||
{
|
Err(Error::custom("i128 is not supported"))
|
||||||
let _ = visitor;
|
|
||||||
Err(Error::custom("i128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||||
@@ -975,18 +1016,15 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>;
|
V: Visitor<'de>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
/// default behavior unconditionally returns an error.
|
where
|
||||||
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
V: Visitor<'de>,
|
||||||
where
|
{
|
||||||
V: Visitor<'de>
|
let _ = visitor;
|
||||||
{
|
Err(Error::custom("u128 is not supported"))
|
||||||
let _ = visitor;
|
|
||||||
Err(Error::custom("u128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||||
@@ -1151,10 +1189,10 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
/// Some types have a human-readable form that may be somewhat expensive to
|
/// Some types have a human-readable form that may be somewhat expensive to
|
||||||
/// construct, as well as a binary form that is compact and efficient.
|
/// construct, as well as a binary form that is compact and efficient.
|
||||||
/// Generally text-based formats like JSON and YAML will prefer to use the
|
/// Generally text-based formats like JSON and YAML will prefer to use the
|
||||||
/// human-readable one and binary formats like Bincode will prefer the
|
/// human-readable one and binary formats like Postcard will prefer the
|
||||||
/// compact one.
|
/// compact one.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::ops::Add;
|
/// # use std::ops::Add;
|
||||||
/// # use std::str::FromStr;
|
/// # use std::str::FromStr;
|
||||||
/// #
|
/// #
|
||||||
@@ -1219,13 +1257,9 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
// Not public API.
|
// Not public API.
|
||||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn __deserialize_content<V>(
|
fn __deserialize_content_v1<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
self,
|
|
||||||
_: ::actually_private::T,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<::private::de::Content<'de>, Self::Error>
|
|
||||||
where
|
where
|
||||||
V: Visitor<'de, Value = ::private::de::Content<'de>>,
|
V: Visitor<'de, Value = crate::private::Content<'de>>,
|
||||||
{
|
{
|
||||||
self.deserialize_any(visitor)
|
self.deserialize_any(visitor)
|
||||||
}
|
}
|
||||||
@@ -1245,10 +1279,9 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::fmt;
|
|
||||||
/// #
|
|
||||||
/// # use serde::de::{self, Unexpected, Visitor};
|
/// # use serde::de::{self, Unexpected, Visitor};
|
||||||
|
/// # use std::fmt;
|
||||||
/// #
|
/// #
|
||||||
/// /// A visitor that deserializes a long string - a string containing at least
|
/// /// A visitor that deserializes a long string - a string containing at least
|
||||||
/// /// some minimum number of bytes.
|
/// /// some minimum number of bytes.
|
||||||
@@ -1275,6 +1308,12 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::Visitor<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait Visitor<'de>: Sized {
|
pub trait Visitor<'de>: Sized {
|
||||||
/// The value produced by this visitor.
|
/// The value produced by this visitor.
|
||||||
type Value;
|
type Value;
|
||||||
@@ -1286,7 +1325,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// "an integer between 0 and 64". The message should not be capitalized and
|
/// "an integer between 0 and 64". The message should not be capitalized and
|
||||||
/// should not end with a period.
|
/// should not end with a period.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// #
|
/// #
|
||||||
/// # struct S {
|
/// # struct S {
|
||||||
@@ -1359,20 +1398,20 @@ pub trait Visitor<'de>: Sized {
|
|||||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// The input contains a `i128`.
|
||||||
/// The input contains a `i128`.
|
///
|
||||||
///
|
/// The default implementation fails with a type error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||||
/// default implementation fails with a type error.
|
where
|
||||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
E: Error,
|
||||||
where
|
{
|
||||||
E: Error,
|
let mut buf = [0u8; 58];
|
||||||
{
|
let mut writer = crate::format::Buf::new(&mut buf);
|
||||||
let mut buf = [0u8; 58];
|
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
||||||
let mut writer = format::Buf::new(&mut buf);
|
Err(Error::invalid_type(
|
||||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
Unexpected::Other(writer.as_str()),
|
||||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
&self,
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The input contains a `u8`.
|
/// The input contains a `u8`.
|
||||||
@@ -1421,20 +1460,20 @@ pub trait Visitor<'de>: Sized {
|
|||||||
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// The input contains a `u128`.
|
||||||
/// The input contains a `u128`.
|
///
|
||||||
///
|
/// The default implementation fails with a type error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||||
/// default implementation fails with a type error.
|
where
|
||||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
E: Error,
|
||||||
where
|
{
|
||||||
E: Error,
|
let mut buf = [0u8; 57];
|
||||||
{
|
let mut writer = crate::format::Buf::new(&mut buf);
|
||||||
let mut buf = [0u8; 57];
|
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
||||||
let mut writer = format::Buf::new(&mut buf);
|
Err(Error::invalid_type(
|
||||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
Unexpected::Other(writer.as_str()),
|
||||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
&self,
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The input contains an `f32`.
|
/// The input contains an `f32`.
|
||||||
@@ -1470,7 +1509,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
self.visit_str(utf8::encode(v).as_str())
|
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The input contains a string. The lifetime of the string is ephemeral and
|
/// The input contains a string. The lifetime of the string is ephemeral and
|
||||||
@@ -1525,6 +1564,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// `String`.
|
/// `String`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -1547,7 +1587,6 @@ pub trait Visitor<'de>: Sized {
|
|||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
let _ = v;
|
|
||||||
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1555,7 +1594,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// `Deserializer`.
|
/// `Deserializer`.
|
||||||
///
|
///
|
||||||
/// This enables zero-copy deserialization of bytes in some formats. For
|
/// This enables zero-copy deserialization of bytes in some formats. For
|
||||||
/// example Bincode data containing bytes can be deserialized with zero
|
/// example Postcard data containing bytes can be deserialized with zero
|
||||||
/// copying into a `&'a [u8]` as long as the input data outlives `'a`.
|
/// copying into a `&'a [u8]` as long as the input data outlives `'a`.
|
||||||
///
|
///
|
||||||
/// The default implementation forwards to `visit_bytes`.
|
/// The default implementation forwards to `visit_bytes`.
|
||||||
@@ -1584,6 +1623,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// The default implementation forwards to `visit_bytes` and then drops the
|
/// The default implementation forwards to `visit_bytes` and then drops the
|
||||||
/// `Vec<u8>`.
|
/// `Vec<u8>`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -1700,6 +1740,12 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// implementation of `SeqAccess` for a basic JSON data format.
|
/// implementation of `SeqAccess` for a basic JSON data format.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::SeqAccess<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait SeqAccess<'de> {
|
pub trait SeqAccess<'de> {
|
||||||
/// The error type that can be returned if some error occurs during
|
/// The error type that can be returned if some error occurs during
|
||||||
/// deserialization.
|
/// deserialization.
|
||||||
@@ -1734,9 +1780,9 @@ pub trait SeqAccess<'de> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
|
impl<'de, A> SeqAccess<'de> for &mut A
|
||||||
where
|
where
|
||||||
A: SeqAccess<'de>,
|
A: ?Sized + SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
type Error = A::Error;
|
type Error = A::Error;
|
||||||
|
|
||||||
@@ -1782,6 +1828,12 @@ where
|
|||||||
/// implementation of `MapAccess` for a basic JSON data format.
|
/// implementation of `MapAccess` for a basic JSON data format.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::MapAccess<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait MapAccess<'de> {
|
pub trait MapAccess<'de> {
|
||||||
/// The error type that can be returned if some error occurs during
|
/// The error type that can be returned if some error occurs during
|
||||||
/// deserialization.
|
/// deserialization.
|
||||||
@@ -1827,9 +1879,9 @@ pub trait MapAccess<'de> {
|
|||||||
K: DeserializeSeed<'de>,
|
K: DeserializeSeed<'de>,
|
||||||
V: DeserializeSeed<'de>,
|
V: DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match try!(self.next_key_seed(kseed)) {
|
match tri!(self.next_key_seed(kseed)) {
|
||||||
Some(key) => {
|
Some(key) => {
|
||||||
let value = try!(self.next_value_seed(vseed));
|
let value = tri!(self.next_value_seed(vseed));
|
||||||
Ok(Some((key, value)))
|
Ok(Some((key, value)))
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
@@ -1887,9 +1939,9 @@ pub trait MapAccess<'de> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
|
impl<'de, A> MapAccess<'de> for &mut A
|
||||||
where
|
where
|
||||||
A: MapAccess<'de>,
|
A: ?Sized + MapAccess<'de>,
|
||||||
{
|
{
|
||||||
type Error = A::Error;
|
type Error = A::Error;
|
||||||
|
|
||||||
@@ -1974,6 +2026,12 @@ where
|
|||||||
/// implementation of `EnumAccess` for a basic JSON data format.
|
/// implementation of `EnumAccess` for a basic JSON data format.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::EnumAccess<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait EnumAccess<'de>: Sized {
|
pub trait EnumAccess<'de>: Sized {
|
||||||
/// The error type that can be returned if some error occurs during
|
/// The error type that can be returned if some error occurs during
|
||||||
/// deserialization.
|
/// deserialization.
|
||||||
@@ -2021,6 +2079,12 @@ pub trait EnumAccess<'de>: Sized {
|
|||||||
/// implementation of `VariantAccess` for a basic JSON data format.
|
/// implementation of `VariantAccess` for a basic JSON data format.
|
||||||
///
|
///
|
||||||
/// [example data format]: https://serde.rs/data-format.html
|
/// [example data format]: https://serde.rs/data-format.html
|
||||||
|
#[cfg_attr(
|
||||||
|
not(no_diagnostic_namespace),
|
||||||
|
diagnostic::on_unimplemented(
|
||||||
|
message = "the trait bound `{Self}: serde::de::VariantAccess<'de>` is not satisfied",
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub trait VariantAccess<'de>: Sized {
|
pub trait VariantAccess<'de>: Sized {
|
||||||
/// The error type that can be returned if some error occurs during
|
/// The error type that can be returned if some error occurs during
|
||||||
/// deserialization. Must match the error type of our `EnumAccess`.
|
/// deserialization. Must match the error type of our `EnumAccess`.
|
||||||
@@ -2031,7 +2095,7 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
/// If the data contains a different type of variant, the following
|
/// If the data contains a different type of variant, the following
|
||||||
/// `invalid_type` error should be constructed:
|
/// `invalid_type` error should be constructed:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||||
/// #
|
/// #
|
||||||
/// # struct X;
|
/// # struct X;
|
||||||
@@ -2071,7 +2135,7 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
/// If the data contains a different type of variant, the following
|
/// If the data contains a different type of variant, the following
|
||||||
/// `invalid_type` error should be constructed:
|
/// `invalid_type` error should be constructed:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||||
/// #
|
/// #
|
||||||
/// # struct X;
|
/// # struct X;
|
||||||
@@ -2127,7 +2191,7 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
/// If the data contains a different type of variant, the following
|
/// If the data contains a different type of variant, the following
|
||||||
/// `invalid_type` error should be constructed:
|
/// `invalid_type` error should be constructed:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||||
/// #
|
/// #
|
||||||
/// # struct X;
|
/// # struct X;
|
||||||
@@ -2144,11 +2208,7 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
/// # T: DeserializeSeed<'de>,
|
/// # T: DeserializeSeed<'de>,
|
||||||
/// # { unimplemented!() }
|
/// # { unimplemented!() }
|
||||||
/// #
|
/// #
|
||||||
/// fn tuple_variant<V>(
|
/// fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||||
/// self,
|
|
||||||
/// _len: usize,
|
|
||||||
/// _visitor: V,
|
|
||||||
/// ) -> Result<V::Value, Self::Error>
|
|
||||||
/// where
|
/// where
|
||||||
/// V: Visitor<'de>,
|
/// V: Visitor<'de>,
|
||||||
/// {
|
/// {
|
||||||
@@ -2174,7 +2234,7 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
/// If the data contains a different type of variant, the following
|
/// If the data contains a different type of variant, the following
|
||||||
/// `invalid_type` error should be constructed:
|
/// `invalid_type` error should be constructed:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||||
/// #
|
/// #
|
||||||
/// # struct X;
|
/// # struct X;
|
||||||
@@ -2234,10 +2294,10 @@ pub trait VariantAccess<'de>: Sized {
|
|||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
|
/// use serde::de::{value, Deserialize, IntoDeserializer};
|
||||||
|
/// use serde_derive::Deserialize;
|
||||||
/// use std::str::FromStr;
|
/// use std::str::FromStr;
|
||||||
/// use serde::Deserialize;
|
|
||||||
/// use serde::de::{value, IntoDeserializer};
|
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// enum Setting {
|
/// enum Setting {
|
||||||
@@ -2281,15 +2341,52 @@ impl Display for OneOf {
|
|||||||
1 => write!(formatter, "`{}`", self.names[0]),
|
1 => write!(formatter, "`{}`", self.names[0]),
|
||||||
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
|
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
|
||||||
_ => {
|
_ => {
|
||||||
try!(write!(formatter, "one of "));
|
tri!(formatter.write_str("one of "));
|
||||||
for (i, alt) in self.names.iter().enumerate() {
|
for (i, alt) in self.names.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
try!(write!(formatter, ", "));
|
tri!(formatter.write_str(", "));
|
||||||
}
|
}
|
||||||
try!(write!(formatter, "`{}`", alt));
|
tri!(write!(formatter, "`{}`", alt));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WithDecimalPoint(f64);
|
||||||
|
|
||||||
|
impl Display for WithDecimalPoint {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
struct LookForDecimalPoint<'f, 'a> {
|
||||||
|
formatter: &'f mut fmt::Formatter<'a>,
|
||||||
|
has_decimal_point: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> {
|
||||||
|
fn write_str(&mut self, fragment: &str) -> fmt::Result {
|
||||||
|
self.has_decimal_point |= fragment.contains('.');
|
||||||
|
self.formatter.write_str(fragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_char(&mut self, ch: char) -> fmt::Result {
|
||||||
|
self.has_decimal_point |= ch == '.';
|
||||||
|
self.formatter.write_char(ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.0.is_finite() {
|
||||||
|
let mut writer = LookForDecimalPoint {
|
||||||
|
formatter,
|
||||||
|
has_decimal_point: false,
|
||||||
|
};
|
||||||
|
tri!(write!(writer, "{}", self.0));
|
||||||
|
if !writer.has_decimal_point {
|
||||||
|
tri!(formatter.write_str(".0"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tri!(write!(formatter, "{}", self.0));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
//! Building blocks for deserializing basic values using the `IntoDeserializer`
|
//! Building blocks for deserializing basic values using the `IntoDeserializer`
|
||||||
//! trait.
|
//! trait.
|
||||||
//!
|
//!
|
||||||
//! ```edition2018
|
//! ```edition2021
|
||||||
|
//! use serde::de::{value, Deserialize, IntoDeserializer};
|
||||||
|
//! use serde_derive::Deserialize;
|
||||||
//! use std::str::FromStr;
|
//! use std::str::FromStr;
|
||||||
//! use serde::Deserialize;
|
|
||||||
//! use serde::de::{value, IntoDeserializer};
|
|
||||||
//!
|
//!
|
||||||
//! #[derive(Deserialize)]
|
//! #[derive(Deserialize)]
|
||||||
//! enum Setting {
|
//! enum Setting {
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use self::private::{First, Second};
|
use self::private::{First, Second};
|
||||||
use __private::size_hint;
|
use crate::de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||||
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
use crate::private::size_hint;
|
||||||
use ser;
|
use crate::ser;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -113,6 +113,7 @@ impl Debug for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
&self.err
|
&self.err
|
||||||
@@ -128,9 +129,7 @@ where
|
|||||||
type Deserializer = UnitDeserializer<E>;
|
type Deserializer = UnitDeserializer<E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> UnitDeserializer<E> {
|
fn into_deserializer(self) -> UnitDeserializer<E> {
|
||||||
UnitDeserializer {
|
UnitDeserializer::new()
|
||||||
marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +140,15 @@ pub struct UnitDeserializer<E> {
|
|||||||
|
|
||||||
impl_copy_clone!(UnitDeserializer);
|
impl_copy_clone!(UnitDeserializer);
|
||||||
|
|
||||||
|
impl<E> UnitDeserializer<E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
UnitDeserializer {
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
|
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -168,6 +176,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for UnitDeserializer<E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E> Debug for UnitDeserializer<E> {
|
impl<E> Debug for UnitDeserializer<E> {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.debug_struct("UnitDeserializer").finish()
|
formatter.debug_struct("UnitDeserializer").finish()
|
||||||
@@ -178,12 +197,14 @@ impl<E> Debug for UnitDeserializer<E> {
|
|||||||
|
|
||||||
/// A deserializer that cannot be instantiated.
|
/// A deserializer that cannot be instantiated.
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||||
pub struct NeverDeserializer<E> {
|
pub struct NeverDeserializer<E> {
|
||||||
never: !,
|
never: !,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||||
impl<'de, E> IntoDeserializer<'de, E> for !
|
impl<'de, E> IntoDeserializer<'de, E> for !
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -216,6 +237,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for NeverDeserializer<E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! primitive_deserializer {
|
macro_rules! primitive_deserializer {
|
||||||
@@ -236,8 +269,15 @@ macro_rules! primitive_deserializer {
|
|||||||
type Deserializer = $name<E>;
|
type Deserializer = $name<E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> $name<E> {
|
fn into_deserializer(self) -> $name<E> {
|
||||||
|
$name::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> $name<E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new(value: $ty) -> Self {
|
||||||
$name {
|
$name {
|
||||||
value: self,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,6 +303,17 @@ macro_rules! primitive_deserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for $name<E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E> Debug for $name<E> {
|
impl<E> Debug for $name<E> {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter
|
formatter
|
||||||
@@ -279,20 +330,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8);
|
|||||||
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
|
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
|
||||||
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
||||||
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
|
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
|
||||||
|
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
|
||||||
primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
|
primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
|
||||||
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
||||||
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
||||||
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
|
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
|
||||||
|
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
|
||||||
primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
|
primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
|
||||||
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
||||||
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
||||||
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
|
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
|
|
||||||
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A deserializer holding a `u32`.
|
/// A deserializer holding a `u32`.
|
||||||
pub struct U32Deserializer<E> {
|
pub struct U32Deserializer<E> {
|
||||||
value: u32,
|
value: u32,
|
||||||
@@ -308,8 +356,15 @@ where
|
|||||||
type Deserializer = U32Deserializer<E>;
|
type Deserializer = U32Deserializer<E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> U32Deserializer<E> {
|
fn into_deserializer(self) -> U32Deserializer<E> {
|
||||||
|
U32Deserializer::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> U32Deserializer<E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new(value: u32) -> Self {
|
||||||
U32Deserializer {
|
U32Deserializer {
|
||||||
value: self,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,6 +404,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for U32Deserializer<E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, E> de::EnumAccess<'de> for U32Deserializer<E>
|
impl<'de, E> de::EnumAccess<'de> for U32Deserializer<E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -390,8 +456,15 @@ where
|
|||||||
type Deserializer = StrDeserializer<'a, E>;
|
type Deserializer = StrDeserializer<'a, E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> StrDeserializer<'a, E> {
|
fn into_deserializer(self) -> StrDeserializer<'a, E> {
|
||||||
|
StrDeserializer::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E> StrDeserializer<'a, E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new(value: &'a str) -> Self {
|
||||||
StrDeserializer {
|
StrDeserializer {
|
||||||
value: self,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,6 +504,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E>
|
impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -470,7 +554,7 @@ impl<'de, E> BorrowedStrDeserializer<'de, E> {
|
|||||||
/// Create a new borrowed deserializer from the given string.
|
/// Create a new borrowed deserializer from the given string.
|
||||||
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
|
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
|
||||||
BorrowedStrDeserializer {
|
BorrowedStrDeserializer {
|
||||||
value: value,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,6 +594,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
|
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -538,6 +633,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
|
|||||||
|
|
||||||
/// A deserializer holding a `String`.
|
/// A deserializer holding a `String`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
pub struct StringDeserializer<E> {
|
pub struct StringDeserializer<E> {
|
||||||
value: String,
|
value: String,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
@@ -554,6 +650,7 @@ impl<E> Clone for StringDeserializer<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, E> IntoDeserializer<'de, E> for String
|
impl<'de, E> IntoDeserializer<'de, E> for String
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -561,8 +658,16 @@ where
|
|||||||
type Deserializer = StringDeserializer<E>;
|
type Deserializer = StringDeserializer<E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> StringDeserializer<E> {
|
fn into_deserializer(self) -> StringDeserializer<E> {
|
||||||
|
StringDeserializer::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<E> StringDeserializer<E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new(value: String) -> Self {
|
||||||
StringDeserializer {
|
StringDeserializer {
|
||||||
value: self,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,6 +708,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for StringDeserializer<E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
|
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
|
||||||
where
|
where
|
||||||
@@ -633,6 +750,7 @@ impl<E> Debug for StringDeserializer<E> {
|
|||||||
|
|
||||||
/// A deserializer holding a `Cow<str>`.
|
/// A deserializer holding a `Cow<str>`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
pub struct CowStrDeserializer<'a, E> {
|
pub struct CowStrDeserializer<'a, E> {
|
||||||
value: Cow<'a, str>,
|
value: Cow<'a, str>,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
@@ -649,6 +767,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
|
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -656,8 +775,16 @@ where
|
|||||||
type Deserializer = CowStrDeserializer<'a, E>;
|
type Deserializer = CowStrDeserializer<'a, E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
|
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
|
||||||
|
CowStrDeserializer::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'a, E> CowStrDeserializer<'a, E> {
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub fn new(value: Cow<'a, str>) -> Self {
|
||||||
CowStrDeserializer {
|
CowStrDeserializer {
|
||||||
value: self,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -701,6 +828,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'de, 'a, E> IntoDeserializer<'de, E> for CowStrDeserializer<'a, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
|
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
|
||||||
where
|
where
|
||||||
@@ -739,7 +878,7 @@ impl<'a, E> BytesDeserializer<'a, E> {
|
|||||||
/// Create a new deserializer from the given bytes.
|
/// Create a new deserializer from the given bytes.
|
||||||
pub fn new(value: &'a [u8]) -> Self {
|
pub fn new(value: &'a [u8]) -> Self {
|
||||||
BytesDeserializer {
|
BytesDeserializer {
|
||||||
value: value,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -778,6 +917,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, E> Debug for BytesDeserializer<'a, E> {
|
impl<'a, E> Debug for BytesDeserializer<'a, E> {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter
|
formatter
|
||||||
@@ -798,7 +948,7 @@ impl<'de, E> BorrowedBytesDeserializer<'de, E> {
|
|||||||
/// Create a new borrowed deserializer from the given borrowed bytes.
|
/// Create a new borrowed deserializer from the given borrowed bytes.
|
||||||
pub fn new(value: &'de [u8]) -> Self {
|
pub fn new(value: &'de [u8]) -> Self {
|
||||||
BorrowedBytesDeserializer {
|
BorrowedBytesDeserializer {
|
||||||
value: value,
|
value,
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,6 +976,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> {
|
impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter
|
formatter
|
||||||
@@ -893,8 +1054,8 @@ where
|
|||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
let v = try!(visitor.visit_seq(&mut self));
|
let v = tri!(visitor.visit_seq(&mut self));
|
||||||
try!(self.end());
|
tri!(self.end());
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,6 +1066,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer<I, E>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = T>,
|
||||||
|
T: IntoDeserializer<'de, E>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer<I, E>
|
impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer<I, E>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = T>,
|
I: Iterator<Item = T>,
|
||||||
@@ -936,7 +1110,7 @@ struct ExpectedInSeq(usize);
|
|||||||
impl Expected for ExpectedInSeq {
|
impl Expected for ExpectedInSeq {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.0 == 1 {
|
if self.0 == 1 {
|
||||||
write!(formatter, "1 element in sequence")
|
formatter.write_str("1 element in sequence")
|
||||||
} else {
|
} else {
|
||||||
write!(formatter, "{} elements in sequence", self.0)
|
write!(formatter, "{} elements in sequence", self.0)
|
||||||
}
|
}
|
||||||
@@ -959,6 +1133,7 @@ where
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
|
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E>,
|
T: IntoDeserializer<'de, E>,
|
||||||
@@ -972,6 +1147,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
|
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E> + Eq + Ord,
|
T: IntoDeserializer<'de, E> + Eq + Ord,
|
||||||
@@ -985,6 +1161,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E> + Eq + Hash,
|
T: IntoDeserializer<'de, E> + Eq + Hash,
|
||||||
@@ -1009,7 +1186,7 @@ pub struct SeqAccessDeserializer<A> {
|
|||||||
impl<A> SeqAccessDeserializer<A> {
|
impl<A> SeqAccessDeserializer<A> {
|
||||||
/// Construct a new `SeqAccessDeserializer<A>`.
|
/// Construct a new `SeqAccessDeserializer<A>`.
|
||||||
pub fn new(seq: A) -> Self {
|
pub fn new(seq: A) -> Self {
|
||||||
SeqAccessDeserializer { seq: seq }
|
SeqAccessDeserializer { seq }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,6 +1210,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer<A>
|
||||||
|
where
|
||||||
|
A: de::SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// A deserializer that iterates over a map.
|
/// A deserializer that iterates over a map.
|
||||||
@@ -1118,8 +1306,8 @@ where
|
|||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
let value = try!(visitor.visit_map(&mut self));
|
let value = tri!(visitor.visit_map(&mut self));
|
||||||
try!(self.end());
|
tri!(self.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1127,8 +1315,8 @@ where
|
|||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
let value = try!(visitor.visit_seq(&mut self));
|
let value = tri!(visitor.visit_seq(&mut self));
|
||||||
try!(self.end());
|
tri!(self.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1147,6 +1335,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E>
|
||||||
|
where
|
||||||
|
I: Iterator,
|
||||||
|
I::Item: private::Pair,
|
||||||
|
First<I::Item>: IntoDeserializer<'de, E>,
|
||||||
|
Second<I::Item>: IntoDeserializer<'de, E>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E>
|
impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E>
|
||||||
where
|
where
|
||||||
I: Iterator,
|
I: Iterator,
|
||||||
@@ -1192,8 +1395,8 @@ where
|
|||||||
{
|
{
|
||||||
match self.next_pair() {
|
match self.next_pair() {
|
||||||
Some((key, value)) => {
|
Some((key, value)) => {
|
||||||
let key = try!(kseed.deserialize(key.into_deserializer()));
|
let key = tri!(kseed.deserialize(key.into_deserializer()));
|
||||||
let value = try!(vseed.deserialize(value.into_deserializer()));
|
let value = tri!(vseed.deserialize(value.into_deserializer()));
|
||||||
Ok(Some((key, value)))
|
Ok(Some((key, value)))
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
@@ -1297,7 +1500,7 @@ where
|
|||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
|
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
|
||||||
let pair = try!(visitor.visit_seq(&mut pair_visitor));
|
let pair = tri!(visitor.visit_seq(&mut pair_visitor));
|
||||||
if pair_visitor.1.is_none() {
|
if pair_visitor.1.is_none() {
|
||||||
Ok(pair)
|
Ok(pair)
|
||||||
} else {
|
} else {
|
||||||
@@ -1361,7 +1564,7 @@ struct ExpectedInMap(usize);
|
|||||||
impl Expected for ExpectedInMap {
|
impl Expected for ExpectedInMap {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.0 == 1 {
|
if self.0 == 1 {
|
||||||
write!(formatter, "1 element in map")
|
formatter.write_str("1 element in map")
|
||||||
} else {
|
} else {
|
||||||
write!(formatter, "{} elements in map", self.0)
|
write!(formatter, "{} elements in map", self.0)
|
||||||
}
|
}
|
||||||
@@ -1371,6 +1574,7 @@ impl Expected for ExpectedInMap {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
|
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
|
||||||
where
|
where
|
||||||
K: IntoDeserializer<'de, E> + Eq + Ord,
|
K: IntoDeserializer<'de, E> + Eq + Ord,
|
||||||
@@ -1385,6 +1589,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
||||||
where
|
where
|
||||||
K: IntoDeserializer<'de, E> + Eq + Hash,
|
K: IntoDeserializer<'de, E> + Eq + Hash,
|
||||||
@@ -1410,7 +1615,7 @@ pub struct MapAccessDeserializer<A> {
|
|||||||
impl<A> MapAccessDeserializer<A> {
|
impl<A> MapAccessDeserializer<A> {
|
||||||
/// Construct a new `MapAccessDeserializer<A>`.
|
/// Construct a new `MapAccessDeserializer<A>`.
|
||||||
pub fn new(map: A) -> Self {
|
pub fn new(map: A) -> Self {
|
||||||
MapAccessDeserializer { map: map }
|
MapAccessDeserializer { map }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,6 +1651,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer<A>
|
||||||
|
where
|
||||||
|
A: de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
|
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
|
||||||
where
|
where
|
||||||
A: de::MapAccess<'de>,
|
A: de::MapAccess<'de>,
|
||||||
@@ -1457,7 +1673,7 @@ where
|
|||||||
where
|
where
|
||||||
T: de::DeserializeSeed<'de>,
|
T: de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.map.next_key_seed(seed)? {
|
match tri!(self.map.next_key_seed(seed)) {
|
||||||
Some(key) => Ok((key, private::map_as_enum(self.map))),
|
Some(key) => Ok((key, private::map_as_enum(self.map))),
|
||||||
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
|
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
|
||||||
}
|
}
|
||||||
@@ -1466,10 +1682,58 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
mod private {
|
/// A deserializer holding an `EnumAccess`.
|
||||||
use lib::*;
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct EnumAccessDeserializer<A> {
|
||||||
|
access: A,
|
||||||
|
}
|
||||||
|
|
||||||
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
|
impl<A> EnumAccessDeserializer<A> {
|
||||||
|
/// Construct a new `EnumAccessDeserializer<A>`.
|
||||||
|
pub fn new(access: A) -> Self {
|
||||||
|
EnumAccessDeserializer { access }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer<A>
|
||||||
|
where
|
||||||
|
A: de::EnumAccess<'de>,
|
||||||
|
{
|
||||||
|
type Error = A::Error;
|
||||||
|
|
||||||
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_enum(self.access)
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_to_deserialize_any! {
|
||||||
|
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
||||||
|
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
||||||
|
tuple_struct map struct enum identifier ignored_any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, A> IntoDeserializer<'de, A::Error> for EnumAccessDeserializer<A>
|
||||||
|
where
|
||||||
|
A: de::EnumAccess<'de>,
|
||||||
|
{
|
||||||
|
type Deserializer = Self;
|
||||||
|
|
||||||
|
fn into_deserializer(self) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
mod private {
|
||||||
|
use crate::lib::*;
|
||||||
|
|
||||||
|
use crate::de::{
|
||||||
|
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct UnitOnly<E> {
|
pub struct UnitOnly<E> {
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
@@ -1534,7 +1798,7 @@ mod private {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_as_enum<A>(map: A) -> MapAsEnum<A> {
|
pub fn map_as_enum<A>(map: A) -> MapAsEnum<A> {
|
||||||
MapAsEnum { map: map }
|
MapAsEnum { map }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, A> VariantAccess<'de> for MapAsEnum<A>
|
impl<'de, A> VariantAccess<'de> for MapAsEnum<A>
|
||||||
@@ -1558,10 +1822,7 @@ mod private {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.map.next_value_seed(SeedTupleVariant {
|
self.map.next_value_seed(SeedTupleVariant { len, visitor })
|
||||||
len: len,
|
|
||||||
visitor: visitor,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_variant<V>(
|
fn struct_variant<V>(
|
||||||
@@ -1572,8 +1833,7 @@ mod private {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.map
|
self.map.next_value_seed(SeedStructVariant { visitor })
|
||||||
.next_value_seed(SeedStructVariant { visitor: visitor })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use lib::fmt::{self, Write};
|
use crate::lib::fmt::{self, Write};
|
||||||
use lib::str;
|
use crate::lib::str;
|
||||||
|
|
||||||
pub struct Buf<'a> {
|
pub(super) struct Buf<'a> {
|
||||||
bytes: &'a mut [u8],
|
bytes: &'a mut [u8],
|
||||||
offset: usize,
|
offset: usize,
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
|
||||||
|
//! structures efficiently and generically.
|
||||||
|
//!
|
||||||
|
//! The `serde_core` crate contains Serde's trait definitions with **no support
|
||||||
|
//! for #\[derive()\]**.
|
||||||
|
//!
|
||||||
|
//! In crates that derive an implementation of `Serialize` or `Deserialize`, you
|
||||||
|
//! must depend on the [`serde`] crate, not `serde_core`.
|
||||||
|
//!
|
||||||
|
//! [`serde`]: https://crates.io/crates/serde
|
||||||
|
//!
|
||||||
|
//! In crates that handwrite implementations of Serde traits, or only use them
|
||||||
|
//! as trait bounds, depending on `serde_core` is permitted. But `serde`
|
||||||
|
//! re-exports all of these traits and can be used for this use case too. If in
|
||||||
|
//! doubt, disregard `serde_core` and always use `serde`.
|
||||||
|
//!
|
||||||
|
//! Crates that depend on `serde_core` instead of `serde` are able to compile in
|
||||||
|
//! parallel with `serde_derive` even when `serde`'s "derive" feature is turned on,
|
||||||
|
//! as shown in the following build timings.
|
||||||
|
//!
|
||||||
|
//! <br>
|
||||||
|
//!
|
||||||
|
//! <table>
|
||||||
|
//! <tr><td align="center">When <code>serde_json</code> depends on <code>serde</code></td></tr>
|
||||||
|
//! <tr><td><img src="https://github.com/user-attachments/assets/78dc179c-6ab1-4059-928c-1474b0d9d0bb"></td></tr>
|
||||||
|
//! </table>
|
||||||
|
//!
|
||||||
|
//! <br>
|
||||||
|
//!
|
||||||
|
//! <table>
|
||||||
|
//! <tr><td align="center">When <code>serde_json</code> depends on <code>serde_core</code></td></tr>
|
||||||
|
//! <tr><td><img src="https://github.com/user-attachments/assets/6b6cff5e-3e45-4ac7-9db1-d99ee8b9f5f7"></td></tr>
|
||||||
|
//! </table>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
|
#![doc(html_root_url = "https://docs.rs/serde_core/1.0.228")]
|
||||||
|
// Support using Serde without the standard library!
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))]
|
||||||
|
#![cfg_attr(docsrs, allow(internal_features))]
|
||||||
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
|
// discussion of these features please refer to this issue:
|
||||||
|
//
|
||||||
|
// https://github.com/serde-rs/serde/issues/812
|
||||||
|
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||||
|
#![allow(unknown_lints, bare_trait_objects, deprecated)]
|
||||||
|
// Ignored clippy and clippy_pedantic lints
|
||||||
|
#![allow(
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
|
||||||
|
clippy::unnested_or_patterns,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
|
||||||
|
clippy::semicolon_if_nothing_returned,
|
||||||
|
// not available in our oldest supported compiler
|
||||||
|
clippy::empty_enums,
|
||||||
|
clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
|
||||||
|
// integer and float ser/de requires these sorts of casts
|
||||||
|
clippy::cast_possible_truncation,
|
||||||
|
clippy::cast_possible_wrap,
|
||||||
|
clippy::cast_precision_loss,
|
||||||
|
clippy::cast_sign_loss,
|
||||||
|
// things are often more readable this way
|
||||||
|
clippy::cast_lossless,
|
||||||
|
clippy::module_name_repetitions,
|
||||||
|
clippy::single_match_else,
|
||||||
|
clippy::type_complexity,
|
||||||
|
clippy::use_self,
|
||||||
|
clippy::zero_prefixed_literal,
|
||||||
|
// correctly used
|
||||||
|
clippy::derive_partial_eq_without_eq,
|
||||||
|
clippy::enum_glob_use,
|
||||||
|
clippy::explicit_auto_deref,
|
||||||
|
clippy::incompatible_msrv,
|
||||||
|
clippy::let_underscore_untyped,
|
||||||
|
clippy::map_err_ignore,
|
||||||
|
clippy::new_without_default,
|
||||||
|
clippy::result_unit_err,
|
||||||
|
clippy::wildcard_imports,
|
||||||
|
// not practical
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::similar_names,
|
||||||
|
clippy::too_many_lines,
|
||||||
|
// preference
|
||||||
|
clippy::doc_markdown,
|
||||||
|
clippy::elidable_lifetime_names,
|
||||||
|
clippy::needless_lifetimes,
|
||||||
|
clippy::unseparated_literal_suffix,
|
||||||
|
// false positive
|
||||||
|
clippy::needless_doctest_main,
|
||||||
|
// noisy
|
||||||
|
clippy::missing_errors_doc,
|
||||||
|
clippy::must_use_candidate,
|
||||||
|
)]
|
||||||
|
// Restrictions
|
||||||
|
#![deny(clippy::question_mark_used)]
|
||||||
|
// Rustc lints.
|
||||||
|
#![deny(missing_docs, unused_imports)]
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod crate_root;
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
|
||||||
|
crate_root!();
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! __require_serde_not_serde_core {
|
||||||
|
() => {
|
||||||
|
::core::compile_error!(
|
||||||
|
"Serde derive requires a dependency on the serde crate, not serde_core"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
// Super explicit first paragraph because this shows up at the top level and
|
// Super explicit first paragraph because this shows up at the top level and
|
||||||
// trips up people who are just looking for basic Serialize / Deserialize
|
// trips up people who are just looking for basic Serialize / Deserialize
|
||||||
// documentation.
|
// documentation.
|
||||||
//
|
|
||||||
/// Helper macro when implementing the `Deserializer` part of a new data format
|
/// Helper macro when implementing the `Deserializer` part of a new data format
|
||||||
/// for Serde.
|
/// for Serde.
|
||||||
///
|
///
|
||||||
@@ -11,7 +10,7 @@
|
|||||||
/// input. This requires repetitive implementations of all the [`Deserializer`]
|
/// input. This requires repetitive implementations of all the [`Deserializer`]
|
||||||
/// trait methods.
|
/// trait methods.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::forward_to_deserialize_any;
|
/// # use serde::forward_to_deserialize_any;
|
||||||
/// # use serde::de::{value, Deserializer, Visitor};
|
/// # use serde::de::{value, Deserializer, Visitor};
|
||||||
/// #
|
/// #
|
||||||
@@ -47,7 +46,7 @@
|
|||||||
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
|
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
|
||||||
/// You can choose which methods to forward.
|
/// You can choose which methods to forward.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::forward_to_deserialize_any;
|
/// # use serde::forward_to_deserialize_any;
|
||||||
/// # use serde::de::{value, Deserializer, Visitor};
|
/// # use serde::de::{value, Deserializer, Visitor};
|
||||||
/// #
|
/// #
|
||||||
@@ -78,11 +77,10 @@
|
|||||||
/// called `V`. A different type parameter and a different lifetime can be
|
/// called `V`. A different type parameter and a different lifetime can be
|
||||||
/// specified explicitly if necessary.
|
/// specified explicitly if necessary.
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use std::marker::PhantomData;
|
|
||||||
/// #
|
|
||||||
/// # use serde::forward_to_deserialize_any;
|
/// # use serde::forward_to_deserialize_any;
|
||||||
/// # use serde::de::{value, Deserializer, Visitor};
|
/// # use serde::de::{value, Deserializer, Visitor};
|
||||||
|
/// # use std::marker::PhantomData;
|
||||||
/// #
|
/// #
|
||||||
/// # struct MyDeserializer<V>(PhantomData<V>);
|
/// # struct MyDeserializer<V>(PhantomData<V>);
|
||||||
/// #
|
/// #
|
||||||
@@ -105,9 +103,9 @@
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Deserializer`]: trait.Deserializer.html
|
/// [`Deserializer`]: crate::Deserializer
|
||||||
/// [`Visitor`]: de/trait.Visitor.html
|
/// [`Visitor`]: crate::de::Visitor
|
||||||
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
|
/// [`Deserializer::deserialize_any`]: crate::Deserializer::deserialize_any
|
||||||
#[macro_export(local_inner_macros)]
|
#[macro_export(local_inner_macros)]
|
||||||
macro_rules! forward_to_deserialize_any {
|
macro_rules! forward_to_deserialize_any {
|
||||||
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
|
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
|
||||||
@@ -124,7 +122,7 @@ macro_rules! forward_to_deserialize_any {
|
|||||||
macro_rules! forward_to_deserialize_any_method {
|
macro_rules! forward_to_deserialize_any_method {
|
||||||
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error>
|
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, <Self as $crate::de::Deserializer<$l>>::Error>
|
||||||
where
|
where
|
||||||
$v: $crate::de::Visitor<$l>,
|
$v: $crate::de::Visitor<$l>,
|
||||||
{
|
{
|
||||||
@@ -155,9 +153,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
|||||||
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
||||||
};
|
};
|
||||||
(i128<$l:tt, $v:ident>) => {
|
(i128<$l:tt, $v:ident>) => {
|
||||||
serde_if_integer128! {
|
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
||||||
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
(u8<$l:tt, $v:ident>) => {
|
(u8<$l:tt, $v:ident>) => {
|
||||||
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
||||||
@@ -172,9 +168,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
|||||||
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
||||||
};
|
};
|
||||||
(u128<$l:tt, $v:ident>) => {
|
(u128<$l:tt, $v:ident>) => {
|
||||||
serde_if_integer128! {
|
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
||||||
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
(f32<$l:tt, $v:ident>) => {
|
(f32<$l:tt, $v:ident>) => {
|
||||||
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
use crate::lib::*;
|
||||||
|
|
||||||
|
// Used from generated code to buffer the contents of the Deserializer when
|
||||||
|
// deserializing untagged enums and internally tagged enums.
|
||||||
|
//
|
||||||
|
// Not public API. Use serde-value instead.
|
||||||
|
//
|
||||||
|
// Obsoleted by format-specific buffer types (https://github.com/serde-rs/serde/pull/2912).
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub enum Content<'de> {
|
||||||
|
Bool(bool),
|
||||||
|
|
||||||
|
U8(u8),
|
||||||
|
U16(u16),
|
||||||
|
U32(u32),
|
||||||
|
U64(u64),
|
||||||
|
|
||||||
|
I8(i8),
|
||||||
|
I16(i16),
|
||||||
|
I32(i32),
|
||||||
|
I64(i64),
|
||||||
|
|
||||||
|
F32(f32),
|
||||||
|
F64(f64),
|
||||||
|
|
||||||
|
Char(char),
|
||||||
|
String(String),
|
||||||
|
Str(&'de str),
|
||||||
|
ByteBuf(Vec<u8>),
|
||||||
|
Bytes(&'de [u8]),
|
||||||
|
|
||||||
|
None,
|
||||||
|
Some(Box<Content<'de>>),
|
||||||
|
|
||||||
|
Unit,
|
||||||
|
Newtype(Box<Content<'de>>),
|
||||||
|
Seq(Vec<Content<'de>>),
|
||||||
|
Map(Vec<(Content<'de>, Content<'de>)>),
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
// Used only by Serde doc tests. Not public API.
|
// Used only by Serde doc tests. Not public API.
|
||||||
|
|
||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use ser;
|
use crate::ser;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error;
|
pub struct Error;
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl ser::Error for Error {
|
impl ser::Error for Error {
|
||||||
fn custom<T>(_: T) -> Self
|
fn custom<T>(_: T) -> Self
|
||||||
where
|
where
|
||||||
@@ -18,12 +19,14 @@ impl ser::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@@ -56,7 +59,10 @@ macro_rules! __serialize_unimplemented {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __serialize_unimplemented_method {
|
macro_rules! __serialize_unimplemented_method {
|
||||||
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
|
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
|
||||||
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error> {
|
fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error>
|
||||||
|
where
|
||||||
|
$($t: ?Sized + $crate::Serialize,)*
|
||||||
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||||
|
mod content;
|
||||||
|
mod seed;
|
||||||
|
|
||||||
|
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod doc;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod size_hint;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod string;
|
||||||
|
|
||||||
|
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use self::content::Content;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use self::seed::InPlaceSeed;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use crate::lib::result::Result;
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use de::{Deserialize, DeserializeSeed, Deserializer};
|
use crate::de::{Deserialize, DeserializeSeed, Deserializer};
|
||||||
|
|
||||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||||
///
|
///
|
||||||
/// Wraps a mutable reference and calls deserialize_in_place on it.
|
/// Wraps a mutable reference and calls deserialize_in_place on it.
|
||||||
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
|
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
|
||||||
|
|
||||||
|
#[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)]
|
||||||
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
|
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
use crate::lib::*;
|
||||||
|
|
||||||
|
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
||||||
|
where
|
||||||
|
I: Iterator,
|
||||||
|
{
|
||||||
|
helper(iter.size_hint())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
pub fn cautious<Element>(hint: Option<usize>) -> usize {
|
||||||
|
const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
|
||||||
|
|
||||||
|
if mem::size_of::<Element>() == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
cmp::min(
|
||||||
|
hint.unwrap_or(0),
|
||||||
|
MAX_PREALLOC_BYTES / mem::size_of::<Element>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
|
||||||
|
match bounds {
|
||||||
|
(lower, Some(upper)) if lower == upper => Some(upper),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
use crate::lib::*;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<'_, str> {
|
||||||
|
String::from_utf8_lossy(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The generated code calls this like:
|
||||||
|
//
|
||||||
|
// let value = &_serde::__private::from_utf8_lossy(bytes);
|
||||||
|
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
|
||||||
|
//
|
||||||
|
// so it is okay for the return type to be different from the std case as long
|
||||||
|
// as the above works.
|
||||||
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
|
||||||
|
// Three unicode replacement characters if it fails. They look like a
|
||||||
|
// white-on-black question mark. The user will recognize it as invalid
|
||||||
|
// UTF-8.
|
||||||
|
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use lib::*;
|
use crate::lib::*;
|
||||||
use ser::{Error, Impossible, Serialize, Serializer};
|
use crate::ser::{Error, Impossible, Serialize, Serializer};
|
||||||
|
|
||||||
impl Error for fmt::Error {
|
impl Error for fmt::Error {
|
||||||
fn custom<T: Display>(_msg: T) -> Self {
|
fn custom<T: Display>(_msg: T) -> Self {
|
||||||
@@ -17,8 +17,9 @@ macro_rules! fmt_primitives {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// use serde::Serialize;
|
/// use serde::ser::Serialize;
|
||||||
|
/// use serde_derive::Serialize;
|
||||||
/// use std::fmt::{self, Display};
|
/// use std::fmt::{self, Display};
|
||||||
///
|
///
|
||||||
/// #[derive(Serialize)]
|
/// #[derive(Serialize)]
|
||||||
@@ -34,7 +35,7 @@ macro_rules! fmt_primitives {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
impl<'a> Serializer for &mut fmt::Formatter<'a> {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = fmt::Error;
|
type Error = fmt::Error;
|
||||||
type SerializeSeq = Impossible<(), fmt::Error>;
|
type SerializeSeq = Impossible<(), fmt::Error>;
|
||||||
@@ -51,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
serialize_i16: i16,
|
serialize_i16: i16,
|
||||||
serialize_i32: i32,
|
serialize_i32: i32,
|
||||||
serialize_i64: i64,
|
serialize_i64: i64,
|
||||||
|
serialize_i128: i128,
|
||||||
serialize_u8: u8,
|
serialize_u8: u8,
|
||||||
serialize_u16: u16,
|
serialize_u16: u16,
|
||||||
serialize_u32: u32,
|
serialize_u32: u32,
|
||||||
serialize_u64: u64,
|
serialize_u64: u64,
|
||||||
|
serialize_u128: u128,
|
||||||
serialize_f32: f32,
|
serialize_f32: f32,
|
||||||
serialize_f64: f64,
|
serialize_f64: f64,
|
||||||
serialize_char: char,
|
serialize_char: char,
|
||||||
@@ -62,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
serialize_unit_struct: &'static str,
|
serialize_unit_struct: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
fmt_primitives! {
|
|
||||||
serialize_i128: i128,
|
|
||||||
serialize_u128: u128,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
fn serialize_unit_variant(
|
||||||
self,
|
self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
@@ -78,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
Display::fmt(variant, self)
|
Display::fmt(variant, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
|
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> fmt::Result
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Serialize::serialize(value, self)
|
Serialize::serialize(value, self)
|
||||||
}
|
}
|
||||||
@@ -93,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
Err(fmt::Error)
|
Err(fmt::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
|
fn serialize_some<T>(self, _value: &T) -> fmt::Result
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Err(fmt::Error)
|
Err(fmt::Error)
|
||||||
}
|
}
|
||||||
@@ -104,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
Err(fmt::Error)
|
Err(fmt::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
fn serialize_newtype_variant<T>(
|
||||||
self,
|
self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
_variant_index: u32,
|
_variant_index: u32,
|
||||||
@@ -112,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
_value: &T,
|
_value: &T,
|
||||||
) -> fmt::Result
|
) -> fmt::Result
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
Err(fmt::Error)
|
Err(fmt::Error)
|
||||||
}
|
}
|
||||||
@@ -165,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
Err(fmt::Error)
|
Err(fmt::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
|
fn collect_str<T>(self, value: &T) -> fmt::Result
|
||||||
where
|
where
|
||||||
T: Display,
|
T: ?Sized + Display,
|
||||||
{
|
{
|
||||||
Display::fmt(value, self)
|
Display::fmt(value, self)
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use ser::{Error, Serialize, SerializeTuple, Serializer};
|
use crate::ser::{Error, Serialize, SerializeTuple, Serializer};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8);
|
|||||||
primitive_impl!(i16, serialize_i16);
|
primitive_impl!(i16, serialize_i16);
|
||||||
primitive_impl!(i32, serialize_i32);
|
primitive_impl!(i32, serialize_i32);
|
||||||
primitive_impl!(i64, serialize_i64);
|
primitive_impl!(i64, serialize_i64);
|
||||||
|
primitive_impl!(i128, serialize_i128);
|
||||||
primitive_impl!(usize, serialize_u64 as u64);
|
primitive_impl!(usize, serialize_u64 as u64);
|
||||||
primitive_impl!(u8, serialize_u8);
|
primitive_impl!(u8, serialize_u8);
|
||||||
primitive_impl!(u16, serialize_u16);
|
primitive_impl!(u16, serialize_u16);
|
||||||
primitive_impl!(u32, serialize_u32);
|
primitive_impl!(u32, serialize_u32);
|
||||||
primitive_impl!(u64, serialize_u64);
|
primitive_impl!(u64, serialize_u64);
|
||||||
|
primitive_impl!(u128, serialize_u128);
|
||||||
primitive_impl!(f32, serialize_f32);
|
primitive_impl!(f32, serialize_f32);
|
||||||
primitive_impl!(f64, serialize_f64);
|
primitive_impl!(f64, serialize_f64);
|
||||||
primitive_impl!(char, serialize_char);
|
primitive_impl!(char, serialize_char);
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
primitive_impl!(i128, serialize_i128);
|
|
||||||
primitive_impl!(u128, serialize_u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl Serialize for str {
|
impl Serialize for str {
|
||||||
@@ -51,6 +48,7 @@ impl Serialize for str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl Serialize for String {
|
impl Serialize for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -72,7 +70,8 @@ impl<'a> Serialize for fmt::Arguments<'a> {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_cstr)))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for CStr {
|
impl Serialize for CStr {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -83,7 +82,8 @@ impl Serialize for CStr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl Serialize for CString {
|
impl Serialize for CString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -114,7 +114,10 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T: ?Sized> Serialize for PhantomData<T> {
|
impl<T> Serialize for PhantomData<T>
|
||||||
|
where
|
||||||
|
T: ?Sized,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -133,7 +136,7 @@ impl<T> Serialize for [T; 0] {
|
|||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
try!(serializer.serialize_tuple(0)).end()
|
tri!(serializer.serialize_tuple(0)).end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +152,9 @@ macro_rules! array_impls {
|
|||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
let mut seq = try!(serializer.serialize_tuple($len));
|
let mut seq = tri!(serializer.serialize_tuple($len));
|
||||||
for e in self {
|
for e in self {
|
||||||
try!(seq.serialize_element(e));
|
tri!(seq.serialize_element(e));
|
||||||
}
|
}
|
||||||
seq.end()
|
seq.end()
|
||||||
}
|
}
|
||||||
@@ -182,13 +185,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
macro_rules! seq_impl {
|
macro_rules! seq_impl {
|
||||||
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
|
$ty:ident <T $(, $typaram:ident : $bound:ident)*>
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||||
where
|
where
|
||||||
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
T: Serialize,
|
||||||
$($typaram: $bound,)*
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -201,23 +206,41 @@ macro_rules! seq_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(BinaryHeap<T: Ord>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BinaryHeap<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(BTreeSet<T: Ord>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BTreeSet<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
seq_impl! {
|
||||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
|
HashSet<T, H: BuildHasher>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(LinkedList<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
LinkedList<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(Vec<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
Vec<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(VecDeque<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
VecDeque<T>
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -230,16 +253,32 @@ where
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
use super::SerializeStruct;
|
use super::SerializeStruct;
|
||||||
let mut state = try!(serializer.serialize_struct("Range", 2));
|
let mut state = tri!(serializer.serialize_struct("Range", 2));
|
||||||
try!(state.serialize_field("start", &self.start));
|
tri!(state.serialize_field("start", &self.start));
|
||||||
try!(state.serialize_field("end", &self.end));
|
tri!(state.serialize_field("end", &self.end));
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl<Idx> Serialize for RangeFrom<Idx>
|
||||||
|
where
|
||||||
|
Idx: Serialize,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
use super::SerializeStruct;
|
||||||
|
let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
|
||||||
|
tri!(state.serialize_field("start", &self.start));
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(not(no_range_inclusive))]
|
|
||||||
impl<Idx> Serialize for RangeInclusive<Idx>
|
impl<Idx> Serialize for RangeInclusive<Idx>
|
||||||
where
|
where
|
||||||
Idx: Serialize,
|
Idx: Serialize,
|
||||||
@@ -249,16 +288,32 @@ where
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
use super::SerializeStruct;
|
use super::SerializeStruct;
|
||||||
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
|
let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2));
|
||||||
try!(state.serialize_field("start", &self.start()));
|
tri!(state.serialize_field("start", &self.start()));
|
||||||
try!(state.serialize_field("end", &self.end()));
|
tri!(state.serialize_field("end", &self.end()));
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl<Idx> Serialize for RangeTo<Idx>
|
||||||
|
where
|
||||||
|
Idx: Serialize,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
use super::SerializeStruct;
|
||||||
|
let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
|
||||||
|
tri!(state.serialize_field("end", &self.end));
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
|
|
||||||
impl<T> Serialize for Bound<T>
|
impl<T> Serialize for Bound<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -292,6 +347,7 @@ impl Serialize for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||||
impl Serialize for ! {
|
impl Serialize for ! {
|
||||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -306,28 +362,46 @@ impl Serialize for ! {
|
|||||||
macro_rules! tuple_impls {
|
macro_rules! tuple_impls {
|
||||||
($($len:expr => ($($n:tt $name:ident)+))+) => {
|
($($len:expr => ($($n:tt $name:ident)+))+) => {
|
||||||
$(
|
$(
|
||||||
|
#[cfg_attr(docsrs, doc(hidden))]
|
||||||
impl<$($name),+> Serialize for ($($name,)+)
|
impl<$($name),+> Serialize for ($($name,)+)
|
||||||
where
|
where
|
||||||
$($name: Serialize,)+
|
$($name: Serialize,)+
|
||||||
{
|
{
|
||||||
#[inline]
|
tuple_impl_body!($len => ($($n)+));
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let mut tuple = try!(serializer.serialize_tuple($len));
|
|
||||||
$(
|
|
||||||
try!(tuple.serialize_element(&self.$n));
|
|
||||||
)+
|
|
||||||
tuple.end()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! tuple_impl_body {
|
||||||
|
($len:expr => ($($n:tt)+)) => {
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut tuple = tri!(serializer.serialize_tuple($len));
|
||||||
|
$(
|
||||||
|
tri!(tuple.serialize_element(&self.$n));
|
||||||
|
)+
|
||||||
|
tuple.end()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(docsrs, doc(fake_variadic))]
|
||||||
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc = "This trait is implemented for tuples up to 16 items long."
|
||||||
|
)]
|
||||||
|
impl<T> Serialize for (T,)
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
tuple_impl_body!(1 => (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple_impls! {
|
tuple_impls! {
|
||||||
1 => (0 T0)
|
|
||||||
2 => (0 T0 1 T1)
|
2 => (0 T0 1 T1)
|
||||||
3 => (0 T0 1 T1 2 T2)
|
3 => (0 T0 1 T1 2 T2)
|
||||||
4 => (0 T0 1 T1 2 T2 3 T3)
|
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||||
@@ -347,14 +421,16 @@ tuple_impls! {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
macro_rules! map_impl {
|
macro_rules! map_impl {
|
||||||
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
|
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||||
where
|
where
|
||||||
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
K: Serialize,
|
||||||
V: Serialize,
|
V: Serialize,
|
||||||
$($typaram: $bound,)*
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -367,20 +443,26 @@ macro_rules! map_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
map_impl! {
|
||||||
map_impl!(BTreeMap<K: Ord, V>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BTreeMap<K: Ord, V>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
map_impl! {
|
||||||
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
|
HashMap<K: Eq + Hash, V, H: BuildHasher>
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! deref_impl {
|
macro_rules! deref_impl {
|
||||||
(
|
(
|
||||||
$(#[doc = $doc:tt])*
|
$(#[$attr:meta])*
|
||||||
<$($desc:tt)+
|
<$($desc:tt)+
|
||||||
) => {
|
) => {
|
||||||
$(#[doc = $doc])*
|
$(#[$attr])*
|
||||||
impl <$($desc)+ {
|
impl <$($desc)+ {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -393,13 +475,20 @@ macro_rules! deref_impl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
|
deref_impl! {
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
<'a, T> Serialize for &'a T where T: ?Sized + Serialize
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
deref_impl! {
|
||||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
<'a, T> Serialize for &'a mut T where T: ?Sized + Serialize
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_impl! {
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
<T> Serialize for Box<T> where T: ?Sized + Serialize
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
deref_impl! {
|
deref_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -409,10 +498,11 @@ deref_impl! {
|
|||||||
/// repeated data.
|
/// repeated data.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
|
<T> Serialize for Rc<T> where T: ?Sized + Serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
deref_impl! {
|
deref_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -422,11 +512,16 @@ deref_impl! {
|
|||||||
/// repeated data.
|
/// repeated data.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
|
<T> Serialize for Arc<T> where T: ?Sized + Serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
deref_impl! {
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
<'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -434,9 +529,13 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
impl<T: ?Sized> Serialize for RcWeak<T>
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
|
impl<T> Serialize for RcWeak<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -450,9 +549,13 @@ where
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
impl<T: ?Sized> Serialize for ArcWeak<T>
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
|
impl<T> Serialize for ArcWeak<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -465,9 +568,8 @@ where
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! nonzero_integers {
|
macro_rules! nonzero_integers {
|
||||||
( $( $T: ident, )+ ) => {
|
($($T:ident,)+) => {
|
||||||
$(
|
$(
|
||||||
#[cfg(not(no_num_nonzero))]
|
|
||||||
impl Serialize for num::$T {
|
impl Serialize for num::$T {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -480,34 +582,19 @@ macro_rules! nonzero_integers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nonzero_integers! {
|
|
||||||
NonZeroU8,
|
|
||||||
NonZeroU16,
|
|
||||||
NonZeroU32,
|
|
||||||
NonZeroU64,
|
|
||||||
NonZeroUsize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(no_num_nonzero_signed))]
|
|
||||||
nonzero_integers! {
|
nonzero_integers! {
|
||||||
NonZeroI8,
|
NonZeroI8,
|
||||||
NonZeroI16,
|
NonZeroI16,
|
||||||
NonZeroI32,
|
NonZeroI32,
|
||||||
NonZeroI64,
|
NonZeroI64,
|
||||||
|
NonZeroI128,
|
||||||
NonZeroIsize,
|
NonZeroIsize,
|
||||||
}
|
NonZeroU8,
|
||||||
|
NonZeroU16,
|
||||||
// Currently 128-bit integers do not work on Emscripten targets so we need an
|
NonZeroU32,
|
||||||
// additional `#[cfg]`
|
NonZeroU64,
|
||||||
serde_if_integer128! {
|
NonZeroU128,
|
||||||
nonzero_integers! {
|
NonZeroUsize,
|
||||||
NonZeroU128,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(no_num_nonzero_signed))]
|
|
||||||
nonzero_integers! {
|
|
||||||
NonZeroI128,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Serialize for Cell<T>
|
impl<T> Serialize for Cell<T>
|
||||||
@@ -524,7 +611,7 @@ where
|
|||||||
|
|
||||||
impl<T> Serialize for RefCell<T>
|
impl<T> Serialize for RefCell<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -538,9 +625,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl<T> Serialize for Mutex<T>
|
impl<T> Serialize for Mutex<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -554,9 +642,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl<T> Serialize for RwLock<T>
|
impl<T> Serialize for RwLock<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -571,6 +660,8 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "result")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "result")))]
|
||||||
impl<T, E> Serialize for Result<T, E>
|
impl<T, E> Serialize for Result<T, E>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -591,16 +682,15 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
|
||||||
impl Serialize for Duration {
|
impl Serialize for Duration {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
use super::SerializeStruct;
|
use super::SerializeStruct;
|
||||||
let mut state = try!(serializer.serialize_struct("Duration", 2));
|
let mut state = tri!(serializer.serialize_struct("Duration", 2));
|
||||||
try!(state.serialize_field("secs", &self.as_secs()));
|
tri!(state.serialize_field("secs", &self.as_secs()));
|
||||||
try!(state.serialize_field("nanos", &self.subsec_nanos()));
|
tri!(state.serialize_field("nanos", &self.subsec_nanos()));
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -608,18 +698,20 @@ impl Serialize for Duration {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for SystemTime {
|
impl Serialize for SystemTime {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
use super::SerializeStruct;
|
use super::SerializeStruct;
|
||||||
let duration_since_epoch = self
|
let duration_since_epoch = match self.duration_since(UNIX_EPOCH) {
|
||||||
.duration_since(UNIX_EPOCH)
|
Ok(duration_since_epoch) => duration_since_epoch,
|
||||||
.map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?;
|
Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")),
|
||||||
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
|
};
|
||||||
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
|
let mut state = tri!(serializer.serialize_struct("SystemTime", 2));
|
||||||
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
|
||||||
|
tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
||||||
state.end()
|
state.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,27 +722,17 @@ impl Serialize for SystemTime {
|
|||||||
/// statically known to never have more than a constant `MAX_LEN` bytes.
|
/// statically known to never have more than a constant `MAX_LEN` bytes.
|
||||||
///
|
///
|
||||||
/// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes.
|
/// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
macro_rules! serialize_display_bounded_length {
|
macro_rules! serialize_display_bounded_length {
|
||||||
($value:expr, $max:expr, $serializer:expr) => {{
|
($value:expr, $max:expr, $serializer:expr) => {{
|
||||||
let mut buffer = [0u8; $max];
|
let mut buffer = [0u8; $max];
|
||||||
let remaining_len = {
|
let mut writer = crate::format::Buf::new(&mut buffer);
|
||||||
let mut remaining = &mut buffer[..];
|
write!(&mut writer, "{}", $value).unwrap();
|
||||||
write!(remaining, "{}", $value).unwrap();
|
$serializer.serialize_str(writer.as_str())
|
||||||
remaining.len()
|
|
||||||
};
|
|
||||||
let written_len = buffer.len() - remaining_len;
|
|
||||||
let written = &buffer[..written_len];
|
|
||||||
|
|
||||||
// write! only provides fmt::Formatter to Display implementations, which
|
|
||||||
// has methods write_str and write_char but no method to write arbitrary
|
|
||||||
// bytes. Therefore `written` must be valid UTF-8.
|
|
||||||
let written_str = str::from_utf8(written).expect("must be valid UTF-8");
|
|
||||||
$serializer.serialize_str(written_str)
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::IpAddr {
|
impl Serialize for net::IpAddr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -674,15 +756,15 @@ impl Serialize for net::IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
const DEC_DIGITS_LUT: &'static [u8] = b"\
|
const DEC_DIGITS_LUT: &[u8] = b"\
|
||||||
0001020304050607080910111213141516171819\
|
0001020304050607080910111213141516171819\
|
||||||
2021222324252627282930313233343536373839\
|
2021222324252627282930313233343536373839\
|
||||||
4041424344454647484950515253545556575859\
|
4041424344454647484950515253545556575859\
|
||||||
6061626364656667686970717273747576777879\
|
6061626364656667686970717273747576777879\
|
||||||
8081828384858687888990919293949596979899";
|
8081828384858687888990919293949596979899";
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||||
if n >= 100 {
|
if n >= 100 {
|
||||||
@@ -703,7 +785,7 @@ fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_u8() {
|
fn test_format_u8() {
|
||||||
let mut i = 0u8;
|
let mut i = 0u8;
|
||||||
@@ -720,7 +802,7 @@ fn test_format_u8() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::Ipv4Addr {
|
impl Serialize for net::Ipv4Addr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -735,15 +817,16 @@ impl Serialize for net::Ipv4Addr {
|
|||||||
// Skip over delimiters that we initialized buf with
|
// Skip over delimiters that we initialized buf with
|
||||||
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
|
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
|
||||||
}
|
}
|
||||||
// We've only written ASCII bytes to the buffer, so it is valid UTF-8
|
// Safety: We've only written ASCII bytes to the buffer, so it is valid UTF-8
|
||||||
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
|
let buf = unsafe { str::from_utf8_unchecked(&buf[..written]) };
|
||||||
|
serializer.serialize_str(buf)
|
||||||
} else {
|
} else {
|
||||||
self.octets().serialize(serializer)
|
self.octets().serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::Ipv6Addr {
|
impl Serialize for net::Ipv6Addr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -759,7 +842,7 @@ impl Serialize for net::Ipv6Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::SocketAddr {
|
impl Serialize for net::SocketAddr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -783,7 +866,7 @@ impl Serialize for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::SocketAddrV4 {
|
impl Serialize for net::SocketAddrV4 {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -799,7 +882,7 @@ impl Serialize for net::SocketAddrV4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||||
impl Serialize for net::SocketAddrV6 {
|
impl Serialize for net::SocketAddrV6 {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -821,6 +904,7 @@ impl Serialize for net::SocketAddrV6 {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for Path {
|
impl Serialize for Path {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -834,6 +918,7 @@ impl Serialize for Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for PathBuf {
|
impl Serialize for PathBuf {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -844,6 +929,7 @@ impl Serialize for PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
impl Serialize for OsStr {
|
impl Serialize for OsStr {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -866,6 +952,7 @@ impl Serialize for OsStr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
impl Serialize for OsString {
|
impl Serialize for OsString {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -890,7 +977,20 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(no_core_reverse))]
|
#[cfg(not(no_core_num_saturating))]
|
||||||
|
impl<T> Serialize for Saturating<T>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
self.0.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Serialize for Reverse<T>
|
impl<T> Serialize for Reverse<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -908,15 +1008,17 @@ where
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
||||||
macro_rules! atomic_impl {
|
macro_rules! atomic_impl {
|
||||||
($($ty:ident)*) => {
|
($($ty:ident $size:expr)*) => {
|
||||||
$(
|
$(
|
||||||
|
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))]
|
||||||
impl Serialize for $ty {
|
impl Serialize for $ty {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
// Matches the atomic ordering used in libcore for the Debug impl
|
// Matches the atomic ordering used in libcore for the Debug impl
|
||||||
self.load(Ordering::SeqCst).serialize(serializer)
|
self.load(Ordering::Relaxed).serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
@@ -925,12 +1027,19 @@ macro_rules! atomic_impl {
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
||||||
atomic_impl! {
|
atomic_impl! {
|
||||||
AtomicBool
|
AtomicBool "8"
|
||||||
AtomicI8 AtomicI16 AtomicI32 AtomicIsize
|
AtomicI8 "8"
|
||||||
AtomicU8 AtomicU16 AtomicU32 AtomicUsize
|
AtomicI16 "16"
|
||||||
|
AtomicI32 "32"
|
||||||
|
AtomicIsize "ptr"
|
||||||
|
AtomicU8 "8"
|
||||||
|
AtomicU16 "16"
|
||||||
|
AtomicU32 "32"
|
||||||
|
AtomicUsize "ptr"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(no_std_atomic64)))]
|
#[cfg(all(feature = "std", not(no_std_atomic64)))]
|
||||||
atomic_impl! {
|
atomic_impl! {
|
||||||
AtomicI64 AtomicU64
|
AtomicI64 "64"
|
||||||
|
AtomicU64 "64"
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
//! This module contains `Impossible` serializer and its implementations.
|
//! This module contains `Impossible` serializer and its implementations.
|
||||||
|
|
||||||
use lib::*;
|
use crate::lib::*;
|
||||||
|
|
||||||
use ser::{
|
use crate::ser::{
|
||||||
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
|
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
|
||||||
};
|
};
|
||||||
@@ -15,9 +15,9 @@ use ser::{
|
|||||||
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
|
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
|
||||||
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
|
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// # use serde::ser::{Serializer, Impossible};
|
/// # use serde::ser::{Serializer, Impossible};
|
||||||
/// # use serde::__private::doc::Error;
|
/// # use serde_core::__private::doc::Error;
|
||||||
/// #
|
/// #
|
||||||
/// # struct MySerializer;
|
/// # struct MySerializer;
|
||||||
/// #
|
/// #
|
||||||
@@ -41,7 +41,7 @@ use ser::{
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /* other Serializer methods */
|
/// /* other Serializer methods */
|
||||||
/// # serde::__serialize_unimplemented! {
|
/// # serde_core::__serialize_unimplemented! {
|
||||||
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
|
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
|
||||||
/// # unit unit_struct unit_variant newtype_struct newtype_variant
|
/// # unit unit_struct unit_variant newtype_struct newtype_variant
|
||||||
/// # tuple tuple_struct tuple_variant map struct struct_variant
|
/// # tuple tuple_struct tuple_variant map struct struct_variant
|
||||||
@@ -49,14 +49,14 @@ use ser::{
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Serializer`]: trait.Serializer.html
|
/// [`Serializer`]: crate::Serializer
|
||||||
/// [`SerializeSeq`]: trait.SerializeSeq.html
|
/// [`SerializeSeq`]: crate::ser::SerializeSeq
|
||||||
/// [`SerializeTuple`]: trait.SerializeTuple.html
|
/// [`SerializeTuple`]: crate::ser::SerializeTuple
|
||||||
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
|
/// [`SerializeTupleStruct`]: crate::ser::SerializeTupleStruct
|
||||||
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
|
/// [`SerializeTupleVariant`]: crate::ser::SerializeTupleVariant
|
||||||
/// [`SerializeMap`]: trait.SerializeMap.html
|
/// [`SerializeMap`]: crate::ser::SerializeMap
|
||||||
/// [`SerializeStruct`]: trait.SerializeStruct.html
|
/// [`SerializeStruct`]: crate::ser::SerializeStruct
|
||||||
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
|
/// [`SerializeStructVariant`]: crate::ser::SerializeStructVariant
|
||||||
pub struct Impossible<Ok, Error> {
|
pub struct Impossible<Ok, Error> {
|
||||||
void: Void,
|
void: Void,
|
||||||
ok: PhantomData<Ok>,
|
ok: PhantomData<Ok>,
|
||||||
@@ -72,9 +72,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = value;
|
let _ = value;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
@@ -92,9 +92,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = value;
|
let _ = value;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
@@ -112,9 +112,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = value;
|
let _ = value;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
@@ -132,9 +132,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = value;
|
let _ = value;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
@@ -152,17 +152,17 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
|
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = key;
|
let _ = key;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = value;
|
let _ = value;
|
||||||
match self.void {}
|
match self.void {}
|
||||||
@@ -180,9 +180,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = key;
|
let _ = key;
|
||||||
let _ = value;
|
let _ = value;
|
||||||
@@ -201,9 +201,9 @@ where
|
|||||||
type Ok = Ok;
|
type Ok = Ok;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: ?Sized + Serialize,
|
||||||
{
|
{
|
||||||
let _ = key;
|
let _ = key;
|
||||||
let _ = value;
|
let _ = value;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
use lib::{Debug, Display};
|
use crate::lib::{Debug, Display};
|
||||||
|
|
||||||
/// Either a re-export of std::error::Error or a new identical trait, depending
|
/// Either a re-export of std::error::Error or a new identical trait, depending
|
||||||
/// on whether Serde's "std" feature is enabled.
|
/// on whether Serde's "std" feature is enabled.
|
||||||
@@ -9,7 +9,7 @@ use lib::{Debug, Display};
|
|||||||
/// generally provide their error types with a `std::error::Error` impl
|
/// generally provide their error types with a `std::error::Error` impl
|
||||||
/// directly:
|
/// directly:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// #[derive(Debug)]
|
/// #[derive(Debug)]
|
||||||
/// struct MySerError {...}
|
/// struct MySerError {...}
|
||||||
///
|
///
|
||||||
@@ -29,7 +29,7 @@ use lib::{Debug, Display};
|
|||||||
/// std = ["serde/std"]
|
/// std = ["serde/std"]
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// #[cfg(feature = "std")]
|
/// #[cfg(feature = "std")]
|
||||||
/// impl std::error::Error for MySerError {}
|
/// impl std::error::Error for MySerError {}
|
||||||
/// ```
|
/// ```
|
||||||
@@ -37,12 +37,12 @@ use lib::{Debug, Display};
|
|||||||
/// ... or else provide the std Error impl unconditionally via Serde's
|
/// ... or else provide the std Error impl unconditionally via Serde's
|
||||||
/// re-export:
|
/// re-export:
|
||||||
///
|
///
|
||||||
/// ```edition2018
|
/// ```edition2021
|
||||||
/// impl serde::ser::StdError for MySerError {}
|
/// impl serde::ser::StdError for MySerError {}
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Error: Debug + Display {
|
pub trait Error: Debug + Display {
|
||||||
/// The underlying cause of this error, if any.
|
/// The underlying cause of this error, if any.
|
||||||
fn source(&self) -> Option<&(Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
msrv = "1.31.0"
|
|
||||||
+21
-11
@@ -1,16 +1,18 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.137" # remember to update html_root_url
|
version = "1.0.228"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
rust-version = "1.31"
|
categories = ["no-std", "no-std::no-alloc"]
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
homepage = "https://serde.rs"
|
|
||||||
repository = "https://github.com/serde-rs/serde"
|
|
||||||
documentation = "https://serde.rs/derive.html"
|
documentation = "https://serde.rs/derive.html"
|
||||||
keywords = ["serde", "serialization", "no_std"]
|
edition = "2021"
|
||||||
|
exclude = ["build.rs"]
|
||||||
|
homepage = "https://serde.rs"
|
||||||
|
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
readme = "crates-io.md"
|
readme = "crates-io.md"
|
||||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
rust-version = "1.68"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
@@ -21,12 +23,20 @@ name = "serde_derive"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = { workspace = true, features = ["proc-macro"] }
|
||||||
quote = "1.0"
|
quote = { workspace = true, features = ["proc-macro"] }
|
||||||
syn = "1.0.90"
|
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = { version = "1.0", path = "../serde" }
|
serde = { version = "1", path = "../serde" }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
rustdoc-args = [
|
||||||
|
"--generate-link-to-definition",
|
||||||
|
"--generate-macro-expansion",
|
||||||
|
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=proc_macro=https://doc.rust-lang.org",
|
||||||
|
]
|
||||||
|
|||||||
+5
-33
@@ -1,36 +1,8 @@
|
|||||||
use std::env;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
|
||||||
// opening a GitHub issue if your build environment requires some way to enable
|
|
||||||
// these cfgs other than by executing our build script.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let minor = match rustc_minor_version() {
|
// Warning: build.rs is not published to crates.io.
|
||||||
Some(minor) => minor,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Underscore const names stabilized in Rust 1.37:
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
// https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros
|
println!("cargo:rustc-cfg=check_cfg");
|
||||||
if minor >= 37 {
|
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
|
||||||
println!("cargo:rustc-cfg=underscore_consts");
|
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
|
||||||
}
|
|
||||||
|
|
||||||
// The ptr::addr_of! macro stabilized in Rust 1.51:
|
|
||||||
// https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis
|
|
||||||
if minor >= 51 {
|
|
||||||
println!("cargo:rustc-cfg=ptr_addr_of");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rustc_minor_version() -> Option<u32> {
|
|
||||||
let rustc = env::var_os("RUSTC")?;
|
|
||||||
let output = Command::new(rustc).arg("--version").output().ok()?;
|
|
||||||
let version = str::from_utf8(&output.stdout).ok()?;
|
|
||||||
let mut pieces = version.split('.');
|
|
||||||
if pieces.next() != Some("rustc 1") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
pieces.next()?.parse().ok()
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-15
@@ -1,12 +1,9 @@
|
|||||||
use std::collections::HashSet;
|
use crate::internals::ast::{Container, Data};
|
||||||
|
use crate::internals::{attr, ungroup};
|
||||||
use syn;
|
|
||||||
use syn::punctuated::{Pair, Punctuated};
|
|
||||||
|
|
||||||
use internals::ast::{Container, Data};
|
|
||||||
use internals::{attr, ungroup};
|
|
||||||
|
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use syn::punctuated::{Pair, Punctuated};
|
||||||
|
use syn::Token;
|
||||||
|
|
||||||
// Remove the default from every type parameter because in the generated impls
|
// Remove the default from every type parameter because in the generated impls
|
||||||
// they look like associated types: "error: associated type bindings are not
|
// they look like associated types: "error: associated type bindings are not
|
||||||
@@ -147,6 +144,7 @@ pub fn with_bound(
|
|||||||
|
|
||||||
fn visit_type(&mut self, ty: &'ast syn::Type) {
|
fn visit_type(&mut self, ty: &'ast syn::Type) {
|
||||||
match ty {
|
match ty {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
syn::Type::Array(ty) => self.visit_type(&ty.elem),
|
syn::Type::Array(ty) => self.visit_type(&ty.elem),
|
||||||
syn::Type::BareFn(ty) => {
|
syn::Type::BareFn(ty) => {
|
||||||
for arg in &ty.inputs {
|
for arg in &ty.inputs {
|
||||||
@@ -184,7 +182,6 @@ pub fn with_bound(
|
|||||||
|
|
||||||
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
|
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
|
||||||
|
|
||||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,11 +196,14 @@ pub fn with_bound(
|
|||||||
syn::PathArguments::AngleBracketed(arguments) => {
|
syn::PathArguments::AngleBracketed(arguments) => {
|
||||||
for arg in &arguments.args {
|
for arg in &arguments.args {
|
||||||
match arg {
|
match arg {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
syn::GenericArgument::Type(arg) => self.visit_type(arg),
|
syn::GenericArgument::Type(arg) => self.visit_type(arg),
|
||||||
syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty),
|
syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty),
|
||||||
syn::GenericArgument::Lifetime(_)
|
syn::GenericArgument::Lifetime(_)
|
||||||
| syn::GenericArgument::Constraint(_)
|
| syn::GenericArgument::Const(_)
|
||||||
| syn::GenericArgument::Const(_) => {}
|
| syn::GenericArgument::AssocConst(_)
|
||||||
|
| syn::GenericArgument::Constraint(_) => {}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,8 +225,12 @@ pub fn with_bound(
|
|||||||
|
|
||||||
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
|
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
|
||||||
match bound {
|
match bound {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
|
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
|
||||||
syn::TypeParamBound::Lifetime(_) => {}
|
syn::TypeParamBound::Lifetime(_)
|
||||||
|
| syn::TypeParamBound::PreciseCapture(_)
|
||||||
|
| syn::TypeParamBound::Verbatim(_) => {}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +255,7 @@ pub fn with_bound(
|
|||||||
};
|
};
|
||||||
match &cont.data {
|
match &cont.data {
|
||||||
Data::Enum(variants) => {
|
Data::Enum(variants) => {
|
||||||
for variant in variants.iter() {
|
for variant in variants {
|
||||||
let relevant_fields = variant
|
let relevant_fields = variant
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
@@ -334,7 +338,7 @@ pub fn with_self_bound(
|
|||||||
|
|
||||||
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
||||||
let bound = syn::Lifetime::new(lifetime, Span::call_site());
|
let bound = syn::Lifetime::new(lifetime, Span::call_site());
|
||||||
let def = syn::LifetimeDef {
|
let def = syn::LifetimeParam {
|
||||||
attrs: Vec::new(),
|
attrs: Vec::new(),
|
||||||
lifetime: bound.clone(),
|
lifetime: bound.clone(),
|
||||||
colon_token: None,
|
colon_token: None,
|
||||||
|
|||||||
+249
-2405
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
|||||||
|
use crate::de::enum_adjacently;
|
||||||
|
use crate::de::enum_externally;
|
||||||
|
use crate::de::enum_internally;
|
||||||
|
use crate::de::enum_untagged;
|
||||||
|
use crate::de::identifier;
|
||||||
|
use crate::de::{field_i, FieldWithAliases, Parameters};
|
||||||
|
use crate::fragment::{Expr, Fragment, Stmts};
|
||||||
|
use crate::internals::ast::Variant;
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
// The variants have already been checked (in ast.rs) that all untagged variants appear at the end
|
||||||
|
match variants.iter().position(|var| var.attrs.untagged()) {
|
||||||
|
Some(variant_idx) => {
|
||||||
|
let (tagged, untagged) = variants.split_at(variant_idx);
|
||||||
|
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
|
||||||
|
// Ignore any error associated with non-untagged deserialization so that we
|
||||||
|
// can fall through to the untagged variants. This may be infallible so we
|
||||||
|
// need to provide the error type.
|
||||||
|
let first_attempt = quote! {
|
||||||
|
if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
|
||||||
|
return _serde::#private::Ok(__ok);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
enum_untagged::deserialize(params, untagged, cattrs, Some(first_attempt))
|
||||||
|
}
|
||||||
|
None => deserialize_homogeneous_enum(params, variants, cattrs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_homogeneous_enum(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
match cattrs.tag() {
|
||||||
|
attr::TagType::External => enum_externally::deserialize(params, variants, cattrs),
|
||||||
|
attr::TagType::Internal { tag } => {
|
||||||
|
enum_internally::deserialize(params, variants, cattrs, tag)
|
||||||
|
}
|
||||||
|
attr::TagType::Adjacent { tag, content } => {
|
||||||
|
enum_adjacently::deserialize(params, variants, cattrs, tag, content)
|
||||||
|
}
|
||||||
|
attr::TagType::None => enum_untagged::deserialize(params, variants, cattrs, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||||
|
let deserialized_variants = variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
|
||||||
|
|
||||||
|
let fallthrough = deserialized_variants
|
||||||
|
.clone()
|
||||||
|
.find(|(_i, variant)| variant.attrs.other())
|
||||||
|
.map(|(i, _variant)| {
|
||||||
|
let ignore_variant = field_i(i);
|
||||||
|
quote!(_serde::#private::Ok(__Field::#ignore_variant))
|
||||||
|
});
|
||||||
|
|
||||||
|
let variants_stmt = {
|
||||||
|
let variant_names = deserialized_variants
|
||||||
|
.clone()
|
||||||
|
.flat_map(|(_i, variant)| variant.attrs.aliases());
|
||||||
|
quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let deserialized_variants: Vec<_> = deserialized_variants
|
||||||
|
.map(|(i, variant)| FieldWithAliases {
|
||||||
|
ident: field_i(i),
|
||||||
|
aliases: variant.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let variant_visitor = Stmts(identifier::deserialize_generated(
|
||||||
|
&deserialized_variants,
|
||||||
|
false, // variant identifiers do not depend on the presence of flatten fields
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
fallthrough,
|
||||||
|
));
|
||||||
|
|
||||||
|
(variants_stmt, variant_visitor)
|
||||||
|
}
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
//! Deserialization for adjacently tagged enums:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! #[serde(tag = "...", content = "...")]
|
||||||
|
//! enum Enum {}
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::de::enum_;
|
||||||
|
use crate::de::enum_untagged;
|
||||||
|
use crate::de::{field_i, Parameters};
|
||||||
|
use crate::fragment::{Fragment, Match};
|
||||||
|
use crate::internals::ast::{Style, Variant};
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag, content)]` attributes
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
tag: &str,
|
||||||
|
content: &str,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||||
|
|
||||||
|
let variant_arms: &Vec<_> = &variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||||
|
.map(|(i, variant)| {
|
||||||
|
let variant_index = field_i(i);
|
||||||
|
|
||||||
|
let block = Match(enum_untagged::deserialize_variant(params, variant, cattrs));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
__Field::#variant_index => #block
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rust_name = params.type_name();
|
||||||
|
let expecting = format!("adjacently tagged enum {}", rust_name);
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
let deny_unknown_fields = cattrs.deny_unknown_fields();
|
||||||
|
|
||||||
|
// If unknown fields are allowed, we pick the visitor that can step over
|
||||||
|
// those. Otherwise we pick the visitor that fails on unknown keys.
|
||||||
|
let field_visitor_ty = if deny_unknown_fields {
|
||||||
|
quote! { _serde::#private::de::TagOrContentFieldVisitor }
|
||||||
|
} else {
|
||||||
|
quote! { _serde::#private::de::TagContentOtherFieldVisitor }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut missing_content = quote! {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
|
||||||
|
};
|
||||||
|
let mut missing_content_fallthrough = quote!();
|
||||||
|
let missing_content_arms = variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||||
|
.filter_map(|(i, variant)| {
|
||||||
|
let variant_index = field_i(i);
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
|
let arm = match variant.style {
|
||||||
|
Style::Unit => quote! {
|
||||||
|
_serde::#private::Ok(#this_value::#variant_ident)
|
||||||
|
},
|
||||||
|
Style::Newtype if variant.attrs.deserialize_with().is_none() => {
|
||||||
|
let span = variant.original.span();
|
||||||
|
let func = quote_spanned!(span=> _serde::#private::de::missing_field);
|
||||||
|
quote! {
|
||||||
|
#func(#content).map(#this_value::#variant_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
missing_content_fallthrough = quote!(_ => #missing_content);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(quote! {
|
||||||
|
__Field::#variant_index => #arm,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if !missing_content_arms.is_empty() {
|
||||||
|
missing_content = quote! {
|
||||||
|
match __field {
|
||||||
|
#(#missing_content_arms)*
|
||||||
|
#missing_content_fallthrough
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance the map by one key, returning early in case of error.
|
||||||
|
let next_key = quote! {
|
||||||
|
_serde::de::MapAccess::next_key_seed(&mut __map, #field_visitor_ty {
|
||||||
|
tag: #tag,
|
||||||
|
content: #content,
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
|
let variant_from_map = quote! {
|
||||||
|
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
|
||||||
|
enum_name: #rust_name,
|
||||||
|
variants: VARIANTS,
|
||||||
|
fields_enum: _serde::#private::PhantomData
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
|
// When allowing unknown fields, we want to transparently step through keys
|
||||||
|
// we don't care about until we find `tag`, `content`, or run out of keys.
|
||||||
|
let next_relevant_key = if deny_unknown_fields {
|
||||||
|
next_key
|
||||||
|
} else {
|
||||||
|
quote!({
|
||||||
|
let mut __rk : _serde::#private::Option<_serde::#private::de::TagOrContentField> = _serde::#private::None;
|
||||||
|
while let _serde::#private::Some(__k) = #next_key {
|
||||||
|
match __k {
|
||||||
|
_serde::#private::de::TagContentOtherField::Other => {
|
||||||
|
let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
_serde::#private::de::TagContentOtherField::Tag => {
|
||||||
|
__rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_serde::#private::de::TagContentOtherField::Content => {
|
||||||
|
__rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Content);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__rk
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step through remaining keys, looking for duplicates of previously-seen
|
||||||
|
// keys. When unknown fields are denied, any key that isn't a duplicate will
|
||||||
|
// at this point immediately produce an error.
|
||||||
|
let visit_remaining_keys = quote! {
|
||||||
|
match #next_relevant_key {
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
||||||
|
}
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content))
|
||||||
|
}
|
||||||
|
_serde::#private::None => _serde::#private::Ok(__ret),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let finish_content_then_tag = if variant_arms.is_empty() {
|
||||||
|
quote! {
|
||||||
|
match #variant_from_map {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
let __seed = __Seed {
|
||||||
|
variant: #variant_from_map,
|
||||||
|
marker: _serde::#private::PhantomData,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
};
|
||||||
|
let __deserializer = _serde::#private::de::ContentDeserializer::<__A::Error>::new(__content);
|
||||||
|
let __ret = _serde::de::DeserializeSeed::deserialize(__seed, __deserializer)?;
|
||||||
|
// Visit remaining keys, looking for duplicates.
|
||||||
|
#visit_remaining_keys
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#variant_visitor
|
||||||
|
|
||||||
|
#variants_stmt
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Seed #de_impl_generics #where_clause {
|
||||||
|
variant: __Field,
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result<Self::Value, __D::Error>
|
||||||
|
where
|
||||||
|
__D: _serde::Deserializer<#delife>,
|
||||||
|
{
|
||||||
|
match self.variant {
|
||||||
|
#(#variant_arms)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::MapAccess<#delife>,
|
||||||
|
{
|
||||||
|
// Visit the first relevant key.
|
||||||
|
match #next_relevant_key {
|
||||||
|
// First key is the tag.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
|
||||||
|
// Parse the tag.
|
||||||
|
let __field = #variant_from_map;
|
||||||
|
// Visit the second key.
|
||||||
|
match #next_relevant_key {
|
||||||
|
// Second key is a duplicate of the tag.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
||||||
|
}
|
||||||
|
// Second key is the content.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
|
||||||
|
let __ret = _serde::de::MapAccess::next_value_seed(&mut __map,
|
||||||
|
__Seed {
|
||||||
|
variant: __field,
|
||||||
|
marker: _serde::#private::PhantomData,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
})?;
|
||||||
|
// Visit remaining keys, looking for duplicates.
|
||||||
|
#visit_remaining_keys
|
||||||
|
}
|
||||||
|
// There is no second key; might be okay if the we have a unit variant.
|
||||||
|
_serde::#private::None => #missing_content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// First key is the content.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
|
||||||
|
// Buffer up the content.
|
||||||
|
let __content = _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?;
|
||||||
|
// Visit the second key.
|
||||||
|
match #next_relevant_key {
|
||||||
|
// Second key is the tag.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
|
||||||
|
#finish_content_then_tag
|
||||||
|
}
|
||||||
|
// Second key is a duplicate of the content.
|
||||||
|
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content))
|
||||||
|
}
|
||||||
|
// There is no second key.
|
||||||
|
_serde::#private::None => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There is no first key.
|
||||||
|
_serde::#private::None => {
|
||||||
|
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<__A>(self, mut __seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
// Visit the first element - the tag.
|
||||||
|
match _serde::de::SeqAccess::next_element(&mut __seq) {
|
||||||
|
_serde::#private::Ok(_serde::#private::Some(__variant)) => {
|
||||||
|
// Visit the second element - the content.
|
||||||
|
match _serde::de::SeqAccess::next_element_seed(
|
||||||
|
&mut __seq,
|
||||||
|
__Seed {
|
||||||
|
variant: __variant,
|
||||||
|
marker: _serde::#private::PhantomData,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
_serde::#private::Ok(_serde::#private::Some(__ret)) => _serde::#private::Ok(__ret),
|
||||||
|
// There is no second element.
|
||||||
|
_serde::#private::Ok(_serde::#private::None) => {
|
||||||
|
_serde::#private::Err(_serde::de::Error::invalid_length(1, &self))
|
||||||
|
}
|
||||||
|
_serde::#private::Err(__err) => _serde::#private::Err(__err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There is no first element.
|
||||||
|
_serde::#private::Ok(_serde::#private::None) => {
|
||||||
|
_serde::#private::Err(_serde::de::Error::invalid_length(0, &self))
|
||||||
|
}
|
||||||
|
_serde::#private::Err(__err) => _serde::#private::Err(__err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[#tag, #content];
|
||||||
|
_serde::Deserializer::deserialize_struct(
|
||||||
|
__deserializer,
|
||||||
|
#type_name,
|
||||||
|
FIELDS,
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
//! Deserialization for externally tagged enums:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! enum Enum {}
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::de::enum_;
|
||||||
|
use crate::de::struct_;
|
||||||
|
use crate::de::tuple;
|
||||||
|
use crate::de::{
|
||||||
|
expr_is_missing, field_i, unwrap_to_variant_closure, wrap_deserialize_field_with,
|
||||||
|
wrap_deserialize_with, Parameters, StructForm, TupleForm,
|
||||||
|
};
|
||||||
|
use crate::fragment::{Expr, Fragment, Match};
|
||||||
|
use crate::internals::ast::{Field, Style, Variant};
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` without additional attributes
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
let expecting = format!("enum {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||||
|
|
||||||
|
// Match arms to extract a variant from a string
|
||||||
|
let variant_arms = variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||||
|
.map(|(i, variant)| {
|
||||||
|
let variant_name = field_i(i);
|
||||||
|
|
||||||
|
let block = Match(deserialize_externally_tagged_variant(
|
||||||
|
params, variant, cattrs,
|
||||||
|
));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
_serde::#private::Ok((__Field::#variant_name, __variant)) => #block
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let all_skipped = variants
|
||||||
|
.iter()
|
||||||
|
.all(|variant| variant.attrs.skip_deserializing());
|
||||||
|
let match_variant = if all_skipped {
|
||||||
|
// This is an empty enum like `enum Impossible {}` or an enum in which
|
||||||
|
// all variants have `#[serde(skip_deserializing)]`.
|
||||||
|
quote! {
|
||||||
|
// FIXME: Once feature(exhaustive_patterns) is stable:
|
||||||
|
// let _serde::#private::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data);
|
||||||
|
// _serde::#private::Err(__err)
|
||||||
|
_serde::#private::Result::map(
|
||||||
|
_serde::de::EnumAccess::variant::<__Field>(__data),
|
||||||
|
|(__impossible, _)| match __impossible {})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
match _serde::de::EnumAccess::variant(__data) {
|
||||||
|
#(#variant_arms)*
|
||||||
|
_serde::#private::Err(__err) => _serde::#private::Err(__err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#variant_visitor
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_enum<__A>(self, __data: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::EnumAccess<#delife>,
|
||||||
|
{
|
||||||
|
#match_variant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#variants_stmt
|
||||||
|
|
||||||
|
_serde::Deserializer::deserialize_enum(
|
||||||
|
__deserializer,
|
||||||
|
#type_name,
|
||||||
|
VARIANTS,
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_externally_tagged_variant(
|
||||||
|
params: &Parameters,
|
||||||
|
variant: &Variant,
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
if let Some(path) = variant.attrs.deserialize_with() {
|
||||||
|
let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path);
|
||||||
|
return quote_block! {
|
||||||
|
#wrapper
|
||||||
|
_serde::#private::Result::map(
|
||||||
|
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
|
match variant.style {
|
||||||
|
Style::Unit => {
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
quote_block! {
|
||||||
|
_serde::de::VariantAccess::unit_variant(__variant)?;
|
||||||
|
_serde::#private::Ok(#this_value::#variant_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Newtype => deserialize_externally_tagged_newtype_variant(
|
||||||
|
variant_ident,
|
||||||
|
params,
|
||||||
|
&variant.fields[0],
|
||||||
|
cattrs,
|
||||||
|
),
|
||||||
|
Style::Tuple => tuple::deserialize(
|
||||||
|
params,
|
||||||
|
&variant.fields,
|
||||||
|
cattrs,
|
||||||
|
TupleForm::ExternallyTagged(variant_ident),
|
||||||
|
),
|
||||||
|
Style::Struct => struct_::deserialize(
|
||||||
|
params,
|
||||||
|
&variant.fields,
|
||||||
|
cattrs,
|
||||||
|
StructForm::ExternallyTagged(variant_ident),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_deserialize_variant_with(
|
||||||
|
params: &Parameters,
|
||||||
|
variant: &Variant,
|
||||||
|
deserialize_with: &syn::ExprPath,
|
||||||
|
) -> (TokenStream, TokenStream, TokenStream) {
|
||||||
|
let field_tys = variant.fields.iter().map(|field| field.ty);
|
||||||
|
let (wrapper, wrapper_ty) =
|
||||||
|
wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with);
|
||||||
|
|
||||||
|
let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
|
||||||
|
|
||||||
|
(wrapper, wrapper_ty, unwrap_fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_externally_tagged_newtype_variant(
|
||||||
|
variant_ident: &syn::Ident,
|
||||||
|
params: &Parameters,
|
||||||
|
field: &Field,
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
|
return quote_block! {
|
||||||
|
_serde::de::VariantAccess::unit_variant(__variant)?;
|
||||||
|
_serde::#private::Ok(#this_value::#variant_ident(#default))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let span = field.original.span();
|
||||||
|
let func =
|
||||||
|
quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
|
||||||
|
quote_expr! {
|
||||||
|
_serde::#private::Result::map(#func(__variant), #this_value::#variant_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
|
quote_block! {
|
||||||
|
#wrapper
|
||||||
|
_serde::#private::Result::map(
|
||||||
|
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
|
||||||
|
|__wrapper| #this_value::#variant_ident(__wrapper.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
//! Deserialization for internally tagged enums:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! #[serde(tag = "...")]
|
||||||
|
//! enum Enum {}
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::de::enum_;
|
||||||
|
use crate::de::enum_untagged;
|
||||||
|
use crate::de::struct_;
|
||||||
|
use crate::de::{
|
||||||
|
effective_style, expr_is_missing, field_i, unwrap_to_variant_closure, Parameters, StructForm,
|
||||||
|
};
|
||||||
|
use crate::fragment::{Expr, Fragment, Match};
|
||||||
|
use crate::internals::ast::{Style, Variant};
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
tag: &str,
|
||||||
|
) -> Fragment {
|
||||||
|
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||||
|
|
||||||
|
// Match arms to extract a variant from a string
|
||||||
|
let variant_arms = variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||||
|
.map(|(i, variant)| {
|
||||||
|
let variant_name = field_i(i);
|
||||||
|
|
||||||
|
let block = Match(deserialize_internally_tagged_variant(
|
||||||
|
params, variant, cattrs,
|
||||||
|
));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
__Field::#variant_name => #block
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let expecting = format!("internally tagged enum {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#variant_visitor
|
||||||
|
|
||||||
|
#variants_stmt
|
||||||
|
|
||||||
|
let (__tag, __content) = _serde::Deserializer::deserialize_any(
|
||||||
|
__deserializer,
|
||||||
|
_serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
|
||||||
|
let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content);
|
||||||
|
|
||||||
|
match __tag {
|
||||||
|
#(#variant_arms)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates significant part of the visit_seq and visit_map bodies of visitors
|
||||||
|
// for the variants of internally tagged enum.
|
||||||
|
fn deserialize_internally_tagged_variant(
|
||||||
|
params: &Parameters,
|
||||||
|
variant: &Variant,
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
if let Some(path) = variant.attrs.deserialize_with() {
|
||||||
|
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
|
||||||
|
return quote_block! {
|
||||||
|
_serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
|
match effective_style(variant) {
|
||||||
|
Style::Unit => {
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let type_name = params.type_name();
|
||||||
|
let variant_name = variant.ident.to_string();
|
||||||
|
let default = variant.fields.first().map(|field| {
|
||||||
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
|
quote!((#default))
|
||||||
|
});
|
||||||
|
quote_block! {
|
||||||
|
_serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
|
||||||
|
_serde::#private::Ok(#this_value::#variant_ident #default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Newtype => {
|
||||||
|
enum_untagged::deserialize_newtype_variant(variant_ident, params, &variant.fields[0])
|
||||||
|
}
|
||||||
|
Style::Struct => struct_::deserialize(
|
||||||
|
params,
|
||||||
|
&variant.fields,
|
||||||
|
cattrs,
|
||||||
|
StructForm::InternallyTagged(variant_ident),
|
||||||
|
),
|
||||||
|
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
//! Deserialization for untagged enums:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! #[serde(untagged)]
|
||||||
|
//! enum Enum {}
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::de::struct_;
|
||||||
|
use crate::de::tuple;
|
||||||
|
use crate::de::{
|
||||||
|
effective_style, expr_is_missing, unwrap_to_variant_closure, Parameters, StructForm, TupleForm,
|
||||||
|
};
|
||||||
|
use crate::fragment::{Expr, Fragment};
|
||||||
|
use crate::internals::ast::{Field, Style, Variant};
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(untagged)]` attribute
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
first_attempt: Option<TokenStream>,
|
||||||
|
) -> Fragment {
|
||||||
|
let attempts = variants
|
||||||
|
.iter()
|
||||||
|
.filter(|variant| !variant.attrs.skip_deserializing())
|
||||||
|
.map(|variant| Expr(deserialize_variant(params, variant, cattrs)));
|
||||||
|
// TODO this message could be better by saving the errors from the failed
|
||||||
|
// attempts. The heuristic used by TOML was to count the number of fields
|
||||||
|
// processed before an error, and use the error that happened after the
|
||||||
|
// largest number of fields. I'm not sure I like that. Maybe it would be
|
||||||
|
// better to save all the errors and combine them into one message that
|
||||||
|
// explains why none of the variants matched.
|
||||||
|
let fallthrough_msg = format!(
|
||||||
|
"data did not match any variant of untagged enum {}",
|
||||||
|
params.type_name()
|
||||||
|
);
|
||||||
|
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
|
||||||
|
|
||||||
|
let private2 = private;
|
||||||
|
quote_block! {
|
||||||
|
let __content = _serde::de::DeserializeSeed::deserialize(_serde::#private::de::ContentVisitor::new(), __deserializer)?;
|
||||||
|
let __deserializer = _serde::#private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
|
||||||
|
|
||||||
|
#first_attempt
|
||||||
|
|
||||||
|
#(
|
||||||
|
if let _serde::#private2::Ok(__ok) = #attempts {
|
||||||
|
return _serde::#private2::Ok(__ok);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
_serde::#private::Err(_serde::de::Error::custom(#fallthrough_msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also used by adjacently tagged enums
|
||||||
|
pub(super) fn deserialize_variant(
|
||||||
|
params: &Parameters,
|
||||||
|
variant: &Variant,
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
if let Some(path) = variant.attrs.deserialize_with() {
|
||||||
|
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
|
||||||
|
return quote_block! {
|
||||||
|
_serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
|
match effective_style(variant) {
|
||||||
|
Style::Unit => {
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let type_name = params.type_name();
|
||||||
|
let variant_name = variant.ident.to_string();
|
||||||
|
let default = variant.fields.first().map(|field| {
|
||||||
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
|
quote!((#default))
|
||||||
|
});
|
||||||
|
quote_expr! {
|
||||||
|
match _serde::Deserializer::deserialize_any(
|
||||||
|
__deserializer,
|
||||||
|
_serde::#private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
||||||
|
) {
|
||||||
|
_serde::#private::Ok(()) => _serde::#private::Ok(#this_value::#variant_ident #default),
|
||||||
|
_serde::#private::Err(__err) => _serde::#private::Err(__err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Newtype => deserialize_newtype_variant(variant_ident, params, &variant.fields[0]),
|
||||||
|
Style::Tuple => tuple::deserialize(
|
||||||
|
params,
|
||||||
|
&variant.fields,
|
||||||
|
cattrs,
|
||||||
|
TupleForm::Untagged(variant_ident),
|
||||||
|
),
|
||||||
|
Style::Struct => struct_::deserialize(
|
||||||
|
params,
|
||||||
|
&variant.fields,
|
||||||
|
cattrs,
|
||||||
|
StructForm::Untagged(variant_ident),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also used by internally tagged enums
|
||||||
|
// Implicitly (via `generate_variant`) used by adjacently tagged enums
|
||||||
|
pub(super) fn deserialize_newtype_variant(
|
||||||
|
variant_ident: &syn::Ident,
|
||||||
|
params: &Parameters,
|
||||||
|
field: &Field,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let field_ty = field.ty;
|
||||||
|
match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let span = field.original.span();
|
||||||
|
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
|
||||||
|
quote_expr! {
|
||||||
|
_serde::#private::Result::map(#func(__deserializer), #this_value::#variant_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
quote_block! {
|
||||||
|
let __value: _serde::#private::Result<#field_ty, _> = #path(__deserializer);
|
||||||
|
_serde::#private::Result::map(__value, #this_value::#variant_ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,477 @@
|
|||||||
|
//! Deserialization of struct field identifiers and enum variant identifiers by
|
||||||
|
//! way of a Rust enum.
|
||||||
|
|
||||||
|
use crate::de::{FieldWithAliases, Parameters};
|
||||||
|
use crate::fragment::{Fragment, Stmts};
|
||||||
|
use crate::internals::ast::{Style, Variant};
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::{Literal, TokenStream};
|
||||||
|
use quote::{quote, ToTokens};
|
||||||
|
|
||||||
|
// Generates `Deserialize::deserialize` body for an enum with
|
||||||
|
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
||||||
|
pub(super) fn deserialize_custom(
|
||||||
|
params: &Parameters,
|
||||||
|
variants: &[Variant],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
let is_variant = match cattrs.identifier() {
|
||||||
|
attr::Identifier::Variant => true,
|
||||||
|
attr::Identifier::Field => false,
|
||||||
|
attr::Identifier::No => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let this_type = params.this_type.to_token_stream();
|
||||||
|
let this_value = params.this_value.to_token_stream();
|
||||||
|
|
||||||
|
let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() {
|
||||||
|
let last_ident = &last.ident;
|
||||||
|
if last.attrs.other() {
|
||||||
|
// Process `serde(other)` attribute. It would always be found on the
|
||||||
|
// last variant (checked in `check_identifier`), so all preceding
|
||||||
|
// are ordinary variants.
|
||||||
|
let ordinary = &variants[..variants.len() - 1];
|
||||||
|
let fallthrough = quote!(_serde::#private::Ok(#this_value::#last_ident));
|
||||||
|
(ordinary, Some(fallthrough), None)
|
||||||
|
} else if let Style::Newtype = last.style {
|
||||||
|
let ordinary = &variants[..variants.len() - 1];
|
||||||
|
let fallthrough = |value| {
|
||||||
|
quote! {
|
||||||
|
_serde::#private::Result::map(
|
||||||
|
_serde::Deserialize::deserialize(
|
||||||
|
_serde::#private::de::IdentifierDeserializer::from(#value)
|
||||||
|
),
|
||||||
|
#this_value::#last_ident)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(
|
||||||
|
ordinary,
|
||||||
|
Some(fallthrough(quote!(__value))),
|
||||||
|
Some(fallthrough(quote!(_serde::#private::de::Borrowed(
|
||||||
|
__value
|
||||||
|
)))),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(variants, None, None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(variants, None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let idents_aliases: Vec<_> = ordinary
|
||||||
|
.iter()
|
||||||
|
.map(|variant| FieldWithAliases {
|
||||||
|
ident: variant.ident.clone(),
|
||||||
|
aliases: variant.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let names = idents_aliases.iter().flat_map(|variant| variant.aliases);
|
||||||
|
|
||||||
|
let names_const = if fallthrough.is_some() {
|
||||||
|
None
|
||||||
|
} else if is_variant {
|
||||||
|
let variants = quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
const VARIANTS: &'static [&'static str] = &[ #(#names),* ];
|
||||||
|
};
|
||||||
|
Some(variants)
|
||||||
|
} else {
|
||||||
|
let fields = quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[ #(#names),* ];
|
||||||
|
};
|
||||||
|
Some(fields)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
let visitor_impl = Stmts(deserialize_identifier(
|
||||||
|
&this_value,
|
||||||
|
&idents_aliases,
|
||||||
|
is_variant,
|
||||||
|
fallthrough,
|
||||||
|
fallthrough_borrowed,
|
||||||
|
false,
|
||||||
|
cattrs.expecting(),
|
||||||
|
));
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#names_const
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __FieldVisitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
#visitor_impl
|
||||||
|
}
|
||||||
|
|
||||||
|
let __visitor = __FieldVisitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
};
|
||||||
|
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn deserialize_generated(
|
||||||
|
deserialized_fields: &[FieldWithAliases],
|
||||||
|
has_flatten: bool,
|
||||||
|
is_variant: bool,
|
||||||
|
ignore_variant: Option<TokenStream>,
|
||||||
|
fallthrough: Option<TokenStream>,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_value = quote!(__Field);
|
||||||
|
let field_idents: &Vec<_> = &deserialized_fields
|
||||||
|
.iter()
|
||||||
|
.map(|field| &field.ident)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let visitor_impl = Stmts(deserialize_identifier(
|
||||||
|
&this_value,
|
||||||
|
deserialized_fields,
|
||||||
|
is_variant,
|
||||||
|
fallthrough,
|
||||||
|
None,
|
||||||
|
!is_variant && has_flatten,
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
|
||||||
|
let lifetime = if !is_variant && has_flatten {
|
||||||
|
Some(quote!(<'de>))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
enum __Field #lifetime {
|
||||||
|
#(#field_idents,)*
|
||||||
|
#ignore_variant
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __FieldVisitor;
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
|
||||||
|
type Value = __Field #lifetime;
|
||||||
|
|
||||||
|
#visitor_impl
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
|
||||||
|
#[inline]
|
||||||
|
fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<Self, __D::Error>
|
||||||
|
where
|
||||||
|
__D: _serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_identifier(
|
||||||
|
this_value: &TokenStream,
|
||||||
|
deserialized_fields: &[FieldWithAliases],
|
||||||
|
is_variant: bool,
|
||||||
|
fallthrough: Option<TokenStream>,
|
||||||
|
fallthrough_borrowed: Option<TokenStream>,
|
||||||
|
collect_other_fields: bool,
|
||||||
|
expecting: Option<&str>,
|
||||||
|
) -> Fragment {
|
||||||
|
let str_mapping = deserialized_fields.iter().map(|field| {
|
||||||
|
let ident = &field.ident;
|
||||||
|
let aliases = field.aliases;
|
||||||
|
let private2 = private;
|
||||||
|
// `aliases` also contains a main name
|
||||||
|
quote! {
|
||||||
|
#(
|
||||||
|
#aliases => _serde::#private2::Ok(#this_value::#ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let bytes_mapping = deserialized_fields.iter().map(|field| {
|
||||||
|
let ident = &field.ident;
|
||||||
|
// `aliases` also contains a main name
|
||||||
|
let aliases = field
|
||||||
|
.aliases
|
||||||
|
.iter()
|
||||||
|
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
|
||||||
|
let private2 = private;
|
||||||
|
quote! {
|
||||||
|
#(
|
||||||
|
#aliases => _serde::#private2::Ok(#this_value::#ident),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let expecting = expecting.unwrap_or(if is_variant {
|
||||||
|
"variant identifier"
|
||||||
|
} else {
|
||||||
|
"field identifier"
|
||||||
|
});
|
||||||
|
|
||||||
|
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
let __value = &_serde::#private::from_utf8_lossy(__value);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let (
|
||||||
|
value_as_str_content,
|
||||||
|
value_as_borrowed_str_content,
|
||||||
|
value_as_bytes_content,
|
||||||
|
value_as_borrowed_bytes_content,
|
||||||
|
) = if collect_other_fields {
|
||||||
|
(
|
||||||
|
Some(quote! {
|
||||||
|
let __value = _serde::#private::de::Content::String(_serde::#private::ToString::to_string(__value));
|
||||||
|
}),
|
||||||
|
Some(quote! {
|
||||||
|
let __value = _serde::#private::de::Content::Str(__value);
|
||||||
|
}),
|
||||||
|
Some(quote! {
|
||||||
|
let __value = _serde::#private::de::Content::ByteBuf(__value.to_vec());
|
||||||
|
}),
|
||||||
|
Some(quote! {
|
||||||
|
let __value = _serde::#private::de::Content::Bytes(__value);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(None, None, None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let fallthrough_arm_tokens;
|
||||||
|
let fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
||||||
|
fallthrough
|
||||||
|
} else if is_variant {
|
||||||
|
fallthrough_arm_tokens = quote! {
|
||||||
|
_serde::#private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
|
||||||
|
};
|
||||||
|
&fallthrough_arm_tokens
|
||||||
|
} else {
|
||||||
|
fallthrough_arm_tokens = quote! {
|
||||||
|
_serde::#private::Err(_serde::de::Error::unknown_field(__value, FIELDS))
|
||||||
|
};
|
||||||
|
&fallthrough_arm_tokens
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_other = if collect_other_fields {
|
||||||
|
quote! {
|
||||||
|
fn visit_bool<__E>(self, __value: bool) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Bool(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i8<__E>(self, __value: i8) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I8(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i16<__E>(self, __value: i16) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I16(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i32<__E>(self, __value: i32) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I32(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i64<__E>(self, __value: i64) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I64(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u8<__E>(self, __value: u8) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U8(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u16<__E>(self, __value: u16) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U16(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u32<__E>(self, __value: u32) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U32(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U64(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f32<__E>(self, __value: f32) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F32(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_f64<__E>(self, __value: f64) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F64(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_char<__E>(self, __value: char) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Char(__value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit<__E>(self) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| {
|
||||||
|
let i = i as u64;
|
||||||
|
let ident = &field.ident;
|
||||||
|
quote!(#i => _serde::#private::Ok(#this_value::#ident))
|
||||||
|
});
|
||||||
|
|
||||||
|
let u64_fallthrough_arm_tokens;
|
||||||
|
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
||||||
|
fallthrough
|
||||||
|
} else {
|
||||||
|
let index_expecting = if is_variant { "variant" } else { "field" };
|
||||||
|
let fallthrough_msg = format!(
|
||||||
|
"{} index 0 <= i < {}",
|
||||||
|
index_expecting,
|
||||||
|
deserialized_fields.len(),
|
||||||
|
);
|
||||||
|
u64_fallthrough_arm_tokens = quote! {
|
||||||
|
_serde::#private::Err(_serde::de::Error::invalid_value(
|
||||||
|
_serde::de::Unexpected::Unsigned(__value),
|
||||||
|
&#fallthrough_msg,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
&u64_fallthrough_arm_tokens
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(#u64_mapping,)*
|
||||||
|
_ => #u64_fallthrough_arm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
||||||
|
let str_mapping = str_mapping.clone();
|
||||||
|
let bytes_mapping = bytes_mapping.clone();
|
||||||
|
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
|
||||||
|
Some(quote! {
|
||||||
|
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(#str_mapping)*
|
||||||
|
_ => {
|
||||||
|
#value_as_borrowed_str_content
|
||||||
|
#fallthrough_borrowed_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(#bytes_mapping)*
|
||||||
|
_ => {
|
||||||
|
#bytes_to_str
|
||||||
|
#value_as_borrowed_bytes_content
|
||||||
|
#fallthrough_borrowed_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_other
|
||||||
|
|
||||||
|
fn visit_str<__E>(self, __value: &str) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(#str_mapping)*
|
||||||
|
_ => {
|
||||||
|
#value_as_str_content
|
||||||
|
#fallthrough_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(#bytes_mapping)*
|
||||||
|
_ => {
|
||||||
|
#bytes_to_str
|
||||||
|
#value_as_bytes_content
|
||||||
|
#fallthrough_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_borrowed
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,697 @@
|
|||||||
|
use crate::de::identifier;
|
||||||
|
use crate::de::{
|
||||||
|
deserialize_seq, expr_is_missing, field_i, has_flatten, wrap_deserialize_field_with,
|
||||||
|
FieldWithAliases, Parameters, StructForm,
|
||||||
|
};
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
use crate::de::{deserialize_seq_in_place, place_lifetime};
|
||||||
|
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
||||||
|
use crate::internals::ast::Field;
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for a `struct Struct {...}`
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
form: StructForm,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
// If there are getters (implying private fields), construct the local type
|
||||||
|
// and use an `Into` conversion to get the remote type. If there are no
|
||||||
|
// getters then construct the target type directly.
|
||||||
|
let construct = if params.has_getter {
|
||||||
|
let local = ¶ms.local;
|
||||||
|
quote!(#local)
|
||||||
|
} else {
|
||||||
|
quote!(#this_value)
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_path = match form {
|
||||||
|
StructForm::Struct => construct,
|
||||||
|
StructForm::ExternallyTagged(variant_ident)
|
||||||
|
| StructForm::InternallyTagged(variant_ident)
|
||||||
|
| StructForm::Untagged(variant_ident) => quote!(#construct::#variant_ident),
|
||||||
|
};
|
||||||
|
let expecting = match form {
|
||||||
|
StructForm::Struct => format!("struct {}", params.type_name()),
|
||||||
|
StructForm::ExternallyTagged(variant_ident)
|
||||||
|
| StructForm::InternallyTagged(variant_ident)
|
||||||
|
| StructForm::Untagged(variant_ident) => {
|
||||||
|
format!("struct variant {}::{}", params.type_name(), variant_ident)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let deserialized_fields: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
// Skip fields that shouldn't be deserialized or that were flattened,
|
||||||
|
// so they don't appear in the storage in their literal form
|
||||||
|
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(i, field)| FieldWithAliases {
|
||||||
|
ident: field_i(i),
|
||||||
|
aliases: field.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let has_flatten = has_flatten(fields);
|
||||||
|
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten);
|
||||||
|
|
||||||
|
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||||
|
// structs that only have a map representation.
|
||||||
|
let visit_seq = match form {
|
||||||
|
StructForm::Untagged(_) => None,
|
||||||
|
_ if has_flatten => None,
|
||||||
|
_ => {
|
||||||
|
let mut_seq = if deserialized_fields.is_empty() {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
|
&type_path, params, fields, true, cattrs, expecting,
|
||||||
|
));
|
||||||
|
|
||||||
|
Some(quote! {
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let visit_map = Stmts(deserialize_map(
|
||||||
|
&type_path,
|
||||||
|
params,
|
||||||
|
fields,
|
||||||
|
cattrs,
|
||||||
|
has_flatten,
|
||||||
|
));
|
||||||
|
|
||||||
|
let visitor_seed = match form {
|
||||||
|
StructForm::ExternallyTagged(..) if has_flatten => Some(quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result<Self::Value, __D::Error>
|
||||||
|
where
|
||||||
|
__D: _serde::Deserializer<#delife>,
|
||||||
|
{
|
||||||
|
_serde::Deserializer::deserialize_map(__deserializer, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let fields_stmt = if has_flatten {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||||
|
|
||||||
|
Some(quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let visitor_expr = quote! {
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dispatch = match form {
|
||||||
|
StructForm::Struct if has_flatten => quote! {
|
||||||
|
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::Struct => {
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
quote! {
|
||||||
|
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StructForm::ExternallyTagged(_) if has_flatten => quote! {
|
||||||
|
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::ExternallyTagged(_) => quote! {
|
||||||
|
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::InternallyTagged(_) => quote! {
|
||||||
|
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::Untagged(_) => quote! {
|
||||||
|
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#field_visitor
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_seq
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::MapAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#visitor_seed
|
||||||
|
|
||||||
|
#fields_stmt
|
||||||
|
|
||||||
|
#dispatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map(
|
||||||
|
struct_path: &TokenStream,
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
has_flatten: bool,
|
||||||
|
) -> Fragment {
|
||||||
|
// Create the field names for the fields.
|
||||||
|
let fields_names: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| (field, field_i(i)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Declare each field that will be deserialized.
|
||||||
|
let let_values = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
quote! {
|
||||||
|
let mut #name: _serde::#private::Option<#field_ty> = _serde::#private::None;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Collect contents for flatten fields into a buffer
|
||||||
|
let let_collect = if has_flatten {
|
||||||
|
Some(quote! {
|
||||||
|
let mut __collect = _serde::#private::Vec::<_serde::#private::Option<(
|
||||||
|
_serde::#private::de::Content,
|
||||||
|
_serde::#private::de::Content
|
||||||
|
)>>::new();
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Match arms to extract a value for a field.
|
||||||
|
let value_arms = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let deser_name = field.attrs.name().deserialize_name();
|
||||||
|
|
||||||
|
let visit = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let span = field.original.span();
|
||||||
|
let func =
|
||||||
|
quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
|
||||||
|
quote! {
|
||||||
|
#func(&mut __map)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
|
quote!({
|
||||||
|
#wrapper
|
||||||
|
match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
||||||
|
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
||||||
|
_serde::#private::Err(__err) => {
|
||||||
|
return _serde::#private::Err(__err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
__Field::#name => {
|
||||||
|
if _serde::#private::Option::is_some(&#name) {
|
||||||
|
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
||||||
|
}
|
||||||
|
#name = _serde::#private::Some(#visit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visit ignored values to consume them
|
||||||
|
let ignored_arm = if has_flatten {
|
||||||
|
Some(quote! {
|
||||||
|
__Field::__other(__name) => {
|
||||||
|
__collect.push(_serde::#private::Some((
|
||||||
|
__name,
|
||||||
|
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?)));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if cattrs.deny_unknown_fields() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
||||||
|
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
||||||
|
quote! {
|
||||||
|
// FIXME: Once feature(exhaustive_patterns) is stable:
|
||||||
|
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
||||||
|
_serde::#private::Option::map(
|
||||||
|
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
||||||
|
|__impossible| match __impossible {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
||||||
|
match __key {
|
||||||
|
#(#value_arms)*
|
||||||
|
#ignored_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let extract_values = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let missing_expr = Match(expr_is_missing(field, cattrs));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
let #name = match #name {
|
||||||
|
_serde::#private::Some(#name) => #name,
|
||||||
|
_serde::#private::None => #missing_expr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let extract_collected = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let func = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let span = field.original.span();
|
||||||
|
quote_spanned!(span=> _serde::de::Deserialize::deserialize)
|
||||||
|
}
|
||||||
|
Some(path) => quote!(#path),
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
let #name: #field_ty = #func(
|
||||||
|
_serde::#private::de::FlatMapDeserializer(
|
||||||
|
&mut __collect,
|
||||||
|
_serde::#private::PhantomData))?;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() {
|
||||||
|
Some(quote! {
|
||||||
|
if let _serde::#private::Some(_serde::#private::Some((__key, _))) =
|
||||||
|
__collect.into_iter().filter(_serde::#private::Option::is_some).next()
|
||||||
|
{
|
||||||
|
if let _serde::#private::Some(__key) = _serde::#private::de::content_as_str(&__key) {
|
||||||
|
return _serde::#private::Err(
|
||||||
|
_serde::de::Error::custom(format_args!("unknown field `{}`", &__key)));
|
||||||
|
} else {
|
||||||
|
return _serde::#private::Err(
|
||||||
|
_serde::de::Error::custom(format_args!("unexpected map key")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = fields_names.iter().map(|(field, name)| {
|
||||||
|
let member = &field.member;
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
let value = Expr(expr_is_missing(field, cattrs));
|
||||||
|
quote!(#member: #value)
|
||||||
|
} else {
|
||||||
|
quote!(#member: #name)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let let_default = match cattrs.default() {
|
||||||
|
attr::Default::Default => Some(quote!(
|
||||||
|
let __default: Self::Value = _serde::#private::Default::default();
|
||||||
|
)),
|
||||||
|
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||||
|
// We attach span of the path to the function so it will be reported
|
||||||
|
// on the #[serde(default = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||||
|
let __default: Self::Value = #path();
|
||||||
|
)),
|
||||||
|
attr::Default::None => {
|
||||||
|
// We don't need the default value, to prevent an unused variable warning
|
||||||
|
// we'll leave the line empty.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = quote!(#struct_path { #(#result),* });
|
||||||
|
if params.has_getter {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (_, ty_generics, _) = params.generics.split_for_impl();
|
||||||
|
result = quote! {
|
||||||
|
_serde::#private::Into::<#this_type #ty_generics>::into(#result)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#(#let_values)*
|
||||||
|
|
||||||
|
#let_collect
|
||||||
|
|
||||||
|
#match_keys
|
||||||
|
|
||||||
|
#let_default
|
||||||
|
|
||||||
|
#(#extract_values)*
|
||||||
|
|
||||||
|
#(#extract_collected)*
|
||||||
|
|
||||||
|
#collected_deny_unknown_fields
|
||||||
|
|
||||||
|
_serde::#private::Ok(#result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}`
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
pub(super) fn deserialize_in_place(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Option<Fragment> {
|
||||||
|
// for now we do not support in_place deserialization for structs that
|
||||||
|
// are represented as map.
|
||||||
|
if has_flatten(fields) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let expecting = format!("struct {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let deserialized_fields: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, field)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(i, field)| FieldWithAliases {
|
||||||
|
ident: field_i(i),
|
||||||
|
aliases: field.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false);
|
||||||
|
|
||||||
|
let mut_seq = if deserialized_fields.is_empty() {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||||
|
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
||||||
|
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
|
||||||
|
let in_place_impl_generics = de_impl_generics.in_place();
|
||||||
|
let in_place_ty_generics = de_ty_generics.in_place();
|
||||||
|
let place_life = place_lifetime();
|
||||||
|
|
||||||
|
Some(quote_block! {
|
||||||
|
#field_visitor
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #in_place_impl_generics #where_clause {
|
||||||
|
place: &#place_life mut #this_type #ty_generics,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::MapAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
||||||
|
|
||||||
|
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor {
|
||||||
|
place: __place,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
fn deserialize_map_in_place(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
assert!(
|
||||||
|
!has_flatten(fields),
|
||||||
|
"inplace deserialization of maps does not support flatten fields"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the field names for the fields.
|
||||||
|
let fields_names: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| (field, field_i(i)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// For deserialize_in_place, declare booleans for each field that will be
|
||||||
|
// deserialized.
|
||||||
|
let let_flags = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(_, name)| {
|
||||||
|
quote! {
|
||||||
|
let mut #name: bool = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Match arms to extract a value for a field.
|
||||||
|
let value_arms_from = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let deser_name = field.attrs.name().deserialize_name();
|
||||||
|
let member = &field.member;
|
||||||
|
|
||||||
|
let visit = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
quote! {
|
||||||
|
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::InPlaceSeed(&mut self.place.#member))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
|
quote!({
|
||||||
|
#wrapper
|
||||||
|
self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
||||||
|
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
||||||
|
_serde::#private::Err(__err) => {
|
||||||
|
return _serde::#private::Err(__err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
__Field::#name => {
|
||||||
|
if #name {
|
||||||
|
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
||||||
|
}
|
||||||
|
#visit;
|
||||||
|
#name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visit ignored values to consume them
|
||||||
|
let ignored_arm = if cattrs.deny_unknown_fields() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
||||||
|
|
||||||
|
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
||||||
|
quote! {
|
||||||
|
// FIXME: Once feature(exhaustive_patterns) is stable:
|
||||||
|
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
||||||
|
_serde::#private::Option::map(
|
||||||
|
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
||||||
|
|__impossible| match __impossible {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
||||||
|
match __key {
|
||||||
|
#(#value_arms_from)*
|
||||||
|
#ignored_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_flags = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let missing_expr = expr_is_missing(field, cattrs);
|
||||||
|
// If missing_expr unconditionally returns an error, don't try
|
||||||
|
// to assign its value to self.place.
|
||||||
|
if field.attrs.default().is_none()
|
||||||
|
&& cattrs.default().is_none()
|
||||||
|
&& field.attrs.deserialize_with().is_some()
|
||||||
|
{
|
||||||
|
let missing_expr = Stmts(missing_expr);
|
||||||
|
quote! {
|
||||||
|
if !#name {
|
||||||
|
#missing_expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let member = &field.member;
|
||||||
|
let missing_expr = Expr(missing_expr);
|
||||||
|
quote! {
|
||||||
|
if !#name {
|
||||||
|
self.place.#member = #missing_expr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (_, ty_generics, _) = params.generics.split_for_impl();
|
||||||
|
|
||||||
|
let let_default = match cattrs.default() {
|
||||||
|
attr::Default::Default => Some(quote!(
|
||||||
|
let __default: #this_type #ty_generics = _serde::#private::Default::default();
|
||||||
|
)),
|
||||||
|
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||||
|
// We attach span of the path to the function so it will be reported
|
||||||
|
// on the #[serde(default = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||||
|
let __default: #this_type #ty_generics = #path();
|
||||||
|
)),
|
||||||
|
attr::Default::None => {
|
||||||
|
// We don't need the default value, to prevent an unused variable warning
|
||||||
|
// we'll leave the line empty.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#(#let_flags)*
|
||||||
|
|
||||||
|
#match_keys
|
||||||
|
|
||||||
|
#let_default
|
||||||
|
|
||||||
|
#(#check_flags)*
|
||||||
|
|
||||||
|
_serde::#private::Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates enum and its `Deserialize` implementation that represents each
|
||||||
|
/// non-skipped field of the struct
|
||||||
|
fn deserialize_field_identifier(
|
||||||
|
deserialized_fields: &[FieldWithAliases],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
has_flatten: bool,
|
||||||
|
) -> Stmts {
|
||||||
|
let (ignore_variant, fallthrough) = if has_flatten {
|
||||||
|
let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),);
|
||||||
|
let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value)));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
} else if cattrs.deny_unknown_fields() {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
let ignore_variant = quote!(__ignore,);
|
||||||
|
let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
};
|
||||||
|
|
||||||
|
Stmts(identifier::deserialize_generated(
|
||||||
|
deserialized_fields,
|
||||||
|
has_flatten,
|
||||||
|
false,
|
||||||
|
ignore_variant,
|
||||||
|
fallthrough,
|
||||||
|
))
|
||||||
|
}
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
use crate::de::{deserialize_seq, has_flatten, Parameters, TupleForm};
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
use crate::de::{deserialize_seq_in_place, place_lifetime};
|
||||||
|
use crate::fragment::{Fragment, Stmts};
|
||||||
|
use crate::internals::ast::Field;
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for a `struct Tuple(...);` including `struct Newtype(T);`
|
||||||
|
pub(super) fn deserialize(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
form: TupleForm,
|
||||||
|
) -> Fragment {
|
||||||
|
assert!(
|
||||||
|
!has_flatten(fields),
|
||||||
|
"tuples and tuple variants cannot have flatten fields"
|
||||||
|
);
|
||||||
|
|
||||||
|
let field_count = fields
|
||||||
|
.iter()
|
||||||
|
.filter(|field| !field.attrs.skip_deserializing())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
// If there are getters (implying private fields), construct the local type
|
||||||
|
// and use an `Into` conversion to get the remote type. If there are no
|
||||||
|
// getters then construct the target type directly.
|
||||||
|
let construct = if params.has_getter {
|
||||||
|
let local = ¶ms.local;
|
||||||
|
quote!(#local)
|
||||||
|
} else {
|
||||||
|
quote!(#this_value)
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_path = match form {
|
||||||
|
TupleForm::Tuple => construct,
|
||||||
|
TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident) => {
|
||||||
|
quote!(#construct::#variant_ident)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let expecting = match form {
|
||||||
|
TupleForm::Tuple => format!("tuple struct {}", params.type_name()),
|
||||||
|
TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident) => {
|
||||||
|
format!("tuple variant {}::{}", params.type_name(), variant_ident)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let nfields = fields.len();
|
||||||
|
|
||||||
|
let visit_newtype_struct = match form {
|
||||||
|
TupleForm::Tuple if nfields == 1 => {
|
||||||
|
Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
|
&type_path, params, fields, false, cattrs, expecting,
|
||||||
|
));
|
||||||
|
|
||||||
|
let visitor_expr = quote! {
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dispatch = match form {
|
||||||
|
TupleForm::Tuple if nfields == 1 => {
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
quote! {
|
||||||
|
_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TupleForm::Tuple => {
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
quote! {
|
||||||
|
_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TupleForm::ExternallyTagged(_) => quote! {
|
||||||
|
_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)
|
||||||
|
},
|
||||||
|
TupleForm::Untagged(_) => quote! {
|
||||||
|
_serde::Deserializer::deserialize_tuple(__deserializer, #field_count, #visitor_expr)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let visitor_var = if field_count == 0 {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_newtype_struct
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#dispatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_newtype_struct(
|
||||||
|
type_path: &TokenStream,
|
||||||
|
params: &Parameters,
|
||||||
|
field: &Field,
|
||||||
|
) -> TokenStream {
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let deserializer_var = quote!(__e);
|
||||||
|
|
||||||
|
let value = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let span = field.original.span();
|
||||||
|
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
|
||||||
|
quote! {
|
||||||
|
#func(#deserializer_var)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||||
|
// We attach span of the path to the function so it will be reported
|
||||||
|
// on the #[serde(with = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
quote_spanned! {path.span()=>
|
||||||
|
#path(#deserializer_var)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = quote!(#type_path(__field0));
|
||||||
|
if params.has_getter {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (_, ty_generics, _) = params.generics.split_for_impl();
|
||||||
|
result = quote! {
|
||||||
|
_serde::#private::Into::<#this_type #ty_generics>::into(#result)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::#private::Result<Self::Value, __E::Error>
|
||||||
|
where
|
||||||
|
__E: _serde::Deserializer<#delife>,
|
||||||
|
{
|
||||||
|
let __field0: #field_ty = #value;
|
||||||
|
_serde::#private::Ok(#result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize_in_place` body for a `struct Tuple(...);` including `struct Newtype(T);`
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
pub(super) fn deserialize_in_place(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
assert!(
|
||||||
|
!has_flatten(fields),
|
||||||
|
"tuples and tuple variants cannot have flatten fields"
|
||||||
|
);
|
||||||
|
|
||||||
|
let field_count = fields
|
||||||
|
.iter()
|
||||||
|
.filter(|field| !field.attrs.skip_deserializing())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let expecting = format!("tuple struct {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let nfields = fields.len();
|
||||||
|
|
||||||
|
let visit_newtype_struct = if nfields == 1 {
|
||||||
|
// We do not generate deserialize_in_place if every field has a
|
||||||
|
// deserialize_with.
|
||||||
|
assert!(fields[0].attrs.deserialize_with().is_none());
|
||||||
|
|
||||||
|
Some(quote! {
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::#private::Result<Self::Value, __E::Error>
|
||||||
|
where
|
||||||
|
__E: _serde::Deserializer<#delife>,
|
||||||
|
{
|
||||||
|
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||||
|
|
||||||
|
let visitor_expr = quote! {
|
||||||
|
__Visitor {
|
||||||
|
place: __place,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
let dispatch = if nfields == 1 {
|
||||||
|
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
|
||||||
|
} else {
|
||||||
|
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr))
|
||||||
|
};
|
||||||
|
|
||||||
|
let visitor_var = if field_count == 0 {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
|
||||||
|
let in_place_impl_generics = de_impl_generics.in_place();
|
||||||
|
let in_place_ty_generics = de_ty_generics.in_place();
|
||||||
|
let place_life = place_lifetime();
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #in_place_impl_generics #where_clause {
|
||||||
|
place: &#place_life mut #this_type #ty_generics,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_newtype_struct
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#dispatch
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
use crate::de::Parameters;
|
||||||
|
use crate::fragment::Fragment;
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for a `struct Unit;`
|
||||||
|
pub(super) fn deserialize(params: &Parameters, cattrs: &attr::Container) -> Fragment {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||||
|
params.generics_with_de_lifetime();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let expecting = format!("unit struct {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit<__E>(self) -> _serde::#private::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
_serde::#private::Ok(#this_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_serde::Deserializer::deserialize_unit_struct(
|
||||||
|
__deserializer,
|
||||||
|
#type_name,
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub fn allow_deprecated(input: &syn::DeriveInput) -> Option<TokenStream> {
|
||||||
|
if should_allow_deprecated(input) {
|
||||||
|
Some(quote! { #[allow(deprecated)] })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determine if an `#[allow(deprecated)]` should be added to the derived impl.
|
||||||
|
///
|
||||||
|
/// This should happen if the derive input or an enum variant it contains has
|
||||||
|
/// one of:
|
||||||
|
/// - `#[deprecated]`
|
||||||
|
/// - `#[allow(deprecated)]`
|
||||||
|
fn should_allow_deprecated(input: &syn::DeriveInput) -> bool {
|
||||||
|
if contains_deprecated(&input.attrs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if let syn::Data::Enum(data_enum) = &input.data {
|
||||||
|
for variant in &data_enum.variants {
|
||||||
|
if contains_deprecated(&variant.attrs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the given attributes contains one of:
|
||||||
|
/// - `#[deprecated]`
|
||||||
|
/// - `#[allow(deprecated)]`
|
||||||
|
fn contains_deprecated(attrs: &[syn::Attribute]) -> bool {
|
||||||
|
for attr in attrs {
|
||||||
|
if attr.path().is_ident("deprecated") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if let syn::Meta::List(meta_list) = &attr.meta {
|
||||||
|
if meta_list.path.is_ident("allow") {
|
||||||
|
let mut allow_deprecated = false;
|
||||||
|
let _ = meta_list.parse_nested_meta(|meta| {
|
||||||
|
if meta.path.is_ident("deprecated") {
|
||||||
|
allow_deprecated = true;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
if allow_deprecated {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
+13
-30
@@ -1,23 +1,7 @@
|
|||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::TokenStream;
|
||||||
use quote::format_ident;
|
use quote::quote;
|
||||||
|
|
||||||
use syn;
|
|
||||||
use try;
|
|
||||||
|
|
||||||
pub fn wrap_in_const(
|
|
||||||
serde_path: Option<&syn::Path>,
|
|
||||||
trait_: &str,
|
|
||||||
ty: &Ident,
|
|
||||||
code: TokenStream,
|
|
||||||
) -> TokenStream {
|
|
||||||
let try_replacement = try::replacement();
|
|
||||||
|
|
||||||
let dummy_const = if cfg!(underscore_consts) {
|
|
||||||
format_ident!("_")
|
|
||||||
} else {
|
|
||||||
format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty))
|
|
||||||
};
|
|
||||||
|
|
||||||
|
pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream {
|
||||||
let use_serde = match serde_path {
|
let use_serde = match serde_path {
|
||||||
Some(path) => quote! {
|
Some(path) => quote! {
|
||||||
use #path as _serde;
|
use #path as _serde;
|
||||||
@@ -30,19 +14,18 @@ pub fn wrap_in_const(
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(
|
||||||
const #dummy_const: () = {
|
non_upper_case_globals,
|
||||||
|
unused_attributes,
|
||||||
|
unused_qualifications,
|
||||||
|
clippy::absolute_paths,
|
||||||
|
)]
|
||||||
|
const _: () = {
|
||||||
#use_serde
|
#use_serde
|
||||||
#try_replacement
|
|
||||||
|
_serde::__require_serde_not_serde_core!();
|
||||||
|
|
||||||
#code
|
#code
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn unraw(ident: &Ident) -> String {
|
|
||||||
// str::trim_start_matches was added in 1.30, trim_left_matches deprecated
|
|
||||||
// in 1.33. We currently support rustc back to 1.15 so we need to continue
|
|
||||||
// to use the deprecated one.
|
|
||||||
ident.to_string().trim_left_matches("r#").to_owned()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::token;
|
use syn::{token, Token};
|
||||||
|
|
||||||
pub enum Fragment {
|
pub enum Fragment {
|
||||||
/// Tokens that can be used as an expression.
|
/// Tokens that can be used as an expression.
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
|
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
|
||||||
|
|
||||||
use internals::attr;
|
use crate::internals::{attr, check, Ctxt, Derive};
|
||||||
use internals::check;
|
use proc_macro2::Ident;
|
||||||
use internals::{Ctxt, Derive};
|
|
||||||
use syn;
|
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
|
use syn::Token;
|
||||||
|
|
||||||
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
|
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
|
||||||
/// parsed into an internal representation.
|
/// parsed into an internal representation.
|
||||||
@@ -64,13 +63,17 @@ impl<'a> Container<'a> {
|
|||||||
cx: &Ctxt,
|
cx: &Ctxt,
|
||||||
item: &'a syn::DeriveInput,
|
item: &'a syn::DeriveInput,
|
||||||
derive: Derive,
|
derive: Derive,
|
||||||
|
private: &Ident,
|
||||||
) -> Option<Container<'a>> {
|
) -> Option<Container<'a>> {
|
||||||
let mut attrs = attr::Container::from_ast(cx, item);
|
let attrs = attr::Container::from_ast(cx, item);
|
||||||
|
|
||||||
let mut data = match &item.data {
|
let mut data = match &item.data {
|
||||||
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
|
syn::Data::Enum(data) => {
|
||||||
|
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default(), private))
|
||||||
|
}
|
||||||
syn::Data::Struct(data) => {
|
syn::Data::Struct(data) => {
|
||||||
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
|
let (style, fields) =
|
||||||
|
struct_from_ast(cx, &data.fields, None, attrs.default(), private);
|
||||||
Data::Struct(style, fields)
|
Data::Struct(style, fields)
|
||||||
}
|
}
|
||||||
syn::Data::Union(_) => {
|
syn::Data::Union(_) => {
|
||||||
@@ -79,35 +82,27 @@ impl<'a> Container<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut has_flatten = false;
|
|
||||||
match &mut data {
|
match &mut data {
|
||||||
Data::Enum(variants) => {
|
Data::Enum(variants) => {
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
variant.attrs.rename_by_rules(attrs.rename_all_rules());
|
variant.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||||
for field in &mut variant.fields {
|
for field in &mut variant.fields {
|
||||||
if field.attrs.flatten() {
|
field.attrs.rename_by_rules(
|
||||||
has_flatten = true;
|
variant
|
||||||
}
|
.attrs
|
||||||
field
|
.rename_all_rules()
|
||||||
.attrs
|
.or(attrs.rename_all_fields_rules()),
|
||||||
.rename_by_rules(variant.attrs.rename_all_rules());
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::Struct(_, fields) => {
|
Data::Struct(_, fields) => {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
if field.attrs.flatten() {
|
|
||||||
has_flatten = true;
|
|
||||||
}
|
|
||||||
field.attrs.rename_by_rules(attrs.rename_all_rules());
|
field.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_flatten {
|
|
||||||
attrs.mark_has_flatten();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut item = Container {
|
let mut item = Container {
|
||||||
ident: item.ident.clone(),
|
ident: item.ident.clone(),
|
||||||
attrs,
|
attrs,
|
||||||
@@ -121,7 +116,7 @@ impl<'a> Container<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Data<'a> {
|
impl<'a> Data<'a> {
|
||||||
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
|
pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a Field<'a>> + 'a> {
|
||||||
match self {
|
match self {
|
||||||
Data::Enum(variants) => {
|
Data::Enum(variants) => {
|
||||||
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
||||||
@@ -139,13 +134,19 @@ fn enum_from_ast<'a>(
|
|||||||
cx: &Ctxt,
|
cx: &Ctxt,
|
||||||
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
||||||
container_default: &attr::Default,
|
container_default: &attr::Default,
|
||||||
|
private: &Ident,
|
||||||
) -> Vec<Variant<'a>> {
|
) -> Vec<Variant<'a>> {
|
||||||
variants
|
let variants: Vec<Variant> = variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|variant| {
|
.map(|variant| {
|
||||||
let attrs = attr::Variant::from_ast(cx, variant);
|
let attrs = attr::Variant::from_ast(cx, variant);
|
||||||
let (style, fields) =
|
let (style, fields) = struct_from_ast(
|
||||||
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
|
cx,
|
||||||
|
&variant.fields,
|
||||||
|
Some(&attrs),
|
||||||
|
container_default,
|
||||||
|
private,
|
||||||
|
);
|
||||||
Variant {
|
Variant {
|
||||||
ident: variant.ident.clone(),
|
ident: variant.ident.clone(),
|
||||||
attrs,
|
attrs,
|
||||||
@@ -154,7 +155,20 @@ fn enum_from_ast<'a>(
|
|||||||
original: variant,
|
original: variant,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect();
|
||||||
|
|
||||||
|
let index_of_last_tagged_variant = variants
|
||||||
|
.iter()
|
||||||
|
.rposition(|variant| !variant.attrs.untagged());
|
||||||
|
if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant {
|
||||||
|
for variant in &variants[..index_of_last_tagged_variant] {
|
||||||
|
if variant.attrs.untagged() {
|
||||||
|
cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variants
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_from_ast<'a>(
|
fn struct_from_ast<'a>(
|
||||||
@@ -162,19 +176,20 @@ fn struct_from_ast<'a>(
|
|||||||
fields: &'a syn::Fields,
|
fields: &'a syn::Fields,
|
||||||
attrs: Option<&attr::Variant>,
|
attrs: Option<&attr::Variant>,
|
||||||
container_default: &attr::Default,
|
container_default: &attr::Default,
|
||||||
|
private: &Ident,
|
||||||
) -> (Style, Vec<Field<'a>>) {
|
) -> (Style, Vec<Field<'a>>) {
|
||||||
match fields {
|
match fields {
|
||||||
syn::Fields::Named(fields) => (
|
syn::Fields::Named(fields) => (
|
||||||
Style::Struct,
|
Style::Struct,
|
||||||
fields_from_ast(cx, &fields.named, attrs, container_default),
|
fields_from_ast(cx, &fields.named, attrs, container_default, private),
|
||||||
),
|
),
|
||||||
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
|
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
|
||||||
Style::Newtype,
|
Style::Newtype,
|
||||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
fields_from_ast(cx, &fields.unnamed, attrs, container_default, private),
|
||||||
),
|
),
|
||||||
syn::Fields::Unnamed(fields) => (
|
syn::Fields::Unnamed(fields) => (
|
||||||
Style::Tuple,
|
Style::Tuple,
|
||||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
fields_from_ast(cx, &fields.unnamed, attrs, container_default, private),
|
||||||
),
|
),
|
||||||
syn::Fields::Unit => (Style::Unit, Vec::new()),
|
syn::Fields::Unit => (Style::Unit, Vec::new()),
|
||||||
}
|
}
|
||||||
@@ -185,6 +200,7 @@ fn fields_from_ast<'a>(
|
|||||||
fields: &'a Punctuated<syn::Field, Token![,]>,
|
fields: &'a Punctuated<syn::Field, Token![,]>,
|
||||||
attrs: Option<&attr::Variant>,
|
attrs: Option<&attr::Variant>,
|
||||||
container_default: &attr::Default,
|
container_default: &attr::Default,
|
||||||
|
private: &Ident,
|
||||||
) -> Vec<Field<'a>> {
|
) -> Vec<Field<'a>> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
@@ -194,7 +210,7 @@ fn fields_from_ast<'a>(
|
|||||||
Some(ident) => syn::Member::Named(ident.clone()),
|
Some(ident) => syn::Member::Named(ident.clone()),
|
||||||
None => syn::Member::Unnamed(i.into()),
|
None => syn::Member::Unnamed(i.into()),
|
||||||
},
|
},
|
||||||
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default, private),
|
||||||
ty: &field.ty,
|
ty: &field.ty,
|
||||||
original: field,
|
original: field,
|
||||||
})
|
})
|
||||||
|
|||||||
+759
-893
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,8 @@
|
|||||||
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
|
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
|
||||||
//! case of the source (e.g. `my-field`, `MY_FIELD`).
|
//! case of the source (e.g. `my-field`, `MY_FIELD`).
|
||||||
|
|
||||||
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
|
|
||||||
#[allow(deprecated, unused_imports)]
|
|
||||||
use std::ascii::AsciiExt;
|
|
||||||
|
|
||||||
use std::fmt::{self, Debug, Display};
|
|
||||||
|
|
||||||
use self::RenameRule::*;
|
use self::RenameRule::*;
|
||||||
|
use std::fmt::{self, Debug, Display};
|
||||||
|
|
||||||
/// The different possible ways to change case of fields in a struct, or variants in an enum.
|
/// The different possible ways to change case of fields in a struct, or variants in an enum.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
@@ -59,8 +54,8 @@ impl RenameRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apply a renaming rule to an enum variant, returning the version expected in the source.
|
/// Apply a renaming rule to an enum variant, returning the version expected in the source.
|
||||||
pub fn apply_to_variant(&self, variant: &str) -> String {
|
pub fn apply_to_variant(self, variant: &str) -> String {
|
||||||
match *self {
|
match self {
|
||||||
None | PascalCase => variant.to_owned(),
|
None | PascalCase => variant.to_owned(),
|
||||||
LowerCase => variant.to_ascii_lowercase(),
|
LowerCase => variant.to_ascii_lowercase(),
|
||||||
UpperCase => variant.to_ascii_uppercase(),
|
UpperCase => variant.to_ascii_uppercase(),
|
||||||
@@ -84,8 +79,8 @@ impl RenameRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apply a renaming rule to a struct field, returning the version expected in the source.
|
/// Apply a renaming rule to a struct field, returning the version expected in the source.
|
||||||
pub fn apply_to_field(&self, field: &str) -> String {
|
pub fn apply_to_field(self, field: &str) -> String {
|
||||||
match *self {
|
match self {
|
||||||
None | LowerCase | SnakeCase => field.to_owned(),
|
None | LowerCase | SnakeCase => field.to_owned(),
|
||||||
UpperCase => field.to_ascii_uppercase(),
|
UpperCase => field.to_ascii_uppercase(),
|
||||||
PascalCase => {
|
PascalCase => {
|
||||||
@@ -112,6 +107,14 @@ impl RenameRule {
|
|||||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
|
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise.
|
||||||
|
pub fn or(self, rule_b: Self) -> Self {
|
||||||
|
match self {
|
||||||
|
None => rule_b,
|
||||||
|
_ => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParseError<'a> {
|
pub struct ParseError<'a> {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use internals::ast::{Container, Data, Field, Style};
|
use crate::internals::ast::{Container, Data, Field, Style};
|
||||||
use internals::attr::{Identifier, TagType};
|
use crate::internals::attr::{Default, Identifier, TagType};
|
||||||
use internals::{ungroup, Ctxt, Derive};
|
use crate::internals::{ungroup, Ctxt, Derive};
|
||||||
use syn::{Member, Type};
|
use syn::{Member, Type};
|
||||||
|
|
||||||
/// Cross-cutting checks that require looking at more than a single attrs
|
// Cross-cutting checks that require looking at more than a single attrs object.
|
||||||
/// object. Simpler checks should happen when parsing and building the attrs.
|
// Simpler checks should happen when parsing and building the attrs.
|
||||||
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||||
|
check_default_on_tuple(cx, cont);
|
||||||
|
check_remote_generic(cx, cont);
|
||||||
check_getter(cx, cont);
|
check_getter(cx, cont);
|
||||||
check_flatten(cx, cont);
|
check_flatten(cx, cont);
|
||||||
check_identifier(cx, cont);
|
check_identifier(cx, cont);
|
||||||
@@ -16,8 +18,63 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
|||||||
check_from_and_try_from(cx, cont);
|
check_from_and_try_from(cx, cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Getters are only allowed inside structs (not enums) with the `remote`
|
// If some field of a tuple struct is marked #[serde(default)] then all fields
|
||||||
/// attribute.
|
// after it must also be marked with that attribute, or the struct must have a
|
||||||
|
// container-level serde(default) attribute. A field's default value is only
|
||||||
|
// used for tuple fields if the sequence is exhausted at that point; that means
|
||||||
|
// all subsequent fields will fail to deserialize if they don't have their own
|
||||||
|
// default.
|
||||||
|
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
|
||||||
|
if let Default::None = cont.attrs.default() {
|
||||||
|
if let Data::Struct(Style::Tuple, fields) = &cont.data {
|
||||||
|
let mut first_default_index = None;
|
||||||
|
for (i, field) in fields.iter().enumerate() {
|
||||||
|
// Skipped fields automatically get the #[serde(default)]
|
||||||
|
// attribute. We are interested only on non-skipped fields here.
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Default::None = field.attrs.default() {
|
||||||
|
if let Some(first) = first_default_index {
|
||||||
|
cx.error_spanned_by(
|
||||||
|
field.ty,
|
||||||
|
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if first_default_index.is_none() {
|
||||||
|
first_default_index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remote derive definition type must have either all of the generics of the
|
||||||
|
// remote type:
|
||||||
|
//
|
||||||
|
// #[serde(remote = "Generic")]
|
||||||
|
// struct Generic<T> {…}
|
||||||
|
//
|
||||||
|
// or none of them, i.e. defining impls for one concrete instantiation of the
|
||||||
|
// remote type only:
|
||||||
|
//
|
||||||
|
// #[serde(remote = "Generic<T>")]
|
||||||
|
// struct ConcreteDef {…}
|
||||||
|
//
|
||||||
|
fn check_remote_generic(cx: &Ctxt, cont: &Container) {
|
||||||
|
if let Some(remote) = cont.attrs.remote() {
|
||||||
|
let local_has_generic = !cont.generics.params.is_empty();
|
||||||
|
let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none();
|
||||||
|
if local_has_generic && remote_has_generic {
|
||||||
|
cx.error_spanned_by(remote, "remove generic parameters from this path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters are only allowed inside structs (not enums) with the `remote`
|
||||||
|
// attribute.
|
||||||
fn check_getter(cx: &Ctxt, cont: &Container) {
|
fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||||
match cont.data {
|
match cont.data {
|
||||||
Data::Enum(_) => {
|
Data::Enum(_) => {
|
||||||
@@ -39,7 +96,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flattening has some restrictions we can test.
|
// Flattening has some restrictions we can test.
|
||||||
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
||||||
match &cont.data {
|
match &cont.data {
|
||||||
Data::Enum(variants) => {
|
Data::Enum(variants) => {
|
||||||
@@ -78,18 +135,16 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `other` attribute must be used at most once and it must be the last
|
// The `other` attribute must be used at most once and it must be the last
|
||||||
/// variant of an enum.
|
// variant of an enum.
|
||||||
///
|
//
|
||||||
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
|
// Inside a `variant_identifier` all variants must be unit variants. Inside a
|
||||||
/// `field_identifier` all but possibly one variant must be unit variants. The
|
// `field_identifier` all but possibly one variant must be unit variants. The
|
||||||
/// last variant may be a newtype variant which is an implicit "other" case.
|
// last variant may be a newtype variant which is an implicit "other" case.
|
||||||
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||||
let variants = match &cont.data {
|
let variants = match &cont.data {
|
||||||
Data::Enum(variants) => variants,
|
Data::Enum(variants) => variants,
|
||||||
Data::Struct(_, _) => {
|
Data::Struct(_, _) => return,
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, variant) in variants.iter().enumerate() {
|
for (i, variant) in variants.iter().enumerate() {
|
||||||
@@ -166,17 +221,15 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip-(de)serializing attributes are not allowed on variants marked
|
// Skip-(de)serializing attributes are not allowed on variants marked
|
||||||
/// (de)serialize_with.
|
// (de)serialize_with.
|
||||||
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||||
let variants = match &cont.data {
|
let variants = match &cont.data {
|
||||||
Data::Enum(variants) => variants,
|
Data::Enum(variants) => variants,
|
||||||
Data::Struct(_, _) => {
|
Data::Struct(_, _) => return,
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for variant in variants.iter() {
|
for variant in variants {
|
||||||
if variant.attrs.serialize_with().is_some() {
|
if variant.attrs.serialize_with().is_some() {
|
||||||
if variant.attrs.skip_serializing() {
|
if variant.attrs.skip_serializing() {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
@@ -241,10 +294,9 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The tag of an internally-tagged struct variant must not be
|
// The tag of an internally-tagged struct variant must not be the same as either
|
||||||
/// the same as either one of its fields, as this would result in
|
// one of its fields, as this would result in duplicate keys in the serialized
|
||||||
/// duplicate keys in the serialized output and/or ambiguity in
|
// output and/or ambiguity in the to-be-deserialized input.
|
||||||
/// the to-be-deserialized input.
|
|
||||||
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
||||||
let variants = match &cont.data {
|
let variants = match &cont.data {
|
||||||
Data::Enum(variants) => variants,
|
Data::Enum(variants) => variants,
|
||||||
@@ -266,19 +318,24 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
for variant in variants {
|
for variant in variants {
|
||||||
match variant.style {
|
match variant.style {
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
|
if variant.attrs.untagged() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
let check_ser = !field.attrs.skip_serializing();
|
let check_ser =
|
||||||
let check_de = !field.attrs.skip_deserializing();
|
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
|
||||||
|
let check_de =
|
||||||
|
!(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing());
|
||||||
let name = field.attrs.name();
|
let name = field.attrs.name();
|
||||||
let ser_name = name.serialize_name();
|
let ser_name = name.serialize_name();
|
||||||
|
|
||||||
if check_ser && ser_name == tag {
|
if check_ser && ser_name.value == tag {
|
||||||
diagnose_conflict();
|
diagnose_conflict();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for de_name in field.attrs.aliases() {
|
for de_name in field.attrs.aliases() {
|
||||||
if check_de && de_name == tag {
|
if check_de && de_name.value == tag {
|
||||||
diagnose_conflict();
|
diagnose_conflict();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -290,8 +347,8 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the case of adjacently-tagged enums, the type and the
|
// In the case of adjacently-tagged enums, the type and the contents tag must
|
||||||
/// contents tag must differ, for the same reason.
|
// differ, for the same reason.
|
||||||
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
|
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
|
||||||
let (type_tag, content_tag) = match cont.attrs.tag() {
|
let (type_tag, content_tag) = match cont.attrs.tag() {
|
||||||
TagType::Adjacent { tag, content } => (tag, content),
|
TagType::Adjacent { tag, content } => (tag, content),
|
||||||
@@ -309,7 +366,7 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enums and unit structs cannot be transparent.
|
// Enums and unit structs cannot be transparent.
|
||||||
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||||
if !cont.attrs.transparent() {
|
if !cont.attrs.transparent() {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use quote::ToTokens;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use syn;
|
|
||||||
|
|
||||||
/// A type to collect errors together and format them.
|
/// A type to collect errors together and format them.
|
||||||
///
|
///
|
||||||
@@ -44,12 +43,18 @@ impl Ctxt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Consume this object, producing a formatted error string if there are errors.
|
/// Consume this object, producing a formatted error string if there are errors.
|
||||||
pub fn check(self) -> Result<(), Vec<syn::Error>> {
|
pub fn check(self) -> syn::Result<()> {
|
||||||
let errors = self.errors.borrow_mut().take().unwrap();
|
let mut errors = self.errors.borrow_mut().take().unwrap().into_iter();
|
||||||
match errors.len() {
|
|
||||||
0 => Ok(()),
|
let Some(mut combined) = errors.next() else {
|
||||||
_ => Err(errors),
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
for rest in errors {
|
||||||
|
combined.combine(rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Err(combined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
|
pub mod name;
|
||||||
mod ctxt;
|
|
||||||
pub use self::ctxt::Ctxt;
|
|
||||||
|
|
||||||
mod receiver;
|
|
||||||
pub use self::receiver::replace_receiver;
|
|
||||||
|
|
||||||
mod case;
|
mod case;
|
||||||
mod check;
|
mod check;
|
||||||
|
mod ctxt;
|
||||||
|
mod receiver;
|
||||||
mod respan;
|
mod respan;
|
||||||
mod symbol;
|
mod symbol;
|
||||||
|
|
||||||
use syn::Type;
|
use syn::Type;
|
||||||
|
|
||||||
|
pub use self::ctxt::Ctxt;
|
||||||
|
pub use self::receiver::replace_receiver;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Derive {
|
pub enum Derive {
|
||||||
Serialize,
|
Serialize,
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use crate::internals::attr::{Attr, VecAttr};
|
||||||
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
|
use quote::ToTokens;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use syn::LitStr;
|
||||||
|
|
||||||
|
pub struct MultiName {
|
||||||
|
pub(crate) serialize: Name,
|
||||||
|
pub(crate) serialize_renamed: bool,
|
||||||
|
pub(crate) deserialize: Name,
|
||||||
|
pub(crate) deserialize_renamed: bool,
|
||||||
|
pub(crate) deserialize_aliases: BTreeSet<Name>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MultiName {
|
||||||
|
pub(crate) fn from_attrs(
|
||||||
|
source_name: Name,
|
||||||
|
ser_name: Attr<Name>,
|
||||||
|
de_name: Attr<Name>,
|
||||||
|
de_aliases: Option<VecAttr<Name>>,
|
||||||
|
) -> Self {
|
||||||
|
let mut alias_set = BTreeSet::new();
|
||||||
|
if let Some(de_aliases) = de_aliases {
|
||||||
|
for alias_name in de_aliases.get() {
|
||||||
|
alias_set.insert(alias_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ser_name = ser_name.get();
|
||||||
|
let ser_renamed = ser_name.is_some();
|
||||||
|
let de_name = de_name.get();
|
||||||
|
let de_renamed = de_name.is_some();
|
||||||
|
MultiName {
|
||||||
|
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
|
||||||
|
serialize_renamed: ser_renamed,
|
||||||
|
deserialize: de_name.unwrap_or(source_name),
|
||||||
|
deserialize_renamed: de_renamed,
|
||||||
|
deserialize_aliases: alias_set,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the container name for the container when serializing.
|
||||||
|
pub fn serialize_name(&self) -> &Name {
|
||||||
|
&self.serialize
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the container name for the container when deserializing.
|
||||||
|
pub fn deserialize_name(&self) -> &Name {
|
||||||
|
&self.deserialize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<Name> {
|
||||||
|
&self.deserialize_aliases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Name {
|
||||||
|
pub value: String,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for Name {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
LitStr::new(&self.value, self.span).to_tokens(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Name {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
Ord::cmp(&self.value, &other.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Name {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(Ord::cmp(self, other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Name {}
|
||||||
|
|
||||||
|
impl PartialEq for Name {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.value == other.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Ident> for Name {
|
||||||
|
fn from(ident: &Ident) -> Self {
|
||||||
|
Name {
|
||||||
|
value: ident.to_string(),
|
||||||
|
span: ident.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&LitStr> for Name {
|
||||||
|
fn from(lit: &LitStr) -> Self {
|
||||||
|
Name {
|
||||||
|
value: lit.value(),
|
||||||
|
span: lit.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Name {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
Display::fmt(&self.value, formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
use internals::respan::respan;
|
use crate::internals::respan::respan;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use syn::punctuated::Punctuated;
|
|
||||||
use syn::{
|
use syn::{
|
||||||
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
|
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
|
||||||
Path, PathArguments, QSelf, ReturnType, Type, TypeParamBound, TypePath, WherePredicate,
|
Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn replace_receiver(input: &mut DeriveInput) {
|
pub fn replace_receiver(input: &mut DeriveInput) {
|
||||||
@@ -49,7 +48,7 @@ impl ReplaceReceiver<'_> {
|
|||||||
|
|
||||||
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
|
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
|
||||||
|
|
||||||
let segments = mem::replace(&mut path.segments, Punctuated::new());
|
let segments = mem::take(&mut path.segments);
|
||||||
path.segments = segments.into_pairs().skip(1).collect();
|
path.segments = segments.into_pairs().skip(1).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ impl ReplaceReceiver<'_> {
|
|||||||
self.visit_type_mut_impl(ty);
|
self.visit_type_mut_impl(ty);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
*ty = self.self_ty(span).into();
|
*ty = Type::Path(self.self_ty(span));
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Self::Assoc` -> `<Receiver>::Assoc`
|
// `Self::Assoc` -> `<Receiver>::Assoc`
|
||||||
@@ -107,6 +106,7 @@ impl ReplaceReceiver<'_> {
|
|||||||
|
|
||||||
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
|
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
|
||||||
match ty {
|
match ty {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
Type::Array(ty) => {
|
Type::Array(ty) => {
|
||||||
self.visit_type_mut(&mut ty.elem);
|
self.visit_type_mut(&mut ty.elem);
|
||||||
self.visit_expr_mut(&mut ty.len);
|
self.visit_expr_mut(&mut ty.len);
|
||||||
@@ -147,7 +147,6 @@ impl ReplaceReceiver<'_> {
|
|||||||
|
|
||||||
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
||||||
|
|
||||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,11 +177,14 @@ impl ReplaceReceiver<'_> {
|
|||||||
PathArguments::AngleBracketed(arguments) => {
|
PathArguments::AngleBracketed(arguments) => {
|
||||||
for arg in &mut arguments.args {
|
for arg in &mut arguments.args {
|
||||||
match arg {
|
match arg {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
GenericArgument::Type(arg) => self.visit_type_mut(arg),
|
GenericArgument::Type(arg) => self.visit_type_mut(arg),
|
||||||
GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty),
|
GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
|
||||||
GenericArgument::Lifetime(_)
|
GenericArgument::Lifetime(_)
|
||||||
| GenericArgument::Constraint(_)
|
| GenericArgument::Const(_)
|
||||||
| GenericArgument::Const(_) => {}
|
| GenericArgument::AssocConst(_)
|
||||||
|
| GenericArgument::Constraint(_) => {}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,8 +206,12 @@ impl ReplaceReceiver<'_> {
|
|||||||
|
|
||||||
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
|
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
|
||||||
match bound {
|
match bound {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
|
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
|
||||||
TypeParamBound::Lifetime(_) => {}
|
TypeParamBound::Lifetime(_)
|
||||||
|
| TypeParamBound::PreciseCapture(_)
|
||||||
|
| TypeParamBound::Verbatim(_) => {}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,13 +229,15 @@ impl ReplaceReceiver<'_> {
|
|||||||
if let Some(where_clause) = &mut generics.where_clause {
|
if let Some(where_clause) = &mut generics.where_clause {
|
||||||
for predicate in &mut where_clause.predicates {
|
for predicate in &mut where_clause.predicates {
|
||||||
match predicate {
|
match predicate {
|
||||||
|
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||||
WherePredicate::Type(predicate) => {
|
WherePredicate::Type(predicate) => {
|
||||||
self.visit_type_mut(&mut predicate.bounded_ty);
|
self.visit_type_mut(&mut predicate.bounded_ty);
|
||||||
for bound in &mut predicate.bounds {
|
for bound in &mut predicate.bounds {
|
||||||
self.visit_type_param_bound_mut(bound);
|
self.visit_type_param_bound_mut(bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WherePredicate::Lifetime(_) | WherePredicate::Eq(_) => {}
|
WherePredicate::Lifetime(_) => {}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,19 @@ pub const DEFAULT: Symbol = Symbol("default");
|
|||||||
pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields");
|
pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields");
|
||||||
pub const DESERIALIZE: Symbol = Symbol("deserialize");
|
pub const DESERIALIZE: Symbol = Symbol("deserialize");
|
||||||
pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with");
|
pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with");
|
||||||
|
pub const EXPECTING: Symbol = Symbol("expecting");
|
||||||
pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier");
|
pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier");
|
||||||
pub const FLATTEN: Symbol = Symbol("flatten");
|
pub const FLATTEN: Symbol = Symbol("flatten");
|
||||||
pub const FROM: Symbol = Symbol("from");
|
pub const FROM: Symbol = Symbol("from");
|
||||||
pub const GETTER: Symbol = Symbol("getter");
|
pub const GETTER: Symbol = Symbol("getter");
|
||||||
pub const INTO: Symbol = Symbol("into");
|
pub const INTO: Symbol = Symbol("into");
|
||||||
|
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
|
||||||
pub const OTHER: Symbol = Symbol("other");
|
pub const OTHER: Symbol = Symbol("other");
|
||||||
pub const REMOTE: Symbol = Symbol("remote");
|
pub const REMOTE: Symbol = Symbol("remote");
|
||||||
pub const RENAME: Symbol = Symbol("rename");
|
pub const RENAME: Symbol = Symbol("rename");
|
||||||
pub const RENAME_ALL: Symbol = Symbol("rename_all");
|
pub const RENAME_ALL: Symbol = Symbol("rename_all");
|
||||||
|
pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields");
|
||||||
|
pub const REPR: Symbol = Symbol("repr");
|
||||||
pub const SERDE: Symbol = Symbol("serde");
|
pub const SERDE: Symbol = Symbol("serde");
|
||||||
pub const SERIALIZE: Symbol = Symbol("serialize");
|
pub const SERIALIZE: Symbol = Symbol("serialize");
|
||||||
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
|
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
|
||||||
@@ -35,7 +39,6 @@ pub const TRY_FROM: Symbol = Symbol("try_from");
|
|||||||
pub const UNTAGGED: Symbol = Symbol("untagged");
|
pub const UNTAGGED: Symbol = Symbol("untagged");
|
||||||
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
|
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
|
||||||
pub const WITH: Symbol = Symbol("with");
|
pub const WITH: Symbol = Symbol("with");
|
||||||
pub const EXPECTING: Symbol = Symbol("expecting");
|
|
||||||
|
|
||||||
impl PartialEq<Symbol> for Ident {
|
impl PartialEq<Symbol> for Ident {
|
||||||
fn eq(&self, word: &Symbol) -> bool {
|
fn eq(&self, word: &Symbol) -> bool {
|
||||||
@@ -43,7 +46,7 @@ impl PartialEq<Symbol> for Ident {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq<Symbol> for &'a Ident {
|
impl PartialEq<Symbol> for &Ident {
|
||||||
fn eq(&self, word: &Symbol) -> bool {
|
fn eq(&self, word: &Symbol) -> bool {
|
||||||
*self == word.0
|
*self == word.0
|
||||||
}
|
}
|
||||||
@@ -55,7 +58,7 @@ impl PartialEq<Symbol> for Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq<Symbol> for &'a Path {
|
impl PartialEq<Symbol> for &Path {
|
||||||
fn eq(&self, word: &Symbol) -> bool {
|
fn eq(&self, word: &Symbol) -> bool {
|
||||||
self.is_ident(word.0)
|
self.is_ident(word.0)
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-17
@@ -1,7 +1,7 @@
|
|||||||
//! This crate provides Serde's two derive macros.
|
//! This crate provides Serde's two derive macros.
|
||||||
//!
|
//!
|
||||||
//! ```edition2018
|
//! ```edition2021
|
||||||
//! # use serde_derive::{Serialize, Deserialize};
|
//! # use serde_derive::{Deserialize, Serialize};
|
||||||
//! #
|
//! #
|
||||||
//! #[derive(Serialize, Deserialize)]
|
//! #[derive(Serialize, Deserialize)]
|
||||||
//! # struct S;
|
//! # struct S;
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.137")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.228")]
|
||||||
#![allow(unknown_lints, bare_trait_objects)]
|
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||||
clippy::manual_map,
|
clippy::manual_map,
|
||||||
clippy::match_like_matches_macro,
|
clippy::match_like_matches_macro,
|
||||||
|
clippy::needless_lifetimes,
|
||||||
clippy::needless_pass_by_value,
|
clippy::needless_pass_by_value,
|
||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
clippy::trivially_copy_pass_by_ref,
|
clippy::trivially_copy_pass_by_ref,
|
||||||
@@ -40,10 +41,11 @@
|
|||||||
clippy::cast_possible_truncation,
|
clippy::cast_possible_truncation,
|
||||||
clippy::checked_conversions,
|
clippy::checked_conversions,
|
||||||
clippy::doc_markdown,
|
clippy::doc_markdown,
|
||||||
|
clippy::elidable_lifetime_names,
|
||||||
clippy::enum_glob_use,
|
clippy::enum_glob_use,
|
||||||
clippy::indexing_slicing,
|
clippy::indexing_slicing,
|
||||||
clippy::items_after_statements,
|
clippy::items_after_statements,
|
||||||
clippy::let_underscore_drop,
|
clippy::let_underscore_untyped,
|
||||||
clippy::manual_assert,
|
clippy::manual_assert,
|
||||||
clippy::map_err_ignore,
|
clippy::map_err_ignore,
|
||||||
clippy::match_same_arms,
|
clippy::match_same_arms,
|
||||||
@@ -51,29 +53,31 @@
|
|||||||
clippy::match_wildcard_for_single_variants,
|
clippy::match_wildcard_for_single_variants,
|
||||||
clippy::module_name_repetitions,
|
clippy::module_name_repetitions,
|
||||||
clippy::must_use_candidate,
|
clippy::must_use_candidate,
|
||||||
clippy::option_if_let_else,
|
|
||||||
clippy::similar_names,
|
clippy::similar_names,
|
||||||
clippy::single_match_else,
|
clippy::single_match_else,
|
||||||
clippy::struct_excessive_bools,
|
clippy::struct_excessive_bools,
|
||||||
clippy::too_many_lines,
|
clippy::too_many_lines,
|
||||||
|
clippy::uninlined_format_args,
|
||||||
clippy::unseparated_literal_suffix,
|
clippy::unseparated_literal_suffix,
|
||||||
clippy::unused_self,
|
clippy::unused_self,
|
||||||
clippy::use_self,
|
clippy::use_self,
|
||||||
clippy::wildcard_imports
|
clippy::wildcard_imports
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
|
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
|
||||||
|
#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
|
||||||
|
|
||||||
#[macro_use]
|
extern crate proc_macro2;
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
#[macro_use]
|
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
extern crate proc_macro2;
|
|
||||||
|
|
||||||
mod internals;
|
mod internals;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::{Ident, Span};
|
||||||
|
use quote::{ToTokens, TokenStreamExt as _};
|
||||||
|
use syn::parse_macro_input;
|
||||||
use syn::DeriveInput;
|
use syn::DeriveInput;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -82,16 +86,35 @@ mod bound;
|
|||||||
mod fragment;
|
mod fragment;
|
||||||
|
|
||||||
mod de;
|
mod de;
|
||||||
|
mod deprecated;
|
||||||
mod dummy;
|
mod dummy;
|
||||||
mod pretend;
|
mod pretend;
|
||||||
mod ser;
|
mod ser;
|
||||||
mod try;
|
mod this;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
struct private;
|
||||||
|
|
||||||
|
impl private {
|
||||||
|
fn ident(&self) -> Ident {
|
||||||
|
Ident::new(
|
||||||
|
concat!("__private", env!("CARGO_PKG_VERSION_PATCH")),
|
||||||
|
Span::call_site(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for private {
|
||||||
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||||
|
tokens.append(self.ident());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||||
let mut input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
ser::expand_derive_serialize(&mut input)
|
ser::expand_derive_serialize(&mut input)
|
||||||
.unwrap_or_else(to_compile_errors)
|
.unwrap_or_else(syn::Error::into_compile_error)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +122,6 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||||
let mut input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
de::expand_derive_deserialize(&mut input)
|
de::expand_derive_deserialize(&mut input)
|
||||||
.unwrap_or_else(to_compile_errors)
|
.unwrap_or_else(syn::Error::into_compile_error)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
|
|
||||||
let compile_errors = errors.iter().map(syn::Error::to_compile_error);
|
|
||||||
quote!(#(#compile_errors)*)
|
|
||||||
}
|
|
||||||
|
|||||||
+22
-35
@@ -1,7 +1,7 @@
|
|||||||
|
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
|
use crate::private;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::format_ident;
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
|
||||||
|
|
||||||
// Suppress dead_code warnings that would otherwise appear when using a remote
|
// Suppress dead_code warnings that would otherwise appear when using a remote
|
||||||
// derive. Other than this pretend code, a struct annotated with remote derive
|
// derive. Other than this pretend code, a struct annotated with remote derive
|
||||||
@@ -65,14 +65,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
|
|||||||
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
|
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
|
||||||
match &cont.data {
|
match &cont.data {
|
||||||
Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
|
Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
|
||||||
Data::Struct(Style::Struct, fields) => {
|
Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => {
|
||||||
if is_packed {
|
if is_packed {
|
||||||
pretend_fields_used_struct_packed(cont, fields)
|
pretend_fields_used_struct_packed(cont, fields)
|
||||||
} else {
|
} else {
|
||||||
pretend_fields_used_struct(cont, fields)
|
pretend_fields_used_struct(cont, fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data::Struct(_, _) => quote!(),
|
Data::Struct(Style::Unit, _) => quote!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +84,8 @@ fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream
|
|||||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
match _serde::__private::None::<&#type_ident #ty_generics> {
|
match _serde::#private::None::<&#type_ident #ty_generics> {
|
||||||
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
|
_serde::#private::Some(#type_ident { #(#members: #placeholders),* }) => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,29 +97,15 @@ fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> Toke
|
|||||||
|
|
||||||
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
|
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
|
||||||
|
|
||||||
#[cfg(ptr_addr_of)]
|
let private2 = private;
|
||||||
{
|
quote! {
|
||||||
quote! {
|
match _serde::#private::None::<&#type_ident #ty_generics> {
|
||||||
match _serde::__private::None::<&#type_ident #ty_generics> {
|
_serde::#private::Some(__v @ #type_ident { #(#members: _),* }) => {
|
||||||
_serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
|
#(
|
||||||
#(
|
let _ = _serde::#private2::ptr::addr_of!(__v.#members);
|
||||||
let _ = _serde::__private::ptr::addr_of!(__v.#members);
|
)*
|
||||||
)*
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(ptr_addr_of))]
|
|
||||||
{
|
|
||||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
match _serde::__private::None::<#type_ident #ty_generics> {
|
|
||||||
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,20 +117,21 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre
|
|||||||
let patterns = variants
|
let patterns = variants
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|variant| match variant.style {
|
.filter_map(|variant| match variant.style {
|
||||||
Style::Struct => {
|
Style::Struct | Style::Tuple | Style::Newtype => {
|
||||||
let variant_ident = &variant.ident;
|
let variant_ident = &variant.ident;
|
||||||
let members = variant.fields.iter().map(|field| &field.member);
|
let members = variant.fields.iter().map(|field| &field.member);
|
||||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
||||||
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
|
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
|
||||||
}
|
}
|
||||||
_ => None,
|
Style::Unit => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let private2 = private;
|
||||||
quote! {
|
quote! {
|
||||||
match _serde::__private::None::<&#type_ident #ty_generics> {
|
match _serde::#private::None::<&#type_ident #ty_generics> {
|
||||||
#(
|
#(
|
||||||
_serde::__private::Some(#patterns) => {}
|
_serde::#private2::Some(#patterns) => {}
|
||||||
)*
|
)*
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -188,8 +175,8 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
match _serde::__private::None {
|
match _serde::#private::None {
|
||||||
_serde::__private::Some((#(#placeholders,)*)) => {
|
_serde::#private::Some((#(#placeholders,)*)) => {
|
||||||
let _ = #type_ident::#variant_ident #turbofish #pat;
|
let _ = #type_ident::#variant_ident #turbofish #pat;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
+184
-154
@@ -1,23 +1,20 @@
|
|||||||
|
use crate::deprecated::allow_deprecated;
|
||||||
|
use crate::fragment::{Fragment, Match, Stmts};
|
||||||
|
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
|
use crate::internals::name::Name;
|
||||||
|
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
|
||||||
|
use crate::{bound, dummy, pretend, private, this};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{self, Ident, Index, Member};
|
use syn::{parse_quote, Ident, Index, Member};
|
||||||
|
|
||||||
use bound;
|
pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
|
||||||
use dummy;
|
|
||||||
use fragment::{Fragment, Match, Stmts};
|
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
|
||||||
use internals::{attr, replace_receiver, Ctxt, Derive};
|
|
||||||
use pretend;
|
|
||||||
|
|
||||||
pub fn expand_derive_serialize(
|
|
||||||
input: &mut syn::DeriveInput,
|
|
||||||
) -> Result<TokenStream, Vec<syn::Error>> {
|
|
||||||
replace_receiver(input);
|
replace_receiver(input);
|
||||||
|
|
||||||
let ctxt = Ctxt::new();
|
let ctxt = Ctxt::new();
|
||||||
let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
|
let Some(cont) = Container::from_ast(&ctxt, input, Derive::Serialize, &private.ident()) else {
|
||||||
Some(cont) => cont,
|
return Err(ctxt.check().unwrap_err());
|
||||||
None => return Err(ctxt.check().unwrap_err()),
|
|
||||||
};
|
};
|
||||||
precondition(&ctxt, &cont);
|
precondition(&ctxt, &cont);
|
||||||
ctxt.check()?;
|
ctxt.check()?;
|
||||||
@@ -26,16 +23,18 @@ pub fn expand_derive_serialize(
|
|||||||
let params = Parameters::new(&cont);
|
let params = Parameters::new(&cont);
|
||||||
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||||
let body = Stmts(serialize_body(&cont, ¶ms));
|
let body = Stmts(serialize_body(&cont, ¶ms));
|
||||||
let serde = cont.attrs.serde_path();
|
let allow_deprecated = allow_deprecated(input);
|
||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
let used = pretend::pretend_used(&cont, params.is_packed);
|
let used = pretend::pretend_used(&cont, params.is_packed);
|
||||||
quote! {
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
#allow_deprecated
|
||||||
impl #impl_generics #ident #ty_generics #where_clause {
|
impl #impl_generics #ident #ty_generics #where_clause {
|
||||||
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
|
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
|
||||||
where
|
where
|
||||||
__S: #serde::Serializer,
|
__S: _serde::Serializer,
|
||||||
{
|
{
|
||||||
#used
|
#used
|
||||||
#body
|
#body
|
||||||
@@ -45,10 +44,11 @@ pub fn expand_derive_serialize(
|
|||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause {
|
#allow_deprecated
|
||||||
fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
|
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
|
||||||
|
fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
|
||||||
where
|
where
|
||||||
__S: #serde::Serializer,
|
__S: _serde::Serializer,
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,6 @@ pub fn expand_derive_serialize(
|
|||||||
|
|
||||||
Ok(dummy::wrap_in_const(
|
Ok(dummy::wrap_in_const(
|
||||||
cont.attrs.custom_serde_path(),
|
cont.attrs.custom_serde_path(),
|
||||||
"SERIALIZE",
|
|
||||||
ident,
|
|
||||||
impl_block,
|
impl_block,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -82,9 +80,13 @@ struct Parameters {
|
|||||||
self_var: Ident,
|
self_var: Ident,
|
||||||
|
|
||||||
/// Path to the type the impl is for. Either a single `Ident` for local
|
/// Path to the type the impl is for. Either a single `Ident` for local
|
||||||
/// types or `some::remote::Ident` for remote types. Does not include
|
/// types (does not include generic parameters) or `some::remote::Path` for
|
||||||
/// generic parameters.
|
/// remote types.
|
||||||
this: syn::Path,
|
this_type: syn::Path,
|
||||||
|
|
||||||
|
/// Same as `this_type` but using `::<T>` for generic parameters for use in
|
||||||
|
/// expression position.
|
||||||
|
this_value: syn::Path,
|
||||||
|
|
||||||
/// Generics including any explicit and inferred bounds for the impl.
|
/// Generics including any explicit and inferred bounds for the impl.
|
||||||
generics: syn::Generics,
|
generics: syn::Generics,
|
||||||
@@ -105,18 +107,15 @@ impl Parameters {
|
|||||||
Ident::new("self", Span::call_site())
|
Ident::new("self", Span::call_site())
|
||||||
};
|
};
|
||||||
|
|
||||||
let this = match cont.attrs.remote() {
|
let this_type = this::this_type(cont);
|
||||||
Some(remote) => remote.clone(),
|
let this_value = this::this_value(cont);
|
||||||
None => cont.ident.clone().into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_packed = cont.attrs.is_packed();
|
let is_packed = cont.attrs.is_packed();
|
||||||
|
|
||||||
let generics = build_generics(cont);
|
let generics = build_generics(cont);
|
||||||
|
|
||||||
Parameters {
|
Parameters {
|
||||||
self_var,
|
self_var,
|
||||||
this,
|
this_type,
|
||||||
|
this_value,
|
||||||
generics,
|
generics,
|
||||||
is_remote,
|
is_remote,
|
||||||
is_packed,
|
is_packed,
|
||||||
@@ -126,7 +125,7 @@ impl Parameters {
|
|||||||
/// Type name to use in error messages and `&'static str` arguments to
|
/// Type name to use in error messages and `&'static str` arguments to
|
||||||
/// various Serializer methods.
|
/// various Serializer methods.
|
||||||
fn type_name(&self) -> String {
|
fn type_name(&self) -> String {
|
||||||
self.this.segments.last().unwrap().ident.to_string()
|
self.this_type.segments.last().unwrap().ident.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +152,7 @@ fn build_generics(cont: &Container) -> syn::Generics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
|
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
|
||||||
// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
|
// belong to a variant with a `skip_serializing` or `serialize_with` attribute,
|
||||||
// are not serialized by us so we do not generate a bound. Fields with a `bound`
|
// are not serialized by us so we do not generate a bound. Fields with a `bound`
|
||||||
// attribute specify their own bound so we do not generate one. All other fields
|
// attribute specify their own bound so we do not generate one. All other fields
|
||||||
// may need a `T: Serialize` bound where T is the type of the field.
|
// may need a `T: Serialize` bound where T is the type of the field.
|
||||||
@@ -215,7 +214,7 @@ fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
|
|||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
quote_block! {
|
quote_block! {
|
||||||
_serde::Serialize::serialize(
|
_serde::Serialize::serialize(
|
||||||
&_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)),
|
&_serde::#private::Into::<#type_into>::into(_serde::#private::Clone::clone(#self_var)),
|
||||||
__serializer)
|
__serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,16 +286,25 @@ fn serialize_tuple_struct(
|
|||||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
|
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?;
|
||||||
#(#serialize_stmts)*
|
#(#serialize_stmts)*
|
||||||
_serde::ser::SerializeTupleStruct::end(__serde_state)
|
_serde::ser::SerializeTupleStruct::end(__serde_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
||||||
assert!(fields.len() as u64 <= u64::from(u32::max_value()));
|
assert!(
|
||||||
|
fields.len() as u64 <= u64::from(u32::MAX),
|
||||||
|
"too many fields in {}: {}, maximum supported count is {}",
|
||||||
|
cattrs.name().serialize_name(),
|
||||||
|
fields.len(),
|
||||||
|
u32::MAX,
|
||||||
|
);
|
||||||
|
|
||||||
if cattrs.has_flatten() {
|
let has_non_skipped_flatten = fields
|
||||||
|
.iter()
|
||||||
|
.any(|field| field.attrs.flatten() && !field.attrs.skip_serializing());
|
||||||
|
if has_non_skipped_flatten {
|
||||||
serialize_struct_as_map(params, fields, cattrs)
|
serialize_struct_as_map(params, fields, cattrs)
|
||||||
} else {
|
} else {
|
||||||
serialize_struct_as_struct(params, fields, cattrs)
|
serialize_struct_as_struct(params, fields, cattrs)
|
||||||
@@ -309,7 +317,7 @@ fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTra
|
|||||||
let type_name = cattrs.name().serialize_name();
|
let type_name = cattrs.name().serialize_name();
|
||||||
let func = struct_trait.serialize_field(Span::call_site());
|
let func = struct_trait.serialize_field(Span::call_site());
|
||||||
quote! {
|
quote! {
|
||||||
try!(#func(&mut __serde_state, #tag, #type_name));
|
#func(&mut __serde_state, #tag, #type_name)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => quote! {},
|
_ => quote! {},
|
||||||
@@ -350,7 +358,7 @@ fn serialize_struct_as_struct(
|
|||||||
);
|
);
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
|
let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
|
||||||
#tag_field
|
#tag_field
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeStruct::end(__serde_state)
|
_serde::ser::SerializeStruct::end(__serde_state)
|
||||||
@@ -375,26 +383,8 @@ fn serialize_struct_as_map(
|
|||||||
|
|
||||||
let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
|
let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
|
||||||
|
|
||||||
let len = if cattrs.has_flatten() {
|
|
||||||
quote!(_serde::__private::None)
|
|
||||||
} else {
|
|
||||||
let len = serialized_fields
|
|
||||||
.map(|field| match field.attrs.skip_serializing_if() {
|
|
||||||
None => quote!(1),
|
|
||||||
Some(path) => {
|
|
||||||
let field_expr = get_member(params, field, &field.member);
|
|
||||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.fold(
|
|
||||||
quote!(#tag_field_exists as usize),
|
|
||||||
|sum, expr| quote!(#sum + #expr),
|
|
||||||
);
|
|
||||||
quote!(_serde::__private::Some(#len))
|
|
||||||
};
|
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
|
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::#private::None)?;
|
||||||
#tag_field
|
#tag_field
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeMap::end(__serde_state)
|
_serde::ser::SerializeMap::end(__serde_state)
|
||||||
@@ -402,11 +392,11 @@ fn serialize_struct_as_map(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
|
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
|
||||||
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
|
assert!(variants.len() as u64 <= u64::from(u32::MAX));
|
||||||
|
|
||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
|
|
||||||
let arms: Vec<_> = variants
|
let mut arms: Vec<_> = variants
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(variant_index, variant)| {
|
.map(|(variant_index, variant)| {
|
||||||
@@ -414,6 +404,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if cattrs.remote().is_some() && cattrs.non_exhaustive() {
|
||||||
|
arms.push(quote! {
|
||||||
|
ref unrecognized => _serde::#private::Err(_serde::ser::Error::custom(_serde::#private::ser::CannotSerializeVariant(unrecognized))),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
quote_expr! {
|
quote_expr! {
|
||||||
match *#self_var {
|
match *#self_var {
|
||||||
#(#arms)*
|
#(#arms)*
|
||||||
@@ -427,7 +423,7 @@ fn serialize_variant(
|
|||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let this = ¶ms.this;
|
let this_value = ¶ms.this_value;
|
||||||
let variant_ident = &variant.ident;
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
if variant.attrs.skip_serializing() {
|
if variant.attrs.skip_serializing() {
|
||||||
@@ -437,7 +433,7 @@ fn serialize_variant(
|
|||||||
variant_ident
|
variant_ident
|
||||||
);
|
);
|
||||||
let skipped_err = quote! {
|
let skipped_err = quote! {
|
||||||
_serde::__private::Err(_serde::ser::Error::custom(#skipped_msg))
|
_serde::#private::Err(_serde::ser::Error::custom(#skipped_msg))
|
||||||
};
|
};
|
||||||
let fields_pat = match variant.style {
|
let fields_pat = match variant.style {
|
||||||
Style::Unit => quote!(),
|
Style::Unit => quote!(),
|
||||||
@@ -445,47 +441,56 @@ fn serialize_variant(
|
|||||||
Style::Struct => quote!({ .. }),
|
Style::Struct => quote!({ .. }),
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
#this::#variant_ident #fields_pat => #skipped_err,
|
#this_value::#variant_ident #fields_pat => #skipped_err,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// variant wasn't skipped
|
// variant wasn't skipped
|
||||||
let case = match variant.style {
|
let case = match variant.style {
|
||||||
Style::Unit => {
|
Style::Unit => {
|
||||||
quote! {
|
quote! {
|
||||||
#this::#variant_ident
|
#this_value::#variant_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Style::Newtype => {
|
Style::Newtype => {
|
||||||
quote! {
|
quote! {
|
||||||
#this::#variant_ident(ref __field0)
|
#this_value::#variant_ident(ref __field0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Style::Tuple => {
|
Style::Tuple => {
|
||||||
let field_names = (0..variant.fields.len())
|
let field_names = (0..variant.fields.len())
|
||||||
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
|
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
|
||||||
quote! {
|
quote! {
|
||||||
#this::#variant_ident(#(ref #field_names),*)
|
#this_value::#variant_ident(#(ref #field_names),*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
let members = variant.fields.iter().map(|f| &f.member);
|
let members = variant.fields.iter().map(|f| &f.member);
|
||||||
quote! {
|
quote! {
|
||||||
#this::#variant_ident { #(ref #members),* }
|
#this_value::#variant_ident { #(ref #members),* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = Match(match cattrs.tag() {
|
let body = Match(match (cattrs.tag(), variant.attrs.untagged()) {
|
||||||
attr::TagType::External => {
|
(attr::TagType::External, false) => {
|
||||||
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
|
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
|
||||||
}
|
}
|
||||||
attr::TagType::Internal { tag } => {
|
(attr::TagType::Internal { tag }, false) => {
|
||||||
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
||||||
}
|
}
|
||||||
attr::TagType::Adjacent { tag, content } => {
|
(attr::TagType::Adjacent { tag, content }, false) => {
|
||||||
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
|
serialize_adjacently_tagged_variant(
|
||||||
|
params,
|
||||||
|
variant,
|
||||||
|
cattrs,
|
||||||
|
variant_index,
|
||||||
|
tag,
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(attr::TagType::None, _) | (_, true) => {
|
||||||
|
serialize_untagged_variant(params, variant, cattrs)
|
||||||
}
|
}
|
||||||
attr::TagType::None => serialize_untagged_variant(params, variant, cattrs),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@@ -562,7 +567,7 @@ fn serialize_externally_tagged_variant(
|
|||||||
},
|
},
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&type_name,
|
type_name,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,7 +587,7 @@ fn serialize_internally_tagged_variant(
|
|||||||
if let Some(path) = variant.attrs.serialize_with() {
|
if let Some(path) = variant.attrs.serialize_with() {
|
||||||
let ser = wrap_serialize_variant_with(params, path, variant);
|
let ser = wrap_serialize_variant_with(params, path, variant);
|
||||||
return quote_expr! {
|
return quote_expr! {
|
||||||
_serde::__private::ser::serialize_tagged_newtype(
|
_serde::#private::ser::serialize_tagged_newtype(
|
||||||
__serializer,
|
__serializer,
|
||||||
#enum_ident_str,
|
#enum_ident_str,
|
||||||
#variant_ident_str,
|
#variant_ident_str,
|
||||||
@@ -596,10 +601,10 @@ fn serialize_internally_tagged_variant(
|
|||||||
match effective_style(variant) {
|
match effective_style(variant) {
|
||||||
Style::Unit => {
|
Style::Unit => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
let mut __struct = _serde::Serializer::serialize_struct(
|
||||||
__serializer, #type_name, 1));
|
__serializer, #type_name, 1)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __struct, #tag, #variant_name));
|
&mut __struct, #tag, #variant_name)?;
|
||||||
_serde::ser::SerializeStruct::end(__struct)
|
_serde::ser::SerializeStruct::end(__struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -611,7 +616,7 @@ fn serialize_internally_tagged_variant(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype);
|
let func = quote_spanned!(span=> _serde::#private::ser::serialize_tagged_newtype);
|
||||||
quote_expr! {
|
quote_expr! {
|
||||||
#func(
|
#func(
|
||||||
__serializer,
|
__serializer,
|
||||||
@@ -627,7 +632,7 @@ fn serialize_internally_tagged_variant(
|
|||||||
StructVariant::InternallyTagged { tag, variant_name },
|
StructVariant::InternallyTagged { tag, variant_name },
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&type_name,
|
type_name,
|
||||||
),
|
),
|
||||||
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
||||||
}
|
}
|
||||||
@@ -637,12 +642,20 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
variant: &Variant,
|
variant: &Variant,
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
|
variant_index: u32,
|
||||||
tag: &str,
|
tag: &str,
|
||||||
content: &str,
|
content: &str,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let this = ¶ms.this;
|
let this_type = ¶ms.this_type;
|
||||||
let type_name = cattrs.name().serialize_name();
|
let type_name = cattrs.name().serialize_name();
|
||||||
let variant_name = variant.attrs.name().serialize_name();
|
let variant_name = variant.attrs.name().serialize_name();
|
||||||
|
let serialize_variant = quote! {
|
||||||
|
&_serde::#private::ser::AdjacentlyTaggedEnumVariant {
|
||||||
|
enum_name: #type_name,
|
||||||
|
variant_index: #variant_index,
|
||||||
|
variant_name: #variant_name,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
|
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
|
||||||
let ser = wrap_serialize_variant_with(params, path, variant);
|
let ser = wrap_serialize_variant_with(params, path, variant);
|
||||||
@@ -653,10 +666,10 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
match effective_style(variant) {
|
match effective_style(variant) {
|
||||||
Style::Unit => {
|
Style::Unit => {
|
||||||
return quote_block! {
|
return quote_block! {
|
||||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
let mut __struct = _serde::Serializer::serialize_struct(
|
||||||
__serializer, #type_name, 1));
|
__serializer, #type_name, 1)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __struct, #tag, #variant_name));
|
&mut __struct, #tag, #serialize_variant)?;
|
||||||
_serde::ser::SerializeStruct::end(__struct)
|
_serde::ser::SerializeStruct::end(__struct)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -670,12 +683,12 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
|
let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
|
||||||
return quote_block! {
|
return quote_block! {
|
||||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
let mut __struct = _serde::Serializer::serialize_struct(
|
||||||
__serializer, #type_name, 2));
|
__serializer, #type_name, 2)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __struct, #tag, #variant_name));
|
&mut __struct, #tag, #serialize_variant)?;
|
||||||
try!(#func(
|
#func(
|
||||||
&mut __struct, #content, #field_expr));
|
&mut __struct, #content, #field_expr)?;
|
||||||
_serde::ser::SerializeStruct::end(__struct)
|
_serde::ser::SerializeStruct::end(__struct)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -686,13 +699,13 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
StructVariant::Untagged,
|
StructVariant::Untagged,
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&variant_name,
|
variant_name,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let fields_ty = variant.fields.iter().map(|f| &f.ty);
|
let fields_ty = variant.fields.iter().map(|f| &f.ty);
|
||||||
let fields_ident: &Vec<_> = &match variant.style {
|
let fields_ident: &[_] = &match variant.style {
|
||||||
Style::Unit => {
|
Style::Unit => {
|
||||||
if variant.attrs.serialize_with().is_some() {
|
if variant.attrs.serialize_with().is_some() {
|
||||||
vec![]
|
vec![]
|
||||||
@@ -717,13 +730,15 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
|
#[doc(hidden)]
|
||||||
struct __AdjacentlyTagged #wrapper_generics #where_clause {
|
struct __AdjacentlyTagged #wrapper_generics #where_clause {
|
||||||
data: (#(&'__a #fields_ty,)*),
|
data: (#(&'__a #fields_ty,)*),
|
||||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
|
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
|
||||||
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
|
fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
|
||||||
where
|
where
|
||||||
__S: _serde::Serializer,
|
__S: _serde::Serializer,
|
||||||
{
|
{
|
||||||
@@ -734,15 +749,15 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
let mut __struct = _serde::Serializer::serialize_struct(
|
||||||
__serializer, #type_name, 2));
|
__serializer, #type_name, 2)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __struct, #tag, #variant_name));
|
&mut __struct, #tag, #serialize_variant)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __struct, #content, &__AdjacentlyTagged {
|
&mut __struct, #content, &__AdjacentlyTagged {
|
||||||
data: (#(#fields_ident,)*),
|
data: (#(#fields_ident,)*),
|
||||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
}));
|
})?;
|
||||||
_serde::ser::SerializeStruct::end(__struct)
|
_serde::ser::SerializeStruct::end(__struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -781,16 +796,16 @@ fn serialize_untagged_variant(
|
|||||||
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
|
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
let type_name = cattrs.name().serialize_name();
|
let type_name = cattrs.name().serialize_name();
|
||||||
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
|
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TupleVariant {
|
enum TupleVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
type_name: String,
|
type_name: &'a Name,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: String,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
@@ -832,21 +847,21 @@ fn serialize_tuple_variant(
|
|||||||
variant_name,
|
variant_name,
|
||||||
} => {
|
} => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
|
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
|
||||||
__serializer,
|
__serializer,
|
||||||
#type_name,
|
#type_name,
|
||||||
#variant_index,
|
#variant_index,
|
||||||
#variant_name,
|
#variant_name,
|
||||||
#len));
|
#len)?;
|
||||||
#(#serialize_stmts)*
|
#(#serialize_stmts)*
|
||||||
_serde::ser::SerializeTupleVariant::end(__serde_state)
|
_serde::ser::SerializeTupleVariant::end(__serde_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TupleVariant::Untagged => {
|
TupleVariant::Untagged => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
|
let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
|
||||||
__serializer,
|
__serializer,
|
||||||
#len));
|
#len)?;
|
||||||
#(#serialize_stmts)*
|
#(#serialize_stmts)*
|
||||||
_serde::ser::SerializeTuple::end(__serde_state)
|
_serde::ser::SerializeTuple::end(__serde_state)
|
||||||
}
|
}
|
||||||
@@ -857,20 +872,20 @@ fn serialize_tuple_variant(
|
|||||||
enum StructVariant<'a> {
|
enum StructVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: String,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
InternallyTagged {
|
InternallyTagged {
|
||||||
tag: &'a str,
|
tag: &'a str,
|
||||||
variant_name: String,
|
variant_name: &'a Name,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct_variant<'a>(
|
fn serialize_struct_variant(
|
||||||
context: StructVariant<'a>,
|
context: StructVariant,
|
||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
name: &str,
|
name: &Name,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
if fields.iter().any(|field| field.attrs.flatten()) {
|
if fields.iter().any(|field| field.attrs.flatten()) {
|
||||||
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
||||||
@@ -909,40 +924,40 @@ fn serialize_struct_variant<'a>(
|
|||||||
variant_name,
|
variant_name,
|
||||||
} => {
|
} => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
|
let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
|
||||||
__serializer,
|
__serializer,
|
||||||
#name,
|
#name,
|
||||||
#variant_index,
|
#variant_index,
|
||||||
#variant_name,
|
#variant_name,
|
||||||
#len,
|
#len,
|
||||||
));
|
)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeStructVariant::end(__serde_state)
|
_serde::ser::SerializeStructVariant::end(__serde_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
let mut __serde_state = _serde::Serializer::serialize_struct(
|
||||||
__serializer,
|
__serializer,
|
||||||
#name,
|
#name,
|
||||||
#len + 1,
|
#len + 1,
|
||||||
));
|
)?;
|
||||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
_serde::ser::SerializeStruct::serialize_field(
|
||||||
&mut __serde_state,
|
&mut __serde_state,
|
||||||
#tag,
|
#tag,
|
||||||
#variant_name,
|
#variant_name,
|
||||||
));
|
)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeStruct::end(__serde_state)
|
_serde::ser::SerializeStruct::end(__serde_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StructVariant::Untagged => {
|
StructVariant::Untagged => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
let #let_mut __serde_state = _serde::Serializer::serialize_struct(
|
||||||
__serializer,
|
__serializer,
|
||||||
#name,
|
#name,
|
||||||
#len,
|
#len,
|
||||||
));
|
)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeStruct::end(__serde_state)
|
_serde::ser::SerializeStruct::end(__serde_state)
|
||||||
}
|
}
|
||||||
@@ -950,11 +965,11 @@ fn serialize_struct_variant<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct_variant_with_flatten<'a>(
|
fn serialize_struct_variant_with_flatten(
|
||||||
context: StructVariant<'a>,
|
context: StructVariant,
|
||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
name: &str,
|
name: &Name,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let struct_trait = StructTrait::SerializeMap;
|
let struct_trait = StructTrait::SerializeMap;
|
||||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||||
@@ -971,7 +986,7 @@ fn serialize_struct_variant_with_flatten<'a>(
|
|||||||
variant_index,
|
variant_index,
|
||||||
variant_name,
|
variant_name,
|
||||||
} => {
|
} => {
|
||||||
let this = ¶ms.this;
|
let this_type = ¶ms.this_type;
|
||||||
let fields_ty = fields.iter().map(|f| &f.ty);
|
let fields_ty = fields.iter().map(|f| &f.ty);
|
||||||
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
|
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
|
||||||
|
|
||||||
@@ -980,20 +995,22 @@ fn serialize_struct_variant_with_flatten<'a>(
|
|||||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
|
#[doc(hidden)]
|
||||||
struct __EnumFlatten #wrapper_generics #where_clause {
|
struct __EnumFlatten #wrapper_generics #where_clause {
|
||||||
data: (#(&'__a #fields_ty,)*),
|
data: (#(&'__a #fields_ty,)*),
|
||||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
|
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
|
||||||
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
|
fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
|
||||||
where
|
where
|
||||||
__S: _serde::Serializer,
|
__S: _serde::Serializer,
|
||||||
{
|
{
|
||||||
let (#(#members,)*) = self.data;
|
let (#(#members,)*) = self.data;
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||||
__serializer,
|
__serializer,
|
||||||
_serde::__private::None));
|
_serde::#private::None)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeMap::end(__serde_state)
|
_serde::ser::SerializeMap::end(__serde_state)
|
||||||
}
|
}
|
||||||
@@ -1006,29 +1023,29 @@ fn serialize_struct_variant_with_flatten<'a>(
|
|||||||
#variant_name,
|
#variant_name,
|
||||||
&__EnumFlatten {
|
&__EnumFlatten {
|
||||||
data: (#(#members,)*),
|
data: (#(#members,)*),
|
||||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||||
__serializer,
|
__serializer,
|
||||||
_serde::__private::None));
|
_serde::#private::None)?;
|
||||||
try!(_serde::ser::SerializeMap::serialize_entry(
|
_serde::ser::SerializeMap::serialize_entry(
|
||||||
&mut __serde_state,
|
&mut __serde_state,
|
||||||
#tag,
|
#tag,
|
||||||
#variant_name,
|
#variant_name,
|
||||||
));
|
)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeMap::end(__serde_state)
|
_serde::ser::SerializeMap::end(__serde_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StructVariant::Untagged => {
|
StructVariant::Untagged => {
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||||
__serializer,
|
__serializer,
|
||||||
_serde::__private::None));
|
_serde::#private::None)?;
|
||||||
#(#serialize_fields)*
|
#(#serialize_fields)*
|
||||||
_serde::ser::SerializeMap::end(__serde_state)
|
_serde::ser::SerializeMap::end(__serde_state)
|
||||||
}
|
}
|
||||||
@@ -1073,7 +1090,7 @@ fn serialize_tuple_struct_visitor(
|
|||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
let func = tuple_trait.serialize_element(span);
|
let func = tuple_trait.serialize_element(span);
|
||||||
let ser = quote! {
|
let ser = quote! {
|
||||||
try!(#func(&mut __serde_state, #field_expr));
|
#func(&mut __serde_state, #field_expr)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
match skip {
|
match skip {
|
||||||
@@ -1117,12 +1134,12 @@ fn serialize_struct_visitor(
|
|||||||
let ser = if field.attrs.flatten() {
|
let ser = if field.attrs.flatten() {
|
||||||
let func = quote_spanned!(span=> _serde::Serialize::serialize);
|
let func = quote_spanned!(span=> _serde::Serialize::serialize);
|
||||||
quote! {
|
quote! {
|
||||||
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
|
#func(&#field_expr, _serde::#private::ser::FlatMapSerializer(&mut __serde_state))?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let func = struct_trait.serialize_field(span);
|
let func = struct_trait.serialize_field(span);
|
||||||
quote! {
|
quote! {
|
||||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
#func(&mut __serde_state, #key_expr, #field_expr)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1134,7 +1151,7 @@ fn serialize_struct_visitor(
|
|||||||
if !#skip {
|
if !#skip {
|
||||||
#ser
|
#ser
|
||||||
} else {
|
} else {
|
||||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
#skip_func(&mut __serde_state, #key_expr)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1192,7 +1209,7 @@ fn wrap_serialize_with(
|
|||||||
field_tys: &[&syn::Type],
|
field_tys: &[&syn::Type],
|
||||||
field_exprs: &[TokenStream],
|
field_exprs: &[TokenStream],
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let this = ¶ms.this;
|
let this_type = ¶ms.this_type;
|
||||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||||
|
|
||||||
let wrapper_generics = if field_exprs.is_empty() {
|
let wrapper_generics = if field_exprs.is_empty() {
|
||||||
@@ -1209,31 +1226,44 @@ fn wrap_serialize_with(
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
quote!({
|
let self_var = quote!(self);
|
||||||
|
let serializer_var = quote!(__s);
|
||||||
|
|
||||||
|
// If #serialize_with returns wrong type, error will be reported on here.
|
||||||
|
// We attach span of the path to this piece so error will be reported
|
||||||
|
// on the #[serde(with = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
let wrapper_serialize = quote_spanned! {serialize_with.span()=>
|
||||||
|
#serialize_with(#(#self_var.values.#field_access, )* #serializer_var)
|
||||||
|
};
|
||||||
|
|
||||||
|
quote!(&{
|
||||||
|
#[doc(hidden)]
|
||||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||||
values: (#(&'__a #field_tys, )*),
|
values: (#(&'__a #field_tys, )*),
|
||||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
|
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
|
||||||
fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
|
fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
|
||||||
where
|
where
|
||||||
__S: _serde::Serializer,
|
__S: _serde::Serializer,
|
||||||
{
|
{
|
||||||
#serialize_with(#(self.values.#field_access, )* __s)
|
#wrapper_serialize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__SerializeWith {
|
__SerializeWith {
|
||||||
values: (#(#field_exprs, )*),
|
values: (#(#field_exprs, )*),
|
||||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
phantom: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialization of an empty struct results in code like:
|
// Serialization of an empty struct results in code like:
|
||||||
//
|
//
|
||||||
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
|
// let mut __serde_state = serializer.serialize_struct("S", 0)?;
|
||||||
// _serde::ser::SerializeStruct::end(__serde_state)
|
// _serde::ser::SerializeStruct::end(__serde_state)
|
||||||
//
|
//
|
||||||
// where we want to omit the `mut` to avoid a warning.
|
// where we want to omit the `mut` to avoid a warning.
|
||||||
@@ -1262,11 +1292,11 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStrea
|
|||||||
quote!(&#self_var.#member)
|
quote!(&#self_var.#member)
|
||||||
};
|
};
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
quote!(_serde::__private::ser::constrain::<#ty>(#inner))
|
quote!(_serde::#private::ser::constrain::<#ty>(#inner))
|
||||||
}
|
}
|
||||||
(true, Some(getter)) => {
|
(true, Some(getter)) => {
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var)))
|
quote!(_serde::#private::ser::constrain::<#ty>(&#getter(#self_var)))
|
||||||
}
|
}
|
||||||
(false, Some(_)) => {
|
(false, Some(_)) => {
|
||||||
unreachable!("getter is only allowed for remote impls");
|
unreachable!("getter is only allowed for remote impls");
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
use crate::internals::ast::Container;
|
||||||
|
use syn::{Path, PathArguments, Token};
|
||||||
|
|
||||||
|
pub fn this_type(cont: &Container) -> Path {
|
||||||
|
if let Some(remote) = cont.attrs.remote() {
|
||||||
|
let mut this = remote.clone();
|
||||||
|
for segment in &mut this.segments {
|
||||||
|
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
|
||||||
|
arguments.colon2_token = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
Path::from(cont.ident.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn this_value(cont: &Container) -> Path {
|
||||||
|
if let Some(remote) = cont.attrs.remote() {
|
||||||
|
let mut this = remote.clone();
|
||||||
|
for segment in &mut this.segments {
|
||||||
|
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
|
||||||
|
if arguments.colon2_token.is_none() {
|
||||||
|
arguments.colon2_token = Some(Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
Path::from(cont.ident.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
use proc_macro2::{Punct, Spacing, TokenStream};
|
|
||||||
|
|
||||||
// None of our generated code requires the `From::from` error conversion
|
|
||||||
// performed by the standard library's `try!` macro. With this simplified macro
|
|
||||||
// we see a significant improvement in type checking and borrow checking time of
|
|
||||||
// the generated code and a slight improvement in binary size.
|
|
||||||
pub fn replacement() -> TokenStream {
|
|
||||||
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
|
|
||||||
let dollar = Punct::new('$', Spacing::Alone);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! try {
|
|
||||||
(#dollar __expr:expr) => {
|
|
||||||
match #dollar __expr {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
msrv = "1.31.0"
|
|
||||||
@@ -1,23 +1,32 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive_internals"
|
name = "serde_derive_internals"
|
||||||
version = "0.26.0" # remember to update html_root_url
|
version = "0.29.1"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
rust-version = "1.31"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
description = "AST representation used by Serde derive macros. Unstable."
|
description = "AST representation used by Serde derive macros. Unstable."
|
||||||
homepage = "https://serde.rs"
|
|
||||||
repository = "https://github.com/serde-rs/serde"
|
|
||||||
documentation = "https://docs.rs/serde_derive_internals"
|
documentation = "https://docs.rs/serde_derive_internals"
|
||||||
|
edition = "2021"
|
||||||
|
exclude = ["build.rs"]
|
||||||
|
homepage = "https://serde.rs"
|
||||||
keywords = ["serde", "serialization"]
|
keywords = ["serde", "serialization"]
|
||||||
include = ["lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
rust-version = "1.68"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = { workspace = true }
|
||||||
quote = "1.0"
|
quote = { workspace = true }
|
||||||
syn = { version = "1.0.90", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
|
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
rustdoc-args = [
|
||||||
|
"--generate-link-to-definition",
|
||||||
|
"--generate-macro-expansion",
|
||||||
|
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||||
|
"--extern-html-root-url=proc_macro=https://doc.rust-lang.org",
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Warning: build.rs is not published to crates.io.
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=src/mod.rs");
|
||||||
|
|
||||||
|
println!("cargo:rustc-cfg=check_cfg");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(serde_build_from_git)");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(feature, values(\"deserialize_in_place\"))");
|
||||||
|
|
||||||
// Sometimes on Windows the git checkout does not correctly wire up the
|
// Sometimes on Windows the git checkout does not correctly wire up the
|
||||||
// symlink from serde_derive_internals/src to serde_derive/src/internals.
|
// symlink from serde_derive_internals/src to serde_derive/src/internals.
|
||||||
// When this happens we'll just build based on relative paths within the git
|
// When this happens we'll just build based on relative paths within the git
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")]
|
||||||
#![allow(unknown_lints, bare_trait_objects)]
|
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::cognitive_complexity,
|
clippy::cognitive_complexity,
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||||
clippy::manual_map,
|
clippy::manual_map,
|
||||||
clippy::missing_panics_doc,
|
clippy::missing_panics_doc,
|
||||||
|
clippy::needless_lifetimes,
|
||||||
clippy::redundant_field_names,
|
clippy::redundant_field_names,
|
||||||
clippy::result_unit_err,
|
clippy::result_unit_err,
|
||||||
clippy::should_implement_trait,
|
clippy::should_implement_trait,
|
||||||
@@ -20,9 +21,10 @@
|
|||||||
// Ignored clippy_pedantic lints
|
// Ignored clippy_pedantic lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::doc_markdown,
|
clippy::doc_markdown,
|
||||||
|
clippy::elidable_lifetime_names,
|
||||||
clippy::enum_glob_use,
|
clippy::enum_glob_use,
|
||||||
clippy::items_after_statements,
|
clippy::items_after_statements,
|
||||||
clippy::let_underscore_drop,
|
clippy::let_underscore_untyped,
|
||||||
clippy::manual_assert,
|
clippy::manual_assert,
|
||||||
clippy::match_same_arms,
|
clippy::match_same_arms,
|
||||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
||||||
@@ -30,18 +32,20 @@
|
|||||||
clippy::missing_errors_doc,
|
clippy::missing_errors_doc,
|
||||||
clippy::module_name_repetitions,
|
clippy::module_name_repetitions,
|
||||||
clippy::must_use_candidate,
|
clippy::must_use_candidate,
|
||||||
|
clippy::return_self_not_must_use,
|
||||||
clippy::similar_names,
|
clippy::similar_names,
|
||||||
|
clippy::single_match_else,
|
||||||
clippy::struct_excessive_bools,
|
clippy::struct_excessive_bools,
|
||||||
clippy::too_many_lines,
|
clippy::too_many_lines,
|
||||||
|
clippy::uninlined_format_args,
|
||||||
clippy::unused_self,
|
clippy::unused_self,
|
||||||
clippy::wildcard_imports
|
clippy::wildcard_imports
|
||||||
)]
|
)]
|
||||||
|
#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
|
||||||
#[macro_use]
|
|
||||||
extern crate syn;
|
|
||||||
|
|
||||||
extern crate proc_macro2;
|
extern crate proc_macro2;
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
|
extern crate syn;
|
||||||
|
|
||||||
#[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
|
#[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
|
||||||
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
|
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
msrv = "1.13.0"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "serde_test"
|
|
||||||
version = "1.0.137" # remember to update html_root_url
|
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
|
||||||
rust-version = "1.13"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
|
||||||
homepage = "https://serde.rs"
|
|
||||||
repository = "https://github.com/serde-rs/serde"
|
|
||||||
documentation = "https://docs.serde.rs/serde_test/"
|
|
||||||
keywords = ["serde", "serialization"]
|
|
||||||
readme = "crates-io.md"
|
|
||||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
serde = { version = "1.0.60", path = "../serde" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
serde = { version = "1.0", path = "../serde" }
|
|
||||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../README.md
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::str::{self, FromStr};
|
|
||||||
|
|
||||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
|
||||||
// opening a GitHub issue if your build environment requires some way to enable
|
|
||||||
// these cfgs other than by executing our build script.
|
|
||||||
fn main() {
|
|
||||||
let minor = match rustc_minor_version() {
|
|
||||||
Some(minor) => minor,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
// #[track_caller] stabilized in Rust 1.46:
|
|
||||||
// https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller
|
|
||||||
if minor >= 46 {
|
|
||||||
println!("cargo:rustc-cfg=track_caller");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rustc_minor_version() -> Option<u32> {
|
|
||||||
let rustc = match env::var_os("RUSTC") {
|
|
||||||
Some(rustc) => rustc,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = match Command::new(rustc).arg("--version").output() {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let version = match str::from_utf8(&output.stdout) {
|
|
||||||
Ok(version) => version,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pieces = version.split('.');
|
|
||||||
if pieces.next() != Some("rustc 1") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next = match pieces.next() {
|
|
||||||
Some(next) => next,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32::from_str(next).ok()
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../crates-io.md
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use de::Deserializer;
|
|
||||||
use ser::Serializer;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_tokens(&s, &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
|
||||||
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
|
||||||
where
|
|
||||||
T: Serialize + Deserialize<'de> + PartialEq + Debug,
|
|
||||||
{
|
|
||||||
assert_ser_tokens(value, tokens);
|
|
||||||
assert_de_tokens(value, tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that `value` serializes to the given `tokens`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_ser_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_ser_tokens(&s, &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
|
||||||
pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
let mut ser = Serializer::new(tokens);
|
|
||||||
match value.serialize(&mut ser) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => panic!("value failed to serialize: {}", err),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ser.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", ser.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that `value` serializes to the given `tokens`, and then yields
|
|
||||||
/// `error`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// use std::sync::{Arc, Mutex};
|
|
||||||
/// use std::thread;
|
|
||||||
///
|
|
||||||
/// use serde::Serialize;
|
|
||||||
/// use serde_test::{assert_ser_tokens_error, Token};
|
|
||||||
///
|
|
||||||
/// #[derive(Serialize)]
|
|
||||||
/// struct Example {
|
|
||||||
/// lock: Arc<Mutex<u32>>,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// let example = Example { lock: Arc::new(Mutex::new(0)) };
|
|
||||||
/// let lock = example.lock.clone();
|
|
||||||
///
|
|
||||||
/// let _ = thread::spawn(move || {
|
|
||||||
/// // This thread will acquire the mutex first, unwrapping the result
|
|
||||||
/// // of `lock` because the lock has not been poisoned.
|
|
||||||
/// let _guard = lock.lock().unwrap();
|
|
||||||
///
|
|
||||||
/// // This panic while holding the lock (`_guard` is in scope) will
|
|
||||||
/// // poison the mutex.
|
|
||||||
/// panic!()
|
|
||||||
/// }).join();
|
|
||||||
///
|
|
||||||
/// let expected = &[
|
|
||||||
/// Token::Struct { name: "Example", len: 1 },
|
|
||||||
/// Token::Str("lock"),
|
|
||||||
/// ];
|
|
||||||
/// let error = "lock poison error while serializing";
|
|
||||||
/// assert_ser_tokens_error(&example, expected, error);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
|
||||||
pub fn assert_ser_tokens_error<T: ?Sized>(value: &T, tokens: &[Token], error: &str)
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
let mut ser = Serializer::new(tokens);
|
|
||||||
match value.serialize(&mut ser) {
|
|
||||||
Ok(_) => panic!("value serialized successfully"),
|
|
||||||
Err(e) => assert_eq!(e, *error),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ser.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", ser.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that the given `tokens` deserialize into `value`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_de_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_de_tokens(&s, &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
|
||||||
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
|
||||||
where
|
|
||||||
T: Deserialize<'de> + PartialEq + Debug,
|
|
||||||
{
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
let mut deserialized_val = match T::deserialize(&mut de) {
|
|
||||||
Ok(v) => {
|
|
||||||
assert_eq!(v, *value);
|
|
||||||
v
|
|
||||||
}
|
|
||||||
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
|
||||||
};
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the same thing for deserialize_in_place. This isn't *great* because a
|
|
||||||
// no-op impl of deserialize_in_place can technically succeed here. Still,
|
|
||||||
// this should catch a lot of junk.
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
|
|
||||||
Ok(()) => {
|
|
||||||
assert_eq!(deserialized_val, *value);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
|
|
||||||
}
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that the given `tokens` yield `error` when deserializing.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_de_tokens_error, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// #[serde(deny_unknown_fields)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// assert_de_tokens_error::<S>(
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("x"),
|
|
||||||
/// ],
|
|
||||||
/// "unknown field `x`, expected `a` or `b`",
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
|
||||||
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
match T::deserialize(&mut de) {
|
|
||||||
Ok(_) => panic!("tokens deserialized successfully"),
|
|
||||||
Err(e) => assert_eq!(e, *error),
|
|
||||||
}
|
|
||||||
|
|
||||||
// There may be one token left if a peek caused the error
|
|
||||||
de.next_token_opt();
|
|
||||||
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,847 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
|
|
||||||
use serde::ser::{
|
|
||||||
SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
|
|
||||||
SerializeTupleStruct, SerializeTupleVariant,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Readable<T: ?Sized>(T);
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Compact<T: ?Sized>(T);
|
|
||||||
|
|
||||||
/// Trait to determine whether a value is represented in human-readable or
|
|
||||||
/// compact form.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
/// use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
///
|
|
||||||
/// #[derive(Debug, PartialEq)]
|
|
||||||
/// struct Example(u8, u8);
|
|
||||||
///
|
|
||||||
/// impl Serialize for Example {
|
|
||||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
/// where
|
|
||||||
/// S: Serializer,
|
|
||||||
/// {
|
|
||||||
/// if serializer.is_human_readable() {
|
|
||||||
/// format!("{}.{}", self.0, self.1).serialize(serializer)
|
|
||||||
/// } else {
|
|
||||||
/// (self.0, self.1).serialize(serializer)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl<'de> Deserialize<'de> for Example {
|
|
||||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
/// where
|
|
||||||
/// D: Deserializer<'de>,
|
|
||||||
/// {
|
|
||||||
/// use serde::de::Error;
|
|
||||||
/// if deserializer.is_human_readable() {
|
|
||||||
/// let s = String::deserialize(deserializer)?;
|
|
||||||
/// let parts: Vec<_> = s.split('.').collect();
|
|
||||||
/// Ok(Example(
|
|
||||||
/// parts[0].parse().map_err(D::Error::custom)?,
|
|
||||||
/// parts[1].parse().map_err(D::Error::custom)?,
|
|
||||||
/// ))
|
|
||||||
/// } else {
|
|
||||||
/// let (x, y) = Deserialize::deserialize(deserializer)?;
|
|
||||||
/// Ok(Example(x, y))
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &Example(1, 0).compact(),
|
|
||||||
/// &[
|
|
||||||
/// Token::Tuple { len: 2 },
|
|
||||||
/// Token::U8(1),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// assert_tokens(&Example(1, 0).readable(), &[Token::Str("1.0")]);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait Configure {
|
|
||||||
/// Marks `self` as using `is_human_readable == true`
|
|
||||||
fn readable(self) -> Readable<Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Readable(self)
|
|
||||||
}
|
|
||||||
/// Marks `self` as using `is_human_readable == false`
|
|
||||||
fn compact(self) -> Compact<Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Compact(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> Configure for T {}
|
|
||||||
|
|
||||||
impl<T: ?Sized> Serialize for Readable<T>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
self.0.serialize(Readable(serializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: ?Sized> Serialize for Compact<T>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
self.0.serialize(Compact(serializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> Deserialize<'de> for Readable<T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
T::deserialize(Readable(deserializer)).map(Readable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> Deserialize<'de> for Compact<T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
T::deserialize(Compact(deserializer)).map(Compact)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, T> DeserializeSeed<'de> for Readable<T>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
type Value = T::Value;
|
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize(Readable(deserializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> DeserializeSeed<'de> for Compact<T>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
type Value = T::Value;
|
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize(Compact(deserializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! forward_method {
|
|
||||||
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
|
|
||||||
fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
|
|
||||||
(self.0).$name( $($arg),* )
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! forward_serialize_methods {
|
|
||||||
( $( $name: ident $arg_type: ty ),* ) => {
|
|
||||||
$(
|
|
||||||
forward_method!($name(self, v : $arg_type) -> Result<Self::Ok, Self::Error>);
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_serializer {
|
|
||||||
($wrapper:ident, $is_human_readable:expr) => {
|
|
||||||
impl<S> Serializer for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
|
|
||||||
type SerializeSeq = $wrapper<S::SerializeSeq>;
|
|
||||||
type SerializeTuple = $wrapper<S::SerializeTuple>;
|
|
||||||
type SerializeTupleStruct = $wrapper<S::SerializeTupleStruct>;
|
|
||||||
type SerializeTupleVariant = $wrapper<S::SerializeTupleVariant>;
|
|
||||||
type SerializeMap = $wrapper<S::SerializeMap>;
|
|
||||||
type SerializeStruct = $wrapper<S::SerializeStruct>;
|
|
||||||
type SerializeStructVariant = $wrapper<S::SerializeStructVariant>;
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
$is_human_readable
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_serialize_methods! {
|
|
||||||
serialize_bool bool,
|
|
||||||
serialize_i8 i8,
|
|
||||||
serialize_i16 i16,
|
|
||||||
serialize_i32 i32,
|
|
||||||
serialize_i64 i64,
|
|
||||||
serialize_u8 u8,
|
|
||||||
serialize_u16 u16,
|
|
||||||
serialize_u32 u32,
|
|
||||||
serialize_u64 u64,
|
|
||||||
serialize_f32 f32,
|
|
||||||
serialize_f64 f64,
|
|
||||||
serialize_char char,
|
|
||||||
serialize_str &str,
|
|
||||||
serialize_bytes &[u8],
|
|
||||||
serialize_unit_struct &'static str
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.serialize_unit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.serialize_unit_variant(name, variant_index, variant)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_newtype_struct(name, &$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.serialize_newtype_variant(name, variant_index, variant, &$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<S::Ok, Self::Error> {
|
|
||||||
self.0.serialize_none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<S::Ok, Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_some(&$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
|
||||||
self.0.serialize_seq(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
|
||||||
self.0.serialize_tuple(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
|
||||||
self.0.serialize_tuple_struct(name, len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
|
||||||
self.0
|
|
||||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
|
||||||
.map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
|
||||||
self.0.serialize_map(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
|
||||||
self.0.serialize_struct(name, len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
|
||||||
self.0
|
|
||||||
.serialize_struct_variant(name, variant_index, variant, len)
|
|
||||||
.map($wrapper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeSeq for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeSeq,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_element(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTuple for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTuple,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_element(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTupleStruct for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTupleStruct,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTupleVariant for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTupleVariant,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeMap for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeMap,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_key(&$wrapper(key))
|
|
||||||
}
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_value(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &K,
|
|
||||||
value: &V,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
K: Serialize,
|
|
||||||
V: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_entry(key, &$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeStruct for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeStruct,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
name: &'static str,
|
|
||||||
field: &T,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(name, &$wrapper(field))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeStructVariant for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeStructVariant,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
name: &'static str,
|
|
||||||
field: &T,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(name, &$wrapper(field))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_serializer!(Readable, true);
|
|
||||||
impl_serializer!(Compact, false);
|
|
||||||
|
|
||||||
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
|
|
||||||
|
|
||||||
macro_rules! forward_deserialize_methods {
|
|
||||||
( $wrapper : ident ( $( $name: ident ),* ) ) => {
|
|
||||||
$(
|
|
||||||
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
(self.0).$name($wrapper(visitor))
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_deserializer {
|
|
||||||
($wrapper:ident, $is_human_readable:expr) => {
|
|
||||||
impl<'de, D> Deserializer<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
|
|
||||||
forward_deserialize_methods! {
|
|
||||||
$wrapper (
|
|
||||||
deserialize_any,
|
|
||||||
deserialize_bool,
|
|
||||||
deserialize_u8,
|
|
||||||
deserialize_u16,
|
|
||||||
deserialize_u32,
|
|
||||||
deserialize_u64,
|
|
||||||
deserialize_i8,
|
|
||||||
deserialize_i16,
|
|
||||||
deserialize_i32,
|
|
||||||
deserialize_i64,
|
|
||||||
deserialize_f32,
|
|
||||||
deserialize_f64,
|
|
||||||
deserialize_char,
|
|
||||||
deserialize_str,
|
|
||||||
deserialize_string,
|
|
||||||
deserialize_bytes,
|
|
||||||
deserialize_byte_buf,
|
|
||||||
deserialize_option,
|
|
||||||
deserialize_unit,
|
|
||||||
deserialize_seq,
|
|
||||||
deserialize_map,
|
|
||||||
deserialize_identifier,
|
|
||||||
deserialize_ignored_any
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_unit_struct(name, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_newtype_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_newtype_struct(name, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_tuple(len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_tuple_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.deserialize_tuple_struct(name, len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_struct(name, fields, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_enum<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variants: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_enum(name, variants, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
$is_human_readable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> Visitor<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: Visitor<'de>,
|
|
||||||
{
|
|
||||||
type Value = D::Value;
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.expecting(formatter)
|
|
||||||
}
|
|
||||||
fn visit_bool<E>(self, v: bool) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_bool(v)
|
|
||||||
}
|
|
||||||
fn visit_i8<E>(self, v: i8) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i8(v)
|
|
||||||
}
|
|
||||||
fn visit_i16<E>(self, v: i16) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i16(v)
|
|
||||||
}
|
|
||||||
fn visit_i32<E>(self, v: i32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i32(v)
|
|
||||||
}
|
|
||||||
fn visit_i64<E>(self, v: i64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i64(v)
|
|
||||||
}
|
|
||||||
fn visit_u8<E>(self, v: u8) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u8(v)
|
|
||||||
}
|
|
||||||
fn visit_u16<E>(self, v: u16) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u16(v)
|
|
||||||
}
|
|
||||||
fn visit_u32<E>(self, v: u32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u32(v)
|
|
||||||
}
|
|
||||||
fn visit_u64<E>(self, v: u64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u64(v)
|
|
||||||
}
|
|
||||||
fn visit_f32<E>(self, v: f32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_f32(v)
|
|
||||||
}
|
|
||||||
fn visit_f64<E>(self, v: f64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_f64(v)
|
|
||||||
}
|
|
||||||
fn visit_char<E>(self, v: char) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_char(v)
|
|
||||||
}
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_str(v)
|
|
||||||
}
|
|
||||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_borrowed_str(v)
|
|
||||||
}
|
|
||||||
fn visit_string<E>(self, v: String) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_string(v)
|
|
||||||
}
|
|
||||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_bytes(v)
|
|
||||||
}
|
|
||||||
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_borrowed_bytes(v)
|
|
||||||
}
|
|
||||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_byte_buf(v)
|
|
||||||
}
|
|
||||||
fn visit_none<E>(self) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_none()
|
|
||||||
}
|
|
||||||
fn visit_some<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
|
||||||
where
|
|
||||||
D2: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_some($wrapper(deserializer))
|
|
||||||
}
|
|
||||||
fn visit_unit<E>(self) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_unit()
|
|
||||||
}
|
|
||||||
fn visit_newtype_struct<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
|
||||||
where
|
|
||||||
D2: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_newtype_struct($wrapper(deserializer))
|
|
||||||
}
|
|
||||||
fn visit_seq<V>(self, seq: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_seq($wrapper(seq))
|
|
||||||
}
|
|
||||||
fn visit_map<V>(self, map: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_map($wrapper(map))
|
|
||||||
}
|
|
||||||
fn visit_enum<V>(self, data: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: EnumAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_enum($wrapper(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> SeqAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, D::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_element_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.0.size_hint()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> MapAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, D::Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_key_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_value_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn next_entry_seed<K, V>(
|
|
||||||
&mut self,
|
|
||||||
kseed: K,
|
|
||||||
vseed: V,
|
|
||||||
) -> Result<Option<(K::Value, V::Value)>, D::Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_entry_seed($wrapper(kseed), $wrapper(vseed))
|
|
||||||
}
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.0.size_hint()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> EnumAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: EnumAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
type Variant = $wrapper<D::Variant>;
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.variant_seed($wrapper(seed))
|
|
||||||
.map(|(value, variant)| (value, $wrapper(variant)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> VariantAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: VariantAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn unit_variant(self) -> Result<(), D::Error> {
|
|
||||||
self.0.unit_variant()
|
|
||||||
}
|
|
||||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, D::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.newtype_variant_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.tuple_variant(len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn struct_variant<V>(
|
|
||||||
self,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.struct_variant(fields, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_deserializer!(Readable, true);
|
|
||||||
impl_deserializer!(Compact, false);
|
|
||||||
@@ -1,683 +0,0 @@
|
|||||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
|
||||||
use serde::de::{
|
|
||||||
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
|
|
||||||
VariantAccess, Visitor,
|
|
||||||
};
|
|
||||||
|
|
||||||
use error::Error;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Deserializer<'de> {
|
|
||||||
tokens: &'de [Token],
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! assert_next_token {
|
|
||||||
($de:expr, $expected:expr) => {
|
|
||||||
match $de.next_token_opt() {
|
|
||||||
Some(token) if token == $expected => {}
|
|
||||||
Some(other) => panic!(
|
|
||||||
"expected Token::{} but deserialization wants Token::{}",
|
|
||||||
other, $expected
|
|
||||||
),
|
|
||||||
None => panic!(
|
|
||||||
"end of tokens but deserialization wants Token::{}",
|
|
||||||
$expected
|
|
||||||
),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! unexpected {
|
|
||||||
($token:expr) => {
|
|
||||||
panic!("deserialization did not expect this token: {}", $token)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! end_of_tokens {
|
|
||||||
() => {
|
|
||||||
panic!("ran out of tokens to deserialize")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserializer<'de> {
|
|
||||||
pub fn new(tokens: &'de [Token]) -> Self {
|
|
||||||
Deserializer { tokens: tokens }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn peek_token_opt(&self) -> Option<Token> {
|
|
||||||
self.tokens.first().cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn peek_token(&self) -> Token {
|
|
||||||
match self.peek_token_opt() {
|
|
||||||
Some(token) => token,
|
|
||||||
None => end_of_tokens!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_token_opt(&mut self) -> Option<Token> {
|
|
||||||
match self.tokens.split_first() {
|
|
||||||
Some((&first, rest)) => {
|
|
||||||
self.tokens = rest;
|
|
||||||
Some(first)
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_token(&mut self) -> Token {
|
|
||||||
match self.tokens.split_first() {
|
|
||||||
Some((&first, rest)) => {
|
|
||||||
self.tokens = rest;
|
|
||||||
first
|
|
||||||
}
|
|
||||||
None => end_of_tokens!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remaining(&self) -> usize {
|
|
||||||
self.tokens.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<V>(
|
|
||||||
&mut self,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let value = visitor.visit_seq(DeserializerSeqVisitor {
|
|
||||||
de: self,
|
|
||||||
len: len,
|
|
||||||
end: end,
|
|
||||||
})?;
|
|
||||||
assert_next_token!(self, end);
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<V>(
|
|
||||||
&mut self,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let value = visitor.visit_map(DeserializerMapVisitor {
|
|
||||||
de: self,
|
|
||||||
len: len,
|
|
||||||
end: end,
|
|
||||||
})?;
|
|
||||||
assert_next_token!(self, end);
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf unit seq map identifier ignored_any
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let token = self.next_token();
|
|
||||||
match token {
|
|
||||||
Token::Bool(v) => visitor.visit_bool(v),
|
|
||||||
Token::I8(v) => visitor.visit_i8(v),
|
|
||||||
Token::I16(v) => visitor.visit_i16(v),
|
|
||||||
Token::I32(v) => visitor.visit_i32(v),
|
|
||||||
Token::I64(v) => visitor.visit_i64(v),
|
|
||||||
Token::U8(v) => visitor.visit_u8(v),
|
|
||||||
Token::U16(v) => visitor.visit_u16(v),
|
|
||||||
Token::U32(v) => visitor.visit_u32(v),
|
|
||||||
Token::U64(v) => visitor.visit_u64(v),
|
|
||||||
Token::F32(v) => visitor.visit_f32(v),
|
|
||||||
Token::F64(v) => visitor.visit_f64(v),
|
|
||||||
Token::Char(v) => visitor.visit_char(v),
|
|
||||||
Token::Str(v) => visitor.visit_str(v),
|
|
||||||
Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
|
|
||||||
Token::String(v) => visitor.visit_string(v.to_owned()),
|
|
||||||
Token::Bytes(v) => visitor.visit_bytes(v),
|
|
||||||
Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
|
|
||||||
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
|
|
||||||
Token::None => visitor.visit_none(),
|
|
||||||
Token::Some => visitor.visit_some(self),
|
|
||||||
Token::Unit | Token::UnitStruct { .. } => visitor.visit_unit(),
|
|
||||||
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
|
|
||||||
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
|
|
||||||
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
|
|
||||||
Token::TupleStruct { len, .. } => {
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
|
||||||
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
|
||||||
Token::Enum { .. } => {
|
|
||||||
let variant = self.next_token();
|
|
||||||
let next = self.peek_token();
|
|
||||||
match (variant, next) {
|
|
||||||
(Token::Str(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_str(variant)
|
|
||||||
}
|
|
||||||
(Token::BorrowedStr(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_borrowed_str(variant)
|
|
||||||
}
|
|
||||||
(Token::String(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_string(variant.to_string())
|
|
||||||
}
|
|
||||||
(Token::Bytes(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_bytes(variant)
|
|
||||||
}
|
|
||||||
(Token::BorrowedBytes(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_borrowed_bytes(variant)
|
|
||||||
}
|
|
||||||
(Token::ByteBuf(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_byte_buf(variant.to_vec())
|
|
||||||
}
|
|
||||||
(Token::U8(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_u8(variant)
|
|
||||||
}
|
|
||||||
(Token::U16(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_u16(variant)
|
|
||||||
}
|
|
||||||
(Token::U32(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_u32(variant)
|
|
||||||
}
|
|
||||||
(Token::U64(variant), Token::Unit) => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_u64(variant)
|
|
||||||
}
|
|
||||||
(variant, Token::Unit) => unexpected!(variant),
|
|
||||||
(variant, _) => {
|
|
||||||
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
|
||||||
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Any,
|
|
||||||
)),
|
|
||||||
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Seq,
|
|
||||||
)),
|
|
||||||
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Map,
|
|
||||||
)),
|
|
||||||
Token::SeqEnd
|
|
||||||
| Token::TupleEnd
|
|
||||||
| Token::TupleStructEnd
|
|
||||||
| Token::MapEnd
|
|
||||||
| Token::StructEnd
|
|
||||||
| Token::TupleVariantEnd
|
|
||||||
| Token::StructVariantEnd => {
|
|
||||||
unexpected!(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::Unit | Token::None => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_none()
|
|
||||||
}
|
|
||||||
Token::Some => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_some(self)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_enum<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variants: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::Enum { name: n } if name == n => {
|
|
||||||
self.next_token();
|
|
||||||
|
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
|
||||||
}
|
|
||||||
Token::UnitVariant { name: n, .. }
|
|
||||||
| Token::NewtypeVariant { name: n, .. }
|
|
||||||
| Token::TupleVariant { name: n, .. }
|
|
||||||
| Token::StructVariant { name: n, .. }
|
|
||||||
if name == n =>
|
|
||||||
{
|
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::UnitStruct { .. } => {
|
|
||||||
assert_next_token!(self, Token::UnitStruct { name: name });
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::NewtypeStruct { .. } => {
|
|
||||||
assert_next_token!(self, Token::NewtypeStruct { name: name });
|
|
||||||
visitor.visit_newtype_struct(self)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::Unit | Token::UnitStruct { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::Seq { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Tuple { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::TupleStruct { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::Unit => {
|
|
||||||
self.next_token();
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::UnitStruct { .. } => {
|
|
||||||
assert_next_token!(self, Token::UnitStruct { name: name });
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::Seq { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Tuple { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::TupleStruct { len: n, .. } => {
|
|
||||||
assert_next_token!(self, Token::TupleStruct { name: name, len: n });
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token() {
|
|
||||||
Token::Struct { len: n, .. } => {
|
|
||||||
assert_next_token!(self, Token::Struct { name: name, len: n });
|
|
||||||
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Map { .. } => {
|
|
||||||
self.next_token();
|
|
||||||
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
panic!(
|
|
||||||
"Types which have different human-readable and compact representations \
|
|
||||||
must explicitly mark their test cases with `serde_test::Configure`"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerSeqVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
if self.de.peek_token_opt() == Some(self.end) {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
|
||||||
seed.deserialize(&mut *self.de).map(Some)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerMapVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
if self.de.peek_token_opt() == Some(self.end) {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
|
||||||
seed.deserialize(&mut *self.de).map(Some)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
seed.deserialize(&mut *self.de)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerEnumVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
type Variant = Self;
|
|
||||||
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token() {
|
|
||||||
Token::UnitVariant { variant: v, .. }
|
|
||||||
| Token::NewtypeVariant { variant: v, .. }
|
|
||||||
| Token::TupleVariant { variant: v, .. }
|
|
||||||
| Token::StructVariant { variant: v, .. } => {
|
|
||||||
let de = v.into_deserializer();
|
|
||||||
let value = seed.deserialize(de)?;
|
|
||||||
Ok((value, self))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let value = seed.deserialize(&mut *self.de)?;
|
|
||||||
Ok((value, self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn unit_variant(self) -> Result<(), Error> {
|
|
||||||
match self.de.peek_token() {
|
|
||||||
Token::UnitVariant { .. } => {
|
|
||||||
self.de.next_token();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Deserialize::deserialize(self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token() {
|
|
||||||
Token::NewtypeVariant { .. } => {
|
|
||||||
self.de.next_token();
|
|
||||||
seed.deserialize(self.de)
|
|
||||||
}
|
|
||||||
_ => seed.deserialize(self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token() {
|
|
||||||
Token::TupleVariant { len: enum_len, .. } => {
|
|
||||||
let token = self.de.next_token();
|
|
||||||
|
|
||||||
if len == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_seq(Some(len), Token::TupleVariantEnd, visitor)
|
|
||||||
} else {
|
|
||||||
unexpected!(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::Seq {
|
|
||||||
len: Some(enum_len),
|
|
||||||
} => {
|
|
||||||
let token = self.de.next_token();
|
|
||||||
|
|
||||||
if len == enum_len {
|
|
||||||
self.de.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
} else {
|
|
||||||
unexpected!(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => de::Deserializer::deserialize_any(self.de, visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn struct_variant<V>(
|
|
||||||
self,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token() {
|
|
||||||
Token::StructVariant { len: enum_len, .. } => {
|
|
||||||
let token = self.de.next_token();
|
|
||||||
|
|
||||||
if fields.len() == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
|
|
||||||
} else {
|
|
||||||
unexpected!(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::Map {
|
|
||||||
len: Some(enum_len),
|
|
||||||
} => {
|
|
||||||
let token = self.de.next_token();
|
|
||||||
|
|
||||||
if fields.len() == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
|
||||||
} else {
|
|
||||||
unexpected!(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => de::Deserializer::deserialize_any(self.de, visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct EnumMapVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
variant: Option<Token>,
|
|
||||||
format: EnumFormat,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EnumFormat {
|
|
||||||
Seq,
|
|
||||||
Map,
|
|
||||||
Any,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
|
|
||||||
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
|
|
||||||
EnumMapVisitor {
|
|
||||||
de: de,
|
|
||||||
variant: Some(variant),
|
|
||||||
format: format,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.variant.take() {
|
|
||||||
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
|
||||||
Some(Token::Bytes(variant)) => seed
|
|
||||||
.deserialize(BytesDeserializer { value: variant })
|
|
||||||
.map(Some),
|
|
||||||
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
|
||||||
Some(other) => unexpected!(other),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.format {
|
|
||||||
EnumFormat::Seq => {
|
|
||||||
let value = {
|
|
||||||
let visitor = DeserializerSeqVisitor {
|
|
||||||
de: self.de,
|
|
||||||
len: None,
|
|
||||||
end: Token::TupleVariantEnd,
|
|
||||||
};
|
|
||||||
seed.deserialize(SeqAccessDeserializer::new(visitor))?
|
|
||||||
};
|
|
||||||
assert_next_token!(self.de, Token::TupleVariantEnd);
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
EnumFormat::Map => {
|
|
||||||
let value = {
|
|
||||||
let visitor = DeserializerMapVisitor {
|
|
||||||
de: self.de,
|
|
||||||
len: None,
|
|
||||||
end: Token::StructVariantEnd,
|
|
||||||
};
|
|
||||||
seed.deserialize(MapAccessDeserializer::new(visitor))?
|
|
||||||
};
|
|
||||||
assert_next_token!(self.de, Token::StructVariantEnd);
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
EnumFormat::Any => seed.deserialize(&mut *self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BytesDeserializer {
|
|
||||||
value: &'static [u8],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> de::Deserializer<'de> for BytesDeserializer {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
|
||||||
V: de::Visitor<'de>,
|
|
||||||
{
|
|
||||||
visitor.visit_bytes(self.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
||||||
tuple_struct map struct enum identifier ignored_any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
use std::error;
|
|
||||||
use std::fmt::{self, Display};
|
|
||||||
|
|
||||||
use serde::{de, ser};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Error {
|
|
||||||
msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ser::Error for Error {
|
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
|
||||||
Error {
|
|
||||||
msg: msg.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl de::Error for Error {
|
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
|
||||||
Error {
|
|
||||||
msg: msg.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str(&self.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for Error {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
&self.msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq<str> for Error {
|
|
||||||
fn eq(&self, other: &str) -> bool {
|
|
||||||
self.msg == other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
//! This crate provides a convenient concise way to write unit tests for
|
|
||||||
//! implementations of [`Serialize`] and [`Deserialize`].
|
|
||||||
//!
|
|
||||||
//! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html
|
|
||||||
//! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
|
|
||||||
//!
|
|
||||||
//! The `Serialize` impl for a value can be characterized by the sequence of
|
|
||||||
//! [`Serializer`] calls that are made in the course of serializing the value,
|
|
||||||
//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly
|
|
||||||
//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to
|
|
||||||
//! test that a value serializes to a particular sequence of method calls, an
|
|
||||||
//! [`assert_de_tokens`] function to test that a value can be deserialized from
|
|
||||||
//! a particular sequence of method calls, and an [`assert_tokens`] function to
|
|
||||||
//! test both directions. There are also functions to test expected failure
|
|
||||||
//! conditions.
|
|
||||||
//!
|
|
||||||
//! [`Serializer`]: https://docs.serde.rs/serde/ser/trait.Serializer.html
|
|
||||||
//! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html
|
|
||||||
//! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html
|
|
||||||
//! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html
|
|
||||||
//! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html
|
|
||||||
//!
|
|
||||||
//! Here is an example from the [`linked-hash-map`] crate.
|
|
||||||
//!
|
|
||||||
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
|
|
||||||
//!
|
|
||||||
//! ```edition2018
|
|
||||||
//! # const IGNORE: &str = stringify! {
|
|
||||||
//! use linked_hash_map::LinkedHashMap;
|
|
||||||
//! # };
|
|
||||||
//! use serde_test::{Token, assert_tokens};
|
|
||||||
//!
|
|
||||||
//! # use std::fmt;
|
|
||||||
//! # use std::marker::PhantomData;
|
|
||||||
//! #
|
|
||||||
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
|
|
||||||
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
|
|
||||||
//! #
|
|
||||||
//! # // Dumb imitation of LinkedHashMap.
|
|
||||||
//! # #[derive(PartialEq, Debug)]
|
|
||||||
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
|
|
||||||
//! #
|
|
||||||
//! # impl<K, V> LinkedHashMap<K, V> {
|
|
||||||
//! # fn new() -> Self {
|
|
||||||
//! # LinkedHashMap(Vec::new())
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # fn insert(&mut self, k: K, v: V) {
|
|
||||||
//! # self.0.push((k, v));
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Serialize,
|
|
||||||
//! # V: Serialize,
|
|
||||||
//! # {
|
|
||||||
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
//! # where
|
|
||||||
//! # S: Serializer,
|
|
||||||
//! # {
|
|
||||||
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
|
|
||||||
//! # for &(ref k, ref v) in &self.0 {
|
|
||||||
//! # map.serialize_entry(k, v)?;
|
|
||||||
//! # }
|
|
||||||
//! # map.end()
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
|
|
||||||
//! #
|
|
||||||
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Deserialize<'de>,
|
|
||||||
//! # V: Deserialize<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # type Value = LinkedHashMap<K, V>;
|
|
||||||
//! #
|
|
||||||
//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
//! # unimplemented!()
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
|
||||||
//! # where
|
|
||||||
//! # M: MapAccess<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # let mut map = LinkedHashMap::new();
|
|
||||||
//! # while let Some((key, value)) = access.next_entry()? {
|
|
||||||
//! # map.insert(key, value);
|
|
||||||
//! # }
|
|
||||||
//! # Ok(map)
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Deserialize<'de>,
|
|
||||||
//! # V: Deserialize<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
//! # where
|
|
||||||
//! # D: Deserializer<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! #[test]
|
|
||||||
//! # fn not_a_test_ser_de_empty() {}
|
|
||||||
//! fn test_ser_de_empty() {
|
|
||||||
//! let map = LinkedHashMap::<char, u32>::new();
|
|
||||||
//!
|
|
||||||
//! assert_tokens(&map, &[
|
|
||||||
//! Token::Map { len: Some(0) },
|
|
||||||
//! Token::MapEnd,
|
|
||||||
//! ]);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! #[test]
|
|
||||||
//! # fn not_a_test_ser_de() {}
|
|
||||||
//! fn test_ser_de() {
|
|
||||||
//! let mut map = LinkedHashMap::new();
|
|
||||||
//! map.insert('b', 20);
|
|
||||||
//! map.insert('a', 10);
|
|
||||||
//! map.insert('c', 30);
|
|
||||||
//!
|
|
||||||
//! assert_tokens(&map, &[
|
|
||||||
//! Token::Map { len: Some(3) },
|
|
||||||
//! Token::Char('b'),
|
|
||||||
//! Token::I32(20),
|
|
||||||
//!
|
|
||||||
//! Token::Char('a'),
|
|
||||||
//! Token::I32(10),
|
|
||||||
//!
|
|
||||||
//! Token::Char('c'),
|
|
||||||
//! Token::I32(30),
|
|
||||||
//! Token::MapEnd,
|
|
||||||
//! ]);
|
|
||||||
//! }
|
|
||||||
//! #
|
|
||||||
//! # fn main() {
|
|
||||||
//! # test_ser_de_empty();
|
|
||||||
//! # test_ser_de();
|
|
||||||
//! # }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.137")]
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
|
||||||
// Ignored clippy lints
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
|
|
||||||
// Ignored clippy_pedantic lints
|
|
||||||
#![cfg_attr(
|
|
||||||
feature = "cargo-clippy",
|
|
||||||
allow(
|
|
||||||
cloned_instead_of_copied,
|
|
||||||
doc_link_with_quotes, // https://github.com/rust-lang/rust-clippy/issues/8961
|
|
||||||
empty_line_after_outer_attr,
|
|
||||||
manual_assert,
|
|
||||||
missing_docs_in_private_items,
|
|
||||||
missing_panics_doc,
|
|
||||||
module_name_repetitions,
|
|
||||||
must_use_candidate,
|
|
||||||
redundant_field_names,
|
|
||||||
too_many_lines,
|
|
||||||
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
|
|
||||||
use_debug,
|
|
||||||
use_self
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde;
|
|
||||||
|
|
||||||
mod de;
|
|
||||||
mod error;
|
|
||||||
mod ser;
|
|
||||||
|
|
||||||
mod assert;
|
|
||||||
mod configure;
|
|
||||||
mod token;
|
|
||||||
|
|
||||||
pub use assert::{
|
|
||||||
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
|
|
||||||
assert_tokens,
|
|
||||||
};
|
|
||||||
pub use token::Token;
|
|
||||||
|
|
||||||
pub use configure::{Compact, Configure, Readable};
|
|
||||||
|
|
||||||
// Not public API.
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub use de::Deserializer;
|
|
||||||
@@ -1,464 +0,0 @@
|
|||||||
use serde::{ser, Serialize};
|
|
||||||
|
|
||||||
use error::Error;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
/// A `Serializer` that ensures that a value serializes to a given list of
|
|
||||||
/// tokens.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Serializer<'a> {
|
|
||||||
tokens: &'a [Token],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serializer<'a> {
|
|
||||||
/// Creates the serializer.
|
|
||||||
pub fn new(tokens: &'a [Token]) -> Self {
|
|
||||||
Serializer { tokens: tokens }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pulls the next token off of the serializer, ignoring it.
|
|
||||||
fn next_token(&mut self) -> Option<Token> {
|
|
||||||
if let Some((&first, rest)) = self.tokens.split_first() {
|
|
||||||
self.tokens = rest;
|
|
||||||
Some(first)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remaining(&self) -> usize {
|
|
||||||
self.tokens.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! assert_next_token {
|
|
||||||
($ser:expr, $actual:ident) => {{
|
|
||||||
assert_next_token!($ser, stringify!($actual), Token::$actual, true);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:ident($v:expr)) => {{
|
|
||||||
assert_next_token!(
|
|
||||||
$ser,
|
|
||||||
format_args!(concat!(stringify!($actual), "({:?})"), $v),
|
|
||||||
Token::$actual(v),
|
|
||||||
v == $v
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:ident { $($k:ident),* }) => {{
|
|
||||||
let compare = ($($k,)*);
|
|
||||||
let field_format = || {
|
|
||||||
use std::fmt::Write;
|
|
||||||
let mut buffer = String::new();
|
|
||||||
$(
|
|
||||||
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
|
|
||||||
)*
|
|
||||||
buffer
|
|
||||||
};
|
|
||||||
assert_next_token!(
|
|
||||||
$ser,
|
|
||||||
format_args!(concat!(stringify!($actual), " {{ {}}}"), field_format()),
|
|
||||||
Token::$actual { $($k),* },
|
|
||||||
($($k,)*) == compare
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
|
|
||||||
match $ser.next_token() {
|
|
||||||
Some($pat) if $guard => {}
|
|
||||||
Some(expected) => {
|
|
||||||
panic!("expected Token::{} but serialized as {}",
|
|
||||||
expected, $actual);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
panic!("expected end of tokens, but {} was serialized",
|
|
||||||
$actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
type SerializeSeq = Self;
|
|
||||||
type SerializeTuple = Self;
|
|
||||||
type SerializeTupleStruct = Self;
|
|
||||||
type SerializeTupleVariant = Variant<'s, 'a>;
|
|
||||||
type SerializeMap = Self;
|
|
||||||
type SerializeStruct = Self;
|
|
||||||
type SerializeStructVariant = Variant<'s, 'a>;
|
|
||||||
|
|
||||||
fn serialize_bool(self, v: bool) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Bool(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I8(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I16(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u8(self, v: u8) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U8(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u16(self, v: u16) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U16(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u32(self, v: u32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u64(self, v: u64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f32(self, v: f32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, F32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f64(self, v: f64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, F64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_char(self, v: char) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Char(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<(), Error> {
|
|
||||||
match self.tokens.first() {
|
|
||||||
Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
|
|
||||||
Some(&Token::String(_)) => assert_next_token!(self, String(v)),
|
|
||||||
_ => assert_next_token!(self, Str(v)),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
match self.tokens.first() {
|
|
||||||
Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
|
|
||||||
Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
|
|
||||||
_ => assert_next_token!(self, Bytes(v)),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Unit);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, UnitStruct { name });
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
assert_next_token!(self, Unit);
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, UnitVariant { name, variant });
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
assert_next_token!(self, NewtypeStruct { name });
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, NewtypeVariant { name, variant });
|
|
||||||
}
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, None);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
assert_next_token!(self, Some);
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Seq { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Tuple { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, TupleStruct { name, len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleVariant, Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
let len = Some(len);
|
|
||||||
assert_next_token!(self, Seq { len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::SeqEnd,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, TupleVariant { name, variant, len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::TupleVariantEnd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Map { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Struct { name, len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStructVariant, Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
let len = Some(len);
|
|
||||||
assert_next_token!(self, Map { len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::MapEnd,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, StructVariant { name, variant, len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::StructVariantEnd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
panic!(
|
|
||||||
"Types which have different human-readable and compact representations \
|
|
||||||
must explicitly mark their test cases with `serde_test::Configure`"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Variant<'s, 'a: 's> {
|
|
||||||
ser: &'s mut Serializer<'a>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, SeqEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, TupleEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, TupleStructEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut *self.ser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
match self.end {
|
|
||||||
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
|
|
||||||
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
assert_next_token!(self, MapEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut **self)?;
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
assert_next_token!(self, StructEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut *self.ser)?;
|
|
||||||
value.serialize(&mut *self.ser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
match self.end {
|
|
||||||
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
|
|
||||||
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,519 +0,0 @@
|
|||||||
use std::fmt::{self, Debug, Display};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub enum Token {
|
|
||||||
/// A serialized `bool`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&true, &[Token::Bool(true)]);
|
|
||||||
/// ```
|
|
||||||
Bool(bool),
|
|
||||||
|
|
||||||
/// A serialized `i8`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i8, &[Token::I8(0)]);
|
|
||||||
/// ```
|
|
||||||
I8(i8),
|
|
||||||
|
|
||||||
/// A serialized `i16`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i16, &[Token::I16(0)]);
|
|
||||||
/// ```
|
|
||||||
I16(i16),
|
|
||||||
|
|
||||||
/// A serialized `i32`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i32, &[Token::I32(0)]);
|
|
||||||
/// ```
|
|
||||||
I32(i32),
|
|
||||||
|
|
||||||
/// A serialized `i64`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i64, &[Token::I64(0)]);
|
|
||||||
/// ```
|
|
||||||
I64(i64),
|
|
||||||
|
|
||||||
/// A serialized `u8`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u8, &[Token::U8(0)]);
|
|
||||||
/// ```
|
|
||||||
U8(u8),
|
|
||||||
|
|
||||||
/// A serialized `u16`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u16, &[Token::U16(0)]);
|
|
||||||
/// ```
|
|
||||||
U16(u16),
|
|
||||||
|
|
||||||
/// A serialized `u32`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u32, &[Token::U32(0)]);
|
|
||||||
/// ```
|
|
||||||
U32(u32),
|
|
||||||
|
|
||||||
/// A serialized `u64`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u64, &[Token::U64(0)]);
|
|
||||||
/// ```
|
|
||||||
U64(u64),
|
|
||||||
|
|
||||||
/// A serialized `f32`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
|
|
||||||
/// ```
|
|
||||||
F32(f32),
|
|
||||||
|
|
||||||
/// A serialized `f64`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
|
|
||||||
/// ```
|
|
||||||
F64(f64),
|
|
||||||
|
|
||||||
/// A serialized `char`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&'\n', &[Token::Char('\n')]);
|
|
||||||
/// ```
|
|
||||||
Char(char),
|
|
||||||
|
|
||||||
/// A serialized `str`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s = String::from("transient");
|
|
||||||
/// assert_tokens(&s, &[Token::Str("transient")]);
|
|
||||||
/// ```
|
|
||||||
Str(&'static str),
|
|
||||||
|
|
||||||
/// A borrowed `str`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s: &str = "borrowed";
|
|
||||||
/// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]);
|
|
||||||
/// ```
|
|
||||||
BorrowedStr(&'static str),
|
|
||||||
|
|
||||||
/// A serialized `String`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s = String::from("owned");
|
|
||||||
/// assert_tokens(&s, &[Token::String("owned")]);
|
|
||||||
/// ```
|
|
||||||
String(&'static str),
|
|
||||||
|
|
||||||
/// A serialized `[u8]`
|
|
||||||
Bytes(&'static [u8]),
|
|
||||||
|
|
||||||
/// A borrowed `[u8]`.
|
|
||||||
BorrowedBytes(&'static [u8]),
|
|
||||||
|
|
||||||
/// A serialized `ByteBuf`
|
|
||||||
ByteBuf(&'static [u8]),
|
|
||||||
|
|
||||||
/// A serialized `Option<T>` containing none.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let opt = None::<char>;
|
|
||||||
/// assert_tokens(&opt, &[Token::None]);
|
|
||||||
/// ```
|
|
||||||
None,
|
|
||||||
|
|
||||||
/// The header to a serialized `Option<T>` containing some value.
|
|
||||||
///
|
|
||||||
/// The tokens of the value follow after this header.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let opt = Some('c');
|
|
||||||
/// assert_tokens(&opt, &[
|
|
||||||
/// Token::Some,
|
|
||||||
/// Token::Char('c'),
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
Some,
|
|
||||||
|
|
||||||
/// A serialized `()`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&(), &[Token::Unit]);
|
|
||||||
/// ```
|
|
||||||
Unit,
|
|
||||||
|
|
||||||
/// A serialized unit struct of the given name.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct X;
|
|
||||||
///
|
|
||||||
/// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
UnitStruct { name: &'static str },
|
|
||||||
|
|
||||||
/// A unit variant of an enum.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// A,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let a = E::A;
|
|
||||||
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
UnitVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// The header to a serialized newtype struct of the given name.
|
|
||||||
///
|
|
||||||
/// After this header is the value contained in the newtype struct.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct N(String);
|
|
||||||
///
|
|
||||||
/// let n = N("newtype".to_owned());
|
|
||||||
/// assert_tokens(&n, &[
|
|
||||||
/// Token::NewtypeStruct { name: "N" },
|
|
||||||
/// Token::String("newtype"),
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
NewtypeStruct { name: &'static str },
|
|
||||||
|
|
||||||
/// The header to a newtype variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header is the value contained in the newtype variant.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// B(u8),
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let b = E::B(0);
|
|
||||||
/// assert_tokens(&b, &[
|
|
||||||
/// Token::NewtypeVariant { name: "E", variant: "B" },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
NewtypeVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// The header to a sequence.
|
|
||||||
///
|
|
||||||
/// After this header are the elements of the sequence, followed by
|
|
||||||
/// `SeqEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let vec = vec!['a', 'b', 'c'];
|
|
||||||
/// assert_tokens(&vec, &[
|
|
||||||
/// Token::Seq { len: Some(3) },
|
|
||||||
/// Token::Char('a'),
|
|
||||||
/// Token::Char('b'),
|
|
||||||
/// Token::Char('c'),
|
|
||||||
/// Token::SeqEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
Seq { len: Option<usize> },
|
|
||||||
|
|
||||||
/// An indicator of the end of a sequence.
|
|
||||||
SeqEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple.
|
|
||||||
///
|
|
||||||
/// After this header are the elements of the tuple, followed by `TupleEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let tuple = ('a', 100);
|
|
||||||
/// assert_tokens(&tuple, &[
|
|
||||||
/// Token::Tuple { len: 2 },
|
|
||||||
/// Token::Char('a'),
|
|
||||||
/// Token::I32(100),
|
|
||||||
/// Token::TupleEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
Tuple { len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple.
|
|
||||||
TupleEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple struct.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the tuple struct, followed by
|
|
||||||
/// `TupleStructEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct T(u8, u8);
|
|
||||||
///
|
|
||||||
/// let t = T(0, 0);
|
|
||||||
/// assert_tokens(&t, &[
|
|
||||||
/// Token::TupleStruct { name: "T", len: 2 },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleStructEnd,
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
TupleStruct { name: &'static str, len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple struct.
|
|
||||||
TupleStructEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the tuple variant, followed by
|
|
||||||
/// `TupleVariantEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// C(u8, u8),
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let c = E::C(0, 0);
|
|
||||||
/// assert_tokens(&c, &[
|
|
||||||
/// Token::TupleVariant { name: "E", variant: "C", len: 2 },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleVariantEnd,
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
TupleVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple variant.
|
|
||||||
TupleVariantEnd,
|
|
||||||
|
|
||||||
/// The header to a map.
|
|
||||||
///
|
|
||||||
/// After this header are the entries of the map, followed by `MapEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// use std::collections::BTreeMap;
|
|
||||||
///
|
|
||||||
/// let mut map = BTreeMap::new();
|
|
||||||
/// map.insert('A', 65);
|
|
||||||
/// map.insert('Z', 90);
|
|
||||||
///
|
|
||||||
/// assert_tokens(&map, &[
|
|
||||||
/// Token::Map { len: Some(2) },
|
|
||||||
/// Token::Char('A'),
|
|
||||||
/// Token::I32(65),
|
|
||||||
/// Token::Char('Z'),
|
|
||||||
/// Token::I32(90),
|
|
||||||
/// Token::MapEnd,
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
|
||||||
Map { len: Option<usize> },
|
|
||||||
|
|
||||||
/// An indicator of the end of a map.
|
|
||||||
MapEnd,
|
|
||||||
|
|
||||||
/// The header of a struct.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct, followed by `StructEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_tokens(&s, &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
Struct { name: &'static str, len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a struct.
|
|
||||||
StructEnd,
|
|
||||||
|
|
||||||
/// The header of a struct variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct variant, followed by
|
|
||||||
/// `StructVariantEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// D { d: u8 },
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let d = E::D { d: 0 };
|
|
||||||
/// assert_tokens(&d, &[
|
|
||||||
/// Token::StructVariant { name: "E", variant: "D", len: 1 },
|
|
||||||
/// Token::Str("d"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructVariantEnd,
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
StructVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// An indicator of the end of a struct variant.
|
|
||||||
StructVariantEnd,
|
|
||||||
|
|
||||||
/// The header to an enum of the given name.
|
|
||||||
///
|
|
||||||
/// ```edition2018
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// A,
|
|
||||||
/// B(u8),
|
|
||||||
/// C(u8, u8),
|
|
||||||
/// D { d: u8 },
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let a = E::A;
|
|
||||||
/// assert_tokens(&a, &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("A"),
|
|
||||||
/// Token::Unit,
|
|
||||||
/// ]);
|
|
||||||
///
|
|
||||||
/// let b = E::B(0);
|
|
||||||
/// assert_tokens(&b, &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("B"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// ]);
|
|
||||||
///
|
|
||||||
/// let c = E::C(0, 0);
|
|
||||||
/// assert_tokens(&c, &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("C"),
|
|
||||||
/// Token::Seq { len: Some(2) },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::SeqEnd,
|
|
||||||
/// ]);
|
|
||||||
///
|
|
||||||
/// let d = E::D { d: 0 };
|
|
||||||
/// assert_tokens(&d, &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("D"),
|
|
||||||
/// Token::Map { len: Some(1) },
|
|
||||||
/// Token::Str("d"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::MapEnd,
|
|
||||||
/// ]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
Enum { name: &'static str },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Token {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Debug::fmt(self, formatter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+6
-12
@@ -2,26 +2,20 @@
|
|||||||
name = "serde_test_suite"
|
name = "serde_test_suite"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
expandtest = []
|
|
||||||
unstable = ["serde/unstable"]
|
unstable = ["serde/unstable"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { path = "../serde" }
|
serde = { path = "../serde" }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
toolchain_find = "0.2"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fnv = "1.0"
|
automod = "1.0.1"
|
||||||
macrotest = "=1.0.9"
|
foldhash = "0.2"
|
||||||
prettyplease = "=0.1.14"
|
|
||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
serde = { path = "../serde", features = ["rc", "derive"] }
|
serde = { path = "../serde", features = ["rc"] }
|
||||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||||
serde_test = { path = "../serde_test" }
|
serde_test = "1.0.176"
|
||||||
trybuild = { version = "1.0.49", features = ["diff"] }
|
trybuild = { version = "1.0.108", features = ["diff"] }
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
use std::process::{Command, ExitStatus, Stdio};
|
|
||||||
|
|
||||||
fn has_cargo_expand() -> bool {
|
|
||||||
let cargo_expand = if cfg!(windows) {
|
|
||||||
"cargo-expand.exe"
|
|
||||||
} else {
|
|
||||||
"cargo-expand"
|
|
||||||
};
|
|
||||||
|
|
||||||
Command::new(cargo_expand)
|
|
||||||
.arg("--version")
|
|
||||||
.stdin(Stdio::null())
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.status()
|
|
||||||
.as_ref()
|
|
||||||
.map(ExitStatus::success)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
if cfg!(feature = "expandtest") && has_cargo_expand() {
|
|
||||||
println!("cargo:rustc-cfg=expandtest");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/target/
|
||||||
|
/Cargo.lock
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive_tests_no_std"
|
name = "serde_derive_tests_no_std"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
edition = "2018"
|
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = { version = "0.2", default-features = false }
|
libc = { version = "0.2", default-features = false }
|
||||||
serde = { path = "../../serde", default-features = false, features = ["derive"] }
|
serde = { path = "../../serde", default-features = false }
|
||||||
|
serde_derive = { path = "../../serde_derive" }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
#![feature(lang_items, start)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
#[start]
|
use core::ffi::c_int;
|
||||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "eh_personality"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rust_eh_personality() {}
|
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -19,24 +17,24 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Unit;
|
pub struct Unit;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Newtype(u8);
|
pub struct Newtype(u8);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Tuple(u8, u8);
|
pub struct Tuple(u8, u8);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Struct {
|
pub struct Struct {
|
||||||
f: u8,
|
f: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum Enum {
|
pub enum Enum {
|
||||||
Unit,
|
Unit,
|
||||||
Newtype(u8),
|
Newtype(u8),
|
||||||
Tuple(u8, u8),
|
Tuple(u8, u8),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
#[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")]
|
||||||
#[rustversion::attr(not(nightly), ignore)]
|
#[rustversion::attr(not(nightly), ignore = "requires nightly")]
|
||||||
#[cfg_attr(miri, ignore)]
|
#[cfg_attr(miri, ignore = "incompatible with miri")]
|
||||||
#[allow(unused_attributes)]
|
#[allow(unused_attributes)]
|
||||||
#[test]
|
#[test]
|
||||||
fn ui() {
|
fn ui() {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
enum DeEnum<B, C, D> {
|
|
||||||
Unit,
|
|
||||||
Seq(i8, B, C, D),
|
|
||||||
Map { a: i8, b: B, c: C, d: D },
|
|
||||||
|
|
||||||
// Make sure we can support more than one variant.
|
|
||||||
_Unit2,
|
|
||||||
_Seq2(i8, B, C, D),
|
|
||||||
_Map2 { a: i8, b: B, c: C, d: D },
|
|
||||||
}
|
|
||||||
@@ -1,448 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
trait AssociatedType {
|
|
||||||
type X;
|
|
||||||
}
|
|
||||||
impl AssociatedType for i32 {
|
|
||||||
type X = i32;
|
|
||||||
}
|
|
||||||
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
|
||||||
phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
|
||||||
const _: () = {
|
|
||||||
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
|
||||||
extern crate serde as _serde;
|
|
||||||
#[automatically_derived]
|
|
||||||
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
|
|
||||||
fn serialize<__S>(
|
|
||||||
&self,
|
|
||||||
__serializer: __S,
|
|
||||||
) -> _serde::__private::Result<__S::Ok, __S::Error>
|
|
||||||
where
|
|
||||||
__S: _serde::Serializer,
|
|
||||||
{
|
|
||||||
let mut __serde_state = match _serde::Serializer::serialize_struct(
|
|
||||||
__serializer,
|
|
||||||
"DefaultTyParam",
|
|
||||||
false as usize + 1,
|
|
||||||
) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match _serde::ser::SerializeStruct::serialize_field(
|
|
||||||
&mut __serde_state,
|
|
||||||
"phantom",
|
|
||||||
&self.phantom,
|
|
||||||
) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_serde::ser::SerializeStruct::end(__serde_state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
|
||||||
const _: () = {
|
|
||||||
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
|
||||||
extern crate serde as _serde;
|
|
||||||
#[automatically_derived]
|
|
||||||
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de>
|
|
||||||
for DefaultTyParam<T> {
|
|
||||||
fn deserialize<__D>(
|
|
||||||
__deserializer: __D,
|
|
||||||
) -> _serde::__private::Result<Self, __D::Error>
|
|
||||||
where
|
|
||||||
__D: _serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
enum __Field {
|
|
||||||
__field0,
|
|
||||||
__ignore,
|
|
||||||
}
|
|
||||||
struct __FieldVisitor;
|
|
||||||
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
|
|
||||||
type Value = __Field;
|
|
||||||
fn expecting(
|
|
||||||
&self,
|
|
||||||
__formatter: &mut _serde::__private::Formatter,
|
|
||||||
) -> _serde::__private::fmt::Result {
|
|
||||||
_serde::__private::Formatter::write_str(
|
|
||||||
__formatter,
|
|
||||||
"field identifier",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn visit_u64<__E>(
|
|
||||||
self,
|
|
||||||
__value: u64,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
0u64 => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn visit_str<__E>(
|
|
||||||
self,
|
|
||||||
__value: &str,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
"phantom" => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn visit_bytes<__E>(
|
|
||||||
self,
|
|
||||||
__value: &[u8],
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
b"phantom" => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de> _serde::Deserialize<'de> for __Field {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<__D>(
|
|
||||||
__deserializer: __D,
|
|
||||||
) -> _serde::__private::Result<Self, __D::Error>
|
|
||||||
where
|
|
||||||
__D: _serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
_serde::Deserializer::deserialize_identifier(
|
|
||||||
__deserializer,
|
|
||||||
__FieldVisitor,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct __Visitor<'de, T: AssociatedType<X = i32>> {
|
|
||||||
marker: _serde::__private::PhantomData<DefaultTyParam<T>>,
|
|
||||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
|
||||||
}
|
|
||||||
impl<'de, T: AssociatedType<X = i32>> _serde::de::Visitor<'de>
|
|
||||||
for __Visitor<'de, T> {
|
|
||||||
type Value = DefaultTyParam<T>;
|
|
||||||
fn expecting(
|
|
||||||
&self,
|
|
||||||
__formatter: &mut _serde::__private::Formatter,
|
|
||||||
) -> _serde::__private::fmt::Result {
|
|
||||||
_serde::__private::Formatter::write_str(
|
|
||||||
__formatter,
|
|
||||||
"struct DefaultTyParam",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn visit_seq<__A>(
|
|
||||||
self,
|
|
||||||
mut __seq: __A,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
let __field0 = match match _serde::de::SeqAccess::next_element::<
|
|
||||||
PhantomData<T>,
|
|
||||||
>(&mut __seq) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
_serde::__private::Some(__value) => __value,
|
|
||||||
_serde::__private::None => {
|
|
||||||
return _serde::__private::Err(
|
|
||||||
_serde::de::Error::invalid_length(
|
|
||||||
0usize,
|
|
||||||
&"struct DefaultTyParam with 1 element",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_serde::__private::Ok(DefaultTyParam {
|
|
||||||
phantom: __field0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn visit_map<__A>(
|
|
||||||
self,
|
|
||||||
mut __map: __A,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::MapAccess<'de>,
|
|
||||||
{
|
|
||||||
let mut __field0: _serde::__private::Option<PhantomData<T>> = _serde::__private::None;
|
|
||||||
while let _serde::__private::Some(__key)
|
|
||||||
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
match __key {
|
|
||||||
__Field::__field0 => {
|
|
||||||
if _serde::__private::Option::is_some(&__field0) {
|
|
||||||
return _serde::__private::Err(
|
|
||||||
<__A::Error as _serde::de::Error>::duplicate_field(
|
|
||||||
"phantom",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
__field0 = _serde::__private::Some(
|
|
||||||
match _serde::de::MapAccess::next_value::<
|
|
||||||
PhantomData<T>,
|
|
||||||
>(&mut __map) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let _ = match _serde::de::MapAccess::next_value::<
|
|
||||||
_serde::de::IgnoredAny,
|
|
||||||
>(&mut __map) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let __field0 = match __field0 {
|
|
||||||
_serde::__private::Some(__field0) => __field0,
|
|
||||||
_serde::__private::None => {
|
|
||||||
match _serde::__private::de::missing_field("phantom") {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_serde::__private::Ok(DefaultTyParam {
|
|
||||||
phantom: __field0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const FIELDS: &'static [&'static str] = &["phantom"];
|
|
||||||
_serde::Deserializer::deserialize_struct(
|
|
||||||
__deserializer,
|
|
||||||
"DefaultTyParam",
|
|
||||||
FIELDS,
|
|
||||||
__Visitor {
|
|
||||||
marker: _serde::__private::PhantomData::<DefaultTyParam<T>>,
|
|
||||||
lifetime: _serde::__private::PhantomData,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn deserialize_in_place<__D>(
|
|
||||||
__deserializer: __D,
|
|
||||||
__place: &mut Self,
|
|
||||||
) -> _serde::__private::Result<(), __D::Error>
|
|
||||||
where
|
|
||||||
__D: _serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
enum __Field {
|
|
||||||
__field0,
|
|
||||||
__ignore,
|
|
||||||
}
|
|
||||||
struct __FieldVisitor;
|
|
||||||
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
|
|
||||||
type Value = __Field;
|
|
||||||
fn expecting(
|
|
||||||
&self,
|
|
||||||
__formatter: &mut _serde::__private::Formatter,
|
|
||||||
) -> _serde::__private::fmt::Result {
|
|
||||||
_serde::__private::Formatter::write_str(
|
|
||||||
__formatter,
|
|
||||||
"field identifier",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fn visit_u64<__E>(
|
|
||||||
self,
|
|
||||||
__value: u64,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
0u64 => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn visit_str<__E>(
|
|
||||||
self,
|
|
||||||
__value: &str,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
"phantom" => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn visit_bytes<__E>(
|
|
||||||
self,
|
|
||||||
__value: &[u8],
|
|
||||||
) -> _serde::__private::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
b"phantom" => _serde::__private::Ok(__Field::__field0),
|
|
||||||
_ => _serde::__private::Ok(__Field::__ignore),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de> _serde::Deserialize<'de> for __Field {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<__D>(
|
|
||||||
__deserializer: __D,
|
|
||||||
) -> _serde::__private::Result<Self, __D::Error>
|
|
||||||
where
|
|
||||||
__D: _serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
_serde::Deserializer::deserialize_identifier(
|
|
||||||
__deserializer,
|
|
||||||
__FieldVisitor,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct __Visitor<'de, 'place, T: AssociatedType<X = i32> + 'place> {
|
|
||||||
place: &'place mut DefaultTyParam<T>,
|
|
||||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
|
||||||
}
|
|
||||||
impl<
|
|
||||||
'de,
|
|
||||||
'place,
|
|
||||||
T: AssociatedType<X = i32> + 'place,
|
|
||||||
> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T> {
|
|
||||||
type Value = ();
|
|
||||||
fn expecting(
|
|
||||||
&self,
|
|
||||||
__formatter: &mut _serde::__private::Formatter,
|
|
||||||
) -> _serde::__private::fmt::Result {
|
|
||||||
_serde::__private::Formatter::write_str(
|
|
||||||
__formatter,
|
|
||||||
"struct DefaultTyParam",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn visit_seq<__A>(
|
|
||||||
self,
|
|
||||||
mut __seq: __A,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
if let _serde::__private::None
|
|
||||||
= match _serde::de::SeqAccess::next_element_seed(
|
|
||||||
&mut __seq,
|
|
||||||
_serde::__private::de::InPlaceSeed(&mut self.place.phantom),
|
|
||||||
) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
return _serde::__private::Err(
|
|
||||||
_serde::de::Error::invalid_length(
|
|
||||||
0usize,
|
|
||||||
&"struct DefaultTyParam with 1 element",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_serde::__private::Ok(())
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn visit_map<__A>(
|
|
||||||
self,
|
|
||||||
mut __map: __A,
|
|
||||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::MapAccess<'de>,
|
|
||||||
{
|
|
||||||
let mut __field0: bool = false;
|
|
||||||
while let _serde::__private::Some(__key)
|
|
||||||
= match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
match __key {
|
|
||||||
__Field::__field0 => {
|
|
||||||
if __field0 {
|
|
||||||
return _serde::__private::Err(
|
|
||||||
<__A::Error as _serde::de::Error>::duplicate_field(
|
|
||||||
"phantom",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
match _serde::de::MapAccess::next_value_seed(
|
|
||||||
&mut __map,
|
|
||||||
_serde::__private::de::InPlaceSeed(&mut self.place.phantom),
|
|
||||||
) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
__field0 = true;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let _ = match _serde::de::MapAccess::next_value::<
|
|
||||||
_serde::de::IgnoredAny,
|
|
||||||
>(&mut __map) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !__field0 {
|
|
||||||
self
|
|
||||||
.place
|
|
||||||
.phantom = match _serde::__private::de::missing_field(
|
|
||||||
"phantom",
|
|
||||||
) {
|
|
||||||
_serde::__private::Ok(__val) => __val,
|
|
||||||
_serde::__private::Err(__err) => {
|
|
||||||
return _serde::__private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_serde::__private::Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const FIELDS: &'static [&'static str] = &["phantom"];
|
|
||||||
_serde::Deserializer::deserialize_struct(
|
|
||||||
__deserializer,
|
|
||||||
"DefaultTyParam",
|
|
||||||
FIELDS,
|
|
||||||
__Visitor {
|
|
||||||
place: __place,
|
|
||||||
lifetime: _serde::__private::PhantomData,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user