有没有办法在序列化后获得某个protobuf消息的最大大小?
我指的是不包含“重复”元素的消息。
请注意,我不指的是具有特定内容的protobuf消息的大小,但指的是它可以到达的最大可能大小(在最坏的情况)。
答案 0 :(得分:14)
通常,任何protobuf消息都可以是任何长度,因为可能存在未知字段。如果您收到消息,则无法对长度做出任何假设。如果您发送您自己构建的消息,那么您可以假设它只包含您知道的字段 - 但是,在这种情况下,您还可以轻松计算确切的消息大小。因此,通常无法询问最大尺寸是多少。
话虽如此,您可以编写使用Descriptor
接口的代码来迭代FieldDescriptor
以获取消息类型(MyMessageType::descriptor()
)。
请参阅:https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor
类似的接口存在于Java,Python和其他可能的接口中。
以下是要实施的规则:
每个字段由一个标记后跟一些数据组成。
对于标签:
对于数据:
bool
总是一个字节。int32
,int64
,uint64
和sint64
的最大数据长度为10个字节(是的,int32
如果是,则可以是10个字节不幸的是,这是负面的。sint32
和uint32
的最大数据长度为5个字节。fixed32
,sfixed32
和float
总是正好是4个字节。fixet64
,sfixed64
和double
总是正好是8个字节。如果您的邮件包含以下任何内容,则其最大长度无限制:
string
或bytes
类型的任何字段。 (除非你知道它们的最大长度,在这种情况下,它是最大长度加上长度前缀,就像子消息一样。)答案 1 :(得分:4)
据我所知,没有任何功能可以计算谷歌自己的protobuf的最大尺寸。
Nanopb generator会尽可能计算最大大小,并将其作为#define
导出到生成的文件中。
根据protobuf encoding documentation手动计算小邮件也很简单。
答案 2 :(得分:3)
在实施protobuffer 3消息大小计算时,我发现Kenton所说的大部分内容都是正确的。我确实遇到了一个疏忽:标签是从字段编号创建的,左移3位,然后按线类型(在wire_format_lite.h中找到)进行按位或运算。然后将该结果编码为var int
。因此对于刚好超过16的标签,标签将是2个字节,但如果字段数更大(> ~1000),则标签将大于3个字节。对于protobuffer 3用户来说这可能不是问题,因为字段数量大是对protobuf的误用。