1mod codec;
4pub(crate) mod log;
5mod persist;
6mod stats;
7mod store;
8
9pub(crate) use persist::node_key;
10pub use persist::{
11 Backend, DEFAULT_STORE_BYTES, NoStore, Persisted, STORE_VERSION, Store, Stored, Through,
12 VERSION_NAME,
13};
14pub(crate) use stats::Recording;
15pub use stats::{CacheStats, Lookup, Outcome};
16pub(crate) use store::joined;
17pub use store::{Cache, CachePolicy, DEFAULT_CACHE_BYTES, DEFAULT_MARK_EVERY, PrunePolicy};
18pub use sva_formula::Hash;
19
20use std::collections::BTreeMap;
21
22use sva_samples::{Buffer, Frames, Label, MachineState};
23
24#[derive(Clone, Debug, PartialEq)]
26pub enum Payload {
27 Segments(Vec<Buffer>),
28 Frames(Box<Frames>),
29 Run(Box<Run>),
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum PayloadKind {
34 Segments,
35 Frames,
36 Run,
37}
38
39#[derive(Clone)]
41pub struct Run {
42 pub samples: Buffer,
43 pub marks: BTreeMap<i64, MachineState>,
44 pub parent: Option<Hash>,
45}
46
47impl Run {
48 pub fn end(&self) -> i64 {
49 self.samples.extent().end
50 }
51
52 pub fn bytes(&self) -> usize {
53 let marks: usize = self.marks.values().map(MachineState::bytes).sum();
54 self.samples.len() * self.samples.width * size_of::<f64>() + marks
55 }
56}
57
58impl PartialEq for Run {
60 fn eq(&self, other: &Run) -> bool {
61 self.samples == other.samples
62 }
63}
64
65impl std::fmt::Debug for Run {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 f.debug_struct("Run")
68 .field("samples", &self.samples.extent())
69 .finish()
70 }
71}
72
73#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75pub enum Expected {
76 Segments { rate: u32, width: usize },
77 Frames,
78 Run { rate: u32, width: usize },
79}
80
81#[derive(Clone, Debug, PartialEq)]
82pub struct Entry {
83 pub payload: Payload,
84 pub label: Option<Label>,
86}
87
88impl Payload {
89 pub fn run(self) -> Option<Run> {
90 match self {
91 Payload::Run(run) => Some(*run),
92 _ => None,
93 }
94 }
95
96 pub fn bytes(&self) -> usize {
97 match self {
98 Payload::Segments(parts) => parts
99 .iter()
100 .map(|b| b.len() * b.width * size_of::<f64>())
101 .sum(),
102 Payload::Frames(f) => f.width * f.frames * f.bins * 2 * size_of::<f64>(),
103 Payload::Run(run) => run.bytes(),
104 }
105 }
106
107 pub fn answers(&self, expected: Expected) -> bool {
108 match (self, expected) {
109 (Payload::Segments(parts), Expected::Segments { rate, width }) => {
110 parts.iter().all(|b| b.rate == rate && b.width == width)
111 }
112 (Payload::Frames(_), Expected::Frames) => true,
113 (Payload::Run(run), Expected::Run { rate, width }) => {
114 run.samples.rate == rate && run.samples.width == width
115 }
116 _ => false,
117 }
118 }
119}
120
121pub fn frames_key(value: Hash, window: usize, hop: usize) -> Hash {
122 mixed(
123 value,
124 &[window as u64, hop as u64, 0x66_72_61_6d_65_73_00_01],
125 )
126}
127
128pub fn value_key(
130 identity: Hash,
131 step: (i128, i128),
132 rate: u32,
133 width: usize,
134 profile: &sva_samples::Profile,
135) -> Hash {
136 mixed(
137 identity,
138 &[
139 step.0 as u64,
140 step.1 as u64,
141 u64::from(rate),
142 width as u64,
143 profile.precision_bits as u64,
144 profile.ceiling_hz.to_bits(),
145 0x76_61_6c_75_65_00_00_01,
146 ],
147 )
148}
149
150const ADDRESS_ROTATE: u32 = 17;
151
152pub(crate) fn mixed(seed: Hash, parts: &[u64]) -> Hash {
153 let mut lanes = sva_formula::Lanes::<ADDRESS_ROTATE>::from(seed);
154 for part in parts {
155 lanes.word(*part);
156 }
157 lanes.finish()
158}