image-meta 0.1.0

Image meta information loader
Documentation

#![allow(unused_imports)]

use std::io::{BufRead, BufReader, Cursor, Read, Seek, SeekFrom, Take};

use byteorder::{ReadBytesExt, LittleEndian};

use crate::errors::{ImageError, ImageResult, ImageResultU};




pub struct RiffReader<T: Read + Seek> {
    buffer: BufReader<T>,
    form_type: [u8;4],
    remain: usize,
    skip_for: usize,
}

pub struct Chunk<'a> {
    skip_for: &'a mut usize,
    identifier: [u8;4],
    buffer: Take<&'a mut BufRead>
}

impl<T: BufRead + Seek> RiffReader<T> {
    pub fn form_type(&self) -> &[u8;4] {
        &self.form_type
    }

    pub fn open(buffer: T) -> ImageResult<Self> {
        let mut buffer = BufReader::new(buffer);

        let mut signature = [0u8;4];
        buffer.read_exact(&mut signature)?;
        if &signature != b"RIFF" {
            return Err(ImageError::InvalidSignature);
        }

        let remain = buffer.read_u32::<LittleEndian>()? as usize - 4; // 4 means form_type

        let mut form_type = [0u8;4];
        buffer.read_exact(&mut form_type)?;

        Ok(RiffReader {
            buffer,
            form_type,
            remain,
            skip_for: 0,
        })
    }

    pub fn read_chunk<'a>(&'a mut self) -> ImageResult<Option<Chunk<'a>>> {
        if 0 < self.skip_for {
            self.buffer.seek(SeekFrom::Current(self.skip_for as i64))?;
        }

        if self.remain == 0 {
            return Ok(None);
        }

        let mut identifier = [0u8;4];
        self.buffer.read_exact(&mut identifier)?;

        let size = self.buffer.read_u32::<LittleEndian>()? as usize;
        self.remain -= size + 8;
        let buffer = (&mut self.buffer as &mut BufRead).take(size as u64);
        self.skip_for = size;

        Ok(Some(Chunk { buffer, identifier, skip_for: &mut self.skip_for }))
    }
}


impl<'a> Chunk<'a> {
    pub fn identifier(&self) -> &[u8;4] {
        &self.identifier
    }
}

impl<'a> Read for Chunk<'a> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.buffer.read(buf).map(|it| {
            *self.skip_for -= it;
            it
        })
    }
}