mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Serialize length-prefixed protos once (#27252)
Avoid calling ByteSize() separately in serialize_length_prefixed(). The serialized payload already carries the exact length to prefix, so this keeps behavior intact while avoiding a duplicate serialization-sized pass.
Closes #27252
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/27252 from Zaczero:python-serialize-length-prefixed-once 8a4f60b4c7
PiperOrigin-RevId: 923539199
This commit is contained in:
parent
00f4fcc7af
commit
e090f8ae77
2 changed files with 27 additions and 2 deletions
|
|
@ -11,6 +11,7 @@
|
|||
import io
|
||||
import unittest
|
||||
|
||||
from google.protobuf import message
|
||||
from google.protobuf import proto
|
||||
from google.protobuf.internal import encoder
|
||||
from google.protobuf.internal import test_proto2_pb2
|
||||
|
|
@ -77,6 +78,29 @@ class ProtoTest(unittest.TestCase):
|
|||
str(context.exception),
|
||||
)
|
||||
|
||||
def test_serialize_length_prefixed_serializes_once(self, message_module):
|
||||
del message_module
|
||||
|
||||
class CountingMessage(message.Message):
|
||||
|
||||
def __init__(self):
|
||||
self.serialize_count = 0
|
||||
|
||||
def SerializeToString(self, deterministic=None):
|
||||
self.serialize_count += 1
|
||||
return b'abc'
|
||||
|
||||
def ByteSize(self):
|
||||
raise AssertionError('serialize_length_prefixed should not call ByteSize')
|
||||
|
||||
msg = CountingMessage()
|
||||
out = io.BytesIO()
|
||||
|
||||
proto.serialize_length_prefixed(msg, out)
|
||||
|
||||
self.assertEqual(b'\x03abc', out.getvalue())
|
||||
self.assertEqual(1, msg.serialize_count)
|
||||
|
||||
def test_byte_size(self, message_module):
|
||||
msg = message_module.TestAllTypes()
|
||||
self.assertEqual(0, proto.byte_size(msg))
|
||||
|
|
|
|||
|
|
@ -64,9 +64,10 @@ def serialize_length_prefixed(message: _MESSAGE, output: io.BytesIO) -> None:
|
|||
message: The protocol buffer message that should be serialized.
|
||||
output: BytesIO or custom buffered IO that data should be written to.
|
||||
"""
|
||||
size = message.ByteSize()
|
||||
payload = serialize(message)
|
||||
size = len(payload)
|
||||
encoder._VarintEncoder()(output.write, size)
|
||||
out_size = output.write(serialize(message))
|
||||
out_size = output.write(payload)
|
||||
|
||||
if out_size != size:
|
||||
raise TypeError(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue