Merge branch 'main' into feat/dns-policy

# Conflicts:
#	Cargo.lock
#	easytier/build/main.rs
This commit is contained in:
Luna Yao
2026-05-15 14:56:13 +02:00
9 changed files with 961 additions and 737 deletions
Generated
+233 -258
View File
@@ -915,7 +915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59"
dependencies = [
"once_cell",
"proc-macro-crate 3.5.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -1604,9 +1604,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
dependencies = [
"crossbeam-utils",
]
@@ -1641,9 +1641,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crunchy"
@@ -1981,6 +1981,37 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "derive_builder"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
"darling 0.20.10",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "derive_builder_macro"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn 2.0.117",
]
[[package]]
name = "derive_more"
version = "0.99.20"
@@ -2231,30 +2262,28 @@ dependencies = [
"defguard_wireguard_rs",
"delegate",
"derivative",
"derive_builder",
"derive_more 2.1.1",
"easytier-rpc-build",
"encoding",
"flume 0.12.0",
"forwarded-header-value",
"futures",
"futures-util",
"getset",
"gethostname 0.5.0",
"git-version",
"globwalk",
"guarden",
"hickory-net",
"hickory-client",
"hickory-proto",
"hickory-resolver",
"hickory-server",
"hmac",
"hostname",
"http",
"http_req",
"humansize",
"humantime-serde",
"idna 1.0.3",
"igd-next",
"indexmap 2.14.0",
"indoc",
"itertools 0.14.0",
"kcp-sys",
@@ -2272,7 +2301,6 @@ dependencies = [
"nix 0.29.0",
"once_cell",
"openssl",
"optionize",
"ordered_hash_map",
"parking_lot",
"paste",
@@ -2280,7 +2308,8 @@ dependencies = [
"petgraph 0.8.1",
"pin-project-lite",
"pnet",
"prefix-trie 0.7.0",
"prefix-trie",
"proc-macro2",
"prost",
"prost-build",
"prost-reflect",
@@ -2290,6 +2319,7 @@ dependencies = [
"prost-wkt-types",
"quinn",
"quinn-plaintext",
"quote",
"rand 0.8.5",
"rcgen",
"regex",
@@ -2302,7 +2332,6 @@ dependencies = [
"rustls",
"serde",
"serde_json",
"serde_with",
"serial_test",
"service-manager",
"sha2",
@@ -2330,7 +2359,6 @@ dependencies = [
"tokio-util",
"tokio-websockets",
"toml 0.8.19",
"tonic-build",
"tracing",
"tracing-subscriber",
"tun-easytier",
@@ -2357,7 +2385,7 @@ version = "0.1.0"
dependencies = [
"android_logger",
"easytier",
"jni 0.21.1",
"jni",
"log",
"once_cell",
"serde",
@@ -2386,7 +2414,7 @@ dependencies = [
"dashmap",
"dunce",
"easytier",
"gethostname",
"gethostname 1.1.0",
"libc",
"once_cell",
"security-framework-sys",
@@ -2409,14 +2437,6 @@ dependencies = [
"windows 0.52.0",
]
[[package]]
name = "easytier-rpc-build"
version = "0.1.0"
dependencies = [
"heck 0.5.0",
"prost-build",
]
[[package]]
name = "easytier-uptime"
version = "0.1.0"
@@ -2681,6 +2701,24 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "enum-as-inner"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "enumflags2"
version = "0.7.12"
@@ -3238,6 +3276,19 @@ dependencies = [
"x11",
]
[[package]]
name = "generator"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
dependencies = [
"cfg-if",
"libc",
"log",
"rustversion",
"windows 0.58.0",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -3249,6 +3300,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "gethostname"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30"
dependencies = [
"rustix 0.38.34",
"windows-targets 0.52.6",
]
[[package]]
name = "gethostname"
version = "1.1.0"
@@ -3311,18 +3372,6 @@ dependencies = [
"wasip3",
]
[[package]]
name = "getset"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912"
dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "ghash"
version = "0.5.1"
@@ -3686,22 +3735,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hickory-net"
version = "0.26.0"
name = "hickory-client"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c61c8db47fae51ba9f8f2a2748bd87542acfbe22f2ec9cf9c8ec72d1ee6e9a6"
checksum = "c466cd63a4217d5b2b8e32f23f58312741ce96e3c84bf7438677d2baff0fc555"
dependencies = [
"cfg-if",
"data-encoding",
"futures-channel",
"futures-util",
"hickory-proto",
"once_cell",
"radix_trie",
"rand 0.9.1",
"thiserror 2.0.11",
"tokio",
"tracing",
]
[[package]]
name = "hickory-proto"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
dependencies = [
"async-trait",
"cfg-if",
"data-encoding",
"enum-as-inner",
"futures-channel",
"futures-io",
"futures-util",
"hickory-proto",
"idna 1.0.3",
"ipnet",
"jni 0.22.4",
"rand 0.10.1",
"once_cell",
"rand 0.9.1",
"ring",
"serde",
"thiserror 2.0.11",
"tinyvec",
@@ -3710,49 +3779,23 @@ dependencies = [
"url",
]
[[package]]
name = "hickory-proto"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a916d0494600d99ecb15aadfab677ad97c4de559e8f1af0c129353a733ac1fcc"
dependencies = [
"data-encoding",
"idna 1.0.3",
"ipnet",
"jni 0.22.4",
"once_cell",
"prefix-trie 0.8.2",
"rand 0.10.1",
"ring",
"serde",
"thiserror 2.0.11",
"tinyvec",
"tracing",
"url",
]
[[package]]
name = "hickory-resolver"
version = "0.26.0"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a10bd64d950b4d38ca21e25c8ae230712e4955fb8290cfcb29a5e5dc6017e544"
checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a"
dependencies = [
"cfg-if",
"futures-util",
"hickory-net",
"hickory-proto",
"ipconfig",
"ipnet",
"jni 0.22.4",
"moka",
"ndk-context",
"once_cell",
"parking_lot",
"rand 0.10.1",
"rand 0.9.1",
"resolv-conf",
"serde",
"smallvec",
"system-configuration 0.7.0",
"thiserror 2.0.11",
"tokio",
"tracing",
@@ -3760,20 +3803,20 @@ dependencies = [
[[package]]
name = "hickory-server"
version = "0.26.0"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91725f56e8e6b1fc4e68d4f86cf15714f1050f68ae817da6916da67041949f02"
checksum = "d53e5fe811b941c74ee46b8818228bfd2bc2688ba276a0eaeb0f2c95ea3b2585"
dependencies = [
"async-trait",
"bytes",
"cfg-if",
"data-encoding",
"enum-as-inner",
"futures-util",
"hickory-net",
"hickory-proto",
"hickory-resolver",
"ipnet",
"prefix-trie 0.8.2",
"prefix-trie",
"serde",
"thiserror 2.0.11",
"time",
@@ -3809,17 +3852,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "hostname"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd"
dependencies = [
"cfg-if",
"libc",
"windows-link 0.2.1",
]
[[package]]
name = "html5ever"
version = "0.29.1"
@@ -4005,7 +4037,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.3",
"socket2 0.5.10",
"tokio",
"tower-service",
"tracing",
@@ -4517,68 +4549,19 @@ dependencies = [
"cesu8",
"cfg-if",
"combine",
"jni-sys 0.3.0",
"jni-sys",
"log",
"thiserror 1.0.63",
"walkdir",
"windows-sys 0.45.0",
]
[[package]]
name = "jni"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
dependencies = [
"cfg-if",
"combine",
"jni-macros",
"jni-sys 0.4.1",
"log",
"simd_cesu8",
"thiserror 2.0.11",
"walkdir",
"windows-link 0.2.1",
]
[[package]]
name = "jni-macros"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"simd_cesu8",
"syn 2.0.117",
]
[[package]]
name = "jni-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jni-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
"syn 2.0.117",
]
[[package]]
name = "jobserver"
version = "0.1.32"
@@ -4865,6 +4848,19 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "loom"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
dependencies = [
"cfg-if",
"generator",
"scoped-tls",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "lru-slab"
version = "0.1.2"
@@ -5096,21 +5092,23 @@ dependencies = [
[[package]]
name = "moka"
version = "0.12.15"
version = "0.12.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046"
checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926"
dependencies = [
"async-lock",
"crossbeam-channel",
"crossbeam-epoch",
"crossbeam-utils",
"equivalent",
"event-listener",
"futures-util",
"loom",
"parking_lot",
"portable-atomic",
"rustc_version",
"smallvec",
"tagptr",
"thiserror 1.0.63",
"uuid",
]
@@ -5205,7 +5203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [
"bitflags 2.8.0",
"jni-sys 0.3.0",
"jni-sys",
"log",
"ndk-sys",
"num_enum",
@@ -5225,7 +5223,7 @@ version = "0.6.0+11769913"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
dependencies = [
"jni-sys 0.3.0",
"jni-sys",
]
[[package]]
@@ -5241,7 +5239,7 @@ dependencies = [
"netlink-packet-route 0.17.1",
"netlink-sys",
"once_cell",
"system-configuration 0.6.1",
"system-configuration",
"windows-sys 0.52.0",
]
@@ -5352,6 +5350,15 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nibble_vec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
dependencies = [
"smallvec",
]
[[package]]
name = "nix"
version = "0.25.1"
@@ -5570,7 +5577,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
dependencies = [
"proc-macro-crate 2.0.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -5921,30 +5928,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "optionize"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f15b218321873a7919c8b2a188ad488bf18c067478274be4c69c3d402b2be3ea"
dependencies = [
"delegate",
"derive_more 2.1.1",
"optionize-macros",
]
[[package]]
name = "optionize-macros"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1af5a2aba73a1808cbb39b451aabb5f8dc5c9c73d68ce5e61b79f8892f775a0f"
dependencies = [
"darling 0.23.0",
"proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "ordered-float"
version = "2.10.1"
@@ -6674,17 +6657,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "prefix-trie"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23370be78b7e5bcbb0cab4a02047eb040279a693c78daad04c2c5f1c24a83503"
dependencies = [
"either",
"ipnet",
"num-traits",
]
[[package]]
name = "prettyplease"
version = "0.2.20"
@@ -6725,11 +6697,11 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit 0.25.11+spec-1.1.0",
"toml_edit 0.22.20",
]
[[package]]
@@ -7082,6 +7054,16 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "radix_trie"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
dependencies = [
"endian-type",
"nibble_vec",
]
[[package]]
name = "rand"
version = "0.7.3"
@@ -7408,7 +7390,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration 0.6.1",
"system-configuration",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -7583,7 +7565,7 @@ checksum = "1f168d99749d307be9de54d23fd226628d99768225ef08f6ffb52e0182a27746"
dependencies = [
"cfg-if",
"glob",
"proc-macro-crate 3.5.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"regex",
@@ -7792,7 +7774,7 @@ checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1"
dependencies = [
"core-foundation 0.10.0",
"core-foundation-sys",
"jni 0.21.1",
"jni",
"log",
"once_cell",
"rustls",
@@ -7931,6 +7913,12 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -8585,16 +8573,6 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simd_cesu8"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
dependencies = [
"rustc_version",
"simdutf8",
]
[[package]]
name = "simdutf8"
version = "0.1.5"
@@ -9154,17 +9132,6 @@ dependencies = [
"system-configuration-sys",
]
[[package]]
name = "system-configuration"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags 2.8.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
@@ -9234,7 +9201,7 @@ dependencies = [
"gdkwayland-sys",
"gdkx11-sys",
"gtk",
"jni 0.21.1",
"jni",
"libc",
"log",
"ndk",
@@ -9296,7 +9263,7 @@ dependencies = [
"heck 0.5.0",
"http",
"image 0.25.10",
"jni 0.21.1",
"jni",
"libc",
"log",
"mime",
@@ -9431,7 +9398,7 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997"
dependencies = [
"gethostname",
"gethostname 1.1.0",
"log",
"os_info",
"serde",
@@ -9524,7 +9491,7 @@ dependencies = [
"dpi",
"gtk",
"http",
"jni 0.21.1",
"jni",
"objc2",
"objc2-ui-kit",
"objc2-web-kit",
@@ -9547,7 +9514,7 @@ checksum = "e11ea2e6f801d275fdd890d6c9603736012742a1c33b96d0db788c9cdebf7f9e"
dependencies = [
"gtk",
"http",
"jni 0.21.1",
"jni",
"log",
"objc2",
"objc2-app-kit",
@@ -9998,15 +9965,6 @@ dependencies = [
"serde_core",
]
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.19.15"
@@ -10044,18 +10002,6 @@ dependencies = [
"winnow 0.6.18",
]
[[package]]
name = "toml_edit"
version = "0.25.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
dependencies = [
"indexmap 2.14.0",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"winnow 1.0.1",
]
[[package]]
name = "toml_parser"
version = "1.1.2+spec-1.1.0"
@@ -10101,19 +10047,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "tonic-build"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568392c5a2bd0020723e3f387891176aabafe36fd9fcd074ad309dfa0c8eb964"
dependencies = [
"prettyplease",
"proc-macro2",
"prost-build",
"quote",
"syn 2.0.117",
]
[[package]]
name = "tower"
version = "0.4.13"
@@ -11111,8 +11044,8 @@ dependencies = [
"webview2-com-sys",
"windows 0.61.3",
"windows-core 0.61.2",
"windows-implement",
"windows-interface",
"windows-implement 0.60.2",
"windows-interface 0.59.3",
]
[[package]]
@@ -11285,6 +11218,16 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
"windows-core 0.58.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows"
version = "0.61.3"
@@ -11337,14 +11280,27 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
"windows-implement 0.58.0",
"windows-interface 0.58.0",
"windows-result 0.2.0",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement",
"windows-interface",
"windows-implement 0.60.2",
"windows-interface 0.59.3",
"windows-link 0.1.3",
"windows-result 0.3.4",
"windows-strings 0.4.2",
@@ -11356,8 +11312,8 @@ version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-implement 0.60.2",
"windows-interface 0.59.3",
"windows-link 0.2.1",
"windows-result 0.4.1",
"windows-strings 0.5.1",
@@ -11385,6 +11341,17 @@ dependencies = [
"windows-threading 0.2.1",
]
[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
@@ -11396,6 +11363,17 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
@@ -11871,9 +11849,6 @@ name = "winnow"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
@@ -12075,7 +12050,7 @@ dependencies = [
"html5ever",
"http",
"javascriptcore-rs",
"jni 0.21.1",
"jni",
"kuchikiki",
"libc",
"ndk",
@@ -12138,7 +12113,7 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
dependencies = [
"gethostname",
"gethostname 1.1.0",
"rustix 1.0.7",
"x11rb-protocol",
]
@@ -12255,7 +12230,7 @@ version = "5.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222"
dependencies = [
"proc-macro-crate 3.5.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -12492,7 +12467,7 @@ version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c"
dependencies = [
"proc-macro-crate 3.5.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.117",
-1
View File
@@ -3,7 +3,6 @@ resolver = "2"
members = [
"easytier",
"easytier-gui/src-tauri",
"easytier-rpc-build",
"easytier-web",
"easytier-contrib/easytier-ffi",
"easytier-contrib/easytier-uptime",
-20
View File
@@ -1,20 +0,0 @@
[package]
name = "easytier-rpc-build"
description = "Protobuf RPC Service Generator for EasyTier"
version = "0.1.0"
edition.workspace = true
homepage = "https://github.com/EasyTier/EasyTier"
repository = "https://github.com/EasyTier/EasyTier"
authors = ["kkrainbow"]
keywords = ["vpn", "p2p", "network", "easytier"]
categories = ["network-programming", "command-line-utilities"]
license-file = "LICENSE"
readme = "README.md"
[dependencies]
heck = "0.5"
prost-build = "0.13"
[features]
default = []
internal-namespace = []
-1
View File
@@ -1 +0,0 @@
../LICENSE
-3
View File
@@ -1,3 +0,0 @@
# Introduction
This is a protobuf rpc service stub generator for [EasyTier](https://github.com/EasyTier/EasyTier) project.
-449
View File
@@ -1,449 +0,0 @@
extern crate heck;
extern crate prost_build;
use std::fmt;
#[cfg(feature = "internal-namespace")]
const NAMESPACE: &str = "crate::proto::rpc_types";
#[cfg(not(feature = "internal-namespace"))]
const NAMESPACE: &str = "easytier::proto::rpc_types";
/// The service generator to be used with `prost-build` to generate RPC implementations for
/// `prost-simple-rpc`.
///
/// See the crate-level documentation for more info.
#[allow(missing_copy_implementations)]
#[derive(Clone, Debug, Default)]
pub struct ServiceGenerator {
_private: (),
}
impl prost_build::ServiceGenerator for ServiceGenerator {
fn generate(&mut self, service: prost_build::Service, mut buf: &mut String) {
use std::fmt::Write;
let descriptor_name = format!("{}Descriptor", service.name);
let server_name = format!("{}Server", service.name);
let client_name = format!("{}Client", service.name);
let method_descriptor_name = format!("{}MethodDescriptor", service.name);
let mut trait_methods = String::new();
let mut weak_impl_methods = String::new();
let mut enum_methods = String::new();
let mut list_enum_methods = String::new();
let mut client_methods = String::new();
let mut client_own_methods = String::new();
let mut match_name_methods = String::new();
let mut match_proto_name_methods = String::new();
let mut match_input_type_methods = String::new();
let mut match_input_proto_type_methods = String::new();
let mut match_output_type_methods = String::new();
let mut match_output_proto_type_methods = String::new();
let mut match_handle_methods = String::new();
// generate trait default method Xxx::json_call_method match branch
let mut match_trait_json_methods = String::new();
let mut match_method_try_from = String::new();
for (idx, method) in service.methods.iter().enumerate() {
assert!(
!method.client_streaming,
"Client streaming not yet supported for method {}",
method.proto_name
);
assert!(
!method.server_streaming,
"Server streaming not yet supported for method {}",
method.proto_name
);
ServiceGenerator::write_comments(&mut trait_methods, 4, &method.comments).unwrap();
writeln!(
trait_methods,
r#" async fn {name}(&self, ctrl: Self::Controller, input: {input_type}) -> {namespace}::error::Result<{output_type}>;"#,
name = method.name,
input_type = method.input_type,
output_type = method.output_type,
namespace = NAMESPACE,
)
.unwrap();
writeln!(
weak_impl_methods,
r#" async fn {method_name}(&self, ctrl: Self::Controller, input: {input_type}) -> {namespace}::error::Result<{output_type}> {{
let Some(service) = self.upgrade() else {{
return Err({namespace}::error::Error::Shutdown);
}};
service.{method_name}(ctrl, input).await
}}"#,
method_name = method.name,
input_type = method.input_type,
output_type = method.output_type,
namespace = NAMESPACE,
)
.unwrap();
ServiceGenerator::write_comments(&mut enum_methods, 4, &method.comments).unwrap();
writeln!(
enum_methods,
" {name} = {index},",
name = method.proto_name,
index = idx + 1
)
.unwrap();
writeln!(
match_method_try_from,
" {index} => Ok({service_name}MethodDescriptor::{name}),",
service_name = service.name,
name = method.proto_name,
index = idx + 1,
)
.unwrap();
writeln!(
list_enum_methods,
" {service_name}MethodDescriptor::{name},",
service_name = service.name,
name = method.proto_name
)
.unwrap();
writeln!(
client_methods,
r#" async fn {name}(&self, ctrl: H::Controller, input: {input_type}) -> {namespace}::error::Result<{output_type}> {{
{client_name}Client::{name}_inner(self.0.clone(), ctrl, input).await
}}"#,
name = method.name,
input_type = method.input_type,
output_type = method.output_type,
client_name = service.name,
namespace = NAMESPACE,
)
.unwrap();
writeln!(
client_own_methods,
r#" async fn {name}_inner(handler: H, ctrl: H::Controller, input: {input_type}) -> {namespace}::error::Result<{output_type}> {{
{namespace}::__rt::call_method(handler, ctrl, {method_descriptor_name}::{proto_name}, input).await
}}"#,
name = method.name,
method_descriptor_name = method_descriptor_name,
proto_name = method.proto_name,
input_type = method.input_type,
output_type = method.output_type,
namespace = NAMESPACE,
).unwrap();
let case = format!(
" {service_name}MethodDescriptor::{proto_name} => ",
service_name = service.name,
proto_name = method.proto_name
);
writeln!(match_name_methods, "{}{:?},", case, method.name).unwrap();
writeln!(match_proto_name_methods, "{}{:?},", case, method.proto_name).unwrap();
writeln!(
match_input_type_methods,
"{}::std::any::TypeId::of::<{}>(),",
case, method.input_type
)
.unwrap();
writeln!(
match_input_proto_type_methods,
"{}{:?},",
case, method.input_proto_type
)
.unwrap();
writeln!(
match_output_type_methods,
"{}::std::any::TypeId::of::<{}>(),",
case, method.output_type
)
.unwrap();
writeln!(
match_output_proto_type_methods,
"{}{:?},",
case, method.output_proto_type
)
.unwrap();
write!(
match_handle_methods,
r#"{} {{
let decoded: {input_type} = {namespace}::__rt::decode(input)?;
let ret = service.{name}(ctrl, decoded).await?;
{namespace}::__rt::encode(ret)
}}
"#,
case,
input_type = method.input_type,
name = method.name,
namespace = NAMESPACE,
)
.unwrap();
write!(
match_trait_json_methods,
r#" "{name}" | "{proto_name}" => {{
let req: {input_type} = ::serde_json::from_value(json).map_err(|e| {namespace}::error::Error::MalformatRpcPacket(format!("json error: {{}}", e)))?;
let resp = self.{typed_method}(ctrl, req).await?;
Ok(::serde_json::to_value(resp).map_err(|e| {namespace}::error::Error::MalformatRpcPacket(format!("json error: {{}}", e)))?)
}}
"#,
name = method.name,
proto_name = method.proto_name,
input_type = method.input_type,
typed_method = method.name,
namespace = NAMESPACE,
)
.unwrap();
}
ServiceGenerator::write_comments(&mut buf, 0, &service.comments).unwrap();
write!(
buf,
r#"
#[async_trait::async_trait]
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait {name} {{
type Controller: {namespace}::controller::Controller;
{trait_methods}
async fn json_call_method(
&self,
ctrl: Self::Controller,
method_name: &str,
json: ::serde_json::Value,
) -> {namespace}::error::Result<::serde_json::Value> {{
match method_name {{
{match_trait_json_methods}
_ => Err({namespace}::error::Error::InvalidMethodIndex(0, method_name.to_string())),
}}
}}
}}
#[async_trait::async_trait]
impl<T> {name} for ::std::sync::Weak<T>
where
T: Send + Sync + 'static,
::std::sync::Arc<T>: {name},
{{
type Controller = <::std::sync::Arc<T> as {name}>::Controller;
{weak_impl_methods}
}}
/// A service descriptor for a `{name}`.
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Default)]
pub struct {descriptor_name};
/// Methods available on a `{name}`.
///
/// This can be used as a key when routing requests for servers/clients of a `{name}`.
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum {method_descriptor_name} {{
{enum_methods}
}}
impl std::convert::TryFrom<u8> for {method_descriptor_name} {{
type Error = {namespace}::error::Error;
fn try_from(value: u8) -> {namespace}::error::Result<Self> {{
match value {{
{match_method_try_from}
_ => Err({namespace}::error::Error::InvalidMethodIndex(value, "{name}".to_string())),
}}
}}
}}
/// A client for a `{name}`.
///
/// This implements the `{name}` trait by dispatching all method calls to the supplied `Handler`.
#[derive(Clone, Debug)]
pub struct {client_name}<H>(H) where H: {namespace}::handler::Handler;
impl<H> {client_name}<H> where H: {namespace}::handler::Handler<Descriptor = {descriptor_name}> {{
/// Creates a new client instance that delegates all method calls to the supplied handler.
pub fn new(handler: H) -> {client_name}<H> {{
{client_name}(handler)
}}
}}
impl<H> {client_name}<H> where H: {namespace}::handler::Handler<Descriptor = {descriptor_name}> {{
{client_own_methods}
}}
#[async_trait::async_trait]
impl<H> {name} for {client_name}<H> where H: {namespace}::handler::Handler<Descriptor = {descriptor_name}> {{
type Controller = H::Controller;
{client_methods}
}}
pub struct {client_name}Factory<C: {namespace}::controller::Controller>(std::marker::PhantomData<C>);
impl<C: {namespace}::controller::Controller> Clone for {client_name}Factory<C> {{
fn clone(&self) -> Self {{
Self(std::marker::PhantomData)
}}
}}
impl<C> {namespace}::__rt::RpcClientFactory for {client_name}Factory<C> where C: {namespace}::controller::Controller {{
type Descriptor = {descriptor_name};
type ClientImpl = Box<dyn {name}<Controller = C> + Send + Sync + 'static>;
type Controller = C;
fn new(handler: impl {namespace}::handler::Handler<Descriptor = Self::Descriptor, Controller = Self::Controller>) -> Self::ClientImpl {{
Box::new({client_name}::new(handler))
}}
}}
/// A server for a `{name}`.
///
/// This implements the `Server` trait by handling requests and dispatch them to methods on the
/// supplied `{name}`.
#[derive(Clone, Debug)]
pub struct {server_name}<A>(A) where A: {name} + Clone + Send + 'static;
impl<T> {server_name}<::std::sync::Weak<T>>
where
T: Send + Sync + 'static,
::std::sync::Arc<T>: {name},
{{
pub fn new_arc(service: ::std::sync::Arc<T>) -> {server_name}<::std::sync::Weak<T>> {{
{server_name}(::std::sync::Arc::downgrade(&service))
}}
}}
impl<A> {server_name}<A> where A: {name} + Clone + Send + 'static {{
/// Creates a new server instance that dispatches all calls to the supplied service.
pub fn new(service: A) -> {server_name}<A> {{
{server_name}(service)
}}
async fn call_inner(
service: A,
method: {method_descriptor_name},
ctrl: A::Controller,
input: ::bytes::Bytes)
-> {namespace}::error::Result<::bytes::Bytes> {{
match method {{
{match_handle_methods}
}}
}}
}}
impl {namespace}::descriptor::ServiceDescriptor for {descriptor_name} {{
type Method = {method_descriptor_name};
fn name(&self) -> &'static str {{ {name:?} }}
fn proto_name(&self) -> &'static str {{ {proto_name:?} }}
fn package(&self) -> &'static str {{ {package:?} }}
fn methods(&self) -> &'static [Self::Method] {{
&[ {list_enum_methods} ]
}}
}}
#[async_trait::async_trait]
impl<A> {namespace}::handler::Handler for {server_name}<A>
where
A: {name} + Clone + Send + Sync + 'static {{
type Descriptor = {descriptor_name};
type Controller = A::Controller;
async fn call(
&self,
ctrl: A::Controller,
method: {method_descriptor_name},
input: ::bytes::Bytes)
-> {namespace}::error::Result<::bytes::Bytes> {{
{server_name}::call_inner(self.0.clone(), method, ctrl, input).await
}}
}}
impl {namespace}::descriptor::MethodDescriptor for {method_descriptor_name} {{
fn name(&self) -> &'static str {{
match *self {{
{match_name_methods}
}}
}}
fn proto_name(&self) -> &'static str {{
match *self {{
{match_proto_name_methods}
}}
}}
fn input_type(&self) -> ::std::any::TypeId {{
match *self {{
{match_input_type_methods}
}}
}}
fn input_proto_type(&self) -> &'static str {{
match *self {{
{match_input_proto_type_methods}
}}
}}
fn output_type(&self) -> ::std::any::TypeId {{
match *self {{
{match_output_type_methods}
}}
}}
fn output_proto_type(&self) -> &'static str {{
match *self {{
{match_output_proto_type_methods}
}}
}}
fn index(&self) -> u8 {{
*self as u8
}}
}}
"#,
name = service.name,
descriptor_name = descriptor_name,
server_name = server_name,
client_name = client_name,
method_descriptor_name = method_descriptor_name,
proto_name = service.proto_name,
package = service.package,
trait_methods = trait_methods,
weak_impl_methods = weak_impl_methods,
enum_methods = enum_methods,
list_enum_methods = list_enum_methods,
client_own_methods = client_own_methods,
client_methods = client_methods,
match_name_methods = match_name_methods,
match_proto_name_methods = match_proto_name_methods,
match_input_type_methods = match_input_type_methods,
match_input_proto_type_methods = match_input_proto_type_methods,
match_output_type_methods = match_output_type_methods,
match_output_proto_type_methods = match_output_proto_type_methods,
match_handle_methods = match_handle_methods,
match_trait_json_methods = match_trait_json_methods,
namespace = NAMESPACE,
).unwrap();
}
}
impl ServiceGenerator {
fn write_comments<W>(
mut write: W,
indent: usize,
comments: &prost_build::Comments,
) -> fmt::Result
where
W: fmt::Write,
{
for comment in &comments.leading {
for line in comment.lines().filter(|s| !s.is_empty()) {
writeln!(write, "{}///{}", " ".repeat(indent), line)?;
}
}
Ok(())
}
}
+4 -4
View File
@@ -11,6 +11,7 @@ keywords = ["vpn", "p2p", "network", "easytier"]
categories = ["network-programming", "command-line-utilities"]
license-file = "LICENSE"
readme = "README.md"
build = "build/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -320,15 +321,14 @@ jemalloc-sys = { package = "tikv-jemalloc-sys", version = "0.6.0", features = [
[build-dependencies]
cfg_aliases = "0.2.1"
tonic-build = "0.12"
indoc = "2.0"
globwalk = "0.8.1"
regex = "1"
prost-build = "0.13.5"
prost-wkt-build = "0.6"
easytier-rpc-build = { path = "../easytier-rpc-build", features = [
"internal-namespace",
] }
prost-reflect-build = { version = "0.14.0" }
proc-macro2 = "1"
quote = "1"
thunk-rs = { git = "https://github.com/easytier/thunk.git", default-features = false, features = [
"win7",
] }
+4 -1
View File
@@ -1,3 +1,6 @@
mod rpc;
use crate::rpc::ServiceGenerator;
use cfg_aliases::cfg_aliases;
use prost_wkt_build::{FileDescriptorSet, Message as _};
#[cfg(target_os = "windows")]
@@ -203,7 +206,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
config
.btree_map(["."])
.service_generator(Box::new(easytier_rpc_build::ServiceGenerator::default()))
.service_generator(Box::new(ServiceGenerator::default()))
.protoc_arg("--experimental_allow_proto3_optional")
.file_descriptor_set_path(&descriptor_file)
.compile_protos(&proto_files, &["src/proto/"])?;
+720
View File
@@ -0,0 +1,720 @@
#![allow(non_snake_case)]
use indoc::formatdoc;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use std::str::FromStr;
fn parse(value: &str) -> TokenStream {
TokenStream::from_str(value)
.unwrap_or_else(|err| panic!("Failed to parse tokens: {} ({})", value, err))
}
fn doc(comments: &prost_build::Comments) -> TokenStream {
let doc = comments
.leading
.iter()
.flat_map(|c| c.lines().filter(|s| !s.is_empty()));
quote! { #( #[doc = #doc] )* }
}
const NAMESPACE: &str = "crate::proto::rpc_types";
struct Method {
index: u8,
doc: TokenStream,
method: Ident,
method_inner: Ident,
method_str: String,
method_proto: Ident,
method_proto_str: String,
Input: TokenStream,
Input_proto_str: String,
Output: TokenStream,
Output_proto_str: String,
}
impl Method {
fn new(index: u8, method: prost_build::Method) -> Self {
assert!(
!method.client_streaming,
"Client streaming not yet supported for method {}",
method.proto_name
);
assert!(
!method.server_streaming,
"Server streaming not yet supported for method {}",
method.proto_name
);
Self {
index,
doc: doc(&method.comments),
method: format_ident!("{}", method.name),
method_inner: format_ident!("{}_inner", method.name),
method_str: method.name,
method_proto: format_ident!("{}", method.proto_name),
method_proto_str: method.proto_name,
Input: parse(&method.input_type),
Input_proto_str: method.input_proto_type,
Output: parse(&method.output_type),
Output_proto_str: method.output_proto_type,
}
}
}
struct Service {
namespace: TokenStream,
doc: TokenStream,
Service: Ident,
ServiceDescriptor: Ident,
ServiceServer: Ident,
ServiceClient: Ident,
ServiceClientFactory: Ident,
ServiceMethodDescriptor: Ident,
Service_str: String,
Service_proto_str: String,
Service_package_str: String,
methods: Vec<Method>,
}
impl Service {
fn new(service: prost_build::Service) -> Self {
let methods = service
.methods
.into_iter()
.enumerate()
.map(|(i, method)| Method::new((i + 1) as u8, method))
.collect();
Self {
namespace: parse(NAMESPACE),
doc: doc(&service.comments),
Service: format_ident!("{}", service.name),
ServiceDescriptor: format_ident!("{}Descriptor", service.name),
ServiceServer: format_ident!("{}Server", service.name),
ServiceClient: format_ident!("{}Client", service.name),
ServiceClientFactory: format_ident!("{}ClientFactory", service.name),
ServiceMethodDescriptor: format_ident!("{}MethodDescriptor", service.name),
Service_str: service.name,
Service_proto_str: service.proto_name,
Service_package_str: service.package,
methods,
}
}
fn trait_Service(&self) -> TokenStream {
let Self {
namespace,
doc,
Service,
methods,
..
} = self;
let match_json_call_method = methods.iter().map(
|Method {
method,
method_str,
method_proto_str,
Input,
..
}| {
quote! {
#method_str | #method_proto_str => {
let req: #Input = ::serde_json::from_value(json)
.map_err(|e| #namespace::error::Error::MalformatRpcPacket(format!("json error: {}", e)))?;
let resp = self.#method(ctrl, req).await?;
Ok(::serde_json::to_value(resp)
.map_err(|e| #namespace::error::Error::MalformatRpcPacket(format!("json error: {}", e)))?)
}
}
},
);
let methods = methods.iter().map(
|Method {
doc,
method,
Input,
Output,
..
}| {
quote! {
#doc
async fn #method(&self, ctrl: Self::Controller, input: #Input) -> #namespace::error::Result<#Output>;
}
},
);
quote! {
#doc
#[async_trait::async_trait]
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait #Service {
type Controller: #namespace::controller::Controller;
#(#methods)*
async fn json_call_method(
&self,
ctrl: Self::Controller,
method: &str,
json: ::serde_json::Value,
) -> #namespace::error::Result<::serde_json::Value> {
match method {
#(#match_json_call_method)*
_ => Err(#namespace::error::Error::InvalidMethodIndex(0, method.to_string())),
}
}
}
}
}
fn impl_Service_for_Weak(&self) -> TokenStream {
let Self {
namespace,
Service,
methods,
..
} = self;
let methods = methods.iter().map(
|Method {
method,
Input,
Output,
..
}| {
quote! {
async fn #method(&self, ctrl: Self::Controller, input: #Input) -> #namespace::error::Result<#Output> {
let Some(service) = self.upgrade() else {
return Err(#namespace::error::Error::Shutdown);
};
service.#method(ctrl, input).await
}
}
},
);
quote! {
#[async_trait::async_trait]
impl<T> #Service for ::std::sync::Weak<T>
where
T: Send + Sync + 'static,
::std::sync::Arc<T>: #Service,
{
type Controller = <::std::sync::Arc<T> as #Service>::Controller;
#(#methods)*
}
}
}
fn struct_ServiceDescriptor(&self) -> TokenStream {
let Self {
namespace,
ServiceDescriptor,
ServiceMethodDescriptor,
Service_str,
Service_proto_str,
Service_package_str,
methods,
..
} = self;
let doc = format!("A service descriptor for a `{}`.", Service_str);
let methods = methods.iter().map(|Method { method_proto, .. }| {
quote! { #ServiceMethodDescriptor::#method_proto, }
});
quote! {
#[doc = #doc]
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Default)]
pub struct #ServiceDescriptor;
impl #namespace::descriptor::ServiceDescriptor for #ServiceDescriptor {
type Method = #ServiceMethodDescriptor;
fn name(&self) -> &'static str { #Service_str }
fn proto_name(&self) -> &'static str { #Service_proto_str }
fn package(&self) -> &'static str { #Service_package_str }
fn methods(&self) -> &'static [Self::Method] {
&[ #(#methods)* ]
}
}
}
}
fn enum_ServiceMethodDescriptor(&self) -> TokenStream {
let Self {
ServiceMethodDescriptor,
Service_str,
methods,
..
} = self;
let doc = formatdoc! {"
Methods available on a `{Service_str}`.
This can be used as a key when routing requests for servers/clients of a `{Service_str}`.
"};
let variants = methods.iter().map(
|Method {
method_proto,
index,
..
}| {
quote! { #method_proto = #index, }
},
);
let impl_MethodDescriptor = self.impl_MethodDescriptor_for_ServiceMethodDescriptor();
let impl_TryFrom = self.impl_TryFrom_for_ServiceMethodDescriptor();
quote! {
#[doc = #doc]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum #ServiceMethodDescriptor {
#(#variants)*
}
#impl_MethodDescriptor
#impl_TryFrom
}
}
fn impl_MethodDescriptor_for_ServiceMethodDescriptor(&self) -> TokenStream {
let Self {
namespace,
ServiceMethodDescriptor,
methods,
..
} = self;
let name = {
let arms = methods.iter().map(
|Method {
method_proto,
method_str,
..
}| {
quote! { #ServiceMethodDescriptor::#method_proto => #method_str, }
},
);
quote! {
fn name(&self) -> &'static str {
match *self {
#(#arms)*
}
}
}
};
let proto_name = {
let arms = methods.iter().map(
|Method {
method_proto,
method_proto_str,
..
}| {
quote! { #ServiceMethodDescriptor::#method_proto => #method_proto_str, }
},
);
quote! {
fn proto_name(&self) -> &'static str {
match *self {
#(#arms)*
}
}
}
};
let input_type = {
let arms = methods.iter().map(|Method { method_proto, Input, .. }| {
quote! { #ServiceMethodDescriptor::#method_proto => ::std::any::TypeId::of::<#Input>(), }
});
quote! {
fn input_type(&self) -> ::std::any::TypeId {
match *self {
#(#arms)*
}
}
}
};
let input_proto_type = {
let arms = methods.iter().map(
|Method {
method_proto,
Input_proto_str,
..
}| {
quote! { #ServiceMethodDescriptor::#method_proto => #Input_proto_str, }
},
);
quote! {
fn input_proto_type(&self) -> &'static str {
match *self {
#(#arms)*
}
}
}
};
let output_type = {
let arms = methods.iter().map(|Method { method_proto, Output, .. }| {
quote! { #ServiceMethodDescriptor::#method_proto => ::std::any::TypeId::of::<#Output>(), }
});
quote! {
fn output_type(&self) -> ::std::any::TypeId {
match *self {
#(#arms)*
}
}
}
};
let output_proto_type = {
let arms = methods.iter().map(
|Method {
method_proto,
Output_proto_str,
..
}| {
quote! { #ServiceMethodDescriptor::#method_proto => #Output_proto_str, }
},
);
quote! {
fn output_proto_type(&self) -> &'static str {
match *self {
#(#arms)*
}
}
}
};
quote! {
impl #namespace::descriptor::MethodDescriptor for #ServiceMethodDescriptor {
#name
#proto_name
#input_type
#input_proto_type
#output_type
#output_proto_type
fn index(&self) -> u8 {
*self as u8
}
}
}
}
fn impl_TryFrom_for_ServiceMethodDescriptor(&self) -> TokenStream {
let Self {
namespace,
ServiceMethodDescriptor,
Service_str,
methods,
..
} = self;
let arms = methods.iter().map(
|Method {
method_proto,
index,
..
}| {
quote! { #index => Ok(#ServiceMethodDescriptor::#method_proto), }
},
);
quote! {
impl std::convert::TryFrom<u8> for #ServiceMethodDescriptor {
type Error = #namespace::error::Error;
fn try_from(value: u8) -> #namespace::error::Result<Self> {
match value {
#(#arms)*
_ => Err(#namespace::error::Error::InvalidMethodIndex(value, #Service_str.to_string())),
}
}
}
}
}
fn struct_ServiceClient(&self) -> TokenStream {
let Self {
namespace,
ServiceDescriptor,
ServiceClient,
Service_str,
..
} = self;
let doc = formatdoc! {"
A client for a `{Service_str}`.
This implements the `{Service_str}` trait by dispatching all method calls to the supplied `Handler`.
"};
let impl_service_client = self.impl_ServiceClient();
let impl_service_for_client = self.impl_Service_for_ServiceClient();
quote! {
#[doc = #doc]
#[derive(Clone, Debug)]
pub struct #ServiceClient<H>(H) where H: #namespace::handler::Handler;
impl<H> #ServiceClient<H> where H: #namespace::handler::Handler<Descriptor = #ServiceDescriptor> {
/// Creates a new client instance that delegates all method calls to the supplied handler.
pub fn new(handler: H) -> Self {
Self(handler)
}
}
#impl_service_client
#impl_service_for_client
}
}
fn impl_ServiceClient(&self) -> TokenStream {
let Self {
namespace,
ServiceClient,
ServiceDescriptor,
ServiceMethodDescriptor,
methods,
..
} = self;
let methods = methods.iter().map(
|Method {
method_inner,
method_proto,
Input,
Output,
..
}| {
quote! {
async fn #method_inner(handler: H, ctrl: H::Controller, input: #Input) -> #namespace::error::Result<#Output> {
#namespace::__rt::call_method(handler, ctrl, #ServiceMethodDescriptor::#method_proto, input).await
}
}
},
);
quote! {
impl<H> #ServiceClient<H> where H: #namespace::handler::Handler<Descriptor = #ServiceDescriptor> {
#(#methods)*
}
}
}
fn impl_Service_for_ServiceClient(&self) -> TokenStream {
let Self {
namespace,
Service,
ServiceClient,
ServiceDescriptor,
methods,
..
} = self;
let methods = methods.iter().map(
|Method {
method,
method_inner,
Input,
Output,
..
}| {
quote! {
async fn #method(&self, ctrl: H::Controller, input: #Input) -> #namespace::error::Result<#Output> {
#ServiceClient::#method_inner(self.0.clone(), ctrl, input).await
}
}
},
);
quote! {
#[async_trait::async_trait]
impl<H> #Service for #ServiceClient<H> where H: #namespace::handler::Handler<Descriptor = #ServiceDescriptor> {
type Controller = H::Controller;
#(#methods)*
}
}
}
fn struct_ServiceClientFactory(&self) -> TokenStream {
let Self {
namespace,
Service,
ServiceClient,
ServiceClientFactory,
ServiceDescriptor,
..
} = self;
quote! {
pub struct #ServiceClientFactory<C: #namespace::controller::Controller>(std::marker::PhantomData<C>);
impl<C: #namespace::controller::Controller> Clone for #ServiceClientFactory<C> {
fn clone(&self) -> Self {
Self(std::marker::PhantomData)
}
}
impl<C> #namespace::__rt::RpcClientFactory for #ServiceClientFactory<C> where C: #namespace::controller::Controller {
type Descriptor = #ServiceDescriptor;
type ClientImpl = Box<dyn #Service<Controller = C> + Send + Sync + 'static>;
type Controller = C;
fn new(handler: impl #namespace::handler::Handler<Descriptor = Self::Descriptor, Controller = Self::Controller>) -> Self::ClientImpl {
Box::new(#ServiceClient::new(handler))
}
}
}
}
fn struct_ServiceServer(&self) -> TokenStream {
let Self {
namespace,
Service,
ServiceDescriptor,
ServiceServer,
ServiceMethodDescriptor,
Service_str,
methods,
..
} = self;
let doc = formatdoc! {"
A server for a `{Service_str}`.
This implements the `Server` trait by handling requests and dispatch them to methods on the
supplied `{Service_str}`.
"};
let arms = methods.iter().map(
|Method {
method_proto,
method,
Input,
..
}| {
quote! {
#ServiceMethodDescriptor::#method_proto => {
let decoded: #Input = #namespace::__rt::decode(input)?;
let ret = service.#method(ctrl, decoded).await?;
#namespace::__rt::encode(ret)
}
}
},
);
quote! {
#[doc = #doc]
#[derive(Clone, Debug)]
pub struct #ServiceServer<A>(A) where A: #Service + Clone + Send + 'static;
impl<T> #ServiceServer<::std::sync::Weak<T>>
where
T: Send + Sync + 'static,
::std::sync::Arc<T>: #Service,
{
pub fn new_arc(service: ::std::sync::Arc<T>) -> #ServiceServer<::std::sync::Weak<T>> {
#ServiceServer(::std::sync::Arc::downgrade(&service))
}
}
impl<A> #ServiceServer<A> where A: #Service + Clone + Send + 'static {
/// Creates a new server instance that dispatches all calls to the supplied service.
pub fn new(service: A) -> #ServiceServer<A> {
#ServiceServer(service)
}
async fn call_inner(
service: A,
method: #ServiceMethodDescriptor,
ctrl: A::Controller,
input: ::bytes::Bytes)
-> #namespace::error::Result<::bytes::Bytes> {
match method {
#(#arms)*
}
}
}
#[async_trait::async_trait]
impl<A> #namespace::handler::Handler for #ServiceServer<A>
where
A: #Service + Clone + Send + Sync + 'static {
type Descriptor = #ServiceDescriptor;
type Controller = A::Controller;
async fn call(
&self,
ctrl: A::Controller,
method: #ServiceMethodDescriptor,
input: ::bytes::Bytes)
-> #namespace::error::Result<::bytes::Bytes> {
#ServiceServer::call_inner(self.0.clone(), method, ctrl, input).await
}
}
}
}
}
/// The service generator to be used with `prost-build` to generate RPC implementations for
/// `prost-simple-rpc`.
///
/// See the crate-level documentation for more info.
#[non_exhaustive]
#[derive(Debug, Default)]
pub struct ServiceGenerator;
impl prost_build::ServiceGenerator for ServiceGenerator {
fn generate(&mut self, service: prost_build::Service, buf: &mut String) {
let info = Service::new(service);
let trait_Service = info.trait_Service();
let impl_Service_for_Weak = info.impl_Service_for_Weak();
let struct_ServiceDescriptor = info.struct_ServiceDescriptor();
let enum_ServiceMethodDescriptor = info.enum_ServiceMethodDescriptor();
let struct_ServiceClient = info.struct_ServiceClient();
let struct_ServiceClientFactory = info.struct_ServiceClientFactory();
let struct_ServiceServer = info.struct_ServiceServer();
let tokens = quote! {
#trait_Service
#impl_Service_for_Weak
#struct_ServiceDescriptor
#enum_ServiceMethodDescriptor
#struct_ServiceClient
#struct_ServiceClientFactory
#struct_ServiceServer
};
buf.push('\n');
buf.push_str(&tokens.to_string());
buf.push('\n');
}
}