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