1use alloc::vec::Vec;
16use core::convert::Infallible;
17use core::fmt;
18
19use zencodec::decode::{ByteRange, Input, InputRequest};
20use zencodec::source::ReadAt;
21
22use crate::admission::{self, InputError};
23use crate::drive::{DriveOptions, DriveStats};
24use crate::window::{ProtocolViolation, Window, check_need, read_target};
25
26pub trait ByteStepper {
28 type Output;
31 type Error;
33
34 fn step(
37 &mut self,
38 input: Input<'_>,
39 pulse: Option<&dyn zencodec::Pulse>,
40 ) -> Result<Stepped<Self::Output>, Self::Error>;
41
42 fn requested(&self) -> &[InputRequest];
44}
45
46#[derive(Debug)]
48pub struct Stepped<O> {
49 pub consumed: usize,
51 pub step: Step<O>,
53}
54
55#[derive(Debug)]
57pub enum Step<O> {
58 Need,
60 Output(O),
62 Finished(O),
64}
65
66#[derive(Debug)]
68pub enum Yield<O> {
69 Output(O),
71 Finished(O),
73}
74
75impl<O> Yield<O> {
76 #[inline]
78 pub fn into_inner(self) -> O {
79 match self {
80 Self::Output(o) | Self::Finished(o) => o,
81 }
82 }
83
84 #[inline]
86 pub fn is_finished(&self) -> bool {
87 matches!(self, Self::Finished(_))
88 }
89}
90
91#[derive(Debug)]
93#[non_exhaustive]
94pub enum DriveFailure<E, SE> {
95 Step(E),
98 Source(SE),
100 Protocol(ProtocolViolation),
102 Input(InputError),
104}
105
106impl<E: fmt::Display, SE: fmt::Display> fmt::Display for DriveFailure<E, SE> {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match self {
109 Self::Step(e) => write!(f, "{e}"),
110 Self::Source(e) => write!(f, "source: {e}"),
111 Self::Protocol(e) => write!(f, "protocol: {e}"),
112 Self::Input(e) => write!(f, "input: {e}"),
113 }
114 }
115}
116
117impl<E: core::error::Error + 'static, SE: core::error::Error + 'static> core::error::Error
118 for DriveFailure<E, SE>
119{
120 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
121 match self {
122 Self::Step(e) => Some(e),
123 Self::Source(e) => Some(e),
124 Self::Protocol(e) => Some(e),
125 Self::Input(e) => Some(e),
126 }
127 }
128}
129
130impl<E> DriveFailure<E, Infallible> {
131 pub fn widen<SE>(self) -> DriveFailure<E, SE> {
133 match self {
134 Self::Step(e) => DriveFailure::Step(e),
135 Self::Protocol(p) => DriveFailure::Protocol(p),
136 Self::Input(e) => DriveFailure::Input(e),
137 Self::Source(never) => match never {},
138 }
139 }
140}
141
142type Next<S, SE> =
145 Result<Yield<<S as ByteStepper>::Output>, DriveFailure<<S as ByteStepper>::Error, SE>>;
146
147pub(crate) fn slice_span(
152 start: usize,
153 end: usize,
154 window: usize,
155 total: usize,
156 requests: &[InputRequest],
157) -> (usize, usize) {
158 match requests[0] {
159 InputRequest::AtLeast { offset, min_len } => {
160 let s = offset as usize;
161 (s, s.saturating_add(min_len.max(window)).min(total))
162 }
163 InputRequest::Range(r) => (r.offset as usize, r.end() as usize),
164 _ => (start, end),
167 }
168}
169
170#[derive(Debug)]
176pub struct SliceCursor {
177 start: usize,
178 end: usize,
179 window: usize,
180 stats: DriveStats,
181}
182
183impl SliceCursor {
184 pub fn new(window: usize) -> Self {
187 Self {
188 start: 0,
189 end: 0,
190 window: window.max(1),
191 stats: DriveStats::default(),
192 }
193 }
194
195 pub fn stats(&self) -> DriveStats {
197 self.stats
198 }
199
200 #[inline]
204 pub(crate) fn offer<'b>(&mut self, bytes: &'b [u8]) -> Input<'b> {
205 self.end = self.end.min(bytes.len());
206 self.start = self.start.min(self.end);
207 Input::new(self.start as u64, &bytes[self.start..self.end])
208 .with_total_len(bytes.len() as u64)
209 }
210
211 #[inline]
213 pub(crate) fn take(&mut self, consumed: usize) {
214 self.stats.steps += 1;
215 self.start += consumed.min(self.end - self.start);
216 }
217
218 pub(crate) fn serve(&mut self, bytes: &[u8], requests: &[InputRequest]) {
221 let (s, e) = slice_span(self.start, self.end, self.window, bytes.len(), requests);
222 self.start = s;
223 self.end = e;
224 self.stats.reads += 1;
225 self.stats.bytes_read += (e - s) as u64;
226 }
227
228 #[inline]
231 pub fn next<S: ByteStepper + ?Sized>(
232 &mut self,
233 bytes: &[u8],
234 stage: &mut S,
235 pulse: Option<&dyn zencodec::Pulse>,
236 ) -> Next<S, Infallible> {
237 loop {
238 let input = self.offer(bytes);
239 let p = stage.step(input, pulse).map_err(DriveFailure::Step)?;
240 self.take(p.consumed);
241 if matches!(p.step, Step::Need) {
242 check_need(stage.requested(), &input, p.consumed)
243 .map_err(DriveFailure::Protocol)?;
244 }
245 match p.step {
246 Step::Output(o) => return Ok(Yield::Output(o)),
247 Step::Finished(o) => return Ok(Yield::Finished(o)),
248 Step::Need => self.serve(bytes, stage.requested()),
249 }
250 }
251 }
252}
253
254#[derive(Debug)]
265pub struct ReadAtCursor {
266 opts: DriveOptions,
267 stats: DriveStats,
268 window: Window,
269 started: bool,
270 fetched: Vec<(u64, Vec<u8>)>,
272 coalesced: Vec<ByteRange>,
273 from_fetched: Option<(usize, usize)>,
275 slice: Option<SliceCursor>,
277}
278
279impl ReadAtCursor {
280 pub fn new(opts: DriveOptions) -> Self {
282 Self {
283 opts,
284 stats: DriveStats::default(),
285 window: Window::new(),
286 started: false,
287 fetched: Vec::new(),
288 coalesced: Vec::new(),
289 from_fetched: None,
290 slice: None,
291 }
292 }
293
294 pub fn stats(&self) -> DriveStats {
296 match &self.slice {
297 Some(s) => s.stats(),
298 None => self.stats,
299 }
300 }
301
302 pub fn retained_input_capacity(&self) -> usize {
304 self.window
305 .capacity()
306 .saturating_add(admission::capacity(&self.fetched))
307 }
308
309 pub(crate) fn offer<'a, Src: ReadAt + ?Sized>(&'a mut self, source: &'a Src) -> Input<'a> {
313 if !self.started {
314 self.started = true;
315 if source.as_slice().is_some() {
316 self.slice = Some(SliceCursor::new(self.opts.read_size));
317 } else {
318 self.window.total = source.len_hint();
319 }
320 }
321 if let Some(cursor) = &mut self.slice {
322 let bytes = source.as_slice().expect("the source stays in memory");
323 return cursor.offer(bytes);
324 }
325 match self.from_fetched {
326 Some((i, at)) => {
327 let (off, buf) = &self.fetched[i];
328 Input::new(off + at as u64, &buf[at..]).with_total_len_opt(self.window.total)
329 }
330 None => self.window.input(),
331 }
332 }
333
334 #[inline]
336 pub(crate) fn take(&mut self, consumed: usize) {
337 if let Some(cursor) = &mut self.slice {
338 return cursor.take(consumed);
339 }
340 self.stats.steps += 1;
341 match &mut self.from_fetched {
342 Some((i, at)) => {
346 let len = self.fetched.get(*i).map_or(0, |(_, b)| b.len());
347 *at = at.saturating_add(consumed).min(len);
348 }
349 None => self.window.consume(consumed),
350 }
351 }
352
353 #[inline]
356 pub fn next<S, Src>(
357 &mut self,
358 source: &mut Src,
359 stage: &mut S,
360 pulse: Option<&dyn zencodec::Pulse>,
361 ) -> Next<S, Src::Error>
362 where
363 S: ByteStepper + ?Sized,
364 Src: ReadAt + ?Sized,
365 {
366 if !self.started && source.as_slice().is_some() {
367 self.started = true;
368 self.slice = Some(SliceCursor::new(self.opts.read_size));
369 }
370 if let Some(cursor) = &mut self.slice {
371 let bytes = source.as_slice().expect("the source stays in memory");
372 return cursor
373 .next(bytes, stage, pulse)
374 .map_err(DriveFailure::widen);
375 }
376 loop {
377 let input = self.offer(source);
378 let p = stage.step(input, pulse).map_err(DriveFailure::Step)?;
379 if matches!(p.step, Step::Need) {
380 check_need(stage.requested(), &input, p.consumed)
381 .map_err(DriveFailure::Protocol)?;
382 }
383 self.take(p.consumed);
384 match p.step {
385 Step::Output(o) => return Ok(Yield::Output(o)),
386 Step::Finished(o) => return Ok(Yield::Finished(o)),
387 Step::Need => self.serve(stage.requested(), source)?,
388 }
389 }
390 }
391
392 pub(crate) fn serve<E, Src: ReadAt + ?Sized>(
394 &mut self,
395 requests: &[InputRequest],
396 source: &mut Src,
397 ) -> Result<(), DriveFailure<E, Src::Error>> {
398 let window = &mut self.window;
399 let limits = self.opts.limits;
400 let request = admission::select(requests, limits).map_err(DriveFailure::Input)?;
401 match request {
402 InputRequest::AtLeast { offset, min_len } => {
403 self.from_fetched = None;
404 window.position(offset, &mut self.fetched);
405 if window.len() >= min_len.max(1) {
408 return Ok(());
409 }
410 limits.reading().map_err(DriveFailure::Input)?;
414 let target = read_target(min_len, self.opts.read_size)
415 .min(limits.max_input_bytes())
416 .min(usize::try_from(u64::MAX - offset).unwrap_or(usize::MAX));
417 admission::make_room(window, &mut self.fetched, target, limits);
418 while window.len() < target && window.total != Some(window.end()) {
419 let end = window.end();
420 let n_want = (target - window.len())
421 .min(usize::try_from(u64::MAX - end).unwrap_or(usize::MAX));
422 let spare = window
423 .try_spare(
424 n_want,
425 limits.max_input_bytes() - admission::capacity(&self.fetched),
426 )
427 .map_err(DriveFailure::Input)?;
428 let n = source.read_at(end, spare).map_err(DriveFailure::Source)?;
429 window.commit(n);
430 self.stats.reads += 1;
431 self.stats.bytes_read += n as u64;
432 if n < n_want {
433 window.total = Some(end + n as u64);
434 }
435 }
436 }
437 InputRequest::Range(first) => {
438 if first.offset >= window.base() && first.end() <= window.end() {
439 self.from_fetched = None;
440 window.consume((first.offset - window.base()) as usize);
441 return Ok(());
442 }
443 let holds = |(off, buf): &(u64, Vec<u8>)| {
444 first.offset >= *off && first.end() <= off + buf.len() as u64
445 };
446 if let Some(i) = self.fetched.iter().position(holds) {
448 self.from_fetched = Some((i, (first.offset - self.fetched[i].0) as usize));
449 return Ok(());
450 }
451 self.from_fetched = None;
452 if window.position(first.offset, &mut self.fetched) {
453 let missing = (first.end() - window.end()) as usize;
456 let offset = window.end();
457 limits.reading().map_err(DriveFailure::Input)?;
458 admission::make_room(window, &mut self.fetched, first.length as usize, limits);
459 let spare = window
460 .try_spare(
461 missing,
462 limits.max_input_bytes() - admission::capacity(&self.fetched),
463 )
464 .map_err(DriveFailure::Input)?;
465 source
466 .read_exact_at(offset, spare)
467 .map_err(DriveFailure::Source)?;
468 window.commit(missing);
469 self.stats.reads += 1;
470 self.stats.bytes_read += missing as u64;
471 return Ok(());
472 }
473 admission::plan(
475 first,
476 requests,
477 self.opts.max_gap,
478 limits,
479 &mut self.coalesced,
480 )
481 .map_err(DriveFailure::Input)?;
482 window.release();
483 let mut pending = core::mem::take(&mut self.fetched);
484 admission::allocate_ranges(&self.coalesced, limits, &mut pending)
485 .map_err(DriveFailure::Input)?;
486 {
487 let mut reqs = Vec::new();
488 admission::reserve(&mut reqs, pending.len()).map_err(DriveFailure::Input)?;
489 reqs.extend(pending.iter_mut().map(|(off, buf)| (*off, &mut buf[..])));
490 for batch in reqs.chunks_mut(limits.max_in_flight()) {
491 source.read_many_at(batch).map_err(DriveFailure::Source)?;
492 self.stats.reads += 1;
493 }
494 }
495 self.fetched = pending;
497 self.stats.bytes_read += self.coalesced.iter().map(|r| r.length).sum::<u64>();
498 let i = self
499 .fetched
500 .iter()
501 .position(holds)
502 .expect("coalesced ranges cover every request");
503 self.from_fetched = Some((i, (first.offset - self.fetched[i].0) as usize));
504 }
505 InputRequest::Len => {
506 self.from_fetched = None;
507 if window.total.is_none() {
508 limits.reading().map_err(DriveFailure::Input)?;
509 window.total = Some(source.len().map_err(DriveFailure::Source)?);
510 }
511 }
512 _ => return Err(DriveFailure::Protocol(ProtocolViolation::EmptyRequest)),
513 }
514 Ok(())
515 }
516}
517
518#[cfg(feature = "std")]
519pub use read::{PumpFailure, ReadCursor};
520
521#[cfg(feature = "std")]
522mod read {
523 use super::*;
524
525 #[derive(Debug)]
527 #[non_exhaustive]
528 pub enum PumpFailure<E> {
529 Step(E),
531 Io(std::io::Error),
533 NeedsRandomAccess(InputRequest),
538 WindowLimit {
540 needed: usize,
542 limit: usize,
544 },
545 Protocol(ProtocolViolation),
547 Input(InputError),
549 }
550
551 impl<E: fmt::Display> fmt::Display for PumpFailure<E> {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 match self {
554 Self::Step(e) => write!(f, "{e}"),
555 Self::Io(e) => write!(f, "reading the stream: {e}"),
556 Self::NeedsRandomAccess(r) => write!(
557 f,
558 "decoder needs random access ({r:?}); a sequential stream cannot serve it"
559 ),
560 Self::WindowLimit { needed, limit } => write!(
561 f,
562 "decoder needs {needed} contiguous bytes, over the {limit}-byte window limit"
563 ),
564 Self::Protocol(e) => write!(f, "protocol: {e}"),
565 Self::Input(e) => write!(f, "input: {e}"),
566 }
567 }
568 }
569
570 impl<E: core::error::Error + 'static> core::error::Error for PumpFailure<E> {
571 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
572 match self {
573 Self::Step(e) => Some(e),
574 Self::Io(e) => Some(e),
575 Self::Protocol(e) => Some(e),
576 Self::Input(e) => Some(e),
577 _ => None,
578 }
579 }
580 }
581
582 #[derive(Debug)]
591 pub struct ReadCursor {
592 read_size: usize,
593 max_window: usize,
594 window: Window,
595 }
596
597 impl ReadCursor {
598 pub fn new(read_size: usize, max_window: usize) -> Self {
601 Self {
602 read_size: read_size.max(512),
603 max_window,
604 window: Window::new(),
605 }
606 }
607
608 pub fn retained_input_capacity(&self) -> usize {
610 self.window.capacity()
611 }
612
613 #[inline]
615 pub(crate) fn offer(&self) -> Input<'_> {
616 self.window.input()
617 }
618
619 #[inline]
621 pub(crate) fn take(&mut self, consumed: usize) {
622 self.window.consume(consumed);
623 }
624
625 pub(crate) fn serve<R, E>(
628 &mut self,
629 reader: &mut R,
630 requests: &[InputRequest],
631 ) -> Result<(), PumpFailure<E>>
632 where
633 R: std::io::Read + ?Sized,
634 {
635 let window = &mut self.window;
636 let request = requests
639 .iter()
640 .copied()
641 .find(|r| r.offset().is_some_and(|o| o >= window.base()))
642 .unwrap_or(requests[0]);
643 let (offset, min_len) = match request {
644 InputRequest::AtLeast { offset, min_len } => (offset, min_len),
645 InputRequest::Range(r) => (
646 r.offset,
647 usize::try_from(r.length).map_err(|_| {
648 PumpFailure::Input(InputError::Limit {
649 needed: r.length,
650 limit: self.max_window,
651 })
652 })?,
653 ),
654 _ => return Err(PumpFailure::NeedsRandomAccess(request)),
655 };
656 if offset < window.base() {
657 return Err(PumpFailure::NeedsRandomAccess(request));
658 }
659 if min_len.max(1) > self.max_window {
660 return Err(PumpFailure::WindowLimit {
661 needed: min_len.max(1),
662 limit: self.max_window,
663 });
664 }
665 while offset > window.end() && window.total.is_none() {
667 let end = window.end();
668 window.reset_to(end);
669 let want = usize::try_from(offset - end)
670 .unwrap_or(usize::MAX)
671 .min(self.read_size)
672 .min(self.max_window);
673 let spare = window
674 .try_spare(want, self.max_window)
675 .map_err(PumpFailure::Input)?;
676 let n = reader.read(spare).map_err(PumpFailure::Io)?;
677 window.commit(n);
678 if n == 0 {
679 window.total = Some(end);
680 }
681 }
682 if offset <= window.end() {
683 window.consume((offset - window.base()) as usize);
684 }
685 let target = read_target(min_len, self.read_size)
688 .min(self.max_window)
689 .min(usize::try_from(u64::MAX - offset).unwrap_or(usize::MAX));
690 while window.len() < min_len.max(1) && window.total.is_none() {
691 let end = window.end();
692 let want = target - window.len().min(target);
693 let spare = window
694 .try_spare(want, self.max_window)
695 .map_err(PumpFailure::Input)?;
696 let n = reader.read(spare).map_err(PumpFailure::Io)?;
697 window.commit(n);
698 if n == 0 {
699 window.total = Some(end);
700 }
701 }
702 Ok(())
703 }
704
705 #[inline]
708 pub fn next<S, R>(
709 &mut self,
710 reader: &mut R,
711 stage: &mut S,
712 pulse: Option<&dyn zencodec::Pulse>,
713 ) -> Result<Yield<S::Output>, PumpFailure<S::Error>>
714 where
715 S: ByteStepper + ?Sized,
716 R: std::io::Read + ?Sized,
717 {
718 loop {
719 let input = self.offer();
720 let p = stage.step(input, pulse).map_err(PumpFailure::Step)?;
721 if matches!(p.step, Step::Need) {
722 check_need(stage.requested(), &input, p.consumed)
723 .map_err(PumpFailure::Protocol)?;
724 }
725 self.take(p.consumed);
726 match p.step {
727 Step::Output(o) => return Ok(Yield::Output(o)),
728 Step::Finished(o) => return Ok(Yield::Finished(o)),
729 Step::Need => self.serve(reader, stage.requested())?,
730 }
731 }
732 }
733 }
734}