Compare commits
No commits in common. "58150002e60802d7b00fe0537e4a2e8c4e389a4a" and "37cca40192d6e08e122c1e3c23f674d01e260ab3" have entirely different histories.
58150002e6
...
37cca40192
12 changed files with 217 additions and 656 deletions
185
Cargo.lock
generated
185
Cargo.lock
generated
|
@ -4,18 +4,18 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.1"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375"
|
||||
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
|
@ -56,13 +56,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.82"
|
||||
version = "0.1.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
|
||||
checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -73,17 +73,17 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.74"
|
||||
version = "0.3.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -158,17 +158,11 @@ version = "3.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.7.1"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
|
||||
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
|
||||
|
||||
[[package]]
|
||||
name = "case"
|
||||
|
@ -178,12 +172,9 @@ checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.18"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -213,15 +204,15 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
|||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.14"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -306,8 +297,8 @@ dependencies = [
|
|||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version 0.4.1",
|
||||
"syn 2.0.77",
|
||||
"rustc_version 0.4.0",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -416,7 +407,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -472,9 +463,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
|
@ -572,9 +563,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.5.0"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
@ -594,9 +585,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.10.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4"
|
||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
|
@ -606,9 +597,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.70"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -621,9 +612,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.158"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
|
@ -686,18 +677,18 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.0"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
||||
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
|
@ -707,7 +698,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mongod"
|
||||
version = "0.2.2"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
|
@ -794,9 +785,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.4"
|
||||
version = "0.36.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
|
||||
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -865,12 +856,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
|
@ -889,9 +877,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -943,9 +931,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
version = "1.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1012,9 +1000,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.23",
|
||||
]
|
||||
|
@ -1105,9 +1093,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -1123,24 +1111,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
version = "1.0.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1189,12 +1176,6 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
|
@ -1281,9 +1262,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
version = "2.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1319,7 +1300,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1370,9 +1351,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.40.0"
|
||||
version = "1.39.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
|
||||
checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -1393,7 +1374,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1408,9 +1389,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.12"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
|
||||
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -1490,9 +1471,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
|
@ -1505,9 +1486,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-properties"
|
||||
version = "0.1.2"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
|
||||
checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
|
@ -1538,9 +1519,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
|
@ -1550,35 +1531,34 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1586,22 +1566,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
|
@ -1810,7 +1790,6 @@ version = "0.7.35"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
|
@ -1822,5 +1801,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "mongod"
|
||||
version = "0.2.2"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
|
|
35
README.md
35
README.md
|
@ -11,9 +11,9 @@ You can derive the `Model` and `Referencable` traits for your struct. This will
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongod::Validate;
|
||||
use mongod::Reference;
|
||||
use mongod::derive::{Model, Referencable};
|
||||
use mongod::derive::{Module, Referencable};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Module, Referencable)]
|
||||
struct MyStruct {
|
||||
_id: String,
|
||||
name: String,
|
||||
|
@ -105,34 +105,3 @@ let ms = MyStruct::get_partial("someid", &serde_json::json!({"other": 1})).await
|
|||
let myref = ms.other.unwrap(); // will be there
|
||||
let name = ms.name.unwrap() // will panic!
|
||||
```
|
||||
|
||||
### Updating values
|
||||
You can either update the values by passing a JSON object overwriting the current values or update the values using a builder pattern.
|
||||
|
||||
```rust
|
||||
[...]
|
||||
struct MyStruct {
|
||||
_id: String,
|
||||
name: String,
|
||||
age: u32,
|
||||
other: Option<Reference>,
|
||||
}
|
||||
|
||||
let mut a = MyStruct::get("someid").await.unwrap();
|
||||
|
||||
// JSON
|
||||
a.update(serde_json::json!({"name": "bye"})).await.unwrap();
|
||||
|
||||
// Builder
|
||||
let mut changes = a.change();
|
||||
|
||||
// Set fields
|
||||
changes = changes.name("bye");
|
||||
|
||||
// There are type specific functions
|
||||
// Increment age by 1
|
||||
changes = changes.age_increment(1);
|
||||
|
||||
// Finalize
|
||||
let changed_model: MyStruct = changes.update().await.unwrap();
|
||||
```
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
use quote::quote;
|
||||
use syn::Field;
|
||||
|
||||
use crate::{extract_inner_type, is_one_of_type, is_type};
|
||||
|
||||
/// Generate the ChangeBuilder field fns
|
||||
pub fn builder_change_fields(field: &Field) -> proc_macro2::TokenStream {
|
||||
let field_name = &field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let field_name_str = field_name.to_string();
|
||||
|
||||
// Never update _id
|
||||
if field_name_str == "_id" {
|
||||
return quote! {};
|
||||
}
|
||||
|
||||
let number_types = [
|
||||
"u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize",
|
||||
"f16", "f32", "f64", "f128",
|
||||
];
|
||||
|
||||
// Number type fn
|
||||
if is_one_of_type(field_type, &number_types) {
|
||||
let documentation = format!("Set the value of `{field_name}`");
|
||||
let inc_fn_name = syn::Ident::new(&format!("{}_increment", field_name), field_name.span());
|
||||
let doc_inc = format!("Increment value of `{field_name}` by `value`. Consecutive calls to this function will not add up, they overwrite the increment.");
|
||||
|
||||
let mul_fn_name = syn::Ident::new(&format!("{}_multiply", field_name), field_name.span());
|
||||
let doc_mul = format!("Multiply value of `{field_name}` by `value`. Consecutive calls to this function will not add up, they overwrite the multiply.");
|
||||
|
||||
return quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #field_name(mut self, value: #field_type)-> Self {
|
||||
self.model.#field_name = value.into();
|
||||
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[doc = #doc_inc]
|
||||
pub fn #inc_fn_name(mut self, value: #field_type) -> Self {
|
||||
self.model.#field_name += value;
|
||||
|
||||
self.changeset.entry("$inc".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap()
|
||||
.insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&value).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[doc = #doc_mul]
|
||||
pub fn #mul_fn_name(mut self, value: #field_type) -> Self {
|
||||
self.model.#field_name *= value;
|
||||
|
||||
self.changeset.entry("$mul".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap()
|
||||
.insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&value).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Vec") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Vec").unwrap();
|
||||
|
||||
let push_fn_name = syn::Ident::new(&format!("{}_push", field_name), field_name.span());
|
||||
|
||||
let documentation = format!("Add a value to the Vec `{field_name}`");
|
||||
let documentation2 = format!("Set the value of `{field_name}`");
|
||||
|
||||
return quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #push_fn_name<T>(mut self, value: T) -> Self where T: Into<#inner_field_type> + serde::Serialize {
|
||||
let mut push = self.changeset.entry("$push".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap();
|
||||
|
||||
if push.contains_key(#field_name_str) {
|
||||
let current = push.get_mut(#field_name_str.to_string()).unwrap();
|
||||
|
||||
if current.as_document().map(|x| !x.contains_key("$each")).unwrap_or(true) {
|
||||
let each = mongod::mongodb::bson::doc! {
|
||||
"$each": [current, mongod::mongodb::bson::to_bson(&value).unwrap()]
|
||||
};
|
||||
|
||||
push.insert(#field_name_str.to_string(), each);
|
||||
} else {
|
||||
current.as_document_mut().unwrap().get_mut("$each").unwrap().as_array_mut().unwrap().push(mongod::mongodb::bson::to_bson(&value).unwrap());
|
||||
}
|
||||
} else {
|
||||
push.insert(#field_name_str.to_string(), mongod::mongodb::bson::to_bson(&value).unwrap());
|
||||
}
|
||||
|
||||
self.model.#field_name.push(value.into());
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[doc = #documentation2]
|
||||
pub fn #field_name<T>(mut self, value: T)-> Self where T: Into<#field_type> + serde::Serialize {
|
||||
self.model.#field_name = value.into();
|
||||
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Historic") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Historic").unwrap();
|
||||
|
||||
let documentation = format!(
|
||||
"Update the value of `{field_name}`. This change will be recorded by the `Historic`"
|
||||
);
|
||||
|
||||
// Code for Historic<T>
|
||||
return quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #field_name<T>(mut self, value: T) -> Self where T: Into<#inner_field_type> + serde::Serialize {
|
||||
self.model.#field_name.update(value.into());
|
||||
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
|
||||
|
||||
self
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Option") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Option").unwrap();
|
||||
|
||||
if is_type(inner_field_type, "Historic") {
|
||||
let inner_field_type = extract_inner_type(inner_field_type, "Historic").unwrap();
|
||||
|
||||
let documentation = format!("Update the value of `{field_name}`. This change will be recorded by the `Historic`. If `{field_name}` is `None` a new `Historic` will be initialized.");
|
||||
|
||||
// Code for Option<Historic<T>>
|
||||
return quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #field_name<T>(mut self, value: T) -> Self where T: Into<#inner_field_type> + serde::Serialize {
|
||||
if let Some(mut opt) = self.model.#field_name.as_mut() {
|
||||
opt.update(value.into());
|
||||
} else {
|
||||
self.model.#field_name = Some(mongod::Historic::new(value.into()));
|
||||
}
|
||||
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let documentation = format!("Set the value of `{field_name}`. If `Some(_)` it will be updated or removed if it is `None`");
|
||||
|
||||
return quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #field_name(mut self, value: Option<#inner_field_type>) -> Self {
|
||||
let is_some = value.is_some();
|
||||
|
||||
self.model.#field_name = value.into();
|
||||
|
||||
if is_some {
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
} else {
|
||||
self.changeset.entry("$unset".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson("").unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let documentation = format!("Set the value of `{field_name}`");
|
||||
// Code for T
|
||||
quote! {
|
||||
#[doc = #documentation]
|
||||
pub fn #field_name<T>(mut self, value: T)-> Self where T: Into<#field_type> + serde::Serialize {
|
||||
self.model.#field_name = value.into();
|
||||
|
||||
self.changeset.entry("$set".to_string()).or_insert(mongod::mongodb::bson::doc! {}.into()).as_document_mut().unwrap().insert(
|
||||
#field_name_str.to_string(),
|
||||
mongod::mongodb::bson::to_bson(&self.model.#field_name).unwrap(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,18 +3,40 @@ use case::CaseExt;
|
|||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, Data, DeriveInput, Fields};
|
||||
use syn::{parse_macro_input, Data, DeriveInput, Fields, Type, TypePath};
|
||||
|
||||
mod types;
|
||||
use types::*;
|
||||
mod partial_fields;
|
||||
use partial_fields::partial_code_field;
|
||||
mod update_fields;
|
||||
use update_fields::update_code_field;
|
||||
mod change_fields;
|
||||
use change_fields::builder_change_fields;
|
||||
/// Get inner type. Example: Returns `T` for `Option<T>`.
|
||||
fn extract_inner_type<'a>(ty: &'a Type, parent: &'a str) -> Option<&'a Type> {
|
||||
if let Type::Path(type_path) = ty {
|
||||
if type_path.path.segments.len() == 1 {
|
||||
let segment = &type_path.path.segments[0];
|
||||
if segment.ident == parent {
|
||||
if let syn::PathArguments::AngleBracketed(ref args) = segment.arguments {
|
||||
if args.args.len() == 1 {
|
||||
if let syn::GenericArgument::Type(ref inner_type) = args.args[0] {
|
||||
return Some(inner_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn type_path(ty: &syn::Type) -> TypePath {
|
||||
if let syn::Type::Path(type_path) = ty {
|
||||
return type_path.clone();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn is_type(ty: &syn::Type, t: &str) -> bool {
|
||||
let type_path = type_path(ty);
|
||||
let id = type_path.path.segments.first().unwrap().ident.to_string();
|
||||
id == t
|
||||
}
|
||||
|
||||
/// #[derive(Model)]
|
||||
#[proc_macro_derive(Model)]
|
||||
pub fn model_derive(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
@ -22,37 +44,84 @@ pub fn model_derive(input: TokenStream) -> TokenStream {
|
|||
let name = input.ident;
|
||||
let name_str = name.to_string().to_snake();
|
||||
let partial_name = syn::Ident::new(&format!("Partial{}", name), name.span());
|
||||
let changebuilder_name = syn::Ident::new(&format!("Change{}", name), name.span());
|
||||
|
||||
let update_doc = "Commit the builder changes to DB";
|
||||
|
||||
// Generate code for each field
|
||||
let field_code = if let Data::Struct(data_struct) = input.data {
|
||||
match data_struct.fields {
|
||||
Fields::Named(fields_named) => {
|
||||
// Update code
|
||||
let field_process_code: Vec<_> =
|
||||
fields_named.named.iter().map(update_code_field).collect();
|
||||
let field_process_code: Vec<_> = fields_named.named.iter().map(|field| {
|
||||
let field_name = &field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let field_name_str = field_name.to_string();
|
||||
|
||||
// Partial struct fields
|
||||
let partial_struct: Vec<_> =
|
||||
fields_named.named.iter().map(partial_code_field).collect();
|
||||
if field_name_str == "_id" {
|
||||
return quote! {};
|
||||
}
|
||||
|
||||
// Builder functions
|
||||
let builder_change_fields: Vec<_> = fields_named
|
||||
if is_type(field_type, "Historic") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Historic").unwrap();
|
||||
if is_type(inner_field_type, "Vec") {
|
||||
return quote! {
|
||||
mongod::update_historic_vec!(self, obj, #field_name_str, #field_name, update);
|
||||
};
|
||||
}
|
||||
|
||||
return quote! {
|
||||
mongod::update_historic_str!(self, obj, #field_name_str, #field_name, update);
|
||||
}
|
||||
}
|
||||
|
||||
if is_type(field_type, "Option") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Option").unwrap();
|
||||
|
||||
if is_type(inner_field_type, "Historic") {
|
||||
let sub_inner_field_type = extract_inner_type(inner_field_type, "Historic").unwrap();
|
||||
if is_type(sub_inner_field_type, "Reference") {
|
||||
return quote! {
|
||||
mongod::update_historic_ref_option!(self, obj, #field_name_str, #field_name, update);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return quote! {
|
||||
mongod::update_value_option!(self, obj, #field_name_str, #field_name, update, #inner_field_type);
|
||||
};
|
||||
}
|
||||
|
||||
quote! {
|
||||
mongod::update_value!(self, obj, #field_name_str, #field_name, update, #field_type);
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let partial_struct: Vec<_> = fields_named
|
||||
.named
|
||||
.iter()
|
||||
.map(builder_change_fields)
|
||||
.map(|field| {
|
||||
let field_name = &field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let field_name_str = field_name.to_string();
|
||||
|
||||
if field_name_str == "_id" {
|
||||
return quote! {
|
||||
pub _id: String,
|
||||
};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Option") {
|
||||
return quote! {
|
||||
pub #field_name: #field_type,
|
||||
};
|
||||
}
|
||||
|
||||
quote! {
|
||||
pub #field_name: Option<#field_type>,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
impl mongod::model::Model for #name {
|
||||
type Partial = #partial_name;
|
||||
type ChangeBuilder = #changebuilder_name;
|
||||
|
||||
fn change_builder(self) -> Self::ChangeBuilder {
|
||||
#changebuilder_name::new(self)
|
||||
}
|
||||
|
||||
async fn update_values(
|
||||
&mut self,
|
||||
|
@ -68,47 +137,6 @@ pub fn model_derive(input: TokenStream) -> TokenStream {
|
|||
#( #partial_struct )*
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct #changebuilder_name {
|
||||
model: #name,
|
||||
changeset: mongod::mongodb::bson::Document
|
||||
}
|
||||
|
||||
impl #changebuilder_name {
|
||||
pub fn new(model: #name) -> Self {
|
||||
Self {
|
||||
model,
|
||||
changeset: mongod::mongodb::bson::doc! {}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = #update_doc]
|
||||
pub async fn update(self) -> Result<#name, mongod::model::UpdateError> {
|
||||
let db = mongod::get_mongo!();
|
||||
let collection = mongod::col!(db, <#name as mongod::Referencable>::collection_name());
|
||||
|
||||
if let Err(msg) = mongod::Validate::validate(&self.model).await {
|
||||
return Err(mongod::model::UpdateError::Validation(msg));
|
||||
}
|
||||
|
||||
let changeset = self.changeset;
|
||||
|
||||
collection
|
||||
.update_one(
|
||||
mongod::id_of!(mongod::Referencable::id(&self.model)),
|
||||
changeset,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(mongod::model::UpdateError::Database)?;
|
||||
|
||||
Ok(self.model)
|
||||
}
|
||||
|
||||
#( #builder_change_fields )*
|
||||
|
||||
}
|
||||
|
||||
impl mongod::model::reference::Referencable for #partial_name {
|
||||
fn collection_name() -> &'static str {
|
||||
#name_str
|
||||
|
@ -129,7 +157,6 @@ pub fn model_derive(input: TokenStream) -> TokenStream {
|
|||
TokenStream::from(field_code)
|
||||
}
|
||||
|
||||
/// #[derive(Referencable)]
|
||||
#[proc_macro_derive(Referencable)]
|
||||
pub fn referencable_derive(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
use quote::quote;
|
||||
use syn::Field;
|
||||
|
||||
use crate::is_type;
|
||||
|
||||
/// Generate struct fields for Partial Model
|
||||
pub fn partial_code_field(field: &Field) -> proc_macro2::TokenStream {
|
||||
let field_name = &field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let field_name_str = field_name.to_string();
|
||||
|
||||
// Keep _id
|
||||
if field_name_str == "_id" {
|
||||
return quote! {
|
||||
pub _id: String,
|
||||
};
|
||||
}
|
||||
|
||||
// Leave Option<T> alone
|
||||
if is_type(field_type, "Option") {
|
||||
return quote! {
|
||||
pub #field_name: #field_type,
|
||||
};
|
||||
}
|
||||
|
||||
// Turn every field into Option<T>
|
||||
quote! {
|
||||
pub #field_name: Option<#field_type>,
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
use syn::{Type, TypePath};
|
||||
|
||||
/// Get inner type. Example: Returns `T` for `Option<T>`.
|
||||
pub fn extract_inner_type<'a>(ty: &'a Type, parent: &'a str) -> Option<&'a Type> {
|
||||
if let Type::Path(type_path) = ty {
|
||||
if type_path.path.segments.len() == 1 {
|
||||
let segment = &type_path.path.segments[0];
|
||||
if segment.ident == parent {
|
||||
if let syn::PathArguments::AngleBracketed(ref args) = segment.arguments {
|
||||
if args.args.len() == 1 {
|
||||
if let syn::GenericArgument::Type(ref inner_type) = args.args[0] {
|
||||
return Some(inner_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn type_path(ty: &syn::Type) -> TypePath {
|
||||
if let syn::Type::Path(type_path) = ty {
|
||||
return type_path.clone();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
pub fn is_one_of_type(ty: &syn::Type, t: &[&str]) -> bool {
|
||||
for typ in t {
|
||||
if is_type(ty, typ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_type(ty: &syn::Type, t: &str) -> bool {
|
||||
let type_path = type_path(ty);
|
||||
let id = type_path.path.segments.first().unwrap().ident.to_string();
|
||||
id == t
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
use quote::quote;
|
||||
use syn::Field;
|
||||
|
||||
use crate::{extract_inner_type, is_type};
|
||||
|
||||
/// Generate code for the update fn of models
|
||||
pub fn update_code_field(field: &Field) -> proc_macro2::TokenStream {
|
||||
let field_name = &field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let field_name_str = field_name.to_string();
|
||||
|
||||
// Never update _id
|
||||
if field_name_str == "_id" {
|
||||
return quote! {};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Historic") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Historic").unwrap();
|
||||
if is_type(inner_field_type, "Vec") {
|
||||
// Custom code Historic<Vec<T>>
|
||||
return quote! {
|
||||
mongod::update_historic_vec!(self, obj, #field_name_str, #field_name, update);
|
||||
};
|
||||
}
|
||||
|
||||
// Code for Historic<T>
|
||||
return quote! {
|
||||
mongod::update_historic_str!(self, obj, #field_name_str, #field_name, update);
|
||||
};
|
||||
}
|
||||
|
||||
if is_type(field_type, "Option") {
|
||||
let inner_field_type = extract_inner_type(field_type, "Option").unwrap();
|
||||
|
||||
if is_type(inner_field_type, "Historic") {
|
||||
let sub_inner_field_type = extract_inner_type(inner_field_type, "Historic").unwrap();
|
||||
if is_type(sub_inner_field_type, "Reference") {
|
||||
// Code for Option<Historic<Reference>>
|
||||
return quote! {
|
||||
mongod::update_historic_ref_option!(self, obj, #field_name_str, #field_name, update);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Code for Option<T>
|
||||
return quote! {
|
||||
mongod::update_value_option!(self, obj, #field_name_str, #field_name, update, #inner_field_type);
|
||||
};
|
||||
}
|
||||
|
||||
// Code for T
|
||||
quote! {
|
||||
mongod::update_value!(self, obj, #field_name_str, #field_name, update, #field_type);
|
||||
}
|
||||
}
|
21
src/lib.rs
21
src/lib.rs
|
@ -3,10 +3,8 @@ pub use model::historic::Historic;
|
|||
pub use model::reference::*;
|
||||
pub use model::valid::Validate;
|
||||
pub use model::Model;
|
||||
pub use model::Sort;
|
||||
pub use mongod_derive as derive;
|
||||
pub use mongodb;
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
pub mod cache;
|
||||
#[cfg(feature = "cache")]
|
||||
|
@ -57,7 +55,7 @@ macro_rules! get_mongo {
|
|||
if let Some(client) = $crate::MONGO_CLIENT.get() {
|
||||
client
|
||||
} else {
|
||||
let client = $crate::mongodb::Client::with_uri_str(&std::env::var("DB_URI").unwrap())
|
||||
let client = mongodb::Client::with_uri_str(&std::env::var("DB_URI").unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
$crate::MONGO_CLIENT.set(client).unwrap();
|
||||
|
@ -97,20 +95,3 @@ macro_rules! id_of {
|
|||
$crate::mongodb::bson::doc! { "_id": $id}
|
||||
};
|
||||
}
|
||||
|
||||
/// A trait to generate a Model API representation in JSON format.
|
||||
pub trait ToAPI: Sized {
|
||||
/// Generate public API JSON
|
||||
fn api(&self) -> impl std::future::Future<Output = serde_json::Value>;
|
||||
}
|
||||
|
||||
/// Converts a slice of items implementing the `ToAPI` trait into a `Vec` of JSON values.
|
||||
pub async fn vec_to_api(items: &[impl ToAPI]) -> Vec<serde_json::Value> {
|
||||
let mut ret = Vec::with_capacity(items.len());
|
||||
|
||||
for e in items {
|
||||
ret.push(e.api().await);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, ops::Deref};
|
|||
|
||||
/// A struct to keep track of historical changes to a value.
|
||||
/// This struct represents a value that has a current state and a history of previous states.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Historic<T> {
|
||||
/// The current value
|
||||
pub current: T,
|
||||
|
@ -24,13 +24,6 @@ impl<T: Clone> Historic<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default + Clone> Historic<T> {
|
||||
/// Create a new tracked value initialized with Default
|
||||
pub fn new_default() -> Historic<T> {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Historic<T> {
|
||||
/// Update the value. The change will be recorded.
|
||||
/// Will record a change even if the value is the same as the current one.
|
||||
|
|
|
@ -8,16 +8,15 @@ use serde::de::DeserializeOwned;
|
|||
use serde_json::{Map, Value};
|
||||
use valid::Validate;
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
use crate::{cache_read, cache_write};
|
||||
|
||||
use crate::{col, collect_results, get_mongo, id_of};
|
||||
use crate::{cache_read, cache_write, col, collect_results, get_mongo, id_of};
|
||||
|
||||
pub mod historic;
|
||||
pub mod reference;
|
||||
pub mod update;
|
||||
pub mod valid;
|
||||
|
||||
// todo : use mongodb projection to only get fields you actually use, maybe PartialModel shadow struct?
|
||||
|
||||
/// Error type when updating a model
|
||||
#[derive(Debug)]
|
||||
pub enum UpdateError {
|
||||
|
@ -33,7 +32,6 @@ pub trait Model:
|
|||
Sized + Referencable + Validate + serde::Serialize + for<'a> serde::Deserialize<'a>
|
||||
{
|
||||
type Partial: DeserializeOwned;
|
||||
type ChangeBuilder;
|
||||
|
||||
/// Insert the `Model` into the database
|
||||
fn insert(
|
||||
|
@ -217,7 +215,7 @@ pub trait Model:
|
|||
/// Get all `Model`s from the database
|
||||
#[must_use]
|
||||
fn find_all() -> impl std::future::Future<Output = Option<Vec<Self>>> {
|
||||
Self::find(doc! {}, None, None)
|
||||
Self::find(doc! {}, None)
|
||||
}
|
||||
|
||||
/// Get all `Model`s partial from the database
|
||||
|
@ -225,7 +223,7 @@ pub trait Model:
|
|||
fn find_all_partial(
|
||||
part: serde_json::Value,
|
||||
) -> impl std::future::Future<Output = Option<Vec<Self::Partial>>> {
|
||||
Self::find_partial(doc! {}, part, None, None)
|
||||
Self::find_partial(doc! {}, part, None)
|
||||
}
|
||||
|
||||
/// Get multiple `Model`s by using a filter from the database. Pass a `limit` parameter to limit the amount of `Model`s returned.
|
||||
|
@ -233,15 +231,17 @@ pub trait Model:
|
|||
fn find(
|
||||
filter: mongodb::bson::Document,
|
||||
limit: Option<i64>,
|
||||
sort: Option<mongodb::bson::Document>,
|
||||
) -> impl std::future::Future<Output = Option<Vec<Self>>> {
|
||||
async move {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
|
||||
let options = FindOptions::builder().limit(limit).sort(sort).build();
|
||||
|
||||
let mut results = collection.find(filter, options).await.ok()?;
|
||||
let mut results = collection
|
||||
.find(
|
||||
filter,
|
||||
limit.map(|x| FindOptions::builder().limit(x).build()),
|
||||
)
|
||||
.await
|
||||
.ok()?;
|
||||
let docs = collect_results!(results);
|
||||
docs.into_iter()
|
||||
.map(|x| mongodb::bson::from_document(x).unwrap())
|
||||
|
@ -249,28 +249,12 @@ pub trait Model:
|
|||
}
|
||||
}
|
||||
|
||||
/// Get unique values of a Models field
|
||||
fn unique<T: DeserializeOwned>(
|
||||
filter: mongodb::bson::Document,
|
||||
field: &str,
|
||||
) -> impl std::future::Future<Output = Vec<T>> {
|
||||
async move {
|
||||
let db = get_mongo!();
|
||||
let collection = col!(db, Self::collection_name());
|
||||
let res = collection.distinct(field, filter, None).await.unwrap();
|
||||
res.into_iter()
|
||||
.filter_map(|x| mongodb::bson::from_bson(x).ok())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get multiple partial `Model`s by using a filter from the database. Pass a `limit` parameter to limit the amount of `Model`s returned.
|
||||
#[must_use]
|
||||
fn find_partial(
|
||||
filter: mongodb::bson::Document,
|
||||
mut part: serde_json::Value,
|
||||
limit: Option<i64>,
|
||||
sort: Option<mongodb::bson::Document>,
|
||||
) -> impl std::future::Future<Output = Option<Vec<Self::Partial>>> {
|
||||
async move {
|
||||
let db = get_mongo!();
|
||||
|
@ -278,13 +262,18 @@ pub trait Model:
|
|||
|
||||
part.as_object_mut()?.insert("_id".into(), 1.into());
|
||||
|
||||
let options = FindOptions::builder()
|
||||
.limit(limit)
|
||||
.sort(sort)
|
||||
.projection(Some(mongodb::bson::to_document(&part).unwrap()))
|
||||
.build();
|
||||
|
||||
let mut results = collection.find(filter, Some(options)).await.ok()?;
|
||||
let mut results = collection
|
||||
.find(
|
||||
filter,
|
||||
Some(
|
||||
FindOptions::builder()
|
||||
.projection(Some(mongodb::bson::to_document(&part).unwrap()))
|
||||
.limit(limit)
|
||||
.build(),
|
||||
),
|
||||
)
|
||||
.await
|
||||
.ok()?;
|
||||
let docs = collect_results!(results);
|
||||
docs.into_iter()
|
||||
.map(|x| mongodb::bson::from_document(x).unwrap())
|
||||
|
@ -292,18 +281,6 @@ pub trait Model:
|
|||
}
|
||||
}
|
||||
|
||||
fn change_builder(self) -> Self::ChangeBuilder;
|
||||
|
||||
/// Update values of `Model` using a builder pattern
|
||||
fn change(self) -> Self::ChangeBuilder {
|
||||
#[cfg(feature = "cache")]
|
||||
{
|
||||
cache_write!().invalidate(Self::collection_name(), self.id());
|
||||
}
|
||||
|
||||
self.change_builder()
|
||||
}
|
||||
|
||||
/// Update values of `Model` into database
|
||||
fn update(
|
||||
&mut self,
|
||||
|
@ -356,28 +333,3 @@ pub trait Model:
|
|||
update: &mut mongodb::bson::Document,
|
||||
) -> impl std::future::Future<Output = ()> + Send;
|
||||
}
|
||||
|
||||
/// Sorting Order
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// let m = MyModel::find(doc! {}, None, Some(doc! {
|
||||
/// "sort_key": Sort::Ascending
|
||||
/// })).await.unwrap();
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub enum Sort {
|
||||
/// Sort in ascending order
|
||||
Ascending,
|
||||
/// Sort in descending order
|
||||
Descending,
|
||||
}
|
||||
|
||||
impl Into<mongodb::bson::Bson> for Sort {
|
||||
fn into(self) -> mongodb::bson::Bson {
|
||||
match self {
|
||||
Sort::Ascending => mongodb::bson::bson!(1),
|
||||
Sort::Descending => mongodb::bson::bson!(-1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,14 +10,9 @@ use super::{valid::Validate, Model};
|
|||
pub struct Reference(String);
|
||||
|
||||
impl Reference {
|
||||
/// Create a new reference from String without checks
|
||||
pub fn new_raw(reference: &str) -> Self {
|
||||
Self(reference.to_string())
|
||||
}
|
||||
|
||||
/// Create a new reference
|
||||
pub async fn new(model: &str, id: &str) -> Option<Self> {
|
||||
let r = Self(format!("{model}::{id}"));
|
||||
/// Create a new reference from String
|
||||
pub async fn new_raw(reference: &str) -> Option<Self> {
|
||||
let r = Self(reference.to_string());
|
||||
if r.validate().await.is_ok() {
|
||||
Some(r)
|
||||
} else {
|
||||
|
@ -25,6 +20,11 @@ impl Reference {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new reference
|
||||
pub async fn new(model: &str, id: &str) -> Option<Self> {
|
||||
Self::new_raw(&format!("{model}::{id}")).await
|
||||
}
|
||||
|
||||
/// Get just the ID of the referenced `Model`
|
||||
pub fn id(&self) -> &str {
|
||||
self.0.split_once("::").unwrap().1
|
||||
|
@ -130,11 +130,11 @@ macro_rules! reference_of {
|
|||
($model:ident, $id:ident) => {{
|
||||
$model::get_partial($id, serde_json::json!({}))
|
||||
.await
|
||||
.map(|x| mongod::Referencable::reference(&x))
|
||||
.map(|x| x.reference())
|
||||
}};
|
||||
($model:ident, $id:literal) => {{
|
||||
$model::get_partial($id, serde_json::json!({}))
|
||||
.await
|
||||
.map(|x| mongod::Referencable::reference(&x))
|
||||
.map(|x| x.reference())
|
||||
}};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue