use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtifactRef {
pub digest: String,
}
impl ArtifactRef {
pub fn new(digest: impl Into<String>) -> Self {
Self {
digest: digest.into(),
}
}
pub fn algorithm(&self) -> Option<&str> {
self.digest.split_once(':').map(|(algo, _)| algo)
}
pub fn hash(&self) -> Option<&str> {
self.digest.split_once(':').map(|(_, hash)| hash)
}
}
#[derive(Debug, Clone)]
pub struct ArtifactBlob {
pub digest: String,
pub size: u64,
pub media_type: String,
pub data: bytes::Bytes,
}
pub const MEDIA_TYPE_OCI_LAYER_GZIP: &str = "application/vnd.oci.image.layer.v1.tar+gzip";
pub const MEDIA_TYPE_OCI_LAYER_TAR: &str = "application/vnd.oci.image.layer.v1.tar";
pub const ARTIFACT_REF_KEY: &str = "__wfe_artifact";
pub fn artifact_ref_value(digest: &str) -> serde_json::Value {
serde_json::json!({ ARTIFACT_REF_KEY: digest })
}
pub fn is_artifact_ref(value: &serde_json::Value) -> bool {
value
.as_object()
.map(|obj| obj.contains_key(ARTIFACT_REF_KEY))
.unwrap_or(false)
}
pub fn parse_artifact_ref(value: &serde_json::Value) -> Option<String> {
value
.as_object()
.and_then(|obj| obj.get(ARTIFACT_REF_KEY))
.and_then(|v| v.as_str())
.map(|s| s.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn artifact_ref_roundtrip() {
let r = ArtifactRef::new("sha256:abc123");
assert_eq!(r.algorithm(), Some("sha256"));
assert_eq!(r.hash(), Some("abc123"));
}
#[test]
fn artifact_ref_value_is_artifact_ref() {
let v = artifact_ref_value("sha256:def456");
assert!(is_artifact_ref(&v));
assert_eq!(parse_artifact_ref(&v), Some("sha256:def456".to_string()));
}
#[test]
fn plain_string_is_not_artifact_ref() {
assert!(!is_artifact_ref(&serde_json::Value::String("hello".into())));
}
}