Skip to main content

core.archive — File-archive packaging

core.archive declares a common interface for packaging file entries into bytes. It contains a tar adapter and selectors for tar, zip, ar and cpio; zip, ar and cpio adapters are not implemented.

The declarations and signatures below are API reference excerpts, not standalone executable examples. The generic tar adapter has a field-access limitation.

Architectural alignment with core.compress​

core.archive and core.compress are siblings at the same architectural layer. Both transform byte streams; they differ in what the transformation models:

ModuleFunctorDomain
core.compressbytes → encoded bytesa single byte stream
core.archivearchive entries → bytesa multi-file bundle

Tar packaging and compression are separate operations. The direct tar writer has this signature:

public fn write_archive(entries: &List<TarEntry>) -> Result<List<Byte>, TarError>;

The declared encoder core.compress.mod_gzip.Gzip.encode takes a byte slice, compression level and mutable output list, and returns Result<Int, CompressError>. Its runtime backend is unavailable; see compression codecs. There is no exported with_compress helper in core.archive.

Universal entry model​

public type ArchiveEntry is {
path: Text,
mode: Int, // POSIX bits, e.g. 0o644
mtime: Int, // Unix seconds; 0 = unset
kind: ArchiveEntryKind,
content: List<Byte>, // only for RegularFile entries
};

public type ArchiveEntryKind is
ArchiveRegularFile
| ArchiveDirectory
| ArchiveSymlink(Text) // target path
| ArchiveHardlink(Text);

ArchiveEntry is the protocol-level entry view used by Archive.pack / unpack. Per-format adapters convert between this universal record and their format-specific representation (e.g., TarEntry for tar — see core.archive.tar for the USTAR-mapped field set).

The record's fields are private. Use the free constructors below to create file, directory and symlink entries.

Algorithm selector​

public type ArchiveAlgorithm is
Tar // USTAR + PAX
| Zip // PKZIP
| Ar // Unix ar
| Cpio; // POSIX cpio

The selector helpers return format tags and associated filename extensions:

Algorithmarchive_algorithm_tagarchive_algorithm_extensions
Tar"tar"["tar"]
Zip"zip"["zip", "jar"]
Ar"ar"["a", "ar"]
Cpio"cpio"["cpio"]

Both helpers take &ArchiveAlgorithm. They return the values above; they do not inspect archive contents or split compound filenames such as output.tar.gz.

Archive protocol​

public type Archive is protocol {
fn algorithm(&self) -> ArchiveAlgorithm;
fn pack(&self, entries: &List<ArchiveEntry>) -> Result<List<Byte>, ArchiveError>;
fn unpack(&self, bytes: &[Byte]) -> Result<List<ArchiveEntry>, ArchiveError>;
};

Bidirectional packaging — format adapters implement this to participate in the universal subsystem. The protocol surface is intentionally minimal:

  • algorithm — adapter self-identification (also useful for multi-format dispatch in user code).
  • pack — universal entries → bytes.
  • unpack — bytes → universal entries.

Higher-level concerns (streaming, partial-archive reads, permissions-preservation policies) compose ON TOP of this protocol via consumer-side adapters; the protocol stays small.

Error surface​

public type ArchiveError is
Format(Text) // format-specific parse / write error
| UnsupportedAlgorithm(ArchiveAlgorithm)
| InvalidEntry(Text);

Display and Debug implementations are declared for these variants.

Algorithm dispatch​

public fn adapter_for(a: ArchiveAlgorithm) -> Result<Heap<dyn Archive>, ArchiveError>;

The declared implementation selects TarFormat for Tar and returns UnsupportedAlgorithm for Zip, Ar and Cpio. tar_format() -> TarFormat constructs the concrete adapter directly. Its pack and unpack methods depend on the conversion functions described below.

Convenience constructors​

These functions are exported by core.archive. Reference signatures:

public fn entry_for_file(path: Text, content: List<Byte>, mode: Int, mtime: Int)
-> ArchiveEntry;
public fn entry_for_directory(path: Text, mode: Int, mtime: Int) -> ArchiveEntry;
public fn entry_for_symlink(path: Text, target: Text, mtime: Int) -> ArchiveEntry;

They set the corresponding ArchiveEntryKind. Directory and symlink entries have empty content lists; the symlink constructor sets mode 0o777. The similarly named constructors in core.archive.tar return TarEntry instead. The parent module re-exports them with a tar_ prefix, such as tar_entry_for_file.

TarEntry ↔ ArchiveEntry adapters​

core.archive.tar exports the TarEntry type, but its fields are private. The parent module declares these converters:

public fn tar_entry_to_universal(t: &TarEntry) -> ArchiveEntry;
public fn universal_to_tar_entry(e: &ArchiveEntry) -> TarEntry;

The current converter implementations read and construct private fields declared in core.archive.tar. Those accesses cross the declaring-module boundary and conflict with the field-visibility contract. TarFormat.pack and TarFormat.unpack call these converters; their signatures alone do not establish a working generic archive round trip.

The conversion is also lossy: the universal record has no UID, GID or owner-name fields. Conversion back sets UID/GID to zero and owner names to empty text. The forward converter maps device, FIFO and other unsupported entry kinds to ArchiveRegularFile. It therefore does not preserve every tar entry kind or its metadata.

Primary consumers​

Use caseComposition
Cog-source publicationverum package publish creates gzip-compressed tar; see archive contents.
Tar byte outputcore.archive.tar.write_archive declares uncompressed tar output; compression is a separate operation.

File-by-file status​

FileStatusNotes
mod.vrundocumentedUniversal entry model, Archive protocol and dispatch declarations; converter field-access limitation described above.
tar.vrregression-onlyUSTAR + PAX reader/writer source and regression fixtures; xattr and sparse-file PAX extensions are unsupported.

There are no zip.vr, ar.vr or cpio.vr adapter implementations.