Source code for mendevi.database.serialize
"""Serialize the sql binary data."""
import functools
import struct
import typing
import numpy as np
VECT_DTYPE = np.float32
[docs]
def skip_none(func: typing.Callable) -> typing.Callable:
"""Allow skipping the process of None input."""
@functools.wraps(func)
def decorated_func(arg: object | None) -> object | None:
return None if arg is None else func(arg)
return decorated_func
[docs]
@skip_none
def list_to_binary(vect: list[float]) -> bytes:
r"""Serialize a float vector into binary data.
Bijection of :py:func:`binary_to_list`.
Parameters
----------
vect : arralike
The list of floats
Returns
-------
data : bytes
The serialized float32 list.
Examples
--------
>>> from mendevi.database.serialize import list_to_binary
>>> list_to_binary([0.0, -1.0, 0.123456789])
b'\x00\x00\x00\x00\x00\x00\x80\xbf\xea\xd6\xfc='
>>>
"""
vect = np.asarray(vect, dtype=VECT_DTYPE)
assert vect.ndim == 1, vect.shape
return vect.tobytes("C")
[docs]
@skip_none
def binary_to_list(data: bytes) -> np.ndarray[VECT_DTYPE]:
r"""Deserialize a binary data into a float vector.
Bijection of :py:func:`list_to_binary`.
Parameters
----------
data : bytes
The serialized float 32 list.
Returns
-------
vect : np.ndarray
The list of floats
Examples
--------
>>> from mendevi.database.serialize import binary_to_list
>>> binary_to_list(b'\x00\x00\x00\x00\x00\x00\x80\xbf\xea\xd6\xfc=')
array([ 0. , -1. , 0.12345679], dtype=float32)
>>>
"""
assert isinstance(data, bytes), data.__class__.__name__
assert len(data) % np.dtype(VECT_DTYPE).itemsize == 0, len(data)
return np.frombuffer(data, dtype=VECT_DTYPE, count=len(data)//np.dtype(VECT_DTYPE).itemsize)
[docs]
@skip_none
def tensor_to_binary(tensor: list[list[float]]) -> bytes:
r"""Serialize a 2d array into binary data.
Bijection os :py:func:`binary_to_tensor`.
Parameters
----------
tensor : arraylike
The list of list of float
Returns
-------
data : bytes
The serialized float32 tensor.
Examples
--------
>>> from mendevi.database.serialize import tensor_to_binary
>>> tensor_to_binary([[1.1, 2.2], [3.3, 4.4], [5.5, 6.6]])
b'\x02\x00\x00\x00\xcd\xcc\x8c?\xcd\xcc\x0c@33S@\xcd\xcc\x8c@\x00\x00\xb0@33\xd3@'
>>>
"""
tensor = np.asarray(tensor, dtype=VECT_DTYPE)
assert tensor.ndim == 2, tensor.shape
return struct.pack("I", tensor.shape[1]) + tensor.tobytes("C")
[docs]
@skip_none
def binary_to_tensor(data: bytes) -> np.ndarray[VECT_DTYPE, VECT_DTYPE]:
r"""Serialize a 2d array into binary data.
Bijection os :py:func:`binary_to_tensor`.
Parameters
----------
data : bytes
The serialized float32 tensor.
Returns
-------
tensor : np.ndarray
The list of list of float
Examples
--------
>>> from mendevi.database.serialize import binary_to_tensor
>>> data = b'\x02\x00\x00\x00\xcd\xcc\x8c?\xcd\xcc\x0c@33S@\xcd\xcc\x8c@\x00\x00\xb0@33\xd3@'
>>> binary_to_tensor(data)
array([[1.1, 2.2],
[3.3, 4.4],
[5.5, 6.6]], dtype=float32)
>>>
"""
assert isinstance(data, bytes), data.__class__.__name__
size, data = data[:4], data[4:]
return np.frombuffer(data, dtype=VECT_DTYPE).reshape(-1, struct.unpack("I", size)[0])