Skip to main content

sva_engine/cache/
stored.rs

1// Concern: what the tier answers of a node, and where a disk entry lays its samples | Non-concern: reading them, the bytes (codec.rs) | IO: Header -> extents
2
3use sva_formula::{Codomain, Hash};
4use sva_samples::{Extent, Grid, Label};
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct Stored {
8    pub key: Hash,
9    pub identity: Hash,
10    pub label: Label,
11    pub width: u8,
12    pub codomain: Codomain,
13    pub rate: Option<u32>,
14    pub grid: Grid,
15    pub support: Extent,
16    /// The most seconds a read under it moved to land on a sample.
17    pub moved: f64,
18    pub readable: bool,
19    pub sampled: bool,
20    pub cut: Option<Cut>,
21    pub(crate) held: Vec<Extent>,
22}
23
24/// Where a node read open ends, as a render found: a function of its key and this threshold.
25#[derive(Clone, Copy, Debug, PartialEq)]
26pub struct Cut {
27    pub silence_threshold_dbfs: f64,
28    pub treated_as_silent_from_sample: Option<i64>,
29}
30
31impl Stored {
32    pub(crate) fn extents(&self) -> &[Extent] {
33        &self.held
34    }
35
36    pub(crate) fn holds(&self, over: Extent) -> bool {
37        let mut from = over.start;
38        for part in &self.held {
39            if from >= over.end || part.start > from {
40                break;
41            }
42            from = from.max(part.end);
43        }
44        from >= over.end
45    }
46
47    pub(crate) fn holding(&self, mut held: Vec<Extent>) -> Stored {
48        held.sort_by_key(|e| e.start);
49        Stored {
50            held,
51            ..self.clone()
52        }
53    }
54}
55
56/// Only the disk tier and the memory tier read a layout. What it holds is its layout's alone.
57#[derive(Clone, Debug, PartialEq)]
58pub(crate) struct Header {
59    stored: Stored,
60    samples: Samples,
61}
62
63#[derive(Clone, Debug, Default, PartialEq)]
64pub(crate) enum Samples {
65    #[default]
66    None,
67    /// Its `n` is the file's `n - shift`.
68    Entry {
69        file: Hash,
70        runs: Vec<Laid>,
71        shift: i64,
72    },
73    Staged {
74        file: Hash,
75        chunks: Vec<(String, Extent)>,
76        shift: i64,
77    },
78    /// As written: sample `n` is `key`'s sample `n + by`.
79    Of { key: Hash, by: i64 },
80}
81
82#[derive(Clone, Debug, PartialEq)]
83pub(crate) struct Laid {
84    pub(crate) rate: u32,
85    pub(crate) start: i64,
86    pub(crate) width: usize,
87    pub(crate) len: usize,
88    /// Its first byte.
89    pub(crate) at: u64,
90    pub(crate) sums: Vec<u64>,
91}
92
93impl Laid {
94    pub(crate) fn extent(&self) -> Extent {
95        Extent::new(self.start, self.start + self.len as i64)
96    }
97}
98
99impl Samples {
100    fn extents(&self) -> Vec<Extent> {
101        match self {
102            Samples::None | Samples::Of { .. } => Vec::new(),
103            Samples::Entry { runs, shift, .. } => runs
104                .iter()
105                .map(|run| run.extent().shifted(*shift))
106                .collect(),
107            Samples::Staged { chunks, shift, .. } => {
108                chunks.iter().map(|(_, e)| e.shifted(*shift)).collect()
109            }
110        }
111    }
112}
113
114impl Header {
115    pub(crate) fn new(stored: Stored, samples: Samples) -> Header {
116        let stored = stored.holding(samples.extents());
117        Header { stored, samples }
118    }
119
120    pub(crate) fn stored(&self) -> &Stored {
121        &self.stored
122    }
123
124    pub(crate) fn samples(&self) -> &Samples {
125        &self.samples
126    }
127
128    pub(crate) fn into_parts(self) -> (Stored, Samples) {
129        (self.stored, self.samples)
130    }
131
132    pub(crate) fn refers(&self) -> bool {
133        matches!(self.samples, Samples::Of { .. })
134    }
135}