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,49 +87,27 @@ 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")),
}
} }
} }
@ -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,12 +1,21 @@
<h3>About posting code</h3> <div id="dep-list">
<p> <input placeholder="search impoted deps.." oninput="filterCodeDeps(this, event)">
<section id="deps">
results show here...
</section>
</div>
<div>
<h3>About posting code</h3>
<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
<strong>hblang/README.md</strong> or <strong>hblang/README.md</strong> or
vizit <a href="/profile/mlokis">mlokis'es posts</a>. Preferably don't edit the code here. vizit <a href="/profile/mlokis">mlokis'es posts</a>. Preferably don't edit the code here.
</p> </p>
<h3>Extra textarea features</h3> <h3>Extra textarea features</h3>
<ul> <ul>
<li>proper tab behaviour</li> <li>proper tab behaviour</li>
<li>snap to previous tab boundary on "empty" lines</li> <li>snap to previous tab boundary on "empty" lines</li>
</ul> </ul>

View file

@ -22,17 +22,20 @@ CREATE TABLE IF NOT EXISTS post(
author TEXT, author TEXT,
timestamp INTEGER, timestamp INTEGER,
code TEXT NOT NULL, code TEXT NOT NULL,
FOREIGN KEY (author) REFERENCES user (name) ON DELETE SET NULL, FOREIGN KEY (author) REFERENCES user(name) ON DELETE SET NULL,
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,
to_name TEXT NOT NULL, to_name TEXT NOT NULL,
to_author TEXT, to_author TEXT,
FOREIGN KEY (from_name, from_author) REFERENCES post (name, author), FOREIGN KEY (from_name, from_author) REFERENCES post(name, author),
FOREIGN KEY (to_name, to_author) REFERENCES post (name, author) FOREIGN KEY (to_name, to_author) REFERENCES post(name, author)
); );
CREATE INDEX IF NOT EXISTS CREATE INDEX IF NOT EXISTS
@ -45,7 +48,7 @@ CREATE TABLE IF NOT EXISTS run(
code_name TEXT NOT NULL, code_name TEXT NOT NULL,
code_author TEXT NOT NULL, code_author TEXT NOT NULL,
runner TEXT NOT NULL, runner TEXT NOT NULL,
FOREIGN KEY (code_name, code_author) REFERENCES post (name, author), FOREIGN KEY (code_name, code_author) REFERENCES post(name, author),
FOREIGN KEY (runner) REFERENCES user(name), FOREIGN KEY (runner) REFERENCES user(name),
PRIMARY KEY (code_name, code_author, runner) PRIMARY KEY (code_name, code_author, runner)
); );

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(()),
} }
} }