1use crate::parser::{FromData, NumFrom, Stream, U24};
2
3pub trait IndexSize: FromData {
4 fn to_u32(self) -> u32;
5}
6
7impl IndexSize for u16 {
8 fn to_u32(self) -> u32 {
9 u32::from(self)
10 }
11}
12
13impl IndexSize for u32 {
14 fn to_u32(self) -> u32 {
15 self
16 }
17}
18
19#[inline]
20pub fn parse_index<'a, T: IndexSize>(s: &mut Stream<'a>) -> Option<Index<'a>> {
21 let count: T = s.read::<T>()?;
22 parse_index_impl(count:count.to_u32(), s)
23}
24
25#[inline(never)]
26fn parse_index_impl<'a>(count: u32, s: &mut Stream<'a>) -> Option<Index<'a>> {
27 if count == 0 || count == core::u32::MAX {
28 return Some(Index::default());
29 }
30
31 let offset_size: OffsetSize = s.read::<OffsetSize>()?;
32 let offsets_len: u32 = (count + 1).checked_mul(offset_size.to_u32())?;
33 let offsets: VarOffsets<'_> = VarOffsets {
34 data: s.read_bytes(len:usize::num_from(offsets_len))?,
35 offset_size,
36 };
37
38 // Last offset indicates a Data Index size.
39 match offsets.last() {
40 Some(last_offset: u32) => {
41 let data: &[u8] = s.read_bytes(len:usize::num_from(last_offset))?;
42 Some(Index { data, offsets })
43 }
44 None => Some(Index::default()),
45 }
46}
47
48#[inline]
49pub fn skip_index<T: IndexSize>(s: &mut Stream) -> Option<()> {
50 let count: T = s.read::<T>()?;
51 skip_index_impl(count:count.to_u32(), s)
52}
53
54#[inline(never)]
55fn skip_index_impl(count: u32, s: &mut Stream) -> Option<()> {
56 if count == 0 || count == core::u32::MAX {
57 return Some(());
58 }
59
60 let offset_size: OffsetSize = s.read::<OffsetSize>()?;
61 let offsets_len: u32 = (count + 1).checked_mul(offset_size.to_u32())?;
62 let offsets: VarOffsets<'_> = VarOffsets {
63 data: s.read_bytes(len:usize::num_from(offsets_len))?,
64 offset_size,
65 };
66
67 if let Some(last_offset: u32) = offsets.last() {
68 s.advance(len:usize::num_from(last_offset));
69 }
70
71 Some(())
72}
73
74#[derive(Clone, Copy, Debug)]
75pub struct VarOffsets<'a> {
76 pub data: &'a [u8],
77 pub offset_size: OffsetSize,
78}
79
80impl<'a> VarOffsets<'a> {
81 pub fn get(&self, index: u32) -> Option<u32> {
82 if index >= self.len() {
83 return None;
84 }
85
86 let start = usize::num_from(index) * self.offset_size.to_usize();
87 let mut s = Stream::new_at(self.data, start)?;
88 let n: u32 = match self.offset_size {
89 OffsetSize::Size1 => u32::from(s.read::<u8>()?),
90 OffsetSize::Size2 => u32::from(s.read::<u16>()?),
91 OffsetSize::Size3 => s.read::<U24>()?.0,
92 OffsetSize::Size4 => s.read::<u32>()?,
93 };
94
95 // Offsets are offset by one byte in the font,
96 // so we have to shift them back.
97 n.checked_sub(1)
98 }
99
100 #[inline]
101 pub fn last(&self) -> Option<u32> {
102 if !self.is_empty() {
103 self.get(self.len() - 1)
104 } else {
105 None
106 }
107 }
108
109 #[inline]
110 pub fn len(&self) -> u32 {
111 self.data.len() as u32 / self.offset_size as u32
112 }
113
114 #[inline]
115 pub fn is_empty(&self) -> bool {
116 self.len() == 0
117 }
118}
119
120#[derive(Clone, Copy, Debug)]
121pub struct Index<'a> {
122 pub data: &'a [u8],
123 pub offsets: VarOffsets<'a>,
124}
125
126impl<'a> Default for Index<'a> {
127 #[inline]
128 fn default() -> Self {
129 Index {
130 data: b"",
131 offsets: VarOffsets {
132 data: b"",
133 offset_size: OffsetSize::Size1,
134 },
135 }
136 }
137}
138
139impl<'a> IntoIterator for Index<'a> {
140 type Item = &'a [u8];
141 type IntoIter = IndexIter<'a>;
142
143 #[inline]
144 fn into_iter(self) -> Self::IntoIter {
145 IndexIter {
146 data: self,
147 offset_index: 0,
148 }
149 }
150}
151
152impl<'a> Index<'a> {
153 #[inline]
154 pub fn len(&self) -> u32 {
155 // Last offset points to the byte after the `Object data`. We should skip it.
156 self.offsets.len().saturating_sub(1)
157 }
158
159 pub fn get(&self, index: u32) -> Option<&'a [u8]> {
160 let next_index: u32 = index.checked_add(1)?; // make sure we do not overflow
161 let start: usize = usize::num_from(self.offsets.get(index)?);
162 let end: usize = usize::num_from(self.offsets.get(next_index)?);
163 self.data.get(index:start..end)
164 }
165}
166
167pub struct IndexIter<'a> {
168 data: Index<'a>,
169 offset_index: u32,
170}
171
172impl<'a> Iterator for IndexIter<'a> {
173 type Item = &'a [u8];
174
175 #[inline]
176 fn next(&mut self) -> Option<Self::Item> {
177 if self.offset_index == self.data.len() {
178 return None;
179 }
180
181 let index: u32 = self.offset_index;
182 self.offset_index += 1;
183 self.data.get(index)
184 }
185}
186
187#[derive(Clone, Copy, PartialEq, Eq, Debug)]
188pub enum OffsetSize {
189 Size1 = 1,
190 Size2 = 2,
191 Size3 = 3,
192 Size4 = 4,
193}
194
195impl OffsetSize {
196 #[inline]
197 pub fn to_u32(self) -> u32 {
198 self as u32
199 }
200 #[inline]
201 pub fn to_usize(self) -> usize {
202 self as usize
203 }
204}
205
206impl FromData for OffsetSize {
207 const SIZE: usize = 1;
208
209 #[inline]
210 fn parse(data: &[u8]) -> Option<Self> {
211 match data.get(index:0)? {
212 1 => Some(OffsetSize::Size1),
213 2 => Some(OffsetSize::Size2),
214 3 => Some(OffsetSize::Size3),
215 4 => Some(OffsetSize::Size4),
216 _ => None,
217 }
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn parse_offset_size() {
227 assert_eq!(core::mem::size_of::<OffsetSize>(), 1);
228
229 assert_eq!(Stream::new(&[0x00]).read::<OffsetSize>(), None);
230 assert_eq!(
231 Stream::new(&[0x01]).read::<OffsetSize>(),
232 Some(OffsetSize::Size1)
233 );
234 assert_eq!(Stream::new(&[0x05]).read::<OffsetSize>(), None);
235 }
236}
237