use std::io::{Cursor,Read};
use byteorder::LittleEndian as LE;
use byteorder::ReadBytesExt;
use ::{FlicError,FlicResult,RasterMut};
pub const FLI_SBSRSC: u16 = 10;
pub fn decode_fli_sbsrsc(src: &[u8], dst: &mut RasterMut)
-> FlicResult<()> {
if dst.x != 0 || dst.y != 0
|| dst.w != 320 || dst.h != 200 || dst.stride != 320 {
return Err(FlicError::WrongResolution);
}
let mut r = Cursor::new(src);
let mut idx0 = r.read_u16::<LE>()? as usize;
let count = r.read_u16::<LE>()?;
for _ in 0..count {
let nskip = r.read_u8()? as usize;
let signed_length = r.read_i8()? as i32;
if signed_length >= 0 {
let start = idx0 + nskip;
let end = start + signed_length as usize;
if end > dst.buf.len() {
return Err(FlicError::Corrupted);
}
r.read_exact(&mut dst.buf[start..end])?;
idx0 = end;
} else {
let start = idx0 + nskip;
let end = start + (-signed_length) as usize;
if end > dst.buf.len() {
return Err(FlicError::Corrupted);
}
let c = r.read_u8()?;
for e in &mut dst.buf[start..end] {
*e = c;
}
idx0 = end;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use ::RasterMut;
use super::decode_fli_sbsrsc;
#[test]
fn test_decode_fli_sbsrsc() {
let src = [
0x01, 0x00, 0x02, 0x00, 3, 5, 0x01, 0x23, 0x45, 0x67, 0x89,
2, (-4i8) as u8, 0xAB ];
let expected = [
0x00,
0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89,
0x00, 0x00, 0xAB, 0xAB, 0xAB, 0xAB,
0x00 ];
const SCREEN_W: usize = 320;
const SCREEN_H: usize = 200;
let mut buf = [0; SCREEN_W * SCREEN_H];
let mut pal = [0; 3 * 256];
let res = decode_fli_sbsrsc(&src,
&mut RasterMut::new(SCREEN_W, SCREEN_H, &mut buf, &mut pal));
assert!(res.is_ok());
assert_eq!(&buf[0..16], &expected[..]);
}
}