mod codec;
mod index;
pub(crate) mod log;
mod persist;
mod stats;
mod store;
mod stored;
pub use codec::STORE_FORMAT;
pub use persist::{
Backend, DEFAULT_STORE_BYTES, INDEX_NAME, NoStore, Persisted, Store, Stored, Through,
};
pub(crate) use stats::Recording;
pub use stats::{CacheStats, Lookup, Outcome};
pub(crate) use store::joined;
pub use store::{Cache, CachePolicy, DEFAULT_CACHE_BYTES, DEFAULT_MARK_EVERY, PrunePolicy};
pub(crate) use stored::node_key;
pub use sva_formula::Hash;
use std::collections::BTreeMap;
use sva_samples::{Buffer, Frames, Label, MachineState};
#[derive(Clone, Debug, PartialEq)]
pub enum Payload {
Segments(Vec<Buffer>),
Frames(Box<Frames>),
Run(Box<Run>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PayloadKind {
Segments,
Frames,
Run,
}
#[derive(Clone)]
pub struct Run {
pub samples: Buffer,
pub marks: BTreeMap<i64, MachineState>,
pub parent: Option<Hash>,
}
impl Run {
pub fn end(&self) -> i64 {
self.samples.extent().end
}
pub fn bytes(&self) -> usize {
let marks: usize = self.marks.values().map(MachineState::bytes).sum();
self.samples.len() * self.samples.width * size_of::<f64>() + marks
}
}
impl PartialEq for Run {
fn eq(&self, other: &Run) -> bool {
self.samples == other.samples
}
}
impl std::fmt::Debug for Run {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Run")
.field("samples", &self.samples.extent())
.finish()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Expected {
Segments { rate: u32, width: usize },
Frames,
Run { rate: u32, width: usize },
}
#[derive(Clone, Debug, PartialEq)]
pub struct Entry {
pub payload: Payload,
pub label: Option<Label>,
}
impl Payload {
pub fn run(self) -> Option<Run> {
match self {
Payload::Run(run) => Some(*run),
_ => None,
}
}
pub fn bytes(&self) -> usize {
match self {
Payload::Segments(parts) => parts
.iter()
.map(|b| b.len() * b.width * size_of::<f64>())
.sum(),
Payload::Frames(f) => f.width * f.frames * f.bins * 2 * size_of::<f64>(),
Payload::Run(run) => run.bytes(),
}
}
pub fn answers(&self, expected: Expected) -> bool {
match (self, expected) {
(Payload::Segments(parts), Expected::Segments { rate, width }) => {
parts.iter().all(|b| b.rate == rate && b.width == width)
}
(Payload::Frames(_), Expected::Frames) => true,
(Payload::Run(run), Expected::Run { rate, width }) => {
run.samples.rate == rate && run.samples.width == width
}
_ => false,
}
}
}
pub fn frames_key(value: Hash, window: usize, hop: usize) -> Hash {
mixed(
value,
&[window as u64, hop as u64, 0x66_72_61_6d_65_73_00_01],
)
}
pub fn value_key(
identity: Hash,
step: (i128, i128),
rate: u32,
width: usize,
profile: &sva_samples::Profile,
) -> Hash {
mixed(
identity,
&[
step.0 as u64,
step.1 as u64,
u64::from(rate),
width as u64,
profile.precision_bits as u64,
profile.ceiling_hz.to_bits(),
profile.prune_db.to_bits(),
0x76_61_6c_75_65_00_00_01,
],
)
}
const ADDRESS_ROTATE: u32 = 17;
pub(crate) fn mixed(seed: Hash, parts: &[u64]) -> Hash {
let mut lanes = sva_formula::Lanes::<ADDRESS_ROTATE>::from(seed);
for part in parts {
lanes.word(*part);
}
lanes.finish()
}