1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Base<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.vert_axis_offset_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 TopLevelTable for Base<'_> {
19 const TAG: Tag = Tag::new(b"BASE");
21}
22
23impl ReadArgs for Base<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Base<'a> {
28 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29 #[allow(clippy::absurd_extreme_comparisons)]
30 if data.len() < Self::MIN_SIZE {
31 return Err(ReadError::OutOfBounds);
32 }
33 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
39pub struct Base<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Base<'a> {
45 pub const MIN_SIZE: usize =
46 (MajorMinor::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
47 basic_table_impls!(impl_the_methods);
48
49 pub fn version(&self) -> MajorMinor {
51 let range = self.version_byte_range();
52 self.data.read_at(range.start).ok().unwrap()
53 }
54
55 pub fn horiz_axis_offset(&self) -> Nullable<Offset16> {
57 let range = self.horiz_axis_offset_byte_range();
58 self.data.read_at(range.start).ok().unwrap()
59 }
60
61 pub fn horiz_axis(&self) -> Option<Result<Axis<'a>, ReadError>> {
63 let data = self.data;
64 self.horiz_axis_offset().resolve(data)
65 }
66
67 pub fn vert_axis_offset(&self) -> Nullable<Offset16> {
69 let range = self.vert_axis_offset_byte_range();
70 self.data.read_at(range.start).ok().unwrap()
71 }
72
73 pub fn vert_axis(&self) -> Option<Result<Axis<'a>, ReadError>> {
75 let data = self.data;
76 self.vert_axis_offset().resolve(data)
77 }
78
79 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
81 let range = self.item_var_store_offset_byte_range();
82 (!range.is_empty())
83 .then(|| self.data.read_at(range.start).ok())
84 .flatten()
85 }
86
87 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
89 let data = self.data;
90 self.item_var_store_offset().map(|x| x.resolve(data))?
91 }
92
93 pub fn version_byte_range(&self) -> Range<usize> {
94 let start = 0;
95 let end = start + MajorMinor::RAW_BYTE_LEN;
96 start..end
97 }
98
99 pub fn horiz_axis_offset_byte_range(&self) -> Range<usize> {
100 let start = self.version_byte_range().end;
101 let end = start + Offset16::RAW_BYTE_LEN;
102 start..end
103 }
104
105 pub fn vert_axis_offset_byte_range(&self) -> Range<usize> {
106 let start = self.horiz_axis_offset_byte_range().end;
107 let end = start + Offset16::RAW_BYTE_LEN;
108 start..end
109 }
110
111 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
112 let start = self.vert_axis_offset_byte_range().end;
113 let end = if self.version().compatible((1u16, 1u16)) {
114 start + Offset32::RAW_BYTE_LEN
115 } else {
116 start
117 };
118 start..end
119 }
120}
121
122const _: () = assert!(FontData::default_data_long_enough(Base::MIN_SIZE));
123
124impl Default for Base<'_> {
125 fn default() -> Self {
126 Self {
127 data: FontData::default_table_data(),
128 }
129 }
130}
131
132#[cfg(feature = "experimental_traverse")]
133impl<'a> SomeTable<'a> for Base<'a> {
134 fn type_name(&self) -> &str {
135 "Base"
136 }
137 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
138 match idx {
139 0usize => Some(Field::new("version", self.version())),
140 1usize => Some(Field::new(
141 "horiz_axis_offset",
142 FieldType::offset(self.horiz_axis_offset(), self.horiz_axis()),
143 )),
144 2usize => Some(Field::new(
145 "vert_axis_offset",
146 FieldType::offset(self.vert_axis_offset(), self.vert_axis()),
147 )),
148 3usize if self.version().compatible((1u16, 1u16)) => Some(Field::new(
149 "item_var_store_offset",
150 FieldType::offset(self.item_var_store_offset().unwrap(), self.item_var_store()),
151 )),
152 _ => None,
153 }
154 }
155}
156
157#[cfg(feature = "experimental_traverse")]
158#[allow(clippy::needless_lifetimes)]
159impl<'a> std::fmt::Debug for Base<'a> {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 (self as &dyn SomeTable<'a>).fmt(f)
162 }
163}
164
165impl<'a> MinByteRange<'a> for Axis<'a> {
166 fn min_byte_range(&self) -> Range<usize> {
167 0..self.base_script_list_offset_byte_range().end
168 }
169 fn min_table_bytes(&self) -> &'a [u8] {
170 let range = self.min_byte_range();
171 self.data.as_bytes().get(range).unwrap_or_default()
172 }
173}
174
175impl ReadArgs for Axis<'_> {
176 type Args = ();
177}
178
179impl<'a> FontRead<'a> for Axis<'a> {
180 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
181 #[allow(clippy::absurd_extreme_comparisons)]
182 if data.len() < Self::MIN_SIZE {
183 return Err(ReadError::OutOfBounds);
184 }
185 Ok(Self { data })
186 }
187}
188
189#[derive(Clone)]
191pub struct Axis<'a> {
192 data: FontData<'a>,
193}
194
195#[allow(clippy::needless_lifetimes)]
196impl<'a> Axis<'a> {
197 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
198 basic_table_impls!(impl_the_methods);
199
200 pub fn base_tag_list_offset(&self) -> Nullable<Offset16> {
203 let range = self.base_tag_list_offset_byte_range();
204 self.data.read_at(range.start).ok().unwrap()
205 }
206
207 pub fn base_tag_list(&self) -> Option<Result<BaseTagList<'a>, ReadError>> {
209 let data = self.data;
210 self.base_tag_list_offset().resolve(data)
211 }
212
213 pub fn base_script_list_offset(&self) -> Offset16 {
215 let range = self.base_script_list_offset_byte_range();
216 self.data.read_at(range.start).ok().unwrap()
217 }
218
219 pub fn base_script_list(&self) -> Result<BaseScriptList<'a>, ReadError> {
221 let data = self.data;
222 self.base_script_list_offset().resolve(data)
223 }
224
225 pub fn base_tag_list_offset_byte_range(&self) -> Range<usize> {
226 let start = 0;
227 let end = start + Offset16::RAW_BYTE_LEN;
228 start..end
229 }
230
231 pub fn base_script_list_offset_byte_range(&self) -> Range<usize> {
232 let start = self.base_tag_list_offset_byte_range().end;
233 let end = start + Offset16::RAW_BYTE_LEN;
234 start..end
235 }
236}
237
238const _: () = assert!(FontData::default_data_long_enough(Axis::MIN_SIZE));
239
240impl Default for Axis<'_> {
241 fn default() -> Self {
242 Self {
243 data: FontData::default_table_data(),
244 }
245 }
246}
247
248#[cfg(feature = "experimental_traverse")]
249impl<'a> SomeTable<'a> for Axis<'a> {
250 fn type_name(&self) -> &str {
251 "Axis"
252 }
253 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
254 match idx {
255 0usize => Some(Field::new(
256 "base_tag_list_offset",
257 FieldType::offset(self.base_tag_list_offset(), self.base_tag_list()),
258 )),
259 1usize => Some(Field::new(
260 "base_script_list_offset",
261 FieldType::offset(self.base_script_list_offset(), self.base_script_list()),
262 )),
263 _ => None,
264 }
265 }
266}
267
268#[cfg(feature = "experimental_traverse")]
269#[allow(clippy::needless_lifetimes)]
270impl<'a> std::fmt::Debug for Axis<'a> {
271 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272 (self as &dyn SomeTable<'a>).fmt(f)
273 }
274}
275
276impl<'a> MinByteRange<'a> for BaseTagList<'a> {
277 fn min_byte_range(&self) -> Range<usize> {
278 0..self.baseline_tags_byte_range().end
279 }
280 fn min_table_bytes(&self) -> &'a [u8] {
281 let range = self.min_byte_range();
282 self.data.as_bytes().get(range).unwrap_or_default()
283 }
284}
285
286impl ReadArgs for BaseTagList<'_> {
287 type Args = ();
288}
289
290impl<'a> FontRead<'a> for BaseTagList<'a> {
291 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
292 #[allow(clippy::absurd_extreme_comparisons)]
293 if data.len() < Self::MIN_SIZE {
294 return Err(ReadError::OutOfBounds);
295 }
296 Ok(Self { data })
297 }
298}
299
300#[derive(Clone)]
302pub struct BaseTagList<'a> {
303 data: FontData<'a>,
304}
305
306#[allow(clippy::needless_lifetimes)]
307impl<'a> BaseTagList<'a> {
308 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
309 basic_table_impls!(impl_the_methods);
310
311 pub fn base_tag_count(&self) -> u16 {
314 let range = self.base_tag_count_byte_range();
315 self.data.read_at(range.start).ok().unwrap()
316 }
317
318 pub fn baseline_tags(&self) -> &'a [BigEndian<Tag>] {
321 let range = self.baseline_tags_byte_range();
322 self.data.read_array(range).ok().unwrap_or_default()
323 }
324
325 pub fn base_tag_count_byte_range(&self) -> Range<usize> {
326 let start = 0;
327 let end = start + u16::RAW_BYTE_LEN;
328 start..end
329 }
330
331 pub fn baseline_tags_byte_range(&self) -> Range<usize> {
332 let base_tag_count = self.base_tag_count();
333 let start = self.base_tag_count_byte_range().end;
334 let end = start + (transforms::to_usize(base_tag_count)).saturating_mul(Tag::RAW_BYTE_LEN);
335 start..end
336 }
337}
338
339const _: () = assert!(FontData::default_data_long_enough(BaseTagList::MIN_SIZE));
340
341impl Default for BaseTagList<'_> {
342 fn default() -> Self {
343 Self {
344 data: FontData::default_table_data(),
345 }
346 }
347}
348
349#[cfg(feature = "experimental_traverse")]
350impl<'a> SomeTable<'a> for BaseTagList<'a> {
351 fn type_name(&self) -> &str {
352 "BaseTagList"
353 }
354 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
355 match idx {
356 0usize => Some(Field::new("base_tag_count", self.base_tag_count())),
357 1usize => Some(Field::new("baseline_tags", self.baseline_tags())),
358 _ => None,
359 }
360 }
361}
362
363#[cfg(feature = "experimental_traverse")]
364#[allow(clippy::needless_lifetimes)]
365impl<'a> std::fmt::Debug for BaseTagList<'a> {
366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367 (self as &dyn SomeTable<'a>).fmt(f)
368 }
369}
370
371impl<'a> MinByteRange<'a> for BaseScriptList<'a> {
372 fn min_byte_range(&self) -> Range<usize> {
373 0..self.base_script_records_byte_range().end
374 }
375 fn min_table_bytes(&self) -> &'a [u8] {
376 let range = self.min_byte_range();
377 self.data.as_bytes().get(range).unwrap_or_default()
378 }
379}
380
381impl ReadArgs for BaseScriptList<'_> {
382 type Args = ();
383}
384
385impl<'a> FontRead<'a> for BaseScriptList<'a> {
386 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
387 #[allow(clippy::absurd_extreme_comparisons)]
388 if data.len() < Self::MIN_SIZE {
389 return Err(ReadError::OutOfBounds);
390 }
391 Ok(Self { data })
392 }
393}
394
395#[derive(Clone)]
397pub struct BaseScriptList<'a> {
398 data: FontData<'a>,
399}
400
401#[allow(clippy::needless_lifetimes)]
402impl<'a> BaseScriptList<'a> {
403 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
404 basic_table_impls!(impl_the_methods);
405
406 pub fn base_script_count(&self) -> u16 {
408 let range = self.base_script_count_byte_range();
409 self.data.read_at(range.start).ok().unwrap()
410 }
411
412 pub fn base_script_records(&self) -> &'a [BaseScriptRecord] {
415 let range = self.base_script_records_byte_range();
416 self.data.read_array(range).ok().unwrap_or_default()
417 }
418
419 pub fn base_script_count_byte_range(&self) -> Range<usize> {
420 let start = 0;
421 let end = start + u16::RAW_BYTE_LEN;
422 start..end
423 }
424
425 pub fn base_script_records_byte_range(&self) -> Range<usize> {
426 let base_script_count = self.base_script_count();
427 let start = self.base_script_count_byte_range().end;
428 let end = start
429 + (transforms::to_usize(base_script_count))
430 .saturating_mul(BaseScriptRecord::RAW_BYTE_LEN);
431 start..end
432 }
433}
434
435const _: () = assert!(FontData::default_data_long_enough(BaseScriptList::MIN_SIZE));
436
437impl Default for BaseScriptList<'_> {
438 fn default() -> Self {
439 Self {
440 data: FontData::default_table_data(),
441 }
442 }
443}
444
445#[cfg(feature = "experimental_traverse")]
446impl<'a> SomeTable<'a> for BaseScriptList<'a> {
447 fn type_name(&self) -> &str {
448 "BaseScriptList"
449 }
450 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
451 match idx {
452 0usize => Some(Field::new("base_script_count", self.base_script_count())),
453 1usize => Some(Field::new(
454 "base_script_records",
455 traversal::FieldType::array_of_records(
456 stringify!(BaseScriptRecord),
457 self.base_script_records(),
458 self.offset_data(),
459 ),
460 )),
461 _ => None,
462 }
463 }
464}
465
466#[cfg(feature = "experimental_traverse")]
467#[allow(clippy::needless_lifetimes)]
468impl<'a> std::fmt::Debug for BaseScriptList<'a> {
469 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470 (self as &dyn SomeTable<'a>).fmt(f)
471 }
472}
473
474#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
476#[repr(C)]
477#[repr(packed)]
478pub struct BaseScriptRecord {
479 pub base_script_tag: BigEndian<Tag>,
481 pub base_script_offset: BigEndian<Offset16>,
483}
484
485impl BaseScriptRecord {
486 pub fn base_script_tag(&self) -> Tag {
488 self.base_script_tag.get()
489 }
490
491 pub fn base_script_offset(&self) -> Offset16 {
493 self.base_script_offset.get()
494 }
495
496 pub fn base_script<'a>(&self, data: FontData<'a>) -> Result<BaseScript<'a>, ReadError> {
501 self.base_script_offset().resolve(data)
502 }
503}
504
505impl FixedSize for BaseScriptRecord {
506 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
507}
508
509#[cfg(feature = "experimental_traverse")]
510impl<'a> SomeRecord<'a> for BaseScriptRecord {
511 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
512 RecordResolver {
513 name: "BaseScriptRecord",
514 get_field: Box::new(move |idx, _data| match idx {
515 0usize => Some(Field::new("base_script_tag", self.base_script_tag())),
516 1usize => Some(Field::new(
517 "base_script_offset",
518 FieldType::offset(self.base_script_offset(), self.base_script(_data)),
519 )),
520 _ => None,
521 }),
522 data,
523 }
524 }
525}
526
527impl<'a> MinByteRange<'a> for BaseScript<'a> {
528 fn min_byte_range(&self) -> Range<usize> {
529 0..self.base_lang_sys_records_byte_range().end
530 }
531 fn min_table_bytes(&self) -> &'a [u8] {
532 let range = self.min_byte_range();
533 self.data.as_bytes().get(range).unwrap_or_default()
534 }
535}
536
537impl ReadArgs for BaseScript<'_> {
538 type Args = ();
539}
540
541impl<'a> FontRead<'a> for BaseScript<'a> {
542 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
543 #[allow(clippy::absurd_extreme_comparisons)]
544 if data.len() < Self::MIN_SIZE {
545 return Err(ReadError::OutOfBounds);
546 }
547 Ok(Self { data })
548 }
549}
550
551#[derive(Clone)]
553pub struct BaseScript<'a> {
554 data: FontData<'a>,
555}
556
557#[allow(clippy::needless_lifetimes)]
558impl<'a> BaseScript<'a> {
559 pub const MIN_SIZE: usize =
560 (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
561 basic_table_impls!(impl_the_methods);
562
563 pub fn base_values_offset(&self) -> Nullable<Offset16> {
565 let range = self.base_values_offset_byte_range();
566 self.data.read_at(range.start).ok().unwrap()
567 }
568
569 pub fn base_values(&self) -> Option<Result<BaseValues<'a>, ReadError>> {
571 let data = self.data;
572 self.base_values_offset().resolve(data)
573 }
574
575 pub fn default_min_max_offset(&self) -> Nullable<Offset16> {
577 let range = self.default_min_max_offset_byte_range();
578 self.data.read_at(range.start).ok().unwrap()
579 }
580
581 pub fn default_min_max(&self) -> Option<Result<MinMax<'a>, ReadError>> {
583 let data = self.data;
584 self.default_min_max_offset().resolve(data)
585 }
586
587 pub fn base_lang_sys_count(&self) -> u16 {
589 let range = self.base_lang_sys_count_byte_range();
590 self.data.read_at(range.start).ok().unwrap()
591 }
592
593 pub fn base_lang_sys_records(&self) -> &'a [BaseLangSysRecord] {
596 let range = self.base_lang_sys_records_byte_range();
597 self.data.read_array(range).ok().unwrap_or_default()
598 }
599
600 pub fn base_values_offset_byte_range(&self) -> Range<usize> {
601 let start = 0;
602 let end = start + Offset16::RAW_BYTE_LEN;
603 start..end
604 }
605
606 pub fn default_min_max_offset_byte_range(&self) -> Range<usize> {
607 let start = self.base_values_offset_byte_range().end;
608 let end = start + Offset16::RAW_BYTE_LEN;
609 start..end
610 }
611
612 pub fn base_lang_sys_count_byte_range(&self) -> Range<usize> {
613 let start = self.default_min_max_offset_byte_range().end;
614 let end = start + u16::RAW_BYTE_LEN;
615 start..end
616 }
617
618 pub fn base_lang_sys_records_byte_range(&self) -> Range<usize> {
619 let base_lang_sys_count = self.base_lang_sys_count();
620 let start = self.base_lang_sys_count_byte_range().end;
621 let end = start
622 + (transforms::to_usize(base_lang_sys_count))
623 .saturating_mul(BaseLangSysRecord::RAW_BYTE_LEN);
624 start..end
625 }
626}
627
628const _: () = assert!(FontData::default_data_long_enough(BaseScript::MIN_SIZE));
629
630impl Default for BaseScript<'_> {
631 fn default() -> Self {
632 Self {
633 data: FontData::default_table_data(),
634 }
635 }
636}
637
638#[cfg(feature = "experimental_traverse")]
639impl<'a> SomeTable<'a> for BaseScript<'a> {
640 fn type_name(&self) -> &str {
641 "BaseScript"
642 }
643 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
644 match idx {
645 0usize => Some(Field::new(
646 "base_values_offset",
647 FieldType::offset(self.base_values_offset(), self.base_values()),
648 )),
649 1usize => Some(Field::new(
650 "default_min_max_offset",
651 FieldType::offset(self.default_min_max_offset(), self.default_min_max()),
652 )),
653 2usize => Some(Field::new(
654 "base_lang_sys_count",
655 self.base_lang_sys_count(),
656 )),
657 3usize => Some(Field::new(
658 "base_lang_sys_records",
659 traversal::FieldType::array_of_records(
660 stringify!(BaseLangSysRecord),
661 self.base_lang_sys_records(),
662 self.offset_data(),
663 ),
664 )),
665 _ => None,
666 }
667 }
668}
669
670#[cfg(feature = "experimental_traverse")]
671#[allow(clippy::needless_lifetimes)]
672impl<'a> std::fmt::Debug for BaseScript<'a> {
673 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
674 (self as &dyn SomeTable<'a>).fmt(f)
675 }
676}
677
678#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
680#[repr(C)]
681#[repr(packed)]
682pub struct BaseLangSysRecord {
683 pub base_lang_sys_tag: BigEndian<Tag>,
685 pub min_max_offset: BigEndian<Offset16>,
687}
688
689impl BaseLangSysRecord {
690 pub fn base_lang_sys_tag(&self) -> Tag {
692 self.base_lang_sys_tag.get()
693 }
694
695 pub fn min_max_offset(&self) -> Offset16 {
697 self.min_max_offset.get()
698 }
699
700 pub fn min_max<'a>(&self, data: FontData<'a>) -> Result<MinMax<'a>, ReadError> {
705 self.min_max_offset().resolve(data)
706 }
707}
708
709impl FixedSize for BaseLangSysRecord {
710 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
711}
712
713#[cfg(feature = "experimental_traverse")]
714impl<'a> SomeRecord<'a> for BaseLangSysRecord {
715 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
716 RecordResolver {
717 name: "BaseLangSysRecord",
718 get_field: Box::new(move |idx, _data| match idx {
719 0usize => Some(Field::new("base_lang_sys_tag", self.base_lang_sys_tag())),
720 1usize => Some(Field::new(
721 "min_max_offset",
722 FieldType::offset(self.min_max_offset(), self.min_max(_data)),
723 )),
724 _ => None,
725 }),
726 data,
727 }
728 }
729}
730
731impl<'a> MinByteRange<'a> for BaseValues<'a> {
732 fn min_byte_range(&self) -> Range<usize> {
733 0..self.base_coord_offsets_byte_range().end
734 }
735 fn min_table_bytes(&self) -> &'a [u8] {
736 let range = self.min_byte_range();
737 self.data.as_bytes().get(range).unwrap_or_default()
738 }
739}
740
741impl ReadArgs for BaseValues<'_> {
742 type Args = ();
743}
744
745impl<'a> FontRead<'a> for BaseValues<'a> {
746 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
747 #[allow(clippy::absurd_extreme_comparisons)]
748 if data.len() < Self::MIN_SIZE {
749 return Err(ReadError::OutOfBounds);
750 }
751 Ok(Self { data })
752 }
753}
754
755#[derive(Clone)]
757pub struct BaseValues<'a> {
758 data: FontData<'a>,
759}
760
761#[allow(clippy::needless_lifetimes)]
762impl<'a> BaseValues<'a> {
763 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
764 basic_table_impls!(impl_the_methods);
765
766 pub fn default_baseline_index(&self) -> u16 {
770 let range = self.default_baseline_index_byte_range();
771 self.data.read_at(range.start).ok().unwrap()
772 }
773
774 pub fn base_coord_count(&self) -> u16 {
777 let range = self.base_coord_count_byte_range();
778 self.data.read_at(range.start).ok().unwrap()
779 }
780
781 pub fn base_coord_offsets(&self) -> &'a [BigEndian<Offset16>] {
785 let range = self.base_coord_offsets_byte_range();
786 self.data.read_array(range).ok().unwrap_or_default()
787 }
788
789 pub fn base_coords(&self) -> ArrayOfOffsets<'a, BaseCoord<'a>, Offset16> {
791 let data = self.data;
792 let offsets = self.base_coord_offsets();
793 ArrayOfOffsets::new(offsets, data, ())
794 }
795
796 pub fn default_baseline_index_byte_range(&self) -> Range<usize> {
797 let start = 0;
798 let end = start + u16::RAW_BYTE_LEN;
799 start..end
800 }
801
802 pub fn base_coord_count_byte_range(&self) -> Range<usize> {
803 let start = self.default_baseline_index_byte_range().end;
804 let end = start + u16::RAW_BYTE_LEN;
805 start..end
806 }
807
808 pub fn base_coord_offsets_byte_range(&self) -> Range<usize> {
809 let base_coord_count = self.base_coord_count();
810 let start = self.base_coord_count_byte_range().end;
811 let end =
812 start + (transforms::to_usize(base_coord_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
813 start..end
814 }
815}
816
817const _: () = assert!(FontData::default_data_long_enough(BaseValues::MIN_SIZE));
818
819impl Default for BaseValues<'_> {
820 fn default() -> Self {
821 Self {
822 data: FontData::default_table_data(),
823 }
824 }
825}
826
827#[cfg(feature = "experimental_traverse")]
828impl<'a> SomeTable<'a> for BaseValues<'a> {
829 fn type_name(&self) -> &str {
830 "BaseValues"
831 }
832 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
833 match idx {
834 0usize => Some(Field::new(
835 "default_baseline_index",
836 self.default_baseline_index(),
837 )),
838 1usize => Some(Field::new("base_coord_count", self.base_coord_count())),
839 2usize => Some(Field::new(
840 "base_coord_offsets",
841 FieldType::from(self.base_coords()),
842 )),
843 _ => None,
844 }
845 }
846}
847
848#[cfg(feature = "experimental_traverse")]
849#[allow(clippy::needless_lifetimes)]
850impl<'a> std::fmt::Debug for BaseValues<'a> {
851 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
852 (self as &dyn SomeTable<'a>).fmt(f)
853 }
854}
855
856impl<'a> MinByteRange<'a> for MinMax<'a> {
857 fn min_byte_range(&self) -> Range<usize> {
858 0..self.feat_min_max_records_byte_range().end
859 }
860 fn min_table_bytes(&self) -> &'a [u8] {
861 let range = self.min_byte_range();
862 self.data.as_bytes().get(range).unwrap_or_default()
863 }
864}
865
866impl ReadArgs for MinMax<'_> {
867 type Args = ();
868}
869
870impl<'a> FontRead<'a> for MinMax<'a> {
871 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
872 #[allow(clippy::absurd_extreme_comparisons)]
873 if data.len() < Self::MIN_SIZE {
874 return Err(ReadError::OutOfBounds);
875 }
876 Ok(Self { data })
877 }
878}
879
880#[derive(Clone)]
882pub struct MinMax<'a> {
883 data: FontData<'a>,
884}
885
886#[allow(clippy::needless_lifetimes)]
887impl<'a> MinMax<'a> {
888 pub const MIN_SIZE: usize =
889 (Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
890 basic_table_impls!(impl_the_methods);
891
892 pub fn min_coord_offset(&self) -> Nullable<Offset16> {
895 let range = self.min_coord_offset_byte_range();
896 self.data.read_at(range.start).ok().unwrap()
897 }
898
899 pub fn min_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> {
901 let data = self.data;
902 self.min_coord_offset().resolve(data)
903 }
904
905 pub fn max_coord_offset(&self) -> Nullable<Offset16> {
908 let range = self.max_coord_offset_byte_range();
909 self.data.read_at(range.start).ok().unwrap()
910 }
911
912 pub fn max_coord(&self) -> Option<Result<BaseCoord<'a>, ReadError>> {
914 let data = self.data;
915 self.max_coord_offset().resolve(data)
916 }
917
918 pub fn feat_min_max_count(&self) -> u16 {
920 let range = self.feat_min_max_count_byte_range();
921 self.data.read_at(range.start).ok().unwrap()
922 }
923
924 pub fn feat_min_max_records(&self) -> &'a [FeatMinMaxRecord] {
927 let range = self.feat_min_max_records_byte_range();
928 self.data.read_array(range).ok().unwrap_or_default()
929 }
930
931 pub fn min_coord_offset_byte_range(&self) -> Range<usize> {
932 let start = 0;
933 let end = start + Offset16::RAW_BYTE_LEN;
934 start..end
935 }
936
937 pub fn max_coord_offset_byte_range(&self) -> Range<usize> {
938 let start = self.min_coord_offset_byte_range().end;
939 let end = start + Offset16::RAW_BYTE_LEN;
940 start..end
941 }
942
943 pub fn feat_min_max_count_byte_range(&self) -> Range<usize> {
944 let start = self.max_coord_offset_byte_range().end;
945 let end = start + u16::RAW_BYTE_LEN;
946 start..end
947 }
948
949 pub fn feat_min_max_records_byte_range(&self) -> Range<usize> {
950 let feat_min_max_count = self.feat_min_max_count();
951 let start = self.feat_min_max_count_byte_range().end;
952 let end = start
953 + (transforms::to_usize(feat_min_max_count))
954 .saturating_mul(FeatMinMaxRecord::RAW_BYTE_LEN);
955 start..end
956 }
957}
958
959const _: () = assert!(FontData::default_data_long_enough(MinMax::MIN_SIZE));
960
961impl Default for MinMax<'_> {
962 fn default() -> Self {
963 Self {
964 data: FontData::default_table_data(),
965 }
966 }
967}
968
969#[cfg(feature = "experimental_traverse")]
970impl<'a> SomeTable<'a> for MinMax<'a> {
971 fn type_name(&self) -> &str {
972 "MinMax"
973 }
974 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
975 match idx {
976 0usize => Some(Field::new(
977 "min_coord_offset",
978 FieldType::offset(self.min_coord_offset(), self.min_coord()),
979 )),
980 1usize => Some(Field::new(
981 "max_coord_offset",
982 FieldType::offset(self.max_coord_offset(), self.max_coord()),
983 )),
984 2usize => Some(Field::new("feat_min_max_count", self.feat_min_max_count())),
985 3usize => Some(Field::new(
986 "feat_min_max_records",
987 traversal::FieldType::array_of_records(
988 stringify!(FeatMinMaxRecord),
989 self.feat_min_max_records(),
990 self.offset_data(),
991 ),
992 )),
993 _ => None,
994 }
995 }
996}
997
998#[cfg(feature = "experimental_traverse")]
999#[allow(clippy::needless_lifetimes)]
1000impl<'a> std::fmt::Debug for MinMax<'a> {
1001 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1002 (self as &dyn SomeTable<'a>).fmt(f)
1003 }
1004}
1005
1006#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1008#[repr(C)]
1009#[repr(packed)]
1010pub struct FeatMinMaxRecord {
1011 pub feature_table_tag: BigEndian<Tag>,
1014 pub min_coord_offset: BigEndian<Nullable<Offset16>>,
1017 pub max_coord_offset: BigEndian<Nullable<Offset16>>,
1020}
1021
1022impl FeatMinMaxRecord {
1023 pub fn feature_table_tag(&self) -> Tag {
1026 self.feature_table_tag.get()
1027 }
1028
1029 pub fn min_coord_offset(&self) -> Nullable<Offset16> {
1032 self.min_coord_offset.get()
1033 }
1034
1035 pub fn min_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> {
1041 self.min_coord_offset().resolve(data)
1042 }
1043
1044 pub fn max_coord_offset(&self) -> Nullable<Offset16> {
1047 self.max_coord_offset.get()
1048 }
1049
1050 pub fn max_coord<'a>(&self, data: FontData<'a>) -> Option<Result<BaseCoord<'a>, ReadError>> {
1056 self.max_coord_offset().resolve(data)
1057 }
1058}
1059
1060impl FixedSize for FeatMinMaxRecord {
1061 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
1062}
1063
1064#[cfg(feature = "experimental_traverse")]
1065impl<'a> SomeRecord<'a> for FeatMinMaxRecord {
1066 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1067 RecordResolver {
1068 name: "FeatMinMaxRecord",
1069 get_field: Box::new(move |idx, _data| match idx {
1070 0usize => Some(Field::new("feature_table_tag", self.feature_table_tag())),
1071 1usize => Some(Field::new(
1072 "min_coord_offset",
1073 FieldType::offset(self.min_coord_offset(), self.min_coord(_data)),
1074 )),
1075 2usize => Some(Field::new(
1076 "max_coord_offset",
1077 FieldType::offset(self.max_coord_offset(), self.max_coord(_data)),
1078 )),
1079 _ => None,
1080 }),
1081 data,
1082 }
1083 }
1084}
1085
1086#[derive(Clone)]
1087pub enum BaseCoord<'a> {
1088 Format1(BaseCoordFormat1<'a>),
1089 Format2(BaseCoordFormat2<'a>),
1090 Format3(BaseCoordFormat3<'a>),
1091}
1092
1093impl Default for BaseCoord<'_> {
1094 fn default() -> Self {
1095 Self::Format1(Default::default())
1096 }
1097}
1098
1099impl<'a> BaseCoord<'a> {
1100 pub fn offset_data(&self) -> FontData<'a> {
1102 match self {
1103 Self::Format1(item) => item.offset_data(),
1104 Self::Format2(item) => item.offset_data(),
1105 Self::Format3(item) => item.offset_data(),
1106 }
1107 }
1108
1109 pub fn base_coord_format(&self) -> u16 {
1111 match self {
1112 Self::Format1(item) => item.base_coord_format(),
1113 Self::Format2(item) => item.base_coord_format(),
1114 Self::Format3(item) => item.base_coord_format(),
1115 }
1116 }
1117
1118 pub fn coordinate(&self) -> i16 {
1120 match self {
1121 Self::Format1(item) => item.coordinate(),
1122 Self::Format2(item) => item.coordinate(),
1123 Self::Format3(item) => item.coordinate(),
1124 }
1125 }
1126}
1127
1128impl ReadArgs for BaseCoord<'_> {
1129 type Args = ();
1130}
1131
1132impl<'a> FontRead<'a> for BaseCoord<'a> {
1133 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1134 let format: u16 = data.read_at(0usize)?;
1135 match format {
1136 BaseCoordFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1137 BaseCoordFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1138 BaseCoordFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
1139 other => Err(ReadError::InvalidFormat(other.into())),
1140 }
1141 }
1142}
1143
1144impl<'a> MinByteRange<'a> for BaseCoord<'a> {
1145 fn min_byte_range(&self) -> Range<usize> {
1146 match self {
1147 Self::Format1(item) => item.min_byte_range(),
1148 Self::Format2(item) => item.min_byte_range(),
1149 Self::Format3(item) => item.min_byte_range(),
1150 }
1151 }
1152 fn min_table_bytes(&self) -> &'a [u8] {
1153 match self {
1154 Self::Format1(item) => item.min_table_bytes(),
1155 Self::Format2(item) => item.min_table_bytes(),
1156 Self::Format3(item) => item.min_table_bytes(),
1157 }
1158 }
1159}
1160
1161#[cfg(feature = "experimental_traverse")]
1162impl<'a> BaseCoord<'a> {
1163 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1164 match self {
1165 Self::Format1(table) => table,
1166 Self::Format2(table) => table,
1167 Self::Format3(table) => table,
1168 }
1169 }
1170}
1171
1172#[cfg(feature = "experimental_traverse")]
1173impl std::fmt::Debug for BaseCoord<'_> {
1174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1175 self.dyn_inner().fmt(f)
1176 }
1177}
1178
1179#[cfg(feature = "experimental_traverse")]
1180impl<'a> SomeTable<'a> for BaseCoord<'a> {
1181 fn type_name(&self) -> &str {
1182 self.dyn_inner().type_name()
1183 }
1184 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1185 self.dyn_inner().get_field(idx)
1186 }
1187}
1188
1189impl Format<u16> for BaseCoordFormat1<'_> {
1190 const FORMAT: u16 = 1;
1191}
1192
1193impl<'a> MinByteRange<'a> for BaseCoordFormat1<'a> {
1194 fn min_byte_range(&self) -> Range<usize> {
1195 0..self.coordinate_byte_range().end
1196 }
1197 fn min_table_bytes(&self) -> &'a [u8] {
1198 let range = self.min_byte_range();
1199 self.data.as_bytes().get(range).unwrap_or_default()
1200 }
1201}
1202
1203impl ReadArgs for BaseCoordFormat1<'_> {
1204 type Args = ();
1205}
1206
1207impl<'a> FontRead<'a> for BaseCoordFormat1<'a> {
1208 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1209 #[allow(clippy::absurd_extreme_comparisons)]
1210 if data.len() < Self::MIN_SIZE {
1211 return Err(ReadError::OutOfBounds);
1212 }
1213 Ok(Self { data })
1214 }
1215}
1216
1217#[derive(Clone)]
1219pub struct BaseCoordFormat1<'a> {
1220 data: FontData<'a>,
1221}
1222
1223#[allow(clippy::needless_lifetimes)]
1224impl<'a> BaseCoordFormat1<'a> {
1225 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
1226 basic_table_impls!(impl_the_methods);
1227
1228 pub fn base_coord_format(&self) -> u16 {
1230 let range = self.base_coord_format_byte_range();
1231 self.data.read_at(range.start).ok().unwrap()
1232 }
1233
1234 pub fn coordinate(&self) -> i16 {
1236 let range = self.coordinate_byte_range();
1237 self.data.read_at(range.start).ok().unwrap()
1238 }
1239
1240 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
1241 let start = 0;
1242 let end = start + u16::RAW_BYTE_LEN;
1243 start..end
1244 }
1245
1246 pub fn coordinate_byte_range(&self) -> Range<usize> {
1247 let start = self.base_coord_format_byte_range().end;
1248 let end = start + i16::RAW_BYTE_LEN;
1249 start..end
1250 }
1251}
1252
1253const _: () = assert!(FontData::default_data_long_enough(
1254 BaseCoordFormat1::MIN_SIZE
1255));
1256
1257impl Default for BaseCoordFormat1<'_> {
1258 fn default() -> Self {
1259 Self {
1260 data: FontData::default_format_1_u16_table_data(),
1261 }
1262 }
1263}
1264
1265#[cfg(feature = "experimental_traverse")]
1266impl<'a> SomeTable<'a> for BaseCoordFormat1<'a> {
1267 fn type_name(&self) -> &str {
1268 "BaseCoordFormat1"
1269 }
1270 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1271 match idx {
1272 0usize => Some(Field::new("base_coord_format", self.base_coord_format())),
1273 1usize => Some(Field::new("coordinate", self.coordinate())),
1274 _ => None,
1275 }
1276 }
1277}
1278
1279#[cfg(feature = "experimental_traverse")]
1280#[allow(clippy::needless_lifetimes)]
1281impl<'a> std::fmt::Debug for BaseCoordFormat1<'a> {
1282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1283 (self as &dyn SomeTable<'a>).fmt(f)
1284 }
1285}
1286
1287impl Format<u16> for BaseCoordFormat2<'_> {
1288 const FORMAT: u16 = 2;
1289}
1290
1291impl<'a> MinByteRange<'a> for BaseCoordFormat2<'a> {
1292 fn min_byte_range(&self) -> Range<usize> {
1293 0..self.base_coord_point_byte_range().end
1294 }
1295 fn min_table_bytes(&self) -> &'a [u8] {
1296 let range = self.min_byte_range();
1297 self.data.as_bytes().get(range).unwrap_or_default()
1298 }
1299}
1300
1301impl ReadArgs for BaseCoordFormat2<'_> {
1302 type Args = ();
1303}
1304
1305impl<'a> FontRead<'a> for BaseCoordFormat2<'a> {
1306 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1307 #[allow(clippy::absurd_extreme_comparisons)]
1308 if data.len() < Self::MIN_SIZE {
1309 return Err(ReadError::OutOfBounds);
1310 }
1311 Ok(Self { data })
1312 }
1313}
1314
1315#[derive(Clone)]
1317pub struct BaseCoordFormat2<'a> {
1318 data: FontData<'a>,
1319}
1320
1321#[allow(clippy::needless_lifetimes)]
1322impl<'a> BaseCoordFormat2<'a> {
1323 pub const MIN_SIZE: usize =
1324 (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1325 basic_table_impls!(impl_the_methods);
1326
1327 pub fn base_coord_format(&self) -> u16 {
1329 let range = self.base_coord_format_byte_range();
1330 self.data.read_at(range.start).ok().unwrap()
1331 }
1332
1333 pub fn coordinate(&self) -> i16 {
1335 let range = self.coordinate_byte_range();
1336 self.data.read_at(range.start).ok().unwrap()
1337 }
1338
1339 pub fn reference_glyph(&self) -> u16 {
1341 let range = self.reference_glyph_byte_range();
1342 self.data.read_at(range.start).ok().unwrap()
1343 }
1344
1345 pub fn base_coord_point(&self) -> u16 {
1347 let range = self.base_coord_point_byte_range();
1348 self.data.read_at(range.start).ok().unwrap()
1349 }
1350
1351 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
1352 let start = 0;
1353 let end = start + u16::RAW_BYTE_LEN;
1354 start..end
1355 }
1356
1357 pub fn coordinate_byte_range(&self) -> Range<usize> {
1358 let start = self.base_coord_format_byte_range().end;
1359 let end = start + i16::RAW_BYTE_LEN;
1360 start..end
1361 }
1362
1363 pub fn reference_glyph_byte_range(&self) -> Range<usize> {
1364 let start = self.coordinate_byte_range().end;
1365 let end = start + u16::RAW_BYTE_LEN;
1366 start..end
1367 }
1368
1369 pub fn base_coord_point_byte_range(&self) -> Range<usize> {
1370 let start = self.reference_glyph_byte_range().end;
1371 let end = start + u16::RAW_BYTE_LEN;
1372 start..end
1373 }
1374}
1375
1376#[cfg(feature = "experimental_traverse")]
1377impl<'a> SomeTable<'a> for BaseCoordFormat2<'a> {
1378 fn type_name(&self) -> &str {
1379 "BaseCoordFormat2"
1380 }
1381 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1382 match idx {
1383 0usize => Some(Field::new("base_coord_format", self.base_coord_format())),
1384 1usize => Some(Field::new("coordinate", self.coordinate())),
1385 2usize => Some(Field::new("reference_glyph", self.reference_glyph())),
1386 3usize => Some(Field::new("base_coord_point", self.base_coord_point())),
1387 _ => None,
1388 }
1389 }
1390}
1391
1392#[cfg(feature = "experimental_traverse")]
1393#[allow(clippy::needless_lifetimes)]
1394impl<'a> std::fmt::Debug for BaseCoordFormat2<'a> {
1395 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1396 (self as &dyn SomeTable<'a>).fmt(f)
1397 }
1398}
1399
1400impl Format<u16> for BaseCoordFormat3<'_> {
1401 const FORMAT: u16 = 3;
1402}
1403
1404impl<'a> MinByteRange<'a> for BaseCoordFormat3<'a> {
1405 fn min_byte_range(&self) -> Range<usize> {
1406 0..self.device_offset_byte_range().end
1407 }
1408 fn min_table_bytes(&self) -> &'a [u8] {
1409 let range = self.min_byte_range();
1410 self.data.as_bytes().get(range).unwrap_or_default()
1411 }
1412}
1413
1414impl ReadArgs for BaseCoordFormat3<'_> {
1415 type Args = ();
1416}
1417
1418impl<'a> FontRead<'a> for BaseCoordFormat3<'a> {
1419 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1420 #[allow(clippy::absurd_extreme_comparisons)]
1421 if data.len() < Self::MIN_SIZE {
1422 return Err(ReadError::OutOfBounds);
1423 }
1424 Ok(Self { data })
1425 }
1426}
1427
1428#[derive(Clone)]
1430pub struct BaseCoordFormat3<'a> {
1431 data: FontData<'a>,
1432}
1433
1434#[allow(clippy::needless_lifetimes)]
1435impl<'a> BaseCoordFormat3<'a> {
1436 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
1437 basic_table_impls!(impl_the_methods);
1438
1439 pub fn base_coord_format(&self) -> u16 {
1441 let range = self.base_coord_format_byte_range();
1442 self.data.read_at(range.start).ok().unwrap()
1443 }
1444
1445 pub fn coordinate(&self) -> i16 {
1447 let range = self.coordinate_byte_range();
1448 self.data.read_at(range.start).ok().unwrap()
1449 }
1450
1451 pub fn device_offset(&self) -> Nullable<Offset16> {
1455 let range = self.device_offset_byte_range();
1456 self.data.read_at(range.start).ok().unwrap()
1457 }
1458
1459 pub fn device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
1461 let data = self.data;
1462 self.device_offset().resolve(data)
1463 }
1464
1465 pub fn base_coord_format_byte_range(&self) -> Range<usize> {
1466 let start = 0;
1467 let end = start + u16::RAW_BYTE_LEN;
1468 start..end
1469 }
1470
1471 pub fn coordinate_byte_range(&self) -> Range<usize> {
1472 let start = self.base_coord_format_byte_range().end;
1473 let end = start + i16::RAW_BYTE_LEN;
1474 start..end
1475 }
1476
1477 pub fn device_offset_byte_range(&self) -> Range<usize> {
1478 let start = self.coordinate_byte_range().end;
1479 let end = start + Offset16::RAW_BYTE_LEN;
1480 start..end
1481 }
1482}
1483
1484#[cfg(feature = "experimental_traverse")]
1485impl<'a> SomeTable<'a> for BaseCoordFormat3<'a> {
1486 fn type_name(&self) -> &str {
1487 "BaseCoordFormat3"
1488 }
1489 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1490 match idx {
1491 0usize => Some(Field::new("base_coord_format", self.base_coord_format())),
1492 1usize => Some(Field::new("coordinate", self.coordinate())),
1493 2usize => Some(Field::new(
1494 "device_offset",
1495 FieldType::offset(self.device_offset(), self.device()),
1496 )),
1497 _ => None,
1498 }
1499 }
1500}
1501
1502#[cfg(feature = "experimental_traverse")]
1503#[allow(clippy::needless_lifetimes)]
1504impl<'a> std::fmt::Debug for BaseCoordFormat3<'a> {
1505 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1506 (self as &dyn SomeTable<'a>).fmt(f)
1507 }
1508}