docker_registry/
mediatypes.rs

1//! Media-types for API objects.
2
3use strum::{Display, EnumProperty, EnumString};
4
5use crate::errors::Result;
6
7// For schema1 types, see https://docs.docker.com/registry/spec/manifest-v2-1/
8// For schema2 types, see https://docs.docker.com/registry/spec/manifest-v2-2/
9
10#[derive(EnumProperty, EnumString, Display, Debug, Hash, PartialEq, Eq, Clone)]
11pub enum MediaTypes {
12  /// Manifest, version 2 schema 1.
13  #[strum(serialize = "application/vnd.docker.distribution.manifest.v1+json")]
14  #[strum(props(Sub = "vnd.docker.distribution.manifest.v1+json"))]
15  ManifestV2S1,
16  /// Signed manifest, version 2 schema 1.
17  #[strum(serialize = "application/vnd.docker.distribution.manifest.v1+prettyjws")]
18  #[strum(props(Sub = "vnd.docker.distribution.manifest.v1+prettyjws"))]
19  ManifestV2S1Signed,
20  /// Manifest, version 2 schema 2.
21  #[strum(serialize = "application/vnd.docker.distribution.manifest.v2+json")]
22  #[strum(props(Sub = "vnd.docker.distribution.manifest.v2+json"))]
23  ManifestV2S2,
24  /// Manifest List (aka "fat manifest").
25  #[strum(serialize = "application/vnd.docker.distribution.manifest.list.v2+json")]
26  #[strum(props(Sub = "vnd.docker.distribution.manifest.list.v2+json"))]
27  ManifestList,
28  /// Image layer, as a gzip-compressed tar.
29  #[strum(serialize = "application/vnd.docker.image.rootfs.diff.tar.gzip")]
30  #[strum(props(Sub = "vnd.docker.image.rootfs.diff.tar.gzip"))]
31  ImageLayerTgz,
32  /// Configuration object for a container.
33  #[strum(serialize = "application/vnd.docker.container.image.v1+json")]
34  #[strum(props(Sub = "vnd.docker.container.image.v1+json"))]
35  ContainerConfigV1,
36
37  /// OCI Manifest
38  #[strum(serialize = "application/vnd.oci.image.manifest.v1+json")]
39  #[strum(props(Sub = "vnd.oci.image.manifest.v1+json"))]
40  OciImageManifest,
41  // OCI Image index
42  #[strum(serialize = "application/vnd.oci.image.index.v1+json")]
43  #[strum(props(Sub = "vnd.oci.image.index.v1+json"))]
44  OciImageIndexV1,
45
46  /// Generic JSON
47  #[strum(serialize = "application/json")]
48  #[strum(props(Sub = "json"))]
49  ApplicationJson,
50}
51
52impl MediaTypes {
53  // TODO(lucab): proper error types
54  pub fn from_mime(mtype: &mime::Mime) -> Result<Self> {
55    match (mtype.type_(), mtype.subtype(), mtype.suffix()) {
56      (mime::APPLICATION, mime::JSON, _) => Ok(MediaTypes::ApplicationJson),
57      (mime::APPLICATION, subt, Some(suff)) => match (subt.to_string().as_str(), suff.to_string().as_str()) {
58        // Docker
59        ("vnd.docker.distribution.manifest.v1", "json") => Ok(MediaTypes::ManifestV2S1),
60        ("vnd.docker.distribution.manifest.v1", "prettyjws") => Ok(MediaTypes::ManifestV2S1Signed),
61        ("vnd.docker.distribution.manifest.v2", "json") => Ok(MediaTypes::ManifestV2S2),
62        ("vnd.docker.distribution.manifest.list.v2", "json") => Ok(MediaTypes::ManifestList),
63        ("vnd.docker.image.rootfs.diff.tar.gzip", _) => Ok(MediaTypes::ImageLayerTgz),
64        ("vnd.docker.container.image.v1", "json") => Ok(MediaTypes::ContainerConfigV1),
65        // OCI
66        ("vnd.oci.image.manifest.v1", "json") => Ok(MediaTypes::OciImageManifest),
67        ("vnd.oci.image.index.v1", "json") => Ok(MediaTypes::OciImageIndexV1),
68        _ => Err(crate::Error::UnknownMimeType(mtype.clone())),
69      },
70      _ => Err(crate::Error::UnknownMimeType(mtype.clone())),
71    }
72  }
73  pub fn to_mime(&self) -> mime::Mime {
74    match self {
75      &MediaTypes::ApplicationJson => Ok(mime::APPLICATION_JSON),
76      m => {
77        if let Some(s) = m.get_str("Sub") {
78          ("application/".to_string() + s).parse()
79        } else {
80          "application/star".parse()
81        }
82      }
83    }
84    .expect("to_mime should be always successful")
85  }
86}