print_raster 0.1.0

A crate for processing print raster images in Rust
Documentation
use byteorder::{BigEndian, LittleEndian};
use futures::AsyncRead;
use pin_project::pin_project;
use std::io;
use std::task::{Context, Poll};
use std::{future::Future, ops::DerefMut, pin::Pin};
mod page;
use crate::decode::{CupsRasterUnifiedDecoder, Limits};
use crate::error::CupsRasterError;
use crate::factory::{CupsPageFactoryV1, CupsPageFactoryV2, CupsPageFactoryV3};
use crate::model::cups::{CupsPageHeaderV2, CupsSyncWord};
use crate::model::RasterByteOrder;
use crate::reader::common::CommonRasterPageReaderFor;
use crate::reader::RasterReader;
pub use page::*;

pub struct CupsRasterUnifiedReader<R> {
    sync_word: CupsSyncWord,
    reader: Pin<R>,
    limits: Limits,
}

impl<R> CupsRasterUnifiedReader<R>
where
    R: DerefMut<Target: AsyncRead>,
{
    pub async fn new(reader: Pin<R>) -> Result<Self, CupsRasterError> {
        Self::new_with_limits(reader, Limits::default()).await
    }

    pub async fn new_with_limits(
        mut reader: Pin<R>,
        limits: Limits,
    ) -> Result<Self, CupsRasterError> {
        let sync_word = CupsRasterReaderReadSyncWord::new(reader.as_mut()).await?;
        Ok(CupsRasterUnifiedReader {
            sync_word,
            reader,
            limits,
        })
    }

    pub fn sync_word(&self) -> CupsSyncWord {
        self.sync_word
    }

    pub fn byte_order(&self) -> RasterByteOrder {
        self.sync_word.byte_order()
    }
}

impl<R> RasterReader<R> for CupsRasterUnifiedReader<R>
where
    R: DerefMut<Target: AsyncRead>,
{
    type PageHeader = CupsPageHeaderV2;
    type PageReader = CupsRasterUnifiedPageReader<R>;
    type Error = CupsRasterError;
    type NextPageFuture = CupsRasterUnifiedReaderNextPage<R>;

    fn next_page(self) -> CupsRasterUnifiedReaderNextPage<R> {
        match self.sync_word {
            CupsSyncWord::V1BigEndian => CupsRasterUnifiedReaderNextPage::V1BigEndian(
                CupsRasterUnifiedPageReaderV1BE::reader_for(self.reader, self.limits),
            ),
            CupsSyncWord::V1LittleEndian => CupsRasterUnifiedReaderNextPage::V1LittleEndian(
                CupsRasterUnifiedPageReaderV1LE::reader_for(self.reader, self.limits),
            ),
            CupsSyncWord::V2BigEndian => CupsRasterUnifiedReaderNextPage::V2BigEndian(
                CupsRasterUnifiedPageReaderV2BE::reader_for(self.reader, self.limits),
            ),
            CupsSyncWord::V2LittleEndian => CupsRasterUnifiedReaderNextPage::V2LittleEndian(
                CupsRasterUnifiedPageReaderV2LE::reader_for(self.reader, self.limits),
            ),
            CupsSyncWord::V3BigEndian => CupsRasterUnifiedReaderNextPage::V3BigEndian(
                CupsRasterUnifiedPageReaderV3BE::reader_for(self.reader, self.limits),
            ),
            CupsSyncWord::V3LittleEndian => CupsRasterUnifiedReaderNextPage::V3LittleEndian(
                CupsRasterUnifiedPageReaderV3LE::reader_for(self.reader, self.limits),
            ),
        }
    }
}

#[pin_project(project = CupsRasterUnifiedReaderNextPageProj)]
pub enum CupsRasterUnifiedReaderNextPage<R>
where
    R: DerefMut<Target: AsyncRead>,
{
    V1BigEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV1<BigEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
    V1LittleEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV1<LittleEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
    V2BigEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV2<BigEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
    V2LittleEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV2<LittleEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
    V3BigEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV3<BigEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
    V3LittleEndian(
        #[pin]
        CommonRasterPageReaderFor<
            CupsPageFactoryV3<LittleEndian>,
            CupsPageHeaderV2,
            CupsRasterUnifiedDecoder<R>,
            R,
        >,
    ),
}

impl<R> Future for CupsRasterUnifiedReaderNextPage<R>
where
    R: DerefMut<Target: AsyncRead>,
{
    type Output = Result<Option<CupsRasterUnifiedPageReader<R>>, CupsRasterError>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        match this {
            CupsRasterUnifiedReaderNextPageProj::V1BigEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
            CupsRasterUnifiedReaderNextPageProj::V1LittleEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
            CupsRasterUnifiedReaderNextPageProj::V2BigEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
            CupsRasterUnifiedReaderNextPageProj::V2LittleEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
            CupsRasterUnifiedReaderNextPageProj::V3BigEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
            CupsRasterUnifiedReaderNextPageProj::V3LittleEndian(reader) => reader
                .poll(cx)
                .map(|result| result.map(|reader| reader.map(CupsRasterUnifiedPageReader::from))),
        }
    }
}

#[pin_project]
struct CupsRasterReaderReadSyncWord<R> {
    buffer: [u8; 4],
    num_read: usize,
    reader: Pin<R>,
}

impl<R> CupsRasterReaderReadSyncWord<R> {
    fn new(reader: Pin<R>) -> Self {
        CupsRasterReaderReadSyncWord {
            buffer: [0; 4],
            num_read: 0,
            reader,
        }
    }
}

impl<R> Future for CupsRasterReaderReadSyncWord<R>
where
    R: DerefMut<Target: AsyncRead>,
{
    type Output = Result<CupsSyncWord, CupsRasterError>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        let mut buffer = &mut this.buffer[*this.num_read..];
        while !buffer.is_empty() {
            match this.reader.as_mut().poll_read(cx, buffer) {
                Poll::Ready(Ok(0)) => {
                    return Poll::Ready(Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()))
                }
                Poll::Ready(Ok(n)) => {
                    buffer = &mut buffer[n..];
                    *this.num_read += n;
                }
                Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())),
                Poll::Pending => return Poll::Pending,
            }
        }

        let sync_word = match this.buffer {
            [b'R', b'a', b'S', b't'] => CupsSyncWord::V1BigEndian,
            [b't', b'S', b'a', b'R'] => CupsSyncWord::V1LittleEndian,
            [b'R', b'a', b'S', b'2'] => CupsSyncWord::V2BigEndian,
            [b'2', b'S', b'a', b'R'] => CupsSyncWord::V2LittleEndian,
            [b'R', b'a', b'S', b'3'] => CupsSyncWord::V3BigEndian,
            [b'3', b'S', b'a', b'R'] => CupsSyncWord::V3LittleEndian,
            _ => return Poll::Ready(Err(CupsRasterError::InvalidSyncWord)),
        };
        Poll::Ready(Ok(sync_word))
    }
}