openentropy_core/source.rs
1//! Abstract entropy source trait and runtime state.
2//!
3//! Every entropy source implements the [`EntropySource`] trait, which provides
4//! metadata via [`SourceInfo`], availability checking, and raw sample collection.
5
6use std::time::Duration;
7
8/// Category of entropy source, used for classification and filtering.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum SourceCategory {
11 Timing,
12 System,
13 Network,
14 Hardware,
15 Silicon,
16 CrossDomain,
17 Novel,
18 Frontier,
19}
20
21impl std::fmt::Display for SourceCategory {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::Timing => write!(f, "timing"),
25 Self::System => write!(f, "system"),
26 Self::Network => write!(f, "network"),
27 Self::Hardware => write!(f, "hardware"),
28 Self::Silicon => write!(f, "silicon"),
29 Self::CrossDomain => write!(f, "cross_domain"),
30 Self::Novel => write!(f, "novel"),
31 Self::Frontier => write!(f, "frontier"),
32 }
33 }
34}
35
36/// Metadata about an entropy source.
37///
38/// Each source declares its name, a human-readable description, a physics
39/// explanation of how it harvests entropy, its category, platform requirements,
40/// and an estimated entropy rate in bits per sample.
41#[derive(Debug, Clone)]
42pub struct SourceInfo {
43 /// Unique identifier (e.g. `"clock_jitter"`).
44 pub name: &'static str,
45 /// One-line human-readable description.
46 pub description: &'static str,
47 /// Physics explanation of the entropy mechanism.
48 pub physics: &'static str,
49 /// Source category for classification.
50 pub category: SourceCategory,
51 /// Platform requirements (e.g. `["macos"]`).
52 pub platform_requirements: &'static [&'static str],
53 /// Estimated entropy rate in bits per sample.
54 pub entropy_rate_estimate: f64,
55 /// Whether this is a composite source (combines multiple standalone sources).
56 ///
57 /// Composite sources don't measure a single independent entropy domain.
58 /// They combine or interleave other sources. The CLI displays them
59 /// separately from standalone sources.
60 pub composite: bool,
61}
62
63/// Trait that every entropy source must implement.
64pub trait EntropySource: Send + Sync {
65 /// Source metadata.
66 fn info(&self) -> &SourceInfo;
67
68 /// Check if this source can operate on the current machine.
69 fn is_available(&self) -> bool;
70
71 /// Collect raw entropy samples. Returns a `Vec<u8>` of up to `n_samples` bytes.
72 fn collect(&self, n_samples: usize) -> Vec<u8>;
73
74 /// Convenience: name from info.
75 fn name(&self) -> &'static str {
76 self.info().name
77 }
78}
79
80/// Runtime state for a registered source in the pool.
81pub struct SourceState {
82 pub source: Box<dyn EntropySource>,
83 pub weight: f64,
84 pub total_bytes: u64,
85 pub failures: u64,
86 pub last_entropy: f64,
87 pub last_min_entropy: f64,
88 pub last_collect_time: Duration,
89 pub healthy: bool,
90}
91
92impl SourceState {
93 pub fn new(source: Box<dyn EntropySource>, weight: f64) -> Self {
94 Self {
95 source,
96 weight,
97 total_bytes: 0,
98 failures: 0,
99 last_entropy: 0.0,
100 last_min_entropy: 0.0,
101 last_collect_time: Duration::ZERO,
102 healthy: true,
103 }
104 }
105}