1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ByteOrder};
use {HEADER_LEN, Error, Result};
#[derive(Debug)]
pub struct Decoder<R> {
r: R,
width: u32,
height: u32,
}
impl<R: Read + Seek> Decoder<R> {
pub fn new(mut r: R) -> Result<Decoder<R>> {
let head = &mut [0; HEADER_LEN as usize];
r.seek(SeekFrom::Start(0))?;
r.read_exact(head)?;
if &head[..8] != b"farbfeld" {
return Err(Error::FormatError("unexpected magic number".to_string()))
}
Ok(Decoder {
r: r,
width: BigEndian::read_u32(&head[8..]),
height: BigEndian::read_u32(&head[12..]),
})
}
pub fn dimensions(&self) -> (u32, u32) {
(self.width, self.height)
}
pub fn row_len(&self) -> usize {
self.width as usize * 8
}
pub fn read_row(&mut self, row: u32, buf: &mut [u8]) -> Result<usize> {
if row > self.height { return Err(Error::ImageEnd) }
let row_len = self.row_len();
let offset = HEADER_LEN + row as u64 * row_len as u64;
self.r.seek(SeekFrom::Start(offset))?;
self.r.read_exact(&mut buf[..row_len])?;
Ok(row_len)
}
pub fn read_image(&mut self) -> Result<Vec<u8>> {
self.r.seek(SeekFrom::Start(HEADER_LEN))?;
let num_raw_bytes = self.height as usize * self.row_len();
let mut buf = vec![0; num_raw_bytes];
self.r.read_exact(&mut buf)?;
Ok(buf)
}
}
#[cfg(test)]
mod tests {
use std::io::{Cursor, ErrorKind, Write};
use Decoder;
use tests::IMAGE_DATA;
use Error;
#[test]
fn invalid_magic() {
let mut img_data = Vec::new();
img_data.write(b"test fail").unwrap();
img_data.write(&IMAGE_DATA[8..]).unwrap();
let buf = Cursor::new(img_data);
match Decoder::new(buf) {
Err(e) => match e {
Error::FormatError(_) => return,
e => panic!("{:?}", e),
},
Ok(_) => panic!("Got Ok expected Error::FormatError"),
}
}
#[test]
fn truncate_header() {
let buf = Cursor::new(&IMAGE_DATA[0..8]);
match Decoder::new(buf) {
Err(Error::IoError(e)) => {
if e.kind() == ErrorKind::UnexpectedEof {
return
} else { panic!("{:?}", e) }
},
Err(e) => panic!("{:?}", e),
Ok(_) => panic!("Got Ok expected Error::FormatError"),
}
}
#[test]
fn truncate_data() {
let buf = Cursor::new(&IMAGE_DATA[..IMAGE_DATA.len()-1]);
let mut img = Decoder::new(buf).unwrap();
match img.read_image() {
Err(Error::IoError(e)) => {
if e.kind() == ErrorKind::UnexpectedEof {
return
} else { panic!("{:?}", e) }
},
Err(e) => panic!("{:?}", e),
Ok(_) => panic!("Got Ok expected Error::FormatError"),
}
}
}