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