Skip to content

Commit

Permalink
Add method to serialise records to a dict (#24)
Browse files Browse the repository at this point in the history
Co-authored-by: Erik Schamper <[email protected]>
  • Loading branch information
idem-s1n and Schamper authored Sep 4, 2023
1 parent f477082 commit af92e25
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
30 changes: 29 additions & 1 deletion dissect/esedb/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import struct
from binascii import hexlify
from functools import lru_cache
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any, Iterator, Optional

from dissect.util.xmemoryview import xmemoryview

Expand Down Expand Up @@ -50,6 +50,9 @@ def get(self, attr: str, raw: bool = False) -> RecordValue:
column = self._table.column(attr)
return self._data.get(column, raw)

def as_dict(self, raw: bool = False) -> dict[str, RecordValue]:
return self._data.as_dict(raw)

def __getitem__(self, attr: str) -> RecordValue:
return self.get(attr)

Expand Down Expand Up @@ -183,6 +186,31 @@ def get(self, column: Column, raw: bool = False) -> RecordValue:
if value is not None:
return self._parse_value(column, value, tag_field)

def as_dict(self, raw: bool = False) -> dict[str, RecordValue]:
"""Serialize the record as a dictionary."""
obj = {}

def _iter_column_id() -> Iterator[Column]:
# Fixed
yield from range(1, self._last_fixed_id + 1)

# Variable
yield from range(128, self._last_variable_id + 1)

# Tagged
for idx in range(self._tagged_data_count):
yield self._get_tag_field(idx).identifier

for column_id in _iter_column_id():
column = self.table._column_id_map[column_id]

try:
obj[column.name] = self.get(column, raw)
except Exception as e:
obj[column.name] = f"!ERROR! {e}"

return obj

def _parse_value(self, column: Column, value: bytes, tag_field: TagField = None) -> RecordValue:
"""Parse the raw value into the appropriate type.
Expand Down
40 changes: 40 additions & 0 deletions tests/test_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import BinaryIO

from dissect.esedb.esedb import EseDB


def test_as_dict(basic_db: BinaryIO):
db = EseDB(basic_db)
table = db.table("basic")

records = list(table.records())
assert len(records) == 2

assert [r.as_dict() for r in records] == [
{
"Id": 1,
"Bit": False,
"UnsignedByte": 213,
"Short": -1337,
"Long": -13371337,
"Currency": 1337133713371337,
"IEEESingle": 1.0,
"IEEEDouble": 13371337.13371337,
"DateTime": 4675210852477960192,
"UnsignedLong": 13371337,
"LongLong": -13371337,
"GUID": "3f360af1-6766-46dc-9af2-0dacf295c2a1",
"UnsignedShort": 1337,
},
{
"Id": 2,
"Bit": True,
"UnsignedByte": 255,
"Short": 1339,
"Long": 13391339,
"Currency": -1339133913391339,
"IEEESingle": -2.0,
"IEEEDouble": -13391339.13391339,
"DateTime": -4537072128574357504,
},
]

0 comments on commit af92e25

Please sign in to comment.