From 0e68aa4f7f6a1f1bf25e18fda03590fd69d9c305 Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 31 Dec 2020 22:42:36 +0000 Subject: [PATCH] initial commit --- .gitignore | 7 + Cargo.lock | 1500 ------------------------------------- Cargo.toml | 41 +- README.org | 2 - TODO | 1 - build.rs | 24 - src/bytes.rs | 108 --- src/cache.rs | 3 - src/config.rs | 94 --- src/ext.rs | 333 -------- src/html/mod.rs | 165 ---- src/identity.rs | 66 -- src/main.rs | 93 +-- src/post/mod.rs | 156 ---- src/regex.rs | 127 ---- src/state/global.rs | 8 - src/state/local/delta.rs | 255 ------- src/state/local/error.rs | 26 - src/state/local/host.rs | 79 -- src/state/local/karada.rs | 101 --- src/state/local/mod.rs | 128 ---- src/state/local/work.rs | 116 --- src/state/mod.rs | 29 - src/suspend.rs | 533 ------------- src/tripcode.rs | 109 --- src/web/error.rs | 61 -- src/web/mod.rs | 269 ------- src/web/route.rs | 254 ------- 28 files changed, 10 insertions(+), 4678 deletions(-) delete mode 100644 Cargo.lock delete mode 100644 README.org delete mode 100644 TODO delete mode 100644 build.rs delete mode 100644 src/bytes.rs delete mode 100644 src/cache.rs delete mode 100644 src/config.rs delete mode 100644 src/ext.rs delete mode 100644 src/html/mod.rs delete mode 100644 src/identity.rs delete mode 100644 src/post/mod.rs delete mode 100644 src/regex.rs delete mode 100644 src/state/global.rs delete mode 100644 src/state/local/delta.rs delete mode 100644 src/state/local/error.rs delete mode 100644 src/state/local/host.rs delete mode 100644 src/state/local/karada.rs delete mode 100644 src/state/local/mod.rs delete mode 100644 src/state/local/work.rs delete mode 100644 src/state/mod.rs delete mode 100644 src/suspend.rs delete mode 100644 src/tripcode.rs delete mode 100644 src/web/error.rs delete mode 100644 src/web/mod.rs delete mode 100644 src/web/route.rs diff --git a/.gitignore b/.gitignore index e2a3069..8b959a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ /target *~ + + +# Added by cargo +# +# already existing elements were commented out + +#/target diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 7980ef2..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1500 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "addr2line" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" - -[[package]] -name = "aho-corasick" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "arc-swap" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" - -[[package]] -name = "async-trait" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783" -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 0.3.9", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "backtrace" -version = "0.3.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bitstring" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e54f7b7a46d7b183eb41e2d82965261fa8a1597c68b50aced268ee1fc70272d" - -[[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 = "build_const" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - -[[package]] -name = "bzip2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.9+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad3b39a260062fca31f7b0b12f207e8f2590a67d32ec7d59c20484b07ea7285e" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "cc" -version = "1.0.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "chrono" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" -dependencies = [ - "num-integer", - "num-traits", - "serde", - "time", -] - -[[package]] -name = "cidr" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6316c62053228eddd526a5e6deb6344c80bf2bc1e9786e7f90b3083e73197c1" -dependencies = [ - "bitstring", - "serde", -] - -[[package]] -name = "color-eyre" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac5c105065fcb0c002304ae32147ba52df86e07cea7de11c88c62d24972d683" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] - -[[package]] -name = "color-spantrace" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a99aa4aa18448eef4c7d3f86d2720d2d8cad5c860fe9ff9b279293efdc8f5be" -dependencies = [ - "ansi_term", - "tracing-core", - "tracing-error", -] - -[[package]] -name = "cpuid-bool" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" - -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -dependencies = [ - "build_const", -] - -[[package]] -name = "crypto-mac" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "cryptohelpers" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825b8339215ceae0288ed0384ebe63fe717f5b0c77b102ff3c9f59aefeed9106" -dependencies = [ - "crc", - "getrandom", - "hex-literal 0.3.1", - "hmac", - "libc", - "openssl", - "pbkdf2", - "serde", - "serde_derive", - "sha2", - "tokio", -] - -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "enum-set" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf2bab91676279dd3148f1d28737631e98b3f6c662e444d700d9d6ccf6665df" - -[[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 = "eyre" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f9683839e579a53258d377fcc0073ca0bf2042ac5e6c60a598069e64403a6d" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "filetime" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.9", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[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 = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" - -[[package]] -name = "futures-executor" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" - -[[package]] -name = "futures-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" - -[[package]] -name = "futures-task" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" -dependencies = [ - "once_cell", -] - -[[package]] -name = "futures-util" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project", - "pin-utils", - "proc-macro-hack", - "proc-macro-nested", - "slab", -] - -[[package]] -name = "generational-arena" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601" -dependencies = [ - "cfg-if", -] - -[[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.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gimli" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" - -[[package]] -name = "h2" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" - -[[package]] -name = "hashbrown" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" - -[[package]] -name = "hermit-abi" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" -dependencies = [ - "libc", -] - -[[package]] -name = "hex-literal" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" -dependencies = [ - "hex-literal-impl", - "proc-macro-hack", -] - -[[package]] -name = "hex-literal" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8" - -[[package]] -name = "hex-literal-impl" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853f769599eb31de176303197b7ba4973299c38c7a7604a6bc88c3eef05b9b46" -dependencies = [ - "proc-macro-hack", -] - -[[package]] -name = "hmac" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "http" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "httparse" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" - -[[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.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project", - "socket2", - "time", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "indenter" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0bd112d44d9d870a6819eb505d04dd92b5e4d94bb8c304924a0872ae7016fb5" - -[[package]] -name = "indexmap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "itoa" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "khash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592c0325561e878d43491e8ef0fed4ecb2b84ddbb1d668405914c50400ba1b9e" -dependencies = [ - "crc", - "getrandom", - "hex-literal 0.2.1", - "libc", - "malloc-array", - "sha2", -] - -[[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.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" - -[[package]] -name = "libpcre-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff3dd28ba96d6fe6752882f2f1b25ba8e1646448e79042442347cf3a92a6666" -dependencies = [ - "bzip2", - "libc", - "pkg-config", - "tar", -] - -[[package]] -name = "log" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "malloc-array" -version = "1.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f994770c7bb3f8f7db7c4160665fc8814c8c705c10ae59a3d7354f0b8838f5c" -dependencies = [ - "libc", -] - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" - -[[package]] -name = "miniz_oxide" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" -dependencies = [ - "cfg-if", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow 0.2.1", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-named-pipes" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" -dependencies = [ - "log", - "mio", - "miow 0.3.5", - "winapi 0.3.9", -] - -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "miow" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" -dependencies = [ - "socket2", - "winapi 0.3.9", -] - -[[package]] -name = "net2" -version = "0.2.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" -dependencies = [ - "cfg-if", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "num-integer" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" -dependencies = [ - "autocfg", -] - -[[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 = "object" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" - -[[package]] -name = "once_cell" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl" -version = "0.10.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "lazy_static", - "libc", - "openssl-sys", -] - -[[package]] -name = "openssl-sys" -version = "0.9.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "owo-colors" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1250cdd103eef6bd542b5ae82989f931fc00a41a27f60377338241594410f3" - -[[package]] -name = "pbkdf2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170d73bf11f39b4ce1809aabc95bf5c33564cdc16fc3200ddda17a5f6e5e48b" -dependencies = [ - "base64", - "crypto-mac", - "hmac", - "rand", - "rand_core", - "sha2", - "subtle", -] - -[[package]] -name = "pcre" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f2cf69d4d3e55fac13ccbbf142e650bccbcd9cd2e5b5b69033df9e97d190562" -dependencies = [ - "enum-set", - "libc", - "libpcre-sys", -] - -[[package]] -name = "pin-project" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" - -[[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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - -[[package]] -name = "pretty_env_logger" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" -dependencies = [ - "env_logger", - "log", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" - -[[package]] -name = "proc-macro-nested" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" - -[[package]] -name = "proc-macro2" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29" -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.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "regex" -version = "1.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-syntax" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha2" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" -dependencies = [ - "block-buffer", - "cfg-if", - "cpuid-bool", - "digest", - "opaque-debug", -] - -[[package]] -name = "sharded-slab" -version = "0.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" -dependencies = [ - "arc-swap", - "libc", -] - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" - -[[package]] -name = "smallmap" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0f2ba34636f226215707072e602d87000095a60ad825f531827e9154d2823" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "socket2" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.9", -] - -[[package]] -name = "subtle" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" - -[[package]] -name = "syn" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tar" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" -dependencies = [ - "filetime", - "libc", - "redox_syscall", - "xattr", -] - -[[package]] -name = "termcolor" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - -[[package]] -name = "tokio" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "libc", - "memchr", - "mio", - "mio-named-pipes", - "mio-uds", - "num_cpus", - "pin-project-lite", - "signal-hook-registry", - "slab", - "tokio-macros", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-macros" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower-service" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" - -[[package]] -name = "tracing" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" -dependencies = [ - "cfg-if", - "log", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-error" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" -dependencies = [ - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "tracing-subscriber" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82bb5079aa76438620837198db8a5c529fb9878c730bc2b28179b0241cf04c10" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - -[[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.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "uuid" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -dependencies = [ - "rand", - "serde", -] - -[[package]] -name = "vcpkg" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" - -[[package]] -name = "version_check" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" - -[[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.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[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-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[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 0.3.9", -] - -[[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 = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "xattr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -dependencies = [ - "libc", -] - -[[package]] -name = "yuurei" -version = "0.1.0" -dependencies = [ - "async-trait", - "byteorder", - "chrono", - "cidr", - "color-eyre", - "cryptohelpers", - "difference", - "futures", - "generational-arena", - "hex-literal 0.3.1", - "hyper", - "khash", - "lazy_static", - "libc", - "log", - "once_cell", - "pcre", - "pin-project", - "pretty_env_logger", - "rustc_version", - "serde", - "serde_cbor", - "smallmap", - "tokio", - "uuid", -] diff --git a/Cargo.toml b/Cargo.toml index 518f3e2..62339de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,49 +1,10 @@ [package] name = "yuurei" +description = "ghost text messaging" version = "0.1.0" authors = ["Avril "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[features] -# Use `memmove` array inserter. -# Depenging on context this can perhaps be slower or perhaps be faster. -# Best to leave it off if you don't have explicit reason to use it. -experimental_inserter = [] - -[profile.release] -opt-level = 3 -lto = "fat" -codegen-units = 1 -panic = "unwind" - [dependencies] -tokio = {version = "0.2", features=["full"]} -async-trait = "0.1" -chrono = {version = "0.4.15", features=["serde"]} -uuid = { version = "0.8.1", features = ["v4", "serde"] } -once_cell = "1.4" -crypto = {version = "1.1.2", package= "cryptohelpers", features= ["serialise", "async", "sha256"]} -libc = "0.2.76" -byteorder = "1.3" -serde_cbor = "0.11.1" -serde = {version = "1.0", features= ["derive"]} -futures = "0.3" -pin-project = "0.4.23" -difference = "2.0.0" -color-eyre = "0.5.2" -hyper = "0.13.7" -cidr = {version = "0.1.1", features=["serde"]} -pretty_env_logger = "0.4.0" -log = "0.4.11" -pcre = "0.2.3" -generational-arena = "0.2.8" -khash = {version = "2.0.0", default-features=false} -hex-literal = "0.3.1" -lazy_static = "1.4.0" -smallmap = "1.1" -maud = "0.22.0" - -[build-dependencies] -rustc_version = "0.2" diff --git a/README.org b/README.org deleted file mode 100644 index 6f8a38d..0000000 --- a/README.org +++ /dev/null @@ -1,2 +0,0 @@ -* yuurei -Anonymous real-time single page textboard diff --git a/TODO b/TODO deleted file mode 100644 index 6f4f13a..0000000 --- a/TODO +++ /dev/null @@ -1 +0,0 @@ -Remove move_via_unsafe. Splice is now faster diff --git a/build.rs b/build.rs deleted file mode 100644 index 6399463..0000000 --- a/build.rs +++ /dev/null @@ -1,24 +0,0 @@ - -extern crate rustc_version; -use rustc_version::{version, version_meta, Channel}; - -fn main() { - // Assert we haven't travelled back in time - assert!(version().unwrap().major >= 1); - - // Set cfg flags depending on release channel - match version_meta().unwrap().channel { - Channel::Stable => { - println!("cargo:rustc-cfg=stable"); - } - Channel::Beta => { - println!("cargo:rustc-cfg=beta"); - } - Channel::Nightly => { - println!("cargo:rustc-cfg=nightly"); - } - Channel::Dev => { - println!("cargo:rustc-cfg=dev"); - } - } -} diff --git a/src/bytes.rs b/src/bytes.rs deleted file mode 100644 index 5291229..0000000 --- a/src/bytes.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::{ - fmt, - error, -}; -use libc::c_void; - -pub unsafe fn refer<'a, T>(src: &'a T) -> &'a [u8] -where T: ?Sized -{ - std::slice::from_raw_parts(src as *const T as *const u8, std::mem::size_of_val(src)) -} - -pub unsafe fn refer_mut<'a, T>(src: &'a mut T) -> &'a mut [u8] -where T: ?Sized -{ - std::slice::from_raw_parts_mut(src as *mut T as *mut u8, std::mem::size_of_val(src)) -} - -pub unsafe fn derefer<'a, T>(src: &'a [u8]) -> &'a T -{ - assert!(src.len() >= std::mem::size_of::()); - &*(&src[0] as *const u8 as *const T) -} - -pub unsafe fn derefer_mut<'a, T>(src: &'a mut [u8]) -> &'a mut T -{ - assert!(src.len() >= std::mem::size_of::()); - &mut *(&mut src[0] as *mut u8 as *mut T) -} -mod old { - use super::*; - /// Represents a type that can be converted from bytes to itself - pub trait FromBytes: Sized - { - type Error; - fn from_bytes>(bytes: T) -> Result; - } - - /// Represents a type that can be converted into bytes - pub trait IntoBytes:Sized - { - fn into_bytes(self) -> Box<[u8]>; - } - - impl>> IntoBytes for T - { - #[inline] fn into_bytes(self) -> Box<[u8]> - { - self.into() - } - } - - impl FromBytes for Vec - { - type Error = !; - #[inline] fn from_bytes>(bytes: T) -> Result - { - Ok(Vec::from(bytes.as_ref())) - } - } - impl FromBytes for Box<[u8]> - { - type Error = !; - #[inline] fn from_bytes>(bytes: T) -> Result - { - Ok(Vec::from(bytes.as_ref()).into_boxed_slice()) - } - } - - - /// The error used when a `FromBytes` conversion fails because the buffer was not the correct size - #[derive(Debug)] - pub struct SizeError; - impl error::Error for SizeError{} - impl fmt::Display for SizeError - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f,"buffer was not the correct size") - } - } - -} -/// Copy slice of bytes only -/// -/// # Notes -/// `dst` and `src` must not overlap. See [move_slice]. -pub fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize -{ - let sz = std::cmp::min(dst.len(),src.len()); - unsafe { - libc::memcpy(&mut dst[0] as *mut u8 as *mut c_void, &src[0] as *const u8 as *const c_void, sz); - } - sz -} - -/// Move slice of bytes only -/// -/// # Notes -/// `dst` and `src` can overlap. -pub fn move_slice(dst: &mut [u8], src: &[u8]) -> usize -{ - let sz = std::cmp::min(dst.len(),src.len()); - unsafe { - libc::memmove(&mut dst[0] as *mut u8 as *mut c_void, &src[0] as *const u8 as *const c_void, sz); - } - sz -} diff --git a/src/cache.rs b/src/cache.rs deleted file mode 100644 index d7671ea..0000000 --- a/src/cache.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Caching interfaces - -//TODO diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index 4acb41a..0000000 --- a/src/config.rs +++ /dev/null @@ -1,94 +0,0 @@ -use super::*; -use std::{ - borrow::Cow, - net::{ - SocketAddr, - Ipv4Addr, - }, -}; -use tokio::{ - time, -}; -use cidr::Cidr; - -//TODO: Use tokio Watcher instead, to allow hotreloading? -use once_cell::sync::OnceCell; - -static INSTANCE: OnceCell = OnceCell::new(); - -/// Set the global config instance. -/// This can only be done once for the duration of the program's runtime -pub fn set(conf: Config) -{ - INSTANCE.set(conf).expect("Failed to set global config state: Already set"); -} - -/// Get the global config instance. -/// `set()` must have been previously called or this function panics. -pub fn get() -> &'static Config -{ - INSTANCE.get().expect("Global config tried to be accessed before it was set") -} - -/// Get the global config instance or return default config instance. -pub fn get_or_default() -> Cow<'static, Config> -{ - match INSTANCE.get() { - Some(e) => Cow::Borrowed(e), - _ => { - warn!("Config instance not initialised, using default."); - Cow::Owned(Config::default()) - } - } -} - -/// A salt for secure tripcode -pub type Salt = [u8; khash::salt::SIZE]; - -/// Config for this run -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Config -{ - /// Name for nanashi - pub anon_name: Cow<'static, str>, - /// The server will listen on this address - pub listen: SocketAddr, - /// Accept all connections in this match - pub accept_mask: Vec, - /// Deny all connections in this match, even if previously matched by allow - pub deny_mask: Vec, - /// Accept by default - pub accept_default: bool, - /// The number of connections allowed to be processed at once on one route - pub dos_max: usize, - - /// The timeout for any routing dispatch - pub req_timeout_local: Option, - /// The timeout for *all* routing dispatchs - pub req_timeout_global: Option, - - /// The salt for secure tripcode - pub tripcode_salt: Salt, -} - -impl Default for Config -{ - #[inline] - fn default() -> Self - { - Self { - anon_name: Cow::Borrowed("Nanashi"), - listen: SocketAddr::from(([0,0,0,0], 8088)), - accept_mask: vec![cidr::Ipv4Cidr::new(Ipv4Addr::new(127,0,0,1), 32).unwrap().into()], - deny_mask: Vec::new(), - accept_default: false, - dos_max: 16, - - req_timeout_local: Some(time::Duration::from_millis(500)), - req_timeout_global: Some(time::Duration::from_secs(1)), - - tripcode_salt: hex!("770d64c6bf46da1a812d067fd224bbe671b7607d3274265abfcdda45c44ca3c1"), - } - } -} - diff --git a/src/ext.rs b/src/ext.rs deleted file mode 100644 index 93f716b..0000000 --- a/src/ext.rs +++ /dev/null @@ -1,333 +0,0 @@ -//! Extensions -use super::*; -use std::{ - marker::PhantomData, - fmt, - ops, -}; - -/// Wrapper to derive debug for types that don't implement it. -#[repr(transparent)] -#[derive(Clone, PartialEq, Eq, Ord,PartialOrd, Hash)] -pub struct OpaqueDebug(T); - -impl OpaqueDebug -{ - /// Create a new wrapper - #[inline] pub const fn new(value: T) -> Self - { - Self(value) - } - - /// Consume into the value - #[inline] pub fn into_inner(self) -> T - { - self.0 - } -} - -impl AsRef for OpaqueDebug -{ - #[inline] fn as_ref(&self) -> &T - { - &self.0 - } -} - -impl AsMut for OpaqueDebug -{ - #[inline] fn as_mut(&mut self) -> &mut T - { - &mut self.0 - } -} - -impl ops::Deref for OpaqueDebug -{ - type Target = T; - #[inline] fn deref(&self) -> &Self::Target - { - &self.0 - } -} - -impl ops::DerefMut for OpaqueDebug -{ - #[inline] fn deref_mut(&mut self) -> &mut Self::Target - { - &mut self.0 - } -} - -impl fmt::Debug for OpaqueDebug -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "") - } -} - - -/// A trait for types that can insert objects at their end. -pub trait BackInserter -{ - /// Insert an object at the end of this container - fn push_back(&mut self, value: T); -} - -impl BackInserter for Vec -{ - #[inline] - fn push_back(&mut self, value: T) - { - self.push(value) - } -} - -/// Absracts a closure for `BackInserter`. -pub struct BackInsertPass(F, PhantomData) -where F: FnMut(T); - -impl BackInsertPass -{ - /// Create a new instance with this closure - #[inline] pub fn new(func: F) -> Self - { - Self(func, PhantomData) - } -} - -impl BackInserter for BackInsertPass -{ - #[inline] fn push_back(&mut self, value: T) - { - self.0(value) - } -} - -/// A `BackInserter` that will only add a max capacity of items before it starts dropping input to its `push_back` function. -pub struct CappedBackInserter<'a, T>(&'a mut T, usize, usize) -where T: BackInserter; - -impl<'a, T> CappedBackInserter<'a, T> -where T: BackInserter -{ - /// Create a new instance with this max capacity - #[inline] pub fn new(from: &'a mut T, cap: usize) -> Self - { - Self(from, 0, cap) - } - - /// The number of elements pushed so far - #[inline] pub fn len(&self) -> usize { - self.1 - } - - /// The max number of elemnts allowed to be pushed - #[inline] pub fn cap(&self) -> usize { - self.2 - } -} - -impl<'a, T> BackInserter for CappedBackInserter<'a, T> -where T: BackInserter -{ - #[inline] fn push_back(&mut self, value: T) - { - if self.1 < self.2 { - self.0.push_back(value); - self.1+=1; - } - } -} - -pub trait VecExt -{ - /// Insert many elements with exact size iterator - fn insert_exact>(&mut self, location: usize, slice: I) - where Ex: ExactSizeIterator; - - /// Insert many elements - fn insert_many>(&mut self, location: usize, slice: I); -} - - -impl VecExt for Vec -{ - #[cfg(not(feature="experimental_inserter"))] - #[inline(always)] - fn insert_exact>(&mut self, location: usize, slice: I) - where Ex: ExactSizeIterator - { - self.insert_many(location, slice) - } - #[cfg(feature="experimental_inserter")] - fn insert_exact>(&mut self, location: usize, slice: I) - where Ex: ExactSizeIterator, - { - #[inline(never)] - #[cold] - fn panic_len(l1: usize, l2: usize) -> ! - { - panic!("Location must be in range 0..{}, got {}", l1,l2) - } - - #[inline(never)] - #[cold] - fn inv_sz() -> ! - { - panic!("ExactSizeIterator returned invalid size"); - } - - if location >= self.len() { - panic_len(self.len(), location); - } - let mut slice = slice.into_iter(); - - let slen = slice.len(); - match slen { - 0 => return, - 1 => { - self.insert(location, slice.next().unwrap()); - return - }, - _ => (), - }; - self.reserve(slice.len()); - - unsafe { - let this = self.as_mut_ptr().add(location); - let len = self.len(); - let rest = std::mem::size_of::() * (location..len).len(); - - libc::memmove(this.add(slen) as *mut libc::c_void, this as *mut libc::c_void, rest); - let mut sent=0; - match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let mut this = this; - for item in slice { - if sent >= slen { - inv_sz(); - } - - this.write(item); - this = this.add(1); - sent+=1; - } - if sent != slen { - inv_sz(); - } - })) { - Err(e) => { - // memory at (location+sent)..slen is now invalid, move the old one back before allowing unwind to contine - libc::memmove(this.add(sent) as *mut libc::c_void, this.add(slen) as *mut libc::c_void, rest); - self.set_len(len + sent); - std::panic::resume_unwind(e) - }, - _ => (), - } - self.set_len(len + sent); - } - } - #[inline] - fn insert_many>(&mut self, location: usize, slice: I) - { - let slice = slice.into_iter(); - match slice.size_hint() { - (0, Some(0)) | (0, None) => (), - (_, Some(bound)) | (bound, _) => self.reserve(bound), - }; - - self.splice(location..location, slice); - - //let splice = self.split_off(location); - //self.extend(slice.chain(splice.into_iter())); - - /* - // shift everything across, replacing with the new values - let splice: Vec<_> = self.splice(location.., slice).collect(); - // ^ -- this allocation bugs me, but we violate aliasing rules if we don't somehow collect it before adding it back in so... - // add tail back - self.extend(splice);*/ - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - #[test] - fn vec_insert_exact() - { - let mut vec = vec![0,1,2,8,9,10]; - vec.insert_exact(3, [3,4,5,6, 7].iter().copied()); - - assert_eq!(&vec[..], - &[0,1,2,3,4,5,6,7,8,9,10] - ); - } - #[test] - fn vec_insert_exact_nt() - { - macro_rules! string { - ($str:literal) => (String::from($str)); - } - let mut vec = vec![ - string!("Hello"), - string!("world"), - string!("foo"), - string!("uhh"), - ]; - let vec2 = vec![ - string!("Hello"), - string!("world"), - string!("hi"), - string!("hello"), - string!("foo"), - string!("uhh"), - ]; - - vec.insert_exact(2, vec![string!("hi"), string!("hello")]); - - assert_eq!(&vec[..], &vec2[..]); - } - - #[cfg(nightly)] - mod benchmatks - { - use super::super::*; - use test::{ - Bencher, black_box, - }; - #[cfg(not(feature="experimental_inserter"))] - #[bench] - fn move_exact(b: &mut Bencher) - { - let mut vec = vec![0,10,11,12]; - let span = [0,1,2,3]; - b.iter(|| { - black_box(vec.insert_exact(vec.len()/2, span.iter().copied())); - }); - } - #[bench] - fn move_via_splice(b: &mut Bencher) - { - let mut vec = vec![0,10,11,12]; - let span = [0,1,2,3]; - - b.iter(|| { - black_box(vec.insert_many(vec.len()/2, span.iter().copied())); - }); - } - - #[cfg(feature="experimental_inserter")] - #[bench] - fn move_via_unsafe(b: &mut Bencher) - { - let mut vec = vec![0,10,11,12]; - let span = [0,1,2,3]; - b.iter(|| { - black_box(vec.insert_exact(vec.len()/2, span.iter().copied())); - }); - } - } -} diff --git a/src/html/mod.rs b/src/html/mod.rs deleted file mode 100644 index 294cbf3..0000000 --- a/src/html/mod.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! HTML rendering -use super::*; -use std::{ - fmt::{ - self, - Display, - }, - io, -}; - -pub struct HtmlTokenStream(W); - -impl HtmlTokenStream -{ - fn push(&mut self, token: T) -> io::Result<()> - { - write!(&mut self.0, "{}", display_html(&token)) //TODO: How to do async version of this? - } -} - -/// Coerce a `DisplayHtml` value into an opaque implementor of `fmt::Display`. -#[inline] pub fn display_html<'a, T: DisplayHtml+?Sized>(from: &'a T) -> impl fmt::Display +'a -{ - struct Wrap<'a, T: DisplayHtml+?Sized>(&'a T); - - impl<'a,T> fmt::Display for Wrap<'a,T> - where T: DisplayHtml+?Sized - { - #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - DisplayHtml::fmt(self.0, f) - } - } - - Wrap(from) -} - -/// Coerse a `Display` value into a `DisplayHtml` by HTML-escaping its output. -/// -/// To output raw HTML, see `Safe`. -#[inline] pub fn escape_html<'a, T: Display+?Sized>(from: &'a T) -> impl DisplayHtml +'a -{ - struct Wrap<'a, T: Display+?Sized>(&'a T); - - struct FilterStream(T, F) - where F: FnMut(&mut T, char) -> fmt::Result; - - impl fmt::Write for FilterStream - where T: fmt::Write, - F: FnMut(&mut T, char) -> fmt::Result - { - fn write_str(&mut self, s: &str) -> fmt::Result - { - for c in s.chars() - { - self.1(&mut self.0, c)?; - } - Ok(()) - } - fn write_char(&mut self, c: char) -> fmt::Result - { - self.1(&mut self.0, c) - } - } - - impl<'a,T> DisplayHtml for Wrap<'a,T> - where T: Display +?Sized - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - use smallmap::Map; - lazy_static! { - static ref HTML_EQ_TABLE: Map = { - let mut map = Map::new(); - map.insert('&', "&"); - map.insert('<', "<"); - map.insert('>', ">"); - map.insert('"', """); - map - }; - } - let mut output = FilterStream(f, |output, c| { - output.write_str(match HTML_EQ_TABLE.get(&c) { - Some(s) => s, - None => { - return output.write_char(c); - }, - }) - }); - use fmt::Write; - write!(&mut output, "{}", self.0) - } - } - - Wrap(from) -} - -/// HTML-safe wrapper around -#[derive(Debug, PartialEq, Eq)] -pub struct Safe(T); - -impl Safe -{ - /// Create a new instance with this value - #[inline] pub fn new(value: T) -> Self - { - Self(value) - } - - /// Consume this instance into its inner value - pub fn into_inner(self) -> T - { - self.0 - } - - /// Gets a reference to the inner value - pub fn display(&self) -> &T - { - &self.0 - } -} - -impl From for Safe -{ - #[inline] fn from(from: T) -> Self - { - Self(from) - } -} - -/// A trait for displaying as html. -/// -/// Any type implementing `Display` will implement `DisplayHtml` by HTML-escaping the output from it's display formatter. -/// You can also use `Safe` to render as raw HTML. -pub trait DisplayHtml -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; - - #[inline] fn to_html(&self) -> String - { - display_html(self).to_string() - } -} -impl DisplayHtml for Safe -{ - #[inline] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result - { - self.0.fmt(fmt) - } - - #[inline] fn to_html(&self) -> String - { - self.0.to_string() - } -} - - -impl DisplayHtml for T -where T: Display -{ - #[inline] fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result - { - escape_html(self).fmt(fmt) - } -} diff --git a/src/identity.rs b/src/identity.rs deleted file mode 100644 index 2b6d3f5..0000000 --- a/src/identity.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Handles post and user identity. -use super::*; -use std::{ - fmt, -}; -use uuid::Uuid; - -/// A globally unique post identifier. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] -#[derive(Serialize, Deserialize)] -pub struct PostID(Uuid); - -impl PostID -{ - /// Generate a new `PostID`. - pub fn new() -> Self - { - Self(Uuid::new_v4()) - } -} - -impl fmt::Display for PostID -{ - #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - self.0.fmt(f) //TODO: Change to use kana-hash. - } -} - -/// A user's data, if set. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] -#[derive(Serialize, Deserialize)] -pub struct User -{ - pub name: Option, - pub email: Option, - pub tripcode: Option, -} - -impl User -{ - /// The name string of this instance, or the default name. - pub fn name_str(&self) -> &str - { - self.name.as_ref().map(|x| &x[..]).unwrap_or(&config::get().anon_name[..]) - } - - /// The email string of this instance, if it is set - pub fn email_str(&self) -> Option<&str> - { - self.email.as_ref().map(|x| &x[..]) - } - - // No str for tripcode because it's not just a string (yet) - - /// Anon with no detials. - pub const fn anon() -> Self - { - Self { - name: None, - email: None, - tripcode: None, - } - } -} - diff --git a/src/main.rs b/src/main.rs index a39c352..e7a11a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,92 +1,3 @@ -#![cfg_attr(nightly, feature(option_unwrap_none))] -#![cfg_attr(nightly, feature(never_type))] - -#![allow(dead_code)] - -#![cfg_attr(nightly, feature(test))] - -#[cfg(all(nightly, test))] extern crate test; - -#[macro_use] extern crate log; - -use async_trait::async_trait; -use serde::{ - Serialize, Deserialize, -}; -use color_eyre::{ - eyre, - Help, - SectionExt, -}; -use futures::{ - FutureExt as _, - prelude::*, -}; -use hex_literal::hex; -use lazy_static::lazy_static; - -macro_rules! cfg_debug { - (if {$($if:tt)*} else {$($else:tt)*}) => { - { - #[cfg(debug_assertions)] { - $($if)* - } - #[cfg(not(debug_assertions))] { - $($else)* - } - } - }; - (if $if:expr) => { - { - #[cfg(debug_assertions)] $if - } - }; - (else $else:expr) => { - { - #[cfg(not(debug_assertions))] $else - } - }; -} - - -mod ext; -use ext::*; -mod bytes; -mod suspend; - -mod regex; -mod cache; - -mod config; -mod tripcode; -mod identity; -mod post; -mod state; - -mod html; -mod web; - -#[tokio::main] -async fn main() -> Result<(), eyre::Report>{ - color_eyre::install()?; - pretty_env_logger::init(); - - trace!("Setting default config"); - - config::set(Default::default()); - - web::serve(Default::default()).await?; - - info!("Server shutdown gracefully"); - /* - let mut vec = vec![vec![1, 0, 0], - vec![0, 0, 1]]; - let span = vec![vec![0, 1, 0], - vec![1, 0, 1], - vec![0, 1, 0]]; - - for _ in 0..10000 { - vec.insert_exact(1, span.iter().cloned()); -}*/ - Ok(()) +fn main() { + println!("Hello, world!"); } diff --git a/src/post/mod.rs b/src/post/mod.rs deleted file mode 100644 index 2a92b5e..0000000 --- a/src/post/mod.rs +++ /dev/null @@ -1,156 +0,0 @@ -//! Structure for updating posts in-place -use super::*; -use std::{ - fmt, - hash::{ - Hash,Hasher, - }, -}; -use chrono::prelude::*; - -/// Represents all valid timestamps for a post. -/// -/// Usually in UTC, pls keep it in Utc... -#[derive(Debug, Clone, PartialEq, Eq)] -#[derive(Serialize, Deserialize)] -pub struct PostTimestamp -{ - pub opened: DateTime, - pub closed: Option>, - pub last_edit: DateTime, -} - -impl PostTimestamp -{ - /// Create a new timestamp for a new post - pub fn new() -> Self - { - let now = Utc::now(); - Self { - opened: now.clone(), - closed: None, - last_edit: now, - } - } -} - -impl Hash for PostTimestamp { - fn hash(&self, state: &mut H) { - self.opened.hash(state); - self.closed.hash(state); - self.last_edit.hash(state); - } -} - -impl fmt::Display for PostTimestamp -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - writeln!(f, " Opened - {}", self.opened)?; - writeln!(f, " Edited - {}", self.last_edit)?; - write!(f, " Closed - ")?; - if let Some(closed) = &self.closed { - writeln!(f, "{}", closed)?; - } else { - writeln!(f, "Stil open")?; - } - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -/// A closed and finished post. The inverse of `Imouto`. -pub struct Static -{ - id: identity::PostID, - - user: identity::User, - - title: Option, - karada: String, - - timestamp: PostTimestamp, - - /// Hash of the rest of the post data. . . . - hash: crypto::sha256::Sha256Hash, -} - -impl Static -{ - /// Compute the hash for this instance - pub fn into_hashed(mut self) -> Self - { - self.hash = Default::default(); - let bytes = serde_cbor::to_vec(&self).expect("Failed to serialise static post to CBOR"); - Self { - hash: crypto::sha256::compute_slice(&bytes), - ..self - } - } - - /// Validate the internal hash of this instance - pub fn validate_hash(&self) -> bool - { - self.clone().into_hashed().hash == self.hash - } -} - -use suspend::{ - Suspendable, - SuspendStream, -}; - -#[async_trait] -impl Suspendable for Static -{ - async fn suspend(self, into: &mut S) -> Result<(), suspend::Error> - { - let mut output = suspend::Object::new(); - output.insert("post-static", self); - into.set_object(output).await - } - async fn load(from: &mut S) -> Result - { - let mut input = from.get_object().await?.ok_or(suspend::Error::BadObject)?; - input.try_get("post-static").ok_or(suspend::Error::BadObject) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - #[tokio::test] - async fn static_post_ser() - { - let mut output = suspend::MemorySuspendStream::new(); - let post1 = Static { - id: identity::PostID::new(), - user: Default::default(), - title: None, - karada: "hello world".to_owned(), - timestamp: PostTimestamp::new(), - hash: Default::default(), - }.into_hashed(); - - let post1c = post1.clone(); - assert!(post1.validate_hash()); - post1.suspend(&mut output).await.expect("Suspend failed"); - - let buffer = output.buffer().clone(); - let post2 = Static::load(&mut output).await.expect("Suspend load failed"); - - assert_eq!(post1c, post2); - assert!(post1c.validate_hash()); - assert!(post2.validate_hash()); - - let buffer2 = suspend::oneshot(post2.clone()).await.expect("Oneshot failed"); - - assert_eq!(&buffer2[..], &buffer[..]); - - let post3: Static = suspend::single(buffer2).await.expect("Single failed"); - - assert!(post3.validate_hash()); - assert_eq!(post3, post2); - } -} diff --git a/src/regex.rs b/src/regex.rs deleted file mode 100644 index bb52a5f..0000000 --- a/src/regex.rs +++ /dev/null @@ -1,127 +0,0 @@ -//! PCRE -use super::*; -use pcre::{ - Pcre, -}; -use std::{ - sync::{ - Mutex, - }, - error, - fmt, -}; - -#[derive(Debug)] -pub struct Regex(Mutex, String); - -/// A regex error -#[derive(Debug)] -pub struct Error(pcre::CompilationError); - -impl error::Error for Error{} - -impl fmt::Display for Error -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f,"regex failed to compile: ")?; - self.0.fmt(f) - } -} - -impl From for Error -{ - #[inline] fn from(from: pcre::CompilationError) -> Self - { - Self(from) - } -} - -pub struct Iter<'a>(Option>, usize); - -impl<'a> Iterator for Iter<'a> -{ - type Item = &'a str; - fn next(&mut self) -> Option { - if let Some(m) = &mut self.0 { - if self.1 >= m.string_count() { - None - } else { - let string = m.group(self.1); - self.1 +=1; - Some(string) - } - } else { - None - } - } - - #[inline] fn size_hint(&self) -> (usize, Option) { - (self.len(), Some(self.len())) - } -} - -impl<'a> std::iter::FusedIterator for Iter<'a>{} -impl<'a> ExactSizeIterator for Iter<'a> -{ - fn len(&self) -> usize - { - match &self.0 { - Some(m) => m.string_count(), - None => 0, - } - } -} - -impl Regex -{ - /// Create a new regular expression from a string - pub fn new(from: impl AsRef, opt: I) -> Result - where I: IntoIterator - { - let string = from.as_ref(); - Ok(Self(Mutex::new(Pcre::compile_with_options(string, &opt.into_iter().collect())?), string.to_owned())) - } - - /// Test against string - pub fn test(&self, string: impl AsRef) -> bool - { - let mut regex = self.0.lock().unwrap(); - regex.exec(string.as_ref()).is_some() - } - - /// Get the groups of a match against string - pub fn exec_ref<'a>(&mut self, string: &'a (impl AsRef + ?Sized)) -> Iter<'a> - { - let regex = self.0.get_mut().unwrap(); - Iter(regex.exec(string.as_ref()), 0) - } - - /// Get the groups as an owned string vector from map against string - pub fn exec(&self, string: impl AsRef) -> Vec - { - let mut regex = self.0.lock().unwrap(); - Iter(regex.exec(string.as_ref()), 0).map(std::borrow::ToOwned::to_owned).collect() - } - - /// Get the string used to create this regex - #[inline] pub fn as_str(&self) -> &str{ - &self.1[..] - } -} - -impl From for Pcre -{ - #[inline] fn from(from: Regex) -> Self - { - from.0.into_inner().unwrap() - } -} - -impl fmt::Display for Regex -{ - #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "{}", self.1) - } -} diff --git a/src/state/global.rs b/src/state/global.rs deleted file mode 100644 index e119b35..0000000 --- a/src/state/global.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Container state for all posts -use super::*; - -/// Contains all posts in an instance, open or closed. -pub struct Oneesan -{ - -} diff --git a/src/state/local/delta.rs b/src/state/local/delta.rs deleted file mode 100644 index dd5e737..0000000 --- a/src/state/local/delta.rs +++ /dev/null @@ -1,255 +0,0 @@ -//! Deltas and applying them -use super::*; -use difference::{ - Changeset, - Difference, -}; - -const MAX_SINGLE_DELTA_SIZE: usize = 14; -const DELTA_BREAK: &str = ""; - -/// Infer all deltas needed to be sequentially applied to `orig` to transform it to `new`, return the number inserted into `output`. -pub fn infer_deltas + ?Sized>(output: &mut T, orig: &str, new: &str) -> usize -{ - let set = Changeset::new(orig, new, DELTA_BREAK); - - let mut done=0; - let mut position =0; - for diff in set.diffs.into_iter() { - match diff { - Difference::Same(string) => { - position += string.len(); - }, - Difference::Rem(string) => { - output.push_back(Delta { - location: position, - kind: DeltaKind::RemoveAhead{span_len: string.len()}, - }); - done+=1; - }, - Difference::Add(string) => { - let mut passer = BackInsertPass::new(|(span, span_len)| { - output.push_back(Delta { - location: position, - kind: DeltaKind::Insert { - span, span_len, - }, - }); - position+= usize::from(span_len); - done+=1; - }); - delta_span_many(&mut passer, string.chars()); - }, - } - } - done -} - -/// Create a delta span from an input iterator. -/// -/// This function can take no more than `min(255, MAX_SINGLE_DELTA_SIZE)` chars from the input. The number of chars inserted is also returned as `u8`. -pub(super) fn delta_span(from: I) -> ([char; MAX_SINGLE_DELTA_SIZE], u8) -where I: IntoIterator -{ - let mut output: [char; MAX_SINGLE_DELTA_SIZE] = Default::default(); - let mut sz: u8 = 0; - - for (d, s) in output.iter_mut().zip(from.into_iter().take(usize::from(u8::MAX))) - { - *d = s; - sz += 1; - } - - (output, sz) -} - -/// Create as many delta spans needed from an input iterator. -/// -/// This function can take as many inputs as needed, and outputs the needed amount of spans into `into`, and then returns the number added. -pub(super) fn delta_span_many + ?Sized, I>(into: &mut T, from: I) -> usize -where I: IntoIterator -{ - let mut iter = from.into_iter(); - let mut added=0; - loop { - match delta_span(&mut iter) { - (_, 0) => break, - other => into.push_back(other), - } - added+=1; - } - added -} - -/// Information about the delta to be applied in `Delta`. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] -pub enum DeltaKind -{ - /// Append to the end of body. Equivilant to `Insert` with a location at `karada.scape.len()` (the end of the buffer). - Append{ - span: [char; MAX_SINGLE_DELTA_SIZE], - span_len: u8, - }, - /// Insert `span_len` chars from `span` into body starting *at* `location` and moving ahead - Insert{ - span: [char; MAX_SINGLE_DELTA_SIZE], - span_len: u8, - }, - /// Remove `span_len` chars from `location`. - RemoveAhead{ - span_len: usize, - }, - /// Remove `span_len` chars up to but not including `location`. - RemoveBehind{ - span_len: usize, - }, - /// Remove everything from `location` to the end. - Truncate, - /// Remove everything from 0 to `location`. - Shift, - /// Remove char at `location` - RemoveSingle, - /// Remove entire post body - Clear, -} - -/// A delta to apply to `Karada`. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] -pub struct Delta -{ - /// Location to insert into. This is the INclusive range of: 0..=(karada.scape.len()). - /// - /// Insertions off the end of the buffer are to be appened instead. - location: usize, - /// The kind of delta to insert - kind: DeltaKind, -} - -/// Static assertion: `MAX_SINGLE_DELTA_SIZE` can fit into `u8`. -const _: [u8;(MAX_SINGLE_DELTA_SIZE < (!0u8 as usize)) as usize] = [0]; - -impl Delta -{ - pub fn insert(&self, inserter: &mut MessageSpan) - { - match self.kind { - DeltaKind::Append{span, span_len} => { - inserter.extend_from_slice(&span[..usize::from(span_len)]); - }, - DeltaKind::Insert{span, span_len} => { - let span = &span[..usize::from(span_len)]; - if self.location == inserter.len() { - inserter.extend_from_slice(span); - } else if span.len() == 1 { - inserter.insert(self.location, span[0]); - } else if span.len() > 1 { - inserter.insert_exact(self.location, span.iter().copied()); - } - }, - DeltaKind::RemoveAhead{span_len} => { - inserter.drain(self.location..(self.location+span_len)); - }, - DeltaKind::RemoveBehind{span_len} => { - let span_st = self.location.checked_sub(span_len).unwrap_or(0); - inserter.drain(span_st..self.location); - }, - DeltaKind::RemoveSingle => { - inserter.remove(self.location); - }, - DeltaKind::Clear => inserter.clear(), - DeltaKind::Truncate => inserter.truncate(self.location), - DeltaKind::Shift => ((),inserter.drain(..self.location)).0, - } - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - - #[test] - fn infer_and_insert() - { - let orig = "the quick brown fox jumped over the lazy dog !!!!"; - let new = "the quick brown dog jumped over the lazy fox twice"; - - let mut deltas = Vec::new(); - infer_deltas(&mut deltas, orig, new); - - println!("{:#?}", deltas); - let output: String = { - let mut scape: Vec<_> = orig.chars().collect(); - for delta in deltas.into_iter() { - delta.insert(&mut scape); - } - scape.into_iter().collect() - }; - - assert_eq!(&output[..], &new[..]); - } - - macro_rules! insert { - ($expects:literal; $start:literal, $ins:literal, $where:expr) => { - { - - let mut message: Vec = $start.chars().collect(); - - let delta = { - let (span, span_len) = delta_span($ins.chars()); - Delta { - location: $where, - kind: DeltaKind::Insert{span, span_len}, - } - }; - - println!("from: {:?}", message); - println!("delta: {:?}", delta); - delta.insert(&mut message); - - assert_eq!(&message.into_iter().collect::()[..], $expects); - } - }; - } - - #[test] - fn insert_body() - { - insert!("123456789"; "126789", "345", 2); - } - #[test] - fn insert_end() - { - insert!("123456789"; "1289", "34567", 2); - } - #[test] - fn insert_end_rev() - { - insert!("123456789"; "1234569", "78", 6); - } - #[test] - fn insert_begin_rev() - { - insert!("123456789"; "1456789", "23", 1); - } - #[test] - fn insert_begin() - { - insert!("123456789"; "789", "123456", 0); - } - #[test] - fn insert_end_f() - { - insert!("123456789"; "123", "456789", 3); - } - #[test] - fn insert_end_f_rev() - { - insert!("123456789"; "1234567", "89", 7); - } - #[test] - fn insert_single() - { - insert!("123456789"; "12346789", "5",4); - } -} diff --git a/src/state/local/error.rs b/src/state/local/error.rs deleted file mode 100644 index 90d41c3..0000000 --- a/src/state/local/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Local state change error -use super::*; -use std::{ - error, - fmt, -}; - -/// Local state updating errors -#[derive(Debug)] -#[non_exhaustive] -pub enum Error { - BroadcastUpdate, - Unknown, -} -impl error::Error for Error{} -impl fmt::Display for Error -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - match self { - Self::BroadcastUpdate => write!(f, "failed to broadcast state body update"), - _ => write!(f, "unknown error"), - } - } -} - diff --git a/src/state/local/host.rs b/src/state/local/host.rs deleted file mode 100644 index 8b1db46..0000000 --- a/src/state/local/host.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Hosts `Imouto`'s `Kokoro`. - -use super::*; -use std::{ - pin::Pin, - task::{ - Poll, - Context, - }, - mem, -}; -use pin_project::{ - pin_project, -}; -use futures::{ - future::Future, -}; -use tokio::{ - task, - sync::{ - oneshot, - mpsc, - }, -}; - -#[derive(Debug)] -pub enum Worker -{ - Attached(task::JoinHandle>), - /// Worker has not been attached yet - Suspended(Kokoro), - /// Worker filed to spawn, - Crashed, -} - -/// Host this `Kokoro` -async fn work(mut kokoro: Kokoro, mut recv: mpsc::Receiver>) -> Result<(), eyre::Report> -{ - while let Some(new) = recv.recv().await { - kokoro.apply(new).await?; - } - Ok(()) -} - -impl Worker -{ - /// Host this suspended state worker with a channel to receive updates from. - /// - /// # Panics - /// If we are not in the `Suspended` state. - pub fn host(&mut self, recv: mpsc::Receiver>) -> WorkerHandle - { - match mem::replace(self, Self::Crashed) { - Self::Suspended(kokoro) => { - let (tx, rx) = oneshot::channel(); - *self = Self::Attached(task::spawn(async move { - let vl = work(kokoro, recv).await; - tx.send(()).unwrap(); - vl - })); - WorkerHandle(rx) - }, - _ => panic!("Attempted to host non-suspended worker"), - } - } -} - -/// A handle on a spawned worker -#[pin_project] -pub struct WorkerHandle(#[pin] oneshot::Receiver<()>); - -impl Future for WorkerHandle -{ - type Output = (); - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.project(); - this.0.poll(cx).map(|x| x.unwrap()) - } -} diff --git a/src/state/local/karada.rs b/src/state/local/karada.rs deleted file mode 100644 index d500352..0000000 --- a/src/state/local/karada.rs +++ /dev/null @@ -1,101 +0,0 @@ -//! Mutating post body -use super::*; - -/// A message that can be mutated by deltas. -pub type MessageSpan = Vec; - -/// Contains post deltas and an intermediate representation of the still-open post body. -/// Created and modified with `Kokoro` worker instances. -/// -/// This should not be created by itself, instead `Kokoro` should create instances of this, so that it can retain the `watch::Sender` and other such things. -#[derive(Debug)] -pub struct Karada -{ - /// The post body so far as a vector of `char`s. - pub(super) scape: Arc>, - /// All applied deltas so far. Last applied one is at the end. - pub(super) deltas: Arc>>, - - /// the latest render of the whole body string. Updated whenever a delta(s) are applied atomically. - pub(super) current_body: watch::Receiver, -} - -impl Karada -{ - /// Clone the body string - pub fn body(&self) -> String - { - self.current_body.borrow().to_owned() - } - - /// Create the deltas required to atomically transform current body into `new`. - /// - /// Return the number of deltas added to `output`. - pub fn create_body_deltas + ?Sized, U: AsRef>(&self, output: &mut T, new: U) -> usize - { - let body = self.body(); - let new = new.as_ref(); - delta::infer_deltas(output, &body[..], new) - } - - /// Consume this instance into a suspension - /// - /// This will only acquire locks if needed, but since they might be needed, it must be awaited in case of `Kokoro` instances potentially owning the data. - pub async fn into_suspended(self) -> Suspension - { - let scape: String = { - let scape = self.scape; - match Arc::try_unwrap(scape) { //try to unwrap if possible, to avoid acquiring useless lock - Ok(scape) => scape.into_inner().into_iter().collect(), - Err(scape) => scape.read().await.iter().collect(), - } - }; - let deltas: Vec = { - let deltas = self.deltas; - match Arc::try_unwrap(deltas) { - Ok(deltas) => deltas.into_inner(), - Err(deltas) => deltas.read().await.clone(), - } - }; - - Suspension{scape,deltas} - } - - pub(super) fn from_suspended(susp: Suspension, current_body: watch::Receiver) -> Self - { - Self { - scape: Arc::new(RwLock::new(susp.scape.chars().collect())), - deltas: Arc::new(RwLock::new(susp.deltas)), - current_body, - } - } -} - -/// Suspension of [`Karada`](Karada). -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Suspension -{ - pub(super) scape: String, - pub(super) deltas: Vec, -} - -use suspend::{ - Suspendable, - SuspendStream, -}; - -#[async_trait] -impl Suspendable for Suspension -{ - async fn suspend(self, into: &mut S) -> Result<(), suspend::Error> - { - let mut output = suspend::Object::new(); - output.insert("post-dynamic", self); - into.set_object(output).await - } - async fn load(from: &mut S) -> Result - { - let mut input = from.get_object().await?.ok_or(suspend::Error::BadObject)?; - input.try_get("post-dynamic").ok_or(suspend::Error::BadObject) - } -} diff --git a/src/state/local/mod.rs b/src/state/local/mod.rs deleted file mode 100644 index df42583..0000000 --- a/src/state/local/mod.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! Handles updating posts -use super::*; -use std::{ - sync::Arc, -}; -use tokio::{ - sync::{ - RwLock, - watch, - }, -}; - -mod karada; -pub use karada::*; - -mod delta; -pub use delta::*; - -mod work; -pub use work::*; - -//mod host; -//pub use host::*; - -mod error; - -pub use error::Error as LocalError; - -/// An open, as yet unfinied post -#[derive(Debug)] -pub struct Imouto -{ - id: identity::PostID, - - user: identity::User, - - title: Option, - - karada: Karada, - worker: Kokoro, - - timestamp: post::PostTimestamp, //Note that `closed` should always be `None` in `Imouto`. We use this for post lifetimes and such -} - -use suspend::{ - Suspendable, - SuspendStream, -}; - -#[async_trait] -impl Suspendable for Imouto -{ - async fn suspend(self, into: &mut S) -> Result<(), suspend::Error> - { - let mut output = suspend::Object::new(); - output.insert("id", self.id); - output.insert("user", self.user); - output.insert("title", self.title); - output.insert("body", self.worker.into_suspended().await); // consume worker if possible - //output.insert("hash", self.hash); - output.insert("timestamp", self.timestamp); - into.set_object(output).await - } - async fn load(from: &mut S) -> Result - { - let mut input = from.get_object().await?.ok_or(suspend::Error::BadObject)?; - macro_rules! get { - ($name:literal) => { - input.try_get($name).ok_or_else(|| suspend::Error::MissingObject(std::borrow::Cow::Borrowed($name)))? - }; - } - let id = get!("id"); - let user = get!("user"); - let title = get!("title"); - let body = get!("body"); - //let hash = get!("hash"); - let timestamp = get!("timestamp"); - - let (karada, worker) = { - let mut kokoro = Kokoro::from_suspended(body); - (kokoro.spawn().unwrap(), kokoro) - }; - Ok(Self { - id, - user, - title, - karada, - worker, - //hash, - timestamp, - }) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - #[tokio::test] - async fn basic_ser() - { - let mut output = suspend::MemorySuspendStream::new(); - let mut lolis = std::iter::repeat_with(|| { - let (karada, kokoro) = { - let mut kokoro = Kokoro::new(); - (kokoro.spawn().unwrap(), kokoro) - }; - Imouto { - id: identity::PostID::new(), - user: Default::default(), - title: None, - - karada, - worker: kokoro, - - timestamp: post::PostTimestamp::new() - } - }); - let imouto = lolis.next().unwrap(); - imouto.suspend(&mut output).await.expect("Suspension failed"); - - let imouto2 = lolis.next().unwrap(); - - let imouto3 = Imouto::load(&mut output).await.expect("Load failed"); - - assert_eq!(imouto2.karada.body(), imouto3.karada.body()); - } -} diff --git a/src/state/local/work.rs b/src/state/local/work.rs deleted file mode 100644 index 82c2a3d..0000000 --- a/src/state/local/work.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! Worker that mutates `Kokoro`. -use super::*; -use tokio::{ - sync::{ - watch, - oneshot, - }, -}; - -/// Handles working on `Karada` instances. -#[derive(Debug)] -pub struct Kokoro -{ - scape: Arc>, - deltas: Arc>>, - update_body: watch::Sender, - - body_recv: Option>, -} - -impl Kokoro -{ - /// Create a new instance. This instance can spawn a `Karada` instance. - pub fn new() -> Self - { - let (tx, rx) = watch::channel(String::new()); - Self { - scape: Arc::new(RwLock::new(MessageSpan::new())), - deltas: Arc::new(RwLock::new(Vec::new())), - - update_body: tx, - body_recv: Some(rx), - } - } - - /// Create a new worker instance from a suspension of `Karada`. - pub fn from_suspended(susp: Suspension) -> Self - { - let span = susp.scape.chars().collect(); - let (tx, rx) = watch::channel(susp.scape); - Self { - scape: Arc::new(RwLock::new(span)), - deltas: Arc::new(RwLock::new(susp.deltas)), - - update_body: tx, - body_recv: Some(rx), - } - } - - /// Consume this instance into a suspension - /// - /// This will only acquire locks if needed, but since they might be needed, it must be awaited in case of `Kokoro` instances potentially owning the data. - pub async fn into_suspended(self) -> Suspension - { - - let scape: String = { - let scape = self.scape; - match Arc::try_unwrap(scape) { //try to unwrap if possible, to avoid acquiring useless lock - Ok(scape) => scape.into_inner().into_iter().collect(), - Err(scape) => scape.read().await.iter().collect(), - } - }; - let deltas: Vec = { - let deltas = self.deltas; - match Arc::try_unwrap(deltas) { - Ok(deltas) => deltas.into_inner(), - Err(deltas) => deltas.read().await.clone(), - } - }; - - Suspension{scape,deltas} - } - - /// Spawn one `Karada` instance. If this has already been called, it returns `None`. - pub fn spawn(&mut self) -> Option - { - self.body_recv.take() - .map(|current_body| { - Karada { - scape: Arc::clone(&self.scape), - deltas: Arc::clone(&self.deltas), - - current_body, - } - }) - } - - /// Spawn a clone `Karada` into a new instance. This function can be called many times to yield `Karada` instances that are all identical and controlled by this instance. - /// - /// # Panics - /// If `spawn` was previously called. - pub fn spawn_clone(&self) -> Karada - { - Karada { - scape: Arc::clone(&self.scape), - deltas: Arc::clone(&self.deltas), - current_body: self.body_recv.as_ref().unwrap().clone(), - } - } - - /// Apply a delta to this instance. - pub async fn apply>(&mut self, delta: I) -> Result<(), error::Error> - { - let (mut scape, mut deltas) = tokio::join!{ - self.scape.write(), - self.deltas.write(), - }; - for delta in delta.into_iter() { - // Only start mutating now that both locks are writable. Is this needed, or can we do the mutation concurrently? - delta.insert(scape.as_mut()); - deltas.push(delta); - } - - self.update_body.broadcast(scape.iter().collect()).map_err(|_| error::Error::BroadcastUpdate) - } -} diff --git a/src/state/mod.rs b/src/state/mod.rs deleted file mode 100644 index e2216e6..0000000 --- a/src/state/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! Structures for handling global and local post state. -use super::*; - -mod global; -pub use global::*; - -mod local; -pub use local::*; - -#[derive(Debug)] -/// An open or closed post -pub enum Post -{ - Open(Imouto), - Closed(post::Static), -} - -impl Post -{ - /// Is this post open - #[inline] pub fn is_open(&self) -> bool - { - if let Self::Open(_) = self { - true - } else { - false - } - } -} diff --git a/src/suspend.rs b/src/suspend.rs deleted file mode 100644 index 2bd7df2..0000000 --- a/src/suspend.rs +++ /dev/null @@ -1,533 +0,0 @@ -//! Handles suspending and reloading posts -use super::*; -use std::{ - marker::{ - PhantomData, - Unpin, - Send, - Sync, - }, - io, - collections::HashMap, - ops::Range, - borrow::{ - Cow, - Borrow, - }, - error, - fmt, -}; -use tokio::{ - prelude::*, - io::{ - AsyncRead, - AsyncWrite, - }, -}; - -/// Represents an opaque bytes stream of serialised data to insert into `SuspendStream`. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Object -{ - data: Vec, - data_instances: HashMap, Range>, -} - -fn calc_len(from: I) -> U -where I: IntoIterator, - T: Borrow>, - U: std::cmp::Ord + Default + Copy, -{ - let mut max = Default::default(); - - for i in from.into_iter() - { - let i = i.borrow().end; - if i > max { - max = i - } - } - max -} - -impl Object -{ - - /// Create a new empty `Object`. - #[inline] pub fn new() -> Self - { - Self{data: Vec::new(), data_instances: HashMap::new()} - } - - /// Are the internal mappings of this object valid? - pub fn validate(&self) -> bool - { - let len = self.data.len(); - for (_, range) in self.data_instances.iter() { - if range.end > len {//range.start + range.end > len { - return false; - } - } - true - } - - /// Try to get a value of type `T` from `name`. - pub fn get<'a, T>(&'a mut self, name: impl Borrow) -> Option - where T: Deserialize<'a> - { - if let Some(bytes) = self.get_bytes(name) { - serde_cbor::from_slice(&bytes[..]).expect("Failed to deserialize CBOR value") - } else { - None - } - } - - /// Try to get a value of type `T` from `name`. - pub fn try_get<'a, T>(&'a mut self, name: impl Borrow) -> Option - where T: Deserialize<'a> - { - if let Some(bytes) = self.get_bytes(name) { - serde_cbor::from_slice(&bytes[..]).ok() - } else { - None - } - } - - - /// Serialize and insert `value` into the stream with `name`. - pub fn insert(&mut self, name: impl Into>, value: T) - where T: Serialize - { - let len = self.data.len(); - match serde_cbor::to_writer(&mut self.data, &value) { - Ok(()) => { - let nlen = self.data.len(); - self.data_instances.insert(name.into(), len..nlen).unwrap_none(); - }, - Err(err) => { - self.data.resize(len, 0); //Roll back result - panic!("Failed inserting CBOR object: {}", err) //TODO: Return Err instead of panic - }, - } - } - - /// Insert bytes directly with this name - pub fn insert_bytes(&mut self, name: impl Into>, bytes: impl AsRef<[u8]>) - { - let bytes= bytes.as_ref(); - let start = self.data.len(); - self.data.extend_from_slice(bytes); - let end = self.data.len(); - - self.data_instances.insert(name.into(), start..end).unwrap_none(); - } - - /// Insert a value's bytes directly with this name - pub unsafe fn insert_value_raw(&mut self, name: U, value: &T) - where T: ?Sized, - U: Into> - { - self.insert_bytes(name, bytes::refer(value)) - } - - /// Try to get the bytes specified by name - pub fn get_bytes(&self, name: impl Borrow) -> Option<&[u8]> - { - if let Some(range) = self.data_instances.get(name.borrow()) { - Some(&self.data[range.clone()]) - } else { - None - } - } - - /// Try to get the value spcified by name - /// - /// # Panics - /// If `T` cannot fit into the size of the range - pub unsafe fn get_value_raw(&self, name: impl Borrow) -> Option<&T> - { - self.get_bytes(name).map(|x| bytes::derefer(x)) - } - - /// Try to get the value specified by name. Will return `None` if `T` cannot fit in the returned bytes. - pub unsafe fn try_get_value_raw(&self, name: impl Borrow) -> Option<&T> - { - if let Some(bytes) = self.get_bytes(name) { - if bytes.len() >= std::mem::size_of::() { - Some(bytes::derefer(bytes)) - } else { - #[cfg(debug_assertions)] eprintln!("Warning! Likely data corruption as {} (size {}) cannot fit into {} bytes",std::any::type_name::(), std::mem::size_of::(), bytes.len()); - None - } - } else { - None - } - } - - /// Consume into the data - pub fn into_bytes(self) -> Box<[u8]> - { - let mut output = Vec::new(); //TOOO: Get cap - - debug_assert!(self.validate(), "passing invalid object to serialise"); - - macro_rules! bin { - ($bytes:expr) => { - { - let bytes = $bytes; - output.extend_from_slice(bytes.as_ref()); - } - }; - (usize $value:expr) => { - { - use std::convert::TryInto; - use byteorder::{ - WriteBytesExt, - LittleEndian, - }; - let val: u64 = $value.try_into().expect("Value could not fit into `u64`"); - WriteBytesExt::write_u64::(&mut output,val).expect("Failed to append `u64` to output buffer"); - - } - }; - } - - bin!(usize self.data_instances.len()); - for (name, &Range{start, end}) in self.data_instances.iter() { - let name = name.as_bytes(); - - bin!(usize name.len()); - bin!(name); - - bin!(usize start); - bin!(usize end); - } - - bin!(usize self.data.len()); //for additional checks - output.extend(self.data); - - output.into_boxed_slice() - } - - /// Read an object from a stream - pub async fn from_stream(input: &mut T) -> io::Result - where T: AsyncRead + Unpin + ?Sized - { - let mut ext_buf = Vec::new(); - - macro_rules! bin { - (usize) => { - { - use std::convert::TryFrom; - let value: u64 = input.read_u64().await?; - usize::try_from(value).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "u64 cannot fit in usize"))? - } - }; - ($size:expr) => { - { - let sz = $size; - ext_buf.resize(sz, 0); - assert_eq!(input.read_exact(&mut ext_buf[..sz]).await?, ext_buf.len()); - &ext_buf[..sz] - } - } - } - let entries = bin!(usize); - - let mut instances = HashMap::with_capacity(entries); - - for _i in 0..entries - { - let name_len = bin!(usize); - - let name_bytes = bin!(name_len); - let name_str = std::str::from_utf8(name_bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData,"item name was corrupted"))?; - - let start = bin!(usize); - let end = bin!(usize); - - instances.insert(Cow::Owned(name_str.to_owned()), start..end); - } - - let expected_len = bin!(usize); - if expected_len != calc_len(instances.iter().map(|(_, v)| v)) - { - return Err(io::Error::new(io::ErrorKind::InvalidData, "expected and read sizes differ")); - } - - let mut data = vec![0; expected_len]; - assert_eq!(input.read_exact(&mut data[..]).await?, expected_len); - - Ok(Self { - data, - data_instances: instances, - }) - } - - /// Write this instance into an async stream - pub async fn into_stream(&self, output: &mut T) -> io::Result - where T: AsyncWrite + Unpin + ?Sized - { - //eprintln!("{}: {:?}", self.data.len(), self); - debug_assert!(self.validate(), "passing invalid object to serialise"); - - let mut written=0usize; - macro_rules! bin { - ($bytes:expr) => { - { - let bytes = $bytes; - output.write_all(bytes).await?; - written+=bytes.len(); - } - }; - (usize $value:expr) => { - { - use std::convert::TryInto; - let val: u64 = $value.try_into().map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "size cannot fit in u64"))?; - output.write_u64(val).await?; - written += std::mem::size_of::(); - } - }; - } - - unsafe { - bin!(usize self.data_instances.len()); - for (name, &Range{start, end}) in self.data_instances.iter() { - let name = name.as_bytes(); - - bin!(usize name.len()); - bin!(name); - - bin!(usize start); - bin!(usize end); - } - } - - bin!(usize self.data.len()); //for additional checks - bin!(&self.data); - Ok(written) - } -} - -/// A suspend stream represents a stream of objects of _the same type_. Can be any number of them, but they all must be for the same type. -#[async_trait] -pub trait SuspendStream -{ - /// Write an object into the opaque stream. - async fn set_object(&mut self, obj: Object) -> Result<(), Error>; - /// Read an object from the opaque stream. - async fn get_object(&mut self) -> Result, Error>; -} - -/// An error that occoured in a suspend operation -#[derive(Debug)] -#[non_exhaustive] -pub enum Error { - BadObject, - MissingObject(Cow<'static, str>), - Corruption, - IO(io::Error), - - Other(eyre::Report), - Unknown, -} -impl error::Error for Error -{ - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - Some(match &self { - Self::IO(io) => io, - _ => return None, - }) - } -} -impl fmt::Display for Error -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - match self { - Self::BadObject => write!(f, "unexpected object in stream"), - Self::MissingObject(string) => write!(f, "missing object from stream: {}", string), - Self::Corruption => write!(f, "data stream corruption"), - Self::IO(_) => write!(f, "i/o error"), - Self::Other(report) => write!(f, "internal: {}", report), - _ => write!(f, "unknown error"), - } - } -} - -impl From for Error -{ - #[inline] fn from(from: io::Error) -> Self - { - Self::IO(from) - } -} - -impl From for Error -{ - fn from(from: eyre::Report) -> Self - { - Self::Other(from) - } -} - - -/// A suspendable type, that can save and reload its data atomically -#[async_trait] -pub trait Suspendable: Sized -{ - async fn suspend(self, into: &mut S) -> Result<(), Error>; - async fn load(from: &mut S) -> Result; -} - -/// An in-memory `SuspendStream`. -#[derive(Debug, Clone)] -pub struct MemorySuspendStream(Vec); - -impl MemorySuspendStream -{ - /// Create a new empty instance - pub fn new() -> Self - { - Self(Vec::new()) - } - - /// Create from a vector of bytes - pub fn from_bytes(from: impl Into>) -> Self - { - Self(from.into()) - } - - /// Create from a slice of bytes - pub fn from_slice(from: impl AsRef<[u8]>) -> Self - { - Self(Vec::from(from.as_ref())) - } - - /// Return the internal bytes - pub fn into_bytes(self) -> Vec - { - self.0 - } - - /// The internal buffer - pub fn buffer(&self) -> &Vec - { - &self.0 - } - - /// The internal buffer - pub fn buffer_mut(&mut self) -> &mut Vec - { - &mut self.0 - } - -} - -impl AsRef<[u8]> for MemorySuspendStream -{ - fn as_ref(&self) -> &[u8] - { - &self.0[..] - } -} - -impl AsMut<[u8]> for MemorySuspendStream -{ - fn as_mut(&mut self) -> &mut [u8] - { - &mut self.0[..] - } -} - -impl From> for MemorySuspendStream -{ - #[inline] fn from(from: Vec) -> Self - { - Self(from.into()) - } -} - -impl From> for MemorySuspendStream -{ - fn from(from: Box<[u8]>) -> Self - { - Self::from_bytes(from) - } -} - -impl From for Box<[u8]> -{ - fn from(from: MemorySuspendStream) -> Self - { - from.0.into() - } -} - -impl From for Vec -{ - #[inline] fn from(from: MemorySuspendStream) -> Self - { - from.0 - } -} - -#[async_trait] -impl SuspendStream for MemorySuspendStream -{ - async fn get_object(&mut self) -> Result, Error> { - if self.0.len() ==0 { - return Ok(None); - } - - let mut ptr = &self.0[..]; - let vl = Object::from_stream(&mut ptr).await?; - let diff = (ptr.as_ptr() as usize) - ((&self.0[..]).as_ptr() as usize); - self.0.drain(0..diff); - - Ok(Some(vl)) - } - async fn set_object(&mut self, obj: Object) -> Result<(), Error> { - obj.into_stream(&mut self.0).await?; - Ok(()) - } -} - -/// Suspend a single object to memory -pub async fn oneshot(value: T) -> Result, Error> -{ - let mut output = MemorySuspendStream::new(); - value.suspend(&mut output).await?; - Ok(output.into_bytes()) -} - -/// Load a single value from memory -pub async fn single(from: impl AsRef<[u8]>) -> Result -{ - struct BorrowedStream<'a>(&'a [u8]); - - #[async_trait] - impl<'a> SuspendStream for BorrowedStream<'a> - { - async fn get_object(&mut self) -> Result, Error> { - if self.0.len() ==0 { - return Ok(None); - } - - let mut ptr = &self.0[..]; - let vl = Object::from_stream(&mut ptr).await?; - let diff = (ptr.as_ptr() as usize) - ((&self.0[..]).as_ptr() as usize); - self.0 = &self.0[diff..]; - - Ok(Some(vl)) - } - async fn set_object(&mut self, _: Object) -> Result<(), Error> { - panic!("Cannot write to borrowed stream") - } - } - - let bytes = from.as_ref(); - let mut stream = BorrowedStream(bytes); - - T::load(&mut stream).await -} diff --git a/src/tripcode.rs b/src/tripcode.rs deleted file mode 100644 index 0a25488..0000000 --- a/src/tripcode.rs +++ /dev/null @@ -1,109 +0,0 @@ -//! Tripcode. TODO: Use kana-hash -use super::*; -use khash::{ - ctx::{ - self, - Algorithm, - }, - salt, -}; -use std::{ - fmt, - error, -}; - -#[derive(Debug)] -pub struct Error(khash::error::Error); - -impl From for Error -{ - #[inline] fn from(from: khash::error::Error) -> Self - { - Self(from) - } -} - -impl fmt::Display for Error -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "failed to compute tripcode") - } -} - - -impl error::Error for Error -{ - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - Some(&self.0) - } -} - -///A kana-hash or special tripcode -#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] -#[derive(Serialize, Deserialize)] -pub enum Tripcode -{ - /// A secure tripcode computed with the user set configured salt - Secure(String), - /// A normal tripcode computed with the default embedded salt - Normal(String), - /// A special tripcode with a pre-set string - Special(String), -} - -impl Tripcode -{ - /// Generate a new normal tripcode - pub fn new_normal(from: impl AsRef<[u8]>) -> Result - { - Ok(Self::Normal(khash::generate(&ctx::Context::new(Algorithm::Sha256Truncated, salt::Salt::internal()), from)?)) - } - /// Generate a new `secure' tripcode. - /// - /// # Panics - /// If global config has not been set yet. - pub fn new_secure(from: impl AsRef<[u8]>) -> Result - { - Ok(Self::Secure(khash::generate(&ctx::Context::new(Algorithm::Sha256Truncated, salt::Salt::fixed(config::get().tripcode_salt)), from)?)) - } - - /// Get the internal string representing the tripcode. - /// - /// # Notes - /// This does not include the prefixes. - pub fn as_str(&self) -> &str - { - match self { - Self::Secure(s) | Self::Normal(s) | Self::Special(s) => s.as_str() - } - } - - /// Consume the instance returning the inner string. - /// - /// # Notes - /// This does not include the prefixes. - pub fn into_inner(self) -> String - { - match self { - Self::Secure(s) | Self::Normal(s) | Self::Special(s) => s - } - } -} - -impl fmt::Display for Tripcode -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - match self { - Self::Secure(sec) => write!(f, "!!{}", sec), - Self::Normal(nor) => write!(f, "!{}", nor), - Self::Special(spec) => write!(f, "{}", spec), - } - } -} - - - - - diff --git a/src/web/error.rs b/src/web/error.rs deleted file mode 100644 index 21462b2..0000000 --- a/src/web/error.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Internal errors -use super::*; -use std::{ - fmt, - error, - net::SocketAddr, -}; - -#[derive(Debug)] -#[non_exhaustive] -pub enum Error { - Denied(SocketAddr, bool), - TimeoutReached, - NoResponse, - Unknown, -} - -#[derive(Debug)] -pub struct HandleError; - -impl Error -{ - /// Print this error as a warning - #[inline(never)] #[cold] pub fn warn(self) -> Self - { - warn!("{}", self); - self - } - - /// Print this error as info - #[inline(never)] #[cold] pub fn info(self) -> Self - { - info!("{}", self); - self - } -} - -impl error::Error for Error{} -impl error::Error for HandleError{} -impl fmt::Display for Error -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - match self { - Self::Denied(sock, true) => write!(f, "denied connection (explicit): {}", sock), - Self::Denied(sock, _) => write!(f, "denied connection (implicit): {}", sock), - Self::TimeoutReached => write!(f, "timeout reached"), - Self::NoResponse => write!(f, "no handler for this request"), - _ => write!(f, "unknown error"), - } - } -} - -impl fmt::Display for HandleError -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "handle response had already been sent or timed out by the time we tried to access it") - } -} - diff --git a/src/web/mod.rs b/src/web/mod.rs deleted file mode 100644 index b7d9015..0000000 --- a/src/web/mod.rs +++ /dev/null @@ -1,269 +0,0 @@ -//! Handle web serving and managing state of web clients -use super::*; -use std::{ - sync::{ - Arc, - Weak, - }, - marker::{ - Send, Sync, - }, - iter, -}; -use hyper::{ - service::{ - make_service_fn, - service_fn, - }, - server::{ - Server, - conn::AddrStream, - }, - Request, - Response, - Body, -}; -use futures::{ - TryStreamExt as _, -}; -use cidr::{ - Cidr, -}; -use tokio::{ - sync::{ - RwLock, - mpsc, - }, -}; - -pub mod error; -pub mod route; - -/// A unique ID generated each time a request is sent through router. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Nonce(uuid::Uuid); - -#[derive(Debug, Clone)] -pub struct Handle -{ - state: Arc, - nonce: Nonce, - req: Arc>, - /// We can let multiple router hooks mutate body if they desire. Such as adding headers, etc. - resp: Arc>>, -} - -impl Handle -{ - /// Attempt to upgrade the response handle into a potentially mutateable `Response`. - /// - /// Function fails if the reference count to the response has expired (i.e. the response has been sent or timed out already) - pub fn access_response(&self) -> Result>>, error::HandleError> - { - Ok(self.resp.clone()) - //self.resp.upgrade().ok_or(error::HandleError) - } - - /// Replace the response with a new one if possible. - /// - /// Fails if `access_response()` fails. - pub async fn set_response(&self, rsp: Response) -> Result, error::HandleError> - { - use std::ops::DerefMut; - match self.access_response() { - Ok(resp) => Ok(std::mem::replace(resp.write().await.deref_mut(), rsp)), - Err(err) => Err(err), - } - } -} - -/// Contains all web-server state -#[derive(Debug)] -pub struct State -{ - config: config::Config, - router: RwLock>, -} - -impl State -{ - /// Create a new state with this specific config instance. - /// - /// # Notes - /// You'll almost always want to use the *global* config instance, in which case use `default()` to create this. - pub fn new(config: config::Config) -> Self - { - Self{ - config, - router: RwLock::new(route::Router::new()), - } - } -} - -impl Default for State -{ - #[inline] - fn default() -> Self - { - Self::new(config::get().clone()) - } -} - -fn mask_contains(mask: &[cidr::IpCidr], value: &std::net::IpAddr) -> bool -{ - for mask in mask.iter() - { - if mask.contains(value) { - return true; - } - } - false -} - -fn handle_test(state: Arc) -> tokio::task::JoinHandle<()> -{ - tokio::task::spawn(async move { - let (hook, mut recv) = { - let mut router = state.router.write().await; - router.hook(None, route::PrefixRouter::new("/hello")) - }; - while let Some((uri, handle)) = recv.recv().await - { - match handle.set_response(Response::builder() - .status(200) - .body(format!("Hello world! You are at {}", uri).into()) - .unwrap()).await { - Ok(_) => (), - Err(e) => { - error!("{}", e); - break; - }, - } - } - { - let mut router = state.router.write().await; - router.unhook(iter::once(hook)); - } - }) -} - -async fn handle_conn(state: Arc, req: Request) -> Result, error::Error> -{ - let response = Arc::new(RwLock::new(Response::new(Body::empty()))); - - let nonce = Nonce(uuid::Uuid::new_v4()); - let req = Arc::new(req); - let resp_num = { - let resp = Arc::clone(&response); - async { - let mut route = state.router.write().await; - let handle = Handle { - state: state.clone(), - nonce, - req: Arc::clone(&req), - resp, - }; - match route.dispatch(req.method(), req.uri().path(), handle, state.config.req_timeout_local).await { - Ok(num) => { - num - }, - Err((num, _)) => { - num - }, - } - } - }; - tokio::pin!(resp_num); - - match match state.config.req_timeout_global { - Some(timeout) => tokio::time::timeout(timeout, resp_num).await, - None => Ok(resp_num.await), - } { - Ok(0) => { - // No handlers matched this - trace!(" x {}", req.uri().path()); - Ok(Response::builder() - .status(404) - .body("404 not found".into()) - .unwrap()) - }, - Ok(_) => { - let resp = { - let mut resp = response; - - loop { - match Arc::try_unwrap(resp) { - Err(e) => { - resp = e; - tokio::task::yield_now().await; - }, - Ok(n) => break n, - } - } - }; - Ok(resp.into_inner()) - }, - Err(_) => { - // Timeout reached - Err(error::Error::TimeoutReached.info()) - }, - } -} - -pub async fn serve(state: State) -> Result<(), eyre::Report> -{ - cfg_debug!(if { - if &state.config != config::get() { - panic!("Our config is not the same as global? This is unsound."); - } - } else { - - if &state.config != config::get() { - warn!("Our config is not the same as global? This is unsound."); - } - }); - let h = { - let state = Arc::new(state); - - let h = handle_test(state.clone()); - - let service = make_service_fn(|conn: &AddrStream| { - let state = Arc::clone(&state); - - let remote_addr = conn.remote_addr(); - let remote_ip = remote_addr.ip(); - let denied = mask_contains(&state.config.deny_mask[..], &remote_ip); - let allowed = mask_contains(&state.config.accept_mask[..], &remote_ip); - async move { - if denied { - Err(error::Error::Denied(remote_addr, true).warn()) - } else if allowed || state.config.accept_default { - trace!("Accepted conn: {}", remote_addr); - - Ok(service_fn(move |req: Request| { - handle_conn(Arc::clone(&state), req) - })) - } else { - Err(error::Error::Denied(remote_addr,false).info()) - } - } - }); - - let server = Server::bind(&state.config.listen).serve(service) - .with_graceful_shutdown(async { - tokio::signal::ctrl_c().await.expect("Failed to catch SIGINT"); - info!("Going down for shutdown now!"); - }); - - server.await?; - // remove all handles now - let mut wr= state.router.write().await; - wr.clear(); - - h - }; - trace!("server down"); - h.await?; - - Ok(()) -} diff --git a/src/web/route.rs b/src/web/route.rs deleted file mode 100644 index fc0d67b..0000000 --- a/src/web/route.rs +++ /dev/null @@ -1,254 +0,0 @@ -//! Basic router -use super::*; -use hyper::{ - Method, -}; -use std::{ - fmt, - marker::{ - Send, - Sync, - }, - iter, -}; -use tokio::{ - sync::{ - mpsc::{ - self, - error::SendTimeoutError, - }, - }, - time, -}; -use futures::{ - future::{ - self, - Future, - }, -}; -use generational_arena::{ - Index, - Arena, -}; - -pub trait UriRoute -{ - fn is_match(&self, uri: &str) -> bool; - #[inline] fn as_string(&self) -> &str - { - "" - } - - #[inline] fn type_name(&self) -> &str - { - std::any::type_name::() - } - - #[inline] fn mutate_uri(&self, uri: String) -> String - { - uri - } -} - -impl UriRoute for str -{ - #[inline] fn is_match(&self, uri: &str) -> bool { - self.eq(uri) - } - #[inline] fn as_string(&self) -> &str { - self - } -} - -impl> UriRoute for T -{ - #[inline] fn is_match(&self, uri: &str) -> bool { - self.as_ref().eq(uri) - } - #[inline] fn as_string(&self) -> &str { - self.as_ref() - } -} - -impl UriRoute for regex::Regex -{ - #[inline] fn is_match(&self, uri: &str) -> bool { - self.test(uri) - } - #[inline] fn as_string(&self) -> &str { - self.as_str() - } -} - -/// A router for all under a prefix -#[derive(Debug, Clone, PartialEq, Hash)] -pub struct PrefixRouter(String); - -impl PrefixRouter -{ - /// Create a new instance with this string - pub fn new(string: impl Into) -> Self - { - Self(string.into()) - } -} - -impl UriRoute for PrefixRouter -{ - #[inline] fn is_match(&self, uri: &str) -> bool { - uri.starts_with(self.0.as_str()) - } - #[inline] fn as_string(&self) -> &str { - self.0.as_str() - } - - fn mutate_uri(&self, mut uri: String) -> String { - uri.replace_range(..self.0.len(), ""); - uri - } -} - -impl fmt::Display for PrefixRouter -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "{}*", self.0) - } -} - - -/// Contains a routing table -#[derive(Debug)] -pub struct Router -{ - routes: Arena<(Option, OpaqueDebug>, mpsc::Sender<(String, T)>)>, -} - -impl fmt::Display for Router -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result - { - write!(f, "Router {{ routes: ")?; - for (i, (method, route, _)) in self.routes.iter() { - writeln!(f, "\t ({:?} => ({:?}, {} ({:?}))),", i, method, route.type_name(), route.as_string())?; - } - write!(f, "}}") - } -} - -impl Router -{ - /// Create an empty routing table - pub fn new() -> Self - { - Self { - routes: Arena::new(), - } - } - - /// Push a new route into the router. - /// - /// # Returns - /// The hook's new index, and the receiver that `dispatch()` sends to. - pub fn hook(&mut self, method: Option, uri: Uri) -> (Index, mpsc::Receiver<(String, T)>) - { - let (tx, rx) = mpsc::channel(config::get_or_default().dos_max); - (self.routes.insert((method, OpaqueDebug::new(Box::new(uri)), tx)), rx) - } - - /// Remove all hooks - pub fn clear(&mut self) - { - self.routes.clear(); - } - - /// Dispatch the URI location across this router, sending to all that match it. - /// - /// # Timeout - /// The timeout is waited on the *individual* dispatches. If you want a global timeout, please timeout the future returned by this function instead. - /// Timed-out dispatches are counted the same as sending errors. - /// - /// # Returns - /// When one or more dispatchers match but faile, `Err` is returned. Inside the `Err` tuple is the amount of successful dispatches, and also a vector containing the indecies of the failed hook sends. - pub async fn dispatch(&mut self, method: &Method, uri: impl AsRef, nonce: T, timeout: Option) -> Result)> - { - let string = uri.as_ref(); - let mut success=0usize; - let vec: Vec<_> = - future::join_all(self.routes.iter_mut() - .filter_map(|(i, (a_method, route, sender))| { - match a_method { - Some(x) if x != method => None, - _ => { - if route.is_match(string) { - trace!("{:?} `{}`: -> {}",i, route.as_string(), string); - let timeout = timeout.clone(); - let nonce= nonce.clone(); - macro_rules! send { - () => { - { - let string = route.mutate_uri(string.to_owned()); - match timeout { - None => sender.send((string, nonce)).await - .map_err(|e| SendTimeoutError::Closed(e.0)), - Some(time) => sender.send_timeout((string, nonce), time).await - } - } - } - }; - Some(async move { - match send!() { - Err(SendTimeoutError::Closed(er)) => { - error!("{:?}: Dispatch failed on hooked route for `{}`", i, er.0); - Err(i) - }, - Err(SendTimeoutError::Timeout(er)) => { - warn!("{:?}: Dispatch timed out on hooked route for `{}`", i, er.0); - Err(i) - }, - _ => Ok(()), - } - }) - } else { - None - } - }, - } - })).await.into_iter() - .filter_map(|res| { - if res.is_ok() { - success+=1; - } - res.err() - }).collect(); - if vec.len() > 0 { - Err((success, vec)) - } else { - Ok(success) - } - } - - /// Forcefully dispatch `uri` on hook `which`, regardless of method or URI matching. - /// - /// # Returns - /// If `which` is not contained within the table, immediately returns `None`, otherwise returns a future that completes when the dispatch is complete. - /// Note: This future must be `await`ed for the dispatch to happen. - pub fn dispatch_force(&mut self, which: Index, uri: String, nonce: T, timeout: Option) -> Option>> + '_> - { - self.routes.get_mut(which).map(move |(_,_,send)| { - match timeout { - Some(timeout) => send.send_timeout((uri, nonce), timeout).boxed(), - None => send.send((uri, nonce)).map(|res| res.map_err(|e| SendTimeoutError::Closed(e.0))).boxed(), - } - }) - } - - /// Attempt to unhook these hooks. If one or more of the provided indecies does not exist in the routing table, it is ignored. - pub fn unhook(&mut self, items: I) - where I: IntoIterator - { - for item in items.into_iter() { - self.routes.remove(item); - } - } -}