///|
/// ZIP Archive - represents a complete ZIP file structure.
///
/// An Archive is the top-level container for a collection of files and directories
/// that can be serialized to/from the ZIP file format. Internally uses a Map for
/// O(log n) lookups by normalized file path.
///
/// Features:
/// - Preserves insertion order for deterministic output
/// - Supports both files and directories
/// - Path normalization and validation via Fpath
/// - JSON serialization for debugging/inspection
///
/// Usage example:
/// archive.empty() |> archive.add(member) |> archive.to_bytes()
struct Archive {
members : Map[Fpath, Member] // Mutable map; iteration yields insertion order for deterministic ZIP output
}
///|
/// JSON serialization for Archive inspection and debugging.
///
/// Produces a JSON object with:
/// - "length": total number of members
/// - "members": array of [path, type] pairs in insertion order
///
/// Example output structure:
/// {"length": 3, "members": [["readme.txt", "File"], ["src/", "Dir"]]}
pub extend Archive with ToJson::{to_json}
///|
pub impl ToJson for Archive with fn to_json(self) {
let members : Array[Json] = []
for path, m in self.members { // insertion order
match m.kind() {
Dir => members.push([path, "Dir"])
File(_f) => members.push([path, "File"])
}
}
{ "length": self.members.length(), "members": members }
}