support multiple modifiers

master
lurchi 2018-08-16 23:59:51 +02:00
parent 48af85e4a6
commit 2735d8e089
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
1 changed files with 37 additions and 26 deletions

View File

@ -74,7 +74,6 @@ proc parseModifierName(input: string,
op: char, op: char,
name: string] = name: string] =
assert(packet.cursor < input.len()) assert(packet.cursor < input.len())
const operators = ['=', ':', '+', '-', '?']
if packet.cursor == input.high(): if packet.cursor == input.high():
result.complete = false result.complete = false
return return
@ -82,8 +81,6 @@ proc parseModifierName(input: string,
packet.cursor.inc() packet.cursor.inc()
return (true, '\0', nil) return (true, '\0', nil)
result.op = input[packet.cursor] result.op = input[packet.cursor]
if not (result.op in operators):
raise new(ValueError) # invalid operator
packet.cursor.inc() packet.cursor.inc()
if result.op == '?': if result.op == '?':
if input[packet.cursor] != '\n': if input[packet.cursor] != '\n':
@ -163,6 +160,10 @@ proc parseData(input: string,
result.value = input[packet.cursor .. packet.cursor + packet.remainingPartLen - 1] result.value = input[packet.cursor .. packet.cursor + packet.remainingPartLen - 1]
packet.remainingPartLen = -1 packet.remainingPartLen = -1
proc isModifierName(input: string, cursor: int): bool =
const operators = ['=', ':', '+', '-', '?']
input[cursor] in operators
proc newPacket*(): PsycPacket = proc newPacket*(): PsycPacket =
PsycPacket(routingHeader: newSeq[Modifier](), PsycPacket(routingHeader: newSeq[Modifier](),
entityHeader: newSeq[Modifier](), entityHeader: newSeq[Modifier](),
@ -191,17 +192,21 @@ proc parse*(input: string,
result.needMoreInput = true result.needMoreInput = true
case packet.state: case packet.state:
of ParseState.RoutingModifierName: of ParseState.RoutingModifierName:
let (complete, op, name) = parseModifierName(input, packet) if not isModifierName(input, packet.cursor):
if complete: packet.state = ParseState.ContentLength
result.needMoreInput = false result.needMoreInput = false
packet.state = ParseState.RoutingModifierValue else:
let modifier = Modifier(op: op, name: name) let (complete, op, name) = parseModifierName(input, packet)
packet.routingHeader.add(modifier) if complete:
result.needMoreInput = false
packet.state = ParseState.RoutingModifierValue
let modifier = Modifier(op: op, name: name)
packet.routingHeader.add(modifier)
of ParseState.RoutingModifierValue: of ParseState.RoutingModifierValue:
let (complete, value) = parseModifierSimpleValue(input, packet) let (complete, value) = parseModifierSimpleValue(input, packet)
result.needMoreInput = not complete result.needMoreInput = not complete
if complete and value.len() > 0: if complete and value.len() > 0:
packet.state = ParseState.ContentLength packet.state = ParseState.RoutingModifierName
if packet.routingHeader[^1].value.isNil(): if packet.routingHeader[^1].value.isNil():
packet.routingHeader[^1].value = "" packet.routingHeader[^1].value = ""
packet.routingHeader[^1].value.add(value) packet.routingHeader[^1].value.add(value)
@ -213,21 +218,25 @@ proc parse*(input: string,
packet.state = ParseState.EntityModifierName packet.state = ParseState.EntityModifierName
packet.contentLength = value packet.contentLength = value
of ParseState.EntityModifierName: of ParseState.EntityModifierName:
let oldCursor = packet.cursor if not input.isModifierName(packet.cursor):
let (complete, op, name) = parseModifierName(input, packet) packet.state = ParseState.Method
packet.entityHeaderLen += packet.cursor - oldCursor
if complete:
result.needMoreInput = false result.needMoreInput = false
packet.state = ParseState.EntityModifierValue else:
let modifier = Modifier(op: op, name: name) let oldCursor = packet.cursor
packet.entityHeader.add(modifier) let (complete, op, name) = parseModifierName(input, packet)
packet.entityHeaderLen += packet.cursor - oldCursor
if complete:
result.needMoreInput = false
packet.state = ParseState.EntityModifierValue
let modifier = Modifier(op: op, name: name)
packet.entityHeader.add(modifier)
of ParseState.EntityModifierValue: of ParseState.EntityModifierValue:
let oldCursor = packet.cursor let oldCursor = packet.cursor
let (complete, value) = parseModifierValue(input, packet) let (complete, value) = parseModifierValue(input, packet)
result.needMoreInput = not complete result.needMoreInput = not complete
packet.entityHeaderLen += (packet.cursor - oldCursor) packet.entityHeaderLen += (packet.cursor - oldCursor)
if complete: if complete:
packet.state = ParseState.Method packet.state = ParseState.EntityModifierName
if not value.isNil(): if not value.isNil():
if packet.entityHeader[^1].value.isNil(): if packet.entityHeader[^1].value.isNil():
packet.entityHeader[^1].value = "" packet.entityHeader[^1].value = ""
@ -258,28 +267,30 @@ suite "parser tests":
var packet = newPacket() var packet = newPacket()
test "state sync": test "state sync":
let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n?\n|\n" let input = ":_target\talice\n\n?\n|\n"
while packet.state != ParseState.Complete: while packet.state != ParseState.Complete:
discard parse(input, packet) discard parse(input, packet)
check(packet.routingHeader.len() == 1) check(packet.routingHeader.len() == 1)
check(packet.routingHeader[0] == Modifier(op: ':', check(packet.routingHeader[0] == Modifier(op: ':',
name: "_target", name: "_target",
value: "psyc://ve.symlynx.com/@blog")) value: "alice"))
check(packet.entityHeader.len() == 1) check(packet.entityHeader.len() == 1)
check(packet.entityHeader[0] == Modifier(op: '?', name: nil, value: nil)) check(packet.entityHeader[0] == Modifier(op: '?', name: nil, value: nil))
test "simple-arg": test "simple-arg":
let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_test\thello\n|\n" let input = ":_target\talice\n\n:_hello\tworld\n:_hallo\twelt\n|\n"
while packet.state != ParseState.Complete: while packet.state != ParseState.Complete:
discard parse(input, packet) discard parse(input, packet)
check(packet.entityHeader.len() == 1) check(packet.entityHeader.len() == 2)
check(packet.entityHeader[0] == Modifier(op: ':', name: "_test", value: "hello")) check(packet.entityHeader[0] == Modifier(op: ':', name: "_hello", value: "world"))
check(packet.entityHeader[1] == Modifier(op: ':', name: "_hallo", value: "welt"))
test "binary-arg": test "binary-arg":
let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_test 5\thello\n|\n" let input = ":_target\talice\n\n:_hello 5\tworld\n:_hallo 4\twelt\n|\n"
while packet.state != ParseState.Complete: while packet.state != ParseState.Complete:
discard parse(input, packet) discard parse(input, packet)
check(packet.entityHeader.len() == 1) check(packet.entityHeader.len() == 2)
check(packet.entityHeader[0] == Modifier(op: ':', name: "_test", value: "hello")) check(packet.entityHeader[0] == Modifier(op: ':', name: "_hello", value: "world"))
check(packet.entityHeader[1] == Modifier(op: ':', name: "_hallo", value: "welt"))
echo "parser tests completed" echo "parser tests completed"