support multiple modifiers

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