From 890b903f04d807046e19256fa7edd6cd1b9d8b1d Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Sun, 11 Dec 2022 23:37:08 +0100 Subject: [PATCH 01/13] Prepare work on Rust2.0 with async/tokio support --- .editorconfig | 2 ++ templates/Rust2.0/.gitignore | 2 ++ templates/Rust2.0/Cargo.toml | 15 ++++++++++++ templates/Rust2.0/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 templates/Rust2.0/.gitignore create mode 100644 templates/Rust2.0/Cargo.toml create mode 100644 templates/Rust2.0/src/lib.rs diff --git a/.editorconfig b/.editorconfig index a49691e..f03fbee 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,3 +13,5 @@ indent_size = 2 indent_size = 4 [*.dart] indent_size = 2 +[*.rs] +indent_size = 4 diff --git a/templates/Rust2.0/.gitignore b/templates/Rust2.0/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/templates/Rust2.0/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/templates/Rust2.0/Cargo.toml b/templates/Rust2.0/Cargo.toml new file mode 100644 index 0000000..603aa7b --- /dev/null +++ b/templates/Rust2.0/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "__name__" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +int-enum = "0.5.0" +serde = { version = "1.0.147", features = ["derive"] } +serde_json = "1.0.88" +threadpool = "1.8.1" +nanoid = "0.4.0" +tokio = { version = "1.22.0", features = ["full"] } + diff --git a/templates/Rust2.0/src/lib.rs b/templates/Rust2.0/src/lib.rs new file mode 100644 index 0000000..c669dc5 --- /dev/null +++ b/templates/Rust2.0/src/lib.rs @@ -0,0 +1,44 @@ +use nanoid::nanoid; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::boxed::Box; +use std::collections::HashMap; +use std::error::Error; +use std::marker::PhantomData; +use std::marker::Send; +use std::sync::mpsc::{Receiver, Sender}; +use std::sync::{Arc, Mutex}; +use threadpool::ThreadPool; + +pub type Result = std::result::Result>; + +#[derive(Serialize, Deserialize)] +pub struct JRPCRequest { + pub jsonrpc: String, + pub id: Option, + pub method: String, + pub params: Value, +} + +#[derive(Serialize, Deserialize)] +pub struct JRPCError { + pub code: i64, + pub message: String, + pub data: Value, +} + +#[derive(Serialize, Deserialize)] +pub struct JRPCResult { + pub jsonrpc: String, + pub id: String, + pub result: Value, + pub error: Option, +} + +struct JRPCServer {} + +impl JRPCServer { + fn handle(&self) -> () {} +} + +struct JRPCServerService {} From 46aff0c61bb9c78d89701baca0eb2b43cae134a0 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Sat, 17 Dec 2022 17:11:28 +0100 Subject: [PATCH 02/13] Finish implementation of new Rust Tokio Target --- examples/Rust/.gitignore | 3 +- examples/Rust/Client/Cargo.lock | 589 +++++++++++++++++++++++++++++++ examples/Rust/Client/Cargo.toml | 10 + examples/Rust/Client/src/main.rs | 52 +++ examples/Rust/Impl/Cargo.lock | 248 ------------- examples/Rust/Impl/Cargo.toml | 7 - examples/Rust/Impl/src/main.rs | 52 --- examples/Rust/Server/Cargo.lock | 589 +++++++++++++++++++++++++++++++ examples/Rust/Server/Cargo.toml | 10 + examples/Rust/Server/src/main.rs | 75 ++++ examples/Typescript/server.ts | 24 +- examples/example.jrpc | 11 + examples/test.jrpc | 14 - package.json | 2 +- src/targets/rust.ts | 74 ++-- templates/Rust/.editorconfig | 2 + templates/Rust/Cargo.toml | 13 +- templates/Rust/src/lib.rs | 447 ++++++++++------------- templates/Rust2.0/.gitignore | 2 - templates/Rust2.0/Cargo.toml | 15 - templates/Rust2.0/src/lib.rs | 44 --- 21 files changed, 1598 insertions(+), 685 deletions(-) create mode 100644 examples/Rust/Client/Cargo.lock create mode 100644 examples/Rust/Client/Cargo.toml create mode 100644 examples/Rust/Client/src/main.rs delete mode 100644 examples/Rust/Impl/Cargo.lock delete mode 100644 examples/Rust/Impl/Cargo.toml delete mode 100644 examples/Rust/Impl/src/main.rs create mode 100644 examples/Rust/Server/Cargo.lock create mode 100644 examples/Rust/Server/Cargo.toml create mode 100644 examples/Rust/Server/src/main.rs delete mode 100644 examples/test.jrpc create mode 100644 templates/Rust/.editorconfig delete mode 100644 templates/Rust2.0/.gitignore delete mode 100644 templates/Rust2.0/Cargo.toml delete mode 100644 templates/Rust2.0/src/lib.rs diff --git a/examples/Rust/.gitignore b/examples/Rust/.gitignore index ddc70ca..622cb74 100644 --- a/examples/Rust/.gitignore +++ b/examples/Rust/.gitignore @@ -1,2 +1,3 @@ Generated/ -Impl/target +Server/target +Client/target diff --git a/examples/Rust/Client/Cargo.lock b/examples/Rust/Client/Cargo.lock new file mode 100644 index 0000000..4050373 --- /dev/null +++ b/examples/Rust/Client/Cargo.lock @@ -0,0 +1,589 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async-trait" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "example" +version = "0.1.0" +dependencies = [ + "async-trait", + "int-enum", + "log", + "nanoid", + "serde", + "serde_json", + "simple_logger", + "tokio", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "int-enum" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff87d3cc4b79b4559e3c75068d64247284aceb6a038bd4bb38387f3f164476d" +dependencies = [ + "int-enum-impl", +] + +[[package]] +name = "int-enum-impl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1f2f068675add1a3fc77f5f5ab2e29290c841ee34d151abc007bce902e5d34" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "nanoid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +dependencies = [ + "rand", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" +dependencies = [ + "atty", + "colored", + "log", + "time", + "windows-sys", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "test-impl-client" +version = "0.1.0" +dependencies = [ + "async-trait", + "example", + "serde_json", + "tokio", +] + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "tokio" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/examples/Rust/Client/Cargo.toml b/examples/Rust/Client/Cargo.toml new file mode 100644 index 0000000..0f29e46 --- /dev/null +++ b/examples/Rust/Client/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "test-impl-client" +version = "0.1.0" +edition = "2021" + +[dependencies] +example = { path = "../Generated/" } +async-trait = "0.1.59" +tokio = { version = "1.22.0", features = ["full"] } +serde_json = "1.0.88" diff --git a/examples/Rust/Client/src/main.rs b/examples/Rust/Client/src/main.rs new file mode 100644 index 0000000..78fbfec --- /dev/null +++ b/examples/Rust/Client/src/main.rs @@ -0,0 +1,52 @@ +use std::sync::atomic::AtomicU64; +use std::sync::Arc; + +use example::client::SimpleTestService; +use example::JRPCClient; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; +use tokio::net::TcpStream; +use tokio::sync::mpsc::channel; + +#[tokio::main] +pub async fn main() { + let (tx, mut rx) = channel(1); + let stream = TcpStream::connect("127.0.0.1:4321").await.unwrap(); + let client = example::JRPCClient::new(tx.clone()); + let test_service = SimpleTestService::new(client.clone()); + + let (reader, mut writer) = stream.into_split(); + let mut reader = BufReader::new(reader); + let mut line = String::new(); + + tokio::spawn(async move { + loop { + line.clear(); + reader.read_line(&mut line).await.unwrap(); + client.on_result(serde_json::from_str(&line).unwrap()).await; + } + }); + + tokio::spawn(async move { + while let Some(message) = rx.recv().await { + writer + .write_all((serde_json::to_string(&message).unwrap() + "\n").as_bytes()) + .await + .unwrap(); + } + }); + + let ticks = Arc::new(AtomicU64::new(0)); + let t2 = ticks.clone(); + tokio::spawn(async move { + loop { + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + println!("Ticks: {}", t2.load(std::sync::atomic::Ordering::Relaxed)); + t2.store(0, std::sync::atomic::Ordering::Relaxed); + } + }); + + loop { + let _result = test_service.GetTest("Hi".to_owned(), 55).await.unwrap(); + ticks.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + } +} diff --git a/examples/Rust/Impl/Cargo.lock b/examples/Rust/Impl/Cargo.lock deleted file mode 100644 index 1c995a6..0000000 --- a/examples/Rust/Impl/Cargo.lock +++ /dev/null @@ -1,248 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "int-enum" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b1428b2b1abe959e6eedb0a17d0ab12f6ba20e1106cc29fc4874e3ba393c177" -dependencies = [ - "cfg-if 0.1.10", - "int-enum-impl", -] - -[[package]] -name = "int-enum-impl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c3cecaad8ca1a5020843500c696de2b9a07b63b624ddeef91f85f9bafb3671" -dependencies = [ - "cfg-if 0.1.10", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "libc" -version = "0.2.123" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd" - -[[package]] -name = "nanoid" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" -dependencies = [ - "rand", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro2" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[package]] -name = "serde" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "syn" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "test" -version = "0.1.0" -dependencies = [ - "int-enum", - "nanoid", - "serde", - "serde_json", - "threadpool", -] - -[[package]] -name = "test-impl" -version = "0.1.0" -dependencies = [ - "test", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "toml" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" -dependencies = [ - "serde", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/examples/Rust/Impl/Cargo.toml b/examples/Rust/Impl/Cargo.toml deleted file mode 100644 index cf31f2c..0000000 --- a/examples/Rust/Impl/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "test-impl" -version = "0.1.0" -edition = "2021" - -[dependencies] -test = { path = "../Generated/" } diff --git a/examples/Rust/Impl/src/main.rs b/examples/Rust/Impl/src/main.rs deleted file mode 100644 index 02a1e23..0000000 --- a/examples/Rust/Impl/src/main.rs +++ /dev/null @@ -1,52 +0,0 @@ -use test::{JRPCServer,Result,Test}; -use test::server::{TestService,TestServiceHandler}; -use std::io::{BufReader,BufRead,Write}; -use std::sync::mpsc::channel; - -#[derive(Clone, Copy)] -struct MyCtx {} - -struct TestServiceImplementation {} - -impl TestService for TestServiceImplementation { - fn GetTest(&self, name: String, age: i64, _context: &MyCtx) -> Result { - return Ok(Test { name, age }); - } - - fn TestNot(&self, _: &MyCtx) -> Result<()> { - return Ok(()); - } -} - -pub fn main() { - let mut srv = JRPCServer::::new(); - srv.add_service(TestServiceHandler::new(Box::from(TestServiceImplementation {}))); - - let listener = std::net::TcpListener::bind("127.0.0.1:4321").expect("Could not start listener!"); - - for stream in listener.incoming() { - println!("Got Connection!"); - let (stx, srx) = channel::(); - let (rtx, rrx) = channel::(); - - let mut stream = stream.expect("Bad stream"); - let mut r = BufReader::new(stream.try_clone().unwrap()); - let mut line = String::new(); - - srv.start_session(srx, rtx, MyCtx {}); - - - r.read_line(&mut line).expect("Could not read line!"); - println!("Got line: {}", line); - stx.send(line).expect("Could not send packet to handler!"); - println!("Sending to handler succeeded"); - let response = rrx.recv().expect("Could not get reponse from handler!"); - println!("Prepared response {}", response); - - stream.write((response + "\n").as_bytes()).expect("Could not send reponse!"); - } - - println!("Hello World"); - - // return Ok(()); -} diff --git a/examples/Rust/Server/Cargo.lock b/examples/Rust/Server/Cargo.lock new file mode 100644 index 0000000..6969fbc --- /dev/null +++ b/examples/Rust/Server/Cargo.lock @@ -0,0 +1,589 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "async-trait" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "example" +version = "0.1.0" +dependencies = [ + "async-trait", + "int-enum", + "log", + "nanoid", + "serde", + "serde_json", + "simple_logger", + "tokio", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "int-enum" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff87d3cc4b79b4559e3c75068d64247284aceb6a038bd4bb38387f3f164476d" +dependencies = [ + "int-enum-impl", +] + +[[package]] +name = "int-enum-impl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1f2f068675add1a3fc77f5f5ab2e29290c841ee34d151abc007bce902e5d34" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "nanoid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +dependencies = [ + "rand", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" +dependencies = [ + "atty", + "colored", + "log", + "time", + "windows-sys", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "test-impl" +version = "0.1.0" +dependencies = [ + "async-trait", + "example", + "serde_json", + "tokio", +] + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "tokio" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/examples/Rust/Server/Cargo.toml b/examples/Rust/Server/Cargo.toml new file mode 100644 index 0000000..0296d8d --- /dev/null +++ b/examples/Rust/Server/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "test-impl" +version = "0.1.0" +edition = "2021" + +[dependencies] +example = { path = "../Generated/" } +async-trait = "0.1.59" +tokio = { version = "1.22.0", features = ["full"] } +serde_json = "1.0.88" diff --git a/examples/Rust/Server/src/main.rs b/examples/Rust/Server/src/main.rs new file mode 100644 index 0000000..71f255a --- /dev/null +++ b/examples/Rust/Server/src/main.rs @@ -0,0 +1,75 @@ +use async_trait::async_trait; +use example::base_lib::JRPCResult; +use example::server::{SimpleTestService, SimpleTestServiceHandler}; +use example::{JRPCServer, Result, Test2}; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; +use tokio::net::TcpStream; +use tokio::sync::mpsc::channel; + +#[derive(Clone)] +struct TestServiceImplementation {} + +#[async_trait] +impl SimpleTestService for TestServiceImplementation { + async fn GetTest(&self, name: String, age: i64) -> Result { + return Ok(Test2 { name, age }); + } + + async fn TestNot(&self) -> Result<()> { + return Ok(()); + } +} + +fn handle_connection(stream: TcpStream, server: &JRPCServer) { + let (response_sender, mut response_receiver) = channel::(1); + + let session = server.get_session(response_sender); + + let (r, mut w) = stream.into_split(); + tokio::spawn(async move { + loop { + let res = response_receiver.recv().await; + match res { + None => break, + Some(res) => w + .write_all((serde_json::to_string(&res).unwrap() + "\n").as_bytes()) + .await + .unwrap(), + } + } + }); + + tokio::spawn(async move { + let mut reader = BufReader::new(r); + loop { + let mut line = String::new(); + let res = reader.read_line(&mut line).await; + match res { + Ok(size) => { + if size > 0 { + session.handle_request(serde_json::from_str(&line).unwrap()) + } else { + break; + } + } + Err(_) => break, + } + } + }); +} + +#[tokio::main] +pub async fn main() { + let mut srv = JRPCServer::new(); + srv.add_service(SimpleTestServiceHandler::new(Box::from( + TestServiceImplementation {}, + ))); + + let listener = tokio::net::TcpListener::bind("0.0.0.0:4321").await.unwrap(); + + loop { + let (stream, address) = listener.accept().await.unwrap(); + println!("Got connection from {}", address); + handle_connection(stream, &srv); + } +} diff --git a/examples/Typescript/server.ts b/examples/Typescript/server.ts index 0f22576..00b5b17 100644 --- a/examples/Typescript/server.ts +++ b/examples/Typescript/server.ts @@ -1,18 +1,31 @@ import * as net from "net"; -import { Server, AddValueRequest, AddValueResponse } from "./out"; +import { Server, AddValueRequest, AddValueResponse, Test2 } from "./out"; import * as readline from 'node:readline'; const server = new Server.ServiceProvider(); +class SimpleTestService extends Server.SimpleTestService { + async GetTest(name: string, age: number, ctx: undefined): Promise { + return { + name, + age, + }; + } + TestNot(ctx: undefined): void { + + } +} + + class TestService extends Server.TestService { async AddValuesSingleParam( request: AddValueRequest, ctx: undefined ): Promise { return { - value: request.value1 + request!.value2, + value: request.value1! + request!.value2!, }; } async AddValuesMultipleParams( @@ -41,6 +54,7 @@ class TestService extends Server.TestService { } server.addService(new TestService()); +server.addService(new SimpleTestService()); net.createServer((socket) => { socket.on("error", console.error); @@ -57,6 +71,6 @@ net.createServer((socket) => { sess.onMessage(JSON.parse(line)); }) rl.on("error", console.error); -}).listen(8859).on("listening", () => { - console.log("Is listening on :8859"); -}).on("error", console.error) \ No newline at end of file +}).listen(4321).on("listening", () => { + console.log("Is listening on :4321"); +}).on("error", console.error) diff --git a/examples/example.jrpc b/examples/example.jrpc index 8b259a0..ca6ec4e 100644 --- a/examples/example.jrpc +++ b/examples/example.jrpc @@ -53,3 +53,14 @@ service TestService { FunctionWithArrayAsParamAndReturn(values1: float[], values2: float[]): float[]; } + +type Test2 { + name: string; + age: int; +} + +service SimpleTestService { + @Description("asdasdasd") + GetTest(name: string, age: int): Test2; + notification TestNot(); +} diff --git a/examples/test.jrpc b/examples/test.jrpc deleted file mode 100644 index af947c5..0000000 --- a/examples/test.jrpc +++ /dev/null @@ -1,14 +0,0 @@ -define rust_crate test; - -type Test { - name: string; - age: int; -} - -service TestService { - @Description("asdasdasd") - GetTest(name: string, age: int): Test; - notification TestNot(); -} - -// { "jsonrpc": "2.0", "method": "TestService.GetTest", "params": [ "SomeName", 25 ], "id": "someid" } diff --git a/package.json b/package.json index 1d67bb5..66b82ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.1.6", + "version": "1.2.0", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/targets/rust.ts b/src/targets/rust.ts index 3d8cd4b..622eb12 100644 --- a/src/targets/rust.ts +++ b/src/targets/rust.ts @@ -122,7 +122,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { this.addDependencies(a, definition); - a(0, `use crate::base_lib::{JRPCClient,JRPCRequest,Result};`); + a(0, `use crate::base_lib::{JRPCClient, JRPCRequest, Result};`); a(0, `use serde_json::{json};`); a(0, ``); a(0, `pub struct ${definition.name}{`); @@ -142,7 +142,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { let ret = fnc.return ? typeToRust(fnc.return.type, fnc.return.array) : "()"; - a(1, `pub fn ${fnc.name}(&self, ${params}) -> Result<${ret}> {`); + a(1, `pub async fn ${fnc.name}(&self, ${params}) -> Result<${ret}> {`); a(2, `let l_req = JRPCRequest {`); a(3, `jsonrpc: "2.0".to_owned(),`); a(3, `id: None, // 'id' will be set by the send_request function`); @@ -151,21 +151,25 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(2, `};`); a(2, ``); if (fnc.return) { - a(2, `let l_res = self.client.send_request(l_req);`); - a(2, `if let Err(e) = l_res {`); - a(3, `return Err(e);`); - a(2, `} else if let Ok(o) = l_res {`); + a(2, `let l_res = self.client.send_request(l_req).await;`); + a(2, `match l_res {`); + a(3, `Err(e) => return Err(e),`); if (fnc.return.type == "void") { - a(3, `return ();`); + a(3, `Ok(_) => {`); + a(4, `return Ok(());`); + a(3, `}`); } else { + a(3, `Ok(o) => {`); a( - 3, + 4, `return serde_json::from_value(o).map_err(|e| Box::from(e));` ); + a(3, `}`); } - a(2, `} else { panic!("What else cases could there be?"); }`); + a(2, `}`); + } else { - a(2, `self.client.send_notification(l_req);`); + a(2, `self.client.send_notification(l_req).await;`); a(2, `return Ok(());`); } a(1, `}`); @@ -180,61 +184,62 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { const { a, getResult } = LineAppender(); this.addDependencies(a, definition); - a(0, `use crate::base_lib::{JRPCServiceHandler,JRPCRequest,Result};`); + a(0, `use crate::base_lib::{JRPCServerService, JRPCRequest, Result};`); a(0, `use serde_json::{Value};`); + a(0, `use std::sync::Arc;`); + a(0, `use async_trait::async_trait;`); const typeToRust = (type: string, array: boolean) => { let rt = toRustType(type); return array ? `Vec<${rt}>` : rt; }; - const CTX_TYPE = "'static + Sync + Send + Copy"; - - a(0, ``); - a(0, `pub trait ${definition.name} {`); + a(0, `#[async_trait]`); + a(0, `pub trait ${definition.name} {`); for (const fnc of definition.functions) { let params = fnc.inputs.length > 0 ? fnc.inputs - .map((i) => i.name + ": " + typeToRust(i.type, i.array)) - .join(", ") + ", " + .map((i) => i.name + ": " + typeToRust(i.type, i.array)) + .join(", ") : ""; let ret = fnc.return ? typeToRust(fnc.return.type, fnc.return.array) : "()"; - a(1, `fn ${fnc.name}(&self, ${params}context: &C) -> Result<${ret}>;`); + a(1, `async fn ${fnc.name}(&self, ${params}) -> Result<${ret}>;`); } a(0, `}`); a(0, ``); - a(0, `pub struct ${definition.name}Handler {`); - a(1, `implementation: Box + Sync + Send>,`); + a(0, `pub struct ${definition.name}Handler {`); + a(1, `implementation: Box,`); a(0, `}`); a(0, ``); - a(0, `impl ${definition.name}Handler {`); + a(0, `impl ${definition.name}Handler {`); a( 1, - `pub fn new(implementation: Box + Sync + Send>) -> Box {` + `pub fn new(implementation: Box) -> Arc {` ); - a(2, `return Box::from(Self { implementation });`); + a(2, `return Arc::from(Self { implementation });`); a(1, `}`); a(0, `}`); a(0, ``); + a(0, `#[async_trait]`); a( 0, - `impl JRPCServiceHandler for ${definition.name}Handler {` + `impl JRPCServerService for ${definition.name}Handler {` ); - a(1, `fn get_name(&self) -> String { "${definition.name}".to_owned() }`); + a(1, `fn get_id(&self) -> String { "${definition.name}".to_owned() }`); a(0, ``); a( 1, - `fn on_message(&self, msg: JRPCRequest, function: String, ctx: &C) -> Result<(bool, Value)> {` + `async fn handle(&self, msg: &JRPCRequest, function: &str) -> Result<(bool, Value)> {` ); - a(2, `match function.as_str() {`); + a(2, `match function {`); for (const fnc of definition.functions) { a(3, `"${fnc.name}" => {`); a(4, `if msg.params.is_array() {`); @@ -250,10 +255,10 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(6, `serde_json::from_value(arr[${i}].clone())`); a( 7, - `.map_err(|_| "Parameter for field '${inp.name}' should be of type '${inp.type}'!")?,` //TODO: Array + `.map_err(|_| "Parameter for field '${inp.name}' should be of type '${inp.type}'!")?${i == fnc.inputs.length - 1 ? "" : ","}` //TODO: Array ); } - a(5, `ctx)?;`); + a(5, `).await?;`); if (fnc.return) { a(5, `return Ok((true, serde_json::to_value(res)?));`); } else { @@ -296,7 +301,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { const as = ls.a; a(0, `pub mod base_lib;`); - a(0, `pub use base_lib::{JRPCServer,Result};`); + a(0, `pub use base_lib::{JRPCServer, JRPCClient, Result};`); for (const [typ, def] of steps) { if (typ == "type" || typ == "enum") { @@ -306,19 +311,18 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { as(0, `mod ${toSnake(def.name)};`); as( 0, - `pub use ${toSnake(def.name)}::{${def.name}, ${ - def.name + `pub use ${toSnake(def.name)}::{${def.name}, ${def.name }Handler};` ); ac(0, `mod ${toSnake(def.name)};`); ac(0, `pub use ${toSnake(def.name)}::${def.name};`); - - a(0, `pub mod server;`); - a(0, `pub mod client;`); } } + a(0, `pub mod server;`); + a(0, `pub mod client;`); + this.writeFile(`src/lib.rs`, getResult()); this.writeFile(`src/server/mod.rs`, ls.getResult()); this.writeFile(`src/client/mod.rs`, lc.getResult()); diff --git a/templates/Rust/.editorconfig b/templates/Rust/.editorconfig new file mode 100644 index 0000000..1c9705c --- /dev/null +++ b/templates/Rust/.editorconfig @@ -0,0 +1,2 @@ +[*.rs] +indent_size = 4 diff --git a/templates/Rust/Cargo.toml b/templates/Rust/Cargo.toml index dde49f3..a4551e2 100644 --- a/templates/Rust/Cargo.toml +++ b/templates/Rust/Cargo.toml @@ -6,10 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -int-enum = "0.4.0" -serde = { version = "1.0.136", features = ["derive"] } -serde_json = "1.0.79" -threadpool = "1.8.1" +int-enum = "0.5.0" +serde = { version = "1.0.147", features = ["derive"] } +serde_json = "1.0.88" nanoid = "0.4.0" - - +tokio = { version = "1.22.0", features = ["full"] } +log = "0.4.17" +simple_logger = { version = "4.0.0", features = ["threads", "colored", "timestamps", "stderr"] } +async-trait = "0.1.59" diff --git a/templates/Rust/src/lib.rs b/templates/Rust/src/lib.rs index 5754855..59b1839 100644 --- a/templates/Rust/src/lib.rs +++ b/templates/Rust/src/lib.rs @@ -1,286 +1,223 @@ +use log::{info, trace, warn}; use nanoid::nanoid; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::boxed::Box; -use std::collections::HashMap; use std::error::Error; -use std::marker::PhantomData; use std::marker::Send; -use std::sync::mpsc::{Receiver, Sender}; -use std::sync::{Arc, Mutex}; -use threadpool::ThreadPool; +use std::{collections::HashMap, sync::Arc}; +use tokio::sync::{mpsc::Sender, Mutex}; -pub type Result = std::result::Result>; +pub type Result = std::result::Result>; -// TODO: Check what happens when error code is not included -// #[repr(i64)] -// #[derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum, Deserialize, Serialize)] -// pub enum ErrorCodes { -// ParseError = -32700, -// InvalidRequest = -32600, -// MethodNotFound = -32601, -// InvalidParams = -32602, -// InternalError = -32603, -// } - -#[derive(Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct JRPCRequest { - pub jsonrpc: String, - pub id: Option, - pub method: String, - pub params: Value, + pub jsonrpc: String, + pub id: Option, + pub method: String, + pub params: Value, } -#[derive(Serialize, Deserialize)] +impl JRPCRequest { + pub fn new_request(method: String, params: Value) -> JRPCRequest { + JRPCRequest { + jsonrpc: "2.0".to_string(), + id: None, + method, + params, + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct JRPCError { - pub code: i64, - pub message: String, - pub data: Value, + pub code: i64, + pub message: String, + pub data: Value, } -#[derive(Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct JRPCResult { - pub jsonrpc: String, - pub id: String, - pub result: Value, - pub error: Option, + pub jsonrpc: String, + pub id: String, + pub result: Value, + pub error: Option, } -// ****************************************************************************** -// * SERVER -// ****************************************************************************** - -pub trait JRPCServiceHandler: Send { - fn get_name(&self) -> String; - fn on_message(&self, msg: JRPCRequest, function: String, ctx: &C) -> Result<(bool, Value)>; -} - -type Shared = Arc>; -type SharedHM = Shared>; -type ServiceSharedHM = SharedHM>>; - -type SharedThreadPool = Shared; - -pub struct JRPCServer { - services: ServiceSharedHM, - pool: SharedThreadPool, -} - -impl JRPCServer { - pub fn new() -> Self { - return Self { - services: Arc::new(Mutex::new(HashMap::new())), - pool: Arc::new(Mutex::new(ThreadPool::new(32))), - }; - } - - pub fn add_service(&mut self, service: Box>) { - let mut services = self.services.lock().unwrap(); - services.insert(service.get_name(), service); - } - - pub fn start_session( - &mut self, - read_ch: Receiver, - write_ch: Sender, - context: CTX, - ) { - let services = self.services.clone(); - let p = self.pool.lock().unwrap(); - let pool = self.pool.clone(); - p.execute(move || { - JRPCSession::start(read_ch, write_ch, context, services, pool); - }); - } -} - -pub struct JRPCSession { - _ctx: PhantomData, -} - -unsafe impl Sync for JRPCSession {} - -impl JRPCSession { - fn start( - read_ch: Receiver, - write_ch: Sender, - context: CTX, - services: ServiceSharedHM, - pool: SharedThreadPool, - ) { - loop { - let pkg = read_ch.recv(); - let data = match pkg { - Err(_) => return, - Ok(res) => res, - }; - if data.len() == 0 { - //TODO: This can be done better - return; - } - let ctx = context.clone(); - let svs = services.clone(); - let wc = write_ch.clone(); - pool.lock().unwrap().execute(move || { - JRPCSession::handle_packet(data, wc, ctx, svs); - }) - } - } - - fn handle_packet( - data: String, - write_ch: Sender, - context: CTX, - services: ServiceSharedHM, - ) { - let req: Result = - serde_json::from_str(data.as_str()).map_err(|err| Box::from(err)); - - let req = match req { - Err(_) => { - return; - } - Ok(parsed) => parsed, - }; - - let req_id = req.id.clone(); - - let mut parts: Vec = req.method.splitn(2, '.').map(|e| e.to_owned()).collect(); - if parts.len() != 2 { - return Self::send_err_res(req_id, write_ch, Box::from("Error".to_owned())); - } - - let service = parts.remove(0); - let function = parts.remove(0); - - let svs = services.lock().unwrap(); - let srv = svs.get(&service); - - if let Some(srv) = srv { - match srv.on_message(req, function, &context) { - Ok((is_send, value)) => { - if is_send { - if let Some(id) = req_id { - let r = JRPCResult { - jsonrpc: "2.0".to_owned(), - id, - result: value, - error: None, - }; - let s = serde_json::to_string(&r); - if s.is_ok() { - write_ch - .send(s.unwrap()) - .expect("Sending data into channel failed!"); - } - } - } - } - Err(err) => return Self::send_err_res(req_id, write_ch, err), - } - } - } - - fn send_err_res(id: Option, write_ch: Sender, err: Box) { - if let Some(id) = id { - let error = JRPCError { - code: 0, //TODO: Make this better? - message: err.to_string(), - data: Value::Null, - }; - - let r = JRPCResult { - jsonrpc: "2.0".to_owned(), - id: id.clone(), - result: Value::Null, - error: Option::from(error), - }; - - let s = serde_json::to_string(&r); - - if s.is_ok() { - write_ch - .send(s.unwrap()) - .expect("Sending data into channel failed!"); - } - } - - return (); - } -} - -// ****************************************************************************** -// * CLIENT -// ****************************************************************************** - -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct JRPCClient { - write_ch: Sender, - requests: SharedHM>>, + message_sender: Sender, + requests: Arc>>>, } -unsafe impl Send for JRPCClient {} //TODO: Is this a problem - impl JRPCClient { - pub fn new(write_ch: Sender, read_ch: Receiver) -> Self { - let n = Self { - write_ch, - requests: Arc::new(Mutex::new(HashMap::new())), - }; + pub fn new(sender: Sender) -> JRPCClient { + JRPCClient { + message_sender: sender, + requests: Arc::new(Mutex::new(HashMap::new())), + } + } - n.start(read_ch); - return n; - } + pub async fn send_request(&self, mut request: JRPCRequest) -> Result { + let (sender, mut receiver) = tokio::sync::mpsc::channel(1); - pub fn start(&self, read_ch: Receiver) { - let s = self.clone(); - std::thread::spawn(move || { - s.start_reader(read_ch); - }); - } + if request.id.is_none() { + request.id = Some(nanoid!()); + } - fn start_reader(&self, read_ch: Receiver) { - loop { - let data = read_ch.recv().expect("Error receiving packet!"); - let response: JRPCResult = - serde_json::from_str(data.as_str()).expect("Error decoding response!"); - let id = response.id; + { + let mut self_requests = self.requests.lock().await; + self_requests.insert(request.id.clone().unwrap(), sender); + } + self.message_sender.send(request).await?; - let reqs = self.requests.lock().expect("Error locking requests map!"); - let req = reqs.get(&id); - if let Some(req) = req { - let res = if let Some(err) = response.error { - Err(Box::from(err.message)) + let result = receiver.recv().await; + + if let Some(result) = result { + if let Some(error) = result.error { + return Err(format!("Error while receiving result: {}", error.message).into()); } else { - Ok(response.result) + return Ok(result.result); + } + } else { + return Err("Error while receiving result".into()); + } + } + + pub async fn send_notification(&self, mut request: JRPCRequest) { + request.id = None; + + _ = self.message_sender.send(request).await; + } + + pub async fn on_result(&self, result: JRPCResult) { + let id = result.id.clone(); + let mut self_requests = self.requests.lock().await; + let sender = self_requests.get(&id); + if let Some(sender) = sender { + _ = sender.send(result).await; + self_requests.remove(&id); + } + } +} + +#[async_trait::async_trait] +pub trait JRPCServerService: Send + Sync + 'static { + fn get_id(&self) -> String; + async fn handle(&self, request: &JRPCRequest, function: &str) -> Result<(bool, Value)>; +} + +pub type JRPCServiceHandle = Arc; + +#[derive(Clone)] +pub struct JRPCSession { + server: JRPCServer, + message_sender: Sender, +} + +impl JRPCSession { + pub fn new(server: JRPCServer, sender: Sender) -> JRPCSession { + JRPCSession { + server, + message_sender: sender, + } + } + + async fn send_error(&self, request: JRPCRequest, error_msg: String, error_code: i64) -> () { + if let Some(request_id) = request.id { + let error = JRPCError { + code: error_code, + message: error_msg, + data: Value::Null, + }; + let result = JRPCResult { + jsonrpc: "2.0".to_string(), + id: request_id, + result: Value::Null, + error: Some(error), }; - req.send(res).expect("Error sending reponse!"); - } - } - } + // Send result + let result = self.message_sender.send(result).await; + if let Err(err) = result { + warn!("Error while sending result: {}", err); + } + } + } - pub fn send_request(&self, mut req: JRPCRequest) -> Result { - let mut reqs = self.requests.lock().expect("Error locking requests map!"); - let id = nanoid!(); - req.id = Some(id.clone()); + pub fn handle_request(&self, request: JRPCRequest) -> () { + let session = self.clone(); + tokio::task::spawn(async move { + info!("Received request: {}", request.method); + trace!("Request data: {:?}", request); + let method: Vec<&str> = request.method.split('.').collect(); + if method.len() != 2 { + warn!("Invalid method received: {}", request.method); + return; + } + let service = method[0]; + let function = method[1]; - let (tx, rx) = std::sync::mpsc::channel(); - - reqs.insert(id, tx); - self - .write_ch - .send(serde_json::to_string(&req).expect("Error converting Request to JSON!")) - .expect("Error Sending to Channel!"); - return rx.recv().expect("Error getting response!"); - } - - pub fn send_notification(&self, mut req: JRPCRequest) { - req.id = None; - - self - .write_ch - .send(serde_json::to_string(&req).expect("Error converting Request to JSON!")) - .expect("Error Sending to Channel!"); - } + let service = session.server.services.get(service); + if let Some(service) = service { + let result = service.handle(&request, function).await; + match result { + Ok((is_send, result)) => { + if is_send && request.id.is_some() { + let result = session + .message_sender + .send(JRPCResult { + jsonrpc: "2.0".to_string(), + id: request.id.unwrap(), + result, + error: None, + }) + .await; + if let Err(err) = result { + warn!("Error while sending result: {}", err); + } + } + } + Err(err) => { + warn!("Error while handling request: {}", err); + session + .send_error( + request, + format!("Error while handling request: {}", err), + 1, + ) + .await; + } + } + } else { + warn!("Service not found: {}", method[0]); + session + .send_error(request, "Service not found".to_string(), 1) + .await; + return; + } + }); + } +} + +#[derive(Clone)] +pub struct JRPCServer { + services: HashMap, +} + +impl JRPCServer { + pub fn new() -> JRPCServer { + JRPCServer { + services: HashMap::new(), + } + } + + pub fn add_service(&mut self, service: JRPCServiceHandle) -> () { + let id = service.get_id(); + self.services.insert(id, service); + } + + pub fn get_session(&self, sender: Sender) -> JRPCSession { + JRPCSession::new(self.clone(), sender) + } } diff --git a/templates/Rust2.0/.gitignore b/templates/Rust2.0/.gitignore deleted file mode 100644 index a9d37c5..0000000 --- a/templates/Rust2.0/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock diff --git a/templates/Rust2.0/Cargo.toml b/templates/Rust2.0/Cargo.toml deleted file mode 100644 index 603aa7b..0000000 --- a/templates/Rust2.0/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "__name__" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -int-enum = "0.5.0" -serde = { version = "1.0.147", features = ["derive"] } -serde_json = "1.0.88" -threadpool = "1.8.1" -nanoid = "0.4.0" -tokio = { version = "1.22.0", features = ["full"] } - diff --git a/templates/Rust2.0/src/lib.rs b/templates/Rust2.0/src/lib.rs deleted file mode 100644 index c669dc5..0000000 --- a/templates/Rust2.0/src/lib.rs +++ /dev/null @@ -1,44 +0,0 @@ -use nanoid::nanoid; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::boxed::Box; -use std::collections::HashMap; -use std::error::Error; -use std::marker::PhantomData; -use std::marker::Send; -use std::sync::mpsc::{Receiver, Sender}; -use std::sync::{Arc, Mutex}; -use threadpool::ThreadPool; - -pub type Result = std::result::Result>; - -#[derive(Serialize, Deserialize)] -pub struct JRPCRequest { - pub jsonrpc: String, - pub id: Option, - pub method: String, - pub params: Value, -} - -#[derive(Serialize, Deserialize)] -pub struct JRPCError { - pub code: i64, - pub message: String, - pub data: Value, -} - -#[derive(Serialize, Deserialize)] -pub struct JRPCResult { - pub jsonrpc: String, - pub id: String, - pub result: Value, - pub error: Option, -} - -struct JRPCServer {} - -impl JRPCServer { - fn handle(&self) -> () {} -} - -struct JRPCServerService {} From a291851b5a5bae4a2eee0b2a3ccb71048ed22bce Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Wed, 28 Dec 2022 10:19:45 +0100 Subject: [PATCH 03/13] Add allow_non_snake on fields in rust --- package.json | 2 +- src/index.ts | 4 +++- src/targets/rust.ts | 4 ++++ templates/Rust/Cargo.toml | 1 - 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 66b82ac..1017fe8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.0", + "version": "1.2.2", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/index.ts b/src/index.ts index 4854cf9..422cd92 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,13 +4,15 @@ import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import startCompile, { Target, Targets } from "./process"; +const pkg = require("../package.json"); + import dbg from "debug"; const log = dbg("app"); dbg.disable(); yargs(hideBin(process.argv)) - .version("1.0.0") + .version(pkg.version) .command( "compile ", "Compile source", diff --git a/src/targets/rust.ts b/src/targets/rust.ts index 622eb12..29f3bc1 100644 --- a/src/targets/rust.ts +++ b/src/targets/rust.ts @@ -71,6 +71,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(0, `#[derive(Clone, Debug, Serialize, Deserialize)]`); a(0, `pub struct ${definition.name} {`); for (const field of definition.fields) { + a(1, `#[allow(non_snake_case)]`); if (field.array) { a(1, `pub ${field.name}: Vec<${toRustType(field.type)}>,`); } else if (field.map) { @@ -142,6 +143,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { let ret = fnc.return ? typeToRust(fnc.return.type, fnc.return.array) : "()"; + a(1, `#[allow(non_snake_case)]`); a(1, `pub async fn ${fnc.name}(&self, ${params}) -> Result<${ret}> {`); a(2, `let l_req = JRPCRequest {`); a(3, `jsonrpc: "2.0".to_owned(),`); @@ -206,6 +208,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { let ret = fnc.return ? typeToRust(fnc.return.type, fnc.return.array) : "()"; + a(1, `#[allow(non_snake_case)]`); a(1, `async fn ${fnc.name}(&self, ${params}) -> Result<${ret}>;`); } a(0, `}`); @@ -235,6 +238,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(1, `fn get_id(&self) -> String { "${definition.name}".to_owned() }`); a(0, ``); + a(1, `#[allow(non_snake_case)]`); a( 1, `async fn handle(&self, msg: &JRPCRequest, function: &str) -> Result<(bool, Value)> {` diff --git a/templates/Rust/Cargo.toml b/templates/Rust/Cargo.toml index a4551e2..e150e28 100644 --- a/templates/Rust/Cargo.toml +++ b/templates/Rust/Cargo.toml @@ -12,5 +12,4 @@ serde_json = "1.0.88" nanoid = "0.4.0" tokio = { version = "1.22.0", features = ["full"] } log = "0.4.17" -simple_logger = { version = "4.0.0", features = ["threads", "colored", "timestamps", "stderr"] } async-trait = "0.1.59" From 6e947bde579189207eba85f9a632a40d1257f7d6 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Mon, 2 Jan 2023 14:40:45 +0100 Subject: [PATCH 04/13] fix rust invalid field names --- package.json | 2 +- src/process.ts | 2 +- src/targets/rust.ts | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 1017fe8..64fc477 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.2", + "version": "1.2.3", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/process.ts b/src/process.ts index e5f1949..7d22a5b 100644 --- a/src/process.ts +++ b/src/process.ts @@ -18,7 +18,7 @@ import { ZIGTarget } from "./targets/zig"; import { DartTarget } from "./targets/dart"; import { URL } from "url"; -class CatchedError extends Error {} +class CatchedError extends Error { } const log = dbg("app"); diff --git a/src/targets/rust.ts b/src/targets/rust.ts index 29f3bc1..e8348af 100644 --- a/src/targets/rust.ts +++ b/src/targets/rust.ts @@ -1,6 +1,6 @@ import chalk from "chalk"; import { CompileTarget } from "../compile"; -import { TypeDefinition, EnumDefinition, ServiceDefinition, Step } from "../ir"; +import { TypeDefinition, EnumDefinition, ServiceDefinition, Step, IR } from "../ir"; import { lineAppender, LineAppender } from "../utils"; const conversion = { @@ -72,17 +72,28 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(0, `pub struct ${definition.name} {`); for (const field of definition.fields) { a(1, `#[allow(non_snake_case)]`); + + let fn = `pub ${field.name}:`; + if (field.name == "type") { + // TODO: Add other keywords as well! + console.log( + chalk.yellow("[RUST] WARNING:"), + "Field name 'type' is not allowed in Rust. Renaming to 'type_'" + ); + fn = `pub type_:`; + a(1, `#[serde(rename = "type")]`); + } if (field.array) { - a(1, `pub ${field.name}: Vec<${toRustType(field.type)}>,`); + a(1, `${fn} Vec<${toRustType(field.type)}>,`); } else if (field.map) { a( 1, - `pub ${field.name}: HashMap<${toRustType( + `${fn} HashMap<${toRustType( field.map )}, ${toRustType(field.type)}>,` ); } else { - a(1, `pub ${field.name}: ${toRustType(field.type)},`); + a(1, `${fn} ${toRustType(field.type)},`); } } a(0, `}`); @@ -219,6 +230,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(0, `}`); a(0, ``); a(0, `impl ${definition.name}Handler {`); + //TODO: Maybe add a new definition like, pub fn new2(implementation: T) where T: ${definition.name} + Sync + Send + 'static {} a( 1, `pub fn new(implementation: Box) -> Arc {` From b3b202c9f9158fae2ab0f9eb91abf7e79c567eac Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Mon, 2 Jan 2023 16:34:13 +0100 Subject: [PATCH 05/13] Support enums --- README.md | 11 ++++++-- examples/import.jrpc | 6 ++--- package.json | 2 +- src/ir.ts | 2 ++ src/parser.ts | 30 +++++++++++++--------- src/targets/rust.ts | 17 +++++++++---- src/targets/typescript.ts | 53 +++++++++++++++++++++------------------ templates/Rust/Cargo.toml | 2 +- 8 files changed, 75 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index f7a9d89..875bd1d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ Type/Service definition language and code generator for json-rpc 2.0. Currently | ------- | --------------------------------- | | ts-node | Typescript for NodeJS | | ts-esm | Typescript in ESM format for Deno | +| rust | Rust | +| dart | Dart | +| c# | C# | ## Usage @@ -23,7 +26,7 @@ enum TestEnum { type Test { testen: TestEnum; someString: string; - someNumber: number; + someNumber?: number; array: string[]; map: {number, TestEnum}; } @@ -44,4 +47,8 @@ Then run the generator like this `jrpc compile test.jrpc -o=ts-node:output/`. This will generate the Client and Server code in the specified folder. -//TODO: Make Documentation better +## TODOS + +1. Documentation +2. Null Checks/Enforcements in all languages +3. More and better tests diff --git a/examples/import.jrpc b/examples/import.jrpc index e44c177..c00e58d 100644 --- a/examples/import.jrpc +++ b/examples/import.jrpc @@ -1,5 +1,5 @@ type TestAtom { - val_number: float; - val_boolean: boolean; - val_string: string; + val_number?: float; + val_boolean?: boolean; + val_string?: string; } diff --git a/package.json b/package.json index 64fc477..3657c80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.3", + "version": "1.2.5", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/ir.ts b/src/ir.ts index 7549d0d..c758f6e 100644 --- a/src/ir.ts +++ b/src/ir.ts @@ -14,6 +14,7 @@ export interface TypeFieldDefinition { name: string; type: string; array: boolean; + optional: boolean; map?: string; } @@ -127,6 +128,7 @@ export default function get_ir(parsed: Parsed): IR { type: field.fieldtype, array: field.array, map: field.map, + optional: field.optional, }; }); steps.push([ diff --git a/src/parser.ts b/src/parser.ts index e9e0d62..2224736 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -16,6 +16,7 @@ export interface ImportStatement extends DefinitionNode { export interface TypeFieldStatement extends DefinitionNode { type: "type_field"; name: string; + optional: boolean; fieldtype: string; array: boolean; map?: string; @@ -134,13 +135,12 @@ export default function parse(tokens: Token[], file: string): Parsed { return val; }; - + const checkTypes = (...types: string[]) => { if (types.indexOf(currentToken.type) < 0) { throw new ParserError( - `Unexpected token value, expected ${types.join(" | ")}, received '${ - currentToken.value + `Unexpected token value, expected ${types.join(" | ")}, received '${currentToken.value }'`, currentToken ); @@ -170,6 +170,11 @@ export default function parse(tokens: Token[], file: string): Parsed { const idx = currentToken.startIdx; let name = currentToken.value; eatToken(); + let optional = false; + if (currentToken.type === "questionmark") { + eatToken("?"); + optional = true; + } eatToken(":"); let array = false; @@ -198,6 +203,7 @@ export default function parse(tokens: Token[], file: string): Parsed { array, map: mapKey, location: { file, idx }, + optional }; }; @@ -303,9 +309,9 @@ export default function parse(tokens: Token[], file: string): Parsed { eatToken("("); let args: string[] = []; let first = true; - while(currentToken.value !== ")") { - if(first) { - first= false; + while (currentToken.value !== ")") { + if (first) { + first = false; } else { eatToken(","); } @@ -399,8 +405,8 @@ export default function parse(tokens: Token[], file: string): Parsed { let functions: ServiceFunctionStatement[] = []; while (currentToken.type !== "curly_close") { - let decorators:Decorators = new Map; - while(currentToken.type == "at") { + let decorators: Decorators = new Map; + while (currentToken.type == "at") { parseFunctionDecorator(decorators); } @@ -427,8 +433,8 @@ export default function parse(tokens: Token[], file: string): Parsed { let [key] = eatText() let value: string = undefined; - if(currentToken.type == "string") { - value = currentToken.value.slice(1,-1); + if (currentToken.type == "string") { + value = currentToken.value.slice(1, -1); eatToken(); } else { [value] = eatText() @@ -437,8 +443,8 @@ export default function parse(tokens: Token[], file: string): Parsed { eatToken(";"); return { - type :"define", - location: {file, idx}, + type: "define", + location: { file, idx }, key, value } diff --git a/src/targets/rust.ts b/src/targets/rust.ts index e8348af..c702080 100644 --- a/src/targets/rust.ts +++ b/src/targets/rust.ts @@ -83,17 +83,24 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { fn = `pub type_:`; a(1, `#[serde(rename = "type")]`); } + let opts = ""; + let opte = ""; + if (field.optional) { + opts = "Option<"; + opte = ">"; + } + if (field.array) { - a(1, `${fn} Vec<${toRustType(field.type)}>,`); + a(1, `${fn} ${opts}Vec<${toRustType(field.type)}>${opte},`); } else if (field.map) { a( 1, - `${fn} HashMap<${toRustType( + `${fn} ${opts}HashMap<${toRustType( field.map - )}, ${toRustType(field.type)}>,` + )}, ${toRustType(field.type)}>${opte},` ); } else { - a(1, `${fn} ${toRustType(field.type)},`); + a(1, `${fn} ${opts}${toRustType(field.type)}${opte},`); } } a(0, `}`); @@ -113,7 +120,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(0, `#[repr(i64)]`); a( 0, - "#[derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum, Deserialize, Serialize)]" + "#[derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum)]" ); a(0, `pub enum ${definition.name} {`); for (const field of definition.values) { diff --git a/src/targets/typescript.ts b/src/targets/typescript.ts index a968a07..761dc6f 100644 --- a/src/targets/typescript.ts +++ b/src/targets/typescript.ts @@ -33,9 +33,8 @@ export class TypescriptTarget extends CompileTarget { } private generateImport(imports: string, path: string) { - return `import ${imports} from "${ - path + (this.flavour === "esm" ? ".ts" : "") - }";\n`; + return `import ${imports} from "${path + (this.flavour === "esm" ? ".ts" : "") + }";\n`; } private generateImports( @@ -89,7 +88,7 @@ export class TypescriptTarget extends CompileTarget { } else { type = toJSType(field.type); } - return `${field.name}?: ${type}; `; + return `${field.name}${field.optional ? "?" : ""}: ${type}; `; }) ); @@ -125,10 +124,18 @@ export class TypescriptTarget extends CompileTarget { ); a(1, `let res = new ${def.name}() as any;`); def.fields.forEach((field) => { - a( - 1, - `if(data["${field.name}"] !== null && data["${field.name}"] !== undefined) {` - ); + if (field.optional) { + a( + 1, + `if(data["${field.name}"] !== null && data["${field.name}"] !== undefined) {` + ); + } else { + a( + 1, + `if(data["${field.name}"] === null || data["${field.name}"] === undefined) throw new VerificationError("${def.name}", "${field.name}", data["${field.name}"]);` + ); + a(1, `else {`); + } if (field.array) { a( 2, @@ -203,9 +210,9 @@ export class TypescriptTarget extends CompileTarget { "{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base" ) + - this.generateImport(" { VerificationError }", "./ts_base") + - "\n\n" + - this.getTemplate("ts_service_client.ts") + this.generateImport(" { VerificationError }", "./ts_base") + + "\n\n" + + this.getTemplate("ts_service_client.ts") ); const { a, getResult } = LineAppender(); @@ -300,9 +307,9 @@ export class TypescriptTarget extends CompileTarget { "{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base" ) + - this.generateImport(" { VerificationError }", "./ts_base") + - "\n\n" + - this.getTemplate("ts_service_server.ts") + this.generateImport(" { VerificationError }", "./ts_base") + + "\n\n" + + this.getTemplate("ts_service_server.ts") ); this.generateImports(a, def); @@ -335,9 +342,8 @@ export class TypescriptTarget extends CompileTarget { `ctx: T`, ].join(", "); const retVal = fnc.return - ? `Promise<${ - toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "") - }>` + ? `Promise<${toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "") + }>` : `void`; a(1, `abstract ${fnc.name}(${params}): ${retVal};`); @@ -380,13 +386,12 @@ export class TypescriptTarget extends CompileTarget { a( 2, `return this.${fnc.name}.call(this, ...p)` + //TODO: Refactor. This line is way to compicated for anyone to understand, including me - (fnc.return - ? `.then(${ - fnc.return?.array - ? `res => res.map(e => apply_${fnc.return.type}(e))` - : `res => apply_${fnc.return.type}(res)` - });` - : "") + (fnc.return + ? `.then(${fnc.return?.array + ? `res => res.map(e => apply_${fnc.return.type}(e))` + : `res => apply_${fnc.return.type}(res)` + });` + : "") ); a(1, `}`); a(0, ``); diff --git a/templates/Rust/Cargo.toml b/templates/Rust/Cargo.toml index e150e28..8ac3329 100644 --- a/templates/Rust/Cargo.toml +++ b/templates/Rust/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -int-enum = "0.5.0" +int-enum = { version ="0.5.0", features = ["serde", "convert"] } serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.88" nanoid = "0.4.0" From 137a3659b79205aaa2ad3d064c4c15649b996cd7 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Thu, 12 Jan 2023 17:47:06 +0100 Subject: [PATCH 06/13] Add better error message to VerificationError --- package.json | 2 +- templates/ts_base.ts | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 3657c80..0ca46f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.5", + "version": "1.2.6", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/templates/ts_base.ts b/templates/ts_base.ts index 7c27aa2..b3b9e3f 100644 --- a/templates/ts_base.ts +++ b/templates/ts_base.ts @@ -1,14 +1,24 @@ +import { isGeneratorFunction } from "util/types"; + +function form_verficiation_error_message(type?: string, field?: string) { + let msg = "Parameter verification failed! "; + if (type && field) { + msg += `At ${type}.${field}! `; + } else if (type) { + msg += `At type ${type}! `; + } else if (field) { + msg += `At field ${field}! `; + } + return msg; +} + export class VerificationError extends Error { constructor( public readonly type?: string, public readonly field?: string, public readonly value?: any ) { - super( - "Parameter verification failed! " + - (type ? "Expected " + type + "! " : "") + - (field ? "At: " + field + "! " : "") - ); + super(form_verficiation_error_message(type, field)); } } @@ -33,4 +43,4 @@ export function apply_boolean(data: any) { return Boolean(data); } -export function apply_void(data: any) {} +export function apply_void(data: any) { } From 5106424a320aa21c73ac2a2cf840dc697b7e0b01 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Mon, 27 Mar 2023 20:21:41 +0200 Subject: [PATCH 07/13] Allow import of http jrpc definitions inside local ones --- package.json | 2 +- src/process.ts | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 0ca46f9..fc0dde0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.6", + "version": "1.2.11", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/process.ts b/src/process.ts index 7d22a5b..21b6a9e 100644 --- a/src/process.ts +++ b/src/process.ts @@ -18,7 +18,7 @@ import { ZIGTarget } from "./targets/zig"; import { DartTarget } from "./targets/dart"; import { URL } from "url"; -class CatchedError extends Error { } +class CatchedError extends Error {} const log = dbg("app"); @@ -46,15 +46,19 @@ function indexToLineAndCol(src: string, index: number) { return { line, col }; } -function resolve(base: string, ...parts: string[]) { - if (base.startsWith("http://") || base.startsWith("https://")) { +function resolve(base: string, sub?: string) { + if (sub && (sub.startsWith("http://") || sub.startsWith("https://"))) { + let u = new URL(sub); + return u.href; + } else if (base.startsWith("http://") || base.startsWith("https://")) { let u = new URL(base); - for (const part of parts) { - u = new URL(part, u); + if (sub) { + u = new URL(sub, u); } return u.href; } else { - return Path.resolve(base, ...parts); + if (!sub) return Path.resolve(base); + else return Path.resolve(Path.dirname(base), sub + ".jrpc"); } } @@ -151,13 +155,7 @@ async function processFile( let resolved: Parsed = []; for (const statement of parsed) { if (statement.type == "import") { - let res: string; - if (file.startsWith("http://") || file.startsWith("https://")) { - res = resolve(file, statement.path + ".jrpc"); - } else { - const base = Path.dirname(file); - res = resolve(base, statement.path + ".jrpc"); - } + let res = resolve(file, statement.path); resolved.push(...((await processFile(ctx, res)) || [])); } else { resolved.push(statement); From 04f82b655b8acd33d70dfca4de4fbb23141ee1ab Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Tue, 25 Apr 2023 08:14:16 +0200 Subject: [PATCH 08/13] Fix missing file extension on sub URL imports --- package.json | 2 +- src/process.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fc0dde0..c410bfa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.11", + "version": "1.2.12", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/process.ts b/src/process.ts index 21b6a9e..8971bde 100644 --- a/src/process.ts +++ b/src/process.ts @@ -18,7 +18,7 @@ import { ZIGTarget } from "./targets/zig"; import { DartTarget } from "./targets/dart"; import { URL } from "url"; -class CatchedError extends Error {} +class CatchedError extends Error { } const log = dbg("app"); @@ -53,6 +53,9 @@ function resolve(base: string, sub?: string) { } else if (base.startsWith("http://") || base.startsWith("https://")) { let u = new URL(base); if (sub) { + if (!sub.endsWith(".jrpc")) { + sub += ".jrpc"; + } u = new URL(sub, u); } return u.href; From 132390fa357f98e0437f90427fbf49779f3bea99 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Tue, 25 Apr 2023 08:55:57 +0200 Subject: [PATCH 09/13] Make result field of JRPCResult Optional --- package.json | 2 +- templates/Rust/src/lib.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c410bfa..4ecad40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.12", + "version": "1.2.13", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/templates/Rust/src/lib.rs b/templates/Rust/src/lib.rs index 59b1839..d474895 100644 --- a/templates/Rust/src/lib.rs +++ b/templates/Rust/src/lib.rs @@ -40,7 +40,7 @@ pub struct JRPCError { pub struct JRPCResult { pub jsonrpc: String, pub id: String, - pub result: Value, + pub result: Option, pub error: Option, } @@ -76,8 +76,10 @@ impl JRPCClient { if let Some(result) = result { if let Some(error) = result.error { return Err(format!("Error while receiving result: {}", error.message).into()); + } else if let Some(result) = result.result { + return Ok(result); } else { - return Ok(result.result); + return Err(format!("No result received").into()); } } else { return Err("Error while receiving result".into()); @@ -133,7 +135,7 @@ impl JRPCSession { let result = JRPCResult { jsonrpc: "2.0".to_string(), id: request_id, - result: Value::Null, + result: None, error: Some(error), }; @@ -169,7 +171,7 @@ impl JRPCSession { .send(JRPCResult { jsonrpc: "2.0".to_string(), id: request.id.unwrap(), - result, + result: Some(result), error: None, }) .await; From f401d58f078a4dbd0befc5e2fba4b22e7dee86da Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Wed, 19 Jul 2023 12:53:36 +0200 Subject: [PATCH 10/13] Fix bug on rust client with void responses --- package.json | 2 +- templates/Rust/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4ecad40..e05f69b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.13", + "version": "1.2.14", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/templates/Rust/src/lib.rs b/templates/Rust/src/lib.rs index d474895..2dc2f96 100644 --- a/templates/Rust/src/lib.rs +++ b/templates/Rust/src/lib.rs @@ -79,7 +79,8 @@ impl JRPCClient { } else if let Some(result) = result.result { return Ok(result); } else { - return Err(format!("No result received").into()); + return Ok(Value::Null); + // return Err(format!("No result received").into()); } } else { return Err("Error while receiving result".into()); From f93755604a6b48782401724b5d9e782c23802ac4 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Thu, 30 Nov 2023 00:13:10 +0100 Subject: [PATCH 11/13] Improve esm compatability --- src/targets/typescript.ts | 4 ++-- templates/ts_base.ts | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/targets/typescript.ts b/src/targets/typescript.ts index 761dc6f..bf256f2 100644 --- a/src/targets/typescript.ts +++ b/src/targets/typescript.ts @@ -33,7 +33,7 @@ export class TypescriptTarget extends CompileTarget { } private generateImport(imports: string, path: string) { - return `import ${imports} from "${path + (this.flavour === "esm" ? ".ts" : "") + return `import ${imports} from "${path + (this.flavour === "esm" ? ".js" : "") }";\n`; } @@ -207,7 +207,7 @@ export class TypescriptTarget extends CompileTarget { this.writeFormattedFile( "service_client.ts", this.generateImport( - "{ RequestObject, ResponseObject, ErrorCodes, Logging }", + "{ type RequestObject, type ResponseObject, ErrorCodes, Logging }", "./service_base" ) + this.generateImport(" { VerificationError }", "./ts_base") + diff --git a/templates/ts_base.ts b/templates/ts_base.ts index b3b9e3f..d296810 100644 --- a/templates/ts_base.ts +++ b/templates/ts_base.ts @@ -1,5 +1,3 @@ -import { isGeneratorFunction } from "util/types"; - function form_verficiation_error_message(type?: string, field?: string) { let msg = "Parameter verification failed! "; if (type && field) { From e15ce1f0a0f8dc0ef083e3ac1eb0e162bcffc295 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Thu, 30 Nov 2023 00:16:53 +0100 Subject: [PATCH 12/13] Fix more --- package.json | 4 ++-- src/targets/typescript.ts | 2 +- templates/ts_service_server.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e05f69b..a543fe9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.14", + "version": "1.2.16", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", @@ -48,4 +48,4 @@ "dependencies": { "fs-extra": "^10.0.0" } -} +} \ No newline at end of file diff --git a/src/targets/typescript.ts b/src/targets/typescript.ts index bf256f2..014b480 100644 --- a/src/targets/typescript.ts +++ b/src/targets/typescript.ts @@ -304,7 +304,7 @@ export class TypescriptTarget extends CompileTarget { this.writeFormattedFile( "service_server.ts", this.generateImport( - "{ RequestObject, ResponseObject, ErrorCodes, Logging }", + "{ type RequestObject, type ResponseObject, ErrorCodes, Logging }", "./service_base" ) + this.generateImport(" { VerificationError }", "./ts_base") + diff --git a/templates/ts_service_server.ts b/templates/ts_service_server.ts index c8c3ec9..0a4e011 100644 --- a/templates/ts_service_server.ts +++ b/templates/ts_service_server.ts @@ -1,14 +1,14 @@ //@template-ignore import { VerificationError } from "./ts_base"; //@template-ignore -import { RequestObject, ResponseObject, ErrorCodes, Logging } from "./ts_service_base"; +import { type RequestObject, type ResponseObject, ErrorCodes, Logging } from "./ts_service_base"; export class Service { public name: string = null as any; public functions = new Set(); - constructor() {} + constructor() { } } type ISendMessageCB = (data: any, catchedErr?: Error) => void; @@ -37,7 +37,7 @@ class Session { this.ctx = ctx || {}; } - send(data: any, catchedErr?:Error) { + send(data: any, catchedErr?: Error) { Logging.log("SERVER: Sending Message", data) this._send(data, catchedErr); } @@ -95,7 +95,7 @@ class Session { } let result = await (service as any)["_" + fncName](data.params, this.ctx); - if(data.id) { //Request + if (data.id) { //Request this.send({ jsonrpc: "2.0", id: data.id, From 7bc9adebaa75f46fb5325f2255d5d859cd444c8d Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Thu, 18 Jan 2024 19:08:44 +0100 Subject: [PATCH 13/13] Fix some keyword errors --- examples/CSharp/Example/Program.cs | 4 ++ examples/example.jrpc | 8 ++++ package.json | 2 +- src/parser.ts | 6 +-- src/targets/csharp.ts | 61 ++++++++++++++++++++---------- src/targets/rust.ts | 24 ++++++++---- templates/ts_service_client.ts | 2 +- 7 files changed, 76 insertions(+), 31 deletions(-) diff --git a/examples/CSharp/Example/Program.cs b/examples/CSharp/Example/Program.cs index 138cdbd..3fe9e23 100644 --- a/examples/CSharp/Example/Program.cs +++ b/examples/CSharp/Example/Program.cs @@ -41,6 +41,10 @@ class TestSrvimpl : Example.TestServiceServer throw new Exception("This is a remote error :)"); } + public override Task FunctionWithKeywords(double type, double static_, double event_, int ctx) + { + throw new NotImplementedException(); + } } class CopyTransportS2 : Example.JRpcTransport diff --git a/examples/example.jrpc b/examples/example.jrpc index ca6ec4e..a156746 100644 --- a/examples/example.jrpc +++ b/examples/example.jrpc @@ -52,6 +52,8 @@ service TestService { FunctionWithArrayAsParamAndReturn(values1: float[], values2: float[]): float[]; + + FunctionWithKeywords(type: float, static: float, event: float): float; } type Test2 { @@ -59,6 +61,12 @@ type Test2 { age: int; } +type TestKeywords { + type: float; + static: float; + event: float; +} + service SimpleTestService { @Description("asdasdasd") GetTest(name: string, age: int): Test2; diff --git a/package.json b/package.json index a543fe9..b87d366 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hibas123/jrpcgen", - "version": "1.2.16", + "version": "1.2.17", "main": "lib/index.js", "license": "MIT", "packageManager": "yarn@3.1.1", diff --git a/src/parser.ts b/src/parser.ts index 2224736..e3b8308 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -115,8 +115,8 @@ export default function parse(tokens: Token[], file: string): Parsed { return idx; }; - const eatText = (): [string, number] => { - checkTypes("text"); + const eatText = (allowKeyword?: boolean): [string, number] => { + checkTypes(...(allowKeyword ? ["text", "keyword"] : ["text"])); let val = currentToken.value; let idx = currentToken.startIdx; eatToken(); @@ -351,7 +351,7 @@ export default function parse(tokens: Token[], file: string): Parsed { if (currentToken.value !== ")") { while (true) { - const [name] = eatText(); + const [name] = eatText(true); eatToken(":"); const [type] = eatText(); let array = false; diff --git a/src/targets/csharp.ts b/src/targets/csharp.ts index 0d5cce5..cd666a7 100644 --- a/src/targets/csharp.ts +++ b/src/targets/csharp.ts @@ -8,6 +8,7 @@ import { import { CompileTarget } from "../compile"; import { LineAppender } from "../utils"; +import chalk from "chalk"; const conversion = { boolean: "bool", @@ -22,6 +23,16 @@ function toCSharpType(type: string): string { return (conversion as any)[type] || type; } +// TODO: Add other keywords as well! +const keywords = new Set(["event", "internal", "public", "private", "static"]); + +const fixKeywordName = (name: string) => { + if (keywords.has(name)) { + return `${name}_`; + } + return name; +} + export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { name: string = "c#"; @@ -61,11 +72,20 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { a(0, ``); a(0, `public class ${definition.name} {`); for (const field of definition.fields) { + let fn = field.name; + if (keywords.has(field.name)) { + console.log( + chalk.yellow("[RUST] WARNING:"), + `Field name '${fn}' is not allowed in C#. Renaming to '${fn}_'` + ); + fn = fixKeywordName(fn); + a(1, `[JsonPropertyName("${fn}")]`); + } + if (field.array) { a( 1, - `public IList<${toCSharpType(field.type)}>? ${ - field.name + `public IList<${toCSharpType(field.type)}>? ${fn } { get; set; }` ); } else if (field.map) { @@ -73,12 +93,12 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { 1, `public Dictionary<${toCSharpType(field.map)}, ${toCSharpType( field.type - )}>? ${field.name} { get; set; }` + )}>? ${fn} { get; set; }` ); } else { a( 1, - `public ${toCSharpType(field.type)}? ${field.name} { get; set; }` + `public ${toCSharpType(field.type)}? ${fn} { get; set; }` ); } } @@ -127,10 +147,12 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { for (const fnc of definition.functions) { let params = fnc.inputs .map((inp) => { + let name = fixKeywordName(inp.name); + if (inp.array) { - return `List<${toCSharpType(inp.type)}> ${inp.name}`; + return `List<${toCSharpType(inp.type)}> ${name}`; } else { - return `${toCSharpType(inp.type)} ${inp.name}`; + return `${toCSharpType(inp.type)} ${name}`; } }) .join(", "); @@ -139,7 +161,7 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { a( 2, `var param = new JsonArray(${fnc.inputs - .map((e) => `JsonSerializer.SerializeToNode(${e.name})`) + .map((e) => `JsonSerializer.SerializeToNode(${fixKeywordName(e.name)})`) .join(", ")});` ); @@ -219,10 +241,11 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { for (const fnc of definition.functions) { let params = [ ...fnc.inputs.map((inp) => { + let name = fixKeywordName(inp.name) if (inp.array) { - return `List<${toCSharpType(inp.type)}> ${inp.name}`; + return `List<${toCSharpType(inp.type)}> ${name}`; } else { - return `${toCSharpType(inp.type)} ${inp.name}`; + return `${toCSharpType(inp.type)} ${name}`; } }), "TContext ctx", @@ -272,15 +295,15 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { a( 4, pref + - `this.${fnc.name}(${[ - ...fnc.inputs.map((inp, idx) => { - let type = inp.array - ? `List<${toCSharpType(inp.type)}>` - : `${toCSharpType(inp.type)}`; - return `param[${idx}]!.Deserialize<${type}>()`; - }), - "context", - ].join(", ")});` + `this.${fnc.name}(${[ + ...fnc.inputs.map((inp, idx) => { + let type = inp.array + ? `List<${toCSharpType(inp.type)}>` + : `${toCSharpType(inp.type)}`; + return `param[${idx}]!.Deserialize<${type}>()`; + }), + "context", + ].join(", ")});` ); if (fnc.return && fnc.return.type != "void") { @@ -314,5 +337,5 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> { this.generateServiceServer(definition); } - finalize(steps: Step[]): void {} + finalize(steps: Step[]): void { } } diff --git a/src/targets/rust.ts b/src/targets/rust.ts index c702080..ff2820c 100644 --- a/src/targets/rust.ts +++ b/src/targets/rust.ts @@ -23,6 +23,16 @@ function toSnake(input: string) { ); } +// TODO: Add other keywords as well! +const keywords = new Set(["type", "static"]); + +const fixKeywordName = (name: string) => { + if (keywords.has(name)) { + return `${name}_`; + } + return name; +} + export class RustTarget extends CompileTarget<{ rust_crate: string }> { name: string = "rust"; @@ -74,14 +84,14 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(1, `#[allow(non_snake_case)]`); let fn = `pub ${field.name}:`; - if (field.name == "type") { + if (keywords.has(field.name)) { // TODO: Add other keywords as well! console.log( chalk.yellow("[RUST] WARNING:"), - "Field name 'type' is not allowed in Rust. Renaming to 'type_'" + `Field name '${field.name}' is not allowed in Rust. Renaming to '${field.name}_'` ); - fn = `pub type_:`; - a(1, `#[serde(rename = "type")]`); + fn = `pub ${fixKeywordName(field.name)}:`; + a(1, `#[serde(rename = "${field.name}")]`); } let opts = ""; let opte = ""; @@ -156,7 +166,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(0, ``); for (const fnc of definition.functions) { let params = fnc.inputs - .map((i) => i.name + ": " + typeToRust(i.type, i.array)) + .map((i) => fixKeywordName(i.name) + ": " + typeToRust(i.type, i.array)) .join(", "); let ret = fnc.return ? typeToRust(fnc.return.type, fnc.return.array) @@ -167,7 +177,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { a(3, `jsonrpc: "2.0".to_owned(),`); a(3, `id: None, // 'id' will be set by the send_request function`); a(3, `method: "${definition.name}.${fnc.name}".to_owned(),`); - a(3, `params: json!([${fnc.inputs.map((e) => e.name)}])`); + a(3, `params: json!([${fnc.inputs.map((e) => fixKeywordName(e.name))}])`); a(2, `};`); a(2, ``); if (fnc.return) { @@ -220,7 +230,7 @@ export class RustTarget extends CompileTarget<{ rust_crate: string }> { let params = fnc.inputs.length > 0 ? fnc.inputs - .map((i) => i.name + ": " + typeToRust(i.type, i.array)) + .map((i) => fixKeywordName(i.name) + ": " + typeToRust(i.type, i.array)) .join(", ") : ""; let ret = fnc.return diff --git a/templates/ts_service_client.ts b/templates/ts_service_client.ts index 17abdd1..0048b83 100644 --- a/templates/ts_service_client.ts +++ b/templates/ts_service_client.ts @@ -1,7 +1,7 @@ //@template-ignore import { VerificationError } from "./ts_base"; //@template-ignore -import { RequestObject, ResponseObject, ErrorCodes, Logging } from "./ts_service_base"; +import { type RequestObject, type ResponseObject, ErrorCodes, Logging } from "./ts_service_base"; export type IMessageCallback = (data: any) => void;