27
27
import os
28
28
import struct
29
29
import sys
30
- from typing import List
30
+ import time
31
+ from typing import List , Optional
31
32
32
33
from . import isal_zlib
33
34
@@ -221,16 +222,29 @@ def _add_read_data(self, data):
221
222
_GzipReader = _IGzipReader
222
223
223
224
224
- # Plagiarized from gzip.py from python's stdlib.
225
+ def _create_simple_gzip_header (compresslevel : int ,
226
+ mtime : Optional [int ] = None ) -> bytes :
227
+ if mtime is None :
228
+ mtime = int (time .time ())
229
+ # There is no best compression level. ISA-L only provides algorithms for
230
+ # fast and medium levels.
231
+ xfl = 4 if compresslevel == _COMPRESS_LEVEL_FAST else 0
232
+ # Pack ID1 and ID2 magic bytes, method (8=deflate), header flags (no extra
233
+ # fields added to header), mtime, xfl and os (255 for unknown OS).
234
+ return struct .pack ("<BBBBLBB" , 0x1f , 0x8b , 8 , 0 , mtime , xfl , 255 )
235
+
236
+
225
237
def compress (data , compresslevel = _COMPRESS_LEVEL_BEST , * , mtime = None ):
226
238
"""Compress data in one shot and return the compressed string.
227
239
Optional argument is the compression level, in range of 0-3.
228
240
"""
229
- buf = io .BytesIO ()
230
- with IGzipFile (fileobj = buf , mode = 'wb' ,
231
- compresslevel = compresslevel , mtime = mtime ) as f :
232
- f .write (data )
233
- return buf .getvalue ()
241
+ header = _create_simple_gzip_header (compresslevel , mtime )
242
+ # Compress the data without header or trailer in a raw deflate block.
243
+ compressed = isal_zlib .compress (data , compresslevel , wbits = - 15 )
244
+ length = len (data ) & 0xFFFFFFFF
245
+ crc = isal_zlib .crc32 (data )
246
+ trailer = struct .pack ("<LL" , crc , length )
247
+ return header + compressed + trailer
234
248
235
249
236
250
def _gzip_header_end (data : bytes ) -> int :
@@ -244,8 +258,8 @@ def _gzip_header_end(data: bytes) -> int:
244
258
raise BadGzipFile ("Unknown compression method" )
245
259
pos = 10
246
260
if flags & FHEXTRA :
247
- xlen = struct . unpack ( "<H" , data [pos : pos + 2 ] )
248
- pos += xlen
261
+ xlen = int . from_bytes ( data [pos : pos + 2 ], "little" , signed = False )
262
+ pos += 2 + xlen
249
263
if flags & FNAME :
250
264
fname_end = data .index (b"\x00 " , pos ) + 1
251
265
pos = fname_end
0 commit comments