···11# bindle-file
2233-[bindle](https://en.wikipedia.org/wiki/Bindle) is an efficient, general purpose binary archive format for collecting files.
33+[bindle](https://en.wikipedia.org/wiki/Bindle) is an fast/efficient, binary archive format.
4455The format uses memory-mapped I/O for fast reads, optional zstd compression, and supports append-only writes with shadowing for updates. Files can be added incrementally without rewriting the entire archive.
66
+41
bench/bench.py
···3737 return f"{seconds:.3f} s"
383839394040+def verify_extraction(src_dir: Path, extract_dir: Path) -> None:
4141+ """Verify extracted files match source files."""
4242+ src_files = {f.relative_to(src_dir): f for f in src_dir.rglob("*") if f.is_file()}
4343+ extract_files = {f.relative_to(extract_dir): f for f in extract_dir.rglob("*") if f.is_file()}
4444+4545+ # Check file count
4646+ if len(src_files) != len(extract_files):
4747+ raise ValueError(f"File count mismatch: {len(src_files)} source, {len(extract_files)} extracted")
4848+4949+ # Check each file exists and has correct size
5050+ for rel_path, src_file in src_files.items():
5151+ if rel_path not in extract_files:
5252+ raise ValueError(f"Missing file in extraction: {rel_path}")
5353+5454+ extract_file = extract_files[rel_path]
5555+ src_size = src_file.stat().st_size
5656+ extract_size = extract_file.stat().st_size
5757+5858+ if src_size != extract_size:
5959+ raise ValueError(f"Size mismatch for {rel_path}: {src_size} vs {extract_size}")
6060+6161+ # Verify content matches
6262+ if src_file.read_bytes() != extract_file.read_bytes():
6363+ raise ValueError(f"Content mismatch for {rel_path}")
6464+6565+4066def create_test_data(base_dir: Path) -> None:
4167 """Create a variety of test files."""
4268 base_dir.mkdir(parents=True, exist_ok=True)
···90116 )
91117 unpack_time = time.perf_counter() - start
92118119119+ # Verify extraction (not timed)
120120+ verify_extraction(src_dir, extract_dir)
121121+93122 return pack_time, size, unpack_time
9412395124···119148 )
120149 unpack_time = time.perf_counter() - start
121150151151+ # Verify extraction (not timed)
152152+ verify_extraction(src_dir, extract_dir)
153153+122154 return pack_time, size, unpack_time
123155124156···146178 )
147179 unpack_time = time.perf_counter() - start
148180181181+ # Verify extraction (not timed)
182182+ verify_extraction(src_dir, extract_dir)
183183+149184 return pack_time, size, unpack_time
150185151186···173208 )
174209 unpack_time = time.perf_counter() - start
175210211211+ # Verify extraction (not timed)
212212+ verify_extraction(src_dir, extract_dir)
213213+176214 return pack_time, size, unpack_time
177215178216···199237 check=True,
200238 )
201239 unpack_time = time.perf_counter() - start
240240+241241+ # Verify extraction (not timed)
242242+ verify_extraction(src_dir, extract_dir)
202243203244 return pack_time, size, unpack_time
204245