Skip to content

Commit 18d32bb

Browse files
ptupitsynisapego
authored andcommitted
IGNITE-14057 Support big-endian systems
Fix primitives decoding on big-endian architectures. This closes #7
1 parent c746329 commit 18d32bb

6 files changed

Lines changed: 47 additions & 12 deletions

File tree

pyignite/api/binary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def get_binary_type(
8686
if result.status != 0:
8787
return result
8888
result.value = {
89-
'type_exists': response.type_exists
89+
'type_exists': Bool.to_python(response.type_exists)
9090
}
9191
if hasattr(response, 'body'):
9292
result.value.update(body_struct.to_python(response.body))

pyignite/datatypes/internal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class Struct:
204204

205205
def parse(
206206
self, client: 'Client'
207-
) -> Tuple[ctypes.BigEndianStructure, bytes]:
207+
) -> Tuple[ctypes.LittleEndianStructure, bytes]:
208208
buffer = b''
209209
fields = []
210210
values = {}

pyignite/datatypes/primitive.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# limitations under the License.
1515

1616
import ctypes
17+
import struct
18+
import sys
1719

1820
from pyignite.constants import *
1921
from .base import IgniteDataType
@@ -48,50 +50,70 @@ class Primitive(IgniteDataType):
4850
def parse(cls, client: 'Client'):
4951
return cls.c_type, client.recv(ctypes.sizeof(cls.c_type))
5052

51-
@staticmethod
52-
def to_python(ctype_object, *args, **kwargs):
53-
return ctype_object
54-
5553
@classmethod
56-
def from_python(cls, value):
57-
return bytes(cls.c_type(value))
54+
def to_python(cls, ctype_object, *args, **kwargs):
55+
return ctype_object
5856

5957

6058
class Byte(Primitive):
6159
_type_name = NAME_BYTE
6260
_type_id = TYPE_BYTE
6361
c_type = ctypes.c_byte
6462

63+
@classmethod
64+
def from_python(cls, value):
65+
return struct.pack("<b", value)
66+
6567

6668
class Short(Primitive):
6769
_type_name = NAME_SHORT
6870
_type_id = TYPE_SHORT
6971
c_type = ctypes.c_short
7072

73+
@classmethod
74+
def from_python(cls, value):
75+
return struct.pack("<h", value)
76+
7177

7278
class Int(Primitive):
7379
_type_name = NAME_INT
7480
_type_id = TYPE_INT
7581
c_type = ctypes.c_int
7682

83+
@classmethod
84+
def from_python(cls, value):
85+
return struct.pack("<i", value)
86+
7787

7888
class Long(Primitive):
7989
_type_name = NAME_LONG
8090
_type_id = TYPE_LONG
8191
c_type = ctypes.c_longlong
8292

93+
@classmethod
94+
def from_python(cls, value):
95+
return struct.pack("<q", value)
96+
8397

8498
class Float(Primitive):
8599
_type_name = NAME_FLOAT
86100
_type_id = TYPE_FLOAT
87101
c_type = ctypes.c_float
88102

103+
@classmethod
104+
def from_python(cls, value):
105+
return struct.pack("<f", value)
106+
89107

90108
class Double(Primitive):
91109
_type_name = NAME_DOUBLE
92110
_type_id = TYPE_DOUBLE
93111
c_type = ctypes.c_double
94112

113+
@classmethod
114+
def from_python(cls, value):
115+
return struct.pack("<d", value)
116+
95117

96118
class Char(Primitive):
97119
_type_name = NAME_CHAR
@@ -122,4 +144,12 @@ def from_python(cls, value):
122144
class Bool(Primitive):
123145
_type_name = NAME_BOOLEAN
124146
_type_id = TYPE_BOOLEAN
125-
c_type = ctypes.c_bool
147+
c_type = ctypes.c_byte # Use c_byte because c_bool throws endianness conversion error on BE systems.
148+
149+
@classmethod
150+
def to_python(cls, ctype_object, *args, **kwargs):
151+
return ctype_object != 0
152+
153+
@classmethod
154+
def from_python(cls, value):
155+
return struct.pack("<b", 1 if value else 0)

pyignite/datatypes/primitive_objects.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,16 @@ def from_python(cls, value):
207207
class BoolObject(DataObject):
208208
_type_name = NAME_BOOLEAN
209209
_type_id = TYPE_BOOLEAN
210-
c_type = ctypes.c_bool
210+
c_type = ctypes.c_byte # Use c_byte because c_bool throws endianness conversion error on BE systems.
211211
type_code = TC_BOOL
212212
pythonic = bool
213213
default = False
214214

215215
@staticmethod
216216
def hashcode(value: bool, *args, **kwargs) -> int:
217217
return 1231 if value else 1237
218+
219+
@classmethod
220+
def to_python(cls, ctype_object, *args, **kwargs):
221+
return ctype_object.value != 0
222+

pyignite/queries/response.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def _parse_success(self, conn: Connection, buffer: bytearray, fields: list):
179179
)
180180
fields += body_class._fields_ + [
181181
('data', data_class),
182-
('more', ctypes.c_bool),
182+
('more', ctypes.c_byte),
183183
]
184184

185185
def _create_parse_result(self, conn: Connection, header_class, fields: list, buffer: bytearray):

tests/test_binary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ class OuterType(
225225

226226
def test_add_schema_to_binary_object(client):
227227

228-
migrate_cache = client.create_cache('migrate_binary')
228+
migrate_cache = client.get_or_create_cache('migrate_binary')
229229

230230
class MyBinaryType(
231231
metaclass=GenericObjectMeta,

0 commit comments

Comments
 (0)