pub const OCI_IMAGE_MANIFEST: &str = "application/vnd.oci.image.manifest.v1+json";
pub const OCI_IMAGE_INDEX: &str = "application/vnd.oci.image.index.v1+json";
pub const OCI_IMAGE_CONFIG: &str = "application/vnd.oci.image.config.v1+json";
pub const OCI_IMAGE_LAYER_TAR: &str = "application/vnd.oci.image.layer.v1.tar";
pub const OCI_IMAGE_LAYER_TAR_GZIP: &str = "application/vnd.oci.image.layer.v1.tar+gzip";
pub const OCI_IMAGE_LAYER_TAR_ZSTD: &str = "application/vnd.oci.image.layer.v1.tar+zstd";
pub const OCI_EMPTY: &str = "application/vnd.oci.empty.v1+json";
pub const DOCKER_MANIFEST_V2: &str = "application/vnd.docker.distribution.manifest.v2+json";
pub const DOCKER_MANIFEST_LIST_V2: &str =
"application/vnd.docker.distribution.manifest.list.v2+json";
pub const DOCKER_IMAGE_CONFIG_V1: &str = "application/vnd.docker.container.image.v1+json";
pub const DOCKER_LAYER_TAR_GZIP: &str = "application/vnd.docker.image.rootfs.diff.tar.gzip";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ManifestKind {
ImageManifest,
ImageIndex,
Artifact,
}
#[must_use]
pub fn classify_manifest_media_type(ct: &str) -> Option<ManifestKind> {
let bare = ct.split(';').next().unwrap_or(ct).trim();
match bare {
OCI_IMAGE_MANIFEST | DOCKER_MANIFEST_V2 => Some(ManifestKind::ImageManifest),
OCI_IMAGE_INDEX | DOCKER_MANIFEST_LIST_V2 => Some(ManifestKind::ImageIndex),
other if other.starts_with("application/vnd.") && other.ends_with("+json") => {
Some(ManifestKind::Artifact)
}
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::{ManifestKind, classify_manifest_media_type};
#[test]
fn oci_image_manifest_is_classified_as_image() {
assert_eq!(
classify_manifest_media_type("application/vnd.oci.image.manifest.v1+json"),
Some(ManifestKind::ImageManifest),
);
}
#[test]
fn oci_image_index_is_classified_as_index() {
assert_eq!(
classify_manifest_media_type("application/vnd.oci.image.index.v1+json"),
Some(ManifestKind::ImageIndex),
);
}
#[test]
fn arbitrary_vnd_json_is_artifact() {
assert_eq!(
classify_manifest_media_type("application/vnd.cncf.helm.config.v1+json"),
Some(ManifestKind::Artifact),
);
}
#[test]
fn plain_json_is_rejected() {
assert_eq!(classify_manifest_media_type("application/json"), None);
}
#[test]
fn charset_parameter_is_stripped() {
assert_eq!(
classify_manifest_media_type(
"application/vnd.oci.image.manifest.v1+json; charset=utf-8"
),
Some(ManifestKind::ImageManifest),
);
}
}