Skip to content

Commit

Permalink
make crc more dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
spacemanspiff2007 committed Oct 24, 2024
1 parent 356ac5e commit 7eb3961
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/smllib/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ class SmlStreamReader:
def __init__(self, build_ctx: Optional[CTX_HINT] = None, crc: Literal['kermit', 'x25'] = 'x25') -> None:
self.bytes: bytes = b''
self.build_ctx: CTX_HINT = build_ctx if build_ctx is not None else create_context()
self.crc_func: Callable[[Union[memoryview, bytes]], int] = {
'x25': crc_module.x25.get_crc, 'kermit': crc_module.kermit.get_crc}[crc]

# This makes it easy to patch additional crc functions to the module
try:
self.crc_func: Callable[[Union[memoryview, bytes]], int] = getattr(crc_module, crc).get_crc
except AttributeError:
available = [f'"{n:s}"' for n in dir(crc_module) if not n.startswith('_')]
raise ValueError(f'Unsupported CRC "{crc}"! Available: {", ".join(available):s}')

def add(self, _bytes: bytes) -> None:
self.bytes += _bytes
Expand Down
40 changes: 40 additions & 0 deletions tests/test_crc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import inspect
import typing
from binascii import a2b_hex
from typing import Union

import pytest

from smllib import SmlStreamReader
from smllib import crc as crc_module
from smllib.crc.x25 import get_crc as x25_get_crc


Expand All @@ -17,3 +22,38 @@ def test_crc_x25(msg) -> None:
crc_msg = f'{_msg[-3]:02x}{_msg[-2]:02x}'
crc_calc = f'{x25_get_crc(_msg[:-4]):04x}'
assert crc_msg == crc_calc


def _get_signature() -> inspect.Signature:
return inspect.Signature(
parameters=[
inspect.Parameter('buf', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Union[memoryview, bytes])
],
return_annotation=int
)


@pytest.mark.parametrize('name', (n for n in dir(crc_module) if not n.startswith('_')))
def test_signature_crc_funcs(name: str) -> None:
crc_impl = getattr(crc_module, name)
crc_sig = inspect.signature(crc_impl.get_crc)
assert crc_sig == _get_signature()


def test_type_hint_reader() -> None:
signature = _get_signature()

a = SmlStreamReader()
hint = typing.get_type_hints(a.crc_func)
assert hint.pop('return') is signature.return_annotation

assert hint
for name in hint:
assert hint[name] == signature.parameters[name].annotation


def test_invalid_crc_name() -> None:

with pytest.raises(ValueError) as e:
SmlStreamReader(crc='asfd')
assert str(e.value) == 'Unsupported CRC "asfd"! Available: "kermit", "x25"'

0 comments on commit 7eb3961

Please sign in to comment.