print_raster/reader/common/
mod.rs

1use crate::decode::{Limits, RasterDecoder, RasterDecoderConsumer, RasterDecoderExt};
2use crate::factory::RasterPageFactory;
3use crate::reader::RasterPageReader;
4use futures::ready;
5use futures::task::Context;
6use futures::AsyncRead;
7use pin_project::pin_project;
8use std::future::Future;
9use std::marker::PhantomData;
10use std::ops::DerefMut;
11use std::pin::Pin;
12use std::task::Poll;
13
14/// A common implementation of `RasterPageReader` for all raster formats.
15///
16/// # Type parameters
17/// - `F`: The `RasterPageFactory` implementation for the raster format.
18/// - `HS`: The type to store the header.
19/// - `DS`: The type to store the decoder.
20/// - `R`: The mutable pointer to AsyncRead.
21pub struct CommonRasterPageReader<F, HS, DS, R>
22where
23    F: RasterPageFactory,
24    HS: From<<F as RasterPageFactory>::Header>,
25    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R>,
26    R: DerefMut<Target: AsyncRead>,
27{
28    header: HS,
29    content: DS,
30    limits: Limits,
31    _factory: PhantomData<F>,
32    _reader: PhantomData<R>,
33}
34
35impl<F, HS, DS, R> CommonRasterPageReader<F, HS, DS, R>
36where
37    F: RasterPageFactory,
38    HS: From<<F as RasterPageFactory>::Header>,
39    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R> + Unpin,
40    R: DerefMut<Target: AsyncRead>,
41    F::Error: From<std::io::Error>,
42{
43    /// Consumes the header of next page and returns a reader for the next page.
44    pub fn reader_for(reader: Pin<R>, limits: Limits) -> CommonRasterPageReaderFor<F, HS, DS, R> {
45        CommonRasterPageReaderFor {
46            reader: Some(reader),
47            buffer: vec![0; F::HEADER_SIZE],
48            limits,
49            start: 0,
50            _header_storage: PhantomData,
51            _decoder_storage: PhantomData,
52            _factory: PhantomData,
53        }
54    }
55}
56
57impl<F, HS, DS, R> RasterPageReader<R> for CommonRasterPageReader<F, HS, DS, R>
58where
59    F: RasterPageFactory,
60    HS: From<<F as RasterPageFactory>::Header>,
61    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R> + Unpin,
62    R: DerefMut<Target: AsyncRead>,
63    F::Error: From<std::io::Error>,
64{
65    type Header = HS;
66    type Decoder = DS;
67    type Error = <F as RasterPageFactory>::Error;
68    type NextPageFuture = CommonRasterPageReaderNext<F, HS, DS, R>;
69
70    fn next_page(self) -> Self::NextPageFuture {
71        let limits = self.limits.clone();
72        let content = self.into_content().consume();
73        CommonRasterPageReaderNext::Consume(content, limits)
74    }
75
76    fn header(&self) -> &Self::Header {
77        &self.header
78    }
79
80    fn content_mut(&mut self) -> &mut Self::Decoder {
81        &mut self.content
82    }
83
84    fn into_content(self) -> Self::Decoder {
85        self.content
86    }
87}
88
89#[pin_project]
90pub struct CommonRasterPageReaderFor<F, HS, DS, R>
91where
92    F: RasterPageFactory,
93    HS: From<<F as RasterPageFactory>::Header>,
94    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R>,
95    R: DerefMut<Target: AsyncRead>,
96    F::Error: From<std::io::Error>,
97{
98    reader: Option<Pin<R>>,
99    buffer: Vec<u8>,
100    limits: Limits,
101    start: usize,
102    _header_storage: std::marker::PhantomData<HS>,
103    _decoder_storage: std::marker::PhantomData<DS>,
104    _factory: std::marker::PhantomData<F>,
105}
106
107impl<F, HS, DS, R> Future for CommonRasterPageReaderFor<F, HS, DS, R>
108where
109    F: RasterPageFactory,
110    HS: From<<F as RasterPageFactory>::Header>,
111    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R>,
112    R: DerefMut<Target: AsyncRead>,
113    F::Error: From<std::io::Error>,
114{
115    type Output = Result<Option<CommonRasterPageReader<F, HS, DS, R>>, F::Error>;
116
117    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
118        let this = self.as_mut().project();
119        if this.reader.is_none() {
120            return Poll::Ready(Ok(None));
121        }
122        let reader = this.reader.as_mut().unwrap();
123        loop {
124            let buf = &mut this.buffer[*this.start..];
125            let num_read = ready!(reader.as_mut().poll_read(cx, buf))?;
126            *this.start += num_read;
127            if *this.start >= F::HEADER_SIZE {
128                // header is read
129                break;
130            }
131            if num_read == 0 {
132                return Poll::Ready(Ok(None));
133            }
134        }
135        let header = F::header_from_bytes(this.buffer)?;
136        let content = F::decode(&header, this.reader.take().unwrap(), this.limits)?;
137        Poll::Ready(Ok(Some(CommonRasterPageReader {
138            header: header.into(),
139            content: content.into(),
140            limits: this.limits.clone(),
141            _factory: PhantomData,
142            _reader: PhantomData,
143        })))
144    }
145}
146
147#[pin_project(project = CommonRasterPageReaderNextProj)]
148pub enum CommonRasterPageReaderNext<F, HS, DS, R>
149where
150    F: RasterPageFactory,
151    HS: From<<F as RasterPageFactory>::Header>,
152    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R> + Unpin,
153    R: DerefMut<Target: AsyncRead>,
154    F::Error: From<std::io::Error>,
155{
156    Consume(#[pin] RasterDecoderConsumer<DS, R>, Limits),
157    ReaderFor(#[pin] CommonRasterPageReaderFor<F, HS, DS, R>),
158}
159
160impl<F, HS, DS, R> Future for CommonRasterPageReaderNext<F, HS, DS, R>
161where
162    F: RasterPageFactory,
163    HS: From<<F as RasterPageFactory>::Header>,
164    DS: From<<F as RasterPageFactory>::Decoder<R>> + RasterDecoder<R> + Unpin,
165    R: DerefMut<Target: AsyncRead>,
166    F::Error: From<std::io::Error>,
167{
168    type Output = Result<Option<CommonRasterPageReader<F, HS, DS, R>>, F::Error>;
169
170    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
171        loop {
172            match self.as_mut().project() {
173                CommonRasterPageReaderNextProj::Consume(consumer, limits) => {
174                    let reader = ready!(consumer.poll(cx))?;
175                    let future =
176                        CommonRasterPageReader::<F, HS, DS, R>::reader_for(reader, limits.clone());
177                    self.set(CommonRasterPageReaderNext::ReaderFor(future));
178                }
179                CommonRasterPageReaderNextProj::ReaderFor(future) => return future.poll(cx),
180            }
181        }
182    }
183}