diff --git a/src/bin/Res.hx b/src/bin/Res.hx new file mode 100644 index 0000000..b453490 --- /dev/null +++ b/src/bin/Res.hx @@ -0,0 +1,56 @@ +package bin; + +import lib.exporter.Export; +import lib.exporter.IExportable; +import kernel.peripherals.Peripherals.Peripheral; +import kernel.service.ServiceManager; +import lib.exporter.Import; +import lib.CLIAppBase; + +class Res extends CLIAppBase { + public function new() { + registerAsyncSubcommand("get", (args)->{ + var url = args[0]; + + return Import.get(url).map((res)->{ + switch (res){ + case Success(data): + handle.writeLine(Std.string(data)); + case Failure(err): + handle.writeLine("Error: "); + handle.writeLine(Std.string(err)); + } + return true; + }); + },""); + + registerAsyncSubcommand("register",(args)->{ + var srv: Null = ServiceManager.instance.get("resmgr"); + + var addr = args[0]; + var name = args[1]; + + if (srv == null) { + handle.writeLine("Error: resmgr not found"); + return false; + } + + var perf: IExportable = Peripheral.instance.getRedstone(addr); + + if (perf == null) { + handle.writeLine("Error: peripheral not found"); + return false; + } + + return srv.register(name,new Export(perf)).map((res)->{ + if (res) { + handle.writeLine("Success"); + } else { + handle.writeLine("Error"); + } + + return res; + }); + }," "); + } +} \ No newline at end of file diff --git a/src/bin/ResManager.hx b/src/bin/ResManager.hx new file mode 100644 index 0000000..4ceb2bb --- /dev/null +++ b/src/bin/ResManager.hx @@ -0,0 +1,67 @@ +package bin; + +import lib.exporter.Request; +import kernel.ps.ProcessHandle; +import lib.RessourceNames; +import lib.exporter.Export; +import kernel.ps.Process; +import kernel.log.Log; +import kernel.net.Package; +import kernel.net.Net; +import kernel.net.Package.GenericPackage; + +using tink.CoreApi; + +class ResManager implements Process { + private var handle:ProcessHandle; + private final exports:Map = []; + + public function new() {} + + public function run(handle:ProcessHandle) { + this.handle = handle; + Net.instance.registerProto("res",handlePackage); + } + + public function register(id: String, export: Export): Future{ + if (exports.exists(id)){ + handle.writeLine("Ressource already exists: " + id); + return Future.sync(false); + } + + return registerName(id).map((success)->{ + if (success){ + exports.set(id,export); + } + return success; + }); + } + + private function handlePackage(pack: GenericPackage){ + Log.debug("Handling ressource request" + pack); + var requestPack: Package = cast pack; + var id = requestPack.data.id; + + if (!exports.exists(id)){ + requestPack.respond(lib.exporter.Response.NotFound); + return; + } + + var export = exports.get(id); + var response = export.handleRequest(requestPack.data); + + requestPack.respond(response); + } + + private function registerName(id: String){ + return RessourceNames.register(id, Net.instance.networkID).map((res)->{ + switch (res) { + case Success(data): + return data; + case Failure(err): + Log.error("Failed to register ressource: " + id + " " + err); + return false; + } + }); + } +} diff --git a/src/kernel/DCEHack.hx b/src/kernel/DCEHack.hx index bd9c7c1..19fbd8c 100644 --- a/src/kernel/DCEHack.hx +++ b/src/kernel/DCEHack.hx @@ -20,6 +20,8 @@ class DCEHack { new bin.srsc.CLI(), new bin.Perf(), new bin.KSettings(), + new bin.ResManager(), + new bin.Res(), ]; } } diff --git a/src/kernel/binstore/BinStore.hx b/src/kernel/binstore/BinStore.hx index 463af4a..6b68496 100644 --- a/src/kernel/binstore/BinStore.hx +++ b/src/kernel/binstore/BinStore.hx @@ -1,5 +1,7 @@ package kernel.binstore; +import bin.Res; +import bin.ResManager; import bin.KSettings; import bin.Perf; import bin.srsc.CLI; @@ -36,6 +38,8 @@ class BinStore { {c: CLI, name: "SRSC CLI", aliases: ["srsc-cli"]}, {c: Perf, name: "Perf", aliases: ["perf"]}, {c: KSettings, name: "KSettings", aliases: ["ksettings","ks"]}, + {c: ResManager, name: "ResManager", aliases: ["resmanager","resmgr"]}, + {c: Res, name: "Res", aliases: ["res"]} ]; @:allow(kernel.Init) diff --git a/src/lib/exporter/Export.hx b/src/lib/exporter/Export.hx new file mode 100644 index 0000000..81d3da6 --- /dev/null +++ b/src/lib/exporter/Export.hx @@ -0,0 +1,35 @@ +package lib.exporter; + +import kernel.log.Log; + +using tink.CoreApi; + +class Export { + private final exportConfig: ExportConfig; + + public function new(exportConfig: IExportable) { + this.exportConfig = exportConfig.export(); + } + + public function handleRequest(req: Request): Response { + switch (req.operation){ + case Get: + return handleGet(req); + case Set(value): + //TODO: implement + return NotFound; + } + } + + private function handleGet(request: Request): Response { + if (!this.exportConfig.getDelegates.exists(request.field)){ + Log.warn('Requested get field ${request.field} does not exist in ??'); + return NotFound; + } + + var delegate = this.exportConfig.getDelegates.get(request.field); + var value = delegate(request.index); + + return Get(value); + } +} diff --git a/src/lib/exporter/ExportConfig.hx b/src/lib/exporter/ExportConfig.hx new file mode 100644 index 0000000..7380deb --- /dev/null +++ b/src/lib/exporter/ExportConfig.hx @@ -0,0 +1,9 @@ +package lib.exporter; + +import lib.exporter.Response; + +typedef ExportConfig = { + type: String, + getDelegates: Map->ValueType>, + // setDelegates: Map)->ValueType>, +} diff --git a/src/lib/exporter/IExportable.hx b/src/lib/exporter/IExportable.hx new file mode 100644 index 0000000..50cb261 --- /dev/null +++ b/src/lib/exporter/IExportable.hx @@ -0,0 +1,5 @@ +package lib.exporter; + +interface IExportable { + public function export(): ExportConfig; +} diff --git a/src/lib/exporter/Import.hx b/src/lib/exporter/Import.hx new file mode 100644 index 0000000..4fb6bf1 --- /dev/null +++ b/src/lib/exporter/Import.hx @@ -0,0 +1,28 @@ +package lib.exporter; + +import kernel.net.Net; +import kernel.net.Package.NetworkID; + +using tink.CoreApi; + +class Import { + public static function get(ressourceLocator: String): Promise { + var request = Request.fromString(ressourceLocator); + + return RessourceNames.get(request.id).next((response)->{ + return performRequest(response,request); + }); + } + + private static function performRequest(netID: NetworkID, request: Request): Promise { + return Net.instance.sendAndAwait(netID,"res",request).map((response)->{ + switch (response){ + case Success(data): + return Success(cast (data.data, Response)); + case Failure(error): + return Failure(error); + } + }); + + } +} diff --git a/src/lib/exporter/Operation.hx b/src/lib/exporter/Operation.hx new file mode 100644 index 0000000..556a9a9 --- /dev/null +++ b/src/lib/exporter/Operation.hx @@ -0,0 +1,6 @@ +package lib.exporter; + +enum Operation { + Get; + Set(value: Dynamic); +} diff --git a/src/lib/exporter/Request.hx b/src/lib/exporter/Request.hx new file mode 100644 index 0000000..85cb587 --- /dev/null +++ b/src/lib/exporter/Request.hx @@ -0,0 +1,51 @@ +package lib.exporter; + +import lua.TableTools; +import lua.NativeStringTools; + +class Request { + public final id:String; + public final field:String; + public final index: Null; + public final operation: Operation; + + public function new(id:String, field:String, index:Null, operation:Operation) { + this.id = id; + this.field = field; + this.index = index; + this.operation = operation; + } + + + /** + Example: + "myfield[2]@myid" + "myfield@myid" + **/ + public static function fromString(locator: String): Request { + if (StringTools.contains(locator,"[")){ + var f = TableTools.pack(NativeStringTools.gmatch(locator, "(%a+)%[([%d]+)%]@(%a+)")()); + + var field = f[1]; + var index = Std.parseInt(f[2]); + var id = f[3]; + + return new Request(id, field, index, Get); + }else{ + var f = TableTools.pack(NativeStringTools.gmatch(locator, "(%a+)@(%a+)")()); + + var field = f[1]; + var id = f[2]; + + return new Request(id, field, null, Get); + } + } + + public function toString() { + if (index == null){ + return field + "@" + id; + }else{ + return field + "[" + index + "]@" + id; + } + } +} diff --git a/src/lib/exporter/Response.hx b/src/lib/exporter/Response.hx new file mode 100644 index 0000000..a4d1385 --- /dev/null +++ b/src/lib/exporter/Response.hx @@ -0,0 +1,14 @@ +package lib.exporter; + +enum Response { + NotFound; + Set; + NotSet; + Get(value: ValueType); +} + +enum ValueType { + Number(value: Int); + String(value: String); + Bool(value: Bool); +}