Skip to main content

read_fonts/generated/
generated_aat.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8/// Lookup tables provide a way of looking up information about a glyph index.
9/// The different cmap subtable formats.
10#[derive(Clone)]
11pub enum Lookup<'a> {
12    Format0(Lookup0<'a>),
13    Format2(Lookup2<'a>),
14    Format4(Lookup4<'a>),
15    Format6(Lookup6<'a>),
16    Format8(Lookup8<'a>),
17    Format10(Lookup10<'a>),
18}
19
20impl Default for Lookup<'_> {
21    fn default() -> Self {
22        Self::Format0(Default::default())
23    }
24}
25
26impl<'a> Lookup<'a> {
27    ///Return the `FontData` used to resolve offsets for this table.
28    pub fn offset_data(&self) -> FontData<'a> {
29        match self {
30            Self::Format0(item) => item.offset_data(),
31            Self::Format2(item) => item.offset_data(),
32            Self::Format4(item) => item.offset_data(),
33            Self::Format6(item) => item.offset_data(),
34            Self::Format8(item) => item.offset_data(),
35            Self::Format10(item) => item.offset_data(),
36        }
37    }
38
39    /// Format number is set to 0.
40    pub fn format(&self) -> u16 {
41        match self {
42            Self::Format0(item) => item.format(),
43            Self::Format2(item) => item.format(),
44            Self::Format4(item) => item.format(),
45            Self::Format6(item) => item.format(),
46            Self::Format8(item) => item.format(),
47            Self::Format10(item) => item.format(),
48        }
49    }
50}
51
52impl ReadArgs for Lookup<'_> {
53    type Args = ();
54}
55
56impl<'a> FontRead<'a> for Lookup<'a> {
57    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
58        let format: u16 = data.read_at(0usize)?;
59        match format {
60            Lookup0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
61            Lookup2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
62            Lookup4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
63            Lookup6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
64            Lookup8::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
65            Lookup10::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
66            other => Err(ReadError::InvalidFormat(other.into())),
67        }
68    }
69}
70
71impl<'a> MinByteRange<'a> for Lookup<'a> {
72    fn min_byte_range(&self) -> Range<usize> {
73        match self {
74            Self::Format0(item) => item.min_byte_range(),
75            Self::Format2(item) => item.min_byte_range(),
76            Self::Format4(item) => item.min_byte_range(),
77            Self::Format6(item) => item.min_byte_range(),
78            Self::Format8(item) => item.min_byte_range(),
79            Self::Format10(item) => item.min_byte_range(),
80        }
81    }
82    fn min_table_bytes(&self) -> &'a [u8] {
83        match self {
84            Self::Format0(item) => item.min_table_bytes(),
85            Self::Format2(item) => item.min_table_bytes(),
86            Self::Format4(item) => item.min_table_bytes(),
87            Self::Format6(item) => item.min_table_bytes(),
88            Self::Format8(item) => item.min_table_bytes(),
89            Self::Format10(item) => item.min_table_bytes(),
90        }
91    }
92}
93
94impl Format<u16> for Lookup0<'_> {
95    const FORMAT: u16 = 0;
96}
97
98impl<'a> MinByteRange<'a> for Lookup0<'a> {
99    fn min_byte_range(&self) -> Range<usize> {
100        0..self.values_data_byte_range().end
101    }
102    fn min_table_bytes(&self) -> &'a [u8] {
103        let range = self.min_byte_range();
104        self.data.as_bytes().get(range).unwrap_or_default()
105    }
106}
107
108impl ReadArgs for Lookup0<'_> {
109    type Args = ();
110}
111
112impl<'a> FontRead<'a> for Lookup0<'a> {
113    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
114        #[allow(clippy::absurd_extreme_comparisons)]
115        if data.len() < Self::MIN_SIZE {
116            return Err(ReadError::OutOfBounds);
117        }
118        Ok(Self { data })
119    }
120}
121
122/// Simple array format. The lookup data is an array of lookup values, indexed
123/// by glyph index.
124#[derive(Clone)]
125pub struct Lookup0<'a> {
126    data: FontData<'a>,
127}
128
129#[allow(clippy::needless_lifetimes)]
130impl<'a> Lookup0<'a> {
131    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
132    basic_table_impls!(impl_the_methods);
133
134    /// Format number is set to 0.
135    pub fn format(&self) -> u16 {
136        let range = self.format_byte_range();
137        self.data.read_at(range.start).ok().unwrap()
138    }
139
140    /// Values, indexed by glyph index.
141    pub fn values_data(&self) -> &'a [u8] {
142        let range = self.values_data_byte_range();
143        self.data.read_array(range).ok().unwrap_or_default()
144    }
145
146    pub fn format_byte_range(&self) -> Range<usize> {
147        let start = 0;
148        let end = start + u16::RAW_BYTE_LEN;
149        start..end
150    }
151
152    pub fn values_data_byte_range(&self) -> Range<usize> {
153        let start = self.format_byte_range().end;
154        let end =
155            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
156        start..end
157    }
158}
159
160const _: () = assert!(FontData::default_data_long_enough(Lookup0::MIN_SIZE));
161
162impl Default for Lookup0<'_> {
163    fn default() -> Self {
164        Self {
165            data: FontData::default_table_data(),
166        }
167    }
168}
169
170impl Format<u16> for Lookup2<'_> {
171    const FORMAT: u16 = 2;
172}
173
174impl<'a> MinByteRange<'a> for Lookup2<'a> {
175    fn min_byte_range(&self) -> Range<usize> {
176        0..self.segments_data_byte_range().end
177    }
178    fn min_table_bytes(&self) -> &'a [u8] {
179        let range = self.min_byte_range();
180        self.data.as_bytes().get(range).unwrap_or_default()
181    }
182}
183
184impl ReadArgs for Lookup2<'_> {
185    type Args = ();
186}
187
188impl<'a> FontRead<'a> for Lookup2<'a> {
189    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
190        #[allow(clippy::absurd_extreme_comparisons)]
191        if data.len() < Self::MIN_SIZE {
192            return Err(ReadError::OutOfBounds);
193        }
194        Ok(Self { data })
195    }
196}
197
198/// Segment single format. Each non-overlapping segment has a single lookup
199/// value that applies to all glyphs in the segment. A segment is defined as
200/// a contiguous range of glyph indexes.
201#[derive(Clone)]
202pub struct Lookup2<'a> {
203    data: FontData<'a>,
204}
205
206#[allow(clippy::needless_lifetimes)]
207impl<'a> Lookup2<'a> {
208    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
209        + u16::RAW_BYTE_LEN
210        + u16::RAW_BYTE_LEN
211        + u16::RAW_BYTE_LEN
212        + u16::RAW_BYTE_LEN
213        + u16::RAW_BYTE_LEN);
214    basic_table_impls!(impl_the_methods);
215
216    /// Format number is set to 2.
217    pub fn format(&self) -> u16 {
218        let range = self.format_byte_range();
219        self.data.read_at(range.start).ok().unwrap()
220    }
221
222    /// Size of a lookup unit for this search in bytes.
223    pub fn unit_size(&self) -> u16 {
224        let range = self.unit_size_byte_range();
225        self.data.read_at(range.start).ok().unwrap()
226    }
227
228    /// Number of units of the preceding size to be searched.
229    pub fn n_units(&self) -> u16 {
230        let range = self.n_units_byte_range();
231        self.data.read_at(range.start).ok().unwrap()
232    }
233
234    /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits.
235    pub fn search_range(&self) -> u16 {
236        let range = self.search_range_byte_range();
237        self.data.read_at(range.start).ok().unwrap()
238    }
239
240    /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits.
241    pub fn entry_selector(&self) -> u16 {
242        let range = self.entry_selector_byte_range();
243        self.data.read_at(range.start).ok().unwrap()
244    }
245
246    /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits.
247    pub fn range_shift(&self) -> u16 {
248        let range = self.range_shift_byte_range();
249        self.data.read_at(range.start).ok().unwrap()
250    }
251
252    /// Segments.
253    pub fn segments_data(&self) -> &'a [u8] {
254        let range = self.segments_data_byte_range();
255        self.data.read_array(range).ok().unwrap_or_default()
256    }
257
258    pub fn format_byte_range(&self) -> Range<usize> {
259        let start = 0;
260        let end = start + u16::RAW_BYTE_LEN;
261        start..end
262    }
263
264    pub fn unit_size_byte_range(&self) -> Range<usize> {
265        let start = self.format_byte_range().end;
266        let end = start + u16::RAW_BYTE_LEN;
267        start..end
268    }
269
270    pub fn n_units_byte_range(&self) -> Range<usize> {
271        let start = self.unit_size_byte_range().end;
272        let end = start + u16::RAW_BYTE_LEN;
273        start..end
274    }
275
276    pub fn search_range_byte_range(&self) -> Range<usize> {
277        let start = self.n_units_byte_range().end;
278        let end = start + u16::RAW_BYTE_LEN;
279        start..end
280    }
281
282    pub fn entry_selector_byte_range(&self) -> Range<usize> {
283        let start = self.search_range_byte_range().end;
284        let end = start + u16::RAW_BYTE_LEN;
285        start..end
286    }
287
288    pub fn range_shift_byte_range(&self) -> Range<usize> {
289        let start = self.entry_selector_byte_range().end;
290        let end = start + u16::RAW_BYTE_LEN;
291        start..end
292    }
293
294    pub fn segments_data_byte_range(&self) -> Range<usize> {
295        let unit_size = self.unit_size();
296        let n_units = self.n_units();
297        let start = self.range_shift_byte_range().end;
298        let end = start
299            + (transforms::add_multiply(unit_size, 0_usize, n_units))
300                .saturating_mul(u8::RAW_BYTE_LEN);
301        start..end
302    }
303}
304
305impl Format<u16> for Lookup4<'_> {
306    const FORMAT: u16 = 4;
307}
308
309impl<'a> MinByteRange<'a> for Lookup4<'a> {
310    fn min_byte_range(&self) -> Range<usize> {
311        0..self.segments_byte_range().end
312    }
313    fn min_table_bytes(&self) -> &'a [u8] {
314        let range = self.min_byte_range();
315        self.data.as_bytes().get(range).unwrap_or_default()
316    }
317}
318
319impl ReadArgs for Lookup4<'_> {
320    type Args = ();
321}
322
323impl<'a> FontRead<'a> for Lookup4<'a> {
324    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
325        #[allow(clippy::absurd_extreme_comparisons)]
326        if data.len() < Self::MIN_SIZE {
327            return Err(ReadError::OutOfBounds);
328        }
329        Ok(Self { data })
330    }
331}
332
333/// Segment array format. A segment mapping is performed (as with Format 2),
334/// but instead of a single lookup value for all the glyphs in the segment,
335/// each glyph in the segment gets its own separate lookup value.
336#[derive(Clone)]
337pub struct Lookup4<'a> {
338    data: FontData<'a>,
339}
340
341#[allow(clippy::needless_lifetimes)]
342impl<'a> Lookup4<'a> {
343    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
344        + u16::RAW_BYTE_LEN
345        + u16::RAW_BYTE_LEN
346        + u16::RAW_BYTE_LEN
347        + u16::RAW_BYTE_LEN
348        + u16::RAW_BYTE_LEN);
349    basic_table_impls!(impl_the_methods);
350
351    /// Format number is set to 4.
352    pub fn format(&self) -> u16 {
353        let range = self.format_byte_range();
354        self.data.read_at(range.start).ok().unwrap()
355    }
356
357    /// Size of a lookup unit for this search in bytes.
358    pub fn unit_size(&self) -> u16 {
359        let range = self.unit_size_byte_range();
360        self.data.read_at(range.start).ok().unwrap()
361    }
362
363    /// Number of units of the preceding size to be searched.
364    pub fn n_units(&self) -> u16 {
365        let range = self.n_units_byte_range();
366        self.data.read_at(range.start).ok().unwrap()
367    }
368
369    /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits.
370    pub fn search_range(&self) -> u16 {
371        let range = self.search_range_byte_range();
372        self.data.read_at(range.start).ok().unwrap()
373    }
374
375    /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits.
376    pub fn entry_selector(&self) -> u16 {
377        let range = self.entry_selector_byte_range();
378        self.data.read_at(range.start).ok().unwrap()
379    }
380
381    /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits.
382    pub fn range_shift(&self) -> u16 {
383        let range = self.range_shift_byte_range();
384        self.data.read_at(range.start).ok().unwrap()
385    }
386
387    /// Segments.
388    pub fn segments(&self) -> &'a [LookupSegment4] {
389        let range = self.segments_byte_range();
390        self.data.read_array(range).ok().unwrap_or_default()
391    }
392
393    pub fn format_byte_range(&self) -> Range<usize> {
394        let start = 0;
395        let end = start + u16::RAW_BYTE_LEN;
396        start..end
397    }
398
399    pub fn unit_size_byte_range(&self) -> Range<usize> {
400        let start = self.format_byte_range().end;
401        let end = start + u16::RAW_BYTE_LEN;
402        start..end
403    }
404
405    pub fn n_units_byte_range(&self) -> Range<usize> {
406        let start = self.unit_size_byte_range().end;
407        let end = start + u16::RAW_BYTE_LEN;
408        start..end
409    }
410
411    pub fn search_range_byte_range(&self) -> Range<usize> {
412        let start = self.n_units_byte_range().end;
413        let end = start + u16::RAW_BYTE_LEN;
414        start..end
415    }
416
417    pub fn entry_selector_byte_range(&self) -> Range<usize> {
418        let start = self.search_range_byte_range().end;
419        let end = start + u16::RAW_BYTE_LEN;
420        start..end
421    }
422
423    pub fn range_shift_byte_range(&self) -> Range<usize> {
424        let start = self.entry_selector_byte_range().end;
425        let end = start + u16::RAW_BYTE_LEN;
426        start..end
427    }
428
429    pub fn segments_byte_range(&self) -> Range<usize> {
430        let n_units = self.n_units();
431        let start = self.range_shift_byte_range().end;
432        let end =
433            start + (transforms::to_usize(n_units)).saturating_mul(LookupSegment4::RAW_BYTE_LEN);
434        start..end
435    }
436}
437
438/// Lookup segment for format 4.
439#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
440#[repr(C)]
441#[repr(packed)]
442pub struct LookupSegment4 {
443    /// Last glyph index in this segment.
444    pub last_glyph: BigEndian<u16>,
445    /// First glyph index in this segment.
446    pub first_glyph: BigEndian<u16>,
447    /// A 16-bit offset from the start of the table to the data.
448    pub value_offset: BigEndian<u16>,
449}
450
451impl LookupSegment4 {
452    /// Last glyph index in this segment.
453    pub fn last_glyph(&self) -> u16 {
454        self.last_glyph.get()
455    }
456
457    /// First glyph index in this segment.
458    pub fn first_glyph(&self) -> u16 {
459        self.first_glyph.get()
460    }
461
462    /// A 16-bit offset from the start of the table to the data.
463    pub fn value_offset(&self) -> u16 {
464        self.value_offset.get()
465    }
466}
467
468impl FixedSize for LookupSegment4 {
469    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
470}
471
472impl Format<u16> for Lookup6<'_> {
473    const FORMAT: u16 = 6;
474}
475
476impl<'a> MinByteRange<'a> for Lookup6<'a> {
477    fn min_byte_range(&self) -> Range<usize> {
478        0..self.entries_data_byte_range().end
479    }
480    fn min_table_bytes(&self) -> &'a [u8] {
481        let range = self.min_byte_range();
482        self.data.as_bytes().get(range).unwrap_or_default()
483    }
484}
485
486impl ReadArgs for Lookup6<'_> {
487    type Args = ();
488}
489
490impl<'a> FontRead<'a> for Lookup6<'a> {
491    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
492        #[allow(clippy::absurd_extreme_comparisons)]
493        if data.len() < Self::MIN_SIZE {
494            return Err(ReadError::OutOfBounds);
495        }
496        Ok(Self { data })
497    }
498}
499
500/// Single table format. The lookup data is a sorted list of
501/// <glyph index,lookup value> pairs.
502#[derive(Clone)]
503pub struct Lookup6<'a> {
504    data: FontData<'a>,
505}
506
507#[allow(clippy::needless_lifetimes)]
508impl<'a> Lookup6<'a> {
509    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
510        + u16::RAW_BYTE_LEN
511        + u16::RAW_BYTE_LEN
512        + u16::RAW_BYTE_LEN
513        + u16::RAW_BYTE_LEN
514        + u16::RAW_BYTE_LEN);
515    basic_table_impls!(impl_the_methods);
516
517    /// Format number is set to 6.
518    pub fn format(&self) -> u16 {
519        let range = self.format_byte_range();
520        self.data.read_at(range.start).ok().unwrap()
521    }
522
523    /// Size of a lookup unit for this search in bytes.
524    pub fn unit_size(&self) -> u16 {
525        let range = self.unit_size_byte_range();
526        self.data.read_at(range.start).ok().unwrap()
527    }
528
529    /// Number of units of the preceding size to be searched.
530    pub fn n_units(&self) -> u16 {
531        let range = self.n_units_byte_range();
532        self.data.read_at(range.start).ok().unwrap()
533    }
534
535    /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits.
536    pub fn search_range(&self) -> u16 {
537        let range = self.search_range_byte_range();
538        self.data.read_at(range.start).ok().unwrap()
539    }
540
541    /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits.
542    pub fn entry_selector(&self) -> u16 {
543        let range = self.entry_selector_byte_range();
544        self.data.read_at(range.start).ok().unwrap()
545    }
546
547    /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits.
548    pub fn range_shift(&self) -> u16 {
549        let range = self.range_shift_byte_range();
550        self.data.read_at(range.start).ok().unwrap()
551    }
552
553    /// Values, indexed by glyph index.
554    pub fn entries_data(&self) -> &'a [u8] {
555        let range = self.entries_data_byte_range();
556        self.data.read_array(range).ok().unwrap_or_default()
557    }
558
559    pub fn format_byte_range(&self) -> Range<usize> {
560        let start = 0;
561        let end = start + u16::RAW_BYTE_LEN;
562        start..end
563    }
564
565    pub fn unit_size_byte_range(&self) -> Range<usize> {
566        let start = self.format_byte_range().end;
567        let end = start + u16::RAW_BYTE_LEN;
568        start..end
569    }
570
571    pub fn n_units_byte_range(&self) -> Range<usize> {
572        let start = self.unit_size_byte_range().end;
573        let end = start + u16::RAW_BYTE_LEN;
574        start..end
575    }
576
577    pub fn search_range_byte_range(&self) -> Range<usize> {
578        let start = self.n_units_byte_range().end;
579        let end = start + u16::RAW_BYTE_LEN;
580        start..end
581    }
582
583    pub fn entry_selector_byte_range(&self) -> Range<usize> {
584        let start = self.search_range_byte_range().end;
585        let end = start + u16::RAW_BYTE_LEN;
586        start..end
587    }
588
589    pub fn range_shift_byte_range(&self) -> Range<usize> {
590        let start = self.entry_selector_byte_range().end;
591        let end = start + u16::RAW_BYTE_LEN;
592        start..end
593    }
594
595    pub fn entries_data_byte_range(&self) -> Range<usize> {
596        let unit_size = self.unit_size();
597        let n_units = self.n_units();
598        let start = self.range_shift_byte_range().end;
599        let end = start
600            + (transforms::add_multiply(unit_size, 0_usize, n_units))
601                .saturating_mul(u8::RAW_BYTE_LEN);
602        start..end
603    }
604}
605
606impl Format<u16> for Lookup8<'_> {
607    const FORMAT: u16 = 8;
608}
609
610impl<'a> MinByteRange<'a> for Lookup8<'a> {
611    fn min_byte_range(&self) -> Range<usize> {
612        0..self.value_array_byte_range().end
613    }
614    fn min_table_bytes(&self) -> &'a [u8] {
615        let range = self.min_byte_range();
616        self.data.as_bytes().get(range).unwrap_or_default()
617    }
618}
619
620impl ReadArgs for Lookup8<'_> {
621    type Args = ();
622}
623
624impl<'a> FontRead<'a> for Lookup8<'a> {
625    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
626        #[allow(clippy::absurd_extreme_comparisons)]
627        if data.len() < Self::MIN_SIZE {
628            return Err(ReadError::OutOfBounds);
629        }
630        Ok(Self { data })
631    }
632}
633
634/// Trimmed array format. The lookup data is a simple trimmed array
635/// indexed by glyph index.
636#[derive(Clone)]
637pub struct Lookup8<'a> {
638    data: FontData<'a>,
639}
640
641#[allow(clippy::needless_lifetimes)]
642impl<'a> Lookup8<'a> {
643    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
644    basic_table_impls!(impl_the_methods);
645
646    /// Format number is set to 8.
647    pub fn format(&self) -> u16 {
648        let range = self.format_byte_range();
649        self.data.read_at(range.start).ok().unwrap()
650    }
651
652    /// First glyph index included in the trimmed array.
653    pub fn first_glyph(&self) -> u16 {
654        let range = self.first_glyph_byte_range();
655        self.data.read_at(range.start).ok().unwrap()
656    }
657
658    /// Total number of glyphs (equivalent to the last glyph minus the value
659    /// of firstGlyph plus 1).
660    pub fn glyph_count(&self) -> u16 {
661        let range = self.glyph_count_byte_range();
662        self.data.read_at(range.start).ok().unwrap()
663    }
664
665    /// The lookup values (indexed by the glyph index minus the value of
666    /// firstGlyph). Entries in the value array must be two bytes.
667    pub fn value_array(&self) -> &'a [BigEndian<u16>] {
668        let range = self.value_array_byte_range();
669        self.data.read_array(range).ok().unwrap_or_default()
670    }
671
672    pub fn format_byte_range(&self) -> Range<usize> {
673        let start = 0;
674        let end = start + u16::RAW_BYTE_LEN;
675        start..end
676    }
677
678    pub fn first_glyph_byte_range(&self) -> Range<usize> {
679        let start = self.format_byte_range().end;
680        let end = start + u16::RAW_BYTE_LEN;
681        start..end
682    }
683
684    pub fn glyph_count_byte_range(&self) -> Range<usize> {
685        let start = self.first_glyph_byte_range().end;
686        let end = start + u16::RAW_BYTE_LEN;
687        start..end
688    }
689
690    pub fn value_array_byte_range(&self) -> Range<usize> {
691        let glyph_count = self.glyph_count();
692        let start = self.glyph_count_byte_range().end;
693        let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
694        start..end
695    }
696}
697
698impl Format<u16> for Lookup10<'_> {
699    const FORMAT: u16 = 10;
700}
701
702impl<'a> MinByteRange<'a> for Lookup10<'a> {
703    fn min_byte_range(&self) -> Range<usize> {
704        0..self.values_data_byte_range().end
705    }
706    fn min_table_bytes(&self) -> &'a [u8] {
707        let range = self.min_byte_range();
708        self.data.as_bytes().get(range).unwrap_or_default()
709    }
710}
711
712impl ReadArgs for Lookup10<'_> {
713    type Args = ();
714}
715
716impl<'a> FontRead<'a> for Lookup10<'a> {
717    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
718        #[allow(clippy::absurd_extreme_comparisons)]
719        if data.len() < Self::MIN_SIZE {
720            return Err(ReadError::OutOfBounds);
721        }
722        Ok(Self { data })
723    }
724}
725
726/// Trimmed array format. The lookup data is a simple trimmed array
727/// indexed by glyph index.
728#[derive(Clone)]
729pub struct Lookup10<'a> {
730    data: FontData<'a>,
731}
732
733#[allow(clippy::needless_lifetimes)]
734impl<'a> Lookup10<'a> {
735    pub const MIN_SIZE: usize =
736        (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
737    basic_table_impls!(impl_the_methods);
738
739    /// Format number is set to 10.
740    pub fn format(&self) -> u16 {
741        let range = self.format_byte_range();
742        self.data.read_at(range.start).ok().unwrap()
743    }
744
745    /// Size of a lookup unit for this lookup table in bytes. Allowed values
746    /// are 1, 2, 4, and 8.
747    pub fn unit_size(&self) -> u16 {
748        let range = self.unit_size_byte_range();
749        self.data.read_at(range.start).ok().unwrap()
750    }
751
752    /// First glyph index included in the trimmed array.
753    pub fn first_glyph(&self) -> u16 {
754        let range = self.first_glyph_byte_range();
755        self.data.read_at(range.start).ok().unwrap()
756    }
757
758    /// Total number of glyphs (equivalent to the last glyph minus the value
759    /// of firstGlyph plus 1).
760    pub fn glyph_count(&self) -> u16 {
761        let range = self.glyph_count_byte_range();
762        self.data.read_at(range.start).ok().unwrap()
763    }
764
765    /// The lookup values (indexed by the glyph index minus the value of
766    /// firstGlyph).
767    pub fn values_data(&self) -> &'a [u8] {
768        let range = self.values_data_byte_range();
769        self.data.read_array(range).ok().unwrap_or_default()
770    }
771
772    pub fn format_byte_range(&self) -> Range<usize> {
773        let start = 0;
774        let end = start + u16::RAW_BYTE_LEN;
775        start..end
776    }
777
778    pub fn unit_size_byte_range(&self) -> Range<usize> {
779        let start = self.format_byte_range().end;
780        let end = start + u16::RAW_BYTE_LEN;
781        start..end
782    }
783
784    pub fn first_glyph_byte_range(&self) -> Range<usize> {
785        let start = self.unit_size_byte_range().end;
786        let end = start + u16::RAW_BYTE_LEN;
787        start..end
788    }
789
790    pub fn glyph_count_byte_range(&self) -> Range<usize> {
791        let start = self.first_glyph_byte_range().end;
792        let end = start + u16::RAW_BYTE_LEN;
793        start..end
794    }
795
796    pub fn values_data_byte_range(&self) -> Range<usize> {
797        let glyph_count = self.glyph_count();
798        let unit_size = self.unit_size();
799        let start = self.glyph_count_byte_range().end;
800        let end = start
801            + (transforms::add_multiply(glyph_count, 0_usize, unit_size))
802                .saturating_mul(u8::RAW_BYTE_LEN);
803        start..end
804    }
805}
806
807impl<'a> MinByteRange<'a> for StateHeader<'a> {
808    fn min_byte_range(&self) -> Range<usize> {
809        0..self.entry_table_offset_byte_range().end
810    }
811    fn min_table_bytes(&self) -> &'a [u8] {
812        let range = self.min_byte_range();
813        self.data.as_bytes().get(range).unwrap_or_default()
814    }
815}
816
817impl ReadArgs for StateHeader<'_> {
818    type Args = ();
819}
820
821impl<'a> FontRead<'a> for StateHeader<'a> {
822    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
823        #[allow(clippy::absurd_extreme_comparisons)]
824        if data.len() < Self::MIN_SIZE {
825            return Err(ReadError::OutOfBounds);
826        }
827        Ok(Self { data })
828    }
829}
830
831/// Header for a state table.
832#[derive(Clone)]
833pub struct StateHeader<'a> {
834    data: FontData<'a>,
835}
836
837#[allow(clippy::needless_lifetimes)]
838impl<'a> StateHeader<'a> {
839    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
840        + Offset16::RAW_BYTE_LEN
841        + Offset16::RAW_BYTE_LEN
842        + Offset16::RAW_BYTE_LEN);
843    basic_table_impls!(impl_the_methods);
844
845    /// Size of a state, in bytes. The size is limited to 8 bits, although the
846    /// field is 16 bits for alignment.
847    pub fn state_size(&self) -> u16 {
848        let range = self.state_size_byte_range();
849        self.data.read_at(range.start).ok().unwrap()
850    }
851
852    /// Byte offset from the beginning of the state table to the class subtable.
853    pub fn class_table_offset(&self) -> Offset16 {
854        let range = self.class_table_offset_byte_range();
855        self.data.read_at(range.start).ok().unwrap()
856    }
857
858    /// Attempt to resolve [`class_table_offset`][Self::class_table_offset].
859    pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> {
860        let data = self.data;
861        self.class_table_offset().resolve(data)
862    }
863
864    /// Byte offset from the beginning of the state table to the state array.
865    pub fn state_array_offset(&self) -> Offset16 {
866        let range = self.state_array_offset_byte_range();
867        self.data.read_at(range.start).ok().unwrap()
868    }
869
870    /// Attempt to resolve [`state_array_offset`][Self::state_array_offset].
871    pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> {
872        let data = self.data;
873        self.state_array_offset().resolve(data)
874    }
875
876    /// Byte offset from the beginning of the state table to the entry subtable.
877    pub fn entry_table_offset(&self) -> Offset16 {
878        let range = self.entry_table_offset_byte_range();
879        self.data.read_at(range.start).ok().unwrap()
880    }
881
882    /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset].
883    pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
884        let data = self.data;
885        self.entry_table_offset().resolve(data)
886    }
887
888    pub fn state_size_byte_range(&self) -> Range<usize> {
889        let start = 0;
890        let end = start + u16::RAW_BYTE_LEN;
891        start..end
892    }
893
894    pub fn class_table_offset_byte_range(&self) -> Range<usize> {
895        let start = self.state_size_byte_range().end;
896        let end = start + Offset16::RAW_BYTE_LEN;
897        start..end
898    }
899
900    pub fn state_array_offset_byte_range(&self) -> Range<usize> {
901        let start = self.class_table_offset_byte_range().end;
902        let end = start + Offset16::RAW_BYTE_LEN;
903        start..end
904    }
905
906    pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
907        let start = self.state_array_offset_byte_range().end;
908        let end = start + Offset16::RAW_BYTE_LEN;
909        start..end
910    }
911}
912
913const _: () = assert!(FontData::default_data_long_enough(StateHeader::MIN_SIZE));
914
915impl Default for StateHeader<'_> {
916    fn default() -> Self {
917        Self {
918            data: FontData::default_table_data(),
919        }
920    }
921}
922
923impl<'a> MinByteRange<'a> for ClassSubtable<'a> {
924    fn min_byte_range(&self) -> Range<usize> {
925        0..self.class_array_byte_range().end
926    }
927    fn min_table_bytes(&self) -> &'a [u8] {
928        let range = self.min_byte_range();
929        self.data.as_bytes().get(range).unwrap_or_default()
930    }
931}
932
933impl ReadArgs for ClassSubtable<'_> {
934    type Args = ();
935}
936
937impl<'a> FontRead<'a> for ClassSubtable<'a> {
938    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
939        #[allow(clippy::absurd_extreme_comparisons)]
940        if data.len() < Self::MIN_SIZE {
941            return Err(ReadError::OutOfBounds);
942        }
943        Ok(Self { data })
944    }
945}
946
947/// Maps the glyph indexes of your font into classes.
948#[derive(Clone)]
949pub struct ClassSubtable<'a> {
950    data: FontData<'a>,
951}
952
953#[allow(clippy::needless_lifetimes)]
954impl<'a> ClassSubtable<'a> {
955    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
956    basic_table_impls!(impl_the_methods);
957
958    /// Glyph index of the first glyph in the class table.
959    pub fn first_glyph(&self) -> u16 {
960        let range = self.first_glyph_byte_range();
961        self.data.read_at(range.start).ok().unwrap()
962    }
963
964    /// Number of glyphs in class table.
965    pub fn n_glyphs(&self) -> u16 {
966        let range = self.n_glyphs_byte_range();
967        self.data.read_at(range.start).ok().unwrap()
968    }
969
970    /// The class codes (indexed by glyph index minus firstGlyph). Class codes
971    /// range from 0 to the value of stateSize minus 1.
972    pub fn class_array(&self) -> &'a [u8] {
973        let range = self.class_array_byte_range();
974        self.data.read_array(range).ok().unwrap_or_default()
975    }
976
977    pub fn first_glyph_byte_range(&self) -> Range<usize> {
978        let start = 0;
979        let end = start + u16::RAW_BYTE_LEN;
980        start..end
981    }
982
983    pub fn n_glyphs_byte_range(&self) -> Range<usize> {
984        let start = self.first_glyph_byte_range().end;
985        let end = start + u16::RAW_BYTE_LEN;
986        start..end
987    }
988
989    pub fn class_array_byte_range(&self) -> Range<usize> {
990        let n_glyphs = self.n_glyphs();
991        let start = self.n_glyphs_byte_range().end;
992        let end = start + (transforms::to_usize(n_glyphs)).saturating_mul(u8::RAW_BYTE_LEN);
993        start..end
994    }
995}
996
997const _: () = assert!(FontData::default_data_long_enough(ClassSubtable::MIN_SIZE));
998
999impl Default for ClassSubtable<'_> {
1000    fn default() -> Self {
1001        Self {
1002            data: FontData::default_table_data(),
1003        }
1004    }
1005}
1006
1007impl<'a> MinByteRange<'a> for RawBytes<'a> {
1008    fn min_byte_range(&self) -> Range<usize> {
1009        0..self.data_byte_range().end
1010    }
1011    fn min_table_bytes(&self) -> &'a [u8] {
1012        let range = self.min_byte_range();
1013        self.data.as_bytes().get(range).unwrap_or_default()
1014    }
1015}
1016
1017impl ReadArgs for RawBytes<'_> {
1018    type Args = ();
1019}
1020
1021impl<'a> FontRead<'a> for RawBytes<'a> {
1022    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1023        #[allow(clippy::absurd_extreme_comparisons)]
1024        if data.len() < Self::MIN_SIZE {
1025            return Err(ReadError::OutOfBounds);
1026        }
1027        Ok(Self { data })
1028    }
1029}
1030
1031/// Used for the `state_array` and `entry_table` fields in [`StateHeader`].
1032#[derive(Clone)]
1033pub struct RawBytes<'a> {
1034    data: FontData<'a>,
1035}
1036
1037#[allow(clippy::needless_lifetimes)]
1038impl<'a> RawBytes<'a> {
1039    pub const MIN_SIZE: usize = 0;
1040    basic_table_impls!(impl_the_methods);
1041
1042    pub fn data(&self) -> &'a [u8] {
1043        let range = self.data_byte_range();
1044        self.data.read_array(range).ok().unwrap_or_default()
1045    }
1046
1047    pub fn data_byte_range(&self) -> Range<usize> {
1048        let start = 0;
1049        let end =
1050            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1051        start..end
1052    }
1053}
1054
1055#[allow(clippy::absurd_extreme_comparisons)]
1056const _: () = assert!(FontData::default_data_long_enough(RawBytes::MIN_SIZE));
1057
1058impl Default for RawBytes<'_> {
1059    fn default() -> Self {
1060        Self {
1061            data: FontData::default_table_data(),
1062        }
1063    }
1064}
1065
1066impl<'a> MinByteRange<'a> for StxHeader<'a> {
1067    fn min_byte_range(&self) -> Range<usize> {
1068        0..self.entry_table_offset_byte_range().end
1069    }
1070    fn min_table_bytes(&self) -> &'a [u8] {
1071        let range = self.min_byte_range();
1072        self.data.as_bytes().get(range).unwrap_or_default()
1073    }
1074}
1075
1076impl ReadArgs for StxHeader<'_> {
1077    type Args = ();
1078}
1079
1080impl<'a> FontRead<'a> for StxHeader<'a> {
1081    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1082        #[allow(clippy::absurd_extreme_comparisons)]
1083        if data.len() < Self::MIN_SIZE {
1084            return Err(ReadError::OutOfBounds);
1085        }
1086        Ok(Self { data })
1087    }
1088}
1089
1090/// Header for an extended state table.
1091#[derive(Clone)]
1092pub struct StxHeader<'a> {
1093    data: FontData<'a>,
1094}
1095
1096#[allow(clippy::needless_lifetimes)]
1097impl<'a> StxHeader<'a> {
1098    pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN
1099        + Offset32::RAW_BYTE_LEN
1100        + Offset32::RAW_BYTE_LEN
1101        + Offset32::RAW_BYTE_LEN);
1102    basic_table_impls!(impl_the_methods);
1103
1104    /// Number of classes, which is the number of 16-bit entry indices in a single line in the state array.
1105    pub fn n_classes(&self) -> u32 {
1106        let range = self.n_classes_byte_range();
1107        self.data.read_at(range.start).ok().unwrap()
1108    }
1109
1110    /// Byte offset from the beginning of the state table to the class subtable.
1111    pub fn class_table_offset(&self) -> Offset32 {
1112        let range = self.class_table_offset_byte_range();
1113        self.data.read_at(range.start).ok().unwrap()
1114    }
1115
1116    /// Attempt to resolve [`class_table_offset`][Self::class_table_offset].
1117    pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> {
1118        let data = self.data;
1119        self.class_table_offset().resolve(data)
1120    }
1121
1122    /// Byte offset from the beginning of the state table to the state array.
1123    pub fn state_array_offset(&self) -> Offset32 {
1124        let range = self.state_array_offset_byte_range();
1125        self.data.read_at(range.start).ok().unwrap()
1126    }
1127
1128    /// Attempt to resolve [`state_array_offset`][Self::state_array_offset].
1129    pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> {
1130        let data = self.data;
1131        self.state_array_offset().resolve(data)
1132    }
1133
1134    /// Byte offset from the beginning of the state table to the entry subtable.
1135    pub fn entry_table_offset(&self) -> Offset32 {
1136        let range = self.entry_table_offset_byte_range();
1137        self.data.read_at(range.start).ok().unwrap()
1138    }
1139
1140    /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset].
1141    pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1142        let data = self.data;
1143        self.entry_table_offset().resolve(data)
1144    }
1145
1146    pub fn n_classes_byte_range(&self) -> Range<usize> {
1147        let start = 0;
1148        let end = start + u32::RAW_BYTE_LEN;
1149        start..end
1150    }
1151
1152    pub fn class_table_offset_byte_range(&self) -> Range<usize> {
1153        let start = self.n_classes_byte_range().end;
1154        let end = start + Offset32::RAW_BYTE_LEN;
1155        start..end
1156    }
1157
1158    pub fn state_array_offset_byte_range(&self) -> Range<usize> {
1159        let start = self.class_table_offset_byte_range().end;
1160        let end = start + Offset32::RAW_BYTE_LEN;
1161        start..end
1162    }
1163
1164    pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
1165        let start = self.state_array_offset_byte_range().end;
1166        let end = start + Offset32::RAW_BYTE_LEN;
1167        start..end
1168    }
1169}
1170
1171const _: () = assert!(FontData::default_data_long_enough(StxHeader::MIN_SIZE));
1172
1173impl Default for StxHeader<'_> {
1174    fn default() -> Self {
1175        Self {
1176            data: FontData::default_table_data(),
1177        }
1178    }
1179}
1180
1181impl<'a> MinByteRange<'a> for RawWords<'a> {
1182    fn min_byte_range(&self) -> Range<usize> {
1183        0..self.data_byte_range().end
1184    }
1185    fn min_table_bytes(&self) -> &'a [u8] {
1186        let range = self.min_byte_range();
1187        self.data.as_bytes().get(range).unwrap_or_default()
1188    }
1189}
1190
1191impl ReadArgs for RawWords<'_> {
1192    type Args = ();
1193}
1194
1195impl<'a> FontRead<'a> for RawWords<'a> {
1196    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1197        #[allow(clippy::absurd_extreme_comparisons)]
1198        if data.len() < Self::MIN_SIZE {
1199            return Err(ReadError::OutOfBounds);
1200        }
1201        Ok(Self { data })
1202    }
1203}
1204
1205/// Used for the `state_array` in [`StxHeader`].
1206#[derive(Clone)]
1207pub struct RawWords<'a> {
1208    data: FontData<'a>,
1209}
1210
1211#[allow(clippy::needless_lifetimes)]
1212impl<'a> RawWords<'a> {
1213    pub const MIN_SIZE: usize = 0;
1214    basic_table_impls!(impl_the_methods);
1215
1216    pub fn data(&self) -> &'a [BigEndian<u16>] {
1217        let range = self.data_byte_range();
1218        self.data.read_array(range).ok().unwrap_or_default()
1219    }
1220
1221    pub fn data_byte_range(&self) -> Range<usize> {
1222        let start = 0;
1223        let end =
1224            start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
1225        start..end
1226    }
1227}
1228
1229#[allow(clippy::absurd_extreme_comparisons)]
1230const _: () = assert!(FontData::default_data_long_enough(RawWords::MIN_SIZE));
1231
1232impl Default for RawWords<'_> {
1233    fn default() -> Self {
1234        Self {
1235            data: FontData::default_table_data(),
1236        }
1237    }
1238}