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 Format3(CoverageFormat3<'a>),
1170 Format4(CoverageFormat4<'a>),
1171}
1172
1173impl Default for CoverageTable<'_> {
1174 fn default() -> Self {
1175 Self::Format1(Default::default())
1176 }
1177}
1178
1179impl<'a> CoverageTable<'a> {
1180 pub fn offset_data(&self) -> FontData<'a> {
1182 match self {
1183 Self::Format1(item) => item.offset_data(),
1184 Self::Format2(item) => item.offset_data(),
1185 Self::Format3(item) => item.offset_data(),
1186 Self::Format4(item) => item.offset_data(),
1187 }
1188 }
1189
1190 pub fn coverage_format(&self) -> u16 {
1192 match self {
1193 Self::Format1(item) => item.coverage_format(),
1194 Self::Format2(item) => item.coverage_format(),
1195 Self::Format3(item) => item.coverage_format(),
1196 Self::Format4(item) => item.coverage_format(),
1197 }
1198 }
1199}
1200
1201impl ReadArgs for CoverageTable<'_> {
1202 type Args = ();
1203}
1204
1205impl<'a> FontRead<'a> for CoverageTable<'a> {
1206 #[inline]
1207 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1208 let format: u16 = data.read_at(0usize)?;
1209 match format {
1210 CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1211 CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1212 CoverageFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
1213 CoverageFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
1214 other => Err(ReadError::InvalidFormat(other.into())),
1215 }
1216 }
1217}
1218
1219impl<'a> MinByteRange<'a> for CoverageTable<'a> {
1220 fn min_byte_range(&self) -> Range<usize> {
1221 match self {
1222 Self::Format1(item) => item.min_byte_range(),
1223 Self::Format2(item) => item.min_byte_range(),
1224 Self::Format3(item) => item.min_byte_range(),
1225 Self::Format4(item) => item.min_byte_range(),
1226 }
1227 }
1228 fn min_table_bytes(&self) -> &'a [u8] {
1229 match self {
1230 Self::Format1(item) => item.min_table_bytes(),
1231 Self::Format2(item) => item.min_table_bytes(),
1232 Self::Format3(item) => item.min_table_bytes(),
1233 Self::Format4(item) => item.min_table_bytes(),
1234 }
1235 }
1236}
1237
1238impl Format<u16> for ClassDefFormat1<'_> {
1239 const FORMAT: u16 = 1;
1240}
1241
1242impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
1243 fn min_byte_range(&self) -> Range<usize> {
1244 0..self.class_value_array_byte_range().end
1245 }
1246 fn min_table_bytes(&self) -> &'a [u8] {
1247 let range = self.min_byte_range();
1248 self.offset_data().as_bytes().get(range).unwrap_or_default()
1249 }
1250}
1251
1252impl ReadArgs for ClassDefFormat1<'_> {
1253 type Args = ();
1254}
1255
1256impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1257 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1258 #[allow(clippy::absurd_extreme_comparisons)]
1259 if data.len() < Self::MIN_SIZE {
1260 return Err(ReadError::OutOfBounds);
1261 }
1262 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1263 return Err(ReadError::OutOfBounds);
1264 };
1265 Ok(Self { data })
1266 }
1267}
1268
1269#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1271#[repr(C, packed)]
1272#[doc(hidden)]
1273pub struct ClassDefFormat1FixedHeader {
1274 pub class_format: BigEndian<u16>,
1275 pub start_glyph_id: BigEndian<GlyphId16>,
1276 pub glyph_count: BigEndian<u16>,
1277}
1278
1279#[allow(clippy::absurd_extreme_comparisons)]
1280const _: () =
1281 assert!(std::mem::size_of::<ClassDefFormat1FixedHeader>() <= ClassDefFormat1::MIN_SIZE);
1282
1283#[derive(Clone)]
1285pub struct ClassDefFormat1<'a> {
1286 data: TableDataRef<'a, ClassDefFormat1FixedHeader>,
1287}
1288
1289#[allow(clippy::needless_lifetimes)]
1290impl<'a> ClassDefFormat1<'a> {
1291 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1292 basic_table_impls!(impl_the_methods);
1293
1294 pub fn class_format(&self) -> u16 {
1296 self.data.header().class_format.get()
1297 }
1298
1299 pub fn start_glyph_id(&self) -> GlyphId16 {
1301 self.data.header().start_glyph_id.get()
1302 }
1303
1304 pub fn glyph_count(&self) -> u16 {
1306 self.data.header().glyph_count.get()
1307 }
1308
1309 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1311 let range = self.class_value_array_byte_range();
1312 self.offset_data()
1313 .read_array(range)
1314 .ok()
1315 .unwrap_or_default()
1316 }
1317
1318 pub fn class_format_byte_range(&self) -> Range<usize> {
1319 let start = 0;
1320 let end = start + u16::RAW_BYTE_LEN;
1321 start..end
1322 }
1323
1324 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1325 let start = self.class_format_byte_range().end;
1326 let end = start + GlyphId16::RAW_BYTE_LEN;
1327 start..end
1328 }
1329
1330 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1331 let start = self.start_glyph_id_byte_range().end;
1332 let end = start + u16::RAW_BYTE_LEN;
1333 start..end
1334 }
1335
1336 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1337 let glyph_count = self.glyph_count();
1338 let start = self.glyph_count_byte_range().end;
1339 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
1340 start..end
1341 }
1342}
1343
1344const _: () = assert!(FontData::default_data_long_enough(
1345 ClassDefFormat1::MIN_SIZE
1346));
1347
1348impl Default for ClassDefFormat1<'_> {
1349 fn default() -> Self {
1350 Self {
1351 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1352 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1353 }
1354 }
1355}
1356
1357impl Format<u16> for ClassDefFormat2<'_> {
1358 const FORMAT: u16 = 2;
1359}
1360
1361impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
1362 fn min_byte_range(&self) -> Range<usize> {
1363 0..self.class_range_records_byte_range().end
1364 }
1365 fn min_table_bytes(&self) -> &'a [u8] {
1366 let range = self.min_byte_range();
1367 self.offset_data().as_bytes().get(range).unwrap_or_default()
1368 }
1369}
1370
1371impl ReadArgs for ClassDefFormat2<'_> {
1372 type Args = ();
1373}
1374
1375impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1376 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1377 #[allow(clippy::absurd_extreme_comparisons)]
1378 if data.len() < Self::MIN_SIZE {
1379 return Err(ReadError::OutOfBounds);
1380 }
1381 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1382 return Err(ReadError::OutOfBounds);
1383 };
1384 Ok(Self { data })
1385 }
1386}
1387
1388#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1390#[repr(C, packed)]
1391#[doc(hidden)]
1392pub struct ClassDefFormat2FixedHeader {
1393 pub class_format: BigEndian<u16>,
1394 pub class_range_count: BigEndian<u16>,
1395}
1396
1397#[allow(clippy::absurd_extreme_comparisons)]
1398const _: () =
1399 assert!(std::mem::size_of::<ClassDefFormat2FixedHeader>() <= ClassDefFormat2::MIN_SIZE);
1400
1401#[derive(Clone)]
1403pub struct ClassDefFormat2<'a> {
1404 data: TableDataRef<'a, ClassDefFormat2FixedHeader>,
1405}
1406
1407#[allow(clippy::needless_lifetimes)]
1408impl<'a> ClassDefFormat2<'a> {
1409 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1410 basic_table_impls!(impl_the_methods);
1411
1412 pub fn class_format(&self) -> u16 {
1414 self.data.header().class_format.get()
1415 }
1416
1417 pub fn class_range_count(&self) -> u16 {
1419 self.data.header().class_range_count.get()
1420 }
1421
1422 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1424 let range = self.class_range_records_byte_range();
1425 self.offset_data()
1426 .read_array(range)
1427 .ok()
1428 .unwrap_or_default()
1429 }
1430
1431 pub fn class_format_byte_range(&self) -> Range<usize> {
1432 let start = 0;
1433 let end = start + u16::RAW_BYTE_LEN;
1434 start..end
1435 }
1436
1437 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1438 let start = self.class_format_byte_range().end;
1439 let end = start + u16::RAW_BYTE_LEN;
1440 start..end
1441 }
1442
1443 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1444 let class_range_count = self.class_range_count();
1445 let start = self.class_range_count_byte_range().end;
1446 let end = start
1447 + (transforms::to_usize(class_range_count))
1448 .saturating_mul(ClassRangeRecord::RAW_BYTE_LEN);
1449 start..end
1450 }
1451}
1452
1453#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1455#[repr(C)]
1456#[repr(packed)]
1457pub struct ClassRangeRecord {
1458 pub start_glyph_id: BigEndian<GlyphId16>,
1460 pub end_glyph_id: BigEndian<GlyphId16>,
1462 pub class: BigEndian<u16>,
1464}
1465
1466impl ClassRangeRecord {
1467 pub fn start_glyph_id(&self) -> GlyphId16 {
1469 self.start_glyph_id.get()
1470 }
1471
1472 pub fn end_glyph_id(&self) -> GlyphId16 {
1474 self.end_glyph_id.get()
1475 }
1476
1477 pub fn class(&self) -> u16 {
1479 self.class.get()
1480 }
1481}
1482
1483impl FixedSize for ClassRangeRecord {
1484 const RAW_BYTE_LEN: usize =
1485 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1486}
1487
1488#[derive(Clone)]
1490pub enum ClassDef<'a> {
1491 Format1(ClassDefFormat1<'a>),
1492 Format2(ClassDefFormat2<'a>),
1493 Format3(ClassDefFormat3<'a>),
1494 Format4(ClassDefFormat4<'a>),
1495}
1496
1497impl Default for ClassDef<'_> {
1498 fn default() -> Self {
1499 Self::Format1(Default::default())
1500 }
1501}
1502
1503impl<'a> ClassDef<'a> {
1504 pub fn offset_data(&self) -> FontData<'a> {
1506 match self {
1507 Self::Format1(item) => item.offset_data(),
1508 Self::Format2(item) => item.offset_data(),
1509 Self::Format3(item) => item.offset_data(),
1510 Self::Format4(item) => item.offset_data(),
1511 }
1512 }
1513
1514 pub fn class_format(&self) -> u16 {
1516 match self {
1517 Self::Format1(item) => item.class_format(),
1518 Self::Format2(item) => item.class_format(),
1519 Self::Format3(item) => item.class_format(),
1520 Self::Format4(item) => item.class_format(),
1521 }
1522 }
1523}
1524
1525impl ReadArgs for ClassDef<'_> {
1526 type Args = ();
1527}
1528
1529impl<'a> FontRead<'a> for ClassDef<'a> {
1530 #[inline]
1531 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1532 let format: u16 = data.read_at(0usize)?;
1533 match format {
1534 ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1535 ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1536 ClassDefFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
1537 ClassDefFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
1538 other => Err(ReadError::InvalidFormat(other.into())),
1539 }
1540 }
1541}
1542
1543impl<'a> MinByteRange<'a> for ClassDef<'a> {
1544 fn min_byte_range(&self) -> Range<usize> {
1545 match self {
1546 Self::Format1(item) => item.min_byte_range(),
1547 Self::Format2(item) => item.min_byte_range(),
1548 Self::Format3(item) => item.min_byte_range(),
1549 Self::Format4(item) => item.min_byte_range(),
1550 }
1551 }
1552 fn min_table_bytes(&self) -> &'a [u8] {
1553 match self {
1554 Self::Format1(item) => item.min_table_bytes(),
1555 Self::Format2(item) => item.min_table_bytes(),
1556 Self::Format3(item) => item.min_table_bytes(),
1557 Self::Format4(item) => item.min_table_bytes(),
1558 }
1559 }
1560}
1561
1562#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1564#[repr(C)]
1565#[repr(packed)]
1566pub struct SequenceLookupRecord {
1567 pub sequence_index: BigEndian<u16>,
1569 pub lookup_list_index: BigEndian<u16>,
1571}
1572
1573impl SequenceLookupRecord {
1574 pub fn sequence_index(&self) -> u16 {
1576 self.sequence_index.get()
1577 }
1578
1579 pub fn lookup_list_index(&self) -> u16 {
1581 self.lookup_list_index.get()
1582 }
1583}
1584
1585impl FixedSize for SequenceLookupRecord {
1586 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1587}
1588
1589impl Format<u16> for SequenceContextFormat1<'_> {
1590 const FORMAT: u16 = 1;
1591}
1592
1593impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
1594 fn min_byte_range(&self) -> Range<usize> {
1595 0..self.seq_rule_set_offsets_byte_range().end
1596 }
1597 fn min_table_bytes(&self) -> &'a [u8] {
1598 let range = self.min_byte_range();
1599 self.offset_data().as_bytes().get(range).unwrap_or_default()
1600 }
1601}
1602
1603impl ReadArgs for SequenceContextFormat1<'_> {
1604 type Args = ();
1605}
1606
1607impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1608 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1609 #[allow(clippy::absurd_extreme_comparisons)]
1610 if data.len() < Self::MIN_SIZE {
1611 return Err(ReadError::OutOfBounds);
1612 }
1613 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1614 return Err(ReadError::OutOfBounds);
1615 };
1616 Ok(Self { data })
1617 }
1618}
1619
1620#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1622#[repr(C, packed)]
1623#[doc(hidden)]
1624pub struct SequenceContextFormat1FixedHeader {
1625 pub format: BigEndian<u16>,
1626 pub coverage_offset: BigEndian<Offset16>,
1627 pub seq_rule_set_count: BigEndian<u16>,
1628}
1629
1630#[allow(clippy::absurd_extreme_comparisons)]
1631const _: () = assert!(
1632 std::mem::size_of::<SequenceContextFormat1FixedHeader>() <= SequenceContextFormat1::MIN_SIZE
1633);
1634
1635#[derive(Clone)]
1637pub struct SequenceContextFormat1<'a> {
1638 data: TableDataRef<'a, SequenceContextFormat1FixedHeader>,
1639}
1640
1641#[allow(clippy::needless_lifetimes)]
1642impl<'a> SequenceContextFormat1<'a> {
1643 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1644 basic_table_impls!(impl_the_methods);
1645
1646 pub fn format(&self) -> u16 {
1648 self.data.header().format.get()
1649 }
1650
1651 pub fn coverage_offset(&self) -> Offset16 {
1654 self.data.header().coverage_offset.get()
1655 }
1656
1657 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1659 let data = self.offset_data();
1660 self.coverage_offset().resolve(data)
1661 }
1662
1663 pub fn seq_rule_set_count(&self) -> u16 {
1665 self.data.header().seq_rule_set_count.get()
1666 }
1667
1668 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1671 let range = self.seq_rule_set_offsets_byte_range();
1672 self.offset_data()
1673 .read_array(range)
1674 .ok()
1675 .unwrap_or_default()
1676 }
1677
1678 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1680 let data = self.offset_data();
1681 let offsets = self.seq_rule_set_offsets();
1682 ArrayOfNullableOffsets::new(offsets, data, ())
1683 }
1684
1685 pub fn format_byte_range(&self) -> Range<usize> {
1686 let start = 0;
1687 let end = start + u16::RAW_BYTE_LEN;
1688 start..end
1689 }
1690
1691 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1692 let start = self.format_byte_range().end;
1693 let end = start + Offset16::RAW_BYTE_LEN;
1694 start..end
1695 }
1696
1697 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1698 let start = self.coverage_offset_byte_range().end;
1699 let end = start + u16::RAW_BYTE_LEN;
1700 start..end
1701 }
1702
1703 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1704 let seq_rule_set_count = self.seq_rule_set_count();
1705 let start = self.seq_rule_set_count_byte_range().end;
1706 let end = start
1707 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1708 start..end
1709 }
1710}
1711
1712const _: () = assert!(FontData::default_data_long_enough(
1713 SequenceContextFormat1::MIN_SIZE
1714));
1715
1716impl Default for SequenceContextFormat1<'_> {
1717 fn default() -> Self {
1718 Self {
1719 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1720 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1721 }
1722 }
1723}
1724
1725impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
1726 fn min_byte_range(&self) -> Range<usize> {
1727 0..self.seq_rule_offsets_byte_range().end
1728 }
1729 fn min_table_bytes(&self) -> &'a [u8] {
1730 let range = self.min_byte_range();
1731 self.offset_data().as_bytes().get(range).unwrap_or_default()
1732 }
1733}
1734
1735impl ReadArgs for SequenceRuleSet<'_> {
1736 type Args = ();
1737}
1738
1739impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
1740 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1741 #[allow(clippy::absurd_extreme_comparisons)]
1742 if data.len() < Self::MIN_SIZE {
1743 return Err(ReadError::OutOfBounds);
1744 }
1745 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1746 return Err(ReadError::OutOfBounds);
1747 };
1748 Ok(Self { data })
1749 }
1750}
1751
1752#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1754#[repr(C, packed)]
1755#[doc(hidden)]
1756pub struct SequenceRuleSetFixedHeader {
1757 pub seq_rule_count: BigEndian<u16>,
1758}
1759
1760#[allow(clippy::absurd_extreme_comparisons)]
1761const _: () =
1762 assert!(std::mem::size_of::<SequenceRuleSetFixedHeader>() <= SequenceRuleSet::MIN_SIZE);
1763
1764#[derive(Clone)]
1766pub struct SequenceRuleSet<'a> {
1767 data: TableDataRef<'a, SequenceRuleSetFixedHeader>,
1768}
1769
1770#[allow(clippy::needless_lifetimes)]
1771impl<'a> SequenceRuleSet<'a> {
1772 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1773 basic_table_impls!(impl_the_methods);
1774
1775 pub fn seq_rule_count(&self) -> u16 {
1777 self.data.header().seq_rule_count.get()
1778 }
1779
1780 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
1783 let range = self.seq_rule_offsets_byte_range();
1784 self.offset_data()
1785 .read_array(range)
1786 .ok()
1787 .unwrap_or_default()
1788 }
1789
1790 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
1792 let data = self.offset_data();
1793 let offsets = self.seq_rule_offsets();
1794 ArrayOfOffsets::new(offsets, data, ())
1795 }
1796
1797 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
1798 let start = 0;
1799 let end = start + u16::RAW_BYTE_LEN;
1800 start..end
1801 }
1802
1803 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
1804 let seq_rule_count = self.seq_rule_count();
1805 let start = self.seq_rule_count_byte_range().end;
1806 let end =
1807 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1808 start..end
1809 }
1810}
1811
1812const _: () = assert!(FontData::default_data_long_enough(
1813 SequenceRuleSet::MIN_SIZE
1814));
1815
1816impl Default for SequenceRuleSet<'_> {
1817 fn default() -> Self {
1818 Self {
1819 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1820 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1821 }
1822 }
1823}
1824
1825impl<'a> MinByteRange<'a> for SequenceRule<'a> {
1826 fn min_byte_range(&self) -> Range<usize> {
1827 0..self.seq_lookup_records_byte_range().end
1828 }
1829 fn min_table_bytes(&self) -> &'a [u8] {
1830 let range = self.min_byte_range();
1831 self.offset_data().as_bytes().get(range).unwrap_or_default()
1832 }
1833}
1834
1835impl ReadArgs for SequenceRule<'_> {
1836 type Args = ();
1837}
1838
1839impl<'a> FontRead<'a> for SequenceRule<'a> {
1840 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1841 #[allow(clippy::absurd_extreme_comparisons)]
1842 if data.len() < Self::MIN_SIZE {
1843 return Err(ReadError::OutOfBounds);
1844 }
1845 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1846 return Err(ReadError::OutOfBounds);
1847 };
1848 Ok(Self { data })
1849 }
1850}
1851
1852#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1854#[repr(C, packed)]
1855#[doc(hidden)]
1856pub struct SequenceRuleFixedHeader {
1857 pub glyph_count: BigEndian<u16>,
1858 pub seq_lookup_count: BigEndian<u16>,
1859}
1860
1861#[allow(clippy::absurd_extreme_comparisons)]
1862const _: () = assert!(std::mem::size_of::<SequenceRuleFixedHeader>() <= SequenceRule::MIN_SIZE);
1863
1864#[derive(Clone)]
1866pub struct SequenceRule<'a> {
1867 data: TableDataRef<'a, SequenceRuleFixedHeader>,
1868}
1869
1870#[allow(clippy::needless_lifetimes)]
1871impl<'a> SequenceRule<'a> {
1872 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1873 basic_table_impls!(impl_the_methods);
1874
1875 pub fn glyph_count(&self) -> u16 {
1877 self.data.header().glyph_count.get()
1878 }
1879
1880 pub fn seq_lookup_count(&self) -> u16 {
1882 self.data.header().seq_lookup_count.get()
1883 }
1884
1885 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
1887 let range = self.input_sequence_byte_range();
1888 self.offset_data()
1889 .read_array(range)
1890 .ok()
1891 .unwrap_or_default()
1892 }
1893
1894 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
1896 let range = self.seq_lookup_records_byte_range();
1897 self.offset_data()
1898 .read_array(range)
1899 .ok()
1900 .unwrap_or_default()
1901 }
1902
1903 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1904 let start = 0;
1905 let end = start + u16::RAW_BYTE_LEN;
1906 start..end
1907 }
1908
1909 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
1910 let start = self.glyph_count_byte_range().end;
1911 let end = start + u16::RAW_BYTE_LEN;
1912 start..end
1913 }
1914
1915 pub fn input_sequence_byte_range(&self) -> Range<usize> {
1916 let glyph_count = self.glyph_count();
1917 let start = self.seq_lookup_count_byte_range().end;
1918 let end = start
1919 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1920 start..end
1921 }
1922
1923 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
1924 let seq_lookup_count = self.seq_lookup_count();
1925 let start = self.input_sequence_byte_range().end;
1926 let end = start
1927 + (transforms::to_usize(seq_lookup_count))
1928 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
1929 start..end
1930 }
1931}
1932
1933const _: () = assert!(FontData::default_data_long_enough(SequenceRule::MIN_SIZE));
1934
1935impl Default for SequenceRule<'_> {
1936 fn default() -> Self {
1937 Self {
1938 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1939 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1940 }
1941 }
1942}
1943
1944impl Format<u16> for SequenceContextFormat2<'_> {
1945 const FORMAT: u16 = 2;
1946}
1947
1948impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
1949 fn min_byte_range(&self) -> Range<usize> {
1950 0..self.class_seq_rule_set_offsets_byte_range().end
1951 }
1952 fn min_table_bytes(&self) -> &'a [u8] {
1953 let range = self.min_byte_range();
1954 self.offset_data().as_bytes().get(range).unwrap_or_default()
1955 }
1956}
1957
1958impl ReadArgs for SequenceContextFormat2<'_> {
1959 type Args = ();
1960}
1961
1962impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
1963 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1964 #[allow(clippy::absurd_extreme_comparisons)]
1965 if data.len() < Self::MIN_SIZE {
1966 return Err(ReadError::OutOfBounds);
1967 }
1968 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1969 return Err(ReadError::OutOfBounds);
1970 };
1971 Ok(Self { data })
1972 }
1973}
1974
1975#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1977#[repr(C, packed)]
1978#[doc(hidden)]
1979pub struct SequenceContextFormat2FixedHeader {
1980 pub format: BigEndian<u16>,
1981 pub coverage_offset: BigEndian<Offset16>,
1982 pub class_def_offset: BigEndian<Offset16>,
1983 pub class_seq_rule_set_count: BigEndian<u16>,
1984}
1985
1986#[allow(clippy::absurd_extreme_comparisons)]
1987const _: () = assert!(
1988 std::mem::size_of::<SequenceContextFormat2FixedHeader>() <= SequenceContextFormat2::MIN_SIZE
1989);
1990
1991#[derive(Clone)]
1993pub struct SequenceContextFormat2<'a> {
1994 data: TableDataRef<'a, SequenceContextFormat2FixedHeader>,
1995}
1996
1997#[allow(clippy::needless_lifetimes)]
1998impl<'a> SequenceContextFormat2<'a> {
1999 pub const MIN_SIZE: usize =
2000 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2001 basic_table_impls!(impl_the_methods);
2002
2003 pub fn format(&self) -> u16 {
2005 self.data.header().format.get()
2006 }
2007
2008 pub fn coverage_offset(&self) -> Offset16 {
2011 self.data.header().coverage_offset.get()
2012 }
2013
2014 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2016 let data = self.offset_data();
2017 self.coverage_offset().resolve(data)
2018 }
2019
2020 pub fn class_def_offset(&self) -> Offset16 {
2023 self.data.header().class_def_offset.get()
2024 }
2025
2026 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2028 let data = self.offset_data();
2029 self.class_def_offset().resolve(data)
2030 }
2031
2032 pub fn class_seq_rule_set_count(&self) -> u16 {
2034 self.data.header().class_seq_rule_set_count.get()
2035 }
2036
2037 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2040 let range = self.class_seq_rule_set_offsets_byte_range();
2041 self.offset_data()
2042 .read_array(range)
2043 .ok()
2044 .unwrap_or_default()
2045 }
2046
2047 pub fn class_seq_rule_sets(
2049 &self,
2050 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
2051 let data = self.offset_data();
2052 let offsets = self.class_seq_rule_set_offsets();
2053 ArrayOfNullableOffsets::new(offsets, data, ())
2054 }
2055
2056 pub fn format_byte_range(&self) -> Range<usize> {
2057 let start = 0;
2058 let end = start + u16::RAW_BYTE_LEN;
2059 start..end
2060 }
2061
2062 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2063 let start = self.format_byte_range().end;
2064 let end = start + Offset16::RAW_BYTE_LEN;
2065 start..end
2066 }
2067
2068 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
2069 let start = self.coverage_offset_byte_range().end;
2070 let end = start + Offset16::RAW_BYTE_LEN;
2071 start..end
2072 }
2073
2074 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2075 let start = self.class_def_offset_byte_range().end;
2076 let end = start + u16::RAW_BYTE_LEN;
2077 start..end
2078 }
2079
2080 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2081 let class_seq_rule_set_count = self.class_seq_rule_set_count();
2082 let start = self.class_seq_rule_set_count_byte_range().end;
2083 let end = start
2084 + (transforms::to_usize(class_seq_rule_set_count))
2085 .saturating_mul(Offset16::RAW_BYTE_LEN);
2086 start..end
2087 }
2088}
2089
2090impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
2091 fn min_byte_range(&self) -> Range<usize> {
2092 0..self.class_seq_rule_offsets_byte_range().end
2093 }
2094 fn min_table_bytes(&self) -> &'a [u8] {
2095 let range = self.min_byte_range();
2096 self.offset_data().as_bytes().get(range).unwrap_or_default()
2097 }
2098}
2099
2100impl ReadArgs for ClassSequenceRuleSet<'_> {
2101 type Args = ();
2102}
2103
2104impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
2105 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2106 #[allow(clippy::absurd_extreme_comparisons)]
2107 if data.len() < Self::MIN_SIZE {
2108 return Err(ReadError::OutOfBounds);
2109 }
2110 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2111 return Err(ReadError::OutOfBounds);
2112 };
2113 Ok(Self { data })
2114 }
2115}
2116
2117#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2119#[repr(C, packed)]
2120#[doc(hidden)]
2121pub struct ClassSequenceRuleSetFixedHeader {
2122 pub class_seq_rule_count: BigEndian<u16>,
2123}
2124
2125#[allow(clippy::absurd_extreme_comparisons)]
2126const _: () = assert!(
2127 std::mem::size_of::<ClassSequenceRuleSetFixedHeader>() <= ClassSequenceRuleSet::MIN_SIZE
2128);
2129
2130#[derive(Clone)]
2132pub struct ClassSequenceRuleSet<'a> {
2133 data: TableDataRef<'a, ClassSequenceRuleSetFixedHeader>,
2134}
2135
2136#[allow(clippy::needless_lifetimes)]
2137impl<'a> ClassSequenceRuleSet<'a> {
2138 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2139 basic_table_impls!(impl_the_methods);
2140
2141 pub fn class_seq_rule_count(&self) -> u16 {
2143 self.data.header().class_seq_rule_count.get()
2144 }
2145
2146 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2149 let range = self.class_seq_rule_offsets_byte_range();
2150 self.offset_data()
2151 .read_array(range)
2152 .ok()
2153 .unwrap_or_default()
2154 }
2155
2156 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
2158 let data = self.offset_data();
2159 let offsets = self.class_seq_rule_offsets();
2160 ArrayOfOffsets::new(offsets, data, ())
2161 }
2162
2163 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
2164 let start = 0;
2165 let end = start + u16::RAW_BYTE_LEN;
2166 start..end
2167 }
2168
2169 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2170 let class_seq_rule_count = self.class_seq_rule_count();
2171 let start = self.class_seq_rule_count_byte_range().end;
2172 let end = start
2173 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2174 start..end
2175 }
2176}
2177
2178const _: () = assert!(FontData::default_data_long_enough(
2179 ClassSequenceRuleSet::MIN_SIZE
2180));
2181
2182impl Default for ClassSequenceRuleSet<'_> {
2183 fn default() -> Self {
2184 Self {
2185 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2186 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2187 }
2188 }
2189}
2190
2191impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
2192 fn min_byte_range(&self) -> Range<usize> {
2193 0..self.seq_lookup_records_byte_range().end
2194 }
2195 fn min_table_bytes(&self) -> &'a [u8] {
2196 let range = self.min_byte_range();
2197 self.offset_data().as_bytes().get(range).unwrap_or_default()
2198 }
2199}
2200
2201impl ReadArgs for ClassSequenceRule<'_> {
2202 type Args = ();
2203}
2204
2205impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
2206 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2207 #[allow(clippy::absurd_extreme_comparisons)]
2208 if data.len() < Self::MIN_SIZE {
2209 return Err(ReadError::OutOfBounds);
2210 }
2211 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2212 return Err(ReadError::OutOfBounds);
2213 };
2214 Ok(Self { data })
2215 }
2216}
2217
2218#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2220#[repr(C, packed)]
2221#[doc(hidden)]
2222pub struct ClassSequenceRuleFixedHeader {
2223 pub glyph_count: BigEndian<u16>,
2224 pub seq_lookup_count: BigEndian<u16>,
2225}
2226
2227#[allow(clippy::absurd_extreme_comparisons)]
2228const _: () =
2229 assert!(std::mem::size_of::<ClassSequenceRuleFixedHeader>() <= ClassSequenceRule::MIN_SIZE);
2230
2231#[derive(Clone)]
2233pub struct ClassSequenceRule<'a> {
2234 data: TableDataRef<'a, ClassSequenceRuleFixedHeader>,
2235}
2236
2237#[allow(clippy::needless_lifetimes)]
2238impl<'a> ClassSequenceRule<'a> {
2239 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2240 basic_table_impls!(impl_the_methods);
2241
2242 pub fn glyph_count(&self) -> u16 {
2244 self.data.header().glyph_count.get()
2245 }
2246
2247 pub fn seq_lookup_count(&self) -> u16 {
2249 self.data.header().seq_lookup_count.get()
2250 }
2251
2252 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2255 let range = self.input_sequence_byte_range();
2256 self.offset_data()
2257 .read_array(range)
2258 .ok()
2259 .unwrap_or_default()
2260 }
2261
2262 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2264 let range = self.seq_lookup_records_byte_range();
2265 self.offset_data()
2266 .read_array(range)
2267 .ok()
2268 .unwrap_or_default()
2269 }
2270
2271 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2272 let start = 0;
2273 let end = start + u16::RAW_BYTE_LEN;
2274 start..end
2275 }
2276
2277 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2278 let start = self.glyph_count_byte_range().end;
2279 let end = start + u16::RAW_BYTE_LEN;
2280 start..end
2281 }
2282
2283 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2284 let glyph_count = self.glyph_count();
2285 let start = self.seq_lookup_count_byte_range().end;
2286 let end =
2287 start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
2288 start..end
2289 }
2290
2291 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2292 let seq_lookup_count = self.seq_lookup_count();
2293 let start = self.input_sequence_byte_range().end;
2294 let end = start
2295 + (transforms::to_usize(seq_lookup_count))
2296 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2297 start..end
2298 }
2299}
2300
2301const _: () = assert!(FontData::default_data_long_enough(
2302 ClassSequenceRule::MIN_SIZE
2303));
2304
2305impl Default for ClassSequenceRule<'_> {
2306 fn default() -> Self {
2307 Self {
2308 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2309 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2310 }
2311 }
2312}
2313
2314impl Format<u16> for SequenceContextFormat3<'_> {
2315 const FORMAT: u16 = 3;
2316}
2317
2318impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
2319 fn min_byte_range(&self) -> Range<usize> {
2320 0..self.seq_lookup_records_byte_range().end
2321 }
2322 fn min_table_bytes(&self) -> &'a [u8] {
2323 let range = self.min_byte_range();
2324 self.offset_data().as_bytes().get(range).unwrap_or_default()
2325 }
2326}
2327
2328impl ReadArgs for SequenceContextFormat3<'_> {
2329 type Args = ();
2330}
2331
2332impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2333 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2334 #[allow(clippy::absurd_extreme_comparisons)]
2335 if data.len() < Self::MIN_SIZE {
2336 return Err(ReadError::OutOfBounds);
2337 }
2338 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2339 return Err(ReadError::OutOfBounds);
2340 };
2341 Ok(Self { data })
2342 }
2343}
2344
2345#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2347#[repr(C, packed)]
2348#[doc(hidden)]
2349pub struct SequenceContextFormat3FixedHeader {
2350 pub format: BigEndian<u16>,
2351 pub glyph_count: BigEndian<u16>,
2352 pub seq_lookup_count: BigEndian<u16>,
2353}
2354
2355#[allow(clippy::absurd_extreme_comparisons)]
2356const _: () = assert!(
2357 std::mem::size_of::<SequenceContextFormat3FixedHeader>() <= SequenceContextFormat3::MIN_SIZE
2358);
2359
2360#[derive(Clone)]
2362pub struct SequenceContextFormat3<'a> {
2363 data: TableDataRef<'a, SequenceContextFormat3FixedHeader>,
2364}
2365
2366#[allow(clippy::needless_lifetimes)]
2367impl<'a> SequenceContextFormat3<'a> {
2368 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2369 basic_table_impls!(impl_the_methods);
2370
2371 pub fn format(&self) -> u16 {
2373 self.data.header().format.get()
2374 }
2375
2376 pub fn glyph_count(&self) -> u16 {
2378 self.data.header().glyph_count.get()
2379 }
2380
2381 pub fn seq_lookup_count(&self) -> u16 {
2383 self.data.header().seq_lookup_count.get()
2384 }
2385
2386 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2389 let range = self.coverage_offsets_byte_range();
2390 self.offset_data()
2391 .read_array(range)
2392 .ok()
2393 .unwrap_or_default()
2394 }
2395
2396 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2398 let data = self.offset_data();
2399 let offsets = self.coverage_offsets();
2400 ArrayOfOffsets::new(offsets, data, ())
2401 }
2402
2403 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2405 let range = self.seq_lookup_records_byte_range();
2406 self.offset_data()
2407 .read_array(range)
2408 .ok()
2409 .unwrap_or_default()
2410 }
2411
2412 pub fn format_byte_range(&self) -> Range<usize> {
2413 let start = 0;
2414 let end = start + u16::RAW_BYTE_LEN;
2415 start..end
2416 }
2417
2418 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2419 let start = self.format_byte_range().end;
2420 let end = start + u16::RAW_BYTE_LEN;
2421 start..end
2422 }
2423
2424 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2425 let start = self.glyph_count_byte_range().end;
2426 let end = start + u16::RAW_BYTE_LEN;
2427 start..end
2428 }
2429
2430 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2431 let glyph_count = self.glyph_count();
2432 let start = self.seq_lookup_count_byte_range().end;
2433 let end =
2434 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2435 start..end
2436 }
2437
2438 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2439 let seq_lookup_count = self.seq_lookup_count();
2440 let start = self.coverage_offsets_byte_range().end;
2441 let end = start
2442 + (transforms::to_usize(seq_lookup_count))
2443 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2444 start..end
2445 }
2446}
2447
2448#[derive(Clone)]
2449pub enum SequenceContext<'a> {
2450 Format1(SequenceContextFormat1<'a>),
2451 Format2(SequenceContextFormat2<'a>),
2452 Format3(SequenceContextFormat3<'a>),
2453 Format4(SequenceContextFormat4<'a>),
2454 Format5(SequenceContextFormat5<'a>),
2455 Format6(SequenceContextFormat6<'a>),
2456}
2457
2458impl Default for SequenceContext<'_> {
2459 fn default() -> Self {
2460 Self::Format1(Default::default())
2461 }
2462}
2463
2464impl<'a> SequenceContext<'a> {
2465 pub fn offset_data(&self) -> FontData<'a> {
2467 match self {
2468 Self::Format1(item) => item.offset_data(),
2469 Self::Format2(item) => item.offset_data(),
2470 Self::Format3(item) => item.offset_data(),
2471 Self::Format4(item) => item.offset_data(),
2472 Self::Format5(item) => item.offset_data(),
2473 Self::Format6(item) => item.offset_data(),
2474 }
2475 }
2476
2477 pub fn format(&self) -> u16 {
2479 match self {
2480 Self::Format1(item) => item.format(),
2481 Self::Format2(item) => item.format(),
2482 Self::Format3(item) => item.format(),
2483 Self::Format4(item) => item.format(),
2484 Self::Format5(item) => item.format(),
2485 Self::Format6(item) => item.format(),
2486 }
2487 }
2488}
2489
2490impl ReadArgs for SequenceContext<'_> {
2491 type Args = ();
2492}
2493
2494impl<'a> FontRead<'a> for SequenceContext<'a> {
2495 #[inline]
2496 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2497 let format: u16 = data.read_at(0usize)?;
2498 match format {
2499 SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2500 SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2501 SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2502 SequenceContextFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
2503 SequenceContextFormat5::FORMAT => Ok(Self::Format5(FontRead::read(data)?)),
2504 SequenceContextFormat6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
2505 other => Err(ReadError::InvalidFormat(other.into())),
2506 }
2507 }
2508}
2509
2510impl<'a> MinByteRange<'a> for SequenceContext<'a> {
2511 fn min_byte_range(&self) -> Range<usize> {
2512 match self {
2513 Self::Format1(item) => item.min_byte_range(),
2514 Self::Format2(item) => item.min_byte_range(),
2515 Self::Format3(item) => item.min_byte_range(),
2516 Self::Format4(item) => item.min_byte_range(),
2517 Self::Format5(item) => item.min_byte_range(),
2518 Self::Format6(item) => item.min_byte_range(),
2519 }
2520 }
2521 fn min_table_bytes(&self) -> &'a [u8] {
2522 match self {
2523 Self::Format1(item) => item.min_table_bytes(),
2524 Self::Format2(item) => item.min_table_bytes(),
2525 Self::Format3(item) => item.min_table_bytes(),
2526 Self::Format4(item) => item.min_table_bytes(),
2527 Self::Format5(item) => item.min_table_bytes(),
2528 Self::Format6(item) => item.min_table_bytes(),
2529 }
2530 }
2531}
2532
2533impl Format<u16> for ChainedSequenceContextFormat1<'_> {
2534 const FORMAT: u16 = 1;
2535}
2536
2537impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
2538 fn min_byte_range(&self) -> Range<usize> {
2539 0..self.chained_seq_rule_set_offsets_byte_range().end
2540 }
2541 fn min_table_bytes(&self) -> &'a [u8] {
2542 let range = self.min_byte_range();
2543 self.offset_data().as_bytes().get(range).unwrap_or_default()
2544 }
2545}
2546
2547impl ReadArgs for ChainedSequenceContextFormat1<'_> {
2548 type Args = ();
2549}
2550
2551impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2552 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2553 #[allow(clippy::absurd_extreme_comparisons)]
2554 if data.len() < Self::MIN_SIZE {
2555 return Err(ReadError::OutOfBounds);
2556 }
2557 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2558 return Err(ReadError::OutOfBounds);
2559 };
2560 Ok(Self { data })
2561 }
2562}
2563
2564#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2566#[repr(C, packed)]
2567#[doc(hidden)]
2568pub struct ChainedSequenceContextFormat1FixedHeader {
2569 pub format: BigEndian<u16>,
2570 pub coverage_offset: BigEndian<Offset16>,
2571 pub chained_seq_rule_set_count: BigEndian<u16>,
2572}
2573
2574#[allow(clippy::absurd_extreme_comparisons)]
2575const _: () = assert!(
2576 std::mem::size_of::<ChainedSequenceContextFormat1FixedHeader>()
2577 <= ChainedSequenceContextFormat1::MIN_SIZE
2578);
2579
2580#[derive(Clone)]
2582pub struct ChainedSequenceContextFormat1<'a> {
2583 data: TableDataRef<'a, ChainedSequenceContextFormat1FixedHeader>,
2584}
2585
2586#[allow(clippy::needless_lifetimes)]
2587impl<'a> ChainedSequenceContextFormat1<'a> {
2588 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2589 basic_table_impls!(impl_the_methods);
2590
2591 pub fn format(&self) -> u16 {
2593 self.data.header().format.get()
2594 }
2595
2596 pub fn coverage_offset(&self) -> Offset16 {
2599 self.data.header().coverage_offset.get()
2600 }
2601
2602 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2604 let data = self.offset_data();
2605 self.coverage_offset().resolve(data)
2606 }
2607
2608 pub fn chained_seq_rule_set_count(&self) -> u16 {
2610 self.data.header().chained_seq_rule_set_count.get()
2611 }
2612
2613 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2616 let range = self.chained_seq_rule_set_offsets_byte_range();
2617 self.offset_data()
2618 .read_array(range)
2619 .ok()
2620 .unwrap_or_default()
2621 }
2622
2623 pub fn chained_seq_rule_sets(
2625 &self,
2626 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2627 let data = self.offset_data();
2628 let offsets = self.chained_seq_rule_set_offsets();
2629 ArrayOfNullableOffsets::new(offsets, data, ())
2630 }
2631
2632 pub fn format_byte_range(&self) -> Range<usize> {
2633 let start = 0;
2634 let end = start + u16::RAW_BYTE_LEN;
2635 start..end
2636 }
2637
2638 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2639 let start = self.format_byte_range().end;
2640 let end = start + Offset16::RAW_BYTE_LEN;
2641 start..end
2642 }
2643
2644 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2645 let start = self.coverage_offset_byte_range().end;
2646 let end = start + u16::RAW_BYTE_LEN;
2647 start..end
2648 }
2649
2650 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2651 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
2652 let start = self.chained_seq_rule_set_count_byte_range().end;
2653 let end = start
2654 + (transforms::to_usize(chained_seq_rule_set_count))
2655 .saturating_mul(Offset16::RAW_BYTE_LEN);
2656 start..end
2657 }
2658}
2659
2660const _: () = assert!(FontData::default_data_long_enough(
2661 ChainedSequenceContextFormat1::MIN_SIZE
2662));
2663
2664impl Default for ChainedSequenceContextFormat1<'_> {
2665 fn default() -> Self {
2666 Self {
2667 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
2668 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2669 }
2670 }
2671}
2672
2673impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
2674 fn min_byte_range(&self) -> Range<usize> {
2675 0..self.chained_seq_rule_offsets_byte_range().end
2676 }
2677 fn min_table_bytes(&self) -> &'a [u8] {
2678 let range = self.min_byte_range();
2679 self.offset_data().as_bytes().get(range).unwrap_or_default()
2680 }
2681}
2682
2683impl ReadArgs for ChainedSequenceRuleSet<'_> {
2684 type Args = ();
2685}
2686
2687impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
2688 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2689 #[allow(clippy::absurd_extreme_comparisons)]
2690 if data.len() < Self::MIN_SIZE {
2691 return Err(ReadError::OutOfBounds);
2692 }
2693 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2694 return Err(ReadError::OutOfBounds);
2695 };
2696 Ok(Self { data })
2697 }
2698}
2699
2700#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2702#[repr(C, packed)]
2703#[doc(hidden)]
2704pub struct ChainedSequenceRuleSetFixedHeader {
2705 pub chained_seq_rule_count: BigEndian<u16>,
2706}
2707
2708#[allow(clippy::absurd_extreme_comparisons)]
2709const _: () = assert!(
2710 std::mem::size_of::<ChainedSequenceRuleSetFixedHeader>() <= ChainedSequenceRuleSet::MIN_SIZE
2711);
2712
2713#[derive(Clone)]
2715pub struct ChainedSequenceRuleSet<'a> {
2716 data: TableDataRef<'a, ChainedSequenceRuleSetFixedHeader>,
2717}
2718
2719#[allow(clippy::needless_lifetimes)]
2720impl<'a> ChainedSequenceRuleSet<'a> {
2721 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2722 basic_table_impls!(impl_the_methods);
2723
2724 pub fn chained_seq_rule_count(&self) -> u16 {
2726 self.data.header().chained_seq_rule_count.get()
2727 }
2728
2729 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2732 let range = self.chained_seq_rule_offsets_byte_range();
2733 self.offset_data()
2734 .read_array(range)
2735 .ok()
2736 .unwrap_or_default()
2737 }
2738
2739 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
2741 let data = self.offset_data();
2742 let offsets = self.chained_seq_rule_offsets();
2743 ArrayOfOffsets::new(offsets, data, ())
2744 }
2745
2746 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
2747 let start = 0;
2748 let end = start + u16::RAW_BYTE_LEN;
2749 start..end
2750 }
2751
2752 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2753 let chained_seq_rule_count = self.chained_seq_rule_count();
2754 let start = self.chained_seq_rule_count_byte_range().end;
2755 let end = start
2756 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2757 start..end
2758 }
2759}
2760
2761const _: () = assert!(FontData::default_data_long_enough(
2762 ChainedSequenceRuleSet::MIN_SIZE
2763));
2764
2765impl Default for ChainedSequenceRuleSet<'_> {
2766 fn default() -> Self {
2767 Self {
2768 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2769 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2770 }
2771 }
2772}
2773
2774impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
2775 fn min_byte_range(&self) -> Range<usize> {
2776 0..self.seq_lookup_records_byte_range().end
2777 }
2778 fn min_table_bytes(&self) -> &'a [u8] {
2779 let range = self.min_byte_range();
2780 self.offset_data().as_bytes().get(range).unwrap_or_default()
2781 }
2782}
2783
2784impl ReadArgs for ChainedSequenceRule<'_> {
2785 type Args = ();
2786}
2787
2788impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
2789 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2790 #[allow(clippy::absurd_extreme_comparisons)]
2791 if data.len() < Self::MIN_SIZE {
2792 return Err(ReadError::OutOfBounds);
2793 }
2794 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2795 return Err(ReadError::OutOfBounds);
2796 };
2797 Ok(Self { data })
2798 }
2799}
2800
2801#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2803#[repr(C, packed)]
2804#[doc(hidden)]
2805pub struct ChainedSequenceRuleFixedHeader {
2806 pub backtrack_glyph_count: BigEndian<u16>,
2807}
2808
2809#[allow(clippy::absurd_extreme_comparisons)]
2810const _: () =
2811 assert!(std::mem::size_of::<ChainedSequenceRuleFixedHeader>() <= ChainedSequenceRule::MIN_SIZE);
2812
2813#[derive(Clone)]
2815pub struct ChainedSequenceRule<'a> {
2816 data: TableDataRef<'a, ChainedSequenceRuleFixedHeader>,
2817}
2818
2819#[allow(clippy::needless_lifetimes)]
2820impl<'a> ChainedSequenceRule<'a> {
2821 pub const MIN_SIZE: usize =
2822 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2823 basic_table_impls!(impl_the_methods);
2824
2825 pub fn backtrack_glyph_count(&self) -> u16 {
2827 self.data.header().backtrack_glyph_count.get()
2828 }
2829
2830 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2832 let range = self.backtrack_sequence_byte_range();
2833 self.offset_data()
2834 .read_array(range)
2835 .ok()
2836 .unwrap_or_default()
2837 }
2838
2839 pub fn input_glyph_count(&self) -> u16 {
2841 let range = self.input_glyph_count_byte_range();
2842 self.offset_data()
2843 .read_at(range.start)
2844 .ok()
2845 .unwrap_or_default()
2846 }
2847
2848 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2850 let range = self.input_sequence_byte_range();
2851 self.offset_data()
2852 .read_array(range)
2853 .ok()
2854 .unwrap_or_default()
2855 }
2856
2857 pub fn lookahead_glyph_count(&self) -> u16 {
2859 let range = self.lookahead_glyph_count_byte_range();
2860 self.offset_data()
2861 .read_at(range.start)
2862 .ok()
2863 .unwrap_or_default()
2864 }
2865
2866 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2868 let range = self.lookahead_sequence_byte_range();
2869 self.offset_data()
2870 .read_array(range)
2871 .ok()
2872 .unwrap_or_default()
2873 }
2874
2875 pub fn seq_lookup_count(&self) -> u16 {
2877 let range = self.seq_lookup_count_byte_range();
2878 self.offset_data()
2879 .read_at(range.start)
2880 .ok()
2881 .unwrap_or_default()
2882 }
2883
2884 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2886 let range = self.seq_lookup_records_byte_range();
2887 self.offset_data()
2888 .read_array(range)
2889 .ok()
2890 .unwrap_or_default()
2891 }
2892
2893 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
2894 let start = 0;
2895 let end = start + u16::RAW_BYTE_LEN;
2896 start..end
2897 }
2898
2899 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
2900 let backtrack_glyph_count = self.backtrack_glyph_count();
2901 let start = self.backtrack_glyph_count_byte_range().end;
2902 let end = start
2903 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2904 start..end
2905 }
2906
2907 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
2908 let start = self.backtrack_sequence_byte_range().end;
2909 let end = start + u16::RAW_BYTE_LEN;
2910 start..end
2911 }
2912
2913 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2914 let input_glyph_count = self.input_glyph_count();
2915 let start = self.input_glyph_count_byte_range().end;
2916 let end = start
2917 + (transforms::subtract(input_glyph_count, 1_usize))
2918 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
2919 start..end
2920 }
2921
2922 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
2923 let start = self.input_sequence_byte_range().end;
2924 let end = start + u16::RAW_BYTE_LEN;
2925 start..end
2926 }
2927
2928 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
2929 let lookahead_glyph_count = self.lookahead_glyph_count();
2930 let start = self.lookahead_glyph_count_byte_range().end;
2931 let end = start
2932 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2933 start..end
2934 }
2935
2936 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2937 let start = self.lookahead_sequence_byte_range().end;
2938 let end = start + u16::RAW_BYTE_LEN;
2939 start..end
2940 }
2941
2942 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2943 let seq_lookup_count = self.seq_lookup_count();
2944 let start = self.seq_lookup_count_byte_range().end;
2945 let end = start
2946 + (transforms::to_usize(seq_lookup_count))
2947 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2948 start..end
2949 }
2950}
2951
2952const _: () = assert!(FontData::default_data_long_enough(
2953 ChainedSequenceRule::MIN_SIZE
2954));
2955
2956impl Default for ChainedSequenceRule<'_> {
2957 fn default() -> Self {
2958 Self {
2959 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2960 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2961 }
2962 }
2963}
2964
2965impl Format<u16> for ChainedSequenceContextFormat2<'_> {
2966 const FORMAT: u16 = 2;
2967}
2968
2969impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
2970 fn min_byte_range(&self) -> Range<usize> {
2971 0..self.chained_class_seq_rule_set_offsets_byte_range().end
2972 }
2973 fn min_table_bytes(&self) -> &'a [u8] {
2974 let range = self.min_byte_range();
2975 self.offset_data().as_bytes().get(range).unwrap_or_default()
2976 }
2977}
2978
2979impl ReadArgs for ChainedSequenceContextFormat2<'_> {
2980 type Args = ();
2981}
2982
2983impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
2984 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2985 #[allow(clippy::absurd_extreme_comparisons)]
2986 if data.len() < Self::MIN_SIZE {
2987 return Err(ReadError::OutOfBounds);
2988 }
2989 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2990 return Err(ReadError::OutOfBounds);
2991 };
2992 Ok(Self { data })
2993 }
2994}
2995
2996#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2998#[repr(C, packed)]
2999#[doc(hidden)]
3000pub struct ChainedSequenceContextFormat2FixedHeader {
3001 pub format: BigEndian<u16>,
3002 pub coverage_offset: BigEndian<Offset16>,
3003 pub backtrack_class_def_offset: BigEndian<Offset16>,
3004 pub input_class_def_offset: BigEndian<Offset16>,
3005 pub lookahead_class_def_offset: BigEndian<Offset16>,
3006 pub chained_class_seq_rule_set_count: BigEndian<u16>,
3007}
3008
3009#[allow(clippy::absurd_extreme_comparisons)]
3010const _: () = assert!(
3011 std::mem::size_of::<ChainedSequenceContextFormat2FixedHeader>()
3012 <= ChainedSequenceContextFormat2::MIN_SIZE
3013);
3014
3015#[derive(Clone)]
3017pub struct ChainedSequenceContextFormat2<'a> {
3018 data: TableDataRef<'a, ChainedSequenceContextFormat2FixedHeader>,
3019}
3020
3021#[allow(clippy::needless_lifetimes)]
3022impl<'a> ChainedSequenceContextFormat2<'a> {
3023 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3024 + Offset16::RAW_BYTE_LEN
3025 + Offset16::RAW_BYTE_LEN
3026 + Offset16::RAW_BYTE_LEN
3027 + Offset16::RAW_BYTE_LEN
3028 + u16::RAW_BYTE_LEN);
3029 basic_table_impls!(impl_the_methods);
3030
3031 pub fn format(&self) -> u16 {
3033 self.data.header().format.get()
3034 }
3035
3036 pub fn coverage_offset(&self) -> Offset16 {
3039 self.data.header().coverage_offset.get()
3040 }
3041
3042 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3044 let data = self.offset_data();
3045 self.coverage_offset().resolve(data)
3046 }
3047
3048 pub fn backtrack_class_def_offset(&self) -> Offset16 {
3051 self.data.header().backtrack_class_def_offset.get()
3052 }
3053
3054 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3056 let data = self.offset_data();
3057 self.backtrack_class_def_offset().resolve(data)
3058 }
3059
3060 pub fn input_class_def_offset(&self) -> Offset16 {
3063 self.data.header().input_class_def_offset.get()
3064 }
3065
3066 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3068 let data = self.offset_data();
3069 self.input_class_def_offset().resolve(data)
3070 }
3071
3072 pub fn lookahead_class_def_offset(&self) -> Offset16 {
3075 self.data.header().lookahead_class_def_offset.get()
3076 }
3077
3078 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3080 let data = self.offset_data();
3081 self.lookahead_class_def_offset().resolve(data)
3082 }
3083
3084 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
3086 self.data.header().chained_class_seq_rule_set_count.get()
3087 }
3088
3089 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3092 let range = self.chained_class_seq_rule_set_offsets_byte_range();
3093 self.offset_data()
3094 .read_array(range)
3095 .ok()
3096 .unwrap_or_default()
3097 }
3098
3099 pub fn chained_class_seq_rule_sets(
3101 &self,
3102 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
3103 let data = self.offset_data();
3104 let offsets = self.chained_class_seq_rule_set_offsets();
3105 ArrayOfNullableOffsets::new(offsets, data, ())
3106 }
3107
3108 pub fn format_byte_range(&self) -> Range<usize> {
3109 let start = 0;
3110 let end = start + u16::RAW_BYTE_LEN;
3111 start..end
3112 }
3113
3114 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
3115 let start = self.format_byte_range().end;
3116 let end = start + Offset16::RAW_BYTE_LEN;
3117 start..end
3118 }
3119
3120 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
3121 let start = self.coverage_offset_byte_range().end;
3122 let end = start + Offset16::RAW_BYTE_LEN;
3123 start..end
3124 }
3125
3126 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
3127 let start = self.backtrack_class_def_offset_byte_range().end;
3128 let end = start + Offset16::RAW_BYTE_LEN;
3129 start..end
3130 }
3131
3132 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
3133 let start = self.input_class_def_offset_byte_range().end;
3134 let end = start + Offset16::RAW_BYTE_LEN;
3135 start..end
3136 }
3137
3138 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
3139 let start = self.lookahead_class_def_offset_byte_range().end;
3140 let end = start + u16::RAW_BYTE_LEN;
3141 start..end
3142 }
3143
3144 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
3145 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
3146 let start = self.chained_class_seq_rule_set_count_byte_range().end;
3147 let end = start
3148 + (transforms::to_usize(chained_class_seq_rule_set_count))
3149 .saturating_mul(Offset16::RAW_BYTE_LEN);
3150 start..end
3151 }
3152}
3153
3154impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
3155 fn min_byte_range(&self) -> Range<usize> {
3156 0..self.chained_class_seq_rule_offsets_byte_range().end
3157 }
3158 fn min_table_bytes(&self) -> &'a [u8] {
3159 let range = self.min_byte_range();
3160 self.offset_data().as_bytes().get(range).unwrap_or_default()
3161 }
3162}
3163
3164impl ReadArgs for ChainedClassSequenceRuleSet<'_> {
3165 type Args = ();
3166}
3167
3168impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
3169 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3170 #[allow(clippy::absurd_extreme_comparisons)]
3171 if data.len() < Self::MIN_SIZE {
3172 return Err(ReadError::OutOfBounds);
3173 }
3174 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3175 return Err(ReadError::OutOfBounds);
3176 };
3177 Ok(Self { data })
3178 }
3179}
3180
3181#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3183#[repr(C, packed)]
3184#[doc(hidden)]
3185pub struct ChainedClassSequenceRuleSetFixedHeader {
3186 pub chained_class_seq_rule_count: BigEndian<u16>,
3187}
3188
3189#[allow(clippy::absurd_extreme_comparisons)]
3190const _: () = assert!(
3191 std::mem::size_of::<ChainedClassSequenceRuleSetFixedHeader>()
3192 <= ChainedClassSequenceRuleSet::MIN_SIZE
3193);
3194
3195#[derive(Clone)]
3197pub struct ChainedClassSequenceRuleSet<'a> {
3198 data: TableDataRef<'a, ChainedClassSequenceRuleSetFixedHeader>,
3199}
3200
3201#[allow(clippy::needless_lifetimes)]
3202impl<'a> ChainedClassSequenceRuleSet<'a> {
3203 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3204 basic_table_impls!(impl_the_methods);
3205
3206 pub fn chained_class_seq_rule_count(&self) -> u16 {
3208 self.data.header().chained_class_seq_rule_count.get()
3209 }
3210
3211 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3214 let range = self.chained_class_seq_rule_offsets_byte_range();
3215 self.offset_data()
3216 .read_array(range)
3217 .ok()
3218 .unwrap_or_default()
3219 }
3220
3221 pub fn chained_class_seq_rules(
3223 &self,
3224 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
3225 let data = self.offset_data();
3226 let offsets = self.chained_class_seq_rule_offsets();
3227 ArrayOfOffsets::new(offsets, data, ())
3228 }
3229
3230 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
3231 let start = 0;
3232 let end = start + u16::RAW_BYTE_LEN;
3233 start..end
3234 }
3235
3236 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3237 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
3238 let start = self.chained_class_seq_rule_count_byte_range().end;
3239 let end = start
3240 + (transforms::to_usize(chained_class_seq_rule_count))
3241 .saturating_mul(Offset16::RAW_BYTE_LEN);
3242 start..end
3243 }
3244}
3245
3246const _: () = assert!(FontData::default_data_long_enough(
3247 ChainedClassSequenceRuleSet::MIN_SIZE
3248));
3249
3250impl Default for ChainedClassSequenceRuleSet<'_> {
3251 fn default() -> Self {
3252 Self {
3253 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3254 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3255 }
3256 }
3257}
3258
3259impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'a> {
3260 fn min_byte_range(&self) -> Range<usize> {
3261 0..self.seq_lookup_records_byte_range().end
3262 }
3263 fn min_table_bytes(&self) -> &'a [u8] {
3264 let range = self.min_byte_range();
3265 self.offset_data().as_bytes().get(range).unwrap_or_default()
3266 }
3267}
3268
3269impl ReadArgs for ChainedClassSequenceRule<'_> {
3270 type Args = ();
3271}
3272
3273impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
3274 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3275 #[allow(clippy::absurd_extreme_comparisons)]
3276 if data.len() < Self::MIN_SIZE {
3277 return Err(ReadError::OutOfBounds);
3278 }
3279 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3280 return Err(ReadError::OutOfBounds);
3281 };
3282 Ok(Self { data })
3283 }
3284}
3285
3286#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3288#[repr(C, packed)]
3289#[doc(hidden)]
3290pub struct ChainedClassSequenceRuleFixedHeader {
3291 pub backtrack_glyph_count: BigEndian<u16>,
3292}
3293
3294#[allow(clippy::absurd_extreme_comparisons)]
3295const _: () = assert!(
3296 std::mem::size_of::<ChainedClassSequenceRuleFixedHeader>()
3297 <= ChainedClassSequenceRule::MIN_SIZE
3298);
3299
3300#[derive(Clone)]
3302pub struct ChainedClassSequenceRule<'a> {
3303 data: TableDataRef<'a, ChainedClassSequenceRuleFixedHeader>,
3304}
3305
3306#[allow(clippy::needless_lifetimes)]
3307impl<'a> ChainedClassSequenceRule<'a> {
3308 pub const MIN_SIZE: usize =
3309 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3310 basic_table_impls!(impl_the_methods);
3311
3312 pub fn backtrack_glyph_count(&self) -> u16 {
3314 self.data.header().backtrack_glyph_count.get()
3315 }
3316
3317 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
3319 let range = self.backtrack_sequence_byte_range();
3320 self.offset_data()
3321 .read_array(range)
3322 .ok()
3323 .unwrap_or_default()
3324 }
3325
3326 pub fn input_glyph_count(&self) -> u16 {
3328 let range = self.input_glyph_count_byte_range();
3329 self.offset_data()
3330 .read_at(range.start)
3331 .ok()
3332 .unwrap_or_default()
3333 }
3334
3335 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
3338 let range = self.input_sequence_byte_range();
3339 self.offset_data()
3340 .read_array(range)
3341 .ok()
3342 .unwrap_or_default()
3343 }
3344
3345 pub fn lookahead_glyph_count(&self) -> u16 {
3347 let range = self.lookahead_glyph_count_byte_range();
3348 self.offset_data()
3349 .read_at(range.start)
3350 .ok()
3351 .unwrap_or_default()
3352 }
3353
3354 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
3356 let range = self.lookahead_sequence_byte_range();
3357 self.offset_data()
3358 .read_array(range)
3359 .ok()
3360 .unwrap_or_default()
3361 }
3362
3363 pub fn seq_lookup_count(&self) -> u16 {
3365 let range = self.seq_lookup_count_byte_range();
3366 self.offset_data()
3367 .read_at(range.start)
3368 .ok()
3369 .unwrap_or_default()
3370 }
3371
3372 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3374 let range = self.seq_lookup_records_byte_range();
3375 self.offset_data()
3376 .read_array(range)
3377 .ok()
3378 .unwrap_or_default()
3379 }
3380
3381 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3382 let start = 0;
3383 let end = start + u16::RAW_BYTE_LEN;
3384 start..end
3385 }
3386
3387 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3388 let backtrack_glyph_count = self.backtrack_glyph_count();
3389 let start = self.backtrack_glyph_count_byte_range().end;
3390 let end =
3391 start + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3392 start..end
3393 }
3394
3395 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3396 let start = self.backtrack_sequence_byte_range().end;
3397 let end = start + u16::RAW_BYTE_LEN;
3398 start..end
3399 }
3400
3401 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3402 let input_glyph_count = self.input_glyph_count();
3403 let start = self.input_glyph_count_byte_range().end;
3404 let end = start
3405 + (transforms::subtract(input_glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
3406 start..end
3407 }
3408
3409 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3410 let start = self.input_sequence_byte_range().end;
3411 let end = start + u16::RAW_BYTE_LEN;
3412 start..end
3413 }
3414
3415 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3416 let lookahead_glyph_count = self.lookahead_glyph_count();
3417 let start = self.lookahead_glyph_count_byte_range().end;
3418 let end =
3419 start + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3420 start..end
3421 }
3422
3423 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3424 let start = self.lookahead_sequence_byte_range().end;
3425 let end = start + u16::RAW_BYTE_LEN;
3426 start..end
3427 }
3428
3429 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3430 let seq_lookup_count = self.seq_lookup_count();
3431 let start = self.seq_lookup_count_byte_range().end;
3432 let end = start
3433 + (transforms::to_usize(seq_lookup_count))
3434 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3435 start..end
3436 }
3437}
3438
3439const _: () = assert!(FontData::default_data_long_enough(
3440 ChainedClassSequenceRule::MIN_SIZE
3441));
3442
3443impl Default for ChainedClassSequenceRule<'_> {
3444 fn default() -> Self {
3445 Self {
3446 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3447 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3448 }
3449 }
3450}
3451
3452impl Format<u16> for ChainedSequenceContextFormat3<'_> {
3453 const FORMAT: u16 = 3;
3454}
3455
3456impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
3457 fn min_byte_range(&self) -> Range<usize> {
3458 0..self.seq_lookup_records_byte_range().end
3459 }
3460 fn min_table_bytes(&self) -> &'a [u8] {
3461 let range = self.min_byte_range();
3462 self.offset_data().as_bytes().get(range).unwrap_or_default()
3463 }
3464}
3465
3466impl ReadArgs for ChainedSequenceContextFormat3<'_> {
3467 type Args = ();
3468}
3469
3470impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
3471 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3472 #[allow(clippy::absurd_extreme_comparisons)]
3473 if data.len() < Self::MIN_SIZE {
3474 return Err(ReadError::OutOfBounds);
3475 }
3476 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3477 return Err(ReadError::OutOfBounds);
3478 };
3479 Ok(Self { data })
3480 }
3481}
3482
3483#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3485#[repr(C, packed)]
3486#[doc(hidden)]
3487pub struct ChainedSequenceContextFormat3FixedHeader {
3488 pub format: BigEndian<u16>,
3489 pub backtrack_glyph_count: BigEndian<u16>,
3490}
3491
3492#[allow(clippy::absurd_extreme_comparisons)]
3493const _: () = assert!(
3494 std::mem::size_of::<ChainedSequenceContextFormat3FixedHeader>()
3495 <= ChainedSequenceContextFormat3::MIN_SIZE
3496);
3497
3498#[derive(Clone)]
3500pub struct ChainedSequenceContextFormat3<'a> {
3501 data: TableDataRef<'a, ChainedSequenceContextFormat3FixedHeader>,
3502}
3503
3504#[allow(clippy::needless_lifetimes)]
3505impl<'a> ChainedSequenceContextFormat3<'a> {
3506 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3507 + u16::RAW_BYTE_LEN
3508 + u16::RAW_BYTE_LEN
3509 + u16::RAW_BYTE_LEN
3510 + u16::RAW_BYTE_LEN);
3511 basic_table_impls!(impl_the_methods);
3512
3513 pub fn format(&self) -> u16 {
3515 self.data.header().format.get()
3516 }
3517
3518 pub fn backtrack_glyph_count(&self) -> u16 {
3520 self.data.header().backtrack_glyph_count.get()
3521 }
3522
3523 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3525 let range = self.backtrack_coverage_offsets_byte_range();
3526 self.offset_data()
3527 .read_array(range)
3528 .ok()
3529 .unwrap_or_default()
3530 }
3531
3532 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3534 let data = self.offset_data();
3535 let offsets = self.backtrack_coverage_offsets();
3536 ArrayOfOffsets::new(offsets, data, ())
3537 }
3538
3539 pub fn input_glyph_count(&self) -> u16 {
3541 let range = self.input_glyph_count_byte_range();
3542 self.offset_data()
3543 .read_at(range.start)
3544 .ok()
3545 .unwrap_or_default()
3546 }
3547
3548 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3550 let range = self.input_coverage_offsets_byte_range();
3551 self.offset_data()
3552 .read_array(range)
3553 .ok()
3554 .unwrap_or_default()
3555 }
3556
3557 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3559 let data = self.offset_data();
3560 let offsets = self.input_coverage_offsets();
3561 ArrayOfOffsets::new(offsets, data, ())
3562 }
3563
3564 pub fn lookahead_glyph_count(&self) -> u16 {
3566 let range = self.lookahead_glyph_count_byte_range();
3567 self.offset_data()
3568 .read_at(range.start)
3569 .ok()
3570 .unwrap_or_default()
3571 }
3572
3573 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3575 let range = self.lookahead_coverage_offsets_byte_range();
3576 self.offset_data()
3577 .read_array(range)
3578 .ok()
3579 .unwrap_or_default()
3580 }
3581
3582 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3584 let data = self.offset_data();
3585 let offsets = self.lookahead_coverage_offsets();
3586 ArrayOfOffsets::new(offsets, data, ())
3587 }
3588
3589 pub fn seq_lookup_count(&self) -> u16 {
3591 let range = self.seq_lookup_count_byte_range();
3592 self.offset_data()
3593 .read_at(range.start)
3594 .ok()
3595 .unwrap_or_default()
3596 }
3597
3598 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3600 let range = self.seq_lookup_records_byte_range();
3601 self.offset_data()
3602 .read_array(range)
3603 .ok()
3604 .unwrap_or_default()
3605 }
3606
3607 pub fn format_byte_range(&self) -> Range<usize> {
3608 let start = 0;
3609 let end = start + u16::RAW_BYTE_LEN;
3610 start..end
3611 }
3612
3613 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3614 let start = self.format_byte_range().end;
3615 let end = start + u16::RAW_BYTE_LEN;
3616 start..end
3617 }
3618
3619 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
3620 let backtrack_glyph_count = self.backtrack_glyph_count();
3621 let start = self.backtrack_glyph_count_byte_range().end;
3622 let end = start
3623 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3624 start..end
3625 }
3626
3627 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3628 let start = self.backtrack_coverage_offsets_byte_range().end;
3629 let end = start + u16::RAW_BYTE_LEN;
3630 start..end
3631 }
3632
3633 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
3634 let input_glyph_count = self.input_glyph_count();
3635 let start = self.input_glyph_count_byte_range().end;
3636 let end = start
3637 + (transforms::to_usize(input_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3638 start..end
3639 }
3640
3641 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3642 let start = self.input_coverage_offsets_byte_range().end;
3643 let end = start + u16::RAW_BYTE_LEN;
3644 start..end
3645 }
3646
3647 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
3648 let lookahead_glyph_count = self.lookahead_glyph_count();
3649 let start = self.lookahead_glyph_count_byte_range().end;
3650 let end = start
3651 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3652 start..end
3653 }
3654
3655 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3656 let start = self.lookahead_coverage_offsets_byte_range().end;
3657 let end = start + u16::RAW_BYTE_LEN;
3658 start..end
3659 }
3660
3661 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3662 let seq_lookup_count = self.seq_lookup_count();
3663 let start = self.seq_lookup_count_byte_range().end;
3664 let end = start
3665 + (transforms::to_usize(seq_lookup_count))
3666 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3667 start..end
3668 }
3669}
3670
3671#[derive(Clone)]
3672pub enum ChainedSequenceContext<'a> {
3673 Format1(ChainedSequenceContextFormat1<'a>),
3674 Format2(ChainedSequenceContextFormat2<'a>),
3675 Format3(ChainedSequenceContextFormat3<'a>),
3676 Format4(ChainedSequenceContextFormat4<'a>),
3677 Format5(ChainedSequenceContextFormat5<'a>),
3678}
3679
3680impl Default for ChainedSequenceContext<'_> {
3681 fn default() -> Self {
3682 Self::Format1(Default::default())
3683 }
3684}
3685
3686impl<'a> ChainedSequenceContext<'a> {
3687 pub fn offset_data(&self) -> FontData<'a> {
3689 match self {
3690 Self::Format1(item) => item.offset_data(),
3691 Self::Format2(item) => item.offset_data(),
3692 Self::Format3(item) => item.offset_data(),
3693 Self::Format4(item) => item.offset_data(),
3694 Self::Format5(item) => item.offset_data(),
3695 }
3696 }
3697
3698 pub fn format(&self) -> u16 {
3700 match self {
3701 Self::Format1(item) => item.format(),
3702 Self::Format2(item) => item.format(),
3703 Self::Format3(item) => item.format(),
3704 Self::Format4(item) => item.format(),
3705 Self::Format5(item) => item.format(),
3706 }
3707 }
3708}
3709
3710impl ReadArgs for ChainedSequenceContext<'_> {
3711 type Args = ();
3712}
3713
3714impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
3715 #[inline]
3716 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3717 let format: u16 = data.read_at(0usize)?;
3718 match format {
3719 ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
3720 ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
3721 ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
3722 ChainedSequenceContextFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
3723 ChainedSequenceContextFormat5::FORMAT => Ok(Self::Format5(FontRead::read(data)?)),
3724 other => Err(ReadError::InvalidFormat(other.into())),
3725 }
3726 }
3727}
3728
3729impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
3730 fn min_byte_range(&self) -> Range<usize> {
3731 match self {
3732 Self::Format1(item) => item.min_byte_range(),
3733 Self::Format2(item) => item.min_byte_range(),
3734 Self::Format3(item) => item.min_byte_range(),
3735 Self::Format4(item) => item.min_byte_range(),
3736 Self::Format5(item) => item.min_byte_range(),
3737 }
3738 }
3739 fn min_table_bytes(&self) -> &'a [u8] {
3740 match self {
3741 Self::Format1(item) => item.min_table_bytes(),
3742 Self::Format2(item) => item.min_table_bytes(),
3743 Self::Format3(item) => item.min_table_bytes(),
3744 Self::Format4(item) => item.min_table_bytes(),
3745 Self::Format5(item) => item.min_table_bytes(),
3746 }
3747 }
3748}
3749
3750#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
3753#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3754#[repr(u16)]
3755#[allow(clippy::manual_non_exhaustive)]
3756pub enum DeltaFormat {
3757 #[default]
3759 Local2BitDeltas = 0x0001,
3760 Local4BitDeltas = 0x0002,
3762 Local8BitDeltas = 0x0003,
3764 VariationIndex = 0x8000,
3766 #[doc(hidden)]
3767 Unknown,
3769}
3770
3771impl DeltaFormat {
3772 pub fn new(raw: u16) -> Self {
3776 match raw {
3777 0x0001 => Self::Local2BitDeltas,
3778 0x0002 => Self::Local4BitDeltas,
3779 0x0003 => Self::Local8BitDeltas,
3780 0x8000 => Self::VariationIndex,
3781 _ => Self::Unknown,
3782 }
3783 }
3784}
3785
3786impl font_types::Scalar for DeltaFormat {
3787 type Raw = <u16 as font_types::Scalar>::Raw;
3788 fn to_raw(self) -> Self::Raw {
3789 (self as u16).to_raw()
3790 }
3791 fn from_raw(raw: Self::Raw) -> Self {
3792 let t = <u16>::from_raw(raw);
3793 Self::new(t)
3794 }
3795}
3796
3797impl<'a> MinByteRange<'a> for Device<'a> {
3798 fn min_byte_range(&self) -> Range<usize> {
3799 0..self.delta_value_byte_range().end
3800 }
3801 fn min_table_bytes(&self) -> &'a [u8] {
3802 let range = self.min_byte_range();
3803 self.offset_data().as_bytes().get(range).unwrap_or_default()
3804 }
3805}
3806
3807impl ReadArgs for Device<'_> {
3808 type Args = ();
3809}
3810
3811impl<'a> FontRead<'a> for Device<'a> {
3812 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3813 #[allow(clippy::absurd_extreme_comparisons)]
3814 if data.len() < Self::MIN_SIZE {
3815 return Err(ReadError::OutOfBounds);
3816 }
3817 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3818 return Err(ReadError::OutOfBounds);
3819 };
3820 Ok(Self { data })
3821 }
3822}
3823
3824#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3826#[repr(C, packed)]
3827#[doc(hidden)]
3828pub struct DeviceFixedHeader {
3829 pub start_size: BigEndian<u16>,
3830 pub end_size: BigEndian<u16>,
3831 pub delta_format: BigEndian<DeltaFormat>,
3832}
3833
3834#[allow(clippy::absurd_extreme_comparisons)]
3835const _: () = assert!(std::mem::size_of::<DeviceFixedHeader>() <= Device::MIN_SIZE);
3836
3837#[derive(Clone)]
3839pub struct Device<'a> {
3840 data: TableDataRef<'a, DeviceFixedHeader>,
3841}
3842
3843#[allow(clippy::needless_lifetimes)]
3844impl<'a> Device<'a> {
3845 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3846 basic_table_impls!(impl_the_methods);
3847
3848 pub fn start_size(&self) -> u16 {
3850 self.data.header().start_size.get()
3851 }
3852
3853 pub fn end_size(&self) -> u16 {
3855 self.data.header().end_size.get()
3856 }
3857
3858 pub fn delta_format(&self) -> DeltaFormat {
3860 self.data.header().delta_format.get()
3861 }
3862
3863 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
3865 let range = self.delta_value_byte_range();
3866 self.offset_data()
3867 .read_array(range)
3868 .ok()
3869 .unwrap_or_default()
3870 }
3871
3872 pub fn start_size_byte_range(&self) -> Range<usize> {
3873 let start = 0;
3874 let end = start + u16::RAW_BYTE_LEN;
3875 start..end
3876 }
3877
3878 pub fn end_size_byte_range(&self) -> Range<usize> {
3879 let start = self.start_size_byte_range().end;
3880 let end = start + u16::RAW_BYTE_LEN;
3881 start..end
3882 }
3883
3884 pub fn delta_format_byte_range(&self) -> Range<usize> {
3885 let start = self.end_size_byte_range().end;
3886 let end = start + DeltaFormat::RAW_BYTE_LEN;
3887 start..end
3888 }
3889
3890 pub fn delta_value_byte_range(&self) -> Range<usize> {
3891 let delta_format = self.delta_format();
3892 let start_size = self.start_size();
3893 let end_size = self.end_size();
3894 let start = self.delta_format_byte_range().end;
3895 let end = start
3896 + (DeltaFormat::value_count(delta_format, start_size, end_size))
3897 .saturating_mul(u16::RAW_BYTE_LEN);
3898 start..end
3899 }
3900}
3901
3902const _: () = assert!(FontData::default_data_long_enough(Device::MIN_SIZE));
3903
3904impl Default for Device<'_> {
3905 fn default() -> Self {
3906 Self {
3907 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3908 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3909 }
3910 }
3911}
3912
3913impl<'a> MinByteRange<'a> for VariationIndex<'a> {
3914 fn min_byte_range(&self) -> Range<usize> {
3915 0..self.delta_format_byte_range().end
3916 }
3917 fn min_table_bytes(&self) -> &'a [u8] {
3918 let range = self.min_byte_range();
3919 self.offset_data().as_bytes().get(range).unwrap_or_default()
3920 }
3921}
3922
3923impl ReadArgs for VariationIndex<'_> {
3924 type Args = ();
3925}
3926
3927impl<'a> FontRead<'a> for VariationIndex<'a> {
3928 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3929 #[allow(clippy::absurd_extreme_comparisons)]
3930 if data.len() < Self::MIN_SIZE {
3931 return Err(ReadError::OutOfBounds);
3932 }
3933 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3934 return Err(ReadError::OutOfBounds);
3935 };
3936 Ok(Self { data })
3937 }
3938}
3939
3940#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3942#[repr(C, packed)]
3943#[doc(hidden)]
3944pub struct VariationIndexFixedHeader {
3945 pub delta_set_outer_index: BigEndian<u16>,
3946 pub delta_set_inner_index: BigEndian<u16>,
3947 pub delta_format: BigEndian<DeltaFormat>,
3948}
3949
3950#[allow(clippy::absurd_extreme_comparisons)]
3951const _: () = assert!(std::mem::size_of::<VariationIndexFixedHeader>() <= VariationIndex::MIN_SIZE);
3952
3953#[derive(Clone)]
3955pub struct VariationIndex<'a> {
3956 data: TableDataRef<'a, VariationIndexFixedHeader>,
3957}
3958
3959#[allow(clippy::needless_lifetimes)]
3960impl<'a> VariationIndex<'a> {
3961 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3962 basic_table_impls!(impl_the_methods);
3963
3964 pub fn delta_set_outer_index(&self) -> u16 {
3967 self.data.header().delta_set_outer_index.get()
3968 }
3969
3970 pub fn delta_set_inner_index(&self) -> u16 {
3973 self.data.header().delta_set_inner_index.get()
3974 }
3975
3976 pub fn delta_format(&self) -> DeltaFormat {
3978 self.data.header().delta_format.get()
3979 }
3980
3981 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
3982 let start = 0;
3983 let end = start + u16::RAW_BYTE_LEN;
3984 start..end
3985 }
3986
3987 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
3988 let start = self.delta_set_outer_index_byte_range().end;
3989 let end = start + u16::RAW_BYTE_LEN;
3990 start..end
3991 }
3992
3993 pub fn delta_format_byte_range(&self) -> Range<usize> {
3994 let start = self.delta_set_inner_index_byte_range().end;
3995 let end = start + DeltaFormat::RAW_BYTE_LEN;
3996 start..end
3997 }
3998}
3999
4000const _: () = assert!(FontData::default_data_long_enough(VariationIndex::MIN_SIZE));
4001
4002impl Default for VariationIndex<'_> {
4003 fn default() -> Self {
4004 Self {
4005 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4006 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4007 }
4008 }
4009}
4010
4011#[derive(Clone)]
4013pub enum DeviceOrVariationIndex<'a> {
4014 Device(Device<'a>),
4015 VariationIndex(VariationIndex<'a>),
4016}
4017
4018impl Default for DeviceOrVariationIndex<'_> {
4019 fn default() -> Self {
4020 Self::Device(Default::default())
4021 }
4022}
4023
4024impl<'a> DeviceOrVariationIndex<'a> {
4025 pub fn offset_data(&self) -> FontData<'a> {
4027 match self {
4028 Self::Device(item) => item.offset_data(),
4029 Self::VariationIndex(item) => item.offset_data(),
4030 }
4031 }
4032}
4033
4034impl ReadArgs for DeviceOrVariationIndex<'_> {
4035 type Args = ();
4036}
4037
4038impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
4039 #[inline]
4040 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4041 let format: DeltaFormat = data.read_at(4usize)?;
4042
4043 #[allow(clippy::redundant_guards)]
4044 match format {
4045 format if format != DeltaFormat::VariationIndex => {
4046 Ok(Self::Device(FontRead::read(data)?))
4047 }
4048 format if format == DeltaFormat::VariationIndex => {
4049 Ok(Self::VariationIndex(FontRead::read(data)?))
4050 }
4051 other => Err(ReadError::InvalidFormat(other.into())),
4052 }
4053 }
4054}
4055
4056impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
4057 fn min_byte_range(&self) -> Range<usize> {
4058 match self {
4059 Self::Device(item) => item.min_byte_range(),
4060 Self::VariationIndex(item) => item.min_byte_range(),
4061 }
4062 }
4063 fn min_table_bytes(&self) -> &'a [u8] {
4064 match self {
4065 Self::Device(item) => item.min_table_bytes(),
4066 Self::VariationIndex(item) => item.min_table_bytes(),
4067 }
4068 }
4069}
4070
4071impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
4072 fn min_byte_range(&self) -> Range<usize> {
4073 0..self.feature_variation_records_byte_range().end
4074 }
4075 fn min_table_bytes(&self) -> &'a [u8] {
4076 let range = self.min_byte_range();
4077 self.offset_data().as_bytes().get(range).unwrap_or_default()
4078 }
4079}
4080
4081impl ReadArgs for FeatureVariations<'_> {
4082 type Args = ();
4083}
4084
4085impl<'a> FontRead<'a> for FeatureVariations<'a> {
4086 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4087 #[allow(clippy::absurd_extreme_comparisons)]
4088 if data.len() < Self::MIN_SIZE {
4089 return Err(ReadError::OutOfBounds);
4090 }
4091 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4092 return Err(ReadError::OutOfBounds);
4093 };
4094 Ok(Self { data })
4095 }
4096}
4097
4098#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4100#[repr(C, packed)]
4101#[doc(hidden)]
4102pub struct FeatureVariationsFixedHeader {
4103 pub version: BigEndian<MajorMinor>,
4104 pub feature_variation_record_count: BigEndian<u32>,
4105}
4106
4107#[allow(clippy::absurd_extreme_comparisons)]
4108const _: () =
4109 assert!(std::mem::size_of::<FeatureVariationsFixedHeader>() <= FeatureVariations::MIN_SIZE);
4110
4111#[derive(Clone)]
4114pub struct FeatureVariations<'a> {
4115 data: TableDataRef<'a, FeatureVariationsFixedHeader>,
4116}
4117
4118#[allow(clippy::needless_lifetimes)]
4119impl<'a> FeatureVariations<'a> {
4120 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4121 basic_table_impls!(impl_the_methods);
4122
4123 pub fn version(&self) -> MajorMinor {
4124 self.data.header().version.get()
4125 }
4126
4127 pub fn feature_variation_record_count(&self) -> u32 {
4129 self.data.header().feature_variation_record_count.get()
4130 }
4131
4132 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
4134 let range = self.feature_variation_records_byte_range();
4135 self.offset_data()
4136 .read_array(range)
4137 .ok()
4138 .unwrap_or_default()
4139 }
4140
4141 pub fn lookup_variation_record_count(&self) -> Option<u32> {
4143 let range = self.lookup_variation_record_count_byte_range();
4144 (!range.is_empty())
4145 .then(|| self.offset_data().read_at(range.start).ok())
4146 .flatten()
4147 }
4148
4149 pub fn version_byte_range(&self) -> Range<usize> {
4150 let start = 0;
4151 let end = start + MajorMinor::RAW_BYTE_LEN;
4152 start..end
4153 }
4154
4155 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
4156 let start = self.version_byte_range().end;
4157 let end = start + u32::RAW_BYTE_LEN;
4158 start..end
4159 }
4160
4161 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
4162 let feature_variation_record_count = self.feature_variation_record_count();
4163 let start = self.feature_variation_record_count_byte_range().end;
4164 let end = start
4165 + (transforms::to_usize(feature_variation_record_count))
4166 .saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN);
4167 start..end
4168 }
4169
4170 pub fn lookup_variation_record_count_byte_range(&self) -> Range<usize> {
4171 let start = self.feature_variation_records_byte_range().end;
4172 let end = if self.version().compatible((1u16, 1u16)) {
4173 start + u32::RAW_BYTE_LEN
4174 } else {
4175 start
4176 };
4177 start..end
4178 }
4179
4180 pub fn lookup_variation_records_byte_range(&self) -> Range<usize> {
4181 let lookup_variation_record_count =
4182 self.lookup_variation_record_count().unwrap_or_default();
4183 let start = self.lookup_variation_record_count_byte_range().end;
4184 let end = if self.version().compatible((1u16, 1u16)) {
4185 start
4186 + (transforms::to_usize(lookup_variation_record_count))
4187 .saturating_mul(LookupVariationRecord::RAW_BYTE_LEN)
4188 } else {
4189 start
4190 };
4191 start..end
4192 }
4193}
4194
4195const _: () = assert!(FontData::default_data_long_enough(
4196 FeatureVariations::MIN_SIZE
4197));
4198
4199impl Default for FeatureVariations<'_> {
4200 fn default() -> Self {
4201 Self {
4202 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4203 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4204 }
4205 }
4206}
4207
4208#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4210#[repr(C)]
4211#[repr(packed)]
4212pub struct FeatureVariationRecord {
4213 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
4216 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
4219}
4220
4221impl FeatureVariationRecord {
4222 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
4225 self.condition_set_offset.get()
4226 }
4227
4228 pub fn condition_set<'a>(
4234 &self,
4235 data: FontData<'a>,
4236 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
4237 self.condition_set_offset().resolve(data)
4238 }
4239
4240 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
4243 self.feature_table_substitution_offset.get()
4244 }
4245
4246 pub fn feature_table_substitution<'a>(
4252 &self,
4253 data: FontData<'a>,
4254 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
4255 self.feature_table_substitution_offset().resolve(data)
4256 }
4257}
4258
4259impl FixedSize for FeatureVariationRecord {
4260 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4261}
4262
4263#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4265#[repr(C)]
4266#[repr(packed)]
4267pub struct LookupVariationRecord {
4268 pub feature_index: BigEndian<u16>,
4269 pub feature_lookups_offset: BigEndian<Offset32>,
4271}
4272
4273impl LookupVariationRecord {
4274 pub fn feature_index(&self) -> u16 {
4275 self.feature_index.get()
4276 }
4277
4278 pub fn feature_lookups_offset(&self) -> Offset32 {
4280 self.feature_lookups_offset.get()
4281 }
4282
4283 pub fn feature_lookups<'a>(&self, data: FontData<'a>) -> Result<FeatureLookups<'a>, ReadError> {
4288 self.feature_lookups_offset().resolve(data)
4289 }
4290}
4291
4292impl FixedSize for LookupVariationRecord {
4293 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4294}
4295
4296impl<'a> MinByteRange<'a> for FeatureLookups<'a> {
4297 fn min_byte_range(&self) -> Range<usize> {
4298 0..self.lookup_condition_records_byte_range().end
4299 }
4300 fn min_table_bytes(&self) -> &'a [u8] {
4301 let range = self.min_byte_range();
4302 self.offset_data().as_bytes().get(range).unwrap_or_default()
4303 }
4304}
4305
4306impl ReadArgs for FeatureLookups<'_> {
4307 type Args = ();
4308}
4309
4310impl<'a> FontRead<'a> for FeatureLookups<'a> {
4311 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4312 #[allow(clippy::absurd_extreme_comparisons)]
4313 if data.len() < Self::MIN_SIZE {
4314 return Err(ReadError::OutOfBounds);
4315 }
4316 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4317 return Err(ReadError::OutOfBounds);
4318 };
4319 Ok(Self { data })
4320 }
4321}
4322
4323#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4325#[repr(C, packed)]
4326#[doc(hidden)]
4327pub struct FeatureLookupsFixedHeader {
4328 pub version: BigEndian<MajorMinor>,
4329 pub flags: BigEndian<FeatureLookupsFlags>,
4330 pub lookup_condition_count: BigEndian<u32>,
4331}
4332
4333#[allow(clippy::absurd_extreme_comparisons)]
4334const _: () = assert!(std::mem::size_of::<FeatureLookupsFixedHeader>() <= FeatureLookups::MIN_SIZE);
4335
4336#[derive(Clone)]
4338pub struct FeatureLookups<'a> {
4339 data: TableDataRef<'a, FeatureLookupsFixedHeader>,
4340}
4341
4342#[allow(clippy::needless_lifetimes)]
4343impl<'a> FeatureLookups<'a> {
4344 pub const MIN_SIZE: usize =
4345 (MajorMinor::RAW_BYTE_LEN + FeatureLookupsFlags::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4346 basic_table_impls!(impl_the_methods);
4347
4348 pub fn version(&self) -> MajorMinor {
4349 self.data.header().version.get()
4350 }
4351
4352 pub fn flags(&self) -> FeatureLookupsFlags {
4353 self.data.header().flags.get()
4354 }
4355
4356 pub fn lookup_condition_count(&self) -> u32 {
4357 self.data.header().lookup_condition_count.get()
4358 }
4359
4360 pub fn lookup_condition_records(&self) -> &'a [LookupConditionRecord] {
4361 let range = self.lookup_condition_records_byte_range();
4362 self.offset_data()
4363 .read_array(range)
4364 .ok()
4365 .unwrap_or_default()
4366 }
4367
4368 pub fn version_byte_range(&self) -> Range<usize> {
4369 let start = 0;
4370 let end = start + MajorMinor::RAW_BYTE_LEN;
4371 start..end
4372 }
4373
4374 pub fn flags_byte_range(&self) -> Range<usize> {
4375 let start = self.version_byte_range().end;
4376 let end = start + FeatureLookupsFlags::RAW_BYTE_LEN;
4377 start..end
4378 }
4379
4380 pub fn lookup_condition_count_byte_range(&self) -> Range<usize> {
4381 let start = self.flags_byte_range().end;
4382 let end = start + u32::RAW_BYTE_LEN;
4383 start..end
4384 }
4385
4386 pub fn lookup_condition_records_byte_range(&self) -> Range<usize> {
4387 let lookup_condition_count = self.lookup_condition_count();
4388 let start = self.lookup_condition_count_byte_range().end;
4389 let end = start
4390 + (transforms::to_usize(lookup_condition_count))
4391 .saturating_mul(LookupConditionRecord::RAW_BYTE_LEN);
4392 start..end
4393 }
4394}
4395
4396const _: () = assert!(FontData::default_data_long_enough(FeatureLookups::MIN_SIZE));
4397
4398impl Default for FeatureLookups<'_> {
4399 fn default() -> Self {
4400 Self {
4401 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4402 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4403 }
4404 }
4405}
4406
4407#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
4409#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4410#[repr(transparent)]
4411pub struct FeatureLookupsFlags {
4412 bits: u16,
4413}
4414
4415impl FeatureLookupsFlags {
4416 pub const ADD_DEFAULT_LOOKUPS: Self = Self { bits: 0x0001 };
4418}
4419
4420impl FeatureLookupsFlags {
4421 #[inline]
4423 pub const fn empty() -> Self {
4424 Self { bits: 0 }
4425 }
4426
4427 #[inline]
4429 pub const fn all() -> Self {
4430 Self {
4431 bits: Self::ADD_DEFAULT_LOOKUPS.bits,
4432 }
4433 }
4434
4435 #[inline]
4437 pub const fn bits(&self) -> u16 {
4438 self.bits
4439 }
4440
4441 #[inline]
4444 pub const fn from_bits(bits: u16) -> Option<Self> {
4445 if (bits & !Self::all().bits()) == 0 {
4446 Some(Self { bits })
4447 } else {
4448 None
4449 }
4450 }
4451
4452 #[inline]
4455 pub const fn from_bits_truncate(bits: u16) -> Self {
4456 Self {
4457 bits: bits & Self::all().bits,
4458 }
4459 }
4460
4461 #[inline]
4463 pub const fn is_empty(&self) -> bool {
4464 self.bits() == Self::empty().bits()
4465 }
4466
4467 #[inline]
4469 pub const fn intersects(&self, other: Self) -> bool {
4470 !(Self {
4471 bits: self.bits & other.bits,
4472 })
4473 .is_empty()
4474 }
4475
4476 #[inline]
4478 pub const fn contains(&self, other: Self) -> bool {
4479 (self.bits & other.bits) == other.bits
4480 }
4481
4482 #[inline]
4484 pub fn insert(&mut self, other: Self) {
4485 self.bits |= other.bits;
4486 }
4487
4488 #[inline]
4490 pub fn remove(&mut self, other: Self) {
4491 self.bits &= !other.bits;
4492 }
4493
4494 #[inline]
4496 pub fn toggle(&mut self, other: Self) {
4497 self.bits ^= other.bits;
4498 }
4499
4500 #[inline]
4511 #[must_use]
4512 pub const fn intersection(self, other: Self) -> Self {
4513 Self {
4514 bits: self.bits & other.bits,
4515 }
4516 }
4517
4518 #[inline]
4529 #[must_use]
4530 pub const fn union(self, other: Self) -> Self {
4531 Self {
4532 bits: self.bits | other.bits,
4533 }
4534 }
4535
4536 #[inline]
4549 #[must_use]
4550 pub const fn difference(self, other: Self) -> Self {
4551 Self {
4552 bits: self.bits & !other.bits,
4553 }
4554 }
4555}
4556
4557impl std::ops::BitOr for FeatureLookupsFlags {
4558 type Output = Self;
4559
4560 #[inline]
4562 fn bitor(self, other: FeatureLookupsFlags) -> Self {
4563 Self {
4564 bits: self.bits | other.bits,
4565 }
4566 }
4567}
4568
4569impl std::ops::BitOrAssign for FeatureLookupsFlags {
4570 #[inline]
4572 fn bitor_assign(&mut self, other: Self) {
4573 self.bits |= other.bits;
4574 }
4575}
4576
4577impl std::ops::BitXor for FeatureLookupsFlags {
4578 type Output = Self;
4579
4580 #[inline]
4582 fn bitxor(self, other: Self) -> Self {
4583 Self {
4584 bits: self.bits ^ other.bits,
4585 }
4586 }
4587}
4588
4589impl std::ops::BitXorAssign for FeatureLookupsFlags {
4590 #[inline]
4592 fn bitxor_assign(&mut self, other: Self) {
4593 self.bits ^= other.bits;
4594 }
4595}
4596
4597impl std::ops::BitAnd for FeatureLookupsFlags {
4598 type Output = Self;
4599
4600 #[inline]
4602 fn bitand(self, other: Self) -> Self {
4603 Self {
4604 bits: self.bits & other.bits,
4605 }
4606 }
4607}
4608
4609impl std::ops::BitAndAssign for FeatureLookupsFlags {
4610 #[inline]
4612 fn bitand_assign(&mut self, other: Self) {
4613 self.bits &= other.bits;
4614 }
4615}
4616
4617impl std::ops::Sub for FeatureLookupsFlags {
4618 type Output = Self;
4619
4620 #[inline]
4622 fn sub(self, other: Self) -> Self {
4623 Self {
4624 bits: self.bits & !other.bits,
4625 }
4626 }
4627}
4628
4629impl std::ops::SubAssign for FeatureLookupsFlags {
4630 #[inline]
4632 fn sub_assign(&mut self, other: Self) {
4633 self.bits &= !other.bits;
4634 }
4635}
4636
4637impl std::ops::Not for FeatureLookupsFlags {
4638 type Output = Self;
4639
4640 #[inline]
4642 fn not(self) -> Self {
4643 Self { bits: !self.bits } & Self::all()
4644 }
4645}
4646
4647impl std::fmt::Debug for FeatureLookupsFlags {
4648 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4649 let members: &[(&str, Self)] = &[("ADD_DEFAULT_LOOKUPS", Self::ADD_DEFAULT_LOOKUPS)];
4650 let mut first = true;
4651 for (name, value) in members {
4652 if self.contains(*value) {
4653 if !first {
4654 f.write_str(" | ")?;
4655 }
4656 first = false;
4657 f.write_str(name)?;
4658 }
4659 }
4660 if first {
4661 f.write_str("(empty)")?;
4662 }
4663 Ok(())
4664 }
4665}
4666
4667impl std::fmt::Binary for FeatureLookupsFlags {
4668 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4669 std::fmt::Binary::fmt(&self.bits, f)
4670 }
4671}
4672
4673impl std::fmt::Octal for FeatureLookupsFlags {
4674 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4675 std::fmt::Octal::fmt(&self.bits, f)
4676 }
4677}
4678
4679impl std::fmt::LowerHex for FeatureLookupsFlags {
4680 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4681 std::fmt::LowerHex::fmt(&self.bits, f)
4682 }
4683}
4684
4685impl std::fmt::UpperHex for FeatureLookupsFlags {
4686 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4687 std::fmt::UpperHex::fmt(&self.bits, f)
4688 }
4689}
4690
4691impl font_types::Scalar for FeatureLookupsFlags {
4692 type Raw = <u16 as font_types::Scalar>::Raw;
4693 fn to_raw(self) -> Self::Raw {
4694 self.bits().to_raw()
4695 }
4696 fn from_raw(raw: Self::Raw) -> Self {
4697 let t = <u16>::from_raw(raw);
4698 Self::from_bits_truncate(t)
4699 }
4700}
4701
4702#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4704#[repr(C)]
4705#[repr(packed)]
4706pub struct LookupConditionRecord {
4707 pub condition_offset: BigEndian<Nullable<Offset32>>,
4709 pub lookup_index_list_offset: BigEndian<Offset32>,
4711}
4712
4713impl LookupConditionRecord {
4714 pub fn condition_offset(&self) -> Nullable<Offset32> {
4716 self.condition_offset.get()
4717 }
4718
4719 pub fn condition<'a>(&self, data: FontData<'a>) -> Option<Result<Condition<'a>, ReadError>> {
4724 self.condition_offset().resolve(data)
4725 }
4726
4727 pub fn lookup_index_list_offset(&self) -> Offset32 {
4729 self.lookup_index_list_offset.get()
4730 }
4731
4732 pub fn lookup_index_list<'a>(
4737 &self,
4738 data: FontData<'a>,
4739 ) -> Result<LookupIndexList<'a>, ReadError> {
4740 self.lookup_index_list_offset().resolve(data)
4741 }
4742}
4743
4744impl FixedSize for LookupConditionRecord {
4745 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4746}
4747
4748impl<'a> MinByteRange<'a> for LookupIndexList<'a> {
4749 fn min_byte_range(&self) -> Range<usize> {
4750 0..self.lookup_indices_byte_range().end
4751 }
4752 fn min_table_bytes(&self) -> &'a [u8] {
4753 let range = self.min_byte_range();
4754 self.offset_data().as_bytes().get(range).unwrap_or_default()
4755 }
4756}
4757
4758impl ReadArgs for LookupIndexList<'_> {
4759 type Args = ();
4760}
4761
4762impl<'a> FontRead<'a> for LookupIndexList<'a> {
4763 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4764 #[allow(clippy::absurd_extreme_comparisons)]
4765 if data.len() < Self::MIN_SIZE {
4766 return Err(ReadError::OutOfBounds);
4767 }
4768 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4769 return Err(ReadError::OutOfBounds);
4770 };
4771 Ok(Self { data })
4772 }
4773}
4774
4775#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4777#[repr(C, packed)]
4778#[doc(hidden)]
4779pub struct LookupIndexListFixedHeader {
4780 pub lookup_index_count: BigEndian<u16>,
4781}
4782
4783#[allow(clippy::absurd_extreme_comparisons)]
4784const _: () =
4785 assert!(std::mem::size_of::<LookupIndexListFixedHeader>() <= LookupIndexList::MIN_SIZE);
4786
4787#[derive(Clone)]
4789pub struct LookupIndexList<'a> {
4790 data: TableDataRef<'a, LookupIndexListFixedHeader>,
4791}
4792
4793#[allow(clippy::needless_lifetimes)]
4794impl<'a> LookupIndexList<'a> {
4795 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
4796 basic_table_impls!(impl_the_methods);
4797
4798 pub fn lookup_index_count(&self) -> u16 {
4799 self.data.header().lookup_index_count.get()
4800 }
4801
4802 pub fn lookup_indices(&self) -> &'a [BigEndian<u16>] {
4803 let range = self.lookup_indices_byte_range();
4804 self.offset_data()
4805 .read_array(range)
4806 .ok()
4807 .unwrap_or_default()
4808 }
4809
4810 pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
4811 let start = 0;
4812 let end = start + u16::RAW_BYTE_LEN;
4813 start..end
4814 }
4815
4816 pub fn lookup_indices_byte_range(&self) -> Range<usize> {
4817 let lookup_index_count = self.lookup_index_count();
4818 let start = self.lookup_index_count_byte_range().end;
4819 let end =
4820 start + (transforms::to_usize(lookup_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
4821 start..end
4822 }
4823}
4824
4825const _: () = assert!(FontData::default_data_long_enough(
4826 LookupIndexList::MIN_SIZE
4827));
4828
4829impl Default for LookupIndexList<'_> {
4830 fn default() -> Self {
4831 Self {
4832 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4833 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4834 }
4835 }
4836}
4837
4838impl<'a> MinByteRange<'a> for ConditionSet<'a> {
4839 fn min_byte_range(&self) -> Range<usize> {
4840 0..self.condition_offsets_byte_range().end
4841 }
4842 fn min_table_bytes(&self) -> &'a [u8] {
4843 let range = self.min_byte_range();
4844 self.offset_data().as_bytes().get(range).unwrap_or_default()
4845 }
4846}
4847
4848impl ReadArgs for ConditionSet<'_> {
4849 type Args = ();
4850}
4851
4852impl<'a> FontRead<'a> for ConditionSet<'a> {
4853 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4854 #[allow(clippy::absurd_extreme_comparisons)]
4855 if data.len() < Self::MIN_SIZE {
4856 return Err(ReadError::OutOfBounds);
4857 }
4858 let Some(data) = TableDataRef::new(data.as_bytes()) else {
4859 return Err(ReadError::OutOfBounds);
4860 };
4861 Ok(Self { data })
4862 }
4863}
4864
4865#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
4867#[repr(C, packed)]
4868#[doc(hidden)]
4869pub struct ConditionSetFixedHeader {
4870 pub condition_count: BigEndian<u16>,
4871}
4872
4873#[allow(clippy::absurd_extreme_comparisons)]
4874const _: () = assert!(std::mem::size_of::<ConditionSetFixedHeader>() <= ConditionSet::MIN_SIZE);
4875
4876#[derive(Clone)]
4878pub struct ConditionSet<'a> {
4879 data: TableDataRef<'a, ConditionSetFixedHeader>,
4880}
4881
4882#[allow(clippy::needless_lifetimes)]
4883impl<'a> ConditionSet<'a> {
4884 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
4885 basic_table_impls!(impl_the_methods);
4886
4887 pub fn condition_count(&self) -> u16 {
4889 self.data.header().condition_count.get()
4890 }
4891
4892 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
4895 let range = self.condition_offsets_byte_range();
4896 self.offset_data()
4897 .read_array(range)
4898 .ok()
4899 .unwrap_or_default()
4900 }
4901
4902 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
4904 let data = self.offset_data();
4905 let offsets = self.condition_offsets();
4906 ArrayOfOffsets::new(offsets, data, ())
4907 }
4908
4909 pub fn condition_count_byte_range(&self) -> Range<usize> {
4910 let start = 0;
4911 let end = start + u16::RAW_BYTE_LEN;
4912 start..end
4913 }
4914
4915 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4916 let condition_count = self.condition_count();
4917 let start = self.condition_count_byte_range().end;
4918 let end =
4919 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
4920 start..end
4921 }
4922}
4923
4924const _: () = assert!(FontData::default_data_long_enough(ConditionSet::MIN_SIZE));
4925
4926impl Default for ConditionSet<'_> {
4927 fn default() -> Self {
4928 Self {
4929 data: TableDataRef::new(FontData::default_table_data().as_bytes())
4930 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
4931 }
4932 }
4933}
4934
4935#[derive(Clone)]
4939pub enum Condition<'a> {
4940 Format1AxisRange(ConditionFormat1<'a>),
4941 Format2VariableValue(ConditionFormat2<'a>),
4942 Format3And(ConditionFormat3<'a>),
4943 Format4Or(ConditionFormat4<'a>),
4944 Format5Negate(ConditionFormat5<'a>),
4945}
4946
4947impl Default for Condition<'_> {
4948 fn default() -> Self {
4949 Self::Format1AxisRange(Default::default())
4950 }
4951}
4952
4953impl<'a> Condition<'a> {
4954 pub fn offset_data(&self) -> FontData<'a> {
4956 match self {
4957 Self::Format1AxisRange(item) => item.offset_data(),
4958 Self::Format2VariableValue(item) => item.offset_data(),
4959 Self::Format3And(item) => item.offset_data(),
4960 Self::Format4Or(item) => item.offset_data(),
4961 Self::Format5Negate(item) => item.offset_data(),
4962 }
4963 }
4964
4965 pub fn format(&self) -> u16 {
4967 match self {
4968 Self::Format1AxisRange(item) => item.format(),
4969 Self::Format2VariableValue(item) => item.format(),
4970 Self::Format3And(item) => item.format(),
4971 Self::Format4Or(item) => item.format(),
4972 Self::Format5Negate(item) => item.format(),
4973 }
4974 }
4975}
4976
4977impl ReadArgs for Condition<'_> {
4978 type Args = ();
4979}
4980
4981impl<'a> FontRead<'a> for Condition<'a> {
4982 #[inline]
4983 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4984 let format: u16 = data.read_at(0usize)?;
4985 match format {
4986 ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
4987 ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
4988 ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
4989 ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
4990 ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
4991 other => Err(ReadError::InvalidFormat(other.into())),
4992 }
4993 }
4994}
4995
4996impl<'a> MinByteRange<'a> for Condition<'a> {
4997 fn min_byte_range(&self) -> Range<usize> {
4998 match self {
4999 Self::Format1AxisRange(item) => item.min_byte_range(),
5000 Self::Format2VariableValue(item) => item.min_byte_range(),
5001 Self::Format3And(item) => item.min_byte_range(),
5002 Self::Format4Or(item) => item.min_byte_range(),
5003 Self::Format5Negate(item) => item.min_byte_range(),
5004 }
5005 }
5006 fn min_table_bytes(&self) -> &'a [u8] {
5007 match self {
5008 Self::Format1AxisRange(item) => item.min_table_bytes(),
5009 Self::Format2VariableValue(item) => item.min_table_bytes(),
5010 Self::Format3And(item) => item.min_table_bytes(),
5011 Self::Format4Or(item) => item.min_table_bytes(),
5012 Self::Format5Negate(item) => item.min_table_bytes(),
5013 }
5014 }
5015}
5016
5017impl Format<u16> for ConditionFormat1<'_> {
5018 const FORMAT: u16 = 1;
5019}
5020
5021impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
5022 fn min_byte_range(&self) -> Range<usize> {
5023 0..self.filter_range_max_value_byte_range().end
5024 }
5025 fn min_table_bytes(&self) -> &'a [u8] {
5026 let range = self.min_byte_range();
5027 self.offset_data().as_bytes().get(range).unwrap_or_default()
5028 }
5029}
5030
5031impl ReadArgs for ConditionFormat1<'_> {
5032 type Args = ();
5033}
5034
5035impl<'a> FontRead<'a> for ConditionFormat1<'a> {
5036 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5037 #[allow(clippy::absurd_extreme_comparisons)]
5038 if data.len() < Self::MIN_SIZE {
5039 return Err(ReadError::OutOfBounds);
5040 }
5041 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5042 return Err(ReadError::OutOfBounds);
5043 };
5044 Ok(Self { data })
5045 }
5046}
5047
5048#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5050#[repr(C, packed)]
5051#[doc(hidden)]
5052pub struct ConditionFormat1FixedHeader {
5053 pub format: BigEndian<u16>,
5054 pub axis_index: BigEndian<u16>,
5055 pub filter_range_min_value: BigEndian<F2Dot14>,
5056 pub filter_range_max_value: BigEndian<F2Dot14>,
5057}
5058
5059#[allow(clippy::absurd_extreme_comparisons)]
5060const _: () =
5061 assert!(std::mem::size_of::<ConditionFormat1FixedHeader>() <= ConditionFormat1::MIN_SIZE);
5062
5063#[derive(Clone)]
5065pub struct ConditionFormat1<'a> {
5066 data: TableDataRef<'a, ConditionFormat1FixedHeader>,
5067}
5068
5069#[allow(clippy::needless_lifetimes)]
5070impl<'a> ConditionFormat1<'a> {
5071 pub const MIN_SIZE: usize =
5072 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
5073 basic_table_impls!(impl_the_methods);
5074
5075 pub fn format(&self) -> u16 {
5077 self.data.header().format.get()
5078 }
5079
5080 pub fn axis_index(&self) -> u16 {
5083 self.data.header().axis_index.get()
5084 }
5085
5086 pub fn filter_range_min_value(&self) -> F2Dot14 {
5089 self.data.header().filter_range_min_value.get()
5090 }
5091
5092 pub fn filter_range_max_value(&self) -> F2Dot14 {
5095 self.data.header().filter_range_max_value.get()
5096 }
5097
5098 pub fn format_byte_range(&self) -> Range<usize> {
5099 let start = 0;
5100 let end = start + u16::RAW_BYTE_LEN;
5101 start..end
5102 }
5103
5104 pub fn axis_index_byte_range(&self) -> Range<usize> {
5105 let start = self.format_byte_range().end;
5106 let end = start + u16::RAW_BYTE_LEN;
5107 start..end
5108 }
5109
5110 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
5111 let start = self.axis_index_byte_range().end;
5112 let end = start + F2Dot14::RAW_BYTE_LEN;
5113 start..end
5114 }
5115
5116 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
5117 let start = self.filter_range_min_value_byte_range().end;
5118 let end = start + F2Dot14::RAW_BYTE_LEN;
5119 start..end
5120 }
5121}
5122
5123const _: () = assert!(FontData::default_data_long_enough(
5124 ConditionFormat1::MIN_SIZE
5125));
5126
5127impl Default for ConditionFormat1<'_> {
5128 fn default() -> Self {
5129 Self {
5130 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
5131 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5132 }
5133 }
5134}
5135
5136impl Format<u16> for ConditionFormat2<'_> {
5137 const FORMAT: u16 = 2;
5138}
5139
5140impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
5141 fn min_byte_range(&self) -> Range<usize> {
5142 0..self.var_index_byte_range().end
5143 }
5144 fn min_table_bytes(&self) -> &'a [u8] {
5145 let range = self.min_byte_range();
5146 self.offset_data().as_bytes().get(range).unwrap_or_default()
5147 }
5148}
5149
5150impl ReadArgs for ConditionFormat2<'_> {
5151 type Args = ();
5152}
5153
5154impl<'a> FontRead<'a> for ConditionFormat2<'a> {
5155 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5156 #[allow(clippy::absurd_extreme_comparisons)]
5157 if data.len() < Self::MIN_SIZE {
5158 return Err(ReadError::OutOfBounds);
5159 }
5160 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5161 return Err(ReadError::OutOfBounds);
5162 };
5163 Ok(Self { data })
5164 }
5165}
5166
5167#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5169#[repr(C, packed)]
5170#[doc(hidden)]
5171pub struct ConditionFormat2FixedHeader {
5172 pub format: BigEndian<u16>,
5173 pub default_value: BigEndian<i16>,
5174 pub var_index: BigEndian<u32>,
5175}
5176
5177#[allow(clippy::absurd_extreme_comparisons)]
5178const _: () =
5179 assert!(std::mem::size_of::<ConditionFormat2FixedHeader>() <= ConditionFormat2::MIN_SIZE);
5180
5181#[derive(Clone)]
5183pub struct ConditionFormat2<'a> {
5184 data: TableDataRef<'a, ConditionFormat2FixedHeader>,
5185}
5186
5187#[allow(clippy::needless_lifetimes)]
5188impl<'a> ConditionFormat2<'a> {
5189 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
5190 basic_table_impls!(impl_the_methods);
5191
5192 pub fn format(&self) -> u16 {
5194 self.data.header().format.get()
5195 }
5196
5197 pub fn default_value(&self) -> i16 {
5199 self.data.header().default_value.get()
5200 }
5201
5202 pub fn var_index(&self) -> u32 {
5204 self.data.header().var_index.get()
5205 }
5206
5207 pub fn format_byte_range(&self) -> Range<usize> {
5208 let start = 0;
5209 let end = start + u16::RAW_BYTE_LEN;
5210 start..end
5211 }
5212
5213 pub fn default_value_byte_range(&self) -> Range<usize> {
5214 let start = self.format_byte_range().end;
5215 let end = start + i16::RAW_BYTE_LEN;
5216 start..end
5217 }
5218
5219 pub fn var_index_byte_range(&self) -> Range<usize> {
5220 let start = self.default_value_byte_range().end;
5221 let end = start + u32::RAW_BYTE_LEN;
5222 start..end
5223 }
5224}
5225
5226impl Format<u16> for ConditionFormat3<'_> {
5227 const FORMAT: u16 = 3;
5228}
5229
5230impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
5231 fn min_byte_range(&self) -> Range<usize> {
5232 0..self.condition_offsets_byte_range().end
5233 }
5234 fn min_table_bytes(&self) -> &'a [u8] {
5235 let range = self.min_byte_range();
5236 self.offset_data().as_bytes().get(range).unwrap_or_default()
5237 }
5238}
5239
5240impl ReadArgs for ConditionFormat3<'_> {
5241 type Args = ();
5242}
5243
5244impl<'a> FontRead<'a> for ConditionFormat3<'a> {
5245 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5246 #[allow(clippy::absurd_extreme_comparisons)]
5247 if data.len() < Self::MIN_SIZE {
5248 return Err(ReadError::OutOfBounds);
5249 }
5250 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5251 return Err(ReadError::OutOfBounds);
5252 };
5253 Ok(Self { data })
5254 }
5255}
5256
5257#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5259#[repr(C, packed)]
5260#[doc(hidden)]
5261pub struct ConditionFormat3FixedHeader {
5262 pub format: BigEndian<u16>,
5263 pub condition_count: u8,
5264}
5265
5266#[allow(clippy::absurd_extreme_comparisons)]
5267const _: () =
5268 assert!(std::mem::size_of::<ConditionFormat3FixedHeader>() <= ConditionFormat3::MIN_SIZE);
5269
5270#[derive(Clone)]
5272pub struct ConditionFormat3<'a> {
5273 data: TableDataRef<'a, ConditionFormat3FixedHeader>,
5274}
5275
5276#[allow(clippy::needless_lifetimes)]
5277impl<'a> ConditionFormat3<'a> {
5278 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5279 basic_table_impls!(impl_the_methods);
5280
5281 pub fn format(&self) -> u16 {
5283 self.data.header().format.get()
5284 }
5285
5286 pub fn condition_count(&self) -> u8 {
5288 self.data.header().condition_count
5289 }
5290
5291 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5293 let range = self.condition_offsets_byte_range();
5294 self.offset_data()
5295 .read_array(range)
5296 .ok()
5297 .unwrap_or_default()
5298 }
5299
5300 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5302 let data = self.offset_data();
5303 let offsets = self.condition_offsets();
5304 ArrayOfOffsets::new(offsets, data, ())
5305 }
5306
5307 pub fn format_byte_range(&self) -> Range<usize> {
5308 let start = 0;
5309 let end = start + u16::RAW_BYTE_LEN;
5310 start..end
5311 }
5312
5313 pub fn condition_count_byte_range(&self) -> Range<usize> {
5314 let start = self.format_byte_range().end;
5315 let end = start + u8::RAW_BYTE_LEN;
5316 start..end
5317 }
5318
5319 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5320 let condition_count = self.condition_count();
5321 let start = self.condition_count_byte_range().end;
5322 let end =
5323 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5324 start..end
5325 }
5326}
5327
5328impl Format<u16> for ConditionFormat4<'_> {
5329 const FORMAT: u16 = 4;
5330}
5331
5332impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
5333 fn min_byte_range(&self) -> Range<usize> {
5334 0..self.condition_offsets_byte_range().end
5335 }
5336 fn min_table_bytes(&self) -> &'a [u8] {
5337 let range = self.min_byte_range();
5338 self.offset_data().as_bytes().get(range).unwrap_or_default()
5339 }
5340}
5341
5342impl ReadArgs for ConditionFormat4<'_> {
5343 type Args = ();
5344}
5345
5346impl<'a> FontRead<'a> for ConditionFormat4<'a> {
5347 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5348 #[allow(clippy::absurd_extreme_comparisons)]
5349 if data.len() < Self::MIN_SIZE {
5350 return Err(ReadError::OutOfBounds);
5351 }
5352 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5353 return Err(ReadError::OutOfBounds);
5354 };
5355 Ok(Self { data })
5356 }
5357}
5358
5359#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5361#[repr(C, packed)]
5362#[doc(hidden)]
5363pub struct ConditionFormat4FixedHeader {
5364 pub format: BigEndian<u16>,
5365 pub condition_count: u8,
5366}
5367
5368#[allow(clippy::absurd_extreme_comparisons)]
5369const _: () =
5370 assert!(std::mem::size_of::<ConditionFormat4FixedHeader>() <= ConditionFormat4::MIN_SIZE);
5371
5372#[derive(Clone)]
5374pub struct ConditionFormat4<'a> {
5375 data: TableDataRef<'a, ConditionFormat4FixedHeader>,
5376}
5377
5378#[allow(clippy::needless_lifetimes)]
5379impl<'a> ConditionFormat4<'a> {
5380 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5381 basic_table_impls!(impl_the_methods);
5382
5383 pub fn format(&self) -> u16 {
5385 self.data.header().format.get()
5386 }
5387
5388 pub fn condition_count(&self) -> u8 {
5390 self.data.header().condition_count
5391 }
5392
5393 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5395 let range = self.condition_offsets_byte_range();
5396 self.offset_data()
5397 .read_array(range)
5398 .ok()
5399 .unwrap_or_default()
5400 }
5401
5402 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5404 let data = self.offset_data();
5405 let offsets = self.condition_offsets();
5406 ArrayOfOffsets::new(offsets, data, ())
5407 }
5408
5409 pub fn format_byte_range(&self) -> Range<usize> {
5410 let start = 0;
5411 let end = start + u16::RAW_BYTE_LEN;
5412 start..end
5413 }
5414
5415 pub fn condition_count_byte_range(&self) -> Range<usize> {
5416 let start = self.format_byte_range().end;
5417 let end = start + u8::RAW_BYTE_LEN;
5418 start..end
5419 }
5420
5421 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5422 let condition_count = self.condition_count();
5423 let start = self.condition_count_byte_range().end;
5424 let end =
5425 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5426 start..end
5427 }
5428}
5429
5430impl Format<u16> for ConditionFormat5<'_> {
5431 const FORMAT: u16 = 5;
5432}
5433
5434impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
5435 fn min_byte_range(&self) -> Range<usize> {
5436 0..self.condition_offset_byte_range().end
5437 }
5438 fn min_table_bytes(&self) -> &'a [u8] {
5439 let range = self.min_byte_range();
5440 self.offset_data().as_bytes().get(range).unwrap_or_default()
5441 }
5442}
5443
5444impl ReadArgs for ConditionFormat5<'_> {
5445 type Args = ();
5446}
5447
5448impl<'a> FontRead<'a> for ConditionFormat5<'a> {
5449 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5450 #[allow(clippy::absurd_extreme_comparisons)]
5451 if data.len() < Self::MIN_SIZE {
5452 return Err(ReadError::OutOfBounds);
5453 }
5454 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5455 return Err(ReadError::OutOfBounds);
5456 };
5457 Ok(Self { data })
5458 }
5459}
5460
5461#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5463#[repr(C, packed)]
5464#[doc(hidden)]
5465pub struct ConditionFormat5FixedHeader {
5466 pub format: BigEndian<u16>,
5467 pub condition_offset: BigEndian<Offset24>,
5468}
5469
5470#[allow(clippy::absurd_extreme_comparisons)]
5471const _: () =
5472 assert!(std::mem::size_of::<ConditionFormat5FixedHeader>() <= ConditionFormat5::MIN_SIZE);
5473
5474#[derive(Clone)]
5476pub struct ConditionFormat5<'a> {
5477 data: TableDataRef<'a, ConditionFormat5FixedHeader>,
5478}
5479
5480#[allow(clippy::needless_lifetimes)]
5481impl<'a> ConditionFormat5<'a> {
5482 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
5483 basic_table_impls!(impl_the_methods);
5484
5485 pub fn format(&self) -> u16 {
5487 self.data.header().format.get()
5488 }
5489
5490 pub fn condition_offset(&self) -> Offset24 {
5492 self.data.header().condition_offset.get()
5493 }
5494
5495 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
5497 let data = self.offset_data();
5498 self.condition_offset().resolve(data)
5499 }
5500
5501 pub fn format_byte_range(&self) -> Range<usize> {
5502 let start = 0;
5503 let end = start + u16::RAW_BYTE_LEN;
5504 start..end
5505 }
5506
5507 pub fn condition_offset_byte_range(&self) -> Range<usize> {
5508 let start = self.format_byte_range().end;
5509 let end = start + Offset24::RAW_BYTE_LEN;
5510 start..end
5511 }
5512}
5513
5514impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
5515 fn min_byte_range(&self) -> Range<usize> {
5516 0..self.substitutions_byte_range().end
5517 }
5518 fn min_table_bytes(&self) -> &'a [u8] {
5519 let range = self.min_byte_range();
5520 self.offset_data().as_bytes().get(range).unwrap_or_default()
5521 }
5522}
5523
5524impl ReadArgs for FeatureTableSubstitution<'_> {
5525 type Args = ();
5526}
5527
5528impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
5529 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5530 #[allow(clippy::absurd_extreme_comparisons)]
5531 if data.len() < Self::MIN_SIZE {
5532 return Err(ReadError::OutOfBounds);
5533 }
5534 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5535 return Err(ReadError::OutOfBounds);
5536 };
5537 Ok(Self { data })
5538 }
5539}
5540
5541#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5543#[repr(C, packed)]
5544#[doc(hidden)]
5545pub struct FeatureTableSubstitutionFixedHeader {
5546 pub version: BigEndian<MajorMinor>,
5547 pub substitution_count: BigEndian<u16>,
5548}
5549
5550#[allow(clippy::absurd_extreme_comparisons)]
5551const _: () = assert!(
5552 std::mem::size_of::<FeatureTableSubstitutionFixedHeader>()
5553 <= FeatureTableSubstitution::MIN_SIZE
5554);
5555
5556#[derive(Clone)]
5558pub struct FeatureTableSubstitution<'a> {
5559 data: TableDataRef<'a, FeatureTableSubstitutionFixedHeader>,
5560}
5561
5562#[allow(clippy::needless_lifetimes)]
5563impl<'a> FeatureTableSubstitution<'a> {
5564 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
5565 basic_table_impls!(impl_the_methods);
5566
5567 pub fn version(&self) -> MajorMinor {
5569 self.data.header().version.get()
5570 }
5571
5572 pub fn substitution_count(&self) -> u16 {
5574 self.data.header().substitution_count.get()
5575 }
5576
5577 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
5579 let range = self.substitutions_byte_range();
5580 self.offset_data()
5581 .read_array(range)
5582 .ok()
5583 .unwrap_or_default()
5584 }
5585
5586 pub fn version_byte_range(&self) -> Range<usize> {
5587 let start = 0;
5588 let end = start + MajorMinor::RAW_BYTE_LEN;
5589 start..end
5590 }
5591
5592 pub fn substitution_count_byte_range(&self) -> Range<usize> {
5593 let start = self.version_byte_range().end;
5594 let end = start + u16::RAW_BYTE_LEN;
5595 start..end
5596 }
5597
5598 pub fn substitutions_byte_range(&self) -> Range<usize> {
5599 let substitution_count = self.substitution_count();
5600 let start = self.substitution_count_byte_range().end;
5601 let end = start
5602 + (transforms::to_usize(substitution_count))
5603 .saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN);
5604 start..end
5605 }
5606}
5607
5608const _: () = assert!(FontData::default_data_long_enough(
5609 FeatureTableSubstitution::MIN_SIZE
5610));
5611
5612impl Default for FeatureTableSubstitution<'_> {
5613 fn default() -> Self {
5614 Self {
5615 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5616 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5617 }
5618 }
5619}
5620
5621#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
5623#[repr(C)]
5624#[repr(packed)]
5625pub struct FeatureTableSubstitutionRecord {
5626 pub feature_index: BigEndian<u16>,
5628 pub alternate_feature_offset: BigEndian<Offset32>,
5631}
5632
5633impl FeatureTableSubstitutionRecord {
5634 pub fn feature_index(&self) -> u16 {
5636 self.feature_index.get()
5637 }
5638
5639 pub fn alternate_feature_offset(&self) -> Offset32 {
5642 self.alternate_feature_offset.get()
5643 }
5644}
5645
5646impl FixedSize for FeatureTableSubstitutionRecord {
5647 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
5648}
5649
5650impl<'a> MinByteRange<'a> for SizeParams<'a> {
5651 fn min_byte_range(&self) -> Range<usize> {
5652 0..self.range_end_byte_range().end
5653 }
5654 fn min_table_bytes(&self) -> &'a [u8] {
5655 let range = self.min_byte_range();
5656 self.offset_data().as_bytes().get(range).unwrap_or_default()
5657 }
5658}
5659
5660impl ReadArgs for SizeParams<'_> {
5661 type Args = ();
5662}
5663
5664impl<'a> FontRead<'a> for SizeParams<'a> {
5665 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5666 #[allow(clippy::absurd_extreme_comparisons)]
5667 if data.len() < Self::MIN_SIZE {
5668 return Err(ReadError::OutOfBounds);
5669 }
5670 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5671 return Err(ReadError::OutOfBounds);
5672 };
5673 Ok(Self { data })
5674 }
5675}
5676
5677#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5679#[repr(C, packed)]
5680#[doc(hidden)]
5681pub struct SizeParamsFixedHeader {
5682 pub design_size: BigEndian<u16>,
5683 pub identifier: BigEndian<u16>,
5684 pub name_entry: BigEndian<u16>,
5685 pub range_start: BigEndian<u16>,
5686 pub range_end: BigEndian<u16>,
5687}
5688
5689#[allow(clippy::absurd_extreme_comparisons)]
5690const _: () = assert!(std::mem::size_of::<SizeParamsFixedHeader>() <= SizeParams::MIN_SIZE);
5691
5692#[derive(Clone)]
5693pub struct SizeParams<'a> {
5694 data: TableDataRef<'a, SizeParamsFixedHeader>,
5695}
5696
5697#[allow(clippy::needless_lifetimes)]
5698impl<'a> SizeParams<'a> {
5699 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5700 + u16::RAW_BYTE_LEN
5701 + u16::RAW_BYTE_LEN
5702 + u16::RAW_BYTE_LEN
5703 + u16::RAW_BYTE_LEN);
5704 basic_table_impls!(impl_the_methods);
5705
5706 pub fn design_size(&self) -> u16 {
5711 self.data.header().design_size.get()
5712 }
5713
5714 pub fn identifier(&self) -> u16 {
5721 self.data.header().identifier.get()
5722 }
5723
5724 pub fn name_entry(&self) -> u16 {
5735 self.data.header().name_entry.get()
5736 }
5737
5738 pub fn range_start(&self) -> u16 {
5744 self.data.header().range_start.get()
5745 }
5746
5747 pub fn range_end(&self) -> u16 {
5748 self.data.header().range_end.get()
5749 }
5750
5751 pub fn design_size_byte_range(&self) -> Range<usize> {
5752 let start = 0;
5753 let end = start + u16::RAW_BYTE_LEN;
5754 start..end
5755 }
5756
5757 pub fn identifier_byte_range(&self) -> Range<usize> {
5758 let start = self.design_size_byte_range().end;
5759 let end = start + u16::RAW_BYTE_LEN;
5760 start..end
5761 }
5762
5763 pub fn name_entry_byte_range(&self) -> Range<usize> {
5764 let start = self.identifier_byte_range().end;
5765 let end = start + u16::RAW_BYTE_LEN;
5766 start..end
5767 }
5768
5769 pub fn range_start_byte_range(&self) -> Range<usize> {
5770 let start = self.name_entry_byte_range().end;
5771 let end = start + u16::RAW_BYTE_LEN;
5772 start..end
5773 }
5774
5775 pub fn range_end_byte_range(&self) -> Range<usize> {
5776 let start = self.range_start_byte_range().end;
5777 let end = start + u16::RAW_BYTE_LEN;
5778 start..end
5779 }
5780}
5781
5782const _: () = assert!(FontData::default_data_long_enough(SizeParams::MIN_SIZE));
5783
5784impl Default for SizeParams<'_> {
5785 fn default() -> Self {
5786 Self {
5787 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5788 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5789 }
5790 }
5791}
5792
5793impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
5794 fn min_byte_range(&self) -> Range<usize> {
5795 0..self.ui_name_id_byte_range().end
5796 }
5797 fn min_table_bytes(&self) -> &'a [u8] {
5798 let range = self.min_byte_range();
5799 self.offset_data().as_bytes().get(range).unwrap_or_default()
5800 }
5801}
5802
5803impl ReadArgs for StylisticSetParams<'_> {
5804 type Args = ();
5805}
5806
5807impl<'a> FontRead<'a> for StylisticSetParams<'a> {
5808 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5809 #[allow(clippy::absurd_extreme_comparisons)]
5810 if data.len() < Self::MIN_SIZE {
5811 return Err(ReadError::OutOfBounds);
5812 }
5813 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5814 return Err(ReadError::OutOfBounds);
5815 };
5816 Ok(Self { data })
5817 }
5818}
5819
5820#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5822#[repr(C, packed)]
5823#[doc(hidden)]
5824pub struct StylisticSetParamsFixedHeader {
5825 pub version: BigEndian<u16>,
5826 pub ui_name_id: BigEndian<NameId>,
5827}
5828
5829#[allow(clippy::absurd_extreme_comparisons)]
5830const _: () =
5831 assert!(std::mem::size_of::<StylisticSetParamsFixedHeader>() <= StylisticSetParams::MIN_SIZE);
5832
5833#[derive(Clone)]
5834pub struct StylisticSetParams<'a> {
5835 data: TableDataRef<'a, StylisticSetParamsFixedHeader>,
5836}
5837
5838#[allow(clippy::needless_lifetimes)]
5839impl<'a> StylisticSetParams<'a> {
5840 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
5841 basic_table_impls!(impl_the_methods);
5842
5843 pub fn version(&self) -> u16 {
5844 self.data.header().version.get()
5845 }
5846
5847 pub fn ui_name_id(&self) -> NameId {
5857 self.data.header().ui_name_id.get()
5858 }
5859
5860 pub fn version_byte_range(&self) -> Range<usize> {
5861 let start = 0;
5862 let end = start + u16::RAW_BYTE_LEN;
5863 start..end
5864 }
5865
5866 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
5867 let start = self.version_byte_range().end;
5868 let end = start + NameId::RAW_BYTE_LEN;
5869 start..end
5870 }
5871}
5872
5873const _: () = assert!(FontData::default_data_long_enough(
5874 StylisticSetParams::MIN_SIZE
5875));
5876
5877impl Default for StylisticSetParams<'_> {
5878 fn default() -> Self {
5879 Self {
5880 data: TableDataRef::new(FontData::default_table_data().as_bytes())
5881 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
5882 }
5883 }
5884}
5885
5886impl Format<u16> for CharacterVariantParams<'_> {
5887 const FORMAT: u16 = 0;
5888}
5889
5890impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
5891 fn min_byte_range(&self) -> Range<usize> {
5892 0..self.character_byte_range().end
5893 }
5894 fn min_table_bytes(&self) -> &'a [u8] {
5895 let range = self.min_byte_range();
5896 self.offset_data().as_bytes().get(range).unwrap_or_default()
5897 }
5898}
5899
5900impl ReadArgs for CharacterVariantParams<'_> {
5901 type Args = ();
5902}
5903
5904impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
5905 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5906 #[allow(clippy::absurd_extreme_comparisons)]
5907 if data.len() < Self::MIN_SIZE {
5908 return Err(ReadError::OutOfBounds);
5909 }
5910 let Some(data) = TableDataRef::new(data.as_bytes()) else {
5911 return Err(ReadError::OutOfBounds);
5912 };
5913 Ok(Self { data })
5914 }
5915}
5916
5917#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
5919#[repr(C, packed)]
5920#[doc(hidden)]
5921pub struct CharacterVariantParamsFixedHeader {
5922 pub format: BigEndian<u16>,
5923 pub feat_ui_label_name_id: BigEndian<NameId>,
5924 pub feat_ui_tooltip_text_name_id: BigEndian<NameId>,
5925 pub sample_text_name_id: BigEndian<NameId>,
5926 pub num_named_parameters: BigEndian<u16>,
5927 pub first_param_ui_label_name_id: BigEndian<NameId>,
5928 pub char_count: BigEndian<u16>,
5929}
5930
5931#[allow(clippy::absurd_extreme_comparisons)]
5932const _: () = assert!(
5933 std::mem::size_of::<CharacterVariantParamsFixedHeader>() <= CharacterVariantParams::MIN_SIZE
5934);
5935
5936#[derive(Clone)]
5938pub struct CharacterVariantParams<'a> {
5939 data: TableDataRef<'a, CharacterVariantParamsFixedHeader>,
5940}
5941
5942#[allow(clippy::needless_lifetimes)]
5943impl<'a> CharacterVariantParams<'a> {
5944 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5945 + NameId::RAW_BYTE_LEN
5946 + NameId::RAW_BYTE_LEN
5947 + NameId::RAW_BYTE_LEN
5948 + u16::RAW_BYTE_LEN
5949 + NameId::RAW_BYTE_LEN
5950 + u16::RAW_BYTE_LEN);
5951 basic_table_impls!(impl_the_methods);
5952
5953 pub fn format(&self) -> u16 {
5955 self.data.header().format.get()
5956 }
5957
5958 pub fn feat_ui_label_name_id(&self) -> NameId {
5962 self.data.header().feat_ui_label_name_id.get()
5963 }
5964
5965 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
5969 self.data.header().feat_ui_tooltip_text_name_id.get()
5970 }
5971
5972 pub fn sample_text_name_id(&self) -> NameId {
5975 self.data.header().sample_text_name_id.get()
5976 }
5977
5978 pub fn num_named_parameters(&self) -> u16 {
5980 self.data.header().num_named_parameters.get()
5981 }
5982
5983 pub fn first_param_ui_label_name_id(&self) -> NameId {
5987 self.data.header().first_param_ui_label_name_id.get()
5988 }
5989
5990 pub fn char_count(&self) -> u16 {
5993 self.data.header().char_count.get()
5994 }
5995
5996 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
5999 let range = self.character_byte_range();
6000 self.offset_data()
6001 .read_array(range)
6002 .ok()
6003 .unwrap_or_default()
6004 }
6005
6006 pub fn format_byte_range(&self) -> Range<usize> {
6007 let start = 0;
6008 let end = start + u16::RAW_BYTE_LEN;
6009 start..end
6010 }
6011
6012 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
6013 let start = self.format_byte_range().end;
6014 let end = start + NameId::RAW_BYTE_LEN;
6015 start..end
6016 }
6017
6018 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
6019 let start = self.feat_ui_label_name_id_byte_range().end;
6020 let end = start + NameId::RAW_BYTE_LEN;
6021 start..end
6022 }
6023
6024 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
6025 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
6026 let end = start + NameId::RAW_BYTE_LEN;
6027 start..end
6028 }
6029
6030 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
6031 let start = self.sample_text_name_id_byte_range().end;
6032 let end = start + u16::RAW_BYTE_LEN;
6033 start..end
6034 }
6035
6036 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
6037 let start = self.num_named_parameters_byte_range().end;
6038 let end = start + NameId::RAW_BYTE_LEN;
6039 start..end
6040 }
6041
6042 pub fn char_count_byte_range(&self) -> Range<usize> {
6043 let start = self.first_param_ui_label_name_id_byte_range().end;
6044 let end = start + u16::RAW_BYTE_LEN;
6045 start..end
6046 }
6047
6048 pub fn character_byte_range(&self) -> Range<usize> {
6049 let char_count = self.char_count();
6050 let start = self.char_count_byte_range().end;
6051 let end = start + (transforms::to_usize(char_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
6052 start..end
6053 }
6054}
6055
6056const _: () = assert!(FontData::default_data_long_enough(
6057 CharacterVariantParams::MIN_SIZE
6058));
6059
6060impl Default for CharacterVariantParams<'_> {
6061 fn default() -> Self {
6062 Self {
6063 data: TableDataRef::new(FontData::default_table_data().as_bytes())
6064 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
6065 }
6066 }
6067}
6068
6069impl Format<u16> for CoverageFormat3<'_> {
6070 const FORMAT: u16 = 3;
6071}
6072
6073impl<'a> MinByteRange<'a> for CoverageFormat3<'a> {
6074 fn min_byte_range(&self) -> Range<usize> {
6075 0..self.glyph_array_byte_range().end
6076 }
6077 fn min_table_bytes(&self) -> &'a [u8] {
6078 let range = self.min_byte_range();
6079 self.offset_data().as_bytes().get(range).unwrap_or_default()
6080 }
6081}
6082
6083impl ReadArgs for CoverageFormat3<'_> {
6084 type Args = ();
6085}
6086
6087impl<'a> FontRead<'a> for CoverageFormat3<'a> {
6088 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6089 #[allow(clippy::absurd_extreme_comparisons)]
6090 if data.len() < Self::MIN_SIZE {
6091 return Err(ReadError::OutOfBounds);
6092 }
6093 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6094 return Err(ReadError::OutOfBounds);
6095 };
6096 Ok(Self { data })
6097 }
6098}
6099
6100#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6102#[repr(C, packed)]
6103#[doc(hidden)]
6104pub struct CoverageFormat3FixedHeader {
6105 pub coverage_format: BigEndian<u16>,
6106 pub glyph_count: BigEndian<Uint24>,
6107}
6108
6109#[allow(clippy::absurd_extreme_comparisons)]
6110const _: () =
6111 assert!(std::mem::size_of::<CoverageFormat3FixedHeader>() <= CoverageFormat3::MIN_SIZE);
6112
6113#[derive(Clone)]
6115pub struct CoverageFormat3<'a> {
6116 data: TableDataRef<'a, CoverageFormat3FixedHeader>,
6117}
6118
6119#[allow(clippy::needless_lifetimes)]
6120impl<'a> CoverageFormat3<'a> {
6121 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
6122 basic_table_impls!(impl_the_methods);
6123
6124 pub fn coverage_format(&self) -> u16 {
6126 self.data.header().coverage_format.get()
6127 }
6128
6129 pub fn glyph_count(&self) -> Uint24 {
6131 self.data.header().glyph_count.get()
6132 }
6133
6134 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId24>] {
6136 let range = self.glyph_array_byte_range();
6137 self.offset_data()
6138 .read_array(range)
6139 .ok()
6140 .unwrap_or_default()
6141 }
6142
6143 pub fn coverage_format_byte_range(&self) -> Range<usize> {
6144 let start = 0;
6145 let end = start + u16::RAW_BYTE_LEN;
6146 start..end
6147 }
6148
6149 pub fn glyph_count_byte_range(&self) -> Range<usize> {
6150 let start = self.coverage_format_byte_range().end;
6151 let end = start + Uint24::RAW_BYTE_LEN;
6152 start..end
6153 }
6154
6155 pub fn glyph_array_byte_range(&self) -> Range<usize> {
6156 let glyph_count = self.glyph_count();
6157 let start = self.glyph_count_byte_range().end;
6158 let end =
6159 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId24::RAW_BYTE_LEN);
6160 start..end
6161 }
6162}
6163
6164impl Format<u16> for CoverageFormat4<'_> {
6165 const FORMAT: u16 = 4;
6166}
6167
6168impl<'a> MinByteRange<'a> for CoverageFormat4<'a> {
6169 fn min_byte_range(&self) -> Range<usize> {
6170 0..self.range_records_byte_range().end
6171 }
6172 fn min_table_bytes(&self) -> &'a [u8] {
6173 let range = self.min_byte_range();
6174 self.offset_data().as_bytes().get(range).unwrap_or_default()
6175 }
6176}
6177
6178impl ReadArgs for CoverageFormat4<'_> {
6179 type Args = ();
6180}
6181
6182impl<'a> FontRead<'a> for CoverageFormat4<'a> {
6183 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6184 #[allow(clippy::absurd_extreme_comparisons)]
6185 if data.len() < Self::MIN_SIZE {
6186 return Err(ReadError::OutOfBounds);
6187 }
6188 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6189 return Err(ReadError::OutOfBounds);
6190 };
6191 Ok(Self { data })
6192 }
6193}
6194
6195#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6197#[repr(C, packed)]
6198#[doc(hidden)]
6199pub struct CoverageFormat4FixedHeader {
6200 pub coverage_format: BigEndian<u16>,
6201 pub range_count: BigEndian<Uint24>,
6202}
6203
6204#[allow(clippy::absurd_extreme_comparisons)]
6205const _: () =
6206 assert!(std::mem::size_of::<CoverageFormat4FixedHeader>() <= CoverageFormat4::MIN_SIZE);
6207
6208#[derive(Clone)]
6210pub struct CoverageFormat4<'a> {
6211 data: TableDataRef<'a, CoverageFormat4FixedHeader>,
6212}
6213
6214#[allow(clippy::needless_lifetimes)]
6215impl<'a> CoverageFormat4<'a> {
6216 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
6217 basic_table_impls!(impl_the_methods);
6218
6219 pub fn coverage_format(&self) -> u16 {
6221 self.data.header().coverage_format.get()
6222 }
6223
6224 pub fn range_count(&self) -> Uint24 {
6226 self.data.header().range_count.get()
6227 }
6228
6229 pub fn range_records(&self) -> &'a [RangeRecord2] {
6231 let range = self.range_records_byte_range();
6232 self.offset_data()
6233 .read_array(range)
6234 .ok()
6235 .unwrap_or_default()
6236 }
6237
6238 pub fn coverage_format_byte_range(&self) -> Range<usize> {
6239 let start = 0;
6240 let end = start + u16::RAW_BYTE_LEN;
6241 start..end
6242 }
6243
6244 pub fn range_count_byte_range(&self) -> Range<usize> {
6245 let start = self.coverage_format_byte_range().end;
6246 let end = start + Uint24::RAW_BYTE_LEN;
6247 start..end
6248 }
6249
6250 pub fn range_records_byte_range(&self) -> Range<usize> {
6251 let range_count = self.range_count();
6252 let start = self.range_count_byte_range().end;
6253 let end =
6254 start + (transforms::to_usize(range_count)).saturating_mul(RangeRecord2::RAW_BYTE_LEN);
6255 start..end
6256 }
6257}
6258
6259#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
6261#[repr(C)]
6262#[repr(packed)]
6263pub struct RangeRecord2 {
6264 pub start_glyph_id: BigEndian<GlyphId24>,
6266 pub end_glyph_id: BigEndian<GlyphId24>,
6268 pub start_coverage_index: BigEndian<Uint24>,
6270}
6271
6272impl RangeRecord2 {
6273 pub fn start_glyph_id(&self) -> GlyphId24 {
6275 self.start_glyph_id.get()
6276 }
6277
6278 pub fn end_glyph_id(&self) -> GlyphId24 {
6280 self.end_glyph_id.get()
6281 }
6282
6283 pub fn start_coverage_index(&self) -> Uint24 {
6285 self.start_coverage_index.get()
6286 }
6287}
6288
6289impl FixedSize for RangeRecord2 {
6290 const RAW_BYTE_LEN: usize =
6291 GlyphId24::RAW_BYTE_LEN + GlyphId24::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN;
6292}
6293
6294impl Format<u16> for ClassDefFormat3<'_> {
6295 const FORMAT: u16 = 3;
6296}
6297
6298impl<'a> MinByteRange<'a> for ClassDefFormat3<'a> {
6299 fn min_byte_range(&self) -> Range<usize> {
6300 0..self.class_value_array_byte_range().end
6301 }
6302 fn min_table_bytes(&self) -> &'a [u8] {
6303 let range = self.min_byte_range();
6304 self.offset_data().as_bytes().get(range).unwrap_or_default()
6305 }
6306}
6307
6308impl ReadArgs for ClassDefFormat3<'_> {
6309 type Args = ();
6310}
6311
6312impl<'a> FontRead<'a> for ClassDefFormat3<'a> {
6313 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6314 #[allow(clippy::absurd_extreme_comparisons)]
6315 if data.len() < Self::MIN_SIZE {
6316 return Err(ReadError::OutOfBounds);
6317 }
6318 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6319 return Err(ReadError::OutOfBounds);
6320 };
6321 Ok(Self { data })
6322 }
6323}
6324
6325#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6327#[repr(C, packed)]
6328#[doc(hidden)]
6329pub struct ClassDefFormat3FixedHeader {
6330 pub class_format: BigEndian<u16>,
6331 pub start_glyph_id: BigEndian<GlyphId24>,
6332 pub glyph_count: BigEndian<Uint24>,
6333}
6334
6335#[allow(clippy::absurd_extreme_comparisons)]
6336const _: () =
6337 assert!(std::mem::size_of::<ClassDefFormat3FixedHeader>() <= ClassDefFormat3::MIN_SIZE);
6338
6339#[derive(Clone)]
6341pub struct ClassDefFormat3<'a> {
6342 data: TableDataRef<'a, ClassDefFormat3FixedHeader>,
6343}
6344
6345#[allow(clippy::needless_lifetimes)]
6346impl<'a> ClassDefFormat3<'a> {
6347 pub const MIN_SIZE: usize =
6348 (u16::RAW_BYTE_LEN + GlyphId24::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
6349 basic_table_impls!(impl_the_methods);
6350
6351 pub fn class_format(&self) -> u16 {
6353 self.data.header().class_format.get()
6354 }
6355
6356 pub fn start_glyph_id(&self) -> GlyphId24 {
6358 self.data.header().start_glyph_id.get()
6359 }
6360
6361 pub fn glyph_count(&self) -> Uint24 {
6363 self.data.header().glyph_count.get()
6364 }
6365
6366 pub fn class_value_array(&self) -> &'a [BigEndian<Uint24>] {
6368 let range = self.class_value_array_byte_range();
6369 self.offset_data()
6370 .read_array(range)
6371 .ok()
6372 .unwrap_or_default()
6373 }
6374
6375 pub fn class_format_byte_range(&self) -> Range<usize> {
6376 let start = 0;
6377 let end = start + u16::RAW_BYTE_LEN;
6378 start..end
6379 }
6380
6381 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
6382 let start = self.class_format_byte_range().end;
6383 let end = start + GlyphId24::RAW_BYTE_LEN;
6384 start..end
6385 }
6386
6387 pub fn glyph_count_byte_range(&self) -> Range<usize> {
6388 let start = self.start_glyph_id_byte_range().end;
6389 let end = start + Uint24::RAW_BYTE_LEN;
6390 start..end
6391 }
6392
6393 pub fn class_value_array_byte_range(&self) -> Range<usize> {
6394 let glyph_count = self.glyph_count();
6395 let start = self.glyph_count_byte_range().end;
6396 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
6397 start..end
6398 }
6399}
6400
6401impl Format<u16> for ClassDefFormat4<'_> {
6402 const FORMAT: u16 = 4;
6403}
6404
6405impl<'a> MinByteRange<'a> for ClassDefFormat4<'a> {
6406 fn min_byte_range(&self) -> Range<usize> {
6407 0..self.class_range_records_byte_range().end
6408 }
6409 fn min_table_bytes(&self) -> &'a [u8] {
6410 let range = self.min_byte_range();
6411 self.offset_data().as_bytes().get(range).unwrap_or_default()
6412 }
6413}
6414
6415impl ReadArgs for ClassDefFormat4<'_> {
6416 type Args = ();
6417}
6418
6419impl<'a> FontRead<'a> for ClassDefFormat4<'a> {
6420 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6421 #[allow(clippy::absurd_extreme_comparisons)]
6422 if data.len() < Self::MIN_SIZE {
6423 return Err(ReadError::OutOfBounds);
6424 }
6425 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6426 return Err(ReadError::OutOfBounds);
6427 };
6428 Ok(Self { data })
6429 }
6430}
6431
6432#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6434#[repr(C, packed)]
6435#[doc(hidden)]
6436pub struct ClassDefFormat4FixedHeader {
6437 pub class_format: BigEndian<u16>,
6438 pub class_range_count: BigEndian<Uint24>,
6439}
6440
6441#[allow(clippy::absurd_extreme_comparisons)]
6442const _: () =
6443 assert!(std::mem::size_of::<ClassDefFormat4FixedHeader>() <= ClassDefFormat4::MIN_SIZE);
6444
6445#[derive(Clone)]
6447pub struct ClassDefFormat4<'a> {
6448 data: TableDataRef<'a, ClassDefFormat4FixedHeader>,
6449}
6450
6451#[allow(clippy::needless_lifetimes)]
6452impl<'a> ClassDefFormat4<'a> {
6453 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
6454 basic_table_impls!(impl_the_methods);
6455
6456 pub fn class_format(&self) -> u16 {
6458 self.data.header().class_format.get()
6459 }
6460
6461 pub fn class_range_count(&self) -> Uint24 {
6463 self.data.header().class_range_count.get()
6464 }
6465
6466 pub fn class_range_records(&self) -> &'a [ClassRangeRecord2] {
6468 let range = self.class_range_records_byte_range();
6469 self.offset_data()
6470 .read_array(range)
6471 .ok()
6472 .unwrap_or_default()
6473 }
6474
6475 pub fn class_format_byte_range(&self) -> Range<usize> {
6476 let start = 0;
6477 let end = start + u16::RAW_BYTE_LEN;
6478 start..end
6479 }
6480
6481 pub fn class_range_count_byte_range(&self) -> Range<usize> {
6482 let start = self.class_format_byte_range().end;
6483 let end = start + Uint24::RAW_BYTE_LEN;
6484 start..end
6485 }
6486
6487 pub fn class_range_records_byte_range(&self) -> Range<usize> {
6488 let class_range_count = self.class_range_count();
6489 let start = self.class_range_count_byte_range().end;
6490 let end = start
6491 + (transforms::to_usize(class_range_count))
6492 .saturating_mul(ClassRangeRecord2::RAW_BYTE_LEN);
6493 start..end
6494 }
6495}
6496
6497#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
6499#[repr(C)]
6500#[repr(packed)]
6501pub struct ClassRangeRecord2 {
6502 pub start_glyph_id: BigEndian<GlyphId24>,
6504 pub end_glyph_id: BigEndian<GlyphId24>,
6506 pub class: BigEndian<u16>,
6508}
6509
6510impl ClassRangeRecord2 {
6511 pub fn start_glyph_id(&self) -> GlyphId24 {
6513 self.start_glyph_id.get()
6514 }
6515
6516 pub fn end_glyph_id(&self) -> GlyphId24 {
6518 self.end_glyph_id.get()
6519 }
6520
6521 pub fn class(&self) -> u16 {
6523 self.class.get()
6524 }
6525}
6526
6527impl FixedSize for ClassRangeRecord2 {
6528 const RAW_BYTE_LEN: usize =
6529 GlyphId24::RAW_BYTE_LEN + GlyphId24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
6530}
6531
6532impl Format<u16> for SequenceContextFormat4<'_> {
6533 const FORMAT: u16 = 4;
6534}
6535
6536impl<'a> MinByteRange<'a> for SequenceContextFormat4<'a> {
6537 fn min_byte_range(&self) -> Range<usize> {
6538 0..self.seq_rule_set_offsets_byte_range().end
6539 }
6540 fn min_table_bytes(&self) -> &'a [u8] {
6541 let range = self.min_byte_range();
6542 self.offset_data().as_bytes().get(range).unwrap_or_default()
6543 }
6544}
6545
6546impl ReadArgs for SequenceContextFormat4<'_> {
6547 type Args = ();
6548}
6549
6550impl<'a> FontRead<'a> for SequenceContextFormat4<'a> {
6551 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6552 #[allow(clippy::absurd_extreme_comparisons)]
6553 if data.len() < Self::MIN_SIZE {
6554 return Err(ReadError::OutOfBounds);
6555 }
6556 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6557 return Err(ReadError::OutOfBounds);
6558 };
6559 Ok(Self { data })
6560 }
6561}
6562
6563#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6565#[repr(C, packed)]
6566#[doc(hidden)]
6567pub struct SequenceContextFormat4FixedHeader {
6568 pub format: BigEndian<u16>,
6569 pub coverage_offset: BigEndian<Offset32>,
6570 pub seq_rule_set_count: BigEndian<Uint24>,
6571}
6572
6573#[allow(clippy::absurd_extreme_comparisons)]
6574const _: () = assert!(
6575 std::mem::size_of::<SequenceContextFormat4FixedHeader>() <= SequenceContextFormat4::MIN_SIZE
6576);
6577
6578#[derive(Clone)]
6580pub struct SequenceContextFormat4<'a> {
6581 data: TableDataRef<'a, SequenceContextFormat4FixedHeader>,
6582}
6583
6584#[allow(clippy::needless_lifetimes)]
6585impl<'a> SequenceContextFormat4<'a> {
6586 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
6587 basic_table_impls!(impl_the_methods);
6588
6589 pub fn format(&self) -> u16 {
6591 self.data.header().format.get()
6592 }
6593
6594 pub fn coverage_offset(&self) -> Offset32 {
6597 self.data.header().coverage_offset.get()
6598 }
6599
6600 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
6602 let data = self.offset_data();
6603 self.coverage_offset().resolve(data)
6604 }
6605
6606 pub fn seq_rule_set_count(&self) -> Uint24 {
6608 self.data.header().seq_rule_set_count.get()
6609 }
6610
6611 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset24>>] {
6614 let range = self.seq_rule_set_offsets_byte_range();
6615 self.offset_data()
6616 .read_array(range)
6617 .ok()
6618 .unwrap_or_default()
6619 }
6620
6621 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet2<'a>, Offset24> {
6623 let data = self.offset_data();
6624 let offsets = self.seq_rule_set_offsets();
6625 ArrayOfNullableOffsets::new(offsets, data, ())
6626 }
6627
6628 pub fn format_byte_range(&self) -> Range<usize> {
6629 let start = 0;
6630 let end = start + u16::RAW_BYTE_LEN;
6631 start..end
6632 }
6633
6634 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
6635 let start = self.format_byte_range().end;
6636 let end = start + Offset32::RAW_BYTE_LEN;
6637 start..end
6638 }
6639
6640 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
6641 let start = self.coverage_offset_byte_range().end;
6642 let end = start + Uint24::RAW_BYTE_LEN;
6643 start..end
6644 }
6645
6646 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
6647 let seq_rule_set_count = self.seq_rule_set_count();
6648 let start = self.seq_rule_set_count_byte_range().end;
6649 let end = start
6650 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
6651 start..end
6652 }
6653}
6654
6655impl<'a> MinByteRange<'a> for SequenceRuleSet2<'a> {
6656 fn min_byte_range(&self) -> Range<usize> {
6657 0..self.seq_rule_offsets_byte_range().end
6658 }
6659 fn min_table_bytes(&self) -> &'a [u8] {
6660 let range = self.min_byte_range();
6661 self.offset_data().as_bytes().get(range).unwrap_or_default()
6662 }
6663}
6664
6665impl ReadArgs for SequenceRuleSet2<'_> {
6666 type Args = ();
6667}
6668
6669impl<'a> FontRead<'a> for SequenceRuleSet2<'a> {
6670 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6671 #[allow(clippy::absurd_extreme_comparisons)]
6672 if data.len() < Self::MIN_SIZE {
6673 return Err(ReadError::OutOfBounds);
6674 }
6675 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6676 return Err(ReadError::OutOfBounds);
6677 };
6678 Ok(Self { data })
6679 }
6680}
6681
6682#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6684#[repr(C, packed)]
6685#[doc(hidden)]
6686pub struct SequenceRuleSet2FixedHeader {
6687 pub seq_rule_count: BigEndian<u16>,
6688}
6689
6690#[allow(clippy::absurd_extreme_comparisons)]
6691const _: () =
6692 assert!(std::mem::size_of::<SequenceRuleSet2FixedHeader>() <= SequenceRuleSet2::MIN_SIZE);
6693
6694#[derive(Clone)]
6696pub struct SequenceRuleSet2<'a> {
6697 data: TableDataRef<'a, SequenceRuleSet2FixedHeader>,
6698}
6699
6700#[allow(clippy::needless_lifetimes)]
6701impl<'a> SequenceRuleSet2<'a> {
6702 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
6703 basic_table_impls!(impl_the_methods);
6704
6705 pub fn seq_rule_count(&self) -> u16 {
6707 self.data.header().seq_rule_count.get()
6708 }
6709
6710 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
6713 let range = self.seq_rule_offsets_byte_range();
6714 self.offset_data()
6715 .read_array(range)
6716 .ok()
6717 .unwrap_or_default()
6718 }
6719
6720 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule2<'a>, Offset16> {
6722 let data = self.offset_data();
6723 let offsets = self.seq_rule_offsets();
6724 ArrayOfOffsets::new(offsets, data, ())
6725 }
6726
6727 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
6728 let start = 0;
6729 let end = start + u16::RAW_BYTE_LEN;
6730 start..end
6731 }
6732
6733 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
6734 let seq_rule_count = self.seq_rule_count();
6735 let start = self.seq_rule_count_byte_range().end;
6736 let end =
6737 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
6738 start..end
6739 }
6740}
6741
6742const _: () = assert!(FontData::default_data_long_enough(
6743 SequenceRuleSet2::MIN_SIZE
6744));
6745
6746impl Default for SequenceRuleSet2<'_> {
6747 fn default() -> Self {
6748 Self {
6749 data: TableDataRef::new(FontData::default_table_data().as_bytes())
6750 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
6751 }
6752 }
6753}
6754
6755impl<'a> MinByteRange<'a> for SequenceRule2<'a> {
6756 fn min_byte_range(&self) -> Range<usize> {
6757 0..self.seq_lookup_records_byte_range().end
6758 }
6759 fn min_table_bytes(&self) -> &'a [u8] {
6760 let range = self.min_byte_range();
6761 self.offset_data().as_bytes().get(range).unwrap_or_default()
6762 }
6763}
6764
6765impl ReadArgs for SequenceRule2<'_> {
6766 type Args = ();
6767}
6768
6769impl<'a> FontRead<'a> for SequenceRule2<'a> {
6770 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6771 #[allow(clippy::absurd_extreme_comparisons)]
6772 if data.len() < Self::MIN_SIZE {
6773 return Err(ReadError::OutOfBounds);
6774 }
6775 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6776 return Err(ReadError::OutOfBounds);
6777 };
6778 Ok(Self { data })
6779 }
6780}
6781
6782#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6784#[repr(C, packed)]
6785#[doc(hidden)]
6786pub struct SequenceRule2FixedHeader {
6787 pub glyph_count: BigEndian<u16>,
6788 pub seq_lookup_count: BigEndian<u16>,
6789}
6790
6791#[allow(clippy::absurd_extreme_comparisons)]
6792const _: () = assert!(std::mem::size_of::<SequenceRule2FixedHeader>() <= SequenceRule2::MIN_SIZE);
6793
6794#[derive(Clone)]
6796pub struct SequenceRule2<'a> {
6797 data: TableDataRef<'a, SequenceRule2FixedHeader>,
6798}
6799
6800#[allow(clippy::needless_lifetimes)]
6801impl<'a> SequenceRule2<'a> {
6802 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
6803 basic_table_impls!(impl_the_methods);
6804
6805 pub fn glyph_count(&self) -> u16 {
6807 self.data.header().glyph_count.get()
6808 }
6809
6810 pub fn seq_lookup_count(&self) -> u16 {
6812 self.data.header().seq_lookup_count.get()
6813 }
6814
6815 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId24>] {
6817 let range = self.input_sequence_byte_range();
6818 self.offset_data()
6819 .read_array(range)
6820 .ok()
6821 .unwrap_or_default()
6822 }
6823
6824 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
6826 let range = self.seq_lookup_records_byte_range();
6827 self.offset_data()
6828 .read_array(range)
6829 .ok()
6830 .unwrap_or_default()
6831 }
6832
6833 pub fn glyph_count_byte_range(&self) -> Range<usize> {
6834 let start = 0;
6835 let end = start + u16::RAW_BYTE_LEN;
6836 start..end
6837 }
6838
6839 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
6840 let start = self.glyph_count_byte_range().end;
6841 let end = start + u16::RAW_BYTE_LEN;
6842 start..end
6843 }
6844
6845 pub fn input_sequence_byte_range(&self) -> Range<usize> {
6846 let glyph_count = self.glyph_count();
6847 let start = self.seq_lookup_count_byte_range().end;
6848 let end = start
6849 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId24::RAW_BYTE_LEN);
6850 start..end
6851 }
6852
6853 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
6854 let seq_lookup_count = self.seq_lookup_count();
6855 let start = self.input_sequence_byte_range().end;
6856 let end = start
6857 + (transforms::to_usize(seq_lookup_count))
6858 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
6859 start..end
6860 }
6861}
6862
6863const _: () = assert!(FontData::default_data_long_enough(SequenceRule2::MIN_SIZE));
6864
6865impl Default for SequenceRule2<'_> {
6866 fn default() -> Self {
6867 Self {
6868 data: TableDataRef::new(FontData::default_table_data().as_bytes())
6869 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
6870 }
6871 }
6872}
6873
6874impl Format<u16> for SequenceContextFormat5<'_> {
6875 const FORMAT: u16 = 5;
6876}
6877
6878impl<'a> MinByteRange<'a> for SequenceContextFormat5<'a> {
6879 fn min_byte_range(&self) -> Range<usize> {
6880 0..self.class_seq_rule_set_offsets_byte_range().end
6881 }
6882 fn min_table_bytes(&self) -> &'a [u8] {
6883 let range = self.min_byte_range();
6884 self.offset_data().as_bytes().get(range).unwrap_or_default()
6885 }
6886}
6887
6888impl ReadArgs for SequenceContextFormat5<'_> {
6889 type Args = ();
6890}
6891
6892impl<'a> FontRead<'a> for SequenceContextFormat5<'a> {
6893 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
6894 #[allow(clippy::absurd_extreme_comparisons)]
6895 if data.len() < Self::MIN_SIZE {
6896 return Err(ReadError::OutOfBounds);
6897 }
6898 let Some(data) = TableDataRef::new(data.as_bytes()) else {
6899 return Err(ReadError::OutOfBounds);
6900 };
6901 Ok(Self { data })
6902 }
6903}
6904
6905#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
6907#[repr(C, packed)]
6908#[doc(hidden)]
6909pub struct SequenceContextFormat5FixedHeader {
6910 pub format: BigEndian<u16>,
6911 pub coverage_offset: BigEndian<Offset32>,
6912 pub class_def_offset: BigEndian<Offset32>,
6913 pub class_seq_rule_set_count: BigEndian<Uint24>,
6914}
6915
6916#[allow(clippy::absurd_extreme_comparisons)]
6917const _: () = assert!(
6918 std::mem::size_of::<SequenceContextFormat5FixedHeader>() <= SequenceContextFormat5::MIN_SIZE
6919);
6920
6921#[derive(Clone)]
6923pub struct SequenceContextFormat5<'a> {
6924 data: TableDataRef<'a, SequenceContextFormat5FixedHeader>,
6925}
6926
6927#[allow(clippy::needless_lifetimes)]
6928impl<'a> SequenceContextFormat5<'a> {
6929 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
6930 + Offset32::RAW_BYTE_LEN
6931 + Offset32::RAW_BYTE_LEN
6932 + Uint24::RAW_BYTE_LEN);
6933 basic_table_impls!(impl_the_methods);
6934
6935 pub fn format(&self) -> u16 {
6937 self.data.header().format.get()
6938 }
6939
6940 pub fn coverage_offset(&self) -> Offset32 {
6943 self.data.header().coverage_offset.get()
6944 }
6945
6946 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
6948 let data = self.offset_data();
6949 self.coverage_offset().resolve(data)
6950 }
6951
6952 pub fn class_def_offset(&self) -> Offset32 {
6955 self.data.header().class_def_offset.get()
6956 }
6957
6958 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
6960 let data = self.offset_data();
6961 self.class_def_offset().resolve(data)
6962 }
6963
6964 pub fn class_seq_rule_set_count(&self) -> Uint24 {
6966 self.data.header().class_seq_rule_set_count.get()
6967 }
6968
6969 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset24>>] {
6972 let range = self.class_seq_rule_set_offsets_byte_range();
6973 self.offset_data()
6974 .read_array(range)
6975 .ok()
6976 .unwrap_or_default()
6977 }
6978
6979 pub fn class_seq_rule_sets(
6981 &self,
6982 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet2<'a>, Offset24> {
6983 let data = self.offset_data();
6984 let offsets = self.class_seq_rule_set_offsets();
6985 ArrayOfNullableOffsets::new(offsets, data, ())
6986 }
6987
6988 pub fn format_byte_range(&self) -> Range<usize> {
6989 let start = 0;
6990 let end = start + u16::RAW_BYTE_LEN;
6991 start..end
6992 }
6993
6994 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
6995 let start = self.format_byte_range().end;
6996 let end = start + Offset32::RAW_BYTE_LEN;
6997 start..end
6998 }
6999
7000 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
7001 let start = self.coverage_offset_byte_range().end;
7002 let end = start + Offset32::RAW_BYTE_LEN;
7003 start..end
7004 }
7005
7006 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
7007 let start = self.class_def_offset_byte_range().end;
7008 let end = start + Uint24::RAW_BYTE_LEN;
7009 start..end
7010 }
7011
7012 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
7013 let class_seq_rule_set_count = self.class_seq_rule_set_count();
7014 let start = self.class_seq_rule_set_count_byte_range().end;
7015 let end = start
7016 + (transforms::to_usize(class_seq_rule_set_count))
7017 .saturating_mul(Offset24::RAW_BYTE_LEN);
7018 start..end
7019 }
7020}
7021
7022impl<'a> MinByteRange<'a> for ClassSequenceRuleSet2<'a> {
7023 fn min_byte_range(&self) -> Range<usize> {
7024 0..self.class_seq_rule_offsets_byte_range().end
7025 }
7026 fn min_table_bytes(&self) -> &'a [u8] {
7027 let range = self.min_byte_range();
7028 self.offset_data().as_bytes().get(range).unwrap_or_default()
7029 }
7030}
7031
7032impl ReadArgs for ClassSequenceRuleSet2<'_> {
7033 type Args = ();
7034}
7035
7036impl<'a> FontRead<'a> for ClassSequenceRuleSet2<'a> {
7037 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7038 #[allow(clippy::absurd_extreme_comparisons)]
7039 if data.len() < Self::MIN_SIZE {
7040 return Err(ReadError::OutOfBounds);
7041 }
7042 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7043 return Err(ReadError::OutOfBounds);
7044 };
7045 Ok(Self { data })
7046 }
7047}
7048
7049#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7051#[repr(C, packed)]
7052#[doc(hidden)]
7053pub struct ClassSequenceRuleSet2FixedHeader {
7054 pub class_seq_rule_count: BigEndian<u16>,
7055}
7056
7057#[allow(clippy::absurd_extreme_comparisons)]
7058const _: () = assert!(
7059 std::mem::size_of::<ClassSequenceRuleSet2FixedHeader>() <= ClassSequenceRuleSet2::MIN_SIZE
7060);
7061
7062#[derive(Clone)]
7064pub struct ClassSequenceRuleSet2<'a> {
7065 data: TableDataRef<'a, ClassSequenceRuleSet2FixedHeader>,
7066}
7067
7068#[allow(clippy::needless_lifetimes)]
7069impl<'a> ClassSequenceRuleSet2<'a> {
7070 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
7071 basic_table_impls!(impl_the_methods);
7072
7073 pub fn class_seq_rule_count(&self) -> u16 {
7075 self.data.header().class_seq_rule_count.get()
7076 }
7077
7078 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset24>] {
7081 let range = self.class_seq_rule_offsets_byte_range();
7082 self.offset_data()
7083 .read_array(range)
7084 .ok()
7085 .unwrap_or_default()
7086 }
7087
7088 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset24> {
7090 let data = self.offset_data();
7091 let offsets = self.class_seq_rule_offsets();
7092 ArrayOfOffsets::new(offsets, data, ())
7093 }
7094
7095 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
7096 let start = 0;
7097 let end = start + u16::RAW_BYTE_LEN;
7098 start..end
7099 }
7100
7101 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
7102 let class_seq_rule_count = self.class_seq_rule_count();
7103 let start = self.class_seq_rule_count_byte_range().end;
7104 let end = start
7105 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
7106 start..end
7107 }
7108}
7109
7110const _: () = assert!(FontData::default_data_long_enough(
7111 ClassSequenceRuleSet2::MIN_SIZE
7112));
7113
7114impl Default for ClassSequenceRuleSet2<'_> {
7115 fn default() -> Self {
7116 Self {
7117 data: TableDataRef::new(FontData::default_table_data().as_bytes())
7118 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
7119 }
7120 }
7121}
7122
7123impl Format<u16> for SequenceContextFormat6<'_> {
7124 const FORMAT: u16 = 6;
7125}
7126
7127impl<'a> MinByteRange<'a> for SequenceContextFormat6<'a> {
7128 fn min_byte_range(&self) -> Range<usize> {
7129 0..self.seq_lookup_records_byte_range().end
7130 }
7131 fn min_table_bytes(&self) -> &'a [u8] {
7132 let range = self.min_byte_range();
7133 self.offset_data().as_bytes().get(range).unwrap_or_default()
7134 }
7135}
7136
7137impl ReadArgs for SequenceContextFormat6<'_> {
7138 type Args = ();
7139}
7140
7141impl<'a> FontRead<'a> for SequenceContextFormat6<'a> {
7142 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7143 #[allow(clippy::absurd_extreme_comparisons)]
7144 if data.len() < Self::MIN_SIZE {
7145 return Err(ReadError::OutOfBounds);
7146 }
7147 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7148 return Err(ReadError::OutOfBounds);
7149 };
7150 Ok(Self { data })
7151 }
7152}
7153
7154#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7156#[repr(C, packed)]
7157#[doc(hidden)]
7158pub struct SequenceContextFormat6FixedHeader {
7159 pub format: BigEndian<u16>,
7160 pub glyph_count: BigEndian<u16>,
7161 pub seq_lookup_count: BigEndian<u16>,
7162}
7163
7164#[allow(clippy::absurd_extreme_comparisons)]
7165const _: () = assert!(
7166 std::mem::size_of::<SequenceContextFormat6FixedHeader>() <= SequenceContextFormat6::MIN_SIZE
7167);
7168
7169#[derive(Clone)]
7171pub struct SequenceContextFormat6<'a> {
7172 data: TableDataRef<'a, SequenceContextFormat6FixedHeader>,
7173}
7174
7175#[allow(clippy::needless_lifetimes)]
7176impl<'a> SequenceContextFormat6<'a> {
7177 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
7178 basic_table_impls!(impl_the_methods);
7179
7180 pub fn format(&self) -> u16 {
7182 self.data.header().format.get()
7183 }
7184
7185 pub fn glyph_count(&self) -> u16 {
7187 self.data.header().glyph_count.get()
7188 }
7189
7190 pub fn seq_lookup_count(&self) -> u16 {
7192 self.data.header().seq_lookup_count.get()
7193 }
7194
7195 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset24>] {
7198 let range = self.coverage_offsets_byte_range();
7199 self.offset_data()
7200 .read_array(range)
7201 .ok()
7202 .unwrap_or_default()
7203 }
7204
7205 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset24> {
7207 let data = self.offset_data();
7208 let offsets = self.coverage_offsets();
7209 ArrayOfOffsets::new(offsets, data, ())
7210 }
7211
7212 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
7214 let range = self.seq_lookup_records_byte_range();
7215 self.offset_data()
7216 .read_array(range)
7217 .ok()
7218 .unwrap_or_default()
7219 }
7220
7221 pub fn format_byte_range(&self) -> Range<usize> {
7222 let start = 0;
7223 let end = start + u16::RAW_BYTE_LEN;
7224 start..end
7225 }
7226
7227 pub fn glyph_count_byte_range(&self) -> Range<usize> {
7228 let start = self.format_byte_range().end;
7229 let end = start + u16::RAW_BYTE_LEN;
7230 start..end
7231 }
7232
7233 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
7234 let start = self.glyph_count_byte_range().end;
7235 let end = start + u16::RAW_BYTE_LEN;
7236 start..end
7237 }
7238
7239 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
7240 let glyph_count = self.glyph_count();
7241 let start = self.seq_lookup_count_byte_range().end;
7242 let end =
7243 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
7244 start..end
7245 }
7246
7247 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
7248 let seq_lookup_count = self.seq_lookup_count();
7249 let start = self.coverage_offsets_byte_range().end;
7250 let end = start
7251 + (transforms::to_usize(seq_lookup_count))
7252 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
7253 start..end
7254 }
7255}
7256
7257impl Format<u16> for ChainedSequenceContextFormat4<'_> {
7258 const FORMAT: u16 = 4;
7259}
7260
7261impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat4<'a> {
7262 fn min_byte_range(&self) -> Range<usize> {
7263 0..self.chained_seq_rule_set_offsets_byte_range().end
7264 }
7265 fn min_table_bytes(&self) -> &'a [u8] {
7266 let range = self.min_byte_range();
7267 self.offset_data().as_bytes().get(range).unwrap_or_default()
7268 }
7269}
7270
7271impl ReadArgs for ChainedSequenceContextFormat4<'_> {
7272 type Args = ();
7273}
7274
7275impl<'a> FontRead<'a> for ChainedSequenceContextFormat4<'a> {
7276 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7277 #[allow(clippy::absurd_extreme_comparisons)]
7278 if data.len() < Self::MIN_SIZE {
7279 return Err(ReadError::OutOfBounds);
7280 }
7281 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7282 return Err(ReadError::OutOfBounds);
7283 };
7284 Ok(Self { data })
7285 }
7286}
7287
7288#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7290#[repr(C, packed)]
7291#[doc(hidden)]
7292pub struct ChainedSequenceContextFormat4FixedHeader {
7293 pub format: BigEndian<u16>,
7294 pub coverage_offset: BigEndian<Offset32>,
7295 pub chained_seq_rule_set_count: BigEndian<Uint24>,
7296}
7297
7298#[allow(clippy::absurd_extreme_comparisons)]
7299const _: () = assert!(
7300 std::mem::size_of::<ChainedSequenceContextFormat4FixedHeader>()
7301 <= ChainedSequenceContextFormat4::MIN_SIZE
7302);
7303
7304#[derive(Clone)]
7306pub struct ChainedSequenceContextFormat4<'a> {
7307 data: TableDataRef<'a, ChainedSequenceContextFormat4FixedHeader>,
7308}
7309
7310#[allow(clippy::needless_lifetimes)]
7311impl<'a> ChainedSequenceContextFormat4<'a> {
7312 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Uint24::RAW_BYTE_LEN);
7313 basic_table_impls!(impl_the_methods);
7314
7315 pub fn format(&self) -> u16 {
7317 self.data.header().format.get()
7318 }
7319
7320 pub fn coverage_offset(&self) -> Offset32 {
7323 self.data.header().coverage_offset.get()
7324 }
7325
7326 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
7328 let data = self.offset_data();
7329 self.coverage_offset().resolve(data)
7330 }
7331
7332 pub fn chained_seq_rule_set_count(&self) -> Uint24 {
7334 self.data.header().chained_seq_rule_set_count.get()
7335 }
7336
7337 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset24>>] {
7340 let range = self.chained_seq_rule_set_offsets_byte_range();
7341 self.offset_data()
7342 .read_array(range)
7343 .ok()
7344 .unwrap_or_default()
7345 }
7346
7347 pub fn chained_seq_rule_sets(
7349 &self,
7350 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet2<'a>, Offset24> {
7351 let data = self.offset_data();
7352 let offsets = self.chained_seq_rule_set_offsets();
7353 ArrayOfNullableOffsets::new(offsets, data, ())
7354 }
7355
7356 pub fn format_byte_range(&self) -> Range<usize> {
7357 let start = 0;
7358 let end = start + u16::RAW_BYTE_LEN;
7359 start..end
7360 }
7361
7362 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
7363 let start = self.format_byte_range().end;
7364 let end = start + Offset32::RAW_BYTE_LEN;
7365 start..end
7366 }
7367
7368 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
7369 let start = self.coverage_offset_byte_range().end;
7370 let end = start + Uint24::RAW_BYTE_LEN;
7371 start..end
7372 }
7373
7374 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
7375 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
7376 let start = self.chained_seq_rule_set_count_byte_range().end;
7377 let end = start
7378 + (transforms::to_usize(chained_seq_rule_set_count))
7379 .saturating_mul(Offset24::RAW_BYTE_LEN);
7380 start..end
7381 }
7382}
7383
7384impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet2<'a> {
7385 fn min_byte_range(&self) -> Range<usize> {
7386 0..self.chained_seq_rule_offsets_byte_range().end
7387 }
7388 fn min_table_bytes(&self) -> &'a [u8] {
7389 let range = self.min_byte_range();
7390 self.offset_data().as_bytes().get(range).unwrap_or_default()
7391 }
7392}
7393
7394impl ReadArgs for ChainedSequenceRuleSet2<'_> {
7395 type Args = ();
7396}
7397
7398impl<'a> FontRead<'a> for ChainedSequenceRuleSet2<'a> {
7399 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7400 #[allow(clippy::absurd_extreme_comparisons)]
7401 if data.len() < Self::MIN_SIZE {
7402 return Err(ReadError::OutOfBounds);
7403 }
7404 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7405 return Err(ReadError::OutOfBounds);
7406 };
7407 Ok(Self { data })
7408 }
7409}
7410
7411#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7413#[repr(C, packed)]
7414#[doc(hidden)]
7415pub struct ChainedSequenceRuleSet2FixedHeader {
7416 pub chained_seq_rule_count: BigEndian<u16>,
7417}
7418
7419#[allow(clippy::absurd_extreme_comparisons)]
7420const _: () = assert!(
7421 std::mem::size_of::<ChainedSequenceRuleSet2FixedHeader>() <= ChainedSequenceRuleSet2::MIN_SIZE
7422);
7423
7424#[derive(Clone)]
7426pub struct ChainedSequenceRuleSet2<'a> {
7427 data: TableDataRef<'a, ChainedSequenceRuleSet2FixedHeader>,
7428}
7429
7430#[allow(clippy::needless_lifetimes)]
7431impl<'a> ChainedSequenceRuleSet2<'a> {
7432 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
7433 basic_table_impls!(impl_the_methods);
7434
7435 pub fn chained_seq_rule_count(&self) -> u16 {
7437 self.data.header().chained_seq_rule_count.get()
7438 }
7439
7440 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset24>] {
7443 let range = self.chained_seq_rule_offsets_byte_range();
7444 self.offset_data()
7445 .read_array(range)
7446 .ok()
7447 .unwrap_or_default()
7448 }
7449
7450 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule2<'a>, Offset24> {
7452 let data = self.offset_data();
7453 let offsets = self.chained_seq_rule_offsets();
7454 ArrayOfOffsets::new(offsets, data, ())
7455 }
7456
7457 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
7458 let start = 0;
7459 let end = start + u16::RAW_BYTE_LEN;
7460 start..end
7461 }
7462
7463 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
7464 let chained_seq_rule_count = self.chained_seq_rule_count();
7465 let start = self.chained_seq_rule_count_byte_range().end;
7466 let end = start
7467 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
7468 start..end
7469 }
7470}
7471
7472const _: () = assert!(FontData::default_data_long_enough(
7473 ChainedSequenceRuleSet2::MIN_SIZE
7474));
7475
7476impl Default for ChainedSequenceRuleSet2<'_> {
7477 fn default() -> Self {
7478 Self {
7479 data: TableDataRef::new(FontData::default_table_data().as_bytes())
7480 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
7481 }
7482 }
7483}
7484
7485impl<'a> MinByteRange<'a> for ChainedSequenceRule2<'a> {
7486 fn min_byte_range(&self) -> Range<usize> {
7487 0..self.seq_lookup_records_byte_range().end
7488 }
7489 fn min_table_bytes(&self) -> &'a [u8] {
7490 let range = self.min_byte_range();
7491 self.offset_data().as_bytes().get(range).unwrap_or_default()
7492 }
7493}
7494
7495impl ReadArgs for ChainedSequenceRule2<'_> {
7496 type Args = ();
7497}
7498
7499impl<'a> FontRead<'a> for ChainedSequenceRule2<'a> {
7500 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7501 #[allow(clippy::absurd_extreme_comparisons)]
7502 if data.len() < Self::MIN_SIZE {
7503 return Err(ReadError::OutOfBounds);
7504 }
7505 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7506 return Err(ReadError::OutOfBounds);
7507 };
7508 Ok(Self { data })
7509 }
7510}
7511
7512#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7514#[repr(C, packed)]
7515#[doc(hidden)]
7516pub struct ChainedSequenceRule2FixedHeader {
7517 pub backtrack_glyph_count: BigEndian<u16>,
7518}
7519
7520#[allow(clippy::absurd_extreme_comparisons)]
7521const _: () = assert!(
7522 std::mem::size_of::<ChainedSequenceRule2FixedHeader>() <= ChainedSequenceRule2::MIN_SIZE
7523);
7524
7525#[derive(Clone)]
7527pub struct ChainedSequenceRule2<'a> {
7528 data: TableDataRef<'a, ChainedSequenceRule2FixedHeader>,
7529}
7530
7531#[allow(clippy::needless_lifetimes)]
7532impl<'a> ChainedSequenceRule2<'a> {
7533 pub const MIN_SIZE: usize =
7534 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
7535 basic_table_impls!(impl_the_methods);
7536
7537 pub fn backtrack_glyph_count(&self) -> u16 {
7539 self.data.header().backtrack_glyph_count.get()
7540 }
7541
7542 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId24>] {
7544 let range = self.backtrack_sequence_byte_range();
7545 self.offset_data()
7546 .read_array(range)
7547 .ok()
7548 .unwrap_or_default()
7549 }
7550
7551 pub fn input_glyph_count(&self) -> u16 {
7553 let range = self.input_glyph_count_byte_range();
7554 self.offset_data()
7555 .read_at(range.start)
7556 .ok()
7557 .unwrap_or_default()
7558 }
7559
7560 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId24>] {
7562 let range = self.input_sequence_byte_range();
7563 self.offset_data()
7564 .read_array(range)
7565 .ok()
7566 .unwrap_or_default()
7567 }
7568
7569 pub fn lookahead_glyph_count(&self) -> u16 {
7571 let range = self.lookahead_glyph_count_byte_range();
7572 self.offset_data()
7573 .read_at(range.start)
7574 .ok()
7575 .unwrap_or_default()
7576 }
7577
7578 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId24>] {
7580 let range = self.lookahead_sequence_byte_range();
7581 self.offset_data()
7582 .read_array(range)
7583 .ok()
7584 .unwrap_or_default()
7585 }
7586
7587 pub fn seq_lookup_count(&self) -> u16 {
7589 let range = self.seq_lookup_count_byte_range();
7590 self.offset_data()
7591 .read_at(range.start)
7592 .ok()
7593 .unwrap_or_default()
7594 }
7595
7596 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
7598 let range = self.seq_lookup_records_byte_range();
7599 self.offset_data()
7600 .read_array(range)
7601 .ok()
7602 .unwrap_or_default()
7603 }
7604
7605 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
7606 let start = 0;
7607 let end = start + u16::RAW_BYTE_LEN;
7608 start..end
7609 }
7610
7611 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
7612 let backtrack_glyph_count = self.backtrack_glyph_count();
7613 let start = self.backtrack_glyph_count_byte_range().end;
7614 let end = start
7615 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId24::RAW_BYTE_LEN);
7616 start..end
7617 }
7618
7619 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
7620 let start = self.backtrack_sequence_byte_range().end;
7621 let end = start + u16::RAW_BYTE_LEN;
7622 start..end
7623 }
7624
7625 pub fn input_sequence_byte_range(&self) -> Range<usize> {
7626 let input_glyph_count = self.input_glyph_count();
7627 let start = self.input_glyph_count_byte_range().end;
7628 let end = start
7629 + (transforms::subtract(input_glyph_count, 1_usize))
7630 .saturating_mul(GlyphId24::RAW_BYTE_LEN);
7631 start..end
7632 }
7633
7634 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
7635 let start = self.input_sequence_byte_range().end;
7636 let end = start + u16::RAW_BYTE_LEN;
7637 start..end
7638 }
7639
7640 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
7641 let lookahead_glyph_count = self.lookahead_glyph_count();
7642 let start = self.lookahead_glyph_count_byte_range().end;
7643 let end = start
7644 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId24::RAW_BYTE_LEN);
7645 start..end
7646 }
7647
7648 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
7649 let start = self.lookahead_sequence_byte_range().end;
7650 let end = start + u16::RAW_BYTE_LEN;
7651 start..end
7652 }
7653
7654 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
7655 let seq_lookup_count = self.seq_lookup_count();
7656 let start = self.seq_lookup_count_byte_range().end;
7657 let end = start
7658 + (transforms::to_usize(seq_lookup_count))
7659 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
7660 start..end
7661 }
7662}
7663
7664const _: () = assert!(FontData::default_data_long_enough(
7665 ChainedSequenceRule2::MIN_SIZE
7666));
7667
7668impl Default for ChainedSequenceRule2<'_> {
7669 fn default() -> Self {
7670 Self {
7671 data: TableDataRef::new(FontData::default_table_data().as_bytes())
7672 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
7673 }
7674 }
7675}
7676
7677impl Format<u16> for ChainedSequenceContextFormat5<'_> {
7678 const FORMAT: u16 = 5;
7679}
7680
7681impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat5<'a> {
7682 fn min_byte_range(&self) -> Range<usize> {
7683 0..self.chained_class_seq_rule_set_offsets_byte_range().end
7684 }
7685 fn min_table_bytes(&self) -> &'a [u8] {
7686 let range = self.min_byte_range();
7687 self.offset_data().as_bytes().get(range).unwrap_or_default()
7688 }
7689}
7690
7691impl ReadArgs for ChainedSequenceContextFormat5<'_> {
7692 type Args = ();
7693}
7694
7695impl<'a> FontRead<'a> for ChainedSequenceContextFormat5<'a> {
7696 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7697 #[allow(clippy::absurd_extreme_comparisons)]
7698 if data.len() < Self::MIN_SIZE {
7699 return Err(ReadError::OutOfBounds);
7700 }
7701 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7702 return Err(ReadError::OutOfBounds);
7703 };
7704 Ok(Self { data })
7705 }
7706}
7707
7708#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7710#[repr(C, packed)]
7711#[doc(hidden)]
7712pub struct ChainedSequenceContextFormat5FixedHeader {
7713 pub format: BigEndian<u16>,
7714 pub coverage_offset: BigEndian<Offset32>,
7715 pub backtrack_class_def_offset: BigEndian<Offset32>,
7716 pub input_class_def_offset: BigEndian<Offset32>,
7717 pub lookahead_class_def_offset: BigEndian<Offset32>,
7718 pub chained_class_seq_rule_set_count: BigEndian<u16>,
7719}
7720
7721#[allow(clippy::absurd_extreme_comparisons)]
7722const _: () = assert!(
7723 std::mem::size_of::<ChainedSequenceContextFormat5FixedHeader>()
7724 <= ChainedSequenceContextFormat5::MIN_SIZE
7725);
7726
7727#[derive(Clone)]
7729pub struct ChainedSequenceContextFormat5<'a> {
7730 data: TableDataRef<'a, ChainedSequenceContextFormat5FixedHeader>,
7731}
7732
7733#[allow(clippy::needless_lifetimes)]
7734impl<'a> ChainedSequenceContextFormat5<'a> {
7735 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
7736 + Offset32::RAW_BYTE_LEN
7737 + Offset32::RAW_BYTE_LEN
7738 + Offset32::RAW_BYTE_LEN
7739 + Offset32::RAW_BYTE_LEN
7740 + u16::RAW_BYTE_LEN);
7741 basic_table_impls!(impl_the_methods);
7742
7743 pub fn format(&self) -> u16 {
7745 self.data.header().format.get()
7746 }
7747
7748 pub fn coverage_offset(&self) -> Offset32 {
7751 self.data.header().coverage_offset.get()
7752 }
7753
7754 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
7756 let data = self.offset_data();
7757 self.coverage_offset().resolve(data)
7758 }
7759
7760 pub fn backtrack_class_def_offset(&self) -> Offset32 {
7763 self.data.header().backtrack_class_def_offset.get()
7764 }
7765
7766 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
7768 let data = self.offset_data();
7769 self.backtrack_class_def_offset().resolve(data)
7770 }
7771
7772 pub fn input_class_def_offset(&self) -> Offset32 {
7775 self.data.header().input_class_def_offset.get()
7776 }
7777
7778 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
7780 let data = self.offset_data();
7781 self.input_class_def_offset().resolve(data)
7782 }
7783
7784 pub fn lookahead_class_def_offset(&self) -> Offset32 {
7787 self.data.header().lookahead_class_def_offset.get()
7788 }
7789
7790 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
7792 let data = self.offset_data();
7793 self.lookahead_class_def_offset().resolve(data)
7794 }
7795
7796 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
7798 self.data.header().chained_class_seq_rule_set_count.get()
7799 }
7800
7801 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset24>>] {
7804 let range = self.chained_class_seq_rule_set_offsets_byte_range();
7805 self.offset_data()
7806 .read_array(range)
7807 .ok()
7808 .unwrap_or_default()
7809 }
7810
7811 pub fn chained_class_seq_rule_sets(
7813 &self,
7814 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet2<'a>, Offset24> {
7815 let data = self.offset_data();
7816 let offsets = self.chained_class_seq_rule_set_offsets();
7817 ArrayOfNullableOffsets::new(offsets, data, ())
7818 }
7819
7820 pub fn format_byte_range(&self) -> Range<usize> {
7821 let start = 0;
7822 let end = start + u16::RAW_BYTE_LEN;
7823 start..end
7824 }
7825
7826 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
7827 let start = self.format_byte_range().end;
7828 let end = start + Offset32::RAW_BYTE_LEN;
7829 start..end
7830 }
7831
7832 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
7833 let start = self.coverage_offset_byte_range().end;
7834 let end = start + Offset32::RAW_BYTE_LEN;
7835 start..end
7836 }
7837
7838 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
7839 let start = self.backtrack_class_def_offset_byte_range().end;
7840 let end = start + Offset32::RAW_BYTE_LEN;
7841 start..end
7842 }
7843
7844 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
7845 let start = self.input_class_def_offset_byte_range().end;
7846 let end = start + Offset32::RAW_BYTE_LEN;
7847 start..end
7848 }
7849
7850 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
7851 let start = self.lookahead_class_def_offset_byte_range().end;
7852 let end = start + u16::RAW_BYTE_LEN;
7853 start..end
7854 }
7855
7856 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
7857 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
7858 let start = self.chained_class_seq_rule_set_count_byte_range().end;
7859 let end = start
7860 + (transforms::to_usize(chained_class_seq_rule_set_count))
7861 .saturating_mul(Offset24::RAW_BYTE_LEN);
7862 start..end
7863 }
7864}
7865
7866impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet2<'a> {
7867 fn min_byte_range(&self) -> Range<usize> {
7868 0..self.chained_class_seq_rule_offsets_byte_range().end
7869 }
7870 fn min_table_bytes(&self) -> &'a [u8] {
7871 let range = self.min_byte_range();
7872 self.offset_data().as_bytes().get(range).unwrap_or_default()
7873 }
7874}
7875
7876impl ReadArgs for ChainedClassSequenceRuleSet2<'_> {
7877 type Args = ();
7878}
7879
7880impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet2<'a> {
7881 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7882 #[allow(clippy::absurd_extreme_comparisons)]
7883 if data.len() < Self::MIN_SIZE {
7884 return Err(ReadError::OutOfBounds);
7885 }
7886 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7887 return Err(ReadError::OutOfBounds);
7888 };
7889 Ok(Self { data })
7890 }
7891}
7892
7893#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
7895#[repr(C, packed)]
7896#[doc(hidden)]
7897pub struct ChainedClassSequenceRuleSet2FixedHeader {
7898 pub chained_class_seq_rule_count: BigEndian<u16>,
7899}
7900
7901#[allow(clippy::absurd_extreme_comparisons)]
7902const _: () = assert!(
7903 std::mem::size_of::<ChainedClassSequenceRuleSet2FixedHeader>()
7904 <= ChainedClassSequenceRuleSet2::MIN_SIZE
7905);
7906
7907#[derive(Clone)]
7909pub struct ChainedClassSequenceRuleSet2<'a> {
7910 data: TableDataRef<'a, ChainedClassSequenceRuleSet2FixedHeader>,
7911}
7912
7913#[allow(clippy::needless_lifetimes)]
7914impl<'a> ChainedClassSequenceRuleSet2<'a> {
7915 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
7916 basic_table_impls!(impl_the_methods);
7917
7918 pub fn chained_class_seq_rule_count(&self) -> u16 {
7920 self.data.header().chained_class_seq_rule_count.get()
7921 }
7922
7923 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset24>] {
7926 let range = self.chained_class_seq_rule_offsets_byte_range();
7927 self.offset_data()
7928 .read_array(range)
7929 .ok()
7930 .unwrap_or_default()
7931 }
7932
7933 pub fn chained_class_seq_rules(
7935 &self,
7936 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset24> {
7937 let data = self.offset_data();
7938 let offsets = self.chained_class_seq_rule_offsets();
7939 ArrayOfOffsets::new(offsets, data, ())
7940 }
7941
7942 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
7943 let start = 0;
7944 let end = start + u16::RAW_BYTE_LEN;
7945 start..end
7946 }
7947
7948 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
7949 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
7950 let start = self.chained_class_seq_rule_count_byte_range().end;
7951 let end = start
7952 + (transforms::to_usize(chained_class_seq_rule_count))
7953 .saturating_mul(Offset24::RAW_BYTE_LEN);
7954 start..end
7955 }
7956}
7957
7958const _: () = assert!(FontData::default_data_long_enough(
7959 ChainedClassSequenceRuleSet2::MIN_SIZE
7960));
7961
7962impl Default for ChainedClassSequenceRuleSet2<'_> {
7963 fn default() -> Self {
7964 Self {
7965 data: TableDataRef::new(FontData::default_table_data().as_bytes())
7966 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
7967 }
7968 }
7969}
7970
7971impl<'a, T> MinByteRange<'a> for LookupList2<'a, T> {
7972 fn min_byte_range(&self) -> Range<usize> {
7973 0..self.lookup_offsets_byte_range().end
7974 }
7975 fn min_table_bytes(&self) -> &'a [u8] {
7976 let range = self.min_byte_range();
7977 self.offset_data().as_bytes().get(range).unwrap_or_default()
7978 }
7979}
7980
7981impl<T> ReadArgs for LookupList2<'_, T> {
7982 type Args = ();
7983}
7984
7985impl<'a, T> FontRead<'a> for LookupList2<'a, T> {
7986 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
7987 #[allow(clippy::absurd_extreme_comparisons)]
7988 if data.len() < Self::MIN_SIZE {
7989 return Err(ReadError::OutOfBounds);
7990 }
7991 let Some(data) = TableDataRef::new(data.as_bytes()) else {
7992 return Err(ReadError::OutOfBounds);
7993 };
7994 Ok(Self {
7995 data,
7996 offset_type: std::marker::PhantomData,
7997 })
7998 }
7999}
8000
8001impl<'a, T> LookupList2<'a, T> {
8002 #[allow(dead_code)]
8003 pub(crate) fn of_unit_type(&self) -> LookupList2<'a, ()> {
8005 LookupList2 {
8006 data: self.data,
8007 offset_type: std::marker::PhantomData,
8008 }
8009 }
8010}
8011
8012#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
8014#[repr(C, packed)]
8015#[doc(hidden)]
8016pub struct LookupList2FixedHeader {
8017 pub lookup_count: BigEndian<u16>,
8018}
8019
8020#[allow(clippy::absurd_extreme_comparisons)]
8021const _: () = assert!(std::mem::size_of::<LookupList2FixedHeader>() <= LookupList2::<()>::MIN_SIZE);
8022
8023#[derive(Clone)]
8025pub struct LookupList2<'a, T = ()> {
8026 data: TableDataRef<'a, LookupList2FixedHeader>,
8027 offset_type: std::marker::PhantomData<*const T>,
8028}
8029
8030#[allow(clippy::needless_lifetimes)]
8031impl<'a, T> LookupList2<'a, T> {
8032 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
8033 basic_table_impls!(impl_the_methods);
8034
8035 pub fn lookup_count(&self) -> u16 {
8037 self.data.header().lookup_count.get()
8038 }
8039
8040 pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset32>] {
8043 let range = self.lookup_offsets_byte_range();
8044 self.offset_data()
8045 .read_array(range)
8046 .ok()
8047 .unwrap_or_default()
8048 }
8049
8050 pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset32>
8052 where
8053 T: FontRead<'a, Args = ()>,
8054 {
8055 let data = self.offset_data();
8056 let offsets = self.lookup_offsets();
8057 ArrayOfOffsets::new(offsets, data, ())
8058 }
8059
8060 pub fn lookup_count_byte_range(&self) -> Range<usize> {
8061 let start = 0;
8062 let end = start + u16::RAW_BYTE_LEN;
8063 start..end
8064 }
8065
8066 pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
8067 let lookup_count = self.lookup_count();
8068 let start = self.lookup_count_byte_range().end;
8069 let end =
8070 start + (transforms::to_usize(lookup_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
8071 start..end
8072 }
8073}
8074
8075const _: () = assert!(FontData::default_data_long_enough(
8076 LookupList2::<()>::MIN_SIZE
8077));
8078
8079impl<T> Default for LookupList2<'_, T> {
8080 fn default() -> Self {
8081 Self {
8082 data: TableDataRef::new(FontData::default_table_data().as_bytes())
8083 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
8084 offset_type: std::marker::PhantomData,
8085 }
8086 }
8087}