commit b3be701339861146da1777c2f6c4f1c192c182bd Author: Orion Kindel Date: Thu Jul 6 22:28:58 2023 -0500 feat: add postgres integration, submodule, start repo pattern diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f68cd5a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "postgres"] + path = postgres + url = https://github.com/sfackler/rust-postgres diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d0b660b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1293 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "api" +version = "0.1.0" +dependencies = [ + "log", + "nb", + "postgres", + "rand", + "serde", + "serde_json", + "simple_logger", + "toad", + "toad-msg", +] + +[[package]] +name = "async-trait" +version = "0.1.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "embedded-time" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" +dependencies = [ + "num", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[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.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[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.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "naan" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6154b19920bf4498afaf169c5d619d5b351de6d83f8061c114e17061c1ebc612" + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "openssl" +version = "0.10.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "openssl-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "postgres" +version = "0.19.5" +dependencies = [ + "bytes", + "fallible-iterator", + "futures-util", + "log", + "tokio", + "tokio-postgres", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.5" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.5" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-protocol", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[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.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "serde_json" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "simple_logger" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230cd5c29b815c9b699fb610b49a5ed65588f3509d9f0108be3a885da629333" +dependencies = [ + "colored", + "log", + "time", + "windows-sys 0.42.0", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[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.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toad" +version = "1.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41fbfaadd52558c4d595bf38fb6942333307c47158abc30c0c3a0bbd1848b65" +dependencies = [ + "embedded-time", + "log", + "naan", + "nb", + "no-std-net", + "openssl", + "paste", + "rand", + "rand_chacha", + "serde", + "serde_json", + "tinyvec", + "toad-array", + "toad-hash", + "toad-len", + "toad-macros", + "toad-map", + "toad-msg", + "toad-stem", + "toad-string", + "toad-writable", +] + +[[package]] +name = "toad-array" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc3f25d13b8cbfe71fe854ff3c9a8f3f9729a5bd008089bb8dc8378b4ef3578f" +dependencies = [ + "tinyvec", + "toad-len", +] + +[[package]] +name = "toad-cursor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dee8dde5a719faedaf8509f68a8ae1b72e6f0d96bcdbcd59b92de074fe7c33e" + +[[package]] +name = "toad-hash" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df947fa0b5724bb3c4e76d04b318a9466bf78a4880aea21a24f9c313d16b643b" +dependencies = [ + "blake2", +] + +[[package]] +name = "toad-len" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819ba7124b9324c03a7043145430b0df5b10374543785d3cc5f773b9c0e36b37" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "toad-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7496069c25b7e13b920d5293629d9e285d7a4ed9cd51ebfd2ce94690af779a" +dependencies = [ + "quote", + "regex", + "syn 1.0.109", +] + +[[package]] +name = "toad-map" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "423d547a014a817ea38dc677ca5e8488edf6aeeda36d69bdfcce5adf7b2a0918" +dependencies = [ + "tinyvec", + "toad-len", +] + +[[package]] +name = "toad-msg" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78ad790094eefd8146fab35178e23b224285fe9b275132a31872c0f74b1a8ff" +dependencies = [ + "blake2", + "tinyvec", + "toad-array", + "toad-cursor", + "toad-hash", + "toad-len", + "toad-macros", + "toad-map", +] + +[[package]] +name = "toad-stem" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "834a7cc46ed626b24dfb861d3de19cdd666fa945f5bd1b4d2d675551afef927c" + +[[package]] +name = "toad-string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdad9197bf6974091949a6d3e00946558d69e0d7b3d159283c6c43fffdef59dc" +dependencies = [ + "tinyvec", + "toad-array", + "toad-len", + "toad-writable", +] + +[[package]] +name = "toad-writable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe82c1076c85774b389e86cb2a2dbb846e35e599e9b42c8f2fc6628593cd0a9" +dependencies = [ + "toad-array", +] + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2 0.4.9", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-postgres" +version = "0.7.8" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "socket2 0.5.3", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9122142 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "api" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +toad = "1.0.0-beta.2" +toad-msg = "0.18.1" +simple_logger = "4.2" +nb = "1.1.0" +serde = {version = "1", features = ["derive"]} +serde_json = "1" +log = "0.4" +postgres = {path = "./postgres/postgres"} +rand = "0.8" diff --git a/postgres b/postgres new file mode 160000 index 0000000..790af54 --- /dev/null +++ b/postgres @@ -0,0 +1 @@ +Subproject commit 790af54a0fdd5c487e77dc9a25d82921ee31ffe6 diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..9523d3e --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,24 @@ +# General +max_width = 100 +newline_style = "Unix" +tab_spaces = 2 +indent_style = "Visual" +format_code_in_doc_comments = true +format_macro_bodies = true + +# Match statements +match_arm_leading_pipes = "Always" +match_block_trailing_comma = true + +# Structs +use_field_init_shorthand = true +struct_field_align_threshold = 0 + +# Enums +enum_discrim_align_threshold = 0 + +# Imports +group_imports = "StdExternalCrate" +imports_granularity = "Module" +imports_indent = "Visual" +imports_layout = "HorizontalVertical" diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..20c6401 --- /dev/null +++ b/src/app.rs @@ -0,0 +1,13 @@ +use crate::hashed_text::{HashedTextExt, HashedTextExtImpl}; +use crate::postgres::PostgresImpl; +use crate::user::UserRepo; + +trait App: Send + Sync + Sized { + type HashedTextExt: HashedTextExt; + type UserRepo: UserRepo; +} + +pub struct AppConcrete { + pg: PostgresImpl, + hashed_text_ext: HashedTextExtImpl>, +} diff --git a/src/hashed_text.rs b/src/hashed_text.rs new file mode 100644 index 0000000..49b8de7 --- /dev/null +++ b/src/hashed_text.rs @@ -0,0 +1,70 @@ +use postgres::{GenericClient, GenericRow}; + +use crate::postgres::{DbError, Postgres}; +use crate::repo::Ext; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct HashedText(String); + +pub trait HashedTextExt: Ext { + fn matches>(&self, this: &HashedText, other: S) -> Result; +} + +pub struct HashedTextExtImpl(&'static Db); + +impl Ext for HashedTextExtImpl where Db: Postgres +{ + type Error = DbError; +} + +impl HashedTextExt for HashedTextExtImpl where Db: Postgres +{ + fn matches>(&self, this: &HashedText, other: S) -> Result> { + static QUERY: &'static str = + "select public.hashed_text_matches($1, public.hashed_text_of_string($2))"; + + self.0 + .with_client(|client| client.query_one(QUERY, &[&other.as_ref(), &this.0.as_str()])) + .and_then(|row| row.try_get(0)) + } +} + +#[cfg(test)] +mod test { + use std::{any::Any, panic::AssertUnwindSafe}; + +use postgres::types::{Type, ToSql, private::BytesMut, FromSql}; + +use crate::{postgres::{test::{Client, Row}, PostgresImpl, Postgres}}; + +use super::{HashedTextExtImpl, HashedTextExt, HashedText}; + + #[test] + fn hashed_text_matches_fn_call() { + let client = || Client { + query_one: Box::new(|_, q, ps| { + assert_eq!(q.unwrap_str(), "select public.hashed_text_matches($1, public.hashed_text_of_string($2))"); + + let mut p0 = BytesMut::with_capacity(32); + let mut p1 = BytesMut::with_capacity(32); + + ps[0].to_sql(&Type::TEXT, &mut p0).unwrap(); + ps[1].to_sql(&Type::TEXT, &mut p1).unwrap(); + + let p0 = <&str as FromSql>::from_sql(&Type::TEXT, &p0).unwrap(); + let p1 = <&str as FromSql>::from_sql(&Type::TEXT, &p1).unwrap(); + + assert_eq!(p1, "XXX"); + + Ok(Row::new(vec![("", Type::BOOL)]).value(Type::BOOL, p0 == "foo")) + }), + ..Client::default() + }; + + let pg = PostgresImpl::>::try_new(|| Ok(client()), 1).unwrap(); + let htext = HashedTextExtImpl(unsafe {std::mem::transmute::<_, &'static PostgresImpl>>(&pg)}); + + assert!(htext.matches(&HashedText(String::from("XXX")), "foo").unwrap()); + assert!(!htext.matches(&HashedText(String::from("XXX")), "foob").unwrap()); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cab9a66 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,73 @@ +use hashed_text::HashedTextExt; +use toad::config::Config; +use toad::net::Addrd; +use toad::platform::Platform as _; +use toad::req::Req; +use toad::resp::Resp; +use toad::std::dtls; + +mod app; +mod hashed_text; +mod postgres; +mod repo; +mod user; +use repo::Repo; +use user::UserRepo; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct Email(String); + +type Dtls = toad::std::dtls::N; +type ToadT = toad::std::PlatformTypes; +type Toad = toad::std::Platform>; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, serde::Serialize, serde::Deserialize)] +struct Foo { + id: String, +} + +fn handle_request(req: Addrd>) -> Result>, String> { + let path = req.data() + .path() + .map_err(|e| format!("{e:?}")) + .unwrap_or(None) + .unwrap_or(""); + let mut path_segments = path.split("/").peekable(); + + if path_segments.peek() == Some(&"users") { + let mut path_segments = path_segments.clone(); + path_segments.next(); + let id = path_segments.next(); + } + + Ok(req.map(|r| Resp::for_request(&r).unwrap())) +} + +fn server_worker(p: &'static Toad) { + loop { + match nb::block!(p.poll_req()) { + | Err(e) => log::error!("{e:?}"), + | Ok(req) => match handle_request(req) { + | Err(e) => log::error!("{e:?}"), + | Ok(rep) => { + nb::block!(p.send_msg(rep.clone().map(Into::into))).map_err(|e| log::error!("{e:?}")) + .ok(); + }, + }, + } + } +} + +fn main() { + simple_logger::init().unwrap(); + + static mut TOAD: Option = None; + + unsafe { + TOAD = Some(Toad::try_new("0.0.0.0:4444", Config::default()).unwrap()); + } + + let r = unsafe { TOAD.as_ref().unwrap() }; + + server_worker(r); +} diff --git a/src/postgres.rs b/src/postgres.rs new file mode 100644 index 0000000..b2cae53 --- /dev/null +++ b/src/postgres.rs @@ -0,0 +1,410 @@ +use std::ops::{Deref, DerefMut}; +use std::pin::Pin; +use std::sync::{Mutex, MutexGuard, TryLockError}; + +use rand::{Rng, SeedableRng}; + +pub type DbError = <::Client as postgres::GenericClient>::Error; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct ConnectionParams { + pub host: String, + pub port: usize, + pub user: String, + pub pass: String, +} + +pub trait Postgres + where Self: Send + Sync + Sized + 'static +{ + type Client: postgres::GenericClient; + + fn try_new(connect: F, pool_size: usize) -> Result> + where F: Fn() -> Result>; + + fn with_client(&self, f: F) -> Result> + where F: FnOnce(&mut Self::Client) -> Result>; +} + +pub struct PostgresImpl { + size: usize, + pool: Pin>>>, +} + +impl PostgresImpl { + fn unused_lock(&self) -> Option> { + self.pool.iter().find_map(|m| m.try_lock().ok()) + } + + fn block_for_next(&self) -> MutexGuard { + let ix = rand::thread_rng().gen_range(0..self.size); + self.pool[ix].lock().unwrap() + } +} + +impl Postgres for PostgresImpl + where Self: Send + Sync, + C: 'static + postgres::GenericClient +{ + type Client = C; + + fn try_new(connect: F, pool_size: usize) -> Result + where F: Fn() -> Result + { + let mut pool = Vec::new(); + + if pool_size == 0 { + panic!("pool size must be > 0"); + } + + (0..pool_size).try_for_each(|_| { + // let c = postgres::Client::connect(&format!("user={user} password='{pass}' host={host} port={port}"), postgres::NoTls)?; + let c = connect()?; + pool.push(Mutex::new(c)); + Ok(()) + })?; + + Ok(PostgresImpl { size: pool_size, + pool: Box::pin(pool) }) + } + + fn with_client(&self, f: F) -> Result + where F: FnOnce(&mut Self::Client) -> Result + { + match self.unused_lock() { + | Some(mut lock) => f(lock.deref_mut()), + | None => f(self.block_for_next().deref_mut()), + } + } +} + +#[cfg(test)] +pub mod test { + use std::marker::PhantomData; + + pub mod client_function { + use postgres::StatementOrString; + + use super::Row; + + pub type Params<'a> = &'a [&'a (dyn postgres::types::ToSql + Sync)]; + + pub trait Execute: + Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result + { + } + pub trait BatchExecute: Fn(&mut C, &str) -> Result<(), E> {} + pub trait Query: + Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result>, E> + { + } + pub trait QueryOne: + Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result, E> + { + } + pub trait QueryOpt: + Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result>, E> + { + } + pub trait SimpleQuery: + Fn(&mut C, &str) -> Result, E> + { + } + pub trait CommitOrRollback: Fn(C) -> Result<(), E> {} + pub trait Transaction: Fn(&C) -> Result {} + + impl Execute for T + where T: Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result + { + } + impl BatchExecute for T where T: Fn(&mut C, &str) -> Result<(), E> {} + impl Query for T + where T: Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result>, E> + { + } + impl QueryOne for T + where T: Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result, E> + { + } + impl QueryOpt for T + where T: Fn(&mut C, StatementOrString<'_>, Params<'_>) -> Result>, E> + { + } + impl SimpleQuery for T + where T: Fn(&mut C, &str) -> Result, E> + { + } + impl CommitOrRollback for T where T: Fn(C) -> Result<(), E> {} + impl Transaction for T where T: Fn(&C) -> Result {} + } + + use client_function::{BatchExecute, + CommitOrRollback, + Execute, + Query, + QueryOne, + QueryOpt, + SimpleQuery, + Transaction}; + use postgres::types::private::BytesMut; + use postgres::types::{FromSql, ToSql, Type}; + use postgres::{Column, GenericRow, GenericClient}; + + use super::{Postgres, PostgresImpl}; + + pub struct Row { + pub columns: Vec, + pub values: Vec, + __phantom: PhantomData, + } + + impl Row { + pub fn new(cols: Vec<(&'static str, Type)>) -> Self { + Self { + columns: cols.into_iter().map(|(name, ty)| Column::new(name.to_string(), ty)).collect(), + values: vec![], + __phantom: PhantomData, + } + } + + pub fn value(mut self, ty: Type, val: V) -> Self where V: ToSql { + let mut bs = BytesMut::with_capacity(128); + val.to_sql(&ty, &mut bs).unwrap(); + self.values.push(bs); + self + } + } + + impl GenericRow for Row where E: core::fmt::Debug { + type Error = E; + + fn columns(&self) -> &[Column] { + &self.columns + } + + fn len(&self) -> usize { + self.values.len() + } + + fn get<'a, I, T>(&'a self, idx: I) -> T + where I: postgres::row::RowIndex + core::fmt::Display, + T: FromSql<'a> + { + let ix = idx.__idx(self.columns()).unwrap(); + let ty = self.columns()[ix].type_(); + T::from_sql(ty, &self.values[ix]).unwrap() + } + + fn try_get<'a, I, T>(&'a self, idx: I) -> Result + where I: postgres::row::RowIndex + core::fmt::Display, + T: FromSql<'a> + { + let ix = idx.__idx(self.columns()).unwrap(); + let ty = self.columns()[ix].type_(); + Ok(T::from_sql(ty, &self.values[ix]).unwrap()) + } + } + + #[non_exhaustive] + pub struct Client { + pub __phantom: PhantomData, + pub execute: Box>, + pub query: Box>, + pub query_one: Box>, + pub query_opt: Box>, + pub simple_query: Box>, + pub batch_execute: Box>, + pub commit: Box>, + pub rollback: Box>, + pub transaction: Box>, + } + + unsafe impl Send for Client {} + unsafe impl Sync for Client {} + + impl Default for Client where E: core::fmt::Debug + { + fn default() -> Self { + Client { __phantom: PhantomData, + execute: Box::new(|_, _, _| panic!("execute not implemented")), + query: Box::new(|_, _, _| panic!("query not implemented")), + query_one: Box::new(|_, _, _| panic!("query_one not implemented")), + query_opt: Box::new(|_, _, _| panic!("query_opt not implemented")), + simple_query: Box::new(|_, _| panic!("simple_query not implemented")), + batch_execute: Box::new(|_, _| panic!("batch_execute not implemented")), + commit: Box::new(|_| panic!("commit not implemented")), + rollback: Box::new(|_| panic!("rollback not implemented")), + transaction: Box::new(|_| panic!("transaction not implemented")) } + } + } + + macro_rules! common { + () => { + fn execute(&mut self, + query: &T, + params: &[&(dyn postgres::types::ToSql + Sync)]) + -> Result + where T: ?Sized + postgres::ToStatement + { + let mut f = Client::::default().execute; + std::mem::swap(&mut self.execute, &mut f); + let res = f(self, query.__convert(), params); + std::mem::swap(&mut self.execute, &mut f); + res + } + + fn query(&mut self, + query: &T, + params: &[&(dyn postgres::types::ToSql + Sync)]) + -> Result>, Self::Error> + where T: ?Sized + postgres::ToStatement + { + let mut f = Client::::default().query; + std::mem::swap(&mut self.query, &mut f); + let res = f(self, query.__convert(), params); + std::mem::swap(&mut self.query, &mut f); + res + } + + fn query_one(&mut self, + query: &T, + params: &[&(dyn postgres::types::ToSql + Sync)]) + -> Result, Self::Error> + where T: ?Sized + postgres::ToStatement + { + let mut f = Client::::default().query_one; + std::mem::swap(&mut self.query_one, &mut f); + let res = f(self, query.__convert(), params); + std::mem::swap(&mut self.query_one, &mut f); + res + } + + fn query_opt(&mut self, + query: &T, + params: &[&(dyn postgres::types::ToSql + Sync)]) + -> Result>, Self::Error> + where T: ?Sized + postgres::ToStatement + { + let mut f = Client::::default().query_opt; + std::mem::swap(&mut self.query_opt, &mut f); + let res = f(self, query.__convert(), params); + std::mem::swap(&mut self.query_opt, &mut f); + res + } + + fn query_raw(&mut self, + _: &T, + _: I) + -> Result, Self::Error> + where T: ?Sized + postgres::ToStatement, + P: postgres::types::BorrowToSql, + I: IntoIterator, + I::IntoIter: ExactSizeIterator + { + panic!("query_raw cannot be mocked") + } + + fn prepare(&mut self, _: &str) -> Result { + panic!("prepared statements cannot be mocked") + } + + fn prepare_typed(&mut self, + _: &str, + _: &[postgres::types::Type]) + -> Result { + panic!("prepared statements cannot be mocked") + } + + fn copy_in(&mut self, _: &T) -> Result, Self::Error> + where T: ?Sized + postgres::ToStatement + { + panic!("copy_in cannot be mocked") + } + + fn copy_out(&mut self, _: &T) -> Result, Self::Error> + where T: ?Sized + postgres::ToStatement + { + panic!("copy_out cannot be mocked") + } + + fn simple_query(&mut self, + query: &str) + -> Result, Self::Error> { + let mut f = Client::::default().simple_query; + std::mem::swap(&mut self.simple_query, &mut f); + let res = f(self, query); + std::mem::swap(&mut self.simple_query, &mut f); + res + } + + fn batch_execute(&mut self, query: &str) -> Result<(), Self::Error> { + let mut f = Client::::default().batch_execute; + std::mem::swap(&mut self.batch_execute, &mut f); + let res = f(self, query); + std::mem::swap(&mut self.batch_execute, &mut f); + res + } + + fn transaction(&mut self) -> Result, Self::Error> { + let mut f = Client::::default().transaction; + std::mem::swap(&mut self.transaction, &mut f); + let res = f(self); + std::mem::swap(&mut self.transaction, &mut f); + res + } + }; + } + + impl<'a, E> postgres::GenericTransaction<'a> for Client where E: core::fmt::Debug + { + type Error = E; + type NestedTransaction<'b> = Client where Client: 'b; + type Row = Row; + + common!(); + + fn commit(mut self) -> Result<(), E> { + let mut f = Client::::default().commit; + std::mem::swap(&mut self.commit, &mut f); + let res = f(self); + res + } + + fn rollback(mut self) -> Result<(), E> { + let mut f = Client::::default().rollback; + std::mem::swap(&mut self.commit, &mut f); + let res = f(self); + res + } + } + + impl postgres::GenericClient for Client where E: core::fmt::Debug + { + type Error = E; + type Transaction<'a> = Client where Client: 'a; + type Row = Row; + + common!(); + } + + #[test] + fn postgres_impl_pooling() { + let client = || Client { query_one: Box::new(|_, _, _| { + Ok(Row::new(vec![("foo", Type::TEXT)]).value(Type::TEXT, "bar")) + }), + ..Client::default() }; + + let pg = PostgresImpl::>::try_new(|| Ok(client()), 2).unwrap(); + + // try_lock locks the first available and returns None when all are locked + let a = pg.unused_lock().expect("there are unlocked clients"); + let _b = pg.unused_lock().expect("there are unlocked clients"); + assert!(pg.unused_lock().is_none()); + drop(a); + assert!(pg.unused_lock().is_some()); + + // with_client does not block when there are available clients + let row = pg.with_client(|c| c.query_one("", &[])).unwrap(); + assert_eq!(row.get::<_, String>("foo"), String::from("bar")); + } +} diff --git a/src/repo.rs b/src/repo.rs new file mode 100644 index 0000000..80e1d11 --- /dev/null +++ b/src/repo.rs @@ -0,0 +1,22 @@ +pub trait Repo: Send + Sync { + type T; + type TPut; + type Error: core::fmt::Debug; + type Id: AsRef; + + fn get(&self, id: Self::Id) -> Result, Self::Error>; + fn get_all(&self) -> Result, Self::Error>; + fn put(&self, id: Self::Id, state: Self::TPut) -> Result<(), Self::Error>; + fn del(&self, id: Self::Id) -> Result<(), Self::Error>; +} + +/// An entity that has some operations which rely on +/// an external service +pub trait Ext: Send + Sync { + type Error: core::fmt::Debug; + + /// Preparing statements would go here + fn init(&self) -> Result<(), Self::Error> { + Ok(()) + } +} diff --git a/src/user.rs b/src/user.rs new file mode 100644 index 0000000..e85d83e --- /dev/null +++ b/src/user.rs @@ -0,0 +1,25 @@ +use crate::repo::Repo; +use crate::{Email, hashed_text::HashedText}; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct UserId(String); + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct UserTag(String); + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct User { + uid: UserId, + tag: UserTag, + password: HashedText, + email: Email, +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct UserPut { + tag: UserTag, + password: HashedText, + email: Email, +} + +pub trait UserRepo: Repo {}