lota of progress

This commit is contained in:
Jakub Doka 2024-10-14 22:04:18 +02:00
parent dc2e0cc5b3
commit ea736d8824
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
11 changed files with 887 additions and 123 deletions

514
Cargo.lock generated
View file

@ -29,6 +29,15 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.18" version = "0.2.18"
@ -41,6 +50,12 @@ version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]] [[package]]
name = "argon2" name = "argon2"
version = "0.5.3" version = "0.5.3"
@ -64,12 +79,45 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.4.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "aws-lc-rs"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d"
dependencies = [
"aws-lc-sys",
"mirai-annotations",
"paste",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972"
dependencies = [
"bindgen",
"cc",
"cmake",
"dunce",
"fs_extra",
"libc",
"paste",
]
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.7.7" version = "0.7.7"
@ -98,7 +146,7 @@ dependencies = [
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper 1.0.1", "sync_wrapper 1.0.1",
"tokio", "tokio",
"tower", "tower 0.5.1",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing", "tracing",
@ -125,6 +173,30 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "axum-server"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56bac90848f6a9393ac03c63c640925c4b7c8ca21654de40d53f55964667c7d8"
dependencies = [
"arc-swap",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"pin-project-lite",
"rustls",
"rustls-pemfile",
"rustls-pki-types",
"tokio",
"tokio-rustls",
"tower 0.4.13",
"tower-service",
]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.74" version = "0.3.74"
@ -146,6 +218,29 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bindgen"
version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"itertools",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash 1.1.0",
"shlex",
"syn",
"which",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.6.0"
@ -191,15 +286,66 @@ version = "1.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
dependencies = [ dependencies = [
"jobserver",
"libc",
"shlex", "shlex",
] ]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "cmake"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
dependencies = [
"cc",
]
[[package]]
name = "const_format"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.14" version = "0.2.14"
@ -225,6 +371,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"argon2", "argon2",
"axum", "axum",
"axum-server",
"const_format",
"getrandom", "getrandom",
"hblang", "hblang",
"htmlm", "htmlm",
@ -256,12 +404,34 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys",
]
[[package]] [[package]]
name = "fallible-iterator" name = "fallible-iterator"
version = "0.2.0" version = "0.2.0"
@ -295,6 +465,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.31" version = "0.3.31"
@ -310,6 +486,12 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-sink"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.31" version = "0.3.31"
@ -366,6 +548,31 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http",
"indexmap 2.6.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -439,6 +646,15 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys",
]
[[package]] [[package]]
name = "htmlm" name = "htmlm"
version = "0.5.0" version = "0.5.0"
@ -509,6 +725,7 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
@ -562,12 +779,42 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.11" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jobserver"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "leb128" name = "leb128"
version = "0.2.5" version = "0.2.5"
@ -580,6 +827,16 @@ version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
version = "0.30.1" version = "0.30.1"
@ -591,6 +848,12 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.22" version = "0.4.22"
@ -624,6 +887,12 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.0" version = "0.8.0"
@ -645,6 +914,22 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "mirai-annotations"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -677,12 +962,38 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.14" version = "0.2.14"
@ -707,6 +1018,16 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "prettyplease"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
dependencies = [
"proc-macro2",
"syn",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.87" version = "1.0.87"
@ -743,10 +1064,54 @@ dependencies = [
"bumpalo", "bumpalo",
"hashbrown 0.14.5", "hashbrown 0.14.5",
"log", "log",
"rustc-hash", "rustc-hash 2.0.0",
"smallvec", "smallvec",
] ]
[[package]]
name = "regex"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "ring"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys",
]
[[package]] [[package]]
name = "rusqlite" name = "rusqlite"
version = "0.32.1" version = "0.32.1"
@ -767,12 +1132,72 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "2.0.0" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustix"
version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustls"
version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8"
dependencies = [
"aws-lc-rs",
"once_cell",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55"
[[package]]
name = "rustls-webpki"
version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"aws-lc-rs",
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.17" version = "1.0.17"
@ -851,6 +1276,15 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"
@ -867,6 +1301,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@ -928,6 +1368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes",
"libc", "libc",
"mio", "mio",
"pin-project-lite", "pin-project-lite",
@ -947,6 +1388,45 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "tokio-rustls"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [
"rustls",
"rustls-pki-types",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tower-layer",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "tower" name = "tower"
version = "0.5.1" version = "0.5.1"
@ -1007,6 +1487,18 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
@ -1101,6 +1593,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
@ -1201,3 +1705,9 @@ dependencies = [
"quote", "quote",
"syn", "syn",
] ]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

View file

@ -23,7 +23,7 @@ hbjit = { path = "jit" }
[profile.release] [profile.release]
lto = true lto = true
debug = true #debug = true
#strip = true #strip = true
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"

View file

@ -6,6 +6,8 @@ edition = "2021"
[dependencies] [dependencies]
argon2 = "0.5.3" argon2 = "0.5.3"
axum = "0.7.7" axum = "0.7.7"
axum-server = { version = "0.7.1", optional = true, features = ["rustls", "tls-rustls"] }
const_format = "0.2.33"
getrandom = "0.2.15" getrandom = "0.2.15"
hblang.workspace = true hblang.workspace = true
htmlm = "0.5.0" htmlm = "0.5.0"
@ -15,3 +17,7 @@ rusqlite = { version = "0.32.1", features = ["bundled"] }
serde = { version = "1.0.210", features = ["derive"] } serde = { version = "1.0.210", features = ["derive"] }
time = "0.3.36" time = "0.3.36"
tokio = { version = "1.40.0", features = ["rt"] } tokio = { version = "1.40.0", features = ["rt"] }
[features]
#default = ["tls"]
tls = ["dep:axum-server"]

View file

@ -28,6 +28,9 @@ body {
main { main {
margin-top: var(--small-gap); margin-top: var(--small-gap);
display: flex;
flex-direction: column;
gap: var(--small-gap);
} }
} }
@ -45,8 +48,6 @@ div.preview {
display: flex; display: flex;
gap: var(--small-gap); gap: var(--small-gap);
} }
margin: var(--small-gap) 0px;
} }
form { form {
@ -119,3 +120,22 @@ div#code-editor {
font-size: 12px; font-size: 12px;
} }
} }
div#dep-list {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--small-gap);
section {
width: 100%;
display: flex;
flex-direction: column;
text-align: center;
gap: var(--small-gap);
div {
text-align: left;
}
}
}

View file

@ -135,14 +135,18 @@ function bufToString(mem, ptr, len) {
function wireUp(target) { function wireUp(target) {
execApply(target); execApply(target);
cacheInputs(target); cacheInputs(target);
bindTextareaAutoResize(target);
bindCodeEdit(target); bindCodeEdit(target);
bindTextareaAutoResize(target);
} }
const importRe = /@use\s*\(\s*"(([^"]|\\")+)"\s*\)/g; const importRe = /@use\s*\(\s*"(([^"]|\\")+)"\s*\)/g;
const prevRoots = new Set();
/** @param {string} code @param {string[]} roots @param {Post[]} buf @returns {void} */ /** @param {string} code
function loadCachedPackages(code, roots, buf) { * @param {string[]} roots
* @param {Post[]} buf
* @param {Set<string>} prevRoots
* @returns {void} */
function loadCachedPackages(code, roots, buf, prevRoots) {
buf[0].code = code; buf[0].code = code;
roots.length = 0; roots.length = 0;
@ -165,6 +169,8 @@ function loadCachedPackages(code, roots, buf) {
} }
} }
/**@type{Set<string>}*/ const prevRoots = new Set();
/** @param {HTMLElement} target */ /** @param {HTMLElement} target */
async function bindCodeEdit(target) { async function bindCodeEdit(target) {
const edit = target.querySelector("#code-edit"); const edit = target.querySelector("#code-edit");
@ -190,6 +196,8 @@ async function bindCodeEdit(target) {
let cancelation = undefined; let cancelation = undefined;
let timeout = 0; let timeout = 0;
prevRoots.clear();
const onInput = () => { const onInput = () => {
importDiff.clear(); importDiff.clear();
for (const match of edit.value.matchAll(importRe)) { for (const match of edit.value.matchAll(importRe)) {
@ -215,10 +223,12 @@ async function bindCodeEdit(target) {
try { try {
const json = await e.json(); const json = await e.json();
if (e.status == 200) { if (e.status == 200) {
for (const key in json) localStorage["package-" + key] = json[key]; for (const [key, value] of Object.entries(json)) {
localStorage["package-" + key] = value;
}
const missing = keyBuf.filter(i => json[i] === undefined); const missing = keyBuf.filter(i => json[i] === undefined);
if (missing.length !== 0) { if (missing.length !== 0) {
errors.textContent = "failed to fetch: " + missing.join(", "); errors.textContent = "deps not found: " + missing.join(", ");
} else { } else {
cancelation = undefined; cancelation = undefined;
edit.dispatchEvent(new InputEvent("input")); edit.dispatchEvent(new InputEvent("input"));
@ -236,7 +246,7 @@ async function bindCodeEdit(target) {
return; return;
} }
loadCachedPackages(edit.value, keyBuf, packages); loadCachedPackages(edit.value, keyBuf, packages, prevRoots);
errors.textContent = compileCode(hbc, packages, 1); errors.textContent = compileCode(hbc, packages, 1);
const minified_size = modifyCode(fmt, edit.value, "minify")?.length; const minified_size = modifyCode(fmt, edit.value, "minify")?.length;
@ -348,7 +358,7 @@ if (window.location.hostname === 'localhost') {
})() })()
} }
document.body.addEventListener('htmx:afterSettle', (ev) => { document.body.addEventListener('htmx:afterSwap', (ev) => {
if (!(ev.target instanceof HTMLElement)) never(); if (!(ev.target instanceof HTMLElement)) never();
wireUp(ev.target); wireUp(ev.target);
}); });
@ -360,7 +370,47 @@ getFmtInstance().then(inst => {
details.parameters['code'] = modifyCode(inst, details.parameters['code'], "minify"); details.parameters['code'] = modifyCode(inst, details.parameters['code'], "minify");
} }
}); });
/** @param {string} query @param {string} target @returns {number} */
function fuzzyCost(query, target) {
let qi = 0, bi = 0, cost = 0, matched = false;
while (qi < query.length) {
if (query.charAt(qi) === target.charAt(bi++)) {
matched = true;
qi++;
} else {
cost++;
}
if (bi === target.length) (bi = 0, qi++);
}
return cost + (matched ? 0 : 100 * target.length);
}
let deps = undefined;
/** @param {HTMLInputElement} input @returns {void} */
function filterCodeDeps(input) {
deps ??= document.getElementById("deps");
if (!(deps instanceof HTMLElement)) never();
if (input.value === "") {
deps.textContent = "results show here...";
return;
}
deps.innerHTML = "";
for (const root of [...prevRoots.keys()]
.sort((a, b) => fuzzyCost(input.value, a) - fuzzyCost(input.value, b))) {
const pane = document.createElement("div");
const code = modifyCode(inst, localStorage["package-" + root], "fmt");
pane.innerHTML = `<div>${root}</div><pre>${code}</pre>`;
deps.appendChild(pane);
}
if (deps.innerHTML === "") {
deps.textContent = "no results";
}
}
Object.assign(window, { filterCodeDeps });
}); });
wireUp(document.body); wireUp(document.body);

View file

@ -3,16 +3,18 @@ use {
argon2::{password_hash::SaltString, PasswordVerifier}, argon2::{password_hash::SaltString, PasswordVerifier},
axum::{ axum::{
body::Bytes, body::Bytes,
extract::Path,
http::{header::COOKIE, request::Parts}, http::{header::COOKIE, request::Parts},
response::{AppendHeaders, Html}, response::{AppendHeaders, Html},
}, },
const_format::formatcp,
core::fmt, core::fmt,
htmlm::{html, write_html}, htmlm::{html, write_html},
rand_core::OsRng, rand_core::OsRng,
serde::{Deserialize, Serialize}, serde::{Deserialize, Serialize},
std::{ std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
fmt::Write, fmt::{Display, Write},
net::Ipv4Addr, net::Ipv4Addr,
}, },
}; };
@ -21,6 +23,7 @@ const MAX_NAME_LENGTH: usize = 32;
const MAX_POSTNAME_LENGTH: usize = 64; const MAX_POSTNAME_LENGTH: usize = 64;
const MAX_CODE_LENGTH: usize = 1024 * 4; const MAX_CODE_LENGTH: usize = 1024 * 4;
const SESSION_DURATION_SECS: u64 = 60 * 60; const SESSION_DURATION_SECS: u64 = 60 * 60;
const MAX_FEED_SIZE: usize = 8 * 1024;
type Redirect<const COUNT: usize = 1> = AppendHeaders<[(&'static str, &'static str); COUNT]>; type Redirect<const COUNT: usize = 1> = AppendHeaders<[(&'static str, &'static str); COUNT]>;
@ -55,9 +58,13 @@ async fn amain() {
.route("/hbfmt.wasm", static_asset!("application/wasm", "hbfmt.wasm")) .route("/hbfmt.wasm", static_asset!("application/wasm", "hbfmt.wasm"))
.route("/hbc.wasm", static_asset!("application/wasm", "hbc.wasm")) .route("/hbc.wasm", static_asset!("application/wasm", "hbc.wasm"))
.route("/index-view", get(Index::get)) .route("/index-view", get(Index::get))
.route("/feed", get(Index::page)) .route("/feed", get(Feed::page))
.route("/feed-view", get(Feed::get))
.route("/feed-more", post(Feed::more))
.route("/profile", get(Profile::page)) .route("/profile", get(Profile::page))
.route("/profile-view", get(Profile::get)) .route("/profile-view", get(Profile::get))
.route("/profile/:name", get(Profile::get_other_page))
.route("/profile-view/:name", get(Profile::get_other))
.route("/post", get(Post::page)) .route("/post", get(Post::page))
.route("/post-view", get(Post::get)) .route("/post-view", get(Post::get))
.route("/post", post(Post::post)) .route("/post", post(Post::post))
@ -80,50 +87,28 @@ async fn amain() {
}), }),
); );
let socket = tokio::net::TcpListener::bind((Ipv4Addr::UNSPECIFIED, 8080)).await.unwrap(); #[cfg(feature = "tls")]
{
let addr =
(Ipv4Addr::UNSPECIFIED, std::env::var("DEPELL_PORT").unwrap().parse::<u16>().unwrap());
let config = axum_server::tls_rustls::RustlsConfig::from_pem_file(
std::env::var("DEPELL_CERT_PATH").unwrap(),
std::env::var("DEPELL_KEY_PATH").unwrap(),
)
.await
.unwrap();
axum_server::bind_rustls(addr.into(), config)
.serve(router.into_make_service())
.await
.unwrap();
}
#[cfg(not(feature = "tls"))]
{
let addr = (Ipv4Addr::UNSPECIFIED, 8080);
let socket = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(socket, router).await.unwrap(); axum::serve(socket, router).await.unwrap();
} }
trait PublicPage: Default {
fn render_to_buf(self, buf: &mut String);
fn render(self) -> String {
let mut str = String::new();
self.render_to_buf(&mut str);
str
}
async fn get() -> Html<String> {
Html(Self::default().render())
}
async fn page(session: Option<Session>) -> Html<String> {
base(|s| Self::default().render_to_buf(s), session.as_ref()).await
}
}
trait Page: Default {
fn render_to_buf(self, session: &Session, buf: &mut String);
fn render(self, session: &Session) -> String {
let mut str = String::new();
self.render_to_buf(session, &mut str);
str
}
async fn get(session: Session) -> Html<String> {
Html(Self::default().render(&session))
}
async fn page(session: Option<Session>) -> Result<Html<String>, axum::response::Redirect> {
match session {
Some(session) => {
Ok(base(|f| Self::default().render_to_buf(&session, f), Some(&session)).await)
}
None => Err(axum::response::Redirect::permanent("/login")),
}
}
} }
async fn fetch_code( async fn fetch_code(
@ -140,16 +125,77 @@ async fn fetch_code(
r.get::<_, String>(2)?, r.get::<_, String>(2)?,
)) ))
}) })
.inspect_err(|e| log::error!("{e}")) .log("fetch deps query")
.into_iter() .into_iter()
.flatten() .flatten()
.filter_map(|r| r.inspect_err(|e| log::error!("{e}")).ok()) .filter_map(|r| r.log("deps row"))
.collect_into(&mut deps); .collect_into(&mut deps);
} }
}); });
axum::Json(deps) axum::Json(deps)
} }
#[derive(Deserialize)]
#[serde(untagged)]
enum Feed {
Before { before_timestamp: u64 },
}
#[derive(Deserialize)]
struct Before {
before_timestamp: u64,
}
impl Feed {
async fn more(session: Session, axum::Form(data): axum::Form<Before>) -> Html<String> {
Self::Before { before_timestamp: data.before_timestamp }.render(&session)
}
}
impl Default for Feed {
fn default() -> Self {
Self::Before { before_timestamp: now() + 3600 }
}
}
impl Page for Feed {
fn render_to_buf(self, _: &Session, buf: &mut String) {
db::with(|db| {
let cursor = match self {
Feed::Before { before_timestamp } => db
.get_pots_before
.query_map((before_timestamp,), Post::from_row)
.log("fetch before posts query")
.into_iter()
.flatten()
.filter_map(|r| r.log("fetch before posts row")),
};
let base_len = buf.len();
let mut last_timestamp = None;
for post in cursor {
write!(buf, "{}", post).unwrap();
last_timestamp = Some(post.timestamp);
if buf.len() - base_len > MAX_FEED_SIZE {
break;
}
}
write_html!((*buf)
if let Some(last_timestamp) = last_timestamp {
<div "hx-post"="/feed-more"
"hx-trigger"="intersect once"
"hx-swap"="outerHTML"
"hx-vals"={format_args!("{{\"before_timestamp\":{last_timestamp}}}")}
>"there might be more"</div>
} else {
"no more stuff"
}
);
});
}
}
#[derive(Default)] #[derive(Default)]
struct Index; struct Index;
@ -199,10 +245,30 @@ impl Page for Post {
} }
impl Post { impl Post {
pub fn from_row(r: &rusqlite::Row) -> rusqlite::Result<Self> {
Ok(Post {
author: r.get(0)?,
name: r.get(1)?,
timestamp: r.get(2)?,
code: r.get(3)?,
..Default::default()
})
}
async fn post( async fn post(
session: Session, session: Session,
axum::Form(mut data): axum::Form<Self>, axum::Form(mut data): axum::Form<Self>,
) -> Result<Redirect, Html<String>> { ) -> Result<Redirect, Html<String>> {
if data.name.len() > MAX_POSTNAME_LENGTH {
data.error = Some(formatcp!("name too long, max length is {MAX_POSTNAME_LENGTH}"));
return Err(data.render(&session));
}
if data.code.len() > MAX_CODE_LENGTH {
data.error = Some(formatcp!("code too long, max length is {MAX_CODE_LENGTH}"));
return Err(data.render(&session));
}
db::with(|db| { db::with(|db| {
if let Err(e) = db.create_post.insert((&data.name, &session.name, now(), &data.code)) { if let Err(e) = db.create_post.insert((&data.name, &session.name, now(), &data.code)) {
if let rusqlite::Error::SqliteFailure(e, _) = e { if let rusqlite::Error::SqliteFailure(e, _) = e {
@ -211,7 +277,7 @@ impl Post {
} }
} }
data.error = data.error.or_else(|| { data.error = data.error.or_else(|| {
log::error!("{e}"); log::error!("create post error: {e}");
Some("internal server error") Some("internal server error")
}); });
return; return;
@ -221,8 +287,12 @@ impl Post {
.filter_map(|v| v.split_once('/')) .filter_map(|v| v.split_once('/'))
.collect::<HashSet<_>>() .collect::<HashSet<_>>()
{ {
if let Err(e) = db.create_import.insert((author, name, &session.name, &data.name)) { if db
log::error!("{e}"); .create_import
.insert((author, name, &session.name, &data.name))
.log("create import query")
.is_none()
{
data.error = Some("internal server error"); data.error = Some("internal server error");
return; return;
}; };
@ -230,7 +300,7 @@ impl Post {
}); });
if data.error.is_some() { if data.error.is_some() {
Err(Html(data.render(&session))) Err(data.render(&session))
} else { } else {
Ok(redirect("/profile")) Ok(redirect("/profile"))
} }
@ -242,7 +312,13 @@ impl fmt::Display for Post {
let Self { author, name, timestamp, imports, runs, dependencies, code, .. } = self; let Self { author, name, timestamp, imports, runs, dependencies, code, .. } = self;
write_html! { f <div class="preview"> write_html! { f <div class="preview">
<div class="info"> <div class="info">
<span>author "/" name</span> <span>
<a "hx-get"={format_args!("/profile-view/{author}")} href="" "hx-target"="main"
"hx-push-url"={format_args!("/profile/{author}")}
"hx-swam"="innerHTML">author</a>
"/"
name
</span>
<span apply="timestamp">timestamp</span> <span apply="timestamp">timestamp</span>
</div> </div>
<div class="stats"> <div class="stats">
@ -264,26 +340,30 @@ impl fmt::Display for Post {
} }
#[derive(Default)] #[derive(Default)]
struct Profile; struct Profile {
other: Option<String>,
}
impl Profile {
async fn get_other(session: Session, Path(name): Path<String>) -> Html<String> {
Profile { other: Some(name) }.render(&session)
}
async fn get_other_page(session: Session, Path(name): Path<String>) -> Html<String> {
base(|b| Profile { other: Some(name) }.render_to_buf(&session, b), Some(&session))
}
}
impl Page for Profile { impl Page for Profile {
fn render_to_buf(self, session: &Session, buf: &mut String) { fn render_to_buf(self, session: &Session, buf: &mut String) {
db::with(|db| { db::with(|db| {
let iter = db let iter = db
.get_user_posts .get_user_posts
.query_map((&session.name,), |r| { .query_map((self.other.as_ref().unwrap_or(&session.name),), Post::from_row)
Ok(Post { .log("get user posts query")
author: r.get(0)?,
name: r.get(1)?,
timestamp: r.get(2)?,
code: r.get(3)?,
..Default::default()
})
})
.inspect_err(|e| log::error!("{e}"))
.into_iter() .into_iter()
.flatten() .flatten()
.filter_map(|p| p.inspect_err(|e| log::error!("{e}")).ok()); .filter_map(|p| p.log("user post row"));
write_html! { (buf) write_html! { (buf)
for post in iter { for post in iter {
!{post} !{post}
@ -345,9 +425,13 @@ impl Login {
data.error = Some("invalid credentials"); data.error = Some("invalid credentials");
} else { } else {
getrandom::getrandom(&mut id).unwrap(); getrandom::getrandom(&mut id).unwrap();
if let Err(e) = db.login.insert((id, &data.name, now() + SESSION_DURATION_SECS)) if db
.login
.insert((id, &data.name, now() + SESSION_DURATION_SECS))
.log("create session query")
.is_none()
{ {
log::error!("{e}"); data.error = Some("internal server error");
} }
} }
} }
@ -362,7 +446,7 @@ impl Login {
if data.error.is_some() { if data.error.is_some() {
log::error!("what {:?}", data); log::error!("what {:?}", data);
Err(Html(data.render())) Err(data.render())
} else { } else {
Ok(AppendHeaders([ Ok(AppendHeaders([
("hx-location", "/feed".into()), ("hx-location", "/feed".into()),
@ -378,7 +462,7 @@ impl Login {
} }
async fn delete(session: Session) -> Redirect { async fn delete(session: Session) -> Redirect {
_ = db::with(|q| q.logout.execute((session.id,)).inspect_err(|e| log::error!("{e}"))); _ = db::with(|q| q.logout.execute((session.id,)).log("delete session query"));
redirect("/login") redirect("/login")
} }
} }
@ -388,15 +472,18 @@ struct Signup {
name: String, name: String,
new_password: String, new_password: String,
confirm_password: String, confirm_password: String,
#[serde(default)]
confirm_no_password: bool,
#[serde(skip)] #[serde(skip)]
error: Option<&'static str>, error: Option<&'static str>,
} }
impl PublicPage for Signup { impl PublicPage for Signup {
fn render_to_buf(self, buf: &mut String) { fn render_to_buf(self, buf: &mut String) {
let Signup { name, new_password, confirm_password, error } = self; let Signup { name, new_password, confirm_password, confirm_no_password, error } = self;
let vals = if confirm_no_password { "{\"confirm_no_password\":true}" } else { "{}" };
write_html! { (buf) write_html! { (buf)
<form "hx-post"="/signup" "hx-swap"="outerHTML"> <form "hx-post"="/signup" "hx-swap"="outerHTML" "hx-vals"=vals>
if let Some(e) = error { <div class="error">e</div> } if let Some(e) = error { <div class="error">e</div> }
<input name="name" type="text" autocomplete="name" placeholder="name" value=name <input name="name" type="text" autocomplete="name" placeholder="name" value=name
maxlength=MAX_NAME_LENGTH required> maxlength=MAX_NAME_LENGTH required>
@ -412,6 +499,17 @@ impl PublicPage for Signup {
impl Signup { impl Signup {
async fn post(axum::Form(mut data): axum::Form<Self>) -> Result<Redirect, Html<String>> { async fn post(axum::Form(mut data): axum::Form<Self>) -> Result<Redirect, Html<String>> {
if data.name.len() > MAX_NAME_LENGTH {
data.error = Some(formatcp!("name too long, max length is {MAX_NAME_LENGTH}"));
return Err(data.render());
}
if !data.confirm_no_password && data.new_password.is_empty() {
data.confirm_no_password = true;
data.error = Some("Are you sure you don't want to use a password? (then submit again)");
return Err(data.render());
}
db::with(|db| { db::with(|db| {
// TODO: hash passwords // TODO: hash passwords
match db.register.insert((&data.name, hash_password(&data.new_password))) { match db.register.insert((&data.name, hash_password(&data.new_password))) {
@ -422,23 +520,32 @@ impl Signup {
data.error = Some("username already taken"); data.error = Some("username already taken");
} }
Err(e) => { Err(e) => {
log::error!("{e}"); log::error!("create user query: {e}");
data.error = Some("internal server error"); data.error = Some("internal server error");
} }
}; };
}); });
if data.error.is_some() { if data.error.is_some() {
Err(Html(data.render())) Err(data.render())
} else { } else {
Ok(redirect("/login")) Ok(redirect("/login"))
} }
} }
} }
async fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html<String> { fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html<String> {
let username = session.map(|s| &s.name); let username = session.map(|s| &s.name);
let nav_button = |f: &mut String, name: &str| {
write_html! {(f)
<button "hx-push-url"={format_args!("/{name}")}
"hx-get"={format_args!("/{name}-view")}
"hx-target"="main"
"hx-swap"="innerHTML">name</button>
}
};
Html(html! { Html(html! {
"<!DOCTYPE html>" "<!DOCTYPE html>"
<html lang="en"> <html lang="en">
@ -452,21 +559,17 @@ async fn base(body: impl FnOnce(&mut String), session: Option<&Session>) -> Html
if let Some(username) = username { if let Some(username) = username {
<button "hx-push-url"="/profile" "hx-get"="/profile-view" "hx-target"="main" <button "hx-push-url"="/profile" "hx-get"="/profile-view" "hx-target"="main"
"hx-swap"="innerHTML">username</button> "hx-swap"="innerHTML">username</button>
<button "hx-push-url"="/post" "hx-get"="/post-view" "hx-target"="main" |f|{nav_button(f, "feed"); nav_button(f, "post")}
"hx-swap"="innerHTML">"post"</button>
<button "hx-delete"="/login">"logout"</button> <button "hx-delete"="/login">"logout"</button>
} else { } else {
<button "hx-push-url"="/login" "hx-get"="/login-view" "hx-target"="main" |f|{nav_button(f, "login"); nav_button(f, "signup")}
"hx-swap"="innerHTML">"login"</button>
<button "hx-push-url"="/signup" "hx-get"="/signup-view" "hx-target"="main"
"hx-swap"="innerHTML">"signup"</button>
} }
</section> </section>
</nav> </nav>
<section id="post-form"></section> <section id="post-form"></section>
<main>|f|{body(f)}</main> <main>|f|{body(f)}</main>
</body> </body>
<script src="https://unpkg.com/htmx.org@2.0.3" integrity="sha384-0895/pl2MU10Hqc6jd4RvrthNlDiE9U1tWmX7WRESftEDRosgxNsQG/Ze9YMRzHq" crossorigin="anonymous"></script> <script src="https://unpkg.com/htmx.org@2.0.3/dist/htmx.min.js" integrity="sha384-0895/pl2MU10Hqc6jd4RvrthNlDiE9U1tWmX7WRESftEDRosgxNsQG/Ze9YMRzHq" crossorigin="anonymous"></script>
<script type="module" src="/index.js"></script> <script type="module" src="/index.js"></script>
</html> </html>
}) })
@ -500,12 +603,11 @@ impl<S> axum::extract::FromRequestParts<S> for Session {
let (name, expiration) = db::with(|db| { let (name, expiration) = db::with(|db| {
db.get_session db.get_session
.query_row((id,), |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?))) .query_row((id,), |r| Ok((r.get::<_, String>(0)?, r.get::<_, u64>(1)?)))
.inspect_err(|e| log::error!("{e}")) .log("fetching session")
.map_err(|_| err) .ok_or(err)
})?; })?;
if expiration < now() { if expiration < now() {
log::error!("expired");
return Err(err); return Err(err);
} }
@ -551,7 +653,7 @@ fn to_hex(src: &[u8]) -> String {
} }
fn main() { fn main() {
tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap().block_on(amain()); tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(amain());
} }
mod db { mod db {
@ -583,7 +685,9 @@ mod db {
login: "INSERT OR REPLACE INTO session (id, username, expiration) VALUES(?, ?, ?)", login: "INSERT OR REPLACE INTO session (id, username, expiration) VALUES(?, ?, ?)",
logout: "DELETE FROM session WHERE id = ?", logout: "DELETE FROM session WHERE id = ?",
get_session: "SELECT username, expiration FROM session WHERE id = ?", get_session: "SELECT username, expiration FROM session WHERE id = ?",
get_user_posts: "SELECT author, name, timestamp, code FROM post WHERE author = ?", get_user_posts: "SELECT author, name, timestamp, code FROM post WHERE author = ?
ORDER BY timestamp DESC",
get_pots_before: "SELECT author, name, timestamp, code FROM post WHERE timestamp < ?",
create_post: "INSERT INTO post (name, author, timestamp, code) VALUES(?, ?, ?, ?)", create_post: "INSERT INTO post (name, author, timestamp, code) VALUES(?, ?, ?, ?)",
fetch_deps: " fetch_deps: "
WITH RECURSIVE roots(name, author, code) AS ( WITH RECURSIVE roots(name, author, code) AS (
@ -634,6 +738,63 @@ fn redirect(to: &'static str) -> Redirect {
AppendHeaders([("hx-location", to)]) AppendHeaders([("hx-location", to)])
} }
trait PublicPage: Default {
fn render_to_buf(self, buf: &mut String);
fn render(self) -> Html<String> {
let mut str = String::new();
self.render_to_buf(&mut str);
Html(str)
}
async fn get() -> Html<String> {
Self::default().render()
}
async fn page(session: Option<Session>) -> Html<String> {
base(|s| Self::default().render_to_buf(s), session.as_ref())
}
}
trait Page: Default {
fn render_to_buf(self, session: &Session, buf: &mut String);
fn render(self, session: &Session) -> Html<String> {
let mut str = String::new();
self.render_to_buf(session, &mut str);
Html(str)
}
async fn get(session: Session) -> Html<String> {
Self::default().render(&session)
}
async fn page(session: Option<Session>) -> Result<Html<String>, axum::response::Redirect> {
match session {
Some(session) => {
Ok(base(|f| Self::default().render_to_buf(&session, f), Some(&session)))
}
None => Err(axum::response::Redirect::permanent("/login")),
}
}
}
trait ResultExt<O, E> {
fn log(self, prefix: impl Display) -> Option<O>;
}
impl<O, E: Display> ResultExt<O, E> for Result<O, E> {
fn log(self, prefix: impl Display) -> Option<O> {
match self {
Ok(v) => Some(v),
Err(e) => {
log::error!("{prefix}: {e}");
None
}
}
}
}
struct Logger; struct Logger;
impl log::Log for Logger { impl log::Log for Logger {
@ -643,12 +804,7 @@ impl log::Log for Logger {
fn log(&self, record: &log::Record) { fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) { if self.enabled(record.metadata()) {
eprintln!( eprintln!("{} - {}", record.module_path().unwrap_or("=="), record.args());
"{} {:?} - {}",
record.module_path().unwrap_or("=="),
record.line(),
record.args()
);
} }
} }

View file

@ -1,3 +1,12 @@
<div id="dep-list">
<input placeholder="search impoted deps.." oninput="filterCodeDeps(this, event)">
<section id="deps">
results show here...
</section>
</div>
<div>
<h3>About posting code</h3> <h3>About posting code</h3>
<p> <p>
If you are unfammiliar with <a href="https://git.ablecorp.us/AbleOS/holey-bytes">hblang</a>, refer to the If you are unfammiliar with <a href="https://git.ablecorp.us/AbleOS/holey-bytes">hblang</a>, refer to the

View file

@ -26,6 +26,9 @@ CREATE TABLE IF NOT EXISTS post(
PRIMARY KEY (author, name) PRIMARY KEY (author, name)
); );
CREATE INDEX IF NOT EXISTS
post_timestamp ON post(timestamp DESC);
CREATE TABLE IF NOT EXISTS import( CREATE TABLE IF NOT EXISTS import(
from_name TEXT NOT NULL, from_name TEXT NOT NULL,
from_author TEXT, from_author TEXT,

View file

@ -83,7 +83,7 @@ unsafe fn compile_and_run(mut fuel: usize) {
while fuel != 0 { while fuel != 0 {
match ct.vm.run() { match ct.vm.run() {
Ok(hbvm::VmRunOk::End) => { Ok(hbvm::VmRunOk::End) => {
log::error!("exit code: {}", ct.vm.read_reg(1).0); log::error!("exit code: {}", ct.vm.read_reg(1).0 as i64);
break; break;
} }
Ok(hbvm::VmRunOk::Ecall) => { Ok(hbvm::VmRunOk::Ecall) => {

View file

@ -570,12 +570,14 @@ impl<'a, 'b> Parser<'a, 'b> {
end: TokenKind, end: TokenKind,
mut f: impl FnMut(&mut Self) -> T, mut f: impl FnMut(&mut Self) -> T,
) -> &'a [T] { ) -> &'a [T] {
let mut trailing_sep = false;
let mut view = self.ctx.stack.view(); let mut view = self.ctx.stack.view();
while !self.advance_if(end) { while !self.advance_if(end) {
let val = f(self); let val = f(self);
self.trailing_sep = self.advance_if(delim); trailing_sep = self.advance_if(delim);
unsafe { self.ctx.stack.push(&mut view, val) }; unsafe { self.ctx.stack.push(&mut view, val) };
} }
self.trailing_sep = trailing_sep;
self.arena.alloc_slice(unsafe { self.ctx.stack.finalize(view) }) self.arena.alloc_slice(unsafe { self.ctx.stack.finalize(view) })
} }

View file

@ -83,17 +83,25 @@ fn main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
"watch-depell-debug" => { "watch-depell-debug" => {
let mut c = build_cmd("cargo watch --why"); let mut c = build_cmd("cargo watch");
c.arg("--exec=xtask build-depell-debug").arg("--exec=run -p depell"); c.args(["--exec=xtask build-depell-debug", "--exec=run -p depell"]);
exec(c)?; exec(c)?;
Ok(()) Ok(())
} }
"watch-depell" => { "watch-depell" => {
let mut c = build_cmd("cargo watch --why"); let mut c = build_cmd("cargo watch");
c.arg("--exec=xtask build-depell").arg("--exec=run -p depell"); c.args(["--exec=xtask build-depell", "--exec=run -p depell --release"]);
exec(c)?; exec(c)?;
Ok(()) Ok(())
} }
"release-depell" => {
exec(build_cmd("cargo xtask build-depell"))?;
exec(build_cmd(
"cargo build -p depell --release --features tls
--target x86_64-unknown-linux-musl",
))?;
Ok(())
}
_ => Ok(()), _ => Ok(()),
} }
} }