Skip to content

Commit cab64dc

Browse files
committed
feat: implement to_bytes and from_bytes
Still have a circular import to solve though
1 parent 2ba377e commit cab64dc

9 files changed

Lines changed: 71 additions & 0 deletions

File tree

libdestruct/c/c_int.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ def get(self: c_int) -> int:
1919
"""Return the value of the integer."""
2020
return int.from_bytes(self.memory[self.address : self.address + self.size], self.endianness, signed=True)
2121

22+
def to_bytes(self: obj) -> bytes:
23+
"""Return the serialized representation of the object."""
24+
if self._frozen:
25+
return self._frozen_value.to_bytes(self.size, self.endianness, signed=True)
26+
27+
return self.memory[self.address : self.address + self.size]
28+
2229
def _set(self: c_int, value: int) -> None:
2330
"""Set the value of the integer to the given value."""
2431
self.memory[self.address : self.address + self.size] = value.to_bytes(self.size, self.endianness, signed=True)

libdestruct/c/c_long.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ def get(self: c_long) -> int:
1919
"""Return the value of the integer."""
2020
return int.from_bytes(self.memory[self.address : self.address + self.size], self.endianness, signed=True)
2121

22+
def to_bytes(self: obj) -> bytes:
23+
"""Return the serialized representation of the object."""
24+
if self._frozen:
25+
return self._frozen_value.to_bytes(self.size, self.endianness, signed=True)
26+
27+
return self.memory[self.address : self.address + self.size]
28+
2229
def _set(self: c_long, value: int) -> None:
2330
"""Set the value of the integer to the given value."""
2431
self.memory[self.address : self.address + self.size] = value.to_bytes(self.size, self.endianness, signed=True)

libdestruct/c/c_str.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ def get(self: c_str, index: int = -1) -> bytes:
3535

3636
return bytes([self.memory[self.address + index]])
3737

38+
def to_bytes(self: obj) -> bytes:
39+
"""Return the serialized representation of the object."""
40+
return self.memory[self.address : self.address + self.size()]
41+
3842
def _set(self: c_str, value: bytes, index: int = -1) -> None:
3943
"""Set the character at the given index to the given value."""
4044
if index != -1 and index < 0 or index >= self.size():

libdestruct/c/c_uint.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ def get(self: c_uint) -> int:
1919
"""Return the value of the integer."""
2020
return int.from_bytes(self.memory[self.address : self.address + self.size], self.endianness, signed=False)
2121

22+
def to_bytes(self: obj) -> bytes:
23+
"""Return the serialized representation of the object."""
24+
if self._frozen:
25+
return self._frozen_value.to_bytes(self.size, self.endianness, signed=False)
26+
27+
return self.memory[self.address : self.address + self.size]
28+
2229
def _set(self: c_uint, value: int) -> None:
2330
"""Set the value of the integer to the given value."""
2431
self.memory[self.address : self.address + self.size] = value.to_bytes(self.size, self.endianness, signed=False)

libdestruct/c/c_ulong.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ def get(self: c_ulong) -> int:
1919
"""Return the value of the integer."""
2020
return int.from_bytes(self.memory[self.address : self.address + self.size], self.endianness, signed=False)
2121

22+
def to_bytes(self: obj) -> bytes:
23+
"""Return the serialized representation of the object."""
24+
if self._frozen:
25+
return self._frozen_value.to_bytes(self.size, self.endianness, signed=False)
26+
27+
return self.memory[self.address : self.address + self.size]
28+
2229
def _set(self: c_ulong, value: int) -> None:
2330
"""Set the value of the integer to the given value."""
2431
self.memory[self.address : self.address + self.size] = value.to_bytes(self.size, self.endianness, signed=False)

libdestruct/common/obj.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ def get(self: obj) -> object:
6363
def _set(self: obj, value: object) -> None:
6464
"""Set the value of the object to the given value."""
6565

66+
@abstractmethod
67+
def to_bytes(self: obj) -> bytes:
68+
"""Serialize the object to bytes."""
69+
70+
@classmethod
71+
def from_bytes(cls, data: bytes) -> obj:
72+
"""Deserialize the object from bytes."""
73+
item = cls(data, 0)
74+
item.freeze()
75+
return item
76+
6677
def set(self: obj, value: object) -> None:
6778
"""Set the value of the object to the given value."""
6879
if self._frozen:
@@ -108,3 +119,7 @@ def __eq__(self, value: object) -> bool:
108119
return False
109120

110121
return self.get() == value.get()
122+
123+
def __bytes__(self: obj) -> bytes:
124+
"""Return the serialized object."""
125+
return self.to_bytes()

libdestruct/common/ptr.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ def get(self: ptr) -> int:
3030
"""Return the value of the pointer."""
3131
return int.from_bytes(self.memory[self.address : self.address + self.size], self.endianness)
3232

33+
def to_bytes(self: obj) -> bytes:
34+
"""Return the serialized representation of the object."""
35+
if self._frozen:
36+
return self._frozen_value.to_bytes(self.size, self.endianness)
37+
38+
return self.memory[self.address : self.address + self.size]
39+
3340
def _set(self: ptr, value: int) -> None:
3441
"""Set the value of the pointer to the given value."""
3542
self.memory[self.address : self.address + self.size] = value.to_bytes(self.size, self.endianness)

libdestruct/common/struct/struct.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,25 @@
66

77
from __future__ import annotations
88

9+
from typing import TYPE_CHECKING
10+
911
from libdestruct.common.obj import obj
1012

13+
if TYPE_CHECKING:
14+
from libdestruct.common.struct.struct_impl import struct_impl
1115

1216
class struct(obj):
1317
"""A C struct."""
1418

1519
def __init__(self: obj) -> None:
1620
"""Initialize the struct."""
1721
raise RuntimeError("This type should not be directly instantiated.")
22+
23+
@classmethod
24+
def from_bytes(cls: type[struct], data: bytes) -> struct_impl:
25+
"""Create a struct from a serialized representation."""
26+
from libdestruct import inflater
27+
28+
type_inflater = inflater(data)
29+
30+
return type_inflater.inflate_struct(cls, 0)

libdestruct/common/struct/struct_impl.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ def get(self: struct_impl) -> str:
5656
"""Return the value of the struct."""
5757
return f"{self.name}(address={self.address}, size={self.size})"
5858

59+
def to_bytes(self: struct_impl) -> bytes:
60+
"""Return the serialized representation of the struct."""
61+
return b"".join(member.to_bytes() for member in self._members.values())
62+
5963
def _set(self: struct_impl, _: str) -> None:
6064
"""Set the value of the struct to the given value."""
6165
raise RuntimeError("Cannot set the value of a struct.")

0 commit comments

Comments
 (0)