Skip to content

Commit

Permalink
Implement msgspec Encoding and Decoding Support
Browse files Browse the repository at this point in the history
  • Loading branch information
rsmb7z committed Dec 4, 2023
1 parent f508f41 commit 4800b7d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
8 changes: 5 additions & 3 deletions nautilus_trader/config/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from nautilus_trader.config.validation import PositiveInt
from nautilus_trader.core.correctness import PyCondition
from nautilus_trader.persistence.catalog.parquet import ParquetDataCatalog
from nautilus_trader.serialization.base import msgspec_decoding_hook
from nautilus_trader.serialization.base import msgspec_encoding_hook


def resolve_path(path: str) -> type:
Expand Down Expand Up @@ -105,7 +107,7 @@ def json(self) -> bytes:
bytes
"""
return msgspec.json.encode(self)
return msgspec.json.encode(self, enc_hook=msgspec_encoding_hook)

@classmethod
def parse(cls, raw: bytes) -> Any:
Expand All @@ -124,7 +126,7 @@ def parse(cls, raw: bytes) -> Any:
Any
"""
return msgspec.json.decode(raw, type=cls)
return msgspec.json.decode(raw, type=cls, dec_hook=msgspec_decoding_hook)

def validate(self) -> bool:
"""
Expand All @@ -135,7 +137,7 @@ def validate(self) -> bool:
bool
"""
return bool(msgspec.json.decode(self.json(), type=self.__class__))
return bool(self.parse(self.json()))

def __hash__(self):
return generate_structure_hash(self.dict())
Expand Down
27 changes: 27 additions & 0 deletions nautilus_trader/serialization/base.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ from nautilus_trader.model.instruments.futures_contract cimport FuturesContract
from nautilus_trader.model.instruments.options_contract cimport OptionsContract
from nautilus_trader.model.instruments.synthetic cimport SyntheticInstrument

from nautilus_trader.model.identifiers import Identifier
from nautilus_trader.model.identifiers import InstrumentId


# Default mappings for Nautilus objects
_OBJECT_TO_DICT_MAP: dict[str, Callable[[None], dict]] = {
Expand Down Expand Up @@ -267,3 +270,27 @@ cdef class Serializer:
cpdef object deserialize(self, bytes obj_bytes):
"""Abstract method (implement in subclass)."""
raise NotImplementedError("method must be implemented in the subclass") # pragma: no cover


def msgspec_encoding_hook(obj: Any):
if isinstance(obj, Identifier):
return str(obj)
else:
obj_to_dict = _OBJECT_TO_DICT_MAP.get(type(obj).__name__)
if obj_to_dict:
return obj_to_dict(obj)
else:
raise NotImplementedError


def msgspec_decoding_hook(obj_type: type, obj: Any) -> Any:
if issubclass(obj_type, InstrumentId):
return InstrumentId.from_str(obj)
elif issubclass(obj_type, Identifier):
return obj_type(obj)
else:
obj_from_dict = _OBJECT_FROM_DICT_MAP.get(obj_type.__name__)
if obj_from_dict and isinstance(obj, dict):
return obj_from_dict(obj)
else:
raise NotImplementedError

0 comments on commit 4800b7d

Please sign in to comment.