Skip to main content

keyhog_scanner/engine/
gpu_cache.rs

1//! GPU matcher on-disk cache helpers and constant-pack types.
2
3/// Cached per-process GPU input constants - pre-packed LE byte streams
4/// for the four pattern-shape inputs the GpuLiteralSet kernel reads on
5/// every dispatch. Filled on first scan, borrowed thereafter.
6pub struct GpuConstPacks {
7    pub pattern_offsets: Vec<u8>,
8    pub pattern_lengths: Vec<u8>,
9    pub pattern_bytes: Vec<u8>,
10    pub pattern_count: Vec<u8>,
11}
12
13/// Cached per-process AC-kernel input constants - pre-packed LE byte
14/// streams for the four DFA-shape inputs the AC bounded-ranges kernel
15/// reads on every dispatch. Separate from `GpuConstPacks` because the
16/// AC kernel binds different fields (`dfa.transitions`,
17/// `dfa.output_offsets`, `dfa.output_records`, `pattern_lengths`).
18pub struct AcConstPacks {
19    pub transitions: Vec<u8>,
20    pub output_offsets: Vec<u8>,
21    pub output_records: Vec<u8>,
22    pub pattern_lengths: Vec<u8>,
23}
24
25/// On-disk cache for `GpuLiteralSet`. The compiled matcher is keyed by a
26/// SHA-256 of the literal set + the vyre wire version (which is bumped
27/// whenever the IR layout changes), so bumping vyre to a new minor
28/// version automatically invalidates the cache instead of silently
29/// loading a stale matcher. Lives at `$XDG_CACHE_HOME/keyhog/programs/`
30/// (typically `~/.cache/keyhog/programs/`).
31const GPU_MATCHER_CACHE_VERSION: u32 = 1;
32
33pub(crate) fn gpu_matcher_cache_dir() -> Option<std::path::PathBuf> {
34    let dir = dirs::cache_dir()?.join("keyhog").join("programs");
35    if !dir.exists() && std::fs::create_dir_all(&dir).is_err() {
36        return None;
37    }
38    Some(dir)
39}
40
41pub(crate) fn gpu_matcher_cache_key(literals: &[&[u8]]) -> String {
42    use sha2::{Digest, Sha256};
43    let mut h = Sha256::new();
44    h.update(GPU_MATCHER_CACHE_VERSION.to_le_bytes());
45    h.update((literals.len() as u32).to_le_bytes());
46    for lit in literals {
47        h.update((lit.len() as u32).to_le_bytes());
48        h.update(lit);
49    }
50    let digest = h.finalize();
51    let mut hex = String::with_capacity(64);
52    for byte in digest {
53        use std::fmt::Write as _;
54        let _ = write!(hex, "{:02x}", byte);
55    }
56    hex
57}