vyre_runtime/pipeline_cache/
fingerprint.rs1use vyre_megakernel::Artifact;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct PipelineFingerprint(pub [u8; 32]);
8
9const _: fn(&Artifact) -> PipelineFingerprint = PipelineFingerprint::of;
10
11impl PipelineFingerprint {
12 #[must_use]
17 pub fn of(artifact: &Artifact) -> Self {
18 Self(artifact.digest().0)
19 }
20
21 #[must_use]
24 pub fn hex(&self) -> String {
25 let mut out = String::with_capacity(64);
26 self.push_hex(&mut out);
27 out
28 }
29
30 pub(super) fn push_hex(&self, out: &mut String) {
31 const HEX: &[u8; 16] = b"0123456789abcdef";
32 for &byte in &self.0 {
33 out.push(HEX[(byte >> 4) as usize] as char);
34 out.push(HEX[(byte & 0x0f) as usize] as char);
35 }
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::pipeline_cache::test_helpers::{artifact_for_program, tiny_artifact};
43 use vyre_foundation::ir::{BufferDecl, DataType, Expr, Node, Program};
44
45 #[test]
46 fn fingerprint_is_deterministic() {
47 let a = PipelineFingerprint::of(&tiny_artifact());
48 let b = PipelineFingerprint::of(&tiny_artifact());
49 assert_eq!(a, b);
50 }
51
52 #[test]
53 fn fingerprint_hex_is_64_chars() {
54 let fp = PipelineFingerprint::of(&tiny_artifact());
55 assert_eq!(fp.hex().len(), 64);
56 }
57
58 #[test]
59 fn distinct_artifacts_do_not_share_fingerprint() {
60 let first = tiny_artifact();
61 let second = artifact_for_program(Program::wrapped(
62 vec![BufferDecl::read_write("out", 0, DataType::U32).with_count(1)],
63 [1, 1, 1],
64 vec![Node::store("out", Expr::u32(0), Expr::u32(43))],
65 ));
66 assert_ne!(
67 PipelineFingerprint::of(&first),
68 PipelineFingerprint::of(&second)
69 );
70 }
71
72 #[test]
73 fn fingerprint_changes_when_declared_program_shape_changes() {
74 let base = tiny_artifact();
75 let widened = artifact_for_program(Program::wrapped(
76 vec![BufferDecl::read_write("out", 0, DataType::U32).with_count(1)],
77 [64, 1, 1],
78 vec![Node::store("out", Expr::u32(0), Expr::u32(42))],
79 ));
80
81 assert_ne!(
82 PipelineFingerprint::of(&base),
83 PipelineFingerprint::of(&widened),
84 "neutral artifact geometry must change the fingerprint"
85 );
86 }
87}