estreams.nim 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import endians
  2. proc swapEndian16*(outp, inp: pointer) =
  3. ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
  4. ## contain at least 2 bytes.
  5. var i = cast[cstring](inp)
  6. var o = cast[cstring](outp)
  7. o[0] = i[1]
  8. o[1] = i[0]
  9. import enet
  10. type
  11. PBuffer* = ref object
  12. data*: string
  13. pos: int
  14. proc free(b: PBuffer) =
  15. GCunref b.data
  16. proc newBuffer*(len: int): PBuffer =
  17. new result, free
  18. result.data = newString(len)
  19. proc newBuffer*(pkt: PPacket): PBuffer =
  20. new result, free
  21. result.data = newString(pkt.dataLength)
  22. copyMem(addr result.data[0], pkt.data, pkt.dataLength)
  23. proc toPacket*(buffer: PBuffer; flags: TPacketFlag): PPacket =
  24. buffer.data.setLen buffer.pos
  25. result = createPacket(cstring(buffer.data), cast[csize_t](buffer.pos), flags)
  26. proc isDirty*(buffer: PBuffer): bool {.inline.} =
  27. result = (buffer.pos != 0)
  28. proc atEnd*(buffer: PBuffer): bool {.inline.} =
  29. result = (buffer.pos == buffer.data.len)
  30. proc reset*(buffer: PBuffer) {.inline.} =
  31. buffer.pos = 0
  32. proc flush*(buf: PBuffer) =
  33. buf.pos = 0
  34. buf.data.setLen(0)
  35. proc send*(peer: PPeer; channel: cuchar; buf: PBuffer; flags: TPacketFlag): cint {.discardable.} =
  36. result = send(peer, channel, buf.toPacket(flags))
  37. proc read*[T: int16|uint16](buffer: PBuffer; outp: var T) =
  38. bigEndian16(addr outp, addr buffer.data[buffer.pos])
  39. inc buffer.pos, 2
  40. proc read*[T: float32|int32|uint32](buffer: PBuffer; outp: var T) =
  41. bigEndian32(addr outp, addr buffer.data[buffer.pos])
  42. inc buffer.pos, 4
  43. proc read*[T: float64|int64|uint64](buffer: PBuffer; outp: var T) =
  44. bigEndian64(addr outp, addr buffer.data[buffer.pos])
  45. inc buffer.pos, 8
  46. proc read*[T: int8|uint8|byte|bool|char](buffer: PBuffer; outp: var T) =
  47. copyMem(addr outp, addr buffer.data[buffer.pos], 1)
  48. inc buffer.pos, 1
  49. proc writeBE*[T: int16|uint16](buffer: PBuffer; val: var T) =
  50. setLen buffer.data, buffer.pos + 2
  51. bigEndian16(addr buffer.data[buffer.pos], addr val)
  52. inc buffer.pos, 2
  53. proc writeBE*[T: int32|uint32|float32](buffer: PBuffer; val: var T) =
  54. setLen buffer.data, buffer.pos + 4
  55. bigEndian32(addr buffer.data[buffer.pos], addr val)
  56. inc buffer.pos, 4
  57. proc writeBE*[T: int64|uint64|float64](buffer: PBuffer; val: var T) =
  58. setLen buffer.data, buffer.pos + 8
  59. bigEndian64(addr buffer.data[buffer.pos], addr val)
  60. inc buffer.pos, 8
  61. proc writeBE*[T: char|int8|uint8|byte|bool](buffer: PBuffer; val: var T) =
  62. setLen buffer.data, buffer.pos + 1
  63. copyMem(addr buffer.data[buffer.pos], addr val, 1)
  64. inc buffer.pos, 1
  65. proc write*(buffer: PBuffer; val: var string) =
  66. var length = len(val).uint16
  67. writeBE buffer, length
  68. setLen buffer.data, buffer.pos + length.int
  69. copyMem(addr buffer.data[buffer.pos], addr val[0], length.int)
  70. inc buffer.pos, length.int
  71. proc write*[T: SomeNumber|bool|char|byte](buffer: PBuffer; val: sink T) =
  72. var v: T
  73. v = val
  74. writeBE buffer, v
  75. proc readInt8*(buffer: PBuffer): int8 =
  76. read buffer, result
  77. proc readInt16*(buffer: PBuffer): int16 =
  78. read buffer, result
  79. proc readInt32*(buffer: PBuffer): int32 =
  80. read buffer, result
  81. proc readInt64*(buffer: PBuffer): int64 =
  82. read buffer, result
  83. proc readFloat32*(buffer: PBuffer): float32 =
  84. read buffer, result
  85. proc readFloat64*(buffer: PBuffer): float64 =
  86. read buffer, result
  87. proc readStr*(buffer: PBuffer): string =
  88. let len = readInt16(buffer).int
  89. result = ""
  90. if len > 0:
  91. result.setLen len
  92. copyMem(addr result[0], addr buffer.data[buffer.pos], len)
  93. inc buffer.pos, len
  94. proc readChar*(buffer: PBuffer): char {.inline.} = return readInt8(buffer).char
  95. proc readBool*(buffer: PBuffer): bool {.inline.} = return readInt8(buffer).bool
  96. when false:
  97. var b = newBuffer(100)
  98. var str = "hello there"
  99. b.write str
  100. echo(repr(b))
  101. b.pos = 0
  102. echo(repr(b.readStr()))
  103. b.flush()
  104. echo "flushed"
  105. b.writeC([1,2,3])
  106. echo(repr(b))