summary refs log tree commit diff stats
path: root/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim')
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim287
1 files changed, 287 insertions, 0 deletions
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
new file mode 100644
index 000000000..d91f1cb35
--- /dev/null
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
@@ -0,0 +1,287 @@
+import macros, macro_dsl, estreams
+from strutils import format
+
+template newLenName() =
+  let lenName {.inject.} = ^("len" & $lenNames)
+  inc(lenNames)
+
+template defPacketImports*() {.dirty.} =
+  import macros, macro_dsl, estreams
+  from strutils import format
+
+macro defPacket*(typeNameN: untyped, typeFields: untyped): untyped =
+  result = newNimNode(nnkStmtList)
+  let
+    typeName = quoted2ident(typeNameN)
+    packetID = ^"p"
+    streamID = ^"s"
+  var
+    constructorParams = newNimNode(nnkFormalParams).und(typeName)
+    constructor = newNimNode(nnkProcDef).und(
+      postfix(^("new" & $typeName.ident), "*"),
+      emptyNode(),
+      emptyNode(),
+      constructorParams,
+      emptyNode(),
+      emptyNode())
+    pack = newNimNode(nnkProcDef).und(
+      postfix(^"pack", "*"),
+      emptyNode(),
+      emptyNode(),
+      newNimNode(nnkFormalParams).und(
+        emptyNode(),   # : void
+        newNimNode(nnkIdentDefs).und(
+          streamID,    # s: PBuffer
+          ^"PBuffer",
+          newNimNode(nnkNilLit)),
+        newNimNode(nnkIdentDefs).und(
+          packetID,    # p: var typeName
+          newNimNode(nnkVarTy).und(typeName),
+          emptyNode())),
+      emptyNode(),
+      emptyNode())
+    read = newNimNode(nnkProcDef).und(
+      newIdentNode("read" & $typeName.ident).postfix("*"),
+      emptyNode(),
+      emptyNode(),
+      newNimNode(nnkFormalParams).und(
+        typeName,   #result type
+        newNimNode(nnkIdentDefs).und(
+          streamID, # s: PBuffer = nil
+          ^"PBuffer",
+          newNimNode(nnkNilLit))),
+      emptyNode(),
+      emptyNode())
+    constructorBody = newNimNode(nnkStmtList)
+    packBody = newNimNode(nnkStmtList)
+    readBody = newNimNode(nnkStmtList)
+    lenNames = 0
+  for i in 0.. typeFields.len - 1:
+    let
+      name = typeFields[i][0]
+      dotName = packetID.dot(name)
+      resName = newIdentNode("result").dot(name)
+    case typeFields[i][1].kind
+    of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type]
+      case $typeFields[i][1][0].ident
+      of "seq":
+        ## let lenX = readInt16(s)
+        newLenName()
+        let
+          item = ^"item"  ## item name in our iterators
+          seqType = typeFields[i][1][1] ## type of seq
+          readName = newIdentNode("read" & $seqType.ident)
+        readBody.add(newNimNode(nnkLetSection).und(
+          newNimNode(nnkIdentDefs).und(
+            lenName,
+            newNimNode(nnkEmpty),
+            newCall("readInt16", streamID))))
+        readBody.add(      ## result.name = @[]
+          resName := ("@".prefix(newNimNode(nnkBracket))),
+          newNimNode(nnkForStmt).und(  ## for item in 1..len:
+            item,
+            infix(1.lit, "..", lenName),
+            newNimNode(nnkStmtList).und(
+              newCall(  ## add(result.name, unpack[seqType](stream))
+                "add", resName, newNimNode(nnkCall).und(readName, streamID)
+        ) ) ) )
+        packbody.add(
+          newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und(
+            lenName,  ## var lenName = int16(len(p.name))
+            newIdentNode("int16"),
+            newCall("int16", newCall("len", dotName)))),
+          newCall("writeBE", streamID, lenName),
+          newNimNode(nnkForStmt).und(  ## for item in 0..length - 1: pack(p.name[item], stream)
+            item,
+            infix(0.lit, "..", infix(lenName, "-", 1.lit)),
+            newNimNode(nnkStmtList).und(
+              newCall("echo", item, ": ".lit),
+              newCall("pack", streamID, dotName[item]))))
+        #set the default value to @[] (new sequence)
+        typeFields[i][2] = "@".prefix(newNimNode(nnkBracket))
+      else:
+        error("Unknown type: " & treeRepr(typeFields[i]))
+    of nnkIdent: ##normal type
+      case $typeFields[i][1].ident
+      of "string": # length encoded string
+        packBody.add(newCall("write", streamID, dotName))
+        readBody.add(resName := newCall("readStr", streamID))
+      of "int8", "int16", "int32", "float32", "float64", "char", "bool":
+        packBody.add(newCall(
+          "writeBE", streamID, dotName))
+        readBody.add(resName := newCall("read" & $typeFields[i][1].ident, streamID))
+      else:  ## hopefully the type you specified was another defpacket() type
+        packBody.add(newCall("pack", streamID, dotName))
+        readBody.add(resName := newCall("read" & $typeFields[i][1].ident, streamID))
+    else:
+      error("I don't know what to do with: " & treerepr(typeFields[i]))
+
+  var
+    toStringFunc = newNimNode(nnkProcDef).und(
+      newNimNode(nnkPostfix).und(
+        ^"*",
+        newNimNode(nnkAccQuoted).und(^"$")),
+      emptyNode(),
+      emptyNode(),
+      newNimNode(nnkFormalParams).und(
+        ^"string",
+        newNimNode(nnkIdentDefs).und(
+          packetID, # p: typeName
+          typeName,
+          emptyNode())),
+      emptyNode(),
+      emptyNode(),
+      newNimNode(nnkStmtList).und(# [6]
+        newNimNode(nnkAsgn).und(
+          ^"result",                  ## result =
+          newNimNode(nnkCall).und(# [6][0][1]
+            ^"format",  ## format
+            emptyNode()))))  ## "[TypeName   $1   $2]"
+    formatStr = "[" & $typeName.ident
+
+  const emptyFields = {nnkEmpty, nnkNilLit}
+  var objFields = newNimNode(nnkRecList)
+  for i in 0 ..< len(typeFields):
+    let fname = typeFields[i][0]
+    constructorParams.add(newNimNode(nnkIdentDefs).und(
+      fname,
+      typeFields[i][1],
+      typeFields[i][2]))
+    constructorBody.add((^"result").dot(fname) := fname)
+    #export the name
+    typeFields[i][0] = fname.postfix("*")
+    if not(typeFields[i][2].kind in emptyFields):
+      ## empty the type default for the type def
+      typeFields[i][2] = newNimNode(nnkEmpty)
+    objFields.add(typeFields[i])
+    toStringFunc[6][0][1].add(
+      prefix("$", packetID.dot(fname)))
+    formatStr.add "   $"
+    formatStr.add($(i + 1))
+
+  formatStr.add ']'
+  toStringFunc[6][0][1][1] = formatStr.lit()
+
+  result.add(
+    newNimNode(nnkTypeSection).und(
+      newNimNode(nnkTypeDef).und(
+        typeName.postfix("*"),
+        newNimNode(nnkEmpty),
+        newNimNode(nnkObjectTy).und(
+          newNimNode(nnkEmpty), #not sure what this is
+          newNimNode(nnkEmpty), #parent: OfInherit(Ident(!"SomeObj"))
+          objFields))))
+  result.add(constructor.und(constructorBody))
+  result.add(pack.und(packBody))
+  result.add(read.und(readBody))
+  result.add(toStringFunc)
+  when defined(GenPacketShowOutput):
+    echo(repr(result))
+
+proc newProc*(name: NimNode; params: varargs[NimNode]; resultType: NimNode): NimNode {.compileTime.} =
+  result = newNimNode(nnkProcDef).und(
+    name,
+    emptyNode(),
+    emptyNode(),
+    newNimNode(nnkFormalParams).und(resultType),
+    emptyNode(),
+    emptyNode(),
+    newNimNode(nnkStmtList))
+  result[3].add(params)
+
+proc body*(procNode: NimNode): NimNode {.compileTime.} =
+  assert procNode.kind == nnkProcDef and procNode[6].kind == nnkStmtList
+  result = procNode[6]
+
+proc iddefs*(a, b: string; c: NimNode): NimNode {.compileTime.} =
+  result = newNimNode(nnkIdentDefs).und(^a, ^b, c)
+proc iddefs*(a: string; b: NimNode): NimNode {.compileTime.} =
+  result = newNimNode(nnkIdentDefs).und(^a, b, emptyNode())
+proc varTy*(a: NimNode): NimNode {.compileTime.} =
+  result = newNimNode(nnkVarTy).und(a)
+
+macro forwardPacket*(typeName: untyped, underlyingType: untyped): untyped =
+  var
+    packetID = ^"p"
+    streamID = ^"s"
+  result = newNimNode(nnkStmtList).und(
+    newProc(
+      (^("read" & $typeName.ident)).postfix("*"),
+      [ iddefs("s", "PBuffer", newNimNode(nnkNilLit)) ],
+      typeName),
+    newProc(
+      (^"pack").postfix("*"),
+      [ iddefs("s", "PBuffer", newNimNode(nnkNilLit)),
+        iddefs("p", varTy(typeName)) ],
+      emptyNode()))
+  var
+    readBody = result[0][6]
+    packBody = result[1][6]
+    resName = ^"result"
+
+  case underlyingType.kind
+  of nnkBracketExpr:
+    case $underlyingType[0].ident
+    of "array":
+      for i in underlyingType[1][1].intval.int .. underlyingType[1][2].intval.int:
+        readBody.add(
+          newCall("read", ^"s", resName[lit(i)]))
+        packBody.add(
+          newCall("writeBE", ^"s", packetID[lit(i)]))
+    else:
+      echo "Unknown type: ", repr(underlyingtype)
+  else:
+    echo "unknown type:", repr(underlyingtype)
+  echo(repr(result))
+
+template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} =
+  proc `read typeName`*(buffer: PBuffer): typeName =
+    #discard readData(s, addr result, sizeof(result))
+    var res: underlyingType
+    buffer.read(res)
+    result = typeName(res)
+  proc `pack`*(buffer: PBuffer; ord: var typeName) =
+    #writeData(s, addr p, sizeof(p))
+    buffer.write(underlyingType(ord))
+
+when false:
+  type
+    SomeEnum = enum
+      A = 0'i8,
+      B, C
+  forwardPacket(SomeEnum, int8)
+
+
+  defPacket(Foo, tuple[x: array[0..4, int8]])
+  var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8])
+  var s2 = newStringStream("")
+  f.pack(s2)
+  assert s2.data == "\4\3\2\1\0"
+
+  var s = newStringStream()
+  s.flushImpl = proc(s: PStream) =
+    var z = PStringStream(s)
+    z.setPosition(0)
+    z.data.setLen(0)
+
+
+  s.setPosition(0)
+  s.data.setLen(0)
+  var o = B
+  o.pack(s)
+  o = A
+  o.pack(s)
+  o = C
+  o.pack(s)
+  assert s.data == "\1\0\2"
+  s.flush
+
+  defPacket(Y, tuple[z: int8])
+  proc `$`(z: Y): string = result = "Y(" & $z.z & ")"
+  defPacket(TestPkt, tuple[x: seq[Y]])
+  var test = newTestPkt()
+  test.x.add([newY(5), newY(4), newY(3), newY(2), newY(1)])
+  for itm in test.x:
+    echo(itm)
+  test.pack(s)
+  echo(repr(s.data))