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.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 Ok(Self { data })
29 }
30}
31
32#[derive(Clone)]
34pub struct ScriptList<'a> {
35 data: FontData<'a>,
36}
37
38#[allow(clippy::needless_lifetimes)]
39impl<'a> ScriptList<'a> {
40 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
41 basic_table_impls!(impl_the_methods);
42
43 pub fn script_count(&self) -> u16 {
45 let range = self.script_count_byte_range();
46 self.data.read_at(range.start).ok().unwrap()
47 }
48
49 pub fn script_records(&self) -> &'a [ScriptRecord] {
51 let range = self.script_records_byte_range();
52 self.data.read_array(range).ok().unwrap_or_default()
53 }
54
55 pub fn script_count_byte_range(&self) -> Range<usize> {
56 let start = 0;
57 let end = start + u16::RAW_BYTE_LEN;
58 start..end
59 }
60
61 pub fn script_records_byte_range(&self) -> Range<usize> {
62 let script_count = self.script_count();
63 let start = self.script_count_byte_range().end;
64 let end =
65 start + (transforms::to_usize(script_count)).saturating_mul(ScriptRecord::RAW_BYTE_LEN);
66 start..end
67 }
68}
69
70const _: () = assert!(FontData::default_data_long_enough(ScriptList::MIN_SIZE));
71
72impl Default for ScriptList<'_> {
73 fn default() -> Self {
74 Self {
75 data: FontData::default_table_data(),
76 }
77 }
78}
79
80#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
82#[repr(C)]
83#[repr(packed)]
84pub struct ScriptRecord {
85 pub script_tag: BigEndian<Tag>,
87 pub script_offset: BigEndian<Offset16>,
89}
90
91impl ScriptRecord {
92 pub fn script_tag(&self) -> Tag {
94 self.script_tag.get()
95 }
96
97 pub fn script_offset(&self) -> Offset16 {
99 self.script_offset.get()
100 }
101
102 pub fn script<'a>(&self, data: FontData<'a>) -> Result<Script<'a>, ReadError> {
107 self.script_offset().resolve(data)
108 }
109}
110
111impl FixedSize for ScriptRecord {
112 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
113}
114
115impl<'a> MinByteRange<'a> for Script<'a> {
116 fn min_byte_range(&self) -> Range<usize> {
117 0..self.lang_sys_records_byte_range().end
118 }
119 fn min_table_bytes(&self) -> &'a [u8] {
120 let range = self.min_byte_range();
121 self.data.as_bytes().get(range).unwrap_or_default()
122 }
123}
124
125impl ReadArgs for Script<'_> {
126 type Args = ();
127}
128
129impl<'a> FontRead<'a> for Script<'a> {
130 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
131 #[allow(clippy::absurd_extreme_comparisons)]
132 if data.len() < Self::MIN_SIZE {
133 return Err(ReadError::OutOfBounds);
134 }
135 Ok(Self { data })
136 }
137}
138
139#[derive(Clone)]
141pub struct Script<'a> {
142 data: FontData<'a>,
143}
144
145#[allow(clippy::needless_lifetimes)]
146impl<'a> Script<'a> {
147 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
148 basic_table_impls!(impl_the_methods);
149
150 pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
153 let range = self.default_lang_sys_offset_byte_range();
154 self.data.read_at(range.start).ok().unwrap()
155 }
156
157 pub fn default_lang_sys(&self) -> Option<Result<LangSys<'a>, ReadError>> {
159 let data = self.data;
160 self.default_lang_sys_offset().resolve(data)
161 }
162
163 pub fn lang_sys_count(&self) -> u16 {
166 let range = self.lang_sys_count_byte_range();
167 self.data.read_at(range.start).ok().unwrap()
168 }
169
170 pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
172 let range = self.lang_sys_records_byte_range();
173 self.data.read_array(range).ok().unwrap_or_default()
174 }
175
176 pub fn default_lang_sys_offset_byte_range(&self) -> Range<usize> {
177 let start = 0;
178 let end = start + Offset16::RAW_BYTE_LEN;
179 start..end
180 }
181
182 pub fn lang_sys_count_byte_range(&self) -> Range<usize> {
183 let start = self.default_lang_sys_offset_byte_range().end;
184 let end = start + u16::RAW_BYTE_LEN;
185 start..end
186 }
187
188 pub fn lang_sys_records_byte_range(&self) -> Range<usize> {
189 let lang_sys_count = self.lang_sys_count();
190 let start = self.lang_sys_count_byte_range().end;
191 let end = start
192 + (transforms::to_usize(lang_sys_count)).saturating_mul(LangSysRecord::RAW_BYTE_LEN);
193 start..end
194 }
195}
196
197const _: () = assert!(FontData::default_data_long_enough(Script::MIN_SIZE));
198
199impl Default for Script<'_> {
200 fn default() -> Self {
201 Self {
202 data: FontData::default_table_data(),
203 }
204 }
205}
206
207#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
208#[repr(C)]
209#[repr(packed)]
210pub struct LangSysRecord {
211 pub lang_sys_tag: BigEndian<Tag>,
213 pub lang_sys_offset: BigEndian<Offset16>,
215}
216
217impl LangSysRecord {
218 pub fn lang_sys_tag(&self) -> Tag {
220 self.lang_sys_tag.get()
221 }
222
223 pub fn lang_sys_offset(&self) -> Offset16 {
225 self.lang_sys_offset.get()
226 }
227
228 pub fn lang_sys<'a>(&self, data: FontData<'a>) -> Result<LangSys<'a>, ReadError> {
233 self.lang_sys_offset().resolve(data)
234 }
235}
236
237impl FixedSize for LangSysRecord {
238 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
239}
240
241impl<'a> MinByteRange<'a> for LangSys<'a> {
242 fn min_byte_range(&self) -> Range<usize> {
243 0..self.feature_indices_byte_range().end
244 }
245 fn min_table_bytes(&self) -> &'a [u8] {
246 let range = self.min_byte_range();
247 self.data.as_bytes().get(range).unwrap_or_default()
248 }
249}
250
251impl ReadArgs for LangSys<'_> {
252 type Args = ();
253}
254
255impl<'a> FontRead<'a> for LangSys<'a> {
256 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
257 #[allow(clippy::absurd_extreme_comparisons)]
258 if data.len() < Self::MIN_SIZE {
259 return Err(ReadError::OutOfBounds);
260 }
261 Ok(Self { data })
262 }
263}
264
265#[derive(Clone)]
267pub struct LangSys<'a> {
268 data: FontData<'a>,
269}
270
271#[allow(clippy::needless_lifetimes)]
272impl<'a> LangSys<'a> {
273 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
274 basic_table_impls!(impl_the_methods);
275
276 pub fn required_feature_index(&self) -> u16 {
279 let range = self.required_feature_index_byte_range();
280 self.data.read_at(range.start).ok().unwrap()
281 }
282
283 pub fn feature_index_count(&self) -> u16 {
286 let range = self.feature_index_count_byte_range();
287 self.data.read_at(range.start).ok().unwrap()
288 }
289
290 pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
292 let range = self.feature_indices_byte_range();
293 self.data.read_array(range).ok().unwrap_or_default()
294 }
295
296 pub fn lookup_order_offset_byte_range(&self) -> Range<usize> {
297 let start = 0;
298 let end = start + u16::RAW_BYTE_LEN;
299 start..end
300 }
301
302 pub fn required_feature_index_byte_range(&self) -> Range<usize> {
303 let start = self.lookup_order_offset_byte_range().end;
304 let end = start + u16::RAW_BYTE_LEN;
305 start..end
306 }
307
308 pub fn feature_index_count_byte_range(&self) -> Range<usize> {
309 let start = self.required_feature_index_byte_range().end;
310 let end = start + u16::RAW_BYTE_LEN;
311 start..end
312 }
313
314 pub fn feature_indices_byte_range(&self) -> Range<usize> {
315 let feature_index_count = self.feature_index_count();
316 let start = self.feature_index_count_byte_range().end;
317 let end =
318 start + (transforms::to_usize(feature_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
319 start..end
320 }
321}
322
323const _: () = assert!(FontData::default_data_long_enough(LangSys::MIN_SIZE));
324
325impl Default for LangSys<'_> {
326 fn default() -> Self {
327 Self {
328 data: FontData::default_table_data(),
329 }
330 }
331}
332
333impl<'a> MinByteRange<'a> for FeatureList<'a> {
334 fn min_byte_range(&self) -> Range<usize> {
335 0..self.feature_records_byte_range().end
336 }
337 fn min_table_bytes(&self) -> &'a [u8] {
338 let range = self.min_byte_range();
339 self.data.as_bytes().get(range).unwrap_or_default()
340 }
341}
342
343impl ReadArgs for FeatureList<'_> {
344 type Args = ();
345}
346
347impl<'a> FontRead<'a> for FeatureList<'a> {
348 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
349 #[allow(clippy::absurd_extreme_comparisons)]
350 if data.len() < Self::MIN_SIZE {
351 return Err(ReadError::OutOfBounds);
352 }
353 Ok(Self { data })
354 }
355}
356
357#[derive(Clone)]
359pub struct FeatureList<'a> {
360 data: FontData<'a>,
361}
362
363#[allow(clippy::needless_lifetimes)]
364impl<'a> FeatureList<'a> {
365 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
366 basic_table_impls!(impl_the_methods);
367
368 pub fn feature_count(&self) -> u16 {
370 let range = self.feature_count_byte_range();
371 self.data.read_at(range.start).ok().unwrap()
372 }
373
374 pub fn feature_records(&self) -> &'a [FeatureRecord] {
377 let range = self.feature_records_byte_range();
378 self.data.read_array(range).ok().unwrap_or_default()
379 }
380
381 pub fn feature_count_byte_range(&self) -> Range<usize> {
382 let start = 0;
383 let end = start + u16::RAW_BYTE_LEN;
384 start..end
385 }
386
387 pub fn feature_records_byte_range(&self) -> Range<usize> {
388 let feature_count = self.feature_count();
389 let start = self.feature_count_byte_range().end;
390 let end = start
391 + (transforms::to_usize(feature_count)).saturating_mul(FeatureRecord::RAW_BYTE_LEN);
392 start..end
393 }
394}
395
396const _: () = assert!(FontData::default_data_long_enough(FeatureList::MIN_SIZE));
397
398impl Default for FeatureList<'_> {
399 fn default() -> Self {
400 Self {
401 data: FontData::default_table_data(),
402 }
403 }
404}
405
406#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
408#[repr(C)]
409#[repr(packed)]
410pub struct FeatureRecord {
411 pub feature_tag: BigEndian<Tag>,
413 pub feature_offset: BigEndian<Offset16>,
415}
416
417impl FeatureRecord {
418 pub fn feature_tag(&self) -> Tag {
420 self.feature_tag.get()
421 }
422
423 pub fn feature_offset(&self) -> Offset16 {
425 self.feature_offset.get()
426 }
427
428 pub fn feature<'a>(&self, data: FontData<'a>) -> Result<Feature<'a>, ReadError> {
433 let args = self.feature_tag();
434 self.feature_offset().resolve_with_args(data, args)
435 }
436}
437
438impl FixedSize for FeatureRecord {
439 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
440}
441
442impl<'a> MinByteRange<'a> for Feature<'a> {
443 fn min_byte_range(&self) -> Range<usize> {
444 0..self.lookup_list_indices_byte_range().end
445 }
446 fn min_table_bytes(&self) -> &'a [u8] {
447 let range = self.min_byte_range();
448 self.data.as_bytes().get(range).unwrap_or_default()
449 }
450}
451
452impl ReadArgs for Feature<'_> {
453 type Args = Tag;
454}
455
456impl<'a> FontRead<'a> for Feature<'a> {
457 fn read_with_args(data: FontData<'a>, args: Tag) -> Result<Self, ReadError> {
458 let feature_tag = args;
459
460 #[allow(clippy::absurd_extreme_comparisons)]
461 if data.len() < Self::MIN_SIZE {
462 return Err(ReadError::OutOfBounds);
463 }
464 Ok(Self { data, feature_tag })
465 }
466}
467
468impl<'a> Feature<'a> {
469 pub fn read(data: FontData<'a>, feature_tag: Tag) -> Result<Self, ReadError> {
474 let args = feature_tag;
475 Self::read_with_args(data, args)
476 }
477}
478
479#[derive(Clone)]
481pub struct Feature<'a> {
482 data: FontData<'a>,
483 feature_tag: Tag,
484}
485
486#[allow(clippy::needless_lifetimes)]
487impl<'a> Feature<'a> {
488 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
489 basic_table_impls!(impl_the_methods);
490
491 pub fn feature_params_offset(&self) -> Nullable<Offset16> {
493 let range = self.feature_params_offset_byte_range();
494 self.data.read_at(range.start).ok().unwrap()
495 }
496
497 pub fn feature_params(&self) -> Option<Result<FeatureParams<'a>, ReadError>> {
499 let data = self.data;
500 let args = self.feature_tag();
501 self.feature_params_offset().resolve_with_args(data, args)
502 }
503
504 pub fn lookup_index_count(&self) -> u16 {
506 let range = self.lookup_index_count_byte_range();
507 self.data.read_at(range.start).ok().unwrap()
508 }
509
510 pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
513 let range = self.lookup_list_indices_byte_range();
514 self.data.read_array(range).ok().unwrap_or_default()
515 }
516
517 pub(crate) fn feature_tag(&self) -> Tag {
518 self.feature_tag
519 }
520
521 pub fn feature_params_offset_byte_range(&self) -> Range<usize> {
522 let start = 0;
523 let end = start + Offset16::RAW_BYTE_LEN;
524 start..end
525 }
526
527 pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
528 let start = self.feature_params_offset_byte_range().end;
529 let end = start + u16::RAW_BYTE_LEN;
530 start..end
531 }
532
533 pub fn lookup_list_indices_byte_range(&self) -> Range<usize> {
534 let lookup_index_count = self.lookup_index_count();
535 let start = self.lookup_index_count_byte_range().end;
536 let end =
537 start + (transforms::to_usize(lookup_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
538 start..end
539 }
540}
541
542const _: () = assert!(FontData::default_data_long_enough(Feature::MIN_SIZE));
543
544impl Default for Feature<'_> {
545 fn default() -> Self {
546 Self {
547 data: FontData::default_table_data(),
548 feature_tag: Default::default(),
549 }
550 }
551}
552
553impl<'a, T> MinByteRange<'a> for LookupList<'a, T> {
554 fn min_byte_range(&self) -> Range<usize> {
555 0..self.lookup_offsets_byte_range().end
556 }
557 fn min_table_bytes(&self) -> &'a [u8] {
558 let range = self.min_byte_range();
559 self.data.as_bytes().get(range).unwrap_or_default()
560 }
561}
562
563impl<T> ReadArgs for LookupList<'_, T> {
564 type Args = ();
565}
566
567impl<'a, T> FontRead<'a> for LookupList<'a, T> {
568 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
569 #[allow(clippy::absurd_extreme_comparisons)]
570 if data.len() < Self::MIN_SIZE {
571 return Err(ReadError::OutOfBounds);
572 }
573 Ok(Self {
574 data,
575 offset_type: std::marker::PhantomData,
576 })
577 }
578}
579
580impl<'a, T> LookupList<'a, T> {
581 #[allow(dead_code)]
582 pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
584 LookupList {
585 data: self.data,
586 offset_type: std::marker::PhantomData,
587 }
588 }
589}
590
591#[derive(Clone)]
593pub struct LookupList<'a, T = ()> {
594 data: FontData<'a>,
595 offset_type: std::marker::PhantomData<*const T>,
596}
597
598#[allow(clippy::needless_lifetimes)]
599impl<'a, T> LookupList<'a, T> {
600 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
601 basic_table_impls!(impl_the_methods);
602
603 pub fn lookup_count(&self) -> u16 {
605 let range = self.lookup_count_byte_range();
606 self.data.read_at(range.start).ok().unwrap()
607 }
608
609 pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
612 let range = self.lookup_offsets_byte_range();
613 self.data.read_array(range).ok().unwrap_or_default()
614 }
615
616 pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset16>
618 where
619 T: FontRead<'a, Args = ()>,
620 {
621 let data = self.data;
622 let offsets = self.lookup_offsets();
623 ArrayOfOffsets::new(offsets, data, ())
624 }
625
626 pub fn lookup_count_byte_range(&self) -> Range<usize> {
627 let start = 0;
628 let end = start + u16::RAW_BYTE_LEN;
629 start..end
630 }
631
632 pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
633 let lookup_count = self.lookup_count();
634 let start = self.lookup_count_byte_range().end;
635 let end =
636 start + (transforms::to_usize(lookup_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
637 start..end
638 }
639}
640
641const _: () = assert!(FontData::default_data_long_enough(
642 LookupList::<()>::MIN_SIZE
643));
644
645impl<T> Default for LookupList<'_, T> {
646 fn default() -> Self {
647 Self {
648 data: FontData::default_table_data(),
649 offset_type: std::marker::PhantomData,
650 }
651 }
652}
653
654impl Discriminant for Lookup<'_, ()> {
655 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
656 data.read_at(0)
657 }
658}
659
660impl<'a, T> MinByteRange<'a> for Lookup<'a, T> {
661 fn min_byte_range(&self) -> Range<usize> {
662 0..self.subtable_offsets_byte_range().end
663 }
664 fn min_table_bytes(&self) -> &'a [u8] {
665 let range = self.min_byte_range();
666 self.data.as_bytes().get(range).unwrap_or_default()
667 }
668}
669
670impl<T> ReadArgs for Lookup<'_, T> {
671 type Args = ();
672}
673
674impl<'a, T> FontRead<'a> for Lookup<'a, T> {
675 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
676 #[allow(clippy::absurd_extreme_comparisons)]
677 if data.len() < Self::MIN_SIZE {
678 return Err(ReadError::OutOfBounds);
679 }
680 Ok(Self {
681 data,
682 offset_type: std::marker::PhantomData,
683 })
684 }
685}
686
687impl<'a, T> Lookup<'a, T> {
688 #[allow(dead_code)]
689 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
691 Lookup {
692 data: self.data,
693 offset_type: std::marker::PhantomData,
694 }
695 }
696}
697
698#[derive(Clone)]
700pub struct Lookup<'a, T = ()> {
701 data: FontData<'a>,
702 offset_type: std::marker::PhantomData<*const T>,
703}
704
705#[allow(clippy::needless_lifetimes)]
706impl<'a, T> Lookup<'a, T> {
707 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + LookupFlag::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
708 basic_table_impls!(impl_the_methods);
709
710 pub fn lookup_type(&self) -> u16 {
712 let range = self.lookup_type_byte_range();
713 self.data.read_at(range.start).ok().unwrap()
714 }
715
716 pub fn lookup_flag(&self) -> LookupFlag {
718 let range = self.lookup_flag_byte_range();
719 self.data.read_at(range.start).ok().unwrap()
720 }
721
722 pub fn sub_table_count(&self) -> u16 {
724 let range = self.sub_table_count_byte_range();
725 self.data.read_at(range.start).ok().unwrap()
726 }
727
728 pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
731 let range = self.subtable_offsets_byte_range();
732 self.data.read_array(range).ok().unwrap_or_default()
733 }
734
735 pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
737 where
738 T: FontRead<'a, Args = ()>,
739 {
740 let data = self.data;
741 let offsets = self.subtable_offsets();
742 ArrayOfOffsets::new(offsets, data, ())
743 }
744
745 pub fn mark_filtering_set(&self) -> Option<u16> {
749 let range = self.mark_filtering_set_byte_range();
750 (!range.is_empty())
751 .then(|| self.data.read_at(range.start).ok())
752 .flatten()
753 }
754
755 pub fn lookup_type_byte_range(&self) -> Range<usize> {
756 let start = 0;
757 let end = start + u16::RAW_BYTE_LEN;
758 start..end
759 }
760
761 pub fn lookup_flag_byte_range(&self) -> Range<usize> {
762 let start = self.lookup_type_byte_range().end;
763 let end = start + LookupFlag::RAW_BYTE_LEN;
764 start..end
765 }
766
767 pub fn sub_table_count_byte_range(&self) -> Range<usize> {
768 let start = self.lookup_flag_byte_range().end;
769 let end = start + u16::RAW_BYTE_LEN;
770 start..end
771 }
772
773 pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
774 let sub_table_count = self.sub_table_count();
775 let start = self.sub_table_count_byte_range().end;
776 let end =
777 start + (transforms::to_usize(sub_table_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
778 start..end
779 }
780
781 pub fn mark_filtering_set_byte_range(&self) -> Range<usize> {
782 let start = self.subtable_offsets_byte_range().end;
783 let end = if self
784 .lookup_flag()
785 .contains(LookupFlag::USE_MARK_FILTERING_SET)
786 {
787 start + u16::RAW_BYTE_LEN
788 } else {
789 start
790 };
791 start..end
792 }
793}
794
795const _: () = assert!(FontData::default_data_long_enough(Lookup::<()>::MIN_SIZE));
796
797impl<T> Default for Lookup<'_, T> {
798 fn default() -> Self {
799 Self {
800 data: FontData::default_table_data(),
801 offset_type: std::marker::PhantomData,
802 }
803 }
804}
805
806impl Format<u16> for CoverageFormat1<'_> {
807 const FORMAT: u16 = 1;
808}
809
810impl<'a> MinByteRange<'a> for CoverageFormat1<'a> {
811 fn min_byte_range(&self) -> Range<usize> {
812 0..self.glyph_array_byte_range().end
813 }
814 fn min_table_bytes(&self) -> &'a [u8] {
815 let range = self.min_byte_range();
816 self.data.as_bytes().get(range).unwrap_or_default()
817 }
818}
819
820impl ReadArgs for CoverageFormat1<'_> {
821 type Args = ();
822}
823
824impl<'a> FontRead<'a> for CoverageFormat1<'a> {
825 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
826 #[allow(clippy::absurd_extreme_comparisons)]
827 if data.len() < Self::MIN_SIZE {
828 return Err(ReadError::OutOfBounds);
829 }
830 Ok(Self { data })
831 }
832}
833
834#[derive(Clone)]
836pub struct CoverageFormat1<'a> {
837 data: FontData<'a>,
838}
839
840#[allow(clippy::needless_lifetimes)]
841impl<'a> CoverageFormat1<'a> {
842 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
843 basic_table_impls!(impl_the_methods);
844
845 pub fn coverage_format(&self) -> u16 {
847 let range = self.coverage_format_byte_range();
848 self.data.read_at(range.start).ok().unwrap()
849 }
850
851 pub fn glyph_count(&self) -> u16 {
853 let range = self.glyph_count_byte_range();
854 self.data.read_at(range.start).ok().unwrap()
855 }
856
857 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
859 let range = self.glyph_array_byte_range();
860 self.data.read_array(range).ok().unwrap_or_default()
861 }
862
863 pub fn coverage_format_byte_range(&self) -> Range<usize> {
864 let start = 0;
865 let end = start + u16::RAW_BYTE_LEN;
866 start..end
867 }
868
869 pub fn glyph_count_byte_range(&self) -> Range<usize> {
870 let start = self.coverage_format_byte_range().end;
871 let end = start + u16::RAW_BYTE_LEN;
872 start..end
873 }
874
875 pub fn glyph_array_byte_range(&self) -> Range<usize> {
876 let glyph_count = self.glyph_count();
877 let start = self.glyph_count_byte_range().end;
878 let end =
879 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
880 start..end
881 }
882}
883
884const _: () = assert!(FontData::default_data_long_enough(
885 CoverageFormat1::MIN_SIZE
886));
887
888impl Default for CoverageFormat1<'_> {
889 fn default() -> Self {
890 Self {
891 data: FontData::default_format_1_u16_table_data(),
892 }
893 }
894}
895
896impl Format<u16> for CoverageFormat2<'_> {
897 const FORMAT: u16 = 2;
898}
899
900impl<'a> MinByteRange<'a> for CoverageFormat2<'a> {
901 fn min_byte_range(&self) -> Range<usize> {
902 0..self.range_records_byte_range().end
903 }
904 fn min_table_bytes(&self) -> &'a [u8] {
905 let range = self.min_byte_range();
906 self.data.as_bytes().get(range).unwrap_or_default()
907 }
908}
909
910impl ReadArgs for CoverageFormat2<'_> {
911 type Args = ();
912}
913
914impl<'a> FontRead<'a> for CoverageFormat2<'a> {
915 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
916 #[allow(clippy::absurd_extreme_comparisons)]
917 if data.len() < Self::MIN_SIZE {
918 return Err(ReadError::OutOfBounds);
919 }
920 Ok(Self { data })
921 }
922}
923
924#[derive(Clone)]
926pub struct CoverageFormat2<'a> {
927 data: FontData<'a>,
928}
929
930#[allow(clippy::needless_lifetimes)]
931impl<'a> CoverageFormat2<'a> {
932 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
933 basic_table_impls!(impl_the_methods);
934
935 pub fn coverage_format(&self) -> u16 {
937 let range = self.coverage_format_byte_range();
938 self.data.read_at(range.start).ok().unwrap()
939 }
940
941 pub fn range_count(&self) -> u16 {
943 let range = self.range_count_byte_range();
944 self.data.read_at(range.start).ok().unwrap()
945 }
946
947 pub fn range_records(&self) -> &'a [RangeRecord] {
949 let range = self.range_records_byte_range();
950 self.data.read_array(range).ok().unwrap_or_default()
951 }
952
953 pub fn coverage_format_byte_range(&self) -> Range<usize> {
954 let start = 0;
955 let end = start + u16::RAW_BYTE_LEN;
956 start..end
957 }
958
959 pub fn range_count_byte_range(&self) -> Range<usize> {
960 let start = self.coverage_format_byte_range().end;
961 let end = start + u16::RAW_BYTE_LEN;
962 start..end
963 }
964
965 pub fn range_records_byte_range(&self) -> Range<usize> {
966 let range_count = self.range_count();
967 let start = self.range_count_byte_range().end;
968 let end =
969 start + (transforms::to_usize(range_count)).saturating_mul(RangeRecord::RAW_BYTE_LEN);
970 start..end
971 }
972}
973
974#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
976#[repr(C)]
977#[repr(packed)]
978pub struct RangeRecord {
979 pub start_glyph_id: BigEndian<GlyphId16>,
981 pub end_glyph_id: BigEndian<GlyphId16>,
983 pub start_coverage_index: BigEndian<u16>,
985}
986
987impl RangeRecord {
988 pub fn start_glyph_id(&self) -> GlyphId16 {
990 self.start_glyph_id.get()
991 }
992
993 pub fn end_glyph_id(&self) -> GlyphId16 {
995 self.end_glyph_id.get()
996 }
997
998 pub fn start_coverage_index(&self) -> u16 {
1000 self.start_coverage_index.get()
1001 }
1002}
1003
1004impl FixedSize for RangeRecord {
1005 const RAW_BYTE_LEN: usize =
1006 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1007}
1008
1009#[derive(Clone)]
1011pub enum CoverageTable<'a> {
1012 Format1(CoverageFormat1<'a>),
1013 Format2(CoverageFormat2<'a>),
1014}
1015
1016impl Default for CoverageTable<'_> {
1017 fn default() -> Self {
1018 Self::Format1(Default::default())
1019 }
1020}
1021
1022impl<'a> CoverageTable<'a> {
1023 pub fn offset_data(&self) -> FontData<'a> {
1025 match self {
1026 Self::Format1(item) => item.offset_data(),
1027 Self::Format2(item) => item.offset_data(),
1028 }
1029 }
1030
1031 pub fn coverage_format(&self) -> u16 {
1033 match self {
1034 Self::Format1(item) => item.coverage_format(),
1035 Self::Format2(item) => item.coverage_format(),
1036 }
1037 }
1038}
1039
1040impl ReadArgs for CoverageTable<'_> {
1041 type Args = ();
1042}
1043
1044impl<'a> FontRead<'a> for CoverageTable<'a> {
1045 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1046 let format: u16 = data.read_at(0usize)?;
1047 match format {
1048 CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1049 CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1050 other => Err(ReadError::InvalidFormat(other.into())),
1051 }
1052 }
1053}
1054
1055impl<'a> MinByteRange<'a> for CoverageTable<'a> {
1056 fn min_byte_range(&self) -> Range<usize> {
1057 match self {
1058 Self::Format1(item) => item.min_byte_range(),
1059 Self::Format2(item) => item.min_byte_range(),
1060 }
1061 }
1062 fn min_table_bytes(&self) -> &'a [u8] {
1063 match self {
1064 Self::Format1(item) => item.min_table_bytes(),
1065 Self::Format2(item) => item.min_table_bytes(),
1066 }
1067 }
1068}
1069
1070impl Format<u16> for ClassDefFormat1<'_> {
1071 const FORMAT: u16 = 1;
1072}
1073
1074impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
1075 fn min_byte_range(&self) -> Range<usize> {
1076 0..self.class_value_array_byte_range().end
1077 }
1078 fn min_table_bytes(&self) -> &'a [u8] {
1079 let range = self.min_byte_range();
1080 self.data.as_bytes().get(range).unwrap_or_default()
1081 }
1082}
1083
1084impl ReadArgs for ClassDefFormat1<'_> {
1085 type Args = ();
1086}
1087
1088impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1089 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1090 #[allow(clippy::absurd_extreme_comparisons)]
1091 if data.len() < Self::MIN_SIZE {
1092 return Err(ReadError::OutOfBounds);
1093 }
1094 Ok(Self { data })
1095 }
1096}
1097
1098#[derive(Clone)]
1100pub struct ClassDefFormat1<'a> {
1101 data: FontData<'a>,
1102}
1103
1104#[allow(clippy::needless_lifetimes)]
1105impl<'a> ClassDefFormat1<'a> {
1106 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1107 basic_table_impls!(impl_the_methods);
1108
1109 pub fn class_format(&self) -> u16 {
1111 let range = self.class_format_byte_range();
1112 self.data.read_at(range.start).ok().unwrap()
1113 }
1114
1115 pub fn start_glyph_id(&self) -> GlyphId16 {
1117 let range = self.start_glyph_id_byte_range();
1118 self.data.read_at(range.start).ok().unwrap()
1119 }
1120
1121 pub fn glyph_count(&self) -> u16 {
1123 let range = self.glyph_count_byte_range();
1124 self.data.read_at(range.start).ok().unwrap()
1125 }
1126
1127 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1129 let range = self.class_value_array_byte_range();
1130 self.data.read_array(range).ok().unwrap_or_default()
1131 }
1132
1133 pub fn class_format_byte_range(&self) -> Range<usize> {
1134 let start = 0;
1135 let end = start + u16::RAW_BYTE_LEN;
1136 start..end
1137 }
1138
1139 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1140 let start = self.class_format_byte_range().end;
1141 let end = start + GlyphId16::RAW_BYTE_LEN;
1142 start..end
1143 }
1144
1145 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1146 let start = self.start_glyph_id_byte_range().end;
1147 let end = start + u16::RAW_BYTE_LEN;
1148 start..end
1149 }
1150
1151 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1152 let glyph_count = self.glyph_count();
1153 let start = self.glyph_count_byte_range().end;
1154 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
1155 start..end
1156 }
1157}
1158
1159const _: () = assert!(FontData::default_data_long_enough(
1160 ClassDefFormat1::MIN_SIZE
1161));
1162
1163impl Default for ClassDefFormat1<'_> {
1164 fn default() -> Self {
1165 Self {
1166 data: FontData::default_format_1_u16_table_data(),
1167 }
1168 }
1169}
1170
1171impl Format<u16> for ClassDefFormat2<'_> {
1172 const FORMAT: u16 = 2;
1173}
1174
1175impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
1176 fn min_byte_range(&self) -> Range<usize> {
1177 0..self.class_range_records_byte_range().end
1178 }
1179 fn min_table_bytes(&self) -> &'a [u8] {
1180 let range = self.min_byte_range();
1181 self.data.as_bytes().get(range).unwrap_or_default()
1182 }
1183}
1184
1185impl ReadArgs for ClassDefFormat2<'_> {
1186 type Args = ();
1187}
1188
1189impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1190 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1191 #[allow(clippy::absurd_extreme_comparisons)]
1192 if data.len() < Self::MIN_SIZE {
1193 return Err(ReadError::OutOfBounds);
1194 }
1195 Ok(Self { data })
1196 }
1197}
1198
1199#[derive(Clone)]
1201pub struct ClassDefFormat2<'a> {
1202 data: FontData<'a>,
1203}
1204
1205#[allow(clippy::needless_lifetimes)]
1206impl<'a> ClassDefFormat2<'a> {
1207 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1208 basic_table_impls!(impl_the_methods);
1209
1210 pub fn class_format(&self) -> u16 {
1212 let range = self.class_format_byte_range();
1213 self.data.read_at(range.start).ok().unwrap()
1214 }
1215
1216 pub fn class_range_count(&self) -> u16 {
1218 let range = self.class_range_count_byte_range();
1219 self.data.read_at(range.start).ok().unwrap()
1220 }
1221
1222 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1224 let range = self.class_range_records_byte_range();
1225 self.data.read_array(range).ok().unwrap_or_default()
1226 }
1227
1228 pub fn class_format_byte_range(&self) -> Range<usize> {
1229 let start = 0;
1230 let end = start + u16::RAW_BYTE_LEN;
1231 start..end
1232 }
1233
1234 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1235 let start = self.class_format_byte_range().end;
1236 let end = start + u16::RAW_BYTE_LEN;
1237 start..end
1238 }
1239
1240 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1241 let class_range_count = self.class_range_count();
1242 let start = self.class_range_count_byte_range().end;
1243 let end = start
1244 + (transforms::to_usize(class_range_count))
1245 .saturating_mul(ClassRangeRecord::RAW_BYTE_LEN);
1246 start..end
1247 }
1248}
1249
1250#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1252#[repr(C)]
1253#[repr(packed)]
1254pub struct ClassRangeRecord {
1255 pub start_glyph_id: BigEndian<GlyphId16>,
1257 pub end_glyph_id: BigEndian<GlyphId16>,
1259 pub class: BigEndian<u16>,
1261}
1262
1263impl ClassRangeRecord {
1264 pub fn start_glyph_id(&self) -> GlyphId16 {
1266 self.start_glyph_id.get()
1267 }
1268
1269 pub fn end_glyph_id(&self) -> GlyphId16 {
1271 self.end_glyph_id.get()
1272 }
1273
1274 pub fn class(&self) -> u16 {
1276 self.class.get()
1277 }
1278}
1279
1280impl FixedSize for ClassRangeRecord {
1281 const RAW_BYTE_LEN: usize =
1282 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1283}
1284
1285#[derive(Clone)]
1287pub enum ClassDef<'a> {
1288 Format1(ClassDefFormat1<'a>),
1289 Format2(ClassDefFormat2<'a>),
1290}
1291
1292impl Default for ClassDef<'_> {
1293 fn default() -> Self {
1294 Self::Format1(Default::default())
1295 }
1296}
1297
1298impl<'a> ClassDef<'a> {
1299 pub fn offset_data(&self) -> FontData<'a> {
1301 match self {
1302 Self::Format1(item) => item.offset_data(),
1303 Self::Format2(item) => item.offset_data(),
1304 }
1305 }
1306
1307 pub fn class_format(&self) -> u16 {
1309 match self {
1310 Self::Format1(item) => item.class_format(),
1311 Self::Format2(item) => item.class_format(),
1312 }
1313 }
1314}
1315
1316impl ReadArgs for ClassDef<'_> {
1317 type Args = ();
1318}
1319
1320impl<'a> FontRead<'a> for ClassDef<'a> {
1321 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1322 let format: u16 = data.read_at(0usize)?;
1323 match format {
1324 ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1325 ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1326 other => Err(ReadError::InvalidFormat(other.into())),
1327 }
1328 }
1329}
1330
1331impl<'a> MinByteRange<'a> for ClassDef<'a> {
1332 fn min_byte_range(&self) -> Range<usize> {
1333 match self {
1334 Self::Format1(item) => item.min_byte_range(),
1335 Self::Format2(item) => item.min_byte_range(),
1336 }
1337 }
1338 fn min_table_bytes(&self) -> &'a [u8] {
1339 match self {
1340 Self::Format1(item) => item.min_table_bytes(),
1341 Self::Format2(item) => item.min_table_bytes(),
1342 }
1343 }
1344}
1345
1346#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1348#[repr(C)]
1349#[repr(packed)]
1350pub struct SequenceLookupRecord {
1351 pub sequence_index: BigEndian<u16>,
1353 pub lookup_list_index: BigEndian<u16>,
1355}
1356
1357impl SequenceLookupRecord {
1358 pub fn sequence_index(&self) -> u16 {
1360 self.sequence_index.get()
1361 }
1362
1363 pub fn lookup_list_index(&self) -> u16 {
1365 self.lookup_list_index.get()
1366 }
1367}
1368
1369impl FixedSize for SequenceLookupRecord {
1370 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1371}
1372
1373impl Format<u16> for SequenceContextFormat1<'_> {
1374 const FORMAT: u16 = 1;
1375}
1376
1377impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
1378 fn min_byte_range(&self) -> Range<usize> {
1379 0..self.seq_rule_set_offsets_byte_range().end
1380 }
1381 fn min_table_bytes(&self) -> &'a [u8] {
1382 let range = self.min_byte_range();
1383 self.data.as_bytes().get(range).unwrap_or_default()
1384 }
1385}
1386
1387impl ReadArgs for SequenceContextFormat1<'_> {
1388 type Args = ();
1389}
1390
1391impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1392 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1393 #[allow(clippy::absurd_extreme_comparisons)]
1394 if data.len() < Self::MIN_SIZE {
1395 return Err(ReadError::OutOfBounds);
1396 }
1397 Ok(Self { data })
1398 }
1399}
1400
1401#[derive(Clone)]
1403pub struct SequenceContextFormat1<'a> {
1404 data: FontData<'a>,
1405}
1406
1407#[allow(clippy::needless_lifetimes)]
1408impl<'a> SequenceContextFormat1<'a> {
1409 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1410 basic_table_impls!(impl_the_methods);
1411
1412 pub fn format(&self) -> u16 {
1414 let range = self.format_byte_range();
1415 self.data.read_at(range.start).ok().unwrap()
1416 }
1417
1418 pub fn coverage_offset(&self) -> Offset16 {
1421 let range = self.coverage_offset_byte_range();
1422 self.data.read_at(range.start).ok().unwrap()
1423 }
1424
1425 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1427 let data = self.data;
1428 self.coverage_offset().resolve(data)
1429 }
1430
1431 pub fn seq_rule_set_count(&self) -> u16 {
1433 let range = self.seq_rule_set_count_byte_range();
1434 self.data.read_at(range.start).ok().unwrap()
1435 }
1436
1437 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1440 let range = self.seq_rule_set_offsets_byte_range();
1441 self.data.read_array(range).ok().unwrap_or_default()
1442 }
1443
1444 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1446 let data = self.data;
1447 let offsets = self.seq_rule_set_offsets();
1448 ArrayOfNullableOffsets::new(offsets, data, ())
1449 }
1450
1451 pub fn format_byte_range(&self) -> Range<usize> {
1452 let start = 0;
1453 let end = start + u16::RAW_BYTE_LEN;
1454 start..end
1455 }
1456
1457 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1458 let start = self.format_byte_range().end;
1459 let end = start + Offset16::RAW_BYTE_LEN;
1460 start..end
1461 }
1462
1463 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1464 let start = self.coverage_offset_byte_range().end;
1465 let end = start + u16::RAW_BYTE_LEN;
1466 start..end
1467 }
1468
1469 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1470 let seq_rule_set_count = self.seq_rule_set_count();
1471 let start = self.seq_rule_set_count_byte_range().end;
1472 let end = start
1473 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1474 start..end
1475 }
1476}
1477
1478const _: () = assert!(FontData::default_data_long_enough(
1479 SequenceContextFormat1::MIN_SIZE
1480));
1481
1482impl Default for SequenceContextFormat1<'_> {
1483 fn default() -> Self {
1484 Self {
1485 data: FontData::default_format_1_u16_table_data(),
1486 }
1487 }
1488}
1489
1490impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
1491 fn min_byte_range(&self) -> Range<usize> {
1492 0..self.seq_rule_offsets_byte_range().end
1493 }
1494 fn min_table_bytes(&self) -> &'a [u8] {
1495 let range = self.min_byte_range();
1496 self.data.as_bytes().get(range).unwrap_or_default()
1497 }
1498}
1499
1500impl ReadArgs for SequenceRuleSet<'_> {
1501 type Args = ();
1502}
1503
1504impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
1505 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1506 #[allow(clippy::absurd_extreme_comparisons)]
1507 if data.len() < Self::MIN_SIZE {
1508 return Err(ReadError::OutOfBounds);
1509 }
1510 Ok(Self { data })
1511 }
1512}
1513
1514#[derive(Clone)]
1516pub struct SequenceRuleSet<'a> {
1517 data: FontData<'a>,
1518}
1519
1520#[allow(clippy::needless_lifetimes)]
1521impl<'a> SequenceRuleSet<'a> {
1522 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1523 basic_table_impls!(impl_the_methods);
1524
1525 pub fn seq_rule_count(&self) -> u16 {
1527 let range = self.seq_rule_count_byte_range();
1528 self.data.read_at(range.start).ok().unwrap()
1529 }
1530
1531 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
1534 let range = self.seq_rule_offsets_byte_range();
1535 self.data.read_array(range).ok().unwrap_or_default()
1536 }
1537
1538 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
1540 let data = self.data;
1541 let offsets = self.seq_rule_offsets();
1542 ArrayOfOffsets::new(offsets, data, ())
1543 }
1544
1545 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
1546 let start = 0;
1547 let end = start + u16::RAW_BYTE_LEN;
1548 start..end
1549 }
1550
1551 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
1552 let seq_rule_count = self.seq_rule_count();
1553 let start = self.seq_rule_count_byte_range().end;
1554 let end =
1555 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1556 start..end
1557 }
1558}
1559
1560const _: () = assert!(FontData::default_data_long_enough(
1561 SequenceRuleSet::MIN_SIZE
1562));
1563
1564impl Default for SequenceRuleSet<'_> {
1565 fn default() -> Self {
1566 Self {
1567 data: FontData::default_table_data(),
1568 }
1569 }
1570}
1571
1572impl<'a> MinByteRange<'a> for SequenceRule<'a> {
1573 fn min_byte_range(&self) -> Range<usize> {
1574 0..self.seq_lookup_records_byte_range().end
1575 }
1576 fn min_table_bytes(&self) -> &'a [u8] {
1577 let range = self.min_byte_range();
1578 self.data.as_bytes().get(range).unwrap_or_default()
1579 }
1580}
1581
1582impl ReadArgs for SequenceRule<'_> {
1583 type Args = ();
1584}
1585
1586impl<'a> FontRead<'a> for SequenceRule<'a> {
1587 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1588 #[allow(clippy::absurd_extreme_comparisons)]
1589 if data.len() < Self::MIN_SIZE {
1590 return Err(ReadError::OutOfBounds);
1591 }
1592 Ok(Self { data })
1593 }
1594}
1595
1596#[derive(Clone)]
1598pub struct SequenceRule<'a> {
1599 data: FontData<'a>,
1600}
1601
1602#[allow(clippy::needless_lifetimes)]
1603impl<'a> SequenceRule<'a> {
1604 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1605 basic_table_impls!(impl_the_methods);
1606
1607 pub fn glyph_count(&self) -> u16 {
1609 let range = self.glyph_count_byte_range();
1610 self.data.read_at(range.start).ok().unwrap()
1611 }
1612
1613 pub fn seq_lookup_count(&self) -> u16 {
1615 let range = self.seq_lookup_count_byte_range();
1616 self.data.read_at(range.start).ok().unwrap()
1617 }
1618
1619 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
1621 let range = self.input_sequence_byte_range();
1622 self.data.read_array(range).ok().unwrap_or_default()
1623 }
1624
1625 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
1627 let range = self.seq_lookup_records_byte_range();
1628 self.data.read_array(range).ok().unwrap_or_default()
1629 }
1630
1631 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1632 let start = 0;
1633 let end = start + u16::RAW_BYTE_LEN;
1634 start..end
1635 }
1636
1637 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
1638 let start = self.glyph_count_byte_range().end;
1639 let end = start + u16::RAW_BYTE_LEN;
1640 start..end
1641 }
1642
1643 pub fn input_sequence_byte_range(&self) -> Range<usize> {
1644 let glyph_count = self.glyph_count();
1645 let start = self.seq_lookup_count_byte_range().end;
1646 let end = start
1647 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1648 start..end
1649 }
1650
1651 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
1652 let seq_lookup_count = self.seq_lookup_count();
1653 let start = self.input_sequence_byte_range().end;
1654 let end = start
1655 + (transforms::to_usize(seq_lookup_count))
1656 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
1657 start..end
1658 }
1659}
1660
1661const _: () = assert!(FontData::default_data_long_enough(SequenceRule::MIN_SIZE));
1662
1663impl Default for SequenceRule<'_> {
1664 fn default() -> Self {
1665 Self {
1666 data: FontData::default_table_data(),
1667 }
1668 }
1669}
1670
1671impl Format<u16> for SequenceContextFormat2<'_> {
1672 const FORMAT: u16 = 2;
1673}
1674
1675impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
1676 fn min_byte_range(&self) -> Range<usize> {
1677 0..self.class_seq_rule_set_offsets_byte_range().end
1678 }
1679 fn min_table_bytes(&self) -> &'a [u8] {
1680 let range = self.min_byte_range();
1681 self.data.as_bytes().get(range).unwrap_or_default()
1682 }
1683}
1684
1685impl ReadArgs for SequenceContextFormat2<'_> {
1686 type Args = ();
1687}
1688
1689impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
1690 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1691 #[allow(clippy::absurd_extreme_comparisons)]
1692 if data.len() < Self::MIN_SIZE {
1693 return Err(ReadError::OutOfBounds);
1694 }
1695 Ok(Self { data })
1696 }
1697}
1698
1699#[derive(Clone)]
1701pub struct SequenceContextFormat2<'a> {
1702 data: FontData<'a>,
1703}
1704
1705#[allow(clippy::needless_lifetimes)]
1706impl<'a> SequenceContextFormat2<'a> {
1707 pub const MIN_SIZE: usize =
1708 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1709 basic_table_impls!(impl_the_methods);
1710
1711 pub fn format(&self) -> u16 {
1713 let range = self.format_byte_range();
1714 self.data.read_at(range.start).ok().unwrap()
1715 }
1716
1717 pub fn coverage_offset(&self) -> Offset16 {
1720 let range = self.coverage_offset_byte_range();
1721 self.data.read_at(range.start).ok().unwrap()
1722 }
1723
1724 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1726 let data = self.data;
1727 self.coverage_offset().resolve(data)
1728 }
1729
1730 pub fn class_def_offset(&self) -> Offset16 {
1733 let range = self.class_def_offset_byte_range();
1734 self.data.read_at(range.start).ok().unwrap()
1735 }
1736
1737 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
1739 let data = self.data;
1740 self.class_def_offset().resolve(data)
1741 }
1742
1743 pub fn class_seq_rule_set_count(&self) -> u16 {
1745 let range = self.class_seq_rule_set_count_byte_range();
1746 self.data.read_at(range.start).ok().unwrap()
1747 }
1748
1749 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1752 let range = self.class_seq_rule_set_offsets_byte_range();
1753 self.data.read_array(range).ok().unwrap_or_default()
1754 }
1755
1756 pub fn class_seq_rule_sets(
1758 &self,
1759 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
1760 let data = self.data;
1761 let offsets = self.class_seq_rule_set_offsets();
1762 ArrayOfNullableOffsets::new(offsets, data, ())
1763 }
1764
1765 pub fn format_byte_range(&self) -> Range<usize> {
1766 let start = 0;
1767 let end = start + u16::RAW_BYTE_LEN;
1768 start..end
1769 }
1770
1771 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1772 let start = self.format_byte_range().end;
1773 let end = start + Offset16::RAW_BYTE_LEN;
1774 start..end
1775 }
1776
1777 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
1778 let start = self.coverage_offset_byte_range().end;
1779 let end = start + Offset16::RAW_BYTE_LEN;
1780 start..end
1781 }
1782
1783 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
1784 let start = self.class_def_offset_byte_range().end;
1785 let end = start + u16::RAW_BYTE_LEN;
1786 start..end
1787 }
1788
1789 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1790 let class_seq_rule_set_count = self.class_seq_rule_set_count();
1791 let start = self.class_seq_rule_set_count_byte_range().end;
1792 let end = start
1793 + (transforms::to_usize(class_seq_rule_set_count))
1794 .saturating_mul(Offset16::RAW_BYTE_LEN);
1795 start..end
1796 }
1797}
1798
1799impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
1800 fn min_byte_range(&self) -> Range<usize> {
1801 0..self.class_seq_rule_offsets_byte_range().end
1802 }
1803 fn min_table_bytes(&self) -> &'a [u8] {
1804 let range = self.min_byte_range();
1805 self.data.as_bytes().get(range).unwrap_or_default()
1806 }
1807}
1808
1809impl ReadArgs for ClassSequenceRuleSet<'_> {
1810 type Args = ();
1811}
1812
1813impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
1814 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1815 #[allow(clippy::absurd_extreme_comparisons)]
1816 if data.len() < Self::MIN_SIZE {
1817 return Err(ReadError::OutOfBounds);
1818 }
1819 Ok(Self { data })
1820 }
1821}
1822
1823#[derive(Clone)]
1825pub struct ClassSequenceRuleSet<'a> {
1826 data: FontData<'a>,
1827}
1828
1829#[allow(clippy::needless_lifetimes)]
1830impl<'a> ClassSequenceRuleSet<'a> {
1831 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1832 basic_table_impls!(impl_the_methods);
1833
1834 pub fn class_seq_rule_count(&self) -> u16 {
1836 let range = self.class_seq_rule_count_byte_range();
1837 self.data.read_at(range.start).ok().unwrap()
1838 }
1839
1840 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
1843 let range = self.class_seq_rule_offsets_byte_range();
1844 self.data.read_array(range).ok().unwrap_or_default()
1845 }
1846
1847 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
1849 let data = self.data;
1850 let offsets = self.class_seq_rule_offsets();
1851 ArrayOfOffsets::new(offsets, data, ())
1852 }
1853
1854 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
1855 let start = 0;
1856 let end = start + u16::RAW_BYTE_LEN;
1857 start..end
1858 }
1859
1860 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
1861 let class_seq_rule_count = self.class_seq_rule_count();
1862 let start = self.class_seq_rule_count_byte_range().end;
1863 let end = start
1864 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1865 start..end
1866 }
1867}
1868
1869const _: () = assert!(FontData::default_data_long_enough(
1870 ClassSequenceRuleSet::MIN_SIZE
1871));
1872
1873impl Default for ClassSequenceRuleSet<'_> {
1874 fn default() -> Self {
1875 Self {
1876 data: FontData::default_table_data(),
1877 }
1878 }
1879}
1880
1881impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
1882 fn min_byte_range(&self) -> Range<usize> {
1883 0..self.seq_lookup_records_byte_range().end
1884 }
1885 fn min_table_bytes(&self) -> &'a [u8] {
1886 let range = self.min_byte_range();
1887 self.data.as_bytes().get(range).unwrap_or_default()
1888 }
1889}
1890
1891impl ReadArgs for ClassSequenceRule<'_> {
1892 type Args = ();
1893}
1894
1895impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
1896 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1897 #[allow(clippy::absurd_extreme_comparisons)]
1898 if data.len() < Self::MIN_SIZE {
1899 return Err(ReadError::OutOfBounds);
1900 }
1901 Ok(Self { data })
1902 }
1903}
1904
1905#[derive(Clone)]
1907pub struct ClassSequenceRule<'a> {
1908 data: FontData<'a>,
1909}
1910
1911#[allow(clippy::needless_lifetimes)]
1912impl<'a> ClassSequenceRule<'a> {
1913 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1914 basic_table_impls!(impl_the_methods);
1915
1916 pub fn glyph_count(&self) -> u16 {
1918 let range = self.glyph_count_byte_range();
1919 self.data.read_at(range.start).ok().unwrap()
1920 }
1921
1922 pub fn seq_lookup_count(&self) -> u16 {
1924 let range = self.seq_lookup_count_byte_range();
1925 self.data.read_at(range.start).ok().unwrap()
1926 }
1927
1928 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
1931 let range = self.input_sequence_byte_range();
1932 self.data.read_array(range).ok().unwrap_or_default()
1933 }
1934
1935 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
1937 let range = self.seq_lookup_records_byte_range();
1938 self.data.read_array(range).ok().unwrap_or_default()
1939 }
1940
1941 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1942 let start = 0;
1943 let end = start + u16::RAW_BYTE_LEN;
1944 start..end
1945 }
1946
1947 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
1948 let start = self.glyph_count_byte_range().end;
1949 let end = start + u16::RAW_BYTE_LEN;
1950 start..end
1951 }
1952
1953 pub fn input_sequence_byte_range(&self) -> Range<usize> {
1954 let glyph_count = self.glyph_count();
1955 let start = self.seq_lookup_count_byte_range().end;
1956 let end =
1957 start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
1958 start..end
1959 }
1960
1961 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
1962 let seq_lookup_count = self.seq_lookup_count();
1963 let start = self.input_sequence_byte_range().end;
1964 let end = start
1965 + (transforms::to_usize(seq_lookup_count))
1966 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
1967 start..end
1968 }
1969}
1970
1971const _: () = assert!(FontData::default_data_long_enough(
1972 ClassSequenceRule::MIN_SIZE
1973));
1974
1975impl Default for ClassSequenceRule<'_> {
1976 fn default() -> Self {
1977 Self {
1978 data: FontData::default_table_data(),
1979 }
1980 }
1981}
1982
1983impl Format<u16> for SequenceContextFormat3<'_> {
1984 const FORMAT: u16 = 3;
1985}
1986
1987impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
1988 fn min_byte_range(&self) -> Range<usize> {
1989 0..self.seq_lookup_records_byte_range().end
1990 }
1991 fn min_table_bytes(&self) -> &'a [u8] {
1992 let range = self.min_byte_range();
1993 self.data.as_bytes().get(range).unwrap_or_default()
1994 }
1995}
1996
1997impl ReadArgs for SequenceContextFormat3<'_> {
1998 type Args = ();
1999}
2000
2001impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2002 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2003 #[allow(clippy::absurd_extreme_comparisons)]
2004 if data.len() < Self::MIN_SIZE {
2005 return Err(ReadError::OutOfBounds);
2006 }
2007 Ok(Self { data })
2008 }
2009}
2010
2011#[derive(Clone)]
2013pub struct SequenceContextFormat3<'a> {
2014 data: FontData<'a>,
2015}
2016
2017#[allow(clippy::needless_lifetimes)]
2018impl<'a> SequenceContextFormat3<'a> {
2019 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2020 basic_table_impls!(impl_the_methods);
2021
2022 pub fn format(&self) -> u16 {
2024 let range = self.format_byte_range();
2025 self.data.read_at(range.start).ok().unwrap()
2026 }
2027
2028 pub fn glyph_count(&self) -> u16 {
2030 let range = self.glyph_count_byte_range();
2031 self.data.read_at(range.start).ok().unwrap()
2032 }
2033
2034 pub fn seq_lookup_count(&self) -> u16 {
2036 let range = self.seq_lookup_count_byte_range();
2037 self.data.read_at(range.start).ok().unwrap()
2038 }
2039
2040 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2043 let range = self.coverage_offsets_byte_range();
2044 self.data.read_array(range).ok().unwrap_or_default()
2045 }
2046
2047 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2049 let data = self.data;
2050 let offsets = self.coverage_offsets();
2051 ArrayOfOffsets::new(offsets, data, ())
2052 }
2053
2054 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2056 let range = self.seq_lookup_records_byte_range();
2057 self.data.read_array(range).ok().unwrap_or_default()
2058 }
2059
2060 pub fn format_byte_range(&self) -> Range<usize> {
2061 let start = 0;
2062 let end = start + u16::RAW_BYTE_LEN;
2063 start..end
2064 }
2065
2066 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2067 let start = self.format_byte_range().end;
2068 let end = start + u16::RAW_BYTE_LEN;
2069 start..end
2070 }
2071
2072 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2073 let start = self.glyph_count_byte_range().end;
2074 let end = start + u16::RAW_BYTE_LEN;
2075 start..end
2076 }
2077
2078 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2079 let glyph_count = self.glyph_count();
2080 let start = self.seq_lookup_count_byte_range().end;
2081 let end =
2082 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2083 start..end
2084 }
2085
2086 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2087 let seq_lookup_count = self.seq_lookup_count();
2088 let start = self.coverage_offsets_byte_range().end;
2089 let end = start
2090 + (transforms::to_usize(seq_lookup_count))
2091 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2092 start..end
2093 }
2094}
2095
2096#[derive(Clone)]
2097pub enum SequenceContext<'a> {
2098 Format1(SequenceContextFormat1<'a>),
2099 Format2(SequenceContextFormat2<'a>),
2100 Format3(SequenceContextFormat3<'a>),
2101}
2102
2103impl Default for SequenceContext<'_> {
2104 fn default() -> Self {
2105 Self::Format1(Default::default())
2106 }
2107}
2108
2109impl<'a> SequenceContext<'a> {
2110 pub fn offset_data(&self) -> FontData<'a> {
2112 match self {
2113 Self::Format1(item) => item.offset_data(),
2114 Self::Format2(item) => item.offset_data(),
2115 Self::Format3(item) => item.offset_data(),
2116 }
2117 }
2118
2119 pub fn format(&self) -> u16 {
2121 match self {
2122 Self::Format1(item) => item.format(),
2123 Self::Format2(item) => item.format(),
2124 Self::Format3(item) => item.format(),
2125 }
2126 }
2127}
2128
2129impl ReadArgs for SequenceContext<'_> {
2130 type Args = ();
2131}
2132
2133impl<'a> FontRead<'a> for SequenceContext<'a> {
2134 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2135 let format: u16 = data.read_at(0usize)?;
2136 match format {
2137 SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2138 SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2139 SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2140 other => Err(ReadError::InvalidFormat(other.into())),
2141 }
2142 }
2143}
2144
2145impl<'a> MinByteRange<'a> for SequenceContext<'a> {
2146 fn min_byte_range(&self) -> Range<usize> {
2147 match self {
2148 Self::Format1(item) => item.min_byte_range(),
2149 Self::Format2(item) => item.min_byte_range(),
2150 Self::Format3(item) => item.min_byte_range(),
2151 }
2152 }
2153 fn min_table_bytes(&self) -> &'a [u8] {
2154 match self {
2155 Self::Format1(item) => item.min_table_bytes(),
2156 Self::Format2(item) => item.min_table_bytes(),
2157 Self::Format3(item) => item.min_table_bytes(),
2158 }
2159 }
2160}
2161
2162impl Format<u16> for ChainedSequenceContextFormat1<'_> {
2163 const FORMAT: u16 = 1;
2164}
2165
2166impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
2167 fn min_byte_range(&self) -> Range<usize> {
2168 0..self.chained_seq_rule_set_offsets_byte_range().end
2169 }
2170 fn min_table_bytes(&self) -> &'a [u8] {
2171 let range = self.min_byte_range();
2172 self.data.as_bytes().get(range).unwrap_or_default()
2173 }
2174}
2175
2176impl ReadArgs for ChainedSequenceContextFormat1<'_> {
2177 type Args = ();
2178}
2179
2180impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2181 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2182 #[allow(clippy::absurd_extreme_comparisons)]
2183 if data.len() < Self::MIN_SIZE {
2184 return Err(ReadError::OutOfBounds);
2185 }
2186 Ok(Self { data })
2187 }
2188}
2189
2190#[derive(Clone)]
2192pub struct ChainedSequenceContextFormat1<'a> {
2193 data: FontData<'a>,
2194}
2195
2196#[allow(clippy::needless_lifetimes)]
2197impl<'a> ChainedSequenceContextFormat1<'a> {
2198 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2199 basic_table_impls!(impl_the_methods);
2200
2201 pub fn format(&self) -> u16 {
2203 let range = self.format_byte_range();
2204 self.data.read_at(range.start).ok().unwrap()
2205 }
2206
2207 pub fn coverage_offset(&self) -> Offset16 {
2210 let range = self.coverage_offset_byte_range();
2211 self.data.read_at(range.start).ok().unwrap()
2212 }
2213
2214 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2216 let data = self.data;
2217 self.coverage_offset().resolve(data)
2218 }
2219
2220 pub fn chained_seq_rule_set_count(&self) -> u16 {
2222 let range = self.chained_seq_rule_set_count_byte_range();
2223 self.data.read_at(range.start).ok().unwrap()
2224 }
2225
2226 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2229 let range = self.chained_seq_rule_set_offsets_byte_range();
2230 self.data.read_array(range).ok().unwrap_or_default()
2231 }
2232
2233 pub fn chained_seq_rule_sets(
2235 &self,
2236 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2237 let data = self.data;
2238 let offsets = self.chained_seq_rule_set_offsets();
2239 ArrayOfNullableOffsets::new(offsets, data, ())
2240 }
2241
2242 pub fn format_byte_range(&self) -> Range<usize> {
2243 let start = 0;
2244 let end = start + u16::RAW_BYTE_LEN;
2245 start..end
2246 }
2247
2248 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2249 let start = self.format_byte_range().end;
2250 let end = start + Offset16::RAW_BYTE_LEN;
2251 start..end
2252 }
2253
2254 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2255 let start = self.coverage_offset_byte_range().end;
2256 let end = start + u16::RAW_BYTE_LEN;
2257 start..end
2258 }
2259
2260 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2261 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
2262 let start = self.chained_seq_rule_set_count_byte_range().end;
2263 let end = start
2264 + (transforms::to_usize(chained_seq_rule_set_count))
2265 .saturating_mul(Offset16::RAW_BYTE_LEN);
2266 start..end
2267 }
2268}
2269
2270const _: () = assert!(FontData::default_data_long_enough(
2271 ChainedSequenceContextFormat1::MIN_SIZE
2272));
2273
2274impl Default for ChainedSequenceContextFormat1<'_> {
2275 fn default() -> Self {
2276 Self {
2277 data: FontData::default_format_1_u16_table_data(),
2278 }
2279 }
2280}
2281
2282impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
2283 fn min_byte_range(&self) -> Range<usize> {
2284 0..self.chained_seq_rule_offsets_byte_range().end
2285 }
2286 fn min_table_bytes(&self) -> &'a [u8] {
2287 let range = self.min_byte_range();
2288 self.data.as_bytes().get(range).unwrap_or_default()
2289 }
2290}
2291
2292impl ReadArgs for ChainedSequenceRuleSet<'_> {
2293 type Args = ();
2294}
2295
2296impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
2297 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2298 #[allow(clippy::absurd_extreme_comparisons)]
2299 if data.len() < Self::MIN_SIZE {
2300 return Err(ReadError::OutOfBounds);
2301 }
2302 Ok(Self { data })
2303 }
2304}
2305
2306#[derive(Clone)]
2308pub struct ChainedSequenceRuleSet<'a> {
2309 data: FontData<'a>,
2310}
2311
2312#[allow(clippy::needless_lifetimes)]
2313impl<'a> ChainedSequenceRuleSet<'a> {
2314 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2315 basic_table_impls!(impl_the_methods);
2316
2317 pub fn chained_seq_rule_count(&self) -> u16 {
2319 let range = self.chained_seq_rule_count_byte_range();
2320 self.data.read_at(range.start).ok().unwrap()
2321 }
2322
2323 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2326 let range = self.chained_seq_rule_offsets_byte_range();
2327 self.data.read_array(range).ok().unwrap_or_default()
2328 }
2329
2330 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
2332 let data = self.data;
2333 let offsets = self.chained_seq_rule_offsets();
2334 ArrayOfOffsets::new(offsets, data, ())
2335 }
2336
2337 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
2338 let start = 0;
2339 let end = start + u16::RAW_BYTE_LEN;
2340 start..end
2341 }
2342
2343 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2344 let chained_seq_rule_count = self.chained_seq_rule_count();
2345 let start = self.chained_seq_rule_count_byte_range().end;
2346 let end = start
2347 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2348 start..end
2349 }
2350}
2351
2352const _: () = assert!(FontData::default_data_long_enough(
2353 ChainedSequenceRuleSet::MIN_SIZE
2354));
2355
2356impl Default for ChainedSequenceRuleSet<'_> {
2357 fn default() -> Self {
2358 Self {
2359 data: FontData::default_table_data(),
2360 }
2361 }
2362}
2363
2364impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
2365 fn min_byte_range(&self) -> Range<usize> {
2366 0..self.seq_lookup_records_byte_range().end
2367 }
2368 fn min_table_bytes(&self) -> &'a [u8] {
2369 let range = self.min_byte_range();
2370 self.data.as_bytes().get(range).unwrap_or_default()
2371 }
2372}
2373
2374impl ReadArgs for ChainedSequenceRule<'_> {
2375 type Args = ();
2376}
2377
2378impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
2379 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2380 #[allow(clippy::absurd_extreme_comparisons)]
2381 if data.len() < Self::MIN_SIZE {
2382 return Err(ReadError::OutOfBounds);
2383 }
2384 Ok(Self { data })
2385 }
2386}
2387
2388#[derive(Clone)]
2390pub struct ChainedSequenceRule<'a> {
2391 data: FontData<'a>,
2392}
2393
2394#[allow(clippy::needless_lifetimes)]
2395impl<'a> ChainedSequenceRule<'a> {
2396 pub const MIN_SIZE: usize =
2397 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2398 basic_table_impls!(impl_the_methods);
2399
2400 pub fn backtrack_glyph_count(&self) -> u16 {
2402 let range = self.backtrack_glyph_count_byte_range();
2403 self.data.read_at(range.start).ok().unwrap()
2404 }
2405
2406 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2408 let range = self.backtrack_sequence_byte_range();
2409 self.data.read_array(range).ok().unwrap_or_default()
2410 }
2411
2412 pub fn input_glyph_count(&self) -> u16 {
2414 let range = self.input_glyph_count_byte_range();
2415 self.data.read_at(range.start).ok().unwrap_or_default()
2416 }
2417
2418 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2420 let range = self.input_sequence_byte_range();
2421 self.data.read_array(range).ok().unwrap_or_default()
2422 }
2423
2424 pub fn lookahead_glyph_count(&self) -> u16 {
2426 let range = self.lookahead_glyph_count_byte_range();
2427 self.data.read_at(range.start).ok().unwrap_or_default()
2428 }
2429
2430 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2432 let range = self.lookahead_sequence_byte_range();
2433 self.data.read_array(range).ok().unwrap_or_default()
2434 }
2435
2436 pub fn seq_lookup_count(&self) -> u16 {
2438 let range = self.seq_lookup_count_byte_range();
2439 self.data.read_at(range.start).ok().unwrap_or_default()
2440 }
2441
2442 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2444 let range = self.seq_lookup_records_byte_range();
2445 self.data.read_array(range).ok().unwrap_or_default()
2446 }
2447
2448 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
2449 let start = 0;
2450 let end = start + u16::RAW_BYTE_LEN;
2451 start..end
2452 }
2453
2454 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
2455 let backtrack_glyph_count = self.backtrack_glyph_count();
2456 let start = self.backtrack_glyph_count_byte_range().end;
2457 let end = start
2458 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2459 start..end
2460 }
2461
2462 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
2463 let start = self.backtrack_sequence_byte_range().end;
2464 let end = start + u16::RAW_BYTE_LEN;
2465 start..end
2466 }
2467
2468 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2469 let input_glyph_count = self.input_glyph_count();
2470 let start = self.input_glyph_count_byte_range().end;
2471 let end = start
2472 + (transforms::subtract(input_glyph_count, 1_usize))
2473 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
2474 start..end
2475 }
2476
2477 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
2478 let start = self.input_sequence_byte_range().end;
2479 let end = start + u16::RAW_BYTE_LEN;
2480 start..end
2481 }
2482
2483 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
2484 let lookahead_glyph_count = self.lookahead_glyph_count();
2485 let start = self.lookahead_glyph_count_byte_range().end;
2486 let end = start
2487 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2488 start..end
2489 }
2490
2491 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2492 let start = self.lookahead_sequence_byte_range().end;
2493 let end = start + u16::RAW_BYTE_LEN;
2494 start..end
2495 }
2496
2497 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2498 let seq_lookup_count = self.seq_lookup_count();
2499 let start = self.seq_lookup_count_byte_range().end;
2500 let end = start
2501 + (transforms::to_usize(seq_lookup_count))
2502 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2503 start..end
2504 }
2505}
2506
2507const _: () = assert!(FontData::default_data_long_enough(
2508 ChainedSequenceRule::MIN_SIZE
2509));
2510
2511impl Default for ChainedSequenceRule<'_> {
2512 fn default() -> Self {
2513 Self {
2514 data: FontData::default_table_data(),
2515 }
2516 }
2517}
2518
2519impl Format<u16> for ChainedSequenceContextFormat2<'_> {
2520 const FORMAT: u16 = 2;
2521}
2522
2523impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
2524 fn min_byte_range(&self) -> Range<usize> {
2525 0..self.chained_class_seq_rule_set_offsets_byte_range().end
2526 }
2527 fn min_table_bytes(&self) -> &'a [u8] {
2528 let range = self.min_byte_range();
2529 self.data.as_bytes().get(range).unwrap_or_default()
2530 }
2531}
2532
2533impl ReadArgs for ChainedSequenceContextFormat2<'_> {
2534 type Args = ();
2535}
2536
2537impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
2538 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2539 #[allow(clippy::absurd_extreme_comparisons)]
2540 if data.len() < Self::MIN_SIZE {
2541 return Err(ReadError::OutOfBounds);
2542 }
2543 Ok(Self { data })
2544 }
2545}
2546
2547#[derive(Clone)]
2549pub struct ChainedSequenceContextFormat2<'a> {
2550 data: FontData<'a>,
2551}
2552
2553#[allow(clippy::needless_lifetimes)]
2554impl<'a> ChainedSequenceContextFormat2<'a> {
2555 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2556 + Offset16::RAW_BYTE_LEN
2557 + Offset16::RAW_BYTE_LEN
2558 + Offset16::RAW_BYTE_LEN
2559 + Offset16::RAW_BYTE_LEN
2560 + u16::RAW_BYTE_LEN);
2561 basic_table_impls!(impl_the_methods);
2562
2563 pub fn format(&self) -> u16 {
2565 let range = self.format_byte_range();
2566 self.data.read_at(range.start).ok().unwrap()
2567 }
2568
2569 pub fn coverage_offset(&self) -> Offset16 {
2572 let range = self.coverage_offset_byte_range();
2573 self.data.read_at(range.start).ok().unwrap()
2574 }
2575
2576 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2578 let data = self.data;
2579 self.coverage_offset().resolve(data)
2580 }
2581
2582 pub fn backtrack_class_def_offset(&self) -> Offset16 {
2585 let range = self.backtrack_class_def_offset_byte_range();
2586 self.data.read_at(range.start).ok().unwrap()
2587 }
2588
2589 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2591 let data = self.data;
2592 self.backtrack_class_def_offset().resolve(data)
2593 }
2594
2595 pub fn input_class_def_offset(&self) -> Offset16 {
2598 let range = self.input_class_def_offset_byte_range();
2599 self.data.read_at(range.start).ok().unwrap()
2600 }
2601
2602 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2604 let data = self.data;
2605 self.input_class_def_offset().resolve(data)
2606 }
2607
2608 pub fn lookahead_class_def_offset(&self) -> Offset16 {
2611 let range = self.lookahead_class_def_offset_byte_range();
2612 self.data.read_at(range.start).ok().unwrap()
2613 }
2614
2615 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2617 let data = self.data;
2618 self.lookahead_class_def_offset().resolve(data)
2619 }
2620
2621 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
2623 let range = self.chained_class_seq_rule_set_count_byte_range();
2624 self.data.read_at(range.start).ok().unwrap()
2625 }
2626
2627 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2630 let range = self.chained_class_seq_rule_set_offsets_byte_range();
2631 self.data.read_array(range).ok().unwrap_or_default()
2632 }
2633
2634 pub fn chained_class_seq_rule_sets(
2636 &self,
2637 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
2638 let data = self.data;
2639 let offsets = self.chained_class_seq_rule_set_offsets();
2640 ArrayOfNullableOffsets::new(offsets, data, ())
2641 }
2642
2643 pub fn format_byte_range(&self) -> Range<usize> {
2644 let start = 0;
2645 let end = start + u16::RAW_BYTE_LEN;
2646 start..end
2647 }
2648
2649 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2650 let start = self.format_byte_range().end;
2651 let end = start + Offset16::RAW_BYTE_LEN;
2652 start..end
2653 }
2654
2655 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
2656 let start = self.coverage_offset_byte_range().end;
2657 let end = start + Offset16::RAW_BYTE_LEN;
2658 start..end
2659 }
2660
2661 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
2662 let start = self.backtrack_class_def_offset_byte_range().end;
2663 let end = start + Offset16::RAW_BYTE_LEN;
2664 start..end
2665 }
2666
2667 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
2668 let start = self.input_class_def_offset_byte_range().end;
2669 let end = start + Offset16::RAW_BYTE_LEN;
2670 start..end
2671 }
2672
2673 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2674 let start = self.lookahead_class_def_offset_byte_range().end;
2675 let end = start + u16::RAW_BYTE_LEN;
2676 start..end
2677 }
2678
2679 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2680 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
2681 let start = self.chained_class_seq_rule_set_count_byte_range().end;
2682 let end = start
2683 + (transforms::to_usize(chained_class_seq_rule_set_count))
2684 .saturating_mul(Offset16::RAW_BYTE_LEN);
2685 start..end
2686 }
2687}
2688
2689impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
2690 fn min_byte_range(&self) -> Range<usize> {
2691 0..self.chained_class_seq_rule_offsets_byte_range().end
2692 }
2693 fn min_table_bytes(&self) -> &'a [u8] {
2694 let range = self.min_byte_range();
2695 self.data.as_bytes().get(range).unwrap_or_default()
2696 }
2697}
2698
2699impl ReadArgs for ChainedClassSequenceRuleSet<'_> {
2700 type Args = ();
2701}
2702
2703impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
2704 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2705 #[allow(clippy::absurd_extreme_comparisons)]
2706 if data.len() < Self::MIN_SIZE {
2707 return Err(ReadError::OutOfBounds);
2708 }
2709 Ok(Self { data })
2710 }
2711}
2712
2713#[derive(Clone)]
2715pub struct ChainedClassSequenceRuleSet<'a> {
2716 data: FontData<'a>,
2717}
2718
2719#[allow(clippy::needless_lifetimes)]
2720impl<'a> ChainedClassSequenceRuleSet<'a> {
2721 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2722 basic_table_impls!(impl_the_methods);
2723
2724 pub fn chained_class_seq_rule_count(&self) -> u16 {
2726 let range = self.chained_class_seq_rule_count_byte_range();
2727 self.data.read_at(range.start).ok().unwrap()
2728 }
2729
2730 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2733 let range = self.chained_class_seq_rule_offsets_byte_range();
2734 self.data.read_array(range).ok().unwrap_or_default()
2735 }
2736
2737 pub fn chained_class_seq_rules(
2739 &self,
2740 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
2741 let data = self.data;
2742 let offsets = self.chained_class_seq_rule_offsets();
2743 ArrayOfOffsets::new(offsets, data, ())
2744 }
2745
2746 pub fn chained_class_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_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2753 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
2754 let start = self.chained_class_seq_rule_count_byte_range().end;
2755 let end = start
2756 + (transforms::to_usize(chained_class_seq_rule_count))
2757 .saturating_mul(Offset16::RAW_BYTE_LEN);
2758 start..end
2759 }
2760}
2761
2762const _: () = assert!(FontData::default_data_long_enough(
2763 ChainedClassSequenceRuleSet::MIN_SIZE
2764));
2765
2766impl Default for ChainedClassSequenceRuleSet<'_> {
2767 fn default() -> Self {
2768 Self {
2769 data: FontData::default_table_data(),
2770 }
2771 }
2772}
2773
2774impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'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.data.as_bytes().get(range).unwrap_or_default()
2781 }
2782}
2783
2784impl ReadArgs for ChainedClassSequenceRule<'_> {
2785 type Args = ();
2786}
2787
2788impl<'a> FontRead<'a> for ChainedClassSequenceRule<'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 Ok(Self { data })
2795 }
2796}
2797
2798#[derive(Clone)]
2800pub struct ChainedClassSequenceRule<'a> {
2801 data: FontData<'a>,
2802}
2803
2804#[allow(clippy::needless_lifetimes)]
2805impl<'a> ChainedClassSequenceRule<'a> {
2806 pub const MIN_SIZE: usize =
2807 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2808 basic_table_impls!(impl_the_methods);
2809
2810 pub fn backtrack_glyph_count(&self) -> u16 {
2812 let range = self.backtrack_glyph_count_byte_range();
2813 self.data.read_at(range.start).ok().unwrap()
2814 }
2815
2816 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
2818 let range = self.backtrack_sequence_byte_range();
2819 self.data.read_array(range).ok().unwrap_or_default()
2820 }
2821
2822 pub fn input_glyph_count(&self) -> u16 {
2824 let range = self.input_glyph_count_byte_range();
2825 self.data.read_at(range.start).ok().unwrap_or_default()
2826 }
2827
2828 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2831 let range = self.input_sequence_byte_range();
2832 self.data.read_array(range).ok().unwrap_or_default()
2833 }
2834
2835 pub fn lookahead_glyph_count(&self) -> u16 {
2837 let range = self.lookahead_glyph_count_byte_range();
2838 self.data.read_at(range.start).ok().unwrap_or_default()
2839 }
2840
2841 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
2843 let range = self.lookahead_sequence_byte_range();
2844 self.data.read_array(range).ok().unwrap_or_default()
2845 }
2846
2847 pub fn seq_lookup_count(&self) -> u16 {
2849 let range = self.seq_lookup_count_byte_range();
2850 self.data.read_at(range.start).ok().unwrap_or_default()
2851 }
2852
2853 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2855 let range = self.seq_lookup_records_byte_range();
2856 self.data.read_array(range).ok().unwrap_or_default()
2857 }
2858
2859 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
2860 let start = 0;
2861 let end = start + u16::RAW_BYTE_LEN;
2862 start..end
2863 }
2864
2865 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
2866 let backtrack_glyph_count = self.backtrack_glyph_count();
2867 let start = self.backtrack_glyph_count_byte_range().end;
2868 let end =
2869 start + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
2870 start..end
2871 }
2872
2873 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
2874 let start = self.backtrack_sequence_byte_range().end;
2875 let end = start + u16::RAW_BYTE_LEN;
2876 start..end
2877 }
2878
2879 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2880 let input_glyph_count = self.input_glyph_count();
2881 let start = self.input_glyph_count_byte_range().end;
2882 let end = start
2883 + (transforms::subtract(input_glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
2884 start..end
2885 }
2886
2887 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
2888 let start = self.input_sequence_byte_range().end;
2889 let end = start + u16::RAW_BYTE_LEN;
2890 start..end
2891 }
2892
2893 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
2894 let lookahead_glyph_count = self.lookahead_glyph_count();
2895 let start = self.lookahead_glyph_count_byte_range().end;
2896 let end =
2897 start + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
2898 start..end
2899 }
2900
2901 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2902 let start = self.lookahead_sequence_byte_range().end;
2903 let end = start + u16::RAW_BYTE_LEN;
2904 start..end
2905 }
2906
2907 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2908 let seq_lookup_count = self.seq_lookup_count();
2909 let start = self.seq_lookup_count_byte_range().end;
2910 let end = start
2911 + (transforms::to_usize(seq_lookup_count))
2912 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2913 start..end
2914 }
2915}
2916
2917const _: () = assert!(FontData::default_data_long_enough(
2918 ChainedClassSequenceRule::MIN_SIZE
2919));
2920
2921impl Default for ChainedClassSequenceRule<'_> {
2922 fn default() -> Self {
2923 Self {
2924 data: FontData::default_table_data(),
2925 }
2926 }
2927}
2928
2929impl Format<u16> for ChainedSequenceContextFormat3<'_> {
2930 const FORMAT: u16 = 3;
2931}
2932
2933impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
2934 fn min_byte_range(&self) -> Range<usize> {
2935 0..self.seq_lookup_records_byte_range().end
2936 }
2937 fn min_table_bytes(&self) -> &'a [u8] {
2938 let range = self.min_byte_range();
2939 self.data.as_bytes().get(range).unwrap_or_default()
2940 }
2941}
2942
2943impl ReadArgs for ChainedSequenceContextFormat3<'_> {
2944 type Args = ();
2945}
2946
2947impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
2948 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2949 #[allow(clippy::absurd_extreme_comparisons)]
2950 if data.len() < Self::MIN_SIZE {
2951 return Err(ReadError::OutOfBounds);
2952 }
2953 Ok(Self { data })
2954 }
2955}
2956
2957#[derive(Clone)]
2959pub struct ChainedSequenceContextFormat3<'a> {
2960 data: FontData<'a>,
2961}
2962
2963#[allow(clippy::needless_lifetimes)]
2964impl<'a> ChainedSequenceContextFormat3<'a> {
2965 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2966 + u16::RAW_BYTE_LEN
2967 + u16::RAW_BYTE_LEN
2968 + u16::RAW_BYTE_LEN
2969 + u16::RAW_BYTE_LEN);
2970 basic_table_impls!(impl_the_methods);
2971
2972 pub fn format(&self) -> u16 {
2974 let range = self.format_byte_range();
2975 self.data.read_at(range.start).ok().unwrap()
2976 }
2977
2978 pub fn backtrack_glyph_count(&self) -> u16 {
2980 let range = self.backtrack_glyph_count_byte_range();
2981 self.data.read_at(range.start).ok().unwrap()
2982 }
2983
2984 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2986 let range = self.backtrack_coverage_offsets_byte_range();
2987 self.data.read_array(range).ok().unwrap_or_default()
2988 }
2989
2990 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2992 let data = self.data;
2993 let offsets = self.backtrack_coverage_offsets();
2994 ArrayOfOffsets::new(offsets, data, ())
2995 }
2996
2997 pub fn input_glyph_count(&self) -> u16 {
2999 let range = self.input_glyph_count_byte_range();
3000 self.data.read_at(range.start).ok().unwrap_or_default()
3001 }
3002
3003 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3005 let range = self.input_coverage_offsets_byte_range();
3006 self.data.read_array(range).ok().unwrap_or_default()
3007 }
3008
3009 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3011 let data = self.data;
3012 let offsets = self.input_coverage_offsets();
3013 ArrayOfOffsets::new(offsets, data, ())
3014 }
3015
3016 pub fn lookahead_glyph_count(&self) -> u16 {
3018 let range = self.lookahead_glyph_count_byte_range();
3019 self.data.read_at(range.start).ok().unwrap_or_default()
3020 }
3021
3022 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3024 let range = self.lookahead_coverage_offsets_byte_range();
3025 self.data.read_array(range).ok().unwrap_or_default()
3026 }
3027
3028 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3030 let data = self.data;
3031 let offsets = self.lookahead_coverage_offsets();
3032 ArrayOfOffsets::new(offsets, data, ())
3033 }
3034
3035 pub fn seq_lookup_count(&self) -> u16 {
3037 let range = self.seq_lookup_count_byte_range();
3038 self.data.read_at(range.start).ok().unwrap_or_default()
3039 }
3040
3041 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3043 let range = self.seq_lookup_records_byte_range();
3044 self.data.read_array(range).ok().unwrap_or_default()
3045 }
3046
3047 pub fn format_byte_range(&self) -> Range<usize> {
3048 let start = 0;
3049 let end = start + u16::RAW_BYTE_LEN;
3050 start..end
3051 }
3052
3053 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3054 let start = self.format_byte_range().end;
3055 let end = start + u16::RAW_BYTE_LEN;
3056 start..end
3057 }
3058
3059 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
3060 let backtrack_glyph_count = self.backtrack_glyph_count();
3061 let start = self.backtrack_glyph_count_byte_range().end;
3062 let end = start
3063 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3064 start..end
3065 }
3066
3067 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3068 let start = self.backtrack_coverage_offsets_byte_range().end;
3069 let end = start + u16::RAW_BYTE_LEN;
3070 start..end
3071 }
3072
3073 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
3074 let input_glyph_count = self.input_glyph_count();
3075 let start = self.input_glyph_count_byte_range().end;
3076 let end = start
3077 + (transforms::to_usize(input_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3078 start..end
3079 }
3080
3081 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3082 let start = self.input_coverage_offsets_byte_range().end;
3083 let end = start + u16::RAW_BYTE_LEN;
3084 start..end
3085 }
3086
3087 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
3088 let lookahead_glyph_count = self.lookahead_glyph_count();
3089 let start = self.lookahead_glyph_count_byte_range().end;
3090 let end = start
3091 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3092 start..end
3093 }
3094
3095 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3096 let start = self.lookahead_coverage_offsets_byte_range().end;
3097 let end = start + u16::RAW_BYTE_LEN;
3098 start..end
3099 }
3100
3101 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3102 let seq_lookup_count = self.seq_lookup_count();
3103 let start = self.seq_lookup_count_byte_range().end;
3104 let end = start
3105 + (transforms::to_usize(seq_lookup_count))
3106 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3107 start..end
3108 }
3109}
3110
3111#[derive(Clone)]
3112pub enum ChainedSequenceContext<'a> {
3113 Format1(ChainedSequenceContextFormat1<'a>),
3114 Format2(ChainedSequenceContextFormat2<'a>),
3115 Format3(ChainedSequenceContextFormat3<'a>),
3116}
3117
3118impl Default for ChainedSequenceContext<'_> {
3119 fn default() -> Self {
3120 Self::Format1(Default::default())
3121 }
3122}
3123
3124impl<'a> ChainedSequenceContext<'a> {
3125 pub fn offset_data(&self) -> FontData<'a> {
3127 match self {
3128 Self::Format1(item) => item.offset_data(),
3129 Self::Format2(item) => item.offset_data(),
3130 Self::Format3(item) => item.offset_data(),
3131 }
3132 }
3133
3134 pub fn format(&self) -> u16 {
3136 match self {
3137 Self::Format1(item) => item.format(),
3138 Self::Format2(item) => item.format(),
3139 Self::Format3(item) => item.format(),
3140 }
3141 }
3142}
3143
3144impl ReadArgs for ChainedSequenceContext<'_> {
3145 type Args = ();
3146}
3147
3148impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
3149 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3150 let format: u16 = data.read_at(0usize)?;
3151 match format {
3152 ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
3153 ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
3154 ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
3155 other => Err(ReadError::InvalidFormat(other.into())),
3156 }
3157 }
3158}
3159
3160impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
3161 fn min_byte_range(&self) -> Range<usize> {
3162 match self {
3163 Self::Format1(item) => item.min_byte_range(),
3164 Self::Format2(item) => item.min_byte_range(),
3165 Self::Format3(item) => item.min_byte_range(),
3166 }
3167 }
3168 fn min_table_bytes(&self) -> &'a [u8] {
3169 match self {
3170 Self::Format1(item) => item.min_table_bytes(),
3171 Self::Format2(item) => item.min_table_bytes(),
3172 Self::Format3(item) => item.min_table_bytes(),
3173 }
3174 }
3175}
3176
3177#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
3180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3181#[repr(u16)]
3182#[allow(clippy::manual_non_exhaustive)]
3183pub enum DeltaFormat {
3184 #[default]
3186 Local2BitDeltas = 0x0001,
3187 Local4BitDeltas = 0x0002,
3189 Local8BitDeltas = 0x0003,
3191 VariationIndex = 0x8000,
3193 #[doc(hidden)]
3194 Unknown,
3196}
3197
3198impl DeltaFormat {
3199 pub fn new(raw: u16) -> Self {
3203 match raw {
3204 0x0001 => Self::Local2BitDeltas,
3205 0x0002 => Self::Local4BitDeltas,
3206 0x0003 => Self::Local8BitDeltas,
3207 0x8000 => Self::VariationIndex,
3208 _ => Self::Unknown,
3209 }
3210 }
3211}
3212
3213impl font_types::Scalar for DeltaFormat {
3214 type Raw = <u16 as font_types::Scalar>::Raw;
3215 fn to_raw(self) -> Self::Raw {
3216 (self as u16).to_raw()
3217 }
3218 fn from_raw(raw: Self::Raw) -> Self {
3219 let t = <u16>::from_raw(raw);
3220 Self::new(t)
3221 }
3222}
3223
3224impl<'a> MinByteRange<'a> for Device<'a> {
3225 fn min_byte_range(&self) -> Range<usize> {
3226 0..self.delta_value_byte_range().end
3227 }
3228 fn min_table_bytes(&self) -> &'a [u8] {
3229 let range = self.min_byte_range();
3230 self.data.as_bytes().get(range).unwrap_or_default()
3231 }
3232}
3233
3234impl ReadArgs for Device<'_> {
3235 type Args = ();
3236}
3237
3238impl<'a> FontRead<'a> for Device<'a> {
3239 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3240 #[allow(clippy::absurd_extreme_comparisons)]
3241 if data.len() < Self::MIN_SIZE {
3242 return Err(ReadError::OutOfBounds);
3243 }
3244 Ok(Self { data })
3245 }
3246}
3247
3248#[derive(Clone)]
3250pub struct Device<'a> {
3251 data: FontData<'a>,
3252}
3253
3254#[allow(clippy::needless_lifetimes)]
3255impl<'a> Device<'a> {
3256 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3257 basic_table_impls!(impl_the_methods);
3258
3259 pub fn start_size(&self) -> u16 {
3261 let range = self.start_size_byte_range();
3262 self.data.read_at(range.start).ok().unwrap()
3263 }
3264
3265 pub fn end_size(&self) -> u16 {
3267 let range = self.end_size_byte_range();
3268 self.data.read_at(range.start).ok().unwrap()
3269 }
3270
3271 pub fn delta_format(&self) -> DeltaFormat {
3273 let range = self.delta_format_byte_range();
3274 self.data.read_at(range.start).ok().unwrap()
3275 }
3276
3277 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
3279 let range = self.delta_value_byte_range();
3280 self.data.read_array(range).ok().unwrap_or_default()
3281 }
3282
3283 pub fn start_size_byte_range(&self) -> Range<usize> {
3284 let start = 0;
3285 let end = start + u16::RAW_BYTE_LEN;
3286 start..end
3287 }
3288
3289 pub fn end_size_byte_range(&self) -> Range<usize> {
3290 let start = self.start_size_byte_range().end;
3291 let end = start + u16::RAW_BYTE_LEN;
3292 start..end
3293 }
3294
3295 pub fn delta_format_byte_range(&self) -> Range<usize> {
3296 let start = self.end_size_byte_range().end;
3297 let end = start + DeltaFormat::RAW_BYTE_LEN;
3298 start..end
3299 }
3300
3301 pub fn delta_value_byte_range(&self) -> Range<usize> {
3302 let delta_format = self.delta_format();
3303 let start_size = self.start_size();
3304 let end_size = self.end_size();
3305 let start = self.delta_format_byte_range().end;
3306 let end = start
3307 + (DeltaFormat::value_count(delta_format, start_size, end_size))
3308 .saturating_mul(u16::RAW_BYTE_LEN);
3309 start..end
3310 }
3311}
3312
3313const _: () = assert!(FontData::default_data_long_enough(Device::MIN_SIZE));
3314
3315impl Default for Device<'_> {
3316 fn default() -> Self {
3317 Self {
3318 data: FontData::default_table_data(),
3319 }
3320 }
3321}
3322
3323impl<'a> MinByteRange<'a> for VariationIndex<'a> {
3324 fn min_byte_range(&self) -> Range<usize> {
3325 0..self.delta_format_byte_range().end
3326 }
3327 fn min_table_bytes(&self) -> &'a [u8] {
3328 let range = self.min_byte_range();
3329 self.data.as_bytes().get(range).unwrap_or_default()
3330 }
3331}
3332
3333impl ReadArgs for VariationIndex<'_> {
3334 type Args = ();
3335}
3336
3337impl<'a> FontRead<'a> for VariationIndex<'a> {
3338 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3339 #[allow(clippy::absurd_extreme_comparisons)]
3340 if data.len() < Self::MIN_SIZE {
3341 return Err(ReadError::OutOfBounds);
3342 }
3343 Ok(Self { data })
3344 }
3345}
3346
3347#[derive(Clone)]
3349pub struct VariationIndex<'a> {
3350 data: FontData<'a>,
3351}
3352
3353#[allow(clippy::needless_lifetimes)]
3354impl<'a> VariationIndex<'a> {
3355 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
3356 basic_table_impls!(impl_the_methods);
3357
3358 pub fn delta_set_outer_index(&self) -> u16 {
3361 let range = self.delta_set_outer_index_byte_range();
3362 self.data.read_at(range.start).ok().unwrap()
3363 }
3364
3365 pub fn delta_set_inner_index(&self) -> u16 {
3368 let range = self.delta_set_inner_index_byte_range();
3369 self.data.read_at(range.start).ok().unwrap()
3370 }
3371
3372 pub fn delta_format(&self) -> DeltaFormat {
3374 let range = self.delta_format_byte_range();
3375 self.data.read_at(range.start).ok().unwrap()
3376 }
3377
3378 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
3379 let start = 0;
3380 let end = start + u16::RAW_BYTE_LEN;
3381 start..end
3382 }
3383
3384 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
3385 let start = self.delta_set_outer_index_byte_range().end;
3386 let end = start + u16::RAW_BYTE_LEN;
3387 start..end
3388 }
3389
3390 pub fn delta_format_byte_range(&self) -> Range<usize> {
3391 let start = self.delta_set_inner_index_byte_range().end;
3392 let end = start + DeltaFormat::RAW_BYTE_LEN;
3393 start..end
3394 }
3395}
3396
3397const _: () = assert!(FontData::default_data_long_enough(VariationIndex::MIN_SIZE));
3398
3399impl Default for VariationIndex<'_> {
3400 fn default() -> Self {
3401 Self {
3402 data: FontData::default_table_data(),
3403 }
3404 }
3405}
3406
3407#[derive(Clone)]
3409pub enum DeviceOrVariationIndex<'a> {
3410 Device(Device<'a>),
3411 VariationIndex(VariationIndex<'a>),
3412}
3413
3414impl Default for DeviceOrVariationIndex<'_> {
3415 fn default() -> Self {
3416 Self::Device(Default::default())
3417 }
3418}
3419
3420impl<'a> DeviceOrVariationIndex<'a> {
3421 pub fn offset_data(&self) -> FontData<'a> {
3423 match self {
3424 Self::Device(item) => item.offset_data(),
3425 Self::VariationIndex(item) => item.offset_data(),
3426 }
3427 }
3428}
3429
3430impl ReadArgs for DeviceOrVariationIndex<'_> {
3431 type Args = ();
3432}
3433
3434impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
3435 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3436 let format: DeltaFormat = data.read_at(4usize)?;
3437
3438 #[allow(clippy::redundant_guards)]
3439 match format {
3440 format if format != DeltaFormat::VariationIndex => {
3441 Ok(Self::Device(FontRead::read(data)?))
3442 }
3443 format if format == DeltaFormat::VariationIndex => {
3444 Ok(Self::VariationIndex(FontRead::read(data)?))
3445 }
3446 other => Err(ReadError::InvalidFormat(other.into())),
3447 }
3448 }
3449}
3450
3451impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
3452 fn min_byte_range(&self) -> Range<usize> {
3453 match self {
3454 Self::Device(item) => item.min_byte_range(),
3455 Self::VariationIndex(item) => item.min_byte_range(),
3456 }
3457 }
3458 fn min_table_bytes(&self) -> &'a [u8] {
3459 match self {
3460 Self::Device(item) => item.min_table_bytes(),
3461 Self::VariationIndex(item) => item.min_table_bytes(),
3462 }
3463 }
3464}
3465
3466impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
3467 fn min_byte_range(&self) -> Range<usize> {
3468 0..self.feature_variation_records_byte_range().end
3469 }
3470 fn min_table_bytes(&self) -> &'a [u8] {
3471 let range = self.min_byte_range();
3472 self.data.as_bytes().get(range).unwrap_or_default()
3473 }
3474}
3475
3476impl ReadArgs for FeatureVariations<'_> {
3477 type Args = ();
3478}
3479
3480impl<'a> FontRead<'a> for FeatureVariations<'a> {
3481 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3482 #[allow(clippy::absurd_extreme_comparisons)]
3483 if data.len() < Self::MIN_SIZE {
3484 return Err(ReadError::OutOfBounds);
3485 }
3486 Ok(Self { data })
3487 }
3488}
3489
3490#[derive(Clone)]
3492pub struct FeatureVariations<'a> {
3493 data: FontData<'a>,
3494}
3495
3496#[allow(clippy::needless_lifetimes)]
3497impl<'a> FeatureVariations<'a> {
3498 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
3499 basic_table_impls!(impl_the_methods);
3500
3501 pub fn version(&self) -> MajorMinor {
3502 let range = self.version_byte_range();
3503 self.data.read_at(range.start).ok().unwrap()
3504 }
3505
3506 pub fn feature_variation_record_count(&self) -> u32 {
3508 let range = self.feature_variation_record_count_byte_range();
3509 self.data.read_at(range.start).ok().unwrap()
3510 }
3511
3512 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
3514 let range = self.feature_variation_records_byte_range();
3515 self.data.read_array(range).ok().unwrap_or_default()
3516 }
3517
3518 pub fn version_byte_range(&self) -> Range<usize> {
3519 let start = 0;
3520 let end = start + MajorMinor::RAW_BYTE_LEN;
3521 start..end
3522 }
3523
3524 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
3525 let start = self.version_byte_range().end;
3526 let end = start + u32::RAW_BYTE_LEN;
3527 start..end
3528 }
3529
3530 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
3531 let feature_variation_record_count = self.feature_variation_record_count();
3532 let start = self.feature_variation_record_count_byte_range().end;
3533 let end = start
3534 + (transforms::to_usize(feature_variation_record_count))
3535 .saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN);
3536 start..end
3537 }
3538}
3539
3540const _: () = assert!(FontData::default_data_long_enough(
3541 FeatureVariations::MIN_SIZE
3542));
3543
3544impl Default for FeatureVariations<'_> {
3545 fn default() -> Self {
3546 Self {
3547 data: FontData::default_table_data(),
3548 }
3549 }
3550}
3551
3552#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
3554#[repr(C)]
3555#[repr(packed)]
3556pub struct FeatureVariationRecord {
3557 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
3560 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
3563}
3564
3565impl FeatureVariationRecord {
3566 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
3569 self.condition_set_offset.get()
3570 }
3571
3572 pub fn condition_set<'a>(
3578 &self,
3579 data: FontData<'a>,
3580 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
3581 self.condition_set_offset().resolve(data)
3582 }
3583
3584 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
3587 self.feature_table_substitution_offset.get()
3588 }
3589
3590 pub fn feature_table_substitution<'a>(
3596 &self,
3597 data: FontData<'a>,
3598 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
3599 self.feature_table_substitution_offset().resolve(data)
3600 }
3601}
3602
3603impl FixedSize for FeatureVariationRecord {
3604 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
3605}
3606
3607impl<'a> MinByteRange<'a> for ConditionSet<'a> {
3608 fn min_byte_range(&self) -> Range<usize> {
3609 0..self.condition_offsets_byte_range().end
3610 }
3611 fn min_table_bytes(&self) -> &'a [u8] {
3612 let range = self.min_byte_range();
3613 self.data.as_bytes().get(range).unwrap_or_default()
3614 }
3615}
3616
3617impl ReadArgs for ConditionSet<'_> {
3618 type Args = ();
3619}
3620
3621impl<'a> FontRead<'a> for ConditionSet<'a> {
3622 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3623 #[allow(clippy::absurd_extreme_comparisons)]
3624 if data.len() < Self::MIN_SIZE {
3625 return Err(ReadError::OutOfBounds);
3626 }
3627 Ok(Self { data })
3628 }
3629}
3630
3631#[derive(Clone)]
3633pub struct ConditionSet<'a> {
3634 data: FontData<'a>,
3635}
3636
3637#[allow(clippy::needless_lifetimes)]
3638impl<'a> ConditionSet<'a> {
3639 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3640 basic_table_impls!(impl_the_methods);
3641
3642 pub fn condition_count(&self) -> u16 {
3644 let range = self.condition_count_byte_range();
3645 self.data.read_at(range.start).ok().unwrap()
3646 }
3647
3648 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
3651 let range = self.condition_offsets_byte_range();
3652 self.data.read_array(range).ok().unwrap_or_default()
3653 }
3654
3655 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
3657 let data = self.data;
3658 let offsets = self.condition_offsets();
3659 ArrayOfOffsets::new(offsets, data, ())
3660 }
3661
3662 pub fn condition_count_byte_range(&self) -> Range<usize> {
3663 let start = 0;
3664 let end = start + u16::RAW_BYTE_LEN;
3665 start..end
3666 }
3667
3668 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
3669 let condition_count = self.condition_count();
3670 let start = self.condition_count_byte_range().end;
3671 let end =
3672 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
3673 start..end
3674 }
3675}
3676
3677const _: () = assert!(FontData::default_data_long_enough(ConditionSet::MIN_SIZE));
3678
3679impl Default for ConditionSet<'_> {
3680 fn default() -> Self {
3681 Self {
3682 data: FontData::default_table_data(),
3683 }
3684 }
3685}
3686
3687#[derive(Clone)]
3692pub enum Condition<'a> {
3693 Format1AxisRange(ConditionFormat1<'a>),
3694 Format2VariableValue(ConditionFormat2<'a>),
3695 Format3And(ConditionFormat3<'a>),
3696 Format4Or(ConditionFormat4<'a>),
3697 Format5Negate(ConditionFormat5<'a>),
3698}
3699
3700impl Default for Condition<'_> {
3701 fn default() -> Self {
3702 Self::Format1AxisRange(Default::default())
3703 }
3704}
3705
3706impl<'a> Condition<'a> {
3707 pub fn offset_data(&self) -> FontData<'a> {
3709 match self {
3710 Self::Format1AxisRange(item) => item.offset_data(),
3711 Self::Format2VariableValue(item) => item.offset_data(),
3712 Self::Format3And(item) => item.offset_data(),
3713 Self::Format4Or(item) => item.offset_data(),
3714 Self::Format5Negate(item) => item.offset_data(),
3715 }
3716 }
3717
3718 pub fn format(&self) -> u16 {
3720 match self {
3721 Self::Format1AxisRange(item) => item.format(),
3722 Self::Format2VariableValue(item) => item.format(),
3723 Self::Format3And(item) => item.format(),
3724 Self::Format4Or(item) => item.format(),
3725 Self::Format5Negate(item) => item.format(),
3726 }
3727 }
3728}
3729
3730impl ReadArgs for Condition<'_> {
3731 type Args = ();
3732}
3733
3734impl<'a> FontRead<'a> for Condition<'a> {
3735 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3736 let format: u16 = data.read_at(0usize)?;
3737 match format {
3738 ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
3739 ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
3740 ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
3741 ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
3742 ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
3743 other => Err(ReadError::InvalidFormat(other.into())),
3744 }
3745 }
3746}
3747
3748impl<'a> MinByteRange<'a> for Condition<'a> {
3749 fn min_byte_range(&self) -> Range<usize> {
3750 match self {
3751 Self::Format1AxisRange(item) => item.min_byte_range(),
3752 Self::Format2VariableValue(item) => item.min_byte_range(),
3753 Self::Format3And(item) => item.min_byte_range(),
3754 Self::Format4Or(item) => item.min_byte_range(),
3755 Self::Format5Negate(item) => item.min_byte_range(),
3756 }
3757 }
3758 fn min_table_bytes(&self) -> &'a [u8] {
3759 match self {
3760 Self::Format1AxisRange(item) => item.min_table_bytes(),
3761 Self::Format2VariableValue(item) => item.min_table_bytes(),
3762 Self::Format3And(item) => item.min_table_bytes(),
3763 Self::Format4Or(item) => item.min_table_bytes(),
3764 Self::Format5Negate(item) => item.min_table_bytes(),
3765 }
3766 }
3767}
3768
3769impl Format<u16> for ConditionFormat1<'_> {
3770 const FORMAT: u16 = 1;
3771}
3772
3773impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
3774 fn min_byte_range(&self) -> Range<usize> {
3775 0..self.filter_range_max_value_byte_range().end
3776 }
3777 fn min_table_bytes(&self) -> &'a [u8] {
3778 let range = self.min_byte_range();
3779 self.data.as_bytes().get(range).unwrap_or_default()
3780 }
3781}
3782
3783impl ReadArgs for ConditionFormat1<'_> {
3784 type Args = ();
3785}
3786
3787impl<'a> FontRead<'a> for ConditionFormat1<'a> {
3788 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3789 #[allow(clippy::absurd_extreme_comparisons)]
3790 if data.len() < Self::MIN_SIZE {
3791 return Err(ReadError::OutOfBounds);
3792 }
3793 Ok(Self { data })
3794 }
3795}
3796
3797#[derive(Clone)]
3799pub struct ConditionFormat1<'a> {
3800 data: FontData<'a>,
3801}
3802
3803#[allow(clippy::needless_lifetimes)]
3804impl<'a> ConditionFormat1<'a> {
3805 pub const MIN_SIZE: usize =
3806 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
3807 basic_table_impls!(impl_the_methods);
3808
3809 pub fn format(&self) -> u16 {
3811 let range = self.format_byte_range();
3812 self.data.read_at(range.start).ok().unwrap()
3813 }
3814
3815 pub fn axis_index(&self) -> u16 {
3818 let range = self.axis_index_byte_range();
3819 self.data.read_at(range.start).ok().unwrap()
3820 }
3821
3822 pub fn filter_range_min_value(&self) -> F2Dot14 {
3825 let range = self.filter_range_min_value_byte_range();
3826 self.data.read_at(range.start).ok().unwrap()
3827 }
3828
3829 pub fn filter_range_max_value(&self) -> F2Dot14 {
3832 let range = self.filter_range_max_value_byte_range();
3833 self.data.read_at(range.start).ok().unwrap()
3834 }
3835
3836 pub fn format_byte_range(&self) -> Range<usize> {
3837 let start = 0;
3838 let end = start + u16::RAW_BYTE_LEN;
3839 start..end
3840 }
3841
3842 pub fn axis_index_byte_range(&self) -> Range<usize> {
3843 let start = self.format_byte_range().end;
3844 let end = start + u16::RAW_BYTE_LEN;
3845 start..end
3846 }
3847
3848 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
3849 let start = self.axis_index_byte_range().end;
3850 let end = start + F2Dot14::RAW_BYTE_LEN;
3851 start..end
3852 }
3853
3854 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
3855 let start = self.filter_range_min_value_byte_range().end;
3856 let end = start + F2Dot14::RAW_BYTE_LEN;
3857 start..end
3858 }
3859}
3860
3861const _: () = assert!(FontData::default_data_long_enough(
3862 ConditionFormat1::MIN_SIZE
3863));
3864
3865impl Default for ConditionFormat1<'_> {
3866 fn default() -> Self {
3867 Self {
3868 data: FontData::default_format_1_u16_table_data(),
3869 }
3870 }
3871}
3872
3873impl Format<u16> for ConditionFormat2<'_> {
3874 const FORMAT: u16 = 2;
3875}
3876
3877impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
3878 fn min_byte_range(&self) -> Range<usize> {
3879 0..self.var_index_byte_range().end
3880 }
3881 fn min_table_bytes(&self) -> &'a [u8] {
3882 let range = self.min_byte_range();
3883 self.data.as_bytes().get(range).unwrap_or_default()
3884 }
3885}
3886
3887impl ReadArgs for ConditionFormat2<'_> {
3888 type Args = ();
3889}
3890
3891impl<'a> FontRead<'a> for ConditionFormat2<'a> {
3892 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3893 #[allow(clippy::absurd_extreme_comparisons)]
3894 if data.len() < Self::MIN_SIZE {
3895 return Err(ReadError::OutOfBounds);
3896 }
3897 Ok(Self { data })
3898 }
3899}
3900
3901#[derive(Clone)]
3903pub struct ConditionFormat2<'a> {
3904 data: FontData<'a>,
3905}
3906
3907#[allow(clippy::needless_lifetimes)]
3908impl<'a> ConditionFormat2<'a> {
3909 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
3910 basic_table_impls!(impl_the_methods);
3911
3912 pub fn format(&self) -> u16 {
3914 let range = self.format_byte_range();
3915 self.data.read_at(range.start).ok().unwrap()
3916 }
3917
3918 pub fn default_value(&self) -> i16 {
3920 let range = self.default_value_byte_range();
3921 self.data.read_at(range.start).ok().unwrap()
3922 }
3923
3924 pub fn var_index(&self) -> u32 {
3926 let range = self.var_index_byte_range();
3927 self.data.read_at(range.start).ok().unwrap()
3928 }
3929
3930 pub fn format_byte_range(&self) -> Range<usize> {
3931 let start = 0;
3932 let end = start + u16::RAW_BYTE_LEN;
3933 start..end
3934 }
3935
3936 pub fn default_value_byte_range(&self) -> Range<usize> {
3937 let start = self.format_byte_range().end;
3938 let end = start + i16::RAW_BYTE_LEN;
3939 start..end
3940 }
3941
3942 pub fn var_index_byte_range(&self) -> Range<usize> {
3943 let start = self.default_value_byte_range().end;
3944 let end = start + u32::RAW_BYTE_LEN;
3945 start..end
3946 }
3947}
3948
3949impl Format<u16> for ConditionFormat3<'_> {
3950 const FORMAT: u16 = 3;
3951}
3952
3953impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
3954 fn min_byte_range(&self) -> Range<usize> {
3955 0..self.condition_offsets_byte_range().end
3956 }
3957 fn min_table_bytes(&self) -> &'a [u8] {
3958 let range = self.min_byte_range();
3959 self.data.as_bytes().get(range).unwrap_or_default()
3960 }
3961}
3962
3963impl ReadArgs for ConditionFormat3<'_> {
3964 type Args = ();
3965}
3966
3967impl<'a> FontRead<'a> for ConditionFormat3<'a> {
3968 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3969 #[allow(clippy::absurd_extreme_comparisons)]
3970 if data.len() < Self::MIN_SIZE {
3971 return Err(ReadError::OutOfBounds);
3972 }
3973 Ok(Self { data })
3974 }
3975}
3976
3977#[derive(Clone)]
3979pub struct ConditionFormat3<'a> {
3980 data: FontData<'a>,
3981}
3982
3983#[allow(clippy::needless_lifetimes)]
3984impl<'a> ConditionFormat3<'a> {
3985 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
3986 basic_table_impls!(impl_the_methods);
3987
3988 pub fn format(&self) -> u16 {
3990 let range = self.format_byte_range();
3991 self.data.read_at(range.start).ok().unwrap()
3992 }
3993
3994 pub fn condition_count(&self) -> u8 {
3996 let range = self.condition_count_byte_range();
3997 self.data.read_at(range.start).ok().unwrap()
3998 }
3999
4000 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
4002 let range = self.condition_offsets_byte_range();
4003 self.data.read_array(range).ok().unwrap_or_default()
4004 }
4005
4006 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
4008 let data = self.data;
4009 let offsets = self.condition_offsets();
4010 ArrayOfOffsets::new(offsets, data, ())
4011 }
4012
4013 pub fn format_byte_range(&self) -> Range<usize> {
4014 let start = 0;
4015 let end = start + u16::RAW_BYTE_LEN;
4016 start..end
4017 }
4018
4019 pub fn condition_count_byte_range(&self) -> Range<usize> {
4020 let start = self.format_byte_range().end;
4021 let end = start + u8::RAW_BYTE_LEN;
4022 start..end
4023 }
4024
4025 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4026 let condition_count = self.condition_count();
4027 let start = self.condition_count_byte_range().end;
4028 let end =
4029 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
4030 start..end
4031 }
4032}
4033
4034impl Format<u16> for ConditionFormat4<'_> {
4035 const FORMAT: u16 = 4;
4036}
4037
4038impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
4039 fn min_byte_range(&self) -> Range<usize> {
4040 0..self.condition_offsets_byte_range().end
4041 }
4042 fn min_table_bytes(&self) -> &'a [u8] {
4043 let range = self.min_byte_range();
4044 self.data.as_bytes().get(range).unwrap_or_default()
4045 }
4046}
4047
4048impl ReadArgs for ConditionFormat4<'_> {
4049 type Args = ();
4050}
4051
4052impl<'a> FontRead<'a> for ConditionFormat4<'a> {
4053 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4054 #[allow(clippy::absurd_extreme_comparisons)]
4055 if data.len() < Self::MIN_SIZE {
4056 return Err(ReadError::OutOfBounds);
4057 }
4058 Ok(Self { data })
4059 }
4060}
4061
4062#[derive(Clone)]
4064pub struct ConditionFormat4<'a> {
4065 data: FontData<'a>,
4066}
4067
4068#[allow(clippy::needless_lifetimes)]
4069impl<'a> ConditionFormat4<'a> {
4070 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
4071 basic_table_impls!(impl_the_methods);
4072
4073 pub fn format(&self) -> u16 {
4075 let range = self.format_byte_range();
4076 self.data.read_at(range.start).ok().unwrap()
4077 }
4078
4079 pub fn condition_count(&self) -> u8 {
4081 let range = self.condition_count_byte_range();
4082 self.data.read_at(range.start).ok().unwrap()
4083 }
4084
4085 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
4087 let range = self.condition_offsets_byte_range();
4088 self.data.read_array(range).ok().unwrap_or_default()
4089 }
4090
4091 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
4093 let data = self.data;
4094 let offsets = self.condition_offsets();
4095 ArrayOfOffsets::new(offsets, data, ())
4096 }
4097
4098 pub fn format_byte_range(&self) -> Range<usize> {
4099 let start = 0;
4100 let end = start + u16::RAW_BYTE_LEN;
4101 start..end
4102 }
4103
4104 pub fn condition_count_byte_range(&self) -> Range<usize> {
4105 let start = self.format_byte_range().end;
4106 let end = start + u8::RAW_BYTE_LEN;
4107 start..end
4108 }
4109
4110 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4111 let condition_count = self.condition_count();
4112 let start = self.condition_count_byte_range().end;
4113 let end =
4114 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
4115 start..end
4116 }
4117}
4118
4119impl Format<u16> for ConditionFormat5<'_> {
4120 const FORMAT: u16 = 5;
4121}
4122
4123impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
4124 fn min_byte_range(&self) -> Range<usize> {
4125 0..self.condition_offset_byte_range().end
4126 }
4127 fn min_table_bytes(&self) -> &'a [u8] {
4128 let range = self.min_byte_range();
4129 self.data.as_bytes().get(range).unwrap_or_default()
4130 }
4131}
4132
4133impl ReadArgs for ConditionFormat5<'_> {
4134 type Args = ();
4135}
4136
4137impl<'a> FontRead<'a> for ConditionFormat5<'a> {
4138 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4139 #[allow(clippy::absurd_extreme_comparisons)]
4140 if data.len() < Self::MIN_SIZE {
4141 return Err(ReadError::OutOfBounds);
4142 }
4143 Ok(Self { data })
4144 }
4145}
4146
4147#[derive(Clone)]
4149pub struct ConditionFormat5<'a> {
4150 data: FontData<'a>,
4151}
4152
4153#[allow(clippy::needless_lifetimes)]
4154impl<'a> ConditionFormat5<'a> {
4155 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
4156 basic_table_impls!(impl_the_methods);
4157
4158 pub fn format(&self) -> u16 {
4160 let range = self.format_byte_range();
4161 self.data.read_at(range.start).ok().unwrap()
4162 }
4163
4164 pub fn condition_offset(&self) -> Offset24 {
4166 let range = self.condition_offset_byte_range();
4167 self.data.read_at(range.start).ok().unwrap()
4168 }
4169
4170 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
4172 let data = self.data;
4173 self.condition_offset().resolve(data)
4174 }
4175
4176 pub fn format_byte_range(&self) -> Range<usize> {
4177 let start = 0;
4178 let end = start + u16::RAW_BYTE_LEN;
4179 start..end
4180 }
4181
4182 pub fn condition_offset_byte_range(&self) -> Range<usize> {
4183 let start = self.format_byte_range().end;
4184 let end = start + Offset24::RAW_BYTE_LEN;
4185 start..end
4186 }
4187}
4188
4189impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
4190 fn min_byte_range(&self) -> Range<usize> {
4191 0..self.substitutions_byte_range().end
4192 }
4193 fn min_table_bytes(&self) -> &'a [u8] {
4194 let range = self.min_byte_range();
4195 self.data.as_bytes().get(range).unwrap_or_default()
4196 }
4197}
4198
4199impl ReadArgs for FeatureTableSubstitution<'_> {
4200 type Args = ();
4201}
4202
4203impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
4204 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4205 #[allow(clippy::absurd_extreme_comparisons)]
4206 if data.len() < Self::MIN_SIZE {
4207 return Err(ReadError::OutOfBounds);
4208 }
4209 Ok(Self { data })
4210 }
4211}
4212
4213#[derive(Clone)]
4215pub struct FeatureTableSubstitution<'a> {
4216 data: FontData<'a>,
4217}
4218
4219#[allow(clippy::needless_lifetimes)]
4220impl<'a> FeatureTableSubstitution<'a> {
4221 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
4222 basic_table_impls!(impl_the_methods);
4223
4224 pub fn version(&self) -> MajorMinor {
4226 let range = self.version_byte_range();
4227 self.data.read_at(range.start).ok().unwrap()
4228 }
4229
4230 pub fn substitution_count(&self) -> u16 {
4232 let range = self.substitution_count_byte_range();
4233 self.data.read_at(range.start).ok().unwrap()
4234 }
4235
4236 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
4238 let range = self.substitutions_byte_range();
4239 self.data.read_array(range).ok().unwrap_or_default()
4240 }
4241
4242 pub fn version_byte_range(&self) -> Range<usize> {
4243 let start = 0;
4244 let end = start + MajorMinor::RAW_BYTE_LEN;
4245 start..end
4246 }
4247
4248 pub fn substitution_count_byte_range(&self) -> Range<usize> {
4249 let start = self.version_byte_range().end;
4250 let end = start + u16::RAW_BYTE_LEN;
4251 start..end
4252 }
4253
4254 pub fn substitutions_byte_range(&self) -> Range<usize> {
4255 let substitution_count = self.substitution_count();
4256 let start = self.substitution_count_byte_range().end;
4257 let end = start
4258 + (transforms::to_usize(substitution_count))
4259 .saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN);
4260 start..end
4261 }
4262}
4263
4264const _: () = assert!(FontData::default_data_long_enough(
4265 FeatureTableSubstitution::MIN_SIZE
4266));
4267
4268impl Default for FeatureTableSubstitution<'_> {
4269 fn default() -> Self {
4270 Self {
4271 data: FontData::default_table_data(),
4272 }
4273 }
4274}
4275
4276#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4278#[repr(C)]
4279#[repr(packed)]
4280pub struct FeatureTableSubstitutionRecord {
4281 pub feature_index: BigEndian<u16>,
4283 pub alternate_feature_offset: BigEndian<Offset32>,
4286}
4287
4288impl FeatureTableSubstitutionRecord {
4289 pub fn feature_index(&self) -> u16 {
4291 self.feature_index.get()
4292 }
4293
4294 pub fn alternate_feature_offset(&self) -> Offset32 {
4297 self.alternate_feature_offset.get()
4298 }
4299}
4300
4301impl FixedSize for FeatureTableSubstitutionRecord {
4302 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4303}
4304
4305impl<'a> MinByteRange<'a> for SizeParams<'a> {
4306 fn min_byte_range(&self) -> Range<usize> {
4307 0..self.range_end_byte_range().end
4308 }
4309 fn min_table_bytes(&self) -> &'a [u8] {
4310 let range = self.min_byte_range();
4311 self.data.as_bytes().get(range).unwrap_or_default()
4312 }
4313}
4314
4315impl ReadArgs for SizeParams<'_> {
4316 type Args = ();
4317}
4318
4319impl<'a> FontRead<'a> for SizeParams<'a> {
4320 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4321 #[allow(clippy::absurd_extreme_comparisons)]
4322 if data.len() < Self::MIN_SIZE {
4323 return Err(ReadError::OutOfBounds);
4324 }
4325 Ok(Self { data })
4326 }
4327}
4328
4329#[derive(Clone)]
4330pub struct SizeParams<'a> {
4331 data: FontData<'a>,
4332}
4333
4334#[allow(clippy::needless_lifetimes)]
4335impl<'a> SizeParams<'a> {
4336 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
4337 + u16::RAW_BYTE_LEN
4338 + u16::RAW_BYTE_LEN
4339 + u16::RAW_BYTE_LEN
4340 + u16::RAW_BYTE_LEN);
4341 basic_table_impls!(impl_the_methods);
4342
4343 pub fn design_size(&self) -> u16 {
4348 let range = self.design_size_byte_range();
4349 self.data.read_at(range.start).ok().unwrap()
4350 }
4351
4352 pub fn identifier(&self) -> u16 {
4359 let range = self.identifier_byte_range();
4360 self.data.read_at(range.start).ok().unwrap()
4361 }
4362
4363 pub fn name_entry(&self) -> u16 {
4374 let range = self.name_entry_byte_range();
4375 self.data.read_at(range.start).ok().unwrap()
4376 }
4377
4378 pub fn range_start(&self) -> u16 {
4384 let range = self.range_start_byte_range();
4385 self.data.read_at(range.start).ok().unwrap()
4386 }
4387
4388 pub fn range_end(&self) -> u16 {
4389 let range = self.range_end_byte_range();
4390 self.data.read_at(range.start).ok().unwrap()
4391 }
4392
4393 pub fn design_size_byte_range(&self) -> Range<usize> {
4394 let start = 0;
4395 let end = start + u16::RAW_BYTE_LEN;
4396 start..end
4397 }
4398
4399 pub fn identifier_byte_range(&self) -> Range<usize> {
4400 let start = self.design_size_byte_range().end;
4401 let end = start + u16::RAW_BYTE_LEN;
4402 start..end
4403 }
4404
4405 pub fn name_entry_byte_range(&self) -> Range<usize> {
4406 let start = self.identifier_byte_range().end;
4407 let end = start + u16::RAW_BYTE_LEN;
4408 start..end
4409 }
4410
4411 pub fn range_start_byte_range(&self) -> Range<usize> {
4412 let start = self.name_entry_byte_range().end;
4413 let end = start + u16::RAW_BYTE_LEN;
4414 start..end
4415 }
4416
4417 pub fn range_end_byte_range(&self) -> Range<usize> {
4418 let start = self.range_start_byte_range().end;
4419 let end = start + u16::RAW_BYTE_LEN;
4420 start..end
4421 }
4422}
4423
4424const _: () = assert!(FontData::default_data_long_enough(SizeParams::MIN_SIZE));
4425
4426impl Default for SizeParams<'_> {
4427 fn default() -> Self {
4428 Self {
4429 data: FontData::default_table_data(),
4430 }
4431 }
4432}
4433
4434impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
4435 fn min_byte_range(&self) -> Range<usize> {
4436 0..self.ui_name_id_byte_range().end
4437 }
4438 fn min_table_bytes(&self) -> &'a [u8] {
4439 let range = self.min_byte_range();
4440 self.data.as_bytes().get(range).unwrap_or_default()
4441 }
4442}
4443
4444impl ReadArgs for StylisticSetParams<'_> {
4445 type Args = ();
4446}
4447
4448impl<'a> FontRead<'a> for StylisticSetParams<'a> {
4449 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4450 #[allow(clippy::absurd_extreme_comparisons)]
4451 if data.len() < Self::MIN_SIZE {
4452 return Err(ReadError::OutOfBounds);
4453 }
4454 Ok(Self { data })
4455 }
4456}
4457
4458#[derive(Clone)]
4459pub struct StylisticSetParams<'a> {
4460 data: FontData<'a>,
4461}
4462
4463#[allow(clippy::needless_lifetimes)]
4464impl<'a> StylisticSetParams<'a> {
4465 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
4466 basic_table_impls!(impl_the_methods);
4467
4468 pub fn version(&self) -> u16 {
4469 let range = self.version_byte_range();
4470 self.data.read_at(range.start).ok().unwrap()
4471 }
4472
4473 pub fn ui_name_id(&self) -> NameId {
4483 let range = self.ui_name_id_byte_range();
4484 self.data.read_at(range.start).ok().unwrap()
4485 }
4486
4487 pub fn version_byte_range(&self) -> Range<usize> {
4488 let start = 0;
4489 let end = start + u16::RAW_BYTE_LEN;
4490 start..end
4491 }
4492
4493 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
4494 let start = self.version_byte_range().end;
4495 let end = start + NameId::RAW_BYTE_LEN;
4496 start..end
4497 }
4498}
4499
4500const _: () = assert!(FontData::default_data_long_enough(
4501 StylisticSetParams::MIN_SIZE
4502));
4503
4504impl Default for StylisticSetParams<'_> {
4505 fn default() -> Self {
4506 Self {
4507 data: FontData::default_table_data(),
4508 }
4509 }
4510}
4511
4512impl Format<u16> for CharacterVariantParams<'_> {
4513 const FORMAT: u16 = 0;
4514}
4515
4516impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
4517 fn min_byte_range(&self) -> Range<usize> {
4518 0..self.character_byte_range().end
4519 }
4520 fn min_table_bytes(&self) -> &'a [u8] {
4521 let range = self.min_byte_range();
4522 self.data.as_bytes().get(range).unwrap_or_default()
4523 }
4524}
4525
4526impl ReadArgs for CharacterVariantParams<'_> {
4527 type Args = ();
4528}
4529
4530impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
4531 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4532 #[allow(clippy::absurd_extreme_comparisons)]
4533 if data.len() < Self::MIN_SIZE {
4534 return Err(ReadError::OutOfBounds);
4535 }
4536 Ok(Self { data })
4537 }
4538}
4539
4540#[derive(Clone)]
4542pub struct CharacterVariantParams<'a> {
4543 data: FontData<'a>,
4544}
4545
4546#[allow(clippy::needless_lifetimes)]
4547impl<'a> CharacterVariantParams<'a> {
4548 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
4549 + NameId::RAW_BYTE_LEN
4550 + NameId::RAW_BYTE_LEN
4551 + NameId::RAW_BYTE_LEN
4552 + u16::RAW_BYTE_LEN
4553 + NameId::RAW_BYTE_LEN
4554 + u16::RAW_BYTE_LEN);
4555 basic_table_impls!(impl_the_methods);
4556
4557 pub fn format(&self) -> u16 {
4559 let range = self.format_byte_range();
4560 self.data.read_at(range.start).ok().unwrap()
4561 }
4562
4563 pub fn feat_ui_label_name_id(&self) -> NameId {
4567 let range = self.feat_ui_label_name_id_byte_range();
4568 self.data.read_at(range.start).ok().unwrap()
4569 }
4570
4571 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
4575 let range = self.feat_ui_tooltip_text_name_id_byte_range();
4576 self.data.read_at(range.start).ok().unwrap()
4577 }
4578
4579 pub fn sample_text_name_id(&self) -> NameId {
4582 let range = self.sample_text_name_id_byte_range();
4583 self.data.read_at(range.start).ok().unwrap()
4584 }
4585
4586 pub fn num_named_parameters(&self) -> u16 {
4588 let range = self.num_named_parameters_byte_range();
4589 self.data.read_at(range.start).ok().unwrap()
4590 }
4591
4592 pub fn first_param_ui_label_name_id(&self) -> NameId {
4596 let range = self.first_param_ui_label_name_id_byte_range();
4597 self.data.read_at(range.start).ok().unwrap()
4598 }
4599
4600 pub fn char_count(&self) -> u16 {
4603 let range = self.char_count_byte_range();
4604 self.data.read_at(range.start).ok().unwrap()
4605 }
4606
4607 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
4610 let range = self.character_byte_range();
4611 self.data.read_array(range).ok().unwrap_or_default()
4612 }
4613
4614 pub fn format_byte_range(&self) -> Range<usize> {
4615 let start = 0;
4616 let end = start + u16::RAW_BYTE_LEN;
4617 start..end
4618 }
4619
4620 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
4621 let start = self.format_byte_range().end;
4622 let end = start + NameId::RAW_BYTE_LEN;
4623 start..end
4624 }
4625
4626 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
4627 let start = self.feat_ui_label_name_id_byte_range().end;
4628 let end = start + NameId::RAW_BYTE_LEN;
4629 start..end
4630 }
4631
4632 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
4633 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
4634 let end = start + NameId::RAW_BYTE_LEN;
4635 start..end
4636 }
4637
4638 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
4639 let start = self.sample_text_name_id_byte_range().end;
4640 let end = start + u16::RAW_BYTE_LEN;
4641 start..end
4642 }
4643
4644 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
4645 let start = self.num_named_parameters_byte_range().end;
4646 let end = start + NameId::RAW_BYTE_LEN;
4647 start..end
4648 }
4649
4650 pub fn char_count_byte_range(&self) -> Range<usize> {
4651 let start = self.first_param_ui_label_name_id_byte_range().end;
4652 let end = start + u16::RAW_BYTE_LEN;
4653 start..end
4654 }
4655
4656 pub fn character_byte_range(&self) -> Range<usize> {
4657 let char_count = self.char_count();
4658 let start = self.char_count_byte_range().end;
4659 let end = start + (transforms::to_usize(char_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
4660 start..end
4661 }
4662}
4663
4664const _: () = assert!(FontData::default_data_long_enough(
4665 CharacterVariantParams::MIN_SIZE
4666));
4667
4668impl Default for CharacterVariantParams<'_> {
4669 fn default() -> Self {
4670 Self {
4671 data: FontData::default_table_data(),
4672 }
4673 }
4674}