diff --git a/message.nim b/message.nim new file mode 100644 index 0000000..7d87f1d --- /dev/null +++ b/message.nim @@ -0,0 +1,47 @@ +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: 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)