Skip to content

Commit

Permalink
bindings for hxbit and msgpack-haxe libs for alternative serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
maitag committed Jun 28, 2018
1 parent 92c6f75 commit c060fea
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 23 deletions.
120 changes: 107 additions & 13 deletions Source/peote/net/Remote.hx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,29 @@ class RemoteImpl
{

#if macro
public static function getPackFromImports(name:String, imports:Array<ImportExpr>):Array<String>
{
var pack = new Array<String>();

for (imp in imports) {
if (imp.path[imp.path.length - 1].name == name)
for (i in 0 ... (imp.path.length - 1) )
pack.push(imp.path[i].name);
}
return pack;
}

public static function build()
{
try { Context.resolvePath("org/msgpack/MsgPack.hx"); isMsgPack = true; } catch (e:Dynamic) {}

var remoteNames = new Array<String>();
var remoteParams = new Array<Array<TypePath>>();
var hasNoNew:Bool = true;

var classname = Context.getLocalClass().get().name;
var classpackage = Context.getLocalClass().get().pack;

var fields = Context.getBuildFields();
for (f in fields)
{
Expand Down Expand Up @@ -53,7 +69,9 @@ class RemoteImpl
case TPath(param):
switch (param.name) {
case "Void":
default: remParams.push(param); // add param type
default:
if (param.pack.length == 0) param.pack = getPackFromImports(param.name, Context.getLocalImports());
remParams.push(param); // add param type
}
default:
}
Expand All @@ -76,7 +94,9 @@ class RemoteImpl
case TPath(param):
switch (param.name) {
case "Void":
default: remParams.push(param); // add param type
default:
if (param.pack.length == 0) param.pack = getPackFromImports(param.name, Context.getLocalImports());
remParams.push(param); // add param type
}
default:
}
Expand Down Expand Up @@ -135,14 +155,15 @@ class RemoteImpl
// ------------------------------------- generates new classs for remote-calling ---------------------
// -------------------------------------------------------------------------------------------------
var classnameRemote = classname+"RemoteServer";
Context.defineType(generateRemoteCaller(classnameRemote, true, remoteNames, remoteParams));
// add function to return an instanze of that class
var getRemoteServer:Function = {
//Context.defineType(generateRemoteCaller(classnameRemote, true, remoteNames, remoteParams));
Context.defineModule(classpackage.concat([classnameRemote]).join('.'),[generateRemoteCaller(classnameRemote, true, remoteNames, remoteParams)],Context.getLocalImports());

var getRemoteServer:Function = { // add function to return an instanze of that class
args:[ {name:"server", type:macro:peote.net.PeoteServer, opt:false, value:null},
{name:"user", type:macro:Int, opt:false, value:null},
{name:"remoteId", type:macro:Int, opt:false, value:null}
],
expr: Context.parse( 'return new $classnameRemote(server, user, remoteId)', Context.currentPos()) ,
expr: Context.parse( 'return new $classnameRemote(server, user, remoteId)', Context.currentPos()),
ret: TPath({ name:classnameRemote, pack:[], params:[] }) // ret = return type
}
fields.push({
Expand All @@ -153,9 +174,10 @@ class RemoteImpl
});

classnameRemote = classname+"RemoteClient";
Context.defineType(generateRemoteCaller(classnameRemote, false, remoteNames, remoteParams));
// add function to return an instanze of that class
var getRemoteClient:Function = {
//Context.defineType(generateRemoteCaller(classnameRemote, false, remoteNames, remoteParams));
Context.defineModule(classpackage.concat([classnameRemote]).join('.'),[generateRemoteCaller(classnameRemote, false, remoteNames, remoteParams)],Context.getLocalImports());

var getRemoteClient:Function = { // add function to return an instanze of that class
args:[ {name:"client", type:macro:peote.net.PeoteClient, opt:false, value:null},
{name:"remoteId", type:macro:Int, opt:false, value:null}
],
Expand Down Expand Up @@ -207,12 +229,13 @@ class RemoteImpl
name:'p$j',
type:TPath({
name: remoteParams[i][j].name,
pack: switch(remoteParams[i][j].name) {
/*pack: switch(remoteParams[i][j].name) {
case "Byte"|"UInt16"|"Int16"|"Int32"|"Double": ["peote", "io"];
case "Bytes": ["haxe", "io"];
case "Vector"|"IntMap"|"StringMap": ["haxe", "ds"];
default:remoteParams[i][j].pack;
},
},*/
pack: remoteParams[i][j].pack,
params:remoteParams[i][j].params
}), opt:false
}],
Expand Down Expand Up @@ -249,6 +272,7 @@ class RemoteImpl
case TPType(TPath(t)): subtypes.push(t);
default:
}
var moduleName = ((tp.pack.length != 0) ? tp.pack.join(".") + "." : "") + tp.name;

return ((depth == 0) ? 'var ' : '') + varname + "=" + switch (tp.name) {
case "Array": 'new Array'+getFullType(tp)+'();' +
Expand Down Expand Up @@ -285,7 +309,22 @@ class RemoteImpl
case "Double": 'input.readDouble();';
case "String": 'input.readString();';
case "Bytes": 'input.read();';
default: 'haxe.Unserializer.run(input.readString());';

case "Dynamic":
if (isMsgPack) {
trace('Remote param "$moduleName" is using MsgPack Serialization.');
'org.msgpack.MsgPack.decode(input.read());';
} else {
trace('Remote param "$moduleName" is using haxe.Serializer.');
'haxe.Unserializer.run(input.readString());';
}

case "Enum": 'haxe.Unserializer.run(input.readString());'; // TODO

default:
if (isHxbit(tp, false)) '(new hxbit.Serializer()).unserialize(input.read(),$moduleName);';
else if (isTypedef(tp, false)) 'org.msgpack.MsgPack.decode(input.read());';
else 'haxe.Unserializer.run(input.readString());';
}
}

Expand Down Expand Up @@ -324,10 +363,65 @@ class RemoteImpl
case "Double": 'output.writeDouble($varname);';
case "String": 'output.writeString($varname);';
case "Bytes": 'output.write($varname);';
default: 'output.writeString(haxe.Serializer.run($varname));';

case "Dynamic":
if (isMsgPack) 'output.write(org.msgpack.MsgPack.encode($varname));';
else 'output.writeString(haxe.Serializer.run($varname));';


case "Enum": 'output.writeString(haxe.Serializer.run($varname));'; // TODO

default:
if (isHxbit(tp)) 'output.write((new hxbit.Serializer()).serialize($varname));';
else if (isTypedef(tp)) 'output.write(org.msgpack.MsgPack.encode($varname));';
else 'output.writeString(haxe.Serializer.run($varname));';
}
}

public static function isHxbit(t:TypePath, silent:Bool = true):Bool
{
#if hxbit
var path = t.name + ".hx";
if (t.pack.length != 0) path = t.pack.join("/") +"/" + path;
//trace(path);
try {
var p = Context.resolvePath(path);
var s:String = sys.io.File.getContent(p);
var r = new EReg('class\\s+'+t.name+getFullType(t)+'\\s+[^{]*?implements\\s+hxbit.Serializable[\\s{]', "");
if (r.match(s)) {
if (!silent) trace("Remote param '"+t.pack.join(".") + ((t.pack.length != 0) ? "." : "") + t.name + "' is using hxbit Serialization.");
return true;
}
}
catch(e:Dynamic) {}
#end
return false;
}

public static var isMsgPack:Bool = false;
public static function isTypedef(t:TypePath, silent:Bool = true):Bool
{
if (isMsgPack)
{
var path = t.name + ".hx";
if (t.pack.length != 0) path = t.pack.join("/") +"/" + path;
//trace(path);
try {
var p = Context.resolvePath(path);
var s:String = sys.io.File.getContent(p);
var r = new EReg('typedef\\s+'+t.name+getFullType(t)+'\\s*=\\s*{', "");
if (r.match(s)) {
if (!silent) trace("Remote param '"+t.pack.join(".") + ((t.pack.length != 0) ? "." : "") + t.name + "' is using MsgPack Serialization.");
return true;
}
}
catch(e:Dynamic) {}
}

if (!silent) trace("Remote param '"+t.pack.join(".") + ((t.pack.length != 0) ? "." : "") + t.name + "' is using haxe.Serializer.");
return false;
}

#end

}
4 changes: 2 additions & 2 deletions haxelib.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"license": "MIT",
"tags": ["peote", "socket", "tcp", "networking", "rpc"],
"description": "Library to write TCP-Networking Applications",
"version": "0.6.8",
"version": "0.6.9",
"classPath": "Source/",
"releasenote": "variable chunksizes and errorhandling",
"releasenote": "hxbit and msgpack-haxe bindings",
"contributors": ["maitag"],
"dependencies": {
"peote-socket": ""
Expand Down
9 changes: 8 additions & 1 deletion samples/rpc/project.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<project>

<meta title="testing peote-net framework" package="peote.test" version="0.4.0" company="Sylvio Sell - maitag" />
<meta title="testing peote-net framework" package="peote.test" version="0.5.0" company="Sylvio Sell - maitag" />

<app main="MainOpenfl" path="build/openfl" file="peote-rpc-local" />
<app if="server" main="MainOpenfl" path="build/openfl" file="peote-rpc-server" />
Expand All @@ -14,13 +14,20 @@

<haxelib name="openfl" />

<!-- for alternative serialization of custom RPC parametertypes -->
<!--<haxelib name="hxbit" />-->

<!-- for alternative serialization of Dynamic rpc-parameter-types -->
<!--<haxelib name="msgpack-haxe" />-->

<haxelib name="peote-socket" />
<haxelib name="peote-net" />

<!--<haxedef name="dom" />-->

<!--<haxedef name="debugPeoteJoint" />-->
<!--<haxedef name="debugPeoteNet" />-->
<haxedef name="debugPeoteIO" />

<!--<haxeflag name="-dce" value="full" />-->
<!--<haxedef name="no-traces" />-->
Expand Down
40 changes: 33 additions & 7 deletions samples/rpc/src/MainOpenfl.hx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ import haxe.ds.IntMap;
import haxe.ds.StringMap;
import haxe.ds.Vector;
import haxe.io.Bytes;
import peote.net.Remote;

import openfl.display.Sprite;

import peote.bridge.PeoteSocketBridge;
import peote.net.PeoteServer;
import peote.net.PeoteClient;
import peote.bridge.PeoteSocketBridge;
import peote.net.Remote;

import peote.io.Byte;
import peote.io.UInt16;
import peote.io.Int16;
import peote.io.Int32;
import peote.io.Double;

import remoteParams.User;
import remoteParams.Message;

import ui.OutputText;

class MainOpenfl extends Sprite
Expand Down Expand Up @@ -84,7 +86,17 @@ class MainOpenfl extends Sprite
serverFunctions.maps = function(m:Map< Int, Map<String, Array<Int>> >) {
out.log('serverobject -> maps(');
for (k in m.keys()) out.log(""+m.get(k));
};
};
serverFunctions.hxbit = function(u:User) {
out.log('serverobject -> hxbit(${u.name}, ${u.age})');
};
serverFunctions.msgpack = function(o:Dynamic) {
out.log('serverobject -> msgpack($o)');
};
serverFunctions.msgpackTyped = function(m:Message) {
out.log('serverobject -> msgpackTyped($m)');
};

server.setRemote(userNr, serverFunctions); // --> Client's onRemote on will be called with 0

},
Expand Down Expand Up @@ -146,10 +158,10 @@ class MainOpenfl extends Sprite
serverFunctions.message("hello from client", true);
serverFunctions.numbers(255, 0xFFFF, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF, 1.2345678901234, 1.2345678901234 );

var v = new Vector<Array<Int>>(2);
var v = new Vector<Array<Int>>(3);
v[0] = [1, 2];
v[1] = [3, 4, 5];
//v[2] = null; // null will result on remote in an empty Array
v[2] = null; // null will result on remote in an empty Array
serverFunctions.complex(Bytes.ofString("dada"), v);

var list = new List<Int>(); for (i in 0...5) list.add(i);
Expand All @@ -159,10 +171,17 @@ class MainOpenfl extends Sprite
var m = [
1 => ["a1" => [10,11], "b1" => [12,13]],
2 => ["a2" => [20, 21], "b2" => [22, 23]],
//7 => null // null will result on remote in an empty Map
7 => null // null will result on remote in an empty Map
];
serverFunctions.maps(m);

var u = new User("Alice", 42, "test");
serverFunctions.hxbit(u);

var m:Message = {name:"Klaus", age:23};
serverFunctions.msgpackTyped(m);

serverFunctions.msgpack({name:"Bob", age:48, friends:["Mary","Johan"]});
},
onDisconnect: function(client:PeoteClient, reason:Int)
{
Expand All @@ -189,6 +208,13 @@ class ServerFunctions implements Remote {
@:remote public var lists:List<Int> -> Void;
//@:remote public var maps:IntMap< haxe.ds.StringMap< Array<Int>> > -> Void;
@:remote public var maps:Map<Int, Map< String, Array<Int>> > -> Void;

// enable hxbit lib in project.xml to use it's serialization here ( https://lib.haxe.org/p/hxbit/ )
@:remote public var hxbit: User -> Void;

// enable msgpack lib in project.xml to use it's serialization here( https://lib.haxe.org/p/msgpack-haxe/ )
@:remote public var msgpackTyped: Message -> Void;
@:remote public var msgpack: Dynamic -> Void;
}

class FirstClientFunctions implements Remote {
Expand Down
8 changes: 8 additions & 0 deletions samples/rpc/src/remoteParams/Message.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package remoteParams;

typedef Message =
{
name: String,
age: Int,
?other: String,
}
21 changes: 21 additions & 0 deletions samples/rpc/src/remoteParams/User.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package remoteParams;

#if hxbit
class User implements hxbit.Serializable {
@:s public var name: String; // serialized
@:s public var age: Int; // serialized
public var other:String; // NOT serialized
#else
class User {
@:s public var name: String; // serialized
@:s public var age: Int; // serialized
public var other:String; // serialized
#end

public function new(n:String, a:Int, o:String) {
name = n;
age = a;
other = o;
}
}

0 comments on commit c060fea

Please sign in to comment.