oci-image 0.3.1

OCI container images on disk: image references, sha256 digests, one-pass layer unpack (whiteouts and opaque directories), gzip (all cores via lgz one-pass streaming decode; small layers on one core) and zstd layers, a content-addressed store of blobs and per-layer directories in overlayfs format (each layer unpacked once, shared between images, refcounted, collected), and overlay snapshot prep.
Documentation
//! Built without its `zstd` feature, oci-image refuses a zstd layer and says
//! which feature reads it, before it writes anything.

#![allow(unexpected_cfgs)]

/// A zstd frame's magic number, then bytes no zstd decoder accepts.
#[cfg(not(feature = "zstd"))]
const ZSTD_HEAD: [u8; 8] = [0x28, 0xb5, 0x2f, 0xfd, 0, 0, 0, 0];

#[cfg(not(feature = "zstd"))]
fn names_the_feature(e: &oci_image::Error) -> bool {
    e.to_string().contains("feature `zstd`")
}

#[cfg(not(feature = "zstd"))]
#[test]
fn without_the_zstd_feature_a_zstd_layer_is_refused_by_name() {
    match oci_image::decoder(&ZSTD_HEAD) {
        Ok(_) => panic!("a zstd blob was opened without the zstd feature"),
        Err(e) => assert!(names_the_feature(&e), "{e}"),
    }
    let dir = tempfile::tempdir().unwrap();
    let blob = dir.path().join("layer");
    std::fs::write(&blob, ZSTD_HEAD).unwrap();
    let root = dir.path().join("root");
    std::fs::create_dir(&root).unwrap();
    match oci_image::apply_layer_file(&blob, &root, &oci_image::UnpackOptions::default()) {
        Ok(_) => panic!("a zstd layer was applied without the zstd feature"),
        Err(e) => assert!(names_the_feature(&e), "{e}"),
    }
    assert_eq!(std::fs::read_dir(&root).unwrap().count(), 0);
}

#[cfg(feature = "zstd")]
#[test]
fn with_the_zstd_feature_a_zstd_blob_opens() {
    let blob = zstd::encode_all(&[0u8; 1024][..], 3).unwrap();
    let mut out = Vec::new();
    std::io::Read::read_to_end(&mut oci_image::decoder(&blob).unwrap(), &mut out).unwrap();
    assert_eq!(out, vec![0u8; 1024]);
}