initial commit
This commit is contained in:
commit
d0a663b2bb
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Lua.diagnostics.globals": [
|
||||||
|
"name",
|
||||||
|
"version",
|
||||||
|
"description",
|
||||||
|
"scripts",
|
||||||
|
"sleep",
|
||||||
|
"create_app"
|
||||||
|
]
|
||||||
|
}
|
||||||
729
Cargo.lock
generated
Normal file
729
Cargo.lock
generated
Normal file
@ -0,0 +1,729 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "erased-serde"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.3.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"indexmap",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpdate"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper"
|
||||||
|
version = "0.14.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"h2",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
|
"itoa",
|
||||||
|
"pin-project-lite",
|
||||||
|
"socket2",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"want",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.139"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lua-src"
|
||||||
|
version = "544.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "708ba3c844d5e9d38def4a09dd871c17c370f519b3c4b7261fbabe4a613a814c"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "luajit-src"
|
||||||
|
version = "210.4.5+resty2cf5186"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27b7992a40e602786272d84c6f2beca44a588ededcfd57b48ec6f82008a7cb97"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchit"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.42.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ee2ad7a9aa69056b148d9d590344bc155d3ce0d2200e3b2838f7034f6ba33c1"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"cc",
|
||||||
|
"erased-serde",
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
"lua-src",
|
||||||
|
"luajit-src",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"pkg-config",
|
||||||
|
"rustc-hash",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.93"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tchoutchou"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"hyper",
|
||||||
|
"matchit",
|
||||||
|
"mlua",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"mio",
|
||||||
|
"num_cpus",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
|
"windows-sys 0.42.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc6a3b08b64e6dfad376fa2432c7b1f01522e37a623c3050bc95db2d3ff21583"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-service"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "try-lock"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "want"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"try-lock",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.45.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||||
31
Cargo.toml
Normal file
31
Cargo.toml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[package]
|
||||||
|
name = "tchoutchou"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
path = "src/cli/main.rs"
|
||||||
|
name = "tt"
|
||||||
|
bench = false
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
opt-level = "z"
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
futures = { version = "0.3" }
|
||||||
|
hyper = { version = "0.14", features = ["full"] }
|
||||||
|
matchit = { version = "0.7" }
|
||||||
|
mlua = { version = "0.8", features = [
|
||||||
|
"lua54",
|
||||||
|
"vendored",
|
||||||
|
"async",
|
||||||
|
"serialize",
|
||||||
|
] }
|
||||||
|
serde_json = { version = "1.0" }
|
||||||
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM rust:alpine as builder
|
||||||
|
RUN apk add --no-cache musl-dev
|
||||||
|
WORKDIR /
|
||||||
|
RUN USER=root cargo new app
|
||||||
|
COPY Cargo.toml Cargo.lock /app
|
||||||
|
WORKDIR /app
|
||||||
|
RUN cargo build --release
|
||||||
|
COPY src /app/src
|
||||||
|
RUN touch /app/src/main.rs
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=builder /app/target/release/tchoutchou /tchoutchou
|
||||||
|
CMD ["/tchoutchou"]
|
||||||
72
server.lua
Normal file
72
server.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
local omg = require("omg")
|
||||||
|
omg()
|
||||||
|
|
||||||
|
-- function sleep(a)
|
||||||
|
-- local sec = tonumber(os.clock() + a);
|
||||||
|
-- while (os.clock() < sec) do
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Admin Section
|
||||||
|
]]
|
||||||
|
local admin = create_app()
|
||||||
|
admin:get("/", function(req, res)
|
||||||
|
res.status = 200
|
||||||
|
res.body = "Admin"
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Main App
|
||||||
|
]]
|
||||||
|
local app = create_app()
|
||||||
|
app:get("/foo/:number", function(req, res)
|
||||||
|
res.body = { data = req.params.number }
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
app:get("/:one/:two/:three/:four/:five", function(req, res)
|
||||||
|
print(req.params.five)
|
||||||
|
res.body = { data = req.params.one }
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
app:get("/bar", function(req, res)
|
||||||
|
res.status = 200
|
||||||
|
res.body = "Hello, World!"
|
||||||
|
sleep(3)
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
app:post("/submit", function(req, res)
|
||||||
|
print(req.body)
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
|
||||||
|
--[[ wip ]]
|
||||||
|
-- app:ws("/ws", function(ws)
|
||||||
|
-- ws:on("message", function(msg)
|
||||||
|
-- print(msg)
|
||||||
|
-- end)
|
||||||
|
-- return ws
|
||||||
|
-- end)
|
||||||
|
-- app:ws("/ws", {
|
||||||
|
-- on_connect = function(ws)
|
||||||
|
-- print("lua connect cb")
|
||||||
|
-- table.insert(ws_clients, ws)
|
||||||
|
-- end,
|
||||||
|
-- on_message = function(ws, message)
|
||||||
|
-- print("lua message cb")
|
||||||
|
-- end,
|
||||||
|
-- })
|
||||||
|
|
||||||
|
app:use("/admin", admin)
|
||||||
|
|
||||||
|
-- Run App
|
||||||
|
app:run(3000)
|
||||||
|
|
||||||
|
local otherapp = create_app()
|
||||||
|
otherapp:get("/", function(req, res)
|
||||||
|
res.status = 200
|
||||||
|
res.body = "Admin"
|
||||||
|
return res
|
||||||
|
end)
|
||||||
|
otherapp:run(3001)
|
||||||
14
src/api/builtins.rs
Normal file
14
src/api/builtins.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use mlua::Lua;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
pub fn load_builtins(lua: &Lua) {
|
||||||
|
let sleep = lua
|
||||||
|
.create_async_function(|_l, n: u64| async move {
|
||||||
|
sleep(Duration::from_secs(n)).await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
lua.globals().set("sleep", sleep).unwrap();
|
||||||
|
}
|
||||||
1
src/api/mod.rs
Normal file
1
src/api/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod builtins;
|
||||||
36
src/cli/main.rs
Normal file
36
src/cli/main.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use std::{env, fs};
|
||||||
|
|
||||||
|
use tchoutchou::api::builtins::load_builtins;
|
||||||
|
use tchoutchou::internal::core::runtime::Runtime;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
if args.len() != 2 {
|
||||||
|
eprintln!("usage: tchoutchou [file.lua]");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lua_script = match fs::read(&args[1]) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(error) => {
|
||||||
|
eprintln!("{}", error);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let runtime = match Runtime::from_script(&lua_script) {
|
||||||
|
Ok(runtime) => runtime,
|
||||||
|
Err(error) => {
|
||||||
|
eprintln!("{}", error);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
runtime.load(&load_builtins);
|
||||||
|
runtime.start().await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
3
src/internal/core/mod.rs
Normal file
3
src/internal/core/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod routers;
|
||||||
|
pub mod runtime;
|
||||||
|
pub mod service;
|
||||||
49
src/internal/core/routers.rs
Normal file
49
src/internal/core/routers.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use hyper::Method;
|
||||||
|
use matchit::Router;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LuaHandle {
|
||||||
|
pub method: String,
|
||||||
|
pub handler_identifier: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Routers {
|
||||||
|
routers: HashMap<u16, Router<LuaHandle>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Routers {
|
||||||
|
pub fn from(apps: HashMap<u16, (String, Vec<(Method, String, String)>)>) -> Self {
|
||||||
|
Self {
|
||||||
|
routers: {
|
||||||
|
let mut routers: HashMap<u16, Router<LuaHandle>> = HashMap::new();
|
||||||
|
for (port, (_id, lua_paths)) in apps {
|
||||||
|
for (method, path, handler_identifier) in lua_paths.iter() {
|
||||||
|
let lua_handle = LuaHandle {
|
||||||
|
method: method.to_string(),
|
||||||
|
handler_identifier: handler_identifier.to_owned(),
|
||||||
|
};
|
||||||
|
if let Some(router) = routers.get_mut(&port) {
|
||||||
|
router.insert(path, lua_handle).unwrap();
|
||||||
|
} else {
|
||||||
|
let mut new_router = Router::new();
|
||||||
|
new_router.insert(path, lua_handle).unwrap();
|
||||||
|
routers.insert(port, new_router);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routers
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for Routers {
|
||||||
|
type Item = (u16, Router<LuaHandle>);
|
||||||
|
type IntoIter = <HashMap<u16, Router<LuaHandle>> as IntoIterator>::IntoIter;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.routers.to_owned().into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/internal/core/runtime.rs
Normal file
75
src/internal/core/runtime.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use std::{collections::HashMap, net::SocketAddr, rc::Rc};
|
||||||
|
|
||||||
|
use futures::future::join_all;
|
||||||
|
use hyper::{Method, Server};
|
||||||
|
use mlua::Lua;
|
||||||
|
use tokio::task::LocalSet;
|
||||||
|
|
||||||
|
use crate::internal::{
|
||||||
|
core::service::{LocalExec, MakeSvc},
|
||||||
|
lua::app::App,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::routers::Routers;
|
||||||
|
|
||||||
|
pub struct Runtime {
|
||||||
|
pub lua: Rc<Lua>,
|
||||||
|
pub routers: Routers,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Runtime {
|
||||||
|
pub fn from_script(lua_script: &Vec<u8>) -> Result<Self, &str> {
|
||||||
|
let lua = Rc::new(Lua::new());
|
||||||
|
|
||||||
|
lua.globals().set("internal_app_counter", 0).unwrap();
|
||||||
|
|
||||||
|
let app_constructor = lua.create_function(|l, ()| {
|
||||||
|
let app_counter: u16 = l.globals().get("internal_app_counter")?;
|
||||||
|
l.globals().set("internal_app_counter", app_counter + 1)?;
|
||||||
|
Ok(App {
|
||||||
|
id: app_counter + 1,
|
||||||
|
handlers: Vec::new(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
lua.globals()
|
||||||
|
.set("create_app", app_constructor.unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
lua.load(std::str::from_utf8(lua_script).unwrap())
|
||||||
|
.eval::<()>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let apps = lua
|
||||||
|
.to_owned()
|
||||||
|
.app_data_ref::<HashMap<u16, (String, Vec<(Method, String, String)>)>>()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
lua: lua.to_owned(),
|
||||||
|
routers: Routers::from(apps),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&self, f: &dyn Fn(&Lua) -> ()) {
|
||||||
|
f(&self.lua);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(&self) {
|
||||||
|
let mut servers = Vec::new();
|
||||||
|
|
||||||
|
for (port, router) in self.routers.to_owned() {
|
||||||
|
println!("Server listening at http://localhost:{}", port);
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
||||||
|
let server = Server::bind(&addr)
|
||||||
|
.executor(LocalExec)
|
||||||
|
.serve(MakeSvc(self.lua.to_owned(), router));
|
||||||
|
servers.push(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create `LocalSet` to spawn !Send futures
|
||||||
|
let local = LocalSet::new();
|
||||||
|
local.run_until(join_all(servers)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
227
src/internal/core/service.rs
Normal file
227
src/internal/core/service.rs
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
use hyper::body::to_bytes;
|
||||||
|
use hyper::server::conn::AddrStream;
|
||||||
|
use hyper::service::Service;
|
||||||
|
use hyper::{Body, Request, Response, StatusCode};
|
||||||
|
use matchit::Router;
|
||||||
|
use mlua::{Error as LuaError, Function, Lua};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use tokio::task::spawn_local;
|
||||||
|
|
||||||
|
use crate::internal::lua::req::Req;
|
||||||
|
use crate::internal::lua::res::Res;
|
||||||
|
|
||||||
|
use super::routers::LuaHandle;
|
||||||
|
|
||||||
|
pub struct Svc(Rc<Lua>, SocketAddr, Router<LuaHandle>);
|
||||||
|
|
||||||
|
impl Service<Request<Body>> for Svc {
|
||||||
|
type Response = Response<Body>;
|
||||||
|
type Error = LuaError;
|
||||||
|
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||||
|
let (parts, body) = req.into_parts();
|
||||||
|
let lua = self.0.clone();
|
||||||
|
let addr = self.1.clone();
|
||||||
|
let router = self.2.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
let uri = parts.uri.to_string();
|
||||||
|
let lua_handle_match = match router.at(uri.as_str()) {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(_) => {
|
||||||
|
return Ok(Response::builder()
|
||||||
|
.status(404)
|
||||||
|
.body(Body::from("Not Found"))
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if lua_handle_match.value.method != parts.method.to_string() {
|
||||||
|
return Ok(Response::builder()
|
||||||
|
.status(405)
|
||||||
|
.body(Body::from("Method Not Allowed"))
|
||||||
|
.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let body_bytes = to_bytes(body).await.unwrap();
|
||||||
|
let body_str = String::from_utf8(body_bytes.to_vec()).unwrap();
|
||||||
|
|
||||||
|
let mut headers_map: HashMap<String, String> = HashMap::new();
|
||||||
|
for (k, v) in parts.headers {
|
||||||
|
headers_map.insert(k.unwrap().to_string(), v.to_str().unwrap().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut params_map: HashMap<String, String> = HashMap::new();
|
||||||
|
for (k, v) in lua_handle_match.params.iter() {
|
||||||
|
params_map.insert(k.to_string(), v.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let req = Req {
|
||||||
|
body: body_str,
|
||||||
|
headers: headers_map,
|
||||||
|
method: lua_handle_match.value.method.to_string(),
|
||||||
|
params: params_map,
|
||||||
|
socket_addr: addr.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = Res {
|
||||||
|
body: "".to_string(),
|
||||||
|
status: StatusCode::OK,
|
||||||
|
};
|
||||||
|
|
||||||
|
let handler: Function = lua
|
||||||
|
.named_registry_value(&lua_handle_match.value.handler_identifier)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match handler.call_async::<_, Res>((req, res)).await {
|
||||||
|
Ok(res) => Ok(Response::builder()
|
||||||
|
.status(res.status)
|
||||||
|
.body(Body::from(res.body))
|
||||||
|
.unwrap()),
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(500)
|
||||||
|
.body(Body::from("Internal Server Error"))
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MakeSvc(pub Rc<Lua>, pub Router<LuaHandle>);
|
||||||
|
|
||||||
|
impl Service<&AddrStream> for MakeSvc {
|
||||||
|
type Response = Svc;
|
||||||
|
type Error = hyper::Error;
|
||||||
|
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, stream: &AddrStream) -> Self::Future {
|
||||||
|
let lua = self.0.clone();
|
||||||
|
let router = self.1.clone();
|
||||||
|
let remote_addr = stream.remote_addr();
|
||||||
|
Box::pin(async move { Ok(Svc(lua, remote_addr, router)) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct LocalExec;
|
||||||
|
|
||||||
|
impl<F> hyper::rt::Executor<F> for LocalExec
|
||||||
|
where
|
||||||
|
F: std::future::Future + 'static, // not requiring `Send`
|
||||||
|
{
|
||||||
|
fn execute(&self, fut: F) {
|
||||||
|
spawn_local(fut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use hyper::Method;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_default() {
|
||||||
|
let lua = Rc::new(Lua::new());
|
||||||
|
let router = Router::new();
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 42));
|
||||||
|
let mut service = Svc(lua, addr, router);
|
||||||
|
|
||||||
|
let mut f = service
|
||||||
|
.call(Request::get("/").body(Body::from("".to_string())).unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(f.status().as_u16(), 404);
|
||||||
|
|
||||||
|
let body_bytes = to_bytes(f.body_mut()).await.unwrap();
|
||||||
|
let body_str = String::from_utf8(body_bytes.to_vec()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(body_str, "Not Found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_complete() {
|
||||||
|
let lua = Rc::new(Lua::new());
|
||||||
|
let mut router = Router::new();
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 42));
|
||||||
|
|
||||||
|
// Create a lua handler
|
||||||
|
let handler = lua
|
||||||
|
.create_async_function(|_, ()| async {
|
||||||
|
Ok(Res {
|
||||||
|
status: StatusCode::IM_A_TEAPOT,
|
||||||
|
body: "Hello, World!".to_string(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let handler_identifier = "response_handler";
|
||||||
|
|
||||||
|
// Register handler in lua state
|
||||||
|
lua.set_named_registry_value(handler_identifier, handler)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Register `matchit` handler
|
||||||
|
router
|
||||||
|
.insert(
|
||||||
|
"/root",
|
||||||
|
LuaHandle {
|
||||||
|
method: Method::GET.to_string(),
|
||||||
|
handler_identifier: handler_identifier.to_string(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Create service
|
||||||
|
let mut service = Svc(lua.clone(), addr, router);
|
||||||
|
|
||||||
|
// 405 Method Not Allowed
|
||||||
|
let mut response = service
|
||||||
|
.call(
|
||||||
|
Request::post("/root")
|
||||||
|
.body(Body::from("".to_string()))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let status = response.status();
|
||||||
|
let body = to_bytes(response.body_mut()).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(status, StatusCode::METHOD_NOT_ALLOWED);
|
||||||
|
assert_eq!(body, "Method Not Allowed");
|
||||||
|
|
||||||
|
// Happy path GET
|
||||||
|
let mut response = service
|
||||||
|
.call(
|
||||||
|
Request::get("/root")
|
||||||
|
.body(Body::from("".to_string()))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let status = response.status();
|
||||||
|
let body = to_bytes(response.body_mut()).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(status, StatusCode::IM_A_TEAPOT);
|
||||||
|
assert_eq!(body, "Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/internal/lua/app.rs
Normal file
53
src/internal/lua/app.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use hyper::Method;
|
||||||
|
use mlua::{Function, UserData, UserDataMethods};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct App {
|
||||||
|
pub id: u16,
|
||||||
|
pub handlers: Vec<(Method, String, String)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for App {
|
||||||
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method_mut("get", |l, this, (path, cb): (String, Function)| {
|
||||||
|
let handler_identifier = format!("{}-get-{}", this.id, path);
|
||||||
|
l.set_named_registry_value(&handler_identifier, cb)?;
|
||||||
|
this.handlers.push((Method::GET, path, handler_identifier));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_method_mut("post", |l, this, (path, cb): (String, Function)| {
|
||||||
|
let handler_identifier = format!("{}-post-{}", this.id, path);
|
||||||
|
l.set_named_registry_value(&handler_identifier, cb)?;
|
||||||
|
this.handlers.push((Method::POST, path, handler_identifier));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_method_mut("use", |_l, this, (root, app): (String, App)| {
|
||||||
|
for (method, path, handler_identifier) in app.handlers {
|
||||||
|
let sub_path = if path == "/" {
|
||||||
|
root.to_owned()
|
||||||
|
} else {
|
||||||
|
[root.to_owned(), path].join("")
|
||||||
|
};
|
||||||
|
this.handlers.push((method, sub_path, handler_identifier));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
methods.add_method_mut("run", |l, this, port: u16| {
|
||||||
|
if let Some(mut apps) =
|
||||||
|
l.app_data_mut::<HashMap<u16, (String, Vec<(Method, String, String)>)>>()
|
||||||
|
{
|
||||||
|
apps.insert(port, (this.id.to_string(), this.handlers.to_owned()));
|
||||||
|
} else {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert(port, (this.id.to_string(), this.handlers.to_owned()));
|
||||||
|
l.set_app_data(map);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/internal/lua/mod.rs
Normal file
3
src/internal/lua/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod app;
|
||||||
|
pub mod req;
|
||||||
|
pub mod res;
|
||||||
45
src/internal/lua/req.rs
Normal file
45
src/internal/lua/req.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use mlua::{LuaSerdeExt, UserData, UserDataFields};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Req {
|
||||||
|
pub body: String,
|
||||||
|
pub headers: HashMap<String, String>,
|
||||||
|
pub method: String,
|
||||||
|
pub params: HashMap<String, String>,
|
||||||
|
pub socket_addr: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for Req {
|
||||||
|
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_set("body", |_, this, value| {
|
||||||
|
this.body = value;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("body", |l, this| {
|
||||||
|
match serde_json::from_str::<serde_json::Value>(&this.body) {
|
||||||
|
Ok(value) => Ok(l.to_value(&value)?),
|
||||||
|
Err(_) => Ok(l.to_value(&this.body)?),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.add_field_method_set("headers", |_, this, value| {
|
||||||
|
this.headers = value;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("headers", |_, this| Ok(this.headers.to_owned()));
|
||||||
|
|
||||||
|
fields.add_field_method_set("method", |_, this, value| {
|
||||||
|
this.method = value;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("method", |_, this| Ok(this.method.to_owned()));
|
||||||
|
|
||||||
|
fields.add_field_method_set("params", |_, this, value| {
|
||||||
|
this.params = value;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("params", |_, this| Ok(this.params.to_owned()));
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/internal/lua/res.rs
Normal file
39
src/internal/lua/res.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use mlua::{Error as LuaError, UserData, UserDataFields, Value as LuaValue};
|
||||||
|
|
||||||
|
pub fn json_encode(value: LuaValue, pretty: Option<bool>) -> Result<Option<String>, LuaError> {
|
||||||
|
match pretty {
|
||||||
|
Some(true) => match serde_json::to_string_pretty(&value) {
|
||||||
|
Ok(s) => Ok(Some(s)),
|
||||||
|
Err(e) => Err(LuaError::SerializeError(e.to_string())),
|
||||||
|
},
|
||||||
|
_ => match serde_json::to_string(&value) {
|
||||||
|
Ok(s) => Ok(Some(s)),
|
||||||
|
Err(e) => Err(LuaError::SerializeError(e.to_string())),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Res {
|
||||||
|
pub status: StatusCode,
|
||||||
|
pub body: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for Res {
|
||||||
|
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_set("body", |_, this, value| {
|
||||||
|
this.body = json_encode(value, None).unwrap().unwrap();
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("body", |_, this| Ok(this.body.to_owned()));
|
||||||
|
|
||||||
|
fields.add_field_method_set("status", |_, this, value: String| {
|
||||||
|
this.status = StatusCode::from_str(value.as_str()).unwrap();
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("status", |_, this| Ok(this.status.as_str().to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/internal/mod.rs
Normal file
2
src/internal/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod core;
|
||||||
|
pub mod lua;
|
||||||
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod api;
|
||||||
|
pub mod internal;
|
||||||
Loading…
Reference in New Issue
Block a user