Finish implementation of new Rust Tokio Target

This commit is contained in:
Fabian Stamm
2022-12-17 17:11:28 +01:00
parent 890b903f04
commit 46aff0c61b
21 changed files with 1598 additions and 685 deletions

View File

@ -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}<C: ${CTX_TYPE}> {`);
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<C: ${CTX_TYPE}> {`);
a(1, `implementation: Box<dyn ${definition.name}<C> + Sync + Send>,`);
a(0, `pub struct ${definition.name}Handler {`);
a(1, `implementation: Box<dyn ${definition.name} + Sync + Send + 'static>,`);
a(0, `}`);
a(0, ``);
a(0, `impl<C: ${CTX_TYPE}> ${definition.name}Handler<C> {`);
a(0, `impl ${definition.name}Handler {`);
a(
1,
`pub fn new(implementation: Box<dyn ${definition.name}<C> + Sync + Send>) -> Box<Self> {`
`pub fn new(implementation: Box<dyn ${definition.name} + Sync + Send + 'static>) -> Arc<Self> {`
);
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<C: ${CTX_TYPE}> JRPCServiceHandler<C> for ${definition.name}Handler<C> {`
`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());