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("mark_filtering_set", self.mark_filtering_set()?))
1054 }
1055 _ => None,
1056 }
1057 }
1058}
1059
1060#[cfg(feature = "experimental_traverse")]
1061#[allow(clippy::needless_lifetimes)]
1062impl<'a, T: FontRead<'a, Args = ()> + SomeTable<'a> + 'a> std::fmt::Debug for Lookup<'a, T> {
1063 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1064 (self as &dyn SomeTable<'a>).fmt(f)
1065 }
1066}
1067
1068impl Format<u16> for CoverageFormat1<'_> {
1069 const FORMAT: u16 = 1;
1070}
1071
1072impl<'a> MinByteRange<'a> for CoverageFormat1<'a> {
1073 fn min_byte_range(&self) -> Range<usize> {
1074 0..self.glyph_array_byte_range().end
1075 }
1076 fn min_table_bytes(&self) -> &'a [u8] {
1077 let range = self.min_byte_range();
1078 self.data.as_bytes().get(range).unwrap_or_default()
1079 }
1080}
1081
1082impl ReadArgs for CoverageFormat1<'_> {
1083 type Args = ();
1084}
1085
1086impl<'a> FontRead<'a> for CoverageFormat1<'a> {
1087 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1088 #[allow(clippy::absurd_extreme_comparisons)]
1089 if data.len() < Self::MIN_SIZE {
1090 return Err(ReadError::OutOfBounds);
1091 }
1092 Ok(Self { data })
1093 }
1094}
1095
1096#[derive(Clone)]
1098pub struct CoverageFormat1<'a> {
1099 data: FontData<'a>,
1100}
1101
1102#[allow(clippy::needless_lifetimes)]
1103impl<'a> CoverageFormat1<'a> {
1104 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1105 basic_table_impls!(impl_the_methods);
1106
1107 pub fn coverage_format(&self) -> u16 {
1109 let range = self.coverage_format_byte_range();
1110 self.data.read_at(range.start).ok().unwrap()
1111 }
1112
1113 pub fn glyph_count(&self) -> u16 {
1115 let range = self.glyph_count_byte_range();
1116 self.data.read_at(range.start).ok().unwrap()
1117 }
1118
1119 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
1121 let range = self.glyph_array_byte_range();
1122 self.data.read_array(range).ok().unwrap_or_default()
1123 }
1124
1125 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1126 let start = 0;
1127 let end = start + u16::RAW_BYTE_LEN;
1128 start..end
1129 }
1130
1131 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1132 let start = self.coverage_format_byte_range().end;
1133 let end = start + u16::RAW_BYTE_LEN;
1134 start..end
1135 }
1136
1137 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1138 let glyph_count = self.glyph_count();
1139 let start = self.glyph_count_byte_range().end;
1140 let end =
1141 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1142 start..end
1143 }
1144}
1145
1146const _: () = assert!(FontData::default_data_long_enough(
1147 CoverageFormat1::MIN_SIZE
1148));
1149
1150impl Default for CoverageFormat1<'_> {
1151 fn default() -> Self {
1152 Self {
1153 data: FontData::default_format_1_u16_table_data(),
1154 }
1155 }
1156}
1157
1158#[cfg(feature = "experimental_traverse")]
1159impl<'a> SomeTable<'a> for CoverageFormat1<'a> {
1160 fn type_name(&self) -> &str {
1161 "CoverageFormat1"
1162 }
1163 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1164 match idx {
1165 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1166 1usize => Some(Field::new("glyph_count", self.glyph_count())),
1167 2usize => Some(Field::new("glyph_array", self.glyph_array())),
1168 _ => None,
1169 }
1170 }
1171}
1172
1173#[cfg(feature = "experimental_traverse")]
1174#[allow(clippy::needless_lifetimes)]
1175impl<'a> std::fmt::Debug for CoverageFormat1<'a> {
1176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1177 (self as &dyn SomeTable<'a>).fmt(f)
1178 }
1179}
1180
1181impl Format<u16> for CoverageFormat2<'_> {
1182 const FORMAT: u16 = 2;
1183}
1184
1185impl<'a> MinByteRange<'a> for CoverageFormat2<'a> {
1186 fn min_byte_range(&self) -> Range<usize> {
1187 0..self.range_records_byte_range().end
1188 }
1189 fn min_table_bytes(&self) -> &'a [u8] {
1190 let range = self.min_byte_range();
1191 self.data.as_bytes().get(range).unwrap_or_default()
1192 }
1193}
1194
1195impl ReadArgs for CoverageFormat2<'_> {
1196 type Args = ();
1197}
1198
1199impl<'a> FontRead<'a> for CoverageFormat2<'a> {
1200 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1201 #[allow(clippy::absurd_extreme_comparisons)]
1202 if data.len() < Self::MIN_SIZE {
1203 return Err(ReadError::OutOfBounds);
1204 }
1205 Ok(Self { data })
1206 }
1207}
1208
1209#[derive(Clone)]
1211pub struct CoverageFormat2<'a> {
1212 data: FontData<'a>,
1213}
1214
1215#[allow(clippy::needless_lifetimes)]
1216impl<'a> CoverageFormat2<'a> {
1217 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1218 basic_table_impls!(impl_the_methods);
1219
1220 pub fn coverage_format(&self) -> u16 {
1222 let range = self.coverage_format_byte_range();
1223 self.data.read_at(range.start).ok().unwrap()
1224 }
1225
1226 pub fn range_count(&self) -> u16 {
1228 let range = self.range_count_byte_range();
1229 self.data.read_at(range.start).ok().unwrap()
1230 }
1231
1232 pub fn range_records(&self) -> &'a [RangeRecord] {
1234 let range = self.range_records_byte_range();
1235 self.data.read_array(range).ok().unwrap_or_default()
1236 }
1237
1238 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1239 let start = 0;
1240 let end = start + u16::RAW_BYTE_LEN;
1241 start..end
1242 }
1243
1244 pub fn range_count_byte_range(&self) -> Range<usize> {
1245 let start = self.coverage_format_byte_range().end;
1246 let end = start + u16::RAW_BYTE_LEN;
1247 start..end
1248 }
1249
1250 pub fn range_records_byte_range(&self) -> Range<usize> {
1251 let range_count = self.range_count();
1252 let start = self.range_count_byte_range().end;
1253 let end =
1254 start + (transforms::to_usize(range_count)).saturating_mul(RangeRecord::RAW_BYTE_LEN);
1255 start..end
1256 }
1257}
1258
1259#[cfg(feature = "experimental_traverse")]
1260impl<'a> SomeTable<'a> for CoverageFormat2<'a> {
1261 fn type_name(&self) -> &str {
1262 "CoverageFormat2"
1263 }
1264 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1265 match idx {
1266 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1267 1usize => Some(Field::new("range_count", self.range_count())),
1268 2usize => Some(Field::new(
1269 "range_records",
1270 traversal::FieldType::array_of_records(
1271 stringify!(RangeRecord),
1272 self.range_records(),
1273 self.offset_data(),
1274 ),
1275 )),
1276 _ => None,
1277 }
1278 }
1279}
1280
1281#[cfg(feature = "experimental_traverse")]
1282#[allow(clippy::needless_lifetimes)]
1283impl<'a> std::fmt::Debug for CoverageFormat2<'a> {
1284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1285 (self as &dyn SomeTable<'a>).fmt(f)
1286 }
1287}
1288
1289#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1291#[repr(C)]
1292#[repr(packed)]
1293pub struct RangeRecord {
1294 pub start_glyph_id: BigEndian<GlyphId16>,
1296 pub end_glyph_id: BigEndian<GlyphId16>,
1298 pub start_coverage_index: BigEndian<u16>,
1300}
1301
1302impl RangeRecord {
1303 pub fn start_glyph_id(&self) -> GlyphId16 {
1305 self.start_glyph_id.get()
1306 }
1307
1308 pub fn end_glyph_id(&self) -> GlyphId16 {
1310 self.end_glyph_id.get()
1311 }
1312
1313 pub fn start_coverage_index(&self) -> u16 {
1315 self.start_coverage_index.get()
1316 }
1317}
1318
1319impl FixedSize for RangeRecord {
1320 const RAW_BYTE_LEN: usize =
1321 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1322}
1323
1324#[cfg(feature = "experimental_traverse")]
1325impl<'a> SomeRecord<'a> for RangeRecord {
1326 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1327 RecordResolver {
1328 name: "RangeRecord",
1329 get_field: Box::new(move |idx, _data| match idx {
1330 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1331 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1332 2usize => Some(Field::new(
1333 "start_coverage_index",
1334 self.start_coverage_index(),
1335 )),
1336 _ => None,
1337 }),
1338 data,
1339 }
1340 }
1341}
1342
1343#[derive(Clone)]
1345pub enum CoverageTable<'a> {
1346 Format1(CoverageFormat1<'a>),
1347 Format2(CoverageFormat2<'a>),
1348}
1349
1350impl Default for CoverageTable<'_> {
1351 fn default() -> Self {
1352 Self::Format1(Default::default())
1353 }
1354}
1355
1356impl<'a> CoverageTable<'a> {
1357 pub fn offset_data(&self) -> FontData<'a> {
1359 match self {
1360 Self::Format1(item) => item.offset_data(),
1361 Self::Format2(item) => item.offset_data(),
1362 }
1363 }
1364
1365 pub fn coverage_format(&self) -> u16 {
1367 match self {
1368 Self::Format1(item) => item.coverage_format(),
1369 Self::Format2(item) => item.coverage_format(),
1370 }
1371 }
1372}
1373
1374impl ReadArgs for CoverageTable<'_> {
1375 type Args = ();
1376}
1377
1378impl<'a> FontRead<'a> for CoverageTable<'a> {
1379 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1380 let format: u16 = data.read_at(0usize)?;
1381 match format {
1382 CoverageFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1383 CoverageFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1384 other => Err(ReadError::InvalidFormat(other.into())),
1385 }
1386 }
1387}
1388
1389impl<'a> MinByteRange<'a> for CoverageTable<'a> {
1390 fn min_byte_range(&self) -> Range<usize> {
1391 match self {
1392 Self::Format1(item) => item.min_byte_range(),
1393 Self::Format2(item) => item.min_byte_range(),
1394 }
1395 }
1396 fn min_table_bytes(&self) -> &'a [u8] {
1397 match self {
1398 Self::Format1(item) => item.min_table_bytes(),
1399 Self::Format2(item) => item.min_table_bytes(),
1400 }
1401 }
1402}
1403
1404#[cfg(feature = "experimental_traverse")]
1405impl<'a> CoverageTable<'a> {
1406 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1407 match self {
1408 Self::Format1(table) => table,
1409 Self::Format2(table) => table,
1410 }
1411 }
1412}
1413
1414#[cfg(feature = "experimental_traverse")]
1415impl std::fmt::Debug for CoverageTable<'_> {
1416 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1417 self.dyn_inner().fmt(f)
1418 }
1419}
1420
1421#[cfg(feature = "experimental_traverse")]
1422impl<'a> SomeTable<'a> for CoverageTable<'a> {
1423 fn type_name(&self) -> &str {
1424 self.dyn_inner().type_name()
1425 }
1426 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1427 self.dyn_inner().get_field(idx)
1428 }
1429}
1430
1431impl Format<u16> for ClassDefFormat1<'_> {
1432 const FORMAT: u16 = 1;
1433}
1434
1435impl<'a> MinByteRange<'a> for ClassDefFormat1<'a> {
1436 fn min_byte_range(&self) -> Range<usize> {
1437 0..self.class_value_array_byte_range().end
1438 }
1439 fn min_table_bytes(&self) -> &'a [u8] {
1440 let range = self.min_byte_range();
1441 self.data.as_bytes().get(range).unwrap_or_default()
1442 }
1443}
1444
1445impl ReadArgs for ClassDefFormat1<'_> {
1446 type Args = ();
1447}
1448
1449impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1450 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1451 #[allow(clippy::absurd_extreme_comparisons)]
1452 if data.len() < Self::MIN_SIZE {
1453 return Err(ReadError::OutOfBounds);
1454 }
1455 Ok(Self { data })
1456 }
1457}
1458
1459#[derive(Clone)]
1461pub struct ClassDefFormat1<'a> {
1462 data: FontData<'a>,
1463}
1464
1465#[allow(clippy::needless_lifetimes)]
1466impl<'a> ClassDefFormat1<'a> {
1467 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1468 basic_table_impls!(impl_the_methods);
1469
1470 pub fn class_format(&self) -> u16 {
1472 let range = self.class_format_byte_range();
1473 self.data.read_at(range.start).ok().unwrap()
1474 }
1475
1476 pub fn start_glyph_id(&self) -> GlyphId16 {
1478 let range = self.start_glyph_id_byte_range();
1479 self.data.read_at(range.start).ok().unwrap()
1480 }
1481
1482 pub fn glyph_count(&self) -> u16 {
1484 let range = self.glyph_count_byte_range();
1485 self.data.read_at(range.start).ok().unwrap()
1486 }
1487
1488 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1490 let range = self.class_value_array_byte_range();
1491 self.data.read_array(range).ok().unwrap_or_default()
1492 }
1493
1494 pub fn class_format_byte_range(&self) -> Range<usize> {
1495 let start = 0;
1496 let end = start + u16::RAW_BYTE_LEN;
1497 start..end
1498 }
1499
1500 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1501 let start = self.class_format_byte_range().end;
1502 let end = start + GlyphId16::RAW_BYTE_LEN;
1503 start..end
1504 }
1505
1506 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1507 let start = self.start_glyph_id_byte_range().end;
1508 let end = start + u16::RAW_BYTE_LEN;
1509 start..end
1510 }
1511
1512 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1513 let glyph_count = self.glyph_count();
1514 let start = self.glyph_count_byte_range().end;
1515 let end = start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
1516 start..end
1517 }
1518}
1519
1520const _: () = assert!(FontData::default_data_long_enough(
1521 ClassDefFormat1::MIN_SIZE
1522));
1523
1524impl Default for ClassDefFormat1<'_> {
1525 fn default() -> Self {
1526 Self {
1527 data: FontData::default_format_1_u16_table_data(),
1528 }
1529 }
1530}
1531
1532#[cfg(feature = "experimental_traverse")]
1533impl<'a> SomeTable<'a> for ClassDefFormat1<'a> {
1534 fn type_name(&self) -> &str {
1535 "ClassDefFormat1"
1536 }
1537 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1538 match idx {
1539 0usize => Some(Field::new("class_format", self.class_format())),
1540 1usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1541 2usize => Some(Field::new("glyph_count", self.glyph_count())),
1542 3usize => Some(Field::new("class_value_array", self.class_value_array())),
1543 _ => None,
1544 }
1545 }
1546}
1547
1548#[cfg(feature = "experimental_traverse")]
1549#[allow(clippy::needless_lifetimes)]
1550impl<'a> std::fmt::Debug for ClassDefFormat1<'a> {
1551 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1552 (self as &dyn SomeTable<'a>).fmt(f)
1553 }
1554}
1555
1556impl Format<u16> for ClassDefFormat2<'_> {
1557 const FORMAT: u16 = 2;
1558}
1559
1560impl<'a> MinByteRange<'a> for ClassDefFormat2<'a> {
1561 fn min_byte_range(&self) -> Range<usize> {
1562 0..self.class_range_records_byte_range().end
1563 }
1564 fn min_table_bytes(&self) -> &'a [u8] {
1565 let range = self.min_byte_range();
1566 self.data.as_bytes().get(range).unwrap_or_default()
1567 }
1568}
1569
1570impl ReadArgs for ClassDefFormat2<'_> {
1571 type Args = ();
1572}
1573
1574impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1575 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1576 #[allow(clippy::absurd_extreme_comparisons)]
1577 if data.len() < Self::MIN_SIZE {
1578 return Err(ReadError::OutOfBounds);
1579 }
1580 Ok(Self { data })
1581 }
1582}
1583
1584#[derive(Clone)]
1586pub struct ClassDefFormat2<'a> {
1587 data: FontData<'a>,
1588}
1589
1590#[allow(clippy::needless_lifetimes)]
1591impl<'a> ClassDefFormat2<'a> {
1592 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1593 basic_table_impls!(impl_the_methods);
1594
1595 pub fn class_format(&self) -> u16 {
1597 let range = self.class_format_byte_range();
1598 self.data.read_at(range.start).ok().unwrap()
1599 }
1600
1601 pub fn class_range_count(&self) -> u16 {
1603 let range = self.class_range_count_byte_range();
1604 self.data.read_at(range.start).ok().unwrap()
1605 }
1606
1607 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1609 let range = self.class_range_records_byte_range();
1610 self.data.read_array(range).ok().unwrap_or_default()
1611 }
1612
1613 pub fn class_format_byte_range(&self) -> Range<usize> {
1614 let start = 0;
1615 let end = start + u16::RAW_BYTE_LEN;
1616 start..end
1617 }
1618
1619 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1620 let start = self.class_format_byte_range().end;
1621 let end = start + u16::RAW_BYTE_LEN;
1622 start..end
1623 }
1624
1625 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1626 let class_range_count = self.class_range_count();
1627 let start = self.class_range_count_byte_range().end;
1628 let end = start
1629 + (transforms::to_usize(class_range_count))
1630 .saturating_mul(ClassRangeRecord::RAW_BYTE_LEN);
1631 start..end
1632 }
1633}
1634
1635#[cfg(feature = "experimental_traverse")]
1636impl<'a> SomeTable<'a> for ClassDefFormat2<'a> {
1637 fn type_name(&self) -> &str {
1638 "ClassDefFormat2"
1639 }
1640 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1641 match idx {
1642 0usize => Some(Field::new("class_format", self.class_format())),
1643 1usize => Some(Field::new("class_range_count", self.class_range_count())),
1644 2usize => Some(Field::new(
1645 "class_range_records",
1646 traversal::FieldType::array_of_records(
1647 stringify!(ClassRangeRecord),
1648 self.class_range_records(),
1649 self.offset_data(),
1650 ),
1651 )),
1652 _ => None,
1653 }
1654 }
1655}
1656
1657#[cfg(feature = "experimental_traverse")]
1658#[allow(clippy::needless_lifetimes)]
1659impl<'a> std::fmt::Debug for ClassDefFormat2<'a> {
1660 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1661 (self as &dyn SomeTable<'a>).fmt(f)
1662 }
1663}
1664
1665#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1667#[repr(C)]
1668#[repr(packed)]
1669pub struct ClassRangeRecord {
1670 pub start_glyph_id: BigEndian<GlyphId16>,
1672 pub end_glyph_id: BigEndian<GlyphId16>,
1674 pub class: BigEndian<u16>,
1676}
1677
1678impl ClassRangeRecord {
1679 pub fn start_glyph_id(&self) -> GlyphId16 {
1681 self.start_glyph_id.get()
1682 }
1683
1684 pub fn end_glyph_id(&self) -> GlyphId16 {
1686 self.end_glyph_id.get()
1687 }
1688
1689 pub fn class(&self) -> u16 {
1691 self.class.get()
1692 }
1693}
1694
1695impl FixedSize for ClassRangeRecord {
1696 const RAW_BYTE_LEN: usize =
1697 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1698}
1699
1700#[cfg(feature = "experimental_traverse")]
1701impl<'a> SomeRecord<'a> for ClassRangeRecord {
1702 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1703 RecordResolver {
1704 name: "ClassRangeRecord",
1705 get_field: Box::new(move |idx, _data| match idx {
1706 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1707 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1708 2usize => Some(Field::new("class", self.class())),
1709 _ => None,
1710 }),
1711 data,
1712 }
1713 }
1714}
1715
1716#[derive(Clone)]
1718pub enum ClassDef<'a> {
1719 Format1(ClassDefFormat1<'a>),
1720 Format2(ClassDefFormat2<'a>),
1721}
1722
1723impl Default for ClassDef<'_> {
1724 fn default() -> Self {
1725 Self::Format1(Default::default())
1726 }
1727}
1728
1729impl<'a> ClassDef<'a> {
1730 pub fn offset_data(&self) -> FontData<'a> {
1732 match self {
1733 Self::Format1(item) => item.offset_data(),
1734 Self::Format2(item) => item.offset_data(),
1735 }
1736 }
1737
1738 pub fn class_format(&self) -> u16 {
1740 match self {
1741 Self::Format1(item) => item.class_format(),
1742 Self::Format2(item) => item.class_format(),
1743 }
1744 }
1745}
1746
1747impl ReadArgs for ClassDef<'_> {
1748 type Args = ();
1749}
1750
1751impl<'a> FontRead<'a> for ClassDef<'a> {
1752 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1753 let format: u16 = data.read_at(0usize)?;
1754 match format {
1755 ClassDefFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1756 ClassDefFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1757 other => Err(ReadError::InvalidFormat(other.into())),
1758 }
1759 }
1760}
1761
1762impl<'a> MinByteRange<'a> for ClassDef<'a> {
1763 fn min_byte_range(&self) -> Range<usize> {
1764 match self {
1765 Self::Format1(item) => item.min_byte_range(),
1766 Self::Format2(item) => item.min_byte_range(),
1767 }
1768 }
1769 fn min_table_bytes(&self) -> &'a [u8] {
1770 match self {
1771 Self::Format1(item) => item.min_table_bytes(),
1772 Self::Format2(item) => item.min_table_bytes(),
1773 }
1774 }
1775}
1776
1777#[cfg(feature = "experimental_traverse")]
1778impl<'a> ClassDef<'a> {
1779 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1780 match self {
1781 Self::Format1(table) => table,
1782 Self::Format2(table) => table,
1783 }
1784 }
1785}
1786
1787#[cfg(feature = "experimental_traverse")]
1788impl std::fmt::Debug for ClassDef<'_> {
1789 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1790 self.dyn_inner().fmt(f)
1791 }
1792}
1793
1794#[cfg(feature = "experimental_traverse")]
1795impl<'a> SomeTable<'a> for ClassDef<'a> {
1796 fn type_name(&self) -> &str {
1797 self.dyn_inner().type_name()
1798 }
1799 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1800 self.dyn_inner().get_field(idx)
1801 }
1802}
1803
1804#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1806#[repr(C)]
1807#[repr(packed)]
1808pub struct SequenceLookupRecord {
1809 pub sequence_index: BigEndian<u16>,
1811 pub lookup_list_index: BigEndian<u16>,
1813}
1814
1815impl SequenceLookupRecord {
1816 pub fn sequence_index(&self) -> u16 {
1818 self.sequence_index.get()
1819 }
1820
1821 pub fn lookup_list_index(&self) -> u16 {
1823 self.lookup_list_index.get()
1824 }
1825}
1826
1827impl FixedSize for SequenceLookupRecord {
1828 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1829}
1830
1831#[cfg(feature = "experimental_traverse")]
1832impl<'a> SomeRecord<'a> for SequenceLookupRecord {
1833 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1834 RecordResolver {
1835 name: "SequenceLookupRecord",
1836 get_field: Box::new(move |idx, _data| match idx {
1837 0usize => Some(Field::new("sequence_index", self.sequence_index())),
1838 1usize => Some(Field::new("lookup_list_index", self.lookup_list_index())),
1839 _ => None,
1840 }),
1841 data,
1842 }
1843 }
1844}
1845
1846impl Format<u16> for SequenceContextFormat1<'_> {
1847 const FORMAT: u16 = 1;
1848}
1849
1850impl<'a> MinByteRange<'a> for SequenceContextFormat1<'a> {
1851 fn min_byte_range(&self) -> Range<usize> {
1852 0..self.seq_rule_set_offsets_byte_range().end
1853 }
1854 fn min_table_bytes(&self) -> &'a [u8] {
1855 let range = self.min_byte_range();
1856 self.data.as_bytes().get(range).unwrap_or_default()
1857 }
1858}
1859
1860impl ReadArgs for SequenceContextFormat1<'_> {
1861 type Args = ();
1862}
1863
1864impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1865 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1866 #[allow(clippy::absurd_extreme_comparisons)]
1867 if data.len() < Self::MIN_SIZE {
1868 return Err(ReadError::OutOfBounds);
1869 }
1870 Ok(Self { data })
1871 }
1872}
1873
1874#[derive(Clone)]
1876pub struct SequenceContextFormat1<'a> {
1877 data: FontData<'a>,
1878}
1879
1880#[allow(clippy::needless_lifetimes)]
1881impl<'a> SequenceContextFormat1<'a> {
1882 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1883 basic_table_impls!(impl_the_methods);
1884
1885 pub fn format(&self) -> u16 {
1887 let range = self.format_byte_range();
1888 self.data.read_at(range.start).ok().unwrap()
1889 }
1890
1891 pub fn coverage_offset(&self) -> Offset16 {
1894 let range = self.coverage_offset_byte_range();
1895 self.data.read_at(range.start).ok().unwrap()
1896 }
1897
1898 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1900 let data = self.data;
1901 self.coverage_offset().resolve(data)
1902 }
1903
1904 pub fn seq_rule_set_count(&self) -> u16 {
1906 let range = self.seq_rule_set_count_byte_range();
1907 self.data.read_at(range.start).ok().unwrap()
1908 }
1909
1910 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1913 let range = self.seq_rule_set_offsets_byte_range();
1914 self.data.read_array(range).ok().unwrap_or_default()
1915 }
1916
1917 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1919 let data = self.data;
1920 let offsets = self.seq_rule_set_offsets();
1921 ArrayOfNullableOffsets::new(offsets, data, ())
1922 }
1923
1924 pub fn format_byte_range(&self) -> Range<usize> {
1925 let start = 0;
1926 let end = start + u16::RAW_BYTE_LEN;
1927 start..end
1928 }
1929
1930 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1931 let start = self.format_byte_range().end;
1932 let end = start + Offset16::RAW_BYTE_LEN;
1933 start..end
1934 }
1935
1936 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1937 let start = self.coverage_offset_byte_range().end;
1938 let end = start + u16::RAW_BYTE_LEN;
1939 start..end
1940 }
1941
1942 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1943 let seq_rule_set_count = self.seq_rule_set_count();
1944 let start = self.seq_rule_set_count_byte_range().end;
1945 let end = start
1946 + (transforms::to_usize(seq_rule_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1947 start..end
1948 }
1949}
1950
1951const _: () = assert!(FontData::default_data_long_enough(
1952 SequenceContextFormat1::MIN_SIZE
1953));
1954
1955impl Default for SequenceContextFormat1<'_> {
1956 fn default() -> Self {
1957 Self {
1958 data: FontData::default_format_1_u16_table_data(),
1959 }
1960 }
1961}
1962
1963#[cfg(feature = "experimental_traverse")]
1964impl<'a> SomeTable<'a> for SequenceContextFormat1<'a> {
1965 fn type_name(&self) -> &str {
1966 "SequenceContextFormat1"
1967 }
1968 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1969 match idx {
1970 0usize => Some(Field::new("format", self.format())),
1971 1usize => Some(Field::new(
1972 "coverage_offset",
1973 FieldType::offset(self.coverage_offset(), self.coverage()),
1974 )),
1975 2usize => Some(Field::new("seq_rule_set_count", self.seq_rule_set_count())),
1976 3usize => Some(Field::new(
1977 "seq_rule_set_offsets",
1978 FieldType::from(self.seq_rule_sets()),
1979 )),
1980 _ => None,
1981 }
1982 }
1983}
1984
1985#[cfg(feature = "experimental_traverse")]
1986#[allow(clippy::needless_lifetimes)]
1987impl<'a> std::fmt::Debug for SequenceContextFormat1<'a> {
1988 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1989 (self as &dyn SomeTable<'a>).fmt(f)
1990 }
1991}
1992
1993impl<'a> MinByteRange<'a> for SequenceRuleSet<'a> {
1994 fn min_byte_range(&self) -> Range<usize> {
1995 0..self.seq_rule_offsets_byte_range().end
1996 }
1997 fn min_table_bytes(&self) -> &'a [u8] {
1998 let range = self.min_byte_range();
1999 self.data.as_bytes().get(range).unwrap_or_default()
2000 }
2001}
2002
2003impl ReadArgs for SequenceRuleSet<'_> {
2004 type Args = ();
2005}
2006
2007impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
2008 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2009 #[allow(clippy::absurd_extreme_comparisons)]
2010 if data.len() < Self::MIN_SIZE {
2011 return Err(ReadError::OutOfBounds);
2012 }
2013 Ok(Self { data })
2014 }
2015}
2016
2017#[derive(Clone)]
2019pub struct SequenceRuleSet<'a> {
2020 data: FontData<'a>,
2021}
2022
2023#[allow(clippy::needless_lifetimes)]
2024impl<'a> SequenceRuleSet<'a> {
2025 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2026 basic_table_impls!(impl_the_methods);
2027
2028 pub fn seq_rule_count(&self) -> u16 {
2030 let range = self.seq_rule_count_byte_range();
2031 self.data.read_at(range.start).ok().unwrap()
2032 }
2033
2034 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2037 let range = self.seq_rule_offsets_byte_range();
2038 self.data.read_array(range).ok().unwrap_or_default()
2039 }
2040
2041 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
2043 let data = self.data;
2044 let offsets = self.seq_rule_offsets();
2045 ArrayOfOffsets::new(offsets, data, ())
2046 }
2047
2048 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
2049 let start = 0;
2050 let end = start + u16::RAW_BYTE_LEN;
2051 start..end
2052 }
2053
2054 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
2055 let seq_rule_count = self.seq_rule_count();
2056 let start = self.seq_rule_count_byte_range().end;
2057 let end =
2058 start + (transforms::to_usize(seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2059 start..end
2060 }
2061}
2062
2063const _: () = assert!(FontData::default_data_long_enough(
2064 SequenceRuleSet::MIN_SIZE
2065));
2066
2067impl Default for SequenceRuleSet<'_> {
2068 fn default() -> Self {
2069 Self {
2070 data: FontData::default_table_data(),
2071 }
2072 }
2073}
2074
2075#[cfg(feature = "experimental_traverse")]
2076impl<'a> SomeTable<'a> for SequenceRuleSet<'a> {
2077 fn type_name(&self) -> &str {
2078 "SequenceRuleSet"
2079 }
2080 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2081 match idx {
2082 0usize => Some(Field::new("seq_rule_count", self.seq_rule_count())),
2083 1usize => Some(Field::new(
2084 "seq_rule_offsets",
2085 FieldType::from(self.seq_rules()),
2086 )),
2087 _ => None,
2088 }
2089 }
2090}
2091
2092#[cfg(feature = "experimental_traverse")]
2093#[allow(clippy::needless_lifetimes)]
2094impl<'a> std::fmt::Debug for SequenceRuleSet<'a> {
2095 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2096 (self as &dyn SomeTable<'a>).fmt(f)
2097 }
2098}
2099
2100impl<'a> MinByteRange<'a> for SequenceRule<'a> {
2101 fn min_byte_range(&self) -> Range<usize> {
2102 0..self.seq_lookup_records_byte_range().end
2103 }
2104 fn min_table_bytes(&self) -> &'a [u8] {
2105 let range = self.min_byte_range();
2106 self.data.as_bytes().get(range).unwrap_or_default()
2107 }
2108}
2109
2110impl ReadArgs for SequenceRule<'_> {
2111 type Args = ();
2112}
2113
2114impl<'a> FontRead<'a> for SequenceRule<'a> {
2115 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2116 #[allow(clippy::absurd_extreme_comparisons)]
2117 if data.len() < Self::MIN_SIZE {
2118 return Err(ReadError::OutOfBounds);
2119 }
2120 Ok(Self { data })
2121 }
2122}
2123
2124#[derive(Clone)]
2126pub struct SequenceRule<'a> {
2127 data: FontData<'a>,
2128}
2129
2130#[allow(clippy::needless_lifetimes)]
2131impl<'a> SequenceRule<'a> {
2132 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2133 basic_table_impls!(impl_the_methods);
2134
2135 pub fn glyph_count(&self) -> u16 {
2137 let range = self.glyph_count_byte_range();
2138 self.data.read_at(range.start).ok().unwrap()
2139 }
2140
2141 pub fn seq_lookup_count(&self) -> u16 {
2143 let range = self.seq_lookup_count_byte_range();
2144 self.data.read_at(range.start).ok().unwrap()
2145 }
2146
2147 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2149 let range = self.input_sequence_byte_range();
2150 self.data.read_array(range).ok().unwrap_or_default()
2151 }
2152
2153 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2155 let range = self.seq_lookup_records_byte_range();
2156 self.data.read_array(range).ok().unwrap_or_default()
2157 }
2158
2159 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2160 let start = 0;
2161 let end = start + u16::RAW_BYTE_LEN;
2162 start..end
2163 }
2164
2165 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2166 let start = self.glyph_count_byte_range().end;
2167 let end = start + u16::RAW_BYTE_LEN;
2168 start..end
2169 }
2170
2171 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2172 let glyph_count = self.glyph_count();
2173 let start = self.seq_lookup_count_byte_range().end;
2174 let end = start
2175 + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
2176 start..end
2177 }
2178
2179 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2180 let seq_lookup_count = self.seq_lookup_count();
2181 let start = self.input_sequence_byte_range().end;
2182 let end = start
2183 + (transforms::to_usize(seq_lookup_count))
2184 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2185 start..end
2186 }
2187}
2188
2189const _: () = assert!(FontData::default_data_long_enough(SequenceRule::MIN_SIZE));
2190
2191impl Default for SequenceRule<'_> {
2192 fn default() -> Self {
2193 Self {
2194 data: FontData::default_table_data(),
2195 }
2196 }
2197}
2198
2199#[cfg(feature = "experimental_traverse")]
2200impl<'a> SomeTable<'a> for SequenceRule<'a> {
2201 fn type_name(&self) -> &str {
2202 "SequenceRule"
2203 }
2204 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2205 match idx {
2206 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2207 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2208 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2209 3usize => Some(Field::new(
2210 "seq_lookup_records",
2211 traversal::FieldType::array_of_records(
2212 stringify!(SequenceLookupRecord),
2213 self.seq_lookup_records(),
2214 self.offset_data(),
2215 ),
2216 )),
2217 _ => None,
2218 }
2219 }
2220}
2221
2222#[cfg(feature = "experimental_traverse")]
2223#[allow(clippy::needless_lifetimes)]
2224impl<'a> std::fmt::Debug for SequenceRule<'a> {
2225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2226 (self as &dyn SomeTable<'a>).fmt(f)
2227 }
2228}
2229
2230impl Format<u16> for SequenceContextFormat2<'_> {
2231 const FORMAT: u16 = 2;
2232}
2233
2234impl<'a> MinByteRange<'a> for SequenceContextFormat2<'a> {
2235 fn min_byte_range(&self) -> Range<usize> {
2236 0..self.class_seq_rule_set_offsets_byte_range().end
2237 }
2238 fn min_table_bytes(&self) -> &'a [u8] {
2239 let range = self.min_byte_range();
2240 self.data.as_bytes().get(range).unwrap_or_default()
2241 }
2242}
2243
2244impl ReadArgs for SequenceContextFormat2<'_> {
2245 type Args = ();
2246}
2247
2248impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
2249 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2250 #[allow(clippy::absurd_extreme_comparisons)]
2251 if data.len() < Self::MIN_SIZE {
2252 return Err(ReadError::OutOfBounds);
2253 }
2254 Ok(Self { data })
2255 }
2256}
2257
2258#[derive(Clone)]
2260pub struct SequenceContextFormat2<'a> {
2261 data: FontData<'a>,
2262}
2263
2264#[allow(clippy::needless_lifetimes)]
2265impl<'a> SequenceContextFormat2<'a> {
2266 pub const MIN_SIZE: usize =
2267 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2268 basic_table_impls!(impl_the_methods);
2269
2270 pub fn format(&self) -> u16 {
2272 let range = self.format_byte_range();
2273 self.data.read_at(range.start).ok().unwrap()
2274 }
2275
2276 pub fn coverage_offset(&self) -> Offset16 {
2279 let range = self.coverage_offset_byte_range();
2280 self.data.read_at(range.start).ok().unwrap()
2281 }
2282
2283 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2285 let data = self.data;
2286 self.coverage_offset().resolve(data)
2287 }
2288
2289 pub fn class_def_offset(&self) -> Offset16 {
2292 let range = self.class_def_offset_byte_range();
2293 self.data.read_at(range.start).ok().unwrap()
2294 }
2295
2296 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2298 let data = self.data;
2299 self.class_def_offset().resolve(data)
2300 }
2301
2302 pub fn class_seq_rule_set_count(&self) -> u16 {
2304 let range = self.class_seq_rule_set_count_byte_range();
2305 self.data.read_at(range.start).ok().unwrap()
2306 }
2307
2308 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2311 let range = self.class_seq_rule_set_offsets_byte_range();
2312 self.data.read_array(range).ok().unwrap_or_default()
2313 }
2314
2315 pub fn class_seq_rule_sets(
2317 &self,
2318 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
2319 let data = self.data;
2320 let offsets = self.class_seq_rule_set_offsets();
2321 ArrayOfNullableOffsets::new(offsets, data, ())
2322 }
2323
2324 pub fn format_byte_range(&self) -> Range<usize> {
2325 let start = 0;
2326 let end = start + u16::RAW_BYTE_LEN;
2327 start..end
2328 }
2329
2330 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2331 let start = self.format_byte_range().end;
2332 let end = start + Offset16::RAW_BYTE_LEN;
2333 start..end
2334 }
2335
2336 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
2337 let start = self.coverage_offset_byte_range().end;
2338 let end = start + Offset16::RAW_BYTE_LEN;
2339 start..end
2340 }
2341
2342 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2343 let start = self.class_def_offset_byte_range().end;
2344 let end = start + u16::RAW_BYTE_LEN;
2345 start..end
2346 }
2347
2348 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2349 let class_seq_rule_set_count = self.class_seq_rule_set_count();
2350 let start = self.class_seq_rule_set_count_byte_range().end;
2351 let end = start
2352 + (transforms::to_usize(class_seq_rule_set_count))
2353 .saturating_mul(Offset16::RAW_BYTE_LEN);
2354 start..end
2355 }
2356}
2357
2358#[cfg(feature = "experimental_traverse")]
2359impl<'a> SomeTable<'a> for SequenceContextFormat2<'a> {
2360 fn type_name(&self) -> &str {
2361 "SequenceContextFormat2"
2362 }
2363 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2364 match idx {
2365 0usize => Some(Field::new("format", self.format())),
2366 1usize => Some(Field::new(
2367 "coverage_offset",
2368 FieldType::offset(self.coverage_offset(), self.coverage()),
2369 )),
2370 2usize => Some(Field::new(
2371 "class_def_offset",
2372 FieldType::offset(self.class_def_offset(), self.class_def()),
2373 )),
2374 3usize => Some(Field::new(
2375 "class_seq_rule_set_count",
2376 self.class_seq_rule_set_count(),
2377 )),
2378 4usize => Some(Field::new(
2379 "class_seq_rule_set_offsets",
2380 FieldType::from(self.class_seq_rule_sets()),
2381 )),
2382 _ => None,
2383 }
2384 }
2385}
2386
2387#[cfg(feature = "experimental_traverse")]
2388#[allow(clippy::needless_lifetimes)]
2389impl<'a> std::fmt::Debug for SequenceContextFormat2<'a> {
2390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2391 (self as &dyn SomeTable<'a>).fmt(f)
2392 }
2393}
2394
2395impl<'a> MinByteRange<'a> for ClassSequenceRuleSet<'a> {
2396 fn min_byte_range(&self) -> Range<usize> {
2397 0..self.class_seq_rule_offsets_byte_range().end
2398 }
2399 fn min_table_bytes(&self) -> &'a [u8] {
2400 let range = self.min_byte_range();
2401 self.data.as_bytes().get(range).unwrap_or_default()
2402 }
2403}
2404
2405impl ReadArgs for ClassSequenceRuleSet<'_> {
2406 type Args = ();
2407}
2408
2409impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
2410 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2411 #[allow(clippy::absurd_extreme_comparisons)]
2412 if data.len() < Self::MIN_SIZE {
2413 return Err(ReadError::OutOfBounds);
2414 }
2415 Ok(Self { data })
2416 }
2417}
2418
2419#[derive(Clone)]
2421pub struct ClassSequenceRuleSet<'a> {
2422 data: FontData<'a>,
2423}
2424
2425#[allow(clippy::needless_lifetimes)]
2426impl<'a> ClassSequenceRuleSet<'a> {
2427 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2428 basic_table_impls!(impl_the_methods);
2429
2430 pub fn class_seq_rule_count(&self) -> u16 {
2432 let range = self.class_seq_rule_count_byte_range();
2433 self.data.read_at(range.start).ok().unwrap()
2434 }
2435
2436 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2439 let range = self.class_seq_rule_offsets_byte_range();
2440 self.data.read_array(range).ok().unwrap_or_default()
2441 }
2442
2443 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
2445 let data = self.data;
2446 let offsets = self.class_seq_rule_offsets();
2447 ArrayOfOffsets::new(offsets, data, ())
2448 }
2449
2450 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
2451 let start = 0;
2452 let end = start + u16::RAW_BYTE_LEN;
2453 start..end
2454 }
2455
2456 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2457 let class_seq_rule_count = self.class_seq_rule_count();
2458 let start = self.class_seq_rule_count_byte_range().end;
2459 let end = start
2460 + (transforms::to_usize(class_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2461 start..end
2462 }
2463}
2464
2465const _: () = assert!(FontData::default_data_long_enough(
2466 ClassSequenceRuleSet::MIN_SIZE
2467));
2468
2469impl Default for ClassSequenceRuleSet<'_> {
2470 fn default() -> Self {
2471 Self {
2472 data: FontData::default_table_data(),
2473 }
2474 }
2475}
2476
2477#[cfg(feature = "experimental_traverse")]
2478impl<'a> SomeTable<'a> for ClassSequenceRuleSet<'a> {
2479 fn type_name(&self) -> &str {
2480 "ClassSequenceRuleSet"
2481 }
2482 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2483 match idx {
2484 0usize => Some(Field::new(
2485 "class_seq_rule_count",
2486 self.class_seq_rule_count(),
2487 )),
2488 1usize => Some(Field::new(
2489 "class_seq_rule_offsets",
2490 FieldType::from(self.class_seq_rules()),
2491 )),
2492 _ => None,
2493 }
2494 }
2495}
2496
2497#[cfg(feature = "experimental_traverse")]
2498#[allow(clippy::needless_lifetimes)]
2499impl<'a> std::fmt::Debug for ClassSequenceRuleSet<'a> {
2500 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2501 (self as &dyn SomeTable<'a>).fmt(f)
2502 }
2503}
2504
2505impl<'a> MinByteRange<'a> for ClassSequenceRule<'a> {
2506 fn min_byte_range(&self) -> Range<usize> {
2507 0..self.seq_lookup_records_byte_range().end
2508 }
2509 fn min_table_bytes(&self) -> &'a [u8] {
2510 let range = self.min_byte_range();
2511 self.data.as_bytes().get(range).unwrap_or_default()
2512 }
2513}
2514
2515impl ReadArgs for ClassSequenceRule<'_> {
2516 type Args = ();
2517}
2518
2519impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
2520 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2521 #[allow(clippy::absurd_extreme_comparisons)]
2522 if data.len() < Self::MIN_SIZE {
2523 return Err(ReadError::OutOfBounds);
2524 }
2525 Ok(Self { data })
2526 }
2527}
2528
2529#[derive(Clone)]
2531pub struct ClassSequenceRule<'a> {
2532 data: FontData<'a>,
2533}
2534
2535#[allow(clippy::needless_lifetimes)]
2536impl<'a> ClassSequenceRule<'a> {
2537 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2538 basic_table_impls!(impl_the_methods);
2539
2540 pub fn glyph_count(&self) -> u16 {
2542 let range = self.glyph_count_byte_range();
2543 self.data.read_at(range.start).ok().unwrap()
2544 }
2545
2546 pub fn seq_lookup_count(&self) -> u16 {
2548 let range = self.seq_lookup_count_byte_range();
2549 self.data.read_at(range.start).ok().unwrap()
2550 }
2551
2552 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2555 let range = self.input_sequence_byte_range();
2556 self.data.read_array(range).ok().unwrap_or_default()
2557 }
2558
2559 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2561 let range = self.seq_lookup_records_byte_range();
2562 self.data.read_array(range).ok().unwrap_or_default()
2563 }
2564
2565 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2566 let start = 0;
2567 let end = start + u16::RAW_BYTE_LEN;
2568 start..end
2569 }
2570
2571 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2572 let start = self.glyph_count_byte_range().end;
2573 let end = start + u16::RAW_BYTE_LEN;
2574 start..end
2575 }
2576
2577 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2578 let glyph_count = self.glyph_count();
2579 let start = self.seq_lookup_count_byte_range().end;
2580 let end =
2581 start + (transforms::subtract(glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
2582 start..end
2583 }
2584
2585 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2586 let seq_lookup_count = self.seq_lookup_count();
2587 let start = self.input_sequence_byte_range().end;
2588 let end = start
2589 + (transforms::to_usize(seq_lookup_count))
2590 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2591 start..end
2592 }
2593}
2594
2595const _: () = assert!(FontData::default_data_long_enough(
2596 ClassSequenceRule::MIN_SIZE
2597));
2598
2599impl Default for ClassSequenceRule<'_> {
2600 fn default() -> Self {
2601 Self {
2602 data: FontData::default_table_data(),
2603 }
2604 }
2605}
2606
2607#[cfg(feature = "experimental_traverse")]
2608impl<'a> SomeTable<'a> for ClassSequenceRule<'a> {
2609 fn type_name(&self) -> &str {
2610 "ClassSequenceRule"
2611 }
2612 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2613 match idx {
2614 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2615 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2616 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2617 3usize => Some(Field::new(
2618 "seq_lookup_records",
2619 traversal::FieldType::array_of_records(
2620 stringify!(SequenceLookupRecord),
2621 self.seq_lookup_records(),
2622 self.offset_data(),
2623 ),
2624 )),
2625 _ => None,
2626 }
2627 }
2628}
2629
2630#[cfg(feature = "experimental_traverse")]
2631#[allow(clippy::needless_lifetimes)]
2632impl<'a> std::fmt::Debug for ClassSequenceRule<'a> {
2633 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2634 (self as &dyn SomeTable<'a>).fmt(f)
2635 }
2636}
2637
2638impl Format<u16> for SequenceContextFormat3<'_> {
2639 const FORMAT: u16 = 3;
2640}
2641
2642impl<'a> MinByteRange<'a> for SequenceContextFormat3<'a> {
2643 fn min_byte_range(&self) -> Range<usize> {
2644 0..self.seq_lookup_records_byte_range().end
2645 }
2646 fn min_table_bytes(&self) -> &'a [u8] {
2647 let range = self.min_byte_range();
2648 self.data.as_bytes().get(range).unwrap_or_default()
2649 }
2650}
2651
2652impl ReadArgs for SequenceContextFormat3<'_> {
2653 type Args = ();
2654}
2655
2656impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2657 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2658 #[allow(clippy::absurd_extreme_comparisons)]
2659 if data.len() < Self::MIN_SIZE {
2660 return Err(ReadError::OutOfBounds);
2661 }
2662 Ok(Self { data })
2663 }
2664}
2665
2666#[derive(Clone)]
2668pub struct SequenceContextFormat3<'a> {
2669 data: FontData<'a>,
2670}
2671
2672#[allow(clippy::needless_lifetimes)]
2673impl<'a> SequenceContextFormat3<'a> {
2674 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2675 basic_table_impls!(impl_the_methods);
2676
2677 pub fn format(&self) -> u16 {
2679 let range = self.format_byte_range();
2680 self.data.read_at(range.start).ok().unwrap()
2681 }
2682
2683 pub fn glyph_count(&self) -> u16 {
2685 let range = self.glyph_count_byte_range();
2686 self.data.read_at(range.start).ok().unwrap()
2687 }
2688
2689 pub fn seq_lookup_count(&self) -> u16 {
2691 let range = self.seq_lookup_count_byte_range();
2692 self.data.read_at(range.start).ok().unwrap()
2693 }
2694
2695 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2698 let range = self.coverage_offsets_byte_range();
2699 self.data.read_array(range).ok().unwrap_or_default()
2700 }
2701
2702 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2704 let data = self.data;
2705 let offsets = self.coverage_offsets();
2706 ArrayOfOffsets::new(offsets, data, ())
2707 }
2708
2709 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2711 let range = self.seq_lookup_records_byte_range();
2712 self.data.read_array(range).ok().unwrap_or_default()
2713 }
2714
2715 pub fn format_byte_range(&self) -> Range<usize> {
2716 let start = 0;
2717 let end = start + u16::RAW_BYTE_LEN;
2718 start..end
2719 }
2720
2721 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2722 let start = self.format_byte_range().end;
2723 let end = start + u16::RAW_BYTE_LEN;
2724 start..end
2725 }
2726
2727 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2728 let start = self.glyph_count_byte_range().end;
2729 let end = start + u16::RAW_BYTE_LEN;
2730 start..end
2731 }
2732
2733 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2734 let glyph_count = self.glyph_count();
2735 let start = self.seq_lookup_count_byte_range().end;
2736 let end =
2737 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2738 start..end
2739 }
2740
2741 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2742 let seq_lookup_count = self.seq_lookup_count();
2743 let start = self.coverage_offsets_byte_range().end;
2744 let end = start
2745 + (transforms::to_usize(seq_lookup_count))
2746 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
2747 start..end
2748 }
2749}
2750
2751#[cfg(feature = "experimental_traverse")]
2752impl<'a> SomeTable<'a> for SequenceContextFormat3<'a> {
2753 fn type_name(&self) -> &str {
2754 "SequenceContextFormat3"
2755 }
2756 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2757 match idx {
2758 0usize => Some(Field::new("format", self.format())),
2759 1usize => Some(Field::new("glyph_count", self.glyph_count())),
2760 2usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2761 3usize => Some(Field::new(
2762 "coverage_offsets",
2763 FieldType::from(self.coverages()),
2764 )),
2765 4usize => Some(Field::new(
2766 "seq_lookup_records",
2767 traversal::FieldType::array_of_records(
2768 stringify!(SequenceLookupRecord),
2769 self.seq_lookup_records(),
2770 self.offset_data(),
2771 ),
2772 )),
2773 _ => None,
2774 }
2775 }
2776}
2777
2778#[cfg(feature = "experimental_traverse")]
2779#[allow(clippy::needless_lifetimes)]
2780impl<'a> std::fmt::Debug for SequenceContextFormat3<'a> {
2781 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2782 (self as &dyn SomeTable<'a>).fmt(f)
2783 }
2784}
2785
2786#[derive(Clone)]
2787pub enum SequenceContext<'a> {
2788 Format1(SequenceContextFormat1<'a>),
2789 Format2(SequenceContextFormat2<'a>),
2790 Format3(SequenceContextFormat3<'a>),
2791}
2792
2793impl Default for SequenceContext<'_> {
2794 fn default() -> Self {
2795 Self::Format1(Default::default())
2796 }
2797}
2798
2799impl<'a> SequenceContext<'a> {
2800 pub fn offset_data(&self) -> FontData<'a> {
2802 match self {
2803 Self::Format1(item) => item.offset_data(),
2804 Self::Format2(item) => item.offset_data(),
2805 Self::Format3(item) => item.offset_data(),
2806 }
2807 }
2808
2809 pub fn format(&self) -> u16 {
2811 match self {
2812 Self::Format1(item) => item.format(),
2813 Self::Format2(item) => item.format(),
2814 Self::Format3(item) => item.format(),
2815 }
2816 }
2817}
2818
2819impl ReadArgs for SequenceContext<'_> {
2820 type Args = ();
2821}
2822
2823impl<'a> FontRead<'a> for SequenceContext<'a> {
2824 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2825 let format: u16 = data.read_at(0usize)?;
2826 match format {
2827 SequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2828 SequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2829 SequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2830 other => Err(ReadError::InvalidFormat(other.into())),
2831 }
2832 }
2833}
2834
2835impl<'a> MinByteRange<'a> for SequenceContext<'a> {
2836 fn min_byte_range(&self) -> Range<usize> {
2837 match self {
2838 Self::Format1(item) => item.min_byte_range(),
2839 Self::Format2(item) => item.min_byte_range(),
2840 Self::Format3(item) => item.min_byte_range(),
2841 }
2842 }
2843 fn min_table_bytes(&self) -> &'a [u8] {
2844 match self {
2845 Self::Format1(item) => item.min_table_bytes(),
2846 Self::Format2(item) => item.min_table_bytes(),
2847 Self::Format3(item) => item.min_table_bytes(),
2848 }
2849 }
2850}
2851
2852#[cfg(feature = "experimental_traverse")]
2853impl<'a> SequenceContext<'a> {
2854 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
2855 match self {
2856 Self::Format1(table) => table,
2857 Self::Format2(table) => table,
2858 Self::Format3(table) => table,
2859 }
2860 }
2861}
2862
2863#[cfg(feature = "experimental_traverse")]
2864impl std::fmt::Debug for SequenceContext<'_> {
2865 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2866 self.dyn_inner().fmt(f)
2867 }
2868}
2869
2870#[cfg(feature = "experimental_traverse")]
2871impl<'a> SomeTable<'a> for SequenceContext<'a> {
2872 fn type_name(&self) -> &str {
2873 self.dyn_inner().type_name()
2874 }
2875 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2876 self.dyn_inner().get_field(idx)
2877 }
2878}
2879
2880impl Format<u16> for ChainedSequenceContextFormat1<'_> {
2881 const FORMAT: u16 = 1;
2882}
2883
2884impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat1<'a> {
2885 fn min_byte_range(&self) -> Range<usize> {
2886 0..self.chained_seq_rule_set_offsets_byte_range().end
2887 }
2888 fn min_table_bytes(&self) -> &'a [u8] {
2889 let range = self.min_byte_range();
2890 self.data.as_bytes().get(range).unwrap_or_default()
2891 }
2892}
2893
2894impl ReadArgs for ChainedSequenceContextFormat1<'_> {
2895 type Args = ();
2896}
2897
2898impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2899 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2900 #[allow(clippy::absurd_extreme_comparisons)]
2901 if data.len() < Self::MIN_SIZE {
2902 return Err(ReadError::OutOfBounds);
2903 }
2904 Ok(Self { data })
2905 }
2906}
2907
2908#[derive(Clone)]
2910pub struct ChainedSequenceContextFormat1<'a> {
2911 data: FontData<'a>,
2912}
2913
2914#[allow(clippy::needless_lifetimes)]
2915impl<'a> ChainedSequenceContextFormat1<'a> {
2916 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2917 basic_table_impls!(impl_the_methods);
2918
2919 pub fn format(&self) -> u16 {
2921 let range = self.format_byte_range();
2922 self.data.read_at(range.start).ok().unwrap()
2923 }
2924
2925 pub fn coverage_offset(&self) -> Offset16 {
2928 let range = self.coverage_offset_byte_range();
2929 self.data.read_at(range.start).ok().unwrap()
2930 }
2931
2932 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2934 let data = self.data;
2935 self.coverage_offset().resolve(data)
2936 }
2937
2938 pub fn chained_seq_rule_set_count(&self) -> u16 {
2940 let range = self.chained_seq_rule_set_count_byte_range();
2941 self.data.read_at(range.start).ok().unwrap()
2942 }
2943
2944 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2947 let range = self.chained_seq_rule_set_offsets_byte_range();
2948 self.data.read_array(range).ok().unwrap_or_default()
2949 }
2950
2951 pub fn chained_seq_rule_sets(
2953 &self,
2954 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2955 let data = self.data;
2956 let offsets = self.chained_seq_rule_set_offsets();
2957 ArrayOfNullableOffsets::new(offsets, data, ())
2958 }
2959
2960 pub fn format_byte_range(&self) -> Range<usize> {
2961 let start = 0;
2962 let end = start + u16::RAW_BYTE_LEN;
2963 start..end
2964 }
2965
2966 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2967 let start = self.format_byte_range().end;
2968 let end = start + Offset16::RAW_BYTE_LEN;
2969 start..end
2970 }
2971
2972 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2973 let start = self.coverage_offset_byte_range().end;
2974 let end = start + u16::RAW_BYTE_LEN;
2975 start..end
2976 }
2977
2978 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2979 let chained_seq_rule_set_count = self.chained_seq_rule_set_count();
2980 let start = self.chained_seq_rule_set_count_byte_range().end;
2981 let end = start
2982 + (transforms::to_usize(chained_seq_rule_set_count))
2983 .saturating_mul(Offset16::RAW_BYTE_LEN);
2984 start..end
2985 }
2986}
2987
2988const _: () = assert!(FontData::default_data_long_enough(
2989 ChainedSequenceContextFormat1::MIN_SIZE
2990));
2991
2992impl Default for ChainedSequenceContextFormat1<'_> {
2993 fn default() -> Self {
2994 Self {
2995 data: FontData::default_format_1_u16_table_data(),
2996 }
2997 }
2998}
2999
3000#[cfg(feature = "experimental_traverse")]
3001impl<'a> SomeTable<'a> for ChainedSequenceContextFormat1<'a> {
3002 fn type_name(&self) -> &str {
3003 "ChainedSequenceContextFormat1"
3004 }
3005 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3006 match idx {
3007 0usize => Some(Field::new("format", self.format())),
3008 1usize => Some(Field::new(
3009 "coverage_offset",
3010 FieldType::offset(self.coverage_offset(), self.coverage()),
3011 )),
3012 2usize => Some(Field::new(
3013 "chained_seq_rule_set_count",
3014 self.chained_seq_rule_set_count(),
3015 )),
3016 3usize => Some(Field::new(
3017 "chained_seq_rule_set_offsets",
3018 FieldType::from(self.chained_seq_rule_sets()),
3019 )),
3020 _ => None,
3021 }
3022 }
3023}
3024
3025#[cfg(feature = "experimental_traverse")]
3026#[allow(clippy::needless_lifetimes)]
3027impl<'a> std::fmt::Debug for ChainedSequenceContextFormat1<'a> {
3028 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3029 (self as &dyn SomeTable<'a>).fmt(f)
3030 }
3031}
3032
3033impl<'a> MinByteRange<'a> for ChainedSequenceRuleSet<'a> {
3034 fn min_byte_range(&self) -> Range<usize> {
3035 0..self.chained_seq_rule_offsets_byte_range().end
3036 }
3037 fn min_table_bytes(&self) -> &'a [u8] {
3038 let range = self.min_byte_range();
3039 self.data.as_bytes().get(range).unwrap_or_default()
3040 }
3041}
3042
3043impl ReadArgs for ChainedSequenceRuleSet<'_> {
3044 type Args = ();
3045}
3046
3047impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
3048 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3049 #[allow(clippy::absurd_extreme_comparisons)]
3050 if data.len() < Self::MIN_SIZE {
3051 return Err(ReadError::OutOfBounds);
3052 }
3053 Ok(Self { data })
3054 }
3055}
3056
3057#[derive(Clone)]
3059pub struct ChainedSequenceRuleSet<'a> {
3060 data: FontData<'a>,
3061}
3062
3063#[allow(clippy::needless_lifetimes)]
3064impl<'a> ChainedSequenceRuleSet<'a> {
3065 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3066 basic_table_impls!(impl_the_methods);
3067
3068 pub fn chained_seq_rule_count(&self) -> u16 {
3070 let range = self.chained_seq_rule_count_byte_range();
3071 self.data.read_at(range.start).ok().unwrap()
3072 }
3073
3074 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3077 let range = self.chained_seq_rule_offsets_byte_range();
3078 self.data.read_array(range).ok().unwrap_or_default()
3079 }
3080
3081 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
3083 let data = self.data;
3084 let offsets = self.chained_seq_rule_offsets();
3085 ArrayOfOffsets::new(offsets, data, ())
3086 }
3087
3088 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
3089 let start = 0;
3090 let end = start + u16::RAW_BYTE_LEN;
3091 start..end
3092 }
3093
3094 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3095 let chained_seq_rule_count = self.chained_seq_rule_count();
3096 let start = self.chained_seq_rule_count_byte_range().end;
3097 let end = start
3098 + (transforms::to_usize(chained_seq_rule_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3099 start..end
3100 }
3101}
3102
3103const _: () = assert!(FontData::default_data_long_enough(
3104 ChainedSequenceRuleSet::MIN_SIZE
3105));
3106
3107impl Default for ChainedSequenceRuleSet<'_> {
3108 fn default() -> Self {
3109 Self {
3110 data: FontData::default_table_data(),
3111 }
3112 }
3113}
3114
3115#[cfg(feature = "experimental_traverse")]
3116impl<'a> SomeTable<'a> for ChainedSequenceRuleSet<'a> {
3117 fn type_name(&self) -> &str {
3118 "ChainedSequenceRuleSet"
3119 }
3120 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3121 match idx {
3122 0usize => Some(Field::new(
3123 "chained_seq_rule_count",
3124 self.chained_seq_rule_count(),
3125 )),
3126 1usize => Some(Field::new(
3127 "chained_seq_rule_offsets",
3128 FieldType::from(self.chained_seq_rules()),
3129 )),
3130 _ => None,
3131 }
3132 }
3133}
3134
3135#[cfg(feature = "experimental_traverse")]
3136#[allow(clippy::needless_lifetimes)]
3137impl<'a> std::fmt::Debug for ChainedSequenceRuleSet<'a> {
3138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3139 (self as &dyn SomeTable<'a>).fmt(f)
3140 }
3141}
3142
3143impl<'a> MinByteRange<'a> for ChainedSequenceRule<'a> {
3144 fn min_byte_range(&self) -> Range<usize> {
3145 0..self.seq_lookup_records_byte_range().end
3146 }
3147 fn min_table_bytes(&self) -> &'a [u8] {
3148 let range = self.min_byte_range();
3149 self.data.as_bytes().get(range).unwrap_or_default()
3150 }
3151}
3152
3153impl ReadArgs for ChainedSequenceRule<'_> {
3154 type Args = ();
3155}
3156
3157impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
3158 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3159 #[allow(clippy::absurd_extreme_comparisons)]
3160 if data.len() < Self::MIN_SIZE {
3161 return Err(ReadError::OutOfBounds);
3162 }
3163 Ok(Self { data })
3164 }
3165}
3166
3167#[derive(Clone)]
3169pub struct ChainedSequenceRule<'a> {
3170 data: FontData<'a>,
3171}
3172
3173#[allow(clippy::needless_lifetimes)]
3174impl<'a> ChainedSequenceRule<'a> {
3175 pub const MIN_SIZE: usize =
3176 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3177 basic_table_impls!(impl_the_methods);
3178
3179 pub fn backtrack_glyph_count(&self) -> u16 {
3181 let range = self.backtrack_glyph_count_byte_range();
3182 self.data.read_at(range.start).ok().unwrap()
3183 }
3184
3185 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3187 let range = self.backtrack_sequence_byte_range();
3188 self.data.read_array(range).ok().unwrap_or_default()
3189 }
3190
3191 pub fn input_glyph_count(&self) -> u16 {
3193 let range = self.input_glyph_count_byte_range();
3194 self.data.read_at(range.start).ok().unwrap_or_default()
3195 }
3196
3197 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3199 let range = self.input_sequence_byte_range();
3200 self.data.read_array(range).ok().unwrap_or_default()
3201 }
3202
3203 pub fn lookahead_glyph_count(&self) -> u16 {
3205 let range = self.lookahead_glyph_count_byte_range();
3206 self.data.read_at(range.start).ok().unwrap_or_default()
3207 }
3208
3209 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3211 let range = self.lookahead_sequence_byte_range();
3212 self.data.read_array(range).ok().unwrap_or_default()
3213 }
3214
3215 pub fn seq_lookup_count(&self) -> u16 {
3217 let range = self.seq_lookup_count_byte_range();
3218 self.data.read_at(range.start).ok().unwrap_or_default()
3219 }
3220
3221 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3223 let range = self.seq_lookup_records_byte_range();
3224 self.data.read_array(range).ok().unwrap_or_default()
3225 }
3226
3227 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3228 let start = 0;
3229 let end = start + u16::RAW_BYTE_LEN;
3230 start..end
3231 }
3232
3233 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3234 let backtrack_glyph_count = self.backtrack_glyph_count();
3235 let start = self.backtrack_glyph_count_byte_range().end;
3236 let end = start
3237 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
3238 start..end
3239 }
3240
3241 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3242 let start = self.backtrack_sequence_byte_range().end;
3243 let end = start + u16::RAW_BYTE_LEN;
3244 start..end
3245 }
3246
3247 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3248 let input_glyph_count = self.input_glyph_count();
3249 let start = self.input_glyph_count_byte_range().end;
3250 let end = start
3251 + (transforms::subtract(input_glyph_count, 1_usize))
3252 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
3253 start..end
3254 }
3255
3256 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3257 let start = self.input_sequence_byte_range().end;
3258 let end = start + u16::RAW_BYTE_LEN;
3259 start..end
3260 }
3261
3262 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3263 let lookahead_glyph_count = self.lookahead_glyph_count();
3264 let start = self.lookahead_glyph_count_byte_range().end;
3265 let end = start
3266 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
3267 start..end
3268 }
3269
3270 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3271 let start = self.lookahead_sequence_byte_range().end;
3272 let end = start + u16::RAW_BYTE_LEN;
3273 start..end
3274 }
3275
3276 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3277 let seq_lookup_count = self.seq_lookup_count();
3278 let start = self.seq_lookup_count_byte_range().end;
3279 let end = start
3280 + (transforms::to_usize(seq_lookup_count))
3281 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3282 start..end
3283 }
3284}
3285
3286const _: () = assert!(FontData::default_data_long_enough(
3287 ChainedSequenceRule::MIN_SIZE
3288));
3289
3290impl Default for ChainedSequenceRule<'_> {
3291 fn default() -> Self {
3292 Self {
3293 data: FontData::default_table_data(),
3294 }
3295 }
3296}
3297
3298#[cfg(feature = "experimental_traverse")]
3299impl<'a> SomeTable<'a> for ChainedSequenceRule<'a> {
3300 fn type_name(&self) -> &str {
3301 "ChainedSequenceRule"
3302 }
3303 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3304 match idx {
3305 0usize => Some(Field::new(
3306 "backtrack_glyph_count",
3307 self.backtrack_glyph_count(),
3308 )),
3309 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3310 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3311 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3312 4usize => Some(Field::new(
3313 "lookahead_glyph_count",
3314 self.lookahead_glyph_count(),
3315 )),
3316 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3317 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3318 7usize => Some(Field::new(
3319 "seq_lookup_records",
3320 traversal::FieldType::array_of_records(
3321 stringify!(SequenceLookupRecord),
3322 self.seq_lookup_records(),
3323 self.offset_data(),
3324 ),
3325 )),
3326 _ => None,
3327 }
3328 }
3329}
3330
3331#[cfg(feature = "experimental_traverse")]
3332#[allow(clippy::needless_lifetimes)]
3333impl<'a> std::fmt::Debug for ChainedSequenceRule<'a> {
3334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3335 (self as &dyn SomeTable<'a>).fmt(f)
3336 }
3337}
3338
3339impl Format<u16> for ChainedSequenceContextFormat2<'_> {
3340 const FORMAT: u16 = 2;
3341}
3342
3343impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat2<'a> {
3344 fn min_byte_range(&self) -> Range<usize> {
3345 0..self.chained_class_seq_rule_set_offsets_byte_range().end
3346 }
3347 fn min_table_bytes(&self) -> &'a [u8] {
3348 let range = self.min_byte_range();
3349 self.data.as_bytes().get(range).unwrap_or_default()
3350 }
3351}
3352
3353impl ReadArgs for ChainedSequenceContextFormat2<'_> {
3354 type Args = ();
3355}
3356
3357impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
3358 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3359 #[allow(clippy::absurd_extreme_comparisons)]
3360 if data.len() < Self::MIN_SIZE {
3361 return Err(ReadError::OutOfBounds);
3362 }
3363 Ok(Self { data })
3364 }
3365}
3366
3367#[derive(Clone)]
3369pub struct ChainedSequenceContextFormat2<'a> {
3370 data: FontData<'a>,
3371}
3372
3373#[allow(clippy::needless_lifetimes)]
3374impl<'a> ChainedSequenceContextFormat2<'a> {
3375 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3376 + Offset16::RAW_BYTE_LEN
3377 + Offset16::RAW_BYTE_LEN
3378 + Offset16::RAW_BYTE_LEN
3379 + Offset16::RAW_BYTE_LEN
3380 + u16::RAW_BYTE_LEN);
3381 basic_table_impls!(impl_the_methods);
3382
3383 pub fn format(&self) -> u16 {
3385 let range = self.format_byte_range();
3386 self.data.read_at(range.start).ok().unwrap()
3387 }
3388
3389 pub fn coverage_offset(&self) -> Offset16 {
3392 let range = self.coverage_offset_byte_range();
3393 self.data.read_at(range.start).ok().unwrap()
3394 }
3395
3396 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3398 let data = self.data;
3399 self.coverage_offset().resolve(data)
3400 }
3401
3402 pub fn backtrack_class_def_offset(&self) -> Offset16 {
3405 let range = self.backtrack_class_def_offset_byte_range();
3406 self.data.read_at(range.start).ok().unwrap()
3407 }
3408
3409 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3411 let data = self.data;
3412 self.backtrack_class_def_offset().resolve(data)
3413 }
3414
3415 pub fn input_class_def_offset(&self) -> Offset16 {
3418 let range = self.input_class_def_offset_byte_range();
3419 self.data.read_at(range.start).ok().unwrap()
3420 }
3421
3422 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3424 let data = self.data;
3425 self.input_class_def_offset().resolve(data)
3426 }
3427
3428 pub fn lookahead_class_def_offset(&self) -> Offset16 {
3431 let range = self.lookahead_class_def_offset_byte_range();
3432 self.data.read_at(range.start).ok().unwrap()
3433 }
3434
3435 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3437 let data = self.data;
3438 self.lookahead_class_def_offset().resolve(data)
3439 }
3440
3441 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
3443 let range = self.chained_class_seq_rule_set_count_byte_range();
3444 self.data.read_at(range.start).ok().unwrap()
3445 }
3446
3447 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3450 let range = self.chained_class_seq_rule_set_offsets_byte_range();
3451 self.data.read_array(range).ok().unwrap_or_default()
3452 }
3453
3454 pub fn chained_class_seq_rule_sets(
3456 &self,
3457 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
3458 let data = self.data;
3459 let offsets = self.chained_class_seq_rule_set_offsets();
3460 ArrayOfNullableOffsets::new(offsets, data, ())
3461 }
3462
3463 pub fn format_byte_range(&self) -> Range<usize> {
3464 let start = 0;
3465 let end = start + u16::RAW_BYTE_LEN;
3466 start..end
3467 }
3468
3469 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
3470 let start = self.format_byte_range().end;
3471 let end = start + Offset16::RAW_BYTE_LEN;
3472 start..end
3473 }
3474
3475 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
3476 let start = self.coverage_offset_byte_range().end;
3477 let end = start + Offset16::RAW_BYTE_LEN;
3478 start..end
3479 }
3480
3481 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
3482 let start = self.backtrack_class_def_offset_byte_range().end;
3483 let end = start + Offset16::RAW_BYTE_LEN;
3484 start..end
3485 }
3486
3487 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
3488 let start = self.input_class_def_offset_byte_range().end;
3489 let end = start + Offset16::RAW_BYTE_LEN;
3490 start..end
3491 }
3492
3493 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
3494 let start = self.lookahead_class_def_offset_byte_range().end;
3495 let end = start + u16::RAW_BYTE_LEN;
3496 start..end
3497 }
3498
3499 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
3500 let chained_class_seq_rule_set_count = self.chained_class_seq_rule_set_count();
3501 let start = self.chained_class_seq_rule_set_count_byte_range().end;
3502 let end = start
3503 + (transforms::to_usize(chained_class_seq_rule_set_count))
3504 .saturating_mul(Offset16::RAW_BYTE_LEN);
3505 start..end
3506 }
3507}
3508
3509#[cfg(feature = "experimental_traverse")]
3510impl<'a> SomeTable<'a> for ChainedSequenceContextFormat2<'a> {
3511 fn type_name(&self) -> &str {
3512 "ChainedSequenceContextFormat2"
3513 }
3514 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3515 match idx {
3516 0usize => Some(Field::new("format", self.format())),
3517 1usize => Some(Field::new(
3518 "coverage_offset",
3519 FieldType::offset(self.coverage_offset(), self.coverage()),
3520 )),
3521 2usize => Some(Field::new(
3522 "backtrack_class_def_offset",
3523 FieldType::offset(
3524 self.backtrack_class_def_offset(),
3525 self.backtrack_class_def(),
3526 ),
3527 )),
3528 3usize => Some(Field::new(
3529 "input_class_def_offset",
3530 FieldType::offset(self.input_class_def_offset(), self.input_class_def()),
3531 )),
3532 4usize => Some(Field::new(
3533 "lookahead_class_def_offset",
3534 FieldType::offset(
3535 self.lookahead_class_def_offset(),
3536 self.lookahead_class_def(),
3537 ),
3538 )),
3539 5usize => Some(Field::new(
3540 "chained_class_seq_rule_set_count",
3541 self.chained_class_seq_rule_set_count(),
3542 )),
3543 6usize => Some(Field::new(
3544 "chained_class_seq_rule_set_offsets",
3545 FieldType::from(self.chained_class_seq_rule_sets()),
3546 )),
3547 _ => None,
3548 }
3549 }
3550}
3551
3552#[cfg(feature = "experimental_traverse")]
3553#[allow(clippy::needless_lifetimes)]
3554impl<'a> std::fmt::Debug for ChainedSequenceContextFormat2<'a> {
3555 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3556 (self as &dyn SomeTable<'a>).fmt(f)
3557 }
3558}
3559
3560impl<'a> MinByteRange<'a> for ChainedClassSequenceRuleSet<'a> {
3561 fn min_byte_range(&self) -> Range<usize> {
3562 0..self.chained_class_seq_rule_offsets_byte_range().end
3563 }
3564 fn min_table_bytes(&self) -> &'a [u8] {
3565 let range = self.min_byte_range();
3566 self.data.as_bytes().get(range).unwrap_or_default()
3567 }
3568}
3569
3570impl ReadArgs for ChainedClassSequenceRuleSet<'_> {
3571 type Args = ();
3572}
3573
3574impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
3575 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3576 #[allow(clippy::absurd_extreme_comparisons)]
3577 if data.len() < Self::MIN_SIZE {
3578 return Err(ReadError::OutOfBounds);
3579 }
3580 Ok(Self { data })
3581 }
3582}
3583
3584#[derive(Clone)]
3586pub struct ChainedClassSequenceRuleSet<'a> {
3587 data: FontData<'a>,
3588}
3589
3590#[allow(clippy::needless_lifetimes)]
3591impl<'a> ChainedClassSequenceRuleSet<'a> {
3592 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3593 basic_table_impls!(impl_the_methods);
3594
3595 pub fn chained_class_seq_rule_count(&self) -> u16 {
3597 let range = self.chained_class_seq_rule_count_byte_range();
3598 self.data.read_at(range.start).ok().unwrap()
3599 }
3600
3601 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3604 let range = self.chained_class_seq_rule_offsets_byte_range();
3605 self.data.read_array(range).ok().unwrap_or_default()
3606 }
3607
3608 pub fn chained_class_seq_rules(
3610 &self,
3611 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
3612 let data = self.data;
3613 let offsets = self.chained_class_seq_rule_offsets();
3614 ArrayOfOffsets::new(offsets, data, ())
3615 }
3616
3617 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
3618 let start = 0;
3619 let end = start + u16::RAW_BYTE_LEN;
3620 start..end
3621 }
3622
3623 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3624 let chained_class_seq_rule_count = self.chained_class_seq_rule_count();
3625 let start = self.chained_class_seq_rule_count_byte_range().end;
3626 let end = start
3627 + (transforms::to_usize(chained_class_seq_rule_count))
3628 .saturating_mul(Offset16::RAW_BYTE_LEN);
3629 start..end
3630 }
3631}
3632
3633const _: () = assert!(FontData::default_data_long_enough(
3634 ChainedClassSequenceRuleSet::MIN_SIZE
3635));
3636
3637impl Default for ChainedClassSequenceRuleSet<'_> {
3638 fn default() -> Self {
3639 Self {
3640 data: FontData::default_table_data(),
3641 }
3642 }
3643}
3644
3645#[cfg(feature = "experimental_traverse")]
3646impl<'a> SomeTable<'a> for ChainedClassSequenceRuleSet<'a> {
3647 fn type_name(&self) -> &str {
3648 "ChainedClassSequenceRuleSet"
3649 }
3650 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3651 match idx {
3652 0usize => Some(Field::new(
3653 "chained_class_seq_rule_count",
3654 self.chained_class_seq_rule_count(),
3655 )),
3656 1usize => Some(Field::new(
3657 "chained_class_seq_rule_offsets",
3658 FieldType::from(self.chained_class_seq_rules()),
3659 )),
3660 _ => None,
3661 }
3662 }
3663}
3664
3665#[cfg(feature = "experimental_traverse")]
3666#[allow(clippy::needless_lifetimes)]
3667impl<'a> std::fmt::Debug for ChainedClassSequenceRuleSet<'a> {
3668 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3669 (self as &dyn SomeTable<'a>).fmt(f)
3670 }
3671}
3672
3673impl<'a> MinByteRange<'a> for ChainedClassSequenceRule<'a> {
3674 fn min_byte_range(&self) -> Range<usize> {
3675 0..self.seq_lookup_records_byte_range().end
3676 }
3677 fn min_table_bytes(&self) -> &'a [u8] {
3678 let range = self.min_byte_range();
3679 self.data.as_bytes().get(range).unwrap_or_default()
3680 }
3681}
3682
3683impl ReadArgs for ChainedClassSequenceRule<'_> {
3684 type Args = ();
3685}
3686
3687impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
3688 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3689 #[allow(clippy::absurd_extreme_comparisons)]
3690 if data.len() < Self::MIN_SIZE {
3691 return Err(ReadError::OutOfBounds);
3692 }
3693 Ok(Self { data })
3694 }
3695}
3696
3697#[derive(Clone)]
3699pub struct ChainedClassSequenceRule<'a> {
3700 data: FontData<'a>,
3701}
3702
3703#[allow(clippy::needless_lifetimes)]
3704impl<'a> ChainedClassSequenceRule<'a> {
3705 pub const MIN_SIZE: usize =
3706 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
3707 basic_table_impls!(impl_the_methods);
3708
3709 pub fn backtrack_glyph_count(&self) -> u16 {
3711 let range = self.backtrack_glyph_count_byte_range();
3712 self.data.read_at(range.start).ok().unwrap()
3713 }
3714
3715 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
3717 let range = self.backtrack_sequence_byte_range();
3718 self.data.read_array(range).ok().unwrap_or_default()
3719 }
3720
3721 pub fn input_glyph_count(&self) -> u16 {
3723 let range = self.input_glyph_count_byte_range();
3724 self.data.read_at(range.start).ok().unwrap_or_default()
3725 }
3726
3727 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
3730 let range = self.input_sequence_byte_range();
3731 self.data.read_array(range).ok().unwrap_or_default()
3732 }
3733
3734 pub fn lookahead_glyph_count(&self) -> u16 {
3736 let range = self.lookahead_glyph_count_byte_range();
3737 self.data.read_at(range.start).ok().unwrap_or_default()
3738 }
3739
3740 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
3742 let range = self.lookahead_sequence_byte_range();
3743 self.data.read_array(range).ok().unwrap_or_default()
3744 }
3745
3746 pub fn seq_lookup_count(&self) -> u16 {
3748 let range = self.seq_lookup_count_byte_range();
3749 self.data.read_at(range.start).ok().unwrap_or_default()
3750 }
3751
3752 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3754 let range = self.seq_lookup_records_byte_range();
3755 self.data.read_array(range).ok().unwrap_or_default()
3756 }
3757
3758 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3759 let start = 0;
3760 let end = start + u16::RAW_BYTE_LEN;
3761 start..end
3762 }
3763
3764 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3765 let backtrack_glyph_count = self.backtrack_glyph_count();
3766 let start = self.backtrack_glyph_count_byte_range().end;
3767 let end =
3768 start + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3769 start..end
3770 }
3771
3772 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3773 let start = self.backtrack_sequence_byte_range().end;
3774 let end = start + u16::RAW_BYTE_LEN;
3775 start..end
3776 }
3777
3778 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3779 let input_glyph_count = self.input_glyph_count();
3780 let start = self.input_glyph_count_byte_range().end;
3781 let end = start
3782 + (transforms::subtract(input_glyph_count, 1_usize)).saturating_mul(u16::RAW_BYTE_LEN);
3783 start..end
3784 }
3785
3786 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3787 let start = self.input_sequence_byte_range().end;
3788 let end = start + u16::RAW_BYTE_LEN;
3789 start..end
3790 }
3791
3792 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3793 let lookahead_glyph_count = self.lookahead_glyph_count();
3794 let start = self.lookahead_glyph_count_byte_range().end;
3795 let end =
3796 start + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(u16::RAW_BYTE_LEN);
3797 start..end
3798 }
3799
3800 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3801 let start = self.lookahead_sequence_byte_range().end;
3802 let end = start + u16::RAW_BYTE_LEN;
3803 start..end
3804 }
3805
3806 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3807 let seq_lookup_count = self.seq_lookup_count();
3808 let start = self.seq_lookup_count_byte_range().end;
3809 let end = start
3810 + (transforms::to_usize(seq_lookup_count))
3811 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
3812 start..end
3813 }
3814}
3815
3816const _: () = assert!(FontData::default_data_long_enough(
3817 ChainedClassSequenceRule::MIN_SIZE
3818));
3819
3820impl Default for ChainedClassSequenceRule<'_> {
3821 fn default() -> Self {
3822 Self {
3823 data: FontData::default_table_data(),
3824 }
3825 }
3826}
3827
3828#[cfg(feature = "experimental_traverse")]
3829impl<'a> SomeTable<'a> for ChainedClassSequenceRule<'a> {
3830 fn type_name(&self) -> &str {
3831 "ChainedClassSequenceRule"
3832 }
3833 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3834 match idx {
3835 0usize => Some(Field::new(
3836 "backtrack_glyph_count",
3837 self.backtrack_glyph_count(),
3838 )),
3839 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3840 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3841 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3842 4usize => Some(Field::new(
3843 "lookahead_glyph_count",
3844 self.lookahead_glyph_count(),
3845 )),
3846 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3847 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3848 7usize => Some(Field::new(
3849 "seq_lookup_records",
3850 traversal::FieldType::array_of_records(
3851 stringify!(SequenceLookupRecord),
3852 self.seq_lookup_records(),
3853 self.offset_data(),
3854 ),
3855 )),
3856 _ => None,
3857 }
3858 }
3859}
3860
3861#[cfg(feature = "experimental_traverse")]
3862#[allow(clippy::needless_lifetimes)]
3863impl<'a> std::fmt::Debug for ChainedClassSequenceRule<'a> {
3864 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3865 (self as &dyn SomeTable<'a>).fmt(f)
3866 }
3867}
3868
3869impl Format<u16> for ChainedSequenceContextFormat3<'_> {
3870 const FORMAT: u16 = 3;
3871}
3872
3873impl<'a> MinByteRange<'a> for ChainedSequenceContextFormat3<'a> {
3874 fn min_byte_range(&self) -> Range<usize> {
3875 0..self.seq_lookup_records_byte_range().end
3876 }
3877 fn min_table_bytes(&self) -> &'a [u8] {
3878 let range = self.min_byte_range();
3879 self.data.as_bytes().get(range).unwrap_or_default()
3880 }
3881}
3882
3883impl ReadArgs for ChainedSequenceContextFormat3<'_> {
3884 type Args = ();
3885}
3886
3887impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
3888 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3889 #[allow(clippy::absurd_extreme_comparisons)]
3890 if data.len() < Self::MIN_SIZE {
3891 return Err(ReadError::OutOfBounds);
3892 }
3893 Ok(Self { data })
3894 }
3895}
3896
3897#[derive(Clone)]
3899pub struct ChainedSequenceContextFormat3<'a> {
3900 data: FontData<'a>,
3901}
3902
3903#[allow(clippy::needless_lifetimes)]
3904impl<'a> ChainedSequenceContextFormat3<'a> {
3905 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3906 + u16::RAW_BYTE_LEN
3907 + u16::RAW_BYTE_LEN
3908 + u16::RAW_BYTE_LEN
3909 + u16::RAW_BYTE_LEN);
3910 basic_table_impls!(impl_the_methods);
3911
3912 pub fn format(&self) -> u16 {
3914 let range = self.format_byte_range();
3915 self.data.read_at(range.start).ok().unwrap()
3916 }
3917
3918 pub fn backtrack_glyph_count(&self) -> u16 {
3920 let range = self.backtrack_glyph_count_byte_range();
3921 self.data.read_at(range.start).ok().unwrap()
3922 }
3923
3924 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3926 let range = self.backtrack_coverage_offsets_byte_range();
3927 self.data.read_array(range).ok().unwrap_or_default()
3928 }
3929
3930 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3932 let data = self.data;
3933 let offsets = self.backtrack_coverage_offsets();
3934 ArrayOfOffsets::new(offsets, data, ())
3935 }
3936
3937 pub fn input_glyph_count(&self) -> u16 {
3939 let range = self.input_glyph_count_byte_range();
3940 self.data.read_at(range.start).ok().unwrap_or_default()
3941 }
3942
3943 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3945 let range = self.input_coverage_offsets_byte_range();
3946 self.data.read_array(range).ok().unwrap_or_default()
3947 }
3948
3949 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3951 let data = self.data;
3952 let offsets = self.input_coverage_offsets();
3953 ArrayOfOffsets::new(offsets, data, ())
3954 }
3955
3956 pub fn lookahead_glyph_count(&self) -> u16 {
3958 let range = self.lookahead_glyph_count_byte_range();
3959 self.data.read_at(range.start).ok().unwrap_or_default()
3960 }
3961
3962 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3964 let range = self.lookahead_coverage_offsets_byte_range();
3965 self.data.read_array(range).ok().unwrap_or_default()
3966 }
3967
3968 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3970 let data = self.data;
3971 let offsets = self.lookahead_coverage_offsets();
3972 ArrayOfOffsets::new(offsets, data, ())
3973 }
3974
3975 pub fn seq_lookup_count(&self) -> u16 {
3977 let range = self.seq_lookup_count_byte_range();
3978 self.data.read_at(range.start).ok().unwrap_or_default()
3979 }
3980
3981 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3983 let range = self.seq_lookup_records_byte_range();
3984 self.data.read_array(range).ok().unwrap_or_default()
3985 }
3986
3987 pub fn format_byte_range(&self) -> Range<usize> {
3988 let start = 0;
3989 let end = start + u16::RAW_BYTE_LEN;
3990 start..end
3991 }
3992
3993 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3994 let start = self.format_byte_range().end;
3995 let end = start + u16::RAW_BYTE_LEN;
3996 start..end
3997 }
3998
3999 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
4000 let backtrack_glyph_count = self.backtrack_glyph_count();
4001 let start = self.backtrack_glyph_count_byte_range().end;
4002 let end = start
4003 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4004 start..end
4005 }
4006
4007 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
4008 let start = self.backtrack_coverage_offsets_byte_range().end;
4009 let end = start + u16::RAW_BYTE_LEN;
4010 start..end
4011 }
4012
4013 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
4014 let input_glyph_count = self.input_glyph_count();
4015 let start = self.input_glyph_count_byte_range().end;
4016 let end = start
4017 + (transforms::to_usize(input_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4018 start..end
4019 }
4020
4021 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
4022 let start = self.input_coverage_offsets_byte_range().end;
4023 let end = start + u16::RAW_BYTE_LEN;
4024 start..end
4025 }
4026
4027 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
4028 let lookahead_glyph_count = self.lookahead_glyph_count();
4029 let start = self.lookahead_glyph_count_byte_range().end;
4030 let end = start
4031 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
4032 start..end
4033 }
4034
4035 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
4036 let start = self.lookahead_coverage_offsets_byte_range().end;
4037 let end = start + u16::RAW_BYTE_LEN;
4038 start..end
4039 }
4040
4041 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
4042 let seq_lookup_count = self.seq_lookup_count();
4043 let start = self.seq_lookup_count_byte_range().end;
4044 let end = start
4045 + (transforms::to_usize(seq_lookup_count))
4046 .saturating_mul(SequenceLookupRecord::RAW_BYTE_LEN);
4047 start..end
4048 }
4049}
4050
4051#[cfg(feature = "experimental_traverse")]
4052impl<'a> SomeTable<'a> for ChainedSequenceContextFormat3<'a> {
4053 fn type_name(&self) -> &str {
4054 "ChainedSequenceContextFormat3"
4055 }
4056 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4057 match idx {
4058 0usize => Some(Field::new("format", self.format())),
4059 1usize => Some(Field::new(
4060 "backtrack_glyph_count",
4061 self.backtrack_glyph_count(),
4062 )),
4063 2usize => Some(Field::new(
4064 "backtrack_coverage_offsets",
4065 FieldType::from(self.backtrack_coverages()),
4066 )),
4067 3usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
4068 4usize => Some(Field::new(
4069 "input_coverage_offsets",
4070 FieldType::from(self.input_coverages()),
4071 )),
4072 5usize => Some(Field::new(
4073 "lookahead_glyph_count",
4074 self.lookahead_glyph_count(),
4075 )),
4076 6usize => Some(Field::new(
4077 "lookahead_coverage_offsets",
4078 FieldType::from(self.lookahead_coverages()),
4079 )),
4080 7usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
4081 8usize => Some(Field::new(
4082 "seq_lookup_records",
4083 traversal::FieldType::array_of_records(
4084 stringify!(SequenceLookupRecord),
4085 self.seq_lookup_records(),
4086 self.offset_data(),
4087 ),
4088 )),
4089 _ => None,
4090 }
4091 }
4092}
4093
4094#[cfg(feature = "experimental_traverse")]
4095#[allow(clippy::needless_lifetimes)]
4096impl<'a> std::fmt::Debug for ChainedSequenceContextFormat3<'a> {
4097 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4098 (self as &dyn SomeTable<'a>).fmt(f)
4099 }
4100}
4101
4102#[derive(Clone)]
4103pub enum ChainedSequenceContext<'a> {
4104 Format1(ChainedSequenceContextFormat1<'a>),
4105 Format2(ChainedSequenceContextFormat2<'a>),
4106 Format3(ChainedSequenceContextFormat3<'a>),
4107}
4108
4109impl Default for ChainedSequenceContext<'_> {
4110 fn default() -> Self {
4111 Self::Format1(Default::default())
4112 }
4113}
4114
4115impl<'a> ChainedSequenceContext<'a> {
4116 pub fn offset_data(&self) -> FontData<'a> {
4118 match self {
4119 Self::Format1(item) => item.offset_data(),
4120 Self::Format2(item) => item.offset_data(),
4121 Self::Format3(item) => item.offset_data(),
4122 }
4123 }
4124
4125 pub fn format(&self) -> u16 {
4127 match self {
4128 Self::Format1(item) => item.format(),
4129 Self::Format2(item) => item.format(),
4130 Self::Format3(item) => item.format(),
4131 }
4132 }
4133}
4134
4135impl ReadArgs for ChainedSequenceContext<'_> {
4136 type Args = ();
4137}
4138
4139impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
4140 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4141 let format: u16 = data.read_at(0usize)?;
4142 match format {
4143 ChainedSequenceContextFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
4144 ChainedSequenceContextFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
4145 ChainedSequenceContextFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
4146 other => Err(ReadError::InvalidFormat(other.into())),
4147 }
4148 }
4149}
4150
4151impl<'a> MinByteRange<'a> for ChainedSequenceContext<'a> {
4152 fn min_byte_range(&self) -> Range<usize> {
4153 match self {
4154 Self::Format1(item) => item.min_byte_range(),
4155 Self::Format2(item) => item.min_byte_range(),
4156 Self::Format3(item) => item.min_byte_range(),
4157 }
4158 }
4159 fn min_table_bytes(&self) -> &'a [u8] {
4160 match self {
4161 Self::Format1(item) => item.min_table_bytes(),
4162 Self::Format2(item) => item.min_table_bytes(),
4163 Self::Format3(item) => item.min_table_bytes(),
4164 }
4165 }
4166}
4167
4168#[cfg(feature = "experimental_traverse")]
4169impl<'a> ChainedSequenceContext<'a> {
4170 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4171 match self {
4172 Self::Format1(table) => table,
4173 Self::Format2(table) => table,
4174 Self::Format3(table) => table,
4175 }
4176 }
4177}
4178
4179#[cfg(feature = "experimental_traverse")]
4180impl std::fmt::Debug for ChainedSequenceContext<'_> {
4181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4182 self.dyn_inner().fmt(f)
4183 }
4184}
4185
4186#[cfg(feature = "experimental_traverse")]
4187impl<'a> SomeTable<'a> for ChainedSequenceContext<'a> {
4188 fn type_name(&self) -> &str {
4189 self.dyn_inner().type_name()
4190 }
4191 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4192 self.dyn_inner().get_field(idx)
4193 }
4194}
4195
4196#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
4199#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4200#[repr(u16)]
4201#[allow(clippy::manual_non_exhaustive)]
4202pub enum DeltaFormat {
4203 #[default]
4205 Local2BitDeltas = 0x0001,
4206 Local4BitDeltas = 0x0002,
4208 Local8BitDeltas = 0x0003,
4210 VariationIndex = 0x8000,
4212 #[doc(hidden)]
4213 Unknown,
4215}
4216
4217impl DeltaFormat {
4218 pub fn new(raw: u16) -> Self {
4222 match raw {
4223 0x0001 => Self::Local2BitDeltas,
4224 0x0002 => Self::Local4BitDeltas,
4225 0x0003 => Self::Local8BitDeltas,
4226 0x8000 => Self::VariationIndex,
4227 _ => Self::Unknown,
4228 }
4229 }
4230}
4231
4232impl font_types::Scalar for DeltaFormat {
4233 type Raw = <u16 as font_types::Scalar>::Raw;
4234 fn to_raw(self) -> Self::Raw {
4235 (self as u16).to_raw()
4236 }
4237 fn from_raw(raw: Self::Raw) -> Self {
4238 let t = <u16>::from_raw(raw);
4239 Self::new(t)
4240 }
4241}
4242
4243#[cfg(feature = "experimental_traverse")]
4244impl<'a> From<DeltaFormat> for FieldType<'a> {
4245 fn from(src: DeltaFormat) -> FieldType<'a> {
4246 (src as u16).into()
4247 }
4248}
4249
4250impl<'a> MinByteRange<'a> for Device<'a> {
4251 fn min_byte_range(&self) -> Range<usize> {
4252 0..self.delta_value_byte_range().end
4253 }
4254 fn min_table_bytes(&self) -> &'a [u8] {
4255 let range = self.min_byte_range();
4256 self.data.as_bytes().get(range).unwrap_or_default()
4257 }
4258}
4259
4260impl ReadArgs for Device<'_> {
4261 type Args = ();
4262}
4263
4264impl<'a> FontRead<'a> for Device<'a> {
4265 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4266 #[allow(clippy::absurd_extreme_comparisons)]
4267 if data.len() < Self::MIN_SIZE {
4268 return Err(ReadError::OutOfBounds);
4269 }
4270 Ok(Self { data })
4271 }
4272}
4273
4274#[derive(Clone)]
4276pub struct Device<'a> {
4277 data: FontData<'a>,
4278}
4279
4280#[allow(clippy::needless_lifetimes)]
4281impl<'a> Device<'a> {
4282 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
4283 basic_table_impls!(impl_the_methods);
4284
4285 pub fn start_size(&self) -> u16 {
4287 let range = self.start_size_byte_range();
4288 self.data.read_at(range.start).ok().unwrap()
4289 }
4290
4291 pub fn end_size(&self) -> u16 {
4293 let range = self.end_size_byte_range();
4294 self.data.read_at(range.start).ok().unwrap()
4295 }
4296
4297 pub fn delta_format(&self) -> DeltaFormat {
4299 let range = self.delta_format_byte_range();
4300 self.data.read_at(range.start).ok().unwrap()
4301 }
4302
4303 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
4305 let range = self.delta_value_byte_range();
4306 self.data.read_array(range).ok().unwrap_or_default()
4307 }
4308
4309 pub fn start_size_byte_range(&self) -> Range<usize> {
4310 let start = 0;
4311 let end = start + u16::RAW_BYTE_LEN;
4312 start..end
4313 }
4314
4315 pub fn end_size_byte_range(&self) -> Range<usize> {
4316 let start = self.start_size_byte_range().end;
4317 let end = start + u16::RAW_BYTE_LEN;
4318 start..end
4319 }
4320
4321 pub fn delta_format_byte_range(&self) -> Range<usize> {
4322 let start = self.end_size_byte_range().end;
4323 let end = start + DeltaFormat::RAW_BYTE_LEN;
4324 start..end
4325 }
4326
4327 pub fn delta_value_byte_range(&self) -> Range<usize> {
4328 let delta_format = self.delta_format();
4329 let start_size = self.start_size();
4330 let end_size = self.end_size();
4331 let start = self.delta_format_byte_range().end;
4332 let end = start
4333 + (DeltaFormat::value_count(delta_format, start_size, end_size))
4334 .saturating_mul(u16::RAW_BYTE_LEN);
4335 start..end
4336 }
4337}
4338
4339const _: () = assert!(FontData::default_data_long_enough(Device::MIN_SIZE));
4340
4341impl Default for Device<'_> {
4342 fn default() -> Self {
4343 Self {
4344 data: FontData::default_table_data(),
4345 }
4346 }
4347}
4348
4349#[cfg(feature = "experimental_traverse")]
4350impl<'a> SomeTable<'a> for Device<'a> {
4351 fn type_name(&self) -> &str {
4352 "Device"
4353 }
4354 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4355 match idx {
4356 0usize => Some(Field::new("start_size", self.start_size())),
4357 1usize => Some(Field::new("end_size", self.end_size())),
4358 2usize => Some(Field::new("delta_format", self.delta_format())),
4359 3usize => Some(Field::new("delta_value", self.delta_value())),
4360 _ => None,
4361 }
4362 }
4363}
4364
4365#[cfg(feature = "experimental_traverse")]
4366#[allow(clippy::needless_lifetimes)]
4367impl<'a> std::fmt::Debug for Device<'a> {
4368 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4369 (self as &dyn SomeTable<'a>).fmt(f)
4370 }
4371}
4372
4373impl<'a> MinByteRange<'a> for VariationIndex<'a> {
4374 fn min_byte_range(&self) -> Range<usize> {
4375 0..self.delta_format_byte_range().end
4376 }
4377 fn min_table_bytes(&self) -> &'a [u8] {
4378 let range = self.min_byte_range();
4379 self.data.as_bytes().get(range).unwrap_or_default()
4380 }
4381}
4382
4383impl ReadArgs for VariationIndex<'_> {
4384 type Args = ();
4385}
4386
4387impl<'a> FontRead<'a> for VariationIndex<'a> {
4388 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4389 #[allow(clippy::absurd_extreme_comparisons)]
4390 if data.len() < Self::MIN_SIZE {
4391 return Err(ReadError::OutOfBounds);
4392 }
4393 Ok(Self { data })
4394 }
4395}
4396
4397#[derive(Clone)]
4399pub struct VariationIndex<'a> {
4400 data: FontData<'a>,
4401}
4402
4403#[allow(clippy::needless_lifetimes)]
4404impl<'a> VariationIndex<'a> {
4405 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + DeltaFormat::RAW_BYTE_LEN);
4406 basic_table_impls!(impl_the_methods);
4407
4408 pub fn delta_set_outer_index(&self) -> u16 {
4411 let range = self.delta_set_outer_index_byte_range();
4412 self.data.read_at(range.start).ok().unwrap()
4413 }
4414
4415 pub fn delta_set_inner_index(&self) -> u16 {
4418 let range = self.delta_set_inner_index_byte_range();
4419 self.data.read_at(range.start).ok().unwrap()
4420 }
4421
4422 pub fn delta_format(&self) -> DeltaFormat {
4424 let range = self.delta_format_byte_range();
4425 self.data.read_at(range.start).ok().unwrap()
4426 }
4427
4428 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
4429 let start = 0;
4430 let end = start + u16::RAW_BYTE_LEN;
4431 start..end
4432 }
4433
4434 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
4435 let start = self.delta_set_outer_index_byte_range().end;
4436 let end = start + u16::RAW_BYTE_LEN;
4437 start..end
4438 }
4439
4440 pub fn delta_format_byte_range(&self) -> Range<usize> {
4441 let start = self.delta_set_inner_index_byte_range().end;
4442 let end = start + DeltaFormat::RAW_BYTE_LEN;
4443 start..end
4444 }
4445}
4446
4447const _: () = assert!(FontData::default_data_long_enough(VariationIndex::MIN_SIZE));
4448
4449impl Default for VariationIndex<'_> {
4450 fn default() -> Self {
4451 Self {
4452 data: FontData::default_table_data(),
4453 }
4454 }
4455}
4456
4457#[cfg(feature = "experimental_traverse")]
4458impl<'a> SomeTable<'a> for VariationIndex<'a> {
4459 fn type_name(&self) -> &str {
4460 "VariationIndex"
4461 }
4462 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4463 match idx {
4464 0usize => Some(Field::new(
4465 "delta_set_outer_index",
4466 self.delta_set_outer_index(),
4467 )),
4468 1usize => Some(Field::new(
4469 "delta_set_inner_index",
4470 self.delta_set_inner_index(),
4471 )),
4472 2usize => Some(Field::new("delta_format", self.delta_format())),
4473 _ => None,
4474 }
4475 }
4476}
4477
4478#[cfg(feature = "experimental_traverse")]
4479#[allow(clippy::needless_lifetimes)]
4480impl<'a> std::fmt::Debug for VariationIndex<'a> {
4481 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4482 (self as &dyn SomeTable<'a>).fmt(f)
4483 }
4484}
4485
4486#[derive(Clone)]
4488pub enum DeviceOrVariationIndex<'a> {
4489 Device(Device<'a>),
4490 VariationIndex(VariationIndex<'a>),
4491}
4492
4493impl Default for DeviceOrVariationIndex<'_> {
4494 fn default() -> Self {
4495 Self::Device(Default::default())
4496 }
4497}
4498
4499impl<'a> DeviceOrVariationIndex<'a> {
4500 pub fn offset_data(&self) -> FontData<'a> {
4502 match self {
4503 Self::Device(item) => item.offset_data(),
4504 Self::VariationIndex(item) => item.offset_data(),
4505 }
4506 }
4507}
4508
4509impl ReadArgs for DeviceOrVariationIndex<'_> {
4510 type Args = ();
4511}
4512
4513impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
4514 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4515 let format: DeltaFormat = data.read_at(4usize)?;
4516
4517 #[allow(clippy::redundant_guards)]
4518 match format {
4519 format if format != DeltaFormat::VariationIndex => {
4520 Ok(Self::Device(FontRead::read(data)?))
4521 }
4522 format if format == DeltaFormat::VariationIndex => {
4523 Ok(Self::VariationIndex(FontRead::read(data)?))
4524 }
4525 other => Err(ReadError::InvalidFormat(other.into())),
4526 }
4527 }
4528}
4529
4530impl<'a> MinByteRange<'a> for DeviceOrVariationIndex<'a> {
4531 fn min_byte_range(&self) -> Range<usize> {
4532 match self {
4533 Self::Device(item) => item.min_byte_range(),
4534 Self::VariationIndex(item) => item.min_byte_range(),
4535 }
4536 }
4537 fn min_table_bytes(&self) -> &'a [u8] {
4538 match self {
4539 Self::Device(item) => item.min_table_bytes(),
4540 Self::VariationIndex(item) => item.min_table_bytes(),
4541 }
4542 }
4543}
4544
4545#[cfg(feature = "experimental_traverse")]
4546impl<'a> DeviceOrVariationIndex<'a> {
4547 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4548 match self {
4549 Self::Device(table) => table,
4550 Self::VariationIndex(table) => table,
4551 }
4552 }
4553}
4554
4555#[cfg(feature = "experimental_traverse")]
4556impl std::fmt::Debug for DeviceOrVariationIndex<'_> {
4557 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4558 self.dyn_inner().fmt(f)
4559 }
4560}
4561
4562#[cfg(feature = "experimental_traverse")]
4563impl<'a> SomeTable<'a> for DeviceOrVariationIndex<'a> {
4564 fn type_name(&self) -> &str {
4565 self.dyn_inner().type_name()
4566 }
4567 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4568 self.dyn_inner().get_field(idx)
4569 }
4570}
4571
4572impl<'a> MinByteRange<'a> for FeatureVariations<'a> {
4573 fn min_byte_range(&self) -> Range<usize> {
4574 0..self.feature_variation_records_byte_range().end
4575 }
4576 fn min_table_bytes(&self) -> &'a [u8] {
4577 let range = self.min_byte_range();
4578 self.data.as_bytes().get(range).unwrap_or_default()
4579 }
4580}
4581
4582impl ReadArgs for FeatureVariations<'_> {
4583 type Args = ();
4584}
4585
4586impl<'a> FontRead<'a> for FeatureVariations<'a> {
4587 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4588 #[allow(clippy::absurd_extreme_comparisons)]
4589 if data.len() < Self::MIN_SIZE {
4590 return Err(ReadError::OutOfBounds);
4591 }
4592 Ok(Self { data })
4593 }
4594}
4595
4596#[derive(Clone)]
4598pub struct FeatureVariations<'a> {
4599 data: FontData<'a>,
4600}
4601
4602#[allow(clippy::needless_lifetimes)]
4603impl<'a> FeatureVariations<'a> {
4604 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
4605 basic_table_impls!(impl_the_methods);
4606
4607 pub fn version(&self) -> MajorMinor {
4608 let range = self.version_byte_range();
4609 self.data.read_at(range.start).ok().unwrap()
4610 }
4611
4612 pub fn feature_variation_record_count(&self) -> u32 {
4614 let range = self.feature_variation_record_count_byte_range();
4615 self.data.read_at(range.start).ok().unwrap()
4616 }
4617
4618 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
4620 let range = self.feature_variation_records_byte_range();
4621 self.data.read_array(range).ok().unwrap_or_default()
4622 }
4623
4624 pub fn version_byte_range(&self) -> Range<usize> {
4625 let start = 0;
4626 let end = start + MajorMinor::RAW_BYTE_LEN;
4627 start..end
4628 }
4629
4630 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
4631 let start = self.version_byte_range().end;
4632 let end = start + u32::RAW_BYTE_LEN;
4633 start..end
4634 }
4635
4636 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
4637 let feature_variation_record_count = self.feature_variation_record_count();
4638 let start = self.feature_variation_record_count_byte_range().end;
4639 let end = start
4640 + (transforms::to_usize(feature_variation_record_count))
4641 .saturating_mul(FeatureVariationRecord::RAW_BYTE_LEN);
4642 start..end
4643 }
4644}
4645
4646const _: () = assert!(FontData::default_data_long_enough(
4647 FeatureVariations::MIN_SIZE
4648));
4649
4650impl Default for FeatureVariations<'_> {
4651 fn default() -> Self {
4652 Self {
4653 data: FontData::default_table_data(),
4654 }
4655 }
4656}
4657
4658#[cfg(feature = "experimental_traverse")]
4659impl<'a> SomeTable<'a> for FeatureVariations<'a> {
4660 fn type_name(&self) -> &str {
4661 "FeatureVariations"
4662 }
4663 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4664 match idx {
4665 0usize => Some(Field::new("version", self.version())),
4666 1usize => Some(Field::new(
4667 "feature_variation_record_count",
4668 self.feature_variation_record_count(),
4669 )),
4670 2usize => Some(Field::new(
4671 "feature_variation_records",
4672 traversal::FieldType::array_of_records(
4673 stringify!(FeatureVariationRecord),
4674 self.feature_variation_records(),
4675 self.offset_data(),
4676 ),
4677 )),
4678 _ => None,
4679 }
4680 }
4681}
4682
4683#[cfg(feature = "experimental_traverse")]
4684#[allow(clippy::needless_lifetimes)]
4685impl<'a> std::fmt::Debug for FeatureVariations<'a> {
4686 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4687 (self as &dyn SomeTable<'a>).fmt(f)
4688 }
4689}
4690
4691#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4693#[repr(C)]
4694#[repr(packed)]
4695pub struct FeatureVariationRecord {
4696 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
4699 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
4702}
4703
4704impl FeatureVariationRecord {
4705 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
4708 self.condition_set_offset.get()
4709 }
4710
4711 pub fn condition_set<'a>(
4717 &self,
4718 data: FontData<'a>,
4719 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
4720 self.condition_set_offset().resolve(data)
4721 }
4722
4723 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
4726 self.feature_table_substitution_offset.get()
4727 }
4728
4729 pub fn feature_table_substitution<'a>(
4735 &self,
4736 data: FontData<'a>,
4737 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
4738 self.feature_table_substitution_offset().resolve(data)
4739 }
4740}
4741
4742impl FixedSize for FeatureVariationRecord {
4743 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4744}
4745
4746#[cfg(feature = "experimental_traverse")]
4747impl<'a> SomeRecord<'a> for FeatureVariationRecord {
4748 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
4749 RecordResolver {
4750 name: "FeatureVariationRecord",
4751 get_field: Box::new(move |idx, _data| match idx {
4752 0usize => Some(Field::new(
4753 "condition_set_offset",
4754 FieldType::offset(self.condition_set_offset(), self.condition_set(_data)),
4755 )),
4756 1usize => Some(Field::new(
4757 "feature_table_substitution_offset",
4758 FieldType::offset(
4759 self.feature_table_substitution_offset(),
4760 self.feature_table_substitution(_data),
4761 ),
4762 )),
4763 _ => None,
4764 }),
4765 data,
4766 }
4767 }
4768}
4769
4770impl<'a> MinByteRange<'a> for ConditionSet<'a> {
4771 fn min_byte_range(&self) -> Range<usize> {
4772 0..self.condition_offsets_byte_range().end
4773 }
4774 fn min_table_bytes(&self) -> &'a [u8] {
4775 let range = self.min_byte_range();
4776 self.data.as_bytes().get(range).unwrap_or_default()
4777 }
4778}
4779
4780impl ReadArgs for ConditionSet<'_> {
4781 type Args = ();
4782}
4783
4784impl<'a> FontRead<'a> for ConditionSet<'a> {
4785 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4786 #[allow(clippy::absurd_extreme_comparisons)]
4787 if data.len() < Self::MIN_SIZE {
4788 return Err(ReadError::OutOfBounds);
4789 }
4790 Ok(Self { data })
4791 }
4792}
4793
4794#[derive(Clone)]
4796pub struct ConditionSet<'a> {
4797 data: FontData<'a>,
4798}
4799
4800#[allow(clippy::needless_lifetimes)]
4801impl<'a> ConditionSet<'a> {
4802 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
4803 basic_table_impls!(impl_the_methods);
4804
4805 pub fn condition_count(&self) -> u16 {
4807 let range = self.condition_count_byte_range();
4808 self.data.read_at(range.start).ok().unwrap()
4809 }
4810
4811 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
4814 let range = self.condition_offsets_byte_range();
4815 self.data.read_array(range).ok().unwrap_or_default()
4816 }
4817
4818 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
4820 let data = self.data;
4821 let offsets = self.condition_offsets();
4822 ArrayOfOffsets::new(offsets, data, ())
4823 }
4824
4825 pub fn condition_count_byte_range(&self) -> Range<usize> {
4826 let start = 0;
4827 let end = start + u16::RAW_BYTE_LEN;
4828 start..end
4829 }
4830
4831 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4832 let condition_count = self.condition_count();
4833 let start = self.condition_count_byte_range().end;
4834 let end =
4835 start + (transforms::to_usize(condition_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
4836 start..end
4837 }
4838}
4839
4840const _: () = assert!(FontData::default_data_long_enough(ConditionSet::MIN_SIZE));
4841
4842impl Default for ConditionSet<'_> {
4843 fn default() -> Self {
4844 Self {
4845 data: FontData::default_table_data(),
4846 }
4847 }
4848}
4849
4850#[cfg(feature = "experimental_traverse")]
4851impl<'a> SomeTable<'a> for ConditionSet<'a> {
4852 fn type_name(&self) -> &str {
4853 "ConditionSet"
4854 }
4855 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4856 match idx {
4857 0usize => Some(Field::new("condition_count", self.condition_count())),
4858 1usize => Some(Field::new(
4859 "condition_offsets",
4860 FieldType::from(self.conditions()),
4861 )),
4862 _ => None,
4863 }
4864 }
4865}
4866
4867#[cfg(feature = "experimental_traverse")]
4868#[allow(clippy::needless_lifetimes)]
4869impl<'a> std::fmt::Debug for ConditionSet<'a> {
4870 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4871 (self as &dyn SomeTable<'a>).fmt(f)
4872 }
4873}
4874
4875#[derive(Clone)]
4880pub enum Condition<'a> {
4881 Format1AxisRange(ConditionFormat1<'a>),
4882 Format2VariableValue(ConditionFormat2<'a>),
4883 Format3And(ConditionFormat3<'a>),
4884 Format4Or(ConditionFormat4<'a>),
4885 Format5Negate(ConditionFormat5<'a>),
4886}
4887
4888impl Default for Condition<'_> {
4889 fn default() -> Self {
4890 Self::Format1AxisRange(Default::default())
4891 }
4892}
4893
4894impl<'a> Condition<'a> {
4895 pub fn offset_data(&self) -> FontData<'a> {
4897 match self {
4898 Self::Format1AxisRange(item) => item.offset_data(),
4899 Self::Format2VariableValue(item) => item.offset_data(),
4900 Self::Format3And(item) => item.offset_data(),
4901 Self::Format4Or(item) => item.offset_data(),
4902 Self::Format5Negate(item) => item.offset_data(),
4903 }
4904 }
4905
4906 pub fn format(&self) -> u16 {
4908 match self {
4909 Self::Format1AxisRange(item) => item.format(),
4910 Self::Format2VariableValue(item) => item.format(),
4911 Self::Format3And(item) => item.format(),
4912 Self::Format4Or(item) => item.format(),
4913 Self::Format5Negate(item) => item.format(),
4914 }
4915 }
4916}
4917
4918impl ReadArgs for Condition<'_> {
4919 type Args = ();
4920}
4921
4922impl<'a> FontRead<'a> for Condition<'a> {
4923 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
4924 let format: u16 = data.read_at(0usize)?;
4925 match format {
4926 ConditionFormat1::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
4927 ConditionFormat2::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
4928 ConditionFormat3::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
4929 ConditionFormat4::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
4930 ConditionFormat5::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
4931 other => Err(ReadError::InvalidFormat(other.into())),
4932 }
4933 }
4934}
4935
4936impl<'a> MinByteRange<'a> for Condition<'a> {
4937 fn min_byte_range(&self) -> Range<usize> {
4938 match self {
4939 Self::Format1AxisRange(item) => item.min_byte_range(),
4940 Self::Format2VariableValue(item) => item.min_byte_range(),
4941 Self::Format3And(item) => item.min_byte_range(),
4942 Self::Format4Or(item) => item.min_byte_range(),
4943 Self::Format5Negate(item) => item.min_byte_range(),
4944 }
4945 }
4946 fn min_table_bytes(&self) -> &'a [u8] {
4947 match self {
4948 Self::Format1AxisRange(item) => item.min_table_bytes(),
4949 Self::Format2VariableValue(item) => item.min_table_bytes(),
4950 Self::Format3And(item) => item.min_table_bytes(),
4951 Self::Format4Or(item) => item.min_table_bytes(),
4952 Self::Format5Negate(item) => item.min_table_bytes(),
4953 }
4954 }
4955}
4956
4957#[cfg(feature = "experimental_traverse")]
4958impl<'a> Condition<'a> {
4959 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4960 match self {
4961 Self::Format1AxisRange(table) => table,
4962 Self::Format2VariableValue(table) => table,
4963 Self::Format3And(table) => table,
4964 Self::Format4Or(table) => table,
4965 Self::Format5Negate(table) => table,
4966 }
4967 }
4968}
4969
4970#[cfg(feature = "experimental_traverse")]
4971impl std::fmt::Debug for Condition<'_> {
4972 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4973 self.dyn_inner().fmt(f)
4974 }
4975}
4976
4977#[cfg(feature = "experimental_traverse")]
4978impl<'a> SomeTable<'a> for Condition<'a> {
4979 fn type_name(&self) -> &str {
4980 self.dyn_inner().type_name()
4981 }
4982 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4983 self.dyn_inner().get_field(idx)
4984 }
4985}
4986
4987impl Format<u16> for ConditionFormat1<'_> {
4988 const FORMAT: u16 = 1;
4989}
4990
4991impl<'a> MinByteRange<'a> for ConditionFormat1<'a> {
4992 fn min_byte_range(&self) -> Range<usize> {
4993 0..self.filter_range_max_value_byte_range().end
4994 }
4995 fn min_table_bytes(&self) -> &'a [u8] {
4996 let range = self.min_byte_range();
4997 self.data.as_bytes().get(range).unwrap_or_default()
4998 }
4999}
5000
5001impl ReadArgs for ConditionFormat1<'_> {
5002 type Args = ();
5003}
5004
5005impl<'a> FontRead<'a> for ConditionFormat1<'a> {
5006 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5007 #[allow(clippy::absurd_extreme_comparisons)]
5008 if data.len() < Self::MIN_SIZE {
5009 return Err(ReadError::OutOfBounds);
5010 }
5011 Ok(Self { data })
5012 }
5013}
5014
5015#[derive(Clone)]
5017pub struct ConditionFormat1<'a> {
5018 data: FontData<'a>,
5019}
5020
5021#[allow(clippy::needless_lifetimes)]
5022impl<'a> ConditionFormat1<'a> {
5023 pub const MIN_SIZE: usize =
5024 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN);
5025 basic_table_impls!(impl_the_methods);
5026
5027 pub fn format(&self) -> u16 {
5029 let range = self.format_byte_range();
5030 self.data.read_at(range.start).ok().unwrap()
5031 }
5032
5033 pub fn axis_index(&self) -> u16 {
5036 let range = self.axis_index_byte_range();
5037 self.data.read_at(range.start).ok().unwrap()
5038 }
5039
5040 pub fn filter_range_min_value(&self) -> F2Dot14 {
5043 let range = self.filter_range_min_value_byte_range();
5044 self.data.read_at(range.start).ok().unwrap()
5045 }
5046
5047 pub fn filter_range_max_value(&self) -> F2Dot14 {
5050 let range = self.filter_range_max_value_byte_range();
5051 self.data.read_at(range.start).ok().unwrap()
5052 }
5053
5054 pub fn format_byte_range(&self) -> Range<usize> {
5055 let start = 0;
5056 let end = start + u16::RAW_BYTE_LEN;
5057 start..end
5058 }
5059
5060 pub fn axis_index_byte_range(&self) -> Range<usize> {
5061 let start = self.format_byte_range().end;
5062 let end = start + u16::RAW_BYTE_LEN;
5063 start..end
5064 }
5065
5066 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
5067 let start = self.axis_index_byte_range().end;
5068 let end = start + F2Dot14::RAW_BYTE_LEN;
5069 start..end
5070 }
5071
5072 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
5073 let start = self.filter_range_min_value_byte_range().end;
5074 let end = start + F2Dot14::RAW_BYTE_LEN;
5075 start..end
5076 }
5077}
5078
5079const _: () = assert!(FontData::default_data_long_enough(
5080 ConditionFormat1::MIN_SIZE
5081));
5082
5083impl Default for ConditionFormat1<'_> {
5084 fn default() -> Self {
5085 Self {
5086 data: FontData::default_format_1_u16_table_data(),
5087 }
5088 }
5089}
5090
5091#[cfg(feature = "experimental_traverse")]
5092impl<'a> SomeTable<'a> for ConditionFormat1<'a> {
5093 fn type_name(&self) -> &str {
5094 "ConditionFormat1"
5095 }
5096 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5097 match idx {
5098 0usize => Some(Field::new("format", self.format())),
5099 1usize => Some(Field::new("axis_index", self.axis_index())),
5100 2usize => Some(Field::new(
5101 "filter_range_min_value",
5102 self.filter_range_min_value(),
5103 )),
5104 3usize => Some(Field::new(
5105 "filter_range_max_value",
5106 self.filter_range_max_value(),
5107 )),
5108 _ => None,
5109 }
5110 }
5111}
5112
5113#[cfg(feature = "experimental_traverse")]
5114#[allow(clippy::needless_lifetimes)]
5115impl<'a> std::fmt::Debug for ConditionFormat1<'a> {
5116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5117 (self as &dyn SomeTable<'a>).fmt(f)
5118 }
5119}
5120
5121impl Format<u16> for ConditionFormat2<'_> {
5122 const FORMAT: u16 = 2;
5123}
5124
5125impl<'a> MinByteRange<'a> for ConditionFormat2<'a> {
5126 fn min_byte_range(&self) -> Range<usize> {
5127 0..self.var_index_byte_range().end
5128 }
5129 fn min_table_bytes(&self) -> &'a [u8] {
5130 let range = self.min_byte_range();
5131 self.data.as_bytes().get(range).unwrap_or_default()
5132 }
5133}
5134
5135impl ReadArgs for ConditionFormat2<'_> {
5136 type Args = ();
5137}
5138
5139impl<'a> FontRead<'a> for ConditionFormat2<'a> {
5140 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5141 #[allow(clippy::absurd_extreme_comparisons)]
5142 if data.len() < Self::MIN_SIZE {
5143 return Err(ReadError::OutOfBounds);
5144 }
5145 Ok(Self { data })
5146 }
5147}
5148
5149#[derive(Clone)]
5151pub struct ConditionFormat2<'a> {
5152 data: FontData<'a>,
5153}
5154
5155#[allow(clippy::needless_lifetimes)]
5156impl<'a> ConditionFormat2<'a> {
5157 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
5158 basic_table_impls!(impl_the_methods);
5159
5160 pub fn format(&self) -> u16 {
5162 let range = self.format_byte_range();
5163 self.data.read_at(range.start).ok().unwrap()
5164 }
5165
5166 pub fn default_value(&self) -> i16 {
5168 let range = self.default_value_byte_range();
5169 self.data.read_at(range.start).ok().unwrap()
5170 }
5171
5172 pub fn var_index(&self) -> u32 {
5174 let range = self.var_index_byte_range();
5175 self.data.read_at(range.start).ok().unwrap()
5176 }
5177
5178 pub fn format_byte_range(&self) -> Range<usize> {
5179 let start = 0;
5180 let end = start + u16::RAW_BYTE_LEN;
5181 start..end
5182 }
5183
5184 pub fn default_value_byte_range(&self) -> Range<usize> {
5185 let start = self.format_byte_range().end;
5186 let end = start + i16::RAW_BYTE_LEN;
5187 start..end
5188 }
5189
5190 pub fn var_index_byte_range(&self) -> Range<usize> {
5191 let start = self.default_value_byte_range().end;
5192 let end = start + u32::RAW_BYTE_LEN;
5193 start..end
5194 }
5195}
5196
5197#[cfg(feature = "experimental_traverse")]
5198impl<'a> SomeTable<'a> for ConditionFormat2<'a> {
5199 fn type_name(&self) -> &str {
5200 "ConditionFormat2"
5201 }
5202 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5203 match idx {
5204 0usize => Some(Field::new("format", self.format())),
5205 1usize => Some(Field::new("default_value", self.default_value())),
5206 2usize => Some(Field::new("var_index", self.var_index())),
5207 _ => None,
5208 }
5209 }
5210}
5211
5212#[cfg(feature = "experimental_traverse")]
5213#[allow(clippy::needless_lifetimes)]
5214impl<'a> std::fmt::Debug for ConditionFormat2<'a> {
5215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5216 (self as &dyn SomeTable<'a>).fmt(f)
5217 }
5218}
5219
5220impl Format<u16> for ConditionFormat3<'_> {
5221 const FORMAT: u16 = 3;
5222}
5223
5224impl<'a> MinByteRange<'a> for ConditionFormat3<'a> {
5225 fn min_byte_range(&self) -> Range<usize> {
5226 0..self.condition_offsets_byte_range().end
5227 }
5228 fn min_table_bytes(&self) -> &'a [u8] {
5229 let range = self.min_byte_range();
5230 self.data.as_bytes().get(range).unwrap_or_default()
5231 }
5232}
5233
5234impl ReadArgs for ConditionFormat3<'_> {
5235 type Args = ();
5236}
5237
5238impl<'a> FontRead<'a> for ConditionFormat3<'a> {
5239 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5240 #[allow(clippy::absurd_extreme_comparisons)]
5241 if data.len() < Self::MIN_SIZE {
5242 return Err(ReadError::OutOfBounds);
5243 }
5244 Ok(Self { data })
5245 }
5246}
5247
5248#[derive(Clone)]
5250pub struct ConditionFormat3<'a> {
5251 data: FontData<'a>,
5252}
5253
5254#[allow(clippy::needless_lifetimes)]
5255impl<'a> ConditionFormat3<'a> {
5256 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5257 basic_table_impls!(impl_the_methods);
5258
5259 pub fn format(&self) -> u16 {
5261 let range = self.format_byte_range();
5262 self.data.read_at(range.start).ok().unwrap()
5263 }
5264
5265 pub fn condition_count(&self) -> u8 {
5267 let range = self.condition_count_byte_range();
5268 self.data.read_at(range.start).ok().unwrap()
5269 }
5270
5271 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5273 let range = self.condition_offsets_byte_range();
5274 self.data.read_array(range).ok().unwrap_or_default()
5275 }
5276
5277 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5279 let data = self.data;
5280 let offsets = self.condition_offsets();
5281 ArrayOfOffsets::new(offsets, data, ())
5282 }
5283
5284 pub fn format_byte_range(&self) -> Range<usize> {
5285 let start = 0;
5286 let end = start + u16::RAW_BYTE_LEN;
5287 start..end
5288 }
5289
5290 pub fn condition_count_byte_range(&self) -> Range<usize> {
5291 let start = self.format_byte_range().end;
5292 let end = start + u8::RAW_BYTE_LEN;
5293 start..end
5294 }
5295
5296 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5297 let condition_count = self.condition_count();
5298 let start = self.condition_count_byte_range().end;
5299 let end =
5300 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5301 start..end
5302 }
5303}
5304
5305#[cfg(feature = "experimental_traverse")]
5306impl<'a> SomeTable<'a> for ConditionFormat3<'a> {
5307 fn type_name(&self) -> &str {
5308 "ConditionFormat3"
5309 }
5310 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5311 match idx {
5312 0usize => Some(Field::new("format", self.format())),
5313 1usize => Some(Field::new("condition_count", self.condition_count())),
5314 2usize => Some(Field::new(
5315 "condition_offsets",
5316 FieldType::from(self.conditions()),
5317 )),
5318 _ => None,
5319 }
5320 }
5321}
5322
5323#[cfg(feature = "experimental_traverse")]
5324#[allow(clippy::needless_lifetimes)]
5325impl<'a> std::fmt::Debug for ConditionFormat3<'a> {
5326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5327 (self as &dyn SomeTable<'a>).fmt(f)
5328 }
5329}
5330
5331impl Format<u16> for ConditionFormat4<'_> {
5332 const FORMAT: u16 = 4;
5333}
5334
5335impl<'a> MinByteRange<'a> for ConditionFormat4<'a> {
5336 fn min_byte_range(&self) -> Range<usize> {
5337 0..self.condition_offsets_byte_range().end
5338 }
5339 fn min_table_bytes(&self) -> &'a [u8] {
5340 let range = self.min_byte_range();
5341 self.data.as_bytes().get(range).unwrap_or_default()
5342 }
5343}
5344
5345impl ReadArgs for ConditionFormat4<'_> {
5346 type Args = ();
5347}
5348
5349impl<'a> FontRead<'a> for ConditionFormat4<'a> {
5350 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5351 #[allow(clippy::absurd_extreme_comparisons)]
5352 if data.len() < Self::MIN_SIZE {
5353 return Err(ReadError::OutOfBounds);
5354 }
5355 Ok(Self { data })
5356 }
5357}
5358
5359#[derive(Clone)]
5361pub struct ConditionFormat4<'a> {
5362 data: FontData<'a>,
5363}
5364
5365#[allow(clippy::needless_lifetimes)]
5366impl<'a> ConditionFormat4<'a> {
5367 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
5368 basic_table_impls!(impl_the_methods);
5369
5370 pub fn format(&self) -> u16 {
5372 let range = self.format_byte_range();
5373 self.data.read_at(range.start).ok().unwrap()
5374 }
5375
5376 pub fn condition_count(&self) -> u8 {
5378 let range = self.condition_count_byte_range();
5379 self.data.read_at(range.start).ok().unwrap()
5380 }
5381
5382 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5384 let range = self.condition_offsets_byte_range();
5385 self.data.read_array(range).ok().unwrap_or_default()
5386 }
5387
5388 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5390 let data = self.data;
5391 let offsets = self.condition_offsets();
5392 ArrayOfOffsets::new(offsets, data, ())
5393 }
5394
5395 pub fn format_byte_range(&self) -> Range<usize> {
5396 let start = 0;
5397 let end = start + u16::RAW_BYTE_LEN;
5398 start..end
5399 }
5400
5401 pub fn condition_count_byte_range(&self) -> Range<usize> {
5402 let start = self.format_byte_range().end;
5403 let end = start + u8::RAW_BYTE_LEN;
5404 start..end
5405 }
5406
5407 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5408 let condition_count = self.condition_count();
5409 let start = self.condition_count_byte_range().end;
5410 let end =
5411 start + (transforms::to_usize(condition_count)).saturating_mul(Offset24::RAW_BYTE_LEN);
5412 start..end
5413 }
5414}
5415
5416#[cfg(feature = "experimental_traverse")]
5417impl<'a> SomeTable<'a> for ConditionFormat4<'a> {
5418 fn type_name(&self) -> &str {
5419 "ConditionFormat4"
5420 }
5421 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5422 match idx {
5423 0usize => Some(Field::new("format", self.format())),
5424 1usize => Some(Field::new("condition_count", self.condition_count())),
5425 2usize => Some(Field::new(
5426 "condition_offsets",
5427 FieldType::from(self.conditions()),
5428 )),
5429 _ => None,
5430 }
5431 }
5432}
5433
5434#[cfg(feature = "experimental_traverse")]
5435#[allow(clippy::needless_lifetimes)]
5436impl<'a> std::fmt::Debug for ConditionFormat4<'a> {
5437 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5438 (self as &dyn SomeTable<'a>).fmt(f)
5439 }
5440}
5441
5442impl Format<u16> for ConditionFormat5<'_> {
5443 const FORMAT: u16 = 5;
5444}
5445
5446impl<'a> MinByteRange<'a> for ConditionFormat5<'a> {
5447 fn min_byte_range(&self) -> Range<usize> {
5448 0..self.condition_offset_byte_range().end
5449 }
5450 fn min_table_bytes(&self) -> &'a [u8] {
5451 let range = self.min_byte_range();
5452 self.data.as_bytes().get(range).unwrap_or_default()
5453 }
5454}
5455
5456impl ReadArgs for ConditionFormat5<'_> {
5457 type Args = ();
5458}
5459
5460impl<'a> FontRead<'a> for ConditionFormat5<'a> {
5461 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5462 #[allow(clippy::absurd_extreme_comparisons)]
5463 if data.len() < Self::MIN_SIZE {
5464 return Err(ReadError::OutOfBounds);
5465 }
5466 Ok(Self { data })
5467 }
5468}
5469
5470#[derive(Clone)]
5472pub struct ConditionFormat5<'a> {
5473 data: FontData<'a>,
5474}
5475
5476#[allow(clippy::needless_lifetimes)]
5477impl<'a> ConditionFormat5<'a> {
5478 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset24::RAW_BYTE_LEN);
5479 basic_table_impls!(impl_the_methods);
5480
5481 pub fn format(&self) -> u16 {
5483 let range = self.format_byte_range();
5484 self.data.read_at(range.start).ok().unwrap()
5485 }
5486
5487 pub fn condition_offset(&self) -> Offset24 {
5489 let range = self.condition_offset_byte_range();
5490 self.data.read_at(range.start).ok().unwrap()
5491 }
5492
5493 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
5495 let data = self.data;
5496 self.condition_offset().resolve(data)
5497 }
5498
5499 pub fn format_byte_range(&self) -> Range<usize> {
5500 let start = 0;
5501 let end = start + u16::RAW_BYTE_LEN;
5502 start..end
5503 }
5504
5505 pub fn condition_offset_byte_range(&self) -> Range<usize> {
5506 let start = self.format_byte_range().end;
5507 let end = start + Offset24::RAW_BYTE_LEN;
5508 start..end
5509 }
5510}
5511
5512#[cfg(feature = "experimental_traverse")]
5513impl<'a> SomeTable<'a> for ConditionFormat5<'a> {
5514 fn type_name(&self) -> &str {
5515 "ConditionFormat5"
5516 }
5517 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5518 match idx {
5519 0usize => Some(Field::new("format", self.format())),
5520 1usize => Some(Field::new(
5521 "condition_offset",
5522 FieldType::offset(self.condition_offset(), self.condition()),
5523 )),
5524 _ => None,
5525 }
5526 }
5527}
5528
5529#[cfg(feature = "experimental_traverse")]
5530#[allow(clippy::needless_lifetimes)]
5531impl<'a> std::fmt::Debug for ConditionFormat5<'a> {
5532 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5533 (self as &dyn SomeTable<'a>).fmt(f)
5534 }
5535}
5536
5537impl<'a> MinByteRange<'a> for FeatureTableSubstitution<'a> {
5538 fn min_byte_range(&self) -> Range<usize> {
5539 0..self.substitutions_byte_range().end
5540 }
5541 fn min_table_bytes(&self) -> &'a [u8] {
5542 let range = self.min_byte_range();
5543 self.data.as_bytes().get(range).unwrap_or_default()
5544 }
5545}
5546
5547impl ReadArgs for FeatureTableSubstitution<'_> {
5548 type Args = ();
5549}
5550
5551impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
5552 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5553 #[allow(clippy::absurd_extreme_comparisons)]
5554 if data.len() < Self::MIN_SIZE {
5555 return Err(ReadError::OutOfBounds);
5556 }
5557 Ok(Self { data })
5558 }
5559}
5560
5561#[derive(Clone)]
5563pub struct FeatureTableSubstitution<'a> {
5564 data: FontData<'a>,
5565}
5566
5567#[allow(clippy::needless_lifetimes)]
5568impl<'a> FeatureTableSubstitution<'a> {
5569 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
5570 basic_table_impls!(impl_the_methods);
5571
5572 pub fn version(&self) -> MajorMinor {
5574 let range = self.version_byte_range();
5575 self.data.read_at(range.start).ok().unwrap()
5576 }
5577
5578 pub fn substitution_count(&self) -> u16 {
5580 let range = self.substitution_count_byte_range();
5581 self.data.read_at(range.start).ok().unwrap()
5582 }
5583
5584 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
5586 let range = self.substitutions_byte_range();
5587 self.data.read_array(range).ok().unwrap_or_default()
5588 }
5589
5590 pub fn version_byte_range(&self) -> Range<usize> {
5591 let start = 0;
5592 let end = start + MajorMinor::RAW_BYTE_LEN;
5593 start..end
5594 }
5595
5596 pub fn substitution_count_byte_range(&self) -> Range<usize> {
5597 let start = self.version_byte_range().end;
5598 let end = start + u16::RAW_BYTE_LEN;
5599 start..end
5600 }
5601
5602 pub fn substitutions_byte_range(&self) -> Range<usize> {
5603 let substitution_count = self.substitution_count();
5604 let start = self.substitution_count_byte_range().end;
5605 let end = start
5606 + (transforms::to_usize(substitution_count))
5607 .saturating_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN);
5608 start..end
5609 }
5610}
5611
5612const _: () = assert!(FontData::default_data_long_enough(
5613 FeatureTableSubstitution::MIN_SIZE
5614));
5615
5616impl Default for FeatureTableSubstitution<'_> {
5617 fn default() -> Self {
5618 Self {
5619 data: FontData::default_table_data(),
5620 }
5621 }
5622}
5623
5624#[cfg(feature = "experimental_traverse")]
5625impl<'a> SomeTable<'a> for FeatureTableSubstitution<'a> {
5626 fn type_name(&self) -> &str {
5627 "FeatureTableSubstitution"
5628 }
5629 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5630 match idx {
5631 0usize => Some(Field::new("version", self.version())),
5632 1usize => Some(Field::new("substitution_count", self.substitution_count())),
5633 2usize => Some(Field::new(
5634 "substitutions",
5635 traversal::FieldType::array_of_records(
5636 stringify!(FeatureTableSubstitutionRecord),
5637 self.substitutions(),
5638 self.offset_data(),
5639 ),
5640 )),
5641 _ => None,
5642 }
5643 }
5644}
5645
5646#[cfg(feature = "experimental_traverse")]
5647#[allow(clippy::needless_lifetimes)]
5648impl<'a> std::fmt::Debug for FeatureTableSubstitution<'a> {
5649 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5650 (self as &dyn SomeTable<'a>).fmt(f)
5651 }
5652}
5653
5654#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
5656#[repr(C)]
5657#[repr(packed)]
5658pub struct FeatureTableSubstitutionRecord {
5659 pub feature_index: BigEndian<u16>,
5661 pub alternate_feature_offset: BigEndian<Offset32>,
5664}
5665
5666impl FeatureTableSubstitutionRecord {
5667 pub fn feature_index(&self) -> u16 {
5669 self.feature_index.get()
5670 }
5671
5672 pub fn alternate_feature_offset(&self) -> Offset32 {
5675 self.alternate_feature_offset.get()
5676 }
5677}
5678
5679impl FixedSize for FeatureTableSubstitutionRecord {
5680 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
5681}
5682
5683#[cfg(feature = "experimental_traverse")]
5684impl<'a> SomeRecord<'a> for FeatureTableSubstitutionRecord {
5685 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
5686 RecordResolver {
5687 name: "FeatureTableSubstitutionRecord",
5688 get_field: Box::new(move |idx, _data| match idx {
5689 0usize => Some(Field::new("feature_index", self.feature_index())),
5690 1usize => Some(Field::new(
5691 "alternate_feature_offset",
5692 FieldType::offset(
5693 self.alternate_feature_offset(),
5694 self.alternate_feature(_data),
5695 ),
5696 )),
5697 _ => None,
5698 }),
5699 data,
5700 }
5701 }
5702}
5703
5704impl<'a> MinByteRange<'a> for SizeParams<'a> {
5705 fn min_byte_range(&self) -> Range<usize> {
5706 0..self.range_end_byte_range().end
5707 }
5708 fn min_table_bytes(&self) -> &'a [u8] {
5709 let range = self.min_byte_range();
5710 self.data.as_bytes().get(range).unwrap_or_default()
5711 }
5712}
5713
5714impl ReadArgs for SizeParams<'_> {
5715 type Args = ();
5716}
5717
5718impl<'a> FontRead<'a> for SizeParams<'a> {
5719 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5720 #[allow(clippy::absurd_extreme_comparisons)]
5721 if data.len() < Self::MIN_SIZE {
5722 return Err(ReadError::OutOfBounds);
5723 }
5724 Ok(Self { data })
5725 }
5726}
5727
5728#[derive(Clone)]
5729pub struct SizeParams<'a> {
5730 data: FontData<'a>,
5731}
5732
5733#[allow(clippy::needless_lifetimes)]
5734impl<'a> SizeParams<'a> {
5735 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5736 + u16::RAW_BYTE_LEN
5737 + u16::RAW_BYTE_LEN
5738 + u16::RAW_BYTE_LEN
5739 + u16::RAW_BYTE_LEN);
5740 basic_table_impls!(impl_the_methods);
5741
5742 pub fn design_size(&self) -> u16 {
5747 let range = self.design_size_byte_range();
5748 self.data.read_at(range.start).ok().unwrap()
5749 }
5750
5751 pub fn identifier(&self) -> u16 {
5758 let range = self.identifier_byte_range();
5759 self.data.read_at(range.start).ok().unwrap()
5760 }
5761
5762 pub fn name_entry(&self) -> u16 {
5773 let range = self.name_entry_byte_range();
5774 self.data.read_at(range.start).ok().unwrap()
5775 }
5776
5777 pub fn range_start(&self) -> u16 {
5783 let range = self.range_start_byte_range();
5784 self.data.read_at(range.start).ok().unwrap()
5785 }
5786
5787 pub fn range_end(&self) -> u16 {
5788 let range = self.range_end_byte_range();
5789 self.data.read_at(range.start).ok().unwrap()
5790 }
5791
5792 pub fn design_size_byte_range(&self) -> Range<usize> {
5793 let start = 0;
5794 let end = start + u16::RAW_BYTE_LEN;
5795 start..end
5796 }
5797
5798 pub fn identifier_byte_range(&self) -> Range<usize> {
5799 let start = self.design_size_byte_range().end;
5800 let end = start + u16::RAW_BYTE_LEN;
5801 start..end
5802 }
5803
5804 pub fn name_entry_byte_range(&self) -> Range<usize> {
5805 let start = self.identifier_byte_range().end;
5806 let end = start + u16::RAW_BYTE_LEN;
5807 start..end
5808 }
5809
5810 pub fn range_start_byte_range(&self) -> Range<usize> {
5811 let start = self.name_entry_byte_range().end;
5812 let end = start + u16::RAW_BYTE_LEN;
5813 start..end
5814 }
5815
5816 pub fn range_end_byte_range(&self) -> Range<usize> {
5817 let start = self.range_start_byte_range().end;
5818 let end = start + u16::RAW_BYTE_LEN;
5819 start..end
5820 }
5821}
5822
5823const _: () = assert!(FontData::default_data_long_enough(SizeParams::MIN_SIZE));
5824
5825impl Default for SizeParams<'_> {
5826 fn default() -> Self {
5827 Self {
5828 data: FontData::default_table_data(),
5829 }
5830 }
5831}
5832
5833#[cfg(feature = "experimental_traverse")]
5834impl<'a> SomeTable<'a> for SizeParams<'a> {
5835 fn type_name(&self) -> &str {
5836 "SizeParams"
5837 }
5838 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5839 match idx {
5840 0usize => Some(Field::new("design_size", self.design_size())),
5841 1usize => Some(Field::new("identifier", self.identifier())),
5842 2usize => Some(Field::new("name_entry", self.name_entry())),
5843 3usize => Some(Field::new("range_start", self.range_start())),
5844 4usize => Some(Field::new("range_end", self.range_end())),
5845 _ => None,
5846 }
5847 }
5848}
5849
5850#[cfg(feature = "experimental_traverse")]
5851#[allow(clippy::needless_lifetimes)]
5852impl<'a> std::fmt::Debug for SizeParams<'a> {
5853 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5854 (self as &dyn SomeTable<'a>).fmt(f)
5855 }
5856}
5857
5858impl<'a> MinByteRange<'a> for StylisticSetParams<'a> {
5859 fn min_byte_range(&self) -> Range<usize> {
5860 0..self.ui_name_id_byte_range().end
5861 }
5862 fn min_table_bytes(&self) -> &'a [u8] {
5863 let range = self.min_byte_range();
5864 self.data.as_bytes().get(range).unwrap_or_default()
5865 }
5866}
5867
5868impl ReadArgs for StylisticSetParams<'_> {
5869 type Args = ();
5870}
5871
5872impl<'a> FontRead<'a> for StylisticSetParams<'a> {
5873 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5874 #[allow(clippy::absurd_extreme_comparisons)]
5875 if data.len() < Self::MIN_SIZE {
5876 return Err(ReadError::OutOfBounds);
5877 }
5878 Ok(Self { data })
5879 }
5880}
5881
5882#[derive(Clone)]
5883pub struct StylisticSetParams<'a> {
5884 data: FontData<'a>,
5885}
5886
5887#[allow(clippy::needless_lifetimes)]
5888impl<'a> StylisticSetParams<'a> {
5889 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN);
5890 basic_table_impls!(impl_the_methods);
5891
5892 pub fn version(&self) -> u16 {
5893 let range = self.version_byte_range();
5894 self.data.read_at(range.start).ok().unwrap()
5895 }
5896
5897 pub fn ui_name_id(&self) -> NameId {
5907 let range = self.ui_name_id_byte_range();
5908 self.data.read_at(range.start).ok().unwrap()
5909 }
5910
5911 pub fn version_byte_range(&self) -> Range<usize> {
5912 let start = 0;
5913 let end = start + u16::RAW_BYTE_LEN;
5914 start..end
5915 }
5916
5917 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
5918 let start = self.version_byte_range().end;
5919 let end = start + NameId::RAW_BYTE_LEN;
5920 start..end
5921 }
5922}
5923
5924const _: () = assert!(FontData::default_data_long_enough(
5925 StylisticSetParams::MIN_SIZE
5926));
5927
5928impl Default for StylisticSetParams<'_> {
5929 fn default() -> Self {
5930 Self {
5931 data: FontData::default_table_data(),
5932 }
5933 }
5934}
5935
5936#[cfg(feature = "experimental_traverse")]
5937impl<'a> SomeTable<'a> for StylisticSetParams<'a> {
5938 fn type_name(&self) -> &str {
5939 "StylisticSetParams"
5940 }
5941 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5942 match idx {
5943 0usize => Some(Field::new("version", self.version())),
5944 1usize => Some(Field::new("ui_name_id", self.ui_name_id())),
5945 _ => None,
5946 }
5947 }
5948}
5949
5950#[cfg(feature = "experimental_traverse")]
5951#[allow(clippy::needless_lifetimes)]
5952impl<'a> std::fmt::Debug for StylisticSetParams<'a> {
5953 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5954 (self as &dyn SomeTable<'a>).fmt(f)
5955 }
5956}
5957
5958impl Format<u16> for CharacterVariantParams<'_> {
5959 const FORMAT: u16 = 0;
5960}
5961
5962impl<'a> MinByteRange<'a> for CharacterVariantParams<'a> {
5963 fn min_byte_range(&self) -> Range<usize> {
5964 0..self.character_byte_range().end
5965 }
5966 fn min_table_bytes(&self) -> &'a [u8] {
5967 let range = self.min_byte_range();
5968 self.data.as_bytes().get(range).unwrap_or_default()
5969 }
5970}
5971
5972impl ReadArgs for CharacterVariantParams<'_> {
5973 type Args = ();
5974}
5975
5976impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
5977 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
5978 #[allow(clippy::absurd_extreme_comparisons)]
5979 if data.len() < Self::MIN_SIZE {
5980 return Err(ReadError::OutOfBounds);
5981 }
5982 Ok(Self { data })
5983 }
5984}
5985
5986#[derive(Clone)]
5988pub struct CharacterVariantParams<'a> {
5989 data: FontData<'a>,
5990}
5991
5992#[allow(clippy::needless_lifetimes)]
5993impl<'a> CharacterVariantParams<'a> {
5994 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
5995 + NameId::RAW_BYTE_LEN
5996 + NameId::RAW_BYTE_LEN
5997 + NameId::RAW_BYTE_LEN
5998 + u16::RAW_BYTE_LEN
5999 + NameId::RAW_BYTE_LEN
6000 + u16::RAW_BYTE_LEN);
6001 basic_table_impls!(impl_the_methods);
6002
6003 pub fn format(&self) -> u16 {
6005 let range = self.format_byte_range();
6006 self.data.read_at(range.start).ok().unwrap()
6007 }
6008
6009 pub fn feat_ui_label_name_id(&self) -> NameId {
6013 let range = self.feat_ui_label_name_id_byte_range();
6014 self.data.read_at(range.start).ok().unwrap()
6015 }
6016
6017 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
6021 let range = self.feat_ui_tooltip_text_name_id_byte_range();
6022 self.data.read_at(range.start).ok().unwrap()
6023 }
6024
6025 pub fn sample_text_name_id(&self) -> NameId {
6028 let range = self.sample_text_name_id_byte_range();
6029 self.data.read_at(range.start).ok().unwrap()
6030 }
6031
6032 pub fn num_named_parameters(&self) -> u16 {
6034 let range = self.num_named_parameters_byte_range();
6035 self.data.read_at(range.start).ok().unwrap()
6036 }
6037
6038 pub fn first_param_ui_label_name_id(&self) -> NameId {
6042 let range = self.first_param_ui_label_name_id_byte_range();
6043 self.data.read_at(range.start).ok().unwrap()
6044 }
6045
6046 pub fn char_count(&self) -> u16 {
6049 let range = self.char_count_byte_range();
6050 self.data.read_at(range.start).ok().unwrap()
6051 }
6052
6053 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
6056 let range = self.character_byte_range();
6057 self.data.read_array(range).ok().unwrap_or_default()
6058 }
6059
6060 pub fn format_byte_range(&self) -> Range<usize> {
6061 let start = 0;
6062 let end = start + u16::RAW_BYTE_LEN;
6063 start..end
6064 }
6065
6066 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
6067 let start = self.format_byte_range().end;
6068 let end = start + NameId::RAW_BYTE_LEN;
6069 start..end
6070 }
6071
6072 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
6073 let start = self.feat_ui_label_name_id_byte_range().end;
6074 let end = start + NameId::RAW_BYTE_LEN;
6075 start..end
6076 }
6077
6078 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
6079 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
6080 let end = start + NameId::RAW_BYTE_LEN;
6081 start..end
6082 }
6083
6084 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
6085 let start = self.sample_text_name_id_byte_range().end;
6086 let end = start + u16::RAW_BYTE_LEN;
6087 start..end
6088 }
6089
6090 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
6091 let start = self.num_named_parameters_byte_range().end;
6092 let end = start + NameId::RAW_BYTE_LEN;
6093 start..end
6094 }
6095
6096 pub fn char_count_byte_range(&self) -> Range<usize> {
6097 let start = self.first_param_ui_label_name_id_byte_range().end;
6098 let end = start + u16::RAW_BYTE_LEN;
6099 start..end
6100 }
6101
6102 pub fn character_byte_range(&self) -> Range<usize> {
6103 let char_count = self.char_count();
6104 let start = self.char_count_byte_range().end;
6105 let end = start + (transforms::to_usize(char_count)).saturating_mul(Uint24::RAW_BYTE_LEN);
6106 start..end
6107 }
6108}
6109
6110const _: () = assert!(FontData::default_data_long_enough(
6111 CharacterVariantParams::MIN_SIZE
6112));
6113
6114impl Default for CharacterVariantParams<'_> {
6115 fn default() -> Self {
6116 Self {
6117 data: FontData::default_table_data(),
6118 }
6119 }
6120}
6121
6122#[cfg(feature = "experimental_traverse")]
6123impl<'a> SomeTable<'a> for CharacterVariantParams<'a> {
6124 fn type_name(&self) -> &str {
6125 "CharacterVariantParams"
6126 }
6127 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
6128 match idx {
6129 0usize => Some(Field::new("format", self.format())),
6130 1usize => Some(Field::new(
6131 "feat_ui_label_name_id",
6132 self.feat_ui_label_name_id(),
6133 )),
6134 2usize => Some(Field::new(
6135 "feat_ui_tooltip_text_name_id",
6136 self.feat_ui_tooltip_text_name_id(),
6137 )),
6138 3usize => Some(Field::new(
6139 "sample_text_name_id",
6140 self.sample_text_name_id(),
6141 )),
6142 4usize => Some(Field::new(
6143 "num_named_parameters",
6144 self.num_named_parameters(),
6145 )),
6146 5usize => Some(Field::new(
6147 "first_param_ui_label_name_id",
6148 self.first_param_ui_label_name_id(),
6149 )),
6150 6usize => Some(Field::new("char_count", self.char_count())),
6151 7usize => Some(Field::new("character", self.character())),
6152 _ => None,
6153 }
6154 }
6155}
6156
6157#[cfg(feature = "experimental_traverse")]
6158#[allow(clippy::needless_lifetimes)]
6159impl<'a> std::fmt::Debug for CharacterVariantParams<'a> {
6160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6161 (self as &dyn SomeTable<'a>).fmt(f)
6162 }
6163}