1use sva_samples::Extent;
4
5use super::RenderConfig;
6use super::table::{Pulled, Table};
7use super::until::{Known, Until};
8use crate::cache::Recording;
9use crate::error::EngineError;
10use crate::flops::Work;
11use crate::query::{DEFAULT_FRAME_SECS, Representation};
12
13pub(super) struct Driver {
14 pub(super) table: Table,
15 pub(super) start: i64,
16 pub(super) at: i64,
17 last: i64,
18 block: usize,
19 until: Option<Until>,
20 frame: usize,
21 stop: Option<i64>,
22 end: Option<i64>,
23 keep: i64,
25 heard: i64,
27 most_bytes: usize,
28 pub(super) work: Work,
29 pub(super) recording: Recording,
30}
31
32pub struct Block {
33 planes: Vec<Vec<f64>>,
34 start: i64,
35}
36
37impl Block {
38 pub fn start(&self) -> i64 {
39 self.start
40 }
41
42 pub fn len(&self) -> usize {
43 self.planes[0].len()
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.len() == 0
48 }
49
50 pub fn width(&self) -> usize {
51 self.planes.len()
52 }
53
54 pub fn plane(&self, c: usize) -> &[f64] {
55 &self.planes[c]
56 }
57
58 pub(super) fn widened(mut self, width: usize) -> Block {
60 if self.planes.len() == 1 {
61 let copies = vec![self.planes[0].clone(); width.saturating_sub(1)];
62 self.planes.extend(copies);
63 }
64 self
65 }
66}
67
68pub(super) fn frame(config: &RenderConfig, rate: u32) -> usize {
70 let secs = config
71 .asks
72 .iter()
73 .find_map(|ask| match ask.representation {
74 Representation::Envelope { frame_secs } => Some(frame_secs),
75 _ => None,
76 })
77 .flatten()
78 .unwrap_or(DEFAULT_FRAME_SECS);
79 ((secs * f64::from(rate)).round() as usize).max(1)
80}
81
82impl Driver {
83 pub(super) fn new(
84 table: Table,
85 range: Extent,
86 block: usize,
87 config: &RenderConfig,
88 recording: Recording,
89 ) -> Driver {
90 let frame = frame(config, config.rate);
91 Driver {
92 table,
93 start: range.start,
94 at: range.start,
95 heard: range.start,
96 last: range.end,
97 block,
98 keep: config.until.as_ref().map_or(0, |_| frame as i64),
99 until: config.until.clone(),
100 frame,
101 stop: None,
102 end: None,
103 most_bytes: 0,
104 work: Work {
105 waves: Some(0),
106 ..Work::default()
107 },
108 recording,
109 }
110 }
111
112 pub(super) fn bound(&mut self, last: i64) {
114 self.last = last;
115 if self.stop.is_none() {
116 self.end = None;
117 }
118 }
119
120 pub(super) fn last(&self) -> i64 {
121 self.last
122 }
123
124 pub(super) fn next(&self) -> Extent {
125 Extent::new(self.at, self.next_to(self.block))
126 }
127
128 fn next_to(&self, n: usize) -> i64 {
129 self.last.min(self.at.saturating_add(n as i64)).max(self.at)
130 }
131
132 pub(super) fn read(&mut self, n: usize) -> Result<Option<Block>, EngineError> {
134 let from = self.at;
135 if !self.pulled(n)? {
136 return Ok(None);
137 }
138 let end = self.end.map_or(self.at, |end| end.clamp(from, self.at));
139 let held = self.table.samples(self.table.root, Extent::new(from, end));
140 Ok(Some(Block {
141 planes: held.planes,
142 start: from,
143 }))
144 }
145
146 pub(super) fn skip(&mut self, to: i64) -> Result<Vec<usize>, EngineError> {
149 if self.end.is_some_and(|end| self.at >= end) {
150 return Ok(Vec::new());
151 }
152 let to = to.min(self.last);
153 let silenced = self.table.skipped(Extent::new(to, self.last))?;
154 self.recording.reach(to);
155 (self.at, self.heard) = (to, to);
156 let future = (to < self.last).then(|| Extent::new(to, self.last));
157 self.table.release(future, Extent::NOWHERE, self.start);
158 if self.last <= to {
159 self.end = Some(to);
160 }
161 Ok(silenced)
162 }
163
164 pub(super) fn pull(&mut self) -> Result<bool, EngineError> {
165 self.pulled(self.block)
166 }
167
168 pub(super) fn pulled(&mut self, n: usize) -> Result<bool, EngineError> {
170 let from = self.at;
171 if self.end.is_some_and(|end| from >= end) {
172 return Ok(false);
173 }
174 let to = self.next_to(n);
175 self.recording.reach(from);
176 let window = Extent::new(from, to);
177 if from == self.start {
178 let history = self
179 .table
180 .history(window, self.block as i64, &mut self.recording)?;
181 self.priced(&history);
182 }
183 let pulled = self.table.pull(window, &mut self.recording)?;
184 self.priced(&pulled);
185 self.work.samples += (to - from) as u64;
186 self.at = to;
187 self.settle(from, to);
188 let future = (to < self.last).then(|| Extent::new(to, self.last));
189 let keep = Extent::new(from.min(to.saturating_sub(self.keep)), to);
190 self.table.release(future, keep, self.start);
191 Ok(true)
192 }
193
194 fn priced(&mut self, pulled: &Pulled) {
195 self.work.priced_flops += pulled.priced;
196 self.work.waves = self.work.waves.map(|held| held + pulled.waves);
197 self.most_bytes = self.most_bytes.max(pulled.most_bytes);
198 }
199
200 pub(super) fn most_bytes(&self) -> usize {
201 self.most_bytes
202 }
203
204 fn settle(&mut self, from: i64, to: i64) {
207 if self.end.is_some() {
208 return;
209 }
210 if self.last <= to {
211 self.end = Some(to);
212 }
213 let Some(until) = &self.until else {
214 return;
215 };
216 let frame = self.frame as i64;
217 let open = self.start + (from - 1 - self.start).div_euclid(frame) * frame;
218 let base = open.max(self.heard);
219 let heard = self.table.samples(self.table.root, Extent::new(base, to));
220 let planes: Vec<&[f64]> = heard.planes.iter().map(Vec::as_slice).collect();
221 let rate = self.table.values[self.table.root].grid.rate;
222 let known = Known::new(planes, base, self.start, self.frame, rate, to == self.last);
223 if let Some(at) = until.first(&known, base, to) {
224 self.stop = Some(at);
225 self.end = Some(at.max(from));
226 }
227 }
228
229 pub(super) fn end(&self) -> Option<i64> {
230 self.end
231 }
232
233 pub(super) fn stop(&self) -> Option<i64> {
234 self.stop
235 }
236}