llpr 0.1.2

low-level PDF reader
Documentation
use std::io::{Cursor, Error, Read, Seek, SeekFrom};

type StdResult<R, E> = ::std::result::Result<R, E>;

pub trait Source: Read {
    fn seek(&mut self, pos: SeekFrom) -> StdResult<u64, Error>;
    fn getch(&mut self) -> crate::Result<Option<char>>;
    fn backup(&mut self);
}

pub struct PdfSource<T>
where
    T: Read + Seek,
{
    source: T,
}

impl<T> PdfSource<T>
where
    T: Read + Seek,
{
    pub fn new(source: T) -> PdfSource<T>
    where
        T: Read + Seek,
    {
        PdfSource { source: source }
    }
}

impl<T> Source for PdfSource<T>
where
    T: Read + Seek,
{
    fn seek(&mut self, pos: SeekFrom) -> StdResult<u64, Error> {
        self.source.seek(pos)
    }

    fn getch(&mut self) -> crate::Result<Option<char>> {
        readch(&mut self.source)
    }

    fn backup(&mut self) {
        let _ = self.seek(SeekFrom::Current(-1));
    }
}

impl<T> Read for PdfSource<T>
where
    T: Read + Seek,
{
    fn read(&mut self, buf: &mut [u8]) -> StdResult<usize, Error> {
        self.source.read(buf)
    }
}

pub struct ByteSliceSource<'a> {
    cursor: Cursor<&'a [u8]>,
}

impl<'a> ByteSliceSource<'a> {
    pub fn new(source: &'a [u8]) -> ByteSliceSource<'a> {
        ByteSliceSource {
            cursor: Cursor::new(source),
        }
    }
}

impl<'a> Source for ByteSliceSource<'a> {
    fn seek(&mut self, pos: SeekFrom) -> StdResult<u64, Error> {
        self.cursor.seek(pos)
    }

    fn getch(&mut self) -> crate::Result<Option<char>> {
        readch(&mut self.cursor)
    }

    fn backup(&mut self) {
        let _ = self.seek(SeekFrom::Current(-1));
    }
}

impl<'a> Read for ByteSliceSource<'a> {
    fn read(&mut self, buf: &mut [u8]) -> StdResult<usize, Error> {
        self.cursor.read(buf)
    }
}

pub struct ByteSource {
    cursor: Cursor<Vec<u8>>,
}

impl ByteSource {
    pub fn new(bytes: Vec<u8>) -> ByteSource {
        ByteSource {
            cursor: Cursor::new(bytes),
        }
    }
}

impl Source for ByteSource {
    fn seek(&mut self, pos: SeekFrom) -> StdResult<u64, Error> {
        self.cursor.seek(pos)
    }

    fn getch(&mut self) -> crate::Result<Option<char>> {
        readch(&mut self.cursor)
    }

    fn backup(&mut self) {
        let _ = self.seek(SeekFrom::Current(-1));
    }
}

impl Read for ByteSource {
    fn read(&mut self, buf: &mut [u8]) -> StdResult<usize, Error> {
        self.cursor.read(buf)
    }
}

fn readch(source: &mut dyn Read) -> crate::Result<Option<char>> {
    let mut buffer = [0];
    match source.read(&mut buffer)? {
        0 => Ok(None),
        _ => Ok(Some(buffer[0] as char)),
    }
}