punchd/message.nim

56 lines
1.7 KiB
Nim

import strutils
from net import IpAddress, parseIpAddress, Port, `$`
proc parseField(input: string, output: var string) =
output = input
proc parseField[T: SomeUnsignedInt](input: string, output: var T) =
let parsed = parseUInt(input)
if parsed > T.high:
raise newException(ValueError, "Unsigned integer out of range")
output = parsed.T
proc parseField(input: string, output: var IpAddress) =
output = parseIpAddress(input)
proc parseField(input: string, output: var Port) =
var portNumber: uint16
parseField(input, portNumber)
output = Port(portNumber)
proc parseField[S, T](input: string, output: var array[S, T]) =
let parts = input.split(",", S.high)
if parts.len != S.high + 1:
raise newException(ValueError, "Array has wrong length")
for i in 0 .. S.high:
parseField(parts[i], output[i])
proc parseField[T](input: string, output: var seq[T]) =
let parts = input.split(",")
if parts.len < 1:
raise newException(ValueError, "Sequence is empty")
output = newSeq[T](parts.len)
for i in 0 .. parts.len - 1:
parseField(parts[i], output[i])
proc parseField[T: tuple | object](input: string, output: var T) =
var fieldCount = 0
for _ in output.fields:
fieldCount = fieldCount + 1
let args = input.parseArgs(fieldCount)
var i = 0
for value in output.fields:
parseField(args[i], value)
i.inc
proc parseArgs*(input: string, count: int, optionalCount = 0): seq[string] =
assert(optionalCount <= count)
result = input.split("|", count - 1)
if result.len < count:
if result.len < count - optionalCount:
raise newException(ValueError, "invalid message")
result.add(repeat("", count - result.len))
proc parseMessage*[T: tuple | object](input: string): T =
parseField(input, result)