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
use std::io::{Read, Seek, SeekFrom};
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Format {
Png,
Jpeg,
Gif,
Webp,
Tiff,
Bmp,
Ico,
Hdr,
}
pub fn guess<R: Read + Seek>(mut input: R) -> Option<Format> {
const MAGIC: &'static [(&'static [u8], Format)] = &[
(b"\x89PNG\r\n\x1a\n", Format::Png),
(&[0xff, 0xd8, 0xff], Format::Jpeg),
(b"GIF89a", Format::Gif),
(b"GIF87a", Format::Gif),
(b"WEBP", Format::Webp),
(b"MM.*", Format::Tiff),
(b"II*.", Format::Tiff),
(b"BM", Format::Bmp),
(&[0, 0, 1, 0], Format::Ico),
(b"#?RADIANCE", Format::Hdr),
];
macro_rules! try {
(return $body:expr) => (
if let Ok(value) = $body {
value
}
else {
return None;
}
);
(continue $body:expr) => (
if let Ok(value) = $body {
value
}
else {
continue;
}
);
}
for &(magic, format) in MAGIC.iter() {
try!(continue input.seek(SeekFrom::Start(0)));
let mut buffer = vec![0; magic.len()];
try!(continue input.read_exact(&mut buffer));
if buffer == &magic[..] {
try!(return input.seek(SeekFrom::Start(0)));
return Some(format);
}
}
try!(return input.seek(SeekFrom::Start(0)));
None
}