diff --git a/parse.nim b/parse.nim index 03efa6d..a17e921 100644 --- a/parse.nim +++ b/parse.nim @@ -29,6 +29,10 @@ type PsycSyntaxError = object of Exception + InvalidModifierName = object of PsycSyntaxError + InvalidModifierValue = object of PsycSyntaxError + InvalidContentLength = object of PsycSyntaxError + Validator = proc(c: char): bool proc validateTrue(c: char): bool = true @@ -48,7 +52,7 @@ proc getUntil(input: string, delimiters: openArray[char], packet: var PsycPacket packet.cursor = i break if not validate(input[i]): - raise newException(PsycSyntaxError, "invalid character in " & $packet.state) + raise newException(InvalidModifierName, "invalid character in " & $packet.state) proc parseKeyword(input: string, packet: var PsycPacket): tuple[complete: bool, value: string] = @@ -58,7 +62,8 @@ proc parseKeyword(input: string, if result.complete: packet.cursor.inc() if result.value.len() == 0 or result.value[0] != '_': - raise newException(PsycSyntaxError, $packet.state & " does not start with '_'") + raise newException(InvalidModifierName, + $packet.state & " does not start with '_'") proc parseModifierValueLength(input: string, packet: var PsycPacket): tuple[complete: bool, @@ -68,13 +73,13 @@ proc parseModifierValueLength(input: string, return (false, -1) packet.cursor.inc() if value.len() == 0: - raise newException(PsycSyntaxError, "missing length after " & $packet.state) + raise newException(InvalidModifierValue, "missing length of binary-arg") try: result = (true, value.parseInt()) except ValueError: - raise newException(PsycSyntaxError, "invalid length after " & $packet.state) + raise newException(InvalidModifierValue, "invalid length of binary-arg") if result.value < 0: - raise newException(PsycSyntaxError, "invalid length after " & $packet.state) + raise newException(InvalidModifierValue, "invalid length of binary-arg") proc parseModifierName(input: string, packet: var PsycPacket): tuple[complete: bool, @@ -84,15 +89,12 @@ proc parseModifierName(input: string, if packet.cursor == input.high(): result.complete = false return - if input[packet.cursor] == '\n': - packet.cursor.inc() - return (true, '\0', nil) result.op = input[packet.cursor] packet.cursor.inc() if result.op == '?': if input[packet.cursor] != '\n': - raise newException(PsycSyntaxError, - $packet.state & " has invalid operator '?'") + raise newException(InvalidModifierName, + "state sync modifier '?' must not have a name") result.complete = true return (result.complete, result.name) = parseKeyword(input, packet) @@ -101,10 +103,13 @@ proc parseModifierName(input: string, return # the following separator must either be ' ' (binary-arg) or '\t' (simple-arg) if input[packet.cursor - 1] == ' ': + if packet.state != ParseState.EntityModifierName: + raise newException(InvalidModifierValue, + "binary-arg not allowed in routing modifier") (result.complete, packet.remainingPartLen) = parseModifierValueLength(input, packet) elif input[packet.cursor - 1] != '\t': - raise newException(PsycSyntaxError, $packet.state & " has invalid separator") + raise newException(InvalidModifierValue, "modifier has invalid separator") proc parseMethod(input: string, packet: var PsycPacket): tuple[complete: bool, value: string] = @@ -134,8 +139,8 @@ proc parseModifierValue(input: string, if result.complete: result.value = input[packet.cursor .. packet.cursor + packet.remainingPartLen - 1] if input[packet.cursor + packet.remainingPartLen] != '\n': - raise newException(PsycSyntaxError, - $packet.state & " is missing '\n' after binary-arg") + raise newException(InvalidModifierValue, + $packet.state & " is missing '\\n' after binary-arg") packet.cursor += result.value.len() + 1 packet.remainingPartLen = -1 else: @@ -156,7 +161,7 @@ proc parseContentLength(input: string, try: result.value = value.parseInt() except ValueError: - raise newException(PsycSyntaxError, + raise newException(InvalidContentLength, $packet.state & " is not a positive integer") proc parseData(input: string, @@ -457,25 +462,32 @@ suite "parser tests": test "invalid character in keyword": let input = ":\0\n" - try: + expect(InvalidModifierName): (needMore, unparsed) = parse(input, packet) - except PsycSyntaxError: - check(getCurrentExceptionMsg() == "invalid character in RoutingModifierName") test "empty keyword": let input = ":\n" - try: + expect(InvalidModifierName): + (needMore, unparsed) = parse(input, packet) + + test "routing modifier with binary-arg": + let input = ":_test 4\ttest\n" + expect(InvalidModifierValue): + (needMore, unparsed) = parse(input, packet) + + test "binary-arg without length": + let input = "\n:_test \t" + (needMore, unparsed) = parse(input, packet) + (needMore, unparsed) = parse(input, packet) + check(packet.state == ParseState.EntityModifierName) + expect(InvalidModifierValue): (needMore, unparsed) = parse(input, packet) - except PsycSyntaxError: - check(getCurrentExceptionMsg() == "RoutingModifierName does not start with '_'") test "invalid content length": let input = "abc\n" (needMore, unparsed) = parse(input, packet) check(packet.state == ParseState.ContentLength) - try: + expect(InvalidContentLength): (needMore, unparsed) = parse(input, packet) - except PsycSyntaxError: - check(getCurrentExceptionMsg() == "ContentLength is not a positive integer") echo "parser tests completed"