use std::io::BufRead;
use std::mem;
use super::common::{Block, Frame};
mod decoder;
pub use self::decoder::{
Decoded, DecodingError, StreamingDecoder,
};
pub fn read_info<R: BufRead>(r: R) -> Result<Decoder<R>, DecodingError> {
Decoder::with_no_init(r, StreamingDecoder::with_options()).init()
}
struct ReadDecoder<R: BufRead> {
reader: R,
decoder: StreamingDecoder,
at_eof: bool,
}
impl<R: BufRead> ReadDecoder<R> {
fn decode_next(&mut self) -> Result<Option<Decoded>, DecodingError> {
while !self.at_eof {
let (consumed, result) = {
let buf = self.reader.fill_buf()?;
if buf.is_empty() {
return Err(DecodingError::format(
"unexpected EOF"
))
}
self.decoder.update(buf)?
};
self.reader.consume(consumed);
match result {
Decoded::Nothing => (),
Decoded::BlockStart(Block::Trailer) => {
self.at_eof = true
},
result => return Ok(unsafe{
Some(mem::transmute::<Decoded, Decoded>(result))
}),
}
}
Ok(None)
}
}
#[allow(dead_code)]
pub struct Decoder<R: BufRead> {
decoder: ReadDecoder<R>,
current_frame: Frame,
}
impl<R> Decoder<R> where R: BufRead {
fn with_no_init(reader: R, decoder: StreamingDecoder) -> Decoder<R> {
Decoder {
decoder: ReadDecoder {
reader,
decoder,
at_eof: false
},
current_frame: Frame::default(),
}
}
fn init(mut self) -> Result<Self, DecodingError> {
loop {
match self.decoder.decode_next()? {
Some(Decoded::BackgroundColor) => {}
Some(Decoded::GlobalPalette) => {
break
},
Some(_) => {
unreachable!()
},
None => return Err(DecodingError::format(
"file does not contain any image data"
))
}
}
Ok(self)
}
pub fn next_frame_info(&mut self) -> Result<Option<&Frame>, DecodingError> {
loop {
match self.decoder.decode_next()? {
Some(Decoded::Frame(frame)) => {
self.current_frame = frame.clone();
break
},
Some(_) => (),
None => return Ok(None)
}
}
Ok(Some(&self.current_frame))
}
pub fn read_into_buffer(&mut self) -> Result<(), DecodingError> {
loop {
match self.decoder.decode_next()? {
Some(Decoded::SomeData) => {
continue
},
Some(_) | None => return Ok(()),
}
}
}
}