| 396 | |
| 397 | @classmethod |
| 398 | def read(cls, bio, manifest_version=18): |
| 399 | cdl_start = bio.tell() |
| 400 | _cdl = cls() |
| 401 | _cdl._manifest_version = manifest_version |
| 402 | |
| 403 | _cdl.size = struct.unpack('<I', bio.read(4))[0] |
| 404 | _cdl.version = struct.unpack('B', bio.read(1))[0] |
| 405 | _cdl.count = struct.unpack('<I', bio.read(4))[0] |
| 406 | |
| 407 | # the way this data is stored is rather odd, maybe there's a nicer way to write this... |
| 408 | |
| 409 | for _ in range(_cdl.count): |
| 410 | _cdl.elements.append(ChunkInfo(manifest_version=manifest_version)) |
| 411 | |
| 412 | # guid, doesn't seem to be a standard like UUID but is fairly straightfoward, 4 bytes, 128 bit. |
| 413 | for chunk in _cdl.elements: |
| 414 | chunk.guid = struct.unpack('<IIII', bio.read(16)) |
| 415 | |
| 416 | # hash is a 64 bit integer, no idea how it's calculated but we don't need to know that. |
| 417 | for chunk in _cdl.elements: |
| 418 | chunk.hash = struct.unpack('<Q', bio.read(8))[0] |
| 419 | |
| 420 | # sha1 hash |
| 421 | for chunk in _cdl.elements: |
| 422 | chunk.sha_hash = bio.read(20) |
| 423 | |
| 424 | # group number, seems to be part of the download path |
| 425 | for chunk in _cdl.elements: |
| 426 | chunk.group_num = struct.unpack('B', bio.read(1))[0] |
| 427 | |
| 428 | # window size is the uncompressed size |
| 429 | for chunk in _cdl.elements: |
| 430 | chunk.window_size = struct.unpack('<I', bio.read(4))[0] |
| 431 | |
| 432 | # file size is the compressed size that will need to be downloaded |
| 433 | for chunk in _cdl.elements: |
| 434 | chunk.file_size = struct.unpack('<q', bio.read(8))[0] |
| 435 | |
| 436 | if (size_read := bio.tell() - cdl_start) != _cdl.size: |
| 437 | logger.warning(f'Did not read entire chunk data list! Version: {_cdl.version}, ' |
| 438 | f'{_cdl.size - size_read} bytes missing, skipping...') |
| 439 | bio.seek(_cdl.size - size_read, 1) |
| 440 | # downgrade version to prevent issues during serialisation |
| 441 | _cdl.version = 0 |
| 442 | |
| 443 | return _cdl |
| 444 | |
| 445 | def write(self, bio): |
| 446 | cdl_start = bio.tell() |