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)