{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "499860ca-54b4-43b7-b82a-8fafe158afe0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dataclasses import dataclass\n",
    "from dataclasses import field\n",
    "from struct import Struct\n",
    "from math import sqrt\n",
    "from collections import namedtuple\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "41b2b84f-7935-4620-857f-cf0c217fd256",
   "metadata": {},
   "outputs": [],
   "source": [
    "@dataclass\n",
    "class vecf:\n",
    "    x: float\n",
    "    y: float\n",
    "    z: float\n",
    "    packer: Struct = field(init=False, repr=False, default=Struct( \"fff\" ))\n",
    "    def normalize(self):\n",
    "        return sqrt(self.x*self.x + self.y*self.y + self.z*self.z)\n",
    "\n",
    "    def pack(self):\n",
    "        return self.packer.pack(*self.to_list())\n",
    "\n",
    "    def unpack(self, pkt):\n",
    "        return self.packer.unpack(pkt)\n",
    "\n",
    "    def to_list(self):\n",
    "        ret = []\n",
    "        for a in self.__dict__.values():\n",
    "            if isinstance(a,float) or isinstance(a,int):\n",
    "                ret.append(a)\n",
    "            else:\n",
    "                for i in a.to_list():\n",
    "                    ret.append(i)\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5542ffee-6568-4be6-b6a5-1ed06d9fea17",
   "metadata": {},
   "outputs": [],
   "source": [
    "@dataclass\n",
    "class imu:\n",
    "    id: int # something\n",
    "    accel: vecf\n",
    "    gyro: vecf\n",
    "    mag: vecf\n",
    "    pressure: float\n",
    "    temperature: float\n",
    "    timestamp: int\n",
    "    packer: Struct = field(init=False, repr=False, default=Struct( \"BfffffffffffI\" ))\n",
    "\n",
    "    def pack(self):\n",
    "        data = self.to_list()\n",
    "        print(data)\n",
    "        return self.packer.pack(*data)\n",
    "\n",
    "    def unpack(self, pkt):\n",
    "        return self.packer.unpack(pkt)\n",
    "\n",
    "    def to_list(self):\n",
    "        ret = []\n",
    "        for a in self.__dict__.values():\n",
    "            if isinstance(a,float) or isinstance(a,int):\n",
    "                ret.append(a)\n",
    "            else:\n",
    "                for i in a.to_list():\n",
    "                    ret.append(i)\n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6e860ce2-f698-43d6-ad30-c6686f291509",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vecf(x=1, y=2, z=3)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[1, 2, 3]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = vecf(1,2,3)\n",
    "print(v)\n",
    "\n",
    "import dataclasses\n",
    "f = dataclasses.fields(v)[0]\n",
    "l = []\n",
    "for a in v.__dict__.values():\n",
    "    if isinstance(a,float) or isinstance(a,int):\n",
    "        l.append(a)\n",
    "    else:\n",
    "        for i in a.to_list():\n",
    "            l.append(i)\n",
    "\n",
    "l\n",
    "# f.values()\n",
    "# for ff in f:\n",
    "    # print(ff)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c28d1237-cc1b-47af-8e08-dcccce811652",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v.to_list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1ff55c3e-c700-4d2d-a18b-0dd22c1dcaef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b'\\x00\\x00\\x80?\\x00\\x00\\x00@\\x00\\x00@@'\n"
     ]
    }
   ],
   "source": [
    "pkt = v.pack()\n",
    "print(pkt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2e221ecc-1801-44f3-a13b-99dead25f3a2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vecf(x=1, y=2, z=3)\n"
     ]
    }
   ],
   "source": [
    "m = v.unpack(pkt)\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "9ad4dc05-d684-4900-a428-ee8311ab37e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "imu(id=1, accel=vecf(x=1, y=2, z=3), gyro=vecf(x=4, y=5, z=6), mag=vecf(x=7, y=8, z=9), pressure=1, temperature=2, timestamp=3)\n"
     ]
    }
   ],
   "source": [
    "i = imu(1,vecf(1,2,3),vecf(4,5,6),vecf(7,8,9),1,2,3)\n",
    "print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e0e6be3c-0041-473e-8cf6-8283389e2f52",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]\n",
      "b'\\x01\\x00\\x00\\x00\\x00\\x00\\x80?\\x00\\x00\\x00@\\x00\\x00@@\\x00\\x00\\x80@\\x00\\x00\\xa0@\\x00\\x00\\xc0@\\x00\\x00\\xe0@\\x00\\x00\\x00A\\x00\\x00\\x10A\\x00\\x00\\x80?\\x00\\x00\\x00@\\x03\\x00\\x00\\x00'\n"
     ]
    }
   ],
   "source": [
    "pkt = i.pack()\n",
    "print(pkt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dcfffe69-d082-45a1-9f4e-54c69e0acd1d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f49efe6-e12c-4f2e-a28c-534391f41144",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "ba4c5e16-0e10-44c7-bf87-2de5f507381e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Base:\n",
    "    def flatten(self, data):\n",
    "        \"\"\"\n",
    "        (0, (1, 2, 3), (4, 5, 6)) -> (0, 1, 2, 3, 4, 5, 6)\n",
    "        \"\"\"\n",
    "        if isinstance(data, tuple):\n",
    "            for x in data:\n",
    "                yield from self.flatten(x)\n",
    "        else:\n",
    "            yield data\n",
    "            \n",
    "    def serialize(self):\n",
    "        return tuple(self.flatten(dataclasses.astuple(self)))\n",
    "        \n",
    "@dataclass(frozen=True)\n",
    "class vec_t(Base):\n",
    "    x: float\n",
    "    y: float\n",
    "    z: float\n",
    "    \n",
    "    def __yivo__(self):\n",
    "        return (\"fff\", 12, vec_t) # (struct format, number bytes)\n",
    "\n",
    "@dataclass(frozen=True)\n",
    "class twist_t(Base):\n",
    "    linear: vec_t\n",
    "    angular: vec_t\n",
    "    \n",
    "    def __yivo__(self):\n",
    "        return (\"3f3f\", 120, twist_t) # (struct format, number bytes)\n",
    "\n",
    "    # def __init__(self,lx,ly,lz,ax,ay,az):\n",
    "    #     object.__setattr__(self, \"linear\", vec_t(lx,ly,lz))\n",
    "    #     object.__setattr__(self, \"angular\", vec_t(ax,ay,az))\n",
    "\n",
    "def fmt(a):\n",
    "    return a.__yivo__()[0]\n",
    "\n",
    "def sizeof(a):\n",
    "    return a.__yivo__()[1]\n",
    "\n",
    "def cls(a):\n",
    "    return a.__yivo__()[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "5762769b-8278-4d2e-847c-44b0097263fb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "twist_t(linear=vec_t(x=0, y=1, z=2), angular=vec_t(x=3, y=4, z=5))"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t=twist_t(vec_t(0,1,2),vec_t(3,4,5))\n",
    "t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "cbb9f312-1afd-4a4b-9ffe-8b049aca4ff5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 1, 2, 3, 4, 5)"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t.serialize()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "81e0836c-ccf9-4734-b7de-3299db80fe22",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((0, 1, 2), (3, 4, 5))"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataclasses.astuple(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "3d6e25f6-6ba8-4d34-8852-8ba948fa5d1a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t2=twist_t(vec_t(0,1,2),vec_t(3,4,5))\n",
    "\n",
    "t == t2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "b8741f3b-0b08-4d5d-9336-f7d5dd63256b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'3f3f'"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fmt(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "4aff82d9-54d0-4023-b5f7-109a1ccd56ee",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "120"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sizeof(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "70074502-0615-4ba2-b0c6-dd16fbd90f97",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "twist_t(linear=1, angular=2)"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x=cls(t)\n",
    "x(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "473e7ff8-8662-41aa-a4ee-fcd0c853b32b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.vec_t"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = vec_t(1,2,3)\n",
    "cls(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "ae749406-de0c-49a0-acbb-6512e3c62c7d",
   "metadata": {},
   "outputs": [
    {
     "ename": "FrozenInstanceError",
     "evalue": "cannot assign to field 'linear'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mFrozenInstanceError\u001b[0m                       Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[110], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlinear\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m4\u001b[39m\n",
      "File \u001b[0;32m<string>:4\u001b[0m, in \u001b[0;36m__setattr__\u001b[0;34m(self, name, value)\u001b[0m\n",
      "\u001b[0;31mFrozenInstanceError\u001b[0m: cannot assign to field 'linear'"
     ]
    }
   ],
   "source": [
    "t.linear = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "id": "4911f017-2f19-4a62-9669-6a75b5ed36e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['__annotations__',\n",
       " '__class__',\n",
       " '__dataclass_fields__',\n",
       " '__dataclass_params__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__getattribute__',\n",
       " '__getstate__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__match_args__',\n",
       " '__module__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " '__weakref__',\n",
       " '__yivo__',\n",
       " 'angular',\n",
       " 'flatten',\n",
       " 'linear',\n",
       " 'serialize']"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "f74439ca-76cb-4910-86dc-0a8f6e1778b2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('3f3f', 120, __main__.twist_t)"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t.__yivo__()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f10c9b9-dac3-4685-acad-7b16123186d9",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}