1515
1616from collections import OrderedDict
1717import ctypes
18- import inspect
18+ from io import SEEK_CUR
1919from typing import Iterable , Dict
2020
2121from pyignite .constants import *
@@ -71,19 +71,20 @@ def build_header(cls):
7171
7272 @classmethod
7373 def parse (cls , stream ):
74- buffer = stream .read ( ctypes .sizeof (ctypes .c_byte ) )
74+ init_pos , type_len = stream .tell (), ctypes .sizeof (ctypes .c_byte )
7575
76+ buffer = stream .read (type_len )
7677 if buffer == TC_NULL :
77- return Null .build_c_type (), buffer
78+ return Null .build_c_type (), ( init_pos , type_len )
7879
7980 header_class = cls .build_header ()
80- buffer += stream . read ( ctypes .sizeof (header_class ) - len ( buffer ) )
81- header = header_class .from_buffer_copy (buffer )
82- fields = []
81+ header_len = ctypes .sizeof (header_class )
82+ header = header_class .from_buffer_copy (stream . mem_view ( init_pos , header_len ) )
83+ stream . seek ( init_pos + header_len )
8384
85+ fields = []
8486 for i in range (header .length ):
85- c_type , buffer_fragment = AnyDataObject .parse (stream )
86- buffer += buffer_fragment
87+ c_type , _ = AnyDataObject .parse (stream )
8788 fields .append (('element_{}' .format (i ), c_type ))
8889
8990 final_class = type (
@@ -94,7 +95,9 @@ def parse(cls, stream):
9495 '_fields_' : fields ,
9596 }
9697 )
97- return final_class , buffer
98+
99+ stream .seek (init_pos + ctypes .sizeof (final_class ))
100+ return final_class , (init_pos , stream .tell () - init_pos )
98101
99102 @classmethod
100103 def to_python (cls , ctype_object , * args , ** kwargs ):
@@ -164,14 +167,16 @@ def build_header(cls):
164167
165168 @classmethod
166169 def parse (cls , stream ):
167- buffer = stream .read ( ctypes .sizeof (ctypes .c_byte ) )
170+ init_pos , type_len = stream .tell (), ctypes .sizeof (ctypes .c_byte )
168171
172+ buffer = stream .read (type_len )
169173 if buffer == TC_NULL :
170- return Null .build_c_type (), buffer
174+ return Null .build_c_type (), ( init_pos , type_len )
171175
172176 header_class = cls .build_header ()
173- buffer += stream .read (ctypes .sizeof (header_class ) - len (buffer ))
174- header = header_class .from_buffer_copy (buffer )
177+ header_len = ctypes .sizeof (header_class )
178+ header = header_class .from_buffer_copy (stream .mem_view (init_pos , header_len ))
179+ stream .seek (init_pos + header_len )
175180
176181 final_class = type (
177182 cls .__name__ ,
@@ -184,10 +189,9 @@ def parse(cls, stream):
184189 ],
185190 }
186191 )
187- buffer += stream .read (
188- ctypes .sizeof (final_class ) - ctypes .sizeof (header_class )
189- )
190- return final_class , buffer
192+
193+ stream .seek (init_pos + ctypes .sizeof (final_class ))
194+ return final_class , (init_pos , stream .tell () - init_pos )
191195
192196 @classmethod
193197 def to_python (cls , ctype_object , * args , ** kwargs ):
@@ -262,19 +266,21 @@ def build_header(cls):
262266
263267 @classmethod
264268 def parse (cls , stream ):
265- buffer = stream .read ( ctypes .sizeof (ctypes .c_byte ) )
269+ init_pos , type_len = stream .tell (), ctypes .sizeof (ctypes .c_byte )
266270
267- if buffer == TC_NULL :
268- return Null .build_c_type (), buffer
271+ type_ = stream .mem_view (init_pos , type_len )
272+ if type_ == TC_NULL :
273+ stream .seek (type_len , SEEK_CUR )
274+ return Null .build_c_type (), (init_pos , type_len )
269275
270276 header_class = cls .build_header ()
271- buffer += stream . read ( ctypes .sizeof (header_class ) - len ( buffer ) )
272- header = header_class .from_buffer_copy (buffer )
273- fields = []
277+ header_len = ctypes .sizeof (header_class )
278+ header = header_class .from_buffer_copy (stream . mem_view ( init_pos , header_len ) )
279+ stream . seek ( init_pos + header_len )
274280
281+ fields = []
275282 for i in range (header .length ):
276- c_type , buffer_fragment = AnyDataObject .parse (stream )
277- buffer += buffer_fragment
283+ c_type , _ = AnyDataObject .parse (stream )
278284 fields .append (('element_{}' .format (i ), c_type ))
279285
280286 final_class = type (
@@ -285,7 +291,7 @@ def parse(cls, stream):
285291 '_fields_' : fields ,
286292 }
287293 )
288- return final_class , buffer
294+ return final_class , ( init_pos , stream . tell () - init_pos )
289295
290296 @classmethod
291297 def to_python (cls , ctype_object , * args , ** kwargs ):
@@ -360,19 +366,20 @@ def build_header(cls):
360366
361367 @classmethod
362368 def parse (cls , stream ):
363- buffer = stream .read ( ctypes .sizeof (ctypes .c_byte ) )
369+ init_pos , type_len = stream .tell (), ctypes .sizeof (ctypes .c_byte )
364370
371+ buffer = stream .read (type_len )
365372 if buffer == TC_NULL :
366- return Null .build_c_type (), buffer
373+ return Null .build_c_type (), ( init_pos , type_len )
367374
368375 header_class = cls .build_header ()
369- buffer += stream . read ( ctypes .sizeof (header_class ) - len ( buffer ) )
370- header = header_class .from_buffer_copy (buffer )
371- fields = []
376+ header_len = ctypes .sizeof (header_class )
377+ header = header_class .from_buffer_copy (stream . mem_view ( init_pos , header_len ) )
378+ stream . seek ( init_pos + header_len )
372379
380+ fields = []
373381 for i in range (header .length << 1 ):
374- c_type , buffer_fragment = AnyDataObject .parse (stream )
375- buffer += buffer_fragment
382+ c_type , _ = AnyDataObject .parse (stream )
376383 fields .append (('element_{}' .format (i ), c_type ))
377384
378385 final_class = type (
@@ -383,7 +390,7 @@ def parse(cls, stream):
383390 '_fields_' : fields ,
384391 }
385392 )
386- return final_class , buffer
393+ return final_class , ( init_pos , stream . tell () - init_pos )
387394
388395 @classmethod
389396 def to_python (cls , ctype_object , * args , ** kwargs ):
@@ -541,27 +548,30 @@ def schema_type(cls, flags: int):
541548 @classmethod
542549 def parse (cls , stream ):
543550 from pyignite .datatypes import Struct
544- buffer = stream .read (ctypes .sizeof (ctypes .c_byte ))
545551
546- if buffer == TC_NULL :
547- return Null .build_c_type (), buffer
552+ init_pos , type_len = stream .tell (), ctypes .sizeof (ctypes .c_byte )
553+
554+ type_ = stream .mem_view (init_pos , type_len )
555+ if type_ == TC_NULL :
556+ stream .seek (type_len , SEEK_CUR )
557+ return Null .build_c_type (), (init_pos , type_len )
548558
549559 header_class = cls .build_header ()
550- buffer += stream .read (ctypes .sizeof (header_class ) - len (buffer ))
551- header = header_class .from_buffer_copy (buffer )
560+ header_len = ctypes .sizeof (header_class )
561+ header = header_class .from_buffer_copy (stream .mem_view (init_pos , header_len ))
562+ stream .seek (init_pos + header_len )
552563
553564 # ignore full schema, always retrieve fields' types and order
554565 # from complex types registry
555566 data_class = stream .get_dataclass (header )
556567 fields = data_class .schema .items ()
557568 object_fields_struct = Struct (fields )
558- object_fields , object_fields_buffer = object_fields_struct .parse (stream )
559- buffer += object_fields_buffer
569+ object_fields , _ = object_fields_struct .parse (stream )
560570 final_class_fields = [('object_fields' , object_fields )]
561571
562572 if header .flags & cls .HAS_SCHEMA :
563573 schema = cls .schema_type (header .flags ) * len (fields )
564- buffer += stream .read (ctypes .sizeof (schema ))
574+ stream .seek (ctypes .sizeof (schema ), SEEK_CUR )
565575 final_class_fields .append (('schema' , schema ))
566576
567577 final_class = type (
@@ -574,7 +584,7 @@ def parse(cls, stream):
574584 )
575585 # register schema encoding approach
576586 stream .compact_footer = bool (header .flags & cls .COMPACT_FOOTER )
577- return final_class , buffer
587+ return final_class , ( init_pos , stream . tell () - init_pos )
578588
579589 @classmethod
580590 def to_python (cls , ctype_object , client : 'Client' = None , * args , ** kwargs ):
@@ -610,4 +620,7 @@ def from_python(cls, stream, value):
610620 return
611621
612622 stream .register_binary_type (value .__class__ )
613- value ._from_python (stream )
623+ if getattr (value , '_buffer' , None ):
624+ stream .write (value ._buffer )
625+ else :
626+ value ._from_python (stream )
0 commit comments