From 35753efa356a5f0d47c1e5a6560221b01b9d42cb Mon Sep 17 00:00:00 2001 From: Damian Shaw Date: Mon, 26 Oct 2026 16:02:12 -0400 Subject: [PATCH] Reuse plain frame bodies during serialization --- CHANGELOG.rst | 2 +- src/hyperframe/frame.py | 14 ++++++++++++++ tests/test_frames.py | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 750102f..c657aa9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -19,7 +19,7 @@ dev **Bugfixes** -- +- Avoided copying unmodified DATA and HEADERS bodies during serialization. 6.1.0 (2025-01-22) ------------------ diff --git a/src/hyperframe/frame.py b/src/hyperframe/frame.py index 5bab673..bd6e127 100644 --- a/src/hyperframe/frame.py +++ b/src/hyperframe/frame.py @@ -304,6 +304,10 @@ def serialize_body(self) -> bytes: padding = b"\0" * self.pad_length if isinstance(self.data, memoryview): self.data = self.data.tobytes() + + if type(self.data) is bytes and type(padding_data) is bytes and not padding_data and not padding: + return self.data + return b"".join([padding_data, self.data, padding]) def parse_body(self, data: memoryview) -> None: @@ -748,6 +752,16 @@ def serialize_body(self) -> bytes: else: priority_data = b"" + if ( + type(self.data) is bytes + and type(padding_data) is bytes + and not padding_data + and type(priority_data) is bytes + and not priority_data + and not padding + ): + return self.data + return b"".join([padding_data, priority_data, self.data, padding]) def parse_body(self, data: memoryview) -> None: diff --git a/tests/test_frames.py b/tests/test_frames.py index b683354..20b7a61 100644 --- a/tests/test_frames.py +++ b/tests/test_frames.py @@ -142,6 +142,12 @@ def test_data_frame_serializes_properly(self, data): s = f.serialize() assert s == self.payload + def test_plain_data_frame_reuses_bytes_body(self): + data = b'testdata' + f = DataFrame(1, data) + + assert f.serialize_body() is data + def test_data_frame_with_padding_serializes_properly(self): f = DataFrame(1) f.flags = set(['END_STREAM', 'PADDED']) @@ -791,6 +797,12 @@ def test_headers_frame_serializes_properly(self): b'hello world' ) + def test_plain_headers_frame_reuses_bytes_body(self): + data = b'hello world' + f = HeadersFrame(1, data) + + assert f.serialize_body() is data + def test_headers_frame_parses_properly(self): s = ( b'\x00\x00\x0B\x01\x05\x00\x00\x00\x01' +