Skip to main content

spyne_text/fonts/parse/
parse.rs

1use std::{fs::read, io::{Error, ErrorKind}, path::Path};
2
3use crate::fonts::parse::{constants::{ARG_1_AND_2_ARE_WORDS, MAC_ROMAN_LOOKUP, MAC_STANDARD_NAMES, MORE_COMPONENTS, REPEAT_FLAG, USE_MARK_FILTERING_SET, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_INSTRUCTIONS, X_ADVANCE, X_ADVANCE_DEVICE, X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR, X_PLACEMENT, X_PLACEMENT_DEVICE, X_SHORT_VECTOR, Y_ADVANCE, Y_ADVANCE_DEVICE, Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR, Y_PLACEMENT, Y_PLACEMENT_DEVICE, Y_SHORT_VECTOR}, structures::{AlternateSet, Anchor, BaseArray, BaseRecord, Class1Record, Class2Record, ClassDef, ClassRangeRecord, CmapSubtable, CmapTable, Component, ComponentRecord, Condition, ConditionSet, Coverage, CoverageRangeRecord, Device, DeviceOrVariationIndex, EncodingRecord, EntryExitRecord, Feature, FeatureList, FeatureParams, FeatureRecord, FeatureTableSubstitution, FeatureTableSubstitutionRecord, FeatureVariationRecord, FeatureVariations, FontFile, FontFileType, GaspRangeRecord, GaspTable, Glyph, GlyphHeader, GposChainSubClassRule, GposChainSubClassSet, GposChainSubRule, GposChainSubRuleSet, GposSubClassRule, GposSubClassSet, GposSubRule, GposSubRuleSet, GposSubtable, GposTable, GposType1Format, GposType2Format, GposType3Format, GposType4Format, GposType5Format, GposType6Format, GposType7Format, GposType8Format, GposType9Format, Group, GsubChainSubClassRule, GsubChainSubClassSet, GsubChainSubRule, GsubChainSubRuleSet, GsubSubClassRule, GsubSubClassSet, GsubSubRule, GsubSubRuleSet, GsubSubtable, GsubTable, GsubType1Format, GsubType2Format, GsubType3Format, GsubType4Format, GsubType5Format, GsubType6Format, GsubType7Format, GsubType8Format, HeadTable, HheaTable, HmtxEntry, HmtxTable, KernClassTable, KernPair, KernSubtable, KernTable, LangSys, LangSysRecord, LangTagRecord, Ligature, LigatureArray, LigatureAttach, LigatureSet, Lookup, LookupList, MacSubtable, Mark2Array, Mark2Record, MarkArray, MarkRecord, MaxpTable, NameRecord, NameTable, OS2Table, PairSet, PairValueRecord, PosLookupRecord, PostTable, Range, Script, ScriptList, ScriptRecord, Sequence, SubHeader, SubstLookupRecord, TableHeader, TableRecord, ValueRecord, VariationIndex, VariationSelectorRecord, VheaTable, VmtxEntry, VmtxTable, WindowsSubtable}};
4
5impl FontFile {
6    pub fn parse_font_file<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
7        let bytes = read(path)?;
8        
9        let file_type = match bytes.get(0..4).ok_or(ErrorKind::UnexpectedEof)? {
10            [0x00, 0x01, 0x00, 0x00] => FontFileType::TrueType,
11            [0x4F, 0x54, 0x54, 0x4F] => FontFileType::OpenType,
12            _ => return Err(Error::new(ErrorKind::InvalidData, "Invalid Magic Number"))
13        };
14        
15        let num_tables = u16::from_be_bytes(bytes.get(4..6).ok_or(ErrorKind::UnexpectedEof)?.try_into().unwrap());
16        let mut table_records: Vec<TableRecord> = Vec::new();
17        let mut current_offset = 12;
18        for _ in 0..num_tables {
19            let tag: [u8; 4] = bytes
20                .get(current_offset..current_offset + 4)
21                .ok_or(ErrorKind::UnexpectedEof)?
22                .try_into()
23                .unwrap();
24            
25            let checksum = u32::from_be_bytes(
26                bytes
27                    .get(current_offset + 4..current_offset + 8)
28                    .ok_or(ErrorKind::UnexpectedEof)?
29                    .try_into()
30                    .unwrap()
31            );
32            
33            let offset = u32::from_be_bytes(
34                bytes
35                    .get(current_offset + 8..current_offset + 12)
36                    .ok_or(ErrorKind::UnexpectedEof)?
37                    .try_into()
38                    .unwrap()
39            );
40            
41            let length = u32::from_be_bytes(
42                bytes
43                    .get(current_offset + 12..current_offset + 16)
44                    .ok_or(ErrorKind::UnexpectedEof)?
45                    .try_into()
46                    .unwrap()
47            );
48            
49            table_records.push(TableRecord::new(tag, checksum, offset, length));
50            current_offset += 16;
51        }
52        
53        table_records.sort_by_key(|rec| rec.tag());
54        
55        Ok(FontFile::new(file_type, bytes, table_records))
56    }
57    
58    pub fn get_table(&self, tag: &[u8; 4]) -> Result<&[u8], Error> {
59        match self.table_records().binary_search_by_key(tag, |rec| rec.tag()) {
60            Ok(idx) => {
61                let table = self.table_records()[idx];
62                let offset = table.offset() as usize;
63                let length = table.length() as usize;
64                
65                Ok(&self.bytes().get(offset..offset + length).ok_or(ErrorKind::UnexpectedEof)?)
66            },
67            Err(_) => Err(Error::new(ErrorKind::NotFound, "Given tag was not found in table records"))
68        }
69    }
70    
71    pub fn parse_head(&self) -> Result<HeadTable, Error> {
72        let bytes = self.get_table(b"head")?;
73        
74        if bytes[12..16] != [0x5F, 0x0F, 0x3C, 0xF5] {
75            return Err(Error::new(ErrorKind::InvalidData, "Head table doesn't contain correct magic number"));
76        }
77        
78        let units_per_em = get_u16(bytes, 18)?;
79        let created = get_i64(bytes, 20)?;
80        let modified = get_i64(bytes, 28)?;
81        let x_min = get_i16(bytes, 36)?; 
82        let y_min = get_i16(bytes, 38)?;
83        let x_max = get_i16(bytes, 40)?;
84        let y_max = get_i16(bytes, 42)?;
85        let mac_style = get_u16(bytes, 44)?;
86        let lowest_rec_ppem = get_u16(bytes, 46)?;
87        let font_direction_hint = get_i16(bytes, 48)?;
88        let index_to_loc_format = get_i16(bytes, 50)?;
89        
90        Ok(HeadTable::new(
91            units_per_em,
92            created,
93            modified,
94            x_min,
95            y_min,
96            x_max,
97            y_max,
98            mac_style,
99            lowest_rec_ppem,
100            font_direction_hint,
101            index_to_loc_format
102        ))
103    }
104    
105    pub fn parse_maxp(&self) -> Result<MaxpTable, Error> {
106        let bytes = self.get_table(b"maxp")?;
107        
108        let version = get_u32(bytes, 0)?;
109        match version {
110            0x5000 => {
111                let num_glyphs = get_u16(bytes, 4)?;
112                let max_points = None;
113                let max_contours = None;
114                let max_composite_points = None;
115                let max_composite_contours = None;
116                let max_zones = None;
117                let max_twilight_points = None;
118                let max_storage = None;
119                let max_function_defs = None;
120                let max_instruction_defs = None;
121                let max_stack_elements = None;
122                let max_size_of_instructions = None;
123                let max_components_elements = None;
124                let max_component_depth = None;
125                
126                Ok(MaxpTable::new(
127                    version,
128                    num_glyphs,
129                    max_points,
130                    max_contours,
131                    max_composite_points,
132                    max_composite_contours,
133                    max_zones,
134                    max_twilight_points,
135                    max_storage,
136                    max_function_defs,
137                    max_instruction_defs,
138                    max_stack_elements,
139                    max_size_of_instructions,
140                    max_components_elements,
141                    max_component_depth
142                ))
143            }
144            0x10000 => {
145                let num_glyphs = get_u16(bytes, 4)?;
146                let max_points = get_u16(bytes, 6)?;
147                let max_contours = get_u16(bytes, 8)?;
148                let max_composite_points = get_u16(bytes, 10)?;
149                let max_composite_contours = get_u16(bytes, 12)?;
150                let max_zones = get_u16(bytes, 14)?;
151                let max_twilight_points = get_u16(bytes, 16)?;
152                let max_storage = get_u16(bytes, 18)?;
153                let max_function_defs = get_u16(bytes, 20)?;
154                let max_instruction_defs = get_u16(bytes, 22)?;
155                let max_stack_elements = get_u16(bytes, 24)?;
156                let max_size_of_instructions = get_u16(bytes, 26)?;
157                let max_component_elements = get_u16(bytes, 28)?;
158                let max_component_depth = get_u16(bytes, 30)?;
159                
160                Ok(MaxpTable::new(
161                    version,
162                    num_glyphs,
163                    Some(max_points),
164                    Some(max_contours),
165                    Some(max_composite_points),
166                    Some(max_composite_contours),
167                    Some(max_zones),
168                    Some(max_twilight_points),
169                    Some(max_storage),
170                    Some(max_function_defs),
171                    Some(max_instruction_defs),
172                    Some(max_stack_elements),
173                    Some(max_size_of_instructions),
174                    Some(max_component_elements),
175                    Some(max_component_depth)
176                ))
177            }
178            _ => Err(Error::new(ErrorKind::InvalidData, "Version number invalid"))
179        }
180    }
181    
182    pub fn parse_cmap(&self) -> Result<CmapTable, Error> {
183        let bytes = self.get_table(b"cmap")?;
184        
185        let version = get_u16(bytes, 0)?;
186        if version != 0 {
187            return Err(Error::new(ErrorKind::InvalidData, "Version number isn't zero"));
188        }
189        let num_tables = get_u16(bytes, 2)?;
190        let mut encoding_records: Vec<EncodingRecord> = Vec::new();
191        let mut count = 4;
192        for _ in 0..num_tables {
193            let platform_id = get_u16(bytes, count)?;
194            let encoding_id = get_u16(bytes, count + 2)?;
195            let offset = get_u32(bytes, count + 4)?;
196            encoding_records.push(EncodingRecord::new(platform_id, encoding_id, offset));
197            count += 8;
198        }
199        
200        let mut subtables: Vec<CmapSubtable> = Vec::new();
201        for rec in encoding_records.iter() {
202            let mut offset = rec.offset() as usize;
203            let format = get_u16(bytes, offset)?;
204            offset += 2;
205            match format {
206                0 => {
207                    let length = get_u16(bytes, offset)?;
208                    let language = get_u16(bytes, offset + 2)?;
209                    let glyph_id_array: [u8; 256] = bytes.get(offset + 4..offset + 260).ok_or(ErrorKind::UnexpectedEof)?.try_into().unwrap();
210                    
211                    subtables.push(CmapSubtable::Format0 { length, language, glyph_id_array });
212                }
213                2 => {
214                    let length = get_u16(bytes, offset)?;
215                    let language = get_u16(bytes, offset + 2)?;
216                    let sub_header_keys: [u16; 256] = bytes.get(offset + 4..offset + 516).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
217                        u16::from_be_bytes(ch.try_into().unwrap())
218                    }).collect::<Vec<u16>>().try_into().unwrap();
219                    offset += 516;
220                    let sub_headers_num = (sub_header_keys.iter().max().unwrap() / 8) + 1;
221                    let sub_headers: Vec<SubHeader> = bytes.get(offset..offset + sub_headers_num as usize * 8).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(8).map(|ch| {
222                        let first_code = u16::from_be_bytes(ch[0..2].try_into().unwrap());
223                        let entry_count = u16::from_be_bytes(ch[2..4].try_into().unwrap());
224                        let id_delta = i16::from_be_bytes(ch[4..6].try_into().unwrap());
225                        let id_range_offset = u16::from_be_bytes(ch[6..8].try_into().unwrap());
226                        
227                        SubHeader::new(first_code, entry_count, id_delta, id_range_offset)
228                    }).collect();
229                    offset += sub_headers_num as usize * 8;
230                    let glyph_id_array: Vec<u16> = bytes.get(offset..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
231                        u16::from_be_bytes(ch.try_into().unwrap())
232                    }).collect();
233                    
234                    subtables.push(CmapSubtable::Format2 { length, language, sub_header_keys, sub_headers, glyph_id_array });
235                }
236                4 => {
237                    let length = get_u16(bytes, offset)?;
238                    let language = get_u16(bytes, offset + 2)?;
239                    let seg_count_x2 = get_u16(bytes, offset + 4)?;
240                    let search_range = get_u16(bytes, offset + 6)?;
241                    let entry_selector = get_u16(bytes, offset + 8)?;
242                    let range_shift = get_u16(bytes, offset + 10)?;
243                    offset += 12;
244                    let end_code: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
245                        u16::from_be_bytes(ch.try_into().unwrap())
246                    }).collect();
247                    offset += seg_count_x2 as usize;
248                    let _reserved_pad = get_u16(bytes, offset)?;
249                    offset += 2;
250                    let start_code: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
251                        u16::from_be_bytes(ch.try_into().unwrap())
252                    }).collect();
253                    offset += seg_count_x2 as usize;
254                    let id_delta: Vec<i16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
255                        i16::from_be_bytes(ch.try_into().unwrap())
256                    }).collect();
257                    offset += seg_count_x2 as usize;
258                    let id_range_offset: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
259                        u16::from_be_bytes(ch.try_into().unwrap())
260                    }).collect();
261                    offset += seg_count_x2 as usize;
262                    let glyph_id_array: Vec<u16> = bytes.get(offset..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
263                        u16::from_be_bytes(ch.try_into().unwrap())
264                    }).collect();
265                    
266                    subtables.push(CmapSubtable::Format4 { length, language, seg_count_x2, search_range, entry_selector, range_shift, end_code, _reserved_pad, start_code, id_delta, id_range_offset, glyph_id_array });
267                }
268                6 => {
269                    let length = get_u16(bytes, offset)?;
270                    let language = get_u16(bytes, offset + 2)?;
271                    let first_code = get_u16(bytes, offset + 4)?;
272                    let entry_count = get_u16(bytes, offset + 6)?;
273                    offset += 8;
274                    let glyph_id_array: Vec<u16> = bytes.get(offset..offset + entry_count as usize * 2).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
275                        u16::from_be_bytes(ch.try_into().unwrap())
276                    }).collect();
277                    
278                    subtables.push(CmapSubtable::Format6 { length, language, first_code, entry_count, glyph_id_array });
279                }
280                12 => {
281                    let _reserved = get_u16(bytes, offset)?;
282                    let length = get_u32(bytes, offset + 2)?;
283                    let language = get_u32(bytes, offset + 6)?;
284                    let num_groups = get_u32(bytes, offset + 10)?;
285                    let groups: Vec<Group> = bytes.get(offset + 14..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(12).map(|ch| {
286                        let start_char_code = u32::from_be_bytes(ch[0..4].try_into().unwrap());
287                        let end_char_code = u32::from_be_bytes(ch[4..8].try_into().unwrap());
288                        let start_glyph_id = u32::from_be_bytes(ch[8..].try_into().unwrap());
289                        
290                        Group::new(start_char_code, end_char_code, start_glyph_id)
291                    }).collect();
292                    
293                    subtables.push(CmapSubtable::Format12 { _reserved, length, language, num_groups, groups });
294                }
295                13 => {
296                    let _reserved = get_u16(bytes, offset)?;
297                    let length = get_u32(bytes, offset + 2)?;
298                    let language = get_u32(bytes, offset + 6)?;
299                    let num_groups = get_u32(bytes, offset + 10)?;
300                    let groups: Vec<Group> = bytes.get(offset + 14..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(12).map(|ch| {
301                        let start_char_code = u32::from_be_bytes(ch[0..4].try_into().unwrap());
302                        let end_char_code = u32::from_be_bytes(ch[4..8].try_into().unwrap());
303                        let start_glyph_id = u32::from_be_bytes(ch[8..].try_into().unwrap());
304                        
305                        Group::new(start_char_code, end_char_code, start_glyph_id)
306                    }).collect();
307                    
308                    subtables.push(CmapSubtable::Format13 { _reserved, length, language, num_groups, groups });
309                }
310                14 => {
311                    let length = get_u32(bytes, offset)?;
312                    let num_var_selector_records = get_u32(bytes, offset + 4)?;
313                    let var_selector: Vec<VariationSelectorRecord> = bytes.get(offset + 8..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(11).map(|ch| {
314                        let var_selector: [u8; 3] = ch[0..3].try_into().unwrap();
315                        let default_uvs_offset = u32::from_be_bytes(ch[3..7].try_into().unwrap());
316                        let non_default_uvs_offset = u32::from_be_bytes(ch[7..11].try_into().unwrap());
317                        
318                        VariationSelectorRecord::new(var_selector, default_uvs_offset, non_default_uvs_offset)
319                    }).collect();
320                    
321                    subtables.push(CmapSubtable::Format14 { length, num_var_selector_records, var_selector });
322                }
323                8 | 10 => return Err(Error::new(ErrorKind::InvalidData, "Subtable formats 8 and 10 are considered deprecated")),
324                _ => return Err(Error::new(ErrorKind::InvalidData, ""))
325            }
326        }
327        
328        Ok(CmapTable::new(version, num_tables, encoding_records, subtables))
329    }
330    
331    pub fn parse_loca(&self, num_glyphs: u16, index_to_loc_format: i16) -> Result<Vec<u32>, Error> {
332        let bytes = self.get_table(b"loca")?;
333        
334        let mut indices: Vec<u32> = Vec::new();
335        match index_to_loc_format {
336            0 => {
337                for i in (0..(num_glyphs as usize + 1) * 2).step_by(2) {
338                    let offset = get_u16(bytes, i)?;
339                    indices.push((offset * 2) as u32);
340                }
341            },
342            1 => {
343                for i in (0..(num_glyphs as usize + 1) * 4).step_by(4) {
344                    let offset = get_u32(bytes, i)?;
345                    indices.push(offset);
346                }
347            },
348            _ => return Err(Error::new(ErrorKind::InvalidInput, "index_to_loc_format was not 0 or 1"))
349        }
350        
351        Ok(indices)
352    }
353    
354    pub fn parse_glyf(&self, loca_offsets: Vec<u32>) -> Result<Vec<Option<Glyph>>, Error> {
355        let bytes = self.get_table(b"glyf")?;
356        let mut loca_iter = loca_offsets.iter().peekable();
357        
358        // Could optimize by initializing with capacity based on offsets
359        let mut glyphs: Vec<Option<Glyph>> = Vec::new();
360        
361        while let Some(offset) = loca_iter.next() {
362            if let Some(next_offset) = loca_iter.peek() {
363                if *next_offset - offset == 0 {
364                    glyphs.push(None);
365                    continue;
366                }
367                
368                let current_glyph_bytes = bytes.get(*offset as usize..**next_offset as usize).ok_or(ErrorKind::UnexpectedEof)?;
369                let mut current_offset: usize = 0;
370                let number_of_contours = get_i16(current_glyph_bytes, 0)?;
371                let x_min = get_i16(current_glyph_bytes, 2)?;
372                let y_min = get_i16(current_glyph_bytes, 4)?;
373                let x_max = get_i16(current_glyph_bytes, 6)?;
374                let y_max = get_i16(current_glyph_bytes, 8)?;
375                current_offset += 10;
376                let header = GlyphHeader::new(number_of_contours, x_min, y_min, x_max, y_max);
377                let mut are_instructions;
378                if number_of_contours > 0 {
379                    let end_pts_of_contours: Vec<u16> = current_glyph_bytes
380                        .get(current_offset..current_offset + number_of_contours as usize * 2)
381                        .ok_or(ErrorKind::UnexpectedEof)?
382                        .chunks_exact(2)
383                        .map(|ch| {
384                            u16::from_be_bytes(ch.try_into().unwrap())
385                        }).collect();
386                    current_offset += number_of_contours as usize * 2;
387                    let instruction_length = get_u16(current_glyph_bytes, current_offset)?;
388                    current_offset += 2;
389                    let instructions: Vec<u8> = current_glyph_bytes.get(current_offset..current_offset + instruction_length as usize).ok_or(ErrorKind::UnexpectedEof)?.to_vec();
390                    current_offset += instruction_length as usize;
391                    let total_points = end_pts_of_contours.last().unwrap() + 1;
392                    let mut flags: Vec<u8> = Vec::with_capacity(total_points as usize);
393                    while flags.len() < total_points as usize {
394                        let flag = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
395                        if flag & REPEAT_FLAG != 0 {
396                            let repeat_count = current_glyph_bytes.get(current_offset + 1).ok_or(ErrorKind::UnexpectedEof)?;
397                            let flag_vec = vec![flag; *repeat_count as usize + 1];
398                            flags.extend(flag_vec);
399                            current_offset += 2;
400                        }
401                        else {
402                            flags.push(*flag);
403                            current_offset += 1;
404                        }
405                    }
406                    let mut x_coordinates: Vec<i16> = Vec::with_capacity(total_points as usize);
407                    let mut current_x: i16 = 0;
408                    for flag in flags.iter() {
409                        if flag & X_SHORT_VECTOR != 0 {
410                            let x = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
411                            if flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR != 0 {
412                                current_x += *x as i16;
413                            }
414                            else {
415                                current_x -= *x as i16;
416                            }
417                            current_offset += 1;
418                        }
419                        else {
420                            if flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR == 0 {
421                                current_x += get_i16(current_glyph_bytes, current_offset)?;
422                                current_offset += 2;
423                            }
424                        }
425                        
426                        x_coordinates.push(current_x);
427                    }
428                    let mut y_coordinates: Vec<i16> = Vec::with_capacity(total_points as usize);
429                    let mut current_y: i16 = 0;
430                    for flag in flags.iter() {
431                        if flag & Y_SHORT_VECTOR != 0 {
432                            let y = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
433                            if flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR != 0 {
434                                current_y += *y as i16;
435                            }
436                            else {
437                                current_y -= *y as i16;
438                            }
439                            current_offset += 1;
440                        }
441                        else {
442                            if flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR == 0 {
443                                current_y += get_i16(current_glyph_bytes, current_offset)?;
444                                current_offset += 2;
445                            }
446                        }
447                        
448                        y_coordinates.push(current_y);
449                    }
450                    
451                    glyphs.push(Some(Glyph::Simple { header, end_pts_of_contours, instruction_length, instructions, flags, x_coordinates, y_coordinates }));
452                }
453                else if number_of_contours == -1 {
454                    let mut components: Vec<Component> = Vec::new();
455                    loop {
456                        let flags = get_u16(current_glyph_bytes, current_offset)?;
457                        let glyph_index = get_u16(current_glyph_bytes, current_offset + 2)?;
458                        current_offset += 4;
459                        let argument_1: i16;
460                        let argument_2: i16;
461                        if flags & ARG_1_AND_2_ARE_WORDS != 0 {
462                            argument_1 = get_i16(current_glyph_bytes, current_offset)?;
463                            argument_2 = get_i16(current_glyph_bytes, current_offset + 2)?;
464                            current_offset += 4;
465                        }
466                        else {
467                            argument_1 = *current_glyph_bytes
468                                .get(current_offset)
469                                .ok_or(ErrorKind::UnexpectedEof)? as i8 as i16;
470                            argument_2 = *current_glyph_bytes
471                                .get(current_offset + 1)
472                                .ok_or(ErrorKind::UnexpectedEof)? as i8 as i16;
473                            current_offset += 2;
474                        }
475                        let transformation: [i16; 4];
476                        if flags & WE_HAVE_A_SCALE != 0 {
477                            transformation = [get_i16(current_glyph_bytes, current_offset)?, 0, 0, 0];
478                            current_offset += 2;
479                        }
480                        else if flags & WE_HAVE_AN_X_AND_Y_SCALE != 0 {
481                            transformation = [
482                                get_i16(current_glyph_bytes, current_offset)?,
483                                get_i16(current_glyph_bytes, current_offset + 2)?,
484                                0, 0
485                            ];
486                            current_offset += 4;
487                        }
488                        else if flags & WE_HAVE_A_TWO_BY_TWO != 0 {
489                            transformation = [
490                                get_i16(current_glyph_bytes, current_offset)?,
491                                get_i16(current_glyph_bytes, current_offset + 2)?,
492                                get_i16(current_glyph_bytes, current_offset + 4)?,
493                                get_i16(current_glyph_bytes, current_offset + 6)?
494                            ];
495                            current_offset += 8;
496                        }
497                        else {
498                            transformation = [0, 0, 0, 0];
499                        }
500                        
501                        components.push(Component::new(flags, glyph_index, argument_1, argument_2, transformation));
502                        
503                        are_instructions = flags & WE_HAVE_INSTRUCTIONS != 0;
504                        
505                        if flags & MORE_COMPONENTS == 0 { break; }
506                    }
507                    let mut instruction_length: Option<u16> = None;
508                    let mut instructions: Option<Vec<u8>> = None;
509                    if are_instructions {
510                        instruction_length = Some(get_u16(current_glyph_bytes, current_offset)?);
511                        current_offset += 2;
512                        instructions = Some(
513                            current_glyph_bytes
514                                .get(current_offset..current_offset + instruction_length.unwrap() as usize)
515                                .ok_or(ErrorKind::UnexpectedEof)?
516                                .to_vec()
517                        )
518                    }
519                    
520                    glyphs.push(Some(Glyph::Composite { header, components, instruction_length, instructions }));
521                }
522                else if number_of_contours == 0 {
523                    glyphs.push(None);
524                }
525            }
526        }
527        
528        Ok(glyphs)
529    }
530    
531    pub fn parse_hhea(&self) -> Result<HheaTable, Error> {
532        let bytes = self.get_table(b"hhea")?;
533        
534        let version = get_u32(bytes, 0)?;
535        if version != 0x00010000 {
536            return Err(Error::new(ErrorKind::InvalidData, "Version number for hhea table is incorrect"));
537        }
538        let ascender = get_i16(bytes, 4)?;
539        let descender = get_i16(bytes, 6)?;
540        let line_gap = get_i16(bytes, 8)?;
541        let advance_width_max = get_u16(bytes, 10)?;
542        let min_left_side_bearing = get_i16(bytes, 12)?;
543        let min_right_side_bearing = get_i16(bytes, 14)?;
544        let x_max_extent = get_i16(bytes, 16)?;
545        let caret_slope_rise = get_i16(bytes, 18)?;
546        let caret_slope_run = get_i16(bytes, 20)?;
547        let caret_offset = get_i16(bytes, 22)?;
548        let _reserved1 = 0;
549        let _reserved2 = 0;
550        let _reserved3 = 0;
551        let _reserved4 = 0;
552        let metric_data_format = get_i16(bytes, 32)?;
553        let number_of_h_metrics = get_u16(bytes, 34)?;
554        
555        Ok(HheaTable::new(
556            version,
557            ascender,
558            descender,
559            line_gap,
560            advance_width_max,
561            min_left_side_bearing,
562            min_right_side_bearing,
563            x_max_extent,
564            caret_slope_rise,
565            caret_slope_run,
566            caret_offset,
567            _reserved1,
568            _reserved2,
569            _reserved3,
570            _reserved4,
571            metric_data_format,
572            number_of_h_metrics
573        ))
574    }
575    
576    pub fn parse_hmtx(&self, num_glyphs: u16, number_of_h_metrics: u16) -> Result<HmtxTable, Error> {
577        let bytes = self.get_table(b"hmtx")?;
578        
579        let mut entries: Vec<HmtxEntry> = bytes
580            .get(0..number_of_h_metrics as usize * 4)
581            .ok_or(ErrorKind::UnexpectedEof)?
582            .chunks_exact(4)
583            .map(|ch| {
584                let advance_width = u16::from_be_bytes(ch[0..2].try_into().unwrap());
585                let lsb = i16::from_be_bytes(ch[2..4].try_into().unwrap());
586                
587                HmtxEntry::FullMetric { advance_width, lsb }
588            }).collect();
589        
590        let shared_advance_var = entries.last().unwrap();
591        let shared_advance_width = match shared_advance_var {
592            HmtxEntry::FullMetric { advance_width, lsb: _ } => *advance_width,
593            _ => unreachable!()
594        };
595        
596        let leftovers = num_glyphs - number_of_h_metrics;
597        
598        entries.extend(
599            bytes
600                .get(number_of_h_metrics as usize * 4..(number_of_h_metrics as usize * 4) + (leftovers as usize * 2))
601                .ok_or(ErrorKind::UnexpectedEof)?
602                .chunks_exact(2)
603                .map(|ch| {
604                    HmtxEntry::LeftoverBearing(i16::from_be_bytes(ch.try_into().unwrap()))
605                })
606        );
607        
608        Ok(HmtxTable::new(entries, shared_advance_width))
609    }
610    
611    pub fn parse_name(&self) -> Result<NameTable, Error> {
612        let bytes = self.get_table(b"name")?;
613        let mut offset = 0;
614        
615        let version = get_u16(bytes, 0)?;
616        if version != 0 && version != 1 {
617            return Err(Error::new(ErrorKind::InvalidData, "Version number is not 0 or 1"));
618        }
619        let count = get_u16(bytes, 2)?;
620        let storage_offset = get_u16(bytes, 4)?;
621        offset += 6;
622        let records: Vec<NameRecord> = bytes.get(offset..offset + count as usize * 12)
623            .ok_or(ErrorKind::UnexpectedEof)?
624            .chunks_exact(12)
625            .map(|ch| {
626                let platform_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
627                let encoding_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
628                let language_id = u16::from_be_bytes(ch[4..6].try_into().unwrap());
629                let name_id = u16::from_be_bytes(ch[6..8].try_into().unwrap());
630                let length = u16::from_be_bytes(ch[8..10].try_into().unwrap());
631                let string_offset = u16::from_be_bytes(ch[10..12].try_into().unwrap());
632                let string_bytes = bytes.get(storage_offset as usize + string_offset as usize..storage_offset as usize + string_offset as usize + length as usize)
633                    .ok_or(ErrorKind::UnexpectedEof)?;
634                let string = decode_name_bytes(string_bytes, platform_id, encoding_id)?;
635                
636                Ok(NameRecord::new(platform_id, encoding_id, language_id, name_id, length, string_offset, string))
637            }).collect::<Result<Vec<_>, Error>>()?;
638        offset += count as usize * 12;
639        let mut lang_tag_count: Option<u16> = None;
640        let mut lang_tag_records: Option<Vec<LangTagRecord>> = None;
641        if version == 1 {
642            lang_tag_count = Some(get_u16(bytes, offset)?);
643            offset += 2;
644            lang_tag_records = Some(
645                bytes.get(offset..offset + lang_tag_count.unwrap() as usize * 4)
646                    .ok_or(ErrorKind::UnexpectedEof)?
647                    .chunks_exact(4)
648                    .map(|ch| {
649                        let length = u16::from_be_bytes(ch[0..2].try_into().unwrap());
650                        let lang_tag_offset = u16::from_be_bytes(ch[2..4].try_into().unwrap());
651                        let string_bytes: Vec<u16> = bytes.get(storage_offset as usize + lang_tag_offset as usize.. storage_offset as usize + lang_tag_offset as usize + length as usize)
652                            .ok_or(ErrorKind::UnexpectedEof)?
653                            .chunks_exact(2)
654                            .map(|ch| {
655                                u16::from_be_bytes(ch[0..2].try_into().unwrap())
656                            }).collect();
657                        let string = String::from_utf16(&string_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
658                        
659                        Ok(LangTagRecord::new(length, lang_tag_offset, string))
660                    }).collect::<Result<Vec<_>, Error>>()?
661            );
662        }
663        
664        Ok(NameTable::new(version, count, storage_offset, records, lang_tag_count, lang_tag_records))
665    }
666    
667    pub fn parse_os2(&self) -> Result<OS2Table, Error> {
668        let bytes = self.get_table(b"OS/2")?;
669        
670        let version = get_u16(bytes, 0)?;
671        let x_avg_char_width = get_i16(bytes, 2)?;
672        let us_weight_class = get_u16(bytes, 4)?;
673        let us_width_class = get_u16(bytes, 6)?;
674        let fs_type = get_u16(bytes, 8)?;
675        let y_subscript_x_size = get_i16(bytes, 10)?;
676        let y_subscript_y_size = get_i16(bytes, 12)?;
677        let y_subscript_x_offset = get_i16(bytes, 14)?;
678        let y_subscript_y_offset = get_i16(bytes, 16)?;
679        let y_superscript_x_size = get_i16(bytes, 18)?;
680        let y_superscript_y_size = get_i16(bytes, 20)?;
681        let y_superscript_x_offset = get_i16(bytes, 22)?;
682        let y_superscript_y_offset = get_i16(bytes, 24)?;
683        let y_strikeout_size = get_i16(bytes, 26)?;
684        let y_strikeout_position = get_i16(bytes, 28)?;
685        let s_family_class = get_i16(bytes, 30)?;
686        let panose: [u8; 10] = bytes.get(32..42)
687            .ok_or(ErrorKind::UnexpectedEof)?
688            .try_into()
689            .unwrap();
690        let ul_unicode_range_1 = get_u32(bytes, 42)?;
691        let ul_unicode_range_2 = get_u32(bytes, 46)?;
692        let ul_unicode_range_3 = get_u32(bytes, 50)?;
693        let ul_unicode_range_4 = get_u32(bytes, 54)?;
694        let ach_vend_id: [u8; 4] = bytes.get(58..62)
695            .ok_or(ErrorKind::UnexpectedEof)?
696            .try_into()
697            .unwrap();
698        let fs_selection = get_u16(bytes, 62)?;
699        let us_first_char_index = get_u16(bytes, 64)?;
700        let us_last_char_index = get_u16(bytes, 66)?;
701        let s_typo_ascender = get_i16(bytes, 68)?;
702        let s_typo_descender = get_i16(bytes, 70)?;
703        let s_typo_line_gap = get_i16(bytes, 72)?;
704        let us_win_ascent = get_u16(bytes, 74)?;
705        let us_win_descent = get_u16(bytes, 76)?;
706        let mut ul_code_page_range_1: Option<u32> = None;
707        let mut ul_code_page_range_2: Option<u32> = None;
708        if version >= 1 {
709            ul_code_page_range_1 = Some(get_u32(bytes, 78)?);
710            ul_code_page_range_2 = Some(get_u32(bytes, 82)?);
711        }
712        let mut sx_height: Option<i16> = None;
713        let mut s_cap_height: Option<i16> = None;
714        let mut us_default_char: Option<u16> = None;
715        let mut us_break_char: Option<u16> = None;
716        let mut us_max_context: Option<u16> = None;
717        if version >= 2 {
718            sx_height = Some(get_i16(bytes, 86)?);
719            s_cap_height = Some(get_i16(bytes, 88)?);
720            us_default_char = Some(get_u16(bytes, 90)?);
721            us_break_char = Some(get_u16(bytes, 92)?);
722            us_max_context = Some(get_u16(bytes, 94)?);
723        }
724        let mut us_lower_optical_point_size: Option<u16> = None;
725        let mut us_upper_optical_point_size: Option<u16> = None;
726        if version >= 5 {
727            us_lower_optical_point_size = Some(get_u16(bytes, 96)?);
728            us_upper_optical_point_size = Some(get_u16(bytes, 98)?);
729        }
730        
731        Ok(OS2Table::new(
732            version,
733            x_avg_char_width,
734            us_weight_class,
735            us_width_class,
736            fs_type,
737            y_subscript_x_size,
738            y_subscript_y_size,
739            y_subscript_x_offset,
740            y_subscript_y_offset,
741            y_superscript_x_size,
742            y_superscript_y_size,
743            y_superscript_x_offset,
744            y_superscript_y_offset,
745            y_strikeout_size,
746            y_strikeout_position,
747            s_family_class,
748            panose,
749            ul_unicode_range_1,
750            ul_unicode_range_2,
751            ul_unicode_range_3,
752            ul_unicode_range_4,
753            ach_vend_id,
754            fs_selection,
755            us_first_char_index,
756            us_last_char_index,
757            s_typo_ascender,
758            s_typo_descender,
759            s_typo_line_gap,
760            us_win_ascent,
761            us_win_descent,
762            ul_code_page_range_1,
763            ul_code_page_range_2,
764            sx_height,
765            s_cap_height,
766            us_default_char,
767            us_break_char,
768            us_max_context,
769            us_lower_optical_point_size,
770            us_upper_optical_point_size
771        ))
772    }
773    
774    pub fn parse_post(&self) -> Result<PostTable, Error> {
775        let bytes = self.get_table(b"post")?;
776        
777        let version = get_u32(bytes, 0)?;
778        let italic_angle = get_i32(bytes, 4)?;
779        let underline_position = get_i16(bytes, 8)?;
780        let underline_thickness = get_i16(bytes, 10)?;
781        let is_fixed_pitch = get_u32(bytes, 12)?;
782        let min_mem_type_42 = get_u32(bytes, 16)?;
783        let max_mem_type_42 = get_u32(bytes, 20)?;
784        let min_mem_type_1 = get_u32(bytes, 24)?;
785        let max_mem_type_1 = get_u32(bytes, 28)?;
786        let mut num_glyphs: Option<u16> = None;
787        let mut glyph_name_index: Option<Vec<u16>> = None;
788        let mut names: Option<Vec<String>> = None;
789        if version == 0x00010000 {
790            names = Some(MAC_STANDARD_NAMES.iter().map(|s| s.to_string()).collect());
791        }
792        else if version == 0x00020000 {
793            let mut offset = 34;
794            num_glyphs = Some(get_u16(bytes, 32)?);
795            glyph_name_index = Some(
796                bytes.get(offset..offset + num_glyphs.unwrap() as usize * 2)
797                    .ok_or(ErrorKind::UnexpectedEof)?
798                    .chunks_exact(2)
799                    .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap())).collect()
800            );
801            let max_idx = glyph_name_index.as_ref().unwrap().iter().max().unwrap();
802            let mut extra_names: Vec<String> = Vec::with_capacity(*max_idx as usize - 257);
803            if *max_idx >= 258 {
804                offset += num_glyphs.unwrap() as usize * 2;
805                for _ in 0..(max_idx - 257) {
806                    let length = bytes.get(offset).ok_or(ErrorKind::UnexpectedEof)?;
807                    offset += 1;
808                    let string_bytes = bytes.get(offset..offset + *length as usize).ok_or(ErrorKind::UnexpectedEof)?;
809                    offset += *length as usize;
810                    extra_names.push(decode_name_bytes(string_bytes, 1, 0)?);
811                }
812            }
813            names = Some(Vec::with_capacity(num_glyphs.unwrap() as usize));
814            for idx in glyph_name_index.as_ref().unwrap() {
815                if *idx <= 257 {
816                    names.as_mut().unwrap().push(MAC_STANDARD_NAMES[*idx as usize].to_string());
817                }
818                else {
819                    names.as_mut().unwrap().push(extra_names[*idx as usize - 258].to_string());
820                }
821            }
822        }
823        else if version == 0x00025000 {
824            return Err(Error::new(ErrorKind::InvalidData, "Version 2.5 is deprecated"))
825        }
826        else if version != 0x00030000 {
827            return Err(Error::new(ErrorKind::InvalidData, format!("Version {} is not valid", version)))
828        }
829        
830        Ok(PostTable::new(
831            version,
832            italic_angle,
833            underline_position,
834            underline_thickness,
835            is_fixed_pitch,
836            min_mem_type_42,
837            max_mem_type_42,
838            min_mem_type_1,
839            max_mem_type_1,
840            num_glyphs,
841            glyph_name_index,
842            names
843        ))
844    }
845    
846    pub fn parse_vhea(&self) -> Result<VheaTable, Error> {
847        let vhea_bytes = self.get_table(b"vhea")?;
848        
849        let version = get_u32(vhea_bytes, 0)?;
850        if version != 0x00010000 && version != 0x00011000 {
851            return Err(Error::new(ErrorKind::InvalidData, format!("Invalid version number: {}", version)))
852        }
853        let vert_typo_ascender = get_i16(vhea_bytes, 4)?;
854        let vert_typo_descender = get_i16(vhea_bytes, 6)?;
855        let vert_typo_line_gap = get_i16(vhea_bytes, 8)?;
856        let advance_height_max = get_u16(vhea_bytes, 10)?;
857        let min_top_side_bearing = get_i16(vhea_bytes, 12)?;
858        let min_bottom_side_bearing = get_i16(vhea_bytes, 14)?;
859        let y_max_extent = get_i16(vhea_bytes, 16)?;
860        let caret_slope_rise = get_i16(vhea_bytes, 18)?;
861        let caret_slope_run = get_i16(vhea_bytes, 20)?;
862        let caret_offset = get_i16(vhea_bytes, 22)?;
863        let _reserved1 = get_i16(vhea_bytes, 24)?;
864        let _reserved2 = get_i16(vhea_bytes, 26)?;
865        let _reserved3 = get_i16(vhea_bytes, 28)?;
866        let _reserved4 = get_i16(vhea_bytes, 30)?;
867        let metric_data_format = get_i16(vhea_bytes, 32)?;
868        let num_of_long_ver_metrics = get_u16(vhea_bytes, 34)?;
869        
870        Ok(VheaTable::new(
871            version,
872            vert_typo_ascender,
873            vert_typo_descender,
874            vert_typo_line_gap,
875            advance_height_max,
876            min_top_side_bearing,
877            min_bottom_side_bearing,
878            y_max_extent,
879            caret_slope_rise,
880            caret_slope_run,
881            caret_offset,
882            _reserved1,
883            _reserved2,
884            _reserved3,
885            _reserved4,
886            metric_data_format,
887            num_of_long_ver_metrics
888        ))
889    }
890    
891    pub fn parse_vmtx(&self, num_glyphs: u16, number_of_v_metrics: u16) -> Result<VmtxTable, Error> {
892        let bytes = self.get_table(b"vmtx")?;
893        
894        let mut entries: Vec<VmtxEntry> = bytes
895            .get(0..number_of_v_metrics as usize * 4)
896            .ok_or(ErrorKind::UnexpectedEof)?
897            .chunks_exact(4)
898            .map(|ch| {
899                let advance_height = u16::from_be_bytes(ch[0..2].try_into().unwrap());
900                let tsb = i16::from_be_bytes(ch[2..4].try_into().unwrap());
901                
902                VmtxEntry::FullMetric { advance_height, tsb }
903            }).collect();
904        
905        let shared_advance_var = entries.last().unwrap();
906        let shared_advance_height = match shared_advance_var {
907            VmtxEntry::FullMetric { advance_height, tsb: _ } => *advance_height,
908            _ => unreachable!()
909        };
910        
911        let leftovers = num_glyphs - number_of_v_metrics;
912        
913        entries.extend(
914            bytes
915                .get(number_of_v_metrics as usize * 4..(number_of_v_metrics as usize * 4) + (leftovers as usize * 2))
916                .ok_or(ErrorKind::UnexpectedEof)?
917                .chunks_exact(2)
918                .map(|ch| {
919                    VmtxEntry::LeftoverBearing(i16::from_be_bytes(ch.try_into().unwrap()))
920                })
921        );
922        
923        Ok(VmtxTable::new(entries, shared_advance_height))
924    }
925    
926    pub fn parse_kern(&self) -> Result<KernTable, Error> {
927        let bytes = self.get_table(b"kern")?;
928        
929        let version_test = get_u16(bytes, 0)?;
930        match version_test {
931            0 => {
932                let version = get_u16(bytes, 0)?;
933                let n_tables = get_u16(bytes, 2)?;
934                let mut subtables: Vec<WindowsSubtable> = Vec::with_capacity(n_tables as usize);
935                let mut offset: usize = 4;
936                let mut subtable_start: usize;
937                for _ in 0..n_tables {
938                    subtable_start = offset;
939                    let version = get_u16(bytes, offset)?;
940                    let length = get_u16(bytes, offset + 2)?;
941                    let coverage = get_u16(bytes, offset + 4)?;
942                    offset += 6;
943                    let subtable = match coverage >> 8 {
944                        0 => parse_kern_format0(&bytes[offset..]),
945                        2 => parse_kern_format2(&bytes[offset..], subtable_start, length as usize),
946                        _ => {
947                            offset += length as usize - 6;
948                            continue;
949                        }
950                    }?;
951                    
952                    subtables.push(WindowsSubtable::new(version, length, coverage, subtable));
953                }
954                
955                Ok(KernTable::Windows {
956                    version,
957                    n_tables,
958                    subtables
959                })
960            }
961            1 => {
962                let version = get_u32(bytes, 0)?;
963                let n_tables = get_u32(bytes, 4)?;
964                let mut offset: usize = 8;
965                let mut subtable_start: usize;
966                let mut subtables: Vec<MacSubtable> = Vec::with_capacity(n_tables as usize);
967                for _ in 0..n_tables {
968                    subtable_start = offset;
969                    let length = get_u32(bytes, offset)?;
970                    let coverage = get_u16(bytes, offset + 4)?;
971                    let tuple_index = get_u16(bytes, offset + 6)?;
972                    offset += 8;
973                    let subtable = match coverage & 0xFF {
974                        0 => parse_kern_format0(&bytes[offset..]),
975                        2 => parse_kern_format2(&bytes[offset..], subtable_start, length as usize),
976                        _ => {
977                            offset += length as usize - 8;
978                            continue;
979                        }
980                    }?;
981                    
982                    subtables.push(MacSubtable::new(length, coverage, tuple_index, subtable));
983                }
984                
985                Ok(KernTable::Mac {
986                    version,
987                    n_tables,
988                    subtables
989                })
990            }
991            _ => Err(Error::new(ErrorKind::InvalidData, format!("Invalid version number: {}", version_test)))
992        }
993    }
994    
995    pub fn parse_gasp(&self) -> Result<GaspTable, Error> {
996        let bytes = self.get_table(b"gasp")?;
997        
998        let version = get_u16(bytes, 0)?;
999        if version != 0 && version != 1 {
1000            return Err(Error::new(ErrorKind::InvalidData, format!("Version number is not 0 or 1: {}", version)))
1001        }
1002        let num_ranges = get_u16(bytes, 2)?;
1003        let range_records: Vec<GaspRangeRecord> = bytes.get(4..4 + num_ranges as usize * 4)
1004            .ok_or(ErrorKind::UnexpectedEof)?
1005            .chunks_exact(4)
1006            .map(|ch| {
1007                let range_max_ppem = get_u16(ch, 0)?;
1008                let range_gasp_behavior = get_u16(ch, 2)?;
1009                
1010                Ok(GaspRangeRecord::new(range_max_ppem, range_gasp_behavior))
1011            }).collect::<Result<Vec<_>, Error>>()?;
1012        
1013        Ok(GaspTable::new(version, num_ranges, range_records))
1014    }
1015    
1016    pub fn parse_cvt(&self) -> Result<Vec<i16>, Error> {
1017        let cvt_bytes = self.get_table(b"cvt ")?;
1018        
1019        Ok(
1020            cvt_bytes.chunks_exact(2)
1021                .map(|ch| {
1022                    i16::from_be_bytes(ch[0..2].try_into().unwrap())
1023                }).collect()
1024        )
1025    }
1026    
1027    pub fn parse_fpgm(&self) -> Result<Vec<u8>, Error> {
1028        Ok(self.get_table(b"fpgm")?.to_vec())
1029    }
1030    
1031    pub fn parse_prep(&self) -> Result<Vec<u8>, Error> {
1032        Ok(self.get_table(b"prep")?.to_vec())
1033    }
1034    
1035    pub fn parse_gpos(&self) -> Result<GposTable<GposSubtable>, Error> {
1036        let bytes = self.get_table(b"GPOS")?;
1037        let mut offset: usize = 0;
1038        
1039        let major_version = get_u16(bytes, 0)?;
1040        let minor_version = get_u16(bytes, 2)?;
1041        let script_list_offset = get_u16(bytes, 4)?;
1042        let feature_list_offset = get_u16(bytes, 6)?;
1043        let lookup_list_offset = get_u16(bytes, 8)?;
1044        offset += 10;
1045        let feature_variations_offset: Option<u32>;
1046        if minor_version >= 1 {
1047            feature_variations_offset = Some(get_u32(bytes, offset)?);
1048        }
1049        else {
1050            feature_variations_offset = None;
1051        }
1052        let header = TableHeader::new(
1053            major_version,
1054            minor_version,
1055            script_list_offset,
1056            feature_list_offset,
1057            lookup_list_offset,
1058            feature_variations_offset
1059        );
1060        let script_list = parse_script_list(bytes, script_list_offset)?;
1061        let feature_list = parse_feature_list(bytes, feature_list_offset)?;
1062        let lookup_list = parse_lookup_list(bytes, lookup_list_offset)?;
1063        let feature_variations: Option<FeatureVariations>;
1064        if feature_variations_offset != None {
1065            feature_variations = Some(parse_feature_variations(bytes, feature_variations_offset.unwrap(), feature_list.clone())?);
1066        }
1067        else {
1068            feature_variations = None;
1069        }
1070        
1071        Ok(GposTable::new(
1072            header,
1073            script_list,
1074            feature_list,
1075            lookup_list,
1076            feature_variations
1077        ))
1078    }
1079    
1080    pub fn parse_gsub(&self) -> Result<GsubTable<GsubSubtable>, Error> {
1081        let bytes = self.get_table(b"GSUB")?;
1082        let mut offset: usize = 0;
1083        
1084        let major_version = get_u16(bytes, 0)?;
1085        let minor_version = get_u16(bytes, 2)?;
1086        let script_list_offset = get_u16(bytes, 4)?;
1087        let feature_list_offset = get_u16(bytes, 6)?;
1088        let lookup_list_offset = get_u16(bytes, 8)?;
1089        offset += 10;
1090        let feature_variations_offset: Option<u32>;
1091        if minor_version >= 1 {
1092            feature_variations_offset = Some(get_u32(bytes, offset)?);
1093        }
1094        else {
1095            feature_variations_offset = None;
1096        }
1097        let header = TableHeader::new(
1098            major_version,
1099            minor_version,
1100            script_list_offset,
1101            feature_list_offset,
1102            lookup_list_offset,
1103            feature_variations_offset
1104        );
1105        let script_list = parse_script_list(bytes, script_list_offset)?;
1106        let feature_list = parse_feature_list(bytes, feature_list_offset)?;
1107        let lookup_list = parse_lookup_list(bytes, lookup_list_offset)?;
1108        let feature_variations: Option<FeatureVariations>;
1109        if feature_variations_offset != None {
1110            feature_variations = Some(parse_feature_variations(bytes, feature_variations_offset.unwrap(), feature_list.clone())?);
1111        }
1112        else {
1113            feature_variations = None;
1114        }
1115        
1116        Ok(GsubTable::new(
1117            header,
1118            script_list,
1119            feature_list,
1120            lookup_list,
1121            feature_variations
1122        ))
1123    }
1124}
1125
1126fn parse_kern_format0(bytes: &[u8]) -> Result<KernSubtable, Error> {
1127    let n_pairs = get_u16(bytes, 0)?;
1128    let search_range = get_u16(bytes, 2)?;
1129    let entry_selector = get_u16(bytes, 4)?;
1130    let range_shift = get_u16(bytes, 6)?;
1131    let pairs: Vec<KernPair> = bytes.get(8..8 + n_pairs as usize * 6)
1132        .ok_or(ErrorKind::UnexpectedEof)?
1133        .chunks_exact(6)
1134        .map(|ch| {
1135            let left = get_u16(ch, 0)?;
1136            let right = get_u16(ch, 2)?;
1137            let value = get_i16(ch, 4)?;
1138            
1139            Ok(KernPair::new(left, right, value))
1140        }).collect::<Result<Vec<_>, Error>>()?;
1141    
1142    Ok(KernSubtable::Format0 {
1143        n_pairs,
1144        search_range,
1145        entry_selector,
1146        range_shift,
1147        pairs
1148    })
1149}
1150
1151fn parse_kern_format2(bytes: &[u8], subtable_start: usize, length: usize) -> Result<KernSubtable, Error> {
1152    let mut offset = 0;
1153    let row_width = get_u16(bytes, offset)?;
1154    let left_offset = get_u16(bytes, offset + 2)?;
1155    let right_offset = get_u16(bytes, offset + 4)?;
1156    let array_offset = get_u16(bytes, offset + 6)?;
1157    offset = subtable_start + left_offset as usize;
1158    let left_class_format = get_u16(bytes, offset)?;
1159    let left_class_table = parse_kern_class(bytes, left_class_format, offset)?;
1160    offset = subtable_start + right_offset as usize;
1161    let right_class_format = get_u16(bytes, offset)?;
1162    let right_class_table = parse_kern_class(bytes, right_class_format, offset)?;
1163    offset = subtable_start + array_offset as usize;
1164    let kerning_array: Vec<i16> = bytes.get(offset..offset + length)
1165        .ok_or(ErrorKind::UnexpectedEof)?
1166        .chunks_exact(2)
1167        .map(|ch| Ok(get_i16(ch, 0)?))
1168        .collect::<Result<Vec<_>, Error>>()?;
1169    
1170    Ok(KernSubtable::Format2 {
1171        row_width,
1172        left_offset,
1173        right_offset,
1174        array_offset,
1175        left_class_table,
1176        right_class_table,
1177        kerning_array
1178    })
1179}
1180
1181fn parse_kern_class(bytes: &[u8], class_format: u16, offset: usize) -> Result<KernClassTable, Error> {
1182    let mut offset = offset;
1183    match class_format {
1184        1 => {
1185            let start_glyph = get_u16(bytes, offset + 2)?;
1186            let glyph_count = get_u16(bytes, offset + 4)?;
1187            offset += 6;
1188            let class_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
1189                .ok_or(ErrorKind::UnexpectedEof)?
1190                .chunks_exact(2)
1191                .map(|ch| Ok(get_u16(ch, 0)?))
1192                .collect::<Result<Vec<_>, Error>>()?;
1193            
1194            Ok(KernClassTable::Format1 { start_glyph, glyph_count, class_ids })
1195        }
1196        2 => {
1197            let range_count = get_u16(bytes, offset)?;
1198            offset += 2;
1199            let ranges: Vec<Range> = bytes.get(offset..offset + range_count as usize * 6)
1200                .ok_or(ErrorKind::UnexpectedEof)?
1201                .chunks_exact(6)
1202                .map(|ch| {
1203                    let start_glyph = get_u16(ch, 0)?;
1204                    let end_glyph = get_u16(ch, 2)?;
1205                    let class = get_u16(ch, 4)?;
1206                    
1207                    Ok(Range::new(start_glyph, end_glyph, class))
1208                }).collect::<Result<Vec<_>, Error>>()?;
1209            
1210            Ok(KernClassTable::Format2 { range_count, ranges })
1211        }
1212        _ => Err(Error::new(ErrorKind::InvalidData, format!("Class table format invalid: {}", class_format)))
1213    }
1214}
1215
1216fn parse_script_list(bytes: &[u8], script_list_offset: u16) -> Result<ScriptList, Error> {
1217    let mut offset = script_list_offset as usize;
1218    
1219    let script_count = get_u16(bytes, offset)?;
1220    offset += 2;
1221    let script_records: Vec<ScriptRecord> = bytes.get(offset..offset + script_count as usize * 6)
1222        .ok_or(ErrorKind::UnexpectedEof)?
1223        .chunks_exact(6)
1224        .map(|ch| {
1225            let script_tag: [u8; 4] = ch[0..4].try_into().unwrap();
1226            let script_offset = get_u16(ch, 4)?;
1227            
1228            Ok(ScriptRecord::new(script_tag, script_offset))
1229        }).collect::<Result<Vec<_>, Error>>()?;
1230    let scripts: Vec<Script> = script_records.iter()
1231        .map(|sr| {
1232            let mut offset = (script_list_offset + sr.script_offset()) as usize;
1233            let test_offset = get_u16(bytes, offset)?;
1234            offset += 2;
1235            let default_lang_sys_offset = if test_offset != 0 {
1236                Some(test_offset)
1237            }
1238            else {
1239                None
1240            };
1241            let default_lang_sys = if default_lang_sys_offset != None {
1242                let mut offset = (script_list_offset + sr.script_offset() + default_lang_sys_offset.unwrap()) as usize;
1243                let _lookup_order_offset = get_u16(bytes, offset)?;
1244                let required_feature_index = get_u16(bytes, offset + 2)?;
1245                let feature_index_count = get_u16(bytes, offset + 4)?;
1246                offset += 6;
1247                let feature_indices = bytes.get(offset..offset + feature_index_count as usize * 2)
1248                    .ok_or(ErrorKind::UnexpectedEof)?
1249                    .chunks_exact(2)
1250                    .map(|ch| {
1251                        Ok(get_u16(ch, 0)?)
1252                    }).collect::<Result<Vec<_>, Error>>()?;
1253                
1254                Some(LangSys::new(
1255                    _lookup_order_offset,
1256                    required_feature_index,
1257                    feature_index_count,
1258                    feature_indices
1259                ))
1260            }
1261            else {
1262                None
1263            };
1264            let lang_sys_count = get_u16(bytes, offset)?;
1265            offset += 2;
1266            let lang_sys_records: Vec<LangSysRecord> = bytes.get(offset..offset + lang_sys_count as usize * 6)
1267                .ok_or(ErrorKind::UnexpectedEof)?
1268                .chunks_exact(6)
1269                .map(|ch| {
1270                    let lang_sys_tag: [u8; 4] = ch.get(0..4)
1271                        .ok_or(ErrorKind::UnexpectedEof)?
1272                        .try_into()
1273                        .unwrap();
1274                    let lang_sys_offset = get_u16(ch, 4)?;
1275                    
1276                    Ok(LangSysRecord::new(lang_sys_tag, lang_sys_offset))
1277                }).collect::<Result<Vec<_>, Error>>()?;
1278            let lang_syses: Vec<LangSys> = lang_sys_records.iter()
1279                .map(|lsr| {
1280                    let mut offset = (script_list_offset + sr.script_offset() + lsr.lang_sys_offset()) as usize;
1281                    let _lookup_order_offset = get_u16(bytes, offset)?;
1282                    let required_feature_index = get_u16(bytes, offset + 2)?;
1283                    let feature_index_count = get_u16(bytes, offset + 4)?;
1284                    offset += 6;
1285                    let feature_indices = bytes.get(offset..offset + feature_index_count as usize * 2)
1286                        .ok_or(ErrorKind::UnexpectedEof)?
1287                        .chunks_exact(2)
1288                        .map(|ch| {
1289                            Ok(get_u16(ch, 0)?)
1290                        }).collect::<Result<Vec<_>, Error>>()?;
1291                    
1292                    Ok(LangSys::new(
1293                        _lookup_order_offset,
1294                        required_feature_index,
1295                        feature_index_count,
1296                        feature_indices
1297                    ))
1298                }).collect::<Result<Vec<_>, Error>>()?;
1299            
1300            Ok(Script::new(
1301                default_lang_sys_offset,
1302                default_lang_sys,
1303                lang_sys_count,
1304                lang_sys_records,
1305                lang_syses
1306            ))
1307        }).collect::<Result<Vec<_>, Error>>()?;
1308    
1309    Ok(ScriptList::new(
1310        script_count,
1311        script_records,
1312        scripts
1313    ))
1314}
1315
1316fn parse_feature_list(bytes: &[u8], feature_list_offset: u16) -> Result<FeatureList, Error> {
1317    let mut offset = feature_list_offset as usize;
1318    
1319    let feature_count = get_u16(bytes, offset)?;
1320    offset += 2;
1321    let feature_records: Vec<FeatureRecord> = bytes.get(offset..offset + feature_count as usize * 6)
1322        .ok_or(ErrorKind::UnexpectedEof)?
1323        .chunks_exact(6)
1324        .map(|ch| {
1325            let feature_tag: [u8; 4] = ch[0..4].try_into().unwrap();
1326            let feature_offset = get_u16(ch, 4)?;
1327            
1328            Ok(FeatureRecord::new(feature_tag, feature_offset))
1329        }).collect::<Result<Vec<_>, Error>>()?;
1330    let features: Vec<Feature> = feature_records.iter()
1331        .map(|fr| {
1332            let mut offset = (feature_list_offset + fr.feature_offset()) as usize;
1333            let test_offset = get_u16(bytes, offset)?;
1334            offset += 2;
1335            let feature_params_offset: Option<u16> = if test_offset != 0 {
1336                Some(test_offset)
1337            }
1338            else {
1339                None
1340            };
1341            let feature_params: Option<FeatureParams> = if feature_params_offset != None {
1342                let offset = (feature_list_offset + fr.feature_offset() + feature_params_offset.unwrap()) as usize;
1343                match &fr.feature_tag() {
1344                    b"size" => {
1345                        let design_size = get_u16(bytes, offset)?;
1346                        let subfamily_id = get_u16(bytes, offset + 2)?;
1347                        let subfamily_name_id = get_u16(bytes, offset + 4)?;
1348                        let range_start = get_u16(bytes, offset + 6)?;
1349                        let range_end = get_u16(bytes, offset + 8)?;
1350                        
1351                        Some(FeatureParams::Size {
1352                            design_size,
1353                            subfamily_id,
1354                            subfamily_name_id,
1355                            range_start,
1356                            range_end
1357                        })
1358                    },
1359                    tag if tag.starts_with(b"ss") => {
1360                        let version = get_u16(bytes, offset)?;
1361                        let ui_name_id = get_u16(bytes, offset + 2)?;
1362                        
1363                        Some(FeatureParams::StylisticSet {
1364                            version,
1365                            ui_name_id
1366                        })
1367                    },
1368                    tag if tag.starts_with(b"cv") => {
1369                        let format = get_u16(bytes, offset)?;
1370                        let feat_ui_label_name_id = get_u16(bytes, offset + 2)?;
1371                        let feat_tooltip_text_name_id = get_u16(bytes, offset + 4)?;
1372                        let sample_text_name_id = get_u16(bytes, offset + 6)?;
1373                        let num_named_parameters = get_u16(bytes, offset + 8)?;
1374                        let first_param_ui_label_name_id = get_u16(bytes, offset + 10)?;
1375                        let char_count = get_u16(bytes, offset + 12)?;
1376                        let character: [u8; 3] = bytes.get(offset + 14..offset + 17)
1377                            .ok_or(ErrorKind::UnexpectedEof)?
1378                            .try_into()
1379                            .unwrap();
1380                        
1381                        Some(FeatureParams::CharacterVariant {
1382                            format,
1383                            feat_ui_label_name_id,
1384                            feat_tooltip_text_name_id,
1385                            sample_text_name_id,
1386                            num_named_parameters,
1387                            first_param_ui_label_name_id,
1388                            char_count,
1389                            character
1390                        })
1391                    }
1392                    _ => return Err(Error::new(ErrorKind::InvalidData, format!("Feature tag is invalid: {:#?}", fr.feature_tag())))
1393                }
1394            }
1395            else {
1396                None
1397            };
1398            let lookup_index_count = get_u16(bytes, offset)?;
1399            offset += 2;
1400            let lookup_list_indices: Vec<u16> = bytes.get(offset..offset + lookup_index_count as usize * 2)
1401                .ok_or(ErrorKind::UnexpectedEof)?
1402                .chunks_exact(2)
1403                .map(|ch| {
1404                    u16::from_be_bytes(ch.try_into().unwrap())
1405                }).collect();
1406            
1407            Ok(Feature::new(
1408                feature_params_offset,
1409                feature_params,
1410                lookup_index_count,
1411                lookup_list_indices
1412            ))
1413        }).collect::<Result<Vec<_>, Error>>()?;
1414    
1415    Ok(FeatureList::new(feature_count, feature_records, features))
1416}
1417
1418fn parse_lookup_list<T: SubtableParser>(bytes: &[u8], lookup_list_offset: u16) -> Result<LookupList<T>, Error> {
1419    let mut offset = lookup_list_offset as usize;
1420    
1421    let lookup_count = get_u16(bytes, offset)?;
1422    offset += 2;
1423    let lookup_offsets: Vec<u16> = bytes.get(offset..offset + lookup_count as usize * 2)
1424        .ok_or(ErrorKind::UnexpectedEof)?
1425        .chunks_exact(2)
1426        .map(|ch| {
1427            u16::from_be_bytes(ch.try_into().unwrap())
1428        }).collect();
1429    let mut lookups: Vec<Lookup<T>> = Vec::with_capacity(lookup_offsets.len());
1430    for offset in lookup_offsets.iter() {
1431        let lookup_offset = lookup_list_offset as usize + *offset as usize;
1432        let mut offset = lookup_offset;
1433        let lookup_type = get_u16(bytes, offset)?;
1434        let lookup_flag = get_u16(bytes, offset + 2)?;
1435        let subtable_count = get_u16(bytes, offset + 4)?;
1436        offset += 6;
1437        let subtable_offsets: Vec<u16> = bytes.get(offset..offset + subtable_count as usize * 2)
1438            .ok_or(ErrorKind::UnexpectedEof)?
1439            .chunks_exact(2)
1440            .map(|ch| {
1441                u16::from_be_bytes(ch.try_into().unwrap())
1442            }).collect();
1443        offset += subtable_count as usize * 2;
1444        let subtables: Vec<T> = subtable_offsets.iter()
1445            .map(|offset| {
1446                Ok(T::parse(bytes, lookup_offset + *offset as usize, 0, lookup_type)?)
1447            }).collect::<Result<Vec<_>, Error>>()?;
1448        let mark_filtering_set = if lookup_flag & USE_MARK_FILTERING_SET != 0 {
1449            Some(get_u16(bytes, offset)?)
1450        }
1451        else {
1452            None
1453        };
1454        
1455        lookups.push(Lookup::new(
1456            lookup_type,
1457            lookup_flag,
1458            subtable_count,
1459            subtable_offsets,
1460            subtables,
1461            mark_filtering_set
1462        ));
1463    }
1464    
1465    Ok(LookupList::new(
1466        lookup_count,
1467        lookup_offsets,
1468        lookups
1469    ))
1470}
1471
1472trait SubtableParser: Sized {
1473    fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error>;
1474}
1475
1476impl SubtableParser for GposSubtable {
1477    fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error> {
1478        let mut offset = (subtable_offset as u32 + extension_offset) as usize;
1479        let format = get_u16(bytes, offset)?;
1480        offset += 2;
1481        match lookup_type {
1482            1 => {
1483                match format {
1484                    1 => {
1485                        let coverage_offset = get_u16(bytes, offset)?;
1486                        offset += 2;
1487                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1488                        let value_format = get_u16(bytes, offset)?;
1489                        offset += 2;
1490                        let value_record = parse_value_record(bytes, value_format, &mut offset, subtable_offset)?;
1491                        
1492                        Ok(GposSubtable::Type1(GposType1Format::Format1 {
1493                            coverage_offset,
1494                            coverage,
1495                            value_format,
1496                            value_record
1497                        }))
1498                    }
1499                    2 => {
1500                        let coverage_offset = get_u16(bytes, offset)?;
1501                        offset += 2;
1502                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1503                        let value_format = get_u16(bytes, offset)?;
1504                        let value_count = get_u16(bytes, offset + 2)?;
1505                        offset += 4;
1506                        let value_records: Vec<ValueRecord> = (0..value_count).map(|_| {
1507                            Ok(parse_value_record(bytes, value_format, &mut offset, subtable_offset)?)
1508                        }).collect::<Result<Vec<_>, Error>>()?;
1509                        
1510                        Ok(GposSubtable::Type1(GposType1Format::Format2 {
1511                            coverage_offset,
1512                            coverage,
1513                            value_format,
1514                            value_count,
1515                            value_records
1516                        }))
1517                    }
1518                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 1 is invalid: {}", format)))
1519                }
1520            }
1521            2 => {
1522                match format {
1523                    1 => {
1524                        let coverage_offset = get_u16(bytes, offset)?;
1525                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1526                        let value_format1 = get_u16(bytes, offset + 2)?;
1527                        let value_format2 = get_u16(bytes, offset + 4)?;
1528                        let pair_set_count = get_u16(bytes, offset + 6)?;
1529                        offset += 6;
1530                        let pair_set_offsets: Vec<u16> = bytes.get(offset..offset + pair_set_count as usize * 2)
1531                            .ok_or(ErrorKind::UnexpectedEof)?
1532                            .chunks_exact(2)
1533                            .map(|ch| {
1534                                u16::from_be_bytes(ch.try_into().unwrap())
1535                            }).collect();
1536                        let pair_sets: Vec<PairSet> = pair_set_offsets.iter()
1537                            .map(|offset| {
1538                                let mut offset = subtable_offset + *offset as usize;
1539                                let pair_value_count = get_u16(bytes, offset)?;
1540                                offset += 2;
1541                                let pair_value_records: Vec<PairValueRecord> = (0..pair_value_count).map(|_| {
1542                                    let second_glyph = get_u16(bytes, offset)?;
1543                                    offset += 2;
1544                                    let value_record1 = parse_value_record(bytes, value_format1, &mut offset, subtable_offset)?;
1545                                    let value_record2 = parse_value_record(bytes, value_format2, &mut offset, subtable_offset)?;
1546                                    
1547                                    Ok(PairValueRecord::new(
1548                                        second_glyph,
1549                                        value_record1,
1550                                        value_record2
1551                                    ))
1552                                }).collect::<Result<Vec<_>, Error>>()?;
1553                                
1554                                Ok(PairSet::new(
1555                                    pair_value_count,
1556                                    pair_value_records
1557                                ))
1558                            }).collect::<Result<Vec<_>, Error>>()?;
1559                        
1560                        Ok(GposSubtable::Type2(GposType2Format::Format1 {
1561                            coverage_offset,
1562                            coverage,
1563                            value_format1,
1564                            value_format2,
1565                            pair_set_count,
1566                            pair_set_offsets,
1567                            pair_sets
1568                        }))
1569                    }
1570                    2 => {
1571                        let coverage_offset = get_u16(bytes, offset)?;
1572                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1573                        let value_format1 = get_u16(bytes, offset + 2)?;
1574                        let value_format2 = get_u16(bytes, offset + 4)?;
1575                        let class_def1_offset = get_u16(bytes, offset + 6)?;
1576                        let class_def1 = parse_class_def(bytes, subtable_offset, class_def1_offset)?;
1577                        let class_def2_offset = get_u16(bytes, offset + 8)?;
1578                        let class_def2 = parse_class_def(bytes, subtable_offset, class_def2_offset)?;
1579                        let class1_count = get_u16(bytes, offset + 10)?;
1580                        let class2_count = get_u16(bytes, offset + 12)?;
1581                        offset += 12;
1582                        let class1_records: Vec<Class1Record> = (0..class1_count).map(|_| {
1583                            Ok(parse_class1_record(bytes, subtable_offset, value_format1, value_format2, class2_count, &mut offset)?)
1584                        }).collect::<Result<Vec<_>, Error>>()?;
1585                        
1586                        Ok(GposSubtable::Type2(GposType2Format::Format2 {
1587                            coverage_offset,
1588                            coverage,
1589                            value_format1,
1590                            value_format2,
1591                            class_def1_offset,
1592                            class_def1,
1593                            class_def2_offset,
1594                            class_def2,
1595                            class1_count,
1596                            class2_count,
1597                            class1_records
1598                        }))
1599                    }
1600                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 2 is invalid: {}", format)))
1601                }
1602            }
1603            3 => {
1604                match format {
1605                    1 => {
1606                        let coverage_offset = get_u16(bytes, offset)?;
1607                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1608                        let entry_exit_count = get_u16(bytes, offset + 2)?;
1609                        offset += 4;
1610                        let entry_exit_records: Vec<EntryExitRecord> = (0..entry_exit_count).map(|_| {
1611                            Ok(parse_entry_exit_record(bytes, subtable_offset, &mut offset)?)
1612                        }).collect::<Result<Vec<_>, Error>>()?;
1613                        
1614                        Ok(GposSubtable::Type3(GposType3Format::Format1 {
1615                            coverage_offset,
1616                            coverage,
1617                            entry_exit_count,
1618                            entry_exit_records
1619                        }))
1620                    }
1621                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 3 is invalid: {}", format)))
1622                }
1623            }
1624            4 => {
1625                match format {
1626                    1 => {
1627                        let mark_coverage_offset = get_u16(bytes, offset)?;
1628                        let mark_coverage = parse_coverage(bytes, subtable_offset, mark_coverage_offset)?;
1629                        let base_coverage_offset = get_u16(bytes, offset + 2)?;
1630                        let base_coverage = parse_coverage(bytes, subtable_offset, base_coverage_offset)?;
1631                        let mark_class_count = get_u16(bytes, offset + 4)?;
1632                        let mark_array_offset = get_u16(bytes, offset + 6)?;
1633                        let mark_array = parse_mark_array(bytes, subtable_offset, mark_array_offset)?;
1634                        let base_array_offset = get_u16(bytes, offset + 8)?;
1635                        let base_array = parse_base_array(bytes, subtable_offset, base_array_offset)?;
1636                        
1637                        Ok(GposSubtable::Type4(GposType4Format::Format1 {
1638                            mark_coverage_offset,
1639                            mark_coverage,
1640                            base_coverage_offset,
1641                            base_coverage,
1642                            mark_class_count,
1643                            mark_array_offset,
1644                            mark_array,
1645                            base_array_offset,
1646                            base_array
1647                        }))
1648                    }
1649                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 4 is invalid: {}", format)))
1650                }
1651            }
1652            5 => {
1653                match format {
1654                    1 => {
1655                        let mark_coverage_offset = get_u16(bytes, offset)?;
1656                        let mark_coverage = parse_coverage(bytes, subtable_offset, mark_coverage_offset)?;
1657                        let ligature_coverage_offset = get_u16(bytes, offset + 2)?;
1658                        let ligature_coverage = parse_coverage(bytes, subtable_offset, ligature_coverage_offset)?;
1659                        let mark_class_count = get_u16(bytes, offset + 4)?;
1660                        let mark_array_offset = get_u16(bytes, offset + 6)?;
1661                        let mark_array = parse_mark_array(bytes, subtable_offset, mark_array_offset)?;
1662                        let ligature_array_offset = get_u16(bytes, offset + 8)?;
1663                        let ligature_array = parse_ligature_array(bytes, subtable_offset, ligature_array_offset, mark_class_count)?;
1664                        
1665                        Ok(GposSubtable::Type5(GposType5Format::Format1 {
1666                            mark_coverage_offset,
1667                            mark_coverage,
1668                            ligature_coverage_offset,
1669                            ligature_coverage,
1670                            mark_class_count,
1671                            mark_array_offset,
1672                            mark_array,
1673                            ligature_array_offset,
1674                            ligature_array
1675                        }))
1676                    }
1677                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 5 is invalid: {}", format)))
1678                }
1679            }
1680            6 => {
1681                match format {
1682                    1 => {
1683                        let mark1_coverage_offset = get_u16(bytes, offset)?;
1684                        let mark1_coverage = parse_coverage(bytes, subtable_offset, mark1_coverage_offset)?;
1685                        let mark2_coverage_offset = get_u16(bytes, offset + 2)?;
1686                        let mark2_coverage = parse_coverage(bytes, subtable_offset, mark2_coverage_offset)?;
1687                        let mark_class_count = get_u16(bytes, offset + 4)?;
1688                        let mark1_array_offset = get_u16(bytes, offset + 6)?;
1689                        let mark1_array = parse_mark_array(bytes, subtable_offset, mark1_array_offset)?;
1690                        let mark2_array_offset = get_u16(bytes, offset + 8)?;
1691                        let mark2_array = parse_mark2_array(bytes, subtable_offset, mark2_array_offset, mark_class_count)?;
1692                        
1693                        Ok(GposSubtable::Type6(GposType6Format::Format1 {
1694                            mark1_coverage_offset,
1695                            mark1_coverage,
1696                            mark2_coverage_offset,
1697                            mark2_coverage,
1698                            mark_class_count,
1699                            mark1_array_offset,
1700                            mark1_array,
1701                            mark2_array_offset,
1702                            mark2_array
1703                        }))
1704                    }
1705                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 6 is invalid: {}", format)))
1706                }
1707            }
1708            7 => {
1709                match format {
1710                    1 => {
1711                        let coverage_offset = get_u16(bytes, offset)?;
1712                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1713                        let sub_rule_set_count = get_u16(bytes, offset + 2)?;
1714                        offset += 2;
1715                        let sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_set_count as usize * 2)
1716                            .ok_or(ErrorKind::UnexpectedEof)?
1717                            .chunks_exact(2)
1718                            .map(|ch| {
1719                                u16::from_be_bytes(ch.try_into().unwrap())
1720                            }).collect();
1721                        let sub_rule_sets: Vec<GposSubRuleSet> = sub_rule_set_offsets.iter()
1722                            .map(|offset| {
1723                                Ok(parse_gpos_sub_rule_set(bytes, subtable_offset, *offset)?)
1724                            }).collect::<Result<Vec<_>, Error>>()?;
1725                        
1726                        Ok(GposSubtable::Type7(GposType7Format::Format1 {
1727                            coverage_offset,
1728                            coverage,
1729                            sub_rule_set_count,
1730                            sub_rule_set_offsets,
1731                            sub_rule_sets
1732                        }))
1733                    }
1734                    2 => {
1735                        let coverage_offset = get_u16(bytes, offset)?;
1736                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1737                        let class_def_offset = get_u16(bytes, offset + 2)?;
1738                        let class_def = parse_class_def(bytes, subtable_offset, class_def_offset)?;
1739                        let sub_class_set_count = get_u16(bytes, offset + 4)?;
1740                        offset += 6;
1741                        let sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_set_count as usize * 2)
1742                            .ok_or(ErrorKind::UnexpectedEof)?
1743                            .chunks_exact(2)
1744                            .map(|ch| {
1745                                u16::from_be_bytes(ch.try_into().unwrap())
1746                            }).collect();
1747                        let sub_class_sets: Vec<GposSubClassSet> = sub_class_set_offsets.iter()
1748                            .map(|offset| {
1749                                Ok(parse_gpos_sub_class_set(bytes, subtable_offset, *offset)?)
1750                            }).collect::<Result<Vec<_>, Error>>()?;
1751                        
1752                        Ok(GposSubtable::Type7(GposType7Format::Format2 {
1753                            coverage_offset,
1754                            coverage,
1755                            class_def_offset,
1756                            class_def,
1757                            sub_class_set_count,
1758                            sub_class_set_offsets,
1759                            sub_class_sets
1760                        }))
1761                    }
1762                    3 => {
1763                        let glyph_count = get_u16(bytes, offset)?;
1764                        let sub_count = get_u16(bytes, offset + 2)?;
1765                        offset += 4;
1766                        let coverage_offsets: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
1767                            .ok_or(ErrorKind::UnexpectedEof)?
1768                            .chunks_exact(2)
1769                            .map(|ch| {
1770                                u16::from_be_bytes(ch.try_into().unwrap())
1771                            }).collect();
1772                        offset += glyph_count as usize * 2;
1773                        let coverages: Vec<Coverage> = coverage_offsets.iter()
1774                            .map(|offset| {
1775                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1776                            }).collect::<Result<Vec<_>, Error>>()?;
1777                        let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
1778                            Ok(parse_pos_lookup_record(bytes, &mut offset)?)
1779                        }).collect::<Result<Vec<_>, Error>>()?;
1780                        
1781                        Ok(GposSubtable::Type7(GposType7Format::Format3 {
1782                            glyph_count,
1783                            sub_count,
1784                            coverage_offsets,
1785                            coverages,
1786                            pos_lookup_records
1787                        }))
1788                    }
1789                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 7 is invalid: {}", format)))
1790                }
1791            }
1792            8 => {
1793                match format {
1794                    1 => {
1795                        let coverage_offset = get_u16(bytes, offset)?;
1796                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1797                        let chain_sub_rule_set_count = get_u16(bytes, offset + 2)?;
1798                        offset += 4;
1799                        let chain_sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_set_count as usize * 2)
1800                            .ok_or(ErrorKind::UnexpectedEof)?
1801                            .chunks_exact(2)
1802                            .map(|ch| {
1803                                u16::from_be_bytes(ch.try_into().unwrap())
1804                            }).collect();
1805                        let chain_sub_rule_sets: Vec<GposChainSubRuleSet> = chain_sub_rule_set_offsets.iter()
1806                            .map(|offset| {
1807                                Ok(parse_gpos_chain_sub_rule_set(bytes, subtable_offset, *offset)?)
1808                            }).collect::<Result<Vec<_>, Error>>()?;
1809                        
1810                        Ok(GposSubtable::Type8(GposType8Format::Format1 {
1811                            coverage_offset,
1812                            coverage,
1813                            chain_sub_rule_set_count,
1814                            chain_sub_rule_set_offsets,
1815                            chain_sub_rule_sets
1816                        }))
1817                    }
1818                    2 => {
1819                        let coverage_offset = get_u16(bytes, offset)?;
1820                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1821                        let backtrack_class_def_offset = get_u16(bytes, offset + 2)?;
1822                        let backtrack_class_def = parse_class_def(bytes, subtable_offset, backtrack_class_def_offset)?;
1823                        let input_class_def_offset = get_u16(bytes, offset + 4)?;
1824                        let input_class_def = parse_class_def(bytes, subtable_offset, input_class_def_offset)?;
1825                        let lookahead_class_def_offset = get_u16(bytes, offset + 6)?;
1826                        let lookahead_class_def = parse_class_def(bytes, subtable_offset, lookahead_class_def_offset)?;
1827                        let chain_sub_class_set_count = get_u16(bytes, offset + 8)?;
1828                        offset += 8;
1829                        let chain_sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_set_count as usize * 2)
1830                            .ok_or(ErrorKind::UnexpectedEof)?
1831                            .chunks_exact(2)
1832                            .map(|ch| {
1833                                u16::from_be_bytes(ch.try_into().unwrap())
1834                            }).collect();
1835                        let chain_sub_class_sets: Vec<GposChainSubClassSet> = chain_sub_class_set_offsets.iter()
1836                            .map(|offset| {
1837                                Ok(parse_gpos_chain_sub_class_set(bytes, subtable_offset, *offset)?)
1838                            }).collect::<Result<Vec<_>, Error>>()?;
1839                        
1840                        Ok(GposSubtable::Type8(GposType8Format::Format2 {
1841                            coverage_offset,
1842                            coverage,
1843                            backtrack_class_def_offset,
1844                            backtrack_class_def,
1845                            input_class_def_offset,
1846                            input_class_def,
1847                            lookahead_class_def_offset,
1848                            lookahead_class_def,
1849                            chain_sub_class_set_count,
1850                            chain_sub_class_set_offsets,
1851                            chain_sub_class_sets
1852                        }))
1853                    }
1854                    3 => {
1855                        let backtrack_glyph_count = get_u16(bytes, offset)?;
1856                        offset += 2;
1857                        let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
1858                            .ok_or(ErrorKind::UnexpectedEof)?
1859                            .chunks_exact(2)
1860                            .map(|ch| {
1861                                u16::from_be_bytes(ch.try_into().unwrap())
1862                            }).collect();
1863                        offset += backtrack_glyph_count as usize * 2;
1864                        let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
1865                            .map(|offset| {
1866                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1867                            }).collect::<Result<Vec<_>, Error>>()?;
1868                        let input_glyph_count = get_u16(bytes, offset)?;
1869                        offset += 2;
1870                        let input_coverage_offsets: Vec<u16> = bytes.get(offset..offset + input_glyph_count as usize * 2)
1871                            .ok_or(ErrorKind::UnexpectedEof)?
1872                            .chunks_exact(2)
1873                            .map(|ch| {
1874                                u16::from_be_bytes(ch.try_into().unwrap())
1875                            }).collect();
1876                        offset += input_glyph_count as usize * 2;
1877                        let input_coverages: Vec<Coverage> = input_coverage_offsets.iter()
1878                            .map(|offset| {
1879                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1880                            }).collect::<Result<Vec<_>, Error>>()?;
1881                        let lookahead_glyph_count = get_u16(bytes, offset)?;
1882                        offset += 2;
1883                        let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
1884                            .ok_or(ErrorKind::UnexpectedEof)?
1885                            .chunks_exact(2)
1886                            .map(|ch| {
1887                                u16::from_be_bytes(ch.try_into().unwrap())
1888                            }).collect();
1889                        offset += lookahead_glyph_count as usize * 2;
1890                        let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
1891                            .map(|offset| {
1892                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1893                            }).collect::<Result<Vec<_>, Error>>()?;
1894                        let sub_count = get_u16(bytes, offset)?;
1895                        offset += 2;
1896                        let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
1897                            Ok(parse_pos_lookup_record(bytes, &mut offset)?)
1898                        }).collect::<Result<Vec<_>, Error>>()?;
1899                        
1900                        Ok(GposSubtable::Type8(GposType8Format::Format3 {
1901                            backtrack_glyph_count,
1902                            backtrack_coverage_offsets,
1903                            backtrack_coverages,
1904                            input_glyph_count,
1905                            input_coverage_offsets,
1906                            input_coverages,
1907                            lookahead_glyph_count,
1908                            lookahead_coverage_offsets,
1909                            lookahead_coverages,
1910                            sub_count,
1911                            pos_lookup_records
1912                        }))
1913                    }
1914                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 8 is invalid: {}", format)))
1915                }
1916            }
1917            9 => {
1918                match format {
1919                    1 => {
1920                        let extension_lookup_type = get_u16(bytes, offset)?;
1921                        let extension_offset = get_u32(bytes, offset + 2)?;
1922                        let extension = Box::new(GposSubtable::parse(bytes, subtable_offset, extension_offset, extension_lookup_type)?);
1923                        
1924                        Ok(GposSubtable::Type9(GposType9Format::Format1 {
1925                            extension_lookup_type,
1926                            extension_offset,
1927                            extension
1928                        }))
1929                    }
1930                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 9 is invalid: {}", format)))
1931                }
1932            }
1933            _ => Err(Error::new(ErrorKind::InvalidData, format!("Lookup Type is invalid: {}", lookup_type)))
1934        }
1935    }
1936}
1937
1938impl SubtableParser for GsubSubtable {
1939    fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error> {
1940        let mut offset = (subtable_offset as u32 + extension_offset) as usize;
1941        let format = get_u16(bytes, offset)?;
1942        offset += 2;
1943        match lookup_type {
1944            1 => {
1945                match format {
1946                    1 => {
1947                        let coverage_offset = get_u16(bytes, offset)?;
1948                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1949                        let delta_glyph_id = get_i16(bytes, offset + 2)?;
1950                        
1951                        Ok(GsubSubtable::Type1(GsubType1Format::Format1 {
1952                            coverage_offset,
1953                            coverage,
1954                            delta_glyph_id
1955                        }))
1956                    }
1957                    2 => {
1958                        let coverage_offset = get_u16(bytes, offset)?;
1959                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1960                        let glyph_count = get_u16(bytes, offset + 2)?;
1961                        offset += 4;
1962                        let substitute_glyph_ids = bytes.get(offset..offset + glyph_count as usize * 2)
1963                            .ok_or(ErrorKind::UnexpectedEof)?
1964                            .chunks_exact(2)
1965                            .map(|ch| {
1966                                u16::from_be_bytes(ch.try_into().unwrap())
1967                            }).collect();
1968                        
1969                        Ok(GsubSubtable::Type1(GsubType1Format::Format2 {
1970                            coverage_offset,
1971                            coverage,
1972                            glyph_count,
1973                            substitute_glyph_ids
1974                        }))
1975                    }
1976                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 1 is invalid: {}", format)))
1977                }
1978            }
1979            2 => {
1980                match format {
1981                    1 => {
1982                        let coverage_offset = get_u16(bytes, offset)?;
1983                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1984                        let sequence_count = get_u16(bytes, offset + 2)?;
1985                        offset += 4;
1986                        let sequence_offsets: Vec<u16> = bytes.get(offset..offset + sequence_count as usize * 2)
1987                            .ok_or(ErrorKind::UnexpectedEof)?
1988                            .chunks_exact(2)
1989                            .map(|ch| {
1990                                u16::from_be_bytes(ch.try_into().unwrap())
1991                            }).collect();
1992                        let sequences: Vec<Sequence> = sequence_offsets.iter()
1993                            .map(|offset| {
1994                                Ok(parse_sequence(bytes, subtable_offset, *offset)?)
1995                            }).collect::<Result<Vec<_>, Error>>()?;
1996                        
1997                        Ok(GsubSubtable::Type2(GsubType2Format::Format1 {
1998                            coverage_offset,
1999                            coverage,
2000                            sequence_count,
2001                            sequence_offsets,
2002                            sequences
2003                        }))
2004                    }
2005                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 2 is invalid: {}", format)))
2006                }
2007            }
2008            3 => {
2009                match format {
2010                    1 => {
2011                        let coverage_offset = get_u16(bytes, offset)?;
2012                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2013                        let alternate_set_count = get_u16(bytes, offset + 2)?;
2014                        offset += 4;
2015                        let alternate_set_offsets: Vec<u16> = bytes.get(offset..offset + alternate_set_count as usize * 2)
2016                            .ok_or(ErrorKind::UnexpectedEof)?
2017                            .chunks_exact(2)
2018                            .map(|ch| {
2019                                u16::from_be_bytes(ch.try_into().unwrap())
2020                            }).collect();
2021                        let alternate_sets: Vec<AlternateSet> = alternate_set_offsets.iter()
2022                            .map(|offset| {
2023                                Ok(parse_alternate_set(bytes, subtable_offset, *offset)?)
2024                            }).collect::<Result<Vec<_>, Error>>()?;
2025                        
2026                        Ok(GsubSubtable::Type3(GsubType3Format::Format1 {
2027                            coverage_offset,
2028                            coverage,
2029                            alternate_set_count,
2030                            alternate_set_offsets,
2031                            alternate_sets
2032                        }))
2033                    }
2034                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 3 is invalid: {}", format)))
2035                }
2036            }
2037            4 => {
2038                match format {
2039                    1 => {
2040                        let coverage_offset = get_u16(bytes, offset)?;
2041                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2042                        let ligature_set_count = get_u16(bytes, offset + 2)?;
2043                        offset += 4;
2044                        let ligature_set_offsets: Vec<u16> = bytes.get(offset..offset + ligature_set_count as usize)
2045                            .ok_or(ErrorKind::UnexpectedEof)?
2046                            .chunks_exact(2)
2047                            .map(|ch| {
2048                                u16::from_be_bytes(ch.try_into().unwrap())
2049                            }).collect();
2050                        let ligature_sets: Vec<LigatureSet> = ligature_set_offsets.iter()
2051                            .map(|offset| {
2052                                Ok(parse_ligature_set(bytes, subtable_offset, *offset)?)
2053                            }).collect::<Result<Vec<_>, Error>>()?;
2054                        
2055                        Ok(GsubSubtable::Type4(GsubType4Format::Format1 {
2056                            coverage_offset,
2057                            coverage,
2058                            ligature_set_count,
2059                            ligature_set_offsets,
2060                            ligature_sets
2061                        }))
2062                    }
2063                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 4 is invalid: {}", format)))
2064                }
2065            }
2066            5 => {
2067                match format {
2068                    1 => {
2069                        let coverage_offset = get_u16(bytes, offset)?;
2070                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2071                        let sub_rule_set_count = get_u16(bytes, offset + 2)?;
2072                        offset += 4;
2073                        let sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_set_count as usize * 2)
2074                            .ok_or(ErrorKind::UnexpectedEof)?
2075                            .chunks_exact(2)
2076                            .map(|ch| {
2077                                u16::from_be_bytes(ch.try_into().unwrap())
2078                            }).collect();
2079                        let sub_rule_sets: Vec<GsubSubRuleSet> = sub_rule_set_offsets.iter()
2080                            .map(|offset| {
2081                                Ok(parse_gsub_sub_rule_set(bytes, subtable_offset, *offset)?)
2082                            }).collect::<Result<Vec<_>, Error>>()?;
2083                        
2084                        Ok(GsubSubtable::Type5(GsubType5Format::Format1 {
2085                            coverage_offset,
2086                            coverage,
2087                            sub_rule_set_count,
2088                            sub_rule_set_offsets,
2089                            sub_rule_sets
2090                        }))
2091                    }
2092                    2 => {
2093                        let coverage_offset = get_u16(bytes, offset)?;
2094                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2095                        let class_def_offset = get_u16(bytes, offset + 2)?;
2096                        let class_def = parse_class_def(bytes, subtable_offset, class_def_offset)?;
2097                        let sub_class_set_count = get_u16(bytes, offset + 4)?;
2098                        offset += 6;
2099                        let sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_set_count as usize * 2)
2100                            .ok_or(ErrorKind::UnexpectedEof)?
2101                            .chunks_exact(2)
2102                            .map(|ch| {
2103                                u16::from_be_bytes(ch.try_into().unwrap())
2104                            }).collect();
2105                        let sub_class_sets: Vec<GsubSubClassSet> = sub_class_set_offsets.iter()
2106                            .map(|offset| {
2107                                Ok(parse_gsub_sub_class_set(bytes, subtable_offset, *offset)?)
2108                            }).collect::<Result<Vec<_>, Error>>()?;
2109                        
2110                        Ok(GsubSubtable::Type5(GsubType5Format::Format2 {
2111                            coverage_offset,
2112                            coverage,
2113                            class_def_offset,
2114                            class_def,
2115                            sub_class_set_count,
2116                            sub_class_set_offsets,
2117                            sub_class_sets
2118                        }))
2119                    }
2120                    3 => {
2121                        let glyph_count = get_u16(bytes, offset)?;
2122                        let sub_count = get_u16(bytes, offset + 2)?;
2123                        offset += 4;
2124                        let coverage_offsets: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2125                            .ok_or(ErrorKind::UnexpectedEof)?
2126                            .chunks_exact(2)
2127                            .map(|ch| {
2128                                u16::from_be_bytes(ch.try_into().unwrap())
2129                            }).collect();
2130                        offset += glyph_count as usize * 2;
2131                        let coverages: Vec<Coverage> = coverage_offsets.iter()
2132                            .map(|offset| {
2133                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2134                            }).collect::<Result<Vec<_>, Error>>()?;
2135                        let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
2136                            Ok(parse_subst_lookup_record(bytes, &mut offset)?)
2137                        }).collect::<Result<Vec<_>, Error>>()?;
2138                        
2139                        Ok(GsubSubtable::Type5(GsubType5Format::Format3 {
2140                            glyph_count,
2141                            sub_count,
2142                            coverage_offsets,
2143                            coverages,
2144                            subst_lookup_records
2145                        }))
2146                    }
2147                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 5 is invalid: {}", format)))
2148                }
2149            }
2150            6 => {
2151                match format {
2152                    1 => {
2153                        let coverage_offset = get_u16(bytes, offset)?;
2154                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2155                        let chain_sub_rule_set_count = get_u16(bytes, offset + 2)?;
2156                        offset += 4;
2157                        let chain_sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_set_count as usize * 2)
2158                            .ok_or(ErrorKind::UnexpectedEof)?
2159                            .chunks_exact(2)
2160                            .map(|ch| {
2161                                u16::from_be_bytes(ch.try_into().unwrap())
2162                            }).collect();
2163                        let chain_sub_rule_sets: Vec<GsubChainSubRuleSet> = chain_sub_rule_set_offsets.iter()
2164                            .map(|offset| {
2165                                Ok(parse_gsub_chain_sub_rule_set(bytes, subtable_offset, *offset)?)
2166                            }).collect::<Result<Vec<_>, Error>>()?;
2167                        
2168                        Ok(GsubSubtable::Type6(GsubType6Format::Format1 {
2169                            coverage_offset,
2170                            coverage,
2171                            chain_sub_rule_set_count,
2172                            chain_sub_rule_set_offsets,
2173                            chain_sub_rule_sets
2174                        }))
2175                    }
2176                    2 => {
2177                        let coverage_offset = get_u16(bytes, offset)?;
2178                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2179                        let backtrack_class_def_offset = get_u16(bytes, offset + 2)?;
2180                        let backtrack_class_def = parse_class_def(bytes, subtable_offset, backtrack_class_def_offset)?;
2181                        let input_class_def_offset = get_u16(bytes, offset + 4)?;
2182                        let input_class_def = parse_class_def(bytes, subtable_offset, input_class_def_offset)?;
2183                        let lookahead_class_def_offset = get_u16(bytes, offset + 6)?;
2184                        let lookahead_class_def = parse_class_def(bytes, subtable_offset, lookahead_class_def_offset)?;
2185                        let chain_sub_class_set_count = get_u16(bytes, offset + 8)?;
2186                        offset += 8;
2187                        let chain_sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_set_count as usize * 2)
2188                            .ok_or(ErrorKind::UnexpectedEof)?
2189                            .chunks_exact(2)
2190                            .map(|ch| {
2191                                u16::from_be_bytes(ch.try_into().unwrap())
2192                            }).collect();
2193                        let chain_sub_class_sets: Vec<GsubChainSubClassSet> = chain_sub_class_set_offsets.iter()
2194                            .map(|offset| {
2195                                Ok(parse_gsub_chain_sub_class_set(bytes, subtable_offset, *offset)?)
2196                            }).collect::<Result<Vec<_>, Error>>()?;
2197                        
2198                        Ok(GsubSubtable::Type6(GsubType6Format::Format2 {
2199                            coverage_offset,
2200                            coverage,
2201                            backtrack_class_def_offset,
2202                            backtrack_class_def,
2203                            input_class_def_offset,
2204                            input_class_def,
2205                            lookahead_class_def_offset,
2206                            lookahead_class_def,
2207                            chain_sub_class_set_count,
2208                            chain_sub_class_set_offsets,
2209                            chain_sub_class_sets
2210                        }))
2211                    }
2212                    3 => {
2213                        let backtrack_glyph_count = get_u16(bytes, offset)?;
2214                        offset += 2;
2215                        let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
2216                            .ok_or(ErrorKind::UnexpectedEof)?
2217                            .chunks_exact(2)
2218                            .map(|ch| {
2219                                u16::from_be_bytes(ch.try_into().unwrap())
2220                            }).collect();
2221                        offset += backtrack_glyph_count as usize * 2;
2222                        let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
2223                            .map(|offset| {
2224                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2225                            }).collect::<Result<Vec<_>, Error>>()?;
2226                        let input_glyph_count = get_u16(bytes, offset)?;
2227                        offset += 2;
2228                        let input_coverage_offsets: Vec<u16> = bytes.get(offset..offset + input_glyph_count as usize * 2)
2229                            .ok_or(ErrorKind::UnexpectedEof)?
2230                            .chunks_exact(2)
2231                            .map(|ch| {
2232                                u16::from_be_bytes(ch.try_into().unwrap())
2233                            }).collect();
2234                        offset += input_glyph_count as usize * 2;
2235                        let input_coverages: Vec<Coverage> = input_coverage_offsets.iter()
2236                            .map(|offset| {
2237                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2238                            }).collect::<Result<Vec<_>, Error>>()?;
2239                        let lookahead_glyph_count = get_u16(bytes, offset)?;
2240                        offset += 2;
2241                        let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
2242                            .ok_or(ErrorKind::UnexpectedEof)?
2243                            .chunks_exact(2)
2244                            .map(|ch| {
2245                                u16::from_be_bytes(ch.try_into().unwrap())
2246                            }).collect();
2247                        offset += lookahead_glyph_count as usize * 2;
2248                        let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
2249                            .map(|offset| {
2250                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2251                            }).collect::<Result<Vec<_>, Error>>()?;
2252                        let sub_count = get_u16(bytes, offset)?;
2253                        offset += 2;
2254                        let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
2255                            Ok(parse_subst_lookup_record(bytes, &mut offset)?)
2256                        }).collect::<Result<Vec<_>, Error>>()?;
2257                        
2258                        Ok(GsubSubtable::Type6(GsubType6Format::Format3 {
2259                            backtrack_glyph_count,
2260                            backtrack_coverage_offsets,
2261                            backtrack_coverages,
2262                            input_glyph_count,
2263                            input_coverage_offsets,
2264                            input_coverages,
2265                            lookahead_glyph_count,
2266                            lookahead_coverage_offsets,
2267                            lookahead_coverages,
2268                            sub_count,
2269                            subst_lookup_records
2270                        }))
2271                    }
2272                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 6 is invalid: {}", format)))
2273                }
2274            }
2275            7 => {
2276                match format {
2277                    1 => {
2278                        let extension_lookup_type = get_u16(bytes, offset)?;
2279                        let extension_offset = get_u32(bytes, offset + 2)?;
2280                        let extension = Box::new(GsubSubtable::parse(bytes, subtable_offset, extension_offset, extension_lookup_type)?);
2281                                                
2282                        Ok(GsubSubtable::Type7(GsubType7Format::Format1 {
2283                            extension_lookup_type,
2284                            extension_offset,
2285                            extension
2286                        }))
2287                    }
2288                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 7 is invalid: {}", format)))
2289                }
2290            }
2291            8 => {
2292                match format {
2293                    1 => {
2294                        let coverage_offset = get_u16(bytes, offset)?;
2295                        let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2296                        let backtrack_glyph_count = get_u16(bytes, offset + 2)?;
2297                        offset += 4;
2298                        let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
2299                            .ok_or(ErrorKind::UnexpectedEof)?
2300                            .chunks_exact(2)
2301                            .map(|ch| {
2302                                u16::from_be_bytes(ch.try_into().unwrap())
2303                            }).collect();
2304                        offset += backtrack_glyph_count as usize * 2;
2305                        let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
2306                            .map(|offset| {
2307                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2308                            }).collect::<Result<Vec<_>, Error>>()?;
2309                        let lookahead_glyph_count = get_u16(bytes, offset)?;
2310                        offset += 2;
2311                        let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
2312                            .ok_or(ErrorKind::UnexpectedEof)?
2313                            .chunks_exact(2)
2314                            .map(|ch| {
2315                                u16::from_be_bytes(ch.try_into().unwrap())
2316                            }).collect();
2317                        offset += lookahead_glyph_count as usize * 2;
2318                        let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
2319                            .map(|offset| {
2320                                Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2321                            }).collect::<Result<Vec<_>, Error>>()?;
2322                        let glyph_count = get_u16(bytes, offset)?;
2323                        offset += 2;
2324                        let substitute_glyph_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2325                            .ok_or(ErrorKind::UnexpectedEof)?
2326                            .chunks_exact(2)
2327                            .map(|ch| {
2328                                u16::from_be_bytes(ch.try_into().unwrap())
2329                            }).collect();
2330                        
2331                        Ok(GsubSubtable::Type8(GsubType8Format::Format1 {
2332                            coverage_offset,
2333                            coverage,
2334                            backtrack_glyph_count,
2335                            backtrack_coverage_offsets,
2336                            backtrack_coverages,
2337                            lookahead_glyph_count,
2338                            lookahead_coverage_offsets,
2339                            lookahead_coverages,
2340                            glyph_count,
2341                            substitute_glyph_ids
2342                        }))
2343                    }
2344                    _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 8 is invalid: {}", format)))
2345                }
2346            }
2347            _ => Err(Error::new(ErrorKind::InvalidData, format!("Lookup Type is invalid: {}", lookup_type)))
2348        }
2349    }
2350}
2351
2352fn parse_feature_variations(bytes: &[u8], feature_variations_offset: u32, feature_list: FeatureList) -> Result<FeatureVariations, Error> {
2353    let mut offset = feature_variations_offset as usize;
2354    
2355    let major_version = get_u16(bytes, offset)?;
2356    let minor_version = get_u16(bytes, offset + 2)?;
2357    let feature_variation_record_count = get_u32(bytes, offset + 4)?;
2358    offset += 8;
2359    let mut feature_variation_records: Vec<FeatureVariationRecord> = Vec::with_capacity(feature_variation_record_count as usize);
2360    for _ in 0..feature_variation_record_count {
2361        let condition_set_offset = get_u32(bytes, offset)?;
2362        offset += 4;
2363        let condition_set: ConditionSet = {
2364            let mut offset = (feature_variations_offset + condition_set_offset) as usize;
2365            let condition_count = get_u16(bytes, offset)?;
2366            offset += 2;
2367            let condition_offsets: Vec<u32> = bytes.get(offset..offset + condition_count as usize * 4)
2368                .ok_or(ErrorKind::UnexpectedEof)?
2369                .chunks_exact(4)
2370                .map(|ch| {
2371                    u32::from_be_bytes(ch.try_into().unwrap())
2372                }).collect();
2373            let conditions: Vec<Condition> = condition_offsets.iter()
2374                .map(|off| {
2375                    let offset = *off as usize;
2376                    let format = get_u16(bytes, offset)?;
2377                    match format {
2378                        1 => {
2379                            let axis_index = get_u16(bytes, offset)?;
2380                            let filter_range_min_value = get_i16(bytes, offset + 2)?;
2381                            let filter_range_max_value = get_i16(bytes, offset + 4)?;
2382                            
2383                            Ok(Condition::Format1 {
2384                                axis_index,
2385                                filter_range_min_value,
2386                                filter_range_max_value
2387                            })
2388                        }
2389                        _ => return Err(Error::new(ErrorKind::InvalidData, format!("Condition format invalid: {}", format)))
2390                    }
2391                }).collect::<Result<Vec<_>, Error>>()?;
2392            
2393            ConditionSet::new(
2394                condition_count,
2395                condition_offsets,
2396                conditions
2397            )
2398        };
2399        let feature_table_substitution_offset = get_u32(bytes, offset)?;
2400        let feature_table_substitution: FeatureTableSubstitution = {
2401            let mut offset = (feature_variations_offset + feature_table_substitution_offset) as usize;
2402            let major_version = get_u16(bytes, offset)?;
2403            let minor_version = get_u16(bytes, offset + 2)?;
2404            let substitution_count = get_u16(bytes, offset + 4)?;
2405            offset += 4;
2406            let mut substitution_records: Vec<FeatureTableSubstitutionRecord> = Vec::with_capacity(substitution_count as usize);
2407            for _ in 0..substitution_count {
2408                let feature_index = get_u16(bytes, offset)?;
2409                let alternate_feature_table_offset = get_u32(bytes, offset + 2)?;
2410                offset += 6;
2411                let alternate_feature_table: Feature = {
2412                    let mut offset = (feature_variations_offset + feature_table_substitution_offset + alternate_feature_table_offset) as usize;
2413                    let test_offset = get_u16(bytes, offset)?;
2414                    offset += 2;
2415                    let feature_params_offset = if test_offset != 0 {
2416                        Some(test_offset)
2417                    }
2418                    else {
2419                        None
2420                    };
2421                    let feature_params = if feature_params_offset != None {
2422                        let feature_tag = feature_list.feature_records()
2423                            .get(feature_index as usize)
2424                            .ok_or(ErrorKind::NotFound)?
2425                            .feature_tag();
2426                        match &feature_tag {
2427                            b"size" => {
2428                                let design_size = get_u16(bytes, offset)?;
2429                                let subfamily_id = get_u16(bytes, offset + 2)?;
2430                                let subfamily_name_id = get_u16(bytes, offset + 4)?;
2431                                let range_start = get_u16(bytes, offset + 6)?;
2432                                let range_end = get_u16(bytes, offset + 8)?;
2433                                
2434                                Some(FeatureParams::Size {
2435                                    design_size,
2436                                    subfamily_id,
2437                                    subfamily_name_id,
2438                                    range_start,
2439                                    range_end
2440                                })
2441                            },
2442                            tag if tag.starts_with(b"ss") => {
2443                                let version = get_u16(bytes, offset)?;
2444                                let ui_name_id = get_u16(bytes, offset + 2)?;
2445                                
2446                                Some(FeatureParams::StylisticSet {
2447                                    version,
2448                                    ui_name_id
2449                                })
2450                            },
2451                            tag if tag.starts_with(b"cv") => {
2452                                let format = get_u16(bytes, offset)?;
2453                                let feat_ui_label_name_id = get_u16(bytes, offset + 2)?;
2454                                let feat_tooltip_text_name_id = get_u16(bytes, offset + 4)?;
2455                                let sample_text_name_id = get_u16(bytes, offset + 6)?;
2456                                let num_named_parameters = get_u16(bytes, offset + 8)?;
2457                                let first_param_ui_label_name_id = get_u16(bytes, offset + 10)?;
2458                                let char_count = get_u16(bytes, offset + 12)?;
2459                                let character: [u8; 3] = bytes.get(offset + 14..offset + 17)
2460                                    .ok_or(ErrorKind::UnexpectedEof)?
2461                                    .try_into()
2462                                    .unwrap();
2463                                
2464                                Some(FeatureParams::CharacterVariant {
2465                                    format,
2466                                    feat_ui_label_name_id,
2467                                    feat_tooltip_text_name_id,
2468                                    sample_text_name_id,
2469                                    num_named_parameters,
2470                                    first_param_ui_label_name_id,
2471                                    char_count,
2472                                    character
2473                                })
2474                            }
2475                            _ => return Err(Error::new(ErrorKind::InvalidData, format!("Feature tag is invalid: {:#?}", feature_tag)))
2476                        }
2477                    }
2478                    else {
2479                        None
2480                    };
2481                    let lookup_index_count = get_u16(bytes, offset)?;
2482                    offset += 2;
2483                    let lookup_list_indices: Vec<u16> = bytes.get(offset..offset + lookup_index_count as usize  * 2)
2484                        .ok_or(ErrorKind::UnexpectedEof)?
2485                        .chunks_exact(2)
2486                        .map(|ch| {
2487                            u16::from_be_bytes(ch.try_into().unwrap())
2488                        }).collect();
2489                    
2490                    Feature::new(
2491                        feature_params_offset,
2492                        feature_params,
2493                        lookup_index_count,
2494                        lookup_list_indices
2495                    )
2496                };
2497                
2498                substitution_records.push(FeatureTableSubstitutionRecord::new(
2499                    feature_index,
2500                    alternate_feature_table_offset,
2501                    alternate_feature_table
2502                ))
2503            }
2504            
2505            FeatureTableSubstitution::new(
2506                major_version,
2507                minor_version,
2508                substitution_count,
2509                substitution_records
2510            )
2511        };
2512        
2513        feature_variation_records.push(FeatureVariationRecord::new(
2514            condition_set_offset,
2515            condition_set,
2516            feature_table_substitution_offset,
2517            feature_table_substitution
2518        ));
2519    }
2520    
2521    Ok(FeatureVariations::new(
2522        major_version,
2523        minor_version,
2524        feature_variation_record_count,
2525        feature_variation_records
2526    ))
2527}
2528
2529fn parse_coverage(bytes: &[u8], subtable_offset: usize, coverage_offset: u16) -> Result<Coverage, Error> {
2530    let mut offset = subtable_offset + coverage_offset as usize;
2531    let format = get_u16(bytes, offset)?;
2532    offset += 2;
2533    match format {
2534        1 => {
2535            let glyph_count = get_u16(bytes, offset)?;
2536            offset += 2;
2537            let glyph_array = bytes.get(offset..offset + glyph_count as usize * 2)
2538                .ok_or(ErrorKind::UnexpectedEof)?
2539                .chunks_exact(2)
2540                .map(|ch| {
2541                    u16::from_be_bytes(ch.try_into().unwrap())
2542                }).collect();
2543            
2544            Ok(Coverage::Format1 {
2545                glyph_count,
2546                glyph_array
2547            })
2548        }
2549        2 => {
2550            let range_count = get_u16(bytes, offset)?;
2551            offset += 2;
2552            let range_records: Vec<CoverageRangeRecord> = bytes.get(offset..offset + range_count as usize * 6)
2553                .ok_or(ErrorKind::UnexpectedEof)?
2554                .chunks_exact(6)
2555                .map(|ch| {
2556                    let start_glyph_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
2557                    let end_glyph_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
2558                    let start_coverage_index = u16::from_be_bytes(ch[4..6].try_into().unwrap());
2559                    
2560                    CoverageRangeRecord::new(
2561                        start_glyph_id,
2562                        end_glyph_id,
2563                        start_coverage_index
2564                    )
2565                }).collect();
2566            
2567            Ok(Coverage::Format2 {
2568                range_count,
2569                range_records
2570            })
2571        }
2572        _ => return Err(Error::new(ErrorKind::InvalidData, format!("Coverage format invalid: {}", format)))
2573    }
2574}
2575
2576fn parse_value_record(bytes: &[u8], value_format: u16, offset: &mut usize, subtable_offset: usize) -> Result<ValueRecord, Error> {
2577    let x_placement = if value_format & X_PLACEMENT != 0 {
2578        *offset += 2;
2579        Some(get_i16(bytes, *offset - 2)?)
2580    }
2581    else { None };
2582    let y_placement = if value_format & Y_PLACEMENT != 0 {
2583        *offset += 2;
2584        Some(get_i16(bytes, *offset - 2)?)
2585    }
2586    else { None };
2587    let x_advance = if value_format & X_ADVANCE != 0 {
2588        *offset += 2;
2589        Some(get_i16(bytes, *offset - 2)?)
2590    }
2591    else { None };
2592    let y_advance = if value_format & Y_ADVANCE != 0 {
2593        *offset += 2;
2594        Some(get_i16(bytes, *offset - 2)?)
2595    }
2596    else { None };
2597    let x_pla_device_offset = if value_format & X_PLACEMENT_DEVICE != 0 {
2598        *offset += 2;
2599        Some(get_u16(bytes, *offset - 2)?)
2600    }
2601    else { None };
2602    let x_pla_device = if x_pla_device_offset != None {
2603        Some(parse_device_or_variation_index(bytes, subtable_offset, x_pla_device_offset.unwrap())?)
2604    }
2605    else { None };
2606    let y_pla_device_offset = if value_format & Y_PLACEMENT_DEVICE != 0 {
2607        *offset += 2;
2608        Some(get_u16(bytes, *offset - 2)?)
2609    }
2610    else { None };
2611    let y_pla_device = if y_pla_device_offset != None {
2612        Some(parse_device_or_variation_index(bytes, subtable_offset, y_pla_device_offset.unwrap())?)
2613    }
2614    else { None };
2615    let x_adv_device_offset = if value_format & X_ADVANCE_DEVICE != 0 {
2616        *offset += 2;
2617        Some(get_u16(bytes, *offset - 2)?)
2618    }
2619    else { None };
2620    let x_adv_device = if x_adv_device_offset != None {
2621        Some(parse_device_or_variation_index(bytes, subtable_offset, x_adv_device_offset.unwrap())?)
2622    }
2623    else { None };
2624    let y_adv_device_offset = if value_format & Y_ADVANCE_DEVICE != 0 {
2625        *offset += 2;
2626        Some(get_u16(bytes, *offset - 2)?)
2627    }
2628    else { None };
2629    let y_adv_device = if y_adv_device_offset != None {
2630        Some(parse_device_or_variation_index(bytes, subtable_offset, y_adv_device_offset.unwrap())?)
2631    }
2632    else { None };
2633    
2634    Ok(ValueRecord::new(
2635        x_placement,
2636        y_placement,
2637        x_advance,
2638        y_advance,
2639        x_pla_device_offset,
2640        x_pla_device,
2641        y_pla_device_offset,
2642        y_pla_device,
2643        x_adv_device_offset,
2644        x_adv_device,
2645        y_adv_device_offset,
2646        y_adv_device
2647    ))
2648}
2649
2650fn parse_device_or_variation_index(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2651    let offset = subtable_offset + device_offset as usize;
2652    let delta_format = get_u16(bytes, offset + 4)?;
2653    if delta_format == 1 || delta_format == 2 || delta_format == 3 {
2654        Ok(parse_device(bytes, subtable_offset, device_offset)?)
2655    }
2656    else if delta_format == 0x8000 {
2657        Ok(parse_variation_index(bytes, subtable_offset, device_offset)?)
2658    }
2659    else {
2660        Err(Error::new(ErrorKind::InvalidData, "DeltaFormat value invalid: {}".to_string()))
2661    }
2662}
2663
2664fn parse_device(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2665    let offset = subtable_offset + device_offset as usize;
2666    let start_size = get_u16(bytes, offset)?;
2667    let end_size = get_u16(bytes, offset + 2)?;
2668    let delta_format = get_u16(bytes, offset + 4)?;
2669    let count = end_size - start_size + 1;
2670    let length = match delta_format {
2671        1 => (count * 2).div_ceil(16),
2672        2 => (count * 4).div_ceil(16),
2673        3 => (count * 8).div_ceil(16),
2674        _ => return Err(Error::new(ErrorKind::InvalidData, format!("DeltaFormat value invalid: {}", delta_format)))
2675    };
2676    let delta_values: Vec<u16> = bytes.get(offset..offset + length as usize * 2)
2677        .ok_or(ErrorKind::UnexpectedEof)?
2678        .chunks_exact(2)
2679        .map(|ch| {
2680            u16::from_be_bytes(ch.try_into().unwrap())
2681        }).collect();
2682    
2683    Ok(DeviceOrVariationIndex::Device(
2684        Device::new(
2685            start_size,
2686            end_size,
2687            delta_format,
2688            delta_values
2689        )
2690    ))
2691}
2692
2693fn parse_variation_index(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2694    let offset = subtable_offset + device_offset as usize;
2695    let delta_set_outer_index = get_u16(bytes, offset)?;
2696    let delta_set_inner_index = get_u16(bytes, offset + 2)?;
2697    let delta_format = get_u16(bytes, offset + 4)?;
2698    
2699    Ok(DeviceOrVariationIndex::VariationIndex(
2700        VariationIndex::new(
2701            delta_set_outer_index,
2702            delta_set_inner_index,
2703            delta_format
2704        )
2705    ))
2706}
2707
2708fn parse_class_def(bytes: &[u8], subtable_offset: usize, class_def_offset: u16) -> Result<ClassDef, Error> {
2709    let mut offset = subtable_offset + class_def_offset as usize;
2710    let format = get_u16(bytes, offset)?;
2711    offset += 2;
2712    match format {
2713        1 => {
2714            let start_glyph_id = get_u16(bytes, offset)?;
2715            let glyph_count = get_u16(bytes, offset + 2)?;
2716            offset += 4;
2717            let class_value_array: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2718                .ok_or(ErrorKind::UnexpectedEof)?
2719                .chunks_exact(2)
2720                .map(|ch| {
2721                    u16::from_be_bytes(ch.try_into().unwrap())
2722                }).collect();
2723            
2724            Ok(ClassDef::Format1 {
2725                start_glyph_id,
2726                glyph_count,
2727                class_value_array
2728            })
2729        }
2730        2 => {
2731            let class_range_count = get_u16(bytes, offset)?;
2732            offset += 2;
2733            let class_range_records: Vec<ClassRangeRecord> = bytes.get(offset..offset + class_range_count as usize * 6)
2734                .ok_or(ErrorKind::UnexpectedEof)?
2735                .chunks_exact(6)
2736                .map(|ch| {
2737                    let start_glyph_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
2738                    let end_glyph_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
2739                    let class = u16::from_be_bytes(ch[4..6].try_into().unwrap());
2740                    
2741                    ClassRangeRecord::new(
2742                        start_glyph_id,
2743                        end_glyph_id,
2744                        class
2745                    )
2746                }).collect();
2747            
2748            Ok(ClassDef::Format2 {
2749                class_range_count,
2750                class_range_records
2751            })
2752        }
2753        _ => return Err(Error::new(ErrorKind::InvalidData, format!("ClassDef format invalid: {}", format)))
2754    }
2755}
2756
2757fn parse_class1_record(
2758    bytes: &[u8],
2759    subtable_offset: usize,
2760    value_format1: u16,
2761    value_format2: u16,
2762    class2_count: u16,
2763    offset: &mut usize
2764) -> Result<Class1Record, Error> {
2765    let class2_records: Vec<Class2Record> = (0..class2_count).map(|_| {
2766        let value_record1 = parse_value_record(bytes, value_format1, offset, subtable_offset)?;
2767        let value_record2 = parse_value_record(bytes, value_format2, offset, subtable_offset)?;
2768        
2769        Ok(Class2Record::new(value_record1, value_record2))
2770    }).collect::<Result<Vec<_>, Error>>()?;
2771    
2772    Ok(Class1Record::new(class2_records))
2773}
2774
2775fn parse_entry_exit_record(bytes: &[u8], subtable_offset: usize, offset: &mut usize) -> Result<EntryExitRecord, Error> {
2776    let test_offset = get_u16(bytes, *offset)?;
2777    let entry_anchor_offset = if test_offset != 0 {
2778        Some(test_offset)
2779    }
2780    else { None };
2781    let entry_anchor = if entry_anchor_offset != None {
2782        Some(parse_anchor(bytes, subtable_offset, entry_anchor_offset.unwrap())?)
2783    }
2784    else { None };
2785    let test_offset = get_u16(bytes, *offset + 2)?;
2786    let exit_anchor_offset = if test_offset != 0 {
2787        Some(test_offset)
2788    }
2789    else { None };
2790    let exit_anchor = if exit_anchor_offset != None {
2791        Some(parse_anchor(bytes, subtable_offset, exit_anchor_offset.unwrap())?)
2792    }
2793    else { None };
2794    *offset += 4;
2795    
2796    Ok(EntryExitRecord::new(
2797        entry_anchor_offset,
2798        entry_anchor,
2799        exit_anchor_offset,
2800        exit_anchor
2801    ))
2802}
2803
2804fn parse_anchor(bytes: &[u8], subtable_offset: usize, anchor_offset: u16) -> Result<Anchor, Error> {
2805    let mut offset = subtable_offset + anchor_offset as usize;
2806    let format = get_u16(bytes, offset)?;
2807    offset += 2;
2808    match format {
2809        1 => {
2810            let x_coordinate = get_i16(bytes, offset)?;
2811            let y_coordinate = get_i16(bytes, offset + 2)?;
2812            
2813            Ok(Anchor::Format1 {
2814                x_coordinate,
2815                y_coordinate
2816            })
2817        }
2818        2 => {
2819            let x_coordinate = get_i16(bytes, offset)?;
2820            let y_coordinate = get_i16(bytes, offset + 2)?;
2821            let anchor_point = get_u16(bytes, offset + 4)?;
2822            
2823            Ok(Anchor::Format2 {
2824                x_coordinate,
2825                y_coordinate,
2826                anchor_point
2827            })
2828        }
2829        3 => {
2830            let x_coordinate = get_i16(bytes, offset)?;
2831            let y_coordinate = get_i16(bytes, offset + 2)?;
2832            let x_device_offset = get_u16(bytes, offset + 4)?;
2833            let x_device = parse_device_or_variation_index(bytes, subtable_offset, x_device_offset)?;
2834            let y_device_offset = get_u16(bytes, offset + 6)?;
2835            let y_device = parse_device_or_variation_index(bytes, subtable_offset, y_device_offset)?;
2836            
2837            Ok(Anchor::Format3 {
2838                x_coordinate,
2839                y_coordinate,
2840                x_device_offset,
2841                x_device,
2842                y_device_offset,
2843                y_device
2844            })
2845        }
2846        _ => Err(Error::new(ErrorKind::InvalidData, format!("Anchor invalid format: {}", format)))
2847    }
2848}
2849
2850fn parse_mark_array(bytes: &[u8], subtable_offset: usize, mark_array_offset: u16) -> Result<MarkArray, Error> {
2851    let mut offset = subtable_offset + mark_array_offset as usize;
2852    let mark_count = get_u16(bytes, offset)?;
2853    offset += 2;
2854    let mark_records: Vec<MarkRecord> =  (0..mark_count).map(|_| {
2855        let mark_class = get_u16(bytes, offset)?;
2856        let mark_anchor_offset = get_u16(bytes, offset + 2)?;
2857        offset += 4;
2858        let mark_anchor = parse_anchor(bytes, subtable_offset, mark_anchor_offset)?;
2859        
2860        Ok(MarkRecord::new(
2861            mark_class,
2862            mark_anchor_offset,
2863            mark_anchor
2864        ))
2865    }).collect::<Result<Vec<_>, Error>>()?;
2866    
2867    Ok(MarkArray::new(
2868        mark_count,
2869        mark_records
2870    ))
2871}
2872
2873fn parse_base_array(bytes: &[u8], subtable_offset: usize, base_array_offset: u16) -> Result<BaseArray, Error> {
2874    let mut offset = subtable_offset + base_array_offset as usize;
2875    let base_count = get_u16(bytes, offset)?;
2876    offset += 2;
2877    let base_records: Vec<BaseRecord> = (0..base_count).map(|_| {
2878        let base_anchor_offsets: Vec<u16> = bytes.get(offset..offset + base_count as usize * 2)
2879            .ok_or(ErrorKind::UnexpectedEof)?
2880            .chunks_exact(2)
2881            .map(|ch| {
2882                u16::from_be_bytes(ch.try_into().unwrap())
2883            }).collect();
2884        offset += base_count as usize * 2;
2885        let base_anchors: Vec<Anchor> = base_anchor_offsets.iter()
2886            .map(|offset| {
2887                Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2888            }).collect::<Result<Vec<_>, Error>>()?;
2889        
2890        Ok(BaseRecord::new(base_anchor_offsets, base_anchors))
2891    }).collect::<Result<Vec<_>, Error>>()?;
2892    
2893    Ok(BaseArray::new(
2894        base_count,
2895        base_records
2896    ))
2897}
2898
2899fn parse_ligature_array(bytes: &[u8], subtable_offset: usize, ligature_array_offset: u16, mark_class_count: u16) -> Result<LigatureArray, Error> {
2900    let mut offset = subtable_offset + ligature_array_offset as usize;
2901    let ligature_count = get_u16(bytes, offset)?;
2902    offset += 2;
2903    let ligature_attach_offsets: Vec<u16> = bytes.get(offset..offset + ligature_count as usize * 2)
2904        .ok_or(ErrorKind::UnexpectedEof)?
2905        .chunks_exact(2)
2906        .map(|ch| {
2907            u16::from_be_bytes(ch.try_into().unwrap())
2908        }).collect();
2909    let ligature_attaches: Vec<LigatureAttach> = ligature_attach_offsets.iter()
2910        .map(|offset| {
2911            Ok(parse_ligature_attach(bytes, subtable_offset, *offset, mark_class_count)?)
2912        }).collect::<Result<Vec<_>, Error>>()?;
2913    
2914    Ok(LigatureArray::new(
2915        ligature_count,
2916        ligature_attach_offsets,
2917        ligature_attaches
2918    ))
2919}
2920
2921fn parse_ligature_attach(
2922    bytes: &[u8],
2923    subtable_offset: usize,
2924    ligature_attach_offset: u16,
2925    mark_class_count: u16
2926) -> Result<LigatureAttach, Error> {
2927    let mut offset = subtable_offset + ligature_attach_offset as usize;
2928    let component_count = get_u16(bytes, offset)?;
2929    offset += 2;
2930    let component_records: Vec<ComponentRecord> = (0..component_count).map(|_| {
2931        Ok(parse_component_record(bytes, subtable_offset, offset, mark_class_count)?)
2932    }).collect::<Result<Vec<_>, Error>>()?;
2933    
2934    Ok(LigatureAttach::new(
2935        component_count,
2936        component_records
2937    ))
2938}
2939
2940fn parse_component_record(
2941    bytes: &[u8],
2942    subtable_offset: usize,
2943    offset: usize,
2944    mark_class_count: u16
2945) -> Result<ComponentRecord, Error> {
2946    let ligature_anchor_offsets: Vec<u16> = bytes.get(offset..offset + mark_class_count as usize * 2)
2947        .ok_or(ErrorKind::UnexpectedEof)?
2948        .chunks_exact(2)
2949        .map(|ch| {
2950            u16::from_be_bytes(ch.try_into().unwrap())
2951        }).collect();
2952    let ligature_anchors: Vec<Anchor> = ligature_anchor_offsets.iter()
2953        .map(|offset| {
2954            Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2955        }).collect::<Result<Vec<_>, Error>>()?;
2956    
2957    Ok(ComponentRecord::new(
2958        ligature_anchor_offsets,
2959        ligature_anchors
2960    ))
2961}
2962
2963fn parse_mark2_array(bytes: &[u8], subtable_offset: usize, mark2_array_offset: u16, mark_class_count: u16) -> Result<Mark2Array, Error> {
2964    let mut offset = subtable_offset + mark2_array_offset as usize;
2965    let mark2_count = get_u16(bytes, offset)?;
2966    offset += 2;
2967    let mark2_records: Vec<Mark2Record> = (0..mark2_count).map(|_| {
2968        Ok(parse_mark2_record(bytes, subtable_offset, &mut offset, mark_class_count)?)
2969    }).collect::<Result<Vec<_>, Error>>()?;
2970    
2971    Ok(Mark2Array::new(
2972        mark2_count,
2973        mark2_records
2974    ))
2975}
2976
2977fn parse_mark2_record(bytes: &[u8], subtable_offset: usize, offset: &mut usize, mark_class_count: u16) -> Result<Mark2Record, Error> {
2978    let mark2_anchor_offsets: Vec<u16> = bytes.get(*offset..*offset + mark_class_count as usize * 2)
2979        .ok_or(ErrorKind::UnexpectedEof)?
2980        .chunks_exact(2)
2981        .map(|ch| {
2982            u16::from_be_bytes(ch.try_into().unwrap())
2983        }).collect();
2984    *offset += mark_class_count as usize * 2;
2985    let mark2_anchors: Vec<Anchor> = mark2_anchor_offsets.iter()
2986        .map(|offset| {
2987            Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2988        }).collect::<Result<Vec<_>, Error>>()?;
2989    
2990    Ok(Mark2Record::new(
2991        mark2_anchor_offsets,
2992        mark2_anchors
2993    ))
2994}
2995
2996fn parse_gpos_sub_rule_set(bytes: &[u8], subtable_offset: usize, sub_rule_set_offset: u16) -> Result<GposSubRuleSet, Error> {
2997    let mut offset = subtable_offset + sub_rule_set_offset as usize;
2998    let sub_rule_count = get_u16(bytes, offset)?;
2999    offset += 2;
3000    let sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_count as usize * 2)
3001        .ok_or(ErrorKind::UnexpectedEof)?
3002        .chunks_exact(2)
3003        .map(|ch| {
3004            u16::from_be_bytes(ch.try_into().unwrap())
3005        }).collect();
3006    let sub_rules: Vec<GposSubRule> = sub_rule_offsets.iter()
3007        .map(|offset| {
3008            Ok(parse_gpos_sub_rule(bytes, subtable_offset, *offset)?)
3009        }).collect::<Result<Vec<_>, Error>>()?;
3010    
3011    Ok(GposSubRuleSet::new(
3012        sub_rule_count,
3013        sub_rule_offsets,
3014        sub_rules
3015    ))
3016}
3017
3018fn parse_gpos_sub_rule(bytes: &[u8], subtable_offset: usize, sub_rule_offset: u16) -> Result<GposSubRule, Error> {
3019    let mut offset = subtable_offset + sub_rule_offset as usize;
3020    let glyph_count = get_u16(bytes, offset)?;
3021    let sub_count = get_u16(bytes, offset + 2)?;
3022    offset += 4;
3023    let input_glyph_ids: Vec<u16> = bytes.get(offset..offset + (glyph_count as usize - 1) * 2)
3024        .ok_or(ErrorKind::UnexpectedEof)?
3025        .chunks_exact(2)
3026        .map(|ch| {
3027            u16::from_be_bytes(ch.try_into().unwrap())
3028        }).collect();
3029    offset += glyph_count as usize * 2;
3030    let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3031        Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3032    }).collect::<Result<Vec<_>, Error>>()?;
3033    
3034    Ok(GposSubRule::new(
3035        glyph_count,
3036        sub_count,
3037        input_glyph_ids,
3038        pos_lookup_records
3039    ))
3040}
3041
3042fn parse_pos_lookup_record(bytes: &[u8], offset: &mut usize) -> Result<PosLookupRecord, Error> {
3043    let glyph_sequence_index = get_u16(bytes, *offset)?;
3044    let lookup_list_index = get_u16(bytes, *offset + 2)?;
3045    *offset += 4;
3046    
3047    Ok(PosLookupRecord::new(
3048        glyph_sequence_index,
3049        lookup_list_index
3050    ))
3051}
3052
3053fn parse_gpos_sub_class_set(bytes: &[u8], subtable_offset: usize, sub_class_set_offset: u16) -> Result<GposSubClassSet, Error> {
3054    let mut offset = subtable_offset + sub_class_set_offset as usize;
3055    let sub_class_rule_count = get_u16(bytes, offset)?;
3056    offset += 2;
3057    let sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_rule_count as usize * 2)
3058        .ok_or(ErrorKind::UnexpectedEof)?
3059        .chunks_exact(2)
3060        .map(|ch| {
3061            u16::from_be_bytes(ch.try_into().unwrap())
3062        }).collect();
3063    let sub_class_rules: Vec<GposSubClassRule> = sub_class_rule_offsets.iter()
3064        .map(|offset| {
3065            Ok(parse_gpos_sub_class_rule(bytes, subtable_offset, *offset)?)
3066        }).collect::<Result<Vec<_>, Error>>()?;
3067    
3068    Ok(GposSubClassSet::new(
3069        sub_class_rule_count,
3070        sub_class_rule_offsets,
3071        sub_class_rules
3072    ))
3073}
3074
3075fn parse_gpos_sub_class_rule(bytes: &[u8], subtable_offset: usize, sub_class_rule_offset: u16) -> Result<GposSubClassRule, Error> {
3076    let mut offset = subtable_offset + sub_class_rule_offset as usize;
3077    let glyph_count = get_u16(bytes, offset)?;
3078    let sub_count = get_u16(bytes, offset + 2)?;
3079    offset += 4;
3080    let class_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3081        .ok_or(ErrorKind::UnexpectedEof)?
3082        .chunks_exact(2)
3083        .map(|ch| {
3084            u16::from_be_bytes(ch.try_into().unwrap())
3085        }).collect();
3086    offset += glyph_count as usize * 2;
3087    let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3088        Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3089    }).collect::<Result<Vec<_>, Error>>()?;
3090    
3091    Ok(GposSubClassRule::new(
3092        glyph_count,
3093        sub_count,
3094        class_ids,
3095        pos_lookup_records
3096    ))
3097}
3098
3099fn parse_gpos_chain_sub_rule_set(bytes: &[u8], subtable_offset: usize, chain_sub_rule_set_offset: u16) -> Result<GposChainSubRuleSet, Error> {
3100    let mut offset = subtable_offset + chain_sub_rule_set_offset as usize;
3101    let chain_sub_rule_count = get_u16(bytes, offset)?;
3102    offset += 2;
3103    let chain_sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_count as usize * 2)
3104        .ok_or(ErrorKind::UnexpectedEof)?
3105        .chunks_exact(2)
3106        .map(|ch| {
3107            u16::from_be_bytes(ch.try_into().unwrap())
3108        }).collect();
3109    let chain_sub_rules: Vec<GposChainSubRule> = chain_sub_rule_offsets.iter()
3110        .map(|offset| {
3111            Ok(parse_gpos_chain_sub_rule(bytes, subtable_offset, *offset)?)
3112        }).collect::<Result<Vec<_>, Error>>()?;
3113    
3114    Ok(GposChainSubRuleSet::new(
3115        chain_sub_rule_count,
3116        chain_sub_rule_offsets,
3117        chain_sub_rules
3118    ))
3119}
3120
3121fn parse_gpos_chain_sub_class_set(bytes: &[u8], subtable_offset: usize, chain_sub_class_set_offset: u16) -> Result<GposChainSubClassSet, Error> {
3122    let mut offset = subtable_offset + chain_sub_class_set_offset as usize;
3123    let chain_sub_class_rule_count = get_u16(bytes, offset)?;
3124    offset += 2;
3125    let chain_sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_rule_count as usize * 2)
3126        .ok_or(ErrorKind::UnexpectedEof)?
3127        .chunks_exact(2)
3128        .map(|ch| {
3129            u16::from_be_bytes(ch.try_into().unwrap())
3130        }).collect();
3131    let chain_sub_class_rules: Vec<GposChainSubClassRule> = chain_sub_class_rule_offsets.iter()
3132        .map(|offset| {
3133            Ok(parse_gpos_chain_sub_class_rule(bytes, subtable_offset, *offset)?)
3134        }).collect::<Result<Vec<_>, Error>>()?;
3135    
3136    Ok(GposChainSubClassSet::new(
3137        chain_sub_class_rule_count,
3138        chain_sub_class_rule_offsets,
3139        chain_sub_class_rules
3140    ))
3141}
3142
3143fn parse_gpos_chain_sub_class_rule(bytes: &[u8], subtable_offset: usize, chain_sub_class_rule_offset: u16) -> Result<GposChainSubClassRule, Error> {
3144    let mut offset = subtable_offset + chain_sub_class_rule_offset as usize;
3145    let backtrack_glyph_count = get_u16(bytes, offset)?;
3146    offset += 2;
3147    let backtrack_class_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3148        .ok_or(ErrorKind::UnexpectedEof)?
3149        .chunks_exact(2)
3150        .map(|ch| {
3151            u16::from_be_bytes(ch.try_into().unwrap())
3152        }).collect();
3153    offset += backtrack_glyph_count as usize * 2;
3154    let input_glyph_count = get_u16(bytes, offset)?;
3155    offset += 2;
3156    let input_class_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3157        .ok_or(ErrorKind::UnexpectedEof)?
3158        .chunks_exact(2)
3159        .map(|ch| {
3160            u16::from_be_bytes(ch.try_into().unwrap())
3161        }).collect();
3162    offset += input_glyph_count as usize * 2;
3163    let lookahead_glyph_count = get_u16(bytes, offset)?;
3164    offset += 2;
3165    let lookahead_class_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3166        .ok_or(ErrorKind::UnexpectedEof)?
3167        .chunks_exact(2)
3168        .map(|ch| {
3169            u16::from_be_bytes(ch.try_into().unwrap())
3170        }).collect();
3171    offset += lookahead_glyph_count as usize * 2;
3172    let sub_count = get_u16(bytes, offset)?;
3173    offset += 2;
3174    let pos_lookup_records = (0..sub_count).map(|_| {
3175        Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3176    }).collect::<Result<Vec<_>, Error>>()?;
3177    
3178    Ok(GposChainSubClassRule::new(
3179        backtrack_glyph_count,
3180        backtrack_class_ids,
3181        input_glyph_count,
3182        input_class_ids,
3183        lookahead_glyph_count,
3184        lookahead_class_ids,
3185        sub_count,
3186        pos_lookup_records
3187    ))
3188}
3189
3190fn parse_gpos_chain_sub_rule(bytes: &[u8], subtable_offset: usize, chain_sub_rule_offset: u16) -> Result<GposChainSubRule, Error> {
3191    let mut offset = subtable_offset + chain_sub_rule_offset as usize;
3192    let backtrack_glyph_count = get_u16(bytes, offset)?;
3193    offset += 2;
3194    let backtrack_glyph_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3195        .ok_or(ErrorKind::UnexpectedEof)?
3196        .chunks_exact(2)
3197        .map(|ch| {
3198            u16::from_be_bytes(ch.try_into().unwrap())
3199        }).collect();
3200    offset += backtrack_glyph_count as usize * 2;
3201    let input_glyph_count = get_u16(bytes, offset)?;
3202    offset += 2;
3203    let input_glyph_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3204        .ok_or(ErrorKind::UnexpectedEof)?
3205        .chunks_exact(2)
3206        .map(|ch| {
3207            u16::from_be_bytes(ch.try_into().unwrap())
3208        }).collect();
3209    offset += input_glyph_count as usize * 2;
3210    let lookahead_glyph_count = get_u16(bytes, offset)?;
3211    offset += 2;
3212    let lookahead_glyph_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3213        .ok_or(ErrorKind::UnexpectedEof)?
3214        .chunks_exact(2)
3215        .map(|ch| {
3216            u16::from_be_bytes(ch.try_into().unwrap())
3217        }).collect();
3218    offset += lookahead_glyph_count as usize * 2;
3219    let sub_count = get_u16(bytes, offset)?;
3220    offset += 2;
3221    let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3222        Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3223    }).collect::<Result<Vec<_>, Error>>()?;
3224    
3225    Ok(GposChainSubRule::new(
3226        backtrack_glyph_count,
3227        backtrack_glyph_ids,
3228        input_glyph_count,
3229        input_glyph_ids,
3230        lookahead_glyph_count,
3231        lookahead_glyph_ids,
3232        sub_count,
3233        pos_lookup_records
3234    ))
3235}
3236
3237fn parse_sequence(bytes: &[u8], subtable_offset: usize, sequence_offset: u16) -> Result<Sequence, Error> {
3238    let mut offset = subtable_offset + sequence_offset as usize;
3239    let glyph_count = get_u16(bytes, offset)?;
3240    offset += 2;
3241    let substitute_glyph_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
3242        .ok_or(ErrorKind::UnexpectedEof)?
3243        .chunks_exact(2)
3244        .map(|ch| {
3245            u16::from_be_bytes(ch.try_into().unwrap())
3246        }).collect();
3247    
3248    Ok(Sequence::new(
3249        glyph_count,
3250        substitute_glyph_ids
3251    ))
3252}
3253
3254fn parse_alternate_set(bytes: &[u8], subtable_offset: usize, alternate_set_offset: u16) -> Result<AlternateSet, Error> {
3255    let mut offset = subtable_offset + alternate_set_offset as usize;
3256    let glyph_count = get_u16(bytes, offset)?;
3257    offset += 2;
3258    let alternate_glyph_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3259        .ok_or(ErrorKind::UnexpectedEof)?
3260        .chunks_exact(2)
3261        .map(|ch| {
3262            u16::from_be_bytes(ch.try_into().unwrap())
3263        }).collect();
3264    
3265    Ok(AlternateSet::new(
3266        glyph_count,
3267        alternate_glyph_ids
3268    ))
3269}
3270
3271fn parse_ligature_set(bytes: &[u8], subtable_offset: usize, ligature_set_offset: u16) -> Result<LigatureSet, Error> {
3272    let mut offset = subtable_offset + ligature_set_offset as usize;
3273    let ligature_count = get_u16(bytes, offset)?;
3274    offset += 2;
3275    let ligature_offsets: Vec<u16> = bytes.get(offset..offset + ligature_count as usize * 2)
3276        .ok_or(ErrorKind::UnexpectedEof)?
3277        .chunks_exact(2)
3278        .map(|ch| {
3279            u16::from_be_bytes(ch.try_into().unwrap())
3280        }).collect();
3281    let ligatures: Vec<Ligature> = ligature_offsets.iter()
3282        .map(|offset| {
3283            Ok(parse_ligature(bytes, subtable_offset, *offset)?)
3284        }).collect::<Result<Vec<_>, Error>>()?;
3285    
3286    Ok(LigatureSet::new(
3287        ligature_count,
3288        ligature_offsets,
3289        ligatures
3290    ))
3291}
3292
3293fn parse_ligature(bytes: &[u8], subtable_offset: usize, ligature_offset: u16) -> Result<Ligature, Error> {
3294    let mut offset = subtable_offset + ligature_offset as usize;
3295    let ligature_glyph_id = get_u16(bytes, offset)?;
3296    let component_count = get_u16(bytes, offset + 2)?;
3297    offset += 4;
3298    let component_glyph_ids: Vec<u16> = bytes.get(offset..offset + component_count as usize * 2)
3299        .ok_or(ErrorKind::UnexpectedEof)?
3300        .chunks_exact(2)
3301        .map(|ch| {
3302            u16::from_be_bytes(ch.try_into().unwrap())
3303        }).collect();
3304    
3305    Ok(Ligature::new(
3306        ligature_glyph_id,
3307        component_count,
3308        component_glyph_ids
3309    ))
3310}
3311
3312fn parse_gsub_sub_rule_set(bytes: &[u8], subtable_offset: usize, sub_rule_set_offset: u16) -> Result<GsubSubRuleSet, Error> {
3313    let mut offset = subtable_offset + sub_rule_set_offset as usize;
3314    let sub_rule_count = get_u16(bytes, offset)?;
3315    offset += 2;
3316    let sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_count as usize * 2)
3317        .ok_or(ErrorKind::UnexpectedEof)?
3318        .chunks_exact(2)
3319        .map(|ch| {
3320            u16::from_be_bytes(ch.try_into().unwrap())
3321        }).collect();
3322    let sub_rules: Vec<GsubSubRule> = sub_rule_offsets.iter()
3323        .map(|offset| {
3324            Ok(parse_gsub_sub_rule(bytes, subtable_offset, *offset)?)
3325        }).collect::<Result<Vec<_>, Error>>()?;
3326    
3327    Ok(GsubSubRuleSet::new(
3328        sub_rule_count,
3329        sub_rule_offsets,
3330        sub_rules
3331    ))
3332}
3333
3334fn parse_gsub_sub_rule(bytes: &[u8], subtable_offset: usize, sub_rule_offset: u16) -> Result<GsubSubRule, Error> {
3335    let mut offset = subtable_offset + sub_rule_offset as usize;
3336    let glyph_count = get_u16(bytes, offset)?;
3337    let sub_count = get_u16(bytes, offset + 2)?;
3338    offset += 4;
3339    let input_glyph_ids: Vec<u16> = bytes.get(offset..offset + (glyph_count as usize - 1) * 2)
3340        .ok_or(ErrorKind::UnexpectedEof)?
3341        .chunks_exact(2)
3342        .map(|ch| {
3343            u16::from_be_bytes(ch.try_into().unwrap())
3344        }).collect();
3345    offset += glyph_count as usize * 2;
3346    let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3347        Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3348    }).collect::<Result<Vec<_>, Error>>()?;
3349    
3350    Ok(GsubSubRule::new(
3351        glyph_count,
3352        sub_count,
3353        input_glyph_ids,
3354        subst_lookup_records
3355    ))
3356}
3357
3358fn parse_subst_lookup_record(bytes: &[u8], offset: &mut usize) -> Result<SubstLookupRecord, Error> {
3359    let glyph_sequence_index = get_u16(bytes, *offset)?;
3360    let lookup_list_index = get_u16(bytes, *offset + 2)?;
3361    *offset += 4;
3362    
3363    Ok(SubstLookupRecord::new(
3364        glyph_sequence_index,
3365        lookup_list_index
3366    ))
3367}
3368
3369fn parse_gsub_sub_class_set(bytes: &[u8], subtable_offset: usize, sub_class_set_offset: u16) -> Result<GsubSubClassSet, Error> {
3370    let mut offset = subtable_offset + sub_class_set_offset as usize;
3371    let sub_class_rule_count = get_u16(bytes, offset)?;
3372    offset += 2;
3373    let sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_rule_count as usize * 2)
3374        .ok_or(ErrorKind::UnexpectedEof)?
3375        .chunks_exact(2)
3376        .map(|ch| {
3377            u16::from_be_bytes(ch.try_into().unwrap())
3378        }).collect();
3379    let sub_class_rules: Vec<GsubSubClassRule> = sub_class_rule_offsets.iter()
3380        .map(|offset| {
3381            Ok(parse_gsub_sub_class_rule(bytes, subtable_offset, *offset)?)
3382        }).collect::<Result<Vec<_>, Error>>()?;
3383    
3384    Ok(GsubSubClassSet::new(
3385        sub_class_rule_count,
3386        sub_class_rule_offsets,
3387        sub_class_rules
3388    ))
3389}
3390
3391fn parse_gsub_sub_class_rule(bytes: &[u8], subtable_offset: usize, sub_class_rule_offset: u16) -> Result<GsubSubClassRule, Error> {
3392    let mut offset = subtable_offset + sub_class_rule_offset as usize;
3393    let glyph_count = get_u16(bytes, offset)?;
3394    let sub_count = get_u16(bytes, offset + 2)?;
3395    offset += 4;
3396    let class_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3397        .ok_or(ErrorKind::UnexpectedEof)?
3398        .chunks_exact(2)
3399        .map(|ch| {
3400            u16::from_be_bytes(ch.try_into().unwrap())
3401        }).collect();
3402    offset += glyph_count as usize * 2;
3403    let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3404        Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3405    }).collect::<Result<Vec<_>, Error>>()?;
3406    
3407    Ok(GsubSubClassRule::new(
3408        glyph_count,
3409        sub_count,
3410        class_ids,
3411        subst_lookup_records
3412    ))
3413}
3414
3415fn parse_gsub_chain_sub_rule_set(bytes: &[u8], subtable_offset: usize, chain_sub_rule_set_offset: u16) -> Result<GsubChainSubRuleSet, Error> {
3416    let mut offset = subtable_offset + chain_sub_rule_set_offset as usize;
3417    let chain_sub_rule_count = get_u16(bytes, offset)?;
3418    offset += 2;
3419    let chain_sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_count as usize * 2)
3420        .ok_or(ErrorKind::UnexpectedEof)?
3421        .chunks_exact(2)
3422        .map(|ch| {
3423            u16::from_be_bytes(ch.try_into().unwrap())
3424        }).collect();
3425    let chain_sub_rules: Vec<GsubChainSubRule> = chain_sub_rule_offsets.iter()
3426        .map(|offset| {
3427            Ok(parse_gsub_chain_sub_rule(bytes, subtable_offset, *offset)?)
3428        }).collect::<Result<Vec<_>, Error>>()?;
3429    
3430    Ok(GsubChainSubRuleSet::new(
3431        chain_sub_rule_count,
3432        chain_sub_rule_offsets,
3433        chain_sub_rules
3434    ))
3435}
3436
3437fn parse_gsub_chain_sub_class_set(bytes: &[u8], subtable_offset: usize, chain_sub_class_set_offset: u16) -> Result<GsubChainSubClassSet, Error> {
3438    let mut offset = subtable_offset + chain_sub_class_set_offset as usize;
3439    let chain_sub_class_rule_count = get_u16(bytes, offset)?;
3440    offset += 2;
3441    let chain_sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_rule_count as usize * 2)
3442        .ok_or(ErrorKind::UnexpectedEof)?
3443        .chunks_exact(2)
3444        .map(|ch| {
3445            u16::from_be_bytes(ch.try_into().unwrap())
3446        }).collect();
3447    let chain_sub_class_rules: Vec<GsubChainSubClassRule> = chain_sub_class_rule_offsets.iter()
3448        .map(|offset| {
3449            Ok(parse_gsub_chain_sub_class_rule(bytes, subtable_offset, *offset)?)
3450        }).collect::<Result<Vec<_>, Error>>()?;
3451    
3452    Ok(GsubChainSubClassSet::new(
3453        chain_sub_class_rule_count,
3454        chain_sub_class_rule_offsets,
3455        chain_sub_class_rules
3456    ))
3457}
3458
3459fn parse_gsub_chain_sub_class_rule(bytes: &[u8], subtable_offset: usize, chain_sub_class_rule_offset: u16) -> Result<GsubChainSubClassRule, Error> {
3460    let mut offset = subtable_offset + chain_sub_class_rule_offset as usize;
3461    let backtrack_glyph_count = get_u16(bytes, offset)?;
3462    offset += 2;
3463    let backtrack_class_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3464        .ok_or(ErrorKind::UnexpectedEof)?
3465        .chunks_exact(2)
3466        .map(|ch| {
3467            u16::from_be_bytes(ch.try_into().unwrap())
3468        }).collect();
3469    offset += backtrack_glyph_count as usize * 2;
3470    let input_glyph_count = get_u16(bytes, offset)?;
3471    offset += 2;
3472    let input_class_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3473        .ok_or(ErrorKind::UnexpectedEof)?
3474        .chunks_exact(2)
3475        .map(|ch| {
3476            u16::from_be_bytes(ch.try_into().unwrap())
3477        }).collect();
3478    offset += input_glyph_count as usize * 2;
3479    let lookahead_glyph_count = get_u16(bytes, offset)?;
3480    offset += 2;
3481    let lookahead_class_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3482        .ok_or(ErrorKind::UnexpectedEof)?
3483        .chunks_exact(2)
3484        .map(|ch| {
3485            u16::from_be_bytes(ch.try_into().unwrap())
3486        }).collect();
3487    offset += lookahead_glyph_count as usize * 2;
3488    let sub_count = get_u16(bytes, offset)?;
3489    offset += 2;
3490    let subst_lookup_records = (0..sub_count).map(|_| {
3491        Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3492    }).collect::<Result<Vec<_>, Error>>()?;
3493    
3494    Ok(GsubChainSubClassRule::new(
3495        backtrack_glyph_count,
3496        backtrack_class_ids,
3497        input_glyph_count,
3498        input_class_ids,
3499        lookahead_glyph_count,
3500        lookahead_class_ids,
3501        sub_count,
3502        subst_lookup_records
3503    ))
3504}
3505
3506fn parse_gsub_chain_sub_rule(bytes: &[u8], subtable_offset: usize, chain_sub_rule_offset: u16) -> Result<GsubChainSubRule, Error> {
3507    let mut offset = subtable_offset + chain_sub_rule_offset as usize;
3508    let backtrack_glyph_count = get_u16(bytes, offset)?;
3509    offset += 2;
3510    let backtrack_glyph_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3511        .ok_or(ErrorKind::UnexpectedEof)?
3512        .chunks_exact(2)
3513        .map(|ch| {
3514            u16::from_be_bytes(ch.try_into().unwrap())
3515        }).collect();
3516    offset += backtrack_glyph_count as usize * 2;
3517    let input_glyph_count = get_u16(bytes, offset)?;
3518    offset += 2;
3519    let input_glyph_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3520        .ok_or(ErrorKind::UnexpectedEof)?
3521        .chunks_exact(2)
3522        .map(|ch| {
3523            u16::from_be_bytes(ch.try_into().unwrap())
3524        }).collect();
3525    offset += input_glyph_count as usize * 2;
3526    let lookahead_glyph_count = get_u16(bytes, offset)?;
3527    offset += 2;
3528    let lookahead_glyph_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3529        .ok_or(ErrorKind::UnexpectedEof)?
3530        .chunks_exact(2)
3531        .map(|ch| {
3532            u16::from_be_bytes(ch.try_into().unwrap())
3533        }).collect();
3534    offset += lookahead_glyph_count as usize * 2;
3535    let sub_count = get_u16(bytes, offset)?;
3536    offset += 2;
3537    let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3538        Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3539    }).collect::<Result<Vec<_>, Error>>()?;
3540    
3541    Ok(GsubChainSubRule::new(
3542        backtrack_glyph_count,
3543        backtrack_glyph_ids,
3544        input_glyph_count,
3545        input_glyph_ids,
3546        lookahead_glyph_count,
3547        lookahead_glyph_ids,
3548        sub_count,
3549        subst_lookup_records
3550    ))
3551}
3552
3553fn get_u16(bytes: &[u8], start: usize) -> Result<u16, Error> {
3554    Ok(
3555        u16::from_be_bytes(
3556        bytes.get(start..start + 2)
3557            .ok_or(ErrorKind::UnexpectedEof)?
3558            .try_into()
3559            .unwrap()
3560        )
3561    )
3562}
3563
3564fn get_u32(bytes: &[u8], start: usize) -> Result<u32, Error> {
3565    Ok(
3566        u32::from_be_bytes(
3567            bytes.get(start..start + 4)
3568                .ok_or(ErrorKind::UnexpectedEof)?
3569                .try_into()
3570                .unwrap()
3571        )
3572    )
3573}
3574
3575fn get_i16(bytes: &[u8], start: usize) -> Result<i16, Error> {
3576    Ok(
3577        i16::from_be_bytes(
3578            bytes.get(start..start + 2)
3579                .ok_or(ErrorKind::UnexpectedEof)?
3580                .try_into()
3581                .unwrap()
3582        )
3583    )
3584}
3585
3586fn get_i32(bytes: &[u8], start: usize) -> Result<i32, Error> {
3587    Ok(
3588        i32::from_be_bytes(
3589            bytes.get(start..start + 4)
3590                .ok_or(ErrorKind::UnexpectedEof)?
3591                .try_into()
3592                .unwrap()
3593        )
3594    )
3595}
3596
3597fn get_i64(bytes: &[u8], start: usize) -> Result<i64, Error> {
3598    Ok(
3599        i64::from_be_bytes(
3600            bytes.get(start..start + 8)
3601                .ok_or(ErrorKind::UnexpectedEof)?
3602                .try_into()
3603                .unwrap()
3604        )
3605    )
3606}
3607
3608// Add support for more once I create HTTP/HTTPS part of spyne
3609fn decode_name_bytes(bytes: &[u8], platform_id: u16, encoding_id: u16) -> Result<String, Error> {
3610    match platform_id {
3611        0 => {
3612            let name_bytes: Vec<u16> = bytes.chunks_exact(2)
3613                .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap()))
3614                .collect();
3615            
3616            Ok(String::from_utf16(&name_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?)
3617        }
3618        1 => {
3619            match encoding_id {
3620                0 => {
3621                    Ok(
3622                        bytes.iter()
3623                            .map(|idx| MAC_ROMAN_LOOKUP[*idx as usize])
3624                            .collect::<String>()
3625                    )
3626                }
3627                _ => Err(Error::new(ErrorKind::Unsupported, "Only encoding 0 (Mac Roman) currently supported for platform 1"))
3628            }
3629        }
3630        3 => {
3631            match encoding_id {
3632                0 | 1 | 10 => {
3633                    let name_bytes: Vec<u16> = bytes.chunks_exact(2)
3634                        .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap()))
3635                        .collect();
3636                    
3637                    Ok(String::from_utf16(&name_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?)
3638                }
3639                _ => Err(Error::new(ErrorKind::Unsupported, "Platform 3, Encodings 2 - 9 decoding currently unsupported"))
3640            }
3641        }
3642        _ => Err(Error::new(ErrorKind::Unsupported, "Platform 2 and 4 decoding currently unsupported"))
3643    }
3644}