Skip to main content

read_fonts/generated/
generated_gvar.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gvar<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.glyph_variation_data_offsets_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 Gvar<'_> {
19    /// `gvar`
20    const TAG: Tag = Tag::new(b"gvar");
21}
22
23impl<'a> FontRead<'a> for Gvar<'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/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header)
34#[derive(Clone)]
35pub struct Gvar<'a> {
36    data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Gvar<'a> {
41    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
42        + u16::RAW_BYTE_LEN
43        + u16::RAW_BYTE_LEN
44        + Offset32::RAW_BYTE_LEN
45        + u16::RAW_BYTE_LEN
46        + GvarFlags::RAW_BYTE_LEN
47        + u32::RAW_BYTE_LEN);
48    basic_table_impls!(impl_the_methods);
49
50    /// Major/minor version number of the glyph variations table — set to (1,0).
51    pub fn version(&self) -> MajorMinor {
52        let range = self.version_byte_range();
53        self.data.read_at(range.start).ok().unwrap()
54    }
55
56    /// The number of variation axes for this font. This must be the
57    /// same number as axisCount in the 'fvar' table.
58    pub fn axis_count(&self) -> u16 {
59        let range = self.axis_count_byte_range();
60        self.data.read_at(range.start).ok().unwrap()
61    }
62
63    /// The number of shared tuple records. Shared tuple records can be
64    /// referenced within glyph variation data tables for multiple
65    /// glyphs, as opposed to other tuple records stored directly
66    /// within a glyph variation data table.
67    pub fn shared_tuple_count(&self) -> u16 {
68        let range = self.shared_tuple_count_byte_range();
69        self.data.read_at(range.start).ok().unwrap()
70    }
71
72    /// Offset from the start of this table to the shared tuple records.
73    pub fn shared_tuples_offset(&self) -> Offset32 {
74        let range = self.shared_tuples_offset_byte_range();
75        self.data.read_at(range.start).ok().unwrap()
76    }
77
78    /// Attempt to resolve [`shared_tuples_offset`][Self::shared_tuples_offset].
79    pub fn shared_tuples(&self) -> Result<SharedTuples<'a>, ReadError> {
80        let data = self.data;
81        let args = (self.shared_tuple_count(), self.axis_count());
82        self.shared_tuples_offset().resolve_with_args(data, &args)
83    }
84
85    /// The number of glyphs in this font. This must match the number
86    /// of glyphs stored elsewhere in the font.
87    pub fn glyph_count(&self) -> u16 {
88        let range = self.glyph_count_byte_range();
89        self.data.read_at(range.start).ok().unwrap()
90    }
91
92    /// Bit-field that gives the format of the offset array that
93    /// follows. If bit 0 is clear, the offsets are uint16; if bit 0 is
94    /// set, the offsets are uint32.
95    pub fn flags(&self) -> GvarFlags {
96        let range = self.flags_byte_range();
97        self.data.read_at(range.start).ok().unwrap()
98    }
99
100    /// Offset from the start of this table to the array of
101    /// GlyphVariationData tables.
102    pub fn glyph_variation_data_array_offset(&self) -> u32 {
103        let range = self.glyph_variation_data_array_offset_byte_range();
104        self.data.read_at(range.start).ok().unwrap()
105    }
106
107    /// Offsets from the start of the GlyphVariationData array to each
108    /// GlyphVariationData table.
109    pub fn glyph_variation_data_offsets(&self) -> ComputedArray<'a, U16Or32> {
110        let range = self.glyph_variation_data_offsets_byte_range();
111        self.data
112            .read_with_args(range, &self.flags())
113            .unwrap_or_default()
114    }
115
116    pub fn version_byte_range(&self) -> Range<usize> {
117        let start = 0;
118        start..start + MajorMinor::RAW_BYTE_LEN
119    }
120
121    pub fn axis_count_byte_range(&self) -> Range<usize> {
122        let start = self.version_byte_range().end;
123        start..start + u16::RAW_BYTE_LEN
124    }
125
126    pub fn shared_tuple_count_byte_range(&self) -> Range<usize> {
127        let start = self.axis_count_byte_range().end;
128        start..start + u16::RAW_BYTE_LEN
129    }
130
131    pub fn shared_tuples_offset_byte_range(&self) -> Range<usize> {
132        let start = self.shared_tuple_count_byte_range().end;
133        start..start + Offset32::RAW_BYTE_LEN
134    }
135
136    pub fn glyph_count_byte_range(&self) -> Range<usize> {
137        let start = self.shared_tuples_offset_byte_range().end;
138        start..start + u16::RAW_BYTE_LEN
139    }
140
141    pub fn flags_byte_range(&self) -> Range<usize> {
142        let start = self.glyph_count_byte_range().end;
143        start..start + GvarFlags::RAW_BYTE_LEN
144    }
145
146    pub fn glyph_variation_data_array_offset_byte_range(&self) -> Range<usize> {
147        let start = self.flags_byte_range().end;
148        start..start + u32::RAW_BYTE_LEN
149    }
150
151    pub fn glyph_variation_data_offsets_byte_range(&self) -> Range<usize> {
152        let glyph_count = self.glyph_count();
153        let start = self.glyph_variation_data_array_offset_byte_range().end;
154        start
155            ..start
156                + (transforms::add(glyph_count, 1_usize)).saturating_mul(
157                    <U16Or32 as ComputeSize>::compute_size(&self.flags()).unwrap_or(0),
158                )
159    }
160}
161
162#[cfg(feature = "experimental_traverse")]
163impl<'a> SomeTable<'a> for Gvar<'a> {
164    fn type_name(&self) -> &str {
165        "Gvar"
166    }
167    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
168        match idx {
169            0usize => Some(Field::new("version", self.version())),
170            1usize => Some(Field::new("axis_count", self.axis_count())),
171            2usize => Some(Field::new("shared_tuple_count", self.shared_tuple_count())),
172            3usize => Some(Field::new(
173                "shared_tuples_offset",
174                FieldType::offset(self.shared_tuples_offset(), self.shared_tuples()),
175            )),
176            4usize => Some(Field::new("glyph_count", self.glyph_count())),
177            5usize => Some(Field::new("flags", self.flags())),
178            6usize => Some(Field::new(
179                "glyph_variation_data_array_offset",
180                self.glyph_variation_data_array_offset(),
181            )),
182            7usize => Some(Field::new(
183                "glyph_variation_data_offsets",
184                traversal::FieldType::Unknown,
185            )),
186            _ => None,
187        }
188    }
189}
190
191#[cfg(feature = "experimental_traverse")]
192#[allow(clippy::needless_lifetimes)]
193impl<'a> std::fmt::Debug for Gvar<'a> {
194    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195        (self as &dyn SomeTable<'a>).fmt(f)
196    }
197}
198
199#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
200#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
201#[repr(transparent)]
202pub struct GvarFlags {
203    bits: u16,
204}
205
206impl GvarFlags {
207    /// If set, offsets to GlyphVariationData are 32 bits
208    pub const LONG_OFFSETS: Self = Self { bits: 1 };
209}
210
211impl GvarFlags {
212    ///  Returns an empty set of flags.
213    #[inline]
214    pub const fn empty() -> Self {
215        Self { bits: 0 }
216    }
217
218    /// Returns the set containing all flags.
219    #[inline]
220    pub const fn all() -> Self {
221        Self {
222            bits: Self::LONG_OFFSETS.bits,
223        }
224    }
225
226    /// Returns the raw value of the flags currently stored.
227    #[inline]
228    pub const fn bits(&self) -> u16 {
229        self.bits
230    }
231
232    /// Convert from underlying bit representation, unless that
233    /// representation contains bits that do not correspond to a flag.
234    #[inline]
235    pub const fn from_bits(bits: u16) -> Option<Self> {
236        if (bits & !Self::all().bits()) == 0 {
237            Some(Self { bits })
238        } else {
239            None
240        }
241    }
242
243    /// Convert from underlying bit representation, dropping any bits
244    /// that do not correspond to flags.
245    #[inline]
246    pub const fn from_bits_truncate(bits: u16) -> Self {
247        Self {
248            bits: bits & Self::all().bits,
249        }
250    }
251
252    /// Returns `true` if no flags are currently stored.
253    #[inline]
254    pub const fn is_empty(&self) -> bool {
255        self.bits() == Self::empty().bits()
256    }
257
258    /// Returns `true` if there are flags common to both `self` and `other`.
259    #[inline]
260    pub const fn intersects(&self, other: Self) -> bool {
261        !(Self {
262            bits: self.bits & other.bits,
263        })
264        .is_empty()
265    }
266
267    /// Returns `true` if all of the flags in `other` are contained within `self`.
268    #[inline]
269    pub const fn contains(&self, other: Self) -> bool {
270        (self.bits & other.bits) == other.bits
271    }
272
273    /// Inserts the specified flags in-place.
274    #[inline]
275    pub fn insert(&mut self, other: Self) {
276        self.bits |= other.bits;
277    }
278
279    /// Removes the specified flags in-place.
280    #[inline]
281    pub fn remove(&mut self, other: Self) {
282        self.bits &= !other.bits;
283    }
284
285    /// Toggles the specified flags in-place.
286    #[inline]
287    pub fn toggle(&mut self, other: Self) {
288        self.bits ^= other.bits;
289    }
290
291    /// Returns the intersection between the flags in `self` and
292    /// `other`.
293    ///
294    /// Specifically, the returned set contains only the flags which are
295    /// present in *both* `self` *and* `other`.
296    ///
297    /// This is equivalent to using the `&` operator (e.g.
298    /// [`ops::BitAnd`]), as in `flags & other`.
299    ///
300    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
301    #[inline]
302    #[must_use]
303    pub const fn intersection(self, other: Self) -> Self {
304        Self {
305            bits: self.bits & other.bits,
306        }
307    }
308
309    /// Returns the union of between the flags in `self` and `other`.
310    ///
311    /// Specifically, the returned set contains all flags which are
312    /// present in *either* `self` *or* `other`, including any which are
313    /// present in both.
314    ///
315    /// This is equivalent to using the `|` operator (e.g.
316    /// [`ops::BitOr`]), as in `flags | other`.
317    ///
318    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
319    #[inline]
320    #[must_use]
321    pub const fn union(self, other: Self) -> Self {
322        Self {
323            bits: self.bits | other.bits,
324        }
325    }
326
327    /// Returns the difference between the flags in `self` and `other`.
328    ///
329    /// Specifically, the returned set contains all flags present in
330    /// `self`, except for the ones present in `other`.
331    ///
332    /// It is also conceptually equivalent to the "bit-clear" operation:
333    /// `flags & !other` (and this syntax is also supported).
334    ///
335    /// This is equivalent to using the `-` operator (e.g.
336    /// [`ops::Sub`]), as in `flags - other`.
337    ///
338    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
339    #[inline]
340    #[must_use]
341    pub const fn difference(self, other: Self) -> Self {
342        Self {
343            bits: self.bits & !other.bits,
344        }
345    }
346}
347
348impl std::ops::BitOr for GvarFlags {
349    type Output = Self;
350
351    /// Returns the union of the two sets of flags.
352    #[inline]
353    fn bitor(self, other: GvarFlags) -> Self {
354        Self {
355            bits: self.bits | other.bits,
356        }
357    }
358}
359
360impl std::ops::BitOrAssign for GvarFlags {
361    /// Adds the set of flags.
362    #[inline]
363    fn bitor_assign(&mut self, other: Self) {
364        self.bits |= other.bits;
365    }
366}
367
368impl std::ops::BitXor for GvarFlags {
369    type Output = Self;
370
371    /// Returns the left flags, but with all the right flags toggled.
372    #[inline]
373    fn bitxor(self, other: Self) -> Self {
374        Self {
375            bits: self.bits ^ other.bits,
376        }
377    }
378}
379
380impl std::ops::BitXorAssign for GvarFlags {
381    /// Toggles the set of flags.
382    #[inline]
383    fn bitxor_assign(&mut self, other: Self) {
384        self.bits ^= other.bits;
385    }
386}
387
388impl std::ops::BitAnd for GvarFlags {
389    type Output = Self;
390
391    /// Returns the intersection between the two sets of flags.
392    #[inline]
393    fn bitand(self, other: Self) -> Self {
394        Self {
395            bits: self.bits & other.bits,
396        }
397    }
398}
399
400impl std::ops::BitAndAssign for GvarFlags {
401    /// Disables all flags disabled in the set.
402    #[inline]
403    fn bitand_assign(&mut self, other: Self) {
404        self.bits &= other.bits;
405    }
406}
407
408impl std::ops::Sub for GvarFlags {
409    type Output = Self;
410
411    /// Returns the set difference of the two sets of flags.
412    #[inline]
413    fn sub(self, other: Self) -> Self {
414        Self {
415            bits: self.bits & !other.bits,
416        }
417    }
418}
419
420impl std::ops::SubAssign for GvarFlags {
421    /// Disables all flags enabled in the set.
422    #[inline]
423    fn sub_assign(&mut self, other: Self) {
424        self.bits &= !other.bits;
425    }
426}
427
428impl std::ops::Not for GvarFlags {
429    type Output = Self;
430
431    /// Returns the complement of this set of flags.
432    #[inline]
433    fn not(self) -> Self {
434        Self { bits: !self.bits } & Self::all()
435    }
436}
437
438impl std::fmt::Debug for GvarFlags {
439    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
440        let members: &[(&str, Self)] = &[("LONG_OFFSETS", Self::LONG_OFFSETS)];
441        let mut first = true;
442        for (name, value) in members {
443            if self.contains(*value) {
444                if !first {
445                    f.write_str(" | ")?;
446                }
447                first = false;
448                f.write_str(name)?;
449            }
450        }
451        if first {
452            f.write_str("(empty)")?;
453        }
454        Ok(())
455    }
456}
457
458impl std::fmt::Binary for GvarFlags {
459    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
460        std::fmt::Binary::fmt(&self.bits, f)
461    }
462}
463
464impl std::fmt::Octal for GvarFlags {
465    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
466        std::fmt::Octal::fmt(&self.bits, f)
467    }
468}
469
470impl std::fmt::LowerHex for GvarFlags {
471    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
472        std::fmt::LowerHex::fmt(&self.bits, f)
473    }
474}
475
476impl std::fmt::UpperHex for GvarFlags {
477    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
478        std::fmt::UpperHex::fmt(&self.bits, f)
479    }
480}
481
482impl font_types::Scalar for GvarFlags {
483    type Raw = <u16 as font_types::Scalar>::Raw;
484    fn to_raw(self) -> Self::Raw {
485        self.bits().to_raw()
486    }
487    fn from_raw(raw: Self::Raw) -> Self {
488        let t = <u16>::from_raw(raw);
489        Self::from_bits_truncate(t)
490    }
491}
492
493#[cfg(feature = "experimental_traverse")]
494impl<'a> From<GvarFlags> for FieldType<'a> {
495    fn from(src: GvarFlags) -> FieldType<'a> {
496        src.bits().into()
497    }
498}
499
500impl<'a> MinByteRange<'a> for SharedTuples<'a> {
501    fn min_byte_range(&self) -> Range<usize> {
502        0..self.tuples_byte_range().end
503    }
504    fn min_table_bytes(&self) -> &'a [u8] {
505        let range = self.min_byte_range();
506        self.data.as_bytes().get(range).unwrap_or_default()
507    }
508}
509
510impl ReadArgs for SharedTuples<'_> {
511    type Args = (u16, u16);
512}
513
514impl<'a> FontReadWithArgs<'a> for SharedTuples<'a> {
515    fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
516        let (shared_tuple_count, axis_count) = *args;
517
518        #[allow(clippy::absurd_extreme_comparisons)]
519        if data.len() < Self::MIN_SIZE {
520            return Err(ReadError::OutOfBounds);
521        }
522        Ok(Self {
523            data,
524            shared_tuple_count,
525            axis_count,
526        })
527    }
528}
529
530impl<'a> SharedTuples<'a> {
531    /// A constructor that requires additional arguments.
532    ///
533    /// This type requires some external state in order to be
534    /// parsed.
535    pub fn read(
536        data: FontData<'a>,
537        shared_tuple_count: u16,
538        axis_count: u16,
539    ) -> Result<Self, ReadError> {
540        let args = (shared_tuple_count, axis_count);
541        Self::read_with_args(data, &args)
542    }
543}
544
545/// Array of tuple records shared across all glyph variation data tables.
546#[derive(Clone)]
547pub struct SharedTuples<'a> {
548    data: FontData<'a>,
549    shared_tuple_count: u16,
550    axis_count: u16,
551}
552
553#[allow(clippy::needless_lifetimes)]
554impl<'a> SharedTuples<'a> {
555    pub const MIN_SIZE: usize = 0;
556    basic_table_impls!(impl_the_methods);
557
558    pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> {
559        let range = self.tuples_byte_range();
560        self.data
561            .read_with_args(range, &self.axis_count())
562            .unwrap_or_default()
563    }
564
565    pub(crate) fn shared_tuple_count(&self) -> u16 {
566        self.shared_tuple_count
567    }
568
569    pub(crate) fn axis_count(&self) -> u16 {
570        self.axis_count
571    }
572
573    pub fn tuples_byte_range(&self) -> Range<usize> {
574        let shared_tuple_count = self.shared_tuple_count();
575        let start = 0;
576        start
577            ..start
578                + (shared_tuple_count as usize).saturating_mul(
579                    <Tuple as ComputeSize>::compute_size(&self.axis_count()).unwrap_or(0),
580                )
581    }
582}
583
584#[cfg(feature = "experimental_traverse")]
585impl<'a> SomeTable<'a> for SharedTuples<'a> {
586    fn type_name(&self) -> &str {
587        "SharedTuples"
588    }
589    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
590        match idx {
591            0usize => Some(Field::new(
592                "tuples",
593                traversal::FieldType::computed_array("Tuple", self.tuples(), self.offset_data()),
594            )),
595            _ => None,
596        }
597    }
598}
599
600#[cfg(feature = "experimental_traverse")]
601#[allow(clippy::needless_lifetimes)]
602impl<'a> std::fmt::Debug for SharedTuples<'a> {
603    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
604        (self as &dyn SomeTable<'a>).fmt(f)
605    }
606}
607
608impl<'a> MinByteRange<'a> for GlyphVariationDataHeader<'a> {
609    fn min_byte_range(&self) -> Range<usize> {
610        0..self.tuple_variation_headers_byte_range().end
611    }
612    fn min_table_bytes(&self) -> &'a [u8] {
613        let range = self.min_byte_range();
614        self.data.as_bytes().get(range).unwrap_or_default()
615    }
616}
617
618impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> {
619    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
620        #[allow(clippy::absurd_extreme_comparisons)]
621        if data.len() < Self::MIN_SIZE {
622            return Err(ReadError::OutOfBounds);
623        }
624        Ok(Self { data })
625    }
626}
627
628/// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table
629#[derive(Clone)]
630pub struct GlyphVariationDataHeader<'a> {
631    data: FontData<'a>,
632}
633
634#[allow(clippy::needless_lifetimes)]
635impl<'a> GlyphVariationDataHeader<'a> {
636    pub const MIN_SIZE: usize = (TupleVariationCount::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
637    basic_table_impls!(impl_the_methods);
638
639    /// A packed field. The high 4 bits are flags, and the low 12 bits
640    /// are the number of tuple variation tables for this glyph. The
641    /// number of tuple variation tables can be any number between 1
642    /// and 4095.
643    pub fn tuple_variation_count(&self) -> TupleVariationCount {
644        let range = self.tuple_variation_count_byte_range();
645        self.data.read_at(range.start).ok().unwrap()
646    }
647
648    /// Offset from the start of the GlyphVariationData table to the
649    /// serialized data
650    pub fn serialized_data_offset(&self) -> Offset16 {
651        let range = self.serialized_data_offset_byte_range();
652        self.data.read_at(range.start).ok().unwrap()
653    }
654
655    /// Attempt to resolve [`serialized_data_offset`][Self::serialized_data_offset].
656    pub fn serialized_data(&self) -> Result<FontData<'a>, ReadError> {
657        let data = self.data;
658        self.serialized_data_offset().resolve(data)
659    }
660
661    /// Array of tuple variation headers.
662    pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> {
663        let range = self.tuple_variation_headers_byte_range();
664        self.data
665            .split_off(range.start)
666            .and_then(|d| VarLenArray::read(d).ok())
667            .unwrap_or_default()
668    }
669
670    pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
671        let start = 0;
672        start..start + TupleVariationCount::RAW_BYTE_LEN
673    }
674
675    pub fn serialized_data_offset_byte_range(&self) -> Range<usize> {
676        let start = self.tuple_variation_count_byte_range().end;
677        start..start + Offset16::RAW_BYTE_LEN
678    }
679
680    pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
681        let start = self.serialized_data_offset_byte_range().end;
682        start..start + self.data.len().saturating_sub(start)
683    }
684}
685
686#[cfg(feature = "experimental_traverse")]
687impl<'a> SomeTable<'a> for GlyphVariationDataHeader<'a> {
688    fn type_name(&self) -> &str {
689        "GlyphVariationDataHeader"
690    }
691    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
692        match idx {
693            0usize => Some(Field::new(
694                "tuple_variation_count",
695                traversal::FieldType::Unknown,
696            )),
697            1usize => Some(Field::new(
698                "serialized_data_offset",
699                traversal::FieldType::Unknown,
700            )),
701            2usize => Some(Field::new(
702                "tuple_variation_headers",
703                traversal::FieldType::Unknown,
704            )),
705            _ => None,
706        }
707    }
708}
709
710#[cfg(feature = "experimental_traverse")]
711#[allow(clippy::needless_lifetimes)]
712impl<'a> std::fmt::Debug for GlyphVariationDataHeader<'a> {
713    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714        (self as &dyn SomeTable<'a>).fmt(f)
715    }
716}