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