1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[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 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 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#[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 pub fn format(&self) -> u16 {
136 let range = self.format_byte_range();
137 self.data.read_at(range.start).ok().unwrap()
138 }
139
140 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#[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 pub fn format(&self) -> u16 {
218 let range = self.format_byte_range();
219 self.data.read_at(range.start).ok().unwrap()
220 }
221
222 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 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 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 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 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 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#[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 pub fn format(&self) -> u16 {
353 let range = self.format_byte_range();
354 self.data.read_at(range.start).ok().unwrap()
355 }
356
357 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 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 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 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 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 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#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
440#[repr(C)]
441#[repr(packed)]
442pub struct LookupSegment4 {
443 pub last_glyph: BigEndian<u16>,
445 pub first_glyph: BigEndian<u16>,
447 pub value_offset: BigEndian<u16>,
449}
450
451impl LookupSegment4 {
452 pub fn last_glyph(&self) -> u16 {
454 self.last_glyph.get()
455 }
456
457 pub fn first_glyph(&self) -> u16 {
459 self.first_glyph.get()
460 }
461
462 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#[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 pub fn format(&self) -> u16 {
519 let range = self.format_byte_range();
520 self.data.read_at(range.start).ok().unwrap()
521 }
522
523 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 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 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 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 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 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#[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 pub fn format(&self) -> u16 {
648 let range = self.format_byte_range();
649 self.data.read_at(range.start).ok().unwrap()
650 }
651
652 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 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 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#[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 pub fn format(&self) -> u16 {
741 let range = self.format_byte_range();
742 self.data.read_at(range.start).ok().unwrap()
743 }
744
745 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 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 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 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#[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 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 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 pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> {
860 let data = self.data;
861 self.class_table_offset().resolve(data)
862 }
863
864 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 pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> {
872 let data = self.data;
873 self.state_array_offset().resolve(data)
874 }
875
876 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 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#[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 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 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 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#[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#[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 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 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 pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> {
1118 let data = self.data;
1119 self.class_table_offset().resolve(data)
1120 }
1121
1122 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 pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> {
1130 let data = self.data;
1131 self.state_array_offset().resolve(data)
1132 }
1133
1134 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 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#[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}