commit 2876eea11ff6cd345343b21f49c04a23c5d87ae6 Author: Fabian Stamm Date: Sun Sep 29 16:41:44 2024 +0200 First Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..61fd370 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1601 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[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", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jrpc-syntax" +version = "0.0.1" +dependencies = [ + "zed_extension_api", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "libjrpc" +version = "0.1.0" +dependencies = [ + "anyhow", + "ctor", + "env_logger", + "lazy_static", + "log", + "regex", + "reqwest", + "url", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[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 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[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 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64", + "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 = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spdx" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +dependencies = [ + "smallvec", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[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-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[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]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "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 = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm-encoder" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fd83062c17b9f4985d438603cde0a5e8c5c8198201a6937f778b607924c7da2" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288f992ea30e6b5c531b52cdd5f3be81c148554b09ea416f058d16556ba92c27" +dependencies = [ + "bitflags", + "wit-bindgen-rt", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85e72719ffbccf279359ad071497e47eb0675fe22106dea4ed2d8a7fcb60ba4" +dependencies = [ + "anyhow", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb8738270f32a2d6739973cbbb7c1b6dd8959ce515578a6e19165853272ee64" + +[[package]] +name = "wit-bindgen-rust" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a39a15d1ae2077688213611209849cad40e9e5cccf6e61951a425850677ff3" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d376d3ae5850526dfd00d937faea0d81a06fa18f7ac1e26f386d760f241a8f4b" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421c0c848a0660a8c22e2fd217929a0191f14476b68962afd2af89fd22e39825" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.201.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196d3ecfc4b759a8573bf86a9b3f8996b304b3732e4c7de81655f875f6efdca6" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zed_extension_api" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "594fd10dd0f2f853eb243e2425e7c95938cef49adb81d9602921d002c5e6d9d9" +dependencies = [ + "serde", + "serde_json", + "wit-bindgen", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9bd654d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["crates/zed", "crates/libjrpc"] diff --git a/crates/libjrpc/.gitignore b/crates/libjrpc/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/crates/libjrpc/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/libjrpc/Cargo.toml b/crates/libjrpc/Cargo.toml new file mode 100644 index 0000000..6efe167 --- /dev/null +++ b/crates/libjrpc/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "libjrpc" +version = "0.1.0" +edition = "2021" + +[features] +default = ["http"] +http = ["dep:reqwest", "dep:url"] + +[dependencies] +anyhow = "1.0.89" +lazy_static = "1.5.0" +log = "0.4.22" +regex = "1.10.6" +reqwest = { version = "0.12.7", optional = true, features = ["blocking"] } +url = { version = "2.5.2", optional = true } + +[dev-dependencies] +env_logger = "0.11.5" +ctor = "*" diff --git a/crates/libjrpc/src/ir.rs b/crates/libjrpc/src/ir.rs new file mode 100644 index 0000000..b49429c --- /dev/null +++ b/crates/libjrpc/src/ir.rs @@ -0,0 +1,461 @@ +use std::{ + collections::{HashMap, HashSet}, + error::Error, + fmt::Display, + hash::{Hash, Hasher}, +}; + +use anyhow::Result; + +use crate::parser::{ + EnumStatement, Node, ParserPosition, RootNode, ServiceStatement, TypeStatement, +}; + +static BUILT_INS: [&str; 4] = ["int", "float", "string", "boolean"]; + +pub trait Definition { + fn get_position(&self) -> ParserPosition; +} + +#[derive(Debug, Clone)] +pub struct IR { + options: HashMap, + steps: Vec, +} + +#[derive(Debug, Clone)] +pub enum Step { + Type(TypeDefinition), + Enum(EnumDefinition), + Service(ServiceDefinition), +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum Type { + Int, + Float, + String, + Bool, + Custom(String), +} +impl Hash for Type { + fn hash(&self, state: &mut H) { + match self { + Type::Int => "int".hash(state), + Type::Float => "float".hash(state), + Type::String => "string".hash(state), + Type::Bool => "bool".hash(state), + Type::Custom(name) => name.hash(state), + } + } +} + +#[derive(Debug, Clone)] +pub struct TypeDefinition { + name: String, + depends: HashSet, + fields: Vec, + position: ParserPosition, +} + +impl Definition for TypeDefinition { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } +} + +#[derive(Debug, Clone)] +pub struct Field { + name: String, + typ: Type, + array: bool, + optional: bool, + map: Option, +} + +#[derive(Debug, Clone)] +pub struct EnumDefinition { + name: String, + values: Vec, + position: ParserPosition, +} + +impl Definition for EnumDefinition { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } +} + +#[derive(Debug, Clone)] +pub struct EnumField { + name: String, + value: i32, +} + +#[derive(Debug, Clone)] +pub struct ServiceDefinition { + name: String, + depends: HashSet, + methods: Vec, + position: ParserPosition, +} + +impl Definition for ServiceDefinition { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } +} + +#[derive(Debug, Clone)] +pub struct Method { + name: String, + inputs: Vec, + output: Option, + decorators: MethodDecorators, +} + +#[derive(Debug, Clone)] +pub struct MethodInput { + name: String, + typ: Type, + array: bool, + optional: bool, +} + +#[derive(Debug, Clone)] +pub struct MethodOutput { + typ: Type, + array: bool, +} + +#[derive(Debug, Clone)] +pub struct MethodDecorators { + description: Option, + parameter_descriptions: HashMap, + return_description: Option, +} + +fn typename_to_type(name: &str) -> Type { + match name { + "int" => Type::Int, + "float" => Type::Float, + "string" => Type::String, + "boolean" => Type::Bool, + "bool" => Type::Bool, + _ => Type::Custom(name.to_string()), + } +} + +fn build_type(stmt: &TypeStatement) -> Result { + let mut typedef = TypeDefinition { + position: stmt.position.clone(), + name: stmt.name.clone(), + depends: HashSet::new(), + fields: Vec::new(), + }; + + for field in &stmt.fields { + let typ = typename_to_type(&field.fieldtype); + typedef.depends.insert(typ.clone()); + + if let Some(maptype) = &field.map { + if maptype != "string" && maptype != "int" { + return Err(IRError::new("Map type must be string or int", field).into()); + } + } + + typedef.fields.push(Field { + name: field.name.clone(), + typ: typ.clone(), + array: field.array, + optional: field.optional, + map: field.map.as_ref().map(|s| typename_to_type(s)), + }); + } + + Ok(typedef) +} + +fn build_enum(stmt: &EnumStatement) -> Result { + let mut enumdef = EnumDefinition { + position: stmt.position.clone(), + name: stmt.name.clone(), + values: Vec::new(), + }; + + let mut last = -1 as i32; + for field in &stmt.values { + let value = if let Some(value) = field.value { + if value > std::i32::MAX as i64 { + return Err(IRError::new("Enum value too large", field).into()); + } + let value = value as i32; + if value <= last { + return Err(IRError::new("Enum values must be increasing", field).into()); + } + last = value; + value + } else { + last = last + 1; + last + }; + enumdef.values.push(EnumField { + name: field.name.clone(), + value, + }); + } + Ok(enumdef) +} + +fn build_service(stmt: &ServiceStatement) -> Result { + let mut servdef = ServiceDefinition { + position: stmt.position.clone(), + name: stmt.name.clone(), + depends: HashSet::new(), + methods: Vec::new(), + }; + + for method in &stmt.methods { + let mut methoddef = Method { + name: method.name.clone(), + inputs: Vec::new(), + output: method.return_type.as_ref().map(|rt| { + let typ = typename_to_type(&rt.fieldtype); + servdef.depends.insert(typ.clone()); + MethodOutput { + typ, + array: rt.array, + } + }), + decorators: MethodDecorators { + description: None, + parameter_descriptions: HashMap::new(), + return_description: None, + }, + }; + + let mut optional_starts = false; + for inp in &method.inputs { + let typ = typename_to_type(&inp.fieldtype); + servdef.depends.insert(typ.clone()); + + if optional_starts && !inp.optional { + return Err( + IRError::new("Optional fields must come after required fields", inp).into(), + ); + } + + if inp.optional { + optional_starts = true; + } + + methoddef.inputs.push(MethodInput { + name: inp.name.clone(), + typ, + array: inp.array, + optional: inp.optional, + }); + } + + for decorator in &method.decorators { + match decorator.name.as_str() { + "Description" => { + if methoddef.decorators.description.is_some() { + return Err(IRError::new("Duplicate description", decorator).into()); + } + + if decorator.args.len() != 1 { + return Err(IRError::new( + "Description must have exactly one argument", + decorator, + ) + .into()); + } + + methoddef.decorators.description = Some(decorator.args[0].clone()); + } + "Returns" => { + if methoddef.decorators.return_description.is_some() { + return Err(IRError::new("Duplicate return description", decorator).into()); + } + + if decorator.args.len() != 1 { + return Err(IRError::new( + "Returns must have exactly one argument", + decorator, + ) + .into()); + } + + methoddef.decorators.return_description = Some(decorator.args[0].clone()); + } + "Param" => { + if decorator.args.len() != 2 { + return Err(IRError::new( + "Param must have exactly two arguments", + decorator, + ) + .into()); + } + + let name = decorator.args[0].clone(); + let description = decorator.args[1].clone(); + + if methoddef + .decorators + .parameter_descriptions + .contains_key(&name) + { + return Err( + IRError::new("Duplicate parameter description", decorator).into() + ); + } + + if methoddef.inputs.iter().find(|i| i.name == name).is_none() { + return Err(IRError::new("Parameter not found", decorator).into()); + } + + methoddef + .decorators + .parameter_descriptions + .insert(name, description); + } + _ => { + return Err(IRError::new("Unknown decorator", decorator).into()); + } + } + } + servdef.methods.push(methoddef); + } + + Ok(servdef) +} + +pub fn build_ir(root: &Vec) -> Result { + let mut options = HashMap::::new(); + let mut steps = Vec::new(); + + for node in root { + match node { + RootNode::Type(stmt) => steps.push(Step::Type(build_type(stmt)?)), + RootNode::Enum(stmt) => steps.push(Step::Enum(build_enum(stmt)?)), + RootNode::Service(stmt) => steps.push(Step::Service(build_service(stmt)?)), + RootNode::Define(stmt) => { + if options.contains_key(&stmt.key) { + return Err(IRError::new("Duplicate define", stmt).into()); + } + + if (stmt.key == "use_messagepack" || stmt.key == "allow_bytes") + && stmt.value == "true" + { + options.insert("allow_bytes".to_owned(), "true".to_owned()); + } + options.insert(stmt.key.clone(), stmt.value.clone()); + } + RootNode::Import(_) => { + panic!("Import not supported at this stage!"); + } + } + } + + let mut all_types = HashSet::::new(); + let mut serv_types = HashSet::::new(); + + for bi in &BUILT_INS { + all_types.insert(bi.to_string()); + } + + for step in &steps { + match step { + Step::Type(typedef) => { + if all_types.contains(&typedef.name) { + return Err(IRError::new_from_def("Duplicate type", typedef).into()); + } + + all_types.insert(typedef.name.clone()); + } + Step::Enum(enumdef) => { + if all_types.contains(&enumdef.name) { + return Err(IRError::new_from_def("Duplicate type", enumdef).into()); + } + + all_types.insert(enumdef.name.clone()); + } + Step::Service(servdef) => { + if serv_types.contains(&servdef.name) { + return Err(IRError::new_from_def("Duplicate type", servdef).into()); + } + + serv_types.insert(servdef.name.clone()); + } + } + } + + // Verify dependencies + + for step in &steps { + match step { + Step::Type(typedef) => { + for dep in &typedef.depends { + if let Type::Custom(dep) = dep { + if !all_types.contains(dep) { + return Err(IRError::new_from_def( + &format!("Type {} depends on unknown type {}", typedef.name, dep), + typedef, + ) + .into()); + } + } + } + } + Step::Service(servdef) => { + for dep in &servdef.depends { + if let Type::Custom(dep) = dep { + if !all_types.contains(dep) { + return Err(IRError::new_from_def( + &format!( + "Service {} depends on unknown type {}", + servdef.name, dep + ), + servdef, + ) + .into()); + } + } + } + } + _ => {} + } + } + + Ok(IR { options, steps }) +} + +#[derive(Debug, Clone)] +pub struct IRError { + pub message: String, + pub position: ParserPosition, +} + +impl IRError { + fn new(msg: &str, node: &impl Node) -> IRError { + IRError { + message: format!("{}: {}", msg, node.get_name()), + position: node.get_position(), + } + } + + fn new_from_def(msg: &str, def: &impl Definition) -> IRError { + IRError { + message: msg.to_string(), + position: def.get_position(), + } + } +} + +impl Error for IRError {} +impl Display for IRError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ParserError: {} at {:?}", self.message, self.position) + } +} diff --git a/crates/libjrpc/src/lib.rs b/crates/libjrpc/src/lib.rs new file mode 100644 index 0000000..691a2e7 --- /dev/null +++ b/crates/libjrpc/src/lib.rs @@ -0,0 +1,39 @@ +mod ir; +mod parser; +mod process; +mod shared; +mod tokenizer; + +pub use tokenizer::{tokenize, Token, TokenError, TokenPosition, TokenType}; + +#[cfg(test)] +mod test { + use std::sync::Arc; + + #[cfg(test)] + #[ctor::ctor] + fn init() { + env_logger::init(); + } + + #[test] + pub fn parse_jrpc() { + let tokens = crate::tokenizer::tokenize( + Arc::new("../test.jrpc".to_owned()), + include_str!("../test.jrpc").to_owned(), + ) + .unwrap(); + + let parsed = crate::parser::Parser::new(tokens).parse().unwrap(); + // println!("Parsed: {:?}", parsed); + + let ir = crate::ir::build_ir(&parsed).unwrap(); + println!("IR: {:?}", ir); + + // let result = crate::JRPCParser::parse(crate::Rule::root, ); + // match result { + // Ok(result) => println!("{:?}", result), + // Err(err) => println!("{:?}", err), + // } + } +} diff --git a/crates/libjrpc/src/parser.rs b/crates/libjrpc/src/parser.rs new file mode 100644 index 0000000..6475ff3 --- /dev/null +++ b/crates/libjrpc/src/parser.rs @@ -0,0 +1,683 @@ +use anyhow::Result; +use log::{debug, trace}; +use std::{collections::HashMap, error::Error, fmt::Display, sync::Arc}; + +use crate::{Token, TokenPosition, TokenType}; + +pub type PResult = Result; + +#[derive(Debug, Clone)] +pub struct ParserPosition { + path: Arc, + position: usize, + token_positions: Vec, +} + +impl ParserPosition { + pub fn from_token(token: &Token) -> Self { + Self { + path: token.2.path.clone(), + position: token.2.start, + token_positions: vec![token.2.clone()], + } + } +} + +pub trait Node { + fn get_position(&self) -> ParserPosition; + fn get_name(&self) -> String { + String::from("") + } +} + +#[derive(Debug, Clone)] +pub enum RootNode { + Define(DefineStatement), + Import(ImportStatement), + Service(ServiceStatement), + Type(TypeStatement), + Enum(EnumStatement), +} + +impl Node for RootNode { + fn get_position(&self) -> ParserPosition { + match self { + RootNode::Define(stmt) => stmt.get_position(), + RootNode::Import(stmt) => stmt.get_position(), + RootNode::Service(stmt) => stmt.get_position(), + RootNode::Type(stmt) => stmt.get_position(), + RootNode::Enum(stmt) => stmt.get_position(), + } + } + + fn get_name(&self) -> String { + match self { + RootNode::Define(_) => String::from("define"), + RootNode::Import(_) => String::from("import"), + RootNode::Service(_) => String::from("service"), + RootNode::Type(_) => String::from("type"), + RootNode::Enum(_) => String::from("enum"), + } + } +} + +#[derive(Debug, Clone)] +pub struct DefineStatement { + pub position: ParserPosition, + pub key: String, + pub value: String, +} +impl Node for DefineStatement { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + fn get_name(&self) -> String { + format!("define {}", self.key) + } +} + +#[derive(Debug, Clone)] +pub struct ImportStatement { + pub position: ParserPosition, + pub path: String, +} +impl Node for ImportStatement { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("import {}", self.path) + } +} + +#[derive(Debug, Clone)] +pub struct TypeStatement { + pub position: ParserPosition, + pub name: String, + pub fields: Vec, +} +impl Node for TypeStatement { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("type {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct TypeFieldNode { + pub position: ParserPosition, + pub name: String, + pub optional: bool, + pub fieldtype: String, + pub array: bool, + pub map: Option, +} +impl Node for TypeFieldNode { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("type_field {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct EnumStatement { + pub position: ParserPosition, + pub name: String, + pub values: Vec, +} +impl Node for EnumStatement { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("enum {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct EnumValueNode { + pub position: ParserPosition, + pub name: String, + pub value: Option, +} +impl Node for EnumValueNode { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("enum_field {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct ServiceStatement { + pub position: ParserPosition, + pub name: String, + pub methods: Vec, +} +impl Node for ServiceStatement { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("service {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct ServiceMethodNode { + pub position: ParserPosition, + pub name: String, + pub inputs: Vec, + pub return_type: Option, + pub decorators: Vec, +} +impl Node for ServiceMethodNode { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("method {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct Decorator { + pub position: ParserPosition, + pub name: String, + pub args: Vec, +} +impl Node for Decorator { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("decorator {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct ServiceMethodInputNode { + pub position: ParserPosition, + pub name: String, + pub fieldtype: String, + pub optional: bool, + pub array: bool, +} +impl Node for ServiceMethodInputNode { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } + + fn get_name(&self) -> String { + format!("method_arg {}", self.name) + } +} + +#[derive(Debug, Clone)] +pub struct ServiceMethodReturnNode { + pub position: ParserPosition, + pub fieldtype: String, + pub array: bool, +} +impl Node for ServiceMethodReturnNode { + fn get_position(&self) -> ParserPosition { + self.position.clone() + } +} + +#[derive(Debug, Clone)] +pub struct Parser { + tokens: Vec, + position: usize, +} + +impl Parser { + pub fn new(tokens: Vec) -> Parser { + // Remove all comments and spaces at this stage + let tokens = tokens + .into_iter() + .filter(|e| e.0 != TokenType::Comment && e.0 != TokenType::Space) + .collect(); + Parser { + tokens, + position: 0, + } + } + + fn has_current_token(&self) -> bool { + self.position < self.tokens.len() + } + + fn current_token(&mut self) -> &Token { + &self.tokens[self.position] + } + + fn assert_types(&mut self, token_types: &[TokenType]) -> PResult<()> { + if token_types.iter().any(|t| *t == self.current_token().0) { + Ok(()) + } else { + Err(ParserError::new( + &format!("Unexpected token. Expected on of {:?}", token_types), + self.current_token(), + )) + } + } + + fn eat_token(&mut self) -> PResult<(String, ParserPosition)> { + debug!("Parser::eat_token()"); + let pos = ParserPosition::from_token(self.current_token()); + let value = self.current_token().1.clone(); + self.position += 1; + Ok((value, pos)) + } + + fn eat_token_value(&mut self, value: &str) -> PResult<(String, ParserPosition)> { + debug!("Parser::eat_token_value({})", value); + let (val, pos) = self.eat_token()?; + + if val != value { + return Err(ParserError::new( + &format!("Expected token of value {}", value), + self.current_token(), + )); + } + + Ok((val, pos)) + } + + fn eat_token_type(&mut self, token_type: TokenType) -> PResult<(String, ParserPosition)> { + debug!("Parser::eat_token_type({:?})", token_type); + if self.current_token().0 != token_type { + return Err(ParserError::new( + &format!("Expected token of type {:?}", token_type), + self.current_token(), + )); + } + + self.eat_token() + } + + fn eat_text(&mut self) -> PResult<(String, ParserPosition)> { + debug!("Parser::eat_text()"); + self.eat_token_type(TokenType::Text) + } + + fn eat_text_with_keywords(&mut self) -> PResult<(String, ParserPosition)> { + debug!("Parser::eat_text_with_keywords()"); + self.assert_types(&[TokenType::Text, TokenType::Keyword])?; + self.eat_token() + } + + fn eat_string_or_text_as_raw(&mut self) -> PResult { + debug!("Parser::eat_string_or_text_as_raw()"); + self.assert_types(&[TokenType::String, TokenType::Text])?; + let token = self.current_token(); + if token.0 == TokenType::String { + let (value, _) = self.eat_token()?; + let count = value.chars().count(); + Ok(value.chars().skip(1).take(count - 2).collect()) + } else { + let (value, _) = self.eat_token()?; + Ok(value) + } + } + + fn eat_number(&mut self) -> PResult { + debug!("Parser::eat_number()"); + self.assert_types(&[TokenType::Number])?; + let (value, _) = self.eat_token()?; + value + .parse() + .map_err(|_| ParserError::new("Invalid number", self.current_token())) + } + + fn parse_define(&mut self) -> PResult { + debug!("Parser::parse_define()"); + let (_, position) = self.eat_token_value("define")?; + + let (key, _) = self.eat_token()?; + trace!("Parser::parse_define()::key = {}", key); + + let value = self.eat_string_or_text_as_raw()?; + + self.eat_token_type(TokenType::Semicolon)?; + + Ok(DefineStatement { + position, + key, + value, + }) + } + + fn parse_import(&mut self) -> PResult { + debug!("Parser::parse_import()"); + let (_, pos) = self.eat_token_value("import")?; + let path = self.eat_string_or_text_as_raw()?; + + self.eat_token_type(TokenType::Semicolon)?; + + Ok(ImportStatement { + position: pos, + path, + }) + } + + fn parse_enum_value(&mut self) -> PResult { + debug!("Parser::parse_enum_value()"); + let (name, pos) = self.eat_token()?; + let value = if self.current_token().0 == TokenType::Equals { + self.eat_token()?; + Some(self.eat_number()?) + } else { + None + }; + + Ok(EnumValueNode { + position: pos, + name, + value, + }) + } + + fn parse_enum(&mut self) -> PResult { + debug!("Parser::parse_enum()"); + let (_, pos) = self.eat_token_value("enum")?; + let (name, _) = self.eat_token()?; + trace!("Parser::parse_enum()::name = {}", name); + + self.eat_token_type(TokenType::CurlyOpen)?; + let mut values: Vec = Vec::new(); + + while self.current_token().0 == TokenType::Text { + values.push(self.parse_enum_value()?); + if self.current_token().0 == TokenType::Comma { + //TODO: Maybe use a next flag or break or something with the commas + self.eat_token()?; + } + } + + self.eat_token_type(TokenType::CurlyClose)?; + + Ok(EnumStatement { + position: pos, + name, + values, + }) + } + + fn parse_type_field(&mut self) -> PResult { + debug!("Parser::parse_type_field()"); + let (name, pos) = self.eat_text_with_keywords()?; + trace!("Parser::parse_type_field()::name = {}", name); + + let mut optional = false; + let mut array = false; + let mut map = None; + + if self.current_token().0 == TokenType::Questionmark { + optional = true; + self.eat_token()?; + } + + _ = self.eat_token_type(TokenType::Colon); + let fieldtype = if self.current_token().0 == TokenType::CurlyOpen { + self.eat_token()?; + let (key_type, _) = self.eat_text()?; + self.eat_token_type(TokenType::Comma)?; + let (value_type, _) = self.eat_text()?; + self.eat_token_type(TokenType::CurlyClose)?; + map = Some(key_type); + value_type + } else { + let (type_name, _) = self.eat_text()?; + if self.current_token().0 == TokenType::Array { + array = true; + self.eat_token()?; + } + + type_name + }; + + self.eat_token_type(TokenType::Semicolon)?; + + Ok(TypeFieldNode { + position: pos, + name, + optional, + fieldtype, + map, + array, + }) + } + + fn parse_type(&mut self) -> PResult { + debug!("Parser::parse_type()"); + let (_, pos) = self.eat_token_value("type")?; + let (name, _) = self.eat_text()?; + trace!("Parser::prase_type()::name = {}", name); + self.eat_token_type(TokenType::CurlyOpen)?; + + let mut fields = Vec::new(); + while self.current_token().0 == TokenType::Text + || self.current_token().0 == TokenType::Keyword + { + fields.push(self.parse_type_field()?); + } + + self.eat_token_type(TokenType::CurlyClose)?; + + Ok(TypeStatement { + position: pos, + name, + fields, + }) + } + + fn parse_decorator(&mut self) -> PResult { + debug!("Parser::parse_decorator()"); + let (_, position) = self.eat_token_type(TokenType::At)?; + let (decorator, _) = self.eat_text()?; + trace!("Parser::parse_decorator()::name = {}", decorator); + + self.eat_token_type(TokenType::BracketOpen)?; + + let mut args = Vec::new(); + let mut first = true; + while self.current_token().0 != TokenType::BracketClose { + if first { + first = false + } else { + self.eat_token_type(TokenType::Comma)?; + } + + args.push(self.eat_string_or_text_as_raw()?); + } + self.eat_token_type(TokenType::BracketClose)?; + + Ok(Decorator { + name: decorator, + args, + position, + }) + } + + fn parse_method( + &mut self, + decorators: Vec, + notification: bool, + ) -> PResult { + debug!( + "Parser::parse_method({}, {})", + decorators.len(), + notification + ); + let (name, pos) = self.eat_text()?; + trace!("Parser::parse_method()::name = {}", name); + + self.eat_token_type(TokenType::BracketOpen)?; + + let mut inputs = Vec::new(); + + while self.current_token().0 != TokenType::BracketClose { + let (name, position) = self.eat_text_with_keywords()?; + + let mut optional = false; + if self.current_token().0 == TokenType::Questionmark { + optional = true; + self.eat_token()?; + } + + self.eat_token_type(TokenType::Colon)?; + let (fieldtype, _) = self.eat_text()?; + let mut array = false; + if self.current_token().0 == TokenType::Array { + array = true; + self.eat_token()?; + } + inputs.push(ServiceMethodInputNode { + name, + fieldtype, + array, + optional, + position, + }); + + if self.current_token().0 == TokenType::Comma { + self.eat_token()?; + } + + trace!( + "Parser::parse_method()::params_next_token: {}", + self.current_token().1 + ); + } + + self.eat_token_type(TokenType::BracketClose)?; + + let mut return_type = None; + if !notification { + self.eat_token_type(TokenType::Colon)?; + + let (fieldtype, position) = self.eat_text()?; + let mut array = false; + if self.current_token().0 == TokenType::Array { + array = true; + self.eat_token()?; + } + + return_type = Some(ServiceMethodReturnNode { + position, + fieldtype, + array, + }); + } + + self.eat_token_type(TokenType::Semicolon)?; + + Ok(ServiceMethodNode { + position: pos, + name, + inputs, + return_type, + decorators, + }) + } + + fn parse_service(&mut self) -> PResult { + debug!("Parser::parse_service()"); + let (_, pos) = self.eat_token_value("service")?; + let (name, _) = self.eat_text()?; + trace!("Parser::parse_service()::name = {}", name); + + self.eat_token_type(TokenType::CurlyOpen)?; + + let mut methods = Vec::new(); + while self.current_token().0 != TokenType::CurlyClose { + let mut decorators = Vec::new(); + while self.current_token().0 == TokenType::At { + decorators.push(self.parse_decorator()?); + } + + let mut notification = false; + if self.current_token().1 == "notification" { + self.eat_token()?; + notification = true; + } + + methods.push(self.parse_method(decorators, notification)?); + } + + self.eat_token_type(TokenType::CurlyClose)?; + + Ok(ServiceStatement { + position: pos, + name, + methods, + }) + } + + fn parse_statement(&mut self) -> PResult { + debug!("Parser::parse_statement()"); + let token = self.current_token(); + + if let TokenType::Keyword = token.0 { + trace!("Parser::parse_statement()::type = {}", token.1); + return match token.1.as_str() { + "define" => Ok(RootNode::Define(self.parse_define()?)), + "import" => Ok(RootNode::Import(self.parse_import()?)), + "type" => Ok(RootNode::Type(self.parse_type()?)), + "service" => Ok(RootNode::Service(self.parse_service()?)), + "enum" => Ok(RootNode::Enum(self.parse_enum()?)), + _ => Err(ParserError::new("Unknown keyword", token)), + }; + } else { + Err(ParserError::new("Expected keyword", token)) + } + } + + pub fn parse(&mut self) -> PResult> { + debug!("Parser::parse()"); + let mut nodes = Vec::new(); + + while self.has_current_token() { + nodes.push(self.parse_statement()?); + } + + Ok(nodes) + } +} + +#[derive(Debug, Clone)] +pub struct ParserError { + pub message: String, + pub token: Token, +} + +impl ParserError { + fn new(msg: &str, token: &Token) -> ParserError { + ParserError { + message: format!("{}: {}", msg, token.1), + token: token.clone(), + } + } +} + +impl Error for ParserError {} +impl Display for ParserError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ParserError: {} at {:?}", self.message, self.token) + } +} diff --git a/crates/libjrpc/src/process.rs b/crates/libjrpc/src/process.rs new file mode 100644 index 0000000..876df3f --- /dev/null +++ b/crates/libjrpc/src/process.rs @@ -0,0 +1,99 @@ +use std::{ + collections::{HashMap, HashSet}, + path::PathBuf, +}; + +use anyhow::Result; +use url::Url; + +use crate::ir::IR; + +pub struct FileProcessor { + file_cache: HashMap, + processed_files: HashSet, +} + +impl FileProcessor { + pub fn new() -> Self { + Self { + file_cache: HashMap::new(), + processed_files: HashSet::new(), + } + } + + fn is_url(inp: Option<&str>) -> bool { + #[cfg(feature = "http")] + if let Some(inp) = inp { + if inp.starts_with("http://") || inp.starts_with("https://") { + return true; + } + } + false + } + + fn resolve_path(input: &str, context: Option<&str>) -> String { + let mut input = input.to_string(); + #[cfg(feature = "http")] + if cfg!(feature = "http") && (Self::is_url(Some(&input)) || Self::is_url(context)) { + if Self::is_url(Some(&input)) { + input.to_string() + } else { + let mut url = Url::parse(context.unwrap()).unwrap(); + if !input.ends_with(".jrpc") { + input = format!("{}.jrpc", input); + } + url.join(&input).unwrap().to_string() + } + } else { + if !input.ends_with(".jrpc") { + input = format!("{}.jrpc", input); + } + if let Some(context) = context { + let mut path = PathBuf::from(context); + path = path.join(input); + path.to_str().unwrap().to_string() + } else { + input + } + } + } + + fn get_file_url(&mut self, url: &str) -> Result { + let resp = reqwest::blocking::get(url)?; + let body = resp.text()?; + self.file_cache.insert(url.to_string(), body.clone()); + Ok(body) + } + + fn get_file_path(&mut self, path: &str) -> Result { + let body = std::fs::read_to_string(path)?; + self.file_cache.insert(path.to_string(), body.clone()); + Ok(body) + } + + fn get_file(&mut self, name: &str) -> Result { + if self.file_cache.contains_key(name) { + return Ok(self.file_cache.get(name).unwrap().clone()); + } else { + #[cfg(feature = "http")] + { + if name.starts_with("http://") || name.starts_with("https://") { + return self.get_file_url(name); + } else { + return self.get_file_path(name); + } + } + + #[cfg(not(feature = "http"))] + { + return self.get_file_path(name); + } + } + } + + fn process_file(&mut self, file: &str, root: bool) {} + + pub fn start_compile(&mut self, file: &str) -> Result { + Err(anyhow::anyhow!("Not implemented")) + } +} diff --git a/crates/libjrpc/src/shared.rs b/crates/libjrpc/src/shared.rs new file mode 100644 index 0000000..61fbb1a --- /dev/null +++ b/crates/libjrpc/src/shared.rs @@ -0,0 +1,7 @@ +pub enum Keywords { + Type, + Enum, + Import, + Service, + Define, +} diff --git a/crates/libjrpc/src/tokenizer.rs b/crates/libjrpc/src/tokenizer.rs new file mode 100644 index 0000000..7ad0ad9 --- /dev/null +++ b/crates/libjrpc/src/tokenizer.rs @@ -0,0 +1,197 @@ +use anyhow::Result; +use lazy_static::lazy_static; +use regex::Regex; +use std::{error::Error, fmt::Display, sync::Arc}; + +fn match_regex(regex: &Regex, input: &str, index: usize) -> Option { + // println!("Matching regex {:?} at index {}", regex, index); + let (_, b) = input.split_at(index); + let Some(caps) = regex.captures(b) else { + return None; + }; + + let capture = caps.get(0).unwrap(); + + if capture.start() != 0 { + return None; + } + + Some(capture.as_str().to_owned()) +} + +struct TokenizerRegex(Regex, TokenType); + +lazy_static! { + static ref REGEXES: Vec = { + let mut regexes = Vec::new(); + + regexes.push(TokenizerRegex( + Regex::new(r#"^\s+"#).unwrap(), + TokenType::Space, + )); + regexes.push(TokenizerRegex( //FIXME: This regex is not working + Regex::new(r#"(?s)^(\/\*)(.|\s)*?(\*\/)/"#).unwrap(), + TokenType::Comment, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\/\/.+"#).unwrap(), + TokenType::Comment, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^#.+"#).unwrap(), + TokenType::Comment, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^".*?""#).unwrap(), + TokenType::String, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^(type|enum|import|service|define)\b"#).unwrap(), + TokenType::Keyword, + )); + regexes.push(TokenizerRegex(Regex::new(r#"^\@"#).unwrap(), TokenType::At)); + regexes.push(TokenizerRegex( + Regex::new(r#"^\:"#).unwrap(), + TokenType::Colon, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\;"#).unwrap(), + TokenType::Semicolon, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\,"#).unwrap(), + TokenType::Comma, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\="#).unwrap(), + TokenType::Equals, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\{"#).unwrap(), + TokenType::CurlyOpen, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\}"#).unwrap(), + TokenType::CurlyClose, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\("#).unwrap(), + TokenType::BracketOpen, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\)"#).unwrap(), + TokenType::BracketClose, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\[\]"#).unwrap(), + TokenType::Array, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^\?"#).unwrap(), + TokenType::Questionmark, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^[\.0-9]+"#).unwrap(), + TokenType::Number, + )); + regexes.push(TokenizerRegex( + Regex::new(r#"^[a-zA-Z_]([a-zA-Z0-9_]?)+"#).unwrap(), + TokenType::Text, + )); + + regexes + }; +} + +#[derive(Debug, Clone)] +pub struct TokenPosition { + pub path: Arc, + pub start: usize, + pub end: usize, +} + +impl TokenPosition { + pub fn new(path: Arc, start: usize, end: usize) -> Self { + Self { path, start, end } + } +} + +impl Display for TokenPosition { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + //TODO: Map index to line and column + write!(f, "{}:{}:{}", self.path, self.start, self.end) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum TokenType { + Space, + Comment, + String, + Keyword, + At, + Colon, + Semicolon, + Comma, + Equals, + CurlyOpen, + CurlyClose, + BracketOpen, + BracketClose, + Array, + Questionmark, + Number, + Text, +} + +#[derive(Debug, Clone)] +pub struct TokenError { + pub message: String, + pub position: TokenPosition, +} + +impl Error for TokenError {} +impl Display for TokenError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "TokenError: {} at {:?}", self.message, self.position) + } +} + +#[derive(Debug, Clone)] +pub struct Token(pub TokenType, pub String, pub TokenPosition); + +pub fn tokenize(path: Arc, input: String) -> Result> { + let mut tokens = Vec::new(); + let mut index = 0; + + while index < input.len() { + let res = REGEXES + .iter() + .map(|regex| (match_regex(®ex.0, &input, index), regex.1)) + .find(|x| x.0.is_some()); + + if let Some(mat) = res { + let value = mat.0.unwrap(); + let value_len = value.len(); + tokens.push(Token( + mat.1, + value, + TokenPosition::new(path.clone(), index, index + value_len), + )); + index += value_len; + } else { + return Err(TokenError { + message: format!( + "Unexpected character: {}", + input.chars().skip(index).take(4).collect::() + ), + position: TokenPosition::new(path.clone(), index, index + 1), + } + .into()); + } + } + + // println!("{:?}", tokens); + + Ok(tokens) +} diff --git a/crates/libjrpc/test.jrpc b/crates/libjrpc/test.jrpc new file mode 100644 index 0000000..50c6bd2 --- /dev/null +++ b/crates/libjrpc/test.jrpc @@ -0,0 +1,75 @@ +// Test +// import "./import"; + +define csharp_namespace Example; +define rust_crate example; +define dart_library_name example; + +enum TestEnum { + VAL1, + VAL2, + VAL10 = 10, + VAL11, + VAL12 +} + +type Test { + atom: TestAtom; + array: TestAtom[]; + enumValue: TestEnum; + map: {int, TestAtom}; +} + + +type AddValueRequest { + value1: float; + value2: float; +} + +type AddValueResponse { + value: float; +} + +service TestService { + @Description("Add two numbers") + @Param("request", "Parameter containing the two numbers") + @Returns("") + AddValuesSingleParam(request: AddValueRequest): AddValueResponse; + + @Description("Add two numbers") + @Param("value1", "The first value") + @Param("value2", "The second value") + AddValuesMultipleParams(value1: float, value2: float): float; + + @Description("Does literaly nothing") + @Param("param1", "Some number") + ReturningVoid(param1: float): void; + + @Description("Just sends an Event with a String") + @Param("param1", "Parameter with some string for event") + notification OnEvent(param1: string); + + ThrowingError(): void; + + + FunctionWithArrayAsParamAndReturn(values1: float[], values2: float[]): float[]; + + FunctionWithKeywords(type: float, static: float, event: float): float; +} + +type Test2 { + name: string; + age: int; +} + +type TestKeywords { + type: float; + static: float; + event: float; +} + +service SimpleTestService { + @Description("asdasdasd") + GetTest(name: string, age: int): Test2; + notification TestNot(); +} diff --git a/crates/zed/.gitignore b/crates/zed/.gitignore new file mode 100644 index 0000000..8a5d274 --- /dev/null +++ b/crates/zed/.gitignore @@ -0,0 +1,2 @@ +target/ +JsonRPC/ diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml new file mode 100644 index 0000000..59b7bf3 --- /dev/null +++ b/crates/zed/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "jrpc-syntax" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +zed_extension_api = "0.1.0" diff --git a/crates/zed/extension.toml b/crates/zed/extension.toml new file mode 100644 index 0000000..46658ac --- /dev/null +++ b/crates/zed/extension.toml @@ -0,0 +1,7 @@ +id = "jrpc-syntax" +name = "JRPC Syntax" +version = "0.0.1" +schema_version = 1 +authors = ["Fabian Stamm "] +description = "Adds JRPC syntax highlighting to Zed" +repository = "https://github.com/" diff --git a/crates/zed/src/lib.rs b/crates/zed/src/lib.rs new file mode 100644 index 0000000..e312cba --- /dev/null +++ b/crates/zed/src/lib.rs @@ -0,0 +1,17 @@ +use zed_extension_api as zed; + +struct JRPCSyntaxExtension { + // ... state +} + +impl zed::Extension for JRPCSyntaxExtension { + fn new() -> Self + where + Self: Sized, + { + todo!() + } + // ... +} + +zed::register_extension!(JRPCSyntaxExtension);