1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for CffHeader<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.trailing_data_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl<'a> FontRead<'a> for CffHeader<'a> {
19 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
20 #[allow(clippy::absurd_extreme_comparisons)]
21 if data.len() < Self::MIN_SIZE {
22 return Err(ReadError::OutOfBounds);
23 }
24 Ok(Self { data })
25 }
26}
27
28#[derive(Clone)]
30pub struct CffHeader<'a> {
31 data: FontData<'a>,
32}
33
34#[allow(clippy::needless_lifetimes)]
35impl<'a> CffHeader<'a> {
36 pub const MIN_SIZE: usize =
37 (u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
38 basic_table_impls!(impl_the_methods);
39
40 pub fn major(&self) -> u8 {
42 let range = self.major_byte_range();
43 self.data.read_at(range.start).ok().unwrap()
44 }
45
46 pub fn minor(&self) -> u8 {
48 let range = self.minor_byte_range();
49 self.data.read_at(range.start).ok().unwrap()
50 }
51
52 pub fn hdr_size(&self) -> u8 {
54 let range = self.hdr_size_byte_range();
55 self.data.read_at(range.start).ok().unwrap()
56 }
57
58 pub fn off_size(&self) -> u8 {
60 let range = self.off_size_byte_range();
61 self.data.read_at(range.start).ok().unwrap()
62 }
63
64 pub fn _padding(&self) -> &'a [u8] {
66 let range = self._padding_byte_range();
67 self.data.read_array(range).ok().unwrap_or_default()
68 }
69
70 pub fn trailing_data(&self) -> &'a [u8] {
72 let range = self.trailing_data_byte_range();
73 self.data.read_array(range).ok().unwrap_or_default()
74 }
75
76 pub fn major_byte_range(&self) -> Range<usize> {
77 let start = 0;
78 start..start + u8::RAW_BYTE_LEN
79 }
80
81 pub fn minor_byte_range(&self) -> Range<usize> {
82 let start = self.major_byte_range().end;
83 start..start + u8::RAW_BYTE_LEN
84 }
85
86 pub fn hdr_size_byte_range(&self) -> Range<usize> {
87 let start = self.minor_byte_range().end;
88 start..start + u8::RAW_BYTE_LEN
89 }
90
91 pub fn off_size_byte_range(&self) -> Range<usize> {
92 let start = self.hdr_size_byte_range().end;
93 start..start + u8::RAW_BYTE_LEN
94 }
95
96 pub fn _padding_byte_range(&self) -> Range<usize> {
97 let hdr_size = self.hdr_size();
98 let start = self.off_size_byte_range().end;
99 start..start + (transforms::subtract(hdr_size, 4_usize)).saturating_mul(u8::RAW_BYTE_LEN)
100 }
101
102 pub fn trailing_data_byte_range(&self) -> Range<usize> {
103 let start = self._padding_byte_range().end;
104 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
105 }
106}
107
108#[cfg(feature = "experimental_traverse")]
109impl<'a> SomeTable<'a> for CffHeader<'a> {
110 fn type_name(&self) -> &str {
111 "CffHeader"
112 }
113 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
114 match idx {
115 0usize => Some(Field::new("major", self.major())),
116 1usize => Some(Field::new("minor", self.minor())),
117 2usize => Some(Field::new("hdr_size", self.hdr_size())),
118 3usize => Some(Field::new("off_size", self.off_size())),
119 4usize => Some(Field::new("_padding", self._padding())),
120 5usize => Some(Field::new("trailing_data", self.trailing_data())),
121 _ => None,
122 }
123 }
124}
125
126#[cfg(feature = "experimental_traverse")]
127#[allow(clippy::needless_lifetimes)]
128impl<'a> std::fmt::Debug for CffHeader<'a> {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 (self as &dyn SomeTable<'a>).fmt(f)
131 }
132}
133
134impl<'a> MinByteRange<'a> for Index<'a> {
135 fn min_byte_range(&self) -> Range<usize> {
136 0..self.data_byte_range().end
137 }
138 fn min_table_bytes(&self) -> &'a [u8] {
139 let range = self.min_byte_range();
140 self.data.as_bytes().get(range).unwrap_or_default()
141 }
142}
143
144impl<'a> FontRead<'a> for Index<'a> {
145 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
146 #[allow(clippy::absurd_extreme_comparisons)]
147 if data.len() < Self::MIN_SIZE {
148 return Err(ReadError::OutOfBounds);
149 }
150 Ok(Self { data })
151 }
152}
153
154#[derive(Clone)]
156pub struct Index<'a> {
157 data: FontData<'a>,
158}
159
160#[allow(clippy::needless_lifetimes)]
161impl<'a> Index<'a> {
162 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
163 basic_table_impls!(impl_the_methods);
164
165 pub fn count(&self) -> u16 {
167 let range = self.count_byte_range();
168 self.data.read_at(range.start).ok().unwrap()
169 }
170
171 pub fn off_size(&self) -> u8 {
173 let range = self.off_size_byte_range();
174 self.data.read_at(range.start).ok().unwrap()
175 }
176
177 pub fn offsets(&self) -> &'a [u8] {
179 let range = self.offsets_byte_range();
180 self.data.read_array(range).ok().unwrap_or_default()
181 }
182
183 pub fn data(&self) -> &'a [u8] {
185 let range = self.data_byte_range();
186 self.data.read_array(range).ok().unwrap_or_default()
187 }
188
189 pub fn count_byte_range(&self) -> Range<usize> {
190 let start = 0;
191 start..start + u16::RAW_BYTE_LEN
192 }
193
194 pub fn off_size_byte_range(&self) -> Range<usize> {
195 let start = self.count_byte_range().end;
196 start..start + u8::RAW_BYTE_LEN
197 }
198
199 pub fn offsets_byte_range(&self) -> Range<usize> {
200 let count = self.count();
201 let off_size = self.off_size();
202 let start = self.off_size_byte_range().end;
203 start
204 ..start
205 + (transforms::add_multiply(count, 1_usize, off_size))
206 .saturating_mul(u8::RAW_BYTE_LEN)
207 }
208
209 pub fn data_byte_range(&self) -> Range<usize> {
210 let start = self.offsets_byte_range().end;
211 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
212 }
213}
214
215#[cfg(feature = "experimental_traverse")]
216impl<'a> SomeTable<'a> for Index<'a> {
217 fn type_name(&self) -> &str {
218 "Index"
219 }
220 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
221 match idx {
222 0usize => Some(Field::new("count", self.count())),
223 1usize => Some(Field::new("off_size", self.off_size())),
224 2usize => Some(Field::new("offsets", self.offsets())),
225 3usize => Some(Field::new("data", self.data())),
226 _ => None,
227 }
228 }
229}
230
231#[cfg(feature = "experimental_traverse")]
232#[allow(clippy::needless_lifetimes)]
233impl<'a> std::fmt::Debug for Index<'a> {
234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 (self as &dyn SomeTable<'a>).fmt(f)
236 }
237}
238
239#[derive(Clone)]
241pub enum FdSelect<'a> {
242 Format0(FdSelectFormat0<'a>),
243 Format3(FdSelectFormat3<'a>),
244 Format4(FdSelectFormat4<'a>),
245}
246
247impl<'a> FdSelect<'a> {
248 pub fn offset_data(&self) -> FontData<'a> {
250 match self {
251 Self::Format0(item) => item.offset_data(),
252 Self::Format3(item) => item.offset_data(),
253 Self::Format4(item) => item.offset_data(),
254 }
255 }
256
257 pub fn format(&self) -> u8 {
259 match self {
260 Self::Format0(item) => item.format(),
261 Self::Format3(item) => item.format(),
262 Self::Format4(item) => item.format(),
263 }
264 }
265}
266
267impl<'a> FontRead<'a> for FdSelect<'a> {
268 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
269 let format: u8 = data.read_at(0usize)?;
270 match format {
271 FdSelectFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
272 FdSelectFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
273 FdSelectFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
274 other => Err(ReadError::InvalidFormat(other.into())),
275 }
276 }
277}
278
279impl<'a> MinByteRange<'a> for FdSelect<'a> {
280 fn min_byte_range(&self) -> Range<usize> {
281 match self {
282 Self::Format0(item) => item.min_byte_range(),
283 Self::Format3(item) => item.min_byte_range(),
284 Self::Format4(item) => item.min_byte_range(),
285 }
286 }
287 fn min_table_bytes(&self) -> &'a [u8] {
288 match self {
289 Self::Format0(item) => item.min_table_bytes(),
290 Self::Format3(item) => item.min_table_bytes(),
291 Self::Format4(item) => item.min_table_bytes(),
292 }
293 }
294}
295
296#[cfg(feature = "experimental_traverse")]
297impl<'a> FdSelect<'a> {
298 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
299 match self {
300 Self::Format0(table) => table,
301 Self::Format3(table) => table,
302 Self::Format4(table) => table,
303 }
304 }
305}
306
307#[cfg(feature = "experimental_traverse")]
308impl std::fmt::Debug for FdSelect<'_> {
309 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
310 self.dyn_inner().fmt(f)
311 }
312}
313
314#[cfg(feature = "experimental_traverse")]
315impl<'a> SomeTable<'a> for FdSelect<'a> {
316 fn type_name(&self) -> &str {
317 self.dyn_inner().type_name()
318 }
319 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
320 self.dyn_inner().get_field(idx)
321 }
322}
323
324impl Format<u8> for FdSelectFormat0<'_> {
325 const FORMAT: u8 = 0;
326}
327
328impl<'a> MinByteRange<'a> for FdSelectFormat0<'a> {
329 fn min_byte_range(&self) -> Range<usize> {
330 0..self.fds_byte_range().end
331 }
332 fn min_table_bytes(&self) -> &'a [u8] {
333 let range = self.min_byte_range();
334 self.data.as_bytes().get(range).unwrap_or_default()
335 }
336}
337
338impl<'a> FontRead<'a> for FdSelectFormat0<'a> {
339 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
340 #[allow(clippy::absurd_extreme_comparisons)]
341 if data.len() < Self::MIN_SIZE {
342 return Err(ReadError::OutOfBounds);
343 }
344 Ok(Self { data })
345 }
346}
347
348#[derive(Clone)]
350pub struct FdSelectFormat0<'a> {
351 data: FontData<'a>,
352}
353
354#[allow(clippy::needless_lifetimes)]
355impl<'a> FdSelectFormat0<'a> {
356 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
357 basic_table_impls!(impl_the_methods);
358
359 pub fn format(&self) -> u8 {
361 let range = self.format_byte_range();
362 self.data.read_at(range.start).ok().unwrap()
363 }
364
365 pub fn fds(&self) -> &'a [u8] {
367 let range = self.fds_byte_range();
368 self.data.read_array(range).ok().unwrap_or_default()
369 }
370
371 pub fn format_byte_range(&self) -> Range<usize> {
372 let start = 0;
373 start..start + u8::RAW_BYTE_LEN
374 }
375
376 pub fn fds_byte_range(&self) -> Range<usize> {
377 let start = self.format_byte_range().end;
378 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
379 }
380}
381
382#[cfg(feature = "experimental_traverse")]
383impl<'a> SomeTable<'a> for FdSelectFormat0<'a> {
384 fn type_name(&self) -> &str {
385 "FdSelectFormat0"
386 }
387 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
388 match idx {
389 0usize => Some(Field::new("format", self.format())),
390 1usize => Some(Field::new("fds", self.fds())),
391 _ => None,
392 }
393 }
394}
395
396#[cfg(feature = "experimental_traverse")]
397#[allow(clippy::needless_lifetimes)]
398impl<'a> std::fmt::Debug for FdSelectFormat0<'a> {
399 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
400 (self as &dyn SomeTable<'a>).fmt(f)
401 }
402}
403
404impl Format<u8> for FdSelectFormat3<'_> {
405 const FORMAT: u8 = 3;
406}
407
408impl<'a> MinByteRange<'a> for FdSelectFormat3<'a> {
409 fn min_byte_range(&self) -> Range<usize> {
410 0..self.sentinel_byte_range().end
411 }
412 fn min_table_bytes(&self) -> &'a [u8] {
413 let range = self.min_byte_range();
414 self.data.as_bytes().get(range).unwrap_or_default()
415 }
416}
417
418impl<'a> FontRead<'a> for FdSelectFormat3<'a> {
419 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
420 #[allow(clippy::absurd_extreme_comparisons)]
421 if data.len() < Self::MIN_SIZE {
422 return Err(ReadError::OutOfBounds);
423 }
424 Ok(Self { data })
425 }
426}
427
428#[derive(Clone)]
430pub struct FdSelectFormat3<'a> {
431 data: FontData<'a>,
432}
433
434#[allow(clippy::needless_lifetimes)]
435impl<'a> FdSelectFormat3<'a> {
436 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
437 basic_table_impls!(impl_the_methods);
438
439 pub fn format(&self) -> u8 {
441 let range = self.format_byte_range();
442 self.data.read_at(range.start).ok().unwrap()
443 }
444
445 pub fn n_ranges(&self) -> u16 {
447 let range = self.n_ranges_byte_range();
448 self.data.read_at(range.start).ok().unwrap()
449 }
450
451 pub fn ranges(&self) -> &'a [FdSelectRange3] {
453 let range = self.ranges_byte_range();
454 self.data.read_array(range).ok().unwrap_or_default()
455 }
456
457 pub fn sentinel(&self) -> u16 {
459 let range = self.sentinel_byte_range();
460 self.data.read_at(range.start).ok().unwrap_or_default()
461 }
462
463 pub fn format_byte_range(&self) -> Range<usize> {
464 let start = 0;
465 start..start + u8::RAW_BYTE_LEN
466 }
467
468 pub fn n_ranges_byte_range(&self) -> Range<usize> {
469 let start = self.format_byte_range().end;
470 start..start + u16::RAW_BYTE_LEN
471 }
472
473 pub fn ranges_byte_range(&self) -> Range<usize> {
474 let n_ranges = self.n_ranges();
475 let start = self.n_ranges_byte_range().end;
476 start..start + (n_ranges as usize).saturating_mul(FdSelectRange3::RAW_BYTE_LEN)
477 }
478
479 pub fn sentinel_byte_range(&self) -> Range<usize> {
480 let start = self.ranges_byte_range().end;
481 start..start + u16::RAW_BYTE_LEN
482 }
483}
484
485#[cfg(feature = "experimental_traverse")]
486impl<'a> SomeTable<'a> for FdSelectFormat3<'a> {
487 fn type_name(&self) -> &str {
488 "FdSelectFormat3"
489 }
490 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
491 match idx {
492 0usize => Some(Field::new("format", self.format())),
493 1usize => Some(Field::new("n_ranges", self.n_ranges())),
494 2usize => Some(Field::new(
495 "ranges",
496 traversal::FieldType::array_of_records(
497 stringify!(FdSelectRange3),
498 self.ranges(),
499 self.offset_data(),
500 ),
501 )),
502 3usize => Some(Field::new("sentinel", self.sentinel())),
503 _ => None,
504 }
505 }
506}
507
508#[cfg(feature = "experimental_traverse")]
509#[allow(clippy::needless_lifetimes)]
510impl<'a> std::fmt::Debug for FdSelectFormat3<'a> {
511 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512 (self as &dyn SomeTable<'a>).fmt(f)
513 }
514}
515
516#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
518#[repr(C)]
519#[repr(packed)]
520pub struct FdSelectRange3 {
521 pub first: BigEndian<u16>,
523 pub fd: u8,
525}
526
527impl FdSelectRange3 {
528 pub fn first(&self) -> u16 {
530 self.first.get()
531 }
532
533 pub fn fd(&self) -> u8 {
535 self.fd
536 }
537}
538
539impl FixedSize for FdSelectRange3 {
540 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
541}
542
543#[cfg(feature = "experimental_traverse")]
544impl<'a> SomeRecord<'a> for FdSelectRange3 {
545 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
546 RecordResolver {
547 name: "FdSelectRange3",
548 get_field: Box::new(move |idx, _data| match idx {
549 0usize => Some(Field::new("first", self.first())),
550 1usize => Some(Field::new("fd", self.fd())),
551 _ => None,
552 }),
553 data,
554 }
555 }
556}
557
558impl Format<u8> for FdSelectFormat4<'_> {
559 const FORMAT: u8 = 4;
560}
561
562impl<'a> MinByteRange<'a> for FdSelectFormat4<'a> {
563 fn min_byte_range(&self) -> Range<usize> {
564 0..self.sentinel_byte_range().end
565 }
566 fn min_table_bytes(&self) -> &'a [u8] {
567 let range = self.min_byte_range();
568 self.data.as_bytes().get(range).unwrap_or_default()
569 }
570}
571
572impl<'a> FontRead<'a> for FdSelectFormat4<'a> {
573 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
574 #[allow(clippy::absurd_extreme_comparisons)]
575 if data.len() < Self::MIN_SIZE {
576 return Err(ReadError::OutOfBounds);
577 }
578 Ok(Self { data })
579 }
580}
581
582#[derive(Clone)]
584pub struct FdSelectFormat4<'a> {
585 data: FontData<'a>,
586}
587
588#[allow(clippy::needless_lifetimes)]
589impl<'a> FdSelectFormat4<'a> {
590 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
591 basic_table_impls!(impl_the_methods);
592
593 pub fn format(&self) -> u8 {
595 let range = self.format_byte_range();
596 self.data.read_at(range.start).ok().unwrap()
597 }
598
599 pub fn n_ranges(&self) -> u32 {
601 let range = self.n_ranges_byte_range();
602 self.data.read_at(range.start).ok().unwrap()
603 }
604
605 pub fn ranges(&self) -> &'a [FdSelectRange4] {
607 let range = self.ranges_byte_range();
608 self.data.read_array(range).ok().unwrap_or_default()
609 }
610
611 pub fn sentinel(&self) -> u32 {
613 let range = self.sentinel_byte_range();
614 self.data.read_at(range.start).ok().unwrap_or_default()
615 }
616
617 pub fn format_byte_range(&self) -> Range<usize> {
618 let start = 0;
619 start..start + u8::RAW_BYTE_LEN
620 }
621
622 pub fn n_ranges_byte_range(&self) -> Range<usize> {
623 let start = self.format_byte_range().end;
624 start..start + u32::RAW_BYTE_LEN
625 }
626
627 pub fn ranges_byte_range(&self) -> Range<usize> {
628 let n_ranges = self.n_ranges();
629 let start = self.n_ranges_byte_range().end;
630 start..start + (n_ranges as usize).saturating_mul(FdSelectRange4::RAW_BYTE_LEN)
631 }
632
633 pub fn sentinel_byte_range(&self) -> Range<usize> {
634 let start = self.ranges_byte_range().end;
635 start..start + u32::RAW_BYTE_LEN
636 }
637}
638
639#[cfg(feature = "experimental_traverse")]
640impl<'a> SomeTable<'a> for FdSelectFormat4<'a> {
641 fn type_name(&self) -> &str {
642 "FdSelectFormat4"
643 }
644 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
645 match idx {
646 0usize => Some(Field::new("format", self.format())),
647 1usize => Some(Field::new("n_ranges", self.n_ranges())),
648 2usize => Some(Field::new(
649 "ranges",
650 traversal::FieldType::array_of_records(
651 stringify!(FdSelectRange4),
652 self.ranges(),
653 self.offset_data(),
654 ),
655 )),
656 3usize => Some(Field::new("sentinel", self.sentinel())),
657 _ => None,
658 }
659 }
660}
661
662#[cfg(feature = "experimental_traverse")]
663#[allow(clippy::needless_lifetimes)]
664impl<'a> std::fmt::Debug for FdSelectFormat4<'a> {
665 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
666 (self as &dyn SomeTable<'a>).fmt(f)
667 }
668}
669
670#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
672#[repr(C)]
673#[repr(packed)]
674pub struct FdSelectRange4 {
675 pub first: BigEndian<u32>,
677 pub fd: BigEndian<u16>,
679}
680
681impl FdSelectRange4 {
682 pub fn first(&self) -> u32 {
684 self.first.get()
685 }
686
687 pub fn fd(&self) -> u16 {
689 self.fd.get()
690 }
691}
692
693impl FixedSize for FdSelectRange4 {
694 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
695}
696
697#[cfg(feature = "experimental_traverse")]
698impl<'a> SomeRecord<'a> for FdSelectRange4 {
699 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
700 RecordResolver {
701 name: "FdSelectRange4",
702 get_field: Box::new(move |idx, _data| match idx {
703 0usize => Some(Field::new("first", self.first())),
704 1usize => Some(Field::new("fd", self.fd())),
705 _ => None,
706 }),
707 data,
708 }
709 }
710}
711
712#[derive(Clone)]
714pub enum CustomCharset<'a> {
715 Format0(CharsetFormat0<'a>),
716 Format1(CharsetFormat1<'a>),
717 Format2(CharsetFormat2<'a>),
718}
719
720impl<'a> CustomCharset<'a> {
721 pub fn offset_data(&self) -> FontData<'a> {
723 match self {
724 Self::Format0(item) => item.offset_data(),
725 Self::Format1(item) => item.offset_data(),
726 Self::Format2(item) => item.offset_data(),
727 }
728 }
729
730 pub fn format(&self) -> u8 {
732 match self {
733 Self::Format0(item) => item.format(),
734 Self::Format1(item) => item.format(),
735 Self::Format2(item) => item.format(),
736 }
737 }
738}
739
740impl<'a> FontRead<'a> for CustomCharset<'a> {
741 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
742 let format: u8 = data.read_at(0usize)?;
743 match format {
744 CharsetFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
745 CharsetFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
746 CharsetFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
747 other => Err(ReadError::InvalidFormat(other.into())),
748 }
749 }
750}
751
752impl<'a> MinByteRange<'a> for CustomCharset<'a> {
753 fn min_byte_range(&self) -> Range<usize> {
754 match self {
755 Self::Format0(item) => item.min_byte_range(),
756 Self::Format1(item) => item.min_byte_range(),
757 Self::Format2(item) => item.min_byte_range(),
758 }
759 }
760 fn min_table_bytes(&self) -> &'a [u8] {
761 match self {
762 Self::Format0(item) => item.min_table_bytes(),
763 Self::Format1(item) => item.min_table_bytes(),
764 Self::Format2(item) => item.min_table_bytes(),
765 }
766 }
767}
768
769#[cfg(feature = "experimental_traverse")]
770impl<'a> CustomCharset<'a> {
771 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
772 match self {
773 Self::Format0(table) => table,
774 Self::Format1(table) => table,
775 Self::Format2(table) => table,
776 }
777 }
778}
779
780#[cfg(feature = "experimental_traverse")]
781impl std::fmt::Debug for CustomCharset<'_> {
782 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
783 self.dyn_inner().fmt(f)
784 }
785}
786
787#[cfg(feature = "experimental_traverse")]
788impl<'a> SomeTable<'a> for CustomCharset<'a> {
789 fn type_name(&self) -> &str {
790 self.dyn_inner().type_name()
791 }
792 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
793 self.dyn_inner().get_field(idx)
794 }
795}
796
797impl Format<u8> for CharsetFormat0<'_> {
798 const FORMAT: u8 = 0;
799}
800
801impl<'a> MinByteRange<'a> for CharsetFormat0<'a> {
802 fn min_byte_range(&self) -> Range<usize> {
803 0..self.glyph_byte_range().end
804 }
805 fn min_table_bytes(&self) -> &'a [u8] {
806 let range = self.min_byte_range();
807 self.data.as_bytes().get(range).unwrap_or_default()
808 }
809}
810
811impl<'a> FontRead<'a> for CharsetFormat0<'a> {
812 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
813 #[allow(clippy::absurd_extreme_comparisons)]
814 if data.len() < Self::MIN_SIZE {
815 return Err(ReadError::OutOfBounds);
816 }
817 Ok(Self { data })
818 }
819}
820
821#[derive(Clone)]
823pub struct CharsetFormat0<'a> {
824 data: FontData<'a>,
825}
826
827#[allow(clippy::needless_lifetimes)]
828impl<'a> CharsetFormat0<'a> {
829 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
830 basic_table_impls!(impl_the_methods);
831
832 pub fn format(&self) -> u8 {
834 let range = self.format_byte_range();
835 self.data.read_at(range.start).ok().unwrap()
836 }
837
838 pub fn glyph(&self) -> &'a [BigEndian<u16>] {
840 let range = self.glyph_byte_range();
841 self.data.read_array(range).ok().unwrap_or_default()
842 }
843
844 pub fn format_byte_range(&self) -> Range<usize> {
845 let start = 0;
846 start..start + u8::RAW_BYTE_LEN
847 }
848
849 pub fn glyph_byte_range(&self) -> Range<usize> {
850 let start = self.format_byte_range().end;
851 start..start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN
852 }
853}
854
855#[cfg(feature = "experimental_traverse")]
856impl<'a> SomeTable<'a> for CharsetFormat0<'a> {
857 fn type_name(&self) -> &str {
858 "CharsetFormat0"
859 }
860 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
861 match idx {
862 0usize => Some(Field::new("format", self.format())),
863 1usize => Some(Field::new("glyph", self.glyph())),
864 _ => None,
865 }
866 }
867}
868
869#[cfg(feature = "experimental_traverse")]
870#[allow(clippy::needless_lifetimes)]
871impl<'a> std::fmt::Debug for CharsetFormat0<'a> {
872 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
873 (self as &dyn SomeTable<'a>).fmt(f)
874 }
875}
876
877impl Format<u8> for CharsetFormat1<'_> {
878 const FORMAT: u8 = 1;
879}
880
881impl<'a> MinByteRange<'a> for CharsetFormat1<'a> {
882 fn min_byte_range(&self) -> Range<usize> {
883 0..self.ranges_byte_range().end
884 }
885 fn min_table_bytes(&self) -> &'a [u8] {
886 let range = self.min_byte_range();
887 self.data.as_bytes().get(range).unwrap_or_default()
888 }
889}
890
891impl<'a> FontRead<'a> for CharsetFormat1<'a> {
892 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
893 #[allow(clippy::absurd_extreme_comparisons)]
894 if data.len() < Self::MIN_SIZE {
895 return Err(ReadError::OutOfBounds);
896 }
897 Ok(Self { data })
898 }
899}
900
901#[derive(Clone)]
903pub struct CharsetFormat1<'a> {
904 data: FontData<'a>,
905}
906
907#[allow(clippy::needless_lifetimes)]
908impl<'a> CharsetFormat1<'a> {
909 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
910 basic_table_impls!(impl_the_methods);
911
912 pub fn format(&self) -> u8 {
914 let range = self.format_byte_range();
915 self.data.read_at(range.start).ok().unwrap()
916 }
917
918 pub fn ranges(&self) -> &'a [CharsetRange1] {
920 let range = self.ranges_byte_range();
921 self.data.read_array(range).ok().unwrap_or_default()
922 }
923
924 pub fn format_byte_range(&self) -> Range<usize> {
925 let start = 0;
926 start..start + u8::RAW_BYTE_LEN
927 }
928
929 pub fn ranges_byte_range(&self) -> Range<usize> {
930 let start = self.format_byte_range().end;
931 start
932 ..start
933 + self.data.len().saturating_sub(start) / CharsetRange1::RAW_BYTE_LEN
934 * CharsetRange1::RAW_BYTE_LEN
935 }
936}
937
938#[cfg(feature = "experimental_traverse")]
939impl<'a> SomeTable<'a> for CharsetFormat1<'a> {
940 fn type_name(&self) -> &str {
941 "CharsetFormat1"
942 }
943 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
944 match idx {
945 0usize => Some(Field::new("format", self.format())),
946 1usize => Some(Field::new(
947 "ranges",
948 traversal::FieldType::array_of_records(
949 stringify!(CharsetRange1),
950 self.ranges(),
951 self.offset_data(),
952 ),
953 )),
954 _ => None,
955 }
956 }
957}
958
959#[cfg(feature = "experimental_traverse")]
960#[allow(clippy::needless_lifetimes)]
961impl<'a> std::fmt::Debug for CharsetFormat1<'a> {
962 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
963 (self as &dyn SomeTable<'a>).fmt(f)
964 }
965}
966
967#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
969#[repr(C)]
970#[repr(packed)]
971pub struct CharsetRange1 {
972 pub first: BigEndian<u16>,
974 pub n_left: u8,
976}
977
978impl CharsetRange1 {
979 pub fn first(&self) -> u16 {
981 self.first.get()
982 }
983
984 pub fn n_left(&self) -> u8 {
986 self.n_left
987 }
988}
989
990impl FixedSize for CharsetRange1 {
991 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
992}
993
994#[cfg(feature = "experimental_traverse")]
995impl<'a> SomeRecord<'a> for CharsetRange1 {
996 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
997 RecordResolver {
998 name: "CharsetRange1",
999 get_field: Box::new(move |idx, _data| match idx {
1000 0usize => Some(Field::new("first", self.first())),
1001 1usize => Some(Field::new("n_left", self.n_left())),
1002 _ => None,
1003 }),
1004 data,
1005 }
1006 }
1007}
1008
1009impl Format<u8> for CharsetFormat2<'_> {
1010 const FORMAT: u8 = 2;
1011}
1012
1013impl<'a> MinByteRange<'a> for CharsetFormat2<'a> {
1014 fn min_byte_range(&self) -> Range<usize> {
1015 0..self.ranges_byte_range().end
1016 }
1017 fn min_table_bytes(&self) -> &'a [u8] {
1018 let range = self.min_byte_range();
1019 self.data.as_bytes().get(range).unwrap_or_default()
1020 }
1021}
1022
1023impl<'a> FontRead<'a> for CharsetFormat2<'a> {
1024 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1025 #[allow(clippy::absurd_extreme_comparisons)]
1026 if data.len() < Self::MIN_SIZE {
1027 return Err(ReadError::OutOfBounds);
1028 }
1029 Ok(Self { data })
1030 }
1031}
1032
1033#[derive(Clone)]
1035pub struct CharsetFormat2<'a> {
1036 data: FontData<'a>,
1037}
1038
1039#[allow(clippy::needless_lifetimes)]
1040impl<'a> CharsetFormat2<'a> {
1041 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
1042 basic_table_impls!(impl_the_methods);
1043
1044 pub fn format(&self) -> u8 {
1046 let range = self.format_byte_range();
1047 self.data.read_at(range.start).ok().unwrap()
1048 }
1049
1050 pub fn ranges(&self) -> &'a [CharsetRange2] {
1052 let range = self.ranges_byte_range();
1053 self.data.read_array(range).ok().unwrap_or_default()
1054 }
1055
1056 pub fn format_byte_range(&self) -> Range<usize> {
1057 let start = 0;
1058 start..start + u8::RAW_BYTE_LEN
1059 }
1060
1061 pub fn ranges_byte_range(&self) -> Range<usize> {
1062 let start = self.format_byte_range().end;
1063 start
1064 ..start
1065 + self.data.len().saturating_sub(start) / CharsetRange2::RAW_BYTE_LEN
1066 * CharsetRange2::RAW_BYTE_LEN
1067 }
1068}
1069
1070#[cfg(feature = "experimental_traverse")]
1071impl<'a> SomeTable<'a> for CharsetFormat2<'a> {
1072 fn type_name(&self) -> &str {
1073 "CharsetFormat2"
1074 }
1075 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1076 match idx {
1077 0usize => Some(Field::new("format", self.format())),
1078 1usize => Some(Field::new(
1079 "ranges",
1080 traversal::FieldType::array_of_records(
1081 stringify!(CharsetRange2),
1082 self.ranges(),
1083 self.offset_data(),
1084 ),
1085 )),
1086 _ => None,
1087 }
1088 }
1089}
1090
1091#[cfg(feature = "experimental_traverse")]
1092#[allow(clippy::needless_lifetimes)]
1093impl<'a> std::fmt::Debug for CharsetFormat2<'a> {
1094 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1095 (self as &dyn SomeTable<'a>).fmt(f)
1096 }
1097}
1098
1099#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1101#[repr(C)]
1102#[repr(packed)]
1103pub struct CharsetRange2 {
1104 pub first: BigEndian<u16>,
1106 pub n_left: BigEndian<u16>,
1108}
1109
1110impl CharsetRange2 {
1111 pub fn first(&self) -> u16 {
1113 self.first.get()
1114 }
1115
1116 pub fn n_left(&self) -> u16 {
1118 self.n_left.get()
1119 }
1120}
1121
1122impl FixedSize for CharsetRange2 {
1123 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1124}
1125
1126#[cfg(feature = "experimental_traverse")]
1127impl<'a> SomeRecord<'a> for CharsetRange2 {
1128 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1129 RecordResolver {
1130 name: "CharsetRange2",
1131 get_field: Box::new(move |idx, _data| match idx {
1132 0usize => Some(Field::new("first", self.first())),
1133 1usize => Some(Field::new("n_left", self.n_left())),
1134 _ => None,
1135 }),
1136 data,
1137 }
1138 }
1139}
1140
1141#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1143#[repr(C)]
1144#[repr(packed)]
1145pub struct EncodingRange1 {
1146 pub first: u8,
1148 pub n_left: u8,
1150}
1151
1152impl EncodingRange1 {
1153 pub fn first(&self) -> u8 {
1155 self.first
1156 }
1157
1158 pub fn n_left(&self) -> u8 {
1160 self.n_left
1161 }
1162}
1163
1164impl FixedSize for EncodingRange1 {
1165 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1166}
1167
1168#[cfg(feature = "experimental_traverse")]
1169impl<'a> SomeRecord<'a> for EncodingRange1 {
1170 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1171 RecordResolver {
1172 name: "EncodingRange1",
1173 get_field: Box::new(move |idx, _data| match idx {
1174 0usize => Some(Field::new("first", self.first())),
1175 1usize => Some(Field::new("n_left", self.n_left())),
1176 _ => None,
1177 }),
1178 data,
1179 }
1180 }
1181}
1182
1183#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1185#[repr(C)]
1186#[repr(packed)]
1187pub struct EncodingSupplement {
1188 pub code: u8,
1190 pub glyph: BigEndian<u16>,
1192}
1193
1194impl EncodingSupplement {
1195 pub fn code(&self) -> u8 {
1197 self.code
1198 }
1199
1200 pub fn glyph(&self) -> u16 {
1202 self.glyph.get()
1203 }
1204}
1205
1206impl FixedSize for EncodingSupplement {
1207 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1208}
1209
1210#[cfg(feature = "experimental_traverse")]
1211impl<'a> SomeRecord<'a> for EncodingSupplement {
1212 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1213 RecordResolver {
1214 name: "EncodingSupplement",
1215 get_field: Box::new(move |idx, _data| match idx {
1216 0usize => Some(Field::new("code", self.code())),
1217 1usize => Some(Field::new("glyph", self.glyph())),
1218 _ => None,
1219 }),
1220 data,
1221 }
1222 }
1223}