1 | use crate::parser::{FromData, NumFrom, Stream, U24}; |
2 | |
3 | pub trait IndexSize: FromData { |
4 | fn to_u32(self) -> u32; |
5 | } |
6 | |
7 | impl IndexSize for u16 { |
8 | fn to_u32(self) -> u32 { |
9 | u32::from(self) |
10 | } |
11 | } |
12 | |
13 | impl IndexSize for u32 { |
14 | fn to_u32(self) -> u32 { |
15 | self |
16 | } |
17 | } |
18 | |
19 | #[inline ] |
20 | pub 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)] |
26 | fn 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 ] |
49 | pub 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)] |
55 | fn 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)] |
75 | pub struct VarOffsets<'a> { |
76 | pub data: &'a [u8], |
77 | pub offset_size: OffsetSize, |
78 | } |
79 | |
80 | impl<'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)] |
121 | pub struct Index<'a> { |
122 | pub data: &'a [u8], |
123 | pub offsets: VarOffsets<'a>, |
124 | } |
125 | |
126 | impl<'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 | |
139 | impl<'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 | |
152 | impl<'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 | |
167 | pub struct IndexIter<'a> { |
168 | data: Index<'a>, |
169 | offset_index: u32, |
170 | } |
171 | |
172 | impl<'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)] |
188 | pub enum OffsetSize { |
189 | Size1 = 1, |
190 | Size2 = 2, |
191 | Size3 = 3, |
192 | Size4 = 4, |
193 | } |
194 | |
195 | impl 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 | |
206 | impl 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)] |
222 | mod 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 | |