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