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
use crate::{ImageFormat, ImageInfo, ImageInfoError, ImageInfoResult, ImageSize, ReadInterface};
use std::io::{BufRead, Seek};

pub fn try_cur_ico<R>(ri: &mut ReadInterface<R>, length: usize) -> ImageInfoResult<ImageInfo>
where
    R: BufRead + Seek,
{
    if length < 6 {
        return Err(ImageInfoError::UnrecognizedFormat);
    }
    let buffer = ri.read(0, 6)?;

    let mut ret =
        // ico type == 1
        if buffer.cmp(0, 4, b"\x00\x00\x01\x00") {
            ImageInfo {
                format: ImageFormat::ICO,
                ext: "ico",
                full_ext: "ico",
                mimetype: "image/ico",
                size: ImageSize {
                    width: 0,
                    height: 0,
                },
                entry_sizes: vec![],
            }
        }
        // cur type == 2
        else if buffer.cmp(0, 4, b"\x00\x00\x02\x00") {
            ImageInfo {
                format: ImageFormat::CUR,
                ext: "cur",
                full_ext: "cur",
                mimetype: "image/cur",
                size: ImageSize {
                    width: 0,
                    height: 0,
                },
                entry_sizes: vec![],
            }
        }
        // invalid
        else {
            return Err(ImageInfoError::UnrecognizedFormat);
        };

    let entry_count = buffer.read_u16_le(4) as usize;
    if entry_count == 0 {
        return Err(ImageInfoError::UnrecognizedFormat);
    }

    let entry_size = 16;
    let entry_total_size = entry_count * entry_size;

    let mut offset = 6usize;
    if length < offset + entry_total_size {
        return Err(ImageInfoError::UnrecognizedFormat);
    }

    let buffer = ri.read(offset, entry_total_size)?;
    offset += entry_total_size;

    for i in 0..entry_count {
        let width = buffer.read_u8(i * entry_size);
        let height = buffer.read_u8(i * entry_size + 1);
        let width = if width == 0 { 256i64 } else { width as i64 };
        let height = if height == 0 { 256i64 } else { height as i64 };
        ret.entry_sizes.push(ImageSize { width, height });

        let bytes = buffer.read_i32_le(i * entry_size + 8) as usize;
        offset += bytes;
    }

    if let Some(size) = ret.entry_sizes.first() {
        ret.size.width = size.width;
        ret.size.height = size.height;
    } else {
        return Err(ImageInfoError::UnrecognizedFormat);
    }

    Ok(ret)
}