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