use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
use crate::NodeId;
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ContentHash(pub [u8; 32]);
impl ContentHash {
#[must_use]
pub fn to_hex(&self) -> String {
let mut out = String::with_capacity(64);
for b in self.0 {
out.push_str(&format!("{b:02x}"));
}
out
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContentAdvertisement {
pub hash: ContentHash,
pub holder: NodeId,
#[serde(default)]
pub hint: ContentKind,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ContentKind {
PodSpec,
ConfigMapData,
HelmChart,
OciLayer,
#[default]
Other,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ContentLocations {
pub hash: ContentHash,
pub holders: BTreeSet<NodeId>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn content_kind_default_is_other() {
assert_eq!(ContentKind::default(), ContentKind::Other);
}
#[test]
fn content_advertisement_round_trips() {
let adv = ContentAdvertisement {
hash: ContentHash([0xaa; 32]),
holder: NodeId::new([0xbb; 32]),
hint: ContentKind::PodSpec,
};
let json = serde_json::to_string(&adv).unwrap();
assert!(json.contains("\"pod_spec\""));
let back: ContentAdvertisement = serde_json::from_str(&json).unwrap();
assert_eq!(back, adv);
}
#[test]
fn content_hash_hex_is_64_chars() {
let h = ContentHash([0; 32]);
assert_eq!(h.to_hex().len(), 64);
}
}