|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
| 3 | +import functools |
3 | 4 | from io import BytesIO
|
4 |
| -from typing import TYPE_CHECKING, Any, BinaryIO, Optional, Union |
| 5 | +from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Optional, Union |
5 | 6 |
|
6 | 7 | from dissect.cstruct.exceptions import ArraySizeError
|
7 | 8 |
|
@@ -83,6 +84,31 @@ def read(cls, obj: Union[BinaryIO, bytes]) -> BaseType:
|
83 | 84 |
|
84 | 85 | return cls._read(obj)
|
85 | 86 |
|
| 87 | + def write(cls, stream: BinaryIO, value: Any) -> int: |
| 88 | + """Write a value to a writable file-like object. |
| 89 | +
|
| 90 | + Args: |
| 91 | + stream: File-like objects that supports writing. |
| 92 | + value: Value to write. |
| 93 | +
|
| 94 | + Returns: |
| 95 | + The amount of bytes written. |
| 96 | + """ |
| 97 | + return cls._write(stream, value) |
| 98 | + |
| 99 | + def dumps(cls, value: Any) -> bytes: |
| 100 | + """Dump a value to a byte string. |
| 101 | +
|
| 102 | + Args: |
| 103 | + value: Value to dump. |
| 104 | +
|
| 105 | + Returns: |
| 106 | + The raw bytes of this type. |
| 107 | + """ |
| 108 | + out = BytesIO() |
| 109 | + cls._write(out, value) |
| 110 | + return out.getvalue() |
| 111 | + |
86 | 112 | def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> BaseType:
|
87 | 113 | """Internal function for reading value.
|
88 | 114 |
|
@@ -152,29 +178,33 @@ def _write_0(cls, stream: BinaryIO, array: list[BaseType]) -> int:
|
152 | 178 | return cls._write_array(stream, array + [cls()])
|
153 | 179 |
|
154 | 180 |
|
155 |
| -class BaseType(metaclass=MetaType): |
156 |
| - """Base class for cstruct type classes.""" |
| 181 | +class _overload: |
| 182 | + """Descriptor to use on the ``write`` and ``dumps`` methods on cstruct types. |
157 | 183 |
|
158 |
| - def dumps(self) -> bytes: |
159 |
| - """Dump this value to a byte string. |
| 184 | + Allows for calling these methods on both the type and instance. |
160 | 185 |
|
161 |
| - Returns: |
162 |
| - The raw bytes of this type. |
163 |
| - """ |
164 |
| - out = BytesIO() |
165 |
| - self.__class__._write(out, self) |
166 |
| - return out.getvalue() |
| 186 | + Example: |
| 187 | + >>> int32.dumps(123) |
| 188 | + b'\\x7b\\x00\\x00\\x00' |
| 189 | + >>> int32(123).dumps() |
| 190 | + b'\\x7b\\x00\\x00\\x00' |
| 191 | + """ |
167 | 192 |
|
168 |
| - def write(self, stream: BinaryIO) -> int: |
169 |
| - """Write this value to a writable file-like object. |
| 193 | + def __init__(self, func: Callable[[Any], Any]) -> None: |
| 194 | + self.func = func |
170 | 195 |
|
171 |
| - Args: |
172 |
| - fh: File-like objects that supports writing. |
| 196 | + def __get__(self, instance: Optional[BaseType], owner: MetaType) -> Callable[[Any], bytes]: |
| 197 | + if instance is None: |
| 198 | + return functools.partial(self.func, owner) |
| 199 | + else: |
| 200 | + return functools.partial(self.func, instance.__class__, value=instance) |
173 | 201 |
|
174 |
| - Returns: |
175 |
| - The amount of bytes written. |
176 |
| - """ |
177 |
| - return self.__class__._write(stream, self) |
| 202 | + |
| 203 | +class BaseType(metaclass=MetaType): |
| 204 | + """Base class for cstruct type classes.""" |
| 205 | + |
| 206 | + dumps = _overload(MetaType.dumps) |
| 207 | + write = _overload(MetaType.write) |
178 | 208 |
|
179 | 209 |
|
180 | 210 | class ArrayMetaType(MetaType):
|
|
0 commit comments