修改原始的protobuf流

时间:2018-08-03 14:33:20

标签: c++ protocol-buffers

假设我已经使用以下原始文件编译了一个应用程序(接收器):

syntax = "proto3";  
message Control {   
    bytes version = 1;  
    uint32 id = 2; 
    bytes color = 3;
}

,我还有另一个应用程序(发送器),该应用程序最初具有相同的原型文件,但在更新后添加了一个新字段,如:

syntax = "proto3";  
message Control {   
    bytes name = 1;  
    uint32 id = 2; 
    bytes color = 3;
    uint32 color_id = 4;
}

我已经看到,如果Receiver应用程序尝试解析原型,请更改一些数据,然后将其序列化回去,从而删除来自Transmitter应用程序的添加字段。

我需要一种无需直接解析/序列化原型即可直接访问原始字节的id字段的方法。有可能吗?

这是必需的,因为我在控制消息中有一些“标头”字段,我知道它们永远不会更改,但是由于应用程序更新,可以在同一传输程序应用程序的原型中添加/更改其他字段。

我已经看到:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.coded_stream 但是我无法修改现有的字节流,并且ReadString无法理解字符串的长度。

预先感谢

3 个答案:

答案 0 :(得分:1)

我认为没有官方的方法可以做到。您可以按照protobuf(https://developers.google.com/protocol-buffers/docs/encoding#structure)的编码准则手动进行操作。

基本上,您应该这样做:

  • 从第一位开始解码
  • 解码,直到达到ID的字段编号
  • 识别代表ID的位,并将其替换为新的(已编码!)ID

这很不好,原因有几个。最重要的是,您的代码必须了解有关消息结构和内容(ID的字段号和数据类型)的详细信息,而这正是使用协议缓冲区时要避免的(您始终需要.proto文件中的一些信息) )。

答案 1 :(得分:0)

在proto2语法中,protobuf C ++库用于保留未知字段,以便在您重新编码消息时将保留它们。不幸的是,proto3语法中的have been removed这个功能(与其他功能一样)。

一种解决方法可能是这样:

  1. id消息中仅设置新的Receiver值并对其进行编码。
  2. 将此数据附加到原始二进制数据之后。

这依赖于protobuf功能,即附加消息替换protobuf消息中字段的原始值。


嗯,实际上是在阅读上面链接的问题报告,看来you can turn on unknown field preservation in protobuf version 3.5 and newer

答案 2 :(得分:0)

只需反序列化整个消息并将其映射到新消息上即可。这是最干净的方法。您没有大量数据,并且可能没有实时要求。创建一个映射器,不要过分考虑问题。