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