oci-image 0.1.2

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), overlay snapshot prep, and an optional anonymous registry pull.
Documentation
use std::io;
use std::path::PathBuf;

use crate::Digest;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("{context}: {source}")]
    Io {
        context: String,
        #[source]
        source: io::Error,
    },
    #[error("invalid digest {0:?} (only sha256:<64 lowercase hex> is accepted)")]
    BadDigest(String),
    #[error("digest mismatch: expected {expected}, got {actual}")]
    DigestMismatch { expected: Digest, actual: Digest },
    #[error("invalid image reference {0:?}")]
    BadReference(String),
    #[error("layer entry {0:?} would land outside the rootfs")]
    Escape(PathBuf),
    #[error("blob {0} is not in the store")]
    MissingBlob(Digest),
    #[error("{0}")]
    Invalid(String),
    #[cfg(feature = "pull")]
    #[error("registry: {0}")]
    Http(#[from] reqwest::Error),
}

/// Attach what was being done to an `io::Error`.
pub(crate) trait Context<T> {
    fn ctx(self, what: impl FnOnce() -> String) -> Result<T>;
}

impl<T> Context<T> for io::Result<T> {
    fn ctx(self, what: impl FnOnce() -> String) -> Result<T> {
        self.map_err(|source| Error::Io {
            context: what(),
            source,
        })
    }
}