зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1750646 - Bulk update of rust crates (q, r, s, t, u, v and w). r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D136192
This commit is contained in:
Родитель
a340a51fa9
Коммит
8dc4151c8b
|
@ -227,7 +227,7 @@ dependencies = [
|
|||
"miow",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"tokio 0.1.11",
|
||||
"tokio 0.1.14",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"winapi",
|
||||
|
@ -245,7 +245,7 @@ dependencies = [
|
|||
"futures 0.1.31",
|
||||
"futures-cpupool",
|
||||
"log",
|
||||
"tokio 0.1.11",
|
||||
"tokio 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -261,7 +261,7 @@ dependencies = [
|
|||
"log",
|
||||
"once_cell",
|
||||
"slab",
|
||||
"tokio 0.1.11",
|
||||
"tokio 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -911,7 +911,7 @@ dependencies = [
|
|||
"log",
|
||||
"regalloc",
|
||||
"smallvec",
|
||||
"target-lexicon 0.12.0",
|
||||
"target-lexicon 0.12.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -945,7 +945,7 @@ dependencies = [
|
|||
"cranelift-codegen",
|
||||
"log",
|
||||
"smallvec",
|
||||
"target-lexicon 0.12.0",
|
||||
"target-lexicon 0.12.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4071,9 +4071,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -4371,11 +4371,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.18.0"
|
||||
version = "1.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71b5a9625a7e6060b23db692facf49082cc78889a7e6ac94a735356ae49db4b0"
|
||||
checksum = "e0593ce4677e3800ddafb3de917e8397b1348e06e688128ade722d88fbe11ebf"
|
||||
dependencies = [
|
||||
"arrayvec 0.5.2",
|
||||
"arrayvec 0.7.2",
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
@ -4413,9 +4413,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "safemem"
|
||||
|
@ -4506,9 +4506,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -4524,9 +4524,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4591,12 +4591,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.21"
|
||||
version = "0.8.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
|
||||
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
@ -4662,9 +4662,9 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
|||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b"
|
||||
checksum = "ba1eead9e94aa5a2e02de9e7839f96a007f686ae7a1d57c7797774810d24908a"
|
||||
|
||||
[[package]]
|
||||
name = "size_of_test"
|
||||
|
@ -4688,9 +4688,9 @@ checksum = "75ce4f9dc4a41b4c3476cc925f1efb11b66df373a8fde5d4b8915fa91b5d995e"
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -4906,9 +4906,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4960,9 +4960,9 @@ checksum = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4"
|
|||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.0"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834"
|
||||
checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
|
@ -5009,24 +5009,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thin-vec"
|
||||
version = "0.2.2"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a33c69726da418b3ee54fedf0adf26ae4bf2174539025b1df0819420b5a8417"
|
||||
checksum = "0579a04d7334e62fa087222544f379bbe99d4c9b2f13f2b4737f717a1ea627ea"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.25"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.25"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -5079,13 +5079,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.1.11"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895"
|
||||
checksum = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5"
|
||||
dependencies = [
|
||||
"bytes 0.4.12",
|
||||
"futures 0.1.31",
|
||||
"mio 0.6.23",
|
||||
"num_cpus",
|
||||
"tokio-codec",
|
||||
"tokio-current-thread",
|
||||
"tokio-executor",
|
||||
|
@ -5216,11 +5217,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-timer"
|
||||
version = "0.2.11"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e"
|
||||
checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.6.6",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures 0.1.31",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
|
@ -5320,9 +5321,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.14.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "uluru"
|
||||
|
@ -5379,9 +5380,9 @@ checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.5"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
checksum = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
|
@ -5450,9 +5451,9 @@ version = "0.2.999"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "viaduct"
|
||||
|
@ -5499,9 +5500,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "warp"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54cd1e2b3eb3539284d88b76a9afcf5e20f2ef2fab74db5b21a1c30d7d945e82"
|
||||
checksum = "0e95175b7a927258ecbb816bdada3cc469cb68593e7940b96a60f4af366a9970"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"futures 0.3.19",
|
||||
|
@ -5560,18 +5561,20 @@ checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65"
|
|||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "38.0.1"
|
||||
version = "39.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae0d7b256bef26c898fa7344a2d627e8499f5a749432ce0a05eae1a64ff0c271"
|
||||
checksum = "e9bbbd53432b267421186feee3e52436531fa69a7cfee9403f5204352df3dd05"
|
||||
dependencies = [
|
||||
"leb128",
|
||||
"memchr",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wat"
|
||||
version = "1.0.40"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcfaeb27e2578d2c6271a45609f4a055e6d7ba3a12eff35b1fd5ba147bdf046"
|
||||
checksum = "ab98ed25494f97c69f28758617f27c3e92e5336040b5c3a14634f2dd3fe61830"
|
||||
dependencies = [
|
||||
"wast",
|
||||
]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"4057136f408f566a2c06bcce49711d67bedcc8ce7a49351538086503afe59762","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"9209682116de84bb9cc7be6ccf44478b46b909c7857f9e186d90bcff522af864","benches/bench.rs":"5dd3181a97b772e5691d4e6a48e00447250fa893fd63e49d154b519bc1b85fb9","src/ext.rs":"a9fed3a1a4c9d3f2de717ba808af99291b995db2cbf8067f4b6927c39cc62bc6","src/format.rs":"a9c3e3a333c6dacf6e330d02b4c726862e273df1c2c6be6da199049cd1e521db","src/ident_fragment.rs":"3ad27e331af8b54a4b97d19e7ae2bb45e01fb51dc410b24c083345ba6a0b20a8","src/lib.rs":"9c423facea42fe5c63763ba9a269d3f119865d43b4be16cb767ade7659e9356b","src/runtime.rs":"9257f094aefaefa4cf0653c39b5b72bb1922d8b8ac5f5cd45efb29e33acd0b98","src/spanned.rs":"adc0ed742ad17327c375879472d435cea168c208c303f53eb93cb2c0f10f3650","src/to_tokens.rs":"a351a680577d520ebb35905633c77533e8bc4b20642a5c438a51c94b2cc85145","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test.rs":"e2e829990115b51946d4776ade8eb65f3be1b9398b364bd3cfd4e1969b3a13be","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"bd6a510c807eeda4c2207006d303bcc4bdb59b6122614d16af339ce1ac595449","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"a0176a2091928037bba14a659d9619117b57112a4640e86466434a2a9cd2e362","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"19287dc8cba743d89996c2d3ded0d5df292f591e6c148a92ea5e9e23d1250837","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"fb595f24e0a133f705cf585692206ed9dce59b2872cc11eed9bf0ebc184c1d20","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"2ed46f3d6975cc48852b63ece071fd170628c8bd4a4e89e3bb7b156dd139248b","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"49991d2b634c8620eb7c76653e2c546223baa473031b0fb4784eb2355f8e6b65","tests/ui/wrong-type-span.rs":"5f310cb7fde3ef51bad01e7f286d244e3b6e67396cd2ea7eab77275c9d902699","tests/ui/wrong-type-span.stderr":"6672d2c5995fe188228c2b24630a3ad658c27383accc03cdf90c30923eaf6906"},"package":"38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"}
|
||||
{"files":{"Cargo.toml":"c4d90730d45d60e14b3848cd2a5a897463ec7d9381fd3c47affc12942da61213","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"9209682116de84bb9cc7be6ccf44478b46b909c7857f9e186d90bcff522af864","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"a9fed3a1a4c9d3f2de717ba808af99291b995db2cbf8067f4b6927c39cc62bc6","src/format.rs":"c9afa364ab1c9ac0f4cc500dc648559cfdb335c1cdf721f513c72d89d7eb968a","src/ident_fragment.rs":"3ad27e331af8b54a4b97d19e7ae2bb45e01fb51dc410b24c083345ba6a0b20a8","src/lib.rs":"7c8e4034c3179f5c50c70a15229a108da2fdea8d54a5a9bf0e332640ec5edb95","src/runtime.rs":"da0db0c8205d58d016b743019535058fe688baf6c9124a21fcf0c472a81f8265","src/spanned.rs":"adc0ed742ad17327c375879472d435cea168c208c303f53eb93cb2c0f10f3650","src/to_tokens.rs":"a351a680577d520ebb35905633c77533e8bc4b20642a5c438a51c94b2cc85145","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/test.rs":"a8f5a0e85854dc0232686989a7f451bb5baea3b5d48c80251da46442015b084b","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"833ccb8e0b7f5327eaba20d2f1975c63c8d152a5da9bf7be50e874fd617263dc","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"4f1dee2aed73362fa761b17430c34d7d050f03cedb49dbe6ef51c456a03c07af","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"a731b784d867ad1503c56511ef4c25f5938a6aab86196df0e7196df5ac08c2d6","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"ada583e7f9043521e0dbfc013fda9d63853acb982901ee73c4481814bc522610","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"3f04500a826311e60da500d165005e6f4c6438caaa84f32288771010c232c6ce","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"b17b74b25e7fb2e37593a9c11755be033a2d8fd44090f74124c872d91154d7e7","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"c986de5cb858272636c9e36ae5f57e5ee13589d4f1a73a050b21824010314f8d"},"package":"47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"}
|
|
@ -13,8 +13,9 @@
|
|||
edition = "2018"
|
||||
rust-version = "1.31"
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
version = "1.0.14"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
autobenches = false
|
||||
description = "Quasi-quoting macro quote!(...)"
|
||||
documentation = "https://docs.rs/quote/"
|
||||
readme = "README.md"
|
||||
|
@ -25,13 +26,13 @@ repository = "https://github.com/dtolnay/quote"
|
|||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
[dependencies.proc-macro2]
|
||||
version = "1.0.20"
|
||||
version = "1.0.36"
|
||||
default-features = false
|
||||
[dev-dependencies.rustversion]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.trybuild]
|
||||
version = "1.0.19"
|
||||
version = "1.0.52"
|
||||
features = ["diff"]
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
use quote::quote;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_impl(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
quote! {
|
||||
impl<'de> _serde::Deserialize<'de> for Response {
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
#[allow(non_camel_case_types)]
|
||||
enum __Field {
|
||||
__field0,
|
||||
__field1,
|
||||
__ignore,
|
||||
}
|
||||
struct __FieldVisitor;
|
||||
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
|
||||
type Value = __Field;
|
||||
fn expecting(
|
||||
&self,
|
||||
__formatter: &mut _serde::export::Formatter,
|
||||
) -> _serde::export::fmt::Result {
|
||||
_serde::export::Formatter::write_str(__formatter, "field identifier")
|
||||
}
|
||||
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
|
||||
where
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
0u64 => _serde::export::Ok(__Field::__field0),
|
||||
1u64 => _serde::export::Ok(__Field::__field1),
|
||||
_ => _serde::export::Err(_serde::de::Error::invalid_value(
|
||||
_serde::de::Unexpected::Unsigned(__value),
|
||||
&"field index 0 <= i < 2",
|
||||
)),
|
||||
}
|
||||
}
|
||||
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
|
||||
where
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
"id" => _serde::export::Ok(__Field::__field0),
|
||||
"s" => _serde::export::Ok(__Field::__field1),
|
||||
_ => _serde::export::Ok(__Field::__ignore),
|
||||
}
|
||||
}
|
||||
fn visit_bytes<__E>(
|
||||
self,
|
||||
__value: &[u8],
|
||||
) -> _serde::export::Result<Self::Value, __E>
|
||||
where
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
b"id" => _serde::export::Ok(__Field::__field0),
|
||||
b"s" => _serde::export::Ok(__Field::__field1),
|
||||
_ => _serde::export::Ok(__Field::__ignore),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'de> _serde::Deserialize<'de> for __Field {
|
||||
#[inline]
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de> {
|
||||
marker: _serde::export::PhantomData<Response>,
|
||||
lifetime: _serde::export::PhantomData<&'de ()>,
|
||||
}
|
||||
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
|
||||
type Value = Response;
|
||||
fn expecting(
|
||||
&self,
|
||||
__formatter: &mut _serde::export::Formatter,
|
||||
) -> _serde::export::fmt::Result {
|
||||
_serde::export::Formatter::write_str(__formatter, "struct Response")
|
||||
}
|
||||
#[inline]
|
||||
fn visit_seq<__A>(
|
||||
self,
|
||||
mut __seq: __A,
|
||||
) -> _serde::export::Result<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::SeqAccess<'de>,
|
||||
{
|
||||
let __field0 =
|
||||
match try!(_serde::de::SeqAccess::next_element::<u64>(&mut __seq)) {
|
||||
_serde::export::Some(__value) => __value,
|
||||
_serde::export::None => {
|
||||
return _serde::export::Err(_serde::de::Error::invalid_length(
|
||||
0usize,
|
||||
&"struct Response with 2 elements",
|
||||
));
|
||||
}
|
||||
};
|
||||
let __field1 =
|
||||
match try!(_serde::de::SeqAccess::next_element::<String>(&mut __seq)) {
|
||||
_serde::export::Some(__value) => __value,
|
||||
_serde::export::None => {
|
||||
return _serde::export::Err(_serde::de::Error::invalid_length(
|
||||
1usize,
|
||||
&"struct Response with 2 elements",
|
||||
));
|
||||
}
|
||||
};
|
||||
_serde::export::Ok(Response {
|
||||
id: __field0,
|
||||
s: __field1,
|
||||
})
|
||||
}
|
||||
#[inline]
|
||||
fn visit_map<__A>(
|
||||
self,
|
||||
mut __map: __A,
|
||||
) -> _serde::export::Result<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::export::Option<u64> = _serde::export::None;
|
||||
let mut __field1: _serde::export::Option<String> = _serde::export::None;
|
||||
while let _serde::export::Some(__key) =
|
||||
try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map))
|
||||
{
|
||||
match __key {
|
||||
__Field::__field0 => {
|
||||
if _serde::export::Option::is_some(&__field0) {
|
||||
return _serde::export::Err(
|
||||
<__A::Error as _serde::de::Error>::duplicate_field("id"),
|
||||
);
|
||||
}
|
||||
__field0 = _serde::export::Some(
|
||||
try!(_serde::de::MapAccess::next_value::<u64>(&mut __map)),
|
||||
);
|
||||
}
|
||||
__Field::__field1 => {
|
||||
if _serde::export::Option::is_some(&__field1) {
|
||||
return _serde::export::Err(
|
||||
<__A::Error as _serde::de::Error>::duplicate_field("s"),
|
||||
);
|
||||
}
|
||||
__field1 = _serde::export::Some(
|
||||
try!(_serde::de::MapAccess::next_value::<String>(&mut __map)),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let _ = try!(_serde::de::MapAccess::next_value::<
|
||||
_serde::de::IgnoredAny,
|
||||
>(&mut __map));
|
||||
}
|
||||
}
|
||||
}
|
||||
let __field0 = match __field0 {
|
||||
_serde::export::Some(__field0) => __field0,
|
||||
_serde::export::None => try!(_serde::private::de::missing_field("id")),
|
||||
};
|
||||
let __field1 = match __field1 {
|
||||
_serde::export::Some(__field1) => __field1,
|
||||
_serde::export::None => try!(_serde::private::de::missing_field("s")),
|
||||
};
|
||||
_serde::export::Ok(Response {
|
||||
id: __field0,
|
||||
s: __field1,
|
||||
})
|
||||
}
|
||||
}
|
||||
const FIELDS: &'static [&'static str] = &["id", "s"];
|
||||
_serde::Deserializer::deserialize_struct(
|
||||
__deserializer,
|
||||
"Response",
|
||||
FIELDS,
|
||||
__Visitor {
|
||||
marker: _serde::export::PhantomData::<Response>,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
components = ["rust-src"]
|
|
@ -11,10 +11,10 @@
|
|||
/// of format types to traits is:
|
||||
///
|
||||
/// * `{}` ⇒ [`IdentFragment`]
|
||||
/// * `{:o}` ⇒ [`Octal`](`std::fmt::Octal`)
|
||||
/// * `{:x}` ⇒ [`LowerHex`](`std::fmt::LowerHex`)
|
||||
/// * `{:X}` ⇒ [`UpperHex`](`std::fmt::UpperHex`)
|
||||
/// * `{:b}` ⇒ [`Binary`](`std::fmt::Binary`)
|
||||
/// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)
|
||||
/// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)
|
||||
/// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)
|
||||
/// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)
|
||||
///
|
||||
/// See [`std::fmt`] for more information.
|
||||
///
|
||||
|
@ -29,7 +29,8 @@
|
|||
/// unsigned integers and strings.
|
||||
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
|
||||
///
|
||||
/// [`Ident`]: `proc_macro2::Ident`
|
||||
/// [`IdentFragment`]: crate::IdentFragment
|
||||
/// [`Ident`]: proc_macro2::Ident
|
||||
///
|
||||
/// <br>
|
||||
///
|
||||
|
@ -59,8 +60,8 @@
|
|||
/// format_ident!("MyIdent", span = my_span);
|
||||
/// ```
|
||||
///
|
||||
/// [`Span`]: `proc_macro2::Span`
|
||||
/// [`Span::call_site`]: `proc_macro2::Span::call_site`
|
||||
/// [`Span`]: proc_macro2::Span
|
||||
/// [`Span::call_site`]: proc_macro2::Span::call_site
|
||||
///
|
||||
/// <p><br></p>
|
||||
///
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
//! ```
|
||||
|
||||
// Quote types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/quote/1.0.10")]
|
||||
#![doc(html_root_url = "https://docs.rs/quote/1.0.14")]
|
||||
#![allow(
|
||||
clippy::doc_markdown,
|
||||
clippy::missing_errors_doc,
|
||||
|
@ -1066,6 +1066,14 @@ macro_rules! quote_token {
|
|||
$crate::__private::push_ident(&mut $tokens, stringify!($ident));
|
||||
};
|
||||
|
||||
($tokens:ident $lifetime:lifetime) => {
|
||||
$crate::__private::push_lifetime(&mut $tokens, stringify!($lifetime));
|
||||
};
|
||||
|
||||
($tokens:ident _) => {
|
||||
$crate::__private::push_underscore(&mut $tokens);
|
||||
};
|
||||
|
||||
($tokens:ident $other:tt) => {
|
||||
$crate::__private::parse(&mut $tokens, stringify!($other));
|
||||
};
|
||||
|
@ -1281,6 +1289,14 @@ macro_rules! quote_token_spanned {
|
|||
$crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident));
|
||||
};
|
||||
|
||||
($tokens:ident $span:ident $lifetime:lifetime) => {
|
||||
$crate::__private::push_lifetime_spanned(&mut $tokens, $span, stringify!($lifetime));
|
||||
};
|
||||
|
||||
($tokens:ident $span:ident _) => {
|
||||
$crate::__private::push_underscore_spanned(&mut $tokens, $span);
|
||||
};
|
||||
|
||||
($tokens:ident $span:ident $other:tt) => {
|
||||
$crate::__private::parse_spanned(&mut $tokens, $span, stringify!($other));
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{IdentFragment, ToTokens, TokenStreamExt};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::ops::BitOr;
|
||||
|
||||
pub use proc_macro2::*;
|
||||
|
@ -178,15 +179,29 @@ pub fn push_group_spanned(
|
|||
|
||||
pub fn parse(tokens: &mut TokenStream, s: &str) {
|
||||
let s: TokenStream = s.parse().expect("invalid token stream");
|
||||
tokens.extend(s);
|
||||
tokens.extend(iter::once(s));
|
||||
}
|
||||
|
||||
pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
|
||||
let s: TokenStream = s.parse().expect("invalid token stream");
|
||||
tokens.extend(s.into_iter().map(|mut t| {
|
||||
t.set_span(span);
|
||||
t
|
||||
}));
|
||||
tokens.extend(s.into_iter().map(|t| respan_token_tree(t, span)));
|
||||
}
|
||||
|
||||
// Token tree with every span replaced by the given one.
|
||||
fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
|
||||
match &mut token {
|
||||
TokenTree::Group(g) => {
|
||||
let stream = g
|
||||
.stream()
|
||||
.into_iter()
|
||||
.map(|token| respan_token_tree(token, span))
|
||||
.collect();
|
||||
*g = Group::new(g.delimiter(), stream);
|
||||
g.set_span(span);
|
||||
}
|
||||
other => other.set_span(span),
|
||||
}
|
||||
token
|
||||
}
|
||||
|
||||
pub fn push_ident(tokens: &mut TokenStream, s: &str) {
|
||||
|
@ -213,6 +228,70 @@ pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
|
||||
struct Lifetime<'a> {
|
||||
name: &'a str,
|
||||
state: u8,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Lifetime<'a> {
|
||||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.state {
|
||||
0 => {
|
||||
self.state = 1;
|
||||
Some(TokenTree::Punct(Punct::new('\'', Spacing::Joint)))
|
||||
}
|
||||
1 => {
|
||||
self.state = 2;
|
||||
Some(TokenTree::Ident(Ident::new(self.name, Span::call_site())))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokens.extend(Lifetime {
|
||||
name: &lifetime[1..],
|
||||
state: 0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
|
||||
struct Lifetime<'a> {
|
||||
name: &'a str,
|
||||
span: Span,
|
||||
state: u8,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Lifetime<'a> {
|
||||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.state {
|
||||
0 => {
|
||||
self.state = 1;
|
||||
let mut apostrophe = Punct::new('\'', Spacing::Joint);
|
||||
apostrophe.set_span(self.span);
|
||||
Some(TokenTree::Punct(apostrophe))
|
||||
}
|
||||
1 => {
|
||||
self.state = 2;
|
||||
Some(TokenTree::Ident(Ident::new(self.name, self.span)))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokens.extend(Lifetime {
|
||||
name: &lifetime[1..],
|
||||
span,
|
||||
state: 0,
|
||||
});
|
||||
}
|
||||
|
||||
macro_rules! push_punct {
|
||||
($name:ident $spanned:ident $char1:tt) => {
|
||||
pub fn $name(tokens: &mut TokenStream) {
|
||||
|
@ -303,6 +382,14 @@ push_punct!(push_star push_star_spanned '*');
|
|||
push_punct!(push_sub push_sub_spanned '-');
|
||||
push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
|
||||
|
||||
pub fn push_underscore(tokens: &mut TokenStream) {
|
||||
push_underscore_spanned(tokens, Span::call_site());
|
||||
}
|
||||
|
||||
pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
|
||||
tokens.append(Ident::new("_", span));
|
||||
}
|
||||
|
||||
// Helper method for constructing identifiers from the `format_ident!` macro,
|
||||
// handling `r#` prefixes.
|
||||
//
|
||||
|
|
|
@ -176,10 +176,11 @@ fn test_integer() {
|
|||
let uusize = 1usize;
|
||||
|
||||
let tokens = quote! {
|
||||
1 1i32 1u256
|
||||
#ii8 #ii16 #ii32 #ii64 #ii128 #iisize
|
||||
#uu8 #uu16 #uu32 #uu64 #uu128 #uusize
|
||||
};
|
||||
let expected = "- 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize";
|
||||
let expected = "1 1i32 1u256 - 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
}
|
||||
|
||||
|
@ -229,6 +230,31 @@ fn test_string() {
|
|||
assert_eq!(expected, tokens.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interpolated_literal() {
|
||||
macro_rules! m {
|
||||
($literal:literal) => {
|
||||
quote!($literal)
|
||||
};
|
||||
}
|
||||
|
||||
let tokens = m!(1);
|
||||
let expected = "1";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
|
||||
let tokens = m!(-1);
|
||||
let expected = "- 1";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
|
||||
let tokens = m!(true);
|
||||
let expected = "true";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
|
||||
let tokens = m!(-true);
|
||||
let expected = "- true";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ident() {
|
||||
let foo = Ident::new("Foo", Span::call_site());
|
||||
|
@ -238,6 +264,13 @@ fn test_ident() {
|
|||
assert_eq!(expected, tokens.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_underscore() {
|
||||
let tokens = quote!(let _;);
|
||||
let expected = "let _ ;";
|
||||
assert_eq!(expected, tokens.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duplicate() {
|
||||
let ch = 'x';
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/does-not-have-iter-interpolated-dup.rs:8:5
|
||||
--> tests/ui/does-not-have-iter-interpolated-dup.rs:8:5
|
||||
|
|
||||
8 | quote!(#(#nonrep #nonrep)*);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
|
||||
| expected due to this
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/does-not-have-iter-interpolated.rs:8:5
|
||||
--> tests/ui/does-not-have-iter-interpolated.rs:8:5
|
||||
|
|
||||
8 | quote!(#(#nonrep)*);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
|
||||
| expected due to this
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/does-not-have-iter-separated.rs:4:5
|
||||
--> tests/ui/does-not-have-iter-separated.rs:4:5
|
||||
|
|
||||
4 | quote!(#(a b),*);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
|
||||
| expected due to this
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/does-not-have-iter.rs:4:5
|
||||
--> tests/ui/does-not-have-iter.rs:4:5
|
||||
|
|
||||
4 | quote!(#(a b)*);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
|
||||
| expected due to this
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied
|
||||
--> $DIR/not-quotable.rs:6:13
|
||||
|
|
||||
6 | let _ = quote! { #ip };
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the trait `ToTokens` is not implemented for `Ipv4Addr`
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by `to_tokens`
|
||||
--> $DIR/to_tokens.rs:55:5
|
||||
|
|
||||
55 | fn to_tokens(&self, tokens: &mut TokenStream);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
--> tests/ui/not-quotable.rs:6:13
|
||||
|
|
||||
6 | let _ = quote! { #ip };
|
||||
| ^^^^^^^^^^^^^^ the trait `ToTokens` is not implemented for `Ipv4Addr`
|
||||
|
|
||||
= note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
@ -1,25 +1,47 @@
|
|||
error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied
|
||||
--> $DIR/not-repeatable.rs:7:13
|
||||
|
|
||||
3 | struct Ipv4Addr;
|
||||
| ----------------
|
||||
| |
|
||||
| method `quote_into_iter` not found for this
|
||||
| doesn't satisfy `Ipv4Addr: Iterator`
|
||||
| doesn't satisfy `Ipv4Addr: ToTokens`
|
||||
| doesn't satisfy `Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
| doesn't satisfy `Ipv4Addr: quote::__private::ext::RepToTokensExt`
|
||||
--> tests/ui/not-repeatable.rs:7:13
|
||||
|
|
||||
3 | struct Ipv4Addr;
|
||||
| ----------------
|
||||
| |
|
||||
| method `quote_into_iter` not found for this
|
||||
| doesn't satisfy `Ipv4Addr: Iterator`
|
||||
| doesn't satisfy `Ipv4Addr: ToTokens`
|
||||
| doesn't satisfy `Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
| doesn't satisfy `Ipv4Addr: quote::__private::ext::RepToTokensExt`
|
||||
...
|
||||
7 | let _ = quote! { #(#ip)* };
|
||||
| ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`Ipv4Addr: Iterator`
|
||||
which is required by `Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
`&Ipv4Addr: Iterator`
|
||||
which is required by `&Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
`Ipv4Addr: ToTokens`
|
||||
which is required by `Ipv4Addr: quote::__private::ext::RepToTokensExt`
|
||||
`&mut Ipv4Addr: Iterator`
|
||||
which is required by `&mut Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
= note: this error originates in the macro `$crate::quote_bind_into_iter` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
7 | let _ = quote! { #(#ip)* };
|
||||
| ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`Ipv4Addr: Iterator`
|
||||
which is required by `Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
`&Ipv4Addr: Iterator`
|
||||
which is required by `&Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
`Ipv4Addr: ToTokens`
|
||||
which is required by `Ipv4Addr: quote::__private::ext::RepToTokensExt`
|
||||
`&mut Ipv4Addr: Iterator`
|
||||
which is required by `&mut Ipv4Addr: quote::__private::ext::RepIteratorExt`
|
||||
note: the following traits must be implemented
|
||||
--> $RUST/core/src/iter/traits/iterator.rs
|
||||
|
|
||||
| / pub trait Iterator {
|
||||
| | /// The type of the elements being iterated over.
|
||||
| | #[stable(feature = "rust1", since = "1.0.0")]
|
||||
| | type Item;
|
||||
... |
|
||||
| | }
|
||||
| | }
|
||||
| |__^
|
||||
|
|
||||
::: src/to_tokens.rs
|
||||
|
|
||||
| / pub trait ToTokens {
|
||||
| | /// Write `self` to the given `TokenStream`.
|
||||
| | ///
|
||||
| | /// The token append methods provided by the [`TokenStreamExt`] extension
|
||||
... |
|
||||
| | }
|
||||
| | }
|
||||
| |_^
|
||||
= note: this error originates in the macro `$crate::quote_bind_into_iter` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
@ -2,6 +2,6 @@ use quote::quote_spanned;
|
|||
|
||||
fn main() {
|
||||
let span = "";
|
||||
let x = 0;
|
||||
let x = 0i32;
|
||||
quote_spanned!(span=> #x);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/wrong-type-span.rs:6:20
|
||||
--> tests/ui/wrong-type-span.rs:6:20
|
||||
|
|
||||
6 | quote_spanned!(span=> #x);
|
||||
| ---------------^^^^-------
|
||||
| ---------------^^^^------
|
||||
| | |
|
||||
| | expected struct `Span`, found `&str`
|
||||
| expected due to this
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"BUILD.md":"ab838b9ec445718ee6cdfdf98c7dc8b360d2f62f851f94b4637c06d078a5df7a","CODE_OF_CONDUCT.md":"64765f10290cfce7191b4208cb21698b708a118568f5016602cccc304846a09a","CONTRIBUTING.md":"471d6281fb5038e17e32d3b4450aacf542a396709605aa170e07d3971d70b9c1","Cargo.toml":"401b67e4e2aced945393f04944cb0e532f3619643a89647f17dedb474aeed7ac","LICENSE":"f8218253704e32441cafea1b9b3bcb2c6a3c51c5553cd8513d179290202bccb2","Makefile.toml":"d013f2e6c2dc8289ec9f90021578b27186a6e9c76ce6b1c98eecc5873fb2f867","README.md":"8cf60ff2a014822d4dd29713bea7f05eed5a82a979d0e14255eb6c2f8ef66db1","VERSION.md":"286017fd909384211b7aa66ff2a5f4b0f5316b3c508dde29d139dfc77704697a","benches/comparison.rs":"e8b14531b129acb8ffca2dd44565d9160f510ec38abd32fc49fd4e2386067e25","benches/lib_benches.rs":"1525a2b3424e04da73153a0a57f8ee6e3c7ba93f3d847940ee596be57d469248","rustfmt.toml":"f33bda44a494d17c95b7bc1b3dd88c203030b75be766f3a7f9b63ef45d960bb0","src/constants.rs":"b40f50e9216ae1ae8a86debbfc6e8f914f4032631146997b5c0edab7d00f0233","src/decimal.rs":"da3c9f479ceceada3cb0cc5de5b3e03c91d4f892adaa70a15df4775180541c5f","src/error.rs":"cc4c55c4bd68dbb14e4ed866d25a8ec24282941b747430074a162864007dcec1","src/fuzz.rs":"86c07d8d541b9ee92a51275993b686902712f94c30785ba93f38997f3569e700","src/lib.rs":"9f6d788018b0a57b315d52ae47d0b56b04854c9270cfdfcfebfc59e69430c7b6","src/maths.rs":"3419ceeee33a55d022b4376a30d600b101f424a2150ea3511793194aa41e022b","src/mysql.rs":"70bed7f41b9f26fee0f9bcce785f230f702d6eafd9cf793514990c9b75f52e02","src/ops.rs":"4d426a35f73b0b69cbceee6e01c6eff59b8cc09aab7c885570aea52d8f258f66","src/ops/add.rs":"a85b6214be92a5563e8bb4a936275d8de094507d77384c9184d63583a78b3f55","src/ops/array.rs":"62c8651cfc30d5e665c02ceaec1eb0ed1c72d167712f4c78dcf373cb7f9d23b6","src/ops/cmp.rs":"95437401daf93d60425c388fc243e52ad5570cfe6c5d818b5aa144759a5f2ef1","src/ops/common.rs":"6d48ecfa4796a38cb9d4c48f50ffed5d1ee79ba8e168a175615b6fe97194b7c2","src/ops/div.rs":"6b1e90b383293eb51f20f22846002a61f17211f7791860d4e9d6f82ad940fb87","src/ops/legacy.rs":"e2075b42bec4a4d830172bcde9d5a67bdbb71573f1fe241fccb96379e755fcbd","src/ops/mul.rs":"b0bb69461b4934cb53c49e105d21da8aa661e1215e8797b8fdc64564df431d92","src/ops/rem.rs":"125d64e9425effd01d4ff400f811f43ef76bf846b6823195059648fdf004b592","src/postgres.rs":"de2cebb731f8c9e6070fd2b7bfcc29af3aa31b34d2dd8db6d846edaa27765194","src/rocket.rs":"4d05f292281e4d463abeba603b07ea460065cb1b8ec1c6dafdb4e41f7b89e828","src/serde.rs":"6075142718d273e5d734e89efff26c150f248e0cd0906bd9dd730f2a68c5acb3","src/str.rs":"d4857b5c934e4c6e981d0fdc01a37a14ae060e565883903cf4b93fbcf089f88f","tests/decimal_tests.rs":"de9c45a038e4924688b8d025a5186550e05e60bc78a33e9101a107f84dd06f99","tests/macros.rs":"f4e1ade99bf8a7aaf2a2d4ee557df5b0b32266a349daf59b2e8b1ae7bc72599c"},"package":"71b5a9625a7e6060b23db692facf49082cc78889a7e6ac94a735356ae49db4b0"}
|
||||
{"files":{"BUILD.md":"93ca669e27faec1ecfe742fac29f1468eca94d43d8de9be4f5b9e72ffca448c8","CODE_OF_CONDUCT.md":"64765f10290cfce7191b4208cb21698b708a118568f5016602cccc304846a09a","CONTRIBUTING.md":"471d6281fb5038e17e32d3b4450aacf542a396709605aa170e07d3971d70b9c1","Cargo.toml":"f34f31d0df0954518f8c1225ee7a1256addf662414e0c1e83c2f952d8475eb1f","LICENSE":"f8218253704e32441cafea1b9b3bcb2c6a3c51c5553cd8513d179290202bccb2","Makefile.toml":"e6220e5e41f7e088df9aa213995c2075bd7f632641605fafface837e5ed781a8","README.md":"be937c40a9bca8ca563bde23228fb8354cd6fab86c25b196c9997f6769a14202","VERSION.md":"ebc17820d940b766c0365864bd75ca5b3e6b6af4722ade7ede9405314ba828c1","benches/comparison.rs":"e8b14531b129acb8ffca2dd44565d9160f510ec38abd32fc49fd4e2386067e25","benches/lib_benches.rs":"1525a2b3424e04da73153a0a57f8ee6e3c7ba93f3d847940ee596be57d469248","rustfmt.toml":"f33bda44a494d17c95b7bc1b3dd88c203030b75be766f3a7f9b63ef45d960bb0","src/constants.rs":"5a31626a234e4bb1f06752d7db6ebb39a543c5e0df1e929dd0032689ef7aaa1f","src/decimal.rs":"3c264bf0f838c6e339f2b019fbb88d3b7465372cce3a9c8fd8e35c60cc15b5c9","src/error.rs":"86ca653d2222f36b815613c478377e006e5c994731b533341bd75d27e9cd7403","src/fuzz.rs":"86c07d8d541b9ee92a51275993b686902712f94c30785ba93f38997f3569e700","src/lib.rs":"d4b9a3105172a48a31b96908f0daf82f760fcc9390e8dd5fe54a88e23b88369b","src/maths.rs":"3419ceeee33a55d022b4376a30d600b101f424a2150ea3511793194aa41e022b","src/mysql.rs":"1995123011bda5ac6a7d2df5885a568dfdfecd9897ab8d89205817877a242cb3","src/ops.rs":"4d426a35f73b0b69cbceee6e01c6eff59b8cc09aab7c885570aea52d8f258f66","src/ops/add.rs":"a85b6214be92a5563e8bb4a936275d8de094507d77384c9184d63583a78b3f55","src/ops/array.rs":"17a1af576390c8f33ed6c13e1b62722eeaa24c0c0086fb951def6d5dacfdc1cd","src/ops/cmp.rs":"95437401daf93d60425c388fc243e52ad5570cfe6c5d818b5aa144759a5f2ef1","src/ops/common.rs":"6d48ecfa4796a38cb9d4c48f50ffed5d1ee79ba8e168a175615b6fe97194b7c2","src/ops/div.rs":"6b1e90b383293eb51f20f22846002a61f17211f7791860d4e9d6f82ad940fb87","src/ops/legacy.rs":"08bc45454b1815a592cc2fd02df8c50bec36c831ab7af098018e29dfc81f0ec4","src/ops/mul.rs":"b0bb69461b4934cb53c49e105d21da8aa661e1215e8797b8fdc64564df431d92","src/ops/rem.rs":"125d64e9425effd01d4ff400f811f43ef76bf846b6823195059648fdf004b592","src/postgres.rs":"a95ac5e58e24fa2702f540b4f34c1d6508242a25dc0678dd2af4137b58739ab4","src/rocket.rs":"4d05f292281e4d463abeba603b07ea460065cb1b8ec1c6dafdb4e41f7b89e828","src/serde.rs":"8590f05a7d3b3389e775c0637f155a2b1a068f8318b95ba70a3395a16dacb4e5","src/str.rs":"f75d1a08c73872cb8018e2bcb002b527d3520e78d0a0f60373f86e142dc307d4","tests/decimal_tests.rs":"0e7efedc5b93586fa3e9f6aaa9a4b9ad0a166b678c18fcca87879cedf0002791","tests/macros.rs":"f4e1ade99bf8a7aaf2a2d4ee557df5b0b32266a349daf59b2e8b1ae7bc72599c"},"package":"e0593ce4677e3800ddafb3de917e8397b1348e06e688128ade722d88fbe11ebf"}
|
|
@ -103,7 +103,7 @@ run by using `makers fuzz`.
|
|||
In order to ensure that Rust Decimal runs quickly, a number of benchmarks have been created and can be executed using
|
||||
`makers bench`.
|
||||
|
||||
When adding new benchmarking configurations please ensure that you add a corresponding `Makefile.toml` task to capture the
|
||||
When adding new benchmarking configurations, please ensure that you add a corresponding `Makefile.toml` task to capture the
|
||||
updated configuration.
|
||||
|
||||
## Code Coverage
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "rust_decimal"
|
||||
version = "1.18.0"
|
||||
version = "1.20.0"
|
||||
authors = ["Paul Mason <paul@form1.co.nz>"]
|
||||
exclude = ["tests/generated/*"]
|
||||
description = "A Decimal Implementation written in pure Rust suitable for financial calculations."
|
||||
|
@ -35,7 +35,7 @@ optional = true
|
|||
default-features = false
|
||||
|
||||
[dependencies.arrayvec]
|
||||
version = "0.5"
|
||||
version = "0.7"
|
||||
default-features = false
|
||||
|
||||
[dependencies.byteorder]
|
||||
|
@ -98,6 +98,11 @@ version = "1"
|
|||
[dev-dependencies.futures]
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.serde_derive]
|
||||
version = "1.0"
|
||||
|
||||
|
@ -120,9 +125,12 @@ maths = []
|
|||
maths-nopanic = ["maths"]
|
||||
rocket-traits = ["rocket"]
|
||||
rust-fuzz = ["arbitrary"]
|
||||
serde-arbitrary-precision = ["serde", "serde_json/arbitrary_precision"]
|
||||
serde-arbitrary-precision = ["serde-with-arbitrary-precision"]
|
||||
serde-bincode = ["serde-str"]
|
||||
serde-float = ["serde"]
|
||||
serde-str = ["serde"]
|
||||
serde-float = ["serde-with-float"]
|
||||
serde-str = ["serde-with-str"]
|
||||
serde-with-arbitrary-precision = ["serde", "serde_json/arbitrary_precision"]
|
||||
serde-with-float = ["serde"]
|
||||
serde-with-str = ["serde"]
|
||||
std = []
|
||||
tokio-pg = ["db-tokio-postgres"]
|
||||
|
|
|
@ -133,7 +133,10 @@ dependencies = [
|
|||
"test-serde-str",
|
||||
"test-serde-str-float",
|
||||
"test-serde-arbitrary-precision",
|
||||
"test-serde-arbitrary-precision-float"
|
||||
"test-serde-arbitrary-precision-float",
|
||||
"test-serde-with-arbitrary-precision",
|
||||
"test-serde-with-float",
|
||||
"test-serde-with-str",
|
||||
]
|
||||
|
||||
[tasks.test-macros]
|
||||
|
@ -225,3 +228,15 @@ args = ["test", "--workspace", "--tests", "--features=serde-arbitrary-precision"
|
|||
[tasks.test-serde-arbitrary-precision-float]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--tests", "--features=serde-arbitrary-precision,serde-float", "serde", "--", "--skip", "generated"]
|
||||
|
||||
[tasks.test-serde-with-arbitrary-precision]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--tests", "--features=serde-with-arbitrary-precision", "serde", "--", "--skip", "generated"]
|
||||
|
||||
[tasks.test-serde-with-float]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--tests", "--features=serde-with-float", "serde", "--", "--skip", "generated"]
|
||||
|
||||
[tasks.test-serde-with-str]
|
||||
command = "cargo"
|
||||
args = ["test", "--workspace", "--tests", "--features=serde-with-str", "serde", "--", "--skip", "generated"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Decimal   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Badge]][docs]
|
||||
# Decimal   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Badge]][docs]
|
||||
|
||||
[Build Status]: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fpaupino%2Frust-decimal%2Fbadge&label=build&logo=none
|
||||
[actions]: https://actions-badge.atrox.dev/paupino/rust-decimal/goto
|
||||
|
@ -17,8 +17,8 @@ To get started, add `rust_decimal` and optionally `rust_decimal_macros` to your
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
rust_decimal = "1.18"
|
||||
rust_decimal_macros = "1.18"
|
||||
rust_decimal = "1.20"
|
||||
rust_decimal_macros = "1.20"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
@ -73,19 +73,30 @@ assert_eq!(total.to_string(), "27.26");
|
|||
|
||||
## Features
|
||||
|
||||
**Behavior / Functionality**
|
||||
|
||||
* [c-repr](#c-repr)
|
||||
* [db-postgres](#db-postgres)
|
||||
* [db-tokio-postgres](#db-tokio-postgres)
|
||||
* [db-diesel-postgres](#db-diesel-postgres)
|
||||
* [db-diesel-mysql](#db-diesel-mysql)
|
||||
* [legacy-ops](#legacy-ops)
|
||||
* [maths](#maths)
|
||||
* [rocket-traits](#rocket-traits)
|
||||
* [rust-fuzz](#rust-fuzz)
|
||||
* [std](#std)
|
||||
|
||||
**Database**
|
||||
|
||||
* [db-postgres](#db-postgres)
|
||||
* [db-tokio-postgres](#db-tokio-postgres)
|
||||
* [db-diesel-postgres](#db-diesel-postgres)
|
||||
* [db-diesel-mysql](#db-diesel-mysql)
|
||||
|
||||
**Serde**
|
||||
|
||||
* [serde-float](#serde-float)
|
||||
* [serde-str](#serde-str)
|
||||
* [serde-arbitrary-precision](#serde-arbitrary-precision)
|
||||
* [std](#std)
|
||||
* [serde-with-float](#serde-with-float)
|
||||
* [serde-with-str](#serde-with-str)
|
||||
* [serde-with-arbitrary-precision](#serde-with-arbitrary-precision)
|
||||
|
||||
### `c-repr`
|
||||
|
||||
|
@ -102,7 +113,7 @@ Enables the tokio postgres module allowing for async communication with PostgreS
|
|||
|
||||
### `db-diesel-postgres`
|
||||
|
||||
Enable `diesel` PostgreSQL support.
|
||||
Enable `diesel` PostgreSQL support.
|
||||
|
||||
### `db-diesel-mysql`
|
||||
|
||||
|
@ -110,18 +121,18 @@ Enable `diesel` MySQL support.
|
|||
|
||||
### `legacy-ops`
|
||||
|
||||
As of `1.10` the algorithms used to perform basic operations have changed which has benefits of significant speed improvements.
|
||||
As of `1.10` the algorithms used to perform basic operations have changed which has benefits of significant speed improvements.
|
||||
To maintain backwards compatibility this can be opted out of by enabling the `legacy-ops` feature.
|
||||
|
||||
### `maths`
|
||||
|
||||
The `maths` feature enables additional complex mathematical functions such as `pow`, `ln`, `enf`, `exp` etc.
|
||||
Documentation detailing the additional functions can be found on the
|
||||
The `maths` feature enables additional complex mathematical functions such as `pow`, `ln`, `enf`, `exp` etc.
|
||||
Documentation detailing the additional functions can be found on the
|
||||
[`MathematicalOps`](https://docs.rs/rust_decimal/latest/rust_decimal/trait.MathematicalOps.html) trait.
|
||||
|
||||
Please note that `ln` and `log10` will panic on invalid input with `checked_ln` and `checked_log10` the preferred functions
|
||||
to curb against this. When the `maths` feature was first developed the library would return `0` on invalid input. To re-enable this
|
||||
non-panicking behavior, please use the feature: `maths-nopanic`.
|
||||
to curb against this. When the `maths` feature was first developed the library would return `0` on invalid input. To re-enable this
|
||||
non-panicking behavior, please use the feature: `maths-nopanic`.
|
||||
|
||||
### `rocket-traits`
|
||||
|
||||
|
@ -133,6 +144,9 @@ Enable `rust-fuzz` support by implementing the `Arbitrary` trait.
|
|||
|
||||
### `serde-float`
|
||||
|
||||
**Note:** it is recommended to use the `serde-with-*` features for greater control. This allows configurability at the data
|
||||
level.
|
||||
|
||||
Enable this so that JSON serialization of `Decimal` types are sent as a float instead of a string (default).
|
||||
|
||||
e.g. with this turned on, JSON serialization would output:
|
||||
|
@ -144,23 +158,66 @@ e.g. with this turned on, JSON serialization would output:
|
|||
|
||||
### `serde-str`
|
||||
|
||||
**Note:** it is recommended to use the `serde-with-*` features for greater control. This allows configurability at the data
|
||||
level.
|
||||
|
||||
This is typically useful for `bincode` or `csv` like implementations.
|
||||
|
||||
Since `bincode` does not specify type information, we need to ensure that a type hint is provided in order to
|
||||
correctly be able to deserialize. Enabling this feature on its own will force deserialization to use `deserialize_str`
|
||||
instead of `deserialize_any`.
|
||||
Since `bincode` does not specify type information, we need to ensure that a type hint is provided in order to
|
||||
correctly be able to deserialize. Enabling this feature on its own will force deserialization to use `deserialize_str`
|
||||
instead of `deserialize_any`.
|
||||
|
||||
If, for some reason, you also have `serde-float` enabled then this will use `deserialize_f64` as a type hint. Because
|
||||
converting to `f64` _loses_ precision, it's highly recommended that you do NOT enable this feature when working with
|
||||
converting to `f64` _loses_ precision, it's highly recommended that you do NOT enable this feature when working with
|
||||
`bincode`. That being said, this will only use 8 bytes so is slightly more efficient in terms of storage size.
|
||||
|
||||
### `serde-arbitrary-precision`
|
||||
|
||||
This is used primarily with `serde_json` and consequently adds it as a "weak dependency". This supports the
|
||||
`arbitrary_precision` feature inside `serde_json` when parsing decimals.
|
||||
**Note:** it is recommended to use the `serde-with-*` features for greater control. This allows configurability at the data
|
||||
level.
|
||||
|
||||
This is used primarily with `serde_json` and consequently adds it as a "weak dependency". This supports the
|
||||
`arbitrary_precision` feature inside `serde_json` when parsing decimals.
|
||||
|
||||
This is recommended when parsing "float" looking data as it will prevent data loss.
|
||||
|
||||
### `serde-with-float`
|
||||
|
||||
Enable this to access the module for serialising `Decimal` types to a float. This can be use in `struct` definitions like so:
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FloatExample {
|
||||
#[serde(with = "rust_decimal::serde::float")]
|
||||
value: Decimal,
|
||||
}
|
||||
```
|
||||
|
||||
### `serde-with-str`
|
||||
|
||||
Enable this to access the module for serialising `Decimal` types to a `String`. This can be use in `struct` definitions like so:
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StrExample {
|
||||
#[serde(with = "rust_decimal::serde::str")]
|
||||
value: Decimal,
|
||||
}
|
||||
```
|
||||
|
||||
### `serde-with-arbitrary-precision`
|
||||
|
||||
Enable this to access the module for serialising `Decimal` types to a `String`. This can be use in `struct` definitions like so:
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ArbitraryExample {
|
||||
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
|
||||
value: Decimal,
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `std`
|
||||
|
||||
Enable `std` library support. This is enabled by default, however in the future will be opt in. For now, to support `no_std`
|
||||
|
@ -172,6 +229,11 @@ Please refer to the [Build document](BUILD.md) for more information on building
|
|||
|
||||
## Minimum Rust Compiler Version
|
||||
|
||||
This library maintains support for rust compiler versions at least one year old and only updates the minimum version if and
|
||||
when required. The current minimum compiler version is [`1.46.0`](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1460-2020-08-27)
|
||||
which was released on `2020-08-27`.
|
||||
The current _minimum_ compiler version is [`1.51.0`](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1510-2021-03-25)
|
||||
which was released on `2021-03-25` and included support for "const generics".
|
||||
|
||||
### Updating the minimum supported version
|
||||
|
||||
This library maintains support for rust compiler versions that are 5 minor versions away from the current stable rust compiler version.
|
||||
For example, if the current stable compiler version is `1.50.0` then we will guarantee support up to and including `1.45.0`.
|
||||
Of note, we will only update the minimum supported version if and when required.
|
||||
|
|
|
@ -1,5 +1,35 @@
|
|||
# Version History
|
||||
|
||||
## 1.20.0
|
||||
|
||||
* Additional fuzz testing for deserialize ([#452](https://github.com/paupino/rust-decimal/pull/452))
|
||||
* Documentation fix for rounding strategy ([#458](https://github.com/paupino/rust-decimal/pull/458))
|
||||
* `from_str` is now over 4x faster, utilizing const generics and TCO ([#456](https://github.com/paupino/rust-decimal/pull/456))
|
||||
* Fixed `from_str` issue with rounding issues when too many digits in source string. ([#453](https://github.com/paupino/rust-decimal/issues/453))
|
||||
* New `serde-with` functionality for greater configurability when using `serde` ([#459](https://github.com/paupino/rust-decimal/pull/459))
|
||||
* Various maintenance tasks ([#460](https://github.com/paupino/rust-decimal/pull/460))
|
||||
|
||||
This is truly a collaborative release and has some significant contributions from the community. A huge thank
|
||||
you to everyone involved:
|
||||
|
||||
* [@chris-cantor](https://github.com/chris-cantor)
|
||||
* [@TradingTomatillo](https://github.com/TradingTomatillo)
|
||||
* [@c410-f3r](https://github.com/c410-f3r)
|
||||
* [@ShigotoMitame](https://github.com/ShigotoMitame)
|
||||
* [@luke-brown](https://github.com/luke-brown)
|
||||
|
||||
## 1.19.0
|
||||
|
||||
This is a minor dot release and contains library updates ([#334](https://github.com/paupino/rust-decimal/pull/334)) and
|
||||
expanded scope in `prelude` to include `num_traits::Signed` ([#450](https://github.com/paupino/rust-decimal/pull/450)).
|
||||
While subtle, it also expands the way towards some bigger improvements including variable precision.
|
||||
|
||||
Of a larger note, the minimum Rust compiler version has been updated so we can start utilizing various compiler features
|
||||
(such as const generics). The miminum compiler version is now `1.51.0`.
|
||||
|
||||
Thank you to [@c410-f3r](https://github.com/c410-f3r) and [@jracollins](https://github.com/jracollins) for your contributions
|
||||
to this release.
|
||||
|
||||
## 1.18.0
|
||||
|
||||
* Fixes integer handling for `to_f64` when scale is set to `0`. [#443](https://github.com/paupino/rust-decimal/pull/443).
|
||||
|
|
|
@ -9,7 +9,7 @@ pub const UNSIGN_MASK: u32 = 0x4FFF_FFFF;
|
|||
// contain a value between 0 and 28 inclusive.
|
||||
pub const SCALE_MASK: u32 = 0x00FF_0000;
|
||||
pub const U8_MASK: u32 = 0x0000_00FF;
|
||||
pub const U32_MASK: u64 = 0xFFFF_FFFF;
|
||||
pub const U32_MASK: u64 = u32::MAX as _;
|
||||
|
||||
// Number of bits scale is shifted by.
|
||||
pub const SCALE_SHIFT: u32 = 16;
|
||||
|
@ -65,3 +65,8 @@ pub const MAX_I32_SCALE: i32 = 9;
|
|||
pub const MAX_I64_SCALE: u32 = 19;
|
||||
#[cfg(not(feature = "legacy-ops"))]
|
||||
pub const U32_MAX: u64 = u32::MAX as u64;
|
||||
|
||||
// Determines potential overflow for 128 bit operations
|
||||
pub const OVERFLOW_U96: u128 = 1u128 << 96;
|
||||
pub const WILL_OVERFLOW_U64: u64 = u64::MAX / 10 - u8::MAX as u64;
|
||||
pub const BYTES_TO_OVERFLOW_U64: usize = 18; // We can probably get away with less
|
||||
|
|
|
@ -83,7 +83,7 @@ const NEGATIVE_ONE: Decimal = Decimal {
|
|||
|
||||
/// `UnpackedDecimal` contains unpacked representation of `Decimal` where each component
|
||||
/// of decimal-format stored in it's own field
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct UnpackedDecimal {
|
||||
pub negative: bool,
|
||||
pub scale: u32,
|
||||
|
@ -125,7 +125,7 @@ pub enum RoundingStrategy {
|
|||
/// is away from zero. e.g. 6.4 -> 6, 6.5 -> 7, -6.5 -> -7
|
||||
MidpointAwayFromZero,
|
||||
/// When a number is halfway between two others, it is rounded toward the nearest number that
|
||||
/// is toward zero. e.g. 6.4 -> 6, 6.5 -> 7, -6.5 -> -6
|
||||
/// is toward zero. e.g. 6.4 -> 6, 6.5 -> 6, -6.5 -> -6
|
||||
MidpointTowardZero,
|
||||
/// The number is always rounded toward zero. e.g. -6.8 -> -6, 6.8 -> 6
|
||||
ToZero,
|
||||
|
@ -1183,7 +1183,7 @@ impl Decimal {
|
|||
|
||||
/// Returns `Some(Decimal)` number rounded to the specified number of significant digits. If
|
||||
/// the resulting number is unable to be represented by the `Decimal` number then `None` will
|
||||
/// be returned.
|
||||
/// be returned.
|
||||
/// When the number of significant figures of the `Decimal` being rounded is greater than the requested
|
||||
/// number of significant digits then rounding will be performed using `MidpointNearestEven` strategy.
|
||||
///
|
||||
|
@ -1224,7 +1224,7 @@ impl Decimal {
|
|||
|
||||
/// Returns `Some(Decimal)` number rounded to the specified number of significant digits. If
|
||||
/// the resulting number is unable to be represented by the `Decimal` number then `None` will
|
||||
/// be returned.
|
||||
/// be returned.
|
||||
/// When the number of significant figures of the `Decimal` being rounded is greater than the requested
|
||||
/// number of significant digits then rounding will be performed using the provided [RoundingStrategy].
|
||||
///
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::constants::MAX_PRECISION_U32;
|
||||
use crate::{constants::MAX_PRECISION_U32, Decimal};
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
|
||||
|
@ -21,6 +21,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
pub(crate) fn tail_error(from: &'static str) -> Result<Decimal, Error> {
|
||||
Err(from.into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! rust_decimal = "1.18"
|
||||
//! rust_decimal_macros = "1.18"
|
||||
//! rust_decimal = "1.20"
|
||||
//! rust_decimal_macros = "1.20"
|
||||
//! ```
|
||||
//!
|
||||
//! ## Usage
|
||||
|
@ -190,7 +190,7 @@ mod postgres;
|
|||
#[cfg(feature = "rocket-traits")]
|
||||
mod rocket;
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde;
|
||||
pub mod serde;
|
||||
|
||||
pub use decimal::{Decimal, RoundingStrategy};
|
||||
pub use error::Error;
|
||||
|
@ -203,7 +203,7 @@ pub mod prelude {
|
|||
pub use crate::maths::MathematicalOps;
|
||||
pub use crate::{Decimal, RoundingStrategy};
|
||||
pub use core::str::FromStr;
|
||||
pub use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
|
||||
pub use num_traits::{FromPrimitive, One, Signed, ToPrimitive, Zero};
|
||||
}
|
||||
|
||||
#[cfg(feature = "diesel")]
|
||||
|
|
|
@ -26,7 +26,7 @@ mod diesel_mysql {
|
|||
// internal types.
|
||||
let bytes = numeric.ok_or("Invalid decimal")?;
|
||||
let s = std::str::from_utf8(bytes)?;
|
||||
Decimal::from_str(&s).map_err(|e| e.into())
|
||||
Decimal::from_str(s).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,19 +15,19 @@ pub(crate) fn rescale_internal(value: &mut [u32; 3], value_scale: &mut u32, new_
|
|||
}
|
||||
|
||||
if *value_scale > new_scale {
|
||||
let mut diff = *value_scale - new_scale;
|
||||
let mut diff = value_scale.wrapping_sub(new_scale);
|
||||
// Scaling further isn't possible since we got an overflow
|
||||
// In this case we need to reduce the accuracy of the "side to keep"
|
||||
|
||||
// Now do the necessary rounding
|
||||
let mut remainder = 0;
|
||||
while diff > 0 {
|
||||
while let Some(diff_minus_one) = diff.checked_sub(1) {
|
||||
if is_all_zero(value) {
|
||||
*value_scale = new_scale;
|
||||
return;
|
||||
}
|
||||
|
||||
diff -= 1;
|
||||
diff = diff_minus_one;
|
||||
|
||||
// Any remainder is discarded if diff > 0 still (i.e. lost precision)
|
||||
remainder = div_by_u32(value, 10);
|
||||
|
@ -35,8 +35,8 @@ pub(crate) fn rescale_internal(value: &mut [u32; 3], value_scale: &mut u32, new_
|
|||
if remainder >= 5 {
|
||||
for part in value.iter_mut() {
|
||||
let digit = u64::from(*part) + 1u64;
|
||||
remainder = if digit > 0xFFFF_FFFF { 1 } else { 0 };
|
||||
*part = (digit & 0xFFFF_FFFF) as u32;
|
||||
remainder = if digit > U32_MASK { 1 } else { 0 };
|
||||
*part = (digit & U32_MASK) as u32;
|
||||
if remainder == 0 {
|
||||
break;
|
||||
}
|
||||
|
@ -44,16 +44,21 @@ pub(crate) fn rescale_internal(value: &mut [u32; 3], value_scale: &mut u32, new_
|
|||
}
|
||||
*value_scale = new_scale;
|
||||
} else {
|
||||
let mut diff = new_scale - *value_scale;
|
||||
let mut diff = new_scale.wrapping_sub(*value_scale);
|
||||
let mut working = [value[0], value[1], value[2]];
|
||||
while diff > 0 && mul_by_10(&mut working) == 0 {
|
||||
value.copy_from_slice(&working);
|
||||
diff -= 1;
|
||||
while let Some(diff_minus_one) = diff.checked_sub(1) {
|
||||
if mul_by_10(&mut working) == 0 {
|
||||
value.copy_from_slice(&working);
|
||||
diff = diff_minus_one;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*value_scale = new_scale - diff;
|
||||
*value_scale = new_scale.wrapping_sub(diff);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "legacy-ops")]
|
||||
pub(crate) fn add_by_internal(value: &mut [u32], by: &[u32]) -> u32 {
|
||||
let mut carry: u64 = 0;
|
||||
let vl = value.len();
|
||||
|
@ -92,14 +97,36 @@ pub(crate) fn add_by_internal(value: &mut [u32], by: &[u32]) -> u32 {
|
|||
carry as u32
|
||||
}
|
||||
|
||||
pub(crate) fn add_by_internal_flattened(value: &mut [u32; 3], by: u32) -> u32 {
|
||||
manage_add_by_internal(by, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn add_one_internal(value: &mut [u32]) -> u32 {
|
||||
let mut carry: u64 = 1; // Start with one, since adding one
|
||||
let mut sum: u64;
|
||||
for i in value.iter_mut() {
|
||||
sum = (*i as u64) + carry;
|
||||
*i = (sum & U32_MASK) as u32;
|
||||
carry = sum >> 32;
|
||||
pub(crate) fn add_one_internal(value: &mut [u32; 3]) -> u32 {
|
||||
manage_add_by_internal(1, value)
|
||||
}
|
||||
|
||||
// `u64 as u32` are safe because of widening and 32bits shifts
|
||||
#[inline]
|
||||
pub(crate) fn manage_add_by_internal<const N: usize>(initial_carry: u32, value: &mut [u32; N]) -> u32 {
|
||||
let mut carry = u64::from(initial_carry);
|
||||
let mut iter = 0..value.len();
|
||||
let mut sum = 0;
|
||||
|
||||
let mut sum_fn = |local_carry: &mut u64, idx| {
|
||||
sum = u64::from(value[idx]).wrapping_add(*local_carry);
|
||||
value[idx] = (sum & U32_MASK) as u32;
|
||||
*local_carry = sum.wrapping_shr(32);
|
||||
};
|
||||
|
||||
if let Some(idx) = iter.next() {
|
||||
sum_fn(&mut carry, idx);
|
||||
}
|
||||
|
||||
for idx in iter {
|
||||
if carry > 0 {
|
||||
sum_fn(&mut carry, idx);
|
||||
}
|
||||
}
|
||||
|
||||
carry as u32
|
||||
|
@ -189,7 +216,7 @@ pub(crate) fn mul_part(left: u32, right: u32, high: u32) -> (u32, u32) {
|
|||
}
|
||||
|
||||
// Returns remainder
|
||||
pub(crate) fn div_by_u32(bits: &mut [u32], divisor: u32) -> u32 {
|
||||
pub(crate) fn div_by_u32<const N: usize>(bits: &mut [u32; N], divisor: u32) -> u32 {
|
||||
if divisor == 0 {
|
||||
// Divide by zero
|
||||
panic!("Internal error: divide by zero");
|
||||
|
@ -251,7 +278,7 @@ pub(crate) fn cmp_internal(left: &[u32; 3], right: &[u32; 3]) -> core::cmp::Orde
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_all_zero(bits: &[u32]) -> bool {
|
||||
pub(crate) fn is_all_zero<const N: usize>(bits: &[u32; N]) -> bool {
|
||||
bits.iter().all(|b| *b == 0)
|
||||
}
|
||||
|
||||
|
|
|
@ -624,7 +624,7 @@ fn add_with_scale_internal(
|
|||
let mut temp4 = [0u32, 0u32, 0u32, 0u32];
|
||||
if *quotient_scale != *working_scale {
|
||||
// TODO: Remove necessity for temp (without performance impact)
|
||||
fn div_by_10(target: &mut [u32], temp: &mut [u32], scale: &mut i32, target_scale: i32) {
|
||||
fn div_by_10<const N: usize>(target: &mut [u32], temp: &mut [u32; N], scale: &mut i32, target_scale: i32) {
|
||||
// Copy to the temp array
|
||||
temp.copy_from_slice(target);
|
||||
// divide by 10 until target scale is reached
|
||||
|
@ -676,7 +676,12 @@ fn add_with_scale_internal(
|
|||
// (ultimately losing significant digits)
|
||||
if *quotient_scale != *working_scale {
|
||||
// TODO: Remove necessity for temp (without performance impact)
|
||||
fn div_by_10_lossy(target: &mut [u32], temp: &mut [u32], scale: &mut i32, target_scale: i32) {
|
||||
fn div_by_10_lossy<const N: usize>(
|
||||
target: &mut [u32],
|
||||
temp: &mut [u32; N],
|
||||
scale: &mut i32,
|
||||
target_scale: i32,
|
||||
) {
|
||||
temp.copy_from_slice(target);
|
||||
// divide by 10 until target scale is reached
|
||||
while *scale > target_scale {
|
||||
|
|
|
@ -460,7 +460,7 @@ mod diesel_postgres {
|
|||
}
|
||||
|
||||
#[cfg(any(feature = "db-postgres", feature = "db-tokio-postgres"))]
|
||||
mod postgres {
|
||||
mod _postgres {
|
||||
use super::*;
|
||||
use ::postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type};
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
|
|
|
@ -4,6 +4,132 @@ use core::{fmt, str::FromStr};
|
|||
use num_traits::FromPrimitive;
|
||||
use serde::{self, de::Unexpected};
|
||||
|
||||
/// Serialize Decimals as arbitrary precision numbers in JSON.
|
||||
///
|
||||
/// ```
|
||||
/// # use serde::{Serialize, Deserialize};
|
||||
/// # use rust_decimal::Decimal;
|
||||
/// # use std::str::FromStr;
|
||||
///
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// pub struct ArbitraryExample {
|
||||
/// #[serde(with = "rust_decimal::serde::arbitrary_precision")]
|
||||
/// value: Decimal,
|
||||
/// }
|
||||
///
|
||||
/// let value = ArbitraryExample { value: Decimal::from_str("123.400").unwrap() };
|
||||
/// assert_eq!(
|
||||
/// &serde_json::to_string(&value).unwrap(),
|
||||
/// r#"{"value":123.400}"#
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
pub mod arbitrary_precision {
|
||||
use super::*;
|
||||
use serde::Serialize;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(DecimalVisitor)
|
||||
}
|
||||
|
||||
pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serde_json::Number::from_str(&value.to_string())
|
||||
.map_err(serde::ser::Error::custom)?
|
||||
.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize Decimals as floats in JSON.
|
||||
///
|
||||
/// ```
|
||||
/// # use serde::{Serialize, Deserialize};
|
||||
/// # use rust_decimal::Decimal;
|
||||
/// # use std::str::FromStr;
|
||||
///
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// pub struct FloatExample {
|
||||
/// #[serde(with = "rust_decimal::serde::float")]
|
||||
/// value: Decimal,
|
||||
/// }
|
||||
///
|
||||
/// let value = FloatExample { value: Decimal::from_str("123.400").unwrap() };
|
||||
/// assert_eq!(
|
||||
/// &serde_json::to_string(&value).unwrap(),
|
||||
/// r#"{"value":123.4}"#
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg(feature = "serde-with-float")]
|
||||
pub mod float {
|
||||
use super::*;
|
||||
use serde::Serialize;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(DecimalVisitor)
|
||||
}
|
||||
|
||||
pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use num_traits::ToPrimitive;
|
||||
value.to_f64().unwrap().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize Decimals as floats in JSON.
|
||||
///
|
||||
/// ```
|
||||
/// # use serde::{Serialize, Deserialize};
|
||||
/// # use rust_decimal::Decimal;
|
||||
/// # use std::str::FromStr;
|
||||
///
|
||||
/// #[derive(Serialize, Deserialize)]
|
||||
/// pub struct StringExample {
|
||||
/// #[serde(with = "rust_decimal::serde::str")]
|
||||
/// value: Decimal,
|
||||
/// }
|
||||
///
|
||||
/// let value = StringExample { value: Decimal::from_str("123.400").unwrap() };
|
||||
/// assert_eq!(
|
||||
/// &serde_json::to_string(&value).unwrap(),
|
||||
/// r#"{"value":"123.400"}"#
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg(feature = "serde-with-str")]
|
||||
pub mod str {
|
||||
use crate::constants::MAX_STR_BUFFER_SIZE;
|
||||
|
||||
use super::*;
|
||||
use arrayvec::ArrayString;
|
||||
use core::convert::TryFrom;
|
||||
use serde::{ser::Error, Serialize};
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(DecimalVisitor)
|
||||
}
|
||||
|
||||
pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
ArrayString::<MAX_STR_BUFFER_SIZE>::try_from(format_args!("{}", value))
|
||||
.map_err(S::Error::custom)?
|
||||
.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "serde-str"))]
|
||||
impl<'de> serde::Deserialize<'de> for Decimal {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>
|
||||
|
@ -35,7 +161,7 @@ impl<'de> serde::Deserialize<'de> for Decimal {
|
|||
}
|
||||
|
||||
// It's a shame this needs to be redefined for this feature and not able to be referenced directly
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
const DECIMAL_KEY_TOKEN: &str = "$serde_json::private::Number";
|
||||
|
||||
struct DecimalVisitor;
|
||||
|
@ -83,7 +209,7 @@ impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
|
|||
.map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
fn visit_map<A>(self, map: A) -> Result<Decimal, A::Error>
|
||||
where
|
||||
A: serde::de::MapAccess<'de>,
|
||||
|
@ -98,10 +224,10 @@ impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
struct DecimalKey;
|
||||
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
impl<'de> serde::de::Deserialize<'de> for DecimalKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<DecimalKey, D::Error>
|
||||
where
|
||||
|
@ -133,12 +259,12 @@ impl<'de> serde::de::Deserialize<'de> for DecimalKey {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
pub struct DecimalFromString {
|
||||
pub value: Decimal,
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-arbitrary-precision")]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
impl<'de> serde::de::Deserialize<'de> for DecimalFromString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<DecimalFromString, D::Error>
|
||||
where
|
||||
|
@ -373,4 +499,49 @@ mod test {
|
|||
let des: Foo = bincode::deserialize(&ser).unwrap();
|
||||
assert_eq!(des.value, s.value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde-with-arbitrary-precision")]
|
||||
fn with_arbitrary_precision() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ArbitraryExample {
|
||||
#[serde(with = "crate::serde::arbitrary_precision")]
|
||||
value: Decimal,
|
||||
}
|
||||
|
||||
let value = ArbitraryExample {
|
||||
value: Decimal::from_str("123.400").unwrap(),
|
||||
};
|
||||
assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.400}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde-with-float")]
|
||||
fn with_float() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FloatExample {
|
||||
#[serde(with = "crate::serde::float")]
|
||||
value: Decimal,
|
||||
}
|
||||
|
||||
let value = FloatExample {
|
||||
value: Decimal::from_str("123.400").unwrap(),
|
||||
};
|
||||
assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.4}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde-with-str")]
|
||||
fn with_str() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StringExample {
|
||||
#[serde(with = "crate::serde::str")]
|
||||
value: Decimal,
|
||||
}
|
||||
|
||||
let value = StringExample {
|
||||
value: Decimal::from_str("123.400").unwrap(),
|
||||
};
|
||||
assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":"123.400"}"#);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
constants::{MAX_PRECISION, MAX_STR_BUFFER_SIZE},
|
||||
error::Error,
|
||||
ops::array::{add_by_internal, add_one_internal, div_by_u32, is_all_zero, mul_by_10, mul_by_u32},
|
||||
constants::{BYTES_TO_OVERFLOW_U64, MAX_PRECISION, MAX_STR_BUFFER_SIZE, OVERFLOW_U96, WILL_OVERFLOW_U64},
|
||||
error::{tail_error, Error},
|
||||
ops::array::{add_by_internal_flattened, add_one_internal, div_by_u32, is_all_zero, mul_by_u32},
|
||||
Decimal,
|
||||
};
|
||||
|
||||
|
@ -15,12 +15,12 @@ pub(crate) fn to_str_internal(
|
|||
value: &Decimal,
|
||||
append_sign: bool,
|
||||
precision: Option<usize>,
|
||||
) -> (ArrayString<[u8; MAX_STR_BUFFER_SIZE]>, Option<usize>) {
|
||||
) -> (ArrayString<MAX_STR_BUFFER_SIZE>, Option<usize>) {
|
||||
// Get the scale - where we need to put the decimal point
|
||||
let scale = value.scale() as usize;
|
||||
|
||||
// Convert to a string and manipulate that (neg at front, inject decimal)
|
||||
let mut chars = ArrayVec::<[_; MAX_STR_BUFFER_SIZE]>::new();
|
||||
let mut chars = ArrayVec::<_, MAX_STR_BUFFER_SIZE>::new();
|
||||
let mut working = value.mantissa_array3();
|
||||
while !is_all_zero(&working) {
|
||||
let remainder = div_by_u32(&mut working, 10u32);
|
||||
|
@ -122,160 +122,236 @@ pub(crate) fn fmt_scientific_notation(
|
|||
}
|
||||
|
||||
// dedicated implementation for the most common case.
|
||||
#[inline]
|
||||
pub(crate) fn parse_str_radix_10(str: &str) -> Result<Decimal, crate::Error> {
|
||||
if str.is_empty() {
|
||||
return Err(Error::from("Invalid decimal: empty"));
|
||||
}
|
||||
|
||||
let mut offset = 0;
|
||||
let mut len = str.len();
|
||||
let bytes = str.as_bytes();
|
||||
let mut negative = false; // assume positive
|
||||
|
||||
// handle the sign
|
||||
if bytes[offset] == b'-' {
|
||||
negative = true; // leading minus means negative
|
||||
offset += 1;
|
||||
len -= 1;
|
||||
} else if bytes[offset] == b'+' {
|
||||
// leading + allowed
|
||||
offset += 1;
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
// should now be at numeric part of the significand
|
||||
let mut digits_before_dot: i32 = -1; // digits before '.', -1 if no '.'
|
||||
let mut coeff = ArrayVec::<[_; MAX_STR_BUFFER_SIZE]>::new(); // integer significand array
|
||||
|
||||
let mut maybe_round = false;
|
||||
while len > 0 {
|
||||
let b = bytes[offset];
|
||||
match b {
|
||||
b'0'..=b'9' => {
|
||||
coeff.push(u32::from(b - b'0'));
|
||||
offset += 1;
|
||||
len -= 1;
|
||||
|
||||
// If the coefficient is longer than the max, exit early
|
||||
if coeff.len() as u32 > 28 {
|
||||
maybe_round = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
b'.' => {
|
||||
if digits_before_dot >= 0 {
|
||||
return Err(Error::from("Invalid decimal: two decimal points"));
|
||||
}
|
||||
digits_before_dot = coeff.len() as i32;
|
||||
offset += 1;
|
||||
len -= 1;
|
||||
}
|
||||
b'_' => {
|
||||
// Must start with a number...
|
||||
if coeff.is_empty() {
|
||||
return Err(Error::from("Invalid decimal: must start lead with a number"));
|
||||
}
|
||||
offset += 1;
|
||||
len -= 1;
|
||||
}
|
||||
_ => return Err(Error::from("Invalid decimal: unknown character")),
|
||||
}
|
||||
}
|
||||
|
||||
// If we exited before the end of the string then do some rounding if necessary
|
||||
if maybe_round && offset < bytes.len() {
|
||||
let next_byte = bytes[offset];
|
||||
let digit = match next_byte {
|
||||
b'0'..=b'9' => u32::from(next_byte - b'0'),
|
||||
b'_' => 0,
|
||||
b'.' => {
|
||||
// Still an error if we have a second dp
|
||||
if digits_before_dot >= 0 {
|
||||
return Err(Error::from("Invalid decimal: two decimal points"));
|
||||
}
|
||||
0
|
||||
}
|
||||
_ => return Err(Error::from("Invalid decimal: unknown character")),
|
||||
};
|
||||
|
||||
// Round at midpoint
|
||||
if digit >= 5 {
|
||||
let mut index = coeff.len() - 1;
|
||||
loop {
|
||||
let new_digit = coeff[index] + 1;
|
||||
if new_digit <= 9 {
|
||||
coeff[index] = new_digit;
|
||||
break;
|
||||
} else {
|
||||
coeff[index] = 0;
|
||||
if index == 0 {
|
||||
coeff.insert(0, 1u32);
|
||||
digits_before_dot += 1;
|
||||
coeff.pop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
index -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// here when no characters left
|
||||
if coeff.is_empty() {
|
||||
return Err(Error::from("Invalid decimal: no digits found"));
|
||||
}
|
||||
|
||||
let mut scale = if digits_before_dot >= 0 {
|
||||
// we had a decimal place so set the scale
|
||||
(coeff.len() as u32) - (digits_before_dot as u32)
|
||||
if bytes.len() < BYTES_TO_OVERFLOW_U64 {
|
||||
parse_str_radix_10_dispatch::<false>(bytes)
|
||||
} else {
|
||||
0
|
||||
parse_str_radix_10_dispatch::<true>(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_str_radix_10_dispatch<const BIG: bool>(bytes: &[u8]) -> Result<Decimal, crate::Error> {
|
||||
match bytes {
|
||||
[b, rest @ ..] => byte_dispatch_u64::<false, false, false, BIG, true>(rest, 0, 0, *b),
|
||||
[] => tail_error("Invalid decimal: empty"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn overflow_64(val: u64) -> bool {
|
||||
val >= WILL_OVERFLOW_U64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn overflow_128(val: u128) -> bool {
|
||||
val >= OVERFLOW_U96
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn dispatch_next<const POINT: bool, const NEG: bool, const HAS: bool, const BIG: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
if let Some((next, bytes)) = bytes.split_first() {
|
||||
byte_dispatch_u64::<POINT, NEG, HAS, BIG, false>(bytes, data64, scale, *next)
|
||||
} else {
|
||||
handle_data::<NEG, HAS>(data64 as u128, scale)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn non_digit_dispatch_u64<const POINT: bool, const NEG: bool, const HAS: bool, const BIG: bool, const FIRST: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
b: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
match b {
|
||||
b'-' if FIRST && !HAS => dispatch_next::<false, true, false, BIG>(bytes, data64, scale),
|
||||
b'+' if FIRST && !HAS => dispatch_next::<false, false, false, BIG>(bytes, data64, scale),
|
||||
b'_' if HAS => handle_separator::<POINT, NEG, BIG>(bytes, data64, scale),
|
||||
b => tail_invalid_digit(b),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn byte_dispatch_u64<const POINT: bool, const NEG: bool, const HAS: bool, const BIG: bool, const FIRST: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
b: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
match b {
|
||||
b'0'..=b'9' => handle_digit_64::<POINT, NEG, BIG>(bytes, data64, scale, b - b'0'),
|
||||
b'.' if !POINT => handle_point::<NEG, HAS, BIG>(bytes, data64, scale),
|
||||
b => non_digit_dispatch_u64::<POINT, NEG, HAS, BIG, FIRST>(bytes, data64, scale, b),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn handle_digit_64<const POINT: bool, const NEG: bool, const BIG: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
digit: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
// we have already validated that we cannot overflow
|
||||
let data64 = data64 * 10 + digit as u64;
|
||||
let scale = if POINT { scale + 1 } else { 0 };
|
||||
|
||||
if let Some((next, bytes)) = bytes.split_first() {
|
||||
let next = *next;
|
||||
if POINT && BIG && scale >= 28 {
|
||||
maybe_round(data64 as u128, next, scale, POINT, NEG)
|
||||
} else if BIG && overflow_64(data64) {
|
||||
handle_full_128::<POINT, NEG>(data64 as u128, bytes, scale, next)
|
||||
} else {
|
||||
byte_dispatch_u64::<POINT, NEG, true, BIG, false>(bytes, data64, scale, next)
|
||||
}
|
||||
} else {
|
||||
let data: u128 = data64 as u128;
|
||||
|
||||
handle_data::<NEG, true>(data, scale)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn handle_point<const NEG: bool, const HAS: bool, const BIG: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
dispatch_next::<true, NEG, HAS, BIG>(bytes, data64, scale)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn handle_separator<const POINT: bool, const NEG: bool, const BIG: bool>(
|
||||
bytes: &[u8],
|
||||
data64: u64,
|
||||
scale: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
dispatch_next::<POINT, NEG, true, BIG>(bytes, data64, scale)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn tail_invalid_digit(digit: u8) -> Result<Decimal, crate::Error> {
|
||||
match digit {
|
||||
b'.' => tail_error("Invalid decimal: two decimal points"),
|
||||
b'_' => tail_error("Invalid decimal: must start lead with a number"),
|
||||
_ => tail_error("Invalid decimal: unknown character"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn handle_full_128<const POINT: bool, const NEG: bool>(
|
||||
mut data: u128,
|
||||
bytes: &[u8],
|
||||
scale: u8,
|
||||
next_byte: u8,
|
||||
) -> Result<Decimal, crate::Error> {
|
||||
let b = next_byte;
|
||||
match b {
|
||||
b'0'..=b'9' => {
|
||||
let digit = u32::from(b - b'0');
|
||||
|
||||
// If the data is going to overflow then we should go into recovery mode
|
||||
let next = (data * 10) + digit as u128;
|
||||
if overflow_128(next) {
|
||||
if !POINT {
|
||||
return tail_error("Invalid decimal: overflow from too many digits");
|
||||
}
|
||||
|
||||
if digit >= 5 {
|
||||
data += 1;
|
||||
}
|
||||
handle_data::<NEG, true>(data, scale)
|
||||
} else {
|
||||
data = next;
|
||||
let scale = scale + POINT as u8;
|
||||
if let Some((next, bytes)) = bytes.split_first() {
|
||||
let next = *next;
|
||||
if POINT && scale >= 28 {
|
||||
maybe_round(data, next, scale, POINT, NEG)
|
||||
} else {
|
||||
handle_full_128::<POINT, NEG>(data, bytes, scale, next)
|
||||
}
|
||||
} else {
|
||||
handle_data::<NEG, true>(data, scale)
|
||||
}
|
||||
}
|
||||
}
|
||||
b'.' if !POINT => {
|
||||
// This call won't tail?
|
||||
if let Some((next, bytes)) = bytes.split_first() {
|
||||
handle_full_128::<true, NEG>(data, bytes, scale, *next)
|
||||
} else {
|
||||
handle_data::<NEG, true>(data, scale)
|
||||
}
|
||||
}
|
||||
b'_' => {
|
||||
if let Some((next, bytes)) = bytes.split_first() {
|
||||
handle_full_128::<POINT, NEG>(data, bytes, scale, *next)
|
||||
} else {
|
||||
handle_data::<NEG, true>(data, scale)
|
||||
}
|
||||
}
|
||||
b => tail_invalid_digit(b),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn maybe_round(mut data: u128, next_byte: u8, scale: u8, point: bool, negative: bool) -> Result<Decimal, crate::Error> {
|
||||
let digit = match next_byte {
|
||||
b'0'..=b'9' => u32::from(next_byte - b'0'),
|
||||
b'_' => 0, // this should be an invalid string?
|
||||
b'.' if point => 0,
|
||||
b => return tail_invalid_digit(b),
|
||||
};
|
||||
|
||||
let mut data = [0u32, 0u32, 0u32];
|
||||
let mut tmp = [0u32, 0u32, 0u32];
|
||||
let len = coeff.len();
|
||||
for (i, digit) in coeff.iter().enumerate() {
|
||||
// If the data is going to overflow then we should go into recovery mode
|
||||
tmp[0] = data[0];
|
||||
tmp[1] = data[1];
|
||||
tmp[2] = data[2];
|
||||
let overflow = mul_by_10(&mut tmp);
|
||||
if overflow > 0 {
|
||||
// This means that we have more data to process, that we're not sure what to do with.
|
||||
// This may or may not be an issue - depending on whether we're past a decimal point
|
||||
// or not.
|
||||
if (i as i32) < digits_before_dot && i + 1 < len {
|
||||
return Err(Error::from("Invalid decimal: overflow from too many digits"));
|
||||
}
|
||||
|
||||
if *digit >= 5 {
|
||||
let carry = add_one_internal(&mut data);
|
||||
if carry > 0 {
|
||||
// Highly unlikely scenario which is more indicative of a bug
|
||||
return Err(Error::from("Invalid decimal: overflow when rounding"));
|
||||
}
|
||||
}
|
||||
// We're also one less digit so reduce the scale
|
||||
let diff = (len - i) as u32;
|
||||
if diff > scale {
|
||||
return Err(Error::from("Invalid decimal: overflow from scale mismatch"));
|
||||
}
|
||||
scale -= diff;
|
||||
break;
|
||||
} else {
|
||||
data[0] = tmp[0];
|
||||
data[1] = tmp[1];
|
||||
data[2] = tmp[2];
|
||||
let carry = add_by_internal(&mut data, &[*digit]);
|
||||
if carry > 0 {
|
||||
// Highly unlikely scenario which is more indicative of a bug
|
||||
return Err(Error::from("Invalid decimal: overflow from carry"));
|
||||
}
|
||||
// Round at midpoint
|
||||
if digit >= 5 {
|
||||
data += 1;
|
||||
if overflow_128(data) {
|
||||
// Highly unlikely scenario which is more indicative of a bug
|
||||
return tail_error("Invalid decimal: overflow when rounding");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Decimal::from_parts(data[0], data[1], data[2], negative, scale))
|
||||
if negative {
|
||||
handle_data::<true, true>(data, scale)
|
||||
} else {
|
||||
handle_data::<false, true>(data, scale)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn tail_no_has() -> Result<Decimal, crate::Error> {
|
||||
tail_error("Invalid decimal: no digits found")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn handle_data<const NEG: bool, const HAS: bool>(data: u128, scale: u8) -> Result<Decimal, crate::Error> {
|
||||
debug_assert_eq!(data >> 96, 0);
|
||||
if !HAS {
|
||||
tail_no_has()
|
||||
} else {
|
||||
Ok(Decimal::from_parts(
|
||||
data as u32,
|
||||
(data >> 32) as u32,
|
||||
(data >> 64) as u32,
|
||||
NEG,
|
||||
scale as u32,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_str_radix_n(str: &str, radix: u32) -> Result<Decimal, crate::Error> {
|
||||
|
@ -308,7 +384,7 @@ pub(crate) fn parse_str_radix_n(str: &str, radix: u32) -> Result<Decimal, crate:
|
|||
|
||||
// should now be at numeric part of the significand
|
||||
let mut digits_before_dot: i32 = -1; // digits before '.', -1 if no '.'
|
||||
let mut coeff = ArrayVec::<[_; 96]>::new(); // integer significand array
|
||||
let mut coeff = ArrayVec::<_, 96>::new(); // integer significand array
|
||||
|
||||
// Supporting different radix
|
||||
let (max_n, max_alpha_lower, max_alpha_upper) = if radix <= 10 {
|
||||
|
@ -528,7 +604,7 @@ pub(crate) fn parse_str_radix_n(str: &str, radix: u32) -> Result<Decimal, crate:
|
|||
data[0] = tmp[0];
|
||||
data[1] = tmp[1];
|
||||
data[2] = tmp[2];
|
||||
let carry = add_by_internal(&mut data, &[*digit]);
|
||||
let carry = add_by_internal_flattened(&mut data, *digit);
|
||||
if carry > 0 {
|
||||
// Highly unlikely scenario which is more indicative of a bug
|
||||
return Err(Error::from("Invalid decimal: overflow from carry"));
|
||||
|
@ -541,6 +617,7 @@ pub(crate) fn parse_str_radix_n(str: &str, radix: u32) -> Result<Decimal, crate:
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::Decimal;
|
||||
use arrayvec::ArrayString;
|
||||
use core::{fmt::Write, str::FromStr};
|
||||
|
@ -548,8 +625,189 @@ mod test {
|
|||
#[test]
|
||||
fn display_does_not_overflow_max_capacity() {
|
||||
let num = Decimal::from_str("1.2").unwrap();
|
||||
let mut buffer = ArrayString::<[u8; 64]>::new();
|
||||
let mut buffer = ArrayString::<64>::new();
|
||||
let _ = buffer.write_fmt(format_args!("{:.31}", num)).unwrap();
|
||||
assert_eq!("1.2000000000000000000000000000000", buffer.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_rounding_0() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("1.234").unwrap().unpack(),
|
||||
Decimal::new(1234, 3).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_rounding_1() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("11111_11111_11111.11111_11111_11111")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(11_111_111_111_111_111_111_111_111_111, 14).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_rounding_2() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("11111_11111_11111.11111_11111_11115")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(11_111_111_111_111_111_111_111_111_112, 14).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_rounding_3() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("11111_11111_11111.11111_11111_11195")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(1_111_111_111_111_111_111_111_111_1120, 14).unpack() // was Decimal::from_i128_with_scale(1_111_111_111_111_111_111_111_111_112, 13)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_rounding_4() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("99999_99999_99999.99999_99999_99995")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(10_000_000_000_000_000_000_000_000_000, 13).unpack() // was Decimal::from_i128_with_scale(1_000_000_000_000_000_000_000_000_000, 12)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_many_pointless_chars() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("00________________________________________________________________001.1")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(11, 1).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_leading_0s_1() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("00001.1").unwrap().unpack(),
|
||||
Decimal::from_i128_with_scale(11, 1).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_leading_0s_2() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("00000_00000_00000_00000_00001.00001")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(100001, 5).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_leading_0s_3() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("0.00000_00000_00000_00000_00000_00100")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(1, 28).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_trailing_0s_1() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("0.00001_00000_00000").unwrap().unpack(),
|
||||
Decimal::from_i128_with_scale(10_000_000_000, 15).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_trailing_0s_2() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("0.00001_00000_00000_00000_00000_00000")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(100_000_000_000_000_000_000_000, 28).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_overflow_1() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("99999_99999_99999_99999_99999_99999.99999"),
|
||||
// The original implementation returned
|
||||
// Ok(10000_00000_00000_00000_00000_0000)
|
||||
// Which is a bug!
|
||||
Err(Error::from("Invalid decimal: overflow from too many digits"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_overflow_2() {
|
||||
assert!(
|
||||
parse_str_radix_10("99999_99999_99999_99999_99999_11111.11111").is_err(),
|
||||
// The original implementation is 'overflow from scale mismatch'
|
||||
// but we got rid of that now
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_overflow_3() {
|
||||
assert!(
|
||||
parse_str_radix_10("99999_99999_99999_99999_99999_99994").is_err() // We could not get into 'overflow when rounding' or 'overflow from carry'
|
||||
// in the original implementation because the rounding logic before prevented it
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_overflow_4() {
|
||||
assert_eq!(
|
||||
// This does not overflow, moving the decimal point 1 more step would result in
|
||||
// 'overflow from too many digits'
|
||||
parse_str_radix_10("99999_99999_99999_99999_99999_999.99")
|
||||
.unwrap()
|
||||
.unpack(),
|
||||
Decimal::from_i128_with_scale(10_000_000_000_000_000_000_000_000_000, 0).unpack()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_edge_cases_1() {
|
||||
assert_eq!(parse_str_radix_10(""), Err(Error::from("Invalid decimal: empty")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_edge_cases_2() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("0.1."),
|
||||
Err(Error::from("Invalid decimal: two decimal points"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_edge_cases_3() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("_"),
|
||||
Err(Error::from("Invalid decimal: must start lead with a number"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_edge_cases_4() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("1?2"),
|
||||
Err(Error::from("Invalid decimal: unknown character"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_edge_cases_5() {
|
||||
assert_eq!(
|
||||
parse_str_radix_10("."),
|
||||
Err(Error::from("Invalid decimal: no digits found"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2893,6 +2893,8 @@ fn it_can_parse_highly_significant_numbers() {
|
|||
"8097370036018690744.259037116",
|
||||
),
|
||||
("1.234567890123456789012345678949999", "1.2345678901234567890123456789"),
|
||||
(".00000000000000000000000000001", "0.0000000000000000000000000000"),
|
||||
(".10000000000000000000000000000", "0.1000000000000000000000000000"),
|
||||
];
|
||||
for &(value, expected) in tests {
|
||||
assert_eq!(expected, Decimal::from_str(value).unwrap().to_string());
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.lock":"78e4ede1b94fb783aa85026e765976cf849d9342bc756b9aeb634c42ebbbaa3b","Cargo.toml":"42c1fd620f2e5b485a4fed0ab1be20601b762fff1bf8c989eb526f78867d3589","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"51bbf87e0aef209ddc39cc4d444d44f4805f44ed3663696eefc22a63f35fdb7e","benches/bench.rs":"ea6f919ff44d86ee26c69bf0b77d8a1502e687b26a68db8613f88d063470dd27","build.rs":"4d0cad8c0501f5b4d81eb91f693f8186db6edcc603c8906ae0305cfccd847df8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"7397b35efc3763c7c705b4d29b8777bbb7f1782698c87e721dcb0e24c99bbfd2","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"630cea1a958a468f0f07f3748e3f52540a9e85fc667af5fef0e542b3c9b93394","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"56a1a53f0c418b82ca8c0d2523da70aa786c001250cdfca7847077d5d91e3b02","src/d2s_small_table.rs":"228d2e182ce940554d8d542c521ce5df9212659c30383f887d1a0489b7e6bef5","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"55320c2301680d8be3a908620cccd9d103b0cd3ad7a7d3378589e274ffc2587b","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"3e9515eba0fa534c029a7fbc31f55894d5de82ee87d91da175a2bb118d53642b","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"6c9aa1c707c567ae338647056e37557a94e5120781ee9f6f64e9c7071ffb50d0","src/pretty/mantissa.rs":"a3eb97fd8928bfabef4523501f204fc7254e948318d727eff8327b9b06e76242","src/pretty/mod.rs":"169c57b14075295b07fa408963c300cefa94fd0b17e098d524ef46535bd84019","src/s2d.rs":"2f572603eedaa9efbe864105999a1ceac8aa4ff4e1d2fbd96127692460194d16","src/s2f.rs":"411b1e5acdeb3d7a29f4fddfdf9ce77e6395475d1c053a05e31482d49e6bf1ee","tests/common_test.rs":"275184cf366f80c11e5f33c2d53065a073e20d81bf71ca70478c89e47fb8da36","tests/d2s_table_test.rs":"54b3a7d40aa9bec03e9dc555d15fb4512ee16a16398b3098a97819fab50c81f3","tests/d2s_test.rs":"39014777edd6e3231095186174c4ef341fd9c12ecc5510765761713b6cac3bb4","tests/exhaustive.rs":"5ae5a567f11cc1d4b980655f1ec6e4784715d77ac49e39394f76763dc227f653","tests/f2s_test.rs":"10940f005e73a42bb106ff498e7a6cc4665d04d82829fef8dc7d0eb36f574e6f","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"a1127481d12c1891153cc8645e05d5b57742b20ba199aa7979666bf376493503","tests/s2f_test.rs":"499f540f03a03e71fc8609c14bc98d9b1b0853ddf41b1679d0ebef0216b25808"},"package":"3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568"}
|
||||
{"files":{"Cargo.lock":"df0cd7b0f10f6551fb604a5e23ede87458c1591db76937eb9ae9f66c1414ac15","Cargo.toml":"7f9e1bf42eda19fea81e681a2bed6c72b233f527f34be918d0b55a8a9dc1a90a","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"91f2433b0f7134b35703c316a73e145f23d9a44c6e340eb971a72d0a4a87eea8","benches/bench.rs":"ea6f919ff44d86ee26c69bf0b77d8a1502e687b26a68db8613f88d063470dd27","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"c5adf9aa037271916e78c61c9fd98e3230a0fed1fca15694d4d57166fa697125","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"83f821f17fd8d2cf72bcc47cc8c603ab24f2377db6cd0f08638031716f8dc17c","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"658d00a64ce2aca7f0780a1acc5939167e4a66d836b51c46de1047820992fec1","src/d2s_small_table.rs":"7b25cfbf0793d0662d83f5d92a9f880295652db9979b5acf702b313359996508","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"55320c2301680d8be3a908620cccd9d103b0cd3ad7a7d3378589e274ffc2587b","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"e061c35718460b62a6a5b1e9ca0dca959c7e9e08515602653c184435d86bc6b4","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"6c9aa1c707c567ae338647056e37557a94e5120781ee9f6f64e9c7071ffb50d0","src/pretty/mantissa.rs":"a3eb97fd8928bfabef4523501f204fc7254e948318d727eff8327b9b06e76242","src/pretty/mod.rs":"169c57b14075295b07fa408963c300cefa94fd0b17e098d524ef46535bd84019","src/s2d.rs":"2f572603eedaa9efbe864105999a1ceac8aa4ff4e1d2fbd96127692460194d16","src/s2f.rs":"411b1e5acdeb3d7a29f4fddfdf9ce77e6395475d1c053a05e31482d49e6bf1ee","tests/common_test.rs":"275184cf366f80c11e5f33c2d53065a073e20d81bf71ca70478c89e47fb8da36","tests/d2s_table_test.rs":"54b3a7d40aa9bec03e9dc555d15fb4512ee16a16398b3098a97819fab50c81f3","tests/d2s_test.rs":"39014777edd6e3231095186174c4ef341fd9c12ecc5510765761713b6cac3bb4","tests/exhaustive.rs":"5ae5a567f11cc1d4b980655f1ec6e4784715d77ac49e39394f76763dc227f653","tests/f2s_test.rs":"10940f005e73a42bb106ff498e7a6cc4665d04d82829fef8dc7d0eb36f574e6f","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"75c3a1044881718db65e05f25c9f6e1d005392dddb2e8dafb799668bb6a9a5c3","tests/s2f_test.rs":"1ec06646cb65229bfe866ec913901a0d8d736668f30b812fc4b00136a43f5142"},"package":"73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"}
|
|
@ -30,9 +30,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.100"
|
||||
version = "0.2.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5"
|
||||
checksum = "8e167738f1866a7ec625567bae89ca0d44477232a4f7c52b1c7f2adc2c98804f"
|
||||
|
||||
[[package]]
|
||||
name = "no-panic"
|
||||
|
@ -57,24 +57,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -130,7 +130,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
dependencies = [
|
||||
"no-panic",
|
||||
"num_cpus",
|
||||
|
@ -140,9 +140,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.75"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -11,13 +11,15 @@
|
|||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.31"
|
||||
rust-version = "1.36"
|
||||
name = "ryu"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
exclude = ["performance.png", "chart/**"]
|
||||
description = "Fast floating point to string conversion"
|
||||
documentation = "https://docs.rs/ryu"
|
||||
readme = "README.md"
|
||||
categories = ["value-formatting"]
|
||||
license = "Apache-2.0 OR BSL-1.0"
|
||||
repository = "https://github.com/dtolnay/ryu"
|
||||
[package.metadata.docs.rs]
|
||||
|
|
|
@ -15,7 +15,7 @@ under the creative commons CC-BY-SA license.
|
|||
This Rust implementation is a line-by-line port of Ulf Adams' implementation in
|
||||
C, [https://github.com/ulfjack/ryu][upstream].
|
||||
|
||||
*Requirements: this crate supports any compiler version back to rustc 1.31; it
|
||||
*Requirements: this crate supports any compiler version back to rustc 1.36; it
|
||||
uses nothing from the Rust standard library so is usable from no_std crates.*
|
||||
|
||||
[paper]: https://dl.acm.org/citation.cfm?id=3192369
|
||||
|
@ -26,6 +26,8 @@ uses nothing from the Rust standard library so is usable from no_std crates.*
|
|||
ryu = "1.0"
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Example
|
||||
|
||||
```rust
|
||||
|
@ -36,7 +38,11 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
## Performance
|
||||
<br>
|
||||
|
||||
## Performance (lower is better)
|
||||
|
||||
![performance](https://raw.githubusercontent.com/dtolnay/ryu/master/performance.png)
|
||||
|
||||
You can run upstream's benchmarks with:
|
||||
|
||||
|
@ -69,20 +75,10 @@ standard library which you can run with:
|
|||
$ cargo bench
|
||||
```
|
||||
|
||||
The benchmark shows Ryū approximately 4-10x faster than the standard library
|
||||
The benchmark shows Ryū approximately 2-5x faster than the standard library
|
||||
across a range of f32 and f64 inputs. Measurements are in nanoseconds per
|
||||
iteration; smaller is better.
|
||||
|
||||
| type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
|
||||
|:--------:|:----:|:------:|:-----------------:|:--------:|
|
||||
| RYU | 3ns | 28ns | 23ns | 22ns |
|
||||
| STD | 40ns | 106ns | 128ns | 110ns |
|
||||
|
||||
| type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
|
||||
|:--------:|:----:|:------:|:-----------------:|:--------:|
|
||||
| RYU | 3ns | 50ns | 35ns | 32ns |
|
||||
| STD | 39ns | 105ns | 128ns | 202ns |
|
||||
|
||||
## Formatting
|
||||
|
||||
This library tends to produce more human-readable output than the standard
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::str::{self, FromStr};
|
||||
|
||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
||||
// opening a GitHub issue if your build environment requires some way to enable
|
||||
// these cfgs other than by executing our build script.
|
||||
fn main() {
|
||||
let minor = match rustc_minor_version() {
|
||||
Some(minor) => minor,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
|
||||
|
||||
// 128-bit integers disabled on Emscripten targets as Emscripten doesn't
|
||||
// currently support integers larger than 64 bits.
|
||||
if !emscripten {
|
||||
println!("cargo:rustc-cfg=integer128");
|
||||
}
|
||||
|
||||
// MaybeUninit<T> stabilized in Rust 1.36:
|
||||
// https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html
|
||||
if minor >= 36 {
|
||||
println!("cargo:rustc-cfg=maybe_uninit");
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_minor_version() -> Option<u32> {
|
||||
let rustc = env::var_os("RUSTC")?;
|
||||
let output = Command::new(rustc).arg("--version").output().ok()?;
|
||||
let version = str::from_utf8(&output.stdout).ok()?;
|
||||
let mut pieces = version.split('.');
|
||||
if pieces.next() != Some("rustc 1") {
|
||||
return None;
|
||||
}
|
||||
let next = pieces.next()?;
|
||||
u32::from_str(next).ok()
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
use crate::raw;
|
||||
#[cfg(not(maybe_uninit))]
|
||||
use core::mem;
|
||||
#[cfg(maybe_uninit)]
|
||||
use core::mem::MaybeUninit;
|
||||
use core::{slice, str};
|
||||
#[cfg(feature = "no-panic")]
|
||||
|
@ -21,10 +18,7 @@ const NEG_INFINITY: &str = "-inf";
|
|||
/// assert_eq!(printed, "1.234");
|
||||
/// ```
|
||||
pub struct Buffer {
|
||||
#[cfg(maybe_uninit)]
|
||||
bytes: [MaybeUninit<u8>; 24],
|
||||
#[cfg(not(maybe_uninit))]
|
||||
bytes: [u8; 24],
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
|
@ -33,13 +27,7 @@ impl Buffer {
|
|||
#[inline]
|
||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||
pub fn new() -> Self {
|
||||
// assume_init is safe here, since this is an array of MaybeUninit, which does not need
|
||||
// to be initialized.
|
||||
#[cfg(maybe_uninit)]
|
||||
let bytes = [MaybeUninit::<u8>::uninit(); 24];
|
||||
#[cfg(not(maybe_uninit))]
|
||||
let bytes = unsafe { mem::uninitialized() };
|
||||
|
||||
Buffer { bytes }
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,6 @@ pub use crate::d2s_full_table::*;
|
|||
use crate::d2s_intrinsics::*;
|
||||
#[cfg(feature = "small")]
|
||||
pub use crate::d2s_small_table::*;
|
||||
#[cfg(not(maybe_uninit))]
|
||||
use core::mem;
|
||||
#[cfg(maybe_uninit)]
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub const DOUBLE_MANTISSA_BITS: u32 = 52;
|
||||
|
@ -117,14 +114,7 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
|
|||
let mut vr: u64;
|
||||
let mut vp: u64;
|
||||
let mut vm: u64;
|
||||
#[cfg(not(maybe_uninit))]
|
||||
{
|
||||
vp = unsafe { mem::uninitialized() };
|
||||
vm = unsafe { mem::uninitialized() };
|
||||
}
|
||||
#[cfg(maybe_uninit)]
|
||||
let mut vp_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
|
||||
#[cfg(maybe_uninit)]
|
||||
let mut vm_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
|
||||
let e10: i32;
|
||||
let mut vm_is_trailing_zeros = false;
|
||||
|
@ -147,30 +137,13 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
|
|||
DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
|
||||
},
|
||||
i as u32,
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vp_uninit.as_mut_ptr()
|
||||
},
|
||||
#[cfg(not(maybe_uninit))]
|
||||
{
|
||||
&mut vp
|
||||
},
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vm_uninit.as_mut_ptr()
|
||||
},
|
||||
#[cfg(not(maybe_uninit))]
|
||||
{
|
||||
&mut vm
|
||||
},
|
||||
vp_uninit.as_mut_ptr(),
|
||||
vm_uninit.as_mut_ptr(),
|
||||
mm_shift,
|
||||
)
|
||||
};
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vp = unsafe { vp_uninit.assume_init() };
|
||||
vm = unsafe { vm_uninit.assume_init() };
|
||||
}
|
||||
vp = unsafe { vp_uninit.assume_init() };
|
||||
vm = unsafe { vm_uninit.assume_init() };
|
||||
if q <= 21 {
|
||||
// This should use q <= 22, but I think 21 is also safe. Smaller values
|
||||
// may still be safe, but it's more difficult to reason about them.
|
||||
|
@ -206,30 +179,13 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
|
|||
DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
|
||||
},
|
||||
j as u32,
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vp_uninit.as_mut_ptr()
|
||||
},
|
||||
#[cfg(not(maybe_uninit))]
|
||||
{
|
||||
&mut vp
|
||||
},
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vm_uninit.as_mut_ptr()
|
||||
},
|
||||
#[cfg(not(maybe_uninit))]
|
||||
{
|
||||
&mut vm
|
||||
},
|
||||
vp_uninit.as_mut_ptr(),
|
||||
vm_uninit.as_mut_ptr(),
|
||||
mm_shift,
|
||||
)
|
||||
};
|
||||
#[cfg(maybe_uninit)]
|
||||
{
|
||||
vp = unsafe { vp_uninit.assume_init() };
|
||||
vm = unsafe { vm_uninit.assume_init() };
|
||||
}
|
||||
vp = unsafe { vp_uninit.assume_init() };
|
||||
vm = unsafe { vm_uninit.assume_init() };
|
||||
if q <= 1 {
|
||||
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
|
||||
// mv = 4 * m2, so it always has at least two trailing 0 bits.
|
||||
|
|
|
@ -20,46 +20,6 @@
|
|||
|
||||
use core::ptr;
|
||||
|
||||
// Returns (lo, hi).
|
||||
#[cfg(not(integer128))]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn umul128(a: u64, b: u64) -> (u64, u64) {
|
||||
let a_lo = a as u32;
|
||||
let a_hi = (a >> 32) as u32;
|
||||
let b_lo = b as u32;
|
||||
let b_hi = (b >> 32) as u32;
|
||||
|
||||
let b00 = a_lo as u64 * b_lo as u64;
|
||||
let b01 = a_lo as u64 * b_hi as u64;
|
||||
let b10 = a_hi as u64 * b_lo as u64;
|
||||
let b11 = a_hi as u64 * b_hi as u64;
|
||||
|
||||
let b00_lo = b00 as u32;
|
||||
let b00_hi = (b00 >> 32) as u32;
|
||||
|
||||
let mid1 = b10 + b00_hi as u64;
|
||||
let mid1_lo = mid1 as u32;
|
||||
let mid1_hi = (mid1 >> 32) as u32;
|
||||
|
||||
let mid2 = b01 + mid1_lo as u64;
|
||||
let mid2_lo = mid2 as u32;
|
||||
let mid2_hi = (mid2 >> 32) as u32;
|
||||
|
||||
let p_hi = b11 + mid1_hi as u64 + mid2_hi as u64;
|
||||
let p_lo = ((mid2_lo as u64) << 32) | b00_lo as u64;
|
||||
|
||||
(p_lo, p_hi)
|
||||
}
|
||||
|
||||
#[cfg(not(integer128))]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn shiftright128(lo: u64, hi: u64, dist: u32) -> u64 {
|
||||
// We don't need to handle the case dist >= 64 here (see above).
|
||||
debug_assert!(dist > 0);
|
||||
debug_assert!(dist < 64);
|
||||
(hi << (64 - dist)) | (lo >> dist)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn div5(x: u64) -> u64 {
|
||||
x / 5
|
||||
|
@ -107,7 +67,6 @@ pub fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
|
|||
(value & ((1u64 << p) - 1)) == 0
|
||||
}
|
||||
|
||||
#[cfg(integer128)]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub fn mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u64 {
|
||||
let b0 = m as u128 * mul.0 as u128;
|
||||
|
@ -115,7 +74,6 @@ pub fn mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u64 {
|
|||
(((b0 >> 64) + b2) >> (j - 64)) as u64
|
||||
}
|
||||
|
||||
#[cfg(integer128)]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn mul_shift_all_64(
|
||||
m: u64,
|
||||
|
@ -129,43 +87,3 @@ pub unsafe fn mul_shift_all_64(
|
|||
ptr::write(vm, mul_shift_64(4 * m - 1 - mm_shift as u64, mul, j));
|
||||
mul_shift_64(4 * m, mul, j)
|
||||
}
|
||||
|
||||
#[cfg(not(integer128))]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn mul_shift_all_64(
|
||||
mut m: u64,
|
||||
mul: &(u64, u64),
|
||||
j: u32,
|
||||
vp: *mut u64,
|
||||
vm: *mut u64,
|
||||
mm_shift: u32,
|
||||
) -> u64 {
|
||||
m <<= 1;
|
||||
// m is maximum 55 bits
|
||||
let (lo, tmp) = umul128(m, mul.0);
|
||||
let (mut mid, mut hi) = umul128(m, mul.1);
|
||||
mid = mid.wrapping_add(tmp);
|
||||
hi = hi.wrapping_add((mid < tmp) as u64); // overflow into hi
|
||||
|
||||
let lo2 = lo.wrapping_add(mul.0);
|
||||
let mid2 = mid.wrapping_add(mul.1).wrapping_add((lo2 < lo) as u64);
|
||||
let hi2 = hi.wrapping_add((mid2 < mid) as u64);
|
||||
ptr::write(vp, shiftright128(mid2, hi2, j - 64 - 1));
|
||||
|
||||
if mm_shift == 1 {
|
||||
let lo3 = lo.wrapping_sub(mul.0);
|
||||
let mid3 = mid.wrapping_sub(mul.1).wrapping_sub((lo3 > lo) as u64);
|
||||
let hi3 = hi.wrapping_sub((mid3 > mid) as u64);
|
||||
ptr::write(vm, shiftright128(mid3, hi3, j - 64 - 1));
|
||||
} else {
|
||||
let lo3 = lo + lo;
|
||||
let mid3 = mid.wrapping_add(mid).wrapping_add((lo3 < lo) as u64);
|
||||
let hi3 = hi.wrapping_add(hi).wrapping_add((mid3 < mid) as u64);
|
||||
let lo4 = lo3.wrapping_sub(mul.0);
|
||||
let mid4 = mid3.wrapping_sub(mul.1).wrapping_sub((lo4 > lo3) as u64);
|
||||
let hi4 = hi3.wrapping_sub((mid4 > mid3) as u64);
|
||||
ptr::write(vm, shiftright128(mid4, hi4, j - 64));
|
||||
}
|
||||
|
||||
shiftright128(mid, hi, j - 64 - 1)
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
// KIND, either express or implied.
|
||||
|
||||
use crate::common::*;
|
||||
#[cfg(not(integer128))]
|
||||
use crate::d2s_intrinsics::*;
|
||||
|
||||
pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 15] = [
|
||||
(1, 2305843009213693952),
|
||||
|
@ -98,7 +96,6 @@ pub static DOUBLE_POW5_TABLE: [u64; 26] = [
|
|||
];
|
||||
|
||||
// Computes 5^i in the form required by Ryū.
|
||||
#[cfg(integer128)]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
|
||||
let base = i / DOUBLE_POW5_TABLE.len() as u32;
|
||||
|
@ -122,7 +119,6 @@ pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
|
|||
}
|
||||
|
||||
// Computes 5^-i in the form required by Ryū.
|
||||
#[cfg(integer128)]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
|
||||
let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
|
||||
|
@ -144,64 +140,3 @@ pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
|
|||
+ ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u128;
|
||||
(shifted_sum as u64, (shifted_sum >> 64) as u64)
|
||||
}
|
||||
|
||||
// Computes 5^i in the form required by Ryū, and stores it in the given pointer.
|
||||
#[cfg(not(integer128))]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
|
||||
let base = i / DOUBLE_POW5_TABLE.len() as u32;
|
||||
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
|
||||
let offset = i - base2;
|
||||
debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
|
||||
let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
|
||||
if offset == 0 {
|
||||
return mul;
|
||||
}
|
||||
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
|
||||
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
|
||||
let (low1, mut high1) = umul128(m, mul.1);
|
||||
let (low0, high0) = umul128(m, mul.0);
|
||||
let sum = high0 + low1;
|
||||
if sum < high0 {
|
||||
high1 += 1; // overflow into high1
|
||||
}
|
||||
// high1 | sum | low0
|
||||
let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
|
||||
debug_assert!(i / 16 < POW5_OFFSETS.len() as u32);
|
||||
(
|
||||
shiftright128(low0, sum, delta as u32)
|
||||
+ ((*POW5_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
|
||||
shiftright128(sum, high1, delta as u32),
|
||||
)
|
||||
}
|
||||
|
||||
// Computes 5^-i in the form required by Ryū, and stores it in the given pointer.
|
||||
#[cfg(not(integer128))]
|
||||
#[cfg_attr(feature = "no-panic", inline)]
|
||||
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
|
||||
let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
|
||||
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
|
||||
let offset = base2 - i;
|
||||
debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
|
||||
let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
|
||||
if offset == 0 {
|
||||
return mul;
|
||||
}
|
||||
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
|
||||
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
|
||||
let (low1, mut high1) = umul128(m, mul.1);
|
||||
let (low0, high0) = umul128(m, mul.0 - 1);
|
||||
let sum = high0 + low1;
|
||||
if sum < high0 {
|
||||
high1 += 1; // overflow into high1
|
||||
}
|
||||
// high1 | sum | low0
|
||||
let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
|
||||
debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
|
||||
(
|
||||
shiftright128(low0, sum, delta as u32)
|
||||
+ 1
|
||||
+ ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
|
||||
shiftright128(sum, high1, delta as u32),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Performance
|
||||
//! ## Performance (lower is better)
|
||||
//!
|
||||
//! ![performance](https://raw.githubusercontent.com/dtolnay/ryu/master/performance.png)
|
||||
//!
|
||||
//! You can run upstream's benchmarks with:
|
||||
//!
|
||||
|
@ -62,20 +64,10 @@
|
|||
//! $ cargo bench
|
||||
//! ```
|
||||
//!
|
||||
//! The benchmark shows Ryū approximately 4-10x faster than the standard library
|
||||
//! The benchmark shows Ryū approximately 2-5x faster than the standard library
|
||||
//! across a range of f32 and f64 inputs. Measurements are in nanoseconds per
|
||||
//! iteration; smaller is better.
|
||||
//!
|
||||
//! | type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
|
||||
//! |:--------:|:----:|:------:|:-----------------:|:--------:|
|
||||
//! | RYU | 3ns | 28ns | 23ns | 22ns |
|
||||
//! | STD | 40ns | 106ns | 128ns | 110ns |
|
||||
//!
|
||||
//! | type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
|
||||
//! |:--------:|:----:|:------:|:-----------------:|:--------:|
|
||||
//! | RYU | 3ns | 50ns | 35ns | 32ns |
|
||||
//! | STD | 39ns | 105ns | 128ns | 202ns |
|
||||
//!
|
||||
//! ## Formatting
|
||||
//!
|
||||
//! This library tends to produce more human-readable output than the standard
|
||||
|
@ -89,7 +81,7 @@
|
|||
//! notation.
|
||||
|
||||
#![no_std]
|
||||
#![doc(html_root_url = "https://docs.rs/ryu/1.0.6")]
|
||||
#![doc(html_root_url = "https://docs.rs/ryu/1.0.9")]
|
||||
#![allow(
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_possible_truncation,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
clippy::cast_sign_loss,
|
||||
clippy::excessive_precision,
|
||||
clippy::float_cmp,
|
||||
clippy::manual_range_contains,
|
||||
clippy::similar_names,
|
||||
clippy::too_many_lines,
|
||||
clippy::unreadable_literal,
|
||||
|
@ -37,12 +38,17 @@
|
|||
#[path = "../src/common.rs"]
|
||||
mod common;
|
||||
|
||||
#[cfg(not(feature = "small"))]
|
||||
#[path = "../src/d2s_full_table.rs"]
|
||||
mod d2s_full_table;
|
||||
|
||||
#[path = "../src/d2s_intrinsics.rs"]
|
||||
mod d2s_intrinsics;
|
||||
|
||||
#[cfg(feature = "small")]
|
||||
#[path = "../src/d2s_small_table.rs"]
|
||||
mod d2s_small_table;
|
||||
|
||||
#[path = "../src/d2s.rs"]
|
||||
mod d2s;
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
clippy::cast_possible_wrap,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::checked_conversions,
|
||||
clippy::float_cmp,
|
||||
clippy::manual_range_contains,
|
||||
clippy::similar_names,
|
||||
clippy::too_many_lines,
|
||||
clippy::unreadable_literal,
|
||||
|
@ -36,12 +38,17 @@
|
|||
#[path = "../src/common.rs"]
|
||||
mod common;
|
||||
|
||||
#[cfg(not(feature = "small"))]
|
||||
#[path = "../src/d2s_full_table.rs"]
|
||||
mod d2s_full_table;
|
||||
|
||||
#[path = "../src/d2s_intrinsics.rs"]
|
||||
mod d2s_intrinsics;
|
||||
|
||||
#[cfg(feature = "small")]
|
||||
#[path = "../src/d2s_small_table.rs"]
|
||||
mod d2s_small_table;
|
||||
|
||||
#[path = "../src/d2s.rs"]
|
||||
mod d2s;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"3657dd930eecc3a6743fc25f341fb3bd06402ddbec2dcdfae6ef156c7167c6f4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5cf9d2158d70048a2916360ad59d9079f6233c6f68781a7a792e70f8b772d8ce","build.rs":"266866315e377f6f74f639bfd993192a46e203be31892e4173862816e8414767","crates-io.md":"25ed421fe25d0f6f74c4b78674144bef2843a5f78bf552d0a8ec633be69d282b","src/de/ignored_any.rs":"c69d6071191c2075372218442e9e73991335c6b4be18736a7a789f04bb305525","src/de/impls.rs":"8505b47b4fa97e426bedf97082005ee2d5700bfac0da41da9127c9826004c163","src/de/mod.rs":"5c176d8d909910a100f67eb26de8228c3e6465886100cdc3bcc146c16aec111e","src/de/seed.rs":"e8cf0233afe0af5b8fb9e4c94f301c92729c5ba417280af9e2201b732e374a72","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"82d530d0bc50cba75a095c819b4269d58229a7384043f7f6e674891cc6dae7bb","src/integer128.rs":"12f6ce6a513c1c293398db38cf1d3ea7c0c5a6717152621bcba61f49abc7b5b1","src/lib.rs":"c2739452e0bbff4727064a6fb9e24cd35271783a5c2c671e84e5fa985367035a","src/macros.rs":"3d695a51f0a07f9f719dcb5620012c21a1b084c06a6283349cabf574ceba8123","src/private/de.rs":"abcd02697fc887d6a9c450dfa1ceb640e069683532998ed4ba3c0b859b4744d7","src/private/doc.rs":"e9801a43c3088fccd5f1fac76416698f948e65b647024aa9da17d673e1e8c217","src/private/mod.rs":"761d198c739508117beeaae44ae4e11769aaa6c2e9a4acf584eb9adc1952879f","src/private/ser.rs":"3a90dfb5c17e81bf1d959fed60a9477713498e9d0934463627c98709132f066e","src/private/size_hint.rs":"605521227e9ba3100fbb9d5ea7fd5853385097c35015ce6908bd5f1ea20d59ad","src/ser/fmt.rs":"7827ed07fd8897e6324f75625ba0c926a4c4e7ec2914cd067391ce54d942ac7b","src/ser/impls.rs":"c99000b33b2b7cb1c9b275f769f0cb5dd6ecb3caf260b66f2d0157e6faf04d96","src/ser/impossible.rs":"db17913522c1c27389c5a085113911353b9813c1b116518681362e7c8b692c3a","src/ser/mod.rs":"4f686acd03f310a966194ef225a0cec5f96810bf73f636f670601c3d2d9018c6","src/std_error.rs":"3aac687856c035517fae44ed2906dd4a1e3184bae4bf613adcdeb73f74126c57"},"package":"f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"}
|
||||
{"files":{"Cargo.toml":"ace9341af7b409c35b4ca81007e3a762dcc5157a2b31459ffeb4989a528bcaf5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5cf9d2158d70048a2916360ad59d9079f6233c6f68781a7a792e70f8b772d8ce","build.rs":"adfdafeb547084efb49f2845325b97f7105e48fa9e8c5045d0bf6c3597d28d14","crates-io.md":"25ed421fe25d0f6f74c4b78674144bef2843a5f78bf552d0a8ec633be69d282b","src/de/ignored_any.rs":"c69d6071191c2075372218442e9e73991335c6b4be18736a7a789f04bb305525","src/de/impls.rs":"8505b47b4fa97e426bedf97082005ee2d5700bfac0da41da9127c9826004c163","src/de/mod.rs":"a390d6a40c8a582914938388b76fe28bc2a1052fd3356fb6c8b953b0551d2913","src/de/seed.rs":"e8cf0233afe0af5b8fb9e4c94f301c92729c5ba417280af9e2201b732e374a72","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"82d530d0bc50cba75a095c819b4269d58229a7384043f7f6e674891cc6dae7bb","src/integer128.rs":"12f6ce6a513c1c293398db38cf1d3ea7c0c5a6717152621bcba61f49abc7b5b1","src/lib.rs":"2c495b29f989ee9087b98a20d347d05a345c2a23817e4ff2aafe5aa53cb7472c","src/macros.rs":"3d695a51f0a07f9f719dcb5620012c21a1b084c06a6283349cabf574ceba8123","src/private/de.rs":"ae9fd944944f9c2fb2eb07a622439c7ebdeab5e9d218cdaec9197cb5caa0941c","src/private/doc.rs":"e9801a43c3088fccd5f1fac76416698f948e65b647024aa9da17d673e1e8c217","src/private/mod.rs":"761d198c739508117beeaae44ae4e11769aaa6c2e9a4acf584eb9adc1952879f","src/private/ser.rs":"3a90dfb5c17e81bf1d959fed60a9477713498e9d0934463627c98709132f066e","src/private/size_hint.rs":"605521227e9ba3100fbb9d5ea7fd5853385097c35015ce6908bd5f1ea20d59ad","src/ser/fmt.rs":"7827ed07fd8897e6324f75625ba0c926a4c4e7ec2914cd067391ce54d942ac7b","src/ser/impls.rs":"6c93706feba06ca56c5b2c7c7e1e82075de3a51ab36569bae49ca22215fb753b","src/ser/impossible.rs":"db17913522c1c27389c5a085113911353b9813c1b116518681362e7c8b692c3a","src/ser/mod.rs":"4f686acd03f310a966194ef225a0cec5f96810bf73f636f670601c3d2d9018c6","src/std_error.rs":"3aac687856c035517fae44ed2906dd4a1e3184bae4bf613adcdeb73f74126c57"},"package":"97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"}
|
|
@ -10,8 +10,9 @@
|
|||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
rust-version = "1.15"
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
version = "1.0.133"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
@ -29,7 +30,7 @@ targets = ["x86_64-unknown-linux-gnu"]
|
|||
[package.metadata.playground]
|
||||
features = ["derive", "rc"]
|
||||
[dependencies.serde_derive]
|
||||
version = "=1.0.130"
|
||||
version = "=1.0.133"
|
||||
optional = true
|
||||
[dev-dependencies.serde_derive]
|
||||
version = "1.0"
|
||||
|
|
|
@ -91,13 +91,14 @@ fn main() {
|
|||
|
||||
// Whitelist of archs that support std::sync::atomic module. Ideally we
|
||||
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
|
||||
// Instead this is based on rustc's src/librustc_target/spec/*.rs.
|
||||
// Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs.
|
||||
let has_atomic64 = target.starts_with("x86_64")
|
||||
|| target.starts_with("i686")
|
||||
|| target.starts_with("aarch64")
|
||||
|| target.starts_with("powerpc64")
|
||||
|| target.starts_with("sparc64")
|
||||
|| target.starts_with("mips64el");
|
||||
|| target.starts_with("mips64el")
|
||||
|| target.starts_with("riscv64");
|
||||
let has_atomic32 = has_atomic64 || emscripten;
|
||||
if has_atomic64 {
|
||||
println!("cargo:rustc-cfg=std_atomic64");
|
||||
|
|
|
@ -1213,6 +1213,20 @@ pub trait Deserializer<'de>: Sized {
|
|||
fn is_human_readable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[cfg(all(serde_derive, any(feature = "std", feature = "alloc")))]
|
||||
#[doc(hidden)]
|
||||
fn __deserialize_content<V>(
|
||||
self,
|
||||
_: ::actually_private::T,
|
||||
visitor: V,
|
||||
) -> Result<::private::de::Content<'de>, Self::Error>
|
||||
where
|
||||
V: Visitor<'de, Value = ::private::de::Content<'de>>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
//!
|
||||
//! [JSON]: https://github.com/serde-rs/json
|
||||
//! [Bincode]: https://github.com/servo/bincode
|
||||
//! [CBOR]: https://github.com/pyfisch/cbor
|
||||
//! [CBOR]: https://github.com/enarx/ciborium
|
||||
//! [YAML]: https://github.com/dtolnay/serde-yaml
|
||||
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
|
||||
//! [TOML]: https://github.com/alexcrichton/toml-rs
|
||||
|
@ -73,7 +73,7 @@
|
|||
//! [URL]: https://docs.rs/serde_qs
|
||||
//! [Envy]: https://github.com/softprops/envy
|
||||
//! [Envy Store]: https://github.com/softprops/envy-store
|
||||
//! [Cargo]: http://doc.crates.io/manifest.html
|
||||
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
|
||||
//! [S-expressions]: https://github.com/rotty/lexpr-rs
|
||||
//! [D-Bus]: https://docs.rs/zvariant
|
||||
|
@ -84,7 +84,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.130")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.133")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Unstable functionality only if the user asks for it. For tracking and
|
||||
|
@ -94,13 +94,14 @@
|
|||
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||
#![allow(unknown_lints, bare_trait_objects, deprecated)]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// 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
|
||||
checked_conversions,
|
||||
empty_enum,
|
||||
|
@ -294,3 +295,8 @@ extern crate serde_derive;
|
|||
#[cfg(feature = "serde_derive")]
|
||||
#[doc(hidden)]
|
||||
pub use serde_derive::*;
|
||||
|
||||
#[cfg(all(serde_derive, any(feature = "std", feature = "alloc")))]
|
||||
mod actually_private {
|
||||
pub struct T;
|
||||
}
|
||||
|
|
|
@ -206,6 +206,7 @@ mod content {
|
|||
use lib::*;
|
||||
|
||||
use __private::size_hint;
|
||||
use actually_private;
|
||||
use de::{
|
||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||
|
@ -215,7 +216,7 @@ mod content {
|
|||
/// deserializing untagged enums and internally tagged enums.
|
||||
///
|
||||
/// Not public API. Use serde-value instead.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Content<'de> {
|
||||
Bool(bool),
|
||||
|
||||
|
@ -294,7 +295,7 @@ mod content {
|
|||
// Untagged and internally tagged enums are only supported in
|
||||
// self-describing formats.
|
||||
let visitor = ContentVisitor { value: PhantomData };
|
||||
deserializer.deserialize_any(visitor)
|
||||
deserializer.__deserialize_content(actually_private::T, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1427,6 +1428,18 @@ mod content {
|
|||
drop(self);
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn __deserialize_content<V>(
|
||||
self,
|
||||
_: actually_private::T,
|
||||
visitor: V,
|
||||
) -> Result<Content<'de>, Self::Error>
|
||||
where
|
||||
V: Visitor<'de, Value = Content<'de>>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Ok(self.content)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> ContentDeserializer<'de, E> {
|
||||
|
@ -2138,6 +2151,18 @@ mod content {
|
|||
{
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn __deserialize_content<V>(
|
||||
self,
|
||||
_: actually_private::T,
|
||||
visitor: V,
|
||||
) -> Result<Content<'de>, Self::Error>
|
||||
where
|
||||
V: Visitor<'de, Value = Content<'de>>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Ok(self.content.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {
|
||||
|
|
|
@ -915,6 +915,7 @@ macro_rules! atomic_impl {
|
|||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// Matches the atomic ordering used in libcore for the Debug impl
|
||||
self.load(Ordering::SeqCst).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"900a8fd1ed5ed528dee953b986d99caef871be0e180d75a867e4d6d552c15ef2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5cf9d2158d70048a2916360ad59d9079f6233c6f68781a7a792e70f8b772d8ce","build.rs":"d0fc2047a792e90b95df7be8d1e75732b231b3a60cb481feebfca46b7edb1209","crates-io.md":"25ed421fe25d0f6f74c4b78674144bef2843a5f78bf552d0a8ec633be69d282b","src/bound.rs":"afb3550b77f271f38d8b5c38141a6a45687a8264dc3c6349ccf14ef0dd911dfe","src/de.rs":"c35ef3bccfc23d07fb6f87e7c52c7cac8a63ce15e35b9000bed406cb2f98685b","src/dummy.rs":"ad78556876053e74be976e91032200666ffbeeb6f7e92f3a7a8463fea1f60ac5","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"d3ae0ad0e7d40fbf3c8a5f86c8a8c5b5f289c3318dd79afc6c5c2ce9b3523931","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"11ea94257d2a2ee2276938a6beb4ae11b74c39225c1e342e6df1e7d2b2924496","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"ad30c3e4583ef07f74c7905f22a6580af25ebd431fdf1e04878b9a770ca4ede6","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"3c9ce461773b7df3bb64d82aa5a0d93052c3bb0e60209db6c0b5c10ee9cfc9cf","src/lib.rs":"3f75e3a849cbe74bac87e7ef2f9d97caabc1e5a5a159bb3ba2da855e55e2ddb0","src/pretend.rs":"113ff3ba6dbf42d4999663b1abe57fdeb72ba7376cfd90dc81829439be7dfbb0","src/ser.rs":"0d99c841f6c7bc9751ab225fe42d1f8b7fe56e36903efcb4ff10bf6e35c390ba","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"}
|
||||
{"files":{"Cargo.toml":"b5633393dd45d256ac07041528902fb2a68208df77fb4204c44a9086d0a4039b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5cf9d2158d70048a2916360ad59d9079f6233c6f68781a7a792e70f8b772d8ce","build.rs":"d0fc2047a792e90b95df7be8d1e75732b231b3a60cb481feebfca46b7edb1209","crates-io.md":"25ed421fe25d0f6f74c4b78674144bef2843a5f78bf552d0a8ec633be69d282b","src/bound.rs":"f3a1a7b76426921ee435e9963c02c2fc7663c15aecfdf6dc1198aacf3f4c2e70","src/de.rs":"c5a41016ce15f8176a2d7a8445ba06d2eb8de0863c1fea0dab51c395dd7dccff","src/dummy.rs":"ad78556876053e74be976e91032200666ffbeeb6f7e92f3a7a8463fea1f60ac5","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"d3ae0ad0e7d40fbf3c8a5f86c8a8c5b5f289c3318dd79afc6c5c2ce9b3523931","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"11ea94257d2a2ee2276938a6beb4ae11b74c39225c1e342e6df1e7d2b2924496","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"ad30c3e4583ef07f74c7905f22a6580af25ebd431fdf1e04878b9a770ca4ede6","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"3c9ce461773b7df3bb64d82aa5a0d93052c3bb0e60209db6c0b5c10ee9cfc9cf","src/lib.rs":"29038346522acd412b6a54e60ccea8c3e89498decdf5e8deb172fdc0bc10f7be","src/pretend.rs":"73fe121ced5804e77d37512bd2c7548be249dcab3eeb0bad59f82e64188f9ace","src/ser.rs":"0d99c841f6c7bc9751ab225fe42d1f8b7fe56e36903efcb4ff10bf6e35c390ba","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"}
|
|
@ -10,8 +10,9 @@
|
|||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
rust-version = "1.31"
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
version = "1.0.133"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn with_where_predicates_from_fields(
|
|||
.data
|
||||
.all_fields()
|
||||
.filter_map(|field| from_field(&field.attrs))
|
||||
.flat_map(|predicates| predicates.to_vec());
|
||||
.flat_map(<[syn::WherePredicate]>::to_vec);
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.make_where_clause().predicates.extend(predicates);
|
||||
|
@ -72,7 +72,7 @@ pub fn with_where_predicates_from_variants(
|
|||
let predicates = variants
|
||||
.iter()
|
||||
.filter_map(|variant| from_variant(&variant.attrs))
|
||||
.flat_map(|predicates| predicates.to_vec());
|
||||
.flat_map(<[syn::WherePredicate]>::to_vec);
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.make_where_clause().predicates.extend(predicates);
|
||||
|
|
|
@ -1458,7 +1458,7 @@ fn deserialize_adjacently_tagged_enum(
|
|||
while let _serde::__private::Some(__k) = #next_key {
|
||||
match __k {
|
||||
_serde::__private::de::TagContentOtherField::Other => {
|
||||
try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
|
||||
let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
|
||||
continue;
|
||||
},
|
||||
_serde::__private::de::TagContentOtherField::Tag => {
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.130")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.133")]
|
||||
#![allow(unknown_lints, bare_trait_objects)]
|
||||
#![deny(clippy::all, clippy::pedantic)]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||
|
@ -44,6 +43,7 @@
|
|||
clippy::indexing_slicing,
|
||||
clippy::items_after_statements,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::manual_assert,
|
||||
clippy::map_err_ignore,
|
||||
clippy::match_same_arms,
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
||||
|
|
|
@ -65,11 +65,13 @@ 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) => if is_packed {
|
||||
pretend_fields_used_struct_packed(cont, fields)
|
||||
} else {
|
||||
pretend_fields_used_struct(cont, fields)
|
||||
},
|
||||
Data::Struct(Style::Struct, fields) => {
|
||||
if is_packed {
|
||||
pretend_fields_used_struct_packed(cont, fields)
|
||||
} else {
|
||||
pretend_fields_used_struct(cont, fields)
|
||||
}
|
||||
}
|
||||
Data::Struct(_, _) => quote!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"a06725969cd30292d9703460dfdeede771ab7efd34cbbed994c12a025293bf98","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0ecc4d2dbcf421446379a2aa54e68632d510148f58620e3df87b57e07bf41951","src/de.rs":"cfbf60479f62e86b6274ebf700cba88168174853ac899a5e68e446faa0ee04a3","src/error.rs":"84ebb62e090ace13bcf14f1f2bebabcdc1a9518b7e24f81c1bb250a152a1ec1e","src/lib.rs":"aadd2dbf3c19ae49c23962dc6004b4800d03cec3b67ef1436002082c3b6d4fa8","src/mapping.rs":"6607911090c89a41ade38f1717b9c0bd6c3c253cc4711890b77b2bda18d6bac7","src/number.rs":"4edf78ad75bf66bae31c1ee4d785ba2b7a2c14c082802d54c9feb93067bcf063","src/path.rs":"44d339ce1814effd10ba131ae0393df215f09dbfb35ab4d678f49d4081f58dd4","src/ser.rs":"f969d7a7eb528e537ad23be97ce2fddc3f616cec31a186e9fa21a66db889f136","src/value/de.rs":"84b213b23a8d4bf6bd9aacd18fc1091254382c4edc479f9a9abc87c416b370f0","src/value/from.rs":"cd66c76c4ab03bed32f8c4b22ffbd96274a837d587624a62d0584c7090633862","src/value/index.rs":"183e00a706310144e33eb79a66fae527cc6c982210b3973f4701c6da6faeb93e","src/value/mod.rs":"171a98133de3445ccd4cfa3991b5c3f96baa1c05542fc1927e6eccf3e4ddbe09","src/value/partial_eq.rs":"0b28c8d2f10a58581dbe2a69d25742fa0f8bf3da797f3046e38e300d1f9691bf","src/value/ser.rs":"7ddb9bfadfbfe16a79c872888ea25f8fb7df14b862fea47dd603d576e162db86","tests/test_de.rs":"283936649181a0de40b099105da743e049422f1e1311399e69e14404b7753bab","tests/test_error.rs":"ca1c349a16ea5eb539ef2382d7af39a63a8afbcd0cb4397292f43bffa519e848","tests/test_serde.rs":"f44daa0d032769779fd437b001188cf1143cec9796fd8785211518fc86828541","tests/test_value.rs":"e9424b8ee13c18c4375c3a7e1af25047e2ef3efb117b1413334c0950c912937a","tests/test_visitor.rs":"c7e15a2712f7e8fbc7f4c09893af732eb92beaa5c3d32dc21d362ed8d851d673"},"package":"d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"}
|
||||
{"files":{"Cargo.toml":"dd6c4ad4666cecccc8e3dfa6c79bde8d6282c73778bde32865f81ebda28ec5c2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0ecc4d2dbcf421446379a2aa54e68632d510148f58620e3df87b57e07bf41951","src/de.rs":"98be0ec59da4b6f69a54b0bfaa199b1b021527e9e36872df3f8a864f203f353c","src/error.rs":"84ebb62e090ace13bcf14f1f2bebabcdc1a9518b7e24f81c1bb250a152a1ec1e","src/lib.rs":"c0a487813783b4db0c4f37be2ec41084042fbf2cb3f24b191de90bce5790ae78","src/mapping.rs":"6607911090c89a41ade38f1717b9c0bd6c3c253cc4711890b77b2bda18d6bac7","src/number.rs":"4edf78ad75bf66bae31c1ee4d785ba2b7a2c14c082802d54c9feb93067bcf063","src/path.rs":"44d339ce1814effd10ba131ae0393df215f09dbfb35ab4d678f49d4081f58dd4","src/ser.rs":"412068add72b3b2d0665fc635590ad1f7d2c097dc5e76721110869dfdf83074a","src/value/de.rs":"84b213b23a8d4bf6bd9aacd18fc1091254382c4edc479f9a9abc87c416b370f0","src/value/from.rs":"cd66c76c4ab03bed32f8c4b22ffbd96274a837d587624a62d0584c7090633862","src/value/index.rs":"183e00a706310144e33eb79a66fae527cc6c982210b3973f4701c6da6faeb93e","src/value/mod.rs":"171a98133de3445ccd4cfa3991b5c3f96baa1c05542fc1927e6eccf3e4ddbe09","src/value/partial_eq.rs":"0b28c8d2f10a58581dbe2a69d25742fa0f8bf3da797f3046e38e300d1f9691bf","src/value/ser.rs":"7ddb9bfadfbfe16a79c872888ea25f8fb7df14b862fea47dd603d576e162db86","tests/test_de.rs":"41911d6392b5704240ee147e2c146371f479b9115cdaf7e0e8639529d0bc1251","tests/test_error.rs":"4ef5c9001f140e1aee1e9d6238c668d26b5b264e237773741d5f65bfff036e75","tests/test_serde.rs":"e237e3144ce0ba943ed37d645f7ccede98c6ea0368e12fde88c4eede650c80d4","tests/test_value.rs":"e9424b8ee13c18c4375c3a7e1af25047e2ef3efb117b1413334c0950c912937a"},"package":"a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"}
|
|
@ -11,8 +11,9 @@
|
|||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.38"
|
||||
name = "serde_yaml"
|
||||
version = "0.8.21"
|
||||
version = "0.8.23"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
description = "YAML support for Serde"
|
||||
documentation = "https://docs.rs/serde_yaml/"
|
||||
|
@ -22,12 +23,12 @@ license = "MIT OR Apache-2.0"
|
|||
repository = "https://github.com/dtolnay/serde-yaml"
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
[dependencies.dtoa]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.5"
|
||||
|
||||
[dependencies.ryu]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0.69"
|
||||
|
||||
|
|
|
@ -987,7 +987,10 @@ where
|
|||
return visitor.visit_i64(n);
|
||||
}
|
||||
}
|
||||
if v.len() > 1 && v.starts_with('0') && v.bytes().all(|b| b.is_ascii_digit()) {
|
||||
if {
|
||||
let v = v.trim_start_matches(&['-', '+'][..]);
|
||||
v.len() > 1 && v.starts_with('0') && v[1..].bytes().all(|b| b.is_ascii_digit())
|
||||
} {
|
||||
// After handling the different number encodings above if we are left
|
||||
// with leading zero(s) followed by numeric characters this is in fact a
|
||||
// string according to the YAML 1.2 spec.
|
||||
|
|
|
@ -65,15 +65,18 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.21")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.23")]
|
||||
#![deny(missing_docs)]
|
||||
// Suppressed clippy_pedantic lints
|
||||
#![allow(
|
||||
// buggy
|
||||
clippy::question_mark, // https://github.com/rust-lang/rust-clippy/issues/7859
|
||||
// private Deserializer::next
|
||||
clippy::should_implement_trait,
|
||||
// things are often more readable this way
|
||||
clippy::cast_lossless,
|
||||
clippy::if_not_else,
|
||||
clippy::manual_assert,
|
||||
clippy::match_same_arms,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::needless_pass_by_value,
|
||||
|
@ -81,6 +84,7 @@
|
|||
clippy::redundant_else,
|
||||
clippy::single_match_else,
|
||||
// code is acceptable
|
||||
clippy::blocks_in_if_conditions,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::cast_precision_loss,
|
||||
clippy::doc_markdown,
|
||||
|
|
|
@ -518,11 +518,7 @@ impl ser::Serializer for SerializerToYaml {
|
|||
num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(),
|
||||
num::FpCategory::Infinite => "-.inf".into(),
|
||||
num::FpCategory::Nan => ".nan".into(),
|
||||
_ => {
|
||||
let mut buf = vec![];
|
||||
dtoa::write(&mut buf, v).unwrap();
|
||||
str::from_utf8(&buf).unwrap().into()
|
||||
}
|
||||
_ => ryu::Buffer::new().format_finite(v).into(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -531,11 +527,7 @@ impl ser::Serializer for SerializerToYaml {
|
|||
num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(),
|
||||
num::FpCategory::Infinite => "-.inf".into(),
|
||||
num::FpCategory::Nan => ".nan".into(),
|
||||
_ => {
|
||||
let mut buf = vec![];
|
||||
dtoa::write(&mut buf, v).unwrap();
|
||||
str::from_utf8(&buf).unwrap().into()
|
||||
}
|
||||
_ => ryu::Buffer::new().format_finite(v).into(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -339,7 +339,17 @@ fn test_numbers() {
|
|||
let value = serde_yaml::from_str::<Value>(yaml).unwrap();
|
||||
match value {
|
||||
Value::Number(number) => assert_eq!(number.to_string(), expected),
|
||||
_ => panic!("expected number"),
|
||||
_ => panic!("expected number. input={:?}, result={:?}", yaml, value),
|
||||
}
|
||||
}
|
||||
|
||||
// NOT numbers.
|
||||
let cases = ["0127", "+0127", "-0127"];
|
||||
for yaml in &cases {
|
||||
let value = serde_yaml::from_str::<Value>(yaml).unwrap();
|
||||
match value {
|
||||
Value::String(string) => assert_eq!(string, *yaml),
|
||||
_ => panic!("expected string. input={:?}, result={:?}", yaml, value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ fn test_incorrect_type() {
|
|||
fn test_incorrect_nested_type() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct A {
|
||||
#[allow(dead_code)]
|
||||
b: Vec<B>,
|
||||
}
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
@ -32,6 +33,7 @@ fn test_incorrect_nested_type() {
|
|||
}
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct C {
|
||||
#[allow(dead_code)]
|
||||
d: bool,
|
||||
}
|
||||
let yaml = indoc! {"
|
||||
|
@ -55,7 +57,9 @@ fn test_empty() {
|
|||
fn test_missing_field() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Basic {
|
||||
#[allow(dead_code)]
|
||||
v: bool,
|
||||
#[allow(dead_code)]
|
||||
w: bool,
|
||||
}
|
||||
let yaml = indoc! {"
|
||||
|
@ -80,6 +84,7 @@ fn test_unknown_anchor() {
|
|||
fn test_ignored_unknown_anchor() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Wrapper {
|
||||
#[allow(dead_code)]
|
||||
c: (),
|
||||
}
|
||||
let yaml = indoc! {"
|
||||
|
@ -220,6 +225,7 @@ fn test_no_location() {
|
|||
fn test_invalid_scalar_type() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct S {
|
||||
#[allow(dead_code)]
|
||||
x: [(); 1],
|
||||
}
|
||||
|
||||
|
@ -232,6 +238,7 @@ fn test_invalid_scalar_type() {
|
|||
fn test_infinite_recursion_objects() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct S {
|
||||
#[allow(dead_code)]
|
||||
x: Option<Box<S>>,
|
||||
}
|
||||
|
||||
|
@ -244,6 +251,7 @@ fn test_infinite_recursion_objects() {
|
|||
fn test_infinite_recursion_arrays() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct S {
|
||||
#[allow(dead_code)]
|
||||
x: Option<Box<S>>,
|
||||
}
|
||||
|
||||
|
@ -256,6 +264,7 @@ fn test_infinite_recursion_arrays() {
|
|||
fn test_finite_recursion_objects() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct S {
|
||||
#[allow(dead_code)]
|
||||
x: Option<Box<S>>,
|
||||
}
|
||||
|
||||
|
@ -268,6 +277,7 @@ fn test_finite_recursion_objects() {
|
|||
fn test_finite_recursion_arrays() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct S {
|
||||
#[allow(dead_code)]
|
||||
x: Option<Box<S>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,6 @@ fn test_float32() {
|
|||
"})
|
||||
.unwrap();
|
||||
assert!(single_float.is_nan());
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -273,6 +272,18 @@ fn test_unit() {
|
|||
test_serde(&thing, yaml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit_struct() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Foo;
|
||||
let thing = Foo;
|
||||
let yaml = indoc! {"
|
||||
---
|
||||
~
|
||||
"};
|
||||
test_serde(&thing, yaml);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit_variant() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
struct Names {
|
||||
inner: HashSet<String>,
|
||||
}
|
||||
|
||||
impl Serialize for Names {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut names: Vec<_> = self.inner.iter().collect();
|
||||
names.sort();
|
||||
names.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Names {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Names, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(NamesVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct NamesVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for NamesVisitor {
|
||||
type Value = Names;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("names or list of names")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
let mut out = HashSet::new();
|
||||
out.insert(v.to_string());
|
||||
Ok(Names { inner: out })
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut out: HashSet<String> = HashSet::new();
|
||||
|
||||
// FIXME: Change `&str` to String to make the error go away
|
||||
while let Some(s) = seq.next_element::<&str>()? {
|
||||
out.insert(s.to_string());
|
||||
}
|
||||
Ok(Names { inner: out })
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
/// This test is an almost exact replica of the "string or struct" example
|
||||
/// in the [serde guide](https://serde.rs/string-or-struct.html)
|
||||
///
|
||||
/// FIXME: it currently breaks. If you explicitly select `String` instead
|
||||
/// of `&str` in the FIXME above, it works.
|
||||
fn test_visitor() {
|
||||
let single = r#"
|
||||
---
|
||||
"foo"
|
||||
"#;
|
||||
let single_expected = Names {
|
||||
inner: {
|
||||
let mut i = HashSet::new();
|
||||
i.insert("foo".into());
|
||||
i
|
||||
},
|
||||
};
|
||||
let multi = r#"
|
||||
---
|
||||
- "foo"
|
||||
- "bar"
|
||||
"#;
|
||||
let multi_expected = Names {
|
||||
inner: {
|
||||
let mut i = HashSet::new();
|
||||
i.insert("foo".into());
|
||||
i.insert("bar".into());
|
||||
i
|
||||
},
|
||||
};
|
||||
|
||||
let result: Names = serde_yaml::from_str(single).expect("didn't deserialize");
|
||||
assert_eq!(result, single_expected);
|
||||
|
||||
let result: Names = serde_yaml::from_str(multi).expect("didn't deserialize");
|
||||
assert_eq!(result, multi_expected);
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{"COPYING":"2667c3da82a038bfbbd64cdb0fde6ecabda683e473fc1c10cc2b31c1c65e7fb6","Cargo.toml":"aff55aa2a246d0476405d0082858528726db4d3437acf9bfd1e6841804105073","README.md":"c0ffa167eca7e8aa8efc05c0514234aff3f522fc2e327edf6f86d4fbfa8502a8","src/lib.rs":"dac421e799bfb49f9721af1083101af6846fef78268362172450f2a2c0f6250c","src/sip.rs":"3bb394ccaf38c604033aaafc5de632634f50d17368181ed6cd37bce78f3f06e8","src/sip128.rs":"b94199088f4ceddd92aef5cc636fc49f23bb1b84174138de77dcdf82408fe413","src/tests.rs":"0195439c356f3557cf83dab2a8e6adbe5eac1c9f6ba66bf27b3c2e40f9345066","src/tests128.rs":"b85b8893c14a3b4ea782d2084b6de414456ef6dd0b55d1c29c68a3e46516d07c"},"package":"533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b"}
|
||||
{"files":{"COPYING":"2667c3da82a038bfbbd64cdb0fde6ecabda683e473fc1c10cc2b31c1c65e7fb6","Cargo.toml":"8da86a3a330dc2b1a48657b71349f23ba7636c775239f9cc8f4f9fc2bea13b76","README.md":"c0ffa167eca7e8aa8efc05c0514234aff3f522fc2e327edf6f86d4fbfa8502a8","src/lib.rs":"dac421e799bfb49f9721af1083101af6846fef78268362172450f2a2c0f6250c","src/sip.rs":"e7fb94566cdaf25c15424dd663c2c4f267e4821b1d4fd04ede9f6c4206a41381","src/sip128.rs":"5de9afdc224c143f3835cc4519b83a6a51fafbd350f61c5ece44fb3b72bc407a","src/tests.rs":"0195439c356f3557cf83dab2a8e6adbe5eac1c9f6ba66bf27b3c2e40f9345066","src/tests128.rs":"b85b8893c14a3b4ea782d2084b6de414456ef6dd0b55d1c29c68a3e46516d07c"},"package":"ba1eead9e94aa5a2e02de9e7839f96a007f686ae7a1d57c7797774810d24908a"}
|
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "siphasher"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
authors = ["Frank Denis <github@pureftpd.org>"]
|
||||
description = "SipHash-2-4, SipHash-1-3 and 128-bit variants in pure Rust"
|
||||
homepage = "https://docs.rs/siphasher"
|
||||
|
|
|
@ -160,7 +160,7 @@ impl SipHasher {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -175,7 +175,7 @@ impl SipHasher {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.0.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.0.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.0.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ impl SipHasher13 {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -215,7 +215,7 @@ impl SipHasher13 {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ impl SipHasher24 {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -255,7 +255,7 @@ impl SipHasher24 {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@ impl SipHasher {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -196,7 +196,7 @@ impl SipHasher {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.0.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.0.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.0.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ impl SipHasher13 {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -244,7 +244,7 @@ impl SipHasher13 {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ impl SipHasher24 {
|
|||
let mut b0 = [0u8; 8];
|
||||
let mut b1 = [0u8; 8];
|
||||
b0.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[0..8]);
|
||||
b1.copy_from_slice(&key[8..16]);
|
||||
let key0 = u64::from_le_bytes(b0);
|
||||
let key1 = u64::from_le_bytes(b1);
|
||||
Self::new_with_keys(key0, key1)
|
||||
|
@ -292,7 +292,7 @@ impl SipHasher24 {
|
|||
pub fn key(&self) -> [u8; 16] {
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes());
|
||||
bytes[0..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes());
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"49cb9a97eb041da60c0db019be4b6c7cf335d16962ed222702d8d7a62d577115","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"7425b60d83d01a0bcedb5855ec8652fb1089194da5b5d8f7d7d9072c8ea9d133","scripts/run_miri.sh":"0d0b8c54c73fa9da1217d29ed0984f8328dd9fb61bb5a02db44458c360cdc3c4","src/lib.rs":"9ba7502191536089d511a0ba9d790d9dc26df6d1f36f89b8539787df1d8565b2","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"5ff6c88e4742b0373a4c3859b91db42bf58601ed611472eee08dd995223249ce","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"}
|
||||
{"files":{"Cargo.toml":"94a908a090a75ef2e262dd128e46129628873c13d7fdbf57d9718efd3ac59567","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"ede0ed2f95612e90261d473f42e26e7b4acb98e9675d051767821391497cd20b","scripts/run_miri.sh":"0d0b8c54c73fa9da1217d29ed0984f8328dd9fb61bb5a02db44458c360cdc3c4","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"87e1ca95b06bde34f330f0253ddc8074785a6204be96fe0317747bfed611aed3","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"2bcf69dc0597e4e8a59a92566a3dd5c82ec3a1ea563aa006ea0f4a2722cb2d17","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"}
|
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "smallvec"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "'Small vector' optimization: store up to a small number of items on the stack"
|
||||
documentation = "https://docs.rs/smallvec/"
|
||||
|
@ -24,6 +24,10 @@ repository = "https://github.com/servo/rust-smallvec"
|
|||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
[dependencies.arbitrary]
|
||||
version = "1"
|
||||
optional = true
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1"
|
||||
optional = true
|
||||
|
|
|
@ -159,12 +159,11 @@ fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let mut vec = V::new();
|
||||
// Add one element, with each iteration we insert one before the end.
|
||||
// This means that we benchmark the insertion operation and not the
|
||||
// time it takes to `ptr::copy` the data.
|
||||
// Always insert at position 0 so that we are subject to shifts of
|
||||
// many different lengths.
|
||||
vec.push(0);
|
||||
for x in 0..n {
|
||||
insert_noinline(&mut vec, x as _, x);
|
||||
insert_noinline(&mut vec, 0, x);
|
||||
}
|
||||
vec
|
||||
});
|
||||
|
@ -179,8 +178,8 @@ fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) {
|
|||
b.iter(|| {
|
||||
let mut vec = V::from_elem(0, n as _);
|
||||
|
||||
for x in (0..n - 1).rev() {
|
||||
remove_noinline(&mut vec, x);
|
||||
for _ in 0..n {
|
||||
remove_noinline(&mut vec, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use crate::{Array, SmallVec};
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
|
||||
impl<'a, A: Array> Arbitrary<'a> for SmallVec<A>
|
||||
where
|
||||
<A as Array>::Item: Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
u.arbitrary_iter()?.collect()
|
||||
}
|
||||
|
||||
fn arbitrary_take_rest(u: Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
u.arbitrary_take_rest_iter()?.collect()
|
||||
}
|
||||
|
||||
fn size_hint(depth: usize) -> (usize, Option<usize>) {
|
||||
arbitrary::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None))
|
||||
}
|
||||
}
|
|
@ -1651,6 +1651,9 @@ trait SpecFrom<A: Array, S> {
|
|||
#[cfg(feature = "specialization")]
|
||||
mod specialization;
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
mod arbitrary;
|
||||
|
||||
#[cfg(feature = "specialization")]
|
||||
impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A>
|
||||
where
|
||||
|
|
|
@ -111,6 +111,13 @@ fn drain() {
|
|||
assert_eq!(v.drain(1..).collect::<Vec<_>>(), &[4, 5]);
|
||||
// drain should not change the capacity
|
||||
assert_eq!(v.capacity(), old_capacity);
|
||||
|
||||
// Exercise the tail-shifting code when in the inline state
|
||||
// This has the potential to produce UB due to aliasing
|
||||
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
|
||||
v.push(1);
|
||||
v.push(2);
|
||||
assert_eq!(v.drain(..1).collect::<Vec<_>>(), &[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -13,7 +13,7 @@
|
|||
edition = "2018"
|
||||
rust-version = "1.31"
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"]
|
||||
description = "Parser for Rust source code"
|
||||
|
@ -52,6 +52,9 @@ version = "0.2"
|
|||
[dev-dependencies.anyhow]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.automod]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.flate2]
|
||||
version = "1.0"
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#![feature(rustc_private, test)]
|
||||
#![recursion_limit = "1024"]
|
||||
#![allow(clippy::missing_panics_doc, clippy::must_use_candidate)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#![cfg_attr(not(syn_only), feature(rustc_private))]
|
||||
#![recursion_limit = "1024"]
|
||||
#![allow(clippy::cast_lossless, clippy::unnecessary_wraps)]
|
||||
|
||||
#[macro_use]
|
||||
#[path = "../tests/macros/mod.rs"]
|
||||
|
@ -116,7 +117,7 @@ fn main() {
|
|||
|
||||
macro_rules! testcases {
|
||||
($($(#[$cfg:meta])* $name:ident,)*) => {
|
||||
vec![
|
||||
[
|
||||
$(
|
||||
$(#[$cfg])*
|
||||
(stringify!($name), $name::bench as fn(&str) -> Result<(), ()>),
|
||||
|
|
|
@ -42,6 +42,6 @@ fn rustc_version() -> Option<Compiler> {
|
|||
return None;
|
||||
}
|
||||
let minor = pieces.next()?.parse().ok()?;
|
||||
let nightly = version.contains("nightly");
|
||||
let nightly = version.contains("nightly") || version.ends_with("-dev");
|
||||
Some(Compiler { minor, nightly })
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::Lifetime;
|
|||
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
/// Internal type which is used instead of `TokenTree` to represent a token tree
|
||||
/// within a `TokenBuffer`.
|
||||
|
@ -36,20 +37,30 @@ enum Entry {
|
|||
///
|
||||
/// *This type is available only if Syn is built with the `"parsing"` feature.*
|
||||
pub struct TokenBuffer {
|
||||
// NOTE: Do not derive clone on this - there are raw pointers inside which
|
||||
// will be messed up. Moving the `TokenBuffer` itself is safe as the actual
|
||||
// backing slices won't be moved.
|
||||
data: Box<[Entry]>,
|
||||
// NOTE: Do not implement clone on this - there are raw pointers inside
|
||||
// these entries which will be messed up. Moving the `TokenBuffer` itself is
|
||||
// safe as the data pointed to won't be moved.
|
||||
ptr: *const Entry,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl Drop for TokenBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let slice = slice::from_raw_parts_mut(self.ptr as *mut Entry, self.len);
|
||||
let _ = Box::from_raw(slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TokenBuffer {
|
||||
// NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
|
||||
// RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
|
||||
// NOTE: Do not mutate the Vec returned from this function once it returns;
|
||||
// the address of its backing memory must remain stable.
|
||||
fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
|
||||
// Build up the entries list, recording the locations of any Groups
|
||||
// in the list to be processed later.
|
||||
let mut entries = Vec::new();
|
||||
let mut seqs = Vec::new();
|
||||
let mut groups = Vec::new();
|
||||
for tt in stream {
|
||||
match tt {
|
||||
TokenTree::Ident(sym) => {
|
||||
|
@ -63,8 +74,8 @@ impl TokenBuffer {
|
|||
}
|
||||
TokenTree::Group(g) => {
|
||||
// Record the index of the interesting entry, and store an
|
||||
// `End(null)` there temporarially.
|
||||
seqs.push((entries.len(), g));
|
||||
// `End(null)` there temporarily.
|
||||
groups.push((entries.len(), g));
|
||||
entries.push(Entry::End(ptr::null()));
|
||||
}
|
||||
}
|
||||
|
@ -78,23 +89,28 @@ impl TokenBuffer {
|
|||
// constant address after this point, as we are going to store a raw
|
||||
// pointer into it.
|
||||
let mut entries = entries.into_boxed_slice();
|
||||
for (idx, group) in seqs {
|
||||
for (idx, group) in groups {
|
||||
// We know that this index refers to one of the temporary
|
||||
// `End(null)` entries, and we know that the last entry is
|
||||
// `End(up)`, so the next index is also valid.
|
||||
let seq_up = &entries[idx + 1] as *const Entry;
|
||||
let group_up = unsafe { entries.as_ptr().add(idx + 1) };
|
||||
|
||||
// The end entry stored at the end of this Entry::Group should
|
||||
// point to the Entry which follows the Group in the list.
|
||||
let inner = Self::inner_new(group.stream(), seq_up);
|
||||
let inner = Self::inner_new(group.stream(), group_up);
|
||||
entries[idx] = Entry::Group(group, inner);
|
||||
}
|
||||
|
||||
TokenBuffer { data: entries }
|
||||
let len = entries.len();
|
||||
let ptr = Box::into_raw(entries);
|
||||
TokenBuffer {
|
||||
ptr: ptr as *const Entry,
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `TokenBuffer` containing all the tokens from the input
|
||||
/// `TokenStream`.
|
||||
/// `proc_macro::TokenStream`.
|
||||
///
|
||||
/// *This method is available only if Syn is built with both the `"parsing"` and
|
||||
/// `"proc-macro"` features.*
|
||||
|
@ -102,20 +118,20 @@ impl TokenBuffer {
|
|||
not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
pub fn new(stream: pm::TokenStream) -> TokenBuffer {
|
||||
pub fn new(stream: pm::TokenStream) -> Self {
|
||||
Self::new2(stream.into())
|
||||
}
|
||||
|
||||
/// Creates a `TokenBuffer` containing all the tokens from the input
|
||||
/// `TokenStream`.
|
||||
pub fn new2(stream: TokenStream) -> TokenBuffer {
|
||||
/// `proc_macro2::TokenStream`.
|
||||
pub fn new2(stream: TokenStream) -> Self {
|
||||
Self::inner_new(stream, ptr::null())
|
||||
}
|
||||
|
||||
/// Creates a cursor referencing the first token in the buffer and able to
|
||||
/// traverse until the end of the buffer.
|
||||
pub fn begin(&self) -> Cursor {
|
||||
unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
|
||||
unsafe { Cursor::create(self.ptr, self.ptr.add(self.len - 1)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +226,7 @@ impl<'a> Cursor<'a> {
|
|||
// situations where we should immediately exit the span after
|
||||
// entering it are handled correctly.
|
||||
unsafe {
|
||||
*self = Cursor::create(&buf.data[0], self.scope);
|
||||
*self = Cursor::create(buf.ptr, self.scope);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
@ -254,7 +270,7 @@ impl<'a> Cursor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// If the cursor is pointing at an `Punct`, returns it along with a cursor
|
||||
/// If the cursor is pointing at a `Punct`, returns it along with a cursor
|
||||
/// pointing at the next `TokenTree`.
|
||||
pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
|
||||
self.ignore_none();
|
||||
|
@ -321,9 +337,7 @@ impl<'a> Cursor<'a> {
|
|||
Entry::Literal(lit) => lit.clone().into(),
|
||||
Entry::Ident(ident) => ident.clone().into(),
|
||||
Entry::Punct(op) => op.clone().into(),
|
||||
Entry::End(..) => {
|
||||
return None;
|
||||
}
|
||||
Entry::End(..) => return None,
|
||||
};
|
||||
|
||||
Some((tree, unsafe { self.bump() }))
|
||||
|
|
|
@ -47,10 +47,11 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
/// ```
|
||||
///
|
||||
/// For errors that arise later than the initial parsing stage, the
|
||||
/// [`.to_compile_error()`] method can be used to perform an explicit conversion
|
||||
/// to `compile_error!`.
|
||||
/// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to
|
||||
/// perform an explicit conversion to `compile_error!`.
|
||||
///
|
||||
/// [`.to_compile_error()`]: Error::to_compile_error
|
||||
/// [`.into_compile_error()`]: Error::into_compile_error
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate proc_macro;
|
||||
|
@ -66,7 +67,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
///
|
||||
/// // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
|
||||
/// expand::my_derive(input)
|
||||
/// .unwrap_or_else(|err| err.to_compile_error())
|
||||
/// .unwrap_or_else(syn::Error::into_compile_error)
|
||||
/// .into()
|
||||
/// }
|
||||
/// #
|
||||
|
|
|
@ -2455,7 +2455,7 @@ pub mod parsing {
|
|||
while let Type::Group(ty) = first_ty_ref {
|
||||
first_ty_ref = &ty.elem;
|
||||
}
|
||||
if let Type::Path(_) = first_ty_ref {
|
||||
if let Type::Path(TypePath { qself: None, .. }) = first_ty_ref {
|
||||
while let Type::Group(ty) = first_ty {
|
||||
first_ty = *ty.elem;
|
||||
}
|
||||
|
|
|
@ -250,16 +250,18 @@
|
|||
//! dynamic library libproc_macro from rustc toolchain.
|
||||
|
||||
// Syn types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/syn/1.0.82")]
|
||||
#![doc(html_root_url = "https://docs.rs/syn/1.0.85")]
|
||||
#![cfg_attr(doc_cfg, feature(doc_cfg))]
|
||||
#![allow(non_camel_case_types)]
|
||||
// Ignored clippy lints.
|
||||
#![allow(
|
||||
clippy::cast_lossless,
|
||||
clippy::collapsible_match, // https://github.com/rust-lang/rust-clippy/issues/7575
|
||||
clippy::doc_markdown,
|
||||
clippy::eval_order_dependence,
|
||||
clippy::inherent_to_string,
|
||||
clippy::large_enum_variant,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::manual_assert,
|
||||
clippy::manual_map, // https://github.com/rust-lang/rust-clippy/issues/6795
|
||||
clippy::match_on_vec_items,
|
||||
|
@ -267,6 +269,7 @@
|
|||
clippy::needless_doctest_main,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::never_loop,
|
||||
clippy::return_self_not_must_use,
|
||||
clippy::too_many_arguments,
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
clippy::unnecessary_unwrap,
|
||||
|
|
|
@ -3,12 +3,9 @@ use crate::lookahead;
|
|||
#[cfg(feature = "parsing")]
|
||||
use crate::parse::{Parse, Parser};
|
||||
use crate::{Error, Result};
|
||||
#[cfg(feature = "printing")]
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro2::{Ident, Literal, Span};
|
||||
#[cfg(feature = "parsing")]
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::TokenTree;
|
||||
use proc_macro2::{Literal, Span};
|
||||
use proc_macro2::{TokenStream, TokenTree};
|
||||
use std::fmt::{self, Display};
|
||||
#[cfg(feature = "extra-traits")]
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -244,6 +241,10 @@ impl LitStr {
|
|||
pub fn suffix(&self) -> &str {
|
||||
&self.repr.suffix
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl LitByteStr {
|
||||
|
@ -275,6 +276,10 @@ impl LitByteStr {
|
|||
pub fn suffix(&self) -> &str {
|
||||
&self.repr.suffix
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl LitByte {
|
||||
|
@ -306,6 +311,10 @@ impl LitByte {
|
|||
pub fn suffix(&self) -> &str {
|
||||
&self.repr.suffix
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl LitChar {
|
||||
|
@ -337,6 +346,10 @@ impl LitChar {
|
|||
pub fn suffix(&self) -> &str {
|
||||
&self.repr.suffix
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl LitInt {
|
||||
|
@ -408,6 +421,10 @@ impl LitInt {
|
|||
pub fn set_span(&mut self, span: Span) {
|
||||
self.repr.token.set_span(span);
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Literal> for LitInt {
|
||||
|
@ -480,6 +497,10 @@ impl LitFloat {
|
|||
pub fn set_span(&mut self, span: Span) {
|
||||
self.repr.token.set_span(span);
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Literal {
|
||||
self.repr.token.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Literal> for LitFloat {
|
||||
|
@ -521,6 +542,11 @@ impl LitBool {
|
|||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Ident {
|
||||
let s = if self.value { "true" } else { "false" };
|
||||
Ident::new(s, self.span)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra-traits")]
|
||||
|
@ -916,8 +942,7 @@ mod printing {
|
|||
#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
|
||||
impl ToTokens for LitBool {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let s = if self.value { "true" } else { "false" };
|
||||
tokens.append(Ident::new(s, self.span));
|
||||
tokens.append(self.token());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
/// `P` with optional trailing punctuation
|
||||
/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
|
||||
///
|
||||
/// [`Punctuated<T, P>`]: crate::punctuated::Punctuated
|
||||
/// [`Vec<Stmt>`]: Block::parse_within
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -66,9 +65,6 @@
|
|||
/// Panics if the tokens fail to parse as the expected syntax tree type. The
|
||||
/// caller is responsible for ensuring that the input tokens are syntactically
|
||||
/// valid.
|
||||
//
|
||||
// TODO: allow Punctuated to be inferred as intra doc link, currently blocked on
|
||||
// https://github.com/rust-lang/rust/issues/62834
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
|
||||
#[macro_export]
|
||||
macro_rules! parse_quote {
|
||||
|
@ -77,6 +73,38 @@ macro_rules! parse_quote {
|
|||
};
|
||||
}
|
||||
|
||||
/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
|
||||
///
|
||||
/// Please refer to each of their documentation.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use quote::{quote, quote_spanned};
|
||||
/// use syn::spanned::Spanned;
|
||||
/// use syn::{parse_quote_spanned, ReturnType, Signature};
|
||||
///
|
||||
/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
|
||||
/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
|
||||
/// // without introducing any call_site() spans.
|
||||
/// fn make_ret_pinned_future(sig: &mut Signature) {
|
||||
/// let ret = match &sig.output {
|
||||
/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
|
||||
/// ReturnType::Type(_, ret) => quote!(#ret),
|
||||
/// };
|
||||
/// sig.output = parse_quote_spanned! {ret.span()=>
|
||||
/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
|
||||
#[macro_export]
|
||||
macro_rules! parse_quote_spanned {
|
||||
($span:expr=> $($tt:tt)*) => {
|
||||
$crate::parse_quote::parse($crate::__private::quote::quote_spanned!($span=> $($tt)*))
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Can parse any type that implements Parse.
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ ast_struct! {
|
|||
pub mod parsing {
|
||||
use super::*;
|
||||
use crate::parse::discouraged::Speculative;
|
||||
use crate::parse::{Parse, ParseStream, Result};
|
||||
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
impl Block {
|
||||
|
@ -152,6 +152,7 @@ pub mod parsing {
|
|||
}
|
||||
|
||||
fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
|
||||
let begin = input.fork();
|
||||
let mut attrs = input.call(Attribute::parse_outer)?;
|
||||
|
||||
// brace-style macros; paren and bracket macros get parsed as
|
||||
|
@ -169,7 +170,7 @@ pub mod parsing {
|
|||
}
|
||||
|
||||
if input.peek(Token![let]) {
|
||||
stmt_local(input, attrs)
|
||||
stmt_local(input, attrs, begin)
|
||||
} else if input.peek(Token![pub])
|
||||
|| input.peek(Token![crate]) && !input.peek2(Token![::])
|
||||
|| input.peek(Token![extern])
|
||||
|
@ -222,9 +223,7 @@ pub mod parsing {
|
|||
})))
|
||||
}
|
||||
|
||||
fn stmt_local(input: ParseStream, attrs: Vec<Attribute>) -> Result<Stmt> {
|
||||
let begin = input.fork();
|
||||
|
||||
fn stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt> {
|
||||
let let_token: Token![let] = input.parse()?;
|
||||
|
||||
let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
|
||||
|
|
|
@ -303,7 +303,7 @@ spanless_eq_struct!(Attribute; kind id style span);
|
|||
spanless_eq_struct!(AttributesData; attrs tokens);
|
||||
spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl);
|
||||
spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal);
|
||||
spanless_eq_struct!(Crate; attrs items span);
|
||||
spanless_eq_struct!(Crate; attrs items span id is_placeholder);
|
||||
spanless_eq_struct!(EnumDef; variants);
|
||||
spanless_eq_struct!(Expr; id kind span attrs !tokens);
|
||||
spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder);
|
||||
|
|
|
@ -39,18 +39,24 @@ macro_rules! snapshot_impl {
|
|||
(($expr:ident) as $t:ty, @$snapshot:literal) => {
|
||||
let $expr = crate::macros::Tokens::parse::<$t>($expr).unwrap();
|
||||
let debug = crate::macros::debug::Lite(&$expr);
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
if !cfg!(miri) {
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
}
|
||||
};
|
||||
(($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{
|
||||
let syntax_tree = crate::macros::Tokens::parse::<$t>($($expr)*).unwrap();
|
||||
let debug = crate::macros::debug::Lite(&syntax_tree);
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
if !cfg!(miri) {
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
}
|
||||
syntax_tree
|
||||
}};
|
||||
(($($expr:tt)*) , @$snapshot:literal) => {{
|
||||
let syntax_tree = $($expr)*;
|
||||
let debug = crate::macros::debug::Lite(&syntax_tree);
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
if !cfg!(miri) {
|
||||
insta::assert_debug_snapshot!(debug, @$snapshot);
|
||||
}
|
||||
syntax_tree
|
||||
}};
|
||||
(($($expr:tt)*) $next:tt $($rest:tt)*) => {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#![allow(clippy::let_underscore_drop)]
|
||||
|
||||
mod regression {
|
||||
automod::dir!("tests/regression");
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#[test]
|
||||
fn issue1108() {
|
||||
let data = "impl<x<>>::x for";
|
||||
let _ = syn::parse_file(data);
|
||||
}
|
|
@ -10,7 +10,7 @@ use std::path::Path;
|
|||
use tar::Archive;
|
||||
use walkdir::DirEntry;
|
||||
|
||||
const REVISION: &str = "ac2d9fc509e36d1b32513744adf58c34bcc4f43c";
|
||||
const REVISION: &str = "e100ec5bc7cd768ec17d75448b29c9ab4a39272b";
|
||||
|
||||
#[rustfmt::skip]
|
||||
static EXCLUDE: &[&str] = &[
|
||||
|
@ -46,16 +46,31 @@ static EXCLUDE: &[&str] = &[
|
|||
"src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
|
||||
"src/tools/rustfmt/tests/target/type.rs",
|
||||
|
||||
// Clippy lint lists represented as expressions
|
||||
"src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_all.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_style.rs",
|
||||
"src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",
|
||||
|
||||
// Not actually test cases
|
||||
"src/test/rustdoc-ui/test-compile-fail2.rs",
|
||||
"src/test/rustdoc-ui/test-compile-fail3.rs",
|
||||
"src/test/ui/include-single-expr-helper.rs",
|
||||
"src/test/ui/include-single-expr-helper-1.rs",
|
||||
"src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
|
||||
"src/test/ui/lint/expansion-time-include.rs",
|
||||
"src/test/ui/macros/auxiliary/macro-comma-support.rs",
|
||||
"src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
|
||||
"src/test/ui/parser/auxiliary/issue-21146-inc.rs",
|
||||
"src/test/ui/macros/include-single-expr-helper.rs",
|
||||
"src/test/ui/macros/include-single-expr-helper-1.rs",
|
||||
"src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
|
||||
];
|
||||
|
||||
pub fn base_dir_filter(entry: &DirEntry) -> bool {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![cfg(not(syn_disable_nightly_tests))]
|
||||
#![cfg(not(miri))]
|
||||
#![recursion_limit = "1024"]
|
||||
#![feature(rustc_private)]
|
||||
#![allow(
|
||||
|
@ -134,16 +135,16 @@ fn test_rustc_precedence() {
|
|||
l_failed
|
||||
);
|
||||
|
||||
passed.fetch_add(l_passed, Ordering::SeqCst);
|
||||
let prev_failed = failed.fetch_add(l_failed, Ordering::SeqCst);
|
||||
passed.fetch_add(l_passed, Ordering::Relaxed);
|
||||
let prev_failed = failed.fetch_add(l_failed, Ordering::Relaxed);
|
||||
|
||||
if prev_failed + l_failed >= abort_after {
|
||||
process::exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
let passed = passed.load(Ordering::SeqCst);
|
||||
let failed = failed.load(Ordering::SeqCst);
|
||||
let passed = passed.load(Ordering::Relaxed);
|
||||
let failed = failed.load(Ordering::Relaxed);
|
||||
|
||||
errorf!("\n===== Precedence Test Results =====\n");
|
||||
errorf!("{} passed | {} failed\n", passed, failed);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![cfg(not(syn_disable_nightly_tests))]
|
||||
#![cfg(not(miri))]
|
||||
#![recursion_limit = "1024"]
|
||||
#![feature(rustc_private)]
|
||||
#![allow(clippy::manual_assert)]
|
||||
|
@ -63,7 +64,7 @@ fn test_round_trip() {
|
|||
}
|
||||
});
|
||||
|
||||
let failed = failed.load(Ordering::SeqCst);
|
||||
let failed = failed.load(Ordering::Relaxed);
|
||||
if failed > 0 {
|
||||
panic!("{} failures", failed);
|
||||
}
|
||||
|
@ -77,7 +78,7 @@ fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
|
|||
Ok(krate) => (krate, start.elapsed()),
|
||||
Err(msg) => {
|
||||
errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
|
||||
let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
|
||||
let prev_failed = failed.fetch_add(1, Ordering::Relaxed);
|
||||
if prev_failed + 1 >= abort_after {
|
||||
process::exit(1);
|
||||
}
|
||||
|
@ -146,7 +147,7 @@ fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
|
|||
}
|
||||
};
|
||||
if !equal {
|
||||
let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
|
||||
let prev_failed = failed.fetch_add(1, Ordering::Relaxed);
|
||||
if prev_failed + 1 >= abort_after {
|
||||
process::exit(1);
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.lock":"b36e1dca3afec35b54b22ab760006ecac8ce9a0b52f1fe21d19fe59ba7cacc43","Cargo.toml":"859d24e450f3d2fb64f674c065c1be4889ac2f4e38dc3e18c5a5c2a42a3bbc4d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c3467056d91be3f59562158ee9604c729b5b5f473efbefb036032803eb76809e","build.rs":"4716b4f955c7a4cb39cb3b7521c1745d5110c1cbd1e054bca906e37f5e974675","examples/host.rs":"503bafddfb372123fe4dc0e7b8037808beb5bfe6df60c00d3315922bd3792c6c","examples/misc.rs":"49a579845450b7b020ed5c97dca142fc548725893cbc82f6f750ee0caab2beca","scripts/rust-targets.sh":"89564342916321c5bc35e772d374a7f0af22cc9ae6dcc0027eca48d2269f18cb","src/data_model.rs":"38c0c184ee65b882872298127d9c6878292bd12c139792e82328a5facc2428ae","src/host.rs":"fb543df4f362e9119a58523563e453110f4e3a426f0995911d0ca386657cf1d9","src/lib.rs":"8e507b48bd616e1fae0e4664770f66a6475b3c6b5377f88edae1e129d133c4eb","src/parse_error.rs":"b3735eabc0fd0a9dfdd6375662f20ec96a79852a00a05a98fb2e421545285e53","src/targets.rs":"85236775f8efa95ab8f8229f693fdbcaa073da0fc4ed6651a474bb8cd92571f5","src/triple.rs":"2add94dcf177dc9b1d979e1a76f0ad0eccc999bd7d0b30bd36c20ba51b859b4a"},"package":"64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834"}
|
||||
{"files":{"Cargo.lock":"c200e2f14c5c8bb5b26f8fbb51b91b760983a59ab6751148aee5316231d82bef","Cargo.toml":"de3e3a32c8998aa5e581922157aab1c37693585fe54a7f37cca0f4fa140fbb02","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c3467056d91be3f59562158ee9604c729b5b5f473efbefb036032803eb76809e","build.rs":"4716b4f955c7a4cb39cb3b7521c1745d5110c1cbd1e054bca906e37f5e974675","examples/host.rs":"503bafddfb372123fe4dc0e7b8037808beb5bfe6df60c00d3315922bd3792c6c","examples/misc.rs":"49a579845450b7b020ed5c97dca142fc548725893cbc82f6f750ee0caab2beca","scripts/rust-targets.sh":"89564342916321c5bc35e772d374a7f0af22cc9ae6dcc0027eca48d2269f18cb","src/data_model.rs":"38c0c184ee65b882872298127d9c6878292bd12c139792e82328a5facc2428ae","src/host.rs":"fb543df4f362e9119a58523563e453110f4e3a426f0995911d0ca386657cf1d9","src/lib.rs":"8e507b48bd616e1fae0e4664770f66a6475b3c6b5377f88edae1e129d133c4eb","src/parse_error.rs":"b3735eabc0fd0a9dfdd6375662f20ec96a79852a00a05a98fb2e421545285e53","src/targets.rs":"3fef1a1e90678dc1adaa71fb268a65906d720481e3e45247277491314bc42ad1","src/triple.rs":"aa3589d744752876d6574e91abf5d1af3b4186fa5561b1f8c6214f0e9bebcaef"},"package":"d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff"}
|
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.0"
|
||||
version = "0.12.2"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "target-lexicon"
|
||||
version = "0.12.0"
|
||||
version = "0.12.2"
|
||||
authors = ["Dan Gohman <sunfish@mozilla.com>"]
|
||||
description = "Targeting utilities for compilers and related tools"
|
||||
documentation = "https://docs.rs/target-lexicon/"
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче