use std::collections::HashMap; use miette::{Report, bail}; use serde::Deserialize; use crate::drivers::types::{ImageMetadata, Platform}; #[derive(Deserialize, Debug, Clone)] pub struct Metadata { manifest: Manifest, image: MetadataImage, } #[derive(Deserialize, Debug, Clone)] pub struct PlatformManifest { digest: String, platform: PlatformManifestInfo, } #[derive(Deserialize, Debug, Clone)] pub struct PlatformManifestInfo { architecture: String, } #[derive(Deserialize, Debug, Clone)] pub struct Manifest { digest: String, #[serde(default)] manifests: Vec, } #[derive(Deserialize, Debug, Clone)] pub struct MetadataPlatformImage { config: Config, } #[derive(Deserialize, Debug, Clone)] #[serde(untagged)] pub enum MetadataImage { Single(MetadataPlatformImage), Multi(HashMap), } #[derive(Deserialize, Debug, Clone)] #[serde(rename_all = "PascalCase")] pub struct Config { labels: HashMap, } impl TryFrom<(Metadata, Platform)> for ImageMetadata { type Error = Report; fn try_from((metadata, platform): (Metadata, Platform)) -> Result { match metadata.image { MetadataImage::Single(image) => Ok(Self { labels: image.config.labels, digest: metadata.manifest.digest, }), MetadataImage::Multi(mut platforms) => { let Some(image) = platforms.remove(&platform.to_string()) else { bail!("Image information does not exist for {platform}"); }; let Some(manifest) = metadata .manifest .manifests .into_iter() .find(|manifest| manifest.platform.architecture == platform.arch()) else { bail!("Manifest does not exist for {platform}"); }; Ok(Self { labels: image.config.labels, digest: manifest.digest, }) } } } }