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