1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for ScriptList<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.script_records_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.offset_data().as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl ReadArgs for ScriptList<'_> {
19 type Args = ();
20}
21
22impl<'a> FontRead<'a> for ScriptList<'a> {
23 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24 #[allow(clippy::absurd_extreme_comparisons)]
25 if data.len() < Self::MIN_SIZE {
26 return Err(ReadError::OutOfBounds);
27 }
28 let Some(data) = TableDataRef::new(data.as_bytes()) else {
29 return Err(ReadError::OutOfBounds);
30 };
31 Ok(Self { data })
32 }
33}
34
35#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
37#[repr(C, packed)]
38#[doc(hidden)]
39pub struct ScriptListFixedHeader {
40 pub script_count: BigEndian<u16>,
41}
42
43#[allow(clippy::absurd_extreme_comparisons)]
44const _: () = assert!(std::mem::size_of::<ScriptListFixedHeader>() <= ScriptList::MIN_SIZE);
45
46#[derive(Clone)]
48pub struct ScriptList<'a> {
49 data: TableDataRef<'a, ScriptListFixedHeader>,
50}
51
52#[allow(clippy::needless_lifetimes)]
53impl<'a> ScriptList<'a> {
54 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
55 basic_table_impls!(impl_the_methods);
56
57 pub fn script_count(&self) -> u16 {
59 self.data.header().script_count.get()
60 }
61
62 pub fn script_records(&self) -> &'a [ScriptRecord] {
64 let range = self.script_records_byte_range();
65 self.offset_data()
66 .read_array(range)
67 .ok()
68 .unwrap_or_default()
69 }
70
71 pub fn script_count_byte_range(&self) -> Range<usize> {
72 let start = 0;
73 let end = start + u16::RAW_BYTE_LEN;
74 start..end
75 }
76
77 pub fn script_records_byte_range(&self) -> Range<usize> {
78 let script_count = self.script_count();
79 let start = self.script_count_byte_range().end;
80 let end =
81 start + (transforms::to_usize(script_count)).saturating_mul(ScriptRecord::RAW_BYTE_LEN);
82 start..end
83 }
84}
85
86const _: () = assert!(FontData::default_data_long_enough(ScriptList::MIN_SIZE));
87
88impl Default for ScriptList<'_> {
89 fn default() -> Self {
90 Self {
91 data: TableDataRef::new(FontData::default_table_data().as_bytes())
92 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
93 }
94 }
95}
96
97#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
99#[repr(C)]
100#[repr(packed)]
101pub struct ScriptRecord {
102 pub script_tag: BigEndian<Tag>,
104 pub script_offset: BigEndian<Offset16>,
106}
107
108impl ScriptRecord {
109 pub fn script_tag(&self) -> Tag {
111 self.script_tag.get()
112 }
113
114 pub fn script_offset(&self) -> Offset16 {
116 self.script_offset.get()
117 }
118
119 pub fn script<'a>(&self, data: FontData<'a>) -> Result<Script<'a>, ReadError> {
124 self.script_offset().resolve(data)
125 }
126}
127
128impl FixedSize for ScriptRecord {
129 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
130}
131
132impl<'a> MinByteRange<'a> for Script<'a> {
133 fn min_byte_range(&self) -> Range<usize> {
134 0..self.lang_sys_records_byte_range().end
135 }
136 fn min_table_bytes(&self) -> &'a [u8] {
137 let range = self.min_byte_range();
138 self.offset_data().as_bytes().get(range).unwrap_or_default()
139 }
140}
141
142impl ReadArgs for Script<'_> {
143 type Args = ();
144}
145
146impl<'a> FontRead<'a> for Script<'a> {
147 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
148 #[allow(clippy::absurd_extreme_comparisons)]
149 if data.len() < Self::MIN_SIZE {
150 return Err(ReadError::OutOfBounds);
151 }
152 let Some(data) = TableDataRef::new(data.as_bytes()) else {
153 return Err(ReadError::OutOfBounds);
154 };
155 Ok(Self { data })
156 }
157}
158
159#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
161#[repr(C, packed)]
162#[doc(hidden)]
163pub struct ScriptFixedHeader {
164 pub default_lang_sys_offset: BigEndian<Nullable<Offset16>>,
165 pub lang_sys_count: BigEndian<u16>,
166}
167
168#[allow(clippy::absurd_extreme_comparisons)]
169const _: () = assert!(std::mem::size_of::<ScriptFixedHeader>() <= Script::MIN_SIZE);
170
171#[derive(Clone)]
173pub struct Script<'a> {
174 data: TableDataRef<'a, ScriptFixedHeader>,
175}
176
177#[allow(clippy::needless_lifetimes)]
178impl<'a> Script<'a> {
179 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
180 basic_table_impls!(impl_the_methods);
181
182 pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
185 self.data.header().default_lang_sys_offset.get()
186 }
187
188 pub fn default_lang_sys(&self) -> Option<Result<LangSys<'a>, ReadError>> {
190 let data = self.offset_data();
191 self.default_lang_sys_offset().resolve(data)
192 }
193
194 pub fn lang_sys_count(&self) -> u16 {
197 self.data.header().lang_sys_count.get()
198 }
199
200 pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
202 let range = self.lang_sys_records_byte_range();
203 self.offset_data()
204 .read_array(range)
205 .ok()
206 .unwrap_or_default()
207 }
208
209 pub fn default_lang_sys_offset_byte_range(&self) -> Range<usize> {
210 let start = 0;
211 let end = start + Offset16::RAW_BYTE_LEN;
212 start..end
213 }
214
215 pub fn lang_sys_count_byte_range(&self) -> Range<usize> {
216 let start = self.default_lang_sys_offset_byte_range().end;
217 let end = start + u16::RAW_BYTE_LEN;
218 start..end
219 }
220
221 pub fn lang_sys_records_byte_range(&self) -> Range<usize> {
222 let lang_sys_count = self.lang_sys_count();
223 let start = self.lang_sys_count_byte_range().end;
224 let end = start
225 + (transforms::to_usize(lang_sys_count)).saturating_mul(LangSysRecord::RAW_BYTE_LEN);
226 start..end
227 }
228}
229
230const _: () = assert!(FontData::default_data_long_enough(Script::MIN_SIZE));
231
232impl Default for Script<'_> {
233 fn default() -> Self {
234 Self {
235 data: TableDataRef::new(FontData::default_table_data().as_bytes())
236 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
237 }
238 }
239}
240
241#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
242#[repr(C)]
243#[repr(packed)]
244pub struct LangSysRecord {
245 pub lang_sys_tag: BigEndian<Tag>,
247 pub lang_sys_offset: BigEndian<Offset16>,
249}
250
251impl LangSysRecord {
252 pub fn lang_sys_tag(&self) -> Tag {
254 self.lang_sys_tag.get()
255 }
256
257 pub fn lang_sys_offset(&self) -> Offset16 {
259 self.lang_sys_offset.get()
260 }
261
262 pub fn lang_sys<'a>(&self, data: FontData<'a>) -> Result<LangSys<'a>, ReadError> {
267 self.lang_sys_offset().resolve(data)
268 }
269}
270
271impl FixedSize for LangSysRecord {
272 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
273}
274
275impl<'a> MinByteRange<'a> for LangSys<'a> {
276 fn min_byte_range(&self) -> Range<usize> {
277 0..self.feature_indices_byte_range().end
278 }
279 fn min_table_bytes(&self) -> &'a [u8] {
280 let range = self.min_byte_range();
281 self.offset_data().as_bytes().get(range).unwrap_or_default()
282 }
283}
284
285impl ReadArgs for LangSys<'_> {
286 type Args = ();
287}
288
289impl<'a> FontRead<'a> for LangSys<'a> {
290 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
291 #[allow(clippy::absurd_extreme_comparisons)]
292 if data.len() < Self::MIN_SIZE {
293 return Err(ReadError::OutOfBounds);
294 }
295 let Some(data) = TableDataRef::new(data.as_bytes()) else {
296 return Err(ReadError::OutOfBounds);
297 };
298 Ok(Self { data })
299 }
300}
301
302#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
304#[repr(C, packed)]
305#[doc(hidden)]
306pub struct LangSysFixedHeader {
307 pub lookup_order_offset: BigEndian<u16>,
308 pub required_feature_index: BigEndian<u16>,
309 pub feature_index_count: BigEndian<u16>,
310}
311
312#[allow(clippy::absurd_extreme_comparisons)]
313const _: () = assert!(std::mem::size_of::<LangSysFixedHeader>() <= LangSys::MIN_SIZE);
314
315#[derive(Clone)]
317pub struct LangSys<'a> {
318 data: TableDataRef<'a, LangSysFixedHeader>,
319}
320
321#[allow(clippy::needless_lifetimes)]
322impl<'a> LangSys<'a> {
323 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
324 basic_table_impls!(impl_the_methods);
325
326 pub fn required_feature_index(&self) -> u16 {
329 self.data.header().required_feature_index.get()
330 }
331
332 pub fn feature_index_count(&self) -> u16 {
335 self.data.header().feature_index_count.get()
336 }
337
338 pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
340 let range = self.feature_indices_byte_range();
341 self.offset_data()
342 .read_array(range)
343 .ok()
344 .unwrap_or_default()
345 }
346
347 pub fn lookup_order_offset_byte_range(&self) -> Range<usize> {
348 let start = 0;
349 let end = start + u16::RAW_BYTE_LEN;
350 start..end
351 }
352
353 pub fn required_feature_index_byte_range(&self) -> Range<usize> {
354 let start = self.lookup_order_offset_byte_range().end;
355 let end = start + u16::RAW_BYTE_LEN;
356 start..end
357 }
358
359 pub fn feature_index_count_byte_range(&self) -> Range<usize> {
360 let start = self.required_feature_index_byte_range().end;
361 let end = start + u16::RAW_BYTE_LEN;
362 start..end
363 }
364
365 pub fn feature_indices_byte_range(&self) -> Range<usize> {
366 let feature_index_count = self.feature_index_count();
367 let start = self.feature_index_count_byte_range().end;
368 let end =
369 start + (transforms::to_usize(feature_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
370 start..end
371 }
372}
373
374const _: () = assert!(FontData::default_data_long_enough(LangSys::MIN_SIZE));
375
376impl Default for LangSys<'_> {
377 fn default() -> Self {
378 Self {
379 data: TableDataRef::new(FontData::default_table_data().as_bytes())
380 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
381 }
382 }
383}
384
385impl<'a> MinByteRange<'a> for FeatureList<'a> {
386 fn min_byte_range(&self) -> Range<usize> {
387 0..self.feature_records_byte_range().end
388 }
389 fn min_table_bytes(&self) -> &'a [u8] {
390 let range = self.min_byte_range();
391 self.offset_data().as_bytes().get(range).unwrap_or_default()
392 }
393}
394
395impl ReadArgs for FeatureList<'_> {
396 type Args = ();
397}
398
399impl<'a> FontRead<'a> for FeatureList<'a> {
400 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
401 #[allow(clippy::absurd_extreme_comparisons)]
402 if data.len() < Self::MIN_SIZE {
403 return Err(ReadError::OutOfBounds);
404 }
405 let Some(data) = TableDataRef::new(data.as_bytes()) else {
406 return Err(ReadError::OutOfBounds);
407 };
408 Ok(Self { data })
409 }
410}
411
412#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
414#[repr(C, packed)]
415#[doc(hidden)]
416pub struct FeatureListFixedHeader {
417 pub feature_count: BigEndian<u16>,
418}
419
420#[allow(clippy::absurd_extreme_comparisons)]
421const _: () = assert!(std::mem::size_of::<FeatureListFixedHeader>() <= FeatureList::MIN_SIZE);
422
423#[derive(Clone)]
425pub struct FeatureList<'a> {
426 data: TableDataRef<'a, FeatureListFixedHeader>,
427}
428
429#[allow(clippy::needless_lifetimes)]
430impl<'a> FeatureList<'a> {
431 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
432 basic_table_impls!(impl_the_methods);
433
434 pub fn feature_count(&self) -> u16 {
436 self.data.header().feature_count.get()
437 }
438
439 pub fn feature_records(&self) -> &'a [FeatureRecord] {
442 let range = self.feature_records_byte_range();
443 self.offset_data()
444 .read_array(range)
445 .ok()
446 .unwrap_or_default()
447 }
448
449 pub fn feature_count_byte_range(&self) -> Range<usize> {
450 let start = 0;
451 let end = start + u16::RAW_BYTE_LEN;
452 start..end
453 }
454
455 pub fn feature_records_byte_range(&self) -> Range<usize> {
456 let feature_count = self.feature_count();
457 let start = self.feature_count_byte_range().end;
458 let end = start
459 + (transforms::to_usize(feature_count)).saturating_mul(FeatureRecord::RAW_BYTE_LEN);
460 start..end
461 }
462}
463
464const _: () = assert!(FontData::default_data_long_enough(FeatureList::MIN_SIZE));
465
466impl Default for FeatureList<'_> {
467 fn default() -> Self {
468 Self {
469 data: TableDataRef::new(FontData::default_table_data().as_bytes())
470 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
471 }
472 }
473}
474
475#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
477#[repr(C)]
478#[repr(packed)]
479pub struct FeatureRecord {
480 pub feature_tag: BigEndian<Tag>,
482 pub feature_offset: BigEndian<Offset16>,
484}
485
486impl FeatureRecord {
487 pub fn feature_tag(&self) -> Tag {
489 self.feature_tag.get()
490 }
491
492 pub fn feature_offset(&self) -> Offset16 {
494 self.feature_offset.get()
495 }
496
497 pub fn feature<'a>(&self, data: FontData<'a>) -> Result<Feature<'a>, ReadError> {
502 let args = self.feature_tag();
503 self.feature_offset().resolve_with_args(data, args)
504 }
505}
506
507impl FixedSize for FeatureRecord {
508 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
509}
510
511impl<'a> MinByteRange<'a> for Feature<'a> {
512 fn min_byte_range(&self) -> Range<usize> {
513 0..self.lookup_list_indices_byte_range().end
514 }
515 fn min_table_bytes(&self) -> &'a [u8] {
516 let range = self.min_byte_range();
517 self.offset_data().as_bytes().get(range).unwrap_or_default()
518 }
519}
520
521impl ReadArgs for Feature<'_> {
522 type Args = Tag;
523}
524
525impl<'a> FontRead<'a> for Feature<'a> {
526 fn read_with_args(data: FontData<'a>, args: Tag) -> Result<Self, ReadError> {
527 let feature_tag = args;
528
529 #[allow(clippy::absurd_extreme_comparisons)]
530 if data.len() < Self::MIN_SIZE {
531 return Err(ReadError::OutOfBounds);
532 }
533 let Some(data) = TableDataRef::new(data.as_bytes()) else {
534 return Err(ReadError::OutOfBounds);
535 };
536 Ok(Self { data, feature_tag })
537 }
538}
539
540impl<'a> Feature<'a> {
541 pub fn read(data: FontData<'a>, feature_tag: Tag) -> Result<Self, ReadError> {
546 let args = feature_tag;
547 Self::read_with_args(data, args)
548 }
549}
550
551#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
553#[repr(C, packed)]
554#[doc(hidden)]
555pub struct FeatureFixedHeader {
556 pub feature_params_offset: BigEndian<Nullable<Offset16>>,
557 pub lookup_index_count: BigEndian<u16>,
558}
559
560#[allow(clippy::absurd_extreme_comparisons)]
561const _: () = assert!(std::mem::size_of::<FeatureFixedHeader>() <= Feature::MIN_SIZE);
562
563#[derive(Clone)]
565pub struct Feature<'a> {
566 data: TableDataRef<'a, FeatureFixedHeader>,
567 feature_tag: Tag,
568}
569
570#[allow(clippy::needless_lifetimes)]
571impl<'a> Feature<'a> {
572 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
573 basic_table_impls!(impl_the_methods);
574
575 pub fn feature_params_offset(&self) -> Nullable<Offset16> {
577 self.data.header().feature_params_offset.get()
578 }
579
580 pub fn feature_params(&self) -> Option<Result<FeatureParams<'a>, ReadError>> {
582 let data = self.offset_data();
583 let args = self.feature_tag();
584 self.feature_params_offset().resolve_with_args(data, args)
585 }
586
587 pub fn lookup_index_count(&self) -> u16 {
589 self.data.header().lookup_index_count.get()
590 }
591
592 pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
595 let range = self.lookup_list_indices_byte_range();
596 self.offset_data()
597 .read_array(range)
598 .ok()
599 .unwrap_or_default()
600 }
601
602 pub(crate) fn feature_tag(&self) -> Tag {
603 self.feature_tag
604 }
605
606 pub fn feature_params_offset_byte_range(&self) -> Range<usize> {
607 let start = 0;
608 let end = start + Offset16::RAW_BYTE_LEN;
609 start..end
610 }
611
612 pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
613 let start = self.feature_params_offset_byte_range().end;
614 let end = start + u16::RAW_BYTE_LEN;
615 start..end
616 }
617
618 pub fn lookup_list_indices_byte_range(&self) -> Range<usize> {
619 let lookup_index_count = self.lookup_index_count();
620 let start = self.lookup_index_count_byte_range().end;
621 let end =
622 start + (transforms::to_usize(lookup_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
623 start..end
624 }
625}
626
627const _: () = assert!(FontData::default_data_long_enough(Feature::MIN_SIZE));
628
629impl Default for Feature<'_> {
630 fn default() -> Self {
631 Self {
632 data: TableDataRef::new(FontData::default_table_data().as_bytes())
633 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
634 feature_tag: Default::default(),
635 }
636 }
637}
638
639impl<'a, T> MinByteRange<'a> for LookupList<'a, T> {
640 fn min_byte_range(&self) -> Range<usize> {
641 0..self.lookup_offsets_byte_range().end
642 }
643 fn min_table_bytes(&self) -> &'a [u8] {
644 let range = self.min_byte_range();
645 self.offset_data().as_bytes().get(range).unwrap_or_default()
646 }
647}
648
649impl<T> ReadArgs for LookupList<'_, T> {
650 type Args = ();
651}
652
653impl<'a, T> FontRead<'a> for LookupList<'a, T> {
654 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
655 #[allow(clippy::absurd_extreme_comparisons)]
656 if data.len() < Self::MIN_SIZE {
657 return Err(ReadError::OutOfBounds);
658 }
659 let Some(data) = TableDataRef::new(data.as_bytes()) else {
660 return Err(ReadError::OutOfBounds);
661 };
662 Ok(Self {
663 data,
664 offset_type: std::marker::PhantomData,
665 })
666 }
667}
668
669impl<'a, T> LookupList<'a, T> {
670 #[allow(dead_code)]
671 pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
673 LookupList {
674 data: self.data,
675 offset_type: std::marker::PhantomData,
676 }
677 }
678}
679
680#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
682#[repr(C, packed)]
683#[doc(hidden)]
684pub struct LookupListFixedHeader {
685 pub lookup_count: BigEndian<u16>,
686}
687
688#[allow(clippy::absurd_extreme_comparisons)]
689const _: () = assert!(std::mem::size_of::<LookupListFixedHeader>() <= LookupList::<()>::MIN_SIZE);
690
691#[derive(Clone)]
693pub struct LookupList<'a, T = ()> {
694 data: TableDataRef<'a, LookupListFixedHeader>,
695 offset_type: std::marker::PhantomData<*const T>,
696}
697
698#[allow(clippy::needless_lifetimes)]
699impl<'a, T> LookupList<'a, T> {
700 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
701 basic_table_impls!(impl_the_methods);
702
703 pub fn lookup_count(&self) -> u16 {
705 self.data.header().lookup_count.get()
706 }
707
708 pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
711 let range = self.lookup_offsets_byte_range();
712 self.offset_data()
713 .read_array(range)
714 .ok()
715 .unwrap_or_default()
716 }
717
718 pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset16>
720 where
721 T: FontRead<'a, Args = ()>,
722 {
723 let data = self.offset_data();
724 let offsets = self.lookup_offsets();
725 ArrayOfOffsets::new(offsets, data, ())
726 }
727
728 pub fn lookup_count_byte_range(&self) -> Range<usize> {
729 let start = 0;
730 let end = start + u16::RAW_BYTE_LEN;
731 start..end
732 }
733
734 pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
735 let lookup_count = self.lookup_count();
736 let start = self.lookup_count_byte_range().end;
737 let end =
738 start + (transforms::to_usize(lookup_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
739 start..end
740 }
741}
742
743const _: () = assert!(FontData::default_data_long_enough(
744 LookupList::<()>::MIN_SIZE
745));
746
747impl<T> Default for LookupList<'_, T> {
748 fn default() -> Self {
749 Self {
750 data: TableDataRef::new(FontData::default_table_data().as_bytes())
751 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
752 offset_type: std::marker::PhantomData,
753 }
754 }
755}
756
757impl Discriminant for Lookup<'_, ()> {
758 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
759 data.read_at(0)
760 }
761}
762
763impl<'a, T> MinByteRange<'a> for Lookup<'a, T> {
764 fn min_byte_range(&self) -> Range<usize> {
765 0..self.subtable_offsets_byte_range().end
766 }
767 fn min_table_bytes(&self) -> &'a [u8] {
768 let range = self.min_byte_range();
769 self.offset_data().as_bytes().get(range).unwrap_or_default()
770 }
771}
772
773impl<T> ReadArgs for Lookup<'_, T> {
774 type Args = ();
775}
776
777impl<'a, T> FontRead<'a> for Lookup<'a, T> {
778 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
779 #[allow(clippy::absurd_extreme_comparisons)]
780 if data.len() < Self::MIN_SIZE {
781 return Err(ReadError::OutOfBounds);
782 }
783 let Some(data) = TableDataRef::new(data.as_bytes()) else {
784 return Err(ReadError::OutOfBounds);
785 };
786 Ok(Self {
787 data,
788 offset_type: std::marker::PhantomData,
789 })
790 }
791}
792
793impl<'a, T> Lookup<'a, T> {
794 #[allow(dead_code)]
795 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
797 Lookup {
798 data: self.data,
799 offset_type: std::marker::PhantomData,
800 }
801 }
802}
803
804#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
806#[repr(C, packed)]
807#[doc(hidden)]
808pub struct LookupFixedHeader {
809 pub lookup_type: BigEndian<u16>,
810 pub lookup_flag: BigEndian<LookupFlag>,
811 pub sub_table_count: BigEndian<u16>,
812}
813
814#[allow(clippy::absurd_extreme_comparisons)]
815const _: () = assert!(std::mem::size_of::<LookupFixedHeader>() <= Lookup::<()>::MIN_SIZE);
816
817#[derive(Clone)]
819pub struct Lookup<'a, T = ()> {
820 data: TableDataRef<'a, LookupFixedHeader>,
821 offset_type: std::marker::PhantomData<*const T>,
822}
823
824#[allow(clippy::needless_lifetimes)]
825impl<'a, T> Lookup<'a, T> {
826 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + LookupFlag::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
827 basic_table_impls!(impl_the_methods);
828
829 pub fn lookup_type(&self) -> u16 {
831 self.data.header().lookup_type.get()
832 }
833
834 pub fn lookup_flag(&self) -> LookupFlag {
836 self.data.header().lookup_flag.get()
837 }
838
839 pub fn sub_table_count(&self) -> u16 {
841 self.data.header().sub_table_count.get()
842 }
843
844 pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
847 let range = self.subtable_offsets_byte_range();
848 self.offset_data()
849 .read_array(range)
850 .ok()
851 .unwrap_or_default()
852 }
853
854 pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
856 where
857 T: FontRead<'a, Args = ()>,
858 {
859 let data = self.offset_data();
860 let offsets = self.subtable_offsets();
861 ArrayOfOffsets::new(offsets, data, ())
862 }
863
864 pub fn mark_filtering_set(&self) -> Option<u16> {
868 let range = self.mark_filtering_set_byte_range();
869 (!range.is_empty())
870 .then(|| self.offset_data().read_at(range.start).ok())
871 .flatten()
872 }
873
874 pub fn lookup_type_byte_range(&self) -> Range<usize> {
875 let start = 0;
876 let end = start + u16::RAW_BYTE_LEN;
877 start..end
878 }
879
880 pub fn lookup_flag_byte_range(&self) -> Range<usize> {
881 let start = self.lookup_type_byte_range().end;
882 let end = start + LookupFlag::RAW_BYTE_LEN;
883 start..end
884 }
885
886 pub fn sub_table_count_byte_range(&self) -> Range<usize> {
887 let start = self.lookup_flag_byte_range().end;
888 let end = start + u16::RAW_BYTE_LEN;
889 start..end
890 }
891
892 pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
893 let sub_table_count = self.sub_table_count();
894 let start = self.sub_table_count_byte_range().end;
895 let end =
896 start + (transforms::to_usize(sub_table_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
897 start..end
898 }
899
900 pub fn mark_filtering_set_byte_range(&self) -> Range<usize> {
901 let start = self.subtable_offsets_byte_range().end;
902 let end = if self
903 .lookup_flag()
904 .contains(LookupFlag::USE_MARK_FILTERING_SET)
905 {
906 start + u16::RAW_BYTE_LEN
907 } else {
908 start
909 };
910 start..end
911 }
912}
913
914const _: () = assert!(FontData::default_data_long_enough(Lookup::<()>::MIN_SIZE));
915
916impl<T> Default for Lookup<'_, T> {
917 fn default() -> Self {
918 Self {
919 data: TableDataRef::new(FontData::default_table_data().as_bytes())
920 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
921 offset_type: std::marker::PhantomData,
922 }
923 }
924}
925
926impl Format<u16> for CoverageFormat1<'_> {
927 const FORMAT: u16 = 1;
928}
929
930impl<'a> MinByteRange<'a> for CoverageFormat1<'a> {
931 fn min_byte_range(&self) -> Range<usize> {
932 0..self.glyph_array_byte_range().end
933 }
934 fn min_table_bytes(&self) -> &'a [u8] {
935 let range = self.min_byte_range();
936 self.offset_data().as_bytes().get(range).unwrap_or_default()
937 }
938}
939
940impl ReadArgs for CoverageFormat1<'_> {
941 type Args = ();
942}
943
944impl<'a> FontRead<'a> for CoverageFormat1<'a> {
945 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
946 #[allow(clippy::absurd_extreme_comparisons)]
947 if data.len() < Self::MIN_SIZE {
948 return Err(ReadError::OutOfBounds);
949 }
950 let Some(data) = TableDataRef::new(data.as_bytes()) else {
951 return Err(ReadError::OutOfBounds);
952 };
953 Ok(Self { data })
954 }
955}
956
957#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
959#[repr(C, packed)]
960#[doc(hidden)]
961pub struct CoverageFormat1FixedHeader {
962 pub coverage_format: BigEndian<u16>,
963 pub glyph_count: BigEndian<u16>,
964}
965
966#[allow(clippy::absurd_extreme_comparisons)]
967const _: () =
968 assert!(std::mem::size_of::<CoverageFormat1FixedHeader>() <= CoverageFormat1::MIN_SIZE);
969
970#[derive(Clone)]
972pub struct CoverageFormat1<'a> {
973 data: TableDataRef<'a, CoverageFormat1FixedHeader>,
974}
975
976#[allow(clippy::needless_lifetimes)]
977impl<'a> CoverageFormat1<'a> {
978 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
979 basic_table_impls!(impl_the_methods);
980
981 pub fn coverage_format(&self) -> u16 {
983 self.data.header().coverage_format.get()
984 }
985
986 pub fn glyph_count(&self) -> u16 {
988 self.data.header().glyph_count.get()
989 }
990
991 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
993 let range = self.glyph_array_byte_range();
994 self.offset_data()
995 .read_array(range)
996 .ok()
997 .unwrap_or_default()
998 }
999
1000 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1001 let start = 0;
1002 let end = start + u16::RAW_BYTE_LEN;
1003 start..end
1004 }
1005
1006 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1007 let start = self.coverage_format_byte_range().end;
1008 let end = start + u16::RAW_BYTE_LEN;
1009 start..end
1010 }
1011
1012 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1013 let glyph_count = self.glyph_count();
1014 let start = self.glyph_count_byte_range().end;
1015 let end =
1016 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1017 start..end
1018 }
1019}
1020
1021const _: () = assert!(FontData::default_data_long_enough(
1022 CoverageFormat1::MIN_SIZE
1023));
1024
1025impl Default for CoverageFormat1<'_> {
1026 fn default() -> Self {
1027 Self {
1028 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1029 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1030 }
1031 }
1032}
1033
1034impl Format<u16> for CoverageFormat2<'_> {
1035 const FORMAT: u16 = 2;
1036}
1037
1038impl<'a> MinByteRange<'a> for CoverageFormat2<'a> {
1039 fn min_byte_range(&self) -> Range<usize> {
1040 0..self.range_records_byte_range().end
1041 }
1042 fn min_table_bytes(&self) -> &'a [u8] {
1043 let range = self.min_byte_range();
1044 self.offset_data().as_bytes().get(range).unwrap_or_default()
1045 }
1046}
1047
1048impl ReadArgs for CoverageFormat2<'_> {
1049 type Args = ();
1050}
1051
1052impl<'a> FontRead<'a> for CoverageFormat2<'a> {
1053 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1054 #[allow(clippy::absurd_extreme_comparisons)]
1055 if data.len() < Self::MIN_SIZE {
1056 return Err(ReadError::OutOfBounds);
1057 }
1058 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1059 return Err(ReadError::OutOfBounds);
1060 };
1061 Ok(Self { data })
1062 }
1063}
1064
1065#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1067#[repr(C, packed)]
1068#[doc(hidden)]
1069pub struct CoverageFormat2FixedHeader {
1070 pub coverage_format: BigEndian<u16>,
1071 pub range_count: BigEndian<u16>,
1072}
1073
1074#[allow(clippy::absurd_extreme_comparisons)]
1075const _: () =
1076 assert!(std::mem::size_of::<CoverageFormat2FixedHeader>() <= CoverageFormat2::MIN_SIZE);
1077
1078#[derive(Clone)]
1080pub struct CoverageFormat2<'a> {
1081 data: TableDataRef<'a, CoverageFormat2FixedHeader>,
1082}
1083
1084#[allow(clippy::needless_lifetimes)]
1085impl<'a> CoverageFormat2<'a> {
1086 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1087 basic_table_impls!(impl_the_methods);
1088
1089 pub fn coverage_format(&self) -> u16 {
1091 self.data.header().coverage_format.get()
1092 }
1093
1094 pub fn range_count(&self) -> u16 {
1096 self.data.header().range_count.get()
1097 }
1098
1099 pub fn range_records(&self) -> &'a [RangeRecord] {
1101 let range = self.range_records_byte_range();
1102 self.offset_data()
1103 .read_array(range)
1104 .ok()
1105 .unwrap_or_default()
1106 }
1107
1108 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1109 let start = 0;
1110 let end = start + u16::RAW_BYTE_LEN;
1111 start..end
1112 }
1113
1114 pub fn range_count_byte_range(&self) -> Range<usize> {
1115 let start = self.coverage_format_byte_range().end;
1116 let end = start + u16::RAW_BYTE_LEN;
1117 start..end
1118 }
1119
1120 pub fn range_records_byte_range(&self) -> Range<usize> {
1121 let range_count = self.range_count();
1122 let start = self.range_count_byte_range().end;
1123 let end =
1124 start + (transforms::to_usize(range_count)).saturating_mul(RangeRecord::RAW_BYTE_LEN);
1125 start..end
1126 }
1127}
1128
1129#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1131#[repr(C)]
1132#[repr(packed)]
1133pub struct RangeRecord {
1134 pub start_glyph_id: BigEndian<GlyphId16>,
1136 pub end_glyph_id: BigEndian<GlyphId16>,
1138 pub start_coverage_index: BigEndian<u16>,
1140}
1141
1142impl RangeRecord {
1143 pub fn start_glyph_id(&self) -> GlyphId16 {
1145 self.start_glyph_id.get()
1146 }
1147
1148 pub fn end_glyph_id(&self) -> GlyphId16 {
1150 self.end_glyph_id.get()
1151 }
1152
1153 pub fn start_coverage_index(&self) -> u16 {
1155 self.start_coverage_index.get()
1156 }
1157}
1158
1159impl FixedSize for RangeRecord {
1160 const RAW_BYTE_LEN: usize =
1161 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1162}
1163
1164#[derive(Clone)]
1166pub enum CoverageTable<'a> {
1167 Format1(CoverageFormat1<'a>),
1168 Format2(CoverageFormat2<'a>),
1169}
1170
1171impl Default for CoverageTable<'_> {
1172 fn default() -> Self {
1173 Self::Format1(Default::default())
1174 }
1175}
1176
1177impl<'a> CoverageTable<'a> {
1178 pub fn offset_data(&self) -> FontData<'a> {
1180 match self {
1181 Self::Format1(item) => item.offset_data(),
1182 Self::Format2(item) => item.offset_data(),
1183 }
1184 }
1185
1186 pub fn coverage_format(&self) -> u16 {
1188 match self {
1189 Self::Format1(item) => item.coverage_format(),
1190 Self::Format2(item) => item.coverage_format(),
1191 }
1192 }
1193}
1194
1195impl ReadArgs for CoverageTable<'_> {
1196 type Args = ();
1197}
1198
1199impl<'a> FontRead<'a> for CoverageTable<'a> {
1200 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1201 let format: u16 = data.read_at(0usize)?;
1202 match format {
1203 CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1204 CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1205 other => Err(ReadError::InvalidFormat(other.into())),
1206 }
1207 }
1208}
1209
1210impl<'a> MinByteRange<'a> for CoverageTable<'a> {
1211 fn min_byte_range(&self) -> Range<usize> {
1212 match self {
1213 Self::Format1(item) => item.min_byte_range(),
1214 Self::Format2(item) => item.min_byte_range(),
1215 }
1216 }
1217 fn min_table_bytes(&self) -> &'a [u8] {
1218 match self {
1219 Self::Format1(item) => item.min_table_bytes(),
1220 Self::Format2(item) => item.min_table_bytes(),
1221 }
1222 }
1223}
1224
1225impl Format<u16> for ClassDefFormat1<'_> {
1226 const FORMAT: u16 = 1;
1227}
1228
1229impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
1230 fn min_byte_range(&self) -> Range<usize> {
1231 0..self.class_value_array_byte_range().end
1232 }
1233 fn min_table_bytes(&self) -> &'a [u8] {
1234 let range = self.min_byte_range();
1235 self.offset_data().as_bytes().get(range).unwrap_or_default()
1236 }
1237}
1238
1239impl ReadArgs for ClassDefFormat1<'_> {
1240 type Args = ();
1241}
1242
1243impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1244 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1245 #[allow(clippy::absurd_extreme_comparisons)]
1246 if data.len() < Self::MIN_SIZE {
1247 return Err(ReadError::OutOfBounds);
1248 }
1249 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1250 return Err(ReadError::OutOfBounds);
1251 };
1252 Ok(Self { data })
1253 }
1254}
1255
1256#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1258#[repr(C, packed)]
1259#[doc(hidden)]
1260pub struct ClassDefFormat1FixedHeader {
1261 pub class_format: BigEndian<u16>,
1262 pub start_glyph_id: BigEndian<GlyphId16>,
1263 pub glyph_count: BigEndian<u16>,
1264}
1265
1266#[allow(clippy::absurd_extreme_comparisons)]
1267const _: () =
1268 assert!(std::mem::size_of::<ClassDefFormat1FixedHeader>() <= ClassDefFormat1::MIN_SIZE);
1269
1270#[derive(Clone)]
1272pub struct ClassDefFormat1<'a> {
1273 data: TableDataRef<'a, ClassDefFormat1FixedHeader>,
1274}
1275
1276#[allow(clippy::needless_lifetimes)]
1277impl<'a> ClassDefFormat1<'a> {
1278 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1279 basic_table_impls!(impl_the_methods);
1280
1281 pub fn class_format(&self) -> u16 {
1283 self.data.header().class_format.get()
1284 }
1285
1286 pub fn start_glyph_id(&self) -> GlyphId16 {
1288 self.data.header().start_glyph_id.get()
1289 }
1290
1291 pub fn glyph_count(&self) -> u16 {
1293 self.data.header().glyph_count.get()
1294 }
1295
1296 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1298 let range = self.class_value_array_byte_range();
1299 self.offset_data()
1300 .read_array(range)
1301 .ok()
1302 .unwrap_or_default()
1303 }
1304
1305 pub fn class_format_byte_range(&self) -> Range<usize> {
1306 let start = 0;
1307 let end = start + u16::RAW_BYTE_LEN;
1308 start..end
1309 }
1310
1311 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1312 let start = self.class_format_byte_range().end;
1313 let end = start + GlyphId16::RAW_BYTE_LEN;
1314 start..end
1315 }
1316
1317 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1318 let start = self.start_glyph_id_byte_range().end;
1319 let end = start + u16::RAW_BYTE_LEN;
1320 start..end
1321 }
1322
1323 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1324 let glyph_count = self.glyph_count();
1325 let start = self.glyph_count_byte_range().end;
1326 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
1327 start..end
1328 }
1329}
1330
1331const _: () = assert!(FontData::default_data_long_enough(
1332 ClassDefFormat1::MIN_SIZE
1333));
1334
1335impl Default for ClassDefFormat1<'_> {
1336 fn default() -> Self {
1337 Self {
1338 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1339 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1340 }
1341 }
1342}
1343
1344impl Format<u16> for ClassDefFormat2<'_> {
1345 const FORMAT: u16 = 2;
1346}
1347
1348impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
1349 fn min_byte_range(&self) -> Range<usize> {
1350 0..self.class_range_records_byte_range().end
1351 }
1352 fn min_table_bytes(&self) -> &'a [u8] {
1353 let range = self.min_byte_range();
1354 self.offset_data().as_bytes().get(range).unwrap_or_default()
1355 }
1356}
1357
1358impl ReadArgs for ClassDefFormat2<'_> {
1359 type Args = ();
1360}
1361
1362impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1363 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1364 #[allow(clippy::absurd_extreme_comparisons)]
1365 if data.len() < Self::MIN_SIZE {
1366 return Err(ReadError::OutOfBounds);
1367 }
1368 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1369 return Err(ReadError::OutOfBounds);
1370 };
1371 Ok(Self { data })
1372 }
1373}
1374
1375#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1377#[repr(C, packed)]
1378#[doc(hidden)]
1379pub struct ClassDefFormat2FixedHeader {
1380 pub class_format: BigEndian<u16>,
1381 pub class_range_count: BigEndian<u16>,
1382}
1383
1384#[allow(clippy::absurd_extreme_comparisons)]
1385const _: () =
1386 assert!(std::mem::size_of::<ClassDefFormat2FixedHeader>() <= ClassDefFormat2::MIN_SIZE);
1387
1388#[derive(Clone)]
1390pub struct ClassDefFormat2<'a> {
1391 data: TableDataRef<'a, ClassDefFormat2FixedHeader>,
1392}
1393
1394#[allow(clippy::needless_lifetimes)]
1395impl<'a> ClassDefFormat2<'a> {
1396 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1397 basic_table_impls!(impl_the_methods);
1398
1399 pub fn class_format(&self) -> u16 {
1401 self.data.header().class_format.get()
1402 }
1403
1404 pub fn class_range_count(&self) -> u16 {
1406 self.data.header().class_range_count.get()
1407 }
1408
1409 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1411 let range = self.class_range_records_byte_range();
1412 self.offset_data()
1413 .read_array(range)
1414 .ok()
1415 .unwrap_or_default()
1416 }
1417
1418 pub fn class_format_byte_range(&self) -> Range<usize> {
1419 let start = 0;
1420 let end = start + u16::RAW_BYTE_LEN;
1421 start..end
1422 }
1423
1424 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1425 let start = self.class_format_byte_range().end;
1426 let end = start + u16::RAW_BYTE_LEN;
1427 start..end
1428 }
1429
1430 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1431 let class_range_count = self.class_range_count();
1432 let start = self.class_range_count_byte_range().end;
1433 let end = start
1434 + (transforms::to_usize(class_range_count))
1435 .saturating_mul(ClassRangeRecord::RAW_BYTE_LEN);
1436 start..end
1437 }
1438}
1439
1440#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1442#[repr(C)]
1443#[repr(packed)]
1444pub struct ClassRangeRecord {
1445 pub start_glyph_id: BigEndian<GlyphId16>,
1447 pub end_glyph_id: BigEndian<GlyphId16>,
1449 pub class: BigEndian<u16>,
1451}
1452
1453impl ClassRangeRecord {
1454 pub fn start_glyph_id(&self) -> GlyphId16 {
1456 self.start_glyph_id.get()
1457 }
1458
1459 pub fn end_glyph_id(&self) -> GlyphId16 {
1461 self.end_glyph_id.get()
1462 }
1463
1464 pub fn class(&self) -> u16 {
1466 self.class.get()
1467 }
1468}
1469
1470impl FixedSize for ClassRangeRecord {
1471 const RAW_BYTE_LEN: usize =
1472 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1473}
1474
1475#[derive(Clone)]
1477pub enum ClassDef<'a> {
1478 Format1(ClassDefFormat1<'a>),
1479 Format2(ClassDefFormat2<'a>),
1480}
1481
1482impl Default for ClassDef<'_> {
1483 fn default() -> Self {
1484 Self::Format1(Default::default())
1485 }
1486}
1487
1488impl<'a> ClassDef<'a> {
1489 pub fn offset_data(&self) -> FontData<'a> {
1491 match self {
1492 Self::Format1(item) => item.offset_data(),
1493 Self::Format2(item) => item.offset_data(),
1494 }
1495 }
1496
1497 pub fn class_format(&self) -> u16 {
1499 match self {
1500 Self::Format1(item) => item.class_format(),
1501 Self::Format2(item) => item.class_format(),
1502 }
1503 }
1504}
1505
1506impl ReadArgs for ClassDef<'_> {
1507 type Args = ();
1508}
1509
1510impl<'a> FontRead<'a> for ClassDef<'a> {
1511 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1512 let format: u16 = data.read_at(0usize)?;
1513 match format {
1514 ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1515 ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1516 other => Err(ReadError::InvalidFormat(other.into())),
1517 }
1518 }
1519}
1520
1521impl<'a> MinByteRange<'a> for ClassDef<'a> {
1522 fn min_byte_range(&self) -> Range<usize> {
1523 match self {
1524 Self::Format1(item) => item.min_byte_range(),
1525 Self::Format2(item) => item.min_byte_range(),
1526 }
1527 }
1528 fn min_table_bytes(&self) -> &'a [u8] {
1529 match self {
1530 Self::Format1(item) => item.min_table_bytes(),
1531 Self::Format2(item) => item.min_table_bytes(),
1532 }
1533 }
1534}
1535
1536#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1538#[repr(C)]
1539#[repr(packed)]
1540pub struct SequenceLookupRecord {
1541 pub sequence_index: BigEndian<u16>,
1543 pub lookup_list_index: BigEndian<u16>,
1545}
1546
1547impl SequenceLookupRecord {
1548 pub fn sequence_index(&self) -> u16 {
1550 self.sequence_index.get()
1551 }
1552
1553 pub fn lookup_list_index(&self) -> u16 {
1555 self.lookup_list_index.get()
1556 }
1557}
1558
1559impl FixedSize for SequenceLookupRecord {
1560 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1561}
1562
1563impl Format<u16> for SequenceContextFormat1<'_> {
1564 const FORMAT: u16 = 1;
1565}
1566
1567impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
1568 fn min_byte_range(&self) -> Range<usize> {
1569 0..self.seq_rule_set_offsets_byte_range().end
1570 }
1571 fn min_table_bytes(&self) -> &'a [u8] {
1572 let range = self.min_byte_range();
1573 self.offset_data().as_bytes().get(range).unwrap_or_default()
1574 }
1575}
1576
1577impl ReadArgs for SequenceContextFormat1<'_> {
1578 type Args = ();
1579}
1580
1581impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1582 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1583 #[allow(clippy::absurd_extreme_comparisons)]
1584 if data.len() < Self::MIN_SIZE {
1585 return Err(ReadError::OutOfBounds);
1586 }
1587 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1588 return Err(ReadError::OutOfBounds);
1589 };
1590 Ok(Self { data })
1591 }
1592}
1593
1594#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1596#[repr(C, packed)]
1597#[doc(hidden)]
1598pub struct SequenceContextFormat1FixedHeader {
1599 pub format: BigEndian<u16>,
1600 pub coverage_offset: BigEndian<Offset16>,
1601 pub seq_rule_set_count: BigEndian<u16>,
1602}
1603
1604#[allow(clippy::absurd_extreme_comparisons)]
1605const _: () = assert!(
1606 std::mem::size_of::<SequenceContextFormat1FixedHeader>() <= SequenceContextFormat1::MIN_SIZE
1607);
1608
1609#[derive(Clone)]
1611pub struct SequenceContextFormat1<'a> {
1612 data: TableDataRef<'a, SequenceContextFormat1FixedHeader>,
1613}
1614
1615#[allow(clippy::needless_lifetimes)]
1616impl<'a> SequenceContextFormat1<'a> {
1617 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1618 basic_table_impls!(impl_the_methods);
1619
1620 pub fn format(&self) -> u16 {
1622 self.data.header().format.get()
1623 }
1624
1625 pub fn coverage_offset(&self) -> Offset16 {
1628 self.data.header().coverage_offset.get()
1629 }
1630
1631 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1633 let data = self.offset_data();
1634 self.coverage_offset().resolve(data)
1635 }
1636
1637 pub fn seq_rule_set_count(&self) -> u16 {
1639 self.data.header().seq_rule_set_count.get()
1640 }
1641
1642 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1645 let range = self.seq_rule_set_offsets_byte_range();
1646 self.offset_data()
1647 .read_array(range)
1648 .ok()
1649 .unwrap_or_default()
1650 }
1651
1652 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1654 let data = self.offset_data();
1655 let offsets = self.seq_rule_set_offsets();
1656 ArrayOfNullableOffsets::new(offsets, data, ())
1657 }
1658
1659 pub fn format_byte_range(&self) -> Range<usize> {
1660 let start = 0;
1661 let end = start + u16::RAW_BYTE_LEN;
1662 start..end
1663 }
1664
1665 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1666 let start = self.format_byte_range().end;
1667 let end = start + Offset16::RAW_BYTE_LEN;
1668 start..end
1669 }
1670
1671 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1672 let start = self.coverage_offset_byte_range().end;
1673 let end = start + u16::RAW_BYTE_LEN;
1674 start..end
1675 }
1676
1677 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1678 let seq_rule_set_count = self.seq_rule_set_count();
1679 let start = self.seq_rule_set_count_byte_range().end;
1680 let end = start
1681 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1682 start..end
1683 }
1684}
1685
1686const _: () = assert!(FontData::default_data_long_enough(
1687 SequenceContextFormat1::MIN_SIZE
1688));
1689
1690impl Default for SequenceContextFormat1<'_> {
1691 fn default() -> Self {
1692 Self {
1693 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1694 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1695 }
1696 }
1697}
1698
1699impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
1700 fn min_byte_range(&self) -> Range<usize> {
1701 0..self.seq_rule_offsets_byte_range().end
1702 }
1703 fn min_table_bytes(&self) -> &'a [u8] {
1704 let range = self.min_byte_range();
1705 self.offset_data().as_bytes().get(range).unwrap_or_default()
1706 }
1707}
1708
1709impl ReadArgs for SequenceRuleSet<'_> {
1710 type Args = ();
1711}
1712
1713impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
1714 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1715 #[allow(clippy::absurd_extreme_comparisons)]
1716 if data.len() < Self::MIN_SIZE {
1717 return Err(ReadError::OutOfBounds);
1718 }
1719 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1720 return Err(ReadError::OutOfBounds);
1721 };
1722 Ok(Self { data })
1723 }
1724}
1725
1726#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1728#[repr(C, packed)]
1729#[doc(hidden)]
1730pub struct SequenceRuleSetFixedHeader {
1731 pub seq_rule_count: BigEndian<u16>,
1732}
1733
1734#[allow(clippy::absurd_extreme_comparisons)]
1735const _: () =
1736 assert!(std::mem::size_of::<SequenceRuleSetFixedHeader>() <= SequenceRuleSet::MIN_SIZE);
1737
1738#[derive(Clone)]
1740pub struct SequenceRuleSet<'a> {
1741 data: TableDataRef<'a, SequenceRuleSetFixedHeader>,
1742}
1743
1744#[allow(clippy::needless_lifetimes)]
1745impl<'a> SequenceRuleSet<'a> {
1746 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1747 basic_table_impls!(impl_the_methods);
1748
1749 pub fn seq_rule_count(&self) -> u16 {
1751 self.data.header().seq_rule_count.get()
1752 }
1753
1754 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
1757 let range = self.seq_rule_offsets_byte_range();
1758 self.offset_data()
1759 .read_array(range)
1760 .ok()
1761 .unwrap_or_default()
1762 }
1763
1764 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
1766 let data = self.offset_data();
1767 let offsets = self.seq_rule_offsets();
1768 ArrayOfOffsets::new(offsets, data, ())
1769 }
1770
1771 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
1772 let start = 0;
1773 let end = start + u16::RAW_BYTE_LEN;
1774 start..end
1775 }
1776
1777 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
1778 let seq_rule_count = self.seq_rule_count();
1779 let start = self.seq_rule_count_byte_range().end;
1780 let end =
1781 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1782 start..end
1783 }
1784}
1785
1786const _: () = assert!(FontData::default_data_long_enough(
1787 SequenceRuleSet::MIN_SIZE
1788));
1789
1790impl Default for SequenceRuleSet<'_> {
1791 fn default() -> Self {
1792 Self {
1793 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1794 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1795 }
1796 }
1797}
1798
1799impl<'a> MinByteRange<'a> for SequenceRule<'a> {
1800 fn min_byte_range(&self) -> Range<usize> {
1801 0..self.seq_lookup_records_byte_range().end
1802 }
1803 fn min_table_bytes(&self) -> &'a [u8] {
1804 let range = self.min_byte_range();
1805 self.offset_data().as_bytes().get(range).unwrap_or_default()
1806 }
1807}
1808
1809impl ReadArgs for SequenceRule<'_> {
1810 type Args = ();
1811}
1812
1813impl<'a> FontRead<'a> for SequenceRule<'a> {
1814 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1815 #[allow(clippy::absurd_extreme_comparisons)]
1816 if data.len() < Self::MIN_SIZE {
1817 return Err(ReadError::OutOfBounds);
1818 }
1819 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1820 return Err(ReadError::OutOfBounds);
1821 };
1822 Ok(Self { data })
1823 }
1824}
1825
1826#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1828#[repr(C, packed)]
1829#[doc(hidden)]
1830pub struct SequenceRuleFixedHeader {
1831 pub glyph_count: BigEndian<u16>,
1832 pub seq_lookup_count: BigEndian<u16>,
1833}
1834
1835#[allow(clippy::absurd_extreme_comparisons)]
1836const _: () = assert!(std::mem::size_of::<SequenceRuleFixedHeader>() <= SequenceRule::MIN_SIZE);
1837
1838#[derive(Clone)]
1840pub struct SequenceRule<'a> {
1841 data: TableDataRef<'a, SequenceRuleFixedHeader>,
1842}
1843
1844#[allow(clippy::needless_lifetimes)]
1845impl<'a> SequenceRule<'a> {
1846 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1847 basic_table_impls!(impl_the_methods);
1848
1849 pub fn glyph_count(&self) -> u16 {
1851 self.data.header().glyph_count.get()
1852 }
1853
1854 pub fn seq_lookup_count(&self) -> u16 {
1856 self.data.header().seq_lookup_count.get()
1857 }
1858
1859 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
1861 let range = self.input_sequence_byte_range();
1862 self.offset_data()
1863 .read_array(range)
1864 .ok()
1865 .unwrap_or_default()
1866 }
1867
1868 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
1870 let range = self.seq_lookup_records_byte_range();
1871 self.offset_data()
1872 .read_array(range)
1873 .ok()
1874 .unwrap_or_default()
1875 }
1876
1877 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1878 let start = 0;
1879 let end = start + u16::RAW_BYTE_LEN;
1880 start..end
1881 }
1882
1883 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
1884 let start = self.glyph_count_byte_range().end;
1885 let end = start + u16::RAW_BYTE_LEN;
1886 start..end
1887 }
1888
1889 pub fn input_sequence_byte_range(&self) -> Range<usize> {
1890 let glyph_count = self.glyph_count();
1891 let start = self.seq_lookup_count_byte_range().end;
1892 let end = start
1893 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1894 start..end
1895 }
1896
1897 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
1898 let seq_lookup_count = self.seq_lookup_count();
1899 let start = self.input_sequence_byte_range().end;
1900 let end = start
1901 + (transforms::to_usize(seq_lookup_count))
1902 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
1903 start..end
1904 }
1905}
1906
1907const _: () = assert!(FontData::default_data_long_enough(SequenceRule::MIN_SIZE));
1908
1909impl Default for SequenceRule<'_> {
1910 fn default() -> Self {
1911 Self {
1912 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1913 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1914 }
1915 }
1916}
1917
1918impl Format<u16> for SequenceContextFormat2<'_> {
1919 const FORMAT: u16 = 2;
1920}
1921
1922impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
1923 fn min_byte_range(&self) -> Range<usize> {
1924 0..self.class_seq_rule_set_offsets_byte_range().end
1925 }
1926 fn min_table_bytes(&self) -> &'a [u8] {
1927 let range = self.min_byte_range();
1928 self.offset_data().as_bytes().get(range).unwrap_or_default()
1929 }
1930}
1931
1932impl ReadArgs for SequenceContextFormat2<'_> {
1933 type Args = ();
1934}
1935
1936impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
1937 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1938 #[allow(clippy::absurd_extreme_comparisons)]
1939 if data.len() < Self::MIN_SIZE {
1940 return Err(ReadError::OutOfBounds);
1941 }
1942 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1943 return Err(ReadError::OutOfBounds);
1944 };
1945 Ok(Self { data })
1946 }
1947}
1948
1949#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1951#[repr(C, packed)]
1952#[doc(hidden)]
1953pub struct SequenceContextFormat2FixedHeader {
1954 pub format: BigEndian<u16>,
1955 pub coverage_offset: BigEndian<Offset16>,
1956 pub class_def_offset: BigEndian<Offset16>,
1957 pub class_seq_rule_set_count: BigEndian<u16>,
1958}
1959
1960#[allow(clippy::absurd_extreme_comparisons)]
1961const _: () = assert!(
1962 std::mem::size_of::<SequenceContextFormat2FixedHeader>() <= SequenceContextFormat2::MIN_SIZE
1963);
1964
1965#[derive(Clone)]
1967pub struct SequenceContextFormat2<'a> {
1968 data: TableDataRef<'a, SequenceContextFormat2FixedHeader>,
1969}
1970
1971#[allow(clippy::needless_lifetimes)]
1972impl<'a> SequenceContextFormat2<'a> {
1973 pub const MIN_SIZE: usize =
1974 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1975 basic_table_impls!(impl_the_methods);
1976
1977 pub fn format(&self) -> u16 {
1979 self.data.header().format.get()
1980 }
1981
1982 pub fn coverage_offset(&self) -> Offset16 {
1985 self.data.header().coverage_offset.get()
1986 }
1987
1988 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1990 let data = self.offset_data();
1991 self.coverage_offset().resolve(data)
1992 }
1993
1994 pub fn class_def_offset(&self) -> Offset16 {
1997 self.data.header().class_def_offset.get()
1998 }
1999
2000 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2002 let data = self.offset_data();
2003 self.class_def_offset().resolve(data)
2004 }
2005
2006 pub fn class_seq_rule_set_count(&self) -> u16 {
2008 self.data.header().class_seq_rule_set_count.get()
2009 }
2010
2011 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2014 let range = self.class_seq_rule_set_offsets_byte_range();
2015 self.offset_data()
2016 .read_array(range)
2017 .ok()
2018 .unwrap_or_default()
2019 }
2020
2021 pub fn class_seq_rule_sets(
2023 &self,
2024 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
2025 let data = self.offset_data();
2026 let offsets = self.class_seq_rule_set_offsets();
2027 ArrayOfNullableOffsets::new(offsets, data, ())
2028 }
2029
2030 pub fn format_byte_range(&self) -> Range<usize> {
2031 let start = 0;
2032 let end = start + u16::RAW_BYTE_LEN;
2033 start..end
2034 }
2035
2036 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2037 let start = self.format_byte_range().end;
2038 let end = start + Offset16::RAW_BYTE_LEN;
2039 start..end
2040 }
2041
2042 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
2043 let start = self.coverage_offset_byte_range().end;
2044 let end = start + Offset16::RAW_BYTE_LEN;
2045 start..end
2046 }
2047
2048 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2049 let start = self.class_def_offset_byte_range().end;
2050 let end = start + u16::RAW_BYTE_LEN;
2051 start..end
2052 }
2053
2054 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2055 let class_seq_rule_set_count = self.class_seq_rule_set_count();
2056 let start = self.class_seq_rule_set_count_byte_range().end;
2057 let end = start
2058 + (transforms::to_usize(class_seq_rule_set_count))
2059 .saturating_mul(Offset16::RAW_BYTE_LEN);
2060 start..end
2061 }
2062}
2063
2064impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
2065 fn min_byte_range(&self) -> Range<usize> {
2066 0..self.class_seq_rule_offsets_byte_range().end
2067 }
2068 fn min_table_bytes(&self) -> &'a [u8] {
2069 let range = self.min_byte_range();
2070 self.offset_data().as_bytes().get(range).unwrap_or_default()
2071 }
2072}
2073
2074impl ReadArgs for ClassSequenceRuleSet<'_> {
2075 type Args = ();
2076}
2077
2078impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
2079 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2080 #[allow(clippy::absurd_extreme_comparisons)]
2081 if data.len() < Self::MIN_SIZE {
2082 return Err(ReadError::OutOfBounds);
2083 }
2084 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2085 return Err(ReadError::OutOfBounds);
2086 };
2087 Ok(Self { data })
2088 }
2089}
2090
2091#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2093#[repr(C, packed)]
2094#[doc(hidden)]
2095pub struct ClassSequenceRuleSetFixedHeader {
2096 pub class_seq_rule_count: BigEndian<u16>,
2097}
2098
2099#[allow(clippy::absurd_extreme_comparisons)]
2100const _: () = assert!(
2101 std::mem::size_of::<ClassSequenceRuleSetFixedHeader>() <= ClassSequenceRuleSet::MIN_SIZE
2102);
2103
2104#[derive(Clone)]
2106pub struct ClassSequenceRuleSet<'a> {
2107 data: TableDataRef<'a, ClassSequenceRuleSetFixedHeader>,
2108}
2109
2110#[allow(clippy::needless_lifetimes)]
2111impl<'a> ClassSequenceRuleSet<'a> {
2112 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2113 basic_table_impls!(impl_the_methods);
2114
2115 pub fn class_seq_rule_count(&self) -> u16 {
2117 self.data.header().class_seq_rule_count.get()
2118 }
2119
2120 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2123 let range = self.class_seq_rule_offsets_byte_range();
2124 self.offset_data()
2125 .read_array(range)
2126 .ok()
2127 .unwrap_or_default()
2128 }
2129
2130 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
2132 let data = self.offset_data();
2133 let offsets = self.class_seq_rule_offsets();
2134 ArrayOfOffsets::new(offsets, data, ())
2135 }
2136
2137 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
2138 let start = 0;
2139 let end = start + u16::RAW_BYTE_LEN;
2140 start..end
2141 }
2142
2143 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2144 let class_seq_rule_count = self.class_seq_rule_count();
2145 let start = self.class_seq_rule_count_byte_range().end;
2146 let end = start
2147 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2148 start..end
2149 }
2150}
2151
2152const _: () = assert!(FontData::default_data_long_enough(
2153 ClassSequenceRuleSet::MIN_SIZE
2154));
2155
2156impl Default for ClassSequenceRuleSet<'_> {
2157 fn default() -> Self {
2158 Self {
2159 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2160 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2161 }
2162 }
2163}
2164
2165impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
2166 fn min_byte_range(&self) -> Range<usize> {
2167 0..self.seq_lookup_records_byte_range().end
2168 }
2169 fn min_table_bytes(&self) -> &'a [u8] {
2170 let range = self.min_byte_range();
2171 self.offset_data().as_bytes().get(range).unwrap_or_default()
2172 }
2173}
2174
2175impl ReadArgs for ClassSequenceRule<'_> {
2176 type Args = ();
2177}
2178
2179impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
2180 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2181 #[allow(clippy::absurd_extreme_comparisons)]
2182 if data.len() < Self::MIN_SIZE {
2183 return Err(ReadError::OutOfBounds);
2184 }
2185 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2186 return Err(ReadError::OutOfBounds);
2187 };
2188 Ok(Self { data })
2189 }
2190}
2191
2192#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2194#[repr(C, packed)]
2195#[doc(hidden)]
2196pub struct ClassSequenceRuleFixedHeader {
2197 pub glyph_count: BigEndian<u16>,
2198 pub seq_lookup_count: BigEndian<u16>,
2199}
2200
2201#[allow(clippy::absurd_extreme_comparisons)]
2202const _: () =
2203 assert!(std::mem::size_of::<ClassSequenceRuleFixedHeader>() <= ClassSequenceRule::MIN_SIZE);
2204
2205#[derive(Clone)]
2207pub struct ClassSequenceRule<'a> {
2208 data: TableDataRef<'a, ClassSequenceRuleFixedHeader>,
2209}
2210
2211#[allow(clippy::needless_lifetimes)]
2212impl<'a> ClassSequenceRule<'a> {
2213 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2214 basic_table_impls!(impl_the_methods);
2215
2216 pub fn glyph_count(&self) -> u16 {
2218 self.data.header().glyph_count.get()
2219 }
2220
2221 pub fn seq_lookup_count(&self) -> u16 {
2223 self.data.header().seq_lookup_count.get()
2224 }
2225
2226 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2229 let range = self.input_sequence_byte_range();
2230 self.offset_data()
2231 .read_array(range)
2232 .ok()
2233 .unwrap_or_default()
2234 }
2235
2236 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2238 let range = self.seq_lookup_records_byte_range();
2239 self.offset_data()
2240 .read_array(range)
2241 .ok()
2242 .unwrap_or_default()
2243 }
2244
2245 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2246 let start = 0;
2247 let end = start + u16::RAW_BYTE_LEN;
2248 start..end
2249 }
2250
2251 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2252 let start = self.glyph_count_byte_range().end;
2253 let end = start + u16::RAW_BYTE_LEN;
2254 start..end
2255 }
2256
2257 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2258 let glyph_count = self.glyph_count();
2259 let start = self.seq_lookup_count_byte_range().end;
2260 let end =
2261 start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
2262 start..end
2263 }
2264
2265 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2266 let seq_lookup_count = self.seq_lookup_count();
2267 let start = self.input_sequence_byte_range().end;
2268 let end = start
2269 + (transforms::to_usize(seq_lookup_count))
2270 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2271 start..end
2272 }
2273}
2274
2275const _: () = assert!(FontData::default_data_long_enough(
2276 ClassSequenceRule::MIN_SIZE
2277));
2278
2279impl Default for ClassSequenceRule<'_> {
2280 fn default() -> Self {
2281 Self {
2282 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2283 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2284 }
2285 }
2286}
2287
2288impl Format<u16> for SequenceContextFormat3<'_> {
2289 const FORMAT: u16 = 3;
2290}
2291
2292impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
2293 fn min_byte_range(&self) -> Range<usize> {
2294 0..self.seq_lookup_records_byte_range().end
2295 }
2296 fn min_table_bytes(&self) -> &'a [u8] {
2297 let range = self.min_byte_range();
2298 self.offset_data().as_bytes().get(range).unwrap_or_default()
2299 }
2300}
2301
2302impl ReadArgs for SequenceContextFormat3<'_> {
2303 type Args = ();
2304}
2305
2306impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2307 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2308 #[allow(clippy::absurd_extreme_comparisons)]
2309 if data.len() < Self::MIN_SIZE {
2310 return Err(ReadError::OutOfBounds);
2311 }
2312 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2313 return Err(ReadError::OutOfBounds);
2314 };
2315 Ok(Self { data })
2316 }
2317}
2318
2319#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2321#[repr(C, packed)]
2322#[doc(hidden)]
2323pub struct SequenceContextFormat3FixedHeader {
2324 pub format: BigEndian<u16>,
2325 pub glyph_count: BigEndian<u16>,
2326 pub seq_lookup_count: BigEndian<u16>,
2327}
2328
2329#[allow(clippy::absurd_extreme_comparisons)]
2330const _: () = assert!(
2331 std::mem::size_of::<SequenceContextFormat3FixedHeader>() <= SequenceContextFormat3::MIN_SIZE
2332);
2333
2334#[derive(Clone)]
2336pub struct SequenceContextFormat3<'a> {
2337 data: TableDataRef<'a, SequenceContextFormat3FixedHeader>,
2338}
2339
2340#[allow(clippy::needless_lifetimes)]
2341impl<'a> SequenceContextFormat3<'a> {
2342 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2343 basic_table_impls!(impl_the_methods);
2344
2345 pub fn format(&self) -> u16 {
2347 self.data.header().format.get()
2348 }
2349
2350 pub fn glyph_count(&self) -> u16 {
2352 self.data.header().glyph_count.get()
2353 }
2354
2355 pub fn seq_lookup_count(&self) -> u16 {
2357 self.data.header().seq_lookup_count.get()
2358 }
2359
2360 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2363 let range = self.coverage_offsets_byte_range();
2364 self.offset_data()
2365 .read_array(range)
2366 .ok()
2367 .unwrap_or_default()
2368 }
2369
2370 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2372 let data = self.offset_data();
2373 let offsets = self.coverage_offsets();
2374 ArrayOfOffsets::new(offsets, data, ())
2375 }
2376
2377 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2379 let range = self.seq_lookup_records_byte_range();
2380 self.offset_data()
2381 .read_array(range)
2382 .ok()
2383 .unwrap_or_default()
2384 }
2385
2386 pub fn format_byte_range(&self) -> Range<usize> {
2387 let start = 0;
2388 let end = start + u16::RAW_BYTE_LEN;
2389 start..end
2390 }
2391
2392 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2393 let start = self.format_byte_range().end;
2394 let end = start + u16::RAW_BYTE_LEN;
2395 start..end
2396 }
2397
2398 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2399 let start = self.glyph_count_byte_range().end;
2400 let end = start + u16::RAW_BYTE_LEN;
2401 start..end
2402 }
2403
2404 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2405 let glyph_count = self.glyph_count();
2406 let start = self.seq_lookup_count_byte_range().end;
2407 let end =
2408 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2409 start..end
2410 }
2411
2412 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2413 let seq_lookup_count = self.seq_lookup_count();
2414 let start = self.coverage_offsets_byte_range().end;
2415 let end = start
2416 + (transforms::to_usize(seq_lookup_count))
2417 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2418 start..end
2419 }
2420}
2421
2422#[derive(Clone)]
2423pub enum SequenceContext<'a> {
2424 Format1(SequenceContextFormat1<'a>),
2425 Format2(SequenceContextFormat2<'a>),
2426 Format3(SequenceContextFormat3<'a>),
2427}
2428
2429impl Default for SequenceContext<'_> {
2430 fn default() -> Self {
2431 Self::Format1(Default::default())
2432 }
2433}
2434
2435impl<'a> SequenceContext<'a> {
2436 pub fn offset_data(&self) -> FontData<'a> {
2438 match self {
2439 Self::Format1(item) => item.offset_data(),
2440 Self::Format2(item) => item.offset_data(),
2441 Self::Format3(item) => item.offset_data(),
2442 }
2443 }
2444
2445 pub fn format(&self) -> u16 {
2447 match self {
2448 Self::Format1(item) => item.format(),
2449 Self::Format2(item) => item.format(),
2450 Self::Format3(item) => item.format(),
2451 }
2452 }
2453}
2454
2455impl ReadArgs for SequenceContext<'_> {
2456 type Args = ();
2457}
2458
2459impl<'a> FontRead<'a> for SequenceContext<'a> {
2460 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2461 let format: u16 = data.read_at(0usize)?;
2462 match format {
2463 SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2464 SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2465 SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2466 other => Err(ReadError::InvalidFormat(other.into())),
2467 }
2468 }
2469}
2470
2471impl<'a> MinByteRange<'a> for SequenceContext<'a> {
2472 fn min_byte_range(&self) -> Range<usize> {
2473 match self {
2474 Self::Format1(item) => item.min_byte_range(),
2475 Self::Format2(item) => item.min_byte_range(),
2476 Self::Format3(item) => item.min_byte_range(),
2477 }
2478 }
2479 fn min_table_bytes(&self) -> &'a [u8] {
2480 match self {
2481 Self::Format1(item) => item.min_table_bytes(),
2482 Self::Format2(item) => item.min_table_bytes(),
2483 Self::Format3(item) => item.min_table_bytes(),
2484 }
2485 }
2486}
2487
2488impl Format<u16> for ChainedSequenceContextFormat1<'_> {
2489 const FORMAT: u16 = 1;
2490}
2491
2492impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
2493 fn min_byte_range(&self) -> Range<usize> {
2494 0..self.chained_seq_rule_set_offsets_byte_range().end
2495 }
2496 fn min_table_bytes(&self) -> &'a [u8] {
2497 let range = self.min_byte_range();
2498 self.offset_data().as_bytes().get(range).unwrap_or_default()
2499 }
2500}
2501
2502impl ReadArgs for ChainedSequenceContextFormat1<'_> {
2503 type Args = ();
2504}
2505
2506impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2507 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2508 #[allow(clippy::absurd_extreme_comparisons)]
2509 if data.len() < Self::MIN_SIZE {
2510 return Err(ReadError::OutOfBounds);
2511 }
2512 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2513 return Err(ReadError::OutOfBounds);
2514 };
2515 Ok(Self { data })
2516 }
2517}
2518
2519#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2521#[repr(C, packed)]
2522#[doc(hidden)]
2523pub struct ChainedSequenceContextFormat1FixedHeader {
2524 pub format: BigEndian<u16>,
2525 pub coverage_offset: BigEndian<Offset16>,
2526 pub chained_seq_rule_set_count: BigEndian<u16>,
2527}
2528
2529#[allow(clippy::absurd_extreme_comparisons)]
2530const _: () = assert!(
2531 std::mem::size_of::<ChainedSequenceContextFormat1FixedHeader>()
2532 <= ChainedSequenceContextFormat1::MIN_SIZE
2533);
2534
2535#[derive(Clone)]
2537pub struct ChainedSequenceContextFormat1<'a> {
2538 data: TableDataRef<'a, ChainedSequenceContextFormat1FixedHeader>,
2539}
2540
2541#[allow(clippy::needless_lifetimes)]
2542impl<'a> ChainedSequenceContextFormat1<'a> {
2543 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2544 basic_table_impls!(impl_the_methods);
2545
2546 pub fn format(&self) -> u16 {
2548 self.data.header().format.get()
2549 }
2550
2551 pub fn coverage_offset(&self) -> Offset16 {
2554 self.data.header().coverage_offset.get()
2555 }
2556
2557 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2559 let data = self.offset_data();
2560 self.coverage_offset().resolve(data)
2561 }
2562
2563 pub fn chained_seq_rule_set_count(&self) -> u16 {
2565 self.data.header().chained_seq_rule_set_count.get()
2566 }
2567
2568 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2571 let range = self.chained_seq_rule_set_offsets_byte_range();
2572 self.offset_data()
2573 .read_array(range)
2574 .ok()
2575 .unwrap_or_default()
2576 }
2577
2578 pub fn chained_seq_rule_sets(
2580 &self,
2581 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2582 let data = self.offset_data();
2583 let offsets = self.chained_seq_rule_set_offsets();
2584 ArrayOfNullableOffsets::new(offsets, data, ())
2585 }
2586
2587 pub fn format_byte_range(&self) -> Range<usize> {
2588 let start = 0;
2589 let end = start + u16::RAW_BYTE_LEN;
2590 start..end
2591 }
2592
2593 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2594 let start = self.format_byte_range().end;
2595 let end = start + Offset16::RAW_BYTE_LEN;
2596 start..end
2597 }
2598
2599 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2600 let start = self.coverage_offset_byte_range().end;
2601 let end = start + u16::RAW_BYTE_LEN;
2602 start..end
2603 }
2604
2605 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2606 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
2607 let start = self.chained_seq_rule_set_count_byte_range().end;
2608 let end = start
2609 + (transforms::to_usize(chained_seq_rule_set_count))
2610 .saturating_mul(Offset16::RAW_BYTE_LEN);
2611 start..end
2612 }
2613}
2614
2615const _: () = assert!(FontData::default_data_long_enough(
2616 ChainedSequenceContextFormat1::MIN_SIZE
2617));
2618
2619impl Default for ChainedSequenceContextFormat1<'_> {
2620 fn default() -> Self {
2621 Self {
2622 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
2623 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2624 }
2625 }
2626}
2627
2628impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
2629 fn min_byte_range(&self) -> Range<usize> {
2630 0..self.chained_seq_rule_offsets_byte_range().end
2631 }
2632 fn min_table_bytes(&self) -> &'a [u8] {
2633 let range = self.min_byte_range();
2634 self.offset_data().as_bytes().get(range).unwrap_or_default()
2635 }
2636}
2637
2638impl ReadArgs for ChainedSequenceRuleSet<'_> {
2639 type Args = ();
2640}
2641
2642impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
2643 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2644 #[allow(clippy::absurd_extreme_comparisons)]
2645 if data.len() < Self::MIN_SIZE {
2646 return Err(ReadError::OutOfBounds);
2647 }
2648 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2649 return Err(ReadError::OutOfBounds);
2650 };
2651 Ok(Self { data })
2652 }
2653}
2654
2655#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2657#[repr(C, packed)]
2658#[doc(hidden)]
2659pub struct ChainedSequenceRuleSetFixedHeader {
2660 pub chained_seq_rule_count: BigEndian<u16>,
2661}
2662
2663#[allow(clippy::absurd_extreme_comparisons)]
2664const _: () = assert!(
2665 std::mem::size_of::<ChainedSequenceRuleSetFixedHeader>() <= ChainedSequenceRuleSet::MIN_SIZE
2666);
2667
2668#[derive(Clone)]
2670pub struct ChainedSequenceRuleSet<'a> {
2671 data: TableDataRef<'a, ChainedSequenceRuleSetFixedHeader>,
2672}
2673
2674#[allow(clippy::needless_lifetimes)]
2675impl<'a> ChainedSequenceRuleSet<'a> {
2676 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2677 basic_table_impls!(impl_the_methods);
2678
2679 pub fn chained_seq_rule_count(&self) -> u16 {
2681 self.data.header().chained_seq_rule_count.get()
2682 }
2683
2684 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2687 let range = self.chained_seq_rule_offsets_byte_range();
2688 self.offset_data()
2689 .read_array(range)
2690 .ok()
2691 .unwrap_or_default()
2692 }
2693
2694 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
2696 let data = self.offset_data();
2697 let offsets = self.chained_seq_rule_offsets();
2698 ArrayOfOffsets::new(offsets, data, ())
2699 }
2700
2701 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
2702 let start = 0;
2703 let end = start + u16::RAW_BYTE_LEN;
2704 start..end
2705 }
2706
2707 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2708 let chained_seq_rule_count = self.chained_seq_rule_count();
2709 let start = self.chained_seq_rule_count_byte_range().end;
2710 let end = start
2711 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2712 start..end
2713 }
2714}
2715
2716const _: () = assert!(FontData::default_data_long_enough(
2717 ChainedSequenceRuleSet::MIN_SIZE
2718));
2719
2720impl Default for ChainedSequenceRuleSet<'_> {
2721 fn default() -> Self {
2722 Self {
2723 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2724 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2725 }
2726 }
2727}
2728
2729impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
2730 fn min_byte_range(&self) -> Range<usize> {
2731 0..self.seq_lookup_records_byte_range().end
2732 }
2733 fn min_table_bytes(&self) -> &'a [u8] {
2734 let range = self.min_byte_range();
2735 self.offset_data().as_bytes().get(range).unwrap_or_default()
2736 }
2737}
2738
2739impl ReadArgs for ChainedSequenceRule<'_> {
2740 type Args = ();
2741}
2742
2743impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
2744 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2745 #[allow(clippy::absurd_extreme_comparisons)]
2746 if data.len() < Self::MIN_SIZE {
2747 return Err(ReadError::OutOfBounds);
2748 }
2749 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2750 return Err(ReadError::OutOfBounds);
2751 };
2752 Ok(Self { data })
2753 }
2754}
2755
2756#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2758#[repr(C, packed)]
2759#[doc(hidden)]
2760pub struct ChainedSequenceRuleFixedHeader {
2761 pub backtrack_glyph_count: BigEndian<u16>,
2762}
2763
2764#[allow(clippy::absurd_extreme_comparisons)]
2765const _: () =
2766 assert!(std::mem::size_of::<ChainedSequenceRuleFixedHeader>() <= ChainedSequenceRule::MIN_SIZE);
2767
2768#[derive(Clone)]
2770pub struct ChainedSequenceRule<'a> {
2771 data: TableDataRef<'a, ChainedSequenceRuleFixedHeader>,
2772}
2773
2774#[allow(clippy::needless_lifetimes)]
2775impl<'a> ChainedSequenceRule<'a> {
2776 pub const MIN_SIZE: usize =
2777 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2778 basic_table_impls!(impl_the_methods);
2779
2780 pub fn backtrack_glyph_count(&self) -> u16 {
2782 self.data.header().backtrack_glyph_count.get()
2783 }
2784
2785 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2787 let range = self.backtrack_sequence_byte_range();
2788 self.offset_data()
2789 .read_array(range)
2790 .ok()
2791 .unwrap_or_default()
2792 }
2793
2794 pub fn input_glyph_count(&self) -> u16 {
2796 let range = self.input_glyph_count_byte_range();
2797 self.offset_data()
2798 .read_at(range.start)
2799 .ok()
2800 .unwrap_or_default()
2801 }
2802
2803 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2805 let range = self.input_sequence_byte_range();
2806 self.offset_data()
2807 .read_array(range)
2808 .ok()
2809 .unwrap_or_default()
2810 }
2811
2812 pub fn lookahead_glyph_count(&self) -> u16 {
2814 let range = self.lookahead_glyph_count_byte_range();
2815 self.offset_data()
2816 .read_at(range.start)
2817 .ok()
2818 .unwrap_or_default()
2819 }
2820
2821 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2823 let range = self.lookahead_sequence_byte_range();
2824 self.offset_data()
2825 .read_array(range)
2826 .ok()
2827 .unwrap_or_default()
2828 }
2829
2830 pub fn seq_lookup_count(&self) -> u16 {
2832 let range = self.seq_lookup_count_byte_range();
2833 self.offset_data()
2834 .read_at(range.start)
2835 .ok()
2836 .unwrap_or_default()
2837 }
2838
2839 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2841 let range = self.seq_lookup_records_byte_range();
2842 self.offset_data()
2843 .read_array(range)
2844 .ok()
2845 .unwrap_or_default()
2846 }
2847
2848 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
2849 let start = 0;
2850 let end = start + u16::RAW_BYTE_LEN;
2851 start..end
2852 }
2853
2854 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
2855 let backtrack_glyph_count = self.backtrack_glyph_count();
2856 let start = self.backtrack_glyph_count_byte_range().end;
2857 let end = start
2858 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2859 start..end
2860 }
2861
2862 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
2863 let start = self.backtrack_sequence_byte_range().end;
2864 let end = start + u16::RAW_BYTE_LEN;
2865 start..end
2866 }
2867
2868 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2869 let input_glyph_count = self.input_glyph_count();
2870 let start = self.input_glyph_count_byte_range().end;
2871 let end = start
2872 + (transforms::subtract(input_glyph_count, 1_usize))
2873 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
2874 start..end
2875 }
2876
2877 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
2878 let start = self.input_sequence_byte_range().end;
2879 let end = start + u16::RAW_BYTE_LEN;
2880 start..end
2881 }
2882
2883 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
2884 let lookahead_glyph_count = self.lookahead_glyph_count();
2885 let start = self.lookahead_glyph_count_byte_range().end;
2886 let end = start
2887 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2888 start..end
2889 }
2890
2891 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2892 let start = self.lookahead_sequence_byte_range().end;
2893 let end = start + u16::RAW_BYTE_LEN;
2894 start..end
2895 }
2896
2897 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2898 let seq_lookup_count = self.seq_lookup_count();
2899 let start = self.seq_lookup_count_byte_range().end;
2900 let end = start
2901 + (transforms::to_usize(seq_lookup_count))
2902 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2903 start..end
2904 }
2905}
2906
2907const _: () = assert!(FontData::default_data_long_enough(
2908 ChainedSequenceRule::MIN_SIZE
2909));
2910
2911impl Default for ChainedSequenceRule<'_> {
2912 fn default() -> Self {
2913 Self {
2914 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2915 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2916 }
2917 }
2918}
2919
2920impl Format<u16> for ChainedSequenceContextFormat2<'_> {
2921 const FORMAT: u16 = 2;
2922}
2923
2924impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
2925 fn min_byte_range(&self) -> Range<usize> {
2926 0..self.chained_class_seq_rule_set_offsets_byte_range().end
2927 }
2928 fn min_table_bytes(&self) -> &'a [u8] {
2929 let range = self.min_byte_range();
2930 self.offset_data().as_bytes().get(range).unwrap_or_default()
2931 }
2932}
2933
2934impl ReadArgs for ChainedSequenceContextFormat2<'_> {
2935 type Args = ();
2936}
2937
2938impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
2939 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2940 #[allow(clippy::absurd_extreme_comparisons)]
2941 if data.len() < Self::MIN_SIZE {
2942 return Err(ReadError::OutOfBounds);
2943 }
2944 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2945 return Err(ReadError::OutOfBounds);
2946 };
2947 Ok(Self { data })
2948 }
2949}
2950
2951#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2953#[repr(C, packed)]
2954#[doc(hidden)]
2955pub struct ChainedSequenceContextFormat2FixedHeader {
2956 pub format: BigEndian<u16>,
2957 pub coverage_offset: BigEndian<Offset16>,
2958 pub backtrack_class_def_offset: BigEndian<Offset16>,
2959 pub input_class_def_offset: BigEndian<Offset16>,
2960 pub lookahead_class_def_offset: BigEndian<Offset16>,
2961 pub chained_class_seq_rule_set_count: BigEndian<u16>,
2962}
2963
2964#[allow(clippy::absurd_extreme_comparisons)]
2965const _: () = assert!(
2966 std::mem::size_of::<ChainedSequenceContextFormat2FixedHeader>()
2967 <= ChainedSequenceContextFormat2::MIN_SIZE
2968);
2969
2970#[derive(Clone)]
2972pub struct ChainedSequenceContextFormat2<'a> {
2973 data: TableDataRef<'a, ChainedSequenceContextFormat2FixedHeader>,
2974}
2975
2976#[allow(clippy::needless_lifetimes)]
2977impl<'a> ChainedSequenceContextFormat2<'a> {
2978 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2979 + Offset16::RAW_BYTE_LEN
2980 + Offset16::RAW_BYTE_LEN
2981 + Offset16::RAW_BYTE_LEN
2982 + Offset16::RAW_BYTE_LEN
2983 + u16::RAW_BYTE_LEN);
2984 basic_table_impls!(impl_the_methods);
2985
2986 pub fn format(&self) -> u16 {
2988 self.data.header().format.get()
2989 }
2990
2991 pub fn coverage_offset(&self) -> Offset16 {
2994 self.data.header().coverage_offset.get()
2995 }
2996
2997 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2999 let data = self.offset_data();
3000 self.coverage_offset().resolve(data)
3001 }
3002
3003 pub fn backtrack_class_def_offset(&self) -> Offset16 {
3006 self.data.header().backtrack_class_def_offset.get()
3007 }
3008
3009 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3011 let data = self.offset_data();
3012 self.backtrack_class_def_offset().resolve(data)
3013 }
3014
3015 pub fn input_class_def_offset(&self) -> Offset16 {
3018 self.data.header().input_class_def_offset.get()
3019 }
3020
3021 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3023 let data = self.offset_data();
3024 self.input_class_def_offset().resolve(data)
3025 }
3026
3027 pub fn lookahead_class_def_offset(&self) -> Offset16 {
3030 self.data.header().lookahead_class_def_offset.get()
3031 }
3032
3033 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3035 let data = self.offset_data();
3036 self.lookahead_class_def_offset().resolve(data)
3037 }
3038
3039 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
3041 self.data.header().chained_class_seq_rule_set_count.get()
3042 }
3043
3044 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3047 let range = self.chained_class_seq_rule_set_offsets_byte_range();
3048 self.offset_data()
3049 .read_array(range)
3050 .ok()
3051 .unwrap_or_default()
3052 }
3053
3054 pub fn chained_class_seq_rule_sets(
3056 &self,
3057 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
3058 let data = self.offset_data();
3059 let offsets = self.chained_class_seq_rule_set_offsets();
3060 ArrayOfNullableOffsets::new(offsets, data, ())
3061 }
3062
3063 pub fn format_byte_range(&self) -> Range<usize> {
3064 let start = 0;
3065 let end = start + u16::RAW_BYTE_LEN;
3066 start..end
3067 }
3068
3069 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
3070 let start = self.format_byte_range().end;
3071 let end = start + Offset16::RAW_BYTE_LEN;
3072 start..end
3073 }
3074
3075 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
3076 let start = self.coverage_offset_byte_range().end;
3077 let end = start + Offset16::RAW_BYTE_LEN;
3078 start..end
3079 }
3080
3081 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
3082 let start = self.backtrack_class_def_offset_byte_range().end;
3083 let end = start + Offset16::RAW_BYTE_LEN;
3084 start..end
3085 }
3086
3087 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
3088 let start = self.input_class_def_offset_byte_range().end;
3089 let end = start + Offset16::RAW_BYTE_LEN;
3090 start..end
3091 }
3092
3093 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
3094 let start = self.lookahead_class_def_offset_byte_range().end;
3095 let end = start + u16::RAW_BYTE_LEN;
3096 start..end
3097 }
3098
3099 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
3100 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
3101 let start = self.chained_class_seq_rule_set_count_byte_range().end;
3102 let end = start
3103 + (transforms::to_usize(chained_class_seq_rule_set_count))
3104 .saturating_mul(Offset16::RAW_BYTE_LEN);
3105 start..end
3106 }
3107}
3108
3109impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
3110 fn min_byte_range(&self) -> Range<usize> {
3111 0..self.chained_class_seq_rule_offsets_byte_range().end
3112 }
3113 fn min_table_bytes(&self) -> &'a [u8] {
3114 let range = self.min_byte_range();
3115 self.offset_data().as_bytes().get(range).unwrap_or_default()
3116 }
3117}
3118
3119impl ReadArgs for ChainedClassSequenceRuleSet<'_> {
3120 type Args = ();
3121}
3122
3123impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
3124 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3125 #[allow(clippy::absurd_extreme_comparisons)]
3126 if data.len() < Self::MIN_SIZE {
3127 return Err(ReadError::OutOfBounds);
3128 }
3129 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3130 return Err(ReadError::OutOfBounds);
3131 };
3132 Ok(Self { data })
3133 }
3134}
3135
3136#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3138#[repr(C, packed)]
3139#[doc(hidden)]
3140pub struct ChainedClassSequenceRuleSetFixedHeader {
3141 pub chained_class_seq_rule_count: BigEndian<u16>,
3142}
3143
3144#[allow(clippy::absurd_extreme_comparisons)]
3145const _: () = assert!(
3146 std::mem::size_of::<ChainedClassSequenceRuleSetFixedHeader>()
3147 <= ChainedClassSequenceRuleSet::MIN_SIZE
3148);
3149
3150#[derive(Clone)]
3152pub struct ChainedClassSequenceRuleSet<'a> {
3153 data: TableDataRef<'a, ChainedClassSequenceRuleSetFixedHeader>,
3154}
3155
3156#[allow(clippy::needless_lifetimes)]
3157impl<'a> ChainedClassSequenceRuleSet<'a> {
3158 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3159 basic_table_impls!(impl_the_methods);
3160
3161 pub fn chained_class_seq_rule_count(&self) -> u16 {
3163 self.data.header().chained_class_seq_rule_count.get()
3164 }
3165
3166 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3169 let range = self.chained_class_seq_rule_offsets_byte_range();
3170 self.offset_data()
3171 .read_array(range)
3172 .ok()
3173 .unwrap_or_default()
3174 }
3175
3176 pub fn chained_class_seq_rules(
3178 &self,
3179 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
3180 let data = self.offset_data();
3181 let offsets = self.chained_class_seq_rule_offsets();
3182 ArrayOfOffsets::new(offsets, data, ())
3183 }
3184
3185 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
3186 let start = 0;
3187 let end = start + u16::RAW_BYTE_LEN;
3188 start..end
3189 }
3190
3191 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3192 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
3193 let start = self.chained_class_seq_rule_count_byte_range().end;
3194 let end = start
3195 + (transforms::to_usize(chained_class_seq_rule_count))
3196 .saturating_mul(Offset16::RAW_BYTE_LEN);
3197 start..end
3198 }
3199}
3200
3201const _: () = assert!(FontData::default_data_long_enough(
3202 ChainedClassSequenceRuleSet::MIN_SIZE
3203));
3204
3205impl Default for ChainedClassSequenceRuleSet<'_> {
3206 fn default() -> Self {
3207 Self {
3208 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3209 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3210 }
3211 }
3212}
3213
3214impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'a> {
3215 fn min_byte_range(&self) -> Range<usize> {
3216 0..self.seq_lookup_records_byte_range().end
3217 }
3218 fn min_table_bytes(&self) -> &'a [u8] {
3219 let range = self.min_byte_range();
3220 self.offset_data().as_bytes().get(range).unwrap_or_default()
3221 }
3222}
3223
3224impl ReadArgs for ChainedClassSequenceRule<'_> {
3225 type Args = ();
3226}
3227
3228impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
3229 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3230 #[allow(clippy::absurd_extreme_comparisons)]
3231 if data.len() < Self::MIN_SIZE {
3232 return Err(ReadError::OutOfBounds);
3233 }
3234 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3235 return Err(ReadError::OutOfBounds);
3236 };
3237 Ok(Self { data })
3238 }
3239}
3240
3241#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3243#[repr(C, packed)]
3244#[doc(hidden)]
3245pub struct ChainedClassSequenceRuleFixedHeader {
3246 pub backtrack_glyph_count: BigEndian<u16>,
3247}
3248
3249#[allow(clippy::absurd_extreme_comparisons)]
3250const _: () = assert!(
3251 std::mem::size_of::<ChainedClassSequenceRuleFixedHeader>()
3252 <= ChainedClassSequenceRule::MIN_SIZE
3253);
3254
3255#[derive(Clone)]
3257pub struct ChainedClassSequenceRule<'a> {
3258 data: TableDataRef<'a, ChainedClassSequenceRuleFixedHeader>,
3259}
3260
3261#[allow(clippy::needless_lifetimes)]
3262impl<'a> ChainedClassSequenceRule<'a> {
3263 pub const MIN_SIZE: usize =
3264 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3265 basic_table_impls!(impl_the_methods);
3266
3267 pub fn backtrack_glyph_count(&self) -> u16 {
3269 self.data.header().backtrack_glyph_count.get()
3270 }
3271
3272 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
3274 let range = self.backtrack_sequence_byte_range();
3275 self.offset_data()
3276 .read_array(range)
3277 .ok()
3278 .unwrap_or_default()
3279 }
3280
3281 pub fn input_glyph_count(&self) -> u16 {
3283 let range = self.input_glyph_count_byte_range();
3284 self.offset_data()
3285 .read_at(range.start)
3286 .ok()
3287 .unwrap_or_default()
3288 }
3289
3290 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
3293 let range = self.input_sequence_byte_range();
3294 self.offset_data()
3295 .read_array(range)
3296 .ok()
3297 .unwrap_or_default()
3298 }
3299
3300 pub fn lookahead_glyph_count(&self) -> u16 {
3302 let range = self.lookahead_glyph_count_byte_range();
3303 self.offset_data()
3304 .read_at(range.start)
3305 .ok()
3306 .unwrap_or_default()
3307 }
3308
3309 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
3311 let range = self.lookahead_sequence_byte_range();
3312 self.offset_data()
3313 .read_array(range)
3314 .ok()
3315 .unwrap_or_default()
3316 }
3317
3318 pub fn seq_lookup_count(&self) -> u16 {
3320 let range = self.seq_lookup_count_byte_range();
3321 self.offset_data()
3322 .read_at(range.start)
3323 .ok()
3324 .unwrap_or_default()
3325 }
3326
3327 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3329 let range = self.seq_lookup_records_byte_range();
3330 self.offset_data()
3331 .read_array(range)
3332 .ok()
3333 .unwrap_or_default()
3334 }
3335
3336 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3337 let start = 0;
3338 let end = start + u16::RAW_BYTE_LEN;
3339 start..end
3340 }
3341
3342 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3343 let backtrack_glyph_count = self.backtrack_glyph_count();
3344 let start = self.backtrack_glyph_count_byte_range().end;
3345 let end =
3346 start + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3347 start..end
3348 }
3349
3350 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3351 let start = self.backtrack_sequence_byte_range().end;
3352 let end = start + u16::RAW_BYTE_LEN;
3353 start..end
3354 }
3355
3356 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3357 let input_glyph_count = self.input_glyph_count();
3358 let start = self.input_glyph_count_byte_range().end;
3359 let end = start
3360 + (transforms::subtract(input_glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
3361 start..end
3362 }
3363
3364 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3365 let start = self.input_sequence_byte_range().end;
3366 let end = start + u16::RAW_BYTE_LEN;
3367 start..end
3368 }
3369
3370 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3371 let lookahead_glyph_count = self.lookahead_glyph_count();
3372 let start = self.lookahead_glyph_count_byte_range().end;
3373 let end =
3374 start + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3375 start..end
3376 }
3377
3378 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3379 let start = self.lookahead_sequence_byte_range().end;
3380 let end = start + u16::RAW_BYTE_LEN;
3381 start..end
3382 }
3383
3384 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3385 let seq_lookup_count = self.seq_lookup_count();
3386 let start = self.seq_lookup_count_byte_range().end;
3387 let end = start
3388 + (transforms::to_usize(seq_lookup_count))
3389 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3390 start..end
3391 }
3392}
3393
3394const _: () = assert!(FontData::default_data_long_enough(
3395 ChainedClassSequenceRule::MIN_SIZE
3396));
3397
3398impl Default for ChainedClassSequenceRule<'_> {
3399 fn default() -> Self {
3400 Self {
3401 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3402 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3403 }
3404 }
3405}
3406
3407impl Format<u16> for ChainedSequenceContextFormat3<'_> {
3408 const FORMAT: u16 = 3;
3409}
3410
3411impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
3412 fn min_byte_range(&self) -> Range<usize> {
3413 0..self.seq_lookup_records_byte_range().end
3414 }
3415 fn min_table_bytes(&self) -> &'a [u8] {
3416 let range = self.min_byte_range();
3417 self.offset_data().as_bytes().get(range).unwrap_or_default()
3418 }
3419}
3420
3421impl ReadArgs for ChainedSequenceContextFormat3<'_> {
3422 type Args = ();
3423}
3424
3425impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
3426 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3427 #[allow(clippy::absurd_extreme_comparisons)]
3428 if data.len() < Self::MIN_SIZE {
3429 return Err(ReadError::OutOfBounds);
3430 }
3431 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3432 return Err(ReadError::OutOfBounds);
3433 };
3434 Ok(Self { data })
3435 }
3436}
3437
3438#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3440#[repr(C, packed)]
3441#[doc(hidden)]
3442pub struct ChainedSequenceContextFormat3FixedHeader {
3443 pub format: BigEndian<u16>,
3444 pub backtrack_glyph_count: BigEndian<u16>,
3445}
3446
3447#[allow(clippy::absurd_extreme_comparisons)]
3448const _: () = assert!(
3449 std::mem::size_of::<ChainedSequenceContextFormat3FixedHeader>()
3450 <= ChainedSequenceContextFormat3::MIN_SIZE
3451);
3452
3453#[derive(Clone)]
3455pub struct ChainedSequenceContextFormat3<'a> {
3456 data: TableDataRef<'a, ChainedSequenceContextFormat3FixedHeader>,
3457}
3458
3459#[allow(clippy::needless_lifetimes)]
3460impl<'a> ChainedSequenceContextFormat3<'a> {
3461 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3462 + u16::RAW_BYTE_LEN
3463 + u16::RAW_BYTE_LEN
3464 + u16::RAW_BYTE_LEN
3465 + u16::RAW_BYTE_LEN);
3466 basic_table_impls!(impl_the_methods);
3467
3468 pub fn format(&self) -> u16 {
3470 self.data.header().format.get()
3471 }
3472
3473 pub fn backtrack_glyph_count(&self) -> u16 {
3475 self.data.header().backtrack_glyph_count.get()
3476 }
3477
3478 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3480 let range = self.backtrack_coverage_offsets_byte_range();
3481 self.offset_data()
3482 .read_array(range)
3483 .ok()
3484 .unwrap_or_default()
3485 }
3486
3487 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3489 let data = self.offset_data();
3490 let offsets = self.backtrack_coverage_offsets();
3491 ArrayOfOffsets::new(offsets, data, ())
3492 }
3493
3494 pub fn input_glyph_count(&self) -> u16 {
3496 let range = self.input_glyph_count_byte_range();
3497 self.offset_data()
3498 .read_at(range.start)
3499 .ok()
3500 .unwrap_or_default()
3501 }
3502
3503 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3505 let range = self.input_coverage_offsets_byte_range();
3506 self.offset_data()
3507 .read_array(range)
3508 .ok()
3509 .unwrap_or_default()
3510 }
3511
3512 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3514 let data = self.offset_data();
3515 let offsets = self.input_coverage_offsets();
3516 ArrayOfOffsets::new(offsets, data, ())
3517 }
3518
3519 pub fn lookahead_glyph_count(&self) -> u16 {
3521 let range = self.lookahead_glyph_count_byte_range();
3522 self.offset_data()
3523 .read_at(range.start)
3524 .ok()
3525 .unwrap_or_default()
3526 }
3527
3528 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3530 let range = self.lookahead_coverage_offsets_byte_range();
3531 self.offset_data()
3532 .read_array(range)
3533 .ok()
3534 .unwrap_or_default()
3535 }
3536
3537 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3539 let data = self.offset_data();
3540 let offsets = self.lookahead_coverage_offsets();
3541 ArrayOfOffsets::new(offsets, data, ())
3542 }
3543
3544 pub fn seq_lookup_count(&self) -> u16 {
3546 let range = self.seq_lookup_count_byte_range();
3547 self.offset_data()
3548 .read_at(range.start)
3549 .ok()
3550 .unwrap_or_default()
3551 }
3552
3553 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3555 let range = self.seq_lookup_records_byte_range();
3556 self.offset_data()
3557 .read_array(range)
3558 .ok()
3559 .unwrap_or_default()
3560 }
3561
3562 pub fn format_byte_range(&self) -> Range<usize> {
3563 let start = 0;
3564 let end = start + u16::RAW_BYTE_LEN;
3565 start..end
3566 }
3567
3568 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3569 let start = self.format_byte_range().end;
3570 let end = start + u16::RAW_BYTE_LEN;
3571 start..end
3572 }
3573
3574 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
3575 let backtrack_glyph_count = self.backtrack_glyph_count();
3576 let start = self.backtrack_glyph_count_byte_range().end;
3577 let end = start
3578 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3579 start..end
3580 }
3581
3582 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3583 let start = self.backtrack_coverage_offsets_byte_range().end;
3584 let end = start + u16::RAW_BYTE_LEN;
3585 start..end
3586 }
3587
3588 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
3589 let input_glyph_count = self.input_glyph_count();
3590 let start = self.input_glyph_count_byte_range().end;
3591 let end = start
3592 + (transforms::to_usize(input_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3593 start..end
3594 }
3595
3596 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3597 let start = self.input_coverage_offsets_byte_range().end;
3598 let end = start + u16::RAW_BYTE_LEN;
3599 start..end
3600 }
3601
3602 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
3603 let lookahead_glyph_count = self.lookahead_glyph_count();
3604 let start = self.lookahead_glyph_count_byte_range().end;
3605 let end = start
3606 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3607 start..end
3608 }
3609
3610 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3611 let start = self.lookahead_coverage_offsets_byte_range().end;
3612 let end = start + u16::RAW_BYTE_LEN;
3613 start..end
3614 }
3615
3616 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3617 let seq_lookup_count = self.seq_lookup_count();
3618 let start = self.seq_lookup_count_byte_range().end;
3619 let end = start
3620 + (transforms::to_usize(seq_lookup_count))
3621 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3622 start..end
3623 }
3624}
3625
3626#[derive(Clone)]
3627pub enum ChainedSequenceContext<'a> {
3628 Format1(ChainedSequenceContextFormat1<'a>),
3629 Format2(ChainedSequenceContextFormat2<'a>),
3630 Format3(ChainedSequenceContextFormat3<'a>),
3631}
3632
3633impl Default for ChainedSequenceContext<'_> {
3634 fn default() -> Self {
3635 Self::Format1(Default::default())
3636 }
3637}
3638
3639impl<'a> ChainedSequenceContext<'a> {
3640 pub fn offset_data(&self) -> FontData<'a> {
3642 match self {
3643 Self::Format1(item) => item.offset_data(),
3644 Self::Format2(item) => item.offset_data(),
3645 Self::Format3(item) => item.offset_data(),
3646 }
3647 }
3648
3649 pub fn format(&self) -> u16 {
3651 match self {
3652 Self::Format1(item) => item.format(),
3653 Self::Format2(item) => item.format(),
3654 Self::Format3(item) => item.format(),
3655 }
3656 }
3657}
3658
3659impl ReadArgs for ChainedSequenceContext<'_> {
3660 type Args = ();
3661}
3662
3663impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
3664 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3665 let format: u16 = data.read_at(0usize)?;
3666 match format {
3667 ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
3668 ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
3669 ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
3670 other => Err(ReadError::InvalidFormat(other.into())),
3671 }
3672 }
3673}
3674
3675impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
3676 fn min_byte_range(&self) -> Range<usize> {
3677 match self {
3678 Self::Format1(item) => item.min_byte_range(),
3679 Self::Format2(item) => item.min_byte_range(),
3680 Self::Format3(item) => item.min_byte_range(),
3681 }
3682 }
3683 fn min_table_bytes(&self) -> &'a [u8] {
3684 match self {
3685 Self::Format1(item) => item.min_table_bytes(),
3686 Self::Format2(item) => item.min_table_bytes(),
3687 Self::Format3(item) => item.min_table_bytes(),
3688 }
3689 }
3690}
3691
3692#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
3695#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3696#[repr(u16)]
3697#[allow(clippy::manual_non_exhaustive)]
3698pub enum DeltaFormat {
3699 #[default]
3701 Local2BitDeltas = 0x0001,
3702 Local4BitDeltas = 0x0002,
3704 Local8BitDeltas = 0x0003,
3706 VariationIndex = 0x8000,
3708 #[doc(hidden)]
3709 Unknown,
3711}
3712
3713impl DeltaFormat {
3714 pub fn new(raw: u16) -> Self {
3718 match raw {
3719 0x0001 => Self::Local2BitDeltas,
3720 0x0002 => Self::Local4BitDeltas,
3721 0x0003 => Self::Local8BitDeltas,
3722 0x8000 => Self::VariationIndex,
3723 _ => Self::Unknown,
3724 }
3725 }
3726}
3727
3728impl font_types::Scalar for DeltaFormat {
3729 type Raw = <u16 as font_types::Scalar>::Raw;
3730 fn to_raw(self) -> Self::Raw {
3731 (self as u16).to_raw()
3732 }
3733 fn from_raw(raw: Self::Raw) -> Self {
3734 let t = <u16>::from_raw(raw);
3735 Self::new(t)
3736 }
3737}
3738
3739impl<'a> MinByteRange<'a> for Device<'a> {
3740 fn min_byte_range(&self) -> Range<usize> {
3741 0..self.delta_value_byte_range().end
3742 }
3743 fn min_table_bytes(&self) -> &'a [u8] {
3744 let range = self.min_byte_range();
3745 self.offset_data().as_bytes().get(range).unwrap_or_default()
3746 }
3747}
3748
3749impl ReadArgs for Device<'_> {
3750 type Args = ();
3751}
3752
3753impl<'a> FontRead<'a> for Device<'a> {
3754 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3755 #[allow(clippy::absurd_extreme_comparisons)]
3756 if data.len() < Self::MIN_SIZE {
3757 return Err(ReadError::OutOfBounds);
3758 }
3759 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3760 return Err(ReadError::OutOfBounds);
3761 };
3762 Ok(Self { data })
3763 }
3764}
3765
3766#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3768#[repr(C, packed)]
3769#[doc(hidden)]
3770pub struct DeviceFixedHeader {
3771 pub start_size: BigEndian<u16>,
3772 pub end_size: BigEndian<u16>,
3773 pub delta_format: BigEndian<DeltaFormat>,
3774}
3775
3776#[allow(clippy::absurd_extreme_comparisons)]
3777const _: () = assert!(std::mem::size_of::<DeviceFixedHeader>() <= Device::MIN_SIZE);
3778
3779#[derive(Clone)]
3781pub struct Device<'a> {
3782 data: TableDataRef<'a, DeviceFixedHeader>,
3783}
3784
3785#[allow(clippy::needless_lifetimes)]
3786impl<'a> Device<'a> {
3787 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3788 basic_table_impls!(impl_the_methods);
3789
3790 pub fn start_size(&self) -> u16 {
3792 self.data.header().start_size.get()
3793 }
3794
3795 pub fn end_size(&self) -> u16 {
3797 self.data.header().end_size.get()
3798 }
3799
3800 pub fn delta_format(&self) -> DeltaFormat {
3802 self.data.header().delta_format.get()
3803 }
3804
3805 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
3807 let range = self.delta_value_byte_range();
3808 self.offset_data()
3809 .read_array(range)
3810 .ok()
3811 .unwrap_or_default()
3812 }
3813
3814 pub fn start_size_byte_range(&self) -> Range<usize> {
3815 let start = 0;
3816 let end = start + u16::RAW_BYTE_LEN;
3817 start..end
3818 }
3819
3820 pub fn end_size_byte_range(&self) -> Range<usize> {
3821 let start = self.start_size_byte_range().end;
3822 let end = start + u16::RAW_BYTE_LEN;
3823 start..end
3824 }
3825
3826 pub fn delta_format_byte_range(&self) -> Range<usize> {
3827 let start = self.end_size_byte_range().end;
3828 let end = start + DeltaFormat::RAW_BYTE_LEN;
3829 start..end
3830 }
3831
3832 pub fn delta_value_byte_range(&self) -> Range<usize> {
3833 let delta_format = self.delta_format();
3834 let start_size = self.start_size();
3835 let end_size = self.end_size();
3836 let start = self.delta_format_byte_range().end;
3837 let end = start
3838 + (DeltaFormat::value_count(delta_format, start_size, end_size))
3839 .saturating_mul(u16::RAW_BYTE_LEN);
3840 start..end
3841 }
3842}
3843
3844const _: () = assert!(FontData::default_data_long_enough(Device::MIN_SIZE));
3845
3846impl Default for Device<'_> {
3847 fn default() -> Self {
3848 Self {
3849 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3850 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3851 }
3852 }
3853}
3854
3855impl<'a> MinByteRange<'a> for VariationIndex<'a> {
3856 fn min_byte_range(&self) -> Range<usize> {
3857 0..self.delta_format_byte_range().end
3858 }
3859 fn min_table_bytes(&self) -> &'a [u8] {
3860 let range = self.min_byte_range();
3861 self.offset_data().as_bytes().get(range).unwrap_or_default()
3862 }
3863}
3864
3865impl ReadArgs for VariationIndex<'_> {
3866 type Args = ();
3867}
3868
3869impl<'a> FontRead<'a> for VariationIndex<'a> {
3870 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3871 #[allow(clippy::absurd_extreme_comparisons)]
3872 if data.len() < Self::MIN_SIZE {
3873 return Err(ReadError::OutOfBounds);
3874 }
3875 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3876 return Err(ReadError::OutOfBounds);
3877 };
3878 Ok(Self { data })
3879 }
3880}
3881
3882#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3884#[repr(C, packed)]
3885#[doc(hidden)]
3886pub struct VariationIndexFixedHeader {
3887 pub delta_set_outer_index: BigEndian<u16>,
3888 pub delta_set_inner_index: BigEndian<u16>,
3889 pub delta_format: BigEndian<DeltaFormat>,
3890}
3891
3892#[allow(clippy::absurd_extreme_comparisons)]
3893const _: () = assert!(std::mem::size_of::<VariationIndexFixedHeader>() <= VariationIndex::MIN_SIZE);
3894
3895#[derive(Clone)]
3897pub struct VariationIndex<'a> {
3898 data: TableDataRef<'a, VariationIndexFixedHeader>,
3899}
3900
3901#[allow(clippy::needless_lifetimes)]
3902impl<'a> VariationIndex<'a> {
3903 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3904 basic_table_impls!(impl_the_methods);
3905
3906 pub fn delta_set_outer_index(&self) -> u16 {
3909 self.data.header().delta_set_outer_index.get()
3910 }
3911
3912 pub fn delta_set_inner_index(&self) -> u16 {
3915 self.data.header().delta_set_inner_index.get()
3916 }
3917
3918 pub fn delta_format(&self) -> DeltaFormat {
3920 self.data.header().delta_format.get()
3921 }
3922
3923 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
3924 let start = 0;
3925 let end = start + u16::RAW_BYTE_LEN;
3926 start..end
3927 }
3928
3929 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
3930 let start = self.delta_set_outer_index_byte_range().end;
3931 let end = start + u16::RAW_BYTE_LEN;
3932 start..end
3933 }
3934
3935 pub fn delta_format_byte_range(&self) -> Range<usize> {
3936 let start = self.delta_set_inner_index_byte_range().end;
3937 let end = start + DeltaFormat::RAW_BYTE_LEN;
3938 start..end
3939 }
3940}
3941
3942const _: () = assert!(FontData::default_data_long_enough(VariationIndex::MIN_SIZE));
3943
3944impl Default for VariationIndex<'_> {
3945 fn default() -> Self {
3946 Self {
3947 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3948 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3949 }
3950 }
3951}
3952
3953#[derive(Clone)]
3955pub enum DeviceOrVariationIndex<'a> {
3956 Device(Device<'a>),
3957 VariationIndex(VariationIndex<'a>),
3958}
3959
3960impl Default for DeviceOrVariationIndex<'_> {
3961 fn default() -> Self {
3962 Self::Device(Default::default())
3963 }
3964}
3965
3966impl<'a> DeviceOrVariationIndex<'a> {
3967 pub fn offset_data(&self) -> FontData<'a> {
3969 match self {
3970 Self::Device(item) => item.offset_data(),
3971 Self::VariationIndex(item) => item.offset_data(),
3972 }
3973 }
3974}
3975
3976impl ReadArgs for DeviceOrVariationIndex<'_> {
3977 type Args = ();
3978}
3979
3980impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
3981 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3982 let format: DeltaFormat = data.read_at(4usize)?;
3983
3984 #[allow(clippy::redundant_guards)]
3985 match format {
3986 format if format != DeltaFormat::VariationIndex => {
3987 Ok(Self::Device(FontRead::read(data)?))
3988 }
3989 format if format == DeltaFormat::VariationIndex => {
3990 Ok(Self::VariationIndex(FontRead::read(data)?))
3991 }
3992 other => Err(ReadError::InvalidFormat(other.into())),
3993 }
3994 }
3995}
3996
3997impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
3998 fn min_byte_range(&self) -> Range<usize> {
3999 match self {
4000 Self::Device(item) => item.min_byte_range(),
4001 Self::VariationIndex(item) => item.min_byte_range(),
4002 }
4003 }
4004 fn min_table_bytes(&self) -> &'a [u8] {
4005 match self {
4006 Self::Device(item) => item.min_table_bytes(),
4007 Self::VariationIndex(item) => item.min_table_bytes(),
4008 }
4009 }
4010}
4011
4012impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
4013 fn min_byte_range(&self) -> Range<usize> {
4014 0..self.feature_variation_records_byte_range().end
4015 }
4016 fn min_table_bytes(&self) -> &'a [u8] {
4017 let range = self.min_byte_range();
4018 self.offset_data().as_bytes().get(range).unwrap_or_default()
4019 }
4020}
4021
4022impl ReadArgs for FeatureVariations<'_> {
4023 type Args = ();
4024}
4025
4026impl<'a> FontRead<'a> for FeatureVariations<'a> {
4027 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4028 #[allow(clippy::absurd_extreme_comparisons)]
4029 if data.len() < Self::MIN_SIZE {
4030 return Err(ReadError::OutOfBounds);
4031 }
4032 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4033 return Err(ReadError::OutOfBounds);
4034 };
4035 Ok(Self { data })
4036 }
4037}
4038
4039#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4041#[repr(C, packed)]
4042#[doc(hidden)]
4043pub struct FeatureVariationsFixedHeader {
4044 pub version: BigEndian<MajorMinor>,
4045 pub feature_variation_record_count: BigEndian<u32>,
4046}
4047
4048#[allow(clippy::absurd_extreme_comparisons)]
4049const _: () =
4050 assert!(std::mem::size_of::<FeatureVariationsFixedHeader>() <= FeatureVariations::MIN_SIZE);
4051
4052#[derive(Clone)]
4054pub struct FeatureVariations<'a> {
4055 data: TableDataRef<'a, FeatureVariationsFixedHeader>,
4056}
4057
4058#[allow(clippy::needless_lifetimes)]
4059impl<'a> FeatureVariations<'a> {
4060 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4061 basic_table_impls!(impl_the_methods);
4062
4063 pub fn version(&self) -> MajorMinor {
4064 self.data.header().version.get()
4065 }
4066
4067 pub fn feature_variation_record_count(&self) -> u32 {
4069 self.data.header().feature_variation_record_count.get()
4070 }
4071
4072 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
4074 let range = self.feature_variation_records_byte_range();
4075 self.offset_data()
4076 .read_array(range)
4077 .ok()
4078 .unwrap_or_default()
4079 }
4080
4081 pub fn version_byte_range(&self) -> Range<usize> {
4082 let start = 0;
4083 let end = start + MajorMinor::RAW_BYTE_LEN;
4084 start..end
4085 }
4086
4087 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
4088 let start = self.version_byte_range().end;
4089 let end = start + u32::RAW_BYTE_LEN;
4090 start..end
4091 }
4092
4093 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
4094 let feature_variation_record_count = self.feature_variation_record_count();
4095 let start = self.feature_variation_record_count_byte_range().end;
4096 let end = start
4097 + (transforms::to_usize(feature_variation_record_count))
4098 .saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN);
4099 start..end
4100 }
4101}
4102
4103const _: () = assert!(FontData::default_data_long_enough(
4104 FeatureVariations::MIN_SIZE
4105));
4106
4107impl Default for FeatureVariations<'_> {
4108 fn default() -> Self {
4109 Self {
4110 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4111 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4112 }
4113 }
4114}
4115
4116#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4118#[repr(C)]
4119#[repr(packed)]
4120pub struct FeatureVariationRecord {
4121 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
4124 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
4127}
4128
4129impl FeatureVariationRecord {
4130 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
4133 self.condition_set_offset.get()
4134 }
4135
4136 pub fn condition_set<'a>(
4142 &self,
4143 data: FontData<'a>,
4144 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
4145 self.condition_set_offset().resolve(data)
4146 }
4147
4148 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
4151 self.feature_table_substitution_offset.get()
4152 }
4153
4154 pub fn feature_table_substitution<'a>(
4160 &self,
4161 data: FontData<'a>,
4162 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
4163 self.feature_table_substitution_offset().resolve(data)
4164 }
4165}
4166
4167impl FixedSize for FeatureVariationRecord {
4168 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4169}
4170
4171impl<'a> MinByteRange<'a> for ConditionSet<'a> {
4172 fn min_byte_range(&self) -> Range<usize> {
4173 0..self.condition_offsets_byte_range().end
4174 }
4175 fn min_table_bytes(&self) -> &'a [u8] {
4176 let range = self.min_byte_range();
4177 self.offset_data().as_bytes().get(range).unwrap_or_default()
4178 }
4179}
4180
4181impl ReadArgs for ConditionSet<'_> {
4182 type Args = ();
4183}
4184
4185impl<'a> FontRead<'a> for ConditionSet<'a> {
4186 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4187 #[allow(clippy::absurd_extreme_comparisons)]
4188 if data.len() < Self::MIN_SIZE {
4189 return Err(ReadError::OutOfBounds);
4190 }
4191 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4192 return Err(ReadError::OutOfBounds);
4193 };
4194 Ok(Self { data })
4195 }
4196}
4197
4198#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4200#[repr(C, packed)]
4201#[doc(hidden)]
4202pub struct ConditionSetFixedHeader {
4203 pub condition_count: BigEndian<u16>,
4204}
4205
4206#[allow(clippy::absurd_extreme_comparisons)]
4207const _: () = assert!(std::mem::size_of::<ConditionSetFixedHeader>() <= ConditionSet::MIN_SIZE);
4208
4209#[derive(Clone)]
4211pub struct ConditionSet<'a> {
4212 data: TableDataRef<'a, ConditionSetFixedHeader>,
4213}
4214
4215#[allow(clippy::needless_lifetimes)]
4216impl<'a> ConditionSet<'a> {
4217 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
4218 basic_table_impls!(impl_the_methods);
4219
4220 pub fn condition_count(&self) -> u16 {
4222 self.data.header().condition_count.get()
4223 }
4224
4225 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
4228 let range = self.condition_offsets_byte_range();
4229 self.offset_data()
4230 .read_array(range)
4231 .ok()
4232 .unwrap_or_default()
4233 }
4234
4235 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
4237 let data = self.offset_data();
4238 let offsets = self.condition_offsets();
4239 ArrayOfOffsets::new(offsets, data, ())
4240 }
4241
4242 pub fn condition_count_byte_range(&self) -> Range<usize> {
4243 let start = 0;
4244 let end = start + u16::RAW_BYTE_LEN;
4245 start..end
4246 }
4247
4248 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4249 let condition_count = self.condition_count();
4250 let start = self.condition_count_byte_range().end;
4251 let end =
4252 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
4253 start..end
4254 }
4255}
4256
4257const _: () = assert!(FontData::default_data_long_enough(ConditionSet::MIN_SIZE));
4258
4259impl Default for ConditionSet<'_> {
4260 fn default() -> Self {
4261 Self {
4262 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4263 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4264 }
4265 }
4266}
4267
4268#[derive(Clone)]
4273pub enum Condition<'a> {
4274 Format1AxisRange(ConditionFormat1<'a>),
4275 Format2VariableValue(ConditionFormat2<'a>),
4276 Format3And(ConditionFormat3<'a>),
4277 Format4Or(ConditionFormat4<'a>),
4278 Format5Negate(ConditionFormat5<'a>),
4279}
4280
4281impl Default for Condition<'_> {
4282 fn default() -> Self {
4283 Self::Format1AxisRange(Default::default())
4284 }
4285}
4286
4287impl<'a> Condition<'a> {
4288 pub fn offset_data(&self) -> FontData<'a> {
4290 match self {
4291 Self::Format1AxisRange(item) => item.offset_data(),
4292 Self::Format2VariableValue(item) => item.offset_data(),
4293 Self::Format3And(item) => item.offset_data(),
4294 Self::Format4Or(item) => item.offset_data(),
4295 Self::Format5Negate(item) => item.offset_data(),
4296 }
4297 }
4298
4299 pub fn format(&self) -> u16 {
4301 match self {
4302 Self::Format1AxisRange(item) => item.format(),
4303 Self::Format2VariableValue(item) => item.format(),
4304 Self::Format3And(item) => item.format(),
4305 Self::Format4Or(item) => item.format(),
4306 Self::Format5Negate(item) => item.format(),
4307 }
4308 }
4309}
4310
4311impl ReadArgs for Condition<'_> {
4312 type Args = ();
4313}
4314
4315impl<'a> FontRead<'a> for Condition<'a> {
4316 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4317 let format: u16 = data.read_at(0usize)?;
4318 match format {
4319 ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
4320 ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
4321 ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
4322 ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
4323 ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
4324 other => Err(ReadError::InvalidFormat(other.into())),
4325 }
4326 }
4327}
4328
4329impl<'a> MinByteRange<'a> for Condition<'a> {
4330 fn min_byte_range(&self) -> Range<usize> {
4331 match self {
4332 Self::Format1AxisRange(item) => item.min_byte_range(),
4333 Self::Format2VariableValue(item) => item.min_byte_range(),
4334 Self::Format3And(item) => item.min_byte_range(),
4335 Self::Format4Or(item) => item.min_byte_range(),
4336 Self::Format5Negate(item) => item.min_byte_range(),
4337 }
4338 }
4339 fn min_table_bytes(&self) -> &'a [u8] {
4340 match self {
4341 Self::Format1AxisRange(item) => item.min_table_bytes(),
4342 Self::Format2VariableValue(item) => item.min_table_bytes(),
4343 Self::Format3And(item) => item.min_table_bytes(),
4344 Self::Format4Or(item) => item.min_table_bytes(),
4345 Self::Format5Negate(item) => item.min_table_bytes(),
4346 }
4347 }
4348}
4349
4350impl Format<u16> for ConditionFormat1<'_> {
4351 const FORMAT: u16 = 1;
4352}
4353
4354impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
4355 fn min_byte_range(&self) -> Range<usize> {
4356 0..self.filter_range_max_value_byte_range().end
4357 }
4358 fn min_table_bytes(&self) -> &'a [u8] {
4359 let range = self.min_byte_range();
4360 self.offset_data().as_bytes().get(range).unwrap_or_default()
4361 }
4362}
4363
4364impl ReadArgs for ConditionFormat1<'_> {
4365 type Args = ();
4366}
4367
4368impl<'a> FontRead<'a> for ConditionFormat1<'a> {
4369 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4370 #[allow(clippy::absurd_extreme_comparisons)]
4371 if data.len() < Self::MIN_SIZE {
4372 return Err(ReadError::OutOfBounds);
4373 }
4374 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4375 return Err(ReadError::OutOfBounds);
4376 };
4377 Ok(Self { data })
4378 }
4379}
4380
4381#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4383#[repr(C, packed)]
4384#[doc(hidden)]
4385pub struct ConditionFormat1FixedHeader {
4386 pub format: BigEndian<u16>,
4387 pub axis_index: BigEndian<u16>,
4388 pub filter_range_min_value: BigEndian<F2Dot14>,
4389 pub filter_range_max_value: BigEndian<F2Dot14>,
4390}
4391
4392#[allow(clippy::absurd_extreme_comparisons)]
4393const _: () =
4394 assert!(std::mem::size_of::<ConditionFormat1FixedHeader>() <= ConditionFormat1::MIN_SIZE);
4395
4396#[derive(Clone)]
4398pub struct ConditionFormat1<'a> {
4399 data: TableDataRef<'a, ConditionFormat1FixedHeader>,
4400}
4401
4402#[allow(clippy::needless_lifetimes)]
4403impl<'a> ConditionFormat1<'a> {
4404 pub const MIN_SIZE: usize =
4405 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
4406 basic_table_impls!(impl_the_methods);
4407
4408 pub fn format(&self) -> u16 {
4410 self.data.header().format.get()
4411 }
4412
4413 pub fn axis_index(&self) -> u16 {
4416 self.data.header().axis_index.get()
4417 }
4418
4419 pub fn filter_range_min_value(&self) -> F2Dot14 {
4422 self.data.header().filter_range_min_value.get()
4423 }
4424
4425 pub fn filter_range_max_value(&self) -> F2Dot14 {
4428 self.data.header().filter_range_max_value.get()
4429 }
4430
4431 pub fn format_byte_range(&self) -> Range<usize> {
4432 let start = 0;
4433 let end = start + u16::RAW_BYTE_LEN;
4434 start..end
4435 }
4436
4437 pub fn axis_index_byte_range(&self) -> Range<usize> {
4438 let start = self.format_byte_range().end;
4439 let end = start + u16::RAW_BYTE_LEN;
4440 start..end
4441 }
4442
4443 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
4444 let start = self.axis_index_byte_range().end;
4445 let end = start + F2Dot14::RAW_BYTE_LEN;
4446 start..end
4447 }
4448
4449 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
4450 let start = self.filter_range_min_value_byte_range().end;
4451 let end = start + F2Dot14::RAW_BYTE_LEN;
4452 start..end
4453 }
4454}
4455
4456const _: () = assert!(FontData::default_data_long_enough(
4457 ConditionFormat1::MIN_SIZE
4458));
4459
4460impl Default for ConditionFormat1<'_> {
4461 fn default() -> Self {
4462 Self {
4463 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
4464 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4465 }
4466 }
4467}
4468
4469impl Format<u16> for ConditionFormat2<'_> {
4470 const FORMAT: u16 = 2;
4471}
4472
4473impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
4474 fn min_byte_range(&self) -> Range<usize> {
4475 0..self.var_index_byte_range().end
4476 }
4477 fn min_table_bytes(&self) -> &'a [u8] {
4478 let range = self.min_byte_range();
4479 self.offset_data().as_bytes().get(range).unwrap_or_default()
4480 }
4481}
4482
4483impl ReadArgs for ConditionFormat2<'_> {
4484 type Args = ();
4485}
4486
4487impl<'a> FontRead<'a> for ConditionFormat2<'a> {
4488 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4489 #[allow(clippy::absurd_extreme_comparisons)]
4490 if data.len() < Self::MIN_SIZE {
4491 return Err(ReadError::OutOfBounds);
4492 }
4493 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4494 return Err(ReadError::OutOfBounds);
4495 };
4496 Ok(Self { data })
4497 }
4498}
4499
4500#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4502#[repr(C, packed)]
4503#[doc(hidden)]
4504pub struct ConditionFormat2FixedHeader {
4505 pub format: BigEndian<u16>,
4506 pub default_value: BigEndian<i16>,
4507 pub var_index: BigEndian<u32>,
4508}
4509
4510#[allow(clippy::absurd_extreme_comparisons)]
4511const _: () =
4512 assert!(std::mem::size_of::<ConditionFormat2FixedHeader>() <= ConditionFormat2::MIN_SIZE);
4513
4514#[derive(Clone)]
4516pub struct ConditionFormat2<'a> {
4517 data: TableDataRef<'a, ConditionFormat2FixedHeader>,
4518}
4519
4520#[allow(clippy::needless_lifetimes)]
4521impl<'a> ConditionFormat2<'a> {
4522 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4523 basic_table_impls!(impl_the_methods);
4524
4525 pub fn format(&self) -> u16 {
4527 self.data.header().format.get()
4528 }
4529
4530 pub fn default_value(&self) -> i16 {
4532 self.data.header().default_value.get()
4533 }
4534
4535 pub fn var_index(&self) -> u32 {
4537 self.data.header().var_index.get()
4538 }
4539
4540 pub fn format_byte_range(&self) -> Range<usize> {
4541 let start = 0;
4542 let end = start + u16::RAW_BYTE_LEN;
4543 start..end
4544 }
4545
4546 pub fn default_value_byte_range(&self) -> Range<usize> {
4547 let start = self.format_byte_range().end;
4548 let end = start + i16::RAW_BYTE_LEN;
4549 start..end
4550 }
4551
4552 pub fn var_index_byte_range(&self) -> Range<usize> {
4553 let start = self.default_value_byte_range().end;
4554 let end = start + u32::RAW_BYTE_LEN;
4555 start..end
4556 }
4557}
4558
4559impl Format<u16> for ConditionFormat3<'_> {
4560 const FORMAT: u16 = 3;
4561}
4562
4563impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
4564 fn min_byte_range(&self) -> Range<usize> {
4565 0..self.condition_offsets_byte_range().end
4566 }
4567 fn min_table_bytes(&self) -> &'a [u8] {
4568 let range = self.min_byte_range();
4569 self.offset_data().as_bytes().get(range).unwrap_or_default()
4570 }
4571}
4572
4573impl ReadArgs for ConditionFormat3<'_> {
4574 type Args = ();
4575}
4576
4577impl<'a> FontRead<'a> for ConditionFormat3<'a> {
4578 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4579 #[allow(clippy::absurd_extreme_comparisons)]
4580 if data.len() < Self::MIN_SIZE {
4581 return Err(ReadError::OutOfBounds);
4582 }
4583 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4584 return Err(ReadError::OutOfBounds);
4585 };
4586 Ok(Self { data })
4587 }
4588}
4589
4590#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4592#[repr(C, packed)]
4593#[doc(hidden)]
4594pub struct ConditionFormat3FixedHeader {
4595 pub format: BigEndian<u16>,
4596 pub condition_count: u8,
4597}
4598
4599#[allow(clippy::absurd_extreme_comparisons)]
4600const _: () =
4601 assert!(std::mem::size_of::<ConditionFormat3FixedHeader>() <= ConditionFormat3::MIN_SIZE);
4602
4603#[derive(Clone)]
4605pub struct ConditionFormat3<'a> {
4606 data: TableDataRef<'a, ConditionFormat3FixedHeader>,
4607}
4608
4609#[allow(clippy::needless_lifetimes)]
4610impl<'a> ConditionFormat3<'a> {
4611 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
4612 basic_table_impls!(impl_the_methods);
4613
4614 pub fn format(&self) -> u16 {
4616 self.data.header().format.get()
4617 }
4618
4619 pub fn condition_count(&self) -> u8 {
4621 self.data.header().condition_count
4622 }
4623
4624 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
4626 let range = self.condition_offsets_byte_range();
4627 self.offset_data()
4628 .read_array(range)
4629 .ok()
4630 .unwrap_or_default()
4631 }
4632
4633 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
4635 let data = self.offset_data();
4636 let offsets = self.condition_offsets();
4637 ArrayOfOffsets::new(offsets, data, ())
4638 }
4639
4640 pub fn format_byte_range(&self) -> Range<usize> {
4641 let start = 0;
4642 let end = start + u16::RAW_BYTE_LEN;
4643 start..end
4644 }
4645
4646 pub fn condition_count_byte_range(&self) -> Range<usize> {
4647 let start = self.format_byte_range().end;
4648 let end = start + u8::RAW_BYTE_LEN;
4649 start..end
4650 }
4651
4652 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4653 let condition_count = self.condition_count();
4654 let start = self.condition_count_byte_range().end;
4655 let end =
4656 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
4657 start..end
4658 }
4659}
4660
4661impl Format<u16> for ConditionFormat4<'_> {
4662 const FORMAT: u16 = 4;
4663}
4664
4665impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
4666 fn min_byte_range(&self) -> Range<usize> {
4667 0..self.condition_offsets_byte_range().end
4668 }
4669 fn min_table_bytes(&self) -> &'a [u8] {
4670 let range = self.min_byte_range();
4671 self.offset_data().as_bytes().get(range).unwrap_or_default()
4672 }
4673}
4674
4675impl ReadArgs for ConditionFormat4<'_> {
4676 type Args = ();
4677}
4678
4679impl<'a> FontRead<'a> for ConditionFormat4<'a> {
4680 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4681 #[allow(clippy::absurd_extreme_comparisons)]
4682 if data.len() < Self::MIN_SIZE {
4683 return Err(ReadError::OutOfBounds);
4684 }
4685 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4686 return Err(ReadError::OutOfBounds);
4687 };
4688 Ok(Self { data })
4689 }
4690}
4691
4692#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4694#[repr(C, packed)]
4695#[doc(hidden)]
4696pub struct ConditionFormat4FixedHeader {
4697 pub format: BigEndian<u16>,
4698 pub condition_count: u8,
4699}
4700
4701#[allow(clippy::absurd_extreme_comparisons)]
4702const _: () =
4703 assert!(std::mem::size_of::<ConditionFormat4FixedHeader>() <= ConditionFormat4::MIN_SIZE);
4704
4705#[derive(Clone)]
4707pub struct ConditionFormat4<'a> {
4708 data: TableDataRef<'a, ConditionFormat4FixedHeader>,
4709}
4710
4711#[allow(clippy::needless_lifetimes)]
4712impl<'a> ConditionFormat4<'a> {
4713 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
4714 basic_table_impls!(impl_the_methods);
4715
4716 pub fn format(&self) -> u16 {
4718 self.data.header().format.get()
4719 }
4720
4721 pub fn condition_count(&self) -> u8 {
4723 self.data.header().condition_count
4724 }
4725
4726 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
4728 let range = self.condition_offsets_byte_range();
4729 self.offset_data()
4730 .read_array(range)
4731 .ok()
4732 .unwrap_or_default()
4733 }
4734
4735 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
4737 let data = self.offset_data();
4738 let offsets = self.condition_offsets();
4739 ArrayOfOffsets::new(offsets, data, ())
4740 }
4741
4742 pub fn format_byte_range(&self) -> Range<usize> {
4743 let start = 0;
4744 let end = start + u16::RAW_BYTE_LEN;
4745 start..end
4746 }
4747
4748 pub fn condition_count_byte_range(&self) -> Range<usize> {
4749 let start = self.format_byte_range().end;
4750 let end = start + u8::RAW_BYTE_LEN;
4751 start..end
4752 }
4753
4754 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4755 let condition_count = self.condition_count();
4756 let start = self.condition_count_byte_range().end;
4757 let end =
4758 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
4759 start..end
4760 }
4761}
4762
4763impl Format<u16> for ConditionFormat5<'_> {
4764 const FORMAT: u16 = 5;
4765}
4766
4767impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
4768 fn min_byte_range(&self) -> Range<usize> {
4769 0..self.condition_offset_byte_range().end
4770 }
4771 fn min_table_bytes(&self) -> &'a [u8] {
4772 let range = self.min_byte_range();
4773 self.offset_data().as_bytes().get(range).unwrap_or_default()
4774 }
4775}
4776
4777impl ReadArgs for ConditionFormat5<'_> {
4778 type Args = ();
4779}
4780
4781impl<'a> FontRead<'a> for ConditionFormat5<'a> {
4782 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4783 #[allow(clippy::absurd_extreme_comparisons)]
4784 if data.len() < Self::MIN_SIZE {
4785 return Err(ReadError::OutOfBounds);
4786 }
4787 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4788 return Err(ReadError::OutOfBounds);
4789 };
4790 Ok(Self { data })
4791 }
4792}
4793
4794#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4796#[repr(C, packed)]
4797#[doc(hidden)]
4798pub struct ConditionFormat5FixedHeader {
4799 pub format: BigEndian<u16>,
4800 pub condition_offset: BigEndian<Offset24>,
4801}
4802
4803#[allow(clippy::absurd_extreme_comparisons)]
4804const _: () =
4805 assert!(std::mem::size_of::<ConditionFormat5FixedHeader>() <= ConditionFormat5::MIN_SIZE);
4806
4807#[derive(Clone)]
4809pub struct ConditionFormat5<'a> {
4810 data: TableDataRef<'a, ConditionFormat5FixedHeader>,
4811}
4812
4813#[allow(clippy::needless_lifetimes)]
4814impl<'a> ConditionFormat5<'a> {
4815 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
4816 basic_table_impls!(impl_the_methods);
4817
4818 pub fn format(&self) -> u16 {
4820 self.data.header().format.get()
4821 }
4822
4823 pub fn condition_offset(&self) -> Offset24 {
4825 self.data.header().condition_offset.get()
4826 }
4827
4828 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
4830 let data = self.offset_data();
4831 self.condition_offset().resolve(data)
4832 }
4833
4834 pub fn format_byte_range(&self) -> Range<usize> {
4835 let start = 0;
4836 let end = start + u16::RAW_BYTE_LEN;
4837 start..end
4838 }
4839
4840 pub fn condition_offset_byte_range(&self) -> Range<usize> {
4841 let start = self.format_byte_range().end;
4842 let end = start + Offset24::RAW_BYTE_LEN;
4843 start..end
4844 }
4845}
4846
4847impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
4848 fn min_byte_range(&self) -> Range<usize> {
4849 0..self.substitutions_byte_range().end
4850 }
4851 fn min_table_bytes(&self) -> &'a [u8] {
4852 let range = self.min_byte_range();
4853 self.offset_data().as_bytes().get(range).unwrap_or_default()
4854 }
4855}
4856
4857impl ReadArgs for FeatureTableSubstitution<'_> {
4858 type Args = ();
4859}
4860
4861impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
4862 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4863 #[allow(clippy::absurd_extreme_comparisons)]
4864 if data.len() < Self::MIN_SIZE {
4865 return Err(ReadError::OutOfBounds);
4866 }
4867 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4868 return Err(ReadError::OutOfBounds);
4869 };
4870 Ok(Self { data })
4871 }
4872}
4873
4874#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4876#[repr(C, packed)]
4877#[doc(hidden)]
4878pub struct FeatureTableSubstitutionFixedHeader {
4879 pub version: BigEndian<MajorMinor>,
4880 pub substitution_count: BigEndian<u16>,
4881}
4882
4883#[allow(clippy::absurd_extreme_comparisons)]
4884const _: () = assert!(
4885 std::mem::size_of::<FeatureTableSubstitutionFixedHeader>()
4886 <= FeatureTableSubstitution::MIN_SIZE
4887);
4888
4889#[derive(Clone)]
4891pub struct FeatureTableSubstitution<'a> {
4892 data: TableDataRef<'a, FeatureTableSubstitutionFixedHeader>,
4893}
4894
4895#[allow(clippy::needless_lifetimes)]
4896impl<'a> FeatureTableSubstitution<'a> {
4897 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
4898 basic_table_impls!(impl_the_methods);
4899
4900 pub fn version(&self) -> MajorMinor {
4902 self.data.header().version.get()
4903 }
4904
4905 pub fn substitution_count(&self) -> u16 {
4907 self.data.header().substitution_count.get()
4908 }
4909
4910 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
4912 let range = self.substitutions_byte_range();
4913 self.offset_data()
4914 .read_array(range)
4915 .ok()
4916 .unwrap_or_default()
4917 }
4918
4919 pub fn version_byte_range(&self) -> Range<usize> {
4920 let start = 0;
4921 let end = start + MajorMinor::RAW_BYTE_LEN;
4922 start..end
4923 }
4924
4925 pub fn substitution_count_byte_range(&self) -> Range<usize> {
4926 let start = self.version_byte_range().end;
4927 let end = start + u16::RAW_BYTE_LEN;
4928 start..end
4929 }
4930
4931 pub fn substitutions_byte_range(&self) -> Range<usize> {
4932 let substitution_count = self.substitution_count();
4933 let start = self.substitution_count_byte_range().end;
4934 let end = start
4935 + (transforms::to_usize(substitution_count))
4936 .saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN);
4937 start..end
4938 }
4939}
4940
4941const _: () = assert!(FontData::default_data_long_enough(
4942 FeatureTableSubstitution::MIN_SIZE
4943));
4944
4945impl Default for FeatureTableSubstitution<'_> {
4946 fn default() -> Self {
4947 Self {
4948 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4949 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4950 }
4951 }
4952}
4953
4954#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4956#[repr(C)]
4957#[repr(packed)]
4958pub struct FeatureTableSubstitutionRecord {
4959 pub feature_index: BigEndian<u16>,
4961 pub alternate_feature_offset: BigEndian<Offset32>,
4964}
4965
4966impl FeatureTableSubstitutionRecord {
4967 pub fn feature_index(&self) -> u16 {
4969 self.feature_index.get()
4970 }
4971
4972 pub fn alternate_feature_offset(&self) -> Offset32 {
4975 self.alternate_feature_offset.get()
4976 }
4977}
4978
4979impl FixedSize for FeatureTableSubstitutionRecord {
4980 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4981}
4982
4983impl<'a> MinByteRange<'a> for SizeParams<'a> {
4984 fn min_byte_range(&self) -> Range<usize> {
4985 0..self.range_end_byte_range().end
4986 }
4987 fn min_table_bytes(&self) -> &'a [u8] {
4988 let range = self.min_byte_range();
4989 self.offset_data().as_bytes().get(range).unwrap_or_default()
4990 }
4991}
4992
4993impl ReadArgs for SizeParams<'_> {
4994 type Args = ();
4995}
4996
4997impl<'a> FontRead<'a> for SizeParams<'a> {
4998 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4999 #[allow(clippy::absurd_extreme_comparisons)]
5000 if data.len() < Self::MIN_SIZE {
5001 return Err(ReadError::OutOfBounds);
5002 }
5003 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5004 return Err(ReadError::OutOfBounds);
5005 };
5006 Ok(Self { data })
5007 }
5008}
5009
5010#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5012#[repr(C, packed)]
5013#[doc(hidden)]
5014pub struct SizeParamsFixedHeader {
5015 pub design_size: BigEndian<u16>,
5016 pub identifier: BigEndian<u16>,
5017 pub name_entry: BigEndian<u16>,
5018 pub range_start: BigEndian<u16>,
5019 pub range_end: BigEndian<u16>,
5020}
5021
5022#[allow(clippy::absurd_extreme_comparisons)]
5023const _: () = assert!(std::mem::size_of::<SizeParamsFixedHeader>() <= SizeParams::MIN_SIZE);
5024
5025#[derive(Clone)]
5026pub struct SizeParams<'a> {
5027 data: TableDataRef<'a, SizeParamsFixedHeader>,
5028}
5029
5030#[allow(clippy::needless_lifetimes)]
5031impl<'a> SizeParams<'a> {
5032 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5033 + u16::RAW_BYTE_LEN
5034 + u16::RAW_BYTE_LEN
5035 + u16::RAW_BYTE_LEN
5036 + u16::RAW_BYTE_LEN);
5037 basic_table_impls!(impl_the_methods);
5038
5039 pub fn design_size(&self) -> u16 {
5044 self.data.header().design_size.get()
5045 }
5046
5047 pub fn identifier(&self) -> u16 {
5054 self.data.header().identifier.get()
5055 }
5056
5057 pub fn name_entry(&self) -> u16 {
5068 self.data.header().name_entry.get()
5069 }
5070
5071 pub fn range_start(&self) -> u16 {
5077 self.data.header().range_start.get()
5078 }
5079
5080 pub fn range_end(&self) -> u16 {
5081 self.data.header().range_end.get()
5082 }
5083
5084 pub fn design_size_byte_range(&self) -> Range<usize> {
5085 let start = 0;
5086 let end = start + u16::RAW_BYTE_LEN;
5087 start..end
5088 }
5089
5090 pub fn identifier_byte_range(&self) -> Range<usize> {
5091 let start = self.design_size_byte_range().end;
5092 let end = start + u16::RAW_BYTE_LEN;
5093 start..end
5094 }
5095
5096 pub fn name_entry_byte_range(&self) -> Range<usize> {
5097 let start = self.identifier_byte_range().end;
5098 let end = start + u16::RAW_BYTE_LEN;
5099 start..end
5100 }
5101
5102 pub fn range_start_byte_range(&self) -> Range<usize> {
5103 let start = self.name_entry_byte_range().end;
5104 let end = start + u16::RAW_BYTE_LEN;
5105 start..end
5106 }
5107
5108 pub fn range_end_byte_range(&self) -> Range<usize> {
5109 let start = self.range_start_byte_range().end;
5110 let end = start + u16::RAW_BYTE_LEN;
5111 start..end
5112 }
5113}
5114
5115const _: () = assert!(FontData::default_data_long_enough(SizeParams::MIN_SIZE));
5116
5117impl Default for SizeParams<'_> {
5118 fn default() -> Self {
5119 Self {
5120 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5121 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5122 }
5123 }
5124}
5125
5126impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
5127 fn min_byte_range(&self) -> Range<usize> {
5128 0..self.ui_name_id_byte_range().end
5129 }
5130 fn min_table_bytes(&self) -> &'a [u8] {
5131 let range = self.min_byte_range();
5132 self.offset_data().as_bytes().get(range).unwrap_or_default()
5133 }
5134}
5135
5136impl ReadArgs for StylisticSetParams<'_> {
5137 type Args = ();
5138}
5139
5140impl<'a> FontRead<'a> for StylisticSetParams<'a> {
5141 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5142 #[allow(clippy::absurd_extreme_comparisons)]
5143 if data.len() < Self::MIN_SIZE {
5144 return Err(ReadError::OutOfBounds);
5145 }
5146 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5147 return Err(ReadError::OutOfBounds);
5148 };
5149 Ok(Self { data })
5150 }
5151}
5152
5153#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5155#[repr(C, packed)]
5156#[doc(hidden)]
5157pub struct StylisticSetParamsFixedHeader {
5158 pub version: BigEndian<u16>,
5159 pub ui_name_id: BigEndian<NameId>,
5160}
5161
5162#[allow(clippy::absurd_extreme_comparisons)]
5163const _: () =
5164 assert!(std::mem::size_of::<StylisticSetParamsFixedHeader>() <= StylisticSetParams::MIN_SIZE);
5165
5166#[derive(Clone)]
5167pub struct StylisticSetParams<'a> {
5168 data: TableDataRef<'a, StylisticSetParamsFixedHeader>,
5169}
5170
5171#[allow(clippy::needless_lifetimes)]
5172impl<'a> StylisticSetParams<'a> {
5173 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
5174 basic_table_impls!(impl_the_methods);
5175
5176 pub fn version(&self) -> u16 {
5177 self.data.header().version.get()
5178 }
5179
5180 pub fn ui_name_id(&self) -> NameId {
5190 self.data.header().ui_name_id.get()
5191 }
5192
5193 pub fn version_byte_range(&self) -> Range<usize> {
5194 let start = 0;
5195 let end = start + u16::RAW_BYTE_LEN;
5196 start..end
5197 }
5198
5199 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
5200 let start = self.version_byte_range().end;
5201 let end = start + NameId::RAW_BYTE_LEN;
5202 start..end
5203 }
5204}
5205
5206const _: () = assert!(FontData::default_data_long_enough(
5207 StylisticSetParams::MIN_SIZE
5208));
5209
5210impl Default for StylisticSetParams<'_> {
5211 fn default() -> Self {
5212 Self {
5213 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5214 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5215 }
5216 }
5217}
5218
5219impl Format<u16> for CharacterVariantParams<'_> {
5220 const FORMAT: u16 = 0;
5221}
5222
5223impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
5224 fn min_byte_range(&self) -> Range<usize> {
5225 0..self.character_byte_range().end
5226 }
5227 fn min_table_bytes(&self) -> &'a [u8] {
5228 let range = self.min_byte_range();
5229 self.offset_data().as_bytes().get(range).unwrap_or_default()
5230 }
5231}
5232
5233impl ReadArgs for CharacterVariantParams<'_> {
5234 type Args = ();
5235}
5236
5237impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
5238 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5239 #[allow(clippy::absurd_extreme_comparisons)]
5240 if data.len() < Self::MIN_SIZE {
5241 return Err(ReadError::OutOfBounds);
5242 }
5243 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5244 return Err(ReadError::OutOfBounds);
5245 };
5246 Ok(Self { data })
5247 }
5248}
5249
5250#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5252#[repr(C, packed)]
5253#[doc(hidden)]
5254pub struct CharacterVariantParamsFixedHeader {
5255 pub format: BigEndian<u16>,
5256 pub feat_ui_label_name_id: BigEndian<NameId>,
5257 pub feat_ui_tooltip_text_name_id: BigEndian<NameId>,
5258 pub sample_text_name_id: BigEndian<NameId>,
5259 pub num_named_parameters: BigEndian<u16>,
5260 pub first_param_ui_label_name_id: BigEndian<NameId>,
5261 pub char_count: BigEndian<u16>,
5262}
5263
5264#[allow(clippy::absurd_extreme_comparisons)]
5265const _: () = assert!(
5266 std::mem::size_of::<CharacterVariantParamsFixedHeader>() <= CharacterVariantParams::MIN_SIZE
5267);
5268
5269#[derive(Clone)]
5271pub struct CharacterVariantParams<'a> {
5272 data: TableDataRef<'a, CharacterVariantParamsFixedHeader>,
5273}
5274
5275#[allow(clippy::needless_lifetimes)]
5276impl<'a> CharacterVariantParams<'a> {
5277 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5278 + NameId::RAW_BYTE_LEN
5279 + NameId::RAW_BYTE_LEN
5280 + NameId::RAW_BYTE_LEN
5281 + u16::RAW_BYTE_LEN
5282 + NameId::RAW_BYTE_LEN
5283 + u16::RAW_BYTE_LEN);
5284 basic_table_impls!(impl_the_methods);
5285
5286 pub fn format(&self) -> u16 {
5288 self.data.header().format.get()
5289 }
5290
5291 pub fn feat_ui_label_name_id(&self) -> NameId {
5295 self.data.header().feat_ui_label_name_id.get()
5296 }
5297
5298 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
5302 self.data.header().feat_ui_tooltip_text_name_id.get()
5303 }
5304
5305 pub fn sample_text_name_id(&self) -> NameId {
5308 self.data.header().sample_text_name_id.get()
5309 }
5310
5311 pub fn num_named_parameters(&self) -> u16 {
5313 self.data.header().num_named_parameters.get()
5314 }
5315
5316 pub fn first_param_ui_label_name_id(&self) -> NameId {
5320 self.data.header().first_param_ui_label_name_id.get()
5321 }
5322
5323 pub fn char_count(&self) -> u16 {
5326 self.data.header().char_count.get()
5327 }
5328
5329 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
5332 let range = self.character_byte_range();
5333 self.offset_data()
5334 .read_array(range)
5335 .ok()
5336 .unwrap_or_default()
5337 }
5338
5339 pub fn format_byte_range(&self) -> Range<usize> {
5340 let start = 0;
5341 let end = start + u16::RAW_BYTE_LEN;
5342 start..end
5343 }
5344
5345 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
5346 let start = self.format_byte_range().end;
5347 let end = start + NameId::RAW_BYTE_LEN;
5348 start..end
5349 }
5350
5351 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
5352 let start = self.feat_ui_label_name_id_byte_range().end;
5353 let end = start + NameId::RAW_BYTE_LEN;
5354 start..end
5355 }
5356
5357 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
5358 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
5359 let end = start + NameId::RAW_BYTE_LEN;
5360 start..end
5361 }
5362
5363 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
5364 let start = self.sample_text_name_id_byte_range().end;
5365 let end = start + u16::RAW_BYTE_LEN;
5366 start..end
5367 }
5368
5369 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
5370 let start = self.num_named_parameters_byte_range().end;
5371 let end = start + NameId::RAW_BYTE_LEN;
5372 start..end
5373 }
5374
5375 pub fn char_count_byte_range(&self) -> Range<usize> {
5376 let start = self.first_param_ui_label_name_id_byte_range().end;
5377 let end = start + u16::RAW_BYTE_LEN;
5378 start..end
5379 }
5380
5381 pub fn character_byte_range(&self) -> Range<usize> {
5382 let char_count = self.char_count();
5383 let start = self.char_count_byte_range().end;
5384 let end = start + (transforms::to_usize(char_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
5385 start..end
5386 }
5387}
5388
5389const _: () = assert!(FontData::default_data_long_enough(
5390 CharacterVariantParams::MIN_SIZE
5391));
5392
5393impl Default for CharacterVariantParams<'_> {
5394 fn default() -> Self {
5395 Self {
5396 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5397 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5398 }
5399 }
5400}