mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 08:18:03 +00:00
Compare commits
467 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 49d098debd | |||
| 40f1d19dbe | |||
| 514848b584 | |||
| 168b6cf789 | |||
| 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 | |||
| f709fc05b0 | |||
| 089aae1292 | |||
| 855acaf112 | |||
| 7ca7720262 | |||
| 78fea3aa4a | |||
| 1efb8b6a53 | |||
| bc1960b106 | |||
| 967023b755 | |||
| bb51e68f16 | |||
| 4e5e55bf1c | |||
| 4513a9e6a7 | |||
| 4f922e4e5b | |||
| 993966600e | |||
| 5b96cf1bde | |||
| f3d50e5209 | |||
| ab21d4d017 | |||
| f7c5d93e6a | |||
| 52a7d40e6e | |||
| 348bc6b257 |
@@ -0,0 +1 @@
|
||||
github: dtolnay
|
||||
+43
-42
@@ -18,16 +18,22 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: Cargo.lock
|
||||
path: Cargo.lock
|
||||
continue-on-error: true
|
||||
|
||||
windows:
|
||||
name: Test suite (windows)
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||
|
||||
@@ -40,12 +46,13 @@ jobs:
|
||||
rust: [stable, beta]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{matrix.rust}}
|
||||
- run: cd serde && cargo build --features rc
|
||||
- run: cd serde && cargo build --no-default-features
|
||||
- run: cd test_suite/no_std && cargo build
|
||||
|
||||
nightly:
|
||||
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
||||
@@ -56,12 +63,13 @@ jobs:
|
||||
os: [ubuntu, windows]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd serde && cargo build
|
||||
- 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 rc,alloc
|
||||
- run: cd serde && cargo build --no-default-features --features unstable
|
||||
- run: cd serde && cargo test --features derive,rc,unstable
|
||||
- run: cd test_suite/no_std && cargo build
|
||||
if: matrix.os != 'windows'
|
||||
@@ -76,82 +84,74 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
|
||||
rust: [1.31.0, 1.34.0]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
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
|
||||
|
||||
more:
|
||||
name: Rust ${{matrix.rust}}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [1.27.0, 1.28.0]
|
||||
timeout-minutes: 45
|
||||
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
|
||||
|
||||
derive:
|
||||
name: Rust 1.56.0
|
||||
name: Rust 1.61.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@1.56.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.61.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
|
||||
- run: cd serde_derive && cargo check
|
||||
- run: cd precompiled/serde_derive && cargo check
|
||||
|
||||
alloc:
|
||||
name: Rust 1.36.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.36.0
|
||||
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||
- run: cd serde && cargo build --no-default-features --features alloc
|
||||
|
||||
macos:
|
||||
name: macOS
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cd precompiled/serde_derive && cargo check
|
||||
|
||||
minimal:
|
||||
name: Minimal versions
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cargo generate-lockfile -Z minimal-versions
|
||||
- run: cargo check --locked --workspace
|
||||
|
||||
doc:
|
||||
name: Documentation
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
RUSTDOCFLAGS: -Dwarnings
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- uses: dtolnay/install@cargo-docs-rs
|
||||
- run: cargo docs-rs -p serde
|
||||
- run: cargo docs-rs -p serde_derive
|
||||
- run: cargo docs-rs -p serde_derive_internals
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@clippy
|
||||
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
||||
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||
@@ -164,7 +164,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@miri
|
||||
- run: cargo miri setup
|
||||
- run: cd serde && cargo miri test --features derive,rc,unstable
|
||||
@@ -180,6 +180,7 @@ jobs:
|
||||
if: github.event_name != 'pull_request'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: dtolnay/install@cargo-outdated
|
||||
- run: cargo outdated --workspace --exit-code 1
|
||||
|
||||
+2
-4
@@ -1,4 +1,2 @@
|
||||
target/
|
||||
**/*.rs.bk
|
||||
*.sw[po]
|
||||
Cargo.lock
|
||||
/target/
|
||||
/Cargo.lock
|
||||
|
||||
@@ -8,3 +8,8 @@ members = [
|
||||
|
||||
[patch.crates-io]
|
||||
serde = { path = "serde" }
|
||||
|
||||
[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 }
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.19+]][Rust 1.19] [![serde_derive: rustc 1.56+]][Rust 1.56]
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.61]
|
||||
|
||||
[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
|
||||
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
||||
[crates.io]: https://crates.io/crates/serde
|
||||
[serde: rustc 1.19+]: https://img.shields.io/badge/serde-rustc_1.19+-lightgray.svg
|
||||
[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
|
||||
[Rust 1.19]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html
|
||||
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
|
||||
[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray
|
||||
[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray
|
||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
||||
[Rust 1.61]: https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html
|
||||
|
||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@ fn main() {
|
||||
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
|
||||
[#rust-questions] or [#rust-beginners] channels of the unofficial community
|
||||
Discord (invite: <https://discord.gg/rust-lang-community>, the [#rust-usage] or
|
||||
[#beginners] channels of the official Rust Project Discord (invite:
|
||||
Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage]
|
||||
or [#beginners] channels of the official Rust Project Discord (invite:
|
||||
<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
|
||||
asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
|
||||
[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
@@ -1,14 +0,0 @@
|
||||
[workspace]
|
||||
members = ["bin", "proc-macro2"]
|
||||
resolver = "2"
|
||||
|
||||
[patch.crates-io]
|
||||
proc-macro2 = { path = "proc-macro2" }
|
||||
|
||||
[profile.precompiled]
|
||||
inherits = "release"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
panic = "abort"
|
||||
strip = true
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.177"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "serde_derive"
|
||||
path = "main.rs"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = { version = "1", default-features = false }
|
||||
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] }
|
||||
@@ -1,4 +0,0 @@
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=precompiled");
|
||||
println!("cargo:rustc-cfg=feature=\"deserialize_in_place\"");
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
extern crate proc_macro2;
|
||||
|
||||
use proc_macro2::watt;
|
||||
use proc_macro2::watt::buffer::InputBuffer;
|
||||
use std::alloc::{GlobalAlloc, Layout, System};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
struct MonotonicAllocator;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: MonotonicAllocator = MonotonicAllocator;
|
||||
|
||||
unsafe impl GlobalAlloc for MonotonicAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
System.alloc(layout)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
// Leak: this cuts 3% of code size from the precompiled macro binary.
|
||||
// There is no way that serde_derive would fill up all memory on the
|
||||
// host. When the subprocess exits, operating system will clean this up.
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut buf = Vec::new();
|
||||
io::stdin().read_to_end(&mut buf).unwrap();
|
||||
|
||||
let mut buf = InputBuffer::new(&buf);
|
||||
let derive = match buf.read_u8() {
|
||||
0 => serde_derive::derive_serialize,
|
||||
1 => serde_derive::derive_deserialize,
|
||||
2 => {
|
||||
serde_derive::DESERIALIZE_IN_PLACE.store(true, Ordering::Relaxed);
|
||||
serde_derive::derive_deserialize
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let input = watt::load(&mut buf);
|
||||
let output = derive(input);
|
||||
let bytes = watt::linearize(output);
|
||||
io::stdout().write_all(&bytes).unwrap();
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../serde_derive/src
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null
|
||||
set -e -x
|
||||
|
||||
# TODO: Sanitize host filesystem paths. https://github.com/rust-lang/cargo/issues/12137
|
||||
|
||||
cargo +nightly build \
|
||||
--manifest-path bin/Cargo.toml \
|
||||
--bin serde_derive \
|
||||
--profile precompiled \
|
||||
-Z unstable-options \
|
||||
-Z build-std=std,panic_abort \
|
||||
-Z build-std-features=panic_immediate_abort \
|
||||
--target x86_64-unknown-linux-musl \
|
||||
--out-dir serde_derive
|
||||
|
||||
rm -f serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
mv serde_derive/serde_derive{,-x86_64-unknown-linux-gnu}
|
||||
|
||||
#upx --best --lzma serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { package = "proc-macro2-fallback", version = "1" }
|
||||
@@ -1,815 +0,0 @@
|
||||
#[doc(hidden)]
|
||||
pub mod watt;
|
||||
|
||||
use crate::extra::DelimSpan;
|
||||
use crate::watt::Identity;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::RangeBounds;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use proc_macro2::{Delimiter, Spacing};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Span {
|
||||
lo: u32,
|
||||
hi: u32,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn call_site() -> Self {
|
||||
Span { lo: 0, hi: 0 }
|
||||
}
|
||||
|
||||
pub fn join(&self, other: Self) -> Option<Self> {
|
||||
Some(Span {
|
||||
lo: self.lo,
|
||||
hi: other.hi,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TokenTree {
|
||||
Group(Group),
|
||||
Ident(Ident),
|
||||
Punct(Punct),
|
||||
Literal(Literal),
|
||||
}
|
||||
|
||||
impl TokenTree {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
TokenTree::Group(group) => group.span(),
|
||||
TokenTree::Ident(ident) => ident.span(),
|
||||
TokenTree::Punct(punct) => punct.span(),
|
||||
TokenTree::Literal(literal) => literal.span(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
TokenTree::Group(group) => group.set_span(span),
|
||||
TokenTree::Ident(ident) => ident.set_span(span),
|
||||
TokenTree::Punct(punct) => punct.set_span(span),
|
||||
TokenTree::Literal(literal) => literal.set_span(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Group> for TokenTree {
|
||||
fn from(group: Group) -> Self {
|
||||
TokenTree::Group(group)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ident> for TokenTree {
|
||||
fn from(ident: Ident) -> Self {
|
||||
TokenTree::Ident(ident)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Punct> for TokenTree {
|
||||
fn from(punct: Punct) -> Self {
|
||||
TokenTree::Punct(punct)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Literal> for TokenTree {
|
||||
fn from(literal: Literal) -> Self {
|
||||
TokenTree::Literal(literal)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TokenTree {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
TokenTree::Group(group) => Debug::fmt(group, formatter),
|
||||
TokenTree::Ident(ident) => {
|
||||
let mut debug = formatter.debug_struct("Ident");
|
||||
debug.field("sym", &format_args!("{}", ident));
|
||||
debug.finish()
|
||||
}
|
||||
TokenTree::Punct(punct) => Debug::fmt(punct, formatter),
|
||||
TokenTree::Literal(literal) => Debug::fmt(literal, formatter),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Group {
|
||||
delimiter: Delimiter,
|
||||
stream: Vec<TokenTree>,
|
||||
span: Span,
|
||||
span_open: Span,
|
||||
span_close: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Group {
|
||||
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
|
||||
Group {
|
||||
delimiter,
|
||||
stream: stream.content,
|
||||
span: Span::call_site(),
|
||||
span_open: Span::call_site(),
|
||||
span_close: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stream(&self) -> TokenStream {
|
||||
TokenStream {
|
||||
content: self.stream.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delimiter(&self) -> Delimiter {
|
||||
self.delimiter
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn span_open(&self) -> Span {
|
||||
self.span_open
|
||||
}
|
||||
|
||||
pub fn span_close(&self) -> Span {
|
||||
self.span_close
|
||||
}
|
||||
|
||||
pub fn delim_span(&self) -> DelimSpan {
|
||||
DelimSpan {
|
||||
join: self.span,
|
||||
open: self.span_open,
|
||||
close: self.span_close,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Group {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (open, close) = match self.delimiter {
|
||||
Delimiter::Parenthesis => ("(", ")"),
|
||||
Delimiter::Brace => ("{ ", "}"),
|
||||
Delimiter::Bracket => ("[", "]"),
|
||||
Delimiter::None => ("", ""),
|
||||
};
|
||||
|
||||
formatter.write_str(open)?;
|
||||
display_tokens(&self.stream, formatter)?;
|
||||
if self.delimiter == Delimiter::Brace && !self.stream.is_empty() {
|
||||
formatter.write_str(" ")?;
|
||||
}
|
||||
formatter.write_str(close)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Group {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut debug = formatter.debug_struct("Group");
|
||||
debug.field("delimiter", &self.delimiter);
|
||||
debug.field("stream", &self.stream);
|
||||
debug.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Ident {
|
||||
fallback: proc_macro2::Ident,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
pub fn new(string: &str, span: Span) -> Self {
|
||||
Ident {
|
||||
fallback: proc_macro2::Ident::new(string, proc_macro2::Span::call_site()),
|
||||
span,
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_raw(string: &str, span: Span) -> Self {
|
||||
Ident {
|
||||
fallback: proc_macro2::Ident::new_raw(string, proc_macro2::Span::call_site()),
|
||||
span,
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Ident {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Ident {}
|
||||
|
||||
impl PartialEq for Ident {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
PartialEq::eq(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq<T> for Ident
|
||||
where
|
||||
T: ?Sized + AsRef<str>,
|
||||
{
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
PartialEq::eq(&self.fallback, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Ident {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Ident {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Ident {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
Hash::hash(&self.fallback, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Punct {
|
||||
fallback: proc_macro2::Punct,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Punct {
|
||||
pub fn new(ch: char, spacing: Spacing) -> Self {
|
||||
Punct {
|
||||
fallback: proc_macro2::Punct::new(ch, spacing),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_char(&self) -> char {
|
||||
self.fallback.as_char()
|
||||
}
|
||||
|
||||
pub fn spacing(&self) -> Spacing {
|
||||
self.fallback.spacing()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Punct {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Punct {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Literal {
|
||||
fallback: proc_macro2::Literal,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
pub fn u8_suffixed(n: u8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u8_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u16_suffixed(n: u16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u16_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u32_suffixed(n: u32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u32_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_suffixed(n: u64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u64_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u128_suffixed(n: u128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u128_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn usize_suffixed(n: usize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::usize_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8_suffixed(n: i8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i8_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i16_suffixed(n: i16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i16_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i32_suffixed(n: i32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i32_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i64_suffixed(n: i64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i64_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i128_suffixed(n: i128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i128_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isize_suffixed(n: isize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::isize_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u8_unsuffixed(n: u8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u8_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u16_unsuffixed(n: u16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u16_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u32_unsuffixed(n: u32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u32_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_unsuffixed(n: u64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u64_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u128_unsuffixed(n: u128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u128_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn usize_unsuffixed(n: usize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::usize_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8_unsuffixed(n: i8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i8_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i16_unsuffixed(n: i16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i16_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i32_unsuffixed(n: i32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i32_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i64_unsuffixed(n: i64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i64_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i128_unsuffixed(n: i128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i128_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isize_unsuffixed(n: isize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::isize_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64_unsuffixed(f: f64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f64_unsuffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64_suffixed(f: f64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f64_suffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f32_unsuffixed(f: f32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f32_unsuffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f32_suffixed(f: f32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f32_suffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string(string: &str) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::string(string),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn character(ch: char) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::character(ch),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byte_string(s: &[u8]) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::byte_string(s),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
|
||||
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
|
||||
let _ = range;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Literal {
|
||||
type Err = LexError;
|
||||
|
||||
fn from_str(repr: &str) -> Result<Self, Self::Err> {
|
||||
let fallback = match proc_macro2::Literal::from_str(repr) {
|
||||
Ok(literal) => literal,
|
||||
Err(error) => {
|
||||
return Err(LexError {
|
||||
fallback: error,
|
||||
span: Span::call_site(),
|
||||
});
|
||||
}
|
||||
};
|
||||
Ok(Literal {
|
||||
fallback,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Literal {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Literal {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenStream {
|
||||
content: Vec<TokenTree>,
|
||||
}
|
||||
|
||||
impl TokenStream {
|
||||
pub fn new() -> Self {
|
||||
TokenStream {
|
||||
content: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.content.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for TokenStream {
|
||||
type Item = TokenTree;
|
||||
type IntoIter = token_stream::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
token_stream::IntoIter {
|
||||
iter: self.content.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<TokenStream> for TokenStream {
|
||||
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
|
||||
self.content.extend(streams.into_iter().flatten());
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<TokenTree> for TokenStream {
|
||||
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
|
||||
self.content.extend(streams);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<TokenStream> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
|
||||
let content = streams.into_iter().flatten().collect();
|
||||
TokenStream { content }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<TokenTree> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
|
||||
let content = streams.into_iter().collect();
|
||||
TokenStream { content }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for TokenStream {
|
||||
type Err = LexError;
|
||||
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let fallback = match proc_macro2::TokenStream::from_str(string) {
|
||||
Ok(token_stream) => token_stream,
|
||||
Err(error) => {
|
||||
return Err(LexError {
|
||||
fallback: error,
|
||||
span: Span::call_site(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fn convert_token_stream(stream: proc_macro2::TokenStream) -> TokenStream {
|
||||
TokenStream {
|
||||
content: stream.into_iter().map(convert_token_tree).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_token_tree(token: proc_macro2::TokenTree) -> TokenTree {
|
||||
match token {
|
||||
proc_macro2::TokenTree::Group(group) => TokenTree::Group(Group::new(
|
||||
group.delimiter(),
|
||||
convert_token_stream(group.stream()),
|
||||
)),
|
||||
proc_macro2::TokenTree::Ident(ident) => TokenTree::Ident(Ident {
|
||||
fallback: ident,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
proc_macro2::TokenTree::Punct(punct) => TokenTree::Punct(Punct {
|
||||
fallback: punct,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
proc_macro2::TokenTree::Literal(literal) => TokenTree::Literal(Literal {
|
||||
fallback: literal,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(convert_token_stream(fallback))
|
||||
}
|
||||
}
|
||||
|
||||
fn display_tokens(tokens: &[TokenTree], formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut joint = false;
|
||||
for (i, token) in tokens.iter().enumerate() {
|
||||
if i != 0 && !joint {
|
||||
write!(formatter, " ")?;
|
||||
}
|
||||
joint = false;
|
||||
match token {
|
||||
TokenTree::Group(group) => Display::fmt(group, formatter),
|
||||
TokenTree::Ident(ident) => Display::fmt(ident, formatter),
|
||||
TokenTree::Punct(punct) => {
|
||||
joint = punct.spacing() == Spacing::Joint;
|
||||
Display::fmt(punct, formatter)
|
||||
}
|
||||
TokenTree::Literal(literal) => Display::fmt(literal, formatter),
|
||||
}?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Display for TokenStream {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
display_tokens(&self.content, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TokenStream {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("TokenStream ")?;
|
||||
formatter.debug_list().entries(&self.content).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LexError {
|
||||
fallback: proc_macro2::LexError,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl LexError {
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for LexError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod token_stream {
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IntoIter {
|
||||
pub(crate) iter: <Vec<TokenTree> as IntoIterator>::IntoIter,
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod extra {
|
||||
use crate::Span;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DelimSpan {
|
||||
pub(crate) join: Span,
|
||||
pub(crate) open: Span,
|
||||
pub(crate) close: Span,
|
||||
}
|
||||
|
||||
impl DelimSpan {
|
||||
pub fn join(&self) -> Span {
|
||||
self.join
|
||||
}
|
||||
|
||||
pub fn open(&self) -> Span {
|
||||
self.open
|
||||
}
|
||||
|
||||
pub fn close(&self) -> Span {
|
||||
self.close
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
use std::str;
|
||||
|
||||
pub struct OutputBuffer {
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl OutputBuffer {
|
||||
pub fn new() -> Self {
|
||||
OutputBuffer { bytes: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, value: u8) {
|
||||
self.bytes.push(value);
|
||||
}
|
||||
|
||||
pub fn write_u16(&mut self, value: u16) {
|
||||
self.bytes.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, value: u32) {
|
||||
self.bytes.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
pub fn write_str(&mut self, value: &str) {
|
||||
self.bytes.extend_from_slice(value.as_bytes());
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputBuffer<'a> {
|
||||
bytes: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> InputBuffer<'a> {
|
||||
pub fn new(bytes: &'a [u8]) -> Self {
|
||||
InputBuffer { bytes }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.bytes.is_empty()
|
||||
}
|
||||
|
||||
pub fn read_u8(&mut self) -> u8 {
|
||||
let (first, rest) = self.bytes.split_first().unwrap();
|
||||
self.bytes = rest;
|
||||
*first
|
||||
}
|
||||
|
||||
pub fn read_u16(&mut self) -> u16 {
|
||||
let (value, rest) = self.bytes.split_at(2);
|
||||
self.bytes = rest;
|
||||
u16::from_le_bytes([value[0], value[1]])
|
||||
}
|
||||
|
||||
pub fn read_u32(&mut self) -> u32 {
|
||||
let (value, rest) = self.bytes.split_at(4);
|
||||
self.bytes = rest;
|
||||
u32::from_le_bytes([value[0], value[1], value[2], value[3]])
|
||||
}
|
||||
|
||||
pub fn read_str(&mut self, len: usize) -> &'a str {
|
||||
let (string, rest) = self.bytes.split_at(len);
|
||||
self.bytes = rest;
|
||||
str::from_utf8(string).unwrap()
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
pub enum Bytecode {}
|
||||
|
||||
impl Bytecode {
|
||||
pub const GROUP_PARENTHESIS: u8 = 0;
|
||||
pub const GROUP_BRACE: u8 = 1;
|
||||
pub const GROUP_BRACKET: u8 = 2;
|
||||
pub const GROUP_NONE: u8 = 3;
|
||||
pub const IDENT: u8 = 4;
|
||||
pub const PUNCT_ALONE: u8 = 5;
|
||||
pub const PUNCT_JOINT: u8 = 6;
|
||||
pub const LITERAL: u8 = 7;
|
||||
pub const LOAD_GROUP: u8 = 8;
|
||||
pub const LOAD_IDENT: u8 = 9;
|
||||
pub const LOAD_PUNCT: u8 = 10;
|
||||
pub const LOAD_LITERAL: u8 = 11;
|
||||
pub const SET_SPAN: u8 = 12;
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
pub mod buffer;
|
||||
pub mod bytecode;
|
||||
|
||||
use crate::watt::buffer::{InputBuffer, OutputBuffer};
|
||||
use crate::watt::bytecode::Bytecode;
|
||||
use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub enum Kind {
|
||||
Group(Delimiter),
|
||||
Ident,
|
||||
Punct(Spacing),
|
||||
Literal,
|
||||
}
|
||||
|
||||
pub enum Identity {}
|
||||
|
||||
impl Identity {
|
||||
pub const RESPANNED: u32 = 1 << 31;
|
||||
pub const NOVEL: u32 = u32::MAX;
|
||||
}
|
||||
|
||||
impl Span {
|
||||
fn is_call_site(&self) -> bool {
|
||||
self.lo == 0 && self.hi == 0
|
||||
}
|
||||
}
|
||||
|
||||
fn post_increment(counter: &mut u32) -> impl FnMut() -> u32 + '_ {
|
||||
|| {
|
||||
let value = *counter;
|
||||
*counter += 1;
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(buf: &mut InputBuffer) -> TokenStream {
|
||||
let mut span_counter = 1;
|
||||
let mut next_span = post_increment(&mut span_counter);
|
||||
let mut next_span = || {
|
||||
let next = next_span();
|
||||
Span { lo: next, hi: next }
|
||||
};
|
||||
|
||||
let [mut group_counter, mut ident_counter, mut punct_counter, mut literal_counter] = [0; 4];
|
||||
let mut next_group = post_increment(&mut group_counter);
|
||||
let mut next_ident = post_increment(&mut ident_counter);
|
||||
let mut next_punct = post_increment(&mut punct_counter);
|
||||
let mut next_literal = post_increment(&mut literal_counter);
|
||||
|
||||
let mut trees = Vec::new();
|
||||
while !buf.is_empty() {
|
||||
match match buf.read_u8() {
|
||||
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
|
||||
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
|
||||
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
|
||||
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
|
||||
Bytecode::IDENT => Kind::Ident,
|
||||
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
|
||||
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
|
||||
Bytecode::LITERAL => Kind::Literal,
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
Kind::Group(delimiter) => {
|
||||
let len = buf.read_u32();
|
||||
let stream = trees.drain(trees.len() - len as usize..).collect();
|
||||
trees.push(TokenTree::Group(Group {
|
||||
delimiter,
|
||||
stream,
|
||||
span: next_span(),
|
||||
span_open: next_span(),
|
||||
span_close: next_span(),
|
||||
identity: next_group(),
|
||||
}));
|
||||
}
|
||||
Kind::Ident => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let ident = if let Some(repr) = repr.strip_prefix("r#") {
|
||||
proc_macro2::Ident::new_raw(repr, proc_macro2::Span::call_site())
|
||||
} else if repr == "$crate" {
|
||||
proc_macro2::Ident::new("crate", proc_macro2::Span::call_site())
|
||||
} else {
|
||||
proc_macro2::Ident::new(repr, proc_macro2::Span::call_site())
|
||||
};
|
||||
trees.push(TokenTree::Ident(Ident {
|
||||
fallback: ident,
|
||||
span: next_span(),
|
||||
identity: next_ident(),
|
||||
}));
|
||||
}
|
||||
Kind::Punct(spacing) => {
|
||||
let ch = buf.read_u8();
|
||||
assert!(ch.is_ascii());
|
||||
let punct = proc_macro2::Punct::new(ch as char, spacing);
|
||||
trees.push(TokenTree::Punct(Punct {
|
||||
fallback: punct,
|
||||
span: next_span(),
|
||||
identity: next_punct(),
|
||||
}));
|
||||
}
|
||||
Kind::Literal => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let literal = proc_macro2::Literal::from_str(repr).unwrap();
|
||||
trees.push(TokenTree::Literal(Literal {
|
||||
fallback: literal,
|
||||
span: next_span(),
|
||||
identity: next_literal(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TokenStream { content: trees }
|
||||
}
|
||||
|
||||
pub fn linearize(tokens: TokenStream) -> Vec<u8> {
|
||||
let mut buf = OutputBuffer::new();
|
||||
for token in &tokens.content {
|
||||
linearize_token(token, &mut buf);
|
||||
}
|
||||
buf.into_bytes()
|
||||
}
|
||||
|
||||
fn linearize_token(token: &TokenTree, buf: &mut OutputBuffer) {
|
||||
let needs_span;
|
||||
match token {
|
||||
TokenTree::Group(group) => {
|
||||
if group.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_GROUP);
|
||||
buf.write_u32(group.identity & !Identity::RESPANNED);
|
||||
needs_span = group.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
let len = group.stream.len();
|
||||
assert!(len <= u32::MAX as usize);
|
||||
for token in &group.stream {
|
||||
linearize_token(token, buf);
|
||||
}
|
||||
buf.write_u8(match group.delimiter {
|
||||
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
|
||||
Delimiter::Brace => Bytecode::GROUP_BRACE,
|
||||
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
|
||||
Delimiter::None => Bytecode::GROUP_NONE,
|
||||
});
|
||||
buf.write_u32(len as u32);
|
||||
needs_span = !group.span.is_call_site();
|
||||
}
|
||||
}
|
||||
TokenTree::Ident(ident) => {
|
||||
if ident.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_IDENT);
|
||||
buf.write_u32(ident.identity & !Identity::RESPANNED);
|
||||
needs_span = ident.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(Bytecode::IDENT);
|
||||
let repr = ident.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
linearize_span(ident.span, buf);
|
||||
needs_span = false;
|
||||
}
|
||||
}
|
||||
TokenTree::Punct(punct) => {
|
||||
if punct.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_PUNCT);
|
||||
buf.write_u32(punct.identity & !Identity::RESPANNED);
|
||||
needs_span = punct.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(match punct.spacing() {
|
||||
Spacing::Alone => Bytecode::PUNCT_ALONE,
|
||||
Spacing::Joint => Bytecode::PUNCT_JOINT,
|
||||
});
|
||||
let ch = punct.as_char();
|
||||
assert!(ch.is_ascii());
|
||||
buf.write_u8(ch as u8);
|
||||
needs_span = !punct.span.is_call_site();
|
||||
}
|
||||
}
|
||||
TokenTree::Literal(literal) => {
|
||||
if literal.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_LITERAL);
|
||||
buf.write_u32(literal.identity & !Identity::RESPANNED);
|
||||
needs_span = literal.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(Bytecode::LITERAL);
|
||||
let repr = literal.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
needs_span = !literal.span.is_call_site();
|
||||
}
|
||||
}
|
||||
}
|
||||
if needs_span {
|
||||
buf.write_u8(Bytecode::SET_SPAN);
|
||||
linearize_span(token.span(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
fn linearize_span(span: Span, buf: &mut OutputBuffer) {
|
||||
buf.write_u32(span.lo);
|
||||
buf.write_u32(span.hi);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.177"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Implementation of #[derive(Serialize, Deserialize)]"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
edition = "2015"
|
||||
homepage = "https://serde.rs"
|
||||
include = ["serde_derive-x86_64-unknown-linux-gnu", "src", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
deserialize_in_place = []
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = "2.0.25"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", path = "../../serde" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
[workspace]
|
||||
@@ -1 +0,0 @@
|
||||
../../LICENSE-APACHE
|
||||
@@ -1 +0,0 @@
|
||||
../../LICENSE-MIT
|
||||
@@ -1 +0,0 @@
|
||||
../../README.md
|
||||
@@ -1 +0,0 @@
|
||||
../../crates-io.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/bound.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../proc-macro2/src/watt/buffer.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../proc-macro2/src/watt/bytecode.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/de.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/dummy.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/fragment.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/internals/
|
||||
@@ -1,22 +0,0 @@
|
||||
//! This crate provides Serde's two derive macros.
|
||||
//!
|
||||
//! ```edition2021
|
||||
//! # use serde_derive::{Deserialize, Serialize};
|
||||
//! #
|
||||
//! #[derive(Serialize, Deserialize)]
|
||||
//! # struct S;
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.177")]
|
||||
|
||||
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
|
||||
include!("lib_from_source.rs");
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))]
|
||||
include!("lib_precompiled.rs");
|
||||
@@ -1,36 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
|
||||
#[macro_use]
|
||||
mod bound;
|
||||
#[macro_use]
|
||||
mod fragment;
|
||||
|
||||
mod de;
|
||||
mod dummy;
|
||||
mod internals;
|
||||
mod pretend;
|
||||
mod ser;
|
||||
mod this;
|
||||
mod try;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
ser::expand_derive_serialize(&mut input)
|
||||
.unwrap_or_else(syn::Error::into_compile_error)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
de::expand_derive_deserialize(&mut input)
|
||||
.unwrap_or_else(syn::Error::into_compile_error)
|
||||
.into()
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
mod buffer;
|
||||
mod bytecode;
|
||||
|
||||
use crate::buffer::{InputBuffer, OutputBuffer};
|
||||
use crate::bytecode::Bytecode;
|
||||
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, ExitStatus, Stdio};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
derive(0, input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
derive(1 + cfg!(feature = "deserialize_in_place") as u8, input)
|
||||
}
|
||||
|
||||
fn derive(select: u8, input: TokenStream) -> TokenStream {
|
||||
let mut memory = TokenMemory::default();
|
||||
let mut buf = OutputBuffer::new();
|
||||
buf.write_u8(select);
|
||||
|
||||
memory.spans.push(Span::call_site());
|
||||
for token in input {
|
||||
memory.linearize_token(token, &mut buf);
|
||||
}
|
||||
|
||||
let exe_path = Path::new(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/serde_derive-x86_64-unknown-linux-gnu",
|
||||
));
|
||||
let mut child = match Command::new(exe_path)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => child,
|
||||
Err(io_error) => {
|
||||
if io_error.kind() == ErrorKind::NotFound {
|
||||
panic!(
|
||||
"file missing from serde_derive manifest directory during macro expansion: {}",
|
||||
exe_path.display(),
|
||||
);
|
||||
} else {
|
||||
panic!("failed to spawn process: {}", io_error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
let mut buf = buf.into_bytes();
|
||||
stdin.write_all(&buf).unwrap();
|
||||
drop(stdin);
|
||||
|
||||
let mut stdout = child.stdout.take().unwrap();
|
||||
buf.clear();
|
||||
stdout.read_to_end(&mut buf).unwrap();
|
||||
|
||||
let success = child.wait().as_ref().map_or(true, ExitStatus::success);
|
||||
if !success || buf.is_empty() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
let mut buf = InputBuffer::new(&buf);
|
||||
memory.receive(&mut buf)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TokenMemory {
|
||||
spans: Vec<Span>,
|
||||
groups: Vec<Group>,
|
||||
idents: Vec<Ident>,
|
||||
puncts: Vec<Punct>,
|
||||
literals: Vec<Literal>,
|
||||
}
|
||||
|
||||
enum Kind {
|
||||
Group(Delimiter),
|
||||
Ident,
|
||||
Punct(Spacing),
|
||||
Literal,
|
||||
}
|
||||
|
||||
impl TokenMemory {
|
||||
// Depth-first post-order traversal.
|
||||
fn linearize_token(&mut self, token: TokenTree, buf: &mut OutputBuffer) {
|
||||
match token {
|
||||
TokenTree::Group(group) => {
|
||||
let mut len = 0usize;
|
||||
for token in group.stream() {
|
||||
self.linearize_token(token, buf);
|
||||
len += 1;
|
||||
}
|
||||
assert!(len <= u32::MAX as usize);
|
||||
buf.write_u8(match group.delimiter() {
|
||||
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
|
||||
Delimiter::Brace => Bytecode::GROUP_BRACE,
|
||||
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
|
||||
Delimiter::None => Bytecode::GROUP_NONE,
|
||||
});
|
||||
buf.write_u32(len as u32);
|
||||
self.spans
|
||||
.extend([group.span(), group.span_open(), group.span_close()]);
|
||||
self.groups.push(group);
|
||||
}
|
||||
TokenTree::Ident(ident) => {
|
||||
buf.write_u8(Bytecode::IDENT);
|
||||
let repr = ident.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
self.spans.push(ident.span());
|
||||
self.idents.push(ident);
|
||||
}
|
||||
TokenTree::Punct(punct) => {
|
||||
buf.write_u8(match punct.spacing() {
|
||||
Spacing::Alone => Bytecode::PUNCT_ALONE,
|
||||
Spacing::Joint => Bytecode::PUNCT_JOINT,
|
||||
});
|
||||
let ch = punct.as_char();
|
||||
assert!(ch.is_ascii());
|
||||
buf.write_u8(ch as u8);
|
||||
self.spans.push(punct.span());
|
||||
self.puncts.push(punct);
|
||||
}
|
||||
TokenTree::Literal(literal) => {
|
||||
buf.write_u8(Bytecode::LITERAL);
|
||||
let repr = literal.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
self.spans.push(literal.span());
|
||||
self.literals.push(literal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn receive(&self, buf: &mut InputBuffer) -> TokenStream {
|
||||
let mut trees = Vec::new();
|
||||
while !buf.is_empty() {
|
||||
match match buf.read_u8() {
|
||||
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
|
||||
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
|
||||
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
|
||||
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
|
||||
Bytecode::IDENT => Kind::Ident,
|
||||
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
|
||||
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
|
||||
Bytecode::LITERAL => Kind::Literal,
|
||||
Bytecode::LOAD_GROUP => {
|
||||
let identity = buf.read_u32();
|
||||
let group = self.groups[identity as usize].clone();
|
||||
trees.push(TokenTree::Group(group));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_IDENT => {
|
||||
let identity = buf.read_u32();
|
||||
let ident = self.idents[identity as usize].clone();
|
||||
trees.push(TokenTree::Ident(ident));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_PUNCT => {
|
||||
let identity = buf.read_u32();
|
||||
let punct = self.puncts[identity as usize].clone();
|
||||
trees.push(TokenTree::Punct(punct));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_LITERAL => {
|
||||
let identity = buf.read_u32();
|
||||
let literal = self.literals[identity as usize].clone();
|
||||
trees.push(TokenTree::Literal(literal));
|
||||
continue;
|
||||
}
|
||||
Bytecode::SET_SPAN => {
|
||||
trees.last_mut().unwrap().set_span(self.read_span(buf));
|
||||
continue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
Kind::Group(delimiter) => {
|
||||
let len = buf.read_u32();
|
||||
let stream = trees.drain(trees.len() - len as usize..).collect();
|
||||
let group = Group::new(delimiter, stream);
|
||||
trees.push(TokenTree::Group(group));
|
||||
}
|
||||
Kind::Ident => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let span = self.read_span(buf);
|
||||
let ident = if let Some(repr) = repr.strip_prefix("r#") {
|
||||
Ident::new_raw(repr, span)
|
||||
} else {
|
||||
Ident::new(repr, span)
|
||||
};
|
||||
trees.push(TokenTree::Ident(ident));
|
||||
}
|
||||
Kind::Punct(spacing) => {
|
||||
let ch = buf.read_u8();
|
||||
assert!(ch.is_ascii());
|
||||
let punct = Punct::new(ch as char, spacing);
|
||||
trees.push(TokenTree::Punct(punct));
|
||||
}
|
||||
Kind::Literal => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let literal = Literal::from_str(repr).unwrap();
|
||||
trees.push(TokenTree::Literal(literal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TokenStream::from_iter(trees)
|
||||
}
|
||||
|
||||
fn read_span(&self, buf: &mut InputBuffer) -> Span {
|
||||
let lo = buf.read_u32();
|
||||
let hi = buf.read_u32();
|
||||
let span = self.spans[lo as usize];
|
||||
if lo == hi {
|
||||
span
|
||||
} else {
|
||||
#[cfg(any())] // FIXME
|
||||
return span.join(self.spans[hi as usize]).unwrap_or(span);
|
||||
span
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/pretend.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/ser.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/this.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/try.rs
|
||||
+19
-8
@@ -1,34 +1,45 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.177" # remember to update html_root_url and serde_derive dependency
|
||||
version = "1.0.219"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||
description = "A generic serialization/deserialization framework"
|
||||
documentation = "https://docs.rs/serde"
|
||||
edition = "2018"
|
||||
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.19"
|
||||
rust-version = "1.31"
|
||||
|
||||
[dependencies]
|
||||
serde_derive = { version = "=1.0.177", optional = true, path = "../serde_derive" }
|
||||
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = { version = "1", path = "../serde_derive" }
|
||||
|
||||
[lib]
|
||||
doc-scrape-examples = false
|
||||
|
||||
[package.metadata.playground]
|
||||
features = ["derive", "rc"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["derive"]
|
||||
features = ["derive", "rc", "unstable"]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--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.219", path = "../serde_derive" }
|
||||
|
||||
|
||||
### FEATURES #################################################################
|
||||
|
||||
+55
-88
@@ -1,6 +1,6 @@
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::str::{self, FromStr};
|
||||
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
|
||||
@@ -13,71 +13,26 @@ fn main() {
|
||||
None => return,
|
||||
};
|
||||
|
||||
if minor >= 77 {
|
||||
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_core_try_from)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_float_copysign)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_num_nonzero_signed)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_relaxed_trait_bounds)");
|
||||
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_systemtime_checked_add)");
|
||||
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";
|
||||
|
||||
// std::collections::Bound was stabilized in Rust 1.17
|
||||
// but it was moved to core::ops later in Rust 1.26:
|
||||
// https://doc.rust-lang.org/core/ops/enum.Bound.html
|
||||
if minor < 26 {
|
||||
println!("cargo:rustc-cfg=no_ops_bound");
|
||||
if minor < 17 {
|
||||
println!("cargo:rustc-cfg=no_collections_bound");
|
||||
}
|
||||
}
|
||||
|
||||
// core::cmp::Reverse stabilized in Rust 1.19:
|
||||
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
|
||||
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");
|
||||
}
|
||||
|
||||
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
|
||||
// stabilized in Rust 1.34:
|
||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
|
||||
@@ -89,9 +44,10 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
|
||||
}
|
||||
|
||||
// Current minimum supported version of serde_derive crate is Rust 1.56.
|
||||
if minor < 56 {
|
||||
println!("cargo:rustc-cfg=no_serde_derive");
|
||||
// f32::copysign and f64::copysign stabilized in Rust 1.35.
|
||||
// https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another
|
||||
if minor < 35 {
|
||||
println!("cargo:rustc-cfg=no_float_copysign");
|
||||
}
|
||||
|
||||
// Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60.
|
||||
@@ -115,38 +71,49 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Current minimum supported version of serde_derive crate is Rust 1.61.
|
||||
if minor < 61 {
|
||||
println!("cargo:rustc-cfg=no_serde_derive");
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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 = 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 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;
|
||||
}
|
||||
|
||||
let next = match pieces.next() {
|
||||
Some(next) => next,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
u32::from_str(next).ok()
|
||||
pieces.next()?.parse().ok()
|
||||
}
|
||||
|
||||
+13
-17
@@ -1,6 +1,6 @@
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use de::{
|
||||
use crate::de::{
|
||||
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
|
||||
};
|
||||
|
||||
@@ -129,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -143,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -197,7 +193,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
while let Some(IgnoredAny) = try!(seq.next_element()) {
|
||||
while let Some(IgnoredAny) = tri!(seq.next_element()) {
|
||||
// Gobble
|
||||
}
|
||||
Ok(IgnoredAny)
|
||||
@@ -208,7 +204,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
|
||||
while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
|
||||
// Gobble
|
||||
}
|
||||
Ok(IgnoredAny)
|
||||
@@ -227,7 +223,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
try!(data.variant::<IgnoredAny>()).1.newtype_variant()
|
||||
tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+605
-432
File diff suppressed because it is too large
Load Diff
+132
-92
@@ -64,8 +64,8 @@
|
||||
//! - RefCell\<T\>
|
||||
//! - Mutex\<T\>
|
||||
//! - RwLock\<T\>
|
||||
//! - Rc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Rc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - **Collection types**:
|
||||
//! - BTreeMap\<K, V\>
|
||||
//! - BTreeSet\<T\>
|
||||
@@ -101,8 +101,8 @@
|
||||
//! - SocketAddrV6
|
||||
//!
|
||||
//! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html
|
||||
//! [`Deserialize`]: ../trait.Deserialize.html
|
||||
//! [`Deserializer`]: ../trait.Deserializer.html
|
||||
//! [`Deserialize`]: crate::Deserialize
|
||||
//! [`Deserializer`]: crate::Deserializer
|
||||
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
||||
//! [`postcard`]: https://github.com/jamesmunns/postcard
|
||||
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
||||
@@ -112,26 +112,27 @@
|
||||
//! [derive section of the manual]: https://serde.rs/derive.html
|
||||
//! [data formats]: https://serde.rs/#data-formats
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub mod value;
|
||||
|
||||
#[cfg(not(no_integer128))]
|
||||
mod format;
|
||||
mod ignored_any;
|
||||
mod impls;
|
||||
mod utf8;
|
||||
pub(crate) mod size_hint;
|
||||
|
||||
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")]
|
||||
#[doc(no_inline)]
|
||||
pub use std::error::Error as StdError;
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[doc(no_inline)]
|
||||
pub use std_error::Error as StdError;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -400,20 +401,20 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
Bool(b) => write!(formatter, "boolean `{}`", b),
|
||||
Unsigned(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),
|
||||
Str(s) => write!(formatter, "string {:?}", s),
|
||||
Bytes(_) => write!(formatter, "byte array"),
|
||||
Unit => write!(formatter, "unit value"),
|
||||
Option => write!(formatter, "Option value"),
|
||||
NewtypeStruct => write!(formatter, "newtype struct"),
|
||||
Seq => write!(formatter, "sequence"),
|
||||
Map => write!(formatter, "map"),
|
||||
Enum => write!(formatter, "enum"),
|
||||
UnitVariant => write!(formatter, "unit variant"),
|
||||
NewtypeVariant => write!(formatter, "newtype variant"),
|
||||
TupleVariant => write!(formatter, "tuple variant"),
|
||||
StructVariant => write!(formatter, "struct variant"),
|
||||
Bytes(_) => formatter.write_str("byte array"),
|
||||
Unit => formatter.write_str("unit value"),
|
||||
Option => formatter.write_str("Option value"),
|
||||
NewtypeStruct => formatter.write_str("newtype struct"),
|
||||
Seq => formatter.write_str("sequence"),
|
||||
Map => formatter.write_str("map"),
|
||||
Enum => formatter.write_str("enum"),
|
||||
UnitVariant => formatter.write_str("unit variant"),
|
||||
NewtypeVariant => formatter.write_str("newtype variant"),
|
||||
TupleVariant => formatter.write_str("tuple variant"),
|
||||
StructVariant => formatter.write_str("struct variant"),
|
||||
Other(other) => formatter.write_str(other),
|
||||
}
|
||||
}
|
||||
@@ -485,13 +486,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Expected for &'a str {
|
||||
impl Expected for &str {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Expected + 'a {
|
||||
impl Display for Expected + '_ {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Expected::fmt(self, formatter)
|
||||
}
|
||||
@@ -530,6 +531,13 @@ impl<'a> Display for Expected + 'a {
|
||||
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
|
||||
///
|
||||
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
||||
#[cfg_attr(
|
||||
not(no_diagnostic_namespace),
|
||||
diagnostic::on_unimplemented(
|
||||
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 {
|
||||
/// Deserialize this value from the given Serde deserializer.
|
||||
///
|
||||
@@ -566,7 +574,7 @@ pub trait Deserialize<'de>: Sized {
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// Default implementation just delegates to `deserialize` impl.
|
||||
*place = try!(Deserialize::deserialize(deserializer));
|
||||
*place = tri!(Deserialize::deserialize(deserializer));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -946,18 +954,15 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||
@@ -980,18 +985,15 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||
@@ -1226,11 +1228,11 @@ pub trait Deserializer<'de>: Sized {
|
||||
#[doc(hidden)]
|
||||
fn __deserialize_content<V>(
|
||||
self,
|
||||
_: ::actually_private::T,
|
||||
_: crate::actually_private::T,
|
||||
visitor: V,
|
||||
) -> Result<::private::de::Content<'de>, Self::Error>
|
||||
) -> Result<crate::__private::de::Content<'de>, Self::Error>
|
||||
where
|
||||
V: Visitor<'de, Value = ::private::de::Content<'de>>,
|
||||
V: Visitor<'de, Value = crate::__private::de::Content<'de>>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
@@ -1363,20 +1365,20 @@ pub trait Visitor<'de>: Sized {
|
||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
/// The input contains a `i128`.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default implementation fails with a type error.
|
||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 58];
|
||||
let mut writer = format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
||||
}
|
||||
/// The input contains a `i128`.
|
||||
///
|
||||
/// The default implementation fails with a type error.
|
||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 58];
|
||||
let mut writer = crate::format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
||||
Err(Error::invalid_type(
|
||||
Unexpected::Other(writer.as_str()),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
/// The input contains a `u8`.
|
||||
@@ -1425,20 +1427,20 @@ pub trait Visitor<'de>: Sized {
|
||||
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
/// The input contains a `u128`.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default implementation fails with a type error.
|
||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 57];
|
||||
let mut writer = format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
||||
}
|
||||
/// The input contains a `u128`.
|
||||
///
|
||||
/// The default implementation fails with a type error.
|
||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 57];
|
||||
let mut writer = crate::format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
||||
Err(Error::invalid_type(
|
||||
Unexpected::Other(writer.as_str()),
|
||||
&self,
|
||||
))
|
||||
}
|
||||
|
||||
/// The input contains an `f32`.
|
||||
@@ -1474,7 +1476,7 @@ pub trait Visitor<'de>: Sized {
|
||||
where
|
||||
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
|
||||
@@ -1529,6 +1531,7 @@ pub trait Visitor<'de>: Sized {
|
||||
/// `String`.
|
||||
#[inline]
|
||||
#[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>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1551,7 +1554,6 @@ pub trait Visitor<'de>: Sized {
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let _ = v;
|
||||
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
||||
}
|
||||
|
||||
@@ -1588,6 +1590,7 @@ pub trait Visitor<'de>: Sized {
|
||||
/// The default implementation forwards to `visit_bytes` and then drops the
|
||||
/// `Vec<u8>`.
|
||||
#[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>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1738,9 +1741,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
|
||||
A: SeqAccess<'de>,
|
||||
A: ?Sized + SeqAccess<'de>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
@@ -1831,9 +1834,9 @@ pub trait MapAccess<'de> {
|
||||
K: DeserializeSeed<'de>,
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match try!(self.next_key_seed(kseed)) {
|
||||
match tri!(self.next_key_seed(kseed)) {
|
||||
Some(key) => {
|
||||
let value = try!(self.next_value_seed(vseed));
|
||||
let value = tri!(self.next_value_seed(vseed));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None),
|
||||
@@ -1891,9 +1894,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
|
||||
A: MapAccess<'de>,
|
||||
A: ?Sized + MapAccess<'de>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
@@ -2281,15 +2284,52 @@ impl Display for OneOf {
|
||||
1 => write!(formatter, "`{}`", self.names[0]),
|
||||
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() {
|
||||
if i > 0 {
|
||||
try!(write!(formatter, ", "));
|
||||
tri!(formatter.write_str(", "));
|
||||
}
|
||||
try!(write!(formatter, "`{}`", alt));
|
||||
tri!(write!(formatter, "`{}`", alt));
|
||||
}
|
||||
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,4 +1,4 @@
|
||||
use de::{Deserialize, DeserializeSeed, Deserializer};
|
||||
use crate::de::{Deserialize, DeserializeSeed, Deserializer};
|
||||
|
||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||
///
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
||||
where
|
||||
@@ -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, 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()
|
||||
}
|
||||
}
|
||||
+207
-23
@@ -21,12 +21,11 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use self::private::{First, Second};
|
||||
use __private::size_hint;
|
||||
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||
use ser;
|
||||
use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||
use crate::ser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -113,6 +112,7 @@ impl Debug for Error {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
&self.err
|
||||
@@ -175,6 +175,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> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.debug_struct("UnitDeserializer").finish()
|
||||
@@ -185,12 +196,14 @@ impl<E> Debug for UnitDeserializer<E> {
|
||||
|
||||
/// A deserializer that cannot be instantiated.
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
pub struct NeverDeserializer<E> {
|
||||
never: !,
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for !
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -223,6 +236,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 {
|
||||
@@ -277,6 +302,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> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -293,20 +329,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8);
|
||||
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
|
||||
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
||||
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!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
||||
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
||||
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!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
||||
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
||||
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`.
|
||||
pub struct U32Deserializer<E> {
|
||||
value: u32,
|
||||
@@ -370,6 +403,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>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -459,6 +503,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>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -538,6 +593,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>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -566,6 +632,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
|
||||
|
||||
/// A deserializer holding a `String`.
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
pub struct StringDeserializer<E> {
|
||||
value: String,
|
||||
marker: PhantomData<E>,
|
||||
@@ -582,6 +649,7 @@ impl<E> Clone for StringDeserializer<E> {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for String
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -639,6 +707,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"))]
|
||||
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
|
||||
where
|
||||
@@ -669,6 +749,7 @@ impl<E> Debug for StringDeserializer<E> {
|
||||
|
||||
/// A deserializer holding a `Cow<str>`.
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
pub struct CowStrDeserializer<'a, E> {
|
||||
value: Cow<'a, str>,
|
||||
marker: PhantomData<E>,
|
||||
@@ -685,6 +766,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> {
|
||||
}
|
||||
|
||||
#[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>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -745,6 +827,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"))]
|
||||
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
|
||||
where
|
||||
@@ -822,6 +916,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> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -870,6 +975,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> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -937,8 +1053,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let v = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
let v = tri!(visitor.visit_seq(&mut self));
|
||||
tri!(self.end());
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
@@ -949,6 +1065,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>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
@@ -980,7 +1109,7 @@ struct ExpectedInSeq(usize);
|
||||
impl Expected for ExpectedInSeq {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
write!(formatter, "1 element in sequence")
|
||||
formatter.write_str("1 element in sequence")
|
||||
} else {
|
||||
write!(formatter, "{} elements in sequence", self.0)
|
||||
}
|
||||
@@ -1003,6 +1132,7 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[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>
|
||||
where
|
||||
T: IntoDeserializer<'de, E>,
|
||||
@@ -1016,6 +1146,7 @@ where
|
||||
}
|
||||
|
||||
#[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>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
@@ -1029,6 +1160,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Hash,
|
||||
@@ -1077,6 +1209,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.
|
||||
@@ -1162,8 +1305,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let value = try!(visitor.visit_map(&mut self));
|
||||
try!(self.end());
|
||||
let value = tri!(visitor.visit_map(&mut self));
|
||||
tri!(self.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -1171,8 +1314,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let value = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
let value = tri!(visitor.visit_seq(&mut self));
|
||||
tri!(self.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -1191,6 +1334,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>
|
||||
where
|
||||
I: Iterator,
|
||||
@@ -1236,8 +1394,8 @@ where
|
||||
{
|
||||
match self.next_pair() {
|
||||
Some((key, value)) => {
|
||||
let key = try!(kseed.deserialize(key.into_deserializer()));
|
||||
let value = try!(vseed.deserialize(value.into_deserializer()));
|
||||
let key = tri!(kseed.deserialize(key.into_deserializer()));
|
||||
let value = tri!(vseed.deserialize(value.into_deserializer()));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None),
|
||||
@@ -1341,7 +1499,7 @@ where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
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() {
|
||||
Ok(pair)
|
||||
} else {
|
||||
@@ -1405,7 +1563,7 @@ struct ExpectedInMap(usize);
|
||||
impl Expected for ExpectedInMap {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
write!(formatter, "1 element in map")
|
||||
formatter.write_str("1 element in map")
|
||||
} else {
|
||||
write!(formatter, "{} elements in map", self.0)
|
||||
}
|
||||
@@ -1415,6 +1573,7 @@ impl Expected for ExpectedInMap {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[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>
|
||||
where
|
||||
K: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
@@ -1429,6 +1588,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
||||
where
|
||||
K: IntoDeserializer<'de, E> + Eq + Hash,
|
||||
@@ -1490,6 +1650,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>
|
||||
where
|
||||
A: de::MapAccess<'de>,
|
||||
@@ -1501,7 +1672,7 @@ where
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match try!(self.map.next_key_seed(seed)) {
|
||||
match tri!(self.map.next_key_seed(seed)) {
|
||||
Some(key) => Ok((key, private::map_as_enum(self.map))),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
|
||||
}
|
||||
@@ -1543,12 +1714,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
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 lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
|
||||
use crate::de::{
|
||||
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
|
||||
};
|
||||
|
||||
pub struct UnitOnly<E> {
|
||||
marker: PhantomData<E>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use lib::fmt::{self, Write};
|
||||
use lib::str;
|
||||
use crate::lib::fmt::{self, Write};
|
||||
use crate::lib::str;
|
||||
|
||||
pub(super) struct Buf<'a> {
|
||||
bytes: &'a mut [u8],
|
||||
+3
-76
@@ -1,82 +1,9 @@
|
||||
/// 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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # 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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// macro_rules! serde_if_integer128 {
|
||||
/// ($($tt:tt)*) => {
|
||||
/// $($tt)*
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// When built without support for 128-bit integers, this macro expands to
|
||||
/// nothing.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// macro_rules! serde_if_integer128 {
|
||||
/// ($($tt:tt)*) => {};
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(not(no_integer128))]
|
||||
// No longer used. Old versions of serde used this macro for supporting targets
|
||||
// that did not yet have 128-bit integer support.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! serde_if_integer128 {
|
||||
($($tt:tt)*) => {
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(no_integer128)]
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! serde_if_integer128 {
|
||||
($($tt:tt)*) => {};
|
||||
}
|
||||
|
||||
+82
-80
@@ -63,6 +63,7 @@
|
||||
//! 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
|
||||
//! [Postcard]: https://github.com/jamesmunns/postcard
|
||||
@@ -89,66 +90,71 @@
|
||||
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
|
||||
//! [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.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.177")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.219")]
|
||||
// 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(error_in_core, never_type))]
|
||||
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||
#![allow(unknown_lints, bare_trait_objects, deprecated)]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||
// Ignored clippy and clippy_pedantic lints
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
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,
|
||||
explicit_auto_deref,
|
||||
let_underscore_untyped,
|
||||
map_err_ignore,
|
||||
new_without_default,
|
||||
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,
|
||||
)
|
||||
#![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_enum,
|
||||
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)]
|
||||
|
||||
@@ -168,21 +174,26 @@ mod lib {
|
||||
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::{iter, num, ptr, str};
|
||||
pub use self::core::{u16, u32, u64, u8, usize};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::core::{cmp, mem, slice};
|
||||
|
||||
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::clone;
|
||||
pub use self::core::cmp::Reverse;
|
||||
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::num::Wrapping;
|
||||
pub use self::core::ops::{Range, RangeFrom, RangeTo};
|
||||
pub use self::core::option::{self, Option};
|
||||
pub use self::core::result::{self, Result};
|
||||
pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
|
||||
pub use self::core::option;
|
||||
pub use self::core::result;
|
||||
pub use self::core::time::Duration;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::borrow::{Cow, ToOwned};
|
||||
@@ -220,7 +231,7 @@ mod lib {
|
||||
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
|
||||
#[cfg(all(not(no_core_cstr), not(feature = "std")))]
|
||||
pub use core::ffi::CStr;
|
||||
pub use self::core::ffi::CStr;
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::ffi::CStr;
|
||||
|
||||
@@ -229,8 +240,13 @@ mod lib {
|
||||
#[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::{error, net};
|
||||
pub use std::net;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::error;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{HashMap, HashSet};
|
||||
@@ -247,18 +263,6 @@ mod lib {
|
||||
#[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", no_target_has_atomic, not(no_std_atomic)))]
|
||||
pub use std::sync::atomic::{
|
||||
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
|
||||
@@ -280,15 +284,15 @@ mod lib {
|
||||
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
|
||||
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
||||
pub use self::core::time::Duration;
|
||||
#[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! try {
|
||||
macro_rules! tri {
|
||||
($expr:expr) => {
|
||||
match $expr {
|
||||
Ok(val) => val,
|
||||
@@ -308,25 +312,22 @@ mod integer128;
|
||||
pub mod de;
|
||||
pub mod ser;
|
||||
|
||||
mod format;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use de::{Deserialize, Deserializer};
|
||||
pub use crate::de::{Deserialize, Deserializer};
|
||||
#[doc(inline)]
|
||||
pub use ser::{Serialize, Serializer};
|
||||
pub use crate::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(any(feature = "std", feature = "unstable")))]
|
||||
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||
mod std_error;
|
||||
|
||||
// Re-export #[derive(Serialize, Deserialize)].
|
||||
@@ -339,6 +340,7 @@ extern crate serde_derive;
|
||||
|
||||
/// Derive macro available if serde is built with `features = ["derive"]`.
|
||||
#[cfg(feature = "serde_derive")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
|
||||
pub use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||
|
||||
+6
-10
@@ -104,9 +104,9 @@
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`Deserializer`]: trait.Deserializer.html
|
||||
/// [`Visitor`]: de/trait.Visitor.html
|
||||
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
|
||||
/// [`Deserializer`]: crate::Deserializer
|
||||
/// [`Visitor`]: crate::de::Visitor
|
||||
/// [`Deserializer::deserialize_any`]: crate::Deserializer::deserialize_any
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! forward_to_deserialize_any {
|
||||
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
|
||||
@@ -123,7 +123,7 @@ macro_rules! forward_to_deserialize_any {
|
||||
macro_rules! forward_to_deserialize_any_method {
|
||||
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
||||
#[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
|
||||
$v: $crate::de::Visitor<$l>,
|
||||
{
|
||||
@@ -154,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
||||
};
|
||||
(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>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
||||
@@ -171,9 +169,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
||||
};
|
||||
(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>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
||||
|
||||
+187
-359
@@ -1,10 +1,13 @@
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
||||
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
|
||||
use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
||||
use crate::de::{
|
||||
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess,
|
||||
Visitor,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use de::{DeserializeSeed, MapAccess, Unexpected};
|
||||
use crate::de::{MapAccess, Unexpected};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::content::{
|
||||
@@ -13,7 +16,7 @@ pub use self::content::{
|
||||
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
|
||||
};
|
||||
|
||||
pub use seed::InPlaceSeed;
|
||||
pub use crate::seed::InPlaceSeed;
|
||||
|
||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||
/// otherwise it is an error.
|
||||
@@ -203,13 +206,13 @@ mod content {
|
||||
// This issue is tracking making some of this stuff public:
|
||||
// https://github.com/serde-rs/serde/issues/741
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use __private::size_hint;
|
||||
use actually_private;
|
||||
use de::{
|
||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||
use crate::actually_private;
|
||||
use crate::de::value::{MapDeserializer, SeqDeserializer};
|
||||
use crate::de::{
|
||||
self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected,
|
||||
IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor,
|
||||
};
|
||||
|
||||
/// Used from generated code to buffer the contents of the Deserializer when
|
||||
@@ -299,6 +302,30 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = ContentDeserializer<'de, E>;
|
||||
|
||||
fn into_deserializer(self) -> Self::Deserializer {
|
||||
ContentDeserializer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de, E> de::IntoDeserializer<'de, E> for &'a Content<'de>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = ContentRefDeserializer<'a, 'de, E>;
|
||||
|
||||
fn into_deserializer(self) -> Self::Deserializer {
|
||||
ContentRefDeserializer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to capture data in [`Content`] from other deserializers.
|
||||
/// Cannot capture externally tagged enums, `i128` and `u128`.
|
||||
struct ContentVisitor<'de> {
|
||||
value: PhantomData<Content<'de>>,
|
||||
}
|
||||
@@ -460,14 +487,16 @@ mod content {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v)))
|
||||
let v = tri!(Deserialize::deserialize(deserializer));
|
||||
Ok(Content::Some(Box::new(v)))
|
||||
}
|
||||
|
||||
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v)))
|
||||
let v = tri!(Deserialize::deserialize(deserializer));
|
||||
Ok(Content::Newtype(Box::new(v)))
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||
@@ -476,7 +505,7 @@ mod content {
|
||||
{
|
||||
let mut vec =
|
||||
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
|
||||
while let Some(e) = try!(visitor.next_element()) {
|
||||
while let Some(e) = tri!(visitor.next_element()) {
|
||||
vec.push(e);
|
||||
}
|
||||
Ok(Content::Seq(vec))
|
||||
@@ -490,7 +519,7 @@ mod content {
|
||||
Vec::<(Content, Content)>::with_capacity(
|
||||
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
|
||||
);
|
||||
while let Some(kv) = try!(visitor.next_entry()) {
|
||||
while let Some(kv) = tri!(visitor.next_entry()) {
|
||||
vec.push(kv);
|
||||
}
|
||||
Ok(Content::Map(vec))
|
||||
@@ -514,6 +543,8 @@ mod content {
|
||||
Content(Content<'de>),
|
||||
}
|
||||
|
||||
/// Serves as a seed for deserializing a key of internally tagged enum.
|
||||
/// Cannot capture externally tagged enums, `i128` and `u128`.
|
||||
struct TagOrContentVisitor<'de> {
|
||||
name: &'static str,
|
||||
value: PhantomData<TagOrContent<'de>>,
|
||||
@@ -800,6 +831,9 @@ mod content {
|
||||
|
||||
/// Used by generated code to deserialize an internally tagged enum.
|
||||
///
|
||||
/// Captures map or sequence from the original deserializer and searches
|
||||
/// a tag in it (in case of sequence, tag is the first element of sequence).
|
||||
///
|
||||
/// Not public API.
|
||||
pub struct TaggedContentVisitor<T> {
|
||||
tag_name: &'static str,
|
||||
@@ -833,14 +867,14 @@ mod content {
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
let tag = match try!(seq.next_element()) {
|
||||
let tag = match tri!(seq.next_element()) {
|
||||
Some(tag) => tag,
|
||||
None => {
|
||||
return Err(de::Error::missing_field(self.tag_name));
|
||||
}
|
||||
};
|
||||
let rest = de::value::SeqAccessDeserializer::new(seq);
|
||||
Ok((tag, try!(Content::deserialize(rest))))
|
||||
Ok((tag, tri!(Content::deserialize(rest))))
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
@@ -852,16 +886,16 @@ mod content {
|
||||
Content,
|
||||
Content,
|
||||
)>(map.size_hint()));
|
||||
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
|
||||
while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
|
||||
match k {
|
||||
TagOrContent::Tag => {
|
||||
if tag.is_some() {
|
||||
return Err(de::Error::duplicate_field(self.tag_name));
|
||||
}
|
||||
tag = Some(try!(map.next_value()));
|
||||
tag = Some(tri!(map.next_value()));
|
||||
}
|
||||
TagOrContent::Content(k) => {
|
||||
let v = try!(map.next_value());
|
||||
let v = tri!(map.next_value());
|
||||
vec.push((k, v));
|
||||
}
|
||||
}
|
||||
@@ -883,7 +917,9 @@ mod content {
|
||||
|
||||
/// Not public API.
|
||||
pub struct TagOrContentFieldVisitor {
|
||||
/// Name of the tag field of the adjacently tagged enum
|
||||
pub tag: &'static str,
|
||||
/// Name of the content field of the adjacently tagged enum
|
||||
pub content: &'static str,
|
||||
}
|
||||
|
||||
@@ -958,7 +994,9 @@ mod content {
|
||||
|
||||
/// Not public API.
|
||||
pub struct TagContentOtherFieldVisitor {
|
||||
/// Name of the tag field of the adjacently tagged enum
|
||||
pub tag: &'static str,
|
||||
/// Name of the content field of the adjacently tagged enum
|
||||
pub content: &'static str,
|
||||
}
|
||||
|
||||
@@ -1073,10 +1111,9 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.into_iter().map(ContentDeserializer::new);
|
||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
let mut seq_visitor = SeqDeserializer::new(content.into_iter());
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -1088,12 +1125,9 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let map = content
|
||||
.into_iter()
|
||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
let mut map_visitor = MapDeserializer::new(content.into_iter());
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -1569,7 +1603,7 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
@@ -1592,10 +1626,10 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Map(v)) => {
|
||||
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
|
||||
de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
|
||||
}
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
@@ -1609,156 +1643,6 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
fn new(vec: Vec<Content<'de>>) -> Self {
|
||||
SeqDeserializer {
|
||||
iter: vec.into_iter(),
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let len = self.iter.len();
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
size_hint::from_bounds(&self.iter)
|
||||
}
|
||||
}
|
||||
|
||||
struct MapDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
|
||||
value: Option<Content<'de>>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> MapDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
|
||||
MapDeserializer {
|
||||
iter: map.into_iter(),
|
||||
value: None,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentDeserializer::new(key)).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.value.take() {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
||||
None => Err(de::Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
size_hint::from_bounds(&self.iter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(self)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// Not public API.
|
||||
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
|
||||
content: &'a Content<'de>,
|
||||
@@ -1819,10 +1703,9 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.iter().map(ContentRefDeserializer::new);
|
||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
let mut seq_visitor = SeqDeserializer::new(content.iter());
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -1834,15 +1717,16 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let map = content.iter().map(|(k, v)| {
|
||||
(
|
||||
ContentRefDeserializer::new(k),
|
||||
ContentRefDeserializer::new(v),
|
||||
)
|
||||
});
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
fn content_ref_deserializer_pair<'a, 'de>(
|
||||
(k, v): &'a (Content<'de>, Content<'de>),
|
||||
) -> (&'a Content<'de>, &'a Content<'de>) {
|
||||
(k, v)
|
||||
}
|
||||
|
||||
let map = content.iter().map(content_ref_deserializer_pair);
|
||||
let mut map_visitor = MapDeserializer::new(map);
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -2023,10 +1907,19 @@ mod content {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// with_optional_field::*
|
||||
match *self.content {
|
||||
Content::None => visitor.visit_none(),
|
||||
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
|
||||
Content::Unit => visitor.visit_unit(),
|
||||
// This case is to support data formats which do not encode an
|
||||
// indication whether a value is optional. An example of such a
|
||||
// format is JSON, and a counterexample is RON. When requesting
|
||||
// `deserialize_any` in JSON, the data format never performs
|
||||
// `Visitor::visit_some` but we still must be able to
|
||||
// deserialize the resulting Content into data structures with
|
||||
// optional fields.
|
||||
_ => visitor.visit_some(self),
|
||||
}
|
||||
}
|
||||
@@ -2056,10 +1949,21 @@ mod content {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_struct
|
||||
match *self.content {
|
||||
Content::Newtype(ref v) => {
|
||||
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
|
||||
}
|
||||
// This case is to support data formats that encode newtype
|
||||
// structs and their underlying data the same, with no
|
||||
// indication whether a newtype wrapper was present. For example
|
||||
// JSON does this, while RON does not. In RON a newtype's name
|
||||
// is included in the serialized representation and it knows to
|
||||
// call `Visitor::visit_newtype_struct` from `deserialize_any`.
|
||||
// JSON's `deserialize_any` never calls `visit_newtype_struct`
|
||||
// but in this code we still must be able to deserialize the
|
||||
// resulting Content into newtypes.
|
||||
_ => visitor.visit_newtype_struct(self),
|
||||
}
|
||||
}
|
||||
@@ -2264,6 +2168,10 @@ mod content {
|
||||
fn unit_variant(self) -> Result<(), E> {
|
||||
match self.value {
|
||||
Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)),
|
||||
// Covered by tests/test_annotations.rs
|
||||
// test_partially_untagged_adjacently_tagged_enum
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_enum::unit
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -2273,6 +2181,11 @@ mod content {
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.value {
|
||||
// Covered by tests/test_annotations.rs
|
||||
// test_partially_untagged_enum_desugared
|
||||
// test_partially_untagged_enum_generic
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_enum::newtype
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
@@ -2286,9 +2199,13 @@ mod content {
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
// Covered by tests/test_annotations.rs
|
||||
// test_partially_untagged_enum
|
||||
// test_partially_untagged_enum_desugared
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_enum::tuple0
|
||||
// newtype_enum::tuple2
|
||||
Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"tuple variant",
|
||||
@@ -2309,12 +2226,13 @@ mod content {
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Map(v)) => {
|
||||
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_enum::struct_from_map
|
||||
Some(Content::Map(v)) => visit_content_map_ref(v, visitor),
|
||||
// Covered by tests/test_enum_untagged.rs
|
||||
// newtype_enum::struct_from_seq
|
||||
// newtype_enum::empty_struct_from_seq
|
||||
Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"struct variant",
|
||||
@@ -2327,158 +2245,6 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqRefDeserializer<'a, 'de: 'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <&'a [Content<'de>] as IntoIterator>::IntoIter,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
fn new(slice: &'a [Content<'de>]) -> Self {
|
||||
SeqRefDeserializer {
|
||||
iter: slice.iter(),
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let len = self.iter.len();
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => seed
|
||||
.deserialize(ContentRefDeserializer::new(value))
|
||||
.map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
size_hint::from_bounds(&self.iter)
|
||||
}
|
||||
}
|
||||
|
||||
struct MapRefDeserializer<'a, 'de: 'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter,
|
||||
value: Option<&'a Content<'de>>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
fn new(map: &'a [(Content<'de>, Content<'de>)]) -> Self {
|
||||
MapRefDeserializer {
|
||||
iter: map.iter(),
|
||||
value: None,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.value.take() {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => Err(de::Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
size_hint::from_bounds(&self.iter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(self)
|
||||
}
|
||||
|
||||
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, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -2541,7 +2307,7 @@ mod content {
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
|
||||
while tri!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2839,6 +2605,17 @@ where
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
@@ -2863,7 +2640,6 @@ where
|
||||
deserialize_string()
|
||||
deserialize_bytes()
|
||||
deserialize_byte_buf()
|
||||
deserialize_unit_struct(&'static str)
|
||||
deserialize_seq()
|
||||
deserialize_tuple(usize)
|
||||
deserialize_tuple_struct(&'static str, usize)
|
||||
@@ -2974,3 +2750,55 @@ fn flat_map_take_entry<'de>(
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AdjacentlyTaggedEnumVariantSeed<F> {
|
||||
pub enum_name: &'static str,
|
||||
pub variants: &'static [&'static str],
|
||||
pub fields_enum: PhantomData<F>,
|
||||
}
|
||||
|
||||
pub struct AdjacentlyTaggedEnumVariantVisitor<F> {
|
||||
enum_name: &'static str,
|
||||
fields_enum: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor<F>
|
||||
where
|
||||
F: Deserialize<'de>,
|
||||
{
|
||||
type Value = F;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "variant of enum {}", self.enum_name)
|
||||
}
|
||||
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
let (variant, variant_access) = tri!(data.variant());
|
||||
tri!(variant_access.unit_variant());
|
||||
Ok(variant)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed<F>
|
||||
where
|
||||
F: Deserialize<'de>,
|
||||
{
|
||||
type Value = F;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_enum(
|
||||
self.enum_name,
|
||||
self.variants,
|
||||
AdjacentlyTaggedEnumVariantVisitor {
|
||||
enum_name: self.enum_name,
|
||||
fields_enum: PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Used only by Serde doc tests. Not public API.
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use ser;
|
||||
use crate::ser;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
@@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented {
|
||||
#[macro_export]
|
||||
macro_rules! __serialize_unimplemented_method {
|
||||
($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!()
|
||||
}
|
||||
};
|
||||
|
||||
+11
-13
@@ -3,30 +3,28 @@ pub mod de;
|
||||
#[cfg(not(no_serde_derive))]
|
||||
pub mod ser;
|
||||
|
||||
pub mod size_hint;
|
||||
|
||||
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
|
||||
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 crate::lib::clone::Clone;
|
||||
pub use crate::lib::convert::{From, Into};
|
||||
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};
|
||||
|
||||
pub use self::string::from_utf8_lossy;
|
||||
|
||||
#[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;
|
||||
pub use crate::lib::convert::TryFrom;
|
||||
|
||||
mod string {
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
|
||||
|
||||
+200
-148
@@ -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"))]
|
||||
use self::content::{
|
||||
@@ -51,11 +51,10 @@ enum Unsupported {
|
||||
String,
|
||||
ByteArray,
|
||||
Optional,
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Enum,
|
||||
}
|
||||
|
||||
@@ -69,11 +68,10 @@ impl Display for Unsupported {
|
||||
Unsupported::String => formatter.write_str("a string"),
|
||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||
Unsupported::Optional => formatter.write_str("an optional"),
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
Unsupported::UnitStruct => formatter.write_str("unit struct"),
|
||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Unsupported::Enum => formatter.write_str("an enum"),
|
||||
}
|
||||
}
|
||||
@@ -174,22 +172,22 @@ where
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(self.bad_type(Unsupported::Optional))
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
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> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(1)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
map.end()
|
||||
}
|
||||
|
||||
@@ -199,24 +197,24 @@ where
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_entry(inner_variant, &()));
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
tri!(map.serialize_entry(inner_variant, &()));
|
||||
map.end()
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
fn serialize_newtype_struct<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
@@ -224,11 +222,11 @@ where
|
||||
inner_value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_entry(inner_variant, inner_value));
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
tri!(map.serialize_entry(inner_variant, inner_value));
|
||||
map.end()
|
||||
}
|
||||
|
||||
@@ -269,9 +267,9 @@ where
|
||||
inner_variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
tri!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeTupleVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
@@ -280,8 +278,8 @@ where
|
||||
}
|
||||
|
||||
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)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
@@ -290,8 +288,8 @@ where
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
|
||||
try!(state.serialize_field(self.tag, self.variant_name));
|
||||
let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
|
||||
tri!(state.serialize_field(self.tag, self.variant_name));
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
@@ -316,9 +314,9 @@ where
|
||||
inner_variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
tri!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeStructVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
@@ -327,9 +325,9 @@ where
|
||||
}
|
||||
|
||||
#[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
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
Err(self.bad_type(Unsupported::String))
|
||||
}
|
||||
@@ -337,9 +335,9 @@ where
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
mod content {
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use ser::{self, Serialize, Serializer};
|
||||
use crate::ser::{self, Serialize, Serializer};
|
||||
|
||||
pub struct SerializeTupleVariantAsMapValue<M> {
|
||||
map: M,
|
||||
@@ -364,17 +362,17 @@ mod content {
|
||||
type Ok = M::Ok;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self
|
||||
tri!(self
|
||||
.map
|
||||
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
||||
self.map.end()
|
||||
@@ -404,21 +402,17 @@ mod content {
|
||||
type Ok = M::Ok;
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), M::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), M::Error>
|
||||
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));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self
|
||||
tri!(self
|
||||
.map
|
||||
.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
self.map.end()
|
||||
@@ -499,50 +493,50 @@ mod content {
|
||||
}
|
||||
Content::Seq(ref elements) => elements.serialize(serializer),
|
||||
Content::Tuple(ref elements) => {
|
||||
use ser::SerializeTuple;
|
||||
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
|
||||
use crate::ser::SerializeTuple;
|
||||
let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
|
||||
for e in elements {
|
||||
try!(tuple.serialize_element(e));
|
||||
tri!(tuple.serialize_element(e));
|
||||
}
|
||||
tuple.end()
|
||||
}
|
||||
Content::TupleStruct(n, ref fields) => {
|
||||
use ser::SerializeTupleStruct;
|
||||
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||
use crate::ser::SerializeTupleStruct;
|
||||
let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||
for f in fields {
|
||||
try!(ts.serialize_field(f));
|
||||
tri!(ts.serialize_field(f));
|
||||
}
|
||||
ts.end()
|
||||
}
|
||||
Content::TupleVariant(n, i, v, ref fields) => {
|
||||
use ser::SerializeTupleVariant;
|
||||
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||
use crate::ser::SerializeTupleVariant;
|
||||
let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||
for f in fields {
|
||||
try!(tv.serialize_field(f));
|
||||
tri!(tv.serialize_field(f));
|
||||
}
|
||||
tv.end()
|
||||
}
|
||||
Content::Map(ref entries) => {
|
||||
use ser::SerializeMap;
|
||||
let mut map = try!(serializer.serialize_map(Some(entries.len())));
|
||||
use crate::ser::SerializeMap;
|
||||
let mut map = tri!(serializer.serialize_map(Some(entries.len())));
|
||||
for (k, v) in entries {
|
||||
try!(map.serialize_entry(k, v));
|
||||
tri!(map.serialize_entry(k, v));
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
Content::Struct(n, ref fields) => {
|
||||
use ser::SerializeStruct;
|
||||
let mut s = try!(serializer.serialize_struct(n, fields.len()));
|
||||
use crate::ser::SerializeStruct;
|
||||
let mut s = tri!(serializer.serialize_struct(n, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
try!(s.serialize_field(k, v));
|
||||
tri!(s.serialize_field(k, v));
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
Content::StructVariant(n, i, v, ref fields) => {
|
||||
use ser::SerializeStructVariant;
|
||||
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||
use crate::ser::SerializeStructVariant;
|
||||
let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
try!(sv.serialize_field(k, v));
|
||||
tri!(sv.serialize_field(k, v));
|
||||
}
|
||||
sv.end()
|
||||
}
|
||||
@@ -635,11 +629,11 @@ mod content {
|
||||
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
|
||||
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> {
|
||||
@@ -659,21 +653,17 @@ mod content {
|
||||
Ok(Content::UnitVariant(name, variant_index, variant))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Content, E>
|
||||
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Content, E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Ok(Content::NewtypeStruct(
|
||||
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,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
@@ -681,13 +671,13 @@ mod content {
|
||||
value: &T,
|
||||
) -> Result<Content, E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Ok(Content::NewtypeVariant(
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
Box::new(try!(value.serialize(self))),
|
||||
Box::new(tri!(value.serialize(self))),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -782,11 +772,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
@@ -808,11 +798,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
@@ -835,11 +825,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
@@ -864,11 +854,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
@@ -896,24 +886,24 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let key = self
|
||||
.key
|
||||
.take()
|
||||
.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));
|
||||
Ok(())
|
||||
}
|
||||
@@ -922,13 +912,13 @@ mod content {
|
||||
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
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.entries.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
@@ -947,11 +937,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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));
|
||||
Ok(())
|
||||
}
|
||||
@@ -976,11 +966,11 @@ mod content {
|
||||
type Ok = Content;
|
||||
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
|
||||
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));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1025,7 +1015,7 @@ where
|
||||
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
|
||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
@@ -1088,9 +1078,9 @@ where
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
@@ -1100,30 +1090,30 @@ where
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(Self::bad_type(Unsupported::UnitStruct))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
variant: &'static str,
|
||||
) -> 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,
|
||||
_: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
@@ -1131,10 +1121,9 @@ where
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
try!(self.0.serialize_key(variant));
|
||||
self.0.serialize_value(value)
|
||||
self.0.serialize_entry(variant, value)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
@@ -1157,10 +1146,11 @@ where
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
variant: &'static str,
|
||||
_: usize,
|
||||
) -> 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> {
|
||||
@@ -1182,7 +1172,7 @@ where
|
||||
inner_variant: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
try!(self.0.serialize_key(inner_variant));
|
||||
tri!(self.0.serialize_key(inner_variant));
|
||||
Ok(FlatMapSerializeStructVariantAsMapValue::new(
|
||||
self.0,
|
||||
inner_variant,
|
||||
@@ -1201,28 +1191,24 @@ where
|
||||
type Ok = ();
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_value(value)
|
||||
}
|
||||
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
&mut self,
|
||||
key: &K,
|
||||
value: &V,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_entry(key, value)
|
||||
}
|
||||
@@ -1243,13 +1229,9 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_entry(key, value)
|
||||
}
|
||||
@@ -1259,6 +1241,52 @@ 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"))]
|
||||
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"))]
|
||||
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
||||
map: &'a mut M,
|
||||
@@ -1288,23 +1316,47 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
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));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
try!(self
|
||||
tri!(self
|
||||
.map
|
||||
.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AdjacentlyTaggedEnumVariant {
|
||||
pub enum_name: &'static str,
|
||||
pub variant_index: u32,
|
||||
pub variant_name: &'static str,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-18
@@ -1,5 +1,5 @@
|
||||
use lib::*;
|
||||
use ser::{Error, Impossible, Serialize, Serializer};
|
||||
use crate::lib::*;
|
||||
use crate::ser::{Error, Impossible, Serialize, Serializer};
|
||||
|
||||
impl Error for fmt::Error {
|
||||
fn custom<T: Display>(_msg: T) -> Self {
|
||||
@@ -35,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 Error = fmt::Error;
|
||||
type SerializeSeq = Impossible<(), fmt::Error>;
|
||||
@@ -52,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
serialize_i16: i16,
|
||||
serialize_i32: i32,
|
||||
serialize_i64: i64,
|
||||
serialize_i128: i128,
|
||||
serialize_u8: u8,
|
||||
serialize_u16: u16,
|
||||
serialize_u32: u32,
|
||||
serialize_u64: u64,
|
||||
serialize_u128: u128,
|
||||
serialize_f32: f32,
|
||||
serialize_f64: f64,
|
||||
serialize_char: char,
|
||||
@@ -63,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
serialize_unit_struct: &'static str,
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
fmt_primitives! {
|
||||
serialize_i128: i128,
|
||||
serialize_u128: u128,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
@@ -79,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Serialize::serialize(value, self)
|
||||
}
|
||||
@@ -94,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
|
||||
fn serialize_some<T>(self, _value: &T) -> fmt::Result
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(fmt::Error)
|
||||
}
|
||||
@@ -105,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
@@ -113,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
_value: &T,
|
||||
) -> fmt::Result
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(fmt::Error)
|
||||
}
|
||||
@@ -166,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
|
||||
fn collect_str<T>(self, value: &T) -> fmt::Result
|
||||
where
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
Display::fmt(value, self)
|
||||
}
|
||||
|
||||
+206
-127
@@ -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!(i32, serialize_i32);
|
||||
primitive_impl!(i64, serialize_i64);
|
||||
primitive_impl!(i128, serialize_i128);
|
||||
primitive_impl!(usize, serialize_u64 as u64);
|
||||
primitive_impl!(u8, serialize_u8);
|
||||
primitive_impl!(u16, serialize_u16);
|
||||
primitive_impl!(u32, serialize_u32);
|
||||
primitive_impl!(u64, serialize_u64);
|
||||
primitive_impl!(u128, serialize_u128);
|
||||
primitive_impl!(f32, serialize_f32);
|
||||
primitive_impl!(f64, serialize_f64);
|
||||
primitive_impl!(char, serialize_char);
|
||||
|
||||
serde_if_integer128! {
|
||||
primitive_impl!(i128, serialize_i128);
|
||||
primitive_impl!(u128, serialize_u128);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl Serialize for str {
|
||||
@@ -51,6 +48,7 @@ impl Serialize for str {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl Serialize for String {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -73,6 +71,7 @@ impl<'a> Serialize for fmt::Arguments<'a> {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_cstr)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for CStr {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -84,6 +83,7 @@ impl Serialize for CStr {
|
||||
}
|
||||
|
||||
#[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 {
|
||||
#[inline]
|
||||
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]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -133,7 +136,7 @@ impl<T> Serialize for [T; 0] {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
try!(serializer.serialize_tuple(0)).end()
|
||||
tri!(serializer.serialize_tuple(0)).end()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,9 +152,9 @@ macro_rules! array_impls {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut seq = try!(serializer.serialize_tuple($len));
|
||||
let mut seq = tri!(serializer.serialize_tuple($len));
|
||||
for e in self {
|
||||
try!(seq.serialize_element(e));
|
||||
tri!(seq.serialize_element(e));
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
@@ -182,9 +185,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
macro_rules! seq_impl {
|
||||
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||
where
|
||||
T: Serialize,
|
||||
@@ -200,9 +207,13 @@ macro_rules! seq_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
macro_rules! seq_impl {
|
||||
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||
where
|
||||
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
||||
@@ -219,23 +230,41 @@ macro_rules! seq_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BinaryHeap<T: Ord>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BinaryHeap<T: Ord>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BTreeSet<T: Ord>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BTreeSet<T: Ord>
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
||||
seq_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
HashSet<T: Eq + Hash, H: BuildHasher>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(LinkedList<T>);
|
||||
seq_impl! {
|
||||
#[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!(Vec<T>);
|
||||
seq_impl! {
|
||||
#[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!(VecDeque<T>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
VecDeque<T>
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -248,9 +277,9 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("Range", 2));
|
||||
try!(state.serialize_field("start", &self.start));
|
||||
try!(state.serialize_field("end", &self.end));
|
||||
let mut state = tri!(serializer.serialize_struct("Range", 2));
|
||||
tri!(state.serialize_field("start", &self.start));
|
||||
tri!(state.serialize_field("end", &self.end));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
@@ -266,15 +295,14 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("RangeFrom", 1));
|
||||
try!(state.serialize_field("start", &self.start));
|
||||
let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
|
||||
tri!(state.serialize_field("start", &self.start));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(not(no_range_inclusive))]
|
||||
impl<Idx> Serialize for RangeInclusive<Idx>
|
||||
where
|
||||
Idx: Serialize,
|
||||
@@ -284,9 +312,9 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
|
||||
try!(state.serialize_field("start", &self.start()));
|
||||
try!(state.serialize_field("end", &self.end()));
|
||||
let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2));
|
||||
tri!(state.serialize_field("start", &self.start()));
|
||||
tri!(state.serialize_field("end", &self.end()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
@@ -302,15 +330,14 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("RangeTo", 1));
|
||||
try!(state.serialize_field("end", &self.end));
|
||||
let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
|
||||
tri!(state.serialize_field("end", &self.end));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
|
||||
impl<T> Serialize for Bound<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@@ -344,6 +371,7 @@ impl Serialize for () {
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
impl Serialize for ! {
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -358,28 +386,46 @@ impl Serialize for ! {
|
||||
macro_rules! tuple_impls {
|
||||
($($len:expr => ($($n:tt $name:ident)+))+) => {
|
||||
$(
|
||||
#[cfg_attr(docsrs, doc(hidden))]
|
||||
impl<$($name),+> Serialize for ($($name,)+)
|
||||
where
|
||||
$($name: Serialize,)+
|
||||
{
|
||||
#[inline]
|
||||
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()
|
||||
}
|
||||
tuple_impl_body!($len => ($($n)+));
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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! {
|
||||
1 => (0 T0)
|
||||
2 => (0 T0 1 T1)
|
||||
3 => (0 T0 1 T1 2 T2)
|
||||
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||
@@ -399,9 +445,13 @@ tuple_impls! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
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)*>
|
||||
where
|
||||
K: Serialize,
|
||||
@@ -418,9 +468,13 @@ macro_rules! map_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
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)*>
|
||||
where
|
||||
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
||||
@@ -438,20 +492,26 @@ macro_rules! map_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
map_impl!(BTreeMap<K: Ord, V>);
|
||||
map_impl! {
|
||||
#[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!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
||||
map_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
HashMap<K: Eq + Hash, V, H: BuildHasher>
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! deref_impl {
|
||||
(
|
||||
$(#[doc = $doc:tt])*
|
||||
$(#[$attr:meta])*
|
||||
<$($desc:tt)+
|
||||
) => {
|
||||
$(#[doc = $doc])*
|
||||
$(#[$attr])*
|
||||
impl <$($desc)+ {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -464,13 +524,20 @@ macro_rules! deref_impl {
|
||||
};
|
||||
}
|
||||
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
||||
deref_impl! {
|
||||
<'a, T> Serialize for &'a T where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
||||
deref_impl! {
|
||||
<'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! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@@ -480,10 +547,11 @@ deref_impl! {
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"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! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@@ -493,11 +561,16 @@ deref_impl! {
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"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!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||
deref_impl! {
|
||||
#[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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -505,9 +578,13 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -521,9 +598,13 @@ where
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -538,7 +619,6 @@ where
|
||||
macro_rules! nonzero_integers {
|
||||
($($T:ident,)+) => {
|
||||
$(
|
||||
#[cfg(not(no_num_nonzero))]
|
||||
impl Serialize for num::$T {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -556,6 +636,7 @@ nonzero_integers! {
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
NonZeroU128,
|
||||
NonZeroUsize,
|
||||
}
|
||||
|
||||
@@ -565,22 +646,10 @@ nonzero_integers! {
|
||||
NonZeroI16,
|
||||
NonZeroI32,
|
||||
NonZeroI64,
|
||||
NonZeroI128,
|
||||
NonZeroIsize,
|
||||
}
|
||||
|
||||
// Currently 128-bit integers do not work on Emscripten targets so we need an
|
||||
// additional `#[cfg]`
|
||||
serde_if_integer128! {
|
||||
nonzero_integers! {
|
||||
NonZeroU128,
|
||||
}
|
||||
|
||||
#[cfg(not(no_num_nonzero_signed))]
|
||||
nonzero_integers! {
|
||||
NonZeroI128,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Serialize for Cell<T>
|
||||
where
|
||||
T: Serialize + Copy,
|
||||
@@ -593,9 +662,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Serialize for RefCell<T>
|
||||
impl<T> Serialize for RefCell<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -609,9 +678,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized> Serialize for Mutex<T>
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<T> Serialize for Mutex<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -625,9 +695,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized> Serialize for RwLock<T>
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<T> Serialize for RwLock<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -662,16 +733,15 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
||||
impl Serialize for Duration {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("Duration", 2));
|
||||
try!(state.serialize_field("secs", &self.as_secs()));
|
||||
try!(state.serialize_field("nanos", &self.subsec_nanos()));
|
||||
let mut state = tri!(serializer.serialize_struct("Duration", 2));
|
||||
tri!(state.serialize_field("secs", &self.as_secs()));
|
||||
tri!(state.serialize_field("nanos", &self.subsec_nanos()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
@@ -679,6 +749,7 @@ impl Serialize for Duration {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for SystemTime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -689,9 +760,9 @@ impl Serialize for SystemTime {
|
||||
Ok(duration_since_epoch) => duration_since_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()));
|
||||
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
||||
let mut state = tri!(serializer.serialize_struct("SystemTime", 2));
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -702,27 +773,17 @@ impl Serialize for SystemTime {
|
||||
/// 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.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! serialize_display_bounded_length {
|
||||
($value:expr, $max:expr, $serializer:expr) => {{
|
||||
let mut buffer = [0u8; $max];
|
||||
let remaining_len = {
|
||||
let mut remaining = &mut buffer[..];
|
||||
write!(remaining, "{}", $value).unwrap();
|
||||
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)
|
||||
let mut writer = crate::format::Buf::new(&mut buffer);
|
||||
write!(&mut writer, "{}", $value).unwrap();
|
||||
$serializer.serialize_str(writer.as_str())
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -746,7 +807,7 @@ impl Serialize for net::IpAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
const DEC_DIGITS_LUT: &[u8] = b"\
|
||||
0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
@@ -754,7 +815,7 @@ const DEC_DIGITS_LUT: &[u8] = b"\
|
||||
6061626364656667686970717273747576777879\
|
||||
8081828384858687888990919293949596979899";
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
#[inline]
|
||||
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||
if n >= 100 {
|
||||
@@ -775,7 +836,7 @@ fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
#[test]
|
||||
fn test_format_u8() {
|
||||
let mut i = 0u8;
|
||||
@@ -792,7 +853,7 @@ fn test_format_u8() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -816,7 +877,7 @@ impl Serialize for net::Ipv4Addr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::Ipv6Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -832,7 +893,7 @@ impl Serialize for net::Ipv6Addr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -856,7 +917,7 @@ impl Serialize for net::SocketAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddrV4 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -872,7 +933,7 @@ impl Serialize for net::SocketAddrV4 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddrV6 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -894,6 +955,7 @@ impl Serialize for net::SocketAddrV6 {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for Path {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -907,6 +969,7 @@ impl Serialize for Path {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for PathBuf {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -917,6 +980,7 @@ impl Serialize for PathBuf {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||
impl Serialize for OsStr {
|
||||
#[cfg(unix)]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -939,6 +1003,7 @@ impl Serialize for OsStr {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||
impl Serialize for OsString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -963,7 +1028,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>
|
||||
where
|
||||
T: Serialize,
|
||||
@@ -984,6 +1062,7 @@ macro_rules! atomic_impl {
|
||||
($($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 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
||||
+26
-26
@@ -1,8 +1,8 @@
|
||||
//! This module contains `Impossible` serializer and its implementations.
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
use ser::{
|
||||
use crate::ser::{
|
||||
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
|
||||
};
|
||||
@@ -49,14 +49,14 @@ use ser::{
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Serializer`]: trait.Serializer.html
|
||||
/// [`SerializeSeq`]: trait.SerializeSeq.html
|
||||
/// [`SerializeTuple`]: trait.SerializeTuple.html
|
||||
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
|
||||
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
|
||||
/// [`SerializeMap`]: trait.SerializeMap.html
|
||||
/// [`SerializeStruct`]: trait.SerializeStruct.html
|
||||
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
|
||||
/// [`Serializer`]: crate::Serializer
|
||||
/// [`SerializeSeq`]: crate::ser::SerializeSeq
|
||||
/// [`SerializeTuple`]: crate::ser::SerializeTuple
|
||||
/// [`SerializeTupleStruct`]: crate::ser::SerializeTupleStruct
|
||||
/// [`SerializeTupleVariant`]: crate::ser::SerializeTupleVariant
|
||||
/// [`SerializeMap`]: crate::ser::SerializeMap
|
||||
/// [`SerializeStruct`]: crate::ser::SerializeStruct
|
||||
/// [`SerializeStructVariant`]: crate::ser::SerializeStructVariant
|
||||
pub struct Impossible<Ok, Error> {
|
||||
void: Void,
|
||||
ok: PhantomData<Ok>,
|
||||
@@ -72,9 +72,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -92,9 +92,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -112,9 +112,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -132,9 +132,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -152,17 +152,17 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -180,9 +180,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
@@ -201,9 +201,9 @@ where
|
||||
type Ok = Ok;
|
||||
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
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
|
||||
+112
-143
@@ -61,8 +61,8 @@
|
||||
//! - RefCell\<T\>
|
||||
//! - Mutex\<T\>
|
||||
//! - RwLock\<T\>
|
||||
//! - Rc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Rc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - **Collection types**:
|
||||
//! - BTreeMap\<K, V\>
|
||||
//! - BTreeSet\<T\>
|
||||
@@ -97,8 +97,8 @@
|
||||
//!
|
||||
//! [Implementing `Serialize`]: https://serde.rs/impl-serialize.html
|
||||
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
||||
//! [`Serialize`]: ../trait.Serialize.html
|
||||
//! [`Serializer`]: ../trait.Serializer.html
|
||||
//! [`Serialize`]: crate::Serialize
|
||||
//! [`Serializer`]: crate::Serializer
|
||||
//! [`postcard`]: https://github.com/jamesmunns/postcard
|
||||
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
||||
//! [`serde_derive`]: https://crates.io/crates/serde_derive
|
||||
@@ -107,7 +107,7 @@
|
||||
//! [derive section of the manual]: https://serde.rs/derive.html
|
||||
//! [data formats]: https://serde.rs/#data-formats
|
||||
|
||||
use lib::*;
|
||||
use crate::lib::*;
|
||||
|
||||
mod fmt;
|
||||
mod impls;
|
||||
@@ -115,15 +115,15 @@ mod impossible;
|
||||
|
||||
pub use self::impossible::Impossible;
|
||||
|
||||
#[cfg(all(feature = "unstable", not(feature = "std")))]
|
||||
#[doc(inline)]
|
||||
#[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")]
|
||||
#[doc(no_inline)]
|
||||
pub use std::error::Error as StdError;
|
||||
#[cfg(not(any(feature = "std", feature = "unstable")))]
|
||||
#[doc(no_inline)]
|
||||
pub use std_error::Error as StdError;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -173,8 +173,8 @@ macro_rules! declare_error_trait {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
|
||||
/// [`Serialize`]: ../trait.Serialize.html
|
||||
/// [`Path`]: std::path::Path
|
||||
/// [`Serialize`]: crate::Serialize
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display;
|
||||
@@ -215,6 +215,13 @@ declare_error_trait!(Error: Sized + Debug + Display);
|
||||
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
||||
/// [`serde_derive`]: https://crates.io/crates/serde_derive
|
||||
/// [derive section of the manual]: https://serde.rs/derive.html
|
||||
#[cfg_attr(
|
||||
not(no_diagnostic_namespace),
|
||||
diagnostic::on_unimplemented(
|
||||
note = "for local types consider adding `#[derive(serde::Serialize)]` to your `{Self}` type",
|
||||
note = "for types from other crates check whether the crate offers a `serde` feature flag",
|
||||
)
|
||||
)]
|
||||
pub trait Serialize {
|
||||
/// Serialize this value into the given Serde serializer.
|
||||
///
|
||||
@@ -338,7 +345,7 @@ pub trait Serializer: Sized {
|
||||
/// in-memory data structures may be simplified by using `Ok` to propagate
|
||||
/// the data structure around.
|
||||
///
|
||||
/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
|
||||
/// [`io::Write`]: std::io::Write
|
||||
type Ok;
|
||||
|
||||
/// The error type when some error occurs during serialization.
|
||||
@@ -488,30 +495,27 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Serialize an `i128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for i128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
/// Serialize an `i128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for i128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
|
||||
/// Serialize a `u8` value.
|
||||
@@ -598,30 +602,27 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Serialize a `u128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for u128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
/// Serialize a `u128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for u128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
|
||||
/// Serialize an `f32` value.
|
||||
@@ -768,7 +769,7 @@ pub trait Serializer: Sized {
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
|
||||
/// [`None`]: core::option::Option::None
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a [`Some(T)`] value.
|
||||
@@ -801,10 +802,10 @@ pub trait Serializer: Sized {
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
|
||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
/// [`Some(T)`]: core::option::Option::Some
|
||||
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a `()` value.
|
||||
///
|
||||
@@ -897,13 +898,13 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
fn serialize_newtype_struct<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
|
||||
///
|
||||
@@ -931,7 +932,7 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
@@ -939,7 +940,7 @@ pub trait Serializer: Sized {
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Begin to serialize a variably sized sequence. This call must be
|
||||
/// followed by zero or more calls to `serialize_element`, then a call to
|
||||
@@ -1176,7 +1177,8 @@ pub trait Serializer: Sized {
|
||||
/// then a call to `end`.
|
||||
///
|
||||
/// The `name` is the name of the struct and the `len` is the number of
|
||||
/// data fields that will be serialized.
|
||||
/// data fields that will be serialized. `len` does not include fields
|
||||
/// which are skipped with [`SerializeStruct::skip_field`].
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
@@ -1213,6 +1215,8 @@ pub trait Serializer: Sized {
|
||||
/// The `name` is the name of the enum, the `variant_index` is the index of
|
||||
/// this variant within the enum, the `variant` is the name of the variant,
|
||||
/// and the `len` is the number of data fields that will be serialized.
|
||||
/// `len` does not include fields which are skipped with
|
||||
/// [`SerializeStructVariant::skip_field`].
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
|
||||
@@ -1279,22 +1283,9 @@ pub trait Serializer: Sized {
|
||||
I: IntoIterator,
|
||||
<I as IntoIterator>::Item: Serialize,
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
|
||||
|
||||
#[cfg(not(no_iterator_try_fold))]
|
||||
{
|
||||
let mut iter = iter;
|
||||
try!(iter.try_for_each(|item| serializer.serialize_element(&item)));
|
||||
}
|
||||
|
||||
#[cfg(no_iterator_try_fold)]
|
||||
{
|
||||
for item in iter {
|
||||
try!(serializer.serialize_element(&item));
|
||||
}
|
||||
}
|
||||
|
||||
let mut iter = iter.into_iter();
|
||||
let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter)));
|
||||
tri!(iter.try_for_each(|item| serializer.serialize_element(&item)));
|
||||
serializer.end()
|
||||
}
|
||||
|
||||
@@ -1330,22 +1321,9 @@ pub trait Serializer: Sized {
|
||||
V: Serialize,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
|
||||
|
||||
#[cfg(not(no_iterator_try_fold))]
|
||||
{
|
||||
let mut iter = iter;
|
||||
try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
|
||||
}
|
||||
|
||||
#[cfg(no_iterator_try_fold)]
|
||||
{
|
||||
for (key, value) in iter {
|
||||
try!(serializer.serialize_entry(&key, &value));
|
||||
}
|
||||
}
|
||||
|
||||
let mut iter = iter.into_iter();
|
||||
let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter)));
|
||||
tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
|
||||
serializer.end()
|
||||
}
|
||||
|
||||
@@ -1375,12 +1353,11 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
|
||||
/// [`serialize_str`]: #tymethod.serialize_str
|
||||
/// [`serialize_str`]: Self::serialize_str
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
self.serialize_str(&value.to_string())
|
||||
}
|
||||
@@ -1411,9 +1388,9 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display;
|
||||
T: ?Sized + Display;
|
||||
|
||||
/// Determine whether `Serialize` implementations should serialize in
|
||||
/// human-readable form.
|
||||
@@ -1525,9 +1502,9 @@ pub trait SerializeSeq {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a sequence element.
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a sequence.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1625,9 +1602,9 @@ pub trait SerializeTuple {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple element.
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1670,9 +1647,9 @@ pub trait SerializeTupleStruct {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple struct field.
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple struct.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1728,9 +1705,9 @@ pub trait SerializeTupleVariant {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple variant field.
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple variant.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1799,9 +1776,9 @@ pub trait SerializeMap {
|
||||
/// `serialize_entry` instead as it may be implemented more efficiently in
|
||||
/// some formats compared to a pair of calls to `serialize_key` and
|
||||
/// `serialize_value`.
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a map value.
|
||||
///
|
||||
@@ -1809,9 +1786,9 @@ pub trait SerializeMap {
|
||||
///
|
||||
/// Calling `serialize_value` before `serialize_key` is incorrect and is
|
||||
/// allowed to panic or produce bogus results.
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a map entry consisting of a key and a value.
|
||||
///
|
||||
@@ -1827,19 +1804,15 @@ pub trait SerializeMap {
|
||||
/// care about performance or are not able to optimize `serialize_entry` any
|
||||
/// better than this.
|
||||
///
|
||||
/// [`Serialize`]: ../trait.Serialize.html
|
||||
/// [`serialize_key`]: #tymethod.serialize_key
|
||||
/// [`serialize_value`]: #tymethod.serialize_value
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
&mut self,
|
||||
key: &K,
|
||||
value: &V,
|
||||
) -> Result<(), Self::Error>
|
||||
/// [`Serialize`]: crate::Serialize
|
||||
/// [`serialize_key`]: Self::serialize_key
|
||||
/// [`serialize_value`]: Self::serialize_value
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
try!(self.serialize_key(key));
|
||||
tri!(self.serialize_key(key));
|
||||
self.serialize_value(value)
|
||||
}
|
||||
|
||||
@@ -1888,15 +1861,13 @@ pub trait SerializeStruct {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a struct field.
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Indicate that a struct field has been skipped.
|
||||
///
|
||||
/// The default implementation does nothing.
|
||||
#[inline]
|
||||
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
|
||||
let _ = key;
|
||||
@@ -1954,15 +1925,13 @@ pub trait SerializeStructVariant {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a struct variant field.
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Indicate that a struct variant field has been skipped.
|
||||
///
|
||||
/// The default implementation does nothing.
|
||||
#[inline]
|
||||
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
|
||||
let _ = key;
|
||||
|
||||
@@ -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
|
||||
/// on whether Serde's "std" feature is enabled.
|
||||
|
||||
+14
-6
@@ -1,16 +1,18 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.177" # remember to update html_root_url
|
||||
version = "1.0.219"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
edition = "2015"
|
||||
exclude = ["build.rs"]
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.61"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
@@ -21,13 +23,19 @@ name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "2.0.25"
|
||||
proc-macro2 = { workspace = true, features = ["proc-macro"] }
|
||||
quote = { workspace = true, features = ["proc-macro"] }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", path = "../serde" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--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",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
// Warning: build.rs is not published to crates.io.
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rustc-cfg=check_cfg");
|
||||
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
|
||||
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
|
||||
}
|
||||
@@ -144,6 +144,7 @@ pub fn with_bound(
|
||||
|
||||
fn visit_type(&mut self, ty: &'ast syn::Type) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::Type::Array(ty) => self.visit_type(&ty.elem),
|
||||
syn::Type::BareFn(ty) => {
|
||||
for arg in &ty.inputs {
|
||||
@@ -181,7 +182,6 @@ pub fn with_bound(
|
||||
|
||||
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -196,16 +196,13 @@ pub fn with_bound(
|
||||
syn::PathArguments::AngleBracketed(arguments) => {
|
||||
for arg in &arguments.args {
|
||||
match arg {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::GenericArgument::Type(arg) => self.visit_type(arg),
|
||||
syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty),
|
||||
syn::GenericArgument::Lifetime(_)
|
||||
| syn::GenericArgument::Const(_)
|
||||
| syn::GenericArgument::AssocConst(_)
|
||||
| syn::GenericArgument::Constraint(_) => {}
|
||||
#[cfg_attr(
|
||||
all(test, exhaustive),
|
||||
deny(non_exhaustive_omitted_patterns)
|
||||
)]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -228,9 +225,11 @@ pub fn with_bound(
|
||||
|
||||
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
|
||||
match bound {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
|
||||
syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::TypeParamBound::Lifetime(_)
|
||||
| syn::TypeParamBound::PreciseCapture(_)
|
||||
| syn::TypeParamBound::Verbatim(_) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
+395
-346
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,7 @@
|
||||
use crate::try;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream {
|
||||
let try_replacement = try::replacement();
|
||||
|
||||
let use_serde = match serde_path {
|
||||
Some(path) => quote! {
|
||||
use #path as _serde;
|
||||
@@ -17,10 +14,14 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token
|
||||
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
#[allow(
|
||||
non_upper_case_globals,
|
||||
unused_attributes,
|
||||
unused_qualifications,
|
||||
clippy::absolute_paths,
|
||||
)]
|
||||
const _: () = {
|
||||
#use_serde
|
||||
#try_replacement
|
||||
#code
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<'a> Container<'a> {
|
||||
item: &'a syn::DeriveInput,
|
||||
derive: Derive,
|
||||
) -> 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 {
|
||||
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
|
||||
@@ -77,15 +77,11 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let mut has_flatten = false;
|
||||
match &mut data {
|
||||
Data::Enum(variants) => {
|
||||
for variant in variants {
|
||||
variant.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||
for field in &mut variant.fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rules(
|
||||
variant
|
||||
.attrs
|
||||
@@ -97,18 +93,11 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
Data::Struct(_, fields) => {
|
||||
for field in fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_flatten {
|
||||
attrs.mark_has_flatten();
|
||||
}
|
||||
|
||||
let mut item = Container {
|
||||
ident: item.ident.clone(),
|
||||
attrs,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::internals::name::{MultiName, Name};
|
||||
use crate::internals::symbol::*;
|
||||
use crate::internals::{ungroup, Ctxt};
|
||||
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
|
||||
@@ -8,6 +9,7 @@ use std::iter::FromIterator;
|
||||
use syn::meta::ParseNestedMeta;
|
||||
use syn::parse::ParseStream;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_quote, token, Ident, Lifetime, Token};
|
||||
|
||||
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
||||
@@ -20,7 +22,7 @@ use syn::{parse_quote, token, Ident, Lifetime, Token};
|
||||
|
||||
pub use crate::internals::case::RenameRule;
|
||||
|
||||
struct Attr<'c, T> {
|
||||
pub(crate) struct Attr<'c, T> {
|
||||
cx: &'c Ctxt,
|
||||
name: Symbol,
|
||||
tokens: TokenStream,
|
||||
@@ -61,7 +63,7 @@ impl<'c, T> Attr<'c, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get(self) -> Option<T> {
|
||||
pub(crate) fn get(self) -> Option<T> {
|
||||
self.value
|
||||
}
|
||||
|
||||
@@ -89,7 +91,7 @@ impl<'c> BoolAttr<'c> {
|
||||
}
|
||||
}
|
||||
|
||||
struct VecAttr<'c, T> {
|
||||
pub(crate) struct VecAttr<'c, T> {
|
||||
cx: &'c Ctxt,
|
||||
name: Symbol,
|
||||
first_dup_tokens: TokenStream,
|
||||
@@ -124,78 +126,19 @@ impl<'c, T> VecAttr<'c, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get(self) -> Vec<T> {
|
||||
pub(crate) fn get(self) -> Vec<T> {
|
||||
self.values
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Name {
|
||||
serialize: String,
|
||||
serialize_renamed: bool,
|
||||
deserialize: String,
|
||||
deserialize_renamed: bool,
|
||||
deserialize_aliases: Vec<String>,
|
||||
}
|
||||
|
||||
fn unraw(ident: &Ident) -> String {
|
||||
ident.to_string().trim_start_matches("r#").to_owned()
|
||||
}
|
||||
|
||||
impl Name {
|
||||
fn from_attrs(
|
||||
source_name: String,
|
||||
ser_name: Attr<String>,
|
||||
de_name: Attr<String>,
|
||||
de_aliases: Option<VecAttr<String>>,
|
||||
) -> Name {
|
||||
let deserialize_aliases = match de_aliases {
|
||||
Some(de_aliases) => {
|
||||
let mut alias_list = BTreeSet::new();
|
||||
for alias_name in de_aliases.get() {
|
||||
alias_list.insert(alias_name);
|
||||
}
|
||||
alias_list.into_iter().collect()
|
||||
}
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
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();
|
||||
Name {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the container name for the container when serializing.
|
||||
pub fn serialize_name(&self) -> String {
|
||||
self.serialize.clone()
|
||||
}
|
||||
|
||||
/// Return the container name for the container when deserializing.
|
||||
pub fn deserialize_name(&self) -> String {
|
||||
self.deserialize.clone()
|
||||
}
|
||||
|
||||
fn deserialize_aliases(&self) -> Vec<String> {
|
||||
let mut aliases = self.deserialize_aliases.clone();
|
||||
let main_name = self.deserialize_name();
|
||||
if !aliases.contains(&main_name) {
|
||||
aliases.push(main_name);
|
||||
}
|
||||
aliases
|
||||
}
|
||||
fn unraw(ident: &Ident) -> Ident {
|
||||
Ident::new(ident.to_string().trim_start_matches("r#"), ident.span())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct RenameAllRules {
|
||||
serialize: RenameRule,
|
||||
deserialize: RenameRule,
|
||||
pub serialize: RenameRule,
|
||||
pub deserialize: RenameRule,
|
||||
}
|
||||
|
||||
impl RenameAllRules {
|
||||
@@ -211,7 +154,7 @@ impl RenameAllRules {
|
||||
|
||||
/// Represents struct or enum attribute information.
|
||||
pub struct Container {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
transparent: bool,
|
||||
deny_unknown_fields: bool,
|
||||
default: Default,
|
||||
@@ -225,11 +168,11 @@ pub struct Container {
|
||||
type_into: Option<syn::Type>,
|
||||
remote: Option<syn::Path>,
|
||||
identifier: Identifier,
|
||||
has_flatten: bool,
|
||||
serde_path: Option<syn::Path>,
|
||||
is_packed: bool,
|
||||
/// Error message generated when type can't be deserialized
|
||||
expecting: Option<String>,
|
||||
non_exhaustive: bool,
|
||||
}
|
||||
|
||||
/// Styles of representing an enum.
|
||||
@@ -315,9 +258,12 @@ impl Container {
|
||||
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
||||
let mut serde_path = Attr::none(cx, CRATE);
|
||||
let mut expecting = Attr::none(cx, EXPECTING);
|
||||
let mut non_exhaustive = false;
|
||||
|
||||
for attr in &item.attrs {
|
||||
if attr.path() != SERDE {
|
||||
non_exhaustive |=
|
||||
matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -332,8 +278,8 @@ impl Container {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_renames(cx, RENAME, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
de_name.set_opt(&meta.path, de.as_ref().map(Name::from));
|
||||
} else if meta.path == RENAME_ALL {
|
||||
// #[serde(rename_all = "foo")]
|
||||
// #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
|
||||
@@ -405,20 +351,20 @@ impl Container {
|
||||
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
|
||||
match &item.data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||
syn::Fields::Named(_) => {
|
||||
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
|
||||
default.set(&meta.path, Default::Path(path));
|
||||
}
|
||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
||||
syn::Fields::Unit => {
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
|
||||
cx.syn_error(meta.error(msg));
|
||||
}
|
||||
},
|
||||
syn::Data::Enum(_) => {
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs";
|
||||
cx.syn_error(meta.error(msg));
|
||||
}
|
||||
syn::Data::Union(_) => {
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
||||
let msg = "#[serde(default = \"...\")] can only be used on structs";
|
||||
cx.syn_error(meta.error(msg));
|
||||
}
|
||||
}
|
||||
@@ -427,20 +373,20 @@ impl Container {
|
||||
// #[serde(default)]
|
||||
match &item.data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||
syn::Fields::Named(_) => {
|
||||
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
|
||||
default.set(meta.path, Default::Default);
|
||||
}
|
||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
|
||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
||||
syn::Fields::Unit => {
|
||||
let msg = "#[serde(default)] can only be used on structs that have fields";
|
||||
cx.error_spanned_by(fields, msg);
|
||||
}
|
||||
},
|
||||
syn::Data::Enum(_) => {
|
||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
||||
let msg = "#[serde(default)] can only be used on structs";
|
||||
cx.syn_error(meta.error(msg));
|
||||
}
|
||||
syn::Data::Union(_) => {
|
||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
||||
let msg = "#[serde(default)] can only be used on structs";
|
||||
cx.syn_error(meta.error(msg));
|
||||
}
|
||||
}
|
||||
@@ -572,7 +518,7 @@ impl Container {
|
||||
}
|
||||
|
||||
Container {
|
||||
name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
|
||||
name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None),
|
||||
transparent: transparent.get(),
|
||||
deny_unknown_fields: deny_unknown_fields.get(),
|
||||
default: default.get().unwrap_or(Default::None),
|
||||
@@ -592,14 +538,14 @@ impl Container {
|
||||
type_into: type_into.get(),
|
||||
remote: remote.get(),
|
||||
identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
|
||||
has_flatten: false,
|
||||
serde_path: serde_path.get(),
|
||||
is_packed,
|
||||
expecting: expecting.get(),
|
||||
non_exhaustive,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
@@ -659,14 +605,6 @@ impl Container {
|
||||
self.identifier
|
||||
}
|
||||
|
||||
pub fn has_flatten(&self) -> bool {
|
||||
self.has_flatten
|
||||
}
|
||||
|
||||
pub fn mark_has_flatten(&mut self) {
|
||||
self.has_flatten = true;
|
||||
}
|
||||
|
||||
pub fn custom_serde_path(&self) -> Option<&syn::Path> {
|
||||
self.serde_path.as_ref()
|
||||
}
|
||||
@@ -681,6 +619,10 @@ impl Container {
|
||||
pub fn expecting(&self) -> Option<&str> {
|
||||
self.expecting.as_ref().map(String::as_ref)
|
||||
}
|
||||
|
||||
pub fn non_exhaustive(&self) -> bool {
|
||||
self.non_exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
fn decide_tag(
|
||||
@@ -716,7 +658,7 @@ fn decide_tag(
|
||||
}
|
||||
TagType::Internal { tag }
|
||||
}
|
||||
(Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
|
||||
(Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => {
|
||||
let msg = "enum cannot be both untagged and internally tagged";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(tag_tokens, msg);
|
||||
@@ -727,14 +669,14 @@ fn decide_tag(
|
||||
cx.error_spanned_by(content_tokens, msg);
|
||||
TagType::External
|
||||
}
|
||||
(Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
|
||||
(Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
|
||||
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(content_tokens, msg);
|
||||
TagType::External
|
||||
}
|
||||
(None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
|
||||
(Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => {
|
||||
(Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => {
|
||||
let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(tag_tokens, msg);
|
||||
@@ -756,7 +698,7 @@ fn decide_identifier(
|
||||
variant_identifier.0.get_with_tokens(),
|
||||
) {
|
||||
(_, None, None) => Identifier::No,
|
||||
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
|
||||
(_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
|
||||
let msg =
|
||||
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
|
||||
cx.error_spanned_by(field_identifier_tokens, msg);
|
||||
@@ -790,7 +732,7 @@ fn decide_identifier(
|
||||
|
||||
/// Represents variant attribute information
|
||||
pub struct Variant {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
rename_all_rules: RenameAllRules,
|
||||
ser_bound: Option<Vec<syn::WherePredicate>>,
|
||||
de_bound: Option<Vec<syn::WherePredicate>>,
|
||||
@@ -841,15 +783,15 @@ impl Variant {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
for de_value in de {
|
||||
de_name.set_if_none(de_value.value());
|
||||
de_aliases.insert(&meta.path, de_value.value());
|
||||
de_name.set_if_none(Name::from(&de_value));
|
||||
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||
}
|
||||
} else if meta.path == ALIAS {
|
||||
// #[serde(alias = "foo")]
|
||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||
de_aliases.insert(&meta.path, s.value());
|
||||
de_aliases.insert(&meta.path, Name::from(&s));
|
||||
}
|
||||
} else if meta.path == RENAME_ALL {
|
||||
// #[serde(rename_all = "foo")]
|
||||
@@ -898,13 +840,13 @@ impl Variant {
|
||||
ser_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("serialize", Span::call_site()).into());
|
||||
.push(Ident::new("serialize", ser_path.span()).into());
|
||||
serialize_with.set(&meta.path, ser_path);
|
||||
let mut de_path = path;
|
||||
de_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("deserialize", Span::call_site()).into());
|
||||
.push(Ident::new("deserialize", de_path.span()).into());
|
||||
deserialize_with.set(&meta.path, de_path);
|
||||
}
|
||||
} else if meta.path == SERIALIZE_WITH {
|
||||
@@ -956,7 +898,12 @@ impl Variant {
|
||||
}
|
||||
|
||||
Variant {
|
||||
name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)),
|
||||
name: MultiName::from_attrs(
|
||||
Name::from(&unraw(&variant.ident)),
|
||||
ser_name,
|
||||
de_name,
|
||||
Some(de_aliases),
|
||||
),
|
||||
rename_all_rules: RenameAllRules {
|
||||
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
|
||||
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
|
||||
@@ -973,21 +920,27 @@ impl Variant {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn aliases(&self) -> Vec<String> {
|
||||
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||
self.name.deserialize_aliases()
|
||||
}
|
||||
|
||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||
if !self.name.serialize_renamed {
|
||||
self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
|
||||
self.name.serialize.value =
|
||||
rules.serialize.apply_to_variant(&self.name.serialize.value);
|
||||
}
|
||||
if !self.name.deserialize_renamed {
|
||||
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
|
||||
self.name.deserialize.value = rules
|
||||
.deserialize
|
||||
.apply_to_variant(&self.name.deserialize.value);
|
||||
}
|
||||
self.name
|
||||
.deserialize_aliases
|
||||
.insert(self.name.deserialize.clone());
|
||||
}
|
||||
|
||||
pub fn rename_all_rules(&self) -> RenameAllRules {
|
||||
@@ -1029,7 +982,7 @@ impl Variant {
|
||||
|
||||
/// Represents field attribute information
|
||||
pub struct Field {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
skip_serializing: bool,
|
||||
skip_deserializing: bool,
|
||||
skip_serializing_if: Option<syn::ExprPath>,
|
||||
@@ -1088,8 +1041,11 @@ impl Field {
|
||||
let mut flatten = BoolAttr::none(cx, FLATTEN);
|
||||
|
||||
let ident = match &field.ident {
|
||||
Some(ident) => unraw(ident),
|
||||
None => index.to_string(),
|
||||
Some(ident) => Name::from(&unraw(ident)),
|
||||
None => Name {
|
||||
value: index.to_string(),
|
||||
span: Span::call_site(),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
|
||||
@@ -1125,15 +1081,15 @@ impl Field {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
for de_value in de {
|
||||
de_name.set_if_none(de_value.value());
|
||||
de_aliases.insert(&meta.path, de_value.value());
|
||||
de_name.set_if_none(Name::from(&de_value));
|
||||
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||
}
|
||||
} else if meta.path == ALIAS {
|
||||
// #[serde(alias = "foo")]
|
||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||
de_aliases.insert(&meta.path, s.value());
|
||||
de_aliases.insert(&meta.path, Name::from(&s));
|
||||
}
|
||||
} else if meta.path == DEFAULT {
|
||||
if meta.input.peek(Token![=]) {
|
||||
@@ -1177,13 +1133,13 @@ impl Field {
|
||||
ser_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("serialize", Span::call_site()).into());
|
||||
.push(Ident::new("serialize", ser_path.span()).into());
|
||||
serialize_with.set(&meta.path, ser_path);
|
||||
let mut de_path = path;
|
||||
de_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("deserialize", Span::call_site()).into());
|
||||
.push(Ident::new("deserialize", de_path.span()).into());
|
||||
deserialize_with.set(&meta.path, de_path);
|
||||
}
|
||||
} else if meta.path == BOUND {
|
||||
@@ -1296,7 +1252,7 @@ impl Field {
|
||||
}
|
||||
|
||||
Field {
|
||||
name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
|
||||
name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
|
||||
skip_serializing: skip_serializing.get(),
|
||||
skip_deserializing: skip_deserializing.get(),
|
||||
skip_serializing_if: skip_serializing_if.get(),
|
||||
@@ -1312,21 +1268,26 @@ impl Field {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn aliases(&self) -> Vec<String> {
|
||||
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||
self.name.deserialize_aliases()
|
||||
}
|
||||
|
||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||
if !self.name.serialize_renamed {
|
||||
self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
|
||||
self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value);
|
||||
}
|
||||
if !self.name.deserialize_renamed {
|
||||
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
|
||||
self.name.deserialize.value = rules
|
||||
.deserialize
|
||||
.apply_to_field(&self.name.deserialize.value);
|
||||
}
|
||||
self.name
|
||||
.deserialize_aliases
|
||||
.insert(self.name.deserialize.clone());
|
||||
}
|
||||
|
||||
pub fn skip_serializing(&self) -> bool {
|
||||
@@ -1772,7 +1733,7 @@ fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
|
||||
// attribute on the field so there must be at least one borrowable lifetime.
|
||||
fn borrowable_lifetimes(
|
||||
cx: &Ctxt,
|
||||
name: &str,
|
||||
name: &Name,
|
||||
field: &syn::Field,
|
||||
) -> Result<BTreeSet<syn::Lifetime>, ()> {
|
||||
let mut lifetimes = BTreeSet::new();
|
||||
@@ -1788,6 +1749,7 @@ fn borrowable_lifetimes(
|
||||
|
||||
fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::Type::Slice(ty) => {
|
||||
collect_lifetimes(&ty.elem, out);
|
||||
}
|
||||
@@ -1823,7 +1785,10 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
syn::GenericArgument::AssocType(binding) => {
|
||||
collect_lifetimes(&binding.ty, out);
|
||||
}
|
||||
_ => {}
|
||||
syn::GenericArgument::Const(_)
|
||||
| syn::GenericArgument::AssocConst(_)
|
||||
| syn::GenericArgument::Constraint(_)
|
||||
| _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1845,7 +1810,6 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
| syn::Type::Infer(_)
|
||||
| syn::Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::internals::ast::{Container, Data, Field, Style};
|
||||
use crate::internals::attr::{Identifier, TagType};
|
||||
use crate::internals::attr::{Default, Identifier, TagType};
|
||||
use crate::internals::{ungroup, Ctxt, Derive};
|
||||
use syn::{Member, Type};
|
||||
|
||||
// Cross-cutting checks that require looking at more than a single attrs object.
|
||||
// Simpler checks should happen when parsing and building the attrs.
|
||||
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_flatten(cx, cont);
|
||||
@@ -17,6 +18,39 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||
check_from_and_try_from(cx, cont);
|
||||
}
|
||||
|
||||
// If some field of a tuple struct is marked #[serde(default)] then all fields
|
||||
// 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:
|
||||
//
|
||||
@@ -284,6 +318,9 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
||||
for variant in variants {
|
||||
match variant.style {
|
||||
Style::Struct => {
|
||||
if variant.attrs.untagged() {
|
||||
continue;
|
||||
}
|
||||
for field in &variant.fields {
|
||||
let check_ser =
|
||||
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
|
||||
@@ -292,13 +329,13 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
||||
let name = field.attrs.name();
|
||||
let ser_name = name.serialize_name();
|
||||
|
||||
if check_ser && ser_name == tag {
|
||||
if check_ser && ser_name.value == tag {
|
||||
diagnose_conflict();
|
||||
return;
|
||||
}
|
||||
|
||||
for de_name in field.attrs.aliases() {
|
||||
if check_de && de_name == tag {
|
||||
if check_de && de_name.value == tag {
|
||||
diagnose_conflict();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod ast;
|
||||
pub mod attr;
|
||||
pub mod name;
|
||||
|
||||
mod case;
|
||||
mod check;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ use crate::internals::respan::respan;
|
||||
use proc_macro2::Span;
|
||||
use quote::ToTokens;
|
||||
use std::mem;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{
|
||||
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
|
||||
Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
|
||||
@@ -49,7 +48,7 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -84,7 +83,7 @@ impl ReplaceReceiver<'_> {
|
||||
self.visit_type_mut_impl(ty);
|
||||
return;
|
||||
};
|
||||
*ty = self.self_ty(span).into();
|
||||
*ty = Type::Path(self.self_ty(span));
|
||||
}
|
||||
|
||||
// `Self::Assoc` -> `<Receiver>::Assoc`
|
||||
@@ -107,6 +106,7 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
Type::Array(ty) => {
|
||||
self.visit_type_mut(&mut ty.elem);
|
||||
self.visit_expr_mut(&mut ty.len);
|
||||
@@ -147,7 +147,6 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -178,13 +177,13 @@ impl ReplaceReceiver<'_> {
|
||||
PathArguments::AngleBracketed(arguments) => {
|
||||
for arg in &mut arguments.args {
|
||||
match arg {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
GenericArgument::Type(arg) => self.visit_type_mut(arg),
|
||||
GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
|
||||
GenericArgument::Lifetime(_)
|
||||
| GenericArgument::Const(_)
|
||||
| GenericArgument::AssocConst(_)
|
||||
| GenericArgument::Constraint(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -207,9 +206,11 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
|
||||
match bound {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
|
||||
TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
TypeParamBound::Lifetime(_)
|
||||
| TypeParamBound::PreciseCapture(_)
|
||||
| TypeParamBound::Verbatim(_) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -228,6 +229,7 @@ impl ReplaceReceiver<'_> {
|
||||
if let Some(where_clause) = &mut generics.where_clause {
|
||||
for predicate in &mut where_clause.predicates {
|
||||
match predicate {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
WherePredicate::Type(predicate) => {
|
||||
self.visit_type_mut(&mut predicate.bounded_ty);
|
||||
for bound in &mut predicate.bounds {
|
||||
@@ -235,7 +237,6 @@ impl ReplaceReceiver<'_> {
|
||||
}
|
||||
}
|
||||
WherePredicate::Lifetime(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ pub const FLATTEN: Symbol = Symbol("flatten");
|
||||
pub const FROM: Symbol = Symbol("from");
|
||||
pub const GETTER: Symbol = Symbol("getter");
|
||||
pub const INTO: Symbol = Symbol("into");
|
||||
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
|
||||
pub const OTHER: Symbol = Symbol("other");
|
||||
pub const REMOTE: Symbol = Symbol("remote");
|
||||
pub const RENAME: Symbol = Symbol("rename");
|
||||
@@ -45,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 {
|
||||
*self == word.0
|
||||
}
|
||||
@@ -57,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 {
|
||||
self.is_ident(word.0)
|
||||
}
|
||||
|
||||
+7
-24
@@ -13,7 +13,8 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.177")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.219")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||
@@ -26,6 +27,7 @@
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::match_like_matches_macro,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::too_many_arguments,
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
@@ -39,6 +41,7 @@
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::checked_conversions,
|
||||
clippy::doc_markdown,
|
||||
clippy::elidable_lifetime_names,
|
||||
clippy::enum_glob_use,
|
||||
clippy::indexing_slicing,
|
||||
clippy::items_after_statements,
|
||||
@@ -50,11 +53,11 @@
|
||||
clippy::match_wildcard_for_single_variants,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::option_if_let_else,
|
||||
clippy::similar_names,
|
||||
clippy::single_match_else,
|
||||
clippy::struct_excessive_bools,
|
||||
clippy::too_many_lines,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unseparated_literal_suffix,
|
||||
clippy::unused_self,
|
||||
clippy::use_self,
|
||||
@@ -66,17 +69,11 @@ extern crate proc_macro2;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
|
||||
#[cfg(not(precompiled))]
|
||||
extern crate proc_macro;
|
||||
#[cfg(precompiled)]
|
||||
extern crate proc_macro2 as proc_macro;
|
||||
|
||||
mod internals;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
#[cfg(precompiled)]
|
||||
use std::sync::atomic::AtomicBool;
|
||||
#[cfg(not(precompiled))]
|
||||
use syn::parse_macro_input;
|
||||
use syn::DeriveInput;
|
||||
|
||||
@@ -90,22 +87,8 @@ mod dummy;
|
||||
mod pretend;
|
||||
mod ser;
|
||||
mod this;
|
||||
mod try;
|
||||
|
||||
#[cfg(precompiled)]
|
||||
macro_rules! parse_macro_input {
|
||||
($tokenstream:ident as $ty:ty) => {
|
||||
match syn::parse2::<$ty>($tokenstream) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return err.to_compile_error(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(precompiled)]
|
||||
pub static DESERIALIZE_IN_PLACE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg_attr(not(precompiled), proc_macro_derive(Serialize, attributes(serde)))]
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
ser::expand_derive_serialize(&mut input)
|
||||
@@ -113,7 +96,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(precompiled), proc_macro_derive(Deserialize, attributes(serde)))]
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
de::expand_derive_deserialize(&mut input)
|
||||
|
||||
@@ -64,14 +64,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
|
||||
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
|
||||
match &cont.data {
|
||||
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 {
|
||||
pretend_fields_used_struct_packed(cont, fields)
|
||||
} else {
|
||||
pretend_fields_used_struct(cont, fields)
|
||||
}
|
||||
}
|
||||
Data::Struct(_, _) => quote!(),
|
||||
Data::Struct(Style::Unit, _) => quote!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +115,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre
|
||||
let patterns = variants
|
||||
.iter()
|
||||
.filter_map(|variant| match variant.style {
|
||||
Style::Struct => {
|
||||
Style::Struct | Style::Tuple | Style::Newtype => {
|
||||
let variant_ident = &variant.ident;
|
||||
let members = variant.fields.iter().map(|field| &field.member);
|
||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
||||
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
|
||||
}
|
||||
_ => None,
|
||||
Style::Unit => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
+114
-86
@@ -1,5 +1,6 @@
|
||||
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, this};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
@@ -28,6 +29,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
|
||||
let vis = &input.vis;
|
||||
let used = pretend::pretend_used(&cont, params.is_packed);
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
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>
|
||||
where
|
||||
@@ -282,16 +284,25 @@ fn serialize_tuple_struct(
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
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)*
|
||||
_serde::ser::SerializeTupleStruct::end(__serde_state)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
} else {
|
||||
serialize_struct_as_struct(params, fields, cattrs)
|
||||
@@ -304,7 +315,7 @@ fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTra
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
let func = struct_trait.serialize_field(Span::call_site());
|
||||
quote! {
|
||||
try!(#func(&mut __serde_state, #tag, #type_name));
|
||||
#func(&mut __serde_state, #tag, #type_name)?;
|
||||
}
|
||||
}
|
||||
_ => quote! {},
|
||||
@@ -345,7 +356,7 @@ fn serialize_struct_as_struct(
|
||||
);
|
||||
|
||||
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
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
@@ -370,26 +381,8 @@ fn serialize_struct_as_map(
|
||||
|
||||
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! {
|
||||
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
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
@@ -397,11 +390,11 @@ fn serialize_struct_as_map(
|
||||
}
|
||||
|
||||
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 arms: Vec<_> = variants
|
||||
let mut arms: Vec<_> = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(variant_index, variant)| {
|
||||
@@ -409,6 +402,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
||||
})
|
||||
.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! {
|
||||
match *#self_var {
|
||||
#(#arms)*
|
||||
@@ -478,7 +477,14 @@ fn serialize_variant(
|
||||
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
||||
}
|
||||
(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)
|
||||
@@ -559,7 +565,7 @@ fn serialize_externally_tagged_variant(
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
type_name,
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -593,10 +599,10 @@ fn serialize_internally_tagged_variant(
|
||||
match effective_style(variant) {
|
||||
Style::Unit => {
|
||||
quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name)?;
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
}
|
||||
}
|
||||
@@ -624,7 +630,7 @@ fn serialize_internally_tagged_variant(
|
||||
StructVariant::InternallyTagged { tag, variant_name },
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
type_name,
|
||||
),
|
||||
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
||||
}
|
||||
@@ -634,12 +640,20 @@ fn serialize_adjacently_tagged_variant(
|
||||
params: &Parameters,
|
||||
variant: &Variant,
|
||||
cattrs: &attr::Container,
|
||||
variant_index: u32,
|
||||
tag: &str,
|
||||
content: &str,
|
||||
) -> Fragment {
|
||||
let this_type = ¶ms.this_type;
|
||||
let type_name = cattrs.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 ser = wrap_serialize_variant_with(params, path, variant);
|
||||
@@ -650,10 +664,10 @@ fn serialize_adjacently_tagged_variant(
|
||||
match effective_style(variant) {
|
||||
Style::Unit => {
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #serialize_variant)?;
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
@@ -667,12 +681,12 @@ fn serialize_adjacently_tagged_variant(
|
||||
let span = field.original.span();
|
||||
let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
try!(#func(
|
||||
&mut __struct, #content, #field_expr));
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #serialize_variant)?;
|
||||
#func(
|
||||
&mut __struct, #content, #field_expr)?;
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
@@ -683,13 +697,13 @@ fn serialize_adjacently_tagged_variant(
|
||||
StructVariant::Untagged,
|
||||
params,
|
||||
&variant.fields,
|
||||
&variant_name,
|
||||
variant_name,
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
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 => {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
vec![]
|
||||
@@ -720,6 +734,7 @@ fn serialize_adjacently_tagged_variant(
|
||||
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
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>
|
||||
where
|
||||
@@ -732,15 +747,15 @@ fn serialize_adjacently_tagged_variant(
|
||||
}
|
||||
}
|
||||
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #serialize_variant)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #content, &__AdjacentlyTagged {
|
||||
data: (#(#fields_ident,)*),
|
||||
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
|
||||
}));
|
||||
})?;
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
}
|
||||
}
|
||||
@@ -779,16 +794,16 @@ fn serialize_untagged_variant(
|
||||
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
|
||||
Style::Struct => {
|
||||
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 {
|
||||
type_name: String,
|
||||
type_name: &'a Name,
|
||||
variant_index: u32,
|
||||
variant_name: String,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
@@ -830,21 +845,21 @@ fn serialize_tuple_variant(
|
||||
variant_name,
|
||||
} => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
|
||||
__serializer,
|
||||
#type_name,
|
||||
#variant_index,
|
||||
#variant_name,
|
||||
#len));
|
||||
#len)?;
|
||||
#(#serialize_stmts)*
|
||||
_serde::ser::SerializeTupleVariant::end(__serde_state)
|
||||
}
|
||||
}
|
||||
TupleVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
|
||||
__serializer,
|
||||
#len));
|
||||
#len)?;
|
||||
#(#serialize_stmts)*
|
||||
_serde::ser::SerializeTuple::end(__serde_state)
|
||||
}
|
||||
@@ -855,11 +870,11 @@ fn serialize_tuple_variant(
|
||||
enum StructVariant<'a> {
|
||||
ExternallyTagged {
|
||||
variant_index: u32,
|
||||
variant_name: String,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
InternallyTagged {
|
||||
tag: &'a str,
|
||||
variant_name: String,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
@@ -868,7 +883,7 @@ fn serialize_struct_variant(
|
||||
context: StructVariant,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
name: &Name,
|
||||
) -> Fragment {
|
||||
if fields.iter().any(|field| field.attrs.flatten()) {
|
||||
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
||||
@@ -907,40 +922,40 @@ fn serialize_struct_variant(
|
||||
variant_name,
|
||||
} => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
|
||||
__serializer,
|
||||
#name,
|
||||
#variant_index,
|
||||
#variant_name,
|
||||
#len,
|
||||
));
|
||||
)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStructVariant::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||
quote_block! {
|
||||
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
||||
let mut __serde_state = _serde::Serializer::serialize_struct(
|
||||
__serializer,
|
||||
#name,
|
||||
#len + 1,
|
||||
));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __serde_state,
|
||||
#tag,
|
||||
#variant_name,
|
||||
));
|
||||
)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_struct(
|
||||
__serializer,
|
||||
#name,
|
||||
#len,
|
||||
));
|
||||
)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
}
|
||||
@@ -952,7 +967,7 @@ fn serialize_struct_variant_with_flatten(
|
||||
context: StructVariant,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
name: &Name,
|
||||
) -> Fragment {
|
||||
let struct_trait = StructTrait::SerializeMap;
|
||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||
@@ -984,15 +999,16 @@ fn serialize_struct_variant_with_flatten(
|
||||
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
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>
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
let (#(#members,)*) = self.data;
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None));
|
||||
_serde::__private::None)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
@@ -1011,23 +1027,23 @@ fn serialize_struct_variant_with_flatten(
|
||||
}
|
||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None));
|
||||
try!(_serde::ser::SerializeMap::serialize_entry(
|
||||
_serde::__private::None)?;
|
||||
_serde::ser::SerializeMap::serialize_entry(
|
||||
&mut __serde_state,
|
||||
#tag,
|
||||
#variant_name,
|
||||
));
|
||||
)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None));
|
||||
_serde::__private::None)?;
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
@@ -1072,7 +1088,7 @@ fn serialize_tuple_struct_visitor(
|
||||
let span = field.original.span();
|
||||
let func = tuple_trait.serialize_element(span);
|
||||
let ser = quote! {
|
||||
try!(#func(&mut __serde_state, #field_expr));
|
||||
#func(&mut __serde_state, #field_expr)?;
|
||||
};
|
||||
|
||||
match skip {
|
||||
@@ -1116,12 +1132,12 @@ fn serialize_struct_visitor(
|
||||
let ser = if field.attrs.flatten() {
|
||||
let func = quote_spanned!(span=> _serde::Serialize::serialize);
|
||||
quote! {
|
||||
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
|
||||
#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
|
||||
}
|
||||
} else {
|
||||
let func = struct_trait.serialize_field(span);
|
||||
quote! {
|
||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
||||
#func(&mut __serde_state, #key_expr, #field_expr)?;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1133,7 +1149,7 @@ fn serialize_struct_visitor(
|
||||
if !#skip {
|
||||
#ser
|
||||
} else {
|
||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
||||
#skip_func(&mut __serde_state, #key_expr)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1208,6 +1224,17 @@ fn wrap_serialize_with(
|
||||
})
|
||||
});
|
||||
|
||||
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 {
|
||||
@@ -1215,12 +1242,13 @@ fn wrap_serialize_with(
|
||||
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
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
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
#serialize_with(#(self.values.#field_access, )* __s)
|
||||
#wrapper_serialize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1233,7 +1261,7 @@ fn wrap_serialize_with(
|
||||
|
||||
// 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)
|
||||
//
|
||||
// where we want to omit the `mut` to avoid a warning.
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
use proc_macro2::{Punct, Spacing, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
// 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,24 +1,31 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.28.0" # remember to update html_root_url
|
||||
version = "0.29.1"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
documentation = "https://docs.rs/serde_derive_internals"
|
||||
edition = "2015"
|
||||
exclude = ["build.rs"]
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.61"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--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,9 +1,17 @@
|
||||
use std::path::Path;
|
||||
|
||||
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
|
||||
// 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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.28.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
clippy::cognitive_complexity,
|
||||
@@ -8,6 +9,7 @@
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::redundant_field_names,
|
||||
clippy::result_unit_err,
|
||||
clippy::should_implement_trait,
|
||||
@@ -19,6 +21,7 @@
|
||||
// Ignored clippy_pedantic lints
|
||||
#![allow(
|
||||
clippy::doc_markdown,
|
||||
clippy::elidable_lifetime_names,
|
||||
clippy::enum_glob_use,
|
||||
clippy::items_after_statements,
|
||||
clippy::let_underscore_untyped,
|
||||
@@ -34,6 +37,7 @@
|
||||
clippy::single_match_else,
|
||||
clippy::struct_excessive_bools,
|
||||
clippy::too_many_lines,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unused_self,
|
||||
clippy::wildcard_imports
|
||||
)]
|
||||
|
||||
@@ -13,9 +13,9 @@ serde = { path = "../serde" }
|
||||
|
||||
[dev-dependencies]
|
||||
automod = "1.0.1"
|
||||
fnv = "1.0"
|
||||
foldhash = "0.1"
|
||||
rustversion = "1.0"
|
||||
serde = { path = "../serde", features = ["rc"] }
|
||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||
serde_test = "1.0.176"
|
||||
trybuild = { version = "1.0.66", features = ["diff"] }
|
||||
trybuild = { version = "1.0.97", features = ["diff"] }
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/target/
|
||||
/Cargo.lock
|
||||
@@ -10,4 +10,10 @@ libc = { version = "0.2", default-features = false }
|
||||
serde = { path = "../../serde", default-features = false }
|
||||
serde_derive = { path = "../../serde_derive" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
[workspace]
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
#![feature(lang_items, start)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[start]
|
||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
use core::ffi::c_int;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_eh_personality() {}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
unsafe {
|
||||
@@ -22,21 +20,21 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
pub struct Unit;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Newtype(u8);
|
||||
pub struct Newtype(u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Tuple(u8, u8);
|
||||
pub struct Tuple(u8, u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct {
|
||||
pub struct Struct {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Enum {
|
||||
pub enum Enum {
|
||||
Unit,
|
||||
Newtype(u8),
|
||||
Tuple(u8, u8),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[rustversion::attr(not(nightly), ignore)]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
#[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")]
|
||||
#[rustversion::attr(not(nightly), ignore = "requires nightly")]
|
||||
#[cfg_attr(miri, ignore = "incompatible with miri")]
|
||||
#[allow(unused_attributes)]
|
||||
#[test]
|
||||
fn ui() {
|
||||
|
||||
@@ -34,9 +34,8 @@ macro_rules! hashset {
|
||||
$(set.insert($value);)+
|
||||
set
|
||||
}};
|
||||
($hasher:ident @ $($value:expr),+) => {{
|
||||
use std::hash::BuildHasherDefault;
|
||||
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
|
||||
($hasher:ty; $($value:expr),+) => {{
|
||||
let mut set = HashSet::<_, $hasher>::default();
|
||||
$(set.insert($value);)+
|
||||
set
|
||||
}};
|
||||
@@ -51,9 +50,8 @@ macro_rules! hashmap {
|
||||
$(map.insert($key, $value);)+
|
||||
map
|
||||
}};
|
||||
($hasher:ident @ $($key:expr => $value:expr),+) => {{
|
||||
use std::hash::BuildHasherDefault;
|
||||
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
|
||||
($hasher:ty; $($key:expr => $value:expr),+) => {{
|
||||
let mut map = HashMap::<_, _, $hasher>::default();
|
||||
$(map.insert($key, $value);)+
|
||||
map
|
||||
}};
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#![allow(dead_code)] // we do not read enum fields
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Nested;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum ExternallyTagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum ExternallyTagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
|
||||
// Internally tagged enums cannot contain tuple variants so not tested here
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
pub enum AdjacentlyTagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
pub enum AdjacentlyTagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Untagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Untagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
@@ -7,7 +7,9 @@ pub struct Nested;
|
||||
pub enum ExternallyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -17,7 +19,9 @@ pub enum ExternallyTagged {
|
||||
pub enum InternallyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -27,7 +31,9 @@ pub enum InternallyTagged {
|
||||
pub enum AdjacentlyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -37,7 +43,9 @@ pub enum AdjacentlyTagged {
|
||||
pub enum UntaggedWorkaround {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
enum Enum {
|
||||
Simple {
|
||||
a: i32,
|
||||
},
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
flatten: (),
|
||||
a: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Simple { a: 42 },
|
||||
&[
|
||||
Token::StructVariant {
|
||||
name: "Enum",
|
||||
variant: "Simple",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::StructVariantEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flatten_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Flatten { flatten: (), a: 42 },
|
||||
&[
|
||||
Token::NewtypeVariant {
|
||||
name: "Enum",
|
||||
variant: "Flatten",
|
||||
},
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#![allow(dead_code)] // we do not read enum fields
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub enum A {
|
||||
B {
|
||||
c: String,
|
||||
},
|
||||
D {
|
||||
#[serde(flatten)]
|
||||
e: E,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct E {}
|
||||
@@ -0,0 +1,33 @@
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
macro_rules! declare_in_macro {
|
||||
($with:literal) => {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct S {
|
||||
#[serde(with = $with)]
|
||||
f: i32,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare_in_macro!("with");
|
||||
|
||||
mod with {
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S>(_: &i32, _: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
macro_rules! declare_in_macro {
|
||||
($with:literal) => {
|
||||
#[derive(Deserialize)]
|
||||
pub struct S(
|
||||
#[serde(with = $with)]
|
||||
#[allow(dead_code)]
|
||||
i32,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
declare_in_macro!("with");
|
||||
|
||||
mod with {
|
||||
use serde::Deserializer;
|
||||
|
||||
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
+1091
-1230
File diff suppressed because it is too large
Load Diff
@@ -162,7 +162,7 @@ fn test_cow() {
|
||||
#[test]
|
||||
fn test_lifetimes() {
|
||||
#[derive(Deserialize)]
|
||||
struct Cows<'a, 'b> {
|
||||
pub struct Cows<'a, 'b> {
|
||||
_copied: Cow<'a, str>,
|
||||
|
||||
#[serde(borrow)]
|
||||
@@ -178,7 +178,7 @@ fn test_lifetimes() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Wrap<'a, 'b> {
|
||||
pub struct Wrap<'a, 'b> {
|
||||
#[serde(borrow = "'b")]
|
||||
_cows: Cows<'a, 'b>,
|
||||
}
|
||||
|
||||
+102
-5
@@ -10,7 +10,7 @@
|
||||
)]
|
||||
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||
|
||||
use fnv::FnvHasher;
|
||||
use serde::de::value::{F32Deserializer, F64Deserializer};
|
||||
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
|
||||
use serde_derive::Deserialize;
|
||||
use serde_test::{assert_de_tokens, Configure, Token};
|
||||
@@ -22,7 +22,7 @@ use std::iter;
|
||||
use std::net;
|
||||
use std::num::{
|
||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
|
||||
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
|
||||
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping,
|
||||
};
|
||||
use std::ops::Bound;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -92,7 +92,7 @@ struct StructSkipDefault {
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct StructSkipDefaultGeneric<T> {
|
||||
pub struct StructSkipDefaultGeneric<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: T,
|
||||
}
|
||||
@@ -832,6 +832,26 @@ fn test_f64() {
|
||||
test(1.11, &[Token::F64(1.11)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nan() {
|
||||
let f32_deserializer = F32Deserializer::<serde::de::value::Error>::new;
|
||||
let f64_deserializer = F64Deserializer::<serde::de::value::Error>::new;
|
||||
|
||||
let pos_f32_nan = f32_deserializer(f32::NAN.copysign(1.0));
|
||||
let pos_f64_nan = f64_deserializer(f64::NAN.copysign(1.0));
|
||||
assert!(f32::deserialize(pos_f32_nan).unwrap().is_sign_positive());
|
||||
assert!(f32::deserialize(pos_f64_nan).unwrap().is_sign_positive());
|
||||
assert!(f64::deserialize(pos_f32_nan).unwrap().is_sign_positive());
|
||||
assert!(f64::deserialize(pos_f64_nan).unwrap().is_sign_positive());
|
||||
|
||||
let neg_f32_nan = f32_deserializer(f32::NAN.copysign(-1.0));
|
||||
let neg_f64_nan = f64_deserializer(f64::NAN.copysign(-1.0));
|
||||
assert!(f32::deserialize(neg_f32_nan).unwrap().is_sign_negative());
|
||||
assert!(f32::deserialize(neg_f64_nan).unwrap().is_sign_negative());
|
||||
assert!(f64::deserialize(neg_f32_nan).unwrap().is_sign_negative());
|
||||
assert!(f64::deserialize(neg_f64_nan).unwrap().is_sign_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_char() {
|
||||
test('a', &[Token::Char('a')]);
|
||||
@@ -1019,7 +1039,7 @@ fn test_hashset() {
|
||||
],
|
||||
);
|
||||
test(
|
||||
hashset![FnvHasher @ 1, 2, 3],
|
||||
hashset![foldhash::fast::FixedState; 1, 2, 3],
|
||||
&[
|
||||
Token::Seq { len: Some(3) },
|
||||
Token::I32(1),
|
||||
@@ -1254,7 +1274,7 @@ fn test_hashmap() {
|
||||
],
|
||||
);
|
||||
test(
|
||||
hashmap![FnvHasher @ 1 => 2, 3 => 4],
|
||||
hashmap![foldhash::fast::FixedState; 1 => 2, 3 => 4],
|
||||
&[
|
||||
Token::Map { len: Some(2) },
|
||||
Token::I32(1),
|
||||
@@ -1877,6 +1897,46 @@ fn test_range_inclusive() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_from() {
|
||||
test(
|
||||
1u32..,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeFrom",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("start"),
|
||||
Token::U32(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
test(
|
||||
1u32..,
|
||||
&[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_to() {
|
||||
test(
|
||||
..2u32,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeTo",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("end"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
test(
|
||||
..2u32,
|
||||
&[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound() {
|
||||
test(
|
||||
@@ -2004,6 +2064,43 @@ fn test_wrapping() {
|
||||
test(Wrapping(1usize), &[Token::U64(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating() {
|
||||
test(Saturating(1usize), &[Token::U32(1)]);
|
||||
test(Saturating(1usize), &[Token::U64(1)]);
|
||||
test(Saturating(0u8), &[Token::I8(0)]);
|
||||
test(Saturating(0u16), &[Token::I16(0)]);
|
||||
|
||||
// saturate input values at the minimum or maximum value
|
||||
test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]);
|
||||
test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]);
|
||||
test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]);
|
||||
test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]);
|
||||
test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]);
|
||||
test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]);
|
||||
test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]);
|
||||
test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]);
|
||||
test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]);
|
||||
test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]);
|
||||
|
||||
test(Saturating(u8::MIN), &[Token::I8(-1)]);
|
||||
test(Saturating(u16::MIN), &[Token::I16(-1)]);
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]);
|
||||
test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]);
|
||||
test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]);
|
||||
test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]);
|
||||
test(Saturating(0usize), &[Token::I64(i64::MIN)]);
|
||||
|
||||
test(
|
||||
Saturating(9_223_372_036_854_775_807usize),
|
||||
&[Token::I64(i64::MAX)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rc_dst() {
|
||||
test(Rc::<str>::from("s"), &[Token::Str("s")]);
|
||||
|
||||
@@ -1434,7 +1434,15 @@ fn test_number_from_string() {
|
||||
fn test_integer_from_float() {
|
||||
assert_de_tokens_error::<isize>(
|
||||
&[Token::F32(0.0)],
|
||||
"invalid type: floating point `0`, expected isize",
|
||||
"invalid type: floating point `0.0`, expected isize",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nan_no_decimal_point() {
|
||||
assert_de_tokens_error::<isize>(
|
||||
&[Token::F32(f32::NAN)],
|
||||
"invalid type: floating point `NaN`, expected isize",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1459,7 +1467,7 @@ fn test_duration_overflow_seq() {
|
||||
assert_de_tokens_error::<Duration>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
@@ -1476,7 +1484,7 @@ fn test_duration_overflow_struct() {
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("secs"),
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::Str("nanos"),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::StructEnd,
|
||||
@@ -1490,7 +1498,7 @@ fn test_systemtime_overflow_seq() {
|
||||
assert_de_tokens_error::<SystemTime>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
@@ -1507,7 +1515,7 @@ fn test_systemtime_overflow_struct() {
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("secs_since_epoch"),
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::Str("nanos_since_epoch"),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::StructEnd,
|
||||
@@ -1516,13 +1524,12 @@ fn test_systemtime_overflow_struct() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(systemtime_checked_add)]
|
||||
#[test]
|
||||
fn test_systemtime_overflow() {
|
||||
assert_de_tokens_error::<SystemTime>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
|
||||
@@ -0,0 +1,799 @@
|
||||
#![deny(trivial_numeric_casts)]
|
||||
#![allow(
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
clippy::enum_variant_names,
|
||||
clippy::redundant_field_names,
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTagged<T> {
|
||||
Unit,
|
||||
Newtype(T),
|
||||
Tuple(u8, u8),
|
||||
Struct { f: u8 },
|
||||
}
|
||||
|
||||
mod unit {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map_str_tag_only() {
|
||||
// Map: tag only
|
||||
assert_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: tag only and incorrect hint for number of elements
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_int_tag_only() {
|
||||
// Map: tag (as number) only
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::U16(0),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_bytes_tag_only() {
|
||||
// Map: tag only
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Bytes(b"t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: tag only
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::BorrowedBytes(b"t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_str_tag_content() {
|
||||
// Map: tag + content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
// Map: content + tag
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: tag + content + excess fields (f, g, h)
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("f"),
|
||||
Token::Unit,
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::Str("g"),
|
||||
Token::Unit,
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::Str("h"),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_int_tag_content() {
|
||||
// Map: tag (as number) + content (as number)
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::U8(0),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::U8(1),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: content (as number) + tag (as number)
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::U64(1),
|
||||
Token::Unit,
|
||||
Token::U64(0),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_bytes_tag_content() {
|
||||
// Map: tag + content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::BorrowedBytes(b"t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::BorrowedBytes(b"c"),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: content + tag
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Bytes(b"c"),
|
||||
Token::Unit,
|
||||
Token::Bytes(b"t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq_tag_content() {
|
||||
// Seq: tag and content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::Unit,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Seq: tag (as string) and content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Seq { len: None },
|
||||
Token::Str("Unit"), // tag
|
||||
Token::Unit, // content
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Seq: tag (as borrowed string) and content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Seq { len: None },
|
||||
Token::BorrowedStr("Unit"), // tag
|
||||
Token::Unit, // content
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod newtype {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map_tag_only() {
|
||||
// optional newtype with no content field
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Newtype::<Option<u8>>(None),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_tag_content() {
|
||||
let value = AdjacentlyTagged::Newtype::<u8>(1);
|
||||
|
||||
// Map: tag + content
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: content + tag
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::U8(1),
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq() {
|
||||
let value = AdjacentlyTagged::Newtype::<u8>(1);
|
||||
|
||||
// Seq: tag and content
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::U8(1),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Seq: tag (as string) and content
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Seq { len: None },
|
||||
Token::Str("Newtype"), // tag
|
||||
Token::U8(1), // content
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Seq: tag (as borrowed string) and content
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Seq { len: None },
|
||||
Token::BorrowedStr("Newtype"), // tag
|
||||
Token::U8(1), // content
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype_with_newtype() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct NewtypeStruct(u32);
|
||||
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Newtype(NewtypeStruct(5)),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::NewtypeStruct {
|
||||
name: "NewtypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
mod tuple {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map() {
|
||||
let value = AdjacentlyTagged::Tuple::<u8>(1, 1);
|
||||
|
||||
// Map: tag + content
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Tuple",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Tuple { len: 2 },
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::TupleEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: content + tag
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Tuple { len: 2 },
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::TupleEnd,
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Tuple",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq() {
|
||||
let value = AdjacentlyTagged::Tuple::<u8>(1, 1);
|
||||
|
||||
// Seq: tag + content
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Tuple",
|
||||
},
|
||||
Token::Tuple { len: 2 },
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::TupleEnd,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod struct_ {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn map() {
|
||||
let value = AdjacentlyTagged::Struct::<u8> { f: 1 };
|
||||
|
||||
// Map: tag + content
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Struct",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Struct {
|
||||
name: "Struct",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("f"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Map: content + tag
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Struct {
|
||||
name: "Struct",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("f"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Struct",
|
||||
},
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq() {
|
||||
let value = AdjacentlyTagged::Struct::<u8> { f: 1 };
|
||||
|
||||
// Seq: tag + content
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Struct",
|
||||
},
|
||||
Token::Struct {
|
||||
name: "Struct",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("f"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_with_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Data",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "Data",
|
||||
variant: "A",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expecting_message() {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
#[serde(expecting = "something strange...")]
|
||||
enum Enum {
|
||||
AdjacentlyTagged,
|
||||
}
|
||||
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Str("AdjacentlyTagged")],
|
||||
r#"invalid type: string "AdjacentlyTagged", expected something strange..."#,
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Map { len: None }, Token::Unit],
|
||||
r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#,
|
||||
);
|
||||
|
||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
|
||||
"invalid type: unit value, expected variant of enum Enum",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partially_untagged() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum Data {
|
||||
A(u32),
|
||||
B,
|
||||
#[serde(untagged)]
|
||||
Var(u32),
|
||||
}
|
||||
|
||||
let data = Data::A(7);
|
||||
|
||||
assert_de_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("t"),
|
||||
Token::Str("A"),
|
||||
Token::Str("c"),
|
||||
Token::U32(7),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
let data = Data::Var(42);
|
||||
|
||||
assert_de_tokens(&data, &[Token::U32(42)]);
|
||||
|
||||
// TODO test error output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deny_unknown_fields() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(tag = "t", content = "c", deny_unknown_fields)]
|
||||
enum AdjacentlyTagged {
|
||||
Unit,
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::Str("h"),
|
||||
],
|
||||
r#"invalid value: string "h", expected "t" or "c""#,
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("h"),
|
||||
],
|
||||
r#"invalid value: string "h", expected "t" or "c""#,
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
Token::Str("h"),
|
||||
],
|
||||
r#"invalid value: string "h", expected "t" or "c""#,
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::U64(0), // tag field
|
||||
Token::UnitVariant {
|
||||
name: "AdjacentlyTagged",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::U64(3),
|
||||
],
|
||||
r#"invalid value: integer `3`, expected "t" or "c""#,
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdjacentlyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Bytes(b"c"),
|
||||
Token::Unit,
|
||||
Token::Bytes(b"h"),
|
||||
],
|
||||
r#"invalid value: byte array, expected "t" or "c""#,
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,583 @@
|
||||
#![deny(trivial_numeric_casts)]
|
||||
#![allow(
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
clippy::enum_variant_names,
|
||||
clippy::redundant_field_names,
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
mod bytes;
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[test]
|
||||
fn complex() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Untagged {
|
||||
A { a: u8 },
|
||||
B { b: u8 },
|
||||
C,
|
||||
D(u8),
|
||||
E(String),
|
||||
F(u8, u8),
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Untagged::A { a: 1 },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("a"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
&Untagged::B { b: 2 },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("b"),
|
||||
Token::U8(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// Serializes to unit, deserializes from either depending on format's
|
||||
// preference.
|
||||
assert_tokens(&Untagged::C, &[Token::Unit]);
|
||||
assert_de_tokens(&Untagged::C, &[Token::None]);
|
||||
|
||||
assert_tokens(&Untagged::D(4), &[Token::U8(4)]);
|
||||
assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]);
|
||||
|
||||
assert_tokens(
|
||||
&Untagged::F(1, 2),
|
||||
&[
|
||||
Token::Tuple { len: 2 },
|
||||
Token::U8(1),
|
||||
Token::U8(2),
|
||||
Token::TupleEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<Untagged>(
|
||||
&[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd],
|
||||
"data did not match any variant of untagged enum Untagged",
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<Untagged>(
|
||||
&[
|
||||
Token::Tuple { len: 3 },
|
||||
Token::U8(1),
|
||||
Token::U8(2),
|
||||
Token::U8(3),
|
||||
Token::TupleEnd,
|
||||
],
|
||||
"data did not match any variant of untagged enum Untagged",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype_unit_and_empty_map() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Message {
|
||||
Unit(Unit),
|
||||
Map(BTreeMap<String, String>),
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Message::Map(BTreeMap::new()),
|
||||
&[Token::Map { len: Some(0) }, Token::MapEnd],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::ContentRefDeserializer::deserialize_newtype_struct
|
||||
#[test]
|
||||
fn newtype_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct NewtypeStruct(u32);
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum E {
|
||||
Newtype(NewtypeStruct),
|
||||
Null,
|
||||
}
|
||||
|
||||
let value = E::Newtype(NewtypeStruct(5));
|
||||
|
||||
// Content::Newtype case
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::NewtypeStruct {
|
||||
name: "NewtypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
],
|
||||
);
|
||||
|
||||
// _ case
|
||||
assert_de_tokens(&value, &[Token::U32(5)]);
|
||||
}
|
||||
|
||||
mod newtype_enum {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Outer {
|
||||
Inner(Inner),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
enum Inner {
|
||||
Unit,
|
||||
Newtype(u8),
|
||||
Tuple0(),
|
||||
Tuple2(u8, u8),
|
||||
Struct { f: u8 },
|
||||
EmptyStruct {},
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::unit_variant
|
||||
#[test]
|
||||
fn unit() {
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Unit),
|
||||
&[Token::UnitVariant {
|
||||
name: "Inner",
|
||||
variant: "Unit",
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::newtype_variant_seed
|
||||
#[test]
|
||||
fn newtype() {
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Newtype(1)),
|
||||
&[
|
||||
Token::NewtypeVariant {
|
||||
name: "Inner",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::U8(1),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant
|
||||
#[test]
|
||||
fn tuple0() {
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Tuple0()),
|
||||
&[
|
||||
Token::TupleVariant {
|
||||
name: "Inner",
|
||||
variant: "Tuple0",
|
||||
len: 0,
|
||||
},
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant
|
||||
#[test]
|
||||
fn tuple2() {
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Tuple2(1, 1)),
|
||||
&[
|
||||
Token::TupleVariant {
|
||||
name: "Inner",
|
||||
variant: "Tuple2",
|
||||
len: 2,
|
||||
},
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::struct_variant
|
||||
// Content::Map case
|
||||
#[test]
|
||||
fn struct_from_map() {
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Struct { f: 1 }),
|
||||
&[
|
||||
Token::StructVariant {
|
||||
name: "Inner",
|
||||
variant: "Struct",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("f"),
|
||||
Token::U8(1),
|
||||
Token::StructVariantEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::struct_variant
|
||||
// Content::Seq case
|
||||
#[test]
|
||||
fn struct_from_seq() {
|
||||
assert_de_tokens(
|
||||
&Outer::Inner(Inner::Struct { f: 1 }),
|
||||
&[
|
||||
Token::Map { len: Some(1) },
|
||||
// tag
|
||||
Token::Str("Struct"),
|
||||
// content
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::U8(1),
|
||||
Token::SeqEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::struct_variant
|
||||
// Content::Map case
|
||||
// Special case - empty map
|
||||
#[test]
|
||||
fn empty_struct_from_map() {
|
||||
assert_de_tokens(
|
||||
&Outer::Inner(Inner::EmptyStruct {}),
|
||||
&[
|
||||
Token::Map { len: Some(1) },
|
||||
// tag
|
||||
Token::Str("EmptyStruct"),
|
||||
// content
|
||||
Token::Map { len: Some(0) },
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantRefDeserializer::struct_variant
|
||||
// Content::Seq case
|
||||
// Special case - empty seq
|
||||
#[test]
|
||||
fn empty_struct_from_seq() {
|
||||
assert_de_tokens(
|
||||
&Outer::Inner(Inner::EmptyStruct {}),
|
||||
&[
|
||||
Token::Map { len: Some(1) },
|
||||
// tag
|
||||
Token::Str("EmptyStruct"),
|
||||
// content
|
||||
Token::Seq { len: Some(0) },
|
||||
Token::SeqEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option
|
||||
mod with_optional_field {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Enum {
|
||||
Struct { optional: Option<u32> },
|
||||
Null,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn some() {
|
||||
assert_tokens(
|
||||
&Enum::Struct { optional: Some(42) },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Enum",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("optional"),
|
||||
Token::Some,
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn some_without_marker() {
|
||||
assert_de_tokens(
|
||||
&Enum::Struct { optional: Some(42) },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Enum",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("optional"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn none() {
|
||||
assert_tokens(
|
||||
&Enum::Struct { optional: None },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Enum",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("optional"),
|
||||
Token::None,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit() {
|
||||
assert_de_tokens(
|
||||
&Enum::Struct { optional: None },
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("optional"),
|
||||
Token::Unit,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_and_bytes() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Untagged {
|
||||
String {
|
||||
string: String,
|
||||
},
|
||||
Bytes {
|
||||
#[serde(with = "bytes")]
|
||||
bytes: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::U8(0),
|
||||
Token::SeqEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(untagged)]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_flatten_with_integer_key() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Untagged {
|
||||
Variant {
|
||||
#[serde(flatten)]
|
||||
map: BTreeMap<u64, String>,
|
||||
},
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Untagged::Variant {
|
||||
map: {
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert(100, "BTreeMap".to_owned());
|
||||
map
|
||||
},
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::U64(100),
|
||||
Token::Str("BTreeMap"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expecting_message() {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[serde(expecting = "something strange...")]
|
||||
enum Enum {
|
||||
Untagged,
|
||||
}
|
||||
|
||||
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], "something strange...");
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#![deny(warnings)]
|
||||
#![allow(
|
||||
confusable_idents,
|
||||
unknown_lints,
|
||||
mixed_script_confusables,
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
@@ -19,6 +20,7 @@
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
clippy::type_repetition_in_bounds
|
||||
)]
|
||||
#![deny(clippy::collection_is_never_read)]
|
||||
|
||||
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
@@ -287,60 +289,60 @@ fn test_gen() {
|
||||
assert::<EmptyEnumVariant>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct NonAsciiIdents {
|
||||
pub struct NonAsciiIdents {
|
||||
σ: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyBraced {}
|
||||
pub struct EmptyBraced {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct EmptyBracedDenyUnknown {}
|
||||
pub struct EmptyBracedDenyUnknown {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct BracedSkipAll {
|
||||
pub struct BracedSkipAll {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct BracedSkipAllDenyUnknown {
|
||||
pub struct BracedSkipAllDenyUnknown {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyTuple();
|
||||
pub struct EmptyTuple();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct EmptyTupleDenyUnknown();
|
||||
pub struct EmptyTupleDenyUnknown();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct TupleSkipAll(#[serde(skip_deserializing)] u8);
|
||||
pub struct TupleSkipAll(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
|
||||
pub struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EmptyEnum {}
|
||||
pub enum EmptyEnum {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum EmptyEnumDenyUnknown {}
|
||||
pub enum EmptyEnumDenyUnknown {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EnumSkipAll {
|
||||
pub enum EnumSkipAll {
|
||||
#[serde(skip_deserializing)]
|
||||
#[allow(dead_code)]
|
||||
Variant,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EmptyVariants {
|
||||
pub enum EmptyVariants {
|
||||
Braced {},
|
||||
Tuple(),
|
||||
BracedSkip {
|
||||
@@ -352,7 +354,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum EmptyVariantsDenyUnknown {
|
||||
pub enum EmptyVariantsDenyUnknown {
|
||||
Braced {},
|
||||
Tuple(),
|
||||
BracedSkip {
|
||||
@@ -364,21 +366,21 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct UnitDenyUnknown;
|
||||
pub struct UnitDenyUnknown;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyArray {
|
||||
pub struct EmptyArray {
|
||||
empty: [X; 0],
|
||||
}
|
||||
|
||||
enum Or<A, B> {
|
||||
pub enum Or<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged, remote = "Or")]
|
||||
enum OrDef<A, B> {
|
||||
pub enum OrDef<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
@@ -390,7 +392,7 @@ fn test_gen() {
|
||||
struct StrDef<'a>(&'a str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Remote<'a> {
|
||||
pub struct Remote<'a> {
|
||||
#[serde(with = "OrDef")]
|
||||
or: Or<u8, bool>,
|
||||
#[serde(borrow, with = "StrDef")]
|
||||
@@ -398,7 +400,7 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum BorrowVariant<'a> {
|
||||
pub enum BorrowVariant<'a> {
|
||||
#[serde(borrow, with = "StrDef")]
|
||||
S(Str<'a>),
|
||||
}
|
||||
@@ -415,14 +417,14 @@ fn test_gen() {
|
||||
|
||||
// This would not work if SDef::serialize / deserialize are private.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct RemoteVisibility {
|
||||
pub struct RemoteVisibility {
|
||||
#[serde(with = "vis::SDef")]
|
||||
s: vis::S,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Self")]
|
||||
struct RemoteSelf;
|
||||
pub struct RemoteSelf;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum ExternallyTaggedVariantWith {
|
||||
@@ -546,26 +548,45 @@ fn test_gen() {
|
||||
assert::<FlattenWith>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct FlattenDenyUnknown<T> {
|
||||
pub struct Flatten<T> {
|
||||
#[serde(flatten)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrStruct<'a> {
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct FlattenDenyUnknown<T> {
|
||||
#[serde(flatten)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SkipDeserializing<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SkipDeserializingDenyUnknown<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StaticStrStruct<'a> {
|
||||
a: &'a str,
|
||||
b: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrTupleStruct<'a>(&'a str, &'static str);
|
||||
pub struct StaticStrTupleStruct<'a>(&'a str, &'static str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrNewtypeStruct(&'static str);
|
||||
pub struct StaticStrNewtypeStruct(&'static str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum StaticStrEnum<'a> {
|
||||
pub enum StaticStrEnum<'a> {
|
||||
Struct { a: &'a str, b: &'static str },
|
||||
Tuple(&'a str, &'static str),
|
||||
Newtype(&'static str),
|
||||
@@ -639,6 +660,7 @@ fn test_gen() {
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct Restricted {
|
||||
pub(super) a: usize,
|
||||
pub(in super::inner) b: usize,
|
||||
@@ -648,7 +670,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTaggedVoid {}
|
||||
pub enum AdjacentlyTaggedVoid {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum SkippedVariant<T> {
|
||||
@@ -661,14 +683,13 @@ fn test_gen() {
|
||||
assert::<SkippedVariant<X>>();
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ImplicitlyBorrowedOption<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct ImplicitlyBorrowedOption<'a> {
|
||||
option: std::option::Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedNewtypeVariantWith {
|
||||
pub enum UntaggedNewtypeVariantWith {
|
||||
Newtype(
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
@@ -678,7 +699,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
struct TransparentWith {
|
||||
pub struct TransparentWith {
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
x: X,
|
||||
@@ -686,41 +707,60 @@ fn test_gen() {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedWithBorrow<'a> {
|
||||
Single(#[serde(borrow)] RelObject<'a>),
|
||||
Many(#[serde(borrow)] Vec<RelObject<'a>>),
|
||||
pub enum UntaggedWithBorrow<'a> {
|
||||
Single(
|
||||
#[serde(borrow)]
|
||||
#[allow(dead_code)]
|
||||
RelObject<'a>,
|
||||
),
|
||||
Many(
|
||||
#[serde(borrow)]
|
||||
#[allow(dead_code)]
|
||||
Vec<RelObject<'a>>,
|
||||
),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RelObject<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct RelObject<'a> {
|
||||
ty: &'a str,
|
||||
#[allow(dead_code)]
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipSerializing<T> {
|
||||
pub struct FlattenSkipSerializing<T> {
|
||||
#[serde(flatten, skip_serializing)]
|
||||
#[allow(dead_code)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipSerializingIf<T> {
|
||||
pub struct FlattenSkipSerializingIf<T> {
|
||||
#[serde(flatten, skip_serializing_if = "StdOption::is_none")]
|
||||
flat: StdOption<T>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipDeserializing<T> {
|
||||
pub struct FlattenSkipDeserializing<T> {
|
||||
#[serde(flatten, skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Inner<T> {
|
||||
Builder {
|
||||
s: T,
|
||||
#[serde(flatten)]
|
||||
o: T,
|
||||
},
|
||||
Default {
|
||||
s: T,
|
||||
},
|
||||
}
|
||||
|
||||
// https://github.com/serde-rs/serde/issues/1804
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Message {
|
||||
pub enum Message {
|
||||
#[serde(skip)]
|
||||
#[allow(dead_code)]
|
||||
String(String),
|
||||
@@ -729,7 +769,8 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[repr(packed)]
|
||||
#[repr(C, packed)]
|
||||
#[allow(dead_code)]
|
||||
struct Packed {
|
||||
x: u8,
|
||||
y: u16,
|
||||
@@ -738,8 +779,7 @@ fn test_gen() {
|
||||
macro_rules! deriving {
|
||||
($field:ty) => {
|
||||
#[derive(Deserialize)]
|
||||
struct MacroRules<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct MacroRules<'a> {
|
||||
field: $field,
|
||||
}
|
||||
};
|
||||
@@ -754,21 +794,20 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BorrowLifetimeInsideMacro<'a> {
|
||||
pub struct BorrowLifetimeInsideMacro<'a> {
|
||||
#[serde(borrow = "'a")]
|
||||
#[allow(dead_code)]
|
||||
f: mac!(Cow<'a, str>),
|
||||
pub f: mac!(Cow<'a, str>),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Struct {
|
||||
pub struct Struct {
|
||||
#[serde(serialize_with = "vec_first_element")]
|
||||
vec: Vec<Self>,
|
||||
pub vec: Vec<Self>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(bound(deserialize = "[&'de str; N]: Copy"))]
|
||||
struct GenericUnitStruct<const N: usize>;
|
||||
pub struct GenericUnitStruct<const N: usize>;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -843,7 +882,7 @@ pub fn is_zero(n: &u8) -> bool {
|
||||
*n == 0
|
||||
}
|
||||
|
||||
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
S: Serializer,
|
||||
@@ -855,7 +894,7 @@ where
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(tag = "tag")]
|
||||
enum InternallyTagged {
|
||||
pub enum InternallyTagged {
|
||||
#[serde(deserialize_with = "deserialize_generic")]
|
||||
Unit,
|
||||
|
||||
@@ -876,14 +915,14 @@ where
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[repr(packed)]
|
||||
#[repr(C, packed)]
|
||||
pub struct RemotePacked {
|
||||
pub a: u16,
|
||||
pub b: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[repr(packed)]
|
||||
#[repr(C, packed)]
|
||||
#[serde(remote = "RemotePacked")]
|
||||
pub struct RemotePackedDef {
|
||||
a: u16,
|
||||
@@ -894,14 +933,14 @@ impl Drop for RemotePackedDef {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[repr(C, packed)]
|
||||
pub struct RemotePackedNonCopy {
|
||||
pub a: u16,
|
||||
pub b: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[repr(packed)]
|
||||
#[repr(C, packed)]
|
||||
#[serde(remote = "RemotePackedNonCopy")]
|
||||
pub struct RemotePackedNonCopyDef {
|
||||
a: u16,
|
||||
|
||||
@@ -3,86 +3,186 @@
|
||||
#![allow(clippy::derive_partial_eq_without_eq)]
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_test::{assert_de_tokens, Token};
|
||||
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
|
||||
|
||||
mod variant_identifier {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_variant_identifier() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(variant_identifier)]
|
||||
enum V {
|
||||
Aaa,
|
||||
#[serde(alias = "Ccc", alias = "Ddd")]
|
||||
Bbb,
|
||||
}
|
||||
|
||||
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
|
||||
#[test]
|
||||
fn variant1() {
|
||||
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
|
||||
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliases() {
|
||||
assert_de_tokens(&V::Bbb, &[Token::U8(1)]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::U16(1)]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::U32(1)]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::U64(1)]);
|
||||
|
||||
assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]);
|
||||
|
||||
assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]);
|
||||
|
||||
assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]);
|
||||
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown() {
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::U8(42)],
|
||||
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::U16(42)],
|
||||
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::U32(42)],
|
||||
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::U64(42)],
|
||||
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::Str("Unknown")],
|
||||
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
|
||||
);
|
||||
assert_de_tokens_error::<V>(
|
||||
&[Token::Bytes(b"Unknown")],
|
||||
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_field_identifier() {
|
||||
mod field_identifier {
|
||||
use super::*;
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F {
|
||||
Aaa,
|
||||
#[serde(alias = "ccc", alias = "ddd")]
|
||||
Bbb,
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit_fallthrough() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
#[serde(other)]
|
||||
Other,
|
||||
#[test]
|
||||
fn field1() {
|
||||
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
|
||||
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other, &[Token::U8(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U16(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U32(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U64(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||
}
|
||||
#[test]
|
||||
fn aliases() {
|
||||
assert_de_tokens(&F::Bbb, &[Token::U8(1)]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::U16(1)]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::U32(1)]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::U64(1)]);
|
||||
|
||||
#[test]
|
||||
fn test_newtype_fallthrough() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
Other(String),
|
||||
assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]);
|
||||
|
||||
assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]);
|
||||
|
||||
assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]);
|
||||
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]);
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_newtype_fallthrough_generic() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F<T> {
|
||||
Aaa,
|
||||
Bbb,
|
||||
Other(T),
|
||||
#[test]
|
||||
fn unknown() {
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::U8(42)],
|
||||
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::U16(42)],
|
||||
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::U32(42)],
|
||||
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::U64(42)],
|
||||
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||
);
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::Str("unknown")],
|
||||
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
|
||||
);
|
||||
assert_de_tokens_error::<F>(
|
||||
&[Token::Bytes(b"unknown")],
|
||||
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
|
||||
);
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
|
||||
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
|
||||
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
|
||||
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
|
||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||
#[test]
|
||||
fn unit_fallthrough() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
#[serde(other)]
|
||||
Other,
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other, &[Token::U8(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U16(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U32(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::U64(42)]);
|
||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype_fallthrough() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype_fallthrough_generic() {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum F<T> {
|
||||
Aaa,
|
||||
Bbb,
|
||||
Other(T),
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
|
||||
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
|
||||
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
|
||||
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
|
||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1212
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user