Source code for udsoncan.common.DidCodec

__all__ = [
    'DidCodec',
    'AsciiCodec'
]

import struct

from typing import Optional, Any


[docs]class DidCodec: """ This class defines how to encode/decode a Data Identifier value to/from a binary payload. One should extend this class and override the ``encode``, ``decode``, ``__len__`` methods as they will be used to generate or parse binary payloads. - ``encode`` Must receive any Python object and must return a bytes payload - ``decode`` Must receive a bytes payload and may return any Python object - ``__len__`` Must return the length of the bytes payload or raise a ``DidCodec.ReadAllRemainingData`` to read the whole payload. Reading the whole payload is not a feature proposed by ISO-14229. If a data can be processed by a pack string, then this class may be used as is, without being extended. :param packstr: A pack string used with struct.pack / struct.unpack. :type packstr: string """ class ReadAllRemainingData(Exception): pass packstr: Optional[str] def __init__(self, packstr: Optional[str] = None): self.packstr = packstr def encode(self, *did_value: Any) -> bytes: if self.packstr is None: raise NotImplementedError('Cannot encode DID to binary payload. Codec has no "encode" implementation') return struct.pack(self.packstr, *did_value) def decode(self, did_payload: bytes) -> Any: if self.packstr is None: raise NotImplementedError('Cannot decode DID from binary payload. Codec has no "decode" implementation') return struct.unpack(self.packstr, did_payload) # Must tell the size of the payload encoded or expected for decoding def __len__(self) -> int: if self.packstr is None: raise NotImplementedError('Cannot tell the payload size. Codec has no "__len__" implementation') return struct.calcsize(self.packstr)
class AsciiCodec(DidCodec): string_len: int def __init__(self, string_len: int): self.string_len = string_len def encode(self, string_ascii: Any) -> bytes: # type: ignore if not isinstance(string_ascii, str): raise ValueError("AsciiCodec requires a string for encoding") if len(string_ascii) != self.string_len: raise ValueError('String must be %d long' % self.string_len) return string_ascii.encode('ascii') def decode(self, string_bin: bytes) -> Any: string_ascii = string_bin.decode('ascii') if len(string_ascii) != self.string_len: raise ValueError('Trying to decode a string of %d bytes but codec expects %d bytes' % (len(string_ascii), self.string_len)) return string_ascii def __len__(self) -> int: return self.string_len