Skip to content

Commit

Permalink
Introduce encode_data and decode_data method
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouziel committed Mar 4, 2025
1 parent b2cfcac commit 6dc4a0b
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 11 deletions.
69 changes: 69 additions & 0 deletions counterparty-core/counterpartycore/lib/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,72 @@ def int_to_bytes(integer_in: int) -> bytes:

def bytes_to_int(bytes_in: bytes) -> int:
return int.from_bytes(bytes_in, "little")


def varint(number):
def _byte(b):
return bytes((b,))

Check warning on line 158 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L157-L158

Added lines #L157 - L158 were not covered by tests

"""Pack `number` into varint bytes"""

Check warning

Code scanning / pylint

String statement has no effect. Warning

String statement has no effect.
buf = b""
while True:
towrite = number & 0x7F
number >>= 7
if number:
buf += _byte(towrite | 0x80)

Check warning on line 166 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L160-L166

Added lines #L160 - L166 were not covered by tests
else:
buf += _byte(towrite)
break
return buf

Check warning on line 170 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L168-L170

Added lines #L168 - L170 were not covered by tests


def encode_data(*args):
data = b""
for arg in args:
if isinstance(arg, str):
if all(c in string.hexdigits for c in arg):
try:
value = bytes.fromhex(arg)
except ValueError:
value = arg.encode("utf-8")

Check warning on line 181 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L174-L181

Added lines #L174 - L181 were not covered by tests
else:
value = arg.encode("utf-8")
elif isinstance(arg, int):
value = int_to_bytes(arg)
elif isinstance(arg, bytes):
value = arg
data += varint(len(value)) + value

Check warning

Code scanning / pylint

Possibly using variable 'value' before assignment. Warning

Possibly using variable 'value' before assignment.
return data

Check warning on line 189 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L183-L189

Added lines #L183 - L189 were not covered by tests


def decode_varint(data, offset=0):
"""Unpack varint bytes starting at offset into a number."""
result = 0
shift = 0
while True:
byte = data[offset]
result |= (byte & 0x7F) << shift
offset += 1
if not (byte & 0x80):

Check warning

Code scanning / pylint

Unnecessary parens after 'not' keyword. Warning

Unnecessary parens after 'not' keyword.
break
shift += 7
return result, offset

Check warning on line 203 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L194-L203

Added lines #L194 - L203 were not covered by tests


def decode_data(data):
"""Decode data encoded with encode_data back into a list of values."""
if not isinstance(data, bytes):
raise TypeError("Input must be bytes")

Check warning on line 209 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L208-L209

Added lines #L208 - L209 were not covered by tests

result = []
offset = 0
while offset < len(data):

Check warning on line 213 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L211-L213

Added lines #L211 - L213 were not covered by tests
# Decode the length of the next value
length, new_offset = decode_varint(data, offset)

Check warning on line 215 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L215

Added line #L215 was not covered by tests
# Extract the value bytes
value = data[new_offset : new_offset + length]
result.append(value)

Check warning on line 218 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L217-L218

Added lines #L217 - L218 were not covered by tests
# Update offset to point after this value
offset = new_offset + length

Check warning on line 220 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L220

Added line #L220 was not covered by tests

return result

Check warning on line 222 in counterparty-core/counterpartycore/lib/utils/helpers.py

View check run for this annotation

Codecov / codecov/patch

counterparty-core/counterpartycore/lib/utils/helpers.py#L222

Added line #L222 was not covered by tests
22 changes: 11 additions & 11 deletions counterparty-core/counterpartycore/test/units/api/apiv1_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "02000000010ad301060bba3f554cd12b5adfa13f59aba221791b8127d352259cff096074b90000000000ffffffff020000000000000000306a2eb6ca4ce614444ebe56b5710c55ba7a167cfde254337662d4d396fe88532f15ba871102bdb91f9e4370ad890fc7e40ec89a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "0200000001c3f809cfdfc5190e9bde38bab8378a6e191db467645fadd23a3182c8013f52f50000000000ffffffff020000000000000000306a2ec504f53e28185bc36017b0741575d9857548189c38fe67cd64743973fd0eb779b757ca7e8afc1ed91375b47d8e3f0ec89a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down Expand Up @@ -47,7 +47,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "0200000001c3f809cfdfc5190e9bde38bab8378a6e191db467645fadd23a3182c8013f52f50000000000ffffffff02e80300000000000069512102a809ef382a1a5dce3b15b0741575d9857449189c38fc9fc7149bdb947f45a7ee21024b5000e3d2dff205e21b62f1a51505abd9937ba7722b150f552f29c89b16f93a210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "020000000123cf835e30524abad885998c242cc8eeaa449f6b2681b81783a2cb49d10d72910000000000ffffffff02e803000000000000695121024c8d7b21aecdb08550b62294a1b2b6dcdf3bc146323d593ee217ed0ce03f5f782103773c820a7ac8de01ee2b12292c81cf79172e0821becb236c71bd18de09adc02e210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down Expand Up @@ -81,7 +81,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "020000000123cf835e30524abad885998c242cc8eeaa449f6b2681b81783a2cb49d10d72910000000000ffffffff02e803000000000000695121037e8d7b21aecdb08550a22294a1b2b6d723d9c146323d5bc4117f83818ad7fcab2102c4bde43b627c3fee1ae4d5f9b9cc1995172e0821becb236c71bd18de09adc0e7210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "0200000001aaf710464016ac2ff3e750e04fc56f7380ef9ede9623fd27e0bc2acc703203900000000000ffffffff02e803000000000000695121021f0c056a765f5a7c73a43c71bce264f0b53862a90663e73a0dbf1443a2d001562102dbd33aebc12a1c839bb057b4a2ab87e6aaef7111a8acd844a0bcb9f51187c125210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand All @@ -98,7 +98,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "0200000001aaf710464016ac2ff3e750e04fc56f7380ef9ede9623fd27e0bc2acc703203900000000000ffffffff0322020000000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ace803000000000000695121031f0c056a765f5a7c73a43c71bc403f1802bd62a90663e73a0e571443a2d001ca2102dbd33aebc12a1c839bb057b4a2ab87e6aaef7111a8acd844a0bcb9f51187c125210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053ae86c09a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "02000000011bf55f4cc6af2be8eda80cff23a8cdf66a6be48e37561345c63a9848b159b8a40000000000ffffffff0322020000000000001976a9148d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec88ace8030000000000006951210214e937ec9fd8ee9234aec62220f20a3e1588920997aadbba550161b65cdefd70210392f051426d7f59929f6f0257a6d00a1145fa7309d23557736a553cbb8bfc00ed210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053ae86c09a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand All @@ -117,7 +117,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "02000000011bf55f4cc6af2be8eda80cff23a8cdf66a6be48e37561345c63a9848b159b8a40000000000ffffffff02e803000000000000695121033be937ec9fd8ee9234b2c622205051dd5eee920997aad940a58160b65cdefdff210392f050426d7f59976a8e0257acd00a1145fa7309d23557736a553cbb8bfc00e4210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "02000000016bdae59894794314088b696b4fc79ddd4961578170c78e672d77d247ccc21dd90000000000ffffffff02e803000000000000695121024b414b8270dc68144804297f7a815df9650a7f414402455b7147fc0a14f2e8a421026efeed7478c2f053bc6d67a9be40a606c1cdd92caf0623f327750fc508dfbf98210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand All @@ -135,7 +135,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "02000000016bdae59894794314088b696b4fc79ddd4961578170c78e672d77d247ccc21dd90000000000ffffffff02e803000000000000695121024b414b8270dc68144804297f7a815df9650b7f41440241e3ad87fc0a14f2e8e621036efeec7478c2f054b37ce7a9be40a606c1cdd4970f0623f327750fc508dfbf02210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "0200000001966cb7d919e7ef5356bc588155d85ab1cdc9c325b245b9181dfa34db0bc1e0a90000000000ffffffff02e80300000000000069512102d5c7b0d916aaafb7849b50132024ad531b1bc4abcce42e636017ba159df368552103458b06ad8fbe9e10c51225237957edd7a9e4244281916c2dc3a96a8c5b07e068210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down Expand Up @@ -164,7 +164,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "0200000001966cb7d919e7ef5356bc588155d85ab1cdc9c325b245b9181dfa34db0bc1e0a90000000000ffffffff03e8030000000000004751210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0210319f6e07b0b8d756156394b9dcf3b011fe9ac19f2700bd6b69a6a1783dbb8b97752aee80300000000000069512103fac7b0d916aaafb7849150132024ad531b1ac4abcde428214c524ff49df368632102458b06ad8fbe9e123fe2a5237357edd7a9e429f921916c2dc3a96a8c5b07e0b2210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aec8bb9a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "02000000019e876739a99203e59524ce12aa739f2e08f0f837804ad3cf3b845d1a7dd126510000000000ffffffff03e8030000000000004751210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0210319f6e07b0b8d756156394b9dcf3b011fe9ac19f2700bd6b69a6a1783dbb8b97752aee803000000000000695121025058f96911e69de34bcb61a4e9b5e3acbe8316b3c41d7ce054fb4919dc3d89162102ae072ffe50fdf2e96421418b8996250f49e84c8865e492fb9b779d9ba645625c210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aec8bb9a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down Expand Up @@ -228,7 +228,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "02000000019e876739a99203e59524ce12aa739f2e08f0f837804ad3cf3b845d1a7dd126510000000000ffffffff03e8030000000000004751210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0210319f6e07b0b8d756156394b9dcf3b011fe9ac19f2700bd6b69a6a1783dbb8b97752aee803000000000000695121035058f96911e69de34bdd61a4e917b84ff5e516b3c51d7ce054febdf8dc3d89532102ae072ffe50fdf2e96421418b8996250f49e84c8865e492fb9b779d9ba645625c210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aec8bb9a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "0200000001070ad198b63d3b85ed274e1293f056bf53b9a9b749358ab629be90731ae6ae050000000000ffffffff03e8030000000000004751210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0210319f6e07b0b8d756156394b9dcf3b011fe9ac19f2700bd6b69a6a1783dbb8b97752aee80300000000000069512103a8096416dd255eb5aca8be7f67519a8b0ec517b6d75fc1a540f46470dbc18d7021033154e78348448a74e59bf0fdb172543f9668c3d40dc783ead4cd73b01daa2e6e210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aec8bb9a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand All @@ -242,7 +242,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "0200000001070ad198b63d3b85ed274e1293f056bf53b9a9b749358ab629be90731ae6ae050000000000ffffffff02e8030000000000006951210295096416dd255eb5aca84180980c3e97ba5c17b6d75fc1a5431c6470db01c3b221026418ab8348448a74e59bf0fdb172543f9668c3d40dc783ead4cd73b01daa2edd210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "0200000001c8b0941d5a9367f13ca7a7b7f558d9c7fcda5a189cb62b78976b844fd52cde9b0000000000ffffffff02e80300000000000069512102b3a9c36c150aafc3b2ef01db8dd3df08fbbf187650f0636a7fac08e693f641432102768bb76d8382d0fea56a0802a0dc61927810e6244587b20180a79d2366d7aef9210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down Expand Up @@ -294,7 +294,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "0200000001c8b0941d5a9367f13ca7a7b7f558d9c7fcda5a189cb62b78976b844fd52cde9b0000000000ffffffff02e80300000000000069512102b3a9c36c150aafc3b2cbfe24722c2502e540187650523889372209e693360fb5210223c7fa6d8382d0fea56a0802a0dc61927810e6244587b20180a79d2366d7ae68210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "02000000017735df3ee6bf0b86a8ab5c78bb1a4a32a35418641e844b9962608f2c86f3b53d0000000000ffffffff02e80300000000000069512103aa8c7ac1116c7ffc5e269fc184b9061a5d60869f98a1e31cf028550b808d893121037983463767e7cacb86972712f3a86edc146ee68b73f500655b29fd949189053a210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand All @@ -309,7 +309,7 @@ def test_create_burn(apiv1_client, defaults):
).json
assert (
result["result"]
== "02000000017735df3ee6bf0b86a8ab5c78bb1a4a32a35418641e844b9962608f2c86f3b53d0000000000ffffffff02e80300000000000069512102aa8c7ac1116c7ffc5e269fc184b903efbc61869952db6480b028550b808d89f721037983463767e7cacb86972712f3a86edc146ee68b73f500655b29fd949189053a210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
== "02000000010ad301060bba3f554cd12b5adfa13f59aba221791b8127d352259cff096074b90000000000ffffffff02e80300000000000069512103d4c756e0164648b30d87710c55ba7a167dfce252f9ac445b589f73e2bb8ca63d21033be1211a0958f06a8cb77d1c421108b0b66ad71d066e59c32bb2e58db3945f87210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b053aed0c29a3b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
)

result = apiv1_client(
Expand Down
181 changes: 181 additions & 0 deletions counterparty-core/counterpartycore/test/units/utils/helpers_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import string

import pytest
from counterpartycore.lib.utils import helpers


Expand All @@ -22,3 +25,181 @@ def test_dhash():
helpers.dhash_string("foobar")
== "3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda1"
)


def test_int_to_bytes():
"""Test the int_to_bytes function"""
# Basic cases
assert helpers.int_to_bytes(0) == b"\x00"
assert helpers.int_to_bytes(1) == b"\x01"
assert helpers.int_to_bytes(255) == b"\xff"

# Numbers requiring multiple bytes
assert helpers.int_to_bytes(256) == b"\x00\x01"
assert helpers.int_to_bytes(65535) == b"\xff\xff"
assert helpers.int_to_bytes(65536) == b"\x00\x00\x01"

# Very large number
big_num = 1234567890123456789
assert helpers.bytes_to_int(helpers.int_to_bytes(big_num)) == big_num


def test_bytes_to_int():
"""Test the bytes_to_int function"""
# Basic cases
assert helpers.bytes_to_int(b"\x00") == 0
assert helpers.bytes_to_int(b"\x01") == 1
assert helpers.bytes_to_int(b"\xff") == 255

# Multi-byte values
assert helpers.bytes_to_int(b"\x00\x01") == 256
assert helpers.bytes_to_int(b"\xff\xff") == 65535

# Verify that int_to_bytes and bytes_to_int are inverse operations
test_numbers = [0, 1, 127, 128, 255, 256, 65535, 65536, 123456789]
for num in test_numbers:
assert helpers.bytes_to_int(helpers.int_to_bytes(num)) == num


def test_varint():
"""Test the varint function"""
# Small numbers
assert helpers.varint(0) == b"\x00"
assert helpers.varint(1) == b"\x01"
assert helpers.varint(127) == b"\x7f"

# Numbers requiring multiple bytes
assert helpers.varint(128) == b"\x80\x01"
assert helpers.varint(129) == b"\x81\x01"
assert helpers.varint(16384) == b"\x80\x80\x01"

# Verification with decode_varint
test_numbers = [0, 1, 127, 128, 255, 16384, 2097152]
for num in test_numbers:
encoded = helpers.varint(num)
decoded, _ = helpers.decode_varint(encoded)
assert decoded == num


def test_decode_varint():
"""Test the decode_varint function"""
# Simple cases
assert helpers.decode_varint(b"\x00") == (0, 1)
assert helpers.decode_varint(b"\x01") == (1, 1)
assert helpers.decode_varint(b"\x7f") == (127, 1)

# Multi-byte varints
assert helpers.decode_varint(b"\x80\x01") == (128, 2)
assert helpers.decode_varint(b"\xff\x01") == (255, 2)
assert helpers.decode_varint(b"\x80\x80\x01") == (16384, 3)

# Test with offset
assert helpers.decode_varint(b"\x00\x7f", 1) == (127, 2)
assert helpers.decode_varint(b"\x00\x80\x01", 1) == (128, 3)

# Test with additional data
data = b"\x05hello\x03world"
length, offset = helpers.decode_varint(data)
assert length == 5
assert offset == 1
assert data[offset : offset + length] == b"hello"


def test_encode_data():
"""Test the encode_data function"""
# Test with a string
result = helpers.encode_data("hello")
assert result == b"\x05hello"

# Test with an integer
result = helpers.encode_data(42)
assert result == b"\x01\x2a"

# Test with bytes
result = helpers.encode_data(b"test")
assert result == b"\x04test"

# Test with a hexadecimal string
result = helpers.encode_data("48656c6c6f") # "Hello" in hexadecimal
assert result == b"\x05Hello"

# Test with multiple arguments
result = helpers.encode_data("abc", 123, b"xyz")
expected = b"\x03abc\x01\x7b\x03xyz"
assert result == expected

# Test with empty strings and zeros
result = helpers.encode_data("", 0, b"")
assert result == b"\x00\x01\x00\x00"


def test_decode_data():
"""Test the decode_data function"""
# Simple cases
assert helpers.decode_data(b"\x05hello") == [b"hello"]
assert helpers.decode_data(b"\x01\x2a") == [b"\x2a"]
assert helpers.decode_data(b"\x04test") == [b"test"]

# Test with multiple values
encoded = b"\x03abc\x01\x7b\x03xyz"
decoded = helpers.decode_data(encoded)
assert decoded == [b"abc", b"\x7b", b"xyz"]

# Test with empty data
assert helpers.decode_data(b"\x00") == [b""]

# Test with TypeError
with pytest.raises(TypeError):
helpers.decode_data("not bytes")


def test_round_trip():
"""Complete test of encoding followed by decoding"""
test_cases = [
["simple string"],
[42],
[b"binary data"],
["abc", 123, b"xyz"],
["", 0, b""], # Cases with empty values
["a" * 1000], # Long string
[2**20], # Large number
]

for case in test_cases:
encoded = helpers.encode_data(*case)
decoded = helpers.decode_data(encoded)

# Transform original values into what we expect after decoding
expected = []
for item in case:
if isinstance(item, str):
if all(c in string.hexdigits for c in item):
try:
expected.append(bytes.fromhex(item))
except ValueError:
expected.append(item.encode("utf-8"))
else:
expected.append(item.encode("utf-8"))
elif isinstance(item, int):
expected.append(helpers.int_to_bytes(item))
elif isinstance(item, bytes):
expected.append(item)

assert decoded == expected


# Additional tests for edge cases
def test_edge_cases():
# Test with extreme values
assert helpers.int_to_bytes(0) == b"\x00"
assert helpers.bytes_to_int(b"") == 0 # Verify behavior with empty bytes

# Strings with non-ASCII characters
utf8_string = "こんにちは" # Hello in Japanese
encoded = helpers.encode_data(utf8_string)
decoded = helpers.decode_data(encoded)
assert decoded[0] == utf8_string.encode("utf-8")

# Test with a number near Python integer limits
large_int = 2**63 - 1 # Max value for a 64-bit signed integer
assert helpers.bytes_to_int(helpers.int_to_bytes(large_int)) == large_int

0 comments on commit 6dc4a0b

Please sign in to comment.