Skip to content

Commit e106058

Browse files
authored
Update to v0.0.2
Added `packMessage` and `unpackMessage` for socket communications. Tests are extended.
2 parents 44a69d2 + d28830c commit e106058

File tree

6 files changed

+73
-17
lines changed

6 files changed

+73
-17
lines changed

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FS message packer
1+
Fusion Solutions message packer
22
Copyright (C) 2021 Fusion Solutions KFT <contact@fusionsolutions.io>
33

44
This program is free software: you can redistribute it and/or modify

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[![Python package](https://github.com/FusionSolutions/python-fspacker/actions/workflows/python-package.yml/badge.svg)](https://github.com/FusionSolutions/python-fspacker/actions/workflows/python-package.yml)
2-
# FS Message packer
2+
# Fusion Solutions message packer
33

44
## Introduction
55

fsPacker/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.0.1"
1+
__version__ = "0.0.2"
22
__doc__ = """
33
FS Message Packer v{}
44
Copyright (C) 2021 Fusion Solutions KFT <contact@fusionsolutions.io>
@@ -17,7 +17,7 @@
1717
along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
1818
""".format(__version__)
1919
from .fsPacker import (dump, dumps, load, loads, FSPackerError, UnsupportedType, UnsupportedVersion, InvalidOP,
20-
MaxDictProtection, MaxOPProtection, OutOfData)
20+
MaxDictProtection, MaxOPProtection, OutOfData, packMessage, unpackMessage)
2121

2222
__all__ = ("dump", "dumps", "load", "loads", "FSPackerError", "UnsupportedType", "UnsupportedVersion", "InvalidOP",
23-
"MaxDictProtection", "MaxOPProtection", "OutOfData")
23+
"MaxDictProtection", "MaxOPProtection", "OutOfData", "packMessage", "unpackMessage")

fsPacker/__main__.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def setUpClass(self) -> None:
2020
0.0,
2121
0.1,
2222
-0.1,
23+
1.234e+16,
24+
1.234e-16,
2325
"",
2426
"test",
2527
"Ő",
@@ -38,6 +40,7 @@ def test_dumpsAndLoads(self) -> None:
3840
d:Any
3941
for d in self.data:
4042
self.assertEqual(loads(dumps( d )), d)
43+
self.assertTupleEqual(loads(dumps( self.data )), self.data)
4144
self.assertTupleEqual(loads(dumps( (self.data, self.data)) ), (self.data, self.data))
4245
self.assertTupleEqual(loads(dumps( [self.data, self.data] )), (self.data, self.data))
4346
self.assertDictEqual(loads(dumps( {"data":self.data} )), {"data":self.data})
@@ -60,5 +63,34 @@ def test_raises(self) -> None:
6063
d = dumps(list(range(1024)))
6164
with self.assertRaises(MaxDictProtection):
6265
loads(d, maxDictSize=512)
63-
66+
def test_messagePackUnPack(self) -> None:
67+
indicatorLength:int
68+
messageLength:int
69+
d:bytes = dumps(self.data)
70+
packedMessage:bytes = packMessage(d)
71+
indicatorLength, messageLength = unpackMessage(packedMessage)
72+
self.assertEqual(indicatorLength, 1)
73+
self.assertEqual(messageLength, len(d))
74+
self.assertEqual(packedMessage[indicatorLength:], d)
75+
#
76+
packedMessage = packMessage(b"\x00"*0xFC)
77+
indicatorLength, messageLength = unpackMessage(packedMessage)
78+
self.assertEqual(indicatorLength, 1)
79+
self.assertEqual(messageLength, 0xFC)
80+
#
81+
packedMessage = packMessage(b"\x00"*0xFD)
82+
indicatorLength, messageLength = unpackMessage(packedMessage)
83+
self.assertEqual(indicatorLength, 3)
84+
self.assertEqual(messageLength, 0xFD)
85+
#
86+
packedMessage = packMessage(b"\x00"*0xFFFF)
87+
indicatorLength, messageLength = unpackMessage(packedMessage)
88+
self.assertEqual(indicatorLength, 3)
89+
self.assertEqual(messageLength, 0xFFFF)
90+
#
91+
packedMessage = packMessage(b"\x00"*0xFFFFFF)
92+
indicatorLength, messageLength = unpackMessage(packedMessage)
93+
self.assertEqual(indicatorLength, 4)
94+
self.assertEqual(messageLength, 0xFFFFFF)
95+
#
6496
unittest.main(verbosity=2)

fsPacker/fsPacker.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from __future__ import annotations
33
from io import BytesIO
44
from math import ceil
5-
from typing import Any, Union, IO
5+
from typing import Dict, Any, List, Tuple, IO
66
# Third party modules
77
# Local modules
88
# Program
@@ -41,6 +41,30 @@ class MaxOPProtection(FSPackerError): pass
4141

4242
class OutOfData(FSPackerError): pass
4343

44+
def packMessage(message:bytes) -> bytes:
45+
d:int = len(message)
46+
if d < 0xFD:
47+
return d.to_bytes(1, VAR_ENDIANNESS) + message
48+
elif d <= 0xFFFF:
49+
return b"\xFD" + d.to_bytes(2, VAR_ENDIANNESS) + message
50+
elif d <= 0xFFFFFF:
51+
return b"\xFE" + d.to_bytes(3, VAR_ENDIANNESS) + message
52+
elif d <= 0xFFFFFFFF:
53+
return b"\xFF" + d.to_bytes(4, VAR_ENDIANNESS) + message
54+
raise RuntimeError("Too big data to pack")
55+
56+
def unpackMessage(buffer:bytes) -> Tuple[int, int]:
57+
d:int = buffer[0]
58+
if d < 0xFD:
59+
return 1, d
60+
elif d == 0xFD:
61+
return 3, int.from_bytes(buffer[1:3], VAR_ENDIANNESS)
62+
elif d == 0xFE:
63+
return 4, int.from_bytes(buffer[1:4], VAR_ENDIANNESS)
64+
elif d == 0xFF:
65+
return 5, int.from_bytes(buffer[1:5], VAR_ENDIANNESS)
66+
return 0, 0
67+
4468
def _create_vint(d:int) -> bytes:
4569
if d < 0xEC:
4670
return d.to_bytes(1, VAR_ENDIANNESS)
@@ -52,18 +76,18 @@ def _create_vint(d:int) -> bytes:
5276
return b"\xEE" + d.to_bytes(8, VAR_ENDIANNESS)
5377

5478
class FSPacker:
79+
def __init__(self) -> None:
80+
self.dictCounter:int = 0
81+
self.dictByKey:Dict[Any, int] = {}
82+
self.dictBuffer:BytesIO = BytesIO()
83+
self.opBuffer:BytesIO = BytesIO()
5584
@classmethod
5685
def dump(self, data:Any, fp:IO[bytes]) -> None:
5786
fp.write( self()._parse(data) )
5887
return
5988
@classmethod
6089
def dumps(self, data:Any) -> bytes:
6190
return self()._parse(data)
62-
def __init__(self):
63-
self.dictCounter:int = 0
64-
self.dictByKey:dict = {}
65-
self.dictBuffer:BytesIO = BytesIO()
66-
self.opBuffer:BytesIO = BytesIO()
6791
def _parse(self, data:Any) -> bytes:
6892
self._dump(data)
6993
return VAR_VERSION + _create_vint(len(self.dictByKey)) + self.dictBuffer.getbuffer() + self.opBuffer.getbuffer()
@@ -149,15 +173,15 @@ def _register(self, k:Any) -> int:
149173
self.dictCounter += 1
150174
return self.dictByKey[k]
151175

152-
class FSUnPacker:
176+
class FSUnpacker:
153177
@classmethod
154178
def load(self, data:IO[bytes], maxDictSize:int=0, maxOPSize:int=0) -> Any:
155179
return self(BytesIO(data.read()), maxDictSize, maxOPSize)._parse()
156180
@classmethod
157181
def loads(self, data:bytes, maxDictSize:int=0, maxOPSize:int=0) -> Any:
158182
return self(BytesIO(data), maxDictSize, maxOPSize)._parse()
159183
def __init__(self, buffer:BytesIO, maxDictSize:int=0, maxOPSize:int=0):
160-
self.dict:list = []
184+
self.dict:List[Any] = []
161185
self.buffer:BytesIO = buffer
162186
self.maxDictSize:int = maxDictSize
163187
self.maxOPSize:int = maxOPSize
@@ -246,5 +270,5 @@ def _loads(self) -> Any:
246270

247271
dump = FSPacker.dump
248272
dumps = FSPacker.dumps
249-
load = FSUnPacker.load
250-
loads = FSUnPacker.loads
273+
load = FSUnpacker.load
274+
loads = FSUnpacker.loads

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
setup(
1212
name = "python-fspacker",
1313
version = fsPacker.__version__,
14-
description = "FS message packer",
14+
description = "Fusion Solutions message packer",
1515
keywords = "message pack packer utility fusion solutions fusionsolutions",
1616
author = "Andor `iFA88` Rajci - Fusions Solutions KFT",
1717
author_email = "ifa@fusionsolutions.io",

0 commit comments

Comments
 (0)