use crate::plan::ResourceId;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use tatara_env::compile::{Env, Resource};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ResourceFingerprint {
pub id: ResourceId,
pub blake3: String,
}
#[must_use]
pub fn fingerprint_resource(r: &Resource) -> ResourceFingerprint {
let blake3 = match tatara_lisp::domain::lookup_attest(&r.keyword) {
Some(meta) => tatara_lisp::domain::attest_value(meta.namespace, &r.value),
None => {
let json = serde_json::to_string(&r.value).unwrap_or_else(|_| "<unserializable>".into());
blake3::hash(json.as_bytes()).to_hex().to_string()
}
};
ResourceFingerprint {
id: ResourceId::from_resource(r),
blake3,
}
}
#[must_use]
pub fn fingerprint_env(env: &Env) -> IndexMap<ResourceId, ResourceFingerprint> {
let mut out = IndexMap::with_capacity(env.resources.len());
for r in &env.resources {
let fp = fingerprint_resource(r);
out.insert(fp.id.clone(), fp);
}
out
}