Compare commits
6 Commits
0e73f7b5b3
...
0.1.1
Author | SHA1 | Date | |
---|---|---|---|
369ccbe84e | |||
6cb51c4120 | |||
bfb8c076be | |||
f4b32f650c | |||
c168df8365 | |||
ffacba2e96 |
211
Cargo.lock
generated
211
Cargo.lock
generated
@ -105,7 +105,7 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -193,6 +193,16 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
@ -210,13 +220,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.2.8"
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -228,29 +237,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"env_filter",
|
||||
"humantime",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@ -456,12 +442,6 @@ version = "1.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.4.1"
|
||||
@ -581,12 +561,13 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "jrpc-cli"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"libjrpc",
|
||||
"log",
|
||||
"simple_logger",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@ -629,8 +610,6 @@ name = "libjrpc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ctor",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"regex",
|
||||
@ -700,6 +679,21 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.4"
|
||||
@ -792,6 +786,12 @@ version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
@ -1060,6 +1060,18 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simple_logger"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"log",
|
||||
"time",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
@ -1166,6 +1178,39 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
@ -1478,7 +1523,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1487,7 +1532,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1497,7 +1542,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1506,7 +1560,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1515,7 +1569,22 @@ version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1524,28 +1593,46 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@ -1558,24 +1645,48 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "jrpc-cli"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
@ -12,5 +12,6 @@ anyhow = "1"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
libjrpc = { path = "libjrpc" }
|
||||
log = "0.4"
|
||||
simple_logger = { version = "5.0.0", features = ["threads"] }
|
||||
[dev-dependencies]
|
||||
walkdir = "2"
|
||||
|
@ -14,7 +14,3 @@ log = "0.4.22"
|
||||
regex = "1.10.6"
|
||||
reqwest = { version = "0.12.7", optional = true, features = ["blocking"] }
|
||||
url = { version = "2.5.2", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.11.5"
|
||||
ctor = "*"
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
use std::{collections::BTreeMap, path::PathBuf};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
|
||||
pub trait Compile {
|
||||
fn new(options: &HashMap<String, String>) -> Result<Self>
|
||||
fn new(options: &BTreeMap<String, String>) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
@ -137,9 +137,9 @@ impl FileGenerator {
|
||||
self.a(6, content);
|
||||
}
|
||||
|
||||
pub fn add_line(&mut self, line: &str) {
|
||||
self.content.push(line.to_string());
|
||||
}
|
||||
// pub fn add_line(&mut self, line: &str) {
|
||||
// self.content.push(line.to_string());
|
||||
// }
|
||||
|
||||
pub fn get_content(&self) -> String {
|
||||
self.content.join("\n")
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
error::Error,
|
||||
fmt::Display,
|
||||
fmt::{Debug, Display},
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
@ -13,13 +13,14 @@ use crate::parser::{
|
||||
|
||||
static BUILT_INS: [&str; 6] = ["int", "float", "string", "boolean", "bytes", "void"];
|
||||
|
||||
pub trait Definition {
|
||||
pub trait Definition: Debug {
|
||||
fn get_position(&self) -> ParserPosition;
|
||||
fn get_name(&self) -> String;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IR {
|
||||
pub options: HashMap<String, String>,
|
||||
pub options: BTreeMap<String, String>,
|
||||
pub steps: Vec<Step>,
|
||||
}
|
||||
|
||||
@ -57,7 +58,12 @@ impl ToString for BaseType {
|
||||
|
||||
impl Hash for BaseType {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.to_string().hash(state);
|
||||
// Hash the enum variant itself
|
||||
std::mem::discriminant(self).hash(state);
|
||||
// If the variant has data, hash that too
|
||||
if let BaseType::Custom(name) = self {
|
||||
name.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +183,7 @@ impl Type {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeDefinition {
|
||||
pub name: String,
|
||||
pub depends: HashSet<BaseType>,
|
||||
pub depends: BTreeSet<BaseType>,
|
||||
pub fields: Vec<Field>,
|
||||
pub position: ParserPosition,
|
||||
}
|
||||
@ -186,6 +192,9 @@ impl Definition for TypeDefinition {
|
||||
fn get_position(&self) -> ParserPosition {
|
||||
self.position.clone()
|
||||
}
|
||||
fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -205,6 +214,9 @@ impl Definition for EnumDefinition {
|
||||
fn get_position(&self) -> ParserPosition {
|
||||
self.position.clone()
|
||||
}
|
||||
fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -216,7 +228,7 @@ pub struct EnumField {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServiceDefinition {
|
||||
pub name: String,
|
||||
pub depends: HashSet<BaseType>,
|
||||
pub depends: BTreeSet<BaseType>,
|
||||
pub methods: Vec<Method>,
|
||||
pub position: ParserPosition,
|
||||
}
|
||||
@ -225,6 +237,9 @@ impl Definition for ServiceDefinition {
|
||||
fn get_position(&self) -> ParserPosition {
|
||||
self.position.clone()
|
||||
}
|
||||
fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -249,7 +264,7 @@ pub struct MethodOutput {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MethodDecorators {
|
||||
pub description: Option<String>,
|
||||
pub parameter_descriptions: HashMap<String, String>,
|
||||
pub parameter_descriptions: BTreeMap<String, String>,
|
||||
pub return_description: Option<String>,
|
||||
}
|
||||
|
||||
@ -257,13 +272,15 @@ fn build_type(stmt: &TypeStatement) -> Result<TypeDefinition> {
|
||||
let mut typedef = TypeDefinition {
|
||||
position: stmt.position.clone(),
|
||||
name: stmt.name.clone(),
|
||||
depends: HashSet::new(),
|
||||
depends: BTreeSet::new(),
|
||||
fields: Vec::new(),
|
||||
};
|
||||
|
||||
for field in &stmt.fields {
|
||||
let typ = BaseType::from(&field.fieldtype);
|
||||
typedef.depends.insert(typ.clone());
|
||||
if stmt.name != field.fieldtype {
|
||||
typedef.depends.insert(typ.clone());
|
||||
}
|
||||
|
||||
if let Some(maptype) = &field.map {
|
||||
if maptype != "string" && maptype != "int" {
|
||||
@ -320,7 +337,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
let mut servdef = ServiceDefinition {
|
||||
position: stmt.position.clone(),
|
||||
name: stmt.name.clone(),
|
||||
depends: HashSet::new(),
|
||||
depends: BTreeSet::new(),
|
||||
methods: Vec::new(),
|
||||
};
|
||||
|
||||
@ -337,7 +354,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
}),
|
||||
decorators: MethodDecorators {
|
||||
description: None,
|
||||
parameter_descriptions: HashMap::new(),
|
||||
parameter_descriptions: BTreeMap::new(),
|
||||
return_description: None,
|
||||
},
|
||||
};
|
||||
@ -438,7 +455,7 @@ fn build_service(stmt: &ServiceStatement) -> Result<ServiceDefinition> {
|
||||
}
|
||||
|
||||
pub fn build_ir(root: &Vec<RootNode>) -> Result<IR> {
|
||||
let mut options = HashMap::<String, String>::new();
|
||||
let mut options = BTreeMap::<String, String>::new();
|
||||
let mut steps = Vec::new();
|
||||
|
||||
for node in root {
|
||||
@ -464,8 +481,8 @@ pub fn build_ir(root: &Vec<RootNode>) -> Result<IR> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut all_types = HashSet::<String>::new();
|
||||
let mut serv_types = HashSet::<String>::new();
|
||||
let mut all_types = BTreeSet::<String>::new();
|
||||
let mut serv_types = BTreeSet::<String>::new();
|
||||
|
||||
for bi in &BUILT_INS {
|
||||
all_types.insert(bi.to_string());
|
||||
@ -565,3 +582,36 @@ impl Display for IRError {
|
||||
write!(f, "ParserError: {} at {:?}", self.message, self.position)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn btreeset_order_is_consistent() {
|
||||
let mut set1 = BTreeSet::new();
|
||||
let mut set2 = BTreeSet::new();
|
||||
|
||||
let elements = vec![
|
||||
BaseType::Custom("CustomType".to_string()),
|
||||
BaseType::Void,
|
||||
BaseType::Bytes,
|
||||
BaseType::Float,
|
||||
];
|
||||
|
||||
// Insert in normal order
|
||||
for elem in &elements {
|
||||
set1.insert(elem.clone());
|
||||
}
|
||||
|
||||
// Insert in reverse order
|
||||
for elem in elements.iter().rev() {
|
||||
set2.insert(elem.clone());
|
||||
}
|
||||
|
||||
let iter1: Vec<_> = set1.iter().cloned().collect();
|
||||
let iter2: Vec<_> = set2.iter().cloned().collect();
|
||||
|
||||
assert_eq!(iter1, iter2); // Order must be the same
|
||||
}
|
||||
}
|
||||
|
@ -10,31 +10,3 @@ pub use ir::IR;
|
||||
pub use parser::{Parser, RootNode};
|
||||
pub use process::FileProcessor;
|
||||
pub use tokenizer::{tokenize, Token, TokenError, TokenPosition, TokenType};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::targets::{self, rust::RustCompiler};
|
||||
|
||||
#[cfg(test)]
|
||||
#[ctor::ctor]
|
||||
fn init() {
|
||||
env_logger::init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn parse_jrpc() {
|
||||
let mut fp = crate::process::FileProcessor::new();
|
||||
// let ir = fp.start_compile("./test.jrpc").unwrap();
|
||||
let ir = fp.start_compile("http://127.0.0.1:7878/test.jrpc").unwrap();
|
||||
|
||||
println!("{:?}", ir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn generate_rust() {
|
||||
let mut fp = crate::process::FileProcessor::new();
|
||||
let ir = fp.start_compile("./test.jrpc").unwrap();
|
||||
|
||||
targets::compile::<RustCompiler>(ir, "./output/rust").unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -667,8 +667,8 @@ pub struct ParserError {
|
||||
}
|
||||
|
||||
impl ParserError {
|
||||
fn new(msg: &str, token: &Token) -> ParserError {
|
||||
ParserError {
|
||||
fn new(msg: &str, token: &Token) -> Self {
|
||||
Self {
|
||||
message: format!("{}: {}", msg, token.1),
|
||||
token: token.clone(),
|
||||
}
|
||||
|
@ -35,38 +35,44 @@ impl FileProcessor {
|
||||
false
|
||||
}
|
||||
|
||||
fn resolve_path(input: &str, context: Option<&str>) -> String {
|
||||
fn resolve_path(input: &str, context: Option<&str>) -> Result<String> {
|
||||
trace!("FileProcessor::resolve_path({}, {:?})", input, context);
|
||||
let mut input = input.to_string();
|
||||
#[cfg(feature = "http")]
|
||||
if cfg!(feature = "http") && (Self::is_url(Some(&input)) || Self::is_url(context)) {
|
||||
if Self::is_url(Some(&input)) {
|
||||
input.to_string()
|
||||
Ok(input.to_string())
|
||||
} else {
|
||||
let url = Url::parse(context.unwrap()).unwrap();
|
||||
if !input.ends_with(".jrpc") {
|
||||
input = format!("{}.jrpc", input);
|
||||
}
|
||||
url.join(&input).unwrap().to_string()
|
||||
Ok(url.join(&input).unwrap().to_string())
|
||||
}
|
||||
} else {
|
||||
if !input.ends_with(".jrpc") {
|
||||
input = format!("{}.jrpc", input);
|
||||
}
|
||||
if let Some(context) = context {
|
||||
let mut path = PathBuf::from(context);
|
||||
let mut path = PathBuf::from(context).canonicalize()?;
|
||||
path.pop();
|
||||
path = path.join(input);
|
||||
path.to_str().unwrap().to_string()
|
||||
path = path.join(input).canonicalize()?;
|
||||
Ok(path.to_str().unwrap().to_string())
|
||||
} else {
|
||||
input
|
||||
// This will resolve the path!
|
||||
let path = PathBuf::from(input).canonicalize()?;
|
||||
Ok(path.to_str().unwrap().to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_file_url(&mut self, url: &str) -> Result<String> {
|
||||
trace!("FileProcessor::get_file_url({})", url);
|
||||
let resp = reqwest::blocking::get(url)?;
|
||||
let resp = reqwest::blocking::ClientBuilder::new()
|
||||
.danger_accept_invalid_certs(std::env::var("ACCPT_INVALID_CERTS").is_ok())
|
||||
.build()?
|
||||
.get(url)
|
||||
.send()?;
|
||||
let body = resp.text()?;
|
||||
self.file_cache.insert(url.to_string(), body.clone());
|
||||
Ok(body)
|
||||
@ -101,7 +107,7 @@ impl FileProcessor {
|
||||
}
|
||||
|
||||
fn process_file(&mut self, file: &str, root: bool) -> Result<Vec<RootNode>> {
|
||||
let file = Self::resolve_path(file, None);
|
||||
let file = Self::resolve_path(file, None)?;
|
||||
trace!("FileProcessor::process_file({}, {})", file, root);
|
||||
if self.processed_files.contains(&file) {
|
||||
return Ok(vec![]);
|
||||
@ -115,7 +121,7 @@ impl FileProcessor {
|
||||
let mut result = Vec::new();
|
||||
for stmt in &parsed {
|
||||
if let crate::parser::RootNode::Import(stmt) = stmt {
|
||||
let file = Self::resolve_path(&stmt.path, Some(&file));
|
||||
let file = Self::resolve_path(&stmt.path, Some(&file))?;
|
||||
let s = self.process_file(&file, false)?;
|
||||
result.extend(s);
|
||||
} else {
|
||||
|
@ -1,13 +1,47 @@
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt::{Debug, Display},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::{
|
||||
compile::{Compile, CompileContext},
|
||||
ir::Definition,
|
||||
IR,
|
||||
};
|
||||
|
||||
pub mod rust;
|
||||
pub mod typescript;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CompilerError<D: Definition> {
|
||||
pub message: String,
|
||||
pub definition: D,
|
||||
}
|
||||
|
||||
impl<D: Definition> CompilerError<D> {
|
||||
fn new(msg: &str, definition: D) -> Self {
|
||||
Self {
|
||||
message: format!("{}: {}", msg, definition.get_name()),
|
||||
definition,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Definition> Error for CompilerError<D> {}
|
||||
|
||||
impl<D: Definition> Display for CompilerError<D> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"CompilerError: {} at {:?}",
|
||||
self.message,
|
||||
self.definition.get_position()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile<T: Compile>(ir: IR, output: &str) -> Result<()> {
|
||||
let mut ctx = CompileContext::new(output);
|
||||
let mut compiler = T::new(&ir.options)?;
|
||||
@ -15,10 +49,29 @@ pub fn compile<T: Compile>(ir: IR, output: &str) -> Result<()> {
|
||||
|
||||
for step in ir.steps.iter() {
|
||||
match step {
|
||||
crate::ir::Step::Type(definition) => compiler.generate_type(&mut ctx, &definition)?,
|
||||
crate::ir::Step::Enum(definition) => compiler.generate_enum(&mut ctx, &definition)?,
|
||||
crate::ir::Step::Type(definition) => {
|
||||
match compiler.generate_type(&mut ctx, &definition) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
return Err(CompilerError::new(&err.to_string(), definition.clone()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::ir::Step::Enum(definition) => {
|
||||
match compiler.generate_enum(&mut ctx, &definition) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
return Err(CompilerError::new(&err.to_string(), definition.clone()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::ir::Step::Service(definition) => {
|
||||
compiler.generate_service(&mut ctx, &definition)?
|
||||
match compiler.generate_service(&mut ctx, &definition) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
return Err(CompilerError::new(&err.to_string(), definition.clone()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use anyhow::Result;
|
||||
use log::warn;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use crate::compile::{Compile, CompileContext, FileGenerator};
|
||||
use crate::ir::{
|
||||
BaseType, EnumDefinition, ServiceDefinition, Step, Type, TypeDefinition, TypeModifier,
|
||||
};
|
||||
use crate::ir::{BaseType, EnumDefinition, ServiceDefinition, Step, Type, TypeDefinition};
|
||||
use crate::shared::Keywords;
|
||||
use crate::IR;
|
||||
|
||||
@ -48,7 +46,7 @@ impl RustCompiler {
|
||||
fn add_dependencies(
|
||||
&mut self,
|
||||
file: &mut FileGenerator,
|
||||
depends: &HashSet<BaseType>,
|
||||
depends: &BTreeSet<BaseType>,
|
||||
) -> Result<()> {
|
||||
for dep in depends {
|
||||
match dep {
|
||||
@ -148,8 +146,9 @@ impl RustCompiler {
|
||||
|
||||
f.a0("#[async_trait]");
|
||||
f.a0(format!("pub trait {} {{", definition.name));
|
||||
f.a1("type Context: Clone + Sync + Send + 'static;");
|
||||
for method in definition.methods.iter() {
|
||||
let params = method
|
||||
let mut params = method
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
@ -159,8 +158,9 @@ impl RustCompiler {
|
||||
Self::type_to_rust_ext(&arg.typ)
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
.collect::<Vec<String>>();
|
||||
params.push("ctx: Self::Context".to_string());
|
||||
let params = params.join(", ");
|
||||
|
||||
let ret = method
|
||||
.output
|
||||
@ -181,17 +181,20 @@ impl RustCompiler {
|
||||
f.a0("}");
|
||||
|
||||
f.a0("");
|
||||
f.a0(format!("pub struct {}Handler {{", definition.name));
|
||||
f.a0(format!("pub struct {}Handler<Context> {{", definition.name));
|
||||
f.a1(format!(
|
||||
"implementation: Box<dyn {} + Sync + Send + 'static>,",
|
||||
"implementation: Box<dyn {}<Context = Context> + Sync + Send + 'static>,",
|
||||
definition.name
|
||||
));
|
||||
f.a0("}");
|
||||
f.a0("");
|
||||
|
||||
f.a0(format!("impl {}Handler {{", definition.name));
|
||||
f.a0(format!(
|
||||
"impl<Context: Clone + Sync + Send + 'static> {}Handler<Context> {{",
|
||||
definition.name
|
||||
));
|
||||
f.a1(format!(
|
||||
"pub fn new(implementation: Box<dyn {} + Sync + Send + 'static>) -> Arc<Self> {{",
|
||||
"pub fn new(implementation: Box<dyn {}<Context = Context> + Sync + Send + 'static>) -> Arc<Self> {{",
|
||||
definition.name,
|
||||
));
|
||||
f.a2("Arc::from(Self { implementation })");
|
||||
@ -202,9 +205,10 @@ impl RustCompiler {
|
||||
|
||||
f.a0("#[async_trait]");
|
||||
f.a0(format!(
|
||||
"impl JRPCServerService for {}Handler {{",
|
||||
"impl<Context: Clone + Sync + Send + 'static> JRPCServerService for {}Handler<Context> {{",
|
||||
definition.name
|
||||
));
|
||||
f.a1("type Context = Context;");
|
||||
f.a1(format!(
|
||||
"fn get_id(&self) -> String {{ \"{}\".to_owned() }} ",
|
||||
definition.name
|
||||
@ -214,7 +218,7 @@ impl RustCompiler {
|
||||
|
||||
f.a1("#[allow(non_snake_case)]");
|
||||
f.a1(
|
||||
"async fn handle(&self, msg: &JRPCRequest, function: &str) -> Result<(bool, Value)> {",
|
||||
"async fn handle(&self, msg: &JRPCRequest, function: &str, ctx: Self::Context) -> Result<(bool, Value)> {",
|
||||
);
|
||||
f.a2("match function {");
|
||||
|
||||
@ -227,7 +231,7 @@ impl RustCompiler {
|
||||
));
|
||||
if method.inputs.len() < 1 {
|
||||
f.a5(format!(
|
||||
"let res = self.implementation.{}().await?;",
|
||||
"let res = self.implementation.{}(ctx).await?;",
|
||||
method.name
|
||||
));
|
||||
f.a5("Ok((true, serde_json::to_value(res)?))");
|
||||
@ -251,7 +255,7 @@ impl RustCompiler {
|
||||
),
|
||||
);
|
||||
}
|
||||
f.a5(").await?;");
|
||||
f.a5(",ctx).await?;");
|
||||
|
||||
if let Some(_output) = &method.output {
|
||||
f.a5("Ok((true, serde_json::to_value(res)?))");
|
||||
@ -279,7 +283,7 @@ impl RustCompiler {
|
||||
),
|
||||
);
|
||||
}
|
||||
f.a5(").await?;");
|
||||
f.a5(", ctx).await?;");
|
||||
if let Some(_output) = &method.output {
|
||||
f.a5("Ok((true, serde_json::to_value(res)?))");
|
||||
} else {
|
||||
@ -405,7 +409,7 @@ impl RustCompiler {
|
||||
}
|
||||
|
||||
impl Compile for RustCompiler {
|
||||
fn new(options: &HashMap<String, String>) -> anyhow::Result<Self> {
|
||||
fn new(options: &BTreeMap<String, String>) -> anyhow::Result<Self> {
|
||||
let crate_name = if let Some(crate_name) = options.get("rust_crate") {
|
||||
crate_name.to_string()
|
||||
} else {
|
||||
@ -474,7 +478,7 @@ impl Compile for RustCompiler {
|
||||
}
|
||||
|
||||
f.a1(format!(
|
||||
"pub {}: {}",
|
||||
"pub {}: {},",
|
||||
Self::fix_keyword_name(&field.name),
|
||||
Self::type_to_rust_ext(&field.typ)
|
||||
));
|
||||
|
@ -1,78 +1,100 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use anyhow::Result;
|
||||
use log::{info, warn};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use log::info;
|
||||
|
||||
use crate::compile::{Compile, CompileContext, FileGenerator};
|
||||
use crate::ir::{BaseType, EnumDefinition, ServiceDefinition, Step, Type, TypeDefinition};
|
||||
use crate::shared::Keywords;
|
||||
|
||||
use crate::IR;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Flavour {
|
||||
ESM,
|
||||
Node,
|
||||
pub trait Flavour {
|
||||
fn ext() -> &'static str;
|
||||
fn name() -> &'static str;
|
||||
}
|
||||
|
||||
pub struct TypeScriptCompiler {
|
||||
flavour: Flavour,
|
||||
pub struct Node;
|
||||
impl Flavour for Node {
|
||||
fn ext() -> &'static str {
|
||||
""
|
||||
}
|
||||
fn name() -> &'static str {
|
||||
"ts-node"
|
||||
}
|
||||
}
|
||||
|
||||
static TS_KEYWORDS: [&'static str; 52] = [
|
||||
"abstract",
|
||||
"arguments",
|
||||
"await",
|
||||
"boolean",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"debugger",
|
||||
"default",
|
||||
"delete",
|
||||
"do",
|
||||
"else",
|
||||
"enum",
|
||||
"export",
|
||||
"extends",
|
||||
"false",
|
||||
"final",
|
||||
"finally",
|
||||
"for",
|
||||
"function",
|
||||
"goto",
|
||||
"if",
|
||||
"implements",
|
||||
"import",
|
||||
"in",
|
||||
"instanceof",
|
||||
"interface",
|
||||
"let",
|
||||
"new",
|
||||
"null",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"return",
|
||||
"super",
|
||||
"switch",
|
||||
"this",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
"typeof",
|
||||
"var",
|
||||
"void",
|
||||
"while",
|
||||
"with",
|
||||
"yield",
|
||||
"static",
|
||||
];
|
||||
pub struct ESM;
|
||||
impl Flavour for ESM {
|
||||
fn ext() -> &'static str {
|
||||
".js"
|
||||
}
|
||||
|
||||
impl TypeScriptCompiler {
|
||||
fn name() -> &'static str {
|
||||
"ts-esm"
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TypeScriptCompiler<F: Flavour> {
|
||||
// flavour: Flavour,
|
||||
flavour: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
// static TS_KEYWORDS: [&'static str; 52] = [
|
||||
// "abstract",
|
||||
// "arguments",
|
||||
// "await",
|
||||
// "boolean",
|
||||
// "break",
|
||||
// "byte",
|
||||
// "case",
|
||||
// "catch",
|
||||
// "class",
|
||||
// "const",
|
||||
// "continue",
|
||||
// "debugger",
|
||||
// "default",
|
||||
// "delete",
|
||||
// "do",
|
||||
// "else",
|
||||
// "enum",
|
||||
// "export",
|
||||
// "extends",
|
||||
// "false",
|
||||
// "final",
|
||||
// "finally",
|
||||
// "for",
|
||||
// "function",
|
||||
// "goto",
|
||||
// "if",
|
||||
// "implements",
|
||||
// "import",
|
||||
// "in",
|
||||
// "instanceof",
|
||||
// "interface",
|
||||
// "let",
|
||||
// "new",
|
||||
// "null",
|
||||
// "package",
|
||||
// "private",
|
||||
// "protected",
|
||||
// "public",
|
||||
// "return",
|
||||
// "super",
|
||||
// "switch",
|
||||
// "this",
|
||||
// "throw",
|
||||
// "true",
|
||||
// "try",
|
||||
// "typeof",
|
||||
// "var",
|
||||
// "void",
|
||||
// "while",
|
||||
// "with",
|
||||
// "yield",
|
||||
// "static",
|
||||
// ];
|
||||
|
||||
impl<F: Flavour> TypeScriptCompiler<F> {
|
||||
fn type_to_typescript(typ: &BaseType) -> String {
|
||||
match typ {
|
||||
BaseType::String => "string".to_string(),
|
||||
@ -88,9 +110,6 @@ impl TypeScriptCompiler {
|
||||
fn type_to_typescript_ext(typ: &Type) -> String {
|
||||
let mut result = Self::type_to_typescript(&typ.0);
|
||||
let (optional, array, map) = typ.1.get_flags();
|
||||
if optional {
|
||||
result = format!("({} | undefined)", result);
|
||||
}
|
||||
if array {
|
||||
result = format!("({})[]", result);
|
||||
}
|
||||
@ -101,21 +120,21 @@ impl TypeScriptCompiler {
|
||||
result
|
||||
);
|
||||
}
|
||||
if optional {
|
||||
// Optional should be the last modifier
|
||||
result = format!("({} | undefined)", result);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn add_dependencies(
|
||||
&mut self,
|
||||
file: &mut FileGenerator,
|
||||
depends: &HashSet<BaseType>,
|
||||
depends: &BTreeSet<BaseType>,
|
||||
) -> Result<()> {
|
||||
let esm = if self.flavour == Flavour::ESM {
|
||||
".js"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let esm = F::ext();
|
||||
file.a0(format!(
|
||||
"import {{ VerificationError, apply_int, apply_float, apply_string, apply_boolean, apply_void }} from \"./ts_base{esm}\""));
|
||||
"import {{ VerificationError, apply_int, apply_float, apply_string, apply_bool, apply_void, apply_array, apply_required, apply_optional, apply_map }} from \"./ts_base{esm}\""));
|
||||
for dep in depends {
|
||||
match dep {
|
||||
BaseType::Custom(name) => {
|
||||
@ -132,17 +151,83 @@ impl TypeScriptCompiler {
|
||||
}
|
||||
|
||||
fn fix_keyword_name(name: &str) -> String {
|
||||
if TS_KEYWORDS.contains(&name) {
|
||||
format!("{}_", name)
|
||||
} else {
|
||||
name.to_string()
|
||||
// if TS_KEYWORDS.contains(&name) {
|
||||
// format!("{}_", name)
|
||||
// } else {
|
||||
// name.to_string()
|
||||
// }
|
||||
// TODO: Check if this is something that can be implemented. There is the issue of JSON generation...
|
||||
name.to_string()
|
||||
}
|
||||
|
||||
fn get_type_apply(typ: &Type, value: &str) -> String {
|
||||
let apply_field_value = format!("apply_{}", typ.0.to_string());
|
||||
match &typ.1 {
|
||||
crate::ir::TypeModifier::None => format!("{}({})", apply_field_value, value),
|
||||
crate::ir::TypeModifier::Optional => format!("apply_optional({}, {})", value, apply_field_value),
|
||||
crate::ir::TypeModifier::Array => format!("apply_array({}, {})", value, apply_field_value),
|
||||
crate::ir::TypeModifier::OptionalArray => format!("apply_optional({}, data => apply_array(data, {}))", value, apply_field_value),
|
||||
crate::ir::TypeModifier::Map(map) => format!("apply_map({}, apply_{}, {})", value, map.to_string(), apply_field_value),
|
||||
crate::ir::TypeModifier::OptionalMap(map) => format!("apply_optional({}, data => apply_map(data, apply_{}, {}))", value, map.to_string(), apply_field_value),
|
||||
crate::ir::TypeModifier::MapArray(map) => format!("apply_map({}, apply_{}, data => apply_array(data, {}))", value, map.to_string(), apply_field_value),
|
||||
crate::ir::TypeModifier::OptionalMapArray(map) => format!("apply_optional({}, data => apply_map(data, apply_{}, (data) => apply_array(data, {})))", value, map.to_string(), apply_field_value),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_service_lib(ctx: &CompileContext, ir: &IR) -> Result<()> {
|
||||
fn generate_service_lib(&mut self, ctx: &CompileContext, ir: &IR) -> Result<()> {
|
||||
let esm = F::ext();
|
||||
|
||||
let mut f = FileGenerator::new();
|
||||
|
||||
let mut fc = FileGenerator::new();
|
||||
fc.a0(format!("export * from \"./ts_service_client{}\";", esm));
|
||||
fc.a0("");
|
||||
|
||||
let mut fs = FileGenerator::new();
|
||||
fs.a0(format!("export * from \"./ts_service_server{}\";", esm));
|
||||
fs.a0("");
|
||||
|
||||
for step in &ir.steps {
|
||||
match step {
|
||||
Step::Enum(def) => {
|
||||
f.a0(format!(
|
||||
"import {}, {{ apply_{} }} from \"./{}{}\";",
|
||||
def.name, def.name, def.name, esm
|
||||
));
|
||||
f.a0(format!("export {{ {}, apply_{} }};", def.name, def.name));
|
||||
f.a0("");
|
||||
}
|
||||
Step::Type(def) => {
|
||||
f.a0(format!(
|
||||
"import {}, {{ apply_{} }} from \"./{}{}\";",
|
||||
def.name, def.name, def.name, esm
|
||||
));
|
||||
f.a0(format!("export {{ {}, apply_{} }};", def.name, def.name));
|
||||
f.a0("");
|
||||
}
|
||||
Step::Service(def) => {
|
||||
fc.a0(format!(
|
||||
"export {{ {} }} from \"./{}_client{}\"",
|
||||
def.name, def.name, esm
|
||||
));
|
||||
fs.a0(format!(
|
||||
"export {{ {} }} from \"./{}_server{}\"",
|
||||
def.name, def.name, esm
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
f.a0(format!("export * as Client from \"./index_client{}\"", esm));
|
||||
f.a0(format!("export * as Server from \"./index_server{}\"", esm));
|
||||
f.a0(format!(
|
||||
"export {{ Logging }} from \"./ts_service_base{}\"",
|
||||
esm
|
||||
));
|
||||
|
||||
ctx.write_file("index.ts", &f.into_content())?;
|
||||
ctx.write_file("index_client.ts", &fc.into_content())?;
|
||||
ctx.write_file("index_server.ts", &fs.into_content())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -152,11 +237,7 @@ impl TypeScriptCompiler {
|
||||
ctx: &mut CompileContext,
|
||||
definition: &ServiceDefinition,
|
||||
) -> anyhow::Result<()> {
|
||||
let esm = if self.flavour == Flavour::ESM {
|
||||
".js"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let esm = F::ext();
|
||||
|
||||
ctx.write_file("ts_service_server.ts", &format!("
|
||||
import {{ type RequestObject, type ResponseObject, ErrorCodes, Logging }} from \"./ts_service_base{esm}\";
|
||||
@ -190,7 +271,13 @@ import {{ VerificationError }} from \"./ts_base{esm}\";
|
||||
let mut params = func
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|p| format!("{}: {}", p.name, Self::type_to_typescript_ext(&p.typ)))
|
||||
.map(|p| {
|
||||
format!(
|
||||
"{}: {}",
|
||||
Self::fix_keyword_name(&p.name),
|
||||
Self::type_to_typescript_ext(&p.typ)
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
params.push("ctx: T".to_string());
|
||||
let params = params.join(", ");
|
||||
@ -207,61 +294,48 @@ import {{ VerificationError }} from \"./ts_base{esm}\";
|
||||
func.name,
|
||||
Self::type_to_typescript_ext(&output.typ)
|
||||
));
|
||||
let params_str_arr = func
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|e| format!("\"{}\"", e.name))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
f.a2(format!(
|
||||
"let p = this._into_parameters([{}], params)",
|
||||
params_str_arr
|
||||
));
|
||||
|
||||
for (index, input) in func.inputs.iter().enumerate() {
|
||||
f.a2(format!(
|
||||
"if(p[{}] !== null && p[{}] !== undefined) {{",
|
||||
index, index
|
||||
));
|
||||
if input.typ.array {
|
||||
f.a2(format!("for (const elm of p[{}]) {{", index));
|
||||
f.a3(format!("apply_{}(elm);", input.name));
|
||||
f.a2(format!("}}"));
|
||||
} else if let Some(_map) = &input.typ.map {
|
||||
// TODO: Implement map type handling
|
||||
panic!("Map in arguments is not allowed!");
|
||||
} else {
|
||||
f.a3(format!(
|
||||
"apply_{}(p[{}]);",
|
||||
input.typ.base.to_string(),
|
||||
index
|
||||
));
|
||||
}
|
||||
f.a2("}");
|
||||
if !input.typ.optional {
|
||||
f.a2(format!(
|
||||
"else throw new Error(`Missing required parameter ${}`);",
|
||||
input.name
|
||||
));
|
||||
}
|
||||
f.a0("");
|
||||
}
|
||||
|
||||
f.a2("p.push(ctx);");
|
||||
|
||||
let ret_apply = String::new();
|
||||
if output.typ.
|
||||
|
||||
f.a2("//@ts-ignore This will cause a typescript error when strict checking, since p is not a tuple");
|
||||
f.a2(format!(
|
||||
"return this.{}.call(this, ...p).then(res=>{});",
|
||||
func.name, ret_apply
|
||||
));
|
||||
|
||||
f.a1("}");
|
||||
} else {
|
||||
f.a1(format!("public abstract {}({}): void;", func.name, params));
|
||||
f.a1(format!(
|
||||
"_{}(params: any[] | any, ctx: T): void {{",
|
||||
func.name,
|
||||
));
|
||||
}
|
||||
let params_str_arr = func
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|e| format!("\"{}\"", e.name))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
f.a2(format!(
|
||||
"let p = this._into_parameters([{}], params);",
|
||||
params_str_arr
|
||||
));
|
||||
|
||||
for (index, input) in func.inputs.iter().enumerate() {
|
||||
f.a2(format!(
|
||||
"p[{}] = {};",
|
||||
index,
|
||||
Self::get_type_apply(&input.typ, &format!("p[{}]", index))
|
||||
));
|
||||
}
|
||||
|
||||
f.a2("p.push(ctx);");
|
||||
|
||||
let ret_value = if let Some(output) = &func.output {
|
||||
let ret_apply = Self::get_type_apply(&output.typ, "res");
|
||||
format!(".then(res => {})", ret_apply)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
f.a2("//@ts-ignore This will cause a typescript error when strict checking, since p is not a tuple");
|
||||
f.a2(format!(
|
||||
"return this.{}.call(this, ...p){};",
|
||||
func.name, ret_value
|
||||
));
|
||||
|
||||
f.a1("}");
|
||||
|
||||
f.a0("");
|
||||
}
|
||||
@ -279,11 +353,7 @@ import {{ VerificationError }} from \"./ts_base{esm}\";
|
||||
ctx: &mut CompileContext,
|
||||
definition: &ServiceDefinition,
|
||||
) -> anyhow::Result<()> {
|
||||
let esm = if self.flavour == Flavour::ESM {
|
||||
".js"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let esm = F::ext();
|
||||
|
||||
ctx.write_file(
|
||||
"ts_service_base.ts",
|
||||
@ -364,23 +434,20 @@ import {{ VerificationError }} from \"./ts_base{esm}\";
|
||||
}
|
||||
}
|
||||
|
||||
impl Compile for TypeScriptCompiler {
|
||||
fn new(options: &HashMap<String, String>) -> Result<Self> {
|
||||
impl<F: Flavour> Compile for TypeScriptCompiler<F> {
|
||||
fn new(options: &BTreeMap<String, String>) -> Result<Self> {
|
||||
let flavour = options
|
||||
.get("flavour")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "node".to_string());
|
||||
info!("TypeScript target initialized with flavour: {}", flavour);
|
||||
Ok(TypeScriptCompiler {
|
||||
flavour: Flavour::ESM,
|
||||
flavour: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
match self.flavour {
|
||||
Flavour::ESM => "ts-esm".to_string(),
|
||||
Flavour::Node => "ts-node".to_string(),
|
||||
}
|
||||
F::name().to_string()
|
||||
}
|
||||
|
||||
fn start(&mut self, ctx: &mut CompileContext) -> anyhow::Result<()> {
|
||||
@ -405,9 +472,12 @@ impl Compile for TypeScriptCompiler {
|
||||
for field in definition.fields.iter() {
|
||||
let typ = Self::type_to_typescript_ext(&field.typ);
|
||||
|
||||
let opt = if field.typ.is_optional() { "?" } else { "" };
|
||||
|
||||
f.a1(format!(
|
||||
"public {}: {};",
|
||||
"public {}{}: {};",
|
||||
Self::fix_keyword_name(&field.name),
|
||||
opt,
|
||||
typ
|
||||
));
|
||||
}
|
||||
@ -418,8 +488,12 @@ impl Compile for TypeScriptCompiler {
|
||||
));
|
||||
f.a2("if(init) {");
|
||||
for field in definition.fields.iter() {
|
||||
f.a3(format!("if(init.{})", field.name));
|
||||
f.a4(format!("this.{} = init[\"{}\"]", field.name, field.name));
|
||||
f.a3(format!("if(init.{})", Self::fix_keyword_name(&field.name)));
|
||||
f.a4(format!(
|
||||
"this.{} = init[\"{}\"]",
|
||||
Self::fix_keyword_name(&field.name),
|
||||
Self::fix_keyword_name(&field.name)
|
||||
));
|
||||
}
|
||||
f.a2("}");
|
||||
f.a1("}");
|
||||
@ -443,68 +517,12 @@ impl Compile for TypeScriptCompiler {
|
||||
f.a1(format!("let res = new {}() as any;", definition.name));
|
||||
|
||||
for field in definition.fields.iter() {
|
||||
if field.typ.is_optional() {
|
||||
f.a1(format!(
|
||||
"if (data.{} !== null && data.{} !== undefined ) {{",
|
||||
field.name, field.name
|
||||
));
|
||||
} else {
|
||||
f.a1(format!(
|
||||
"if (data.{} === null || data.{} === undefined ) throw new VerificationError(\"{}\", \"{}\", data.{});",
|
||||
field.name, field.name,
|
||||
definition.name,
|
||||
field.name,
|
||||
field.name
|
||||
));
|
||||
f.a1("else {");
|
||||
}
|
||||
|
||||
if field.typ.is_map() {
|
||||
f.a2(format!(
|
||||
"if (typeof data.{} != \"object\") throw new VerificationError(\"map\", \"{}\", data.{}); ",
|
||||
field.name,
|
||||
definition.name,
|
||||
field.name
|
||||
));
|
||||
f.a2(format!("res.{} = {{}}", field.name));
|
||||
f.a2(format!(
|
||||
"Object.entries(data.{}).forEach(([key, val]) => res.{}[key] = apply_{}(val));",
|
||||
field.name,
|
||||
field.name,
|
||||
Self::type_to_typescript(&field.typ.base),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
if field.typ.is_array() {
|
||||
f.a2(format!(
|
||||
"if (!Array.isArray(data.{})) throw new VerificationError(\"array\", \"{}\", data.{});",
|
||||
field.name,
|
||||
definition.name,
|
||||
field.name
|
||||
));
|
||||
f.a2(format!(
|
||||
"res.{} = data.{}.map(elm => apply_{}(elm));",
|
||||
field.name,
|
||||
field.name,
|
||||
Self::type_to_typescript(&field.typ.base),
|
||||
));
|
||||
}
|
||||
|
||||
if field.typ.array {
|
||||
|
||||
} else if let Some(_map) = &field.typ.map {
|
||||
|
||||
|
||||
} else {
|
||||
f.a2(format!(
|
||||
"res.{} = apply_{}(data.{})",
|
||||
field.name,
|
||||
Self::type_to_typescript(&field.typ.base),
|
||||
field.name
|
||||
));
|
||||
}
|
||||
f.a1("}");
|
||||
let value_name = format!("data.{}", Self::fix_keyword_name(&field.name));
|
||||
f.a1(format!(
|
||||
"res.{} = {};",
|
||||
Self::fix_keyword_name(&field.name),
|
||||
Self::get_type_apply(&field.typ, &value_name)
|
||||
));
|
||||
}
|
||||
f.a1("return res;");
|
||||
|
||||
@ -522,7 +540,7 @@ impl Compile for TypeScriptCompiler {
|
||||
) -> anyhow::Result<()> {
|
||||
let mut f = FileGenerator::new();
|
||||
|
||||
self.add_dependencies(&mut f, &HashSet::new())?;
|
||||
self.add_dependencies(&mut f, &BTreeSet::new())?;
|
||||
|
||||
f.a0(format!("enum {} {{", definition.name));
|
||||
for value in &definition.values {
|
||||
@ -560,7 +578,7 @@ impl Compile for TypeScriptCompiler {
|
||||
}
|
||||
|
||||
fn finalize(&mut self, ctx: &mut CompileContext, ir: &IR) -> anyhow::Result<()> {
|
||||
Self::generate_service_lib(ctx, ir)?;
|
||||
self.generate_service_lib(ctx, ir)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
2
libjrpc/templates/CSharp/.gitignore
vendored
Normal file
2
libjrpc/templates/CSharp/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
bin/
|
||||
obj/
|
@ -6,10 +6,10 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
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"
|
||||
tokio = { version = "1.22.0", features = ["full"] }
|
||||
log = "0.4.17"
|
||||
async-trait = "0.1.59"
|
||||
int-enum = { version = "0.5", features = ["serde", "convert"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
nanoid = "0.4"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
log = "0.4"
|
||||
async-trait = "0.1"
|
||||
|
@ -105,21 +105,27 @@ impl JRPCClient {
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait JRPCServerService: Send + Sync + 'static {
|
||||
pub trait JRPCServerService: Send + Sync {
|
||||
type Context;
|
||||
fn get_id(&self) -> String;
|
||||
async fn handle(&self, request: &JRPCRequest, function: &str) -> Result<(bool, Value)>;
|
||||
async fn handle(
|
||||
&self,
|
||||
request: &JRPCRequest,
|
||||
function: &str,
|
||||
ctx: Self::Context,
|
||||
) -> Result<(bool, Value)>;
|
||||
}
|
||||
|
||||
pub type JRPCServiceHandle = Arc<dyn JRPCServerService>;
|
||||
pub type JRPCServiceHandle<Context> = Arc<dyn JRPCServerService<Context = Context>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct JRPCSession {
|
||||
server: JRPCServer,
|
||||
pub struct JRPCSession<Context> {
|
||||
server: JRPCServer<Context>,
|
||||
message_sender: Sender<JRPCResult>,
|
||||
}
|
||||
|
||||
impl JRPCSession {
|
||||
pub fn new(server: JRPCServer, sender: Sender<JRPCResult>) -> JRPCSession {
|
||||
impl<Context: Clone + Send + Sync + 'static> JRPCSession<Context> {
|
||||
pub fn new(server: JRPCServer<Context>, sender: Sender<JRPCResult>) -> Self {
|
||||
JRPCSession {
|
||||
server,
|
||||
message_sender: sender,
|
||||
@ -148,7 +154,7 @@ impl JRPCSession {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_request(&self, request: JRPCRequest) -> () {
|
||||
pub fn handle_request(&self, request: JRPCRequest, ctx: Context) -> () {
|
||||
let session = self.clone();
|
||||
tokio::task::spawn(async move {
|
||||
info!("Received request: {}", request.method);
|
||||
@ -163,7 +169,7 @@ impl JRPCSession {
|
||||
|
||||
let service = session.server.services.get(service);
|
||||
if let Some(service) = service {
|
||||
let result = service.handle(&request, function).await;
|
||||
let result = service.handle(&request, function, ctx).await;
|
||||
match result {
|
||||
Ok((is_send, result)) => {
|
||||
if is_send && request.id.is_some() {
|
||||
@ -204,23 +210,23 @@ impl JRPCSession {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct JRPCServer {
|
||||
services: HashMap<String, JRPCServiceHandle>,
|
||||
pub struct JRPCServer<Context> {
|
||||
services: HashMap<String, JRPCServiceHandle<Context>>,
|
||||
}
|
||||
|
||||
impl JRPCServer {
|
||||
pub fn new() -> JRPCServer {
|
||||
impl<Context: Clone + Send + Sync + 'static> JRPCServer<Context> {
|
||||
pub fn new() -> Self {
|
||||
JRPCServer {
|
||||
services: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_service(&mut self, service: JRPCServiceHandle) -> () {
|
||||
pub fn add_service(&mut self, service: JRPCServiceHandle<Context>) -> () {
|
||||
let id = service.get_id();
|
||||
self.services.insert(id, service);
|
||||
}
|
||||
|
||||
pub fn get_session(&self, sender: Sender<JRPCResult>) -> JRPCSession {
|
||||
pub fn get_session(&self, sender: Sender<JRPCResult>) -> JRPCSession<Context> {
|
||||
JRPCSession::new(self.clone(), sender)
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,87 @@
|
||||
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;
|
||||
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(form_verficiation_error_message(type, field));
|
||||
}
|
||||
constructor(
|
||||
public readonly type?: string,
|
||||
public readonly field?: string,
|
||||
public readonly value?: any,
|
||||
) {
|
||||
super(form_verficiation_error_message(type, field));
|
||||
}
|
||||
}
|
||||
|
||||
export function apply_int(data: any) {
|
||||
data = Math.floor(Number(data));
|
||||
if (Number.isNaN(data)) throw new VerificationError("int", undefined, data);
|
||||
return data;
|
||||
data = Math.floor(Number(data));
|
||||
if (Number.isNaN(data)) throw new VerificationError("int", undefined, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
export function apply_float(data: any) {
|
||||
data = Number(data);
|
||||
if (Number.isNaN(data))
|
||||
throw new VerificationError("float", undefined, data);
|
||||
return data;
|
||||
data = Number(data);
|
||||
if (Number.isNaN(data)) throw new VerificationError("float", undefined, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
export function apply_string(data: any) {
|
||||
return String(data);
|
||||
return String(data);
|
||||
}
|
||||
|
||||
export function apply_boolean(data: any) {
|
||||
return Boolean(data);
|
||||
export function apply_bool(data: any) {
|
||||
return Boolean(data);
|
||||
}
|
||||
|
||||
export function apply_void(data: any) { }
|
||||
export function apply_map(
|
||||
data: any,
|
||||
apply_key: (data: any) => any,
|
||||
apply_value: (data: any) => any,
|
||||
) {
|
||||
if (typeof data !== "object")
|
||||
throw new VerificationError("map", undefined, data);
|
||||
|
||||
let res = {};
|
||||
for (const key in data) {
|
||||
let key_ = apply_key(key);
|
||||
let value_ = apply_value(data[key]);
|
||||
res[key_] = value_;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function apply_array(data: any, apply_value: (data: any) => any) {
|
||||
if (!Array.isArray(data))
|
||||
throw new VerificationError("array", undefined, data);
|
||||
return data.map((item) => apply_value(item));
|
||||
}
|
||||
|
||||
export function apply_required(
|
||||
data: any,
|
||||
apply_value: (data: any) => any,
|
||||
): any {
|
||||
if (typeof data === "undefined" || data === null) {
|
||||
throw new VerificationError("required", undefined, data);
|
||||
}
|
||||
return apply_value(data);
|
||||
}
|
||||
|
||||
export function apply_optional(
|
||||
data: any,
|
||||
apply_value: (data: any) => any,
|
||||
): any {
|
||||
if (typeof data === "undefined" || data === null) {
|
||||
return data;
|
||||
} else {
|
||||
return apply_value(data);
|
||||
}
|
||||
}
|
||||
|
||||
export function apply_void(data: any) {}
|
||||
|
23
src/main.rs
23
src/main.rs
@ -1,7 +1,10 @@
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use libjrpc::{
|
||||
targets::{rust::RustCompiler, typescript::TypeScriptCompiler},
|
||||
targets::{
|
||||
rust::RustCompiler,
|
||||
typescript::{Node, TypeScriptCompiler},
|
||||
},
|
||||
FileProcessor,
|
||||
};
|
||||
|
||||
@ -29,6 +32,9 @@ enum Commands {
|
||||
}
|
||||
|
||||
pub fn main() -> Result<()> {
|
||||
use simple_logger::SimpleLogger;
|
||||
SimpleLogger::new().init()?;
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
if cli.verbose {
|
||||
@ -55,17 +61,28 @@ pub fn main() -> Result<()> {
|
||||
|
||||
match output_target {
|
||||
"rust" => libjrpc::targets::compile::<RustCompiler>(ir, output_dir)?,
|
||||
"ts-node" => libjrpc::targets::compile::<TypeScriptCompiler>(ir, output_dir)?,
|
||||
"ts-node" => {
|
||||
libjrpc::targets::compile::<TypeScriptCompiler<Node>>(ir, output_dir)?
|
||||
}
|
||||
"ts-esm" => {
|
||||
libjrpc::targets::compile::<TypeScriptCompiler<Node>>(ir, output_dir)?
|
||||
}
|
||||
_ => {
|
||||
println!("Unsupported target: {}", output_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(_def) = definition {
|
||||
panic!("Definition output is not yet implemented!");
|
||||
}
|
||||
|
||||
//TODO: Implement definition output!
|
||||
}
|
||||
Commands::Targets => {
|
||||
panic!("Not yet implemented!")
|
||||
println!("rust");
|
||||
println!("ts-node");
|
||||
println!("ts-esm");
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user