imagesize/
util.rs

1use crate::{ImageError, ImageResult};
2use std::io::{self, BufRead, Seek};
3
4/// Used for TIFF decoding
5pub enum Endian {
6    Little,
7    Big,
8}
9
10pub fn read_i32<R: BufRead + Seek>(reader: &mut R, endianness: &Endian) -> ImageResult<i32> {
11    let mut attr_size_buf = [0; 4];
12    reader.read_exact(&mut attr_size_buf)?;
13    match endianness {
14        Endian::Little => Ok(i32::from_le_bytes(attr_size_buf)),
15        Endian::Big => Ok(i32::from_be_bytes(attr_size_buf)),
16    }
17}
18
19pub fn read_u32<R: BufRead + Seek>(reader: &mut R, endianness: &Endian) -> ImageResult<u32> {
20    let mut buf = [0; 4];
21    reader.read_exact(&mut buf)?;
22
23    match endianness {
24        Endian::Little => Ok(((buf[3] as u32) << 24)
25            | ((buf[2] as u32) << 16)
26            | ((buf[1] as u32) << 8)
27            | (buf[0] as u32)),
28        Endian::Big => Ok(((buf[0] as u32) << 24)
29            | ((buf[1] as u32) << 16)
30            | ((buf[2] as u32) << 8)
31            | (buf[3] as u32)),
32    }
33}
34
35pub fn read_u24<R: BufRead + Seek>(reader: &mut R, endianness: &Endian) -> ImageResult<u32> {
36    let mut buf = [0; 3];
37    reader.read_exact(&mut buf)?;
38
39    match endianness {
40        Endian::Little => Ok(((buf[2] as u32) << 16) | ((buf[1] as u32) << 8) | (buf[0] as u32)),
41        Endian::Big => Ok(((buf[0] as u32) << 16) | ((buf[1] as u32) << 8) | (buf[2] as u32)),
42    }
43}
44
45pub fn read_u16<R: BufRead + Seek>(reader: &mut R, endianness: &Endian) -> ImageResult<u16> {
46    let mut buf = [0; 2];
47    reader.read_exact(&mut buf)?;
48
49    match endianness {
50        Endian::Little => Ok(((buf[1] as u16) << 8) | (buf[0] as u16)),
51        Endian::Big => Ok(((buf[0] as u16) << 8) | (buf[1] as u16)),
52    }
53}
54
55pub fn read_u8<R: BufRead + Seek>(reader: &mut R) -> ImageResult<u8> {
56    let mut buf = [0; 1];
57    reader.read_exact(&mut buf)?;
58    Ok(buf[0])
59}
60
61pub fn read_bits(source: u128, num_bits: usize, offset: usize, size: usize) -> ImageResult<usize> {
62    if offset + num_bits < size {
63        Ok((source >> offset) as usize & ((1 << num_bits) - 1))
64    } else {
65        Err(ImageError::CorruptedImage)
66    }
67}
68
69/// Assumes tags are in format of 4 char string followed by big endian size for tag
70pub fn read_tag<R: BufRead + Seek>(reader: &mut R) -> ImageResult<(String, usize)> {
71    let mut tag_buf = [0; 4];
72    let size = read_u32(reader, &Endian::Big)? as usize;
73    reader.read_exact(&mut tag_buf)?;
74
75    Ok((String::from_utf8_lossy(&tag_buf).into_owned(), size))
76}
77
78pub fn read_until_capped<R: BufRead>(reader: &mut R, delimiter: u8, max_size: usize) -> io::Result<Vec<u8>> {
79    let mut bytes = Vec::new();
80    let mut amount_read = 0;
81
82    while amount_read < max_size {
83        let mut byte = [0; 1];
84        reader.read_exact(&mut byte)?;
85
86        if byte[0] == delimiter {
87            break;
88        }
89
90        bytes.push(byte[0]);
91        amount_read += 1;
92    }
93
94    if amount_read >= max_size {
95        return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Delimiter not found within {} bytes", max_size)));
96    }
97
98    Ok(bytes)
99}
100
101/// Skips all starting whitespace characters and then reads a string until the next whitespace character
102/// Example:
103///     "    test   string" => "test"
104pub fn read_until_whitespace<R: BufRead>(reader: &mut R, max_size: usize) -> io::Result<String> {
105    let mut bytes = Vec::new();
106    let mut amount_read = 0;
107    let mut seen_non_whitespace = false;
108
109    while amount_read < max_size {
110        amount_read += 1;
111        
112        let mut byte = [0; 1];
113        reader.read_exact(&mut byte)?;
114
115        if byte[0].is_ascii_whitespace() {
116            // If we've seen a non-whitespace character before then exit
117            if seen_non_whitespace {
118                break;
119            }
120
121            // Skip whitespace until we found first non-whitespace character
122            continue;
123        }
124
125        bytes.push(byte[0]);
126        seen_non_whitespace = true;
127    }
128
129    if amount_read >= max_size {
130        return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Delimiter not found within {} bytes", max_size)));
131    }
132
133    String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
134}
135
136pub fn read_line_capped<R: BufRead>(reader: &mut R, max_size: usize) -> io::Result<String> {
137    let bytes = read_until_capped(reader, b'\n', max_size)?;
138    String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
139}
140
141pub fn read_null_terminated_string<R: BufRead>(reader: &mut R, max_size: usize) -> io::Result<String> {
142    let bytes = read_until_capped(reader, 0, max_size)?;
143    String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
144}