Coverage Report

Created: 2026-10-24 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/read-fonts-0.46.0/generated/font.rs
Line
Count
Source
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)]
6
use crate::codegen_prelude::*;
7
8
impl<'a> MinByteRange<'a> for TableDirectory<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.table_records_byte_range().end
11
0
    }
12
0
    fn min_table_bytes(&self) -> &'a [u8] {
13
0
        let range = self.min_byte_range();
14
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
15
0
    }
16
}
17
18
impl ReadArgs for TableDirectory<'_> {
19
    type Args = ();
20
}
21
22
impl<'a> FontRead<'a> for TableDirectory<'a> {
23
77.4k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
24
        #[allow(clippy::absurd_extreme_comparisons)]
25
77.4k
        if data.len() < Self::MIN_SIZE {
26
240
            return Err(ReadError::OutOfBounds);
27
77.2k
        }
28
77.2k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
29
0
            return Err(ReadError::OutOfBounds);
30
        };
31
77.2k
        Ok(Self { data })
32
77.4k
    }
33
}
34
35
/// The fields at the start of the table, which are read directly.
36
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
37
#[repr(C, packed)]
38
#[doc(hidden)]
39
pub struct TableDirectoryFixedHeader {
40
    pub sfnt_version: BigEndian<u32>,
41
    pub num_tables: BigEndian<u16>,
42
    pub search_range: BigEndian<u16>,
43
    pub entry_selector: BigEndian<u16>,
44
    pub range_shift: BigEndian<u16>,
45
}
46
47
#[allow(clippy::absurd_extreme_comparisons)]
48
const _: () = assert!(std::mem::size_of::<TableDirectoryFixedHeader>() <= TableDirectory::MIN_SIZE);
49
50
/// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory)
51
#[derive(Clone)]
52
pub struct TableDirectory<'a> {
53
    data: TableDataRef<'a, TableDirectoryFixedHeader>,
54
}
55
56
#[allow(clippy::needless_lifetimes)]
57
impl<'a> TableDirectory<'a> {
58
    pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN
59
        + u16::RAW_BYTE_LEN
60
        + u16::RAW_BYTE_LEN
61
        + u16::RAW_BYTE_LEN
62
        + u16::RAW_BYTE_LEN);
63
    basic_table_impls!(impl_the_methods);
64
65
    /// 0x00010000 or 0x4F54544F
66
88.9k
    pub fn sfnt_version(&self) -> u32 {
67
88.9k
        self.data.header().sfnt_version.get()
68
88.9k
    }
69
70
    /// Number of tables.
71
164k
    pub fn num_tables(&self) -> u16 {
72
164k
        self.data.header().num_tables.get()
73
164k
    }
74
75
0
    pub fn search_range(&self) -> u16 {
76
0
        self.data.header().search_range.get()
77
0
    }
78
79
0
    pub fn entry_selector(&self) -> u16 {
80
0
        self.data.header().entry_selector.get()
81
0
    }
82
83
0
    pub fn range_shift(&self) -> u16 {
84
0
        self.data.header().range_shift.get()
85
0
    }
86
87
    /// Table records array—one for each top-level table in the font
88
164k
    pub fn table_records(&self) -> &'a [TableRecord] {
89
164k
        let range = self.table_records_byte_range();
90
164k
        self.offset_data()
91
164k
            .read_array(range)
92
164k
            .ok()
93
164k
            .unwrap_or_default()
94
164k
    }
95
96
164k
    pub fn sfnt_version_byte_range(&self) -> Range<usize> {
97
164k
        let start = 0;
98
164k
        let end = start + u32::RAW_BYTE_LEN;
99
164k
        start..end
100
164k
    }
101
102
164k
    pub fn num_tables_byte_range(&self) -> Range<usize> {
103
164k
        let start = self.sfnt_version_byte_range().end;
104
164k
        let end = start + u16::RAW_BYTE_LEN;
105
164k
        start..end
106
164k
    }
107
108
164k
    pub fn search_range_byte_range(&self) -> Range<usize> {
109
164k
        let start = self.num_tables_byte_range().end;
110
164k
        let end = start + u16::RAW_BYTE_LEN;
111
164k
        start..end
112
164k
    }
113
114
164k
    pub fn entry_selector_byte_range(&self) -> Range<usize> {
115
164k
        let start = self.search_range_byte_range().end;
116
164k
        let end = start + u16::RAW_BYTE_LEN;
117
164k
        start..end
118
164k
    }
119
120
164k
    pub fn range_shift_byte_range(&self) -> Range<usize> {
121
164k
        let start = self.entry_selector_byte_range().end;
122
164k
        let end = start + u16::RAW_BYTE_LEN;
123
164k
        start..end
124
164k
    }
125
126
164k
    pub fn table_records_byte_range(&self) -> Range<usize> {
127
164k
        let num_tables = self.num_tables();
128
164k
        let start = self.range_shift_byte_range().end;
129
164k
        let end =
130
164k
            start + (transforms::to_usize(num_tables)).saturating_mul(TableRecord::RAW_BYTE_LEN);
131
164k
        start..end
132
164k
    }
133
}
134
135
const _: () = assert!(FontData::default_data_long_enough(TableDirectory::MIN_SIZE));
136
137
impl Default for TableDirectory<'_> {
138
0
    fn default() -> Self {
139
        Self {
140
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
141
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
142
        }
143
0
    }
144
}
145
146
/// Record for a table in a font.
147
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
148
#[repr(C)]
149
#[repr(packed)]
150
pub struct TableRecord {
151
    /// Table identifier.
152
    pub tag: BigEndian<Tag>,
153
    /// Checksum for the table.
154
    pub checksum: BigEndian<u32>,
155
    /// Offset from the beginning of the font data.
156
    pub offset: BigEndian<u32>,
157
    /// Length of the table.
158
    pub length: BigEndian<u32>,
159
}
160
161
impl TableRecord {
162
    /// Table identifier.
163
7.14M
    pub fn tag(&self) -> Tag {
164
7.14M
        self.tag.get()
165
7.14M
    }
166
167
    /// Checksum for the table.
168
0
    pub fn checksum(&self) -> u32 {
169
0
        self.checksum.get()
170
0
    }
171
172
    /// Offset from the beginning of the font data.
173
55.4k
    pub fn offset(&self) -> u32 {
174
55.4k
        self.offset.get()
175
55.4k
    }
176
177
    /// Length of the table.
178
55.4k
    pub fn length(&self) -> u32 {
179
55.4k
        self.length.get()
180
55.4k
    }
181
}
182
183
impl FixedSize for TableRecord {
184
    const RAW_BYTE_LEN: usize =
185
        Tag::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
186
}
187
188
impl<'a> MinByteRange<'a> for TTCHeader<'a> {
189
0
    fn min_byte_range(&self) -> Range<usize> {
190
0
        0..self.table_directory_offsets_byte_range().end
191
0
    }
192
0
    fn min_table_bytes(&self) -> &'a [u8] {
193
0
        let range = self.min_byte_range();
194
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
195
0
    }
196
}
197
198
impl ReadArgs for TTCHeader<'_> {
199
    type Args = ();
200
}
201
202
impl<'a> FontRead<'a> for TTCHeader<'a> {
203
64.8k
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
204
        #[allow(clippy::absurd_extreme_comparisons)]
205
64.8k
        if data.len() < Self::MIN_SIZE {
206
29
            return Err(ReadError::OutOfBounds);
207
64.8k
        }
208
64.8k
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
209
0
            return Err(ReadError::OutOfBounds);
210
        };
211
64.8k
        Ok(Self { data })
212
64.8k
    }
213
}
214
215
/// The fields at the start of the table, which are read directly.
216
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
217
#[repr(C, packed)]
218
#[doc(hidden)]
219
pub struct TTCHeaderFixedHeader {
220
    pub ttc_tag: BigEndian<Tag>,
221
    pub version: BigEndian<MajorMinor>,
222
    pub num_fonts: BigEndian<u32>,
223
}
224
225
#[allow(clippy::absurd_extreme_comparisons)]
226
const _: () = assert!(std::mem::size_of::<TTCHeaderFixedHeader>() <= TTCHeader::MIN_SIZE);
227
228
/// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header)
229
#[derive(Clone)]
230
pub struct TTCHeader<'a> {
231
    data: TableDataRef<'a, TTCHeaderFixedHeader>,
232
}
233
234
#[allow(clippy::needless_lifetimes)]
235
impl<'a> TTCHeader<'a> {
236
    pub const MIN_SIZE: usize = (Tag::RAW_BYTE_LEN + MajorMinor::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
237
    basic_table_impls!(impl_the_methods);
238
239
    /// Font Collection ID string: \"ttcf\"
240
129k
    pub fn ttc_tag(&self) -> Tag {
241
129k
        self.data.header().ttc_tag.get()
242
129k
    }
243
244
    /// Major/minor version of the TTC Header
245
279
    pub fn version(&self) -> MajorMinor {
246
279
        self.data.header().version.get()
247
279
    }
248
249
    /// Number of fonts in TTC
250
279
    pub fn num_fonts(&self) -> u32 {
251
279
        self.data.header().num_fonts.get()
252
279
    }
253
254
    /// Array of offsets to the TableDirectory for each font from the beginning of the file
255
0
    pub fn table_directory_offsets(&self) -> &'a [BigEndian<u32>] {
256
0
        let range = self.table_directory_offsets_byte_range();
257
0
        self.offset_data()
258
0
            .read_array(range)
259
0
            .ok()
260
0
            .unwrap_or_default()
261
0
    }
262
263
    /// Tag indicating that a DSIG table exists, 0x44534947 ('DSIG') (null if no signature)
264
0
    pub fn dsig_tag(&self) -> Option<u32> {
265
0
        let range = self.dsig_tag_byte_range();
266
0
        (!range.is_empty())
267
0
            .then(|| self.offset_data().read_at(range.start).ok())
268
0
            .flatten()
269
0
    }
270
271
    /// The length (in bytes) of the DSIG table (null if no signature)
272
0
    pub fn dsig_length(&self) -> Option<u32> {
273
0
        let range = self.dsig_length_byte_range();
274
0
        (!range.is_empty())
275
0
            .then(|| self.offset_data().read_at(range.start).ok())
276
0
            .flatten()
277
0
    }
278
279
    /// The offset (in bytes) of the DSIG table from the beginning of the TTC file (null if no signature)
280
0
    pub fn dsig_offset(&self) -> Option<u32> {
281
0
        let range = self.dsig_offset_byte_range();
282
0
        (!range.is_empty())
283
0
            .then(|| self.offset_data().read_at(range.start).ok())
284
0
            .flatten()
285
0
    }
286
287
0
    pub fn ttc_tag_byte_range(&self) -> Range<usize> {
288
0
        let start = 0;
289
0
        let end = start + Tag::RAW_BYTE_LEN;
290
0
        start..end
291
0
    }
292
293
0
    pub fn version_byte_range(&self) -> Range<usize> {
294
0
        let start = self.ttc_tag_byte_range().end;
295
0
        let end = start + MajorMinor::RAW_BYTE_LEN;
296
0
        start..end
297
0
    }
298
299
0
    pub fn num_fonts_byte_range(&self) -> Range<usize> {
300
0
        let start = self.version_byte_range().end;
301
0
        let end = start + u32::RAW_BYTE_LEN;
302
0
        start..end
303
0
    }
304
305
0
    pub fn table_directory_offsets_byte_range(&self) -> Range<usize> {
306
0
        let num_fonts = self.num_fonts();
307
0
        let start = self.num_fonts_byte_range().end;
308
0
        let end = start + (transforms::to_usize(num_fonts)).saturating_mul(u32::RAW_BYTE_LEN);
309
0
        start..end
310
0
    }
311
312
0
    pub fn dsig_tag_byte_range(&self) -> Range<usize> {
313
0
        let start = self.table_directory_offsets_byte_range().end;
314
0
        let end = if self.version().compatible((2u16, 0u16)) {
315
0
            start + u32::RAW_BYTE_LEN
316
        } else {
317
0
            start
318
        };
319
0
        start..end
320
0
    }
321
322
0
    pub fn dsig_length_byte_range(&self) -> Range<usize> {
323
0
        let start = self.dsig_tag_byte_range().end;
324
0
        let end = if self.version().compatible((2u16, 0u16)) {
325
0
            start + u32::RAW_BYTE_LEN
326
        } else {
327
0
            start
328
        };
329
0
        start..end
330
0
    }
331
332
0
    pub fn dsig_offset_byte_range(&self) -> Range<usize> {
333
0
        let start = self.dsig_length_byte_range().end;
334
0
        let end = if self.version().compatible((2u16, 0u16)) {
335
0
            start + u32::RAW_BYTE_LEN
336
        } else {
337
0
            start
338
        };
339
0
        start..end
340
0
    }
341
}
342
343
const _: () = assert!(FontData::default_data_long_enough(TTCHeader::MIN_SIZE));
344
345
impl Default for TTCHeader<'_> {
346
0
    fn default() -> Self {
347
        Self {
348
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
349
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
350
        }
351
0
    }
352
}