1use std::io::{Cursor,Read};
4use byteorder::LittleEndian as LE;
5use byteorder::ReadBytesExt;
6
7use ::{FlicError,FlicResult,RasterMut};
8
9pub const FLI_WRUN: u16 = 1;
13
14pub fn decode_fli_wrun(src: &[u8], dst: &mut RasterMut)
18 -> FlicResult<()> {
19 if dst.x != 0 || dst.y != 0
20 || dst.w != 320 || dst.h != 200 || dst.stride != 320 {
21 return Err(FlicError::WrongResolution);
22 }
23
24 let mut r = Cursor::new(src);
25 let mut idx0 = 0;
26
27 let count = r.read_u16::<LE>()?;
28 for _ in 0..count {
29 let signed_length = (r.read_u16::<LE>()? as i8) as i32;
31
32 if signed_length >= 0 {
33 let start = idx0;
34 let end = start + 2 * signed_length as usize;
35 if end > dst.buf.len() {
36 return Err(FlicError::Corrupted);
37 }
38
39 let c0 = r.read_u8()?;
40 let c1 = r.read_u8()?;
41 for e in &mut dst.buf[start..end].chunks_mut(2) {
42 e[0] = c0;
43 e[1] = c1;
44 }
45
46 idx0 = end;
47 } else {
48 let start = idx0;
49 let end = start + 2 * (-signed_length) as usize;
50 if end > dst.buf.len() {
51 return Err(FlicError::Corrupted);
52 }
53
54 r.read_exact(&mut dst.buf[start..end])?;
55
56 idx0 = end;
57 }
58 }
59
60 Ok(())
61}
62
63#[cfg(test)]
64mod tests {
65 use ::RasterMut;
66 use super::decode_fli_wrun;
67
68 #[test]
69 fn test_decode_fli_wrun() {
70 let src = [
71 0x02, 0x00, 0x03, 0xFF, 0xCD, 0xAB, 0xFC, 0xFF, 0x23, 0x01, 0x67, 0x45, 0xAB, 0x89, 0xEF, 0xCD ];
76
77 let expected = [
78 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB,
79 0x23, 0x01, 0x67, 0x45, 0xAB, 0x89, 0xEF, 0xCD,
80 0x00, 0x00 ];
81
82 const SCREEN_W: usize = 320;
83 const SCREEN_H: usize = 200;
84 let mut buf = [0; SCREEN_W * SCREEN_H];
85 let mut pal = [0; 3 * 256];
86
87 let res = decode_fli_wrun(&src,
88 &mut RasterMut::new(SCREEN_W, SCREEN_H, &mut buf, &mut pal));
89 assert!(res.is_ok());
90 assert_eq!(&buf[0..16], &expected[..]);
91 }
92}