@@ -279,12 +279,16 @@ def _internal_parse_buffer(
279279
280280 # check for compressed result
281281 if cmd == SQCLOUD_CMD .COMPRESSED .value :
282- buffer = self ._internal_uncompress_data (buffer , blen )
282+ buffer = self ._internal_uncompress_data (buffer )
283283 if buffer is None :
284284 raise SQCloudException (
285285 f"An error occurred while decompressing the input buffer of len { blen } ."
286286 )
287287
288+ # buffer after decompression
289+ blen = len (buffer )
290+ cmd = chr (buffer [0 ])
291+
288292 # first character contains command type
289293 if cmd in [
290294 SQCLOUD_CMD .ZEROSTRING .value ,
@@ -338,7 +342,10 @@ def _internal_parse_buffer(
338342
339343 elif cmd in [SQCLOUD_CMD .ROWSET .value , SQCLOUD_CMD .ROWSET_CHUNK .value ]:
340344 # CMD_ROWSET: *LEN 0:VERSION ROWS COLS DATA
345+ # - When decompressed, LEN for ROWSET is *0
346+ #
341347 # CMD_ROWSET_CHUNK: /LEN IDX:VERSION ROWS COLS DATA
348+ #
342349 rowset_signature = self ._internal_parse_rowset_signature (buffer )
343350 if rowset_signature .start < 0 :
344351 raise SQCloudException ("Cannot parse rowset signature" )
@@ -361,7 +368,7 @@ def _internal_parse_buffer(
361368 # continue parsing next chunk in the buffer
362369 sign_len = rowset_signature .len
363370 buffer = buffer [sign_len + len (f"/{ sign_len } " ) :]
364- if buffer :
371+ if cmd == SQCLOUD_CMD . ROWSET_CHUNK . value and buffer :
365372 return self ._internal_parse_buffer (connection , buffer , len (buffer ))
366373
367374 return rowset
@@ -387,7 +394,7 @@ def _internal_parse_buffer(
387394 # TODO: exception here?
388395 return SQCloudResult (None )
389396
390- def _internal_uncompress_data (self , buffer : bytes , blen : int ) -> Optional [bytes ]:
397+ def _internal_uncompress_data (self , buffer : bytes ) -> Optional [bytes ]:
391398 """
392399 %LEN COMPRESSED UNCOMPRESSED BUFFER
393400
@@ -398,51 +405,34 @@ def _internal_uncompress_data(self, buffer: bytes, blen: int) -> Optional[bytes]
398405 Returns:
399406 str: The uncompressed data.
400407 """
401- tlen = 0 # total length
402- clen = 0 # compressed length
403- ulen = 0 # uncompressed length
404- hlen = 0 # raw header length
405- seek1 = 0
408+ space_index = buffer .index (b" " )
409+ buffer = buffer [space_index + 1 :]
406410
407- start = 1
408- counter = 0
409- for i in range (blen ):
410- if chr (buffer [i ]) != " " :
411- continue
412- counter += 1
411+ # extract compressed size
412+ space_index = buffer .index (b" " )
413+ compressed_size = int (buffer [:space_index ].decode ("utf-8" ))
414+ buffer = buffer [space_index + 1 :]
413415
414- data = buffer [start :i ]
415- start = i + 1
416-
417- if counter == 1 :
418- tlen = int (data )
419- seek1 = start
420- elif counter == 2 :
421- clen = int (data )
422- elif counter == 3 :
423- ulen = int (data )
424- break
425-
426- # sanity check header values
427- if tlen == 0 or clen == 0 or ulen == 0 or start == 1 or seek1 == 0 :
428- return None
416+ # extract decompressed size
417+ space_index = buffer .index (b" " )
418+ uncompressed_size = int (buffer [:space_index ].decode ("utf-8" ))
419+ buffer = buffer [space_index + 1 :]
429420
430- # copy raw header
431- hlen = start - seek1
432- header = buffer [start : start + hlen ]
421+ # extract data header
422+ header = buffer [:- compressed_size ]
433423
434- # compute index of the first compressed byte
435- start += hlen
424+ # extract compressed data
425+ compressed_buffer = buffer [ - compressed_size :]
436426
437- # perform real decompression
438- # clone = header + lz4.block.decompress(buffer[start:])
439- clone = lz4decode ( buffer , start , header )
427+ decompressed_buffer = header + lz4 . block . decompress (
428+ compressed_buffer , uncompressed_size
429+ )
440430
441431 # sanity check result
442- if len (clone ) != ulen + hlen :
432+ if len (decompressed_buffer ) != uncompressed_size + len ( header ) :
443433 return None
444434
445- return clone
435+ return decompressed_buffer
446436
447437 def _internal_parse_array (self , buffer : bytes ) -> list :
448438 start = 0
0 commit comments