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#[cfg(feature = "experimental_traverse")]
81impl<'a> SomeTable<'a> for ScriptList<'a> {
82 fn type_name(&self) -> &str {
83 "ScriptList"
84 }
85 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
86 match idx {
87 0usize => Some(Field::new("script_count", self.script_count())),
88 1usize => Some(Field::new(
89 "script_records",
90 traversal::FieldType::array_of_records(
91 stringify!(ScriptRecord),
92 self.script_records(),
93 self.offset_data(),
94 ),
95 )),
96 _ => None,
97 }
98 }
99}
100
101#[cfg(feature = "experimental_traverse")]
102#[allow(clippy::needless_lifetimes)]
103impl<'a> std::fmt::Debug for ScriptList<'a> {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 (self as &dyn SomeTable<'a>).fmt(f)
106 }
107}
108
109#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
111#[repr(C)]
112#[repr(packed)]
113pub struct ScriptRecord {
114 pub script_tag: BigEndian<Tag>,
116 pub script_offset: BigEndian<Offset16>,
118}
119
120impl ScriptRecord {
121 pub fn script_tag(&self) -> Tag {
123 self.script_tag.get()
124 }
125
126 pub fn script_offset(&self) -> Offset16 {
128 self.script_offset.get()
129 }
130
131 pub fn script<'a>(&self, data: FontData<'a>) -> Result<Script<'a>, ReadError> {
136 self.script_offset().resolve(data)
137 }
138}
139
140impl FixedSize for ScriptRecord {
141 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
142}
143
144#[cfg(feature = "experimental_traverse")]
145impl<'a> SomeRecord<'a> for ScriptRecord {
146 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
147 RecordResolver {
148 name: "ScriptRecord",
149 get_field: Box::new(move |idx, _data| match idx {
150 0usize => Some(Field::new("script_tag", self.script_tag())),
151 1usize => Some(Field::new(
152 "script_offset",
153 FieldType::offset(self.script_offset(), self.script(_data)),
154 )),
155 _ => None,
156 }),
157 data,
158 }
159 }
160}
161
162impl<'a> MinByteRange<'a> for Script<'a> {
163 fn min_byte_range(&self) -> Range<usize> {
164 0..self.lang_sys_records_byte_range().end
165 }
166 fn min_table_bytes(&self) -> &'a [u8] {
167 let range = self.min_byte_range();
168 self.data.as_bytes().get(range).unwrap_or_default()
169 }
170}
171
172impl ReadArgs for Script<'_> {
173 type Args = ();
174}
175
176impl<'a> FontRead<'a> for Script<'a> {
177 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
178 #[allow(clippy::absurd_extreme_comparisons)]
179 if data.len() < Self::MIN_SIZE {
180 return Err(ReadError::OutOfBounds);
181 }
182 Ok(Self { data })
183 }
184}
185
186#[derive(Clone)]
188pub struct Script<'a> {
189 data: FontData<'a>,
190}
191
192#[allow(clippy::needless_lifetimes)]
193impl<'a> Script<'a> {
194 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
195 basic_table_impls!(impl_the_methods);
196
197 pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
200 let range = self.default_lang_sys_offset_byte_range();
201 self.data.read_at(range.start).ok().unwrap()
202 }
203
204 pub fn default_lang_sys(&self) -> Option<Result<LangSys<'a>, ReadError>> {
206 let data = self.data;
207 self.default_lang_sys_offset().resolve(data)
208 }
209
210 pub fn lang_sys_count(&self) -> u16 {
213 let range = self.lang_sys_count_byte_range();
214 self.data.read_at(range.start).ok().unwrap()
215 }
216
217 pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
219 let range = self.lang_sys_records_byte_range();
220 self.data.read_array(range).ok().unwrap_or_default()
221 }
222
223 pub fn default_lang_sys_offset_byte_range(&self) -> Range<usize> {
224 let start = 0;
225 let end = start + Offset16::RAW_BYTE_LEN;
226 start..end
227 }
228
229 pub fn lang_sys_count_byte_range(&self) -> Range<usize> {
230 let start = self.default_lang_sys_offset_byte_range().end;
231 let end = start + u16::RAW_BYTE_LEN;
232 start..end
233 }
234
235 pub fn lang_sys_records_byte_range(&self) -> Range<usize> {
236 let lang_sys_count = self.lang_sys_count();
237 let start = self.lang_sys_count_byte_range().end;
238 let end = start
239 + (transforms::to_usize(lang_sys_count)).saturating_mul(LangSysRecord::RAW_BYTE_LEN);
240 start..end
241 }
242}
243
244const _: () = assert!(FontData::default_data_long_enough(Script::MIN_SIZE));
245
246impl Default for Script<'_> {
247 fn default() -> Self {
248 Self {
249 data: FontData::default_table_data(),
250 }
251 }
252}
253
254#[cfg(feature = "experimental_traverse")]
255impl<'a> SomeTable<'a> for Script<'a> {
256 fn type_name(&self) -> &str {
257 "Script"
258 }
259 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
260 match idx {
261 0usize => Some(Field::new(
262 "default_lang_sys_offset",
263 FieldType::offset(self.default_lang_sys_offset(), self.default_lang_sys()),
264 )),
265 1usize => Some(Field::new("lang_sys_count", self.lang_sys_count())),
266 2usize => Some(Field::new(
267 "lang_sys_records",
268 traversal::FieldType::array_of_records(
269 stringify!(LangSysRecord),
270 self.lang_sys_records(),
271 self.offset_data(),
272 ),
273 )),
274 _ => None,
275 }
276 }
277}
278
279#[cfg(feature = "experimental_traverse")]
280#[allow(clippy::needless_lifetimes)]
281impl<'a> std::fmt::Debug for Script<'a> {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 (self as &dyn SomeTable<'a>).fmt(f)
284 }
285}
286
287#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
288#[repr(C)]
289#[repr(packed)]
290pub struct LangSysRecord {
291 pub lang_sys_tag: BigEndian<Tag>,
293 pub lang_sys_offset: BigEndian<Offset16>,
295}
296
297impl LangSysRecord {
298 pub fn lang_sys_tag(&self) -> Tag {
300 self.lang_sys_tag.get()
301 }
302
303 pub fn lang_sys_offset(&self) -> Offset16 {
305 self.lang_sys_offset.get()
306 }
307
308 pub fn lang_sys<'a>(&self, data: FontData<'a>) -> Result<LangSys<'a>, ReadError> {
313 self.lang_sys_offset().resolve(data)
314 }
315}
316
317impl FixedSize for LangSysRecord {
318 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
319}
320
321#[cfg(feature = "experimental_traverse")]
322impl<'a> SomeRecord<'a> for LangSysRecord {
323 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
324 RecordResolver {
325 name: "LangSysRecord",
326 get_field: Box::new(move |idx, _data| match idx {
327 0usize => Some(Field::new("lang_sys_tag", self.lang_sys_tag())),
328 1usize => Some(Field::new(
329 "lang_sys_offset",
330 FieldType::offset(self.lang_sys_offset(), self.lang_sys(_data)),
331 )),
332 _ => None,
333 }),
334 data,
335 }
336 }
337}
338
339impl<'a> MinByteRange<'a> for LangSys<'a> {
340 fn min_byte_range(&self) -> Range<usize> {
341 0..self.feature_indices_byte_range().end
342 }
343 fn min_table_bytes(&self) -> &'a [u8] {
344 let range = self.min_byte_range();
345 self.data.as_bytes().get(range).unwrap_or_default()
346 }
347}
348
349impl ReadArgs for LangSys<'_> {
350 type Args = ();
351}
352
353impl<'a> FontRead<'a> for LangSys<'a> {
354 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
355 #[allow(clippy::absurd_extreme_comparisons)]
356 if data.len() < Self::MIN_SIZE {
357 return Err(ReadError::OutOfBounds);
358 }
359 Ok(Self { data })
360 }
361}
362
363#[derive(Clone)]
365pub struct LangSys<'a> {
366 data: FontData<'a>,
367}
368
369#[allow(clippy::needless_lifetimes)]
370impl<'a> LangSys<'a> {
371 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
372 basic_table_impls!(impl_the_methods);
373
374 pub fn required_feature_index(&self) -> u16 {
377 let range = self.required_feature_index_byte_range();
378 self.data.read_at(range.start).ok().unwrap()
379 }
380
381 pub fn feature_index_count(&self) -> u16 {
384 let range = self.feature_index_count_byte_range();
385 self.data.read_at(range.start).ok().unwrap()
386 }
387
388 pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
390 let range = self.feature_indices_byte_range();
391 self.data.read_array(range).ok().unwrap_or_default()
392 }
393
394 pub fn lookup_order_offset_byte_range(&self) -> Range<usize> {
395 let start = 0;
396 let end = start + u16::RAW_BYTE_LEN;
397 start..end
398 }
399
400 pub fn required_feature_index_byte_range(&self) -> Range<usize> {
401 let start = self.lookup_order_offset_byte_range().end;
402 let end = start + u16::RAW_BYTE_LEN;
403 start..end
404 }
405
406 pub fn feature_index_count_byte_range(&self) -> Range<usize> {
407 let start = self.required_feature_index_byte_range().end;
408 let end = start + u16::RAW_BYTE_LEN;
409 start..end
410 }
411
412 pub fn feature_indices_byte_range(&self) -> Range<usize> {
413 let feature_index_count = self.feature_index_count();
414 let start = self.feature_index_count_byte_range().end;
415 let end =
416 start + (transforms::to_usize(feature_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
417 start..end
418 }
419}
420
421const _: () = assert!(FontData::default_data_long_enough(LangSys::MIN_SIZE));
422
423impl Default for LangSys<'_> {
424 fn default() -> Self {
425 Self {
426 data: FontData::default_table_data(),
427 }
428 }
429}
430
431#[cfg(feature = "experimental_traverse")]
432impl<'a> SomeTable<'a> for LangSys<'a> {
433 fn type_name(&self) -> &str {
434 "LangSys"
435 }
436 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
437 match idx {
438 0usize => Some(Field::new(
439 "required_feature_index",
440 self.required_feature_index(),
441 )),
442 1usize => Some(Field::new(
443 "feature_index_count",
444 self.feature_index_count(),
445 )),
446 2usize => Some(Field::new("feature_indices", self.feature_indices())),
447 _ => None,
448 }
449 }
450}
451
452#[cfg(feature = "experimental_traverse")]
453#[allow(clippy::needless_lifetimes)]
454impl<'a> std::fmt::Debug for LangSys<'a> {
455 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
456 (self as &dyn SomeTable<'a>).fmt(f)
457 }
458}
459
460impl<'a> MinByteRange<'a> for FeatureList<'a> {
461 fn min_byte_range(&self) -> Range<usize> {
462 0..self.feature_records_byte_range().end
463 }
464 fn min_table_bytes(&self) -> &'a [u8] {
465 let range = self.min_byte_range();
466 self.data.as_bytes().get(range).unwrap_or_default()
467 }
468}
469
470impl ReadArgs for FeatureList<'_> {
471 type Args = ();
472}
473
474impl<'a> FontRead<'a> for FeatureList<'a> {
475 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
476 #[allow(clippy::absurd_extreme_comparisons)]
477 if data.len() < Self::MIN_SIZE {
478 return Err(ReadError::OutOfBounds);
479 }
480 Ok(Self { data })
481 }
482}
483
484#[derive(Clone)]
486pub struct FeatureList<'a> {
487 data: FontData<'a>,
488}
489
490#[allow(clippy::needless_lifetimes)]
491impl<'a> FeatureList<'a> {
492 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
493 basic_table_impls!(impl_the_methods);
494
495 pub fn feature_count(&self) -> u16 {
497 let range = self.feature_count_byte_range();
498 self.data.read_at(range.start).ok().unwrap()
499 }
500
501 pub fn feature_records(&self) -> &'a [FeatureRecord] {
504 let range = self.feature_records_byte_range();
505 self.data.read_array(range).ok().unwrap_or_default()
506 }
507
508 pub fn feature_count_byte_range(&self) -> Range<usize> {
509 let start = 0;
510 let end = start + u16::RAW_BYTE_LEN;
511 start..end
512 }
513
514 pub fn feature_records_byte_range(&self) -> Range<usize> {
515 let feature_count = self.feature_count();
516 let start = self.feature_count_byte_range().end;
517 let end = start
518 + (transforms::to_usize(feature_count)).saturating_mul(FeatureRecord::RAW_BYTE_LEN);
519 start..end
520 }
521}
522
523const _: () = assert!(FontData::default_data_long_enough(FeatureList::MIN_SIZE));
524
525impl Default for FeatureList<'_> {
526 fn default() -> Self {
527 Self {
528 data: FontData::default_table_data(),
529 }
530 }
531}
532
533#[cfg(feature = "experimental_traverse")]
534impl<'a> SomeTable<'a> for FeatureList<'a> {
535 fn type_name(&self) -> &str {
536 "FeatureList"
537 }
538 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
539 match idx {
540 0usize => Some(Field::new("feature_count", self.feature_count())),
541 1usize => Some(Field::new(
542 "feature_records",
543 traversal::FieldType::array_of_records(
544 stringify!(FeatureRecord),
545 self.feature_records(),
546 self.offset_data(),
547 ),
548 )),
549 _ => None,
550 }
551 }
552}
553
554#[cfg(feature = "experimental_traverse")]
555#[allow(clippy::needless_lifetimes)]
556impl<'a> std::fmt::Debug for FeatureList<'a> {
557 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
558 (self as &dyn SomeTable<'a>).fmt(f)
559 }
560}
561
562#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
564#[repr(C)]
565#[repr(packed)]
566pub struct FeatureRecord {
567 pub feature_tag: BigEndian<Tag>,
569 pub feature_offset: BigEndian<Offset16>,
571}
572
573impl FeatureRecord {
574 pub fn feature_tag(&self) -> Tag {
576 self.feature_tag.get()
577 }
578
579 pub fn feature_offset(&self) -> Offset16 {
581 self.feature_offset.get()
582 }
583
584 pub fn feature<'a>(&self, data: FontData<'a>) -> Result<Feature<'a>, ReadError> {
589 let args = self.feature_tag();
590 self.feature_offset().resolve_with_args(data, args)
591 }
592}
593
594impl FixedSize for FeatureRecord {
595 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
596}
597
598#[cfg(feature = "experimental_traverse")]
599impl<'a> SomeRecord<'a> for FeatureRecord {
600 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
601 RecordResolver {
602 name: "FeatureRecord",
603 get_field: Box::new(move |idx, _data| match idx {
604 0usize => Some(Field::new("feature_tag", self.feature_tag())),
605 1usize => Some(Field::new(
606 "feature_offset",
607 FieldType::offset(self.feature_offset(), self.feature(_data)),
608 )),
609 _ => None,
610 }),
611 data,
612 }
613 }
614}
615
616impl<'a> MinByteRange<'a> for Feature<'a> {
617 fn min_byte_range(&self) -> Range<usize> {
618 0..self.lookup_list_indices_byte_range().end
619 }
620 fn min_table_bytes(&self) -> &'a [u8] {
621 let range = self.min_byte_range();
622 self.data.as_bytes().get(range).unwrap_or_default()
623 }
624}
625
626impl ReadArgs for Feature<'_> {
627 type Args = Tag;
628}
629
630impl<'a> FontRead<'a> for Feature<'a> {
631 fn read_with_args(data: FontData<'a>, args: Tag) -> Result<Self, ReadError> {
632 let feature_tag = args;
633
634 #[allow(clippy::absurd_extreme_comparisons)]
635 if data.len() < Self::MIN_SIZE {
636 return Err(ReadError::OutOfBounds);
637 }
638 Ok(Self { data, feature_tag })
639 }
640}
641
642impl<'a> Feature<'a> {
643 pub fn read(data: FontData<'a>, feature_tag: Tag) -> Result<Self, ReadError> {
648 let args = feature_tag;
649 Self::read_with_args(data, args)
650 }
651}
652
653#[derive(Clone)]
655pub struct Feature<'a> {
656 data: FontData<'a>,
657 feature_tag: Tag,
658}
659
660#[allow(clippy::needless_lifetimes)]
661impl<'a> Feature<'a> {
662 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
663 basic_table_impls!(impl_the_methods);
664
665 pub fn feature_params_offset(&self) -> Nullable<Offset16> {
667 let range = self.feature_params_offset_byte_range();
668 self.data.read_at(range.start).ok().unwrap()
669 }
670
671 pub fn feature_params(&self) -> Option<Result<FeatureParams<'a>, ReadError>> {
673 let data = self.data;
674 let args = self.feature_tag();
675 self.feature_params_offset().resolve_with_args(data, args)
676 }
677
678 pub fn lookup_index_count(&self) -> u16 {
680 let range = self.lookup_index_count_byte_range();
681 self.data.read_at(range.start).ok().unwrap()
682 }
683
684 pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
687 let range = self.lookup_list_indices_byte_range();
688 self.data.read_array(range).ok().unwrap_or_default()
689 }
690
691 pub(crate) fn feature_tag(&self) -> Tag {
692 self.feature_tag
693 }
694
695 pub fn feature_params_offset_byte_range(&self) -> Range<usize> {
696 let start = 0;
697 let end = start + Offset16::RAW_BYTE_LEN;
698 start..end
699 }
700
701 pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
702 let start = self.feature_params_offset_byte_range().end;
703 let end = start + u16::RAW_BYTE_LEN;
704 start..end
705 }
706
707 pub fn lookup_list_indices_byte_range(&self) -> Range<usize> {
708 let lookup_index_count = self.lookup_index_count();
709 let start = self.lookup_index_count_byte_range().end;
710 let end =
711 start + (transforms::to_usize(lookup_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
712 start..end
713 }
714}
715
716const _: () = assert!(FontData::default_data_long_enough(Feature::MIN_SIZE));
717
718impl Default for Feature<'_> {
719 fn default() -> Self {
720 Self {
721 data: FontData::default_table_data(),
722 feature_tag: Default::default(),
723 }
724 }
725}
726
727#[cfg(feature = "experimental_traverse")]
728impl<'a> SomeTable<'a> for Feature<'a> {
729 fn type_name(&self) -> &str {
730 "Feature"
731 }
732 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
733 match idx {
734 0usize => Some(Field::new(
735 "feature_params_offset",
736 FieldType::offset(self.feature_params_offset(), self.feature_params()),
737 )),
738 1usize => Some(Field::new("lookup_index_count", self.lookup_index_count())),
739 2usize => Some(Field::new(
740 "lookup_list_indices",
741 self.lookup_list_indices(),
742 )),
743 _ => None,
744 }
745 }
746}
747
748#[cfg(feature = "experimental_traverse")]
749#[allow(clippy::needless_lifetimes)]
750impl<'a> std::fmt::Debug for Feature<'a> {
751 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
752 (self as &dyn SomeTable<'a>).fmt(f)
753 }
754}
755
756impl<'a, T> MinByteRange<'a> for LookupList<'a, T> {
757 fn min_byte_range(&self) -> Range<usize> {
758 0..self.lookup_offsets_byte_range().end
759 }
760 fn min_table_bytes(&self) -> &'a [u8] {
761 let range = self.min_byte_range();
762 self.data.as_bytes().get(range).unwrap_or_default()
763 }
764}
765
766impl<T> ReadArgs for LookupList<'_, T> {
767 type Args = ();
768}
769
770impl<'a, T> FontRead<'a> for LookupList<'a, T> {
771 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
772 #[allow(clippy::absurd_extreme_comparisons)]
773 if data.len() < Self::MIN_SIZE {
774 return Err(ReadError::OutOfBounds);
775 }
776 Ok(Self {
777 data,
778 offset_type: std::marker::PhantomData,
779 })
780 }
781}
782
783impl<'a, T> LookupList<'a, T> {
784 #[allow(dead_code)]
785 pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
787 LookupList {
788 data: self.data,
789 offset_type: std::marker::PhantomData,
790 }
791 }
792}
793
794#[derive(Clone)]
796pub struct LookupList<'a, T = ()> {
797 data: FontData<'a>,
798 offset_type: std::marker::PhantomData<*const T>,
799}
800
801#[allow(clippy::needless_lifetimes)]
802impl<'a, T> LookupList<'a, T> {
803 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
804 basic_table_impls!(impl_the_methods);
805
806 pub fn lookup_count(&self) -> u16 {
808 let range = self.lookup_count_byte_range();
809 self.data.read_at(range.start).ok().unwrap()
810 }
811
812 pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
815 let range = self.lookup_offsets_byte_range();
816 self.data.read_array(range).ok().unwrap_or_default()
817 }
818
819 pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset16>
821 where
822 T: FontRead<'a, Args = ()>,
823 {
824 let data = self.data;
825 let offsets = self.lookup_offsets();
826 ArrayOfOffsets::new(offsets, data, ())
827 }
828
829 pub fn lookup_count_byte_range(&self) -> Range<usize> {
830 let start = 0;
831 let end = start + u16::RAW_BYTE_LEN;
832 start..end
833 }
834
835 pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
836 let lookup_count = self.lookup_count();
837 let start = self.lookup_count_byte_range().end;
838 let end =
839 start + (transforms::to_usize(lookup_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
840 start..end
841 }
842}
843
844const _: () = assert!(FontData::default_data_long_enough(
845 LookupList::<()>::MIN_SIZE
846));
847
848impl<T> Default for LookupList<'_, T> {
849 fn default() -> Self {
850 Self {
851 data: FontData::default_table_data(),
852 offset_type: std::marker::PhantomData,
853 }
854 }
855}
856
857#[cfg(feature = "experimental_traverse")]
858impl<'a, T: FontRead<'a, Args = ()> + SomeTable<'a> + 'a> SomeTable<'a> for LookupList<'a, T> {
859 fn type_name(&self) -> &str {
860 "LookupList"
861 }
862 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
863 match idx {
864 0usize => Some(Field::new("lookup_count", self.lookup_count())),
865 1usize => Some(Field::new(
866 "lookup_offsets",
867 FieldType::from(self.lookups()),
868 )),
869 _ => None,
870 }
871 }
872}
873
874#[cfg(feature = "experimental_traverse")]
875#[allow(clippy::needless_lifetimes)]
876impl<'a, T: FontRead<'a, Args = ()> + SomeTable<'a> + 'a> std::fmt::Debug for LookupList<'a, T> {
877 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
878 (self as &dyn SomeTable<'a>).fmt(f)
879 }
880}
881
882impl Discriminant for Lookup<'_, ()> {
883 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
884 data.read_at(0)
885 }
886}
887
888impl<'a, T> MinByteRange<'a> for Lookup<'a, T> {
889 fn min_byte_range(&self) -> Range<usize> {
890 0..self.subtable_offsets_byte_range().end
891 }
892 fn min_table_bytes(&self) -> &'a [u8] {
893 let range = self.min_byte_range();
894 self.data.as_bytes().get(range).unwrap_or_default()
895 }
896}
897
898impl<T> ReadArgs for Lookup<'_, T> {
899 type Args = ();
900}
901
902impl<'a, T> FontRead<'a> for Lookup<'a, T> {
903 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
904 #[allow(clippy::absurd_extreme_comparisons)]
905 if data.len() < Self::MIN_SIZE {
906 return Err(ReadError::OutOfBounds);
907 }
908 Ok(Self {
909 data,
910 offset_type: std::marker::PhantomData,
911 })
912 }
913}
914
915impl<'a, T> Lookup<'a, T> {
916 #[allow(dead_code)]
917 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
919 Lookup {
920 data: self.data,
921 offset_type: std::marker::PhantomData,
922 }
923 }
924}
925
926#[derive(Clone)]
928pub struct Lookup<'a, T = ()> {
929 data: FontData<'a>,
930 offset_type: std::marker::PhantomData<*const T>,
931}
932
933#[allow(clippy::needless_lifetimes)]
934impl<'a, T> Lookup<'a, T> {
935 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + LookupFlag::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
936 basic_table_impls!(impl_the_methods);
937
938 pub fn lookup_type(&self) -> u16 {
940 let range = self.lookup_type_byte_range();
941 self.data.read_at(range.start).ok().unwrap()
942 }
943
944 pub fn lookup_flag(&self) -> LookupFlag {
946 let range = self.lookup_flag_byte_range();
947 self.data.read_at(range.start).ok().unwrap()
948 }
949
950 pub fn sub_table_count(&self) -> u16 {
952 let range = self.sub_table_count_byte_range();
953 self.data.read_at(range.start).ok().unwrap()
954 }
955
956 pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
959 let range = self.subtable_offsets_byte_range();
960 self.data.read_array(range).ok().unwrap_or_default()
961 }
962
963 pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
965 where
966 T: FontRead<'a, Args = ()>,
967 {
968 let data = self.data;
969 let offsets = self.subtable_offsets();
970 ArrayOfOffsets::new(offsets, data, ())
971 }
972
973 pub fn mark_filtering_set(&self) -> Option<u16> {
977 let range = self.mark_filtering_set_byte_range();
978 (!range.is_empty())
979 .then(|| self.data.read_at(range.start).ok())
980 .flatten()
981 }
982
983 pub fn lookup_type_byte_range(&self) -> Range<usize> {
984 let start = 0;
985 let end = start + u16::RAW_BYTE_LEN;
986 start..end
987 }
988
989 pub fn lookup_flag_byte_range(&self) -> Range<usize> {
990 let start = self.lookup_type_byte_range().end;
991 let end = start + LookupFlag::RAW_BYTE_LEN;
992 start..end
993 }
994
995 pub fn sub_table_count_byte_range(&self) -> Range<usize> {
996 let start = self.lookup_flag_byte_range().end;
997 let end = start + u16::RAW_BYTE_LEN;
998 start..end
999 }
1000
1001 pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
1002 let sub_table_count = self.sub_table_count();
1003 let start = self.sub_table_count_byte_range().end;
1004 let end =
1005 start + (transforms::to_usize(sub_table_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1006 start..end
1007 }
1008
1009 pub fn mark_filtering_set_byte_range(&self) -> Range<usize> {
1010 let start = self.subtable_offsets_byte_range().end;
1011 let end = if self
1012 .lookup_flag()
1013 .contains(LookupFlag::USE_MARK_FILTERING_SET)
1014 {
1015 start + u16::RAW_BYTE_LEN
1016 } else {
1017 start
1018 };
1019 start..end
1020 }
1021}
1022
1023const _: () = assert!(FontData::default_data_long_enough(Lookup::<()>::MIN_SIZE));
1024
1025impl<T> Default for Lookup<'_, T> {
1026 fn default() -> Self {
1027 Self {
1028 data: FontData::default_table_data(),
1029 offset_type: std::marker::PhantomData,
1030 }
1031 }
1032}
1033
1034#[cfg(feature = "experimental_traverse")]
1035impl<'a, T: FontRead<'a, Args = ()> + SomeTable<'a> + 'a> SomeTable<'a> for Lookup<'a, T> {
1036 fn type_name(&self) -> &str {
1037 "Lookup"
1038 }
1039 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1040 match idx {
1041 0usize => Some(Field::new("lookup_type", self.lookup_type())),
1042 1usize => Some(Field::new("lookup_flag", self.traverse_lookup_flag())),
1043 2usize => Some(Field::new("sub_table_count", self.sub_table_count())),
1044 3usize => Some(Field::new(
1045 "subtable_offsets",
1046 FieldType::from(self.subtables()),
1047 )),
1048 4usize
1049 if self
1050 .lookup_flag()
1051 .contains(LookupFlag::USE_MARK_FILTERING_SET) =>
1052 {
1053 Some(Field::new(
1054 "mark_filtering_set",
1055 self.mark_filtering_set().unwrap(),
1056 ))
1057 }
1058 _ => None,
1059 }
1060 }
1061}
1062
1063#[cfg(feature = "experimental_traverse")]
1064#[allow(clippy::needless_lifetimes)]
1065impl<'a, T: FontRead<'a, Args = ()> + SomeTable<'a> + 'a> std::fmt::Debug for Lookup<'a, T> {
1066 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1067 (self as &dyn SomeTable<'a>).fmt(f)
1068 }
1069}
1070
1071impl Format<u16> for CoverageFormat1<'_> {
1072 const FORMAT: u16 = 1;
1073}
1074
1075impl<'a> MinByteRange<'a> for CoverageFormat1<'a> {
1076 fn min_byte_range(&self) -> Range<usize> {
1077 0..self.glyph_array_byte_range().end
1078 }
1079 fn min_table_bytes(&self) -> &'a [u8] {
1080 let range = self.min_byte_range();
1081 self.data.as_bytes().get(range).unwrap_or_default()
1082 }
1083}
1084
1085impl ReadArgs for CoverageFormat1<'_> {
1086 type Args = ();
1087}
1088
1089impl<'a> FontRead<'a> for CoverageFormat1<'a> {
1090 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1091 #[allow(clippy::absurd_extreme_comparisons)]
1092 if data.len() < Self::MIN_SIZE {
1093 return Err(ReadError::OutOfBounds);
1094 }
1095 Ok(Self { data })
1096 }
1097}
1098
1099#[derive(Clone)]
1101pub struct CoverageFormat1<'a> {
1102 data: FontData<'a>,
1103}
1104
1105#[allow(clippy::needless_lifetimes)]
1106impl<'a> CoverageFormat1<'a> {
1107 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1108 basic_table_impls!(impl_the_methods);
1109
1110 pub fn coverage_format(&self) -> u16 {
1112 let range = self.coverage_format_byte_range();
1113 self.data.read_at(range.start).ok().unwrap()
1114 }
1115
1116 pub fn glyph_count(&self) -> u16 {
1118 let range = self.glyph_count_byte_range();
1119 self.data.read_at(range.start).ok().unwrap()
1120 }
1121
1122 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
1124 let range = self.glyph_array_byte_range();
1125 self.data.read_array(range).ok().unwrap_or_default()
1126 }
1127
1128 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1129 let start = 0;
1130 let end = start + u16::RAW_BYTE_LEN;
1131 start..end
1132 }
1133
1134 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1135 let start = self.coverage_format_byte_range().end;
1136 let end = start + u16::RAW_BYTE_LEN;
1137 start..end
1138 }
1139
1140 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1141 let glyph_count = self.glyph_count();
1142 let start = self.glyph_count_byte_range().end;
1143 let end =
1144 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1145 start..end
1146 }
1147}
1148
1149const _: () = assert!(FontData::default_data_long_enough(
1150 CoverageFormat1::MIN_SIZE
1151));
1152
1153impl Default for CoverageFormat1<'_> {
1154 fn default() -> Self {
1155 Self {
1156 data: FontData::default_format_1_u16_table_data(),
1157 }
1158 }
1159}
1160
1161#[cfg(feature = "experimental_traverse")]
1162impl<'a> SomeTable<'a> for CoverageFormat1<'a> {
1163 fn type_name(&self) -> &str {
1164 "CoverageFormat1"
1165 }
1166 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1167 match idx {
1168 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1169 1usize => Some(Field::new("glyph_count", self.glyph_count())),
1170 2usize => Some(Field::new("glyph_array", self.glyph_array())),
1171 _ => None,
1172 }
1173 }
1174}
1175
1176#[cfg(feature = "experimental_traverse")]
1177#[allow(clippy::needless_lifetimes)]
1178impl<'a> std::fmt::Debug for CoverageFormat1<'a> {
1179 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1180 (self as &dyn SomeTable<'a>).fmt(f)
1181 }
1182}
1183
1184impl Format<u16> for CoverageFormat2<'_> {
1185 const FORMAT: u16 = 2;
1186}
1187
1188impl<'a> MinByteRange<'a> for CoverageFormat2<'a> {
1189 fn min_byte_range(&self) -> Range<usize> {
1190 0..self.range_records_byte_range().end
1191 }
1192 fn min_table_bytes(&self) -> &'a [u8] {
1193 let range = self.min_byte_range();
1194 self.data.as_bytes().get(range).unwrap_or_default()
1195 }
1196}
1197
1198impl ReadArgs for CoverageFormat2<'_> {
1199 type Args = ();
1200}
1201
1202impl<'a> FontRead<'a> for CoverageFormat2<'a> {
1203 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1204 #[allow(clippy::absurd_extreme_comparisons)]
1205 if data.len() < Self::MIN_SIZE {
1206 return Err(ReadError::OutOfBounds);
1207 }
1208 Ok(Self { data })
1209 }
1210}
1211
1212#[derive(Clone)]
1214pub struct CoverageFormat2<'a> {
1215 data: FontData<'a>,
1216}
1217
1218#[allow(clippy::needless_lifetimes)]
1219impl<'a> CoverageFormat2<'a> {
1220 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1221 basic_table_impls!(impl_the_methods);
1222
1223 pub fn coverage_format(&self) -> u16 {
1225 let range = self.coverage_format_byte_range();
1226 self.data.read_at(range.start).ok().unwrap()
1227 }
1228
1229 pub fn range_count(&self) -> u16 {
1231 let range = self.range_count_byte_range();
1232 self.data.read_at(range.start).ok().unwrap()
1233 }
1234
1235 pub fn range_records(&self) -> &'a [RangeRecord] {
1237 let range = self.range_records_byte_range();
1238 self.data.read_array(range).ok().unwrap_or_default()
1239 }
1240
1241 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1242 let start = 0;
1243 let end = start + u16::RAW_BYTE_LEN;
1244 start..end
1245 }
1246
1247 pub fn range_count_byte_range(&self) -> Range<usize> {
1248 let start = self.coverage_format_byte_range().end;
1249 let end = start + u16::RAW_BYTE_LEN;
1250 start..end
1251 }
1252
1253 pub fn range_records_byte_range(&self) -> Range<usize> {
1254 let range_count = self.range_count();
1255 let start = self.range_count_byte_range().end;
1256 let end =
1257 start + (transforms::to_usize(range_count)).saturating_mul(RangeRecord::RAW_BYTE_LEN);
1258 start..end
1259 }
1260}
1261
1262#[cfg(feature = "experimental_traverse")]
1263impl<'a> SomeTable<'a> for CoverageFormat2<'a> {
1264 fn type_name(&self) -> &str {
1265 "CoverageFormat2"
1266 }
1267 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1268 match idx {
1269 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1270 1usize => Some(Field::new("range_count", self.range_count())),
1271 2usize => Some(Field::new(
1272 "range_records",
1273 traversal::FieldType::array_of_records(
1274 stringify!(RangeRecord),
1275 self.range_records(),
1276 self.offset_data(),
1277 ),
1278 )),
1279 _ => None,
1280 }
1281 }
1282}
1283
1284#[cfg(feature = "experimental_traverse")]
1285#[allow(clippy::needless_lifetimes)]
1286impl<'a> std::fmt::Debug for CoverageFormat2<'a> {
1287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1288 (self as &dyn SomeTable<'a>).fmt(f)
1289 }
1290}
1291
1292#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1294#[repr(C)]
1295#[repr(packed)]
1296pub struct RangeRecord {
1297 pub start_glyph_id: BigEndian<GlyphId16>,
1299 pub end_glyph_id: BigEndian<GlyphId16>,
1301 pub start_coverage_index: BigEndian<u16>,
1303}
1304
1305impl RangeRecord {
1306 pub fn start_glyph_id(&self) -> GlyphId16 {
1308 self.start_glyph_id.get()
1309 }
1310
1311 pub fn end_glyph_id(&self) -> GlyphId16 {
1313 self.end_glyph_id.get()
1314 }
1315
1316 pub fn start_coverage_index(&self) -> u16 {
1318 self.start_coverage_index.get()
1319 }
1320}
1321
1322impl FixedSize for RangeRecord {
1323 const RAW_BYTE_LEN: usize =
1324 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1325}
1326
1327#[cfg(feature = "experimental_traverse")]
1328impl<'a> SomeRecord<'a> for RangeRecord {
1329 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1330 RecordResolver {
1331 name: "RangeRecord",
1332 get_field: Box::new(move |idx, _data| match idx {
1333 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1334 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1335 2usize => Some(Field::new(
1336 "start_coverage_index",
1337 self.start_coverage_index(),
1338 )),
1339 _ => None,
1340 }),
1341 data,
1342 }
1343 }
1344}
1345
1346#[derive(Clone)]
1348pub enum CoverageTable<'a> {
1349 Format1(CoverageFormat1<'a>),
1350 Format2(CoverageFormat2<'a>),
1351}
1352
1353impl Default for CoverageTable<'_> {
1354 fn default() -> Self {
1355 Self::Format1(Default::default())
1356 }
1357}
1358
1359impl<'a> CoverageTable<'a> {
1360 pub fn offset_data(&self) -> FontData<'a> {
1362 match self {
1363 Self::Format1(item) => item.offset_data(),
1364 Self::Format2(item) => item.offset_data(),
1365 }
1366 }
1367
1368 pub fn coverage_format(&self) -> u16 {
1370 match self {
1371 Self::Format1(item) => item.coverage_format(),
1372 Self::Format2(item) => item.coverage_format(),
1373 }
1374 }
1375}
1376
1377impl ReadArgs for CoverageTable<'_> {
1378 type Args = ();
1379}
1380
1381impl<'a> FontRead<'a> for CoverageTable<'a> {
1382 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1383 let format: u16 = data.read_at(0usize)?;
1384 match format {
1385 CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1386 CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1387 other => Err(ReadError::InvalidFormat(other.into())),
1388 }
1389 }
1390}
1391
1392impl<'a> MinByteRange<'a> for CoverageTable<'a> {
1393 fn min_byte_range(&self) -> Range<usize> {
1394 match self {
1395 Self::Format1(item) => item.min_byte_range(),
1396 Self::Format2(item) => item.min_byte_range(),
1397 }
1398 }
1399 fn min_table_bytes(&self) -> &'a [u8] {
1400 match self {
1401 Self::Format1(item) => item.min_table_bytes(),
1402 Self::Format2(item) => item.min_table_bytes(),
1403 }
1404 }
1405}
1406
1407#[cfg(feature = "experimental_traverse")]
1408impl<'a> CoverageTable<'a> {
1409 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1410 match self {
1411 Self::Format1(table) => table,
1412 Self::Format2(table) => table,
1413 }
1414 }
1415}
1416
1417#[cfg(feature = "experimental_traverse")]
1418impl std::fmt::Debug for CoverageTable<'_> {
1419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1420 self.dyn_inner().fmt(f)
1421 }
1422}
1423
1424#[cfg(feature = "experimental_traverse")]
1425impl<'a> SomeTable<'a> for CoverageTable<'a> {
1426 fn type_name(&self) -> &str {
1427 self.dyn_inner().type_name()
1428 }
1429 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1430 self.dyn_inner().get_field(idx)
1431 }
1432}
1433
1434impl Format<u16> for ClassDefFormat1<'_> {
1435 const FORMAT: u16 = 1;
1436}
1437
1438impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
1439 fn min_byte_range(&self) -> Range<usize> {
1440 0..self.class_value_array_byte_range().end
1441 }
1442 fn min_table_bytes(&self) -> &'a [u8] {
1443 let range = self.min_byte_range();
1444 self.data.as_bytes().get(range).unwrap_or_default()
1445 }
1446}
1447
1448impl ReadArgs for ClassDefFormat1<'_> {
1449 type Args = ();
1450}
1451
1452impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1453 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1454 #[allow(clippy::absurd_extreme_comparisons)]
1455 if data.len() < Self::MIN_SIZE {
1456 return Err(ReadError::OutOfBounds);
1457 }
1458 Ok(Self { data })
1459 }
1460}
1461
1462#[derive(Clone)]
1464pub struct ClassDefFormat1<'a> {
1465 data: FontData<'a>,
1466}
1467
1468#[allow(clippy::needless_lifetimes)]
1469impl<'a> ClassDefFormat1<'a> {
1470 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1471 basic_table_impls!(impl_the_methods);
1472
1473 pub fn class_format(&self) -> u16 {
1475 let range = self.class_format_byte_range();
1476 self.data.read_at(range.start).ok().unwrap()
1477 }
1478
1479 pub fn start_glyph_id(&self) -> GlyphId16 {
1481 let range = self.start_glyph_id_byte_range();
1482 self.data.read_at(range.start).ok().unwrap()
1483 }
1484
1485 pub fn glyph_count(&self) -> u16 {
1487 let range = self.glyph_count_byte_range();
1488 self.data.read_at(range.start).ok().unwrap()
1489 }
1490
1491 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1493 let range = self.class_value_array_byte_range();
1494 self.data.read_array(range).ok().unwrap_or_default()
1495 }
1496
1497 pub fn class_format_byte_range(&self) -> Range<usize> {
1498 let start = 0;
1499 let end = start + u16::RAW_BYTE_LEN;
1500 start..end
1501 }
1502
1503 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1504 let start = self.class_format_byte_range().end;
1505 let end = start + GlyphId16::RAW_BYTE_LEN;
1506 start..end
1507 }
1508
1509 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1510 let start = self.start_glyph_id_byte_range().end;
1511 let end = start + u16::RAW_BYTE_LEN;
1512 start..end
1513 }
1514
1515 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1516 let glyph_count = self.glyph_count();
1517 let start = self.glyph_count_byte_range().end;
1518 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
1519 start..end
1520 }
1521}
1522
1523const _: () = assert!(FontData::default_data_long_enough(
1524 ClassDefFormat1::MIN_SIZE
1525));
1526
1527impl Default for ClassDefFormat1<'_> {
1528 fn default() -> Self {
1529 Self {
1530 data: FontData::default_format_1_u16_table_data(),
1531 }
1532 }
1533}
1534
1535#[cfg(feature = "experimental_traverse")]
1536impl<'a> SomeTable<'a> for ClassDefFormat1<'a> {
1537 fn type_name(&self) -> &str {
1538 "ClassDefFormat1"
1539 }
1540 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1541 match idx {
1542 0usize => Some(Field::new("class_format", self.class_format())),
1543 1usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1544 2usize => Some(Field::new("glyph_count", self.glyph_count())),
1545 3usize => Some(Field::new("class_value_array", self.class_value_array())),
1546 _ => None,
1547 }
1548 }
1549}
1550
1551#[cfg(feature = "experimental_traverse")]
1552#[allow(clippy::needless_lifetimes)]
1553impl<'a> std::fmt::Debug for ClassDefFormat1<'a> {
1554 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1555 (self as &dyn SomeTable<'a>).fmt(f)
1556 }
1557}
1558
1559impl Format<u16> for ClassDefFormat2<'_> {
1560 const FORMAT: u16 = 2;
1561}
1562
1563impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
1564 fn min_byte_range(&self) -> Range<usize> {
1565 0..self.class_range_records_byte_range().end
1566 }
1567 fn min_table_bytes(&self) -> &'a [u8] {
1568 let range = self.min_byte_range();
1569 self.data.as_bytes().get(range).unwrap_or_default()
1570 }
1571}
1572
1573impl ReadArgs for ClassDefFormat2<'_> {
1574 type Args = ();
1575}
1576
1577impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1578 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1579 #[allow(clippy::absurd_extreme_comparisons)]
1580 if data.len() < Self::MIN_SIZE {
1581 return Err(ReadError::OutOfBounds);
1582 }
1583 Ok(Self { data })
1584 }
1585}
1586
1587#[derive(Clone)]
1589pub struct ClassDefFormat2<'a> {
1590 data: FontData<'a>,
1591}
1592
1593#[allow(clippy::needless_lifetimes)]
1594impl<'a> ClassDefFormat2<'a> {
1595 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1596 basic_table_impls!(impl_the_methods);
1597
1598 pub fn class_format(&self) -> u16 {
1600 let range = self.class_format_byte_range();
1601 self.data.read_at(range.start).ok().unwrap()
1602 }
1603
1604 pub fn class_range_count(&self) -> u16 {
1606 let range = self.class_range_count_byte_range();
1607 self.data.read_at(range.start).ok().unwrap()
1608 }
1609
1610 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1612 let range = self.class_range_records_byte_range();
1613 self.data.read_array(range).ok().unwrap_or_default()
1614 }
1615
1616 pub fn class_format_byte_range(&self) -> Range<usize> {
1617 let start = 0;
1618 let end = start + u16::RAW_BYTE_LEN;
1619 start..end
1620 }
1621
1622 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1623 let start = self.class_format_byte_range().end;
1624 let end = start + u16::RAW_BYTE_LEN;
1625 start..end
1626 }
1627
1628 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1629 let class_range_count = self.class_range_count();
1630 let start = self.class_range_count_byte_range().end;
1631 let end = start
1632 + (transforms::to_usize(class_range_count))
1633 .saturating_mul(ClassRangeRecord::RAW_BYTE_LEN);
1634 start..end
1635 }
1636}
1637
1638#[cfg(feature = "experimental_traverse")]
1639impl<'a> SomeTable<'a> for ClassDefFormat2<'a> {
1640 fn type_name(&self) -> &str {
1641 "ClassDefFormat2"
1642 }
1643 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1644 match idx {
1645 0usize => Some(Field::new("class_format", self.class_format())),
1646 1usize => Some(Field::new("class_range_count", self.class_range_count())),
1647 2usize => Some(Field::new(
1648 "class_range_records",
1649 traversal::FieldType::array_of_records(
1650 stringify!(ClassRangeRecord),
1651 self.class_range_records(),
1652 self.offset_data(),
1653 ),
1654 )),
1655 _ => None,
1656 }
1657 }
1658}
1659
1660#[cfg(feature = "experimental_traverse")]
1661#[allow(clippy::needless_lifetimes)]
1662impl<'a> std::fmt::Debug for ClassDefFormat2<'a> {
1663 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1664 (self as &dyn SomeTable<'a>).fmt(f)
1665 }
1666}
1667
1668#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1670#[repr(C)]
1671#[repr(packed)]
1672pub struct ClassRangeRecord {
1673 pub start_glyph_id: BigEndian<GlyphId16>,
1675 pub end_glyph_id: BigEndian<GlyphId16>,
1677 pub class: BigEndian<u16>,
1679}
1680
1681impl ClassRangeRecord {
1682 pub fn start_glyph_id(&self) -> GlyphId16 {
1684 self.start_glyph_id.get()
1685 }
1686
1687 pub fn end_glyph_id(&self) -> GlyphId16 {
1689 self.end_glyph_id.get()
1690 }
1691
1692 pub fn class(&self) -> u16 {
1694 self.class.get()
1695 }
1696}
1697
1698impl FixedSize for ClassRangeRecord {
1699 const RAW_BYTE_LEN: usize =
1700 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1701}
1702
1703#[cfg(feature = "experimental_traverse")]
1704impl<'a> SomeRecord<'a> for ClassRangeRecord {
1705 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1706 RecordResolver {
1707 name: "ClassRangeRecord",
1708 get_field: Box::new(move |idx, _data| match idx {
1709 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1710 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1711 2usize => Some(Field::new("class", self.class())),
1712 _ => None,
1713 }),
1714 data,
1715 }
1716 }
1717}
1718
1719#[derive(Clone)]
1721pub enum ClassDef<'a> {
1722 Format1(ClassDefFormat1<'a>),
1723 Format2(ClassDefFormat2<'a>),
1724}
1725
1726impl Default for ClassDef<'_> {
1727 fn default() -> Self {
1728 Self::Format1(Default::default())
1729 }
1730}
1731
1732impl<'a> ClassDef<'a> {
1733 pub fn offset_data(&self) -> FontData<'a> {
1735 match self {
1736 Self::Format1(item) => item.offset_data(),
1737 Self::Format2(item) => item.offset_data(),
1738 }
1739 }
1740
1741 pub fn class_format(&self) -> u16 {
1743 match self {
1744 Self::Format1(item) => item.class_format(),
1745 Self::Format2(item) => item.class_format(),
1746 }
1747 }
1748}
1749
1750impl ReadArgs for ClassDef<'_> {
1751 type Args = ();
1752}
1753
1754impl<'a> FontRead<'a> for ClassDef<'a> {
1755 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1756 let format: u16 = data.read_at(0usize)?;
1757 match format {
1758 ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1759 ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1760 other => Err(ReadError::InvalidFormat(other.into())),
1761 }
1762 }
1763}
1764
1765impl<'a> MinByteRange<'a> for ClassDef<'a> {
1766 fn min_byte_range(&self) -> Range<usize> {
1767 match self {
1768 Self::Format1(item) => item.min_byte_range(),
1769 Self::Format2(item) => item.min_byte_range(),
1770 }
1771 }
1772 fn min_table_bytes(&self) -> &'a [u8] {
1773 match self {
1774 Self::Format1(item) => item.min_table_bytes(),
1775 Self::Format2(item) => item.min_table_bytes(),
1776 }
1777 }
1778}
1779
1780#[cfg(feature = "experimental_traverse")]
1781impl<'a> ClassDef<'a> {
1782 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1783 match self {
1784 Self::Format1(table) => table,
1785 Self::Format2(table) => table,
1786 }
1787 }
1788}
1789
1790#[cfg(feature = "experimental_traverse")]
1791impl std::fmt::Debug for ClassDef<'_> {
1792 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1793 self.dyn_inner().fmt(f)
1794 }
1795}
1796
1797#[cfg(feature = "experimental_traverse")]
1798impl<'a> SomeTable<'a> for ClassDef<'a> {
1799 fn type_name(&self) -> &str {
1800 self.dyn_inner().type_name()
1801 }
1802 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1803 self.dyn_inner().get_field(idx)
1804 }
1805}
1806
1807#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1809#[repr(C)]
1810#[repr(packed)]
1811pub struct SequenceLookupRecord {
1812 pub sequence_index: BigEndian<u16>,
1814 pub lookup_list_index: BigEndian<u16>,
1816}
1817
1818impl SequenceLookupRecord {
1819 pub fn sequence_index(&self) -> u16 {
1821 self.sequence_index.get()
1822 }
1823
1824 pub fn lookup_list_index(&self) -> u16 {
1826 self.lookup_list_index.get()
1827 }
1828}
1829
1830impl FixedSize for SequenceLookupRecord {
1831 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1832}
1833
1834#[cfg(feature = "experimental_traverse")]
1835impl<'a> SomeRecord<'a> for SequenceLookupRecord {
1836 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1837 RecordResolver {
1838 name: "SequenceLookupRecord",
1839 get_field: Box::new(move |idx, _data| match idx {
1840 0usize => Some(Field::new("sequence_index", self.sequence_index())),
1841 1usize => Some(Field::new("lookup_list_index", self.lookup_list_index())),
1842 _ => None,
1843 }),
1844 data,
1845 }
1846 }
1847}
1848
1849impl Format<u16> for SequenceContextFormat1<'_> {
1850 const FORMAT: u16 = 1;
1851}
1852
1853impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
1854 fn min_byte_range(&self) -> Range<usize> {
1855 0..self.seq_rule_set_offsets_byte_range().end
1856 }
1857 fn min_table_bytes(&self) -> &'a [u8] {
1858 let range = self.min_byte_range();
1859 self.data.as_bytes().get(range).unwrap_or_default()
1860 }
1861}
1862
1863impl ReadArgs for SequenceContextFormat1<'_> {
1864 type Args = ();
1865}
1866
1867impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1868 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1869 #[allow(clippy::absurd_extreme_comparisons)]
1870 if data.len() < Self::MIN_SIZE {
1871 return Err(ReadError::OutOfBounds);
1872 }
1873 Ok(Self { data })
1874 }
1875}
1876
1877#[derive(Clone)]
1879pub struct SequenceContextFormat1<'a> {
1880 data: FontData<'a>,
1881}
1882
1883#[allow(clippy::needless_lifetimes)]
1884impl<'a> SequenceContextFormat1<'a> {
1885 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1886 basic_table_impls!(impl_the_methods);
1887
1888 pub fn format(&self) -> u16 {
1890 let range = self.format_byte_range();
1891 self.data.read_at(range.start).ok().unwrap()
1892 }
1893
1894 pub fn coverage_offset(&self) -> Offset16 {
1897 let range = self.coverage_offset_byte_range();
1898 self.data.read_at(range.start).ok().unwrap()
1899 }
1900
1901 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1903 let data = self.data;
1904 self.coverage_offset().resolve(data)
1905 }
1906
1907 pub fn seq_rule_set_count(&self) -> u16 {
1909 let range = self.seq_rule_set_count_byte_range();
1910 self.data.read_at(range.start).ok().unwrap()
1911 }
1912
1913 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1916 let range = self.seq_rule_set_offsets_byte_range();
1917 self.data.read_array(range).ok().unwrap_or_default()
1918 }
1919
1920 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1922 let data = self.data;
1923 let offsets = self.seq_rule_set_offsets();
1924 ArrayOfNullableOffsets::new(offsets, data, ())
1925 }
1926
1927 pub fn format_byte_range(&self) -> Range<usize> {
1928 let start = 0;
1929 let end = start + u16::RAW_BYTE_LEN;
1930 start..end
1931 }
1932
1933 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1934 let start = self.format_byte_range().end;
1935 let end = start + Offset16::RAW_BYTE_LEN;
1936 start..end
1937 }
1938
1939 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1940 let start = self.coverage_offset_byte_range().end;
1941 let end = start + u16::RAW_BYTE_LEN;
1942 start..end
1943 }
1944
1945 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1946 let seq_rule_set_count = self.seq_rule_set_count();
1947 let start = self.seq_rule_set_count_byte_range().end;
1948 let end = start
1949 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1950 start..end
1951 }
1952}
1953
1954const _: () = assert!(FontData::default_data_long_enough(
1955 SequenceContextFormat1::MIN_SIZE
1956));
1957
1958impl Default for SequenceContextFormat1<'_> {
1959 fn default() -> Self {
1960 Self {
1961 data: FontData::default_format_1_u16_table_data(),
1962 }
1963 }
1964}
1965
1966#[cfg(feature = "experimental_traverse")]
1967impl<'a> SomeTable<'a> for SequenceContextFormat1<'a> {
1968 fn type_name(&self) -> &str {
1969 "SequenceContextFormat1"
1970 }
1971 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1972 match idx {
1973 0usize => Some(Field::new("format", self.format())),
1974 1usize => Some(Field::new(
1975 "coverage_offset",
1976 FieldType::offset(self.coverage_offset(), self.coverage()),
1977 )),
1978 2usize => Some(Field::new("seq_rule_set_count", self.seq_rule_set_count())),
1979 3usize => Some(Field::new(
1980 "seq_rule_set_offsets",
1981 FieldType::from(self.seq_rule_sets()),
1982 )),
1983 _ => None,
1984 }
1985 }
1986}
1987
1988#[cfg(feature = "experimental_traverse")]
1989#[allow(clippy::needless_lifetimes)]
1990impl<'a> std::fmt::Debug for SequenceContextFormat1<'a> {
1991 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1992 (self as &dyn SomeTable<'a>).fmt(f)
1993 }
1994}
1995
1996impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
1997 fn min_byte_range(&self) -> Range<usize> {
1998 0..self.seq_rule_offsets_byte_range().end
1999 }
2000 fn min_table_bytes(&self) -> &'a [u8] {
2001 let range = self.min_byte_range();
2002 self.data.as_bytes().get(range).unwrap_or_default()
2003 }
2004}
2005
2006impl ReadArgs for SequenceRuleSet<'_> {
2007 type Args = ();
2008}
2009
2010impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
2011 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2012 #[allow(clippy::absurd_extreme_comparisons)]
2013 if data.len() < Self::MIN_SIZE {
2014 return Err(ReadError::OutOfBounds);
2015 }
2016 Ok(Self { data })
2017 }
2018}
2019
2020#[derive(Clone)]
2022pub struct SequenceRuleSet<'a> {
2023 data: FontData<'a>,
2024}
2025
2026#[allow(clippy::needless_lifetimes)]
2027impl<'a> SequenceRuleSet<'a> {
2028 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2029 basic_table_impls!(impl_the_methods);
2030
2031 pub fn seq_rule_count(&self) -> u16 {
2033 let range = self.seq_rule_count_byte_range();
2034 self.data.read_at(range.start).ok().unwrap()
2035 }
2036
2037 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2040 let range = self.seq_rule_offsets_byte_range();
2041 self.data.read_array(range).ok().unwrap_or_default()
2042 }
2043
2044 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
2046 let data = self.data;
2047 let offsets = self.seq_rule_offsets();
2048 ArrayOfOffsets::new(offsets, data, ())
2049 }
2050
2051 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
2052 let start = 0;
2053 let end = start + u16::RAW_BYTE_LEN;
2054 start..end
2055 }
2056
2057 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
2058 let seq_rule_count = self.seq_rule_count();
2059 let start = self.seq_rule_count_byte_range().end;
2060 let end =
2061 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2062 start..end
2063 }
2064}
2065
2066const _: () = assert!(FontData::default_data_long_enough(
2067 SequenceRuleSet::MIN_SIZE
2068));
2069
2070impl Default for SequenceRuleSet<'_> {
2071 fn default() -> Self {
2072 Self {
2073 data: FontData::default_table_data(),
2074 }
2075 }
2076}
2077
2078#[cfg(feature = "experimental_traverse")]
2079impl<'a> SomeTable<'a> for SequenceRuleSet<'a> {
2080 fn type_name(&self) -> &str {
2081 "SequenceRuleSet"
2082 }
2083 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2084 match idx {
2085 0usize => Some(Field::new("seq_rule_count", self.seq_rule_count())),
2086 1usize => Some(Field::new(
2087 "seq_rule_offsets",
2088 FieldType::from(self.seq_rules()),
2089 )),
2090 _ => None,
2091 }
2092 }
2093}
2094
2095#[cfg(feature = "experimental_traverse")]
2096#[allow(clippy::needless_lifetimes)]
2097impl<'a> std::fmt::Debug for SequenceRuleSet<'a> {
2098 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2099 (self as &dyn SomeTable<'a>).fmt(f)
2100 }
2101}
2102
2103impl<'a> MinByteRange<'a> for SequenceRule<'a> {
2104 fn min_byte_range(&self) -> Range<usize> {
2105 0..self.seq_lookup_records_byte_range().end
2106 }
2107 fn min_table_bytes(&self) -> &'a [u8] {
2108 let range = self.min_byte_range();
2109 self.data.as_bytes().get(range).unwrap_or_default()
2110 }
2111}
2112
2113impl ReadArgs for SequenceRule<'_> {
2114 type Args = ();
2115}
2116
2117impl<'a> FontRead<'a> for SequenceRule<'a> {
2118 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2119 #[allow(clippy::absurd_extreme_comparisons)]
2120 if data.len() < Self::MIN_SIZE {
2121 return Err(ReadError::OutOfBounds);
2122 }
2123 Ok(Self { data })
2124 }
2125}
2126
2127#[derive(Clone)]
2129pub struct SequenceRule<'a> {
2130 data: FontData<'a>,
2131}
2132
2133#[allow(clippy::needless_lifetimes)]
2134impl<'a> SequenceRule<'a> {
2135 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2136 basic_table_impls!(impl_the_methods);
2137
2138 pub fn glyph_count(&self) -> u16 {
2140 let range = self.glyph_count_byte_range();
2141 self.data.read_at(range.start).ok().unwrap()
2142 }
2143
2144 pub fn seq_lookup_count(&self) -> u16 {
2146 let range = self.seq_lookup_count_byte_range();
2147 self.data.read_at(range.start).ok().unwrap()
2148 }
2149
2150 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2152 let range = self.input_sequence_byte_range();
2153 self.data.read_array(range).ok().unwrap_or_default()
2154 }
2155
2156 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2158 let range = self.seq_lookup_records_byte_range();
2159 self.data.read_array(range).ok().unwrap_or_default()
2160 }
2161
2162 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2163 let start = 0;
2164 let end = start + u16::RAW_BYTE_LEN;
2165 start..end
2166 }
2167
2168 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2169 let start = self.glyph_count_byte_range().end;
2170 let end = start + u16::RAW_BYTE_LEN;
2171 start..end
2172 }
2173
2174 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2175 let glyph_count = self.glyph_count();
2176 let start = self.seq_lookup_count_byte_range().end;
2177 let end = start
2178 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2179 start..end
2180 }
2181
2182 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2183 let seq_lookup_count = self.seq_lookup_count();
2184 let start = self.input_sequence_byte_range().end;
2185 let end = start
2186 + (transforms::to_usize(seq_lookup_count))
2187 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2188 start..end
2189 }
2190}
2191
2192const _: () = assert!(FontData::default_data_long_enough(SequenceRule::MIN_SIZE));
2193
2194impl Default for SequenceRule<'_> {
2195 fn default() -> Self {
2196 Self {
2197 data: FontData::default_table_data(),
2198 }
2199 }
2200}
2201
2202#[cfg(feature = "experimental_traverse")]
2203impl<'a> SomeTable<'a> for SequenceRule<'a> {
2204 fn type_name(&self) -> &str {
2205 "SequenceRule"
2206 }
2207 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2208 match idx {
2209 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2210 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2211 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2212 3usize => Some(Field::new(
2213 "seq_lookup_records",
2214 traversal::FieldType::array_of_records(
2215 stringify!(SequenceLookupRecord),
2216 self.seq_lookup_records(),
2217 self.offset_data(),
2218 ),
2219 )),
2220 _ => None,
2221 }
2222 }
2223}
2224
2225#[cfg(feature = "experimental_traverse")]
2226#[allow(clippy::needless_lifetimes)]
2227impl<'a> std::fmt::Debug for SequenceRule<'a> {
2228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2229 (self as &dyn SomeTable<'a>).fmt(f)
2230 }
2231}
2232
2233impl Format<u16> for SequenceContextFormat2<'_> {
2234 const FORMAT: u16 = 2;
2235}
2236
2237impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
2238 fn min_byte_range(&self) -> Range<usize> {
2239 0..self.class_seq_rule_set_offsets_byte_range().end
2240 }
2241 fn min_table_bytes(&self) -> &'a [u8] {
2242 let range = self.min_byte_range();
2243 self.data.as_bytes().get(range).unwrap_or_default()
2244 }
2245}
2246
2247impl ReadArgs for SequenceContextFormat2<'_> {
2248 type Args = ();
2249}
2250
2251impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
2252 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2253 #[allow(clippy::absurd_extreme_comparisons)]
2254 if data.len() < Self::MIN_SIZE {
2255 return Err(ReadError::OutOfBounds);
2256 }
2257 Ok(Self { data })
2258 }
2259}
2260
2261#[derive(Clone)]
2263pub struct SequenceContextFormat2<'a> {
2264 data: FontData<'a>,
2265}
2266
2267#[allow(clippy::needless_lifetimes)]
2268impl<'a> SequenceContextFormat2<'a> {
2269 pub const MIN_SIZE: usize =
2270 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2271 basic_table_impls!(impl_the_methods);
2272
2273 pub fn format(&self) -> u16 {
2275 let range = self.format_byte_range();
2276 self.data.read_at(range.start).ok().unwrap()
2277 }
2278
2279 pub fn coverage_offset(&self) -> Offset16 {
2282 let range = self.coverage_offset_byte_range();
2283 self.data.read_at(range.start).ok().unwrap()
2284 }
2285
2286 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2288 let data = self.data;
2289 self.coverage_offset().resolve(data)
2290 }
2291
2292 pub fn class_def_offset(&self) -> Offset16 {
2295 let range = self.class_def_offset_byte_range();
2296 self.data.read_at(range.start).ok().unwrap()
2297 }
2298
2299 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2301 let data = self.data;
2302 self.class_def_offset().resolve(data)
2303 }
2304
2305 pub fn class_seq_rule_set_count(&self) -> u16 {
2307 let range = self.class_seq_rule_set_count_byte_range();
2308 self.data.read_at(range.start).ok().unwrap()
2309 }
2310
2311 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2314 let range = self.class_seq_rule_set_offsets_byte_range();
2315 self.data.read_array(range).ok().unwrap_or_default()
2316 }
2317
2318 pub fn class_seq_rule_sets(
2320 &self,
2321 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
2322 let data = self.data;
2323 let offsets = self.class_seq_rule_set_offsets();
2324 ArrayOfNullableOffsets::new(offsets, data, ())
2325 }
2326
2327 pub fn format_byte_range(&self) -> Range<usize> {
2328 let start = 0;
2329 let end = start + u16::RAW_BYTE_LEN;
2330 start..end
2331 }
2332
2333 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2334 let start = self.format_byte_range().end;
2335 let end = start + Offset16::RAW_BYTE_LEN;
2336 start..end
2337 }
2338
2339 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
2340 let start = self.coverage_offset_byte_range().end;
2341 let end = start + Offset16::RAW_BYTE_LEN;
2342 start..end
2343 }
2344
2345 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2346 let start = self.class_def_offset_byte_range().end;
2347 let end = start + u16::RAW_BYTE_LEN;
2348 start..end
2349 }
2350
2351 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2352 let class_seq_rule_set_count = self.class_seq_rule_set_count();
2353 let start = self.class_seq_rule_set_count_byte_range().end;
2354 let end = start
2355 + (transforms::to_usize(class_seq_rule_set_count))
2356 .saturating_mul(Offset16::RAW_BYTE_LEN);
2357 start..end
2358 }
2359}
2360
2361#[cfg(feature = "experimental_traverse")]
2362impl<'a> SomeTable<'a> for SequenceContextFormat2<'a> {
2363 fn type_name(&self) -> &str {
2364 "SequenceContextFormat2"
2365 }
2366 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2367 match idx {
2368 0usize => Some(Field::new("format", self.format())),
2369 1usize => Some(Field::new(
2370 "coverage_offset",
2371 FieldType::offset(self.coverage_offset(), self.coverage()),
2372 )),
2373 2usize => Some(Field::new(
2374 "class_def_offset",
2375 FieldType::offset(self.class_def_offset(), self.class_def()),
2376 )),
2377 3usize => Some(Field::new(
2378 "class_seq_rule_set_count",
2379 self.class_seq_rule_set_count(),
2380 )),
2381 4usize => Some(Field::new(
2382 "class_seq_rule_set_offsets",
2383 FieldType::from(self.class_seq_rule_sets()),
2384 )),
2385 _ => None,
2386 }
2387 }
2388}
2389
2390#[cfg(feature = "experimental_traverse")]
2391#[allow(clippy::needless_lifetimes)]
2392impl<'a> std::fmt::Debug for SequenceContextFormat2<'a> {
2393 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2394 (self as &dyn SomeTable<'a>).fmt(f)
2395 }
2396}
2397
2398impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
2399 fn min_byte_range(&self) -> Range<usize> {
2400 0..self.class_seq_rule_offsets_byte_range().end
2401 }
2402 fn min_table_bytes(&self) -> &'a [u8] {
2403 let range = self.min_byte_range();
2404 self.data.as_bytes().get(range).unwrap_or_default()
2405 }
2406}
2407
2408impl ReadArgs for ClassSequenceRuleSet<'_> {
2409 type Args = ();
2410}
2411
2412impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
2413 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2414 #[allow(clippy::absurd_extreme_comparisons)]
2415 if data.len() < Self::MIN_SIZE {
2416 return Err(ReadError::OutOfBounds);
2417 }
2418 Ok(Self { data })
2419 }
2420}
2421
2422#[derive(Clone)]
2424pub struct ClassSequenceRuleSet<'a> {
2425 data: FontData<'a>,
2426}
2427
2428#[allow(clippy::needless_lifetimes)]
2429impl<'a> ClassSequenceRuleSet<'a> {
2430 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2431 basic_table_impls!(impl_the_methods);
2432
2433 pub fn class_seq_rule_count(&self) -> u16 {
2435 let range = self.class_seq_rule_count_byte_range();
2436 self.data.read_at(range.start).ok().unwrap()
2437 }
2438
2439 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2442 let range = self.class_seq_rule_offsets_byte_range();
2443 self.data.read_array(range).ok().unwrap_or_default()
2444 }
2445
2446 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
2448 let data = self.data;
2449 let offsets = self.class_seq_rule_offsets();
2450 ArrayOfOffsets::new(offsets, data, ())
2451 }
2452
2453 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
2454 let start = 0;
2455 let end = start + u16::RAW_BYTE_LEN;
2456 start..end
2457 }
2458
2459 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2460 let class_seq_rule_count = self.class_seq_rule_count();
2461 let start = self.class_seq_rule_count_byte_range().end;
2462 let end = start
2463 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2464 start..end
2465 }
2466}
2467
2468const _: () = assert!(FontData::default_data_long_enough(
2469 ClassSequenceRuleSet::MIN_SIZE
2470));
2471
2472impl Default for ClassSequenceRuleSet<'_> {
2473 fn default() -> Self {
2474 Self {
2475 data: FontData::default_table_data(),
2476 }
2477 }
2478}
2479
2480#[cfg(feature = "experimental_traverse")]
2481impl<'a> SomeTable<'a> for ClassSequenceRuleSet<'a> {
2482 fn type_name(&self) -> &str {
2483 "ClassSequenceRuleSet"
2484 }
2485 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2486 match idx {
2487 0usize => Some(Field::new(
2488 "class_seq_rule_count",
2489 self.class_seq_rule_count(),
2490 )),
2491 1usize => Some(Field::new(
2492 "class_seq_rule_offsets",
2493 FieldType::from(self.class_seq_rules()),
2494 )),
2495 _ => None,
2496 }
2497 }
2498}
2499
2500#[cfg(feature = "experimental_traverse")]
2501#[allow(clippy::needless_lifetimes)]
2502impl<'a> std::fmt::Debug for ClassSequenceRuleSet<'a> {
2503 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2504 (self as &dyn SomeTable<'a>).fmt(f)
2505 }
2506}
2507
2508impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
2509 fn min_byte_range(&self) -> Range<usize> {
2510 0..self.seq_lookup_records_byte_range().end
2511 }
2512 fn min_table_bytes(&self) -> &'a [u8] {
2513 let range = self.min_byte_range();
2514 self.data.as_bytes().get(range).unwrap_or_default()
2515 }
2516}
2517
2518impl ReadArgs for ClassSequenceRule<'_> {
2519 type Args = ();
2520}
2521
2522impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
2523 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2524 #[allow(clippy::absurd_extreme_comparisons)]
2525 if data.len() < Self::MIN_SIZE {
2526 return Err(ReadError::OutOfBounds);
2527 }
2528 Ok(Self { data })
2529 }
2530}
2531
2532#[derive(Clone)]
2534pub struct ClassSequenceRule<'a> {
2535 data: FontData<'a>,
2536}
2537
2538#[allow(clippy::needless_lifetimes)]
2539impl<'a> ClassSequenceRule<'a> {
2540 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2541 basic_table_impls!(impl_the_methods);
2542
2543 pub fn glyph_count(&self) -> u16 {
2545 let range = self.glyph_count_byte_range();
2546 self.data.read_at(range.start).ok().unwrap()
2547 }
2548
2549 pub fn seq_lookup_count(&self) -> u16 {
2551 let range = self.seq_lookup_count_byte_range();
2552 self.data.read_at(range.start).ok().unwrap()
2553 }
2554
2555 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2558 let range = self.input_sequence_byte_range();
2559 self.data.read_array(range).ok().unwrap_or_default()
2560 }
2561
2562 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2564 let range = self.seq_lookup_records_byte_range();
2565 self.data.read_array(range).ok().unwrap_or_default()
2566 }
2567
2568 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2569 let start = 0;
2570 let end = start + u16::RAW_BYTE_LEN;
2571 start..end
2572 }
2573
2574 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2575 let start = self.glyph_count_byte_range().end;
2576 let end = start + u16::RAW_BYTE_LEN;
2577 start..end
2578 }
2579
2580 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2581 let glyph_count = self.glyph_count();
2582 let start = self.seq_lookup_count_byte_range().end;
2583 let end =
2584 start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
2585 start..end
2586 }
2587
2588 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2589 let seq_lookup_count = self.seq_lookup_count();
2590 let start = self.input_sequence_byte_range().end;
2591 let end = start
2592 + (transforms::to_usize(seq_lookup_count))
2593 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2594 start..end
2595 }
2596}
2597
2598const _: () = assert!(FontData::default_data_long_enough(
2599 ClassSequenceRule::MIN_SIZE
2600));
2601
2602impl Default for ClassSequenceRule<'_> {
2603 fn default() -> Self {
2604 Self {
2605 data: FontData::default_table_data(),
2606 }
2607 }
2608}
2609
2610#[cfg(feature = "experimental_traverse")]
2611impl<'a> SomeTable<'a> for ClassSequenceRule<'a> {
2612 fn type_name(&self) -> &str {
2613 "ClassSequenceRule"
2614 }
2615 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2616 match idx {
2617 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2618 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2619 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2620 3usize => Some(Field::new(
2621 "seq_lookup_records",
2622 traversal::FieldType::array_of_records(
2623 stringify!(SequenceLookupRecord),
2624 self.seq_lookup_records(),
2625 self.offset_data(),
2626 ),
2627 )),
2628 _ => None,
2629 }
2630 }
2631}
2632
2633#[cfg(feature = "experimental_traverse")]
2634#[allow(clippy::needless_lifetimes)]
2635impl<'a> std::fmt::Debug for ClassSequenceRule<'a> {
2636 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2637 (self as &dyn SomeTable<'a>).fmt(f)
2638 }
2639}
2640
2641impl Format<u16> for SequenceContextFormat3<'_> {
2642 const FORMAT: u16 = 3;
2643}
2644
2645impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
2646 fn min_byte_range(&self) -> Range<usize> {
2647 0..self.seq_lookup_records_byte_range().end
2648 }
2649 fn min_table_bytes(&self) -> &'a [u8] {
2650 let range = self.min_byte_range();
2651 self.data.as_bytes().get(range).unwrap_or_default()
2652 }
2653}
2654
2655impl ReadArgs for SequenceContextFormat3<'_> {
2656 type Args = ();
2657}
2658
2659impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2660 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2661 #[allow(clippy::absurd_extreme_comparisons)]
2662 if data.len() < Self::MIN_SIZE {
2663 return Err(ReadError::OutOfBounds);
2664 }
2665 Ok(Self { data })
2666 }
2667}
2668
2669#[derive(Clone)]
2671pub struct SequenceContextFormat3<'a> {
2672 data: FontData<'a>,
2673}
2674
2675#[allow(clippy::needless_lifetimes)]
2676impl<'a> SequenceContextFormat3<'a> {
2677 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2678 basic_table_impls!(impl_the_methods);
2679
2680 pub fn format(&self) -> u16 {
2682 let range = self.format_byte_range();
2683 self.data.read_at(range.start).ok().unwrap()
2684 }
2685
2686 pub fn glyph_count(&self) -> u16 {
2688 let range = self.glyph_count_byte_range();
2689 self.data.read_at(range.start).ok().unwrap()
2690 }
2691
2692 pub fn seq_lookup_count(&self) -> u16 {
2694 let range = self.seq_lookup_count_byte_range();
2695 self.data.read_at(range.start).ok().unwrap()
2696 }
2697
2698 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2701 let range = self.coverage_offsets_byte_range();
2702 self.data.read_array(range).ok().unwrap_or_default()
2703 }
2704
2705 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2707 let data = self.data;
2708 let offsets = self.coverage_offsets();
2709 ArrayOfOffsets::new(offsets, data, ())
2710 }
2711
2712 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2714 let range = self.seq_lookup_records_byte_range();
2715 self.data.read_array(range).ok().unwrap_or_default()
2716 }
2717
2718 pub fn format_byte_range(&self) -> Range<usize> {
2719 let start = 0;
2720 let end = start + u16::RAW_BYTE_LEN;
2721 start..end
2722 }
2723
2724 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2725 let start = self.format_byte_range().end;
2726 let end = start + u16::RAW_BYTE_LEN;
2727 start..end
2728 }
2729
2730 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2731 let start = self.glyph_count_byte_range().end;
2732 let end = start + u16::RAW_BYTE_LEN;
2733 start..end
2734 }
2735
2736 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2737 let glyph_count = self.glyph_count();
2738 let start = self.seq_lookup_count_byte_range().end;
2739 let end =
2740 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2741 start..end
2742 }
2743
2744 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2745 let seq_lookup_count = self.seq_lookup_count();
2746 let start = self.coverage_offsets_byte_range().end;
2747 let end = start
2748 + (transforms::to_usize(seq_lookup_count))
2749 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2750 start..end
2751 }
2752}
2753
2754#[cfg(feature = "experimental_traverse")]
2755impl<'a> SomeTable<'a> for SequenceContextFormat3<'a> {
2756 fn type_name(&self) -> &str {
2757 "SequenceContextFormat3"
2758 }
2759 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2760 match idx {
2761 0usize => Some(Field::new("format", self.format())),
2762 1usize => Some(Field::new("glyph_count", self.glyph_count())),
2763 2usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2764 3usize => Some(Field::new(
2765 "coverage_offsets",
2766 FieldType::from(self.coverages()),
2767 )),
2768 4usize => Some(Field::new(
2769 "seq_lookup_records",
2770 traversal::FieldType::array_of_records(
2771 stringify!(SequenceLookupRecord),
2772 self.seq_lookup_records(),
2773 self.offset_data(),
2774 ),
2775 )),
2776 _ => None,
2777 }
2778 }
2779}
2780
2781#[cfg(feature = "experimental_traverse")]
2782#[allow(clippy::needless_lifetimes)]
2783impl<'a> std::fmt::Debug for SequenceContextFormat3<'a> {
2784 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2785 (self as &dyn SomeTable<'a>).fmt(f)
2786 }
2787}
2788
2789#[derive(Clone)]
2790pub enum SequenceContext<'a> {
2791 Format1(SequenceContextFormat1<'a>),
2792 Format2(SequenceContextFormat2<'a>),
2793 Format3(SequenceContextFormat3<'a>),
2794}
2795
2796impl Default for SequenceContext<'_> {
2797 fn default() -> Self {
2798 Self::Format1(Default::default())
2799 }
2800}
2801
2802impl<'a> SequenceContext<'a> {
2803 pub fn offset_data(&self) -> FontData<'a> {
2805 match self {
2806 Self::Format1(item) => item.offset_data(),
2807 Self::Format2(item) => item.offset_data(),
2808 Self::Format3(item) => item.offset_data(),
2809 }
2810 }
2811
2812 pub fn format(&self) -> u16 {
2814 match self {
2815 Self::Format1(item) => item.format(),
2816 Self::Format2(item) => item.format(),
2817 Self::Format3(item) => item.format(),
2818 }
2819 }
2820}
2821
2822impl ReadArgs for SequenceContext<'_> {
2823 type Args = ();
2824}
2825
2826impl<'a> FontRead<'a> for SequenceContext<'a> {
2827 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2828 let format: u16 = data.read_at(0usize)?;
2829 match format {
2830 SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2831 SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2832 SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2833 other => Err(ReadError::InvalidFormat(other.into())),
2834 }
2835 }
2836}
2837
2838impl<'a> MinByteRange<'a> for SequenceContext<'a> {
2839 fn min_byte_range(&self) -> Range<usize> {
2840 match self {
2841 Self::Format1(item) => item.min_byte_range(),
2842 Self::Format2(item) => item.min_byte_range(),
2843 Self::Format3(item) => item.min_byte_range(),
2844 }
2845 }
2846 fn min_table_bytes(&self) -> &'a [u8] {
2847 match self {
2848 Self::Format1(item) => item.min_table_bytes(),
2849 Self::Format2(item) => item.min_table_bytes(),
2850 Self::Format3(item) => item.min_table_bytes(),
2851 }
2852 }
2853}
2854
2855#[cfg(feature = "experimental_traverse")]
2856impl<'a> SequenceContext<'a> {
2857 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
2858 match self {
2859 Self::Format1(table) => table,
2860 Self::Format2(table) => table,
2861 Self::Format3(table) => table,
2862 }
2863 }
2864}
2865
2866#[cfg(feature = "experimental_traverse")]
2867impl std::fmt::Debug for SequenceContext<'_> {
2868 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2869 self.dyn_inner().fmt(f)
2870 }
2871}
2872
2873#[cfg(feature = "experimental_traverse")]
2874impl<'a> SomeTable<'a> for SequenceContext<'a> {
2875 fn type_name(&self) -> &str {
2876 self.dyn_inner().type_name()
2877 }
2878 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2879 self.dyn_inner().get_field(idx)
2880 }
2881}
2882
2883impl Format<u16> for ChainedSequenceContextFormat1<'_> {
2884 const FORMAT: u16 = 1;
2885}
2886
2887impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
2888 fn min_byte_range(&self) -> Range<usize> {
2889 0..self.chained_seq_rule_set_offsets_byte_range().end
2890 }
2891 fn min_table_bytes(&self) -> &'a [u8] {
2892 let range = self.min_byte_range();
2893 self.data.as_bytes().get(range).unwrap_or_default()
2894 }
2895}
2896
2897impl ReadArgs for ChainedSequenceContextFormat1<'_> {
2898 type Args = ();
2899}
2900
2901impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2902 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2903 #[allow(clippy::absurd_extreme_comparisons)]
2904 if data.len() < Self::MIN_SIZE {
2905 return Err(ReadError::OutOfBounds);
2906 }
2907 Ok(Self { data })
2908 }
2909}
2910
2911#[derive(Clone)]
2913pub struct ChainedSequenceContextFormat1<'a> {
2914 data: FontData<'a>,
2915}
2916
2917#[allow(clippy::needless_lifetimes)]
2918impl<'a> ChainedSequenceContextFormat1<'a> {
2919 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2920 basic_table_impls!(impl_the_methods);
2921
2922 pub fn format(&self) -> u16 {
2924 let range = self.format_byte_range();
2925 self.data.read_at(range.start).ok().unwrap()
2926 }
2927
2928 pub fn coverage_offset(&self) -> Offset16 {
2931 let range = self.coverage_offset_byte_range();
2932 self.data.read_at(range.start).ok().unwrap()
2933 }
2934
2935 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2937 let data = self.data;
2938 self.coverage_offset().resolve(data)
2939 }
2940
2941 pub fn chained_seq_rule_set_count(&self) -> u16 {
2943 let range = self.chained_seq_rule_set_count_byte_range();
2944 self.data.read_at(range.start).ok().unwrap()
2945 }
2946
2947 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2950 let range = self.chained_seq_rule_set_offsets_byte_range();
2951 self.data.read_array(range).ok().unwrap_or_default()
2952 }
2953
2954 pub fn chained_seq_rule_sets(
2956 &self,
2957 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2958 let data = self.data;
2959 let offsets = self.chained_seq_rule_set_offsets();
2960 ArrayOfNullableOffsets::new(offsets, data, ())
2961 }
2962
2963 pub fn format_byte_range(&self) -> Range<usize> {
2964 let start = 0;
2965 let end = start + u16::RAW_BYTE_LEN;
2966 start..end
2967 }
2968
2969 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2970 let start = self.format_byte_range().end;
2971 let end = start + Offset16::RAW_BYTE_LEN;
2972 start..end
2973 }
2974
2975 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2976 let start = self.coverage_offset_byte_range().end;
2977 let end = start + u16::RAW_BYTE_LEN;
2978 start..end
2979 }
2980
2981 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2982 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
2983 let start = self.chained_seq_rule_set_count_byte_range().end;
2984 let end = start
2985 + (transforms::to_usize(chained_seq_rule_set_count))
2986 .saturating_mul(Offset16::RAW_BYTE_LEN);
2987 start..end
2988 }
2989}
2990
2991const _: () = assert!(FontData::default_data_long_enough(
2992 ChainedSequenceContextFormat1::MIN_SIZE
2993));
2994
2995impl Default for ChainedSequenceContextFormat1<'_> {
2996 fn default() -> Self {
2997 Self {
2998 data: FontData::default_format_1_u16_table_data(),
2999 }
3000 }
3001}
3002
3003#[cfg(feature = "experimental_traverse")]
3004impl<'a> SomeTable<'a> for ChainedSequenceContextFormat1<'a> {
3005 fn type_name(&self) -> &str {
3006 "ChainedSequenceContextFormat1"
3007 }
3008 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3009 match idx {
3010 0usize => Some(Field::new("format", self.format())),
3011 1usize => Some(Field::new(
3012 "coverage_offset",
3013 FieldType::offset(self.coverage_offset(), self.coverage()),
3014 )),
3015 2usize => Some(Field::new(
3016 "chained_seq_rule_set_count",
3017 self.chained_seq_rule_set_count(),
3018 )),
3019 3usize => Some(Field::new(
3020 "chained_seq_rule_set_offsets",
3021 FieldType::from(self.chained_seq_rule_sets()),
3022 )),
3023 _ => None,
3024 }
3025 }
3026}
3027
3028#[cfg(feature = "experimental_traverse")]
3029#[allow(clippy::needless_lifetimes)]
3030impl<'a> std::fmt::Debug for ChainedSequenceContextFormat1<'a> {
3031 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3032 (self as &dyn SomeTable<'a>).fmt(f)
3033 }
3034}
3035
3036impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
3037 fn min_byte_range(&self) -> Range<usize> {
3038 0..self.chained_seq_rule_offsets_byte_range().end
3039 }
3040 fn min_table_bytes(&self) -> &'a [u8] {
3041 let range = self.min_byte_range();
3042 self.data.as_bytes().get(range).unwrap_or_default()
3043 }
3044}
3045
3046impl ReadArgs for ChainedSequenceRuleSet<'_> {
3047 type Args = ();
3048}
3049
3050impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
3051 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3052 #[allow(clippy::absurd_extreme_comparisons)]
3053 if data.len() < Self::MIN_SIZE {
3054 return Err(ReadError::OutOfBounds);
3055 }
3056 Ok(Self { data })
3057 }
3058}
3059
3060#[derive(Clone)]
3062pub struct ChainedSequenceRuleSet<'a> {
3063 data: FontData<'a>,
3064}
3065
3066#[allow(clippy::needless_lifetimes)]
3067impl<'a> ChainedSequenceRuleSet<'a> {
3068 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3069 basic_table_impls!(impl_the_methods);
3070
3071 pub fn chained_seq_rule_count(&self) -> u16 {
3073 let range = self.chained_seq_rule_count_byte_range();
3074 self.data.read_at(range.start).ok().unwrap()
3075 }
3076
3077 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3080 let range = self.chained_seq_rule_offsets_byte_range();
3081 self.data.read_array(range).ok().unwrap_or_default()
3082 }
3083
3084 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
3086 let data = self.data;
3087 let offsets = self.chained_seq_rule_offsets();
3088 ArrayOfOffsets::new(offsets, data, ())
3089 }
3090
3091 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
3092 let start = 0;
3093 let end = start + u16::RAW_BYTE_LEN;
3094 start..end
3095 }
3096
3097 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3098 let chained_seq_rule_count = self.chained_seq_rule_count();
3099 let start = self.chained_seq_rule_count_byte_range().end;
3100 let end = start
3101 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3102 start..end
3103 }
3104}
3105
3106const _: () = assert!(FontData::default_data_long_enough(
3107 ChainedSequenceRuleSet::MIN_SIZE
3108));
3109
3110impl Default for ChainedSequenceRuleSet<'_> {
3111 fn default() -> Self {
3112 Self {
3113 data: FontData::default_table_data(),
3114 }
3115 }
3116}
3117
3118#[cfg(feature = "experimental_traverse")]
3119impl<'a> SomeTable<'a> for ChainedSequenceRuleSet<'a> {
3120 fn type_name(&self) -> &str {
3121 "ChainedSequenceRuleSet"
3122 }
3123 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3124 match idx {
3125 0usize => Some(Field::new(
3126 "chained_seq_rule_count",
3127 self.chained_seq_rule_count(),
3128 )),
3129 1usize => Some(Field::new(
3130 "chained_seq_rule_offsets",
3131 FieldType::from(self.chained_seq_rules()),
3132 )),
3133 _ => None,
3134 }
3135 }
3136}
3137
3138#[cfg(feature = "experimental_traverse")]
3139#[allow(clippy::needless_lifetimes)]
3140impl<'a> std::fmt::Debug for ChainedSequenceRuleSet<'a> {
3141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3142 (self as &dyn SomeTable<'a>).fmt(f)
3143 }
3144}
3145
3146impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
3147 fn min_byte_range(&self) -> Range<usize> {
3148 0..self.seq_lookup_records_byte_range().end
3149 }
3150 fn min_table_bytes(&self) -> &'a [u8] {
3151 let range = self.min_byte_range();
3152 self.data.as_bytes().get(range).unwrap_or_default()
3153 }
3154}
3155
3156impl ReadArgs for ChainedSequenceRule<'_> {
3157 type Args = ();
3158}
3159
3160impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
3161 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3162 #[allow(clippy::absurd_extreme_comparisons)]
3163 if data.len() < Self::MIN_SIZE {
3164 return Err(ReadError::OutOfBounds);
3165 }
3166 Ok(Self { data })
3167 }
3168}
3169
3170#[derive(Clone)]
3172pub struct ChainedSequenceRule<'a> {
3173 data: FontData<'a>,
3174}
3175
3176#[allow(clippy::needless_lifetimes)]
3177impl<'a> ChainedSequenceRule<'a> {
3178 pub const MIN_SIZE: usize =
3179 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3180 basic_table_impls!(impl_the_methods);
3181
3182 pub fn backtrack_glyph_count(&self) -> u16 {
3184 let range = self.backtrack_glyph_count_byte_range();
3185 self.data.read_at(range.start).ok().unwrap()
3186 }
3187
3188 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3190 let range = self.backtrack_sequence_byte_range();
3191 self.data.read_array(range).ok().unwrap_or_default()
3192 }
3193
3194 pub fn input_glyph_count(&self) -> u16 {
3196 let range = self.input_glyph_count_byte_range();
3197 self.data.read_at(range.start).ok().unwrap_or_default()
3198 }
3199
3200 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3202 let range = self.input_sequence_byte_range();
3203 self.data.read_array(range).ok().unwrap_or_default()
3204 }
3205
3206 pub fn lookahead_glyph_count(&self) -> u16 {
3208 let range = self.lookahead_glyph_count_byte_range();
3209 self.data.read_at(range.start).ok().unwrap_or_default()
3210 }
3211
3212 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3214 let range = self.lookahead_sequence_byte_range();
3215 self.data.read_array(range).ok().unwrap_or_default()
3216 }
3217
3218 pub fn seq_lookup_count(&self) -> u16 {
3220 let range = self.seq_lookup_count_byte_range();
3221 self.data.read_at(range.start).ok().unwrap_or_default()
3222 }
3223
3224 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3226 let range = self.seq_lookup_records_byte_range();
3227 self.data.read_array(range).ok().unwrap_or_default()
3228 }
3229
3230 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3231 let start = 0;
3232 let end = start + u16::RAW_BYTE_LEN;
3233 start..end
3234 }
3235
3236 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3237 let backtrack_glyph_count = self.backtrack_glyph_count();
3238 let start = self.backtrack_glyph_count_byte_range().end;
3239 let end = start
3240 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
3241 start..end
3242 }
3243
3244 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3245 let start = self.backtrack_sequence_byte_range().end;
3246 let end = start + u16::RAW_BYTE_LEN;
3247 start..end
3248 }
3249
3250 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3251 let input_glyph_count = self.input_glyph_count();
3252 let start = self.input_glyph_count_byte_range().end;
3253 let end = start
3254 + (transforms::subtract(input_glyph_count, 1_usize))
3255 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
3256 start..end
3257 }
3258
3259 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3260 let start = self.input_sequence_byte_range().end;
3261 let end = start + u16::RAW_BYTE_LEN;
3262 start..end
3263 }
3264
3265 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3266 let lookahead_glyph_count = self.lookahead_glyph_count();
3267 let start = self.lookahead_glyph_count_byte_range().end;
3268 let end = start
3269 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
3270 start..end
3271 }
3272
3273 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3274 let start = self.lookahead_sequence_byte_range().end;
3275 let end = start + u16::RAW_BYTE_LEN;
3276 start..end
3277 }
3278
3279 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3280 let seq_lookup_count = self.seq_lookup_count();
3281 let start = self.seq_lookup_count_byte_range().end;
3282 let end = start
3283 + (transforms::to_usize(seq_lookup_count))
3284 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3285 start..end
3286 }
3287}
3288
3289const _: () = assert!(FontData::default_data_long_enough(
3290 ChainedSequenceRule::MIN_SIZE
3291));
3292
3293impl Default for ChainedSequenceRule<'_> {
3294 fn default() -> Self {
3295 Self {
3296 data: FontData::default_table_data(),
3297 }
3298 }
3299}
3300
3301#[cfg(feature = "experimental_traverse")]
3302impl<'a> SomeTable<'a> for ChainedSequenceRule<'a> {
3303 fn type_name(&self) -> &str {
3304 "ChainedSequenceRule"
3305 }
3306 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3307 match idx {
3308 0usize => Some(Field::new(
3309 "backtrack_glyph_count",
3310 self.backtrack_glyph_count(),
3311 )),
3312 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3313 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3314 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3315 4usize => Some(Field::new(
3316 "lookahead_glyph_count",
3317 self.lookahead_glyph_count(),
3318 )),
3319 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3320 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3321 7usize => Some(Field::new(
3322 "seq_lookup_records",
3323 traversal::FieldType::array_of_records(
3324 stringify!(SequenceLookupRecord),
3325 self.seq_lookup_records(),
3326 self.offset_data(),
3327 ),
3328 )),
3329 _ => None,
3330 }
3331 }
3332}
3333
3334#[cfg(feature = "experimental_traverse")]
3335#[allow(clippy::needless_lifetimes)]
3336impl<'a> std::fmt::Debug for ChainedSequenceRule<'a> {
3337 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3338 (self as &dyn SomeTable<'a>).fmt(f)
3339 }
3340}
3341
3342impl Format<u16> for ChainedSequenceContextFormat2<'_> {
3343 const FORMAT: u16 = 2;
3344}
3345
3346impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
3347 fn min_byte_range(&self) -> Range<usize> {
3348 0..self.chained_class_seq_rule_set_offsets_byte_range().end
3349 }
3350 fn min_table_bytes(&self) -> &'a [u8] {
3351 let range = self.min_byte_range();
3352 self.data.as_bytes().get(range).unwrap_or_default()
3353 }
3354}
3355
3356impl ReadArgs for ChainedSequenceContextFormat2<'_> {
3357 type Args = ();
3358}
3359
3360impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
3361 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3362 #[allow(clippy::absurd_extreme_comparisons)]
3363 if data.len() < Self::MIN_SIZE {
3364 return Err(ReadError::OutOfBounds);
3365 }
3366 Ok(Self { data })
3367 }
3368}
3369
3370#[derive(Clone)]
3372pub struct ChainedSequenceContextFormat2<'a> {
3373 data: FontData<'a>,
3374}
3375
3376#[allow(clippy::needless_lifetimes)]
3377impl<'a> ChainedSequenceContextFormat2<'a> {
3378 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3379 + Offset16::RAW_BYTE_LEN
3380 + Offset16::RAW_BYTE_LEN
3381 + Offset16::RAW_BYTE_LEN
3382 + Offset16::RAW_BYTE_LEN
3383 + u16::RAW_BYTE_LEN);
3384 basic_table_impls!(impl_the_methods);
3385
3386 pub fn format(&self) -> u16 {
3388 let range = self.format_byte_range();
3389 self.data.read_at(range.start).ok().unwrap()
3390 }
3391
3392 pub fn coverage_offset(&self) -> Offset16 {
3395 let range = self.coverage_offset_byte_range();
3396 self.data.read_at(range.start).ok().unwrap()
3397 }
3398
3399 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3401 let data = self.data;
3402 self.coverage_offset().resolve(data)
3403 }
3404
3405 pub fn backtrack_class_def_offset(&self) -> Offset16 {
3408 let range = self.backtrack_class_def_offset_byte_range();
3409 self.data.read_at(range.start).ok().unwrap()
3410 }
3411
3412 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3414 let data = self.data;
3415 self.backtrack_class_def_offset().resolve(data)
3416 }
3417
3418 pub fn input_class_def_offset(&self) -> Offset16 {
3421 let range = self.input_class_def_offset_byte_range();
3422 self.data.read_at(range.start).ok().unwrap()
3423 }
3424
3425 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3427 let data = self.data;
3428 self.input_class_def_offset().resolve(data)
3429 }
3430
3431 pub fn lookahead_class_def_offset(&self) -> Offset16 {
3434 let range = self.lookahead_class_def_offset_byte_range();
3435 self.data.read_at(range.start).ok().unwrap()
3436 }
3437
3438 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3440 let data = self.data;
3441 self.lookahead_class_def_offset().resolve(data)
3442 }
3443
3444 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
3446 let range = self.chained_class_seq_rule_set_count_byte_range();
3447 self.data.read_at(range.start).ok().unwrap()
3448 }
3449
3450 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3453 let range = self.chained_class_seq_rule_set_offsets_byte_range();
3454 self.data.read_array(range).ok().unwrap_or_default()
3455 }
3456
3457 pub fn chained_class_seq_rule_sets(
3459 &self,
3460 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
3461 let data = self.data;
3462 let offsets = self.chained_class_seq_rule_set_offsets();
3463 ArrayOfNullableOffsets::new(offsets, data, ())
3464 }
3465
3466 pub fn format_byte_range(&self) -> Range<usize> {
3467 let start = 0;
3468 let end = start + u16::RAW_BYTE_LEN;
3469 start..end
3470 }
3471
3472 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
3473 let start = self.format_byte_range().end;
3474 let end = start + Offset16::RAW_BYTE_LEN;
3475 start..end
3476 }
3477
3478 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
3479 let start = self.coverage_offset_byte_range().end;
3480 let end = start + Offset16::RAW_BYTE_LEN;
3481 start..end
3482 }
3483
3484 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
3485 let start = self.backtrack_class_def_offset_byte_range().end;
3486 let end = start + Offset16::RAW_BYTE_LEN;
3487 start..end
3488 }
3489
3490 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
3491 let start = self.input_class_def_offset_byte_range().end;
3492 let end = start + Offset16::RAW_BYTE_LEN;
3493 start..end
3494 }
3495
3496 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
3497 let start = self.lookahead_class_def_offset_byte_range().end;
3498 let end = start + u16::RAW_BYTE_LEN;
3499 start..end
3500 }
3501
3502 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
3503 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
3504 let start = self.chained_class_seq_rule_set_count_byte_range().end;
3505 let end = start
3506 + (transforms::to_usize(chained_class_seq_rule_set_count))
3507 .saturating_mul(Offset16::RAW_BYTE_LEN);
3508 start..end
3509 }
3510}
3511
3512#[cfg(feature = "experimental_traverse")]
3513impl<'a> SomeTable<'a> for ChainedSequenceContextFormat2<'a> {
3514 fn type_name(&self) -> &str {
3515 "ChainedSequenceContextFormat2"
3516 }
3517 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3518 match idx {
3519 0usize => Some(Field::new("format", self.format())),
3520 1usize => Some(Field::new(
3521 "coverage_offset",
3522 FieldType::offset(self.coverage_offset(), self.coverage()),
3523 )),
3524 2usize => Some(Field::new(
3525 "backtrack_class_def_offset",
3526 FieldType::offset(
3527 self.backtrack_class_def_offset(),
3528 self.backtrack_class_def(),
3529 ),
3530 )),
3531 3usize => Some(Field::new(
3532 "input_class_def_offset",
3533 FieldType::offset(self.input_class_def_offset(), self.input_class_def()),
3534 )),
3535 4usize => Some(Field::new(
3536 "lookahead_class_def_offset",
3537 FieldType::offset(
3538 self.lookahead_class_def_offset(),
3539 self.lookahead_class_def(),
3540 ),
3541 )),
3542 5usize => Some(Field::new(
3543 "chained_class_seq_rule_set_count",
3544 self.chained_class_seq_rule_set_count(),
3545 )),
3546 6usize => Some(Field::new(
3547 "chained_class_seq_rule_set_offsets",
3548 FieldType::from(self.chained_class_seq_rule_sets()),
3549 )),
3550 _ => None,
3551 }
3552 }
3553}
3554
3555#[cfg(feature = "experimental_traverse")]
3556#[allow(clippy::needless_lifetimes)]
3557impl<'a> std::fmt::Debug for ChainedSequenceContextFormat2<'a> {
3558 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3559 (self as &dyn SomeTable<'a>).fmt(f)
3560 }
3561}
3562
3563impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
3564 fn min_byte_range(&self) -> Range<usize> {
3565 0..self.chained_class_seq_rule_offsets_byte_range().end
3566 }
3567 fn min_table_bytes(&self) -> &'a [u8] {
3568 let range = self.min_byte_range();
3569 self.data.as_bytes().get(range).unwrap_or_default()
3570 }
3571}
3572
3573impl ReadArgs for ChainedClassSequenceRuleSet<'_> {
3574 type Args = ();
3575}
3576
3577impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
3578 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3579 #[allow(clippy::absurd_extreme_comparisons)]
3580 if data.len() < Self::MIN_SIZE {
3581 return Err(ReadError::OutOfBounds);
3582 }
3583 Ok(Self { data })
3584 }
3585}
3586
3587#[derive(Clone)]
3589pub struct ChainedClassSequenceRuleSet<'a> {
3590 data: FontData<'a>,
3591}
3592
3593#[allow(clippy::needless_lifetimes)]
3594impl<'a> ChainedClassSequenceRuleSet<'a> {
3595 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3596 basic_table_impls!(impl_the_methods);
3597
3598 pub fn chained_class_seq_rule_count(&self) -> u16 {
3600 let range = self.chained_class_seq_rule_count_byte_range();
3601 self.data.read_at(range.start).ok().unwrap()
3602 }
3603
3604 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3607 let range = self.chained_class_seq_rule_offsets_byte_range();
3608 self.data.read_array(range).ok().unwrap_or_default()
3609 }
3610
3611 pub fn chained_class_seq_rules(
3613 &self,
3614 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
3615 let data = self.data;
3616 let offsets = self.chained_class_seq_rule_offsets();
3617 ArrayOfOffsets::new(offsets, data, ())
3618 }
3619
3620 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
3621 let start = 0;
3622 let end = start + u16::RAW_BYTE_LEN;
3623 start..end
3624 }
3625
3626 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3627 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
3628 let start = self.chained_class_seq_rule_count_byte_range().end;
3629 let end = start
3630 + (transforms::to_usize(chained_class_seq_rule_count))
3631 .saturating_mul(Offset16::RAW_BYTE_LEN);
3632 start..end
3633 }
3634}
3635
3636const _: () = assert!(FontData::default_data_long_enough(
3637 ChainedClassSequenceRuleSet::MIN_SIZE
3638));
3639
3640impl Default for ChainedClassSequenceRuleSet<'_> {
3641 fn default() -> Self {
3642 Self {
3643 data: FontData::default_table_data(),
3644 }
3645 }
3646}
3647
3648#[cfg(feature = "experimental_traverse")]
3649impl<'a> SomeTable<'a> for ChainedClassSequenceRuleSet<'a> {
3650 fn type_name(&self) -> &str {
3651 "ChainedClassSequenceRuleSet"
3652 }
3653 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3654 match idx {
3655 0usize => Some(Field::new(
3656 "chained_class_seq_rule_count",
3657 self.chained_class_seq_rule_count(),
3658 )),
3659 1usize => Some(Field::new(
3660 "chained_class_seq_rule_offsets",
3661 FieldType::from(self.chained_class_seq_rules()),
3662 )),
3663 _ => None,
3664 }
3665 }
3666}
3667
3668#[cfg(feature = "experimental_traverse")]
3669#[allow(clippy::needless_lifetimes)]
3670impl<'a> std::fmt::Debug for ChainedClassSequenceRuleSet<'a> {
3671 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3672 (self as &dyn SomeTable<'a>).fmt(f)
3673 }
3674}
3675
3676impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'a> {
3677 fn min_byte_range(&self) -> Range<usize> {
3678 0..self.seq_lookup_records_byte_range().end
3679 }
3680 fn min_table_bytes(&self) -> &'a [u8] {
3681 let range = self.min_byte_range();
3682 self.data.as_bytes().get(range).unwrap_or_default()
3683 }
3684}
3685
3686impl ReadArgs for ChainedClassSequenceRule<'_> {
3687 type Args = ();
3688}
3689
3690impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
3691 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3692 #[allow(clippy::absurd_extreme_comparisons)]
3693 if data.len() < Self::MIN_SIZE {
3694 return Err(ReadError::OutOfBounds);
3695 }
3696 Ok(Self { data })
3697 }
3698}
3699
3700#[derive(Clone)]
3702pub struct ChainedClassSequenceRule<'a> {
3703 data: FontData<'a>,
3704}
3705
3706#[allow(clippy::needless_lifetimes)]
3707impl<'a> ChainedClassSequenceRule<'a> {
3708 pub const MIN_SIZE: usize =
3709 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3710 basic_table_impls!(impl_the_methods);
3711
3712 pub fn backtrack_glyph_count(&self) -> u16 {
3714 let range = self.backtrack_glyph_count_byte_range();
3715 self.data.read_at(range.start).ok().unwrap()
3716 }
3717
3718 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
3720 let range = self.backtrack_sequence_byte_range();
3721 self.data.read_array(range).ok().unwrap_or_default()
3722 }
3723
3724 pub fn input_glyph_count(&self) -> u16 {
3726 let range = self.input_glyph_count_byte_range();
3727 self.data.read_at(range.start).ok().unwrap_or_default()
3728 }
3729
3730 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
3733 let range = self.input_sequence_byte_range();
3734 self.data.read_array(range).ok().unwrap_or_default()
3735 }
3736
3737 pub fn lookahead_glyph_count(&self) -> u16 {
3739 let range = self.lookahead_glyph_count_byte_range();
3740 self.data.read_at(range.start).ok().unwrap_or_default()
3741 }
3742
3743 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
3745 let range = self.lookahead_sequence_byte_range();
3746 self.data.read_array(range).ok().unwrap_or_default()
3747 }
3748
3749 pub fn seq_lookup_count(&self) -> u16 {
3751 let range = self.seq_lookup_count_byte_range();
3752 self.data.read_at(range.start).ok().unwrap_or_default()
3753 }
3754
3755 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3757 let range = self.seq_lookup_records_byte_range();
3758 self.data.read_array(range).ok().unwrap_or_default()
3759 }
3760
3761 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3762 let start = 0;
3763 let end = start + u16::RAW_BYTE_LEN;
3764 start..end
3765 }
3766
3767 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3768 let backtrack_glyph_count = self.backtrack_glyph_count();
3769 let start = self.backtrack_glyph_count_byte_range().end;
3770 let end =
3771 start + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3772 start..end
3773 }
3774
3775 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3776 let start = self.backtrack_sequence_byte_range().end;
3777 let end = start + u16::RAW_BYTE_LEN;
3778 start..end
3779 }
3780
3781 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3782 let input_glyph_count = self.input_glyph_count();
3783 let start = self.input_glyph_count_byte_range().end;
3784 let end = start
3785 + (transforms::subtract(input_glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
3786 start..end
3787 }
3788
3789 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3790 let start = self.input_sequence_byte_range().end;
3791 let end = start + u16::RAW_BYTE_LEN;
3792 start..end
3793 }
3794
3795 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3796 let lookahead_glyph_count = self.lookahead_glyph_count();
3797 let start = self.lookahead_glyph_count_byte_range().end;
3798 let end =
3799 start + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3800 start..end
3801 }
3802
3803 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3804 let start = self.lookahead_sequence_byte_range().end;
3805 let end = start + u16::RAW_BYTE_LEN;
3806 start..end
3807 }
3808
3809 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3810 let seq_lookup_count = self.seq_lookup_count();
3811 let start = self.seq_lookup_count_byte_range().end;
3812 let end = start
3813 + (transforms::to_usize(seq_lookup_count))
3814 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3815 start..end
3816 }
3817}
3818
3819const _: () = assert!(FontData::default_data_long_enough(
3820 ChainedClassSequenceRule::MIN_SIZE
3821));
3822
3823impl Default for ChainedClassSequenceRule<'_> {
3824 fn default() -> Self {
3825 Self {
3826 data: FontData::default_table_data(),
3827 }
3828 }
3829}
3830
3831#[cfg(feature = "experimental_traverse")]
3832impl<'a> SomeTable<'a> for ChainedClassSequenceRule<'a> {
3833 fn type_name(&self) -> &str {
3834 "ChainedClassSequenceRule"
3835 }
3836 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3837 match idx {
3838 0usize => Some(Field::new(
3839 "backtrack_glyph_count",
3840 self.backtrack_glyph_count(),
3841 )),
3842 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3843 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3844 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3845 4usize => Some(Field::new(
3846 "lookahead_glyph_count",
3847 self.lookahead_glyph_count(),
3848 )),
3849 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3850 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3851 7usize => Some(Field::new(
3852 "seq_lookup_records",
3853 traversal::FieldType::array_of_records(
3854 stringify!(SequenceLookupRecord),
3855 self.seq_lookup_records(),
3856 self.offset_data(),
3857 ),
3858 )),
3859 _ => None,
3860 }
3861 }
3862}
3863
3864#[cfg(feature = "experimental_traverse")]
3865#[allow(clippy::needless_lifetimes)]
3866impl<'a> std::fmt::Debug for ChainedClassSequenceRule<'a> {
3867 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3868 (self as &dyn SomeTable<'a>).fmt(f)
3869 }
3870}
3871
3872impl Format<u16> for ChainedSequenceContextFormat3<'_> {
3873 const FORMAT: u16 = 3;
3874}
3875
3876impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
3877 fn min_byte_range(&self) -> Range<usize> {
3878 0..self.seq_lookup_records_byte_range().end
3879 }
3880 fn min_table_bytes(&self) -> &'a [u8] {
3881 let range = self.min_byte_range();
3882 self.data.as_bytes().get(range).unwrap_or_default()
3883 }
3884}
3885
3886impl ReadArgs for ChainedSequenceContextFormat3<'_> {
3887 type Args = ();
3888}
3889
3890impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
3891 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3892 #[allow(clippy::absurd_extreme_comparisons)]
3893 if data.len() < Self::MIN_SIZE {
3894 return Err(ReadError::OutOfBounds);
3895 }
3896 Ok(Self { data })
3897 }
3898}
3899
3900#[derive(Clone)]
3902pub struct ChainedSequenceContextFormat3<'a> {
3903 data: FontData<'a>,
3904}
3905
3906#[allow(clippy::needless_lifetimes)]
3907impl<'a> ChainedSequenceContextFormat3<'a> {
3908 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3909 + u16::RAW_BYTE_LEN
3910 + u16::RAW_BYTE_LEN
3911 + u16::RAW_BYTE_LEN
3912 + u16::RAW_BYTE_LEN);
3913 basic_table_impls!(impl_the_methods);
3914
3915 pub fn format(&self) -> u16 {
3917 let range = self.format_byte_range();
3918 self.data.read_at(range.start).ok().unwrap()
3919 }
3920
3921 pub fn backtrack_glyph_count(&self) -> u16 {
3923 let range = self.backtrack_glyph_count_byte_range();
3924 self.data.read_at(range.start).ok().unwrap()
3925 }
3926
3927 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3929 let range = self.backtrack_coverage_offsets_byte_range();
3930 self.data.read_array(range).ok().unwrap_or_default()
3931 }
3932
3933 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3935 let data = self.data;
3936 let offsets = self.backtrack_coverage_offsets();
3937 ArrayOfOffsets::new(offsets, data, ())
3938 }
3939
3940 pub fn input_glyph_count(&self) -> u16 {
3942 let range = self.input_glyph_count_byte_range();
3943 self.data.read_at(range.start).ok().unwrap_or_default()
3944 }
3945
3946 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3948 let range = self.input_coverage_offsets_byte_range();
3949 self.data.read_array(range).ok().unwrap_or_default()
3950 }
3951
3952 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3954 let data = self.data;
3955 let offsets = self.input_coverage_offsets();
3956 ArrayOfOffsets::new(offsets, data, ())
3957 }
3958
3959 pub fn lookahead_glyph_count(&self) -> u16 {
3961 let range = self.lookahead_glyph_count_byte_range();
3962 self.data.read_at(range.start).ok().unwrap_or_default()
3963 }
3964
3965 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3967 let range = self.lookahead_coverage_offsets_byte_range();
3968 self.data.read_array(range).ok().unwrap_or_default()
3969 }
3970
3971 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3973 let data = self.data;
3974 let offsets = self.lookahead_coverage_offsets();
3975 ArrayOfOffsets::new(offsets, data, ())
3976 }
3977
3978 pub fn seq_lookup_count(&self) -> u16 {
3980 let range = self.seq_lookup_count_byte_range();
3981 self.data.read_at(range.start).ok().unwrap_or_default()
3982 }
3983
3984 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3986 let range = self.seq_lookup_records_byte_range();
3987 self.data.read_array(range).ok().unwrap_or_default()
3988 }
3989
3990 pub fn format_byte_range(&self) -> Range<usize> {
3991 let start = 0;
3992 let end = start + u16::RAW_BYTE_LEN;
3993 start..end
3994 }
3995
3996 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3997 let start = self.format_byte_range().end;
3998 let end = start + u16::RAW_BYTE_LEN;
3999 start..end
4000 }
4001
4002 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
4003 let backtrack_glyph_count = self.backtrack_glyph_count();
4004 let start = self.backtrack_glyph_count_byte_range().end;
4005 let end = start
4006 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4007 start..end
4008 }
4009
4010 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
4011 let start = self.backtrack_coverage_offsets_byte_range().end;
4012 let end = start + u16::RAW_BYTE_LEN;
4013 start..end
4014 }
4015
4016 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
4017 let input_glyph_count = self.input_glyph_count();
4018 let start = self.input_glyph_count_byte_range().end;
4019 let end = start
4020 + (transforms::to_usize(input_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4021 start..end
4022 }
4023
4024 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
4025 let start = self.input_coverage_offsets_byte_range().end;
4026 let end = start + u16::RAW_BYTE_LEN;
4027 start..end
4028 }
4029
4030 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
4031 let lookahead_glyph_count = self.lookahead_glyph_count();
4032 let start = self.lookahead_glyph_count_byte_range().end;
4033 let end = start
4034 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4035 start..end
4036 }
4037
4038 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
4039 let start = self.lookahead_coverage_offsets_byte_range().end;
4040 let end = start + u16::RAW_BYTE_LEN;
4041 start..end
4042 }
4043
4044 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
4045 let seq_lookup_count = self.seq_lookup_count();
4046 let start = self.seq_lookup_count_byte_range().end;
4047 let end = start
4048 + (transforms::to_usize(seq_lookup_count))
4049 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
4050 start..end
4051 }
4052}
4053
4054#[cfg(feature = "experimental_traverse")]
4055impl<'a> SomeTable<'a> for ChainedSequenceContextFormat3<'a> {
4056 fn type_name(&self) -> &str {
4057 "ChainedSequenceContextFormat3"
4058 }
4059 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4060 match idx {
4061 0usize => Some(Field::new("format", self.format())),
4062 1usize => Some(Field::new(
4063 "backtrack_glyph_count",
4064 self.backtrack_glyph_count(),
4065 )),
4066 2usize => Some(Field::new(
4067 "backtrack_coverage_offsets",
4068 FieldType::from(self.backtrack_coverages()),
4069 )),
4070 3usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
4071 4usize => Some(Field::new(
4072 "input_coverage_offsets",
4073 FieldType::from(self.input_coverages()),
4074 )),
4075 5usize => Some(Field::new(
4076 "lookahead_glyph_count",
4077 self.lookahead_glyph_count(),
4078 )),
4079 6usize => Some(Field::new(
4080 "lookahead_coverage_offsets",
4081 FieldType::from(self.lookahead_coverages()),
4082 )),
4083 7usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
4084 8usize => Some(Field::new(
4085 "seq_lookup_records",
4086 traversal::FieldType::array_of_records(
4087 stringify!(SequenceLookupRecord),
4088 self.seq_lookup_records(),
4089 self.offset_data(),
4090 ),
4091 )),
4092 _ => None,
4093 }
4094 }
4095}
4096
4097#[cfg(feature = "experimental_traverse")]
4098#[allow(clippy::needless_lifetimes)]
4099impl<'a> std::fmt::Debug for ChainedSequenceContextFormat3<'a> {
4100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4101 (self as &dyn SomeTable<'a>).fmt(f)
4102 }
4103}
4104
4105#[derive(Clone)]
4106pub enum ChainedSequenceContext<'a> {
4107 Format1(ChainedSequenceContextFormat1<'a>),
4108 Format2(ChainedSequenceContextFormat2<'a>),
4109 Format3(ChainedSequenceContextFormat3<'a>),
4110}
4111
4112impl Default for ChainedSequenceContext<'_> {
4113 fn default() -> Self {
4114 Self::Format1(Default::default())
4115 }
4116}
4117
4118impl<'a> ChainedSequenceContext<'a> {
4119 pub fn offset_data(&self) -> FontData<'a> {
4121 match self {
4122 Self::Format1(item) => item.offset_data(),
4123 Self::Format2(item) => item.offset_data(),
4124 Self::Format3(item) => item.offset_data(),
4125 }
4126 }
4127
4128 pub fn format(&self) -> u16 {
4130 match self {
4131 Self::Format1(item) => item.format(),
4132 Self::Format2(item) => item.format(),
4133 Self::Format3(item) => item.format(),
4134 }
4135 }
4136}
4137
4138impl ReadArgs for ChainedSequenceContext<'_> {
4139 type Args = ();
4140}
4141
4142impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
4143 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4144 let format: u16 = data.read_at(0usize)?;
4145 match format {
4146 ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
4147 ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
4148 ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
4149 other => Err(ReadError::InvalidFormat(other.into())),
4150 }
4151 }
4152}
4153
4154impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
4155 fn min_byte_range(&self) -> Range<usize> {
4156 match self {
4157 Self::Format1(item) => item.min_byte_range(),
4158 Self::Format2(item) => item.min_byte_range(),
4159 Self::Format3(item) => item.min_byte_range(),
4160 }
4161 }
4162 fn min_table_bytes(&self) -> &'a [u8] {
4163 match self {
4164 Self::Format1(item) => item.min_table_bytes(),
4165 Self::Format2(item) => item.min_table_bytes(),
4166 Self::Format3(item) => item.min_table_bytes(),
4167 }
4168 }
4169}
4170
4171#[cfg(feature = "experimental_traverse")]
4172impl<'a> ChainedSequenceContext<'a> {
4173 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4174 match self {
4175 Self::Format1(table) => table,
4176 Self::Format2(table) => table,
4177 Self::Format3(table) => table,
4178 }
4179 }
4180}
4181
4182#[cfg(feature = "experimental_traverse")]
4183impl std::fmt::Debug for ChainedSequenceContext<'_> {
4184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4185 self.dyn_inner().fmt(f)
4186 }
4187}
4188
4189#[cfg(feature = "experimental_traverse")]
4190impl<'a> SomeTable<'a> for ChainedSequenceContext<'a> {
4191 fn type_name(&self) -> &str {
4192 self.dyn_inner().type_name()
4193 }
4194 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4195 self.dyn_inner().get_field(idx)
4196 }
4197}
4198
4199#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
4202#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4203#[repr(u16)]
4204#[allow(clippy::manual_non_exhaustive)]
4205pub enum DeltaFormat {
4206 #[default]
4208 Local2BitDeltas = 0x0001,
4209 Local4BitDeltas = 0x0002,
4211 Local8BitDeltas = 0x0003,
4213 VariationIndex = 0x8000,
4215 #[doc(hidden)]
4216 Unknown,
4218}
4219
4220impl DeltaFormat {
4221 pub fn new(raw: u16) -> Self {
4225 match raw {
4226 0x0001 => Self::Local2BitDeltas,
4227 0x0002 => Self::Local4BitDeltas,
4228 0x0003 => Self::Local8BitDeltas,
4229 0x8000 => Self::VariationIndex,
4230 _ => Self::Unknown,
4231 }
4232 }
4233}
4234
4235impl font_types::Scalar for DeltaFormat {
4236 type Raw = <u16 as font_types::Scalar>::Raw;
4237 fn to_raw(self) -> Self::Raw {
4238 (self as u16).to_raw()
4239 }
4240 fn from_raw(raw: Self::Raw) -> Self {
4241 let t = <u16>::from_raw(raw);
4242 Self::new(t)
4243 }
4244}
4245
4246#[cfg(feature = "experimental_traverse")]
4247impl<'a> From<DeltaFormat> for FieldType<'a> {
4248 fn from(src: DeltaFormat) -> FieldType<'a> {
4249 (src as u16).into()
4250 }
4251}
4252
4253impl<'a> MinByteRange<'a> for Device<'a> {
4254 fn min_byte_range(&self) -> Range<usize> {
4255 0..self.delta_value_byte_range().end
4256 }
4257 fn min_table_bytes(&self) -> &'a [u8] {
4258 let range = self.min_byte_range();
4259 self.data.as_bytes().get(range).unwrap_or_default()
4260 }
4261}
4262
4263impl ReadArgs for Device<'_> {
4264 type Args = ();
4265}
4266
4267impl<'a> FontRead<'a> for Device<'a> {
4268 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4269 #[allow(clippy::absurd_extreme_comparisons)]
4270 if data.len() < Self::MIN_SIZE {
4271 return Err(ReadError::OutOfBounds);
4272 }
4273 Ok(Self { data })
4274 }
4275}
4276
4277#[derive(Clone)]
4279pub struct Device<'a> {
4280 data: FontData<'a>,
4281}
4282
4283#[allow(clippy::needless_lifetimes)]
4284impl<'a> Device<'a> {
4285 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
4286 basic_table_impls!(impl_the_methods);
4287
4288 pub fn start_size(&self) -> u16 {
4290 let range = self.start_size_byte_range();
4291 self.data.read_at(range.start).ok().unwrap()
4292 }
4293
4294 pub fn end_size(&self) -> u16 {
4296 let range = self.end_size_byte_range();
4297 self.data.read_at(range.start).ok().unwrap()
4298 }
4299
4300 pub fn delta_format(&self) -> DeltaFormat {
4302 let range = self.delta_format_byte_range();
4303 self.data.read_at(range.start).ok().unwrap()
4304 }
4305
4306 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
4308 let range = self.delta_value_byte_range();
4309 self.data.read_array(range).ok().unwrap_or_default()
4310 }
4311
4312 pub fn start_size_byte_range(&self) -> Range<usize> {
4313 let start = 0;
4314 let end = start + u16::RAW_BYTE_LEN;
4315 start..end
4316 }
4317
4318 pub fn end_size_byte_range(&self) -> Range<usize> {
4319 let start = self.start_size_byte_range().end;
4320 let end = start + u16::RAW_BYTE_LEN;
4321 start..end
4322 }
4323
4324 pub fn delta_format_byte_range(&self) -> Range<usize> {
4325 let start = self.end_size_byte_range().end;
4326 let end = start + DeltaFormat::RAW_BYTE_LEN;
4327 start..end
4328 }
4329
4330 pub fn delta_value_byte_range(&self) -> Range<usize> {
4331 let delta_format = self.delta_format();
4332 let start_size = self.start_size();
4333 let end_size = self.end_size();
4334 let start = self.delta_format_byte_range().end;
4335 let end = start
4336 + (DeltaFormat::value_count(delta_format, start_size, end_size))
4337 .saturating_mul(u16::RAW_BYTE_LEN);
4338 start..end
4339 }
4340}
4341
4342const _: () = assert!(FontData::default_data_long_enough(Device::MIN_SIZE));
4343
4344impl Default for Device<'_> {
4345 fn default() -> Self {
4346 Self {
4347 data: FontData::default_table_data(),
4348 }
4349 }
4350}
4351
4352#[cfg(feature = "experimental_traverse")]
4353impl<'a> SomeTable<'a> for Device<'a> {
4354 fn type_name(&self) -> &str {
4355 "Device"
4356 }
4357 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4358 match idx {
4359 0usize => Some(Field::new("start_size", self.start_size())),
4360 1usize => Some(Field::new("end_size", self.end_size())),
4361 2usize => Some(Field::new("delta_format", self.delta_format())),
4362 3usize => Some(Field::new("delta_value", self.delta_value())),
4363 _ => None,
4364 }
4365 }
4366}
4367
4368#[cfg(feature = "experimental_traverse")]
4369#[allow(clippy::needless_lifetimes)]
4370impl<'a> std::fmt::Debug for Device<'a> {
4371 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4372 (self as &dyn SomeTable<'a>).fmt(f)
4373 }
4374}
4375
4376impl<'a> MinByteRange<'a> for VariationIndex<'a> {
4377 fn min_byte_range(&self) -> Range<usize> {
4378 0..self.delta_format_byte_range().end
4379 }
4380 fn min_table_bytes(&self) -> &'a [u8] {
4381 let range = self.min_byte_range();
4382 self.data.as_bytes().get(range).unwrap_or_default()
4383 }
4384}
4385
4386impl ReadArgs for VariationIndex<'_> {
4387 type Args = ();
4388}
4389
4390impl<'a> FontRead<'a> for VariationIndex<'a> {
4391 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4392 #[allow(clippy::absurd_extreme_comparisons)]
4393 if data.len() < Self::MIN_SIZE {
4394 return Err(ReadError::OutOfBounds);
4395 }
4396 Ok(Self { data })
4397 }
4398}
4399
4400#[derive(Clone)]
4402pub struct VariationIndex<'a> {
4403 data: FontData<'a>,
4404}
4405
4406#[allow(clippy::needless_lifetimes)]
4407impl<'a> VariationIndex<'a> {
4408 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
4409 basic_table_impls!(impl_the_methods);
4410
4411 pub fn delta_set_outer_index(&self) -> u16 {
4414 let range = self.delta_set_outer_index_byte_range();
4415 self.data.read_at(range.start).ok().unwrap()
4416 }
4417
4418 pub fn delta_set_inner_index(&self) -> u16 {
4421 let range = self.delta_set_inner_index_byte_range();
4422 self.data.read_at(range.start).ok().unwrap()
4423 }
4424
4425 pub fn delta_format(&self) -> DeltaFormat {
4427 let range = self.delta_format_byte_range();
4428 self.data.read_at(range.start).ok().unwrap()
4429 }
4430
4431 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
4432 let start = 0;
4433 let end = start + u16::RAW_BYTE_LEN;
4434 start..end
4435 }
4436
4437 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
4438 let start = self.delta_set_outer_index_byte_range().end;
4439 let end = start + u16::RAW_BYTE_LEN;
4440 start..end
4441 }
4442
4443 pub fn delta_format_byte_range(&self) -> Range<usize> {
4444 let start = self.delta_set_inner_index_byte_range().end;
4445 let end = start + DeltaFormat::RAW_BYTE_LEN;
4446 start..end
4447 }
4448}
4449
4450const _: () = assert!(FontData::default_data_long_enough(VariationIndex::MIN_SIZE));
4451
4452impl Default for VariationIndex<'_> {
4453 fn default() -> Self {
4454 Self {
4455 data: FontData::default_table_data(),
4456 }
4457 }
4458}
4459
4460#[cfg(feature = "experimental_traverse")]
4461impl<'a> SomeTable<'a> for VariationIndex<'a> {
4462 fn type_name(&self) -> &str {
4463 "VariationIndex"
4464 }
4465 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4466 match idx {
4467 0usize => Some(Field::new(
4468 "delta_set_outer_index",
4469 self.delta_set_outer_index(),
4470 )),
4471 1usize => Some(Field::new(
4472 "delta_set_inner_index",
4473 self.delta_set_inner_index(),
4474 )),
4475 2usize => Some(Field::new("delta_format", self.delta_format())),
4476 _ => None,
4477 }
4478 }
4479}
4480
4481#[cfg(feature = "experimental_traverse")]
4482#[allow(clippy::needless_lifetimes)]
4483impl<'a> std::fmt::Debug for VariationIndex<'a> {
4484 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4485 (self as &dyn SomeTable<'a>).fmt(f)
4486 }
4487}
4488
4489#[derive(Clone)]
4491pub enum DeviceOrVariationIndex<'a> {
4492 Device(Device<'a>),
4493 VariationIndex(VariationIndex<'a>),
4494}
4495
4496impl Default for DeviceOrVariationIndex<'_> {
4497 fn default() -> Self {
4498 Self::Device(Default::default())
4499 }
4500}
4501
4502impl<'a> DeviceOrVariationIndex<'a> {
4503 pub fn offset_data(&self) -> FontData<'a> {
4505 match self {
4506 Self::Device(item) => item.offset_data(),
4507 Self::VariationIndex(item) => item.offset_data(),
4508 }
4509 }
4510}
4511
4512impl ReadArgs for DeviceOrVariationIndex<'_> {
4513 type Args = ();
4514}
4515
4516impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
4517 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4518 let format: DeltaFormat = data.read_at(4usize)?;
4519
4520 #[allow(clippy::redundant_guards)]
4521 match format {
4522 format if format != DeltaFormat::VariationIndex => {
4523 Ok(Self::Device(FontRead::read(data)?))
4524 }
4525 format if format == DeltaFormat::VariationIndex => {
4526 Ok(Self::VariationIndex(FontRead::read(data)?))
4527 }
4528 other => Err(ReadError::InvalidFormat(other.into())),
4529 }
4530 }
4531}
4532
4533impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
4534 fn min_byte_range(&self) -> Range<usize> {
4535 match self {
4536 Self::Device(item) => item.min_byte_range(),
4537 Self::VariationIndex(item) => item.min_byte_range(),
4538 }
4539 }
4540 fn min_table_bytes(&self) -> &'a [u8] {
4541 match self {
4542 Self::Device(item) => item.min_table_bytes(),
4543 Self::VariationIndex(item) => item.min_table_bytes(),
4544 }
4545 }
4546}
4547
4548#[cfg(feature = "experimental_traverse")]
4549impl<'a> DeviceOrVariationIndex<'a> {
4550 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4551 match self {
4552 Self::Device(table) => table,
4553 Self::VariationIndex(table) => table,
4554 }
4555 }
4556}
4557
4558#[cfg(feature = "experimental_traverse")]
4559impl std::fmt::Debug for DeviceOrVariationIndex<'_> {
4560 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4561 self.dyn_inner().fmt(f)
4562 }
4563}
4564
4565#[cfg(feature = "experimental_traverse")]
4566impl<'a> SomeTable<'a> for DeviceOrVariationIndex<'a> {
4567 fn type_name(&self) -> &str {
4568 self.dyn_inner().type_name()
4569 }
4570 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4571 self.dyn_inner().get_field(idx)
4572 }
4573}
4574
4575impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
4576 fn min_byte_range(&self) -> Range<usize> {
4577 0..self.feature_variation_records_byte_range().end
4578 }
4579 fn min_table_bytes(&self) -> &'a [u8] {
4580 let range = self.min_byte_range();
4581 self.data.as_bytes().get(range).unwrap_or_default()
4582 }
4583}
4584
4585impl ReadArgs for FeatureVariations<'_> {
4586 type Args = ();
4587}
4588
4589impl<'a> FontRead<'a> for FeatureVariations<'a> {
4590 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4591 #[allow(clippy::absurd_extreme_comparisons)]
4592 if data.len() < Self::MIN_SIZE {
4593 return Err(ReadError::OutOfBounds);
4594 }
4595 Ok(Self { data })
4596 }
4597}
4598
4599#[derive(Clone)]
4601pub struct FeatureVariations<'a> {
4602 data: FontData<'a>,
4603}
4604
4605#[allow(clippy::needless_lifetimes)]
4606impl<'a> FeatureVariations<'a> {
4607 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4608 basic_table_impls!(impl_the_methods);
4609
4610 pub fn version(&self) -> MajorMinor {
4611 let range = self.version_byte_range();
4612 self.data.read_at(range.start).ok().unwrap()
4613 }
4614
4615 pub fn feature_variation_record_count(&self) -> u32 {
4617 let range = self.feature_variation_record_count_byte_range();
4618 self.data.read_at(range.start).ok().unwrap()
4619 }
4620
4621 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
4623 let range = self.feature_variation_records_byte_range();
4624 self.data.read_array(range).ok().unwrap_or_default()
4625 }
4626
4627 pub fn version_byte_range(&self) -> Range<usize> {
4628 let start = 0;
4629 let end = start + MajorMinor::RAW_BYTE_LEN;
4630 start..end
4631 }
4632
4633 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
4634 let start = self.version_byte_range().end;
4635 let end = start + u32::RAW_BYTE_LEN;
4636 start..end
4637 }
4638
4639 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
4640 let feature_variation_record_count = self.feature_variation_record_count();
4641 let start = self.feature_variation_record_count_byte_range().end;
4642 let end = start
4643 + (transforms::to_usize(feature_variation_record_count))
4644 .saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN);
4645 start..end
4646 }
4647}
4648
4649const _: () = assert!(FontData::default_data_long_enough(
4650 FeatureVariations::MIN_SIZE
4651));
4652
4653impl Default for FeatureVariations<'_> {
4654 fn default() -> Self {
4655 Self {
4656 data: FontData::default_table_data(),
4657 }
4658 }
4659}
4660
4661#[cfg(feature = "experimental_traverse")]
4662impl<'a> SomeTable<'a> for FeatureVariations<'a> {
4663 fn type_name(&self) -> &str {
4664 "FeatureVariations"
4665 }
4666 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4667 match idx {
4668 0usize => Some(Field::new("version", self.version())),
4669 1usize => Some(Field::new(
4670 "feature_variation_record_count",
4671 self.feature_variation_record_count(),
4672 )),
4673 2usize => Some(Field::new(
4674 "feature_variation_records",
4675 traversal::FieldType::array_of_records(
4676 stringify!(FeatureVariationRecord),
4677 self.feature_variation_records(),
4678 self.offset_data(),
4679 ),
4680 )),
4681 _ => None,
4682 }
4683 }
4684}
4685
4686#[cfg(feature = "experimental_traverse")]
4687#[allow(clippy::needless_lifetimes)]
4688impl<'a> std::fmt::Debug for FeatureVariations<'a> {
4689 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4690 (self as &dyn SomeTable<'a>).fmt(f)
4691 }
4692}
4693
4694#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4696#[repr(C)]
4697#[repr(packed)]
4698pub struct FeatureVariationRecord {
4699 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
4702 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
4705}
4706
4707impl FeatureVariationRecord {
4708 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
4711 self.condition_set_offset.get()
4712 }
4713
4714 pub fn condition_set<'a>(
4720 &self,
4721 data: FontData<'a>,
4722 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
4723 self.condition_set_offset().resolve(data)
4724 }
4725
4726 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
4729 self.feature_table_substitution_offset.get()
4730 }
4731
4732 pub fn feature_table_substitution<'a>(
4738 &self,
4739 data: FontData<'a>,
4740 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
4741 self.feature_table_substitution_offset().resolve(data)
4742 }
4743}
4744
4745impl FixedSize for FeatureVariationRecord {
4746 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4747}
4748
4749#[cfg(feature = "experimental_traverse")]
4750impl<'a> SomeRecord<'a> for FeatureVariationRecord {
4751 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
4752 RecordResolver {
4753 name: "FeatureVariationRecord",
4754 get_field: Box::new(move |idx, _data| match idx {
4755 0usize => Some(Field::new(
4756 "condition_set_offset",
4757 FieldType::offset(self.condition_set_offset(), self.condition_set(_data)),
4758 )),
4759 1usize => Some(Field::new(
4760 "feature_table_substitution_offset",
4761 FieldType::offset(
4762 self.feature_table_substitution_offset(),
4763 self.feature_table_substitution(_data),
4764 ),
4765 )),
4766 _ => None,
4767 }),
4768 data,
4769 }
4770 }
4771}
4772
4773impl<'a> MinByteRange<'a> for ConditionSet<'a> {
4774 fn min_byte_range(&self) -> Range<usize> {
4775 0..self.condition_offsets_byte_range().end
4776 }
4777 fn min_table_bytes(&self) -> &'a [u8] {
4778 let range = self.min_byte_range();
4779 self.data.as_bytes().get(range).unwrap_or_default()
4780 }
4781}
4782
4783impl ReadArgs for ConditionSet<'_> {
4784 type Args = ();
4785}
4786
4787impl<'a> FontRead<'a> for ConditionSet<'a> {
4788 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4789 #[allow(clippy::absurd_extreme_comparisons)]
4790 if data.len() < Self::MIN_SIZE {
4791 return Err(ReadError::OutOfBounds);
4792 }
4793 Ok(Self { data })
4794 }
4795}
4796
4797#[derive(Clone)]
4799pub struct ConditionSet<'a> {
4800 data: FontData<'a>,
4801}
4802
4803#[allow(clippy::needless_lifetimes)]
4804impl<'a> ConditionSet<'a> {
4805 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
4806 basic_table_impls!(impl_the_methods);
4807
4808 pub fn condition_count(&self) -> u16 {
4810 let range = self.condition_count_byte_range();
4811 self.data.read_at(range.start).ok().unwrap()
4812 }
4813
4814 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
4817 let range = self.condition_offsets_byte_range();
4818 self.data.read_array(range).ok().unwrap_or_default()
4819 }
4820
4821 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
4823 let data = self.data;
4824 let offsets = self.condition_offsets();
4825 ArrayOfOffsets::new(offsets, data, ())
4826 }
4827
4828 pub fn condition_count_byte_range(&self) -> Range<usize> {
4829 let start = 0;
4830 let end = start + u16::RAW_BYTE_LEN;
4831 start..end
4832 }
4833
4834 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4835 let condition_count = self.condition_count();
4836 let start = self.condition_count_byte_range().end;
4837 let end =
4838 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
4839 start..end
4840 }
4841}
4842
4843const _: () = assert!(FontData::default_data_long_enough(ConditionSet::MIN_SIZE));
4844
4845impl Default for ConditionSet<'_> {
4846 fn default() -> Self {
4847 Self {
4848 data: FontData::default_table_data(),
4849 }
4850 }
4851}
4852
4853#[cfg(feature = "experimental_traverse")]
4854impl<'a> SomeTable<'a> for ConditionSet<'a> {
4855 fn type_name(&self) -> &str {
4856 "ConditionSet"
4857 }
4858 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4859 match idx {
4860 0usize => Some(Field::new("condition_count", self.condition_count())),
4861 1usize => Some(Field::new(
4862 "condition_offsets",
4863 FieldType::from(self.conditions()),
4864 )),
4865 _ => None,
4866 }
4867 }
4868}
4869
4870#[cfg(feature = "experimental_traverse")]
4871#[allow(clippy::needless_lifetimes)]
4872impl<'a> std::fmt::Debug for ConditionSet<'a> {
4873 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4874 (self as &dyn SomeTable<'a>).fmt(f)
4875 }
4876}
4877
4878#[derive(Clone)]
4883pub enum Condition<'a> {
4884 Format1AxisRange(ConditionFormat1<'a>),
4885 Format2VariableValue(ConditionFormat2<'a>),
4886 Format3And(ConditionFormat3<'a>),
4887 Format4Or(ConditionFormat4<'a>),
4888 Format5Negate(ConditionFormat5<'a>),
4889}
4890
4891impl Default for Condition<'_> {
4892 fn default() -> Self {
4893 Self::Format1AxisRange(Default::default())
4894 }
4895}
4896
4897impl<'a> Condition<'a> {
4898 pub fn offset_data(&self) -> FontData<'a> {
4900 match self {
4901 Self::Format1AxisRange(item) => item.offset_data(),
4902 Self::Format2VariableValue(item) => item.offset_data(),
4903 Self::Format3And(item) => item.offset_data(),
4904 Self::Format4Or(item) => item.offset_data(),
4905 Self::Format5Negate(item) => item.offset_data(),
4906 }
4907 }
4908
4909 pub fn format(&self) -> u16 {
4911 match self {
4912 Self::Format1AxisRange(item) => item.format(),
4913 Self::Format2VariableValue(item) => item.format(),
4914 Self::Format3And(item) => item.format(),
4915 Self::Format4Or(item) => item.format(),
4916 Self::Format5Negate(item) => item.format(),
4917 }
4918 }
4919}
4920
4921impl ReadArgs for Condition<'_> {
4922 type Args = ();
4923}
4924
4925impl<'a> FontRead<'a> for Condition<'a> {
4926 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4927 let format: u16 = data.read_at(0usize)?;
4928 match format {
4929 ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
4930 ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
4931 ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
4932 ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
4933 ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
4934 other => Err(ReadError::InvalidFormat(other.into())),
4935 }
4936 }
4937}
4938
4939impl<'a> MinByteRange<'a> for Condition<'a> {
4940 fn min_byte_range(&self) -> Range<usize> {
4941 match self {
4942 Self::Format1AxisRange(item) => item.min_byte_range(),
4943 Self::Format2VariableValue(item) => item.min_byte_range(),
4944 Self::Format3And(item) => item.min_byte_range(),
4945 Self::Format4Or(item) => item.min_byte_range(),
4946 Self::Format5Negate(item) => item.min_byte_range(),
4947 }
4948 }
4949 fn min_table_bytes(&self) -> &'a [u8] {
4950 match self {
4951 Self::Format1AxisRange(item) => item.min_table_bytes(),
4952 Self::Format2VariableValue(item) => item.min_table_bytes(),
4953 Self::Format3And(item) => item.min_table_bytes(),
4954 Self::Format4Or(item) => item.min_table_bytes(),
4955 Self::Format5Negate(item) => item.min_table_bytes(),
4956 }
4957 }
4958}
4959
4960#[cfg(feature = "experimental_traverse")]
4961impl<'a> Condition<'a> {
4962 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4963 match self {
4964 Self::Format1AxisRange(table) => table,
4965 Self::Format2VariableValue(table) => table,
4966 Self::Format3And(table) => table,
4967 Self::Format4Or(table) => table,
4968 Self::Format5Negate(table) => table,
4969 }
4970 }
4971}
4972
4973#[cfg(feature = "experimental_traverse")]
4974impl std::fmt::Debug for Condition<'_> {
4975 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4976 self.dyn_inner().fmt(f)
4977 }
4978}
4979
4980#[cfg(feature = "experimental_traverse")]
4981impl<'a> SomeTable<'a> for Condition<'a> {
4982 fn type_name(&self) -> &str {
4983 self.dyn_inner().type_name()
4984 }
4985 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4986 self.dyn_inner().get_field(idx)
4987 }
4988}
4989
4990impl Format<u16> for ConditionFormat1<'_> {
4991 const FORMAT: u16 = 1;
4992}
4993
4994impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
4995 fn min_byte_range(&self) -> Range<usize> {
4996 0..self.filter_range_max_value_byte_range().end
4997 }
4998 fn min_table_bytes(&self) -> &'a [u8] {
4999 let range = self.min_byte_range();
5000 self.data.as_bytes().get(range).unwrap_or_default()
5001 }
5002}
5003
5004impl ReadArgs for ConditionFormat1<'_> {
5005 type Args = ();
5006}
5007
5008impl<'a> FontRead<'a> for ConditionFormat1<'a> {
5009 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5010 #[allow(clippy::absurd_extreme_comparisons)]
5011 if data.len() < Self::MIN_SIZE {
5012 return Err(ReadError::OutOfBounds);
5013 }
5014 Ok(Self { data })
5015 }
5016}
5017
5018#[derive(Clone)]
5020pub struct ConditionFormat1<'a> {
5021 data: FontData<'a>,
5022}
5023
5024#[allow(clippy::needless_lifetimes)]
5025impl<'a> ConditionFormat1<'a> {
5026 pub const MIN_SIZE: usize =
5027 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
5028 basic_table_impls!(impl_the_methods);
5029
5030 pub fn format(&self) -> u16 {
5032 let range = self.format_byte_range();
5033 self.data.read_at(range.start).ok().unwrap()
5034 }
5035
5036 pub fn axis_index(&self) -> u16 {
5039 let range = self.axis_index_byte_range();
5040 self.data.read_at(range.start).ok().unwrap()
5041 }
5042
5043 pub fn filter_range_min_value(&self) -> F2Dot14 {
5046 let range = self.filter_range_min_value_byte_range();
5047 self.data.read_at(range.start).ok().unwrap()
5048 }
5049
5050 pub fn filter_range_max_value(&self) -> F2Dot14 {
5053 let range = self.filter_range_max_value_byte_range();
5054 self.data.read_at(range.start).ok().unwrap()
5055 }
5056
5057 pub fn format_byte_range(&self) -> Range<usize> {
5058 let start = 0;
5059 let end = start + u16::RAW_BYTE_LEN;
5060 start..end
5061 }
5062
5063 pub fn axis_index_byte_range(&self) -> Range<usize> {
5064 let start = self.format_byte_range().end;
5065 let end = start + u16::RAW_BYTE_LEN;
5066 start..end
5067 }
5068
5069 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
5070 let start = self.axis_index_byte_range().end;
5071 let end = start + F2Dot14::RAW_BYTE_LEN;
5072 start..end
5073 }
5074
5075 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
5076 let start = self.filter_range_min_value_byte_range().end;
5077 let end = start + F2Dot14::RAW_BYTE_LEN;
5078 start..end
5079 }
5080}
5081
5082const _: () = assert!(FontData::default_data_long_enough(
5083 ConditionFormat1::MIN_SIZE
5084));
5085
5086impl Default for ConditionFormat1<'_> {
5087 fn default() -> Self {
5088 Self {
5089 data: FontData::default_format_1_u16_table_data(),
5090 }
5091 }
5092}
5093
5094#[cfg(feature = "experimental_traverse")]
5095impl<'a> SomeTable<'a> for ConditionFormat1<'a> {
5096 fn type_name(&self) -> &str {
5097 "ConditionFormat1"
5098 }
5099 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5100 match idx {
5101 0usize => Some(Field::new("format", self.format())),
5102 1usize => Some(Field::new("axis_index", self.axis_index())),
5103 2usize => Some(Field::new(
5104 "filter_range_min_value",
5105 self.filter_range_min_value(),
5106 )),
5107 3usize => Some(Field::new(
5108 "filter_range_max_value",
5109 self.filter_range_max_value(),
5110 )),
5111 _ => None,
5112 }
5113 }
5114}
5115
5116#[cfg(feature = "experimental_traverse")]
5117#[allow(clippy::needless_lifetimes)]
5118impl<'a> std::fmt::Debug for ConditionFormat1<'a> {
5119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5120 (self as &dyn SomeTable<'a>).fmt(f)
5121 }
5122}
5123
5124impl Format<u16> for ConditionFormat2<'_> {
5125 const FORMAT: u16 = 2;
5126}
5127
5128impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
5129 fn min_byte_range(&self) -> Range<usize> {
5130 0..self.var_index_byte_range().end
5131 }
5132 fn min_table_bytes(&self) -> &'a [u8] {
5133 let range = self.min_byte_range();
5134 self.data.as_bytes().get(range).unwrap_or_default()
5135 }
5136}
5137
5138impl ReadArgs for ConditionFormat2<'_> {
5139 type Args = ();
5140}
5141
5142impl<'a> FontRead<'a> for ConditionFormat2<'a> {
5143 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5144 #[allow(clippy::absurd_extreme_comparisons)]
5145 if data.len() < Self::MIN_SIZE {
5146 return Err(ReadError::OutOfBounds);
5147 }
5148 Ok(Self { data })
5149 }
5150}
5151
5152#[derive(Clone)]
5154pub struct ConditionFormat2<'a> {
5155 data: FontData<'a>,
5156}
5157
5158#[allow(clippy::needless_lifetimes)]
5159impl<'a> ConditionFormat2<'a> {
5160 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
5161 basic_table_impls!(impl_the_methods);
5162
5163 pub fn format(&self) -> u16 {
5165 let range = self.format_byte_range();
5166 self.data.read_at(range.start).ok().unwrap()
5167 }
5168
5169 pub fn default_value(&self) -> i16 {
5171 let range = self.default_value_byte_range();
5172 self.data.read_at(range.start).ok().unwrap()
5173 }
5174
5175 pub fn var_index(&self) -> u32 {
5177 let range = self.var_index_byte_range();
5178 self.data.read_at(range.start).ok().unwrap()
5179 }
5180
5181 pub fn format_byte_range(&self) -> Range<usize> {
5182 let start = 0;
5183 let end = start + u16::RAW_BYTE_LEN;
5184 start..end
5185 }
5186
5187 pub fn default_value_byte_range(&self) -> Range<usize> {
5188 let start = self.format_byte_range().end;
5189 let end = start + i16::RAW_BYTE_LEN;
5190 start..end
5191 }
5192
5193 pub fn var_index_byte_range(&self) -> Range<usize> {
5194 let start = self.default_value_byte_range().end;
5195 let end = start + u32::RAW_BYTE_LEN;
5196 start..end
5197 }
5198}
5199
5200#[cfg(feature = "experimental_traverse")]
5201impl<'a> SomeTable<'a> for ConditionFormat2<'a> {
5202 fn type_name(&self) -> &str {
5203 "ConditionFormat2"
5204 }
5205 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5206 match idx {
5207 0usize => Some(Field::new("format", self.format())),
5208 1usize => Some(Field::new("default_value", self.default_value())),
5209 2usize => Some(Field::new("var_index", self.var_index())),
5210 _ => None,
5211 }
5212 }
5213}
5214
5215#[cfg(feature = "experimental_traverse")]
5216#[allow(clippy::needless_lifetimes)]
5217impl<'a> std::fmt::Debug for ConditionFormat2<'a> {
5218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5219 (self as &dyn SomeTable<'a>).fmt(f)
5220 }
5221}
5222
5223impl Format<u16> for ConditionFormat3<'_> {
5224 const FORMAT: u16 = 3;
5225}
5226
5227impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
5228 fn min_byte_range(&self) -> Range<usize> {
5229 0..self.condition_offsets_byte_range().end
5230 }
5231 fn min_table_bytes(&self) -> &'a [u8] {
5232 let range = self.min_byte_range();
5233 self.data.as_bytes().get(range).unwrap_or_default()
5234 }
5235}
5236
5237impl ReadArgs for ConditionFormat3<'_> {
5238 type Args = ();
5239}
5240
5241impl<'a> FontRead<'a> for ConditionFormat3<'a> {
5242 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5243 #[allow(clippy::absurd_extreme_comparisons)]
5244 if data.len() < Self::MIN_SIZE {
5245 return Err(ReadError::OutOfBounds);
5246 }
5247 Ok(Self { data })
5248 }
5249}
5250
5251#[derive(Clone)]
5253pub struct ConditionFormat3<'a> {
5254 data: FontData<'a>,
5255}
5256
5257#[allow(clippy::needless_lifetimes)]
5258impl<'a> ConditionFormat3<'a> {
5259 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5260 basic_table_impls!(impl_the_methods);
5261
5262 pub fn format(&self) -> u16 {
5264 let range = self.format_byte_range();
5265 self.data.read_at(range.start).ok().unwrap()
5266 }
5267
5268 pub fn condition_count(&self) -> u8 {
5270 let range = self.condition_count_byte_range();
5271 self.data.read_at(range.start).ok().unwrap()
5272 }
5273
5274 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5276 let range = self.condition_offsets_byte_range();
5277 self.data.read_array(range).ok().unwrap_or_default()
5278 }
5279
5280 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5282 let data = self.data;
5283 let offsets = self.condition_offsets();
5284 ArrayOfOffsets::new(offsets, data, ())
5285 }
5286
5287 pub fn format_byte_range(&self) -> Range<usize> {
5288 let start = 0;
5289 let end = start + u16::RAW_BYTE_LEN;
5290 start..end
5291 }
5292
5293 pub fn condition_count_byte_range(&self) -> Range<usize> {
5294 let start = self.format_byte_range().end;
5295 let end = start + u8::RAW_BYTE_LEN;
5296 start..end
5297 }
5298
5299 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5300 let condition_count = self.condition_count();
5301 let start = self.condition_count_byte_range().end;
5302 let end =
5303 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5304 start..end
5305 }
5306}
5307
5308#[cfg(feature = "experimental_traverse")]
5309impl<'a> SomeTable<'a> for ConditionFormat3<'a> {
5310 fn type_name(&self) -> &str {
5311 "ConditionFormat3"
5312 }
5313 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5314 match idx {
5315 0usize => Some(Field::new("format", self.format())),
5316 1usize => Some(Field::new("condition_count", self.condition_count())),
5317 2usize => Some(Field::new(
5318 "condition_offsets",
5319 FieldType::from(self.conditions()),
5320 )),
5321 _ => None,
5322 }
5323 }
5324}
5325
5326#[cfg(feature = "experimental_traverse")]
5327#[allow(clippy::needless_lifetimes)]
5328impl<'a> std::fmt::Debug for ConditionFormat3<'a> {
5329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5330 (self as &dyn SomeTable<'a>).fmt(f)
5331 }
5332}
5333
5334impl Format<u16> for ConditionFormat4<'_> {
5335 const FORMAT: u16 = 4;
5336}
5337
5338impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
5339 fn min_byte_range(&self) -> Range<usize> {
5340 0..self.condition_offsets_byte_range().end
5341 }
5342 fn min_table_bytes(&self) -> &'a [u8] {
5343 let range = self.min_byte_range();
5344 self.data.as_bytes().get(range).unwrap_or_default()
5345 }
5346}
5347
5348impl ReadArgs for ConditionFormat4<'_> {
5349 type Args = ();
5350}
5351
5352impl<'a> FontRead<'a> for ConditionFormat4<'a> {
5353 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5354 #[allow(clippy::absurd_extreme_comparisons)]
5355 if data.len() < Self::MIN_SIZE {
5356 return Err(ReadError::OutOfBounds);
5357 }
5358 Ok(Self { data })
5359 }
5360}
5361
5362#[derive(Clone)]
5364pub struct ConditionFormat4<'a> {
5365 data: FontData<'a>,
5366}
5367
5368#[allow(clippy::needless_lifetimes)]
5369impl<'a> ConditionFormat4<'a> {
5370 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5371 basic_table_impls!(impl_the_methods);
5372
5373 pub fn format(&self) -> u16 {
5375 let range = self.format_byte_range();
5376 self.data.read_at(range.start).ok().unwrap()
5377 }
5378
5379 pub fn condition_count(&self) -> u8 {
5381 let range = self.condition_count_byte_range();
5382 self.data.read_at(range.start).ok().unwrap()
5383 }
5384
5385 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5387 let range = self.condition_offsets_byte_range();
5388 self.data.read_array(range).ok().unwrap_or_default()
5389 }
5390
5391 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5393 let data = self.data;
5394 let offsets = self.condition_offsets();
5395 ArrayOfOffsets::new(offsets, data, ())
5396 }
5397
5398 pub fn format_byte_range(&self) -> Range<usize> {
5399 let start = 0;
5400 let end = start + u16::RAW_BYTE_LEN;
5401 start..end
5402 }
5403
5404 pub fn condition_count_byte_range(&self) -> Range<usize> {
5405 let start = self.format_byte_range().end;
5406 let end = start + u8::RAW_BYTE_LEN;
5407 start..end
5408 }
5409
5410 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5411 let condition_count = self.condition_count();
5412 let start = self.condition_count_byte_range().end;
5413 let end =
5414 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5415 start..end
5416 }
5417}
5418
5419#[cfg(feature = "experimental_traverse")]
5420impl<'a> SomeTable<'a> for ConditionFormat4<'a> {
5421 fn type_name(&self) -> &str {
5422 "ConditionFormat4"
5423 }
5424 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5425 match idx {
5426 0usize => Some(Field::new("format", self.format())),
5427 1usize => Some(Field::new("condition_count", self.condition_count())),
5428 2usize => Some(Field::new(
5429 "condition_offsets",
5430 FieldType::from(self.conditions()),
5431 )),
5432 _ => None,
5433 }
5434 }
5435}
5436
5437#[cfg(feature = "experimental_traverse")]
5438#[allow(clippy::needless_lifetimes)]
5439impl<'a> std::fmt::Debug for ConditionFormat4<'a> {
5440 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5441 (self as &dyn SomeTable<'a>).fmt(f)
5442 }
5443}
5444
5445impl Format<u16> for ConditionFormat5<'_> {
5446 const FORMAT: u16 = 5;
5447}
5448
5449impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
5450 fn min_byte_range(&self) -> Range<usize> {
5451 0..self.condition_offset_byte_range().end
5452 }
5453 fn min_table_bytes(&self) -> &'a [u8] {
5454 let range = self.min_byte_range();
5455 self.data.as_bytes().get(range).unwrap_or_default()
5456 }
5457}
5458
5459impl ReadArgs for ConditionFormat5<'_> {
5460 type Args = ();
5461}
5462
5463impl<'a> FontRead<'a> for ConditionFormat5<'a> {
5464 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5465 #[allow(clippy::absurd_extreme_comparisons)]
5466 if data.len() < Self::MIN_SIZE {
5467 return Err(ReadError::OutOfBounds);
5468 }
5469 Ok(Self { data })
5470 }
5471}
5472
5473#[derive(Clone)]
5475pub struct ConditionFormat5<'a> {
5476 data: FontData<'a>,
5477}
5478
5479#[allow(clippy::needless_lifetimes)]
5480impl<'a> ConditionFormat5<'a> {
5481 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
5482 basic_table_impls!(impl_the_methods);
5483
5484 pub fn format(&self) -> u16 {
5486 let range = self.format_byte_range();
5487 self.data.read_at(range.start).ok().unwrap()
5488 }
5489
5490 pub fn condition_offset(&self) -> Offset24 {
5492 let range = self.condition_offset_byte_range();
5493 self.data.read_at(range.start).ok().unwrap()
5494 }
5495
5496 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
5498 let data = self.data;
5499 self.condition_offset().resolve(data)
5500 }
5501
5502 pub fn format_byte_range(&self) -> Range<usize> {
5503 let start = 0;
5504 let end = start + u16::RAW_BYTE_LEN;
5505 start..end
5506 }
5507
5508 pub fn condition_offset_byte_range(&self) -> Range<usize> {
5509 let start = self.format_byte_range().end;
5510 let end = start + Offset24::RAW_BYTE_LEN;
5511 start..end
5512 }
5513}
5514
5515#[cfg(feature = "experimental_traverse")]
5516impl<'a> SomeTable<'a> for ConditionFormat5<'a> {
5517 fn type_name(&self) -> &str {
5518 "ConditionFormat5"
5519 }
5520 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5521 match idx {
5522 0usize => Some(Field::new("format", self.format())),
5523 1usize => Some(Field::new(
5524 "condition_offset",
5525 FieldType::offset(self.condition_offset(), self.condition()),
5526 )),
5527 _ => None,
5528 }
5529 }
5530}
5531
5532#[cfg(feature = "experimental_traverse")]
5533#[allow(clippy::needless_lifetimes)]
5534impl<'a> std::fmt::Debug for ConditionFormat5<'a> {
5535 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5536 (self as &dyn SomeTable<'a>).fmt(f)
5537 }
5538}
5539
5540impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
5541 fn min_byte_range(&self) -> Range<usize> {
5542 0..self.substitutions_byte_range().end
5543 }
5544 fn min_table_bytes(&self) -> &'a [u8] {
5545 let range = self.min_byte_range();
5546 self.data.as_bytes().get(range).unwrap_or_default()
5547 }
5548}
5549
5550impl ReadArgs for FeatureTableSubstitution<'_> {
5551 type Args = ();
5552}
5553
5554impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
5555 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5556 #[allow(clippy::absurd_extreme_comparisons)]
5557 if data.len() < Self::MIN_SIZE {
5558 return Err(ReadError::OutOfBounds);
5559 }
5560 Ok(Self { data })
5561 }
5562}
5563
5564#[derive(Clone)]
5566pub struct FeatureTableSubstitution<'a> {
5567 data: FontData<'a>,
5568}
5569
5570#[allow(clippy::needless_lifetimes)]
5571impl<'a> FeatureTableSubstitution<'a> {
5572 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
5573 basic_table_impls!(impl_the_methods);
5574
5575 pub fn version(&self) -> MajorMinor {
5577 let range = self.version_byte_range();
5578 self.data.read_at(range.start).ok().unwrap()
5579 }
5580
5581 pub fn substitution_count(&self) -> u16 {
5583 let range = self.substitution_count_byte_range();
5584 self.data.read_at(range.start).ok().unwrap()
5585 }
5586
5587 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
5589 let range = self.substitutions_byte_range();
5590 self.data.read_array(range).ok().unwrap_or_default()
5591 }
5592
5593 pub fn version_byte_range(&self) -> Range<usize> {
5594 let start = 0;
5595 let end = start + MajorMinor::RAW_BYTE_LEN;
5596 start..end
5597 }
5598
5599 pub fn substitution_count_byte_range(&self) -> Range<usize> {
5600 let start = self.version_byte_range().end;
5601 let end = start + u16::RAW_BYTE_LEN;
5602 start..end
5603 }
5604
5605 pub fn substitutions_byte_range(&self) -> Range<usize> {
5606 let substitution_count = self.substitution_count();
5607 let start = self.substitution_count_byte_range().end;
5608 let end = start
5609 + (transforms::to_usize(substitution_count))
5610 .saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN);
5611 start..end
5612 }
5613}
5614
5615const _: () = assert!(FontData::default_data_long_enough(
5616 FeatureTableSubstitution::MIN_SIZE
5617));
5618
5619impl Default for FeatureTableSubstitution<'_> {
5620 fn default() -> Self {
5621 Self {
5622 data: FontData::default_table_data(),
5623 }
5624 }
5625}
5626
5627#[cfg(feature = "experimental_traverse")]
5628impl<'a> SomeTable<'a> for FeatureTableSubstitution<'a> {
5629 fn type_name(&self) -> &str {
5630 "FeatureTableSubstitution"
5631 }
5632 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5633 match idx {
5634 0usize => Some(Field::new("version", self.version())),
5635 1usize => Some(Field::new("substitution_count", self.substitution_count())),
5636 2usize => Some(Field::new(
5637 "substitutions",
5638 traversal::FieldType::array_of_records(
5639 stringify!(FeatureTableSubstitutionRecord),
5640 self.substitutions(),
5641 self.offset_data(),
5642 ),
5643 )),
5644 _ => None,
5645 }
5646 }
5647}
5648
5649#[cfg(feature = "experimental_traverse")]
5650#[allow(clippy::needless_lifetimes)]
5651impl<'a> std::fmt::Debug for FeatureTableSubstitution<'a> {
5652 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5653 (self as &dyn SomeTable<'a>).fmt(f)
5654 }
5655}
5656
5657#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
5659#[repr(C)]
5660#[repr(packed)]
5661pub struct FeatureTableSubstitutionRecord {
5662 pub feature_index: BigEndian<u16>,
5664 pub alternate_feature_offset: BigEndian<Offset32>,
5667}
5668
5669impl FeatureTableSubstitutionRecord {
5670 pub fn feature_index(&self) -> u16 {
5672 self.feature_index.get()
5673 }
5674
5675 pub fn alternate_feature_offset(&self) -> Offset32 {
5678 self.alternate_feature_offset.get()
5679 }
5680}
5681
5682impl FixedSize for FeatureTableSubstitutionRecord {
5683 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
5684}
5685
5686#[cfg(feature = "experimental_traverse")]
5687impl<'a> SomeRecord<'a> for FeatureTableSubstitutionRecord {
5688 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
5689 RecordResolver {
5690 name: "FeatureTableSubstitutionRecord",
5691 get_field: Box::new(move |idx, _data| match idx {
5692 0usize => Some(Field::new("feature_index", self.feature_index())),
5693 1usize => Some(Field::new(
5694 "alternate_feature_offset",
5695 FieldType::offset(
5696 self.alternate_feature_offset(),
5697 self.alternate_feature(_data),
5698 ),
5699 )),
5700 _ => None,
5701 }),
5702 data,
5703 }
5704 }
5705}
5706
5707impl<'a> MinByteRange<'a> for SizeParams<'a> {
5708 fn min_byte_range(&self) -> Range<usize> {
5709 0..self.range_end_byte_range().end
5710 }
5711 fn min_table_bytes(&self) -> &'a [u8] {
5712 let range = self.min_byte_range();
5713 self.data.as_bytes().get(range).unwrap_or_default()
5714 }
5715}
5716
5717impl ReadArgs for SizeParams<'_> {
5718 type Args = ();
5719}
5720
5721impl<'a> FontRead<'a> for SizeParams<'a> {
5722 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5723 #[allow(clippy::absurd_extreme_comparisons)]
5724 if data.len() < Self::MIN_SIZE {
5725 return Err(ReadError::OutOfBounds);
5726 }
5727 Ok(Self { data })
5728 }
5729}
5730
5731#[derive(Clone)]
5732pub struct SizeParams<'a> {
5733 data: FontData<'a>,
5734}
5735
5736#[allow(clippy::needless_lifetimes)]
5737impl<'a> SizeParams<'a> {
5738 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5739 + u16::RAW_BYTE_LEN
5740 + u16::RAW_BYTE_LEN
5741 + u16::RAW_BYTE_LEN
5742 + u16::RAW_BYTE_LEN);
5743 basic_table_impls!(impl_the_methods);
5744
5745 pub fn design_size(&self) -> u16 {
5750 let range = self.design_size_byte_range();
5751 self.data.read_at(range.start).ok().unwrap()
5752 }
5753
5754 pub fn identifier(&self) -> u16 {
5761 let range = self.identifier_byte_range();
5762 self.data.read_at(range.start).ok().unwrap()
5763 }
5764
5765 pub fn name_entry(&self) -> u16 {
5776 let range = self.name_entry_byte_range();
5777 self.data.read_at(range.start).ok().unwrap()
5778 }
5779
5780 pub fn range_start(&self) -> u16 {
5786 let range = self.range_start_byte_range();
5787 self.data.read_at(range.start).ok().unwrap()
5788 }
5789
5790 pub fn range_end(&self) -> u16 {
5791 let range = self.range_end_byte_range();
5792 self.data.read_at(range.start).ok().unwrap()
5793 }
5794
5795 pub fn design_size_byte_range(&self) -> Range<usize> {
5796 let start = 0;
5797 let end = start + u16::RAW_BYTE_LEN;
5798 start..end
5799 }
5800
5801 pub fn identifier_byte_range(&self) -> Range<usize> {
5802 let start = self.design_size_byte_range().end;
5803 let end = start + u16::RAW_BYTE_LEN;
5804 start..end
5805 }
5806
5807 pub fn name_entry_byte_range(&self) -> Range<usize> {
5808 let start = self.identifier_byte_range().end;
5809 let end = start + u16::RAW_BYTE_LEN;
5810 start..end
5811 }
5812
5813 pub fn range_start_byte_range(&self) -> Range<usize> {
5814 let start = self.name_entry_byte_range().end;
5815 let end = start + u16::RAW_BYTE_LEN;
5816 start..end
5817 }
5818
5819 pub fn range_end_byte_range(&self) -> Range<usize> {
5820 let start = self.range_start_byte_range().end;
5821 let end = start + u16::RAW_BYTE_LEN;
5822 start..end
5823 }
5824}
5825
5826const _: () = assert!(FontData::default_data_long_enough(SizeParams::MIN_SIZE));
5827
5828impl Default for SizeParams<'_> {
5829 fn default() -> Self {
5830 Self {
5831 data: FontData::default_table_data(),
5832 }
5833 }
5834}
5835
5836#[cfg(feature = "experimental_traverse")]
5837impl<'a> SomeTable<'a> for SizeParams<'a> {
5838 fn type_name(&self) -> &str {
5839 "SizeParams"
5840 }
5841 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5842 match idx {
5843 0usize => Some(Field::new("design_size", self.design_size())),
5844 1usize => Some(Field::new("identifier", self.identifier())),
5845 2usize => Some(Field::new("name_entry", self.name_entry())),
5846 3usize => Some(Field::new("range_start", self.range_start())),
5847 4usize => Some(Field::new("range_end", self.range_end())),
5848 _ => None,
5849 }
5850 }
5851}
5852
5853#[cfg(feature = "experimental_traverse")]
5854#[allow(clippy::needless_lifetimes)]
5855impl<'a> std::fmt::Debug for SizeParams<'a> {
5856 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5857 (self as &dyn SomeTable<'a>).fmt(f)
5858 }
5859}
5860
5861impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
5862 fn min_byte_range(&self) -> Range<usize> {
5863 0..self.ui_name_id_byte_range().end
5864 }
5865 fn min_table_bytes(&self) -> &'a [u8] {
5866 let range = self.min_byte_range();
5867 self.data.as_bytes().get(range).unwrap_or_default()
5868 }
5869}
5870
5871impl ReadArgs for StylisticSetParams<'_> {
5872 type Args = ();
5873}
5874
5875impl<'a> FontRead<'a> for StylisticSetParams<'a> {
5876 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5877 #[allow(clippy::absurd_extreme_comparisons)]
5878 if data.len() < Self::MIN_SIZE {
5879 return Err(ReadError::OutOfBounds);
5880 }
5881 Ok(Self { data })
5882 }
5883}
5884
5885#[derive(Clone)]
5886pub struct StylisticSetParams<'a> {
5887 data: FontData<'a>,
5888}
5889
5890#[allow(clippy::needless_lifetimes)]
5891impl<'a> StylisticSetParams<'a> {
5892 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
5893 basic_table_impls!(impl_the_methods);
5894
5895 pub fn version(&self) -> u16 {
5896 let range = self.version_byte_range();
5897 self.data.read_at(range.start).ok().unwrap()
5898 }
5899
5900 pub fn ui_name_id(&self) -> NameId {
5910 let range = self.ui_name_id_byte_range();
5911 self.data.read_at(range.start).ok().unwrap()
5912 }
5913
5914 pub fn version_byte_range(&self) -> Range<usize> {
5915 let start = 0;
5916 let end = start + u16::RAW_BYTE_LEN;
5917 start..end
5918 }
5919
5920 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
5921 let start = self.version_byte_range().end;
5922 let end = start + NameId::RAW_BYTE_LEN;
5923 start..end
5924 }
5925}
5926
5927const _: () = assert!(FontData::default_data_long_enough(
5928 StylisticSetParams::MIN_SIZE
5929));
5930
5931impl Default for StylisticSetParams<'_> {
5932 fn default() -> Self {
5933 Self {
5934 data: FontData::default_table_data(),
5935 }
5936 }
5937}
5938
5939#[cfg(feature = "experimental_traverse")]
5940impl<'a> SomeTable<'a> for StylisticSetParams<'a> {
5941 fn type_name(&self) -> &str {
5942 "StylisticSetParams"
5943 }
5944 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5945 match idx {
5946 0usize => Some(Field::new("version", self.version())),
5947 1usize => Some(Field::new("ui_name_id", self.ui_name_id())),
5948 _ => None,
5949 }
5950 }
5951}
5952
5953#[cfg(feature = "experimental_traverse")]
5954#[allow(clippy::needless_lifetimes)]
5955impl<'a> std::fmt::Debug for StylisticSetParams<'a> {
5956 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5957 (self as &dyn SomeTable<'a>).fmt(f)
5958 }
5959}
5960
5961impl Format<u16> for CharacterVariantParams<'_> {
5962 const FORMAT: u16 = 0;
5963}
5964
5965impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
5966 fn min_byte_range(&self) -> Range<usize> {
5967 0..self.character_byte_range().end
5968 }
5969 fn min_table_bytes(&self) -> &'a [u8] {
5970 let range = self.min_byte_range();
5971 self.data.as_bytes().get(range).unwrap_or_default()
5972 }
5973}
5974
5975impl ReadArgs for CharacterVariantParams<'_> {
5976 type Args = ();
5977}
5978
5979impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
5980 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5981 #[allow(clippy::absurd_extreme_comparisons)]
5982 if data.len() < Self::MIN_SIZE {
5983 return Err(ReadError::OutOfBounds);
5984 }
5985 Ok(Self { data })
5986 }
5987}
5988
5989#[derive(Clone)]
5991pub struct CharacterVariantParams<'a> {
5992 data: FontData<'a>,
5993}
5994
5995#[allow(clippy::needless_lifetimes)]
5996impl<'a> CharacterVariantParams<'a> {
5997 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5998 + NameId::RAW_BYTE_LEN
5999 + NameId::RAW_BYTE_LEN
6000 + NameId::RAW_BYTE_LEN
6001 + u16::RAW_BYTE_LEN
6002 + NameId::RAW_BYTE_LEN
6003 + u16::RAW_BYTE_LEN);
6004 basic_table_impls!(impl_the_methods);
6005
6006 pub fn format(&self) -> u16 {
6008 let range = self.format_byte_range();
6009 self.data.read_at(range.start).ok().unwrap()
6010 }
6011
6012 pub fn feat_ui_label_name_id(&self) -> NameId {
6016 let range = self.feat_ui_label_name_id_byte_range();
6017 self.data.read_at(range.start).ok().unwrap()
6018 }
6019
6020 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
6024 let range = self.feat_ui_tooltip_text_name_id_byte_range();
6025 self.data.read_at(range.start).ok().unwrap()
6026 }
6027
6028 pub fn sample_text_name_id(&self) -> NameId {
6031 let range = self.sample_text_name_id_byte_range();
6032 self.data.read_at(range.start).ok().unwrap()
6033 }
6034
6035 pub fn num_named_parameters(&self) -> u16 {
6037 let range = self.num_named_parameters_byte_range();
6038 self.data.read_at(range.start).ok().unwrap()
6039 }
6040
6041 pub fn first_param_ui_label_name_id(&self) -> NameId {
6045 let range = self.first_param_ui_label_name_id_byte_range();
6046 self.data.read_at(range.start).ok().unwrap()
6047 }
6048
6049 pub fn char_count(&self) -> u16 {
6052 let range = self.char_count_byte_range();
6053 self.data.read_at(range.start).ok().unwrap()
6054 }
6055
6056 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
6059 let range = self.character_byte_range();
6060 self.data.read_array(range).ok().unwrap_or_default()
6061 }
6062
6063 pub fn format_byte_range(&self) -> Range<usize> {
6064 let start = 0;
6065 let end = start + u16::RAW_BYTE_LEN;
6066 start..end
6067 }
6068
6069 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
6070 let start = self.format_byte_range().end;
6071 let end = start + NameId::RAW_BYTE_LEN;
6072 start..end
6073 }
6074
6075 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
6076 let start = self.feat_ui_label_name_id_byte_range().end;
6077 let end = start + NameId::RAW_BYTE_LEN;
6078 start..end
6079 }
6080
6081 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
6082 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
6083 let end = start + NameId::RAW_BYTE_LEN;
6084 start..end
6085 }
6086
6087 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
6088 let start = self.sample_text_name_id_byte_range().end;
6089 let end = start + u16::RAW_BYTE_LEN;
6090 start..end
6091 }
6092
6093 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
6094 let start = self.num_named_parameters_byte_range().end;
6095 let end = start + NameId::RAW_BYTE_LEN;
6096 start..end
6097 }
6098
6099 pub fn char_count_byte_range(&self) -> Range<usize> {
6100 let start = self.first_param_ui_label_name_id_byte_range().end;
6101 let end = start + u16::RAW_BYTE_LEN;
6102 start..end
6103 }
6104
6105 pub fn character_byte_range(&self) -> Range<usize> {
6106 let char_count = self.char_count();
6107 let start = self.char_count_byte_range().end;
6108 let end = start + (transforms::to_usize(char_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
6109 start..end
6110 }
6111}
6112
6113const _: () = assert!(FontData::default_data_long_enough(
6114 CharacterVariantParams::MIN_SIZE
6115));
6116
6117impl Default for CharacterVariantParams<'_> {
6118 fn default() -> Self {
6119 Self {
6120 data: FontData::default_table_data(),
6121 }
6122 }
6123}
6124
6125#[cfg(feature = "experimental_traverse")]
6126impl<'a> SomeTable<'a> for CharacterVariantParams<'a> {
6127 fn type_name(&self) -> &str {
6128 "CharacterVariantParams"
6129 }
6130 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
6131 match idx {
6132 0usize => Some(Field::new("format", self.format())),
6133 1usize => Some(Field::new(
6134 "feat_ui_label_name_id",
6135 self.feat_ui_label_name_id(),
6136 )),
6137 2usize => Some(Field::new(
6138 "feat_ui_tooltip_text_name_id",
6139 self.feat_ui_tooltip_text_name_id(),
6140 )),
6141 3usize => Some(Field::new(
6142 "sample_text_name_id",
6143 self.sample_text_name_id(),
6144 )),
6145 4usize => Some(Field::new(
6146 "num_named_parameters",
6147 self.num_named_parameters(),
6148 )),
6149 5usize => Some(Field::new(
6150 "first_param_ui_label_name_id",
6151 self.first_param_ui_label_name_id(),
6152 )),
6153 6usize => Some(Field::new("char_count", self.char_count())),
6154 7usize => Some(Field::new("character", self.character())),
6155 _ => None,
6156 }
6157 }
6158}
6159
6160#[cfg(feature = "experimental_traverse")]
6161#[allow(clippy::needless_lifetimes)]
6162impl<'a> std::fmt::Debug for CharacterVariantParams<'a> {
6163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6164 (self as &dyn SomeTable<'a>).fmt(f)
6165 }
6166}