Skip to main content

keyhog_scanner/compiled_scanner/
types.rs

1//! Public scanner lifecycle and backend-readiness types.
2
3#[cfg(all(test, feature = "gpu", target_os = "linux"))]
4pub(crate) use crate::gpu::load_dynamic_library;
5#[cfg(all(feature = "gpu", target_os = "linux"))]
6pub(crate) use crate::gpu::probe_cuda_peer;
7pub use crate::gpu::GpuBackendAvailability;
8pub(crate) use crate::gpu::{GpuBackendAcquisitionFailure, GpuBackendPeers};
9use crate::hw_probe::ScanBackend;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum GpuInitPolicy {
13    /// Honor the resolved GPU runtime policy.
14    FromRuntimePolicy,
15    /// Census GPU peers regardless of the disabled-GPU policy. The selected
16    /// execution backend is still materialized lazily.
17    ForceEnabled,
18    /// Skip CUDA, Metal, and WGPU census and acquisition. Used when the selected CLI path
19    /// cannot route to GPU, avoiding startup and RSS overhead without changing
20    /// scan results.
21    ForceDisabled,
22}
23
24#[cfg(all(test, feature = "gpu", target_os = "linux"))]
25#[path = "../../tests/unit/compiled_scanner_cuda_driver_preflight.rs"]
26mod cuda_driver_preflight_tests;
27
28#[derive(Clone, Debug, Eq, PartialEq)]
29pub struct GpuBackendCandidateStatus {
30    pub backend: ScanBackend,
31    /// Whether the lightweight host census found a hardware peer with enough
32    /// identity to participate in autoroute.
33    pub available: bool,
34    /// Whether this process has materialized the execution backend.
35    pub acquired: bool,
36    pub driver_id: Option<&'static str>,
37    pub driver_version: Option<&'static str>,
38    pub device_identity: Option<String>,
39    pub runtime_identity: Option<String>,
40    pub is_software: bool,
41    pub acquisition_error: Option<String>,
42}
43
44impl GpuBackendCandidateStatus {
45    #[must_use]
46    pub fn has_complete_identity(&self) -> bool {
47        self.driver_id.is_some_and(|value| !value.trim().is_empty())
48            && self
49                .driver_version
50                .is_some_and(|value| !value.trim().is_empty())
51            && self
52                .device_identity
53                .as_deref()
54                .is_some_and(|value| !value.trim().is_empty())
55            && self
56                .runtime_identity
57                .as_deref()
58                .is_some_and(|value| !value.trim().is_empty())
59    }
60
61    /// Whether the lightweight census found hardware with complete identity.
62    /// This makes the peer eligible for materialization, but does not prove
63    /// that device acquisition has succeeded.
64    #[must_use]
65    pub fn is_eligible(&self) -> bool {
66        self.available && !self.is_software && self.has_complete_identity()
67    }
68
69    /// Whether this exact peer has materialized and retains complete identity.
70    #[must_use]
71    pub fn is_acquired_eligible(&self) -> bool {
72        self.acquired && self.is_eligible()
73    }
74}
75
76#[derive(Clone, Copy, Debug, Eq, PartialEq)]
77pub struct CompiledScannerRuntime {
78    pub detector_count: usize,
79    pub pattern_count: usize,
80    /// Versioned 64-bit projection of the canonical 256-bit scan-execution
81    /// hash. Autoroute also persists the complete hash as its rules identity.
82    pub detector_digest: u64,
83    /// Backend used by the no-backend library APIs. CLI calibrated routing is a
84    /// separate persisted per-workload decision and is never inferred here.
85    pub preferred_backend: &'static str,
86    pub gpu_backends: GpuBackendAvailability,
87    pub gpu_degrade_count: u64,
88}