diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-07 10:43:27 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-07 10:43:27 +0300 |
| commit | 66a5f4733b24df953a3b8ae0ec310c223fa18c90 (patch) | |
| tree | c028bf47b7fb573b9dad604487203557eab66319 | |
| parent | 9a42b640e492b9ad224b3177591968701fcfda2f (diff) | |
| download | nimpb_protoc-66a5f4733b24df953a3b8ae0ec310c223fa18c90.tar.gz nimpb_protoc-66a5f4733b24df953a3b8ae0ec310c223fa18c90.zip | |
Read fields even for empty messages
When a message definition doesnt have any fields, it could be that in the future
the definition has fields. The message on the wire could have unknown fields,
even if our definition does not have any fields. So, we should read fields
for "empty" messages and store the unknown fields so that we can pass them
through if needed.
| -rw-r--r-- | src/nimpb_buildpkg/plugin.nim | 99 |
1 files changed, 49 insertions, 50 deletions
diff --git a/src/nimpb_buildpkg/plugin.nim b/src/nimpb_buildpkg/plugin.nim index 70346af..4e46300 100644 --- a/src/nimpb_buildpkg/plugin.nim +++ b/src/nimpb_buildpkg/plugin.nim @@ -704,59 +704,58 @@ iterator genReadMapKVProc(msg: Message): string = iterator genReadMessageProc(msg: Message): string = yield &"proc read{msg.names}*(stream: ProtobufStream): {msg.names} =" yield indent(&"result = new{msg.names}()", 4) - if len(msg.fields) > 0: - yield indent("while not atEnd(stream):", 4) - yield indent("let", 8) - yield indent("tag = readTag(stream)", 12) - yield indent("wireType = wireType(tag)", 12) - yield indent("case fieldNumber(tag)", 8) - yield indent("of 0:", 8) - yield indent("raise newException(InvalidFieldNumberError, \"Invalid field number: 0\")", 12) - for field in msg.fields: - let - setter = - if isRepeated(field): - &"add{field.name}" - else: - &"set{field.name}" - yield indent(&"of {field.number}:", 8) - if isRepeated(field): - if isMapEntry(field): - yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) - yield indent("let", 12) - yield indent("size = readVarint(stream)", 16) - yield indent("data = safeReadStr(stream, int(size))", 16) - yield indent("pbs = newProtobufStream(newStringStream(data))", 16) - yield indent(&"{field.readProc}(pbs, result.{field.name})", 12) - elif isNumeric(field): - yield indent(&"expectWireType(wireType, {field.wiretypeStr}, WireType.LengthDelimited)", 12) - yield indent("if wireType == WireType.LengthDelimited:", 12) - yield indent("let", 16) - yield indent("size = readVarint(stream)", 20) - yield indent("start = uint64(getPosition(stream))", 20) - yield indent("var consumed = 0'u64", 16) - yield indent("while consumed < size:", 16) - yield indent(&"{setter}(result, {field.readProc}(stream))", 20) - yield indent("consumed = uint64(getPosition(stream)) - start", 20) - yield indent("if consumed != size:", 16) - yield indent("raise newException(Exception, \"packed field size mismatch\")", 20) - yield indent("else:", 12) - yield indent(&"{setter}(result, {field.readProc}(stream))", 16) - elif isMessage(field): - yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) - yield indent(&"let data = readLengthDelimited(stream)", 12) - yield indent(&"{setter}(result, new{field.typeName}(data))", 12) + yield indent("while not atEnd(stream):", 4) + yield indent("let", 8) + yield indent("tag = readTag(stream)", 12) + yield indent("wireType = wireType(tag)", 12) + yield indent("case fieldNumber(tag)", 8) + yield indent("of 0:", 8) + yield indent("raise newException(InvalidFieldNumberError, \"Invalid field number: 0\")", 12) + for field in msg.fields: + let + setter = + if isRepeated(field): + &"add{field.name}" else: - yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) - yield indent(&"{setter}(result, {field.readProc}(stream))", 12) + &"set{field.name}" + yield indent(&"of {field.number}:", 8) + if isRepeated(field): + if isMapEntry(field): + yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) + yield indent("let", 12) + yield indent("size = readVarint(stream)", 16) + yield indent("data = safeReadStr(stream, int(size))", 16) + yield indent("pbs = newProtobufStream(newStringStream(data))", 16) + yield indent(&"{field.readProc}(pbs, result.{field.name})", 12) + elif isNumeric(field): + yield indent(&"expectWireType(wireType, {field.wiretypeStr}, WireType.LengthDelimited)", 12) + yield indent("if wireType == WireType.LengthDelimited:", 12) + yield indent("let", 16) + yield indent("size = readVarint(stream)", 20) + yield indent("start = uint64(getPosition(stream))", 20) + yield indent("var consumed = 0'u64", 16) + yield indent("while consumed < size:", 16) + yield indent(&"{setter}(result, {field.readProc}(stream))", 20) + yield indent("consumed = uint64(getPosition(stream)) - start", 20) + yield indent("if consumed != size:", 16) + yield indent("raise newException(Exception, \"packed field size mismatch\")", 20) + yield indent("else:", 12) + yield indent(&"{setter}(result, {field.readProc}(stream))", 16) + elif isMessage(field): + yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) + yield indent(&"let data = readLengthDelimited(stream)", 12) + yield indent(&"{setter}(result, new{field.typeName}(data))", 12) else: yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) - if isMessage(field): - yield indent("let data = readLengthDelimited(stream)", 12) - yield indent(&"{setter}(result, new{field.typeName}(data))", 12) - else: - yield indent(&"{setter}(result, {field.readProc}(stream))", 12) - yield indent("else: readUnknownField(stream, tag, result.unknownFields)", 8) + yield indent(&"{setter}(result, {field.readProc}(stream))", 12) + else: + yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) + if isMessage(field): + yield indent("let data = readLengthDelimited(stream)", 12) + yield indent(&"{setter}(result, new{field.typeName}(data))", 12) + else: + yield indent(&"{setter}(result, {field.readProc}(stream))", 12) + yield indent("else: readUnknownField(stream, tag, result.unknownFields)", 8) yield "" iterator genSizeOfMapKVProc(message: Message): string = |
