1use crate::error::{Error, Result};
2use crate::header::ByteOrder;
3use crate::io::Cursor;
4use crate::source::TiffSource;
5
6pub use tiff_core::{Tag, TagType, TagValue};
7
8pub fn parse_tag_classic(
10 code: u16,
11 type_code: u16,
12 count: u64,
13 value_offset_bytes: &[u8],
14 source: &dyn TiffSource,
15 byte_order: ByteOrder,
16) -> Result<Tag> {
17 let tag_type = TagType::from_code(type_code);
18 let total_size = value_len(code, count, tag_type.element_size())?;
19
20 let owned;
21 let value_bytes = if total_size <= 4 {
22 &value_offset_bytes[..total_size]
23 } else {
24 let offset = match byte_order {
25 ByteOrder::LittleEndian => u32::from_le_bytes(value_offset_bytes.try_into().unwrap()),
26 ByteOrder::BigEndian => u32::from_be_bytes(value_offset_bytes.try_into().unwrap()),
27 } as u64;
28 owned = read_value_bytes(source, offset, total_size)?;
29 owned.as_slice()
30 };
31
32 let value = decode_value(&tag_type, count, value_bytes, byte_order)?;
33 Ok(Tag {
34 code,
35 tag_type,
36 count,
37 value,
38 })
39}
40
41pub fn parse_tag_bigtiff(
43 code: u16,
44 type_code: u16,
45 count: u64,
46 value_offset_bytes: &[u8],
47 source: &dyn TiffSource,
48 byte_order: ByteOrder,
49) -> Result<Tag> {
50 let tag_type = TagType::from_code(type_code);
51 let total_size = value_len(code, count, tag_type.element_size())?;
52
53 let owned;
54 let value_bytes = if total_size <= 8 {
55 &value_offset_bytes[..total_size]
56 } else {
57 let offset = match byte_order {
58 ByteOrder::LittleEndian => u64::from_le_bytes(value_offset_bytes.try_into().unwrap()),
59 ByteOrder::BigEndian => u64::from_be_bytes(value_offset_bytes.try_into().unwrap()),
60 };
61 owned = read_value_bytes(source, offset, total_size)?;
62 owned.as_slice()
63 };
64
65 let value = decode_value(&tag_type, count, value_bytes, byte_order)?;
66 Ok(Tag {
67 code,
68 tag_type,
69 count,
70 value,
71 })
72}
73
74fn read_value_bytes(source: &dyn TiffSource, offset: u64, len: usize) -> Result<Vec<u8>> {
75 if let Some(data) = source.as_slice() {
76 return Ok(slice_at(data, offset, len)?.to_vec());
77 }
78 source.read_exact_at(offset, len)
79}
80
81fn value_len(tag: u16, count: u64, element_size: usize) -> Result<usize> {
82 let count = usize::try_from(count).map_err(|_| Error::InvalidTagValue {
83 tag,
84 reason: "value count does not fit in memory".into(),
85 })?;
86 count
87 .checked_mul(element_size)
88 .ok_or_else(|| Error::InvalidTagValue {
89 tag,
90 reason: "value byte length overflows usize".into(),
91 })
92}
93
94fn slice_at(data: &[u8], offset: u64, len: usize) -> Result<&[u8]> {
95 let start = usize::try_from(offset).map_err(|_| Error::OffsetOutOfBounds {
96 offset,
97 length: len as u64,
98 data_len: data.len() as u64,
99 })?;
100 let end = start.checked_add(len).ok_or(Error::OffsetOutOfBounds {
101 offset,
102 length: len as u64,
103 data_len: data.len() as u64,
104 })?;
105 if end > data.len() {
106 return Err(Error::OffsetOutOfBounds {
107 offset,
108 length: len as u64,
109 data_len: data.len() as u64,
110 });
111 }
112 Ok(&data[start..end])
113}
114
115fn decode_value(
116 tag_type: &TagType,
117 count: u64,
118 bytes: &[u8],
119 byte_order: ByteOrder,
120) -> Result<TagValue> {
121 let mut cursor = Cursor::new(bytes, byte_order);
122 let n = count as usize;
123
124 Ok(match tag_type {
125 TagType::Byte | TagType::Unknown(_) => TagValue::Byte(cursor.read_bytes(n)?.to_vec()),
126 TagType::Ascii => {
127 let raw = cursor.read_bytes(n)?;
128 let s = String::from_utf8_lossy(raw)
129 .trim_end_matches('\0')
130 .to_string();
131 TagValue::Ascii(s)
132 }
133 TagType::Short => {
134 let mut v = Vec::with_capacity(n);
135 for _ in 0..n {
136 v.push(cursor.read_u16()?);
137 }
138 TagValue::Short(v)
139 }
140 TagType::Long => {
141 let mut v = Vec::with_capacity(n);
142 for _ in 0..n {
143 v.push(cursor.read_u32()?);
144 }
145 TagValue::Long(v)
146 }
147 TagType::Rational => {
148 let mut v = Vec::with_capacity(n);
149 for _ in 0..n {
150 let num = cursor.read_u32()?;
151 let den = cursor.read_u32()?;
152 v.push([num, den]);
153 }
154 TagValue::Rational(v)
155 }
156 TagType::SByte => {
157 let raw = cursor.read_bytes(n)?;
158 TagValue::SByte(raw.iter().map(|&b| b as i8).collect())
159 }
160 TagType::Undefined => TagValue::Undefined(cursor.read_bytes(n)?.to_vec()),
161 TagType::SShort => {
162 let mut v = Vec::with_capacity(n);
163 for _ in 0..n {
164 v.push(cursor.read_u16()? as i16);
165 }
166 TagValue::SShort(v)
167 }
168 TagType::SLong => {
169 let mut v = Vec::with_capacity(n);
170 for _ in 0..n {
171 v.push(cursor.read_u32()? as i32);
172 }
173 TagValue::SLong(v)
174 }
175 TagType::SRational => {
176 let mut v = Vec::with_capacity(n);
177 for _ in 0..n {
178 let num = cursor.read_u32()? as i32;
179 let den = cursor.read_u32()? as i32;
180 v.push([num, den]);
181 }
182 TagValue::SRational(v)
183 }
184 TagType::Float => {
185 let mut v = Vec::with_capacity(n);
186 for _ in 0..n {
187 let bits = cursor.read_u32()?;
188 v.push(f32::from_bits(bits));
189 }
190 TagValue::Float(v)
191 }
192 TagType::Double => {
193 let mut v = Vec::with_capacity(n);
194 for _ in 0..n {
195 v.push(cursor.read_f64()?);
196 }
197 TagValue::Double(v)
198 }
199 TagType::Long8 | TagType::Ifd8 => {
200 let mut v = Vec::with_capacity(n);
201 for _ in 0..n {
202 v.push(cursor.read_u64()?);
203 }
204 TagValue::Long8(v)
205 }
206 TagType::SLong8 => {
207 let mut v = Vec::with_capacity(n);
208 for _ in 0..n {
209 v.push(cursor.read_u64()? as i64);
210 }
211 TagValue::SLong8(v)
212 }
213 })
214}