From 944715d610a7c873d216c4890687c1e02a7981b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Tue, 12 Oct 2021 18:14:02 +0300 Subject: [PATCH] inital commit --- .gitignore | 1 + Cargo.lock | 1105 +++++++++++++++++++++ Cargo.toml | 30 + README.md | 25 + examples/web/.env.example | 11 + examples/web/Cargo.lock | 1059 ++++++++++++++++++++ examples/web/Cargo.toml | 30 + examples/web/Migra.toml | 8 + examples/web/database/initdb.d/.gitkeep | 0 examples/web/database/initdb.d/schema.sql | 5 + examples/web/database/schema.sql | 5 + examples/web/docker-compose.dev.yml | 13 + examples/web/src/app/list/_mocks.rs | 8 + examples/web/src/app/list/controller.rs | 32 + examples/web/src/app/list/mod.rs | 14 + examples/web/src/app/list/service.rs | 33 + examples/web/src/app/list/storage_type.rs | 10 + examples/web/src/app/mod.rs | 1 + examples/web/src/config.rs | 47 + examples/web/src/db/list/mod.rs | 21 + examples/web/src/db/list/storage.rs | 29 + examples/web/src/db/mod.rs | 2 + examples/web/src/db/persistence.rs | 35 + examples/web/src/error.rs | 65 ++ examples/web/src/lib.rs | 17 + examples/web/src/main.rs | 10 + examples/web/src/rest/context.rs | 10 + examples/web/src/rest/mod.rs | 6 + examples/web/src/rest/prelude.rs | 6 + examples/web/src/rest/routes/api/list.rs | 32 + examples/web/src/rest/routes/api/mod.rs | 33 + examples/web/src/rest/routes/mod.rs | 16 + examples/web/src/rest/routes/root.rs | 44 + examples/web/src/rest/server.rs | 95 ++ examples/web/src/rest/server_utils.rs | 65 ++ examples/web/src/rest/types.rs | 64 ++ src/asyn.rs | 14 + src/bb8_postgres.rs | 52 + src/error.rs | 36 + src/lib.rs | 23 + src/r2d2_postgres.rs | 51 + src/syn.rs | 13 + 42 files changed, 3176 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 examples/web/.env.example create mode 100644 examples/web/Cargo.lock create mode 100644 examples/web/Cargo.toml create mode 100644 examples/web/Migra.toml create mode 100644 examples/web/database/initdb.d/.gitkeep create mode 100644 examples/web/database/initdb.d/schema.sql create mode 100644 examples/web/database/schema.sql create mode 100644 examples/web/docker-compose.dev.yml create mode 100644 examples/web/src/app/list/_mocks.rs create mode 100644 examples/web/src/app/list/controller.rs create mode 100644 examples/web/src/app/list/mod.rs create mode 100644 examples/web/src/app/list/service.rs create mode 100644 examples/web/src/app/list/storage_type.rs create mode 100644 examples/web/src/app/mod.rs create mode 100644 examples/web/src/config.rs create mode 100644 examples/web/src/db/list/mod.rs create mode 100644 examples/web/src/db/list/storage.rs create mode 100644 examples/web/src/db/mod.rs create mode 100644 examples/web/src/db/persistence.rs create mode 100644 examples/web/src/error.rs create mode 100644 examples/web/src/lib.rs create mode 100644 examples/web/src/main.rs create mode 100644 examples/web/src/rest/context.rs create mode 100644 examples/web/src/rest/mod.rs create mode 100644 examples/web/src/rest/prelude.rs create mode 100644 examples/web/src/rest/routes/api/list.rs create mode 100644 examples/web/src/rest/routes/api/mod.rs create mode 100644 examples/web/src/rest/routes/mod.rs create mode 100644 examples/web/src/rest/routes/root.rs create mode 100644 examples/web/src/rest/server.rs create mode 100644 examples/web/src/rest/server_utils.rs create mode 100644 examples/web/src/rest/types.rs create mode 100644 src/asyn.rs create mode 100644 src/bb8_postgres.rs create mode 100644 src/error.rs create mode 100644 src/lib.rs create mode 100644 src/r2d2_postgres.rs create mode 100644 src/syn.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..307bf5a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1105 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-trait" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bb8" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9f4fa9768efd269499d8fba693260cfc670891cf6de3adc935588447a77cc8" +dependencies = [ + "async-trait", + "futures-channel", + "futures-util", + "parking_lot", + "tokio", +] + +[[package]] +name = "bb8-postgres" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fdf56d52b2cca401d2380407e5c35d3d25d3560224ecf74d6e4ca13e51239b" +dependencies = [ + "async-trait", + "bb8", + "tokio", + "tokio-postgres", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" + +[[package]] +name = "futures-executor" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" + +[[package]] +name = "futures-macro" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +dependencies = [ + "autocfg", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" + +[[package]] +name = "futures-task" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" + +[[package]] +name = "futures-util" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +dependencies = [ + "autocfg", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest", +] + +[[package]] +name = "http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "httpdate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.14.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itconfig" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c0409a6ca1c517cc0395107e182666c4476daf98f6624cc52b99280e49d6120" +dependencies = [ + "itconfig-macro", +] + +[[package]] +name = "itconfig-macro" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3575d4586d697df22eeebb8d663257ba5d20f1ed28207882ae43c71861714e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer", + "digest", + "opaque-debug", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "ood_persistence" +version = "0.1.0" +dependencies = [ + "async-trait", + "bb8", + "bb8-postgres", + "r2d2", + "r2d2_postgres", +] + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "phf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postgres" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb76d6535496f633fa799bb872ffb4790e9cbdedda9d35564ca0252f930c0dd5" +dependencies = [ + "bytes", + "fallible-iterator", + "futures", + "log", + "tokio", + "tokio-postgres", +] + +[[package]] +name = "postgres-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c857dd221cb0e7d8414b894a0ce29eae44d453dda0baa132447878e75e701477" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b145e6a4ed52cb316a27787fc20fe8a25221cb476479f61e4e0327c15b98d91a" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04619f94ba0cc80999f4fc7073607cb825bc739a883cb6d20900fc5e009d6b0d" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-derive", + "postgres-protocol", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r2d2" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_postgres" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7029c56be658cb54f321e0bee597810ee16796b735fa2559d7056bf06b12230b" +dependencies = [ + "postgres", + "r2d2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + +[[package]] +name = "slab" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "socket2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tinyvec" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-postgres" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f916ee7e52c8a74dfe4162dd73a073d0d7d4b387ea7b97a774c0c10b0776531" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "socket2", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "web_example" +version = "0.1.0" +dependencies = [ + "async-trait", + "dotenv", + "env_logger", + "hyper", + "itconfig", + "lazy_static", + "log", + "ood_persistence", + "postgres-types", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e5cee0b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "ood_persistence" +version = "0.1.0" +edition = "2018" +authors = ["Dmitriy Pleshevskiy "] +repository = "https://github.com/pleshevskiy/ood_persistence" +description = "Asynchronous and synchronous interfaces and persistence implementations for your OOD architecture" +keywords = ["objected", "design", "architecture", "interface", "implementation"] +categories = ["rust-patterns", "database", "database-implementations"] +license = "MIT OR Apache-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +async = ["async-trait"] +sync = [] + +bb8_postgres = ["async", "bb8", "bb8-postgres"] +r2d2_postgres = ["sync", "r2d2", "r2d2-postgres"] + +[dependencies] +async-trait = { version = "0.1", optional = true } + +bb8 = { version = "0.7", optional = true } +bb8-postgres = { version = "0.7", optional = true } + +r2d2 = { version = "0.8", optional = true } +r2d2-postgres = { package = "r2d2_postgres", version = "0.18", optional = true } + +[workspace] +members = ["examples/*"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..e637b97 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# OOD Persistence + +Asynchronous and synchronous interfaces and persistence implementations for your OOD architecture + +## Installation + +Add `ood_persistence = { version = "0", features = [""] }` as a dependency in `Cargo.toml`. + +NOTE: change `` to feature name from available list. See `Cargo.toml` for more information. + +`Cargo.toml` example: + +```toml +[package] +name = "my-crate" +version = "0.1.0" +authors = ["Me "] + +[dependencies] +ood_persistence = { version = "0", features = ["bb8_postgres"] } +``` + +## Usage + +See examples directory. diff --git a/examples/web/.env.example b/examples/web/.env.example new file mode 100644 index 0000000..65efe71 --- /dev/null +++ b/examples/web/.env.example @@ -0,0 +1,11 @@ +RUST_BACKTRACE="1" +RUST_LOG="debug" + +POSTGRES_PASSWORD="test" +POSTGRES_USER="postgres" +POSTGRES_DB="x" +DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5577/${POSTGRES_DB}" + +DATABASE_POOL_MAX_SIZE=15 +SERVER_PORT=32444 +FEATURE_CORS=true diff --git a/examples/web/Cargo.lock b/examples/web/Cargo.lock new file mode 100644 index 0000000..c70bdd8 --- /dev/null +++ b/examples/web/Cargo.lock @@ -0,0 +1,1059 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-trait" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bb8" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9f4fa9768efd269499d8fba693260cfc670891cf6de3adc935588447a77cc8" +dependencies = [ + "async-trait", + "futures-channel", + "futures-util", + "parking_lot", + "tokio", +] + +[[package]] +name = "bb8-postgres" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fdf56d52b2cca401d2380407e5c35d3d25d3560224ecf74d6e4ca13e51239b" +dependencies = [ + "async-trait", + "bb8", + "tokio", + "tokio-postgres", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" + +[[package]] +name = "futures-executor" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" + +[[package]] +name = "futures-macro" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +dependencies = [ + "autocfg", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" + +[[package]] +name = "futures-task" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" + +[[package]] +name = "futures-util" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +dependencies = [ + "autocfg", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest", +] + +[[package]] +name = "http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "httpdate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.14.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itconfig" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c0409a6ca1c517cc0395107e182666c4476daf98f6624cc52b99280e49d6120" +dependencies = [ + "itconfig-macro", +] + +[[package]] +name = "itconfig-macro" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3575d4586d697df22eeebb8d663257ba5d20f1ed28207882ae43c71861714e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer", + "digest", + "opaque-debug", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "ood_persistence" +version = "0.1.0" +dependencies = [ + "async-trait", + "bb8", + "bb8-postgres", +] + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "phf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postgres-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c857dd221cb0e7d8414b894a0ce29eae44d453dda0baa132447878e75e701477" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b145e6a4ed52cb316a27787fc20fe8a25221cb476479f61e4e0327c15b98d91a" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04619f94ba0cc80999f4fc7073607cb825bc739a883cb6d20900fc5e009d6b0d" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-derive", + "postgres-protocol", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + +[[package]] +name = "slab" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "socket2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tinyvec" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-postgres" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f916ee7e52c8a74dfe4162dd73a073d0d7d4b387ea7b97a774c0c10b0776531" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "socket2", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "web_example" +version = "0.1.0" +dependencies = [ + "async-trait", + "dotenv", + "env_logger", + "hyper", + "itconfig", + "lazy_static", + "log", + "ood_persistence", + "postgres-types", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/examples/web/Cargo.toml b/examples/web/Cargo.toml new file mode 100644 index 0000000..4cb3558 --- /dev/null +++ b/examples/web/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "web_example" +version = "0.1.0" +edition = "2018" +publish = false + +[dependencies] +# configuration +log = "0.4" +env_logger = "0.7" +itconfig = { version = "1.1", features = ["macro"] } +lazy_static = "1.4" +# for local development +dotenv = { version = "0.15", optional = true } +async-trait = "0.1" + +# database +ood_persistence = { path = "../../", features = ["bb8_postgres"] } +postgres-types = { version = "0.2", features = ["derive"] } + +# runtime +tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "signal"] } + +# server +hyper = { version = "0.14", features = ["server", "http1", "runtime"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" + +[features] +dev = ["dotenv"] diff --git a/examples/web/Migra.toml b/examples/web/Migra.toml new file mode 100644 index 0000000..6d7c63d --- /dev/null +++ b/examples/web/Migra.toml @@ -0,0 +1,8 @@ +root = "database" + +[database] +connection = "$DATABASE_URL" + +[migrations] +directory = "migrations" +table_name = "migrations" diff --git a/examples/web/database/initdb.d/.gitkeep b/examples/web/database/initdb.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/examples/web/database/initdb.d/schema.sql b/examples/web/database/initdb.d/schema.sql new file mode 100644 index 0000000..bbba12f --- /dev/null +++ b/examples/web/database/initdb.d/schema.sql @@ -0,0 +1,5 @@ + +create table lists ( + id serial primary key, + name text not null +); diff --git a/examples/web/database/schema.sql b/examples/web/database/schema.sql new file mode 100644 index 0000000..bbba12f --- /dev/null +++ b/examples/web/database/schema.sql @@ -0,0 +1,5 @@ + +create table lists ( + id serial primary key, + name text not null +); diff --git a/examples/web/docker-compose.dev.yml b/examples/web/docker-compose.dev.yml new file mode 100644 index 0000000..2106350 --- /dev/null +++ b/examples/web/docker-compose.dev.yml @@ -0,0 +1,13 @@ +version: '3' + +services: + postgresql: + image: postgres:12.3-alpine + ports: + - 5577:5432 + volumes: + - ./database/initdb.d:/docker-entrypoint-initdb.d + environment: + POSTGRES_PASSWORD: test + POSTGRES_USER: postgres + POSTGRES_DB: x diff --git a/examples/web/src/app/list/_mocks.rs b/examples/web/src/app/list/_mocks.rs new file mode 100644 index 0000000..e4d4046 --- /dev/null +++ b/examples/web/src/app/list/_mocks.rs @@ -0,0 +1,8 @@ +use super::List; + +pub fn create_list_1_mock() -> List { + List { + id: 1, + name: String::from("My first list"), + } +} diff --git a/examples/web/src/app/list/controller.rs b/examples/web/src/app/list/controller.rs new file mode 100644 index 0000000..d7bb2d9 --- /dev/null +++ b/examples/web/src/app/list/controller.rs @@ -0,0 +1,32 @@ +use super::service::{create_postgres_list_service, ListService}; +use super::{List, ListId}; +use crate::db::persistence::PersistencePool; +use crate::db::persistence::PostgresPersistence; +use crate::error::ApiResult; + +pub fn create_postgres_list_controller( + persistence: PostgresPersistence, +) -> ListController { + ListController { + list_service: create_postgres_list_service(persistence), + } +} + +pub struct ListController

+where + P: PersistencePool, +{ + list_service: ListService

, +} + +impl

ListController

+where + P: PersistencePool, +{ + pub async fn get_list_opt(&self, list_id: Option) -> ApiResult> { + match list_id { + Some(list_id) => self.list_service.get_list_opt(list_id).await, + _ => Ok(None), + } + } +} diff --git a/examples/web/src/app/list/mod.rs b/examples/web/src/app/list/mod.rs new file mode 100644 index 0000000..7bf41bf --- /dev/null +++ b/examples/web/src/app/list/mod.rs @@ -0,0 +1,14 @@ +#[cfg(test)] +pub mod _mocks; + +pub mod controller; +pub mod service; +pub mod storage_type; + +pub type ListId = i32; + +#[derive(Debug, PartialEq, Eq, Serialize)] +pub struct List { + pub id: ListId, + pub name: String, +} diff --git a/examples/web/src/app/list/service.rs b/examples/web/src/app/list/service.rs new file mode 100644 index 0000000..fa30ce0 --- /dev/null +++ b/examples/web/src/app/list/service.rs @@ -0,0 +1,33 @@ +use super::storage_type::ListStorage; +use super::{List, ListId}; +use crate::db::list::storage::PostgresListStorage; +use crate::db::persistence::{PersistencePool, PostgresPersistence}; +use crate::error::ApiResult; + +pub fn create_postgres_list_service( + persistence: PostgresPersistence, +) -> ListService { + ListService { + persistence, + list_storage: Box::new(PostgresListStorage {}), + } +} + +pub struct ListService

+where + P: PersistencePool, +{ + persistence: P, + list_storage: Box>, +} + +impl

ListService

+where + P: PersistencePool, +{ + pub async fn get_list_opt(&self, list_id: ListId) -> ApiResult> { + let mut conn = self.persistence.get_connection().await?; + let list = self.list_storage.get_list_opt(&mut conn, list_id).await?; + Ok(list) + } +} diff --git a/examples/web/src/app/list/storage_type.rs b/examples/web/src/app/list/storage_type.rs new file mode 100644 index 0000000..29d5a09 --- /dev/null +++ b/examples/web/src/app/list/storage_type.rs @@ -0,0 +1,10 @@ +use super::{List, ListId}; +use crate::db::persistence::{ConnectionClient, QueryResult}; + +#[async_trait] +pub trait ListStorage: Send + Sync +where + Conn: ConnectionClient, +{ + async fn get_list_opt(&self, conn: &mut Conn, id: ListId) -> QueryResult>; +} diff --git a/examples/web/src/app/mod.rs b/examples/web/src/app/mod.rs new file mode 100644 index 0000000..d17e233 --- /dev/null +++ b/examples/web/src/app/mod.rs @@ -0,0 +1 @@ +pub mod list; diff --git a/examples/web/src/config.rs b/examples/web/src/config.rs new file mode 100644 index 0000000..3205b00 --- /dev/null +++ b/examples/web/src/config.rs @@ -0,0 +1,47 @@ +#![allow(non_snake_case)] + +itconfig::config! { + #![config(unwrap)] + + // RUST_BACKTRACE => "1", + + RUST_LOG => "error", + + database { + URL, + + pool { + MAX_SIZE: u32 => 15, + } + } + + server { + PORT: u16 => 8000, + }, + + feature { + static CORS: bool => false, + } +} + +/// Util for configure application via env variables. +/// +/// * Reads .env file for configure application (only for `dev` feature) +/// * Enables log macros via `env_logger` (See: https://docs.rs/env_logger) +/// * Initializes env config (See: https://docs.rs/itconfig) +/// +/// Note: When enabled `dev` feature, this function try to load .env file +/// for configure application. If .env file cannot read will panic. +pub fn load_env_config() { + #[cfg(feature = "dev")] + dotenv::dotenv().expect("Cannot load .env file"); + + init(); + + env_logger::init(); + + #[cfg(feature = "dev")] + debug!("Env variables from .env file loaded successfully"); + + debug!("Env configuration loaded successfully"); +} diff --git a/examples/web/src/db/list/mod.rs b/examples/web/src/db/list/mod.rs new file mode 100644 index 0000000..a082b6a --- /dev/null +++ b/examples/web/src/db/list/mod.rs @@ -0,0 +1,21 @@ +use crate::app::list::List; + +pub mod storage; + +pub type DbListId = i32; + +#[derive(Debug, FromSql)] +#[postgres(name = "lists")] +struct DbList { + pub id: DbListId, + pub name: String, +} + +impl From for List { + fn from(db: DbList) -> Self { + Self { + id: db.id, + name: db.name, + } + } +} diff --git a/examples/web/src/db/list/storage.rs b/examples/web/src/db/list/storage.rs new file mode 100644 index 0000000..c7c7242 --- /dev/null +++ b/examples/web/src/db/list/storage.rs @@ -0,0 +1,29 @@ +use super::DbList; +use crate::app::list::storage_type::ListStorage; +use crate::app::list::{List, ListId}; +use crate::db::persistence::{try_get_one, ConnectionClient, PostgresConnection, QueryResult}; +use postgres_types::Type; + +pub struct PostgresListStorage {} + +#[async_trait] +impl<'c> ListStorage> for PostgresListStorage { + async fn get_list_opt( + &self, + conn: &mut PostgresConnection<'c>, + list_id: ListId, + ) -> QueryResult> { + let inner_conn = conn.inner(); + + let stmt = inner_conn + .prepare_typed("select l from lists as l where l.id = $1", &[Type::INT4]) + .await?; + + inner_conn + .query_opt(&stmt, &[&list_id]) + .await? + .map(try_get_one::) + .transpose() + .map_err(From::from) + } +} diff --git a/examples/web/src/db/mod.rs b/examples/web/src/db/mod.rs new file mode 100644 index 0000000..893353f --- /dev/null +++ b/examples/web/src/db/mod.rs @@ -0,0 +1,2 @@ +pub mod list; +pub mod persistence; diff --git a/examples/web/src/db/persistence.rs b/examples/web/src/db/persistence.rs new file mode 100644 index 0000000..d3ae7ed --- /dev/null +++ b/examples/web/src/db/persistence.rs @@ -0,0 +1,35 @@ +use crate::config; +use ood_persistence::bb8_postgres::{tokio_postgres, NoTlsManager}; +pub use ood_persistence::bb8_postgres::{ + NoTlsConnection as PostgresConnection, NoTlsPersistence as PostgresPersistence, + NoTlsPool as PostgresPool, +}; +pub use ood_persistence::{ + asyn::{ConnectionClient, PersistencePool}, + error::Result as QueryResult, +}; + +pub async fn create_postgres_pool() -> PostgresPool { + let db_conn_config = config::database::URL() + .parse() + .expect("Failed to convert database url to database config"); + + let manager = NoTlsManager::new(db_conn_config, tokio_postgres::NoTls); + let pool = PostgresPool::builder() + .max_size(config::database::pool::MAX_SIZE()) + .build(manager) + .await + .expect("Failed to create database pool"); + + debug!("Created database DatabaseConnection pool successfully"); + + pool +} + +pub fn try_get_one(row: tokio_postgres::Row) -> Result +where + Db: postgres_types::FromSqlOwned, + App: From, +{ + row.try_get(0).map(From::::from) +} diff --git a/examples/web/src/error.rs b/examples/web/src/error.rs new file mode 100644 index 0000000..ce9d087 --- /dev/null +++ b/examples/web/src/error.rs @@ -0,0 +1,65 @@ +use ood_persistence::error::PersistenceError; +use std::error; +use std::fmt; + +pub type SyncStdError = Box; +pub type StdResult = Result; +pub type ApiResult = Result; + +#[derive(Debug)] +pub enum Error { + PersistenceError(PersistenceError), + Rest(RestKind), + Serde(serde_json::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PersistenceError(err) => write!(f, "{}", err), + Self::Rest(err) => write!(f, "{}", err), + Self::Serde(err) => write!(f, "{}", err), + } + } +} + +impl std::error::Error for Error {} + +impl From for Error { + fn from(err: PersistenceError) -> Self { + Self::PersistenceError(err) + } +} + +impl From for Error { + fn from(err: hyper::Error) -> Self { + Self::Rest(RestKind::Hyper(err)) + } +} + +impl From for Error { + fn from(err: hyper::http::Error) -> Self { + Self::Rest(RestKind::HyperHttp(err)) + } +} + +impl From for Error { + fn from(err: serde_json::Error) -> Self { + Self::Serde(err) + } +} + +#[derive(Debug)] +pub enum RestKind { + Hyper(hyper::Error), + HyperHttp(hyper::http::Error), +} + +impl fmt::Display for RestKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Hyper(err) => write!(f, "{}", err), + Self::HyperHttp(err) => write!(f, "{}", err), + } + } +} diff --git a/examples/web/src/lib.rs b/examples/web/src/lib.rs new file mode 100644 index 0000000..6092d5a --- /dev/null +++ b/examples/web/src/lib.rs @@ -0,0 +1,17 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate postgres_types; +#[macro_use] +extern crate log; +#[macro_use] +extern crate async_trait; +#[macro_use] +extern crate serde; + +pub mod config; +pub mod error; + +mod app; +mod db; +pub mod rest; diff --git a/examples/web/src/main.rs b/examples/web/src/main.rs new file mode 100644 index 0000000..94fbb2f --- /dev/null +++ b/examples/web/src/main.rs @@ -0,0 +1,10 @@ +use web_example::config::load_env_config; +use web_example::error::StdResult; +use web_example::rest::server::start_server; + +#[tokio::main] +async fn main() -> StdResult<()> { + load_env_config(); + start_server().await?; + Ok(()) +} diff --git a/examples/web/src/rest/context.rs b/examples/web/src/rest/context.rs new file mode 100644 index 0000000..1e8e32f --- /dev/null +++ b/examples/web/src/rest/context.rs @@ -0,0 +1,10 @@ +use crate::db::persistence::{PostgresPersistence, PostgresPool}; + +pub struct RestGlobalContext { + pub pool: PostgresPool, +} + +#[derive(Clone)] +pub struct RestReqContext<'p> { + pub persistence: PostgresPersistence<'p>, +} diff --git a/examples/web/src/rest/mod.rs b/examples/web/src/rest/mod.rs new file mode 100644 index 0000000..dbe14e8 --- /dev/null +++ b/examples/web/src/rest/mod.rs @@ -0,0 +1,6 @@ +pub mod context; +pub mod prelude; +pub mod routes; +pub mod server; +pub mod server_utils; +pub mod types; diff --git a/examples/web/src/rest/prelude.rs b/examples/web/src/rest/prelude.rs new file mode 100644 index 0000000..86b241b --- /dev/null +++ b/examples/web/src/rest/prelude.rs @@ -0,0 +1,6 @@ +pub use super::types::{QueryParams, ReqVariables, RestResponseData, RestResult}; +pub use crate::error::{ApiResult, StdResult}; +pub use hyper::{ + header::{self, HeaderValue}, + Body, Method, Request, Response, StatusCode, +}; diff --git a/examples/web/src/rest/routes/api/list.rs b/examples/web/src/rest/routes/api/list.rs new file mode 100644 index 0000000..48d1dee --- /dev/null +++ b/examples/web/src/rest/routes/api/list.rs @@ -0,0 +1,32 @@ +use crate::app::list::controller::create_postgres_list_controller; +use crate::rest::routes::*; +use crate::rest::server_utils::{create_not_found_err_json_response, create_ok_json_response}; + +pub enum Router { + GetListById(String), +} + +impl MaybeFrom> for Router { + fn maybe_from((method, uri_path_parts): RouteParts<'_>) -> Option { + match (method, uri_path_parts) { + (&Method::GET, [list_id]) => Some(Self::GetListById(list_id.to_string())), + _ => None, + } + } +} + +#[async_trait] +impl Resolver for Router { + async fn resolve(&self, ctx: RestReqContext<'_>, vars: ReqVariables<'_>) -> RestResult { + let controller = create_postgres_list_controller(ctx.persistence); + match self { + Self::GetListById(list_id) => { + let res = controller.get_list_opt(list_id.parse().ok()).await?; + match res { + Some(list) => create_ok_json_response(list), + None => create_not_found_err_json_response("List not found"), + } + } + } + } +} diff --git a/examples/web/src/rest/routes/api/mod.rs b/examples/web/src/rest/routes/api/mod.rs new file mode 100644 index 0000000..c4c380c --- /dev/null +++ b/examples/web/src/rest/routes/api/mod.rs @@ -0,0 +1,33 @@ +use crate::rest::routes::*; + +mod list; + +pub enum Router { + List(list::Router), +} + +impl MaybeFrom> for Router { + fn maybe_from((method, uri_path_parts): RouteParts<'_>) -> Option { + let rest_parts = &uri_path_parts[1..]; + uri_path_parts.get(0).copied().and_then(|part| match part { + "lists" => list::Router::maybe_from((method, rest_parts)).map(Self::List), + _ => None, + }) + } +} + +#[async_trait] +impl Resolver for Router { + async fn resolve(&self, ctx: RestReqContext<'_>, vars: ReqVariables<'_>) -> RestResult { + let mut res = match self { + Self::List(router) => router.resolve(ctx, vars).await?, + }; + + res.headers_mut().append( + header::CONTENT_TYPE, + HeaderValue::from_static("application/json; charset=utf-8"), + ); + + Ok(res) + } +} diff --git a/examples/web/src/rest/routes/mod.rs b/examples/web/src/rest/routes/mod.rs new file mode 100644 index 0000000..89618d8 --- /dev/null +++ b/examples/web/src/rest/routes/mod.rs @@ -0,0 +1,16 @@ +use crate::rest::context::RestReqContext; +use crate::rest::prelude::*; + +mod api; +pub mod root; + +#[async_trait] +pub trait Resolver { + async fn resolve(&self, ctx: RestReqContext<'_>, vars: ReqVariables<'_>) -> RestResult; +} + +type RouteParts<'a> = (&'a Method, &'a [&'a str]); + +trait MaybeFrom: Sized { + fn maybe_from(_: T) -> Option; +} diff --git a/examples/web/src/rest/routes/root.rs b/examples/web/src/rest/routes/root.rs new file mode 100644 index 0000000..dcd4882 --- /dev/null +++ b/examples/web/src/rest/routes/root.rs @@ -0,0 +1,44 @@ +use crate::config; +use crate::rest::routes::*; + +#[non_exhaustive] +pub enum Router { + #[allow(clippy::upper_case_acronyms)] + CORS, + HealthCheck, + NotFound, + Api(api::Router), +} + +impl From> for Router { + fn from((method, uri_path_parts): RouteParts<'_>) -> Self { + match (method, uri_path_parts) { + (&Method::OPTIONS, _) if config::feature::CORS() => Self::CORS, + (_, &["api", ..]) => api::Router::maybe_from((method, &uri_path_parts[1..])) + .map(Self::Api) + .unwrap_or(Self::NotFound), + (&Method::GET, &["health"]) => Self::HealthCheck, + _ => Self::NotFound, + } + } +} + +#[async_trait] +impl Resolver for Router { + async fn resolve(&self, ctx: RestReqContext<'_>, vars: ReqVariables<'_>) -> RestResult { + let res = match self { + Self::CORS => Response::builder() + .status(StatusCode::OK) + .body(Body::empty())?, + Self::Api(route) => route.resolve(ctx, vars).await?, + Self::HealthCheck => Response::builder() + .status(StatusCode::OK) + .body(Body::from("Ok"))?, + Self::NotFound => Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::from("Not Found"))?, + }; + + Ok(res) + } +} diff --git a/examples/web/src/rest/server.rs b/examples/web/src/rest/server.rs new file mode 100644 index 0000000..6c1ffd4 --- /dev/null +++ b/examples/web/src/rest/server.rs @@ -0,0 +1,95 @@ +use super::server_utils; +use crate::config; +use crate::db::persistence::create_postgres_pool; +use crate::error::SyncStdError; +use crate::rest::context::{RestGlobalContext, RestReqContext}; +use crate::rest::prelude::*; +use crate::rest::routes::{self, Resolver}; +use crate::rest::types::REST_INTERNAL_SERVER_ERROR; +use hyper::service::{make_service_fn, service_fn}; +use hyper::Server; +use std::sync::Arc; + +/// Waits for the Ctrl+C signal for graceful shutdown backend +async fn shutdown_signal() { + tokio::signal::ctrl_c() + .await + .expect("failed to install CTRL+C signal handler"); +} + +pub async fn start_server() -> StdResult<()> { + let pool = create_postgres_pool().await; + // let persistence = ood_persistence::bb8_postgres::new(&pool); + let context = Arc::new(RestGlobalContext { pool }); + + let new_service = make_service_fn(move |_| { + let context = context.clone(); + async { + Ok::<_, SyncStdError>(service_fn(move |req| process_request(req, context.clone()))) + } + }); + + let port = config::server::PORT(); + let addr = ([0, 0, 0, 0], port).into(); + let server = Server::bind(&addr) + .serve(new_service) + .with_graceful_shutdown(shutdown_signal()); + + info!("🚀 Server listening on http://localhost:{}", port); + + server.await?; + + Ok(()) +} + +fn split_request_uri_path(uri_path: &str) -> Vec<&str> { + uri_path + .split('/') + .filter(|part| !part.is_empty()) + .collect() +} + +async fn process_request( + req: Request, + context: Arc, +) -> StdResult> { + let (req_parts, req_body) = req.into_parts(); + let query_params = server_utils::get_query_params(req_parts.uri.query()); + let req_variables = ReqVariables::new(req_body, query_params); + + let method = &req_parts.method; + let uri_path_parts = &split_request_uri_path(req_parts.uri.path())[..]; + + let req_context = RestReqContext { + persistence: ood_persistence::bb8_postgres::new(&context.pool), + }; + + let route = routes::root::Router::from((method, uri_path_parts)); + let mut res = match route.resolve(req_context, req_variables).await { + Err(_) => server_utils::create_json_response( + StatusCode::INTERNAL_SERVER_ERROR, + RestResponseData::::error(REST_INTERNAL_SERVER_ERROR), + ) + // TODO(pleshevskiy): investigate why `Send` is not implemented + .unwrap(), + Ok(res) => res, + }; + + if config::feature::CORS() { + let headers = res.headers_mut(); + headers.insert( + header::ACCESS_CONTROL_ALLOW_ORIGIN, + HeaderValue::from_static("*"), + ); + headers.insert( + header::ACCESS_CONTROL_ALLOW_METHODS, + HeaderValue::from_static("HEAD, GET, POST, PUT, PATCH"), + ); + headers.insert( + header::ACCESS_CONTROL_ALLOW_HEADERS, + HeaderValue::from_static("Authorization, Content-Type"), + ); + } + + Ok(res) +} diff --git a/examples/web/src/rest/server_utils.rs b/examples/web/src/rest/server_utils.rs new file mode 100644 index 0000000..b21e27c --- /dev/null +++ b/examples/web/src/rest/server_utils.rs @@ -0,0 +1,65 @@ +use crate::error::StdResult; +use crate::rest::prelude::*; +use serde::{de, ser}; + +pub async fn deserialize_request_body(req_body: Body) -> StdResult +where + T: de::DeserializeOwned, +{ + let body_bytes = hyper::body::to_bytes(req_body).await?; + serde_json::from_slice(&body_bytes).map_err(From::from) +} + +pub fn serialize_response(res: Response) -> RestResult +where + T: ser::Serialize, +{ + let (parts, body) = res.into_parts(); + let body = serde_json::to_vec(&body)?; + Ok(Response::from_parts(parts, Body::from(body))) +} + +pub fn get_query_params(req_query: Option<&str>) -> QueryParams<'_> { + req_query + .map(|query| { + query + .split('&') + .into_iter() + .filter_map(|param| { + let mut parts = param.split('='); + if let (Some(key), Some(value)) = (parts.next(), parts.next()) { + Some((key, value)) + } else { + None + } + }) + .collect::>() + }) + .unwrap_or_default() +} + +pub fn create_not_found_err_json_response(message: &'static str) -> RestResult { + create_err_json_response(StatusCode::NOT_FOUND, message) +} + +pub fn create_err_json_response(status: StatusCode, message: &'static str) -> RestResult { + create_json_response::(status, RestResponseData::simple_error(message)) +} + +pub fn create_ok_json_response(body: Data) -> RestResult { + create_json_response(StatusCode::OK, RestResponseData::new(body)) +} + +pub fn create_json_response( + status: StatusCode, + body: RestResponseData, +) -> RestResult { + let res = Response::builder() + .status(status) + .header( + header::CONTENT_TYPE, + HeaderValue::from_static("application/json; charset=utf-8"), + ) + .body(body)?; + serialize_response(res) +} diff --git a/examples/web/src/rest/types.rs b/examples/web/src/rest/types.rs new file mode 100644 index 0000000..d2aa9cf --- /dev/null +++ b/examples/web/src/rest/types.rs @@ -0,0 +1,64 @@ +use crate::rest::prelude::ApiResult; +use hyper::{Body, Response}; +use serde::Serialize; +use std::collections::HashMap; + +pub type RestResult = ApiResult>; + +pub type QueryParams<'a> = HashMap<&'a str, &'a str>; + +#[derive(Debug)] +pub struct ReqVariables<'params> { + body: Body, + query_params: QueryParams<'params>, +} + +impl<'params> ReqVariables<'params> { + pub fn new(body: Body, query_params: QueryParams<'params>) -> Self { + ReqVariables { body, query_params } + } +} + +#[derive(Debug, Serialize)] +pub struct RestResponseData { + data: Option, + error: Option, +} + +impl Default for RestResponseData { + fn default() -> Self { + Self { + data: None, + error: None, + } + } +} + +impl RestResponseData { + pub fn new(data: Data) -> Self { + Self { + data: Some(data), + ..Default::default() + } + } + + pub fn error(err: RestResponseError) -> Self { + Self { + error: Some(err), + ..Default::default() + } + } + + pub fn simple_error(message: &'static str) -> Self { + Self::error(RestResponseError { message }) + } +} + +#[derive(Debug, Serialize)] +pub struct RestResponseError { + message: &'static str, +} + +pub const REST_INTERNAL_SERVER_ERROR: RestResponseError = RestResponseError { + message: "internal server error", +}; diff --git a/src/asyn.rs b/src/asyn.rs new file mode 100644 index 0000000..52bf285 --- /dev/null +++ b/src/asyn.rs @@ -0,0 +1,14 @@ +use crate::error; + +#[async_trait] +pub trait PersistencePool: Send + Sync { + type Conn: ConnectionClient; + + async fn get_connection(&self) -> error::Result; +} + +pub trait ConnectionClient { + type InnerConn; + + fn inner(&mut self) -> &mut Self::InnerConn; +} diff --git a/src/bb8_postgres.rs b/src/bb8_postgres.rs new file mode 100644 index 0000000..310a63e --- /dev/null +++ b/src/bb8_postgres.rs @@ -0,0 +1,52 @@ +use crate::asyn::{ConnectionClient, PersistencePool}; +use crate::error; + +pub use bb8::{Pool, PooledConnection}; +pub use bb8_postgres::tokio_postgres; +pub use bb8_postgres::PostgresConnectionManager as Manager; + +pub type NoTlsManager = Manager; +pub type NoTlsPersistence<'p> = Persistence<'p, NoTlsManager>; +pub type NoTlsConnection<'p> = Connection<'p, NoTlsManager>; +pub type NoTlsPool = Pool; + +pub type InnerConn<'p, M> = PooledConnection<'p, M>; + +pub fn new(pool: &Pool) -> Persistence +where + M: bb8::ManageConnection, +{ + Persistence(pool) +} + +#[derive(Clone)] +pub struct Persistence<'p, M: bb8::ManageConnection>(&'p Pool); + +#[async_trait] +impl<'p, M> PersistencePool for Persistence<'p, M> +where + M: bb8::ManageConnection + Send + Sync, +{ + type Conn = Connection<'p, M>; + + async fn get_connection(&self) -> error::Result { + self.0 + .get() + .await + .map_err(|_| error::PersistenceError::GetConnection) + .map(Connection) + } +} + +pub struct Connection<'p, M: bb8::ManageConnection>(InnerConn<'p, M>); + +impl<'c, M> ConnectionClient for Connection<'c, M> +where + M: bb8::ManageConnection, +{ + type InnerConn = InnerConn<'c, M>; + + fn inner(&mut self) -> &mut Self::InnerConn { + &mut self.0 + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..9d171a6 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,36 @@ +use std::error; +use std::fmt; + +pub type Result = std::result::Result; + +#[derive(Debug)] +pub enum PersistenceError { + GetConnection, + UpgradeToTransaction, + CommitTransaction, + RollbackTransaction, + DbError(Box), +} + +impl fmt::Display for PersistenceError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PersistenceError::GetConnection => f.write_str("Cannot get connection"), + PersistenceError::UpgradeToTransaction => { + f.write_str("Cannot upgrade connection to transaction") + } + PersistenceError::CommitTransaction => f.write_str("Cannot commit transaction"), + PersistenceError::RollbackTransaction => f.write_str("Cannot rollback transaction"), + PersistenceError::DbError(err) => write!(f, "DbError: {}", err), + } + } +} + +impl error::Error for PersistenceError {} + +#[cfg(feature = "bb8_postgres")] +impl From for PersistenceError { + fn from(err: bb8_postgres::tokio_postgres::Error) -> Self { + Self::DbError(Box::new(err)) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..59711f9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,23 @@ +#[cfg(feature = "async")] +#[macro_use] +extern crate async_trait; + +#[cfg(feature = "async")] +pub mod asyn; + +#[cfg(feature = "sync")] +pub mod syn; + +#[cfg(feature = "bb8")] +pub use bb8; + +#[cfg(feature = "bb8_postgres")] +pub mod bb8_postgres; + +#[cfg(feature = "r2d2")] +pub use r2d2; + +#[cfg(feature = "r2d2_postgres")] +pub mod r2d2_postgres; + +pub mod error; diff --git a/src/r2d2_postgres.rs b/src/r2d2_postgres.rs new file mode 100644 index 0000000..13b98ef --- /dev/null +++ b/src/r2d2_postgres.rs @@ -0,0 +1,51 @@ +use crate::error; +use crate::syn::{ConnectionClient, PersistencePool}; + +pub use r2d2::{Pool, PooledConnection}; +pub use r2d2_postgres::postgres; +pub use r2d2_postgres::PostgresConnectionManager as Manager; + +pub type NoTlsManager = Manager; +pub type NoTlsPersistence<'p> = Persistence<'p, NoTlsManager>; +pub type NoTlsConnection<'p> = Connection; +pub type NoTlsPool = Pool; + +pub type InnerConn = PooledConnection; + +pub fn new(pool: &Pool) -> Persistence +where + M: r2d2::ManageConnection, +{ + Persistence(pool) +} + +#[derive(Clone)] +pub struct Persistence<'p, M: r2d2::ManageConnection>(&'p Pool); + +#[async_trait] +impl<'p, M> PersistencePool for Persistence<'p, M> +where + M: r2d2::ManageConnection + Send + Sync, +{ + type Conn = Connection; + + fn get_connection(&self) -> error::Result { + self.0 + .get() + .map_err(|_| error::PersistenceError::GetConnection) + .map(Connection) + } +} + +pub struct Connection(InnerConn); + +impl ConnectionClient for Connection +where + M: r2d2::ManageConnection, +{ + type InnerConn = InnerConn; + + fn inner(&mut self) -> &mut Self::InnerConn { + &mut self.0 + } +} diff --git a/src/syn.rs b/src/syn.rs new file mode 100644 index 0000000..461abf6 --- /dev/null +++ b/src/syn.rs @@ -0,0 +1,13 @@ +use crate::error; + +pub trait PersistencePool { + type Conn: ConnectionClient; + + fn get_connection(&self) -> error::Result; +} + +pub trait ConnectionClient { + type InnerConn; + + fn inner(&mut self) -> &mut Self::InnerConn; +}