added RPC macro

This commit is contained in:
Djeeberjr 2023-07-10 22:56:07 +02:00
parent 10a061c41b
commit 5fa6c3ecbf
4 changed files with 127 additions and 12 deletions

View File

@ -1,5 +1,6 @@
package bin;
import kernel.log.Log;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
@ -11,6 +12,13 @@ class HelloWorld implements Process {
public function run(handle:ProcessHandle) {
handle.write("Hello World!");
var c = new HelloWorldServiceRPC(0);
c.getNumber().handle((res)->{
Log.debug("Got number: " + res);
});
handle.close();
}
}

View File

@ -1,26 +1,25 @@
package bin;
import kernel.Timer;
import macros.rpc.RPC;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
using tink.CoreApi;
@:build(macros.rpc.RPC.buildRPC())
class HelloWorldService implements Process {
private var timer:Timer;
private var handle:ProcessHandle;
public function new() {}
public function run(handle:ProcessHandle) {
handle.write("Hello World! Started\n");
this.startTimer(handle);
handle.addDeferFunc(()->{
timer.cancle();
});
this.handle = handle;
RPC.generateRPCPackageHandle();
}
public function startTimer(handle: ProcessHandle) {
this.timer = new Timer(5, function() {
handle.write("Hello World!\n");
this.startTimer(handle);
});
@rpc
public function getNumber():Int{
return 42;
}
}

79
src/macros/rpc/RPC.hx Normal file
View File

@ -0,0 +1,79 @@
package macros.rpc;
import haxe.macro.Context;
import haxe.macro.Expr;
using Lambda;
class RPC {
macro static public function buildRPC(): Array<Field> {
var fields = Context.getBuildFields();
var className = Context.getLocalClass().get().name + "RPC";
var c = macro class $className extends macros.rpc.RPCBase {
public function new(id: kernel.net.Package.NetworkID) {
super(id,$v{className});
}
}
for (field in fields){
if (field.meta == null) continue;
if (field.meta.exists((i) -> i.name == "rpc") == false) continue;
switch (field.kind){
case FFun(f):
c.fields.push({
name: field.name,
pos: field.pos,
kind: FFun({
args: f.args,
expr: macro {
return cast this._performRequest($v{field.name},[]);
},
ret: TPath({name: "Promise", params: [TPType(f.ret)], pack: ["tink","core"]}),
}),
access: [APublic],
doc: null,
meta: [],
});
default:
Context.error("Only functions can be used for rpc", field.pos);
}
}
haxe.macro.Context.defineType(c);
return fields;
}
macro static public function generateRPCPackageHandle() {
var proto = Context.getLocalClass().get().name + "RPC";
var exprs: Array<Expr> = [];
var fields = Context.getLocalClass().get().fields.get();
for (field in fields){
if (field.meta == null) continue;
if (!field.meta.has("rpc")) continue;
switch (field.kind){
case FMethod(k):
var funName = field.name;
exprs.push(macro {
if (pack.data.func == $v{funName}){
pack.respond(this.$funName());
}
});
default:
Context.error("Only functions can be used for rpc", field.pos);
}
}
return macro {
kernel.net.Net.instance.registerProto($v{proto},(pack)->{
$a{exprs}
});
};
}
}

29
src/macros/rpc/RPCBase.hx Normal file
View File

@ -0,0 +1,29 @@
package macros.rpc;
import kernel.net.Net;
import kernel.net.Package.NetworkID;
using tink.CoreApi;
abstract class RPCBase {
public final id:NetworkID;
private final _proto:String;
public function new(id: NetworkID, proto: String) {
this.id = id;
this._proto = proto;
}
private function _performRequest(func: String, args: Array<Dynamic>):Promise<Dynamic> {
return Net.instance.sendAndAwait(id, this._proto, {
func: func,
// args: args
}).map((res) -> {
switch (res){
case Success(pack):
return pack.data;
case Failure(_):
return res;
}
});
}
}