summary refs log tree commit diff stats
path: root/tests/manyloc/keineschweine/lib/estreams.nim
blob: bd0a2c31a563ad10bfd5cc04b8a84a08950404e9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import endians

proc swapEndian16*(outp, inp: pointer) = 
  ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
  ## contain at least 2 bytes.
  var i = cast[cstring](inp)
  var o = cast[cstring](outp)
  o[0] = i[1]
  o[1] = i[0]
when cpuEndian == bigEndian:
  proc bigEndian16(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 2)
else:
  proc bigEndian16*(outp, inp: pointer) {.inline.} = swapEndian16(outp, inp)

import enet

type
  PBuffer* = ref object
    data*: string
    pos: int

proc free(b: PBuffer) =
  GCunref b.data
proc newBuffer*(len: int): PBuffer =
  new result, free
  result.data = newString(len)
proc newBuffer*(pkt: PPacket): PBuffer =
  new result, free
  result.data = newString(pkt.dataLength)
  copyMem(addr result.data[0], pkt.data, pkt.dataLength)
proc toPacket*(buffer: PBuffer; flags: TPacketFlag): PPacket =
  buffer.data.setLen buffer.pos
  result = createPacket(cstring(buffer.data), buffer.pos, flags)

proc isDirty*(buffer: PBuffer): bool {.inline.} =
  result = (buffer.pos != 0)
proc atEnd*(buffer: PBuffer): bool {.inline.} =
  result = (buffer.pos == buffer.data.len)
proc reset*(buffer: PBuffer) {.inline.} =
  buffer.pos = 0

proc flush*(buf: PBuffer) =
  buf.pos = 0
  buf.data.setLen(0)
proc send*(peer: PPeer; channel: cuchar; buf: PBuffer; flags: TPacketFlag): cint {.discardable.} =
  result = send(peer, channel, buf.toPacket(flags))

proc read*[T: int16|uint16](buffer: PBuffer; outp: var T) =
  bigEndian16(addr outp, addr buffer.data[buffer.pos])
  inc buffer.pos, 2
proc read*[T: float32|int32|uint32](buffer: PBuffer; outp: var T) =
  bigEndian32(addr outp, addr buffer.data[buffer.pos])
  inc buffer.pos, 4
proc read*[T: float64|int64|uint64](buffer: PBuffer; outp: var T) =
  bigEndian64(addr outp, addr buffer.data[buffer.pos])
  inc buffer.pos, 8
proc read*[T: int8|uint8|byte|bool|char](buffer: PBuffer; outp: var T) =
  copyMem(addr outp, addr buffer.data[buffer.pos], 1)
  inc buffer.pos, 1

proc writeBE*[T: int16|uint16](buffer: PBuffer; val: var T) =
  setLen buffer.data, buffer.pos + 2
  bigEndian16(addr buffer.data[buffer.pos], addr val)
  inc buffer.pos, 2
proc writeBE*[T: int32|uint32|float32](buffer: PBuffer; val: var T) =
  setLen buffer.data, buffer.pos + 4
  bigEndian32(addr buffer.data[buffer.pos], addr val)
  inc buffer.pos, 4
proc writeBE*[T: int64|uint64|float64](buffer: PBuffer; val: var T) =
  setLen buffer.data, buffer.pos + 8
  bigEndian64(addr buffer.data[buffer.pos], addr val)
  inc buffer.pos, 8
proc writeBE*[T: char|int8|uint8|byte|bool](buffer: PBuffer; val: var T) =
  setLen buffer.data, buffer.pos + 1
  copyMem(addr buffer.data[buffer.pos], addr val, 1)
  inc buffer.pos, 1


proc write*(buffer: PBuffer; val: var string) =
  var length = len(val).uint16
  writeBE buffer, length
  setLen buffer.data, buffer.pos + length.int
  copyMem(addr buffer.data[buffer.pos], addr val[0], length.int)
  inc buffer.pos, length.int
proc write*[T: TNumber|bool|char|byte](buffer: PBuffer; val: T) =
  var v: T
  shallowCopy v, val
  writeBE buffer, v

proc readInt8*(buffer: PBuffer): int8 =
  read buffer, result
proc readInt16*(buffer: PBuffer): int16 =
  read buffer, result
proc readInt32*(buffer: PBuffer): int32 =
  read buffer, result
proc readInt64*(buffer: PBuffer): int64 =
  read buffer, result
proc readFloat32*(buffer: PBuffer): float32 =
  read buffer, result
proc readFloat64*(buffer: PBuffer): float64 =
  read buffer, result
proc readStr*(buffer: PBuffer): string =
  let len = readInt16(buffer).int
  result = ""
  if len > 0:
    result.setLen len
    copyMem(addr result[0], addr buffer.data[buffer.pos], len)
    inc buffer.pos, len
proc readChar*(buffer: PBuffer): char {.inline.} = return readInt8(buffer).char
proc readBool*(buffer: PBuffer): bool {.inline.} = return readInt8(buffer).bool


when isMainModule:
  var b = newBuffer(100)
  var str = "hello there"
  b.write str
  echo(repr(b))
  b.pos = 0
  echo(repr(b.readStr()))
  
  b.flush()
  echo "flushed"
  b.writeC([1,2,3])
  echo(repr(b))