Skip to content

Commit c0e8c05

Browse files
committed
Tested data from trx-rs
1 parent 951e7c9 commit c0e8c05

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

trx/tests/test_memmap.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,107 @@ def test__ensure_little_endian_big_endian_input():
498498
assert result[0] == 0x12345678
499499

500500

501+
def test_load_zip64_with_extra_fields():
502+
"""Test loading ZIP64 files where both local and CD headers have extra fields.
503+
504+
Rust and other tools always write ZIP64 extended information (extra field
505+
ID 0x0001, 20 bytes: 4-byte tag+size + 8-byte orig + 8-byte comp) in both
506+
local file headers and central directory entries, even for small files.
507+
This ensures the data offset is computed correctly by reading the local
508+
header's extra_len rather than assuming a fixed layout.
509+
"""
510+
positions = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
511+
offsets = np.array([0, 2], dtype=np.uint64)
512+
header = {
513+
"DIMENSIONS": [10, 10, 10],
514+
"VOXEL_TO_RASMM": np.eye(4).tolist(),
515+
"NB_VERTICES": 2,
516+
"NB_STREAMLINES": 1,
517+
}
518+
519+
def make_zip64_extra(orig_size, comp_size):
520+
data = struct.pack("<QQ", orig_size, comp_size)
521+
return struct.pack("<HH", 0x0001, len(data)) + data
522+
523+
with tempfile.TemporaryDirectory() as tmp_dir:
524+
trx_path = os.path.join(tmp_dir, "test_zip64.trx")
525+
526+
with open(trx_path, "wb") as f:
527+
local_info = []
528+
529+
for name, data in [
530+
("header.json", json.dumps(header).encode()),
531+
("positions.3.float32", positions.astype("<f4").tobytes()),
532+
("offsets.uint64", offsets.astype("<u8").tobytes()),
533+
]:
534+
offset = f.tell()
535+
fname = name.encode()
536+
crc = zipfile.crc32(data)
537+
# ZIP64 extended info in local header (20 bytes)
538+
extra = make_zip64_extra(len(data), len(data))
539+
f.write(
540+
struct.pack(
541+
"<4sHHHHHIIIHH",
542+
b"PK\x03\x04",
543+
45, # version needed: ZIP64
544+
0, 0, 0, 0,
545+
crc,
546+
len(data),
547+
len(data),
548+
len(fname),
549+
len(extra),
550+
)
551+
)
552+
f.write(fname)
553+
f.write(extra)
554+
f.write(data)
555+
local_info.append((name, offset, crc, len(data)))
556+
557+
cd_start = f.tell()
558+
for name, offset, crc, size in local_info:
559+
fname = name.encode()
560+
# ZIP64 extended info in central directory entry (20 bytes)
561+
extra = make_zip64_extra(size, size)
562+
f.write(
563+
struct.pack(
564+
"<4sHHHHHHIIIHHHHHII",
565+
b"PK\x01\x02",
566+
45, # version made by: ZIP64
567+
45, # version needed: ZIP64
568+
0, 0, 0, 0,
569+
crc,
570+
size,
571+
size,
572+
len(fname),
573+
len(extra),
574+
0, 0, 0, 0,
575+
offset,
576+
)
577+
)
578+
f.write(fname)
579+
f.write(extra)
580+
581+
cd_size = f.tell() - cd_start
582+
f.write(
583+
struct.pack(
584+
"<4sHHHHIIH",
585+
b"PK\x05\x06",
586+
0, 0,
587+
len(local_info),
588+
len(local_info),
589+
cd_size,
590+
cd_start,
591+
0,
592+
)
593+
)
594+
595+
trx = tmm.load_from_zip(trx_path)
596+
np.testing.assert_array_almost_equal(trx.streamlines._data, positions)
597+
assert trx.header["NB_VERTICES"] == 2
598+
assert trx.header["NB_STREAMLINES"] == 1
599+
trx.close()
600+
601+
501602
def test_load_zip_with_local_header_extra_field():
502603
"""Test loading ZIP where local header has extra field not in central dir.
503604

0 commit comments

Comments
 (0)