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: [u8; 4] = [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: [u8; 4] = [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: [u8; 3] = [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: [u8; 2] = [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: [u8; 1] = [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: [u8; 4] = [0; 4];
72 let size: usize = 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>(
79 reader: &mut R,
80 delimiter: u8,
81 max_size: usize,
82) -> io::Result<Vec<u8>> {
83 let mut bytes = Vec::new();
84 let mut amount_read = 0;
85
86 while amount_read < max_size {
87 let mut byte = [0; 1];
88 reader.read_exact(&mut byte)?;
89
90 if byte[0] == delimiter {
91 break;
92 }
93
94 bytes.push(byte[0]);
95 amount_read += 1;
96 }
97
98 if amount_read >= max_size {
99 return Err(io::Error::new(
100 io::ErrorKind::InvalidData,
101 format!("Delimiter not found within {} bytes", max_size),
102 ));
103 }
104
105 Ok(bytes)
106}
107
108/// Skips all starting whitespace characters and then reads a string until the next whitespace character
109/// Example:
110/// " test string" => "test"
111pub fn read_until_whitespace<R: BufRead>(reader: &mut R, max_size: usize) -> io::Result<String> {
112 let mut bytes = Vec::new();
113 let mut amount_read = 0;
114 let mut seen_non_whitespace = false;
115
116 while amount_read < max_size {
117 amount_read += 1;
118
119 let mut byte = [0; 1];
120 reader.read_exact(&mut byte)?;
121
122 if byte[0].is_ascii_whitespace() {
123 // If we've seen a non-whitespace character before then exit
124 if seen_non_whitespace {
125 break;
126 }
127
128 // Skip whitespace until we found first non-whitespace character
129 continue;
130 }
131
132 bytes.push(byte[0]);
133 seen_non_whitespace = true;
134 }
135
136 if amount_read >= max_size {
137 return Err(io::Error::new(
138 io::ErrorKind::InvalidData,
139 format!("Delimiter not found within {} bytes", max_size),
140 ));
141 }
142
143 String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
144}
145
146pub fn read_line_capped<R: BufRead>(reader: &mut R, max_size: usize) -> io::Result<String> {
147 let bytes: Vec = read_until_capped(reader, delimiter:b'\n', max_size)?;
148 String::from_utf8(bytes).map_err(|e: FromUtf8Error| io::Error::new(kind:io::ErrorKind::InvalidData, error:e))
149}
150
151pub fn read_null_terminated_string<R: BufRead>(
152 reader: &mut R,
153 max_size: usize,
154) -> io::Result<String> {
155 let bytes: Vec = read_until_capped(reader, delimiter:0, max_size)?;
156 String::from_utf8(bytes).map_err(|e: FromUtf8Error| io::Error::new(kind:io::ErrorKind::InvalidData, error:e))
157}
158