use std::io::{self, Read};
use std::mem;
use std::ops;
use std::slice;
use libc::{malloc, size_t, c_int, read, close};
use common::Block;
use reader::{Decoded, DecodingError, PLTE_CHANNELS};
use c_api::{GifFileType, SavedImage, ColorMapObject, GifColorType, _Bool,
InputFunc
};
use util;
pub trait CInterface {
fn read_screen_desc(&mut self, &mut GifFileType);
fn current_image_buffer(&mut self) -> Result<(&[u8], &mut usize), DecodingError>;
fn last_ext(&self) -> (u8, &[u8], bool);
fn next_record_type(&mut self) -> Result<Block, DecodingError>;
fn decode_next(&mut self) -> Result<Option<Decoded>, DecodingError>;
}
pub unsafe fn saved_images_new(count: usize) -> *mut SavedImage {
mem::transmute::<_, *mut SavedImage>(malloc(
(mem::size_of::<SavedImage>() * count) as size_t
))
}
pub unsafe fn copy_data(buf: &[u8]) -> *mut u8 {
let data = mem::transmute::<_, *mut u8>(malloc(
(mem::size_of::<SavedImage>() * buf.len()) as size_t
));
util::copy_memory(buf, slice::from_raw_parts_mut(data, buf.len()));
data
}
pub unsafe fn copy_colormap(map: &Option<Vec<u8>>) -> *mut ColorMapObject {
let map: &[u8] = match *map {
Some(ref map) => &*map,
None => &[]
};
let new_map = mem::transmute::<_, *mut ColorMapObject>(malloc(mem::size_of::<ColorMapObject>() as size_t));
(*new_map).ColorCount = (map.len()/PLTE_CHANNELS) as c_int;
(*new_map).BitsPerPixel = 8;
(*new_map).SortFlag = _Bool::False;
let colors = mem::transmute::<_, *mut GifColorType>(malloc(
(mem::size_of::<GifColorType>() * (*new_map).ColorCount as usize) as size_t
));
for (i, c) in map.chunks(PLTE_CHANNELS).enumerate() {
*colors.offset(i as isize) = GifColorType {
Red: c[0],
Green: c[1],
Blue: c[2],
}
}
(*new_map).Colors = colors;
new_map
}
pub struct CFile {
fp: c_int
}
impl CFile {
pub fn new(fp: c_int) -> CFile {
CFile {
fp: fp
}
}
}
impl Read for CFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let count = unsafe { read(
self.fp,
mem::transmute(buf.as_mut_ptr()),
buf.len() as size_t
) };
match count {
-1 => Err(io::Error::last_os_error()),
n => Ok(n as usize)
}
}
}
impl ops::Drop for CFile {
fn drop(&mut self) {
unsafe {close(self.fp)};
}
}
pub struct FnInputFile {
func: InputFunc,
file: *mut GifFileType
}
impl FnInputFile {
pub fn new(func: InputFunc, file: *mut GifFileType) -> FnInputFile {
FnInputFile {
func: func,
file: file
}
}
}
impl Read for FnInputFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let count = unsafe { (self.func)(
self.file,
mem::transmute(buf.as_mut_ptr()),
buf.len() as c_int
) };
match count {
-1 => Err(io::Error::from_raw_os_error(count)),
n => Ok(n as usize)
}
}
}