use serde::{Deserialize, Serialize};
pub const LOCAL_IMAGE_METADATA_FILE: &str = "metadata.json";
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct LocalImageMetadata {
pub reference: String,
pub os: String,
pub architecture: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub digest: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created: Option<String>,
}
impl LocalImageMetadata {
#[must_use]
pub fn new(
reference: impl Into<String>,
os: impl Into<String>,
architecture: impl Into<String>,
) -> Self {
Self {
reference: reference.into(),
os: os.into(),
architecture: architecture.into(),
size: None,
digest: None,
created: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_through_json() {
let meta = LocalImageMetadata {
reference: "myapp:latest".to_string(),
os: "darwin".to_string(),
architecture: "arm64".to_string(),
size: Some(4096),
digest: Some("sha256:abc".to_string()),
created: None,
};
let json = serde_json::to_string(&meta).expect("serialize");
let back: LocalImageMetadata = serde_json::from_str(&json).expect("deserialize");
assert_eq!(meta, back);
}
#[test]
fn unset_optionals_are_omitted_and_default_back() {
let meta = LocalImageMetadata::new("myapp:latest", "darwin", "arm64");
let json = serde_json::to_string(&meta).expect("serialize");
assert!(!json.contains("size"));
assert!(!json.contains("digest"));
assert!(!json.contains("created"));
let back: LocalImageMetadata = serde_json::from_str(&json).expect("deserialize");
assert_eq!(meta, back);
assert!(back.size.is_none());
}
}