///|
/// Bio.Datastore Demo.
///
/// Demonstrates the MD5-keyed BagIt-style local data cache: payload
/// registration with MD5 manifests, fetch-through caching with hit/miss
/// accounting, bag-info tags (Payload-Oxum), manifest serialization,
/// verification and bag loading.
///|
fn main raise {
println("=== 1. MD5 (RFC 1321 test vectors) ===")
println("md5(\"\") = \{@src.md5_hex("")}")
println("md5(\"a\") = \{@src.md5_hex("a")}")
println("md5(\"abc\") = \{@src.md5_hex("abc")}")
println("md5(\"message digest\") = \{@src.md5_hex("message digest")}")
println("\n=== 2. Create a bag and register payloads ===")
let bag = @src.Datastore::new(root="demo-bag")
let _ = bag.add("sequences/fasta/hsa.fas", ">hsa\nMVLSPADKTNVKAAWGK\n")
let _ = bag.add("sequences/fasta/mmu.fas", ">mmu\nMVLSGEDKSNIKAAWGK\n")
let _ = bag.add("notes/readme.txt", "synthetic demo payload\n")
bag.set_tag("Contact-Name", "Demo User")
bag.set_tag("External-Identifier", "demo:sequences-001")
println("root: \{bag.root()}")
println("payloads: \{Repr(bag.names())}")
println("tags: \{Repr(bag.tags())}")
println("\n=== 3. Fetch-through cache ===")
// first fetch: cache miss -> the loader callback provides the payload
let first = bag.fetch("structures/pdb/1sct.pdb", fn(name) {
println(" (loading \{name} from the remote source)")
"ATOM 1 N ALA A 1\nEND\n"
})
// second fetch: cache hit -> no loader call
let second = bag.fetch("structures/pdb/1sct.pdb", fn(name) {
println(" (this loader call should never happen: \{name})")
""
})
println("fetched payload stable: \{first == second}")
println("cache hits: \{bag.hits()}, cache misses: \{bag.misses()}")
println("\n=== 4. Manifest and BagIt files ===")
println("payload-oxum: \{bag.payload_oxum()}")
for line in bag.manifest_lines() {
println("manifest: \{line}")
}
println("--- bagit.txt ---")
println(bag.bagit_txt())
println("--- bag-info.txt ---")
println(bag.bag_info_txt())
println("\n=== 5. Verify ===")
println("bag verifies: \{bag.verify()}")
let entry = bag.entry("notes/readme.txt")
let checksum = match entry {
Some(e) => e.checksum()
None => "(missing)"
}
println("stored checksum of notes/readme.txt: \{checksum}")
println("\n=== 6. Load a bag from an external manifest ===")
// a consistent manifest: declare the real md5 of the provided payload
let data_one = ">one\nAAAA\n"
let good_manifest = @src.md5_hex(data_one) + " data/seqs/one.fas\n"
let loaded = @src.Datastore::load_bag(
root="external-bag",
manifest_text=good_manifest,
loader=fn(_name) { Some(data_one) },
)
println("loaded payload names: \{Repr(loaded.names())}")
println("consistent bag verifies: \{loaded.verify()}")
// a manifest with a stale checksum makes verification fail
let stale_manifest = "0cc175b9c0f1b6a831c399e269772661 data/seqs/one.fas\n"
let mismatched = @src.Datastore::load_bag(
root="stale-bag",
manifest_text=stale_manifest,
loader=fn(_name) { Some(data_one) },
)
println("stale manifest verifies: \{mismatched.verify()}")
println("\nDone.")
}