1use how_far::Pulse;
4use zencodec::decode::{DecodeRowSink, Event, IncrementalDecode, OutputInfo, StepError};
5
6use crate::drive::Progressor;
7use crate::stepper::{PumpFailure, ReadCursor};
8use crate::window::check_need;
9
10pub type PumpError<E> = PumpFailure<StepError<E>>;
13
14pub fn pump_read_to_sink<R, D>(
23 mut reader: R,
24 decoder: &mut D,
25 sink: &mut dyn DecodeRowSink,
26 pulse: Option<&dyn Pulse>,
27 read_size: usize,
28 max_window: usize,
29) -> Result<OutputInfo, PumpError<D::Error>>
30where
31 R: std::io::Read,
32 D: IncrementalDecode + ?Sized,
33{
34 let mut progress = Progressor::new(pulse);
35 let mut cursor = ReadCursor::new(read_size, max_window);
36 loop {
37 let input = cursor.offer();
38 let p = decoder.step(input, sink, pulse).map_err(PumpError::Step)?;
39 if p.event == Event::Need {
40 check_need(decoder.requested(), &input, p.consumed).map_err(PumpError::Protocol)?;
41 }
42 cursor.take(p.consumed);
43 progress.observe(decoder, &p.event);
44 match p.event {
45 Event::Done(info) => return Ok(info),
46 Event::Need => cursor.serve(&mut reader, decoder.requested())?,
47 _ => {}
48 }
49 }
50}