1use std::{fmt::Debug, ops::Deref};
17
18use types::{
19 BigEndian, F2Dot14, FWord, Fixed, GlyphId16, Int24, LongDateTime, MajorMinor, NameId, Nullable,
20 Offset16, Offset24, Offset32, Scalar, Tag, UfWord, Uint24, Version16Dot16,
21};
22
23use crate::{
24 array::{ComputedArray, VarLenArray},
25 read::{ComputeSize, ReadArgs},
26 FontData, FontRead, FontReadWithArgs, ReadError, VarSize,
27};
28
29pub enum FieldType<'a> {
33 I8(i8),
34 U8(u8),
35 I16(i16),
36 U16(u16),
37 I32(i32),
38 U32(u32),
39 I24(Int24),
40 U24(Uint24),
41 Tag(Tag),
42 FWord(FWord),
43 UfWord(UfWord),
44 MajorMinor(MajorMinor),
45 Version16Dot16(Version16Dot16),
46 F2Dot14(F2Dot14),
47 Fixed(Fixed),
48 LongDateTime(LongDateTime),
49 GlyphId16(GlyphId16),
50 NameId(NameId),
51 BareOffset(OffsetType),
52 ResolvedOffset(ResolvedOffset<'a>),
53 StringOffset(StringOffset<'a>),
55 ArrayOffset(ArrayOffset<'a>),
57 Record(RecordResolver<'a>),
58 Array(Box<dyn SomeArray<'a> + 'a>),
59 Unknown,
60}
61
62#[derive(Clone, Copy)]
64pub enum OffsetType {
65 Offset16(u16),
66 Offset24(Uint24),
67 Offset32(u32),
68}
69
70impl OffsetType {
71 pub fn to_u32(self) -> u32 {
73 match self {
74 Self::Offset16(val) => val.into(),
75 Self::Offset24(val) => val.into(),
76 Self::Offset32(val) => val,
77 }
78 }
79}
80
81pub struct ResolvedOffset<'a> {
83 pub offset: OffsetType,
85 pub target: Result<Box<dyn SomeTable<'a> + 'a>, ReadError>,
87}
88
89pub struct StringOffset<'a> {
93 pub offset: OffsetType,
94 pub target: Result<Box<dyn SomeString<'a> + 'a>, ReadError>,
95}
96
97pub struct ArrayOffset<'a> {
99 pub offset: OffsetType,
100 pub target: Result<Box<dyn SomeArray<'a> + 'a>, ReadError>,
101}
102
103pub(crate) struct ArrayOfOffsets<'a, O> {
104 type_name: &'static str,
105 offsets: &'a [O],
106 resolver: Box<dyn Fn(&O) -> FieldType<'a> + 'a>,
107}
108
109impl<'a, O> SomeArray<'a> for ArrayOfOffsets<'a, O> {
110 fn type_name(&self) -> &str {
111 self.type_name
112 }
113
114 fn len(&self) -> usize {
115 self.offsets.len()
116 }
117
118 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
119 let off = self.offsets.get(idx)?;
120 let target = (self.resolver)(off);
121 Some(target)
122 }
123}
124
125impl<'a> FieldType<'a> {
126 pub fn array_of_records<T>(
129 type_name: &'static str,
130 records: &'a [T],
131 data: FontData<'a>,
132 ) -> FieldType<'a>
133 where
134 T: Clone + SomeRecord<'a> + 'a,
135 {
136 ArrayOfRecords {
137 type_name,
138 data,
139 records,
140 }
141 .into()
142 }
143
144 pub fn computed_array<T>(
146 type_name: &'static str,
147 array: ComputedArray<'a, T>,
148 data: FontData<'a>,
149 ) -> FieldType<'a>
150 where
151 T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a,
152 T::Args: Copy + 'static,
153 {
154 ComputedArrayOfRecords {
155 type_name,
156 data,
157 array,
158 }
159 .into()
160 }
161
162 pub fn var_array<T>(
164 type_name: &'static str,
165 array: VarLenArray<'a, T>,
166 data: FontData<'a>,
167 ) -> FieldType<'a>
168 where
169 T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,
170 {
171 VarLenArrayOfRecords {
172 type_name,
173 data,
174 array,
175 }
176 .into()
177 }
178
179 pub fn array_of_offsets<O>(
184 type_name: &'static str,
185 offsets: &'a [O],
186 resolver: impl Fn(&O) -> FieldType<'a> + 'a,
187 ) -> Self
188where {
189 FieldType::Array(Box::new(ArrayOfOffsets {
190 type_name,
191 offsets,
192 resolver: Box::new(resolver),
193 }))
194 }
195
196 pub fn offset_to_array_of_scalars<T: SomeArray<'a> + 'a>(
198 offset: impl Into<OffsetType>,
199 result: impl Into<Option<Result<T, ReadError>>>,
200 ) -> Self {
201 let offset = offset.into();
202 match result.into() {
203 Some(target) => FieldType::ArrayOffset(ArrayOffset {
204 offset,
205 target: target.map(|x| Box::new(x) as Box<dyn SomeArray>),
206 }),
207 None => FieldType::BareOffset(offset),
208 }
209 }
210
211 pub fn offset_to_array_of_records<T: Clone + SomeRecord<'a> + 'a>(
213 offset: impl Into<OffsetType>,
214 result: impl Into<Option<Result<&'a [T], ReadError>>>,
215 type_name: &'static str,
216 data: FontData<'a>,
217 ) -> Self {
218 let offset = offset.into();
219 match result.into() {
220 Some(target) => {
221 let target = target.map(|records| {
222 Box::new(ArrayOfRecords {
223 type_name,
224 data,
225 records,
226 }) as Box<dyn SomeArray>
227 });
228 FieldType::ArrayOffset(ArrayOffset { offset, target })
229 }
230 None => FieldType::BareOffset(offset),
231 }
232 }
233
234 pub fn offset<T: SomeTable<'a> + 'a>(
240 offset: impl Into<OffsetType>,
241 result: impl Into<Option<Result<T, ReadError>>>,
242 ) -> Self {
243 let offset = offset.into();
244 match result.into() {
245 Some(target) => FieldType::ResolvedOffset(ResolvedOffset {
246 offset,
247 target: target.map(|x| Box::new(x) as Box<dyn SomeTable>),
248 }),
249 None => FieldType::BareOffset(offset),
250 }
251 }
252
253 pub fn unknown_offset(offset: impl Into<OffsetType>) -> Self {
255 Self::BareOffset(offset.into())
256 }
257}
258
259pub struct Field<'a> {
261 pub name: &'static str,
263 pub value: FieldType<'a>,
265}
266
267pub trait SomeTable<'a> {
272 fn type_name(&self) -> &str;
274 fn get_field(&self, idx: usize) -> Option<Field<'a>>;
276}
277
278impl<'a> dyn SomeTable<'a> + 'a {
279 pub fn iter(&self) -> impl Iterator<Item = Field<'a>> + '_ {
281 FieldIter {
282 table: self,
283 idx: 0,
284 }
285 }
286}
287
288struct FieldIter<'a, 'b> {
289 table: &'b dyn SomeTable<'a>,
290 idx: usize,
291}
292
293impl<'a> Iterator for FieldIter<'a, '_> {
294 type Item = Field<'a>;
295
296 fn next(&mut self) -> Option<Self::Item> {
297 let this = self.idx;
298 self.idx += 1;
299 self.table.get_field(this)
300 }
301}
302
303impl<'a> SomeTable<'a> for Box<dyn SomeTable<'a> + 'a> {
304 fn type_name(&self) -> &str {
305 self.deref().type_name()
306 }
307
308 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
309 self.deref().get_field(idx)
310 }
311}
312
313pub trait SomeRecord<'a> {
316 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a>;
317}
318
319pub struct RecordResolver<'a> {
322 pub(crate) name: &'static str,
323 pub(crate) get_field: Box<dyn Fn(usize, FontData<'a>) -> Option<Field<'a>> + 'a>,
324 pub(crate) data: FontData<'a>,
325}
326
327pub trait SomeArray<'a> {
329 fn type_name(&self) -> &str;
331
332 fn len(&self) -> usize;
334
335 fn is_empty(&self) -> bool {
337 self.len() == 0
338 }
339
340 fn get(&self, idx: usize) -> Option<FieldType<'a>>;
342}
343
344impl<'a> dyn SomeArray<'a> + 'a {
345 pub fn iter(&self) -> impl Iterator<Item = FieldType<'a>> + '_ {
347 ArrayIter {
348 array: self,
349 idx: 0,
350 }
351 }
352}
353
354struct ArrayIter<'a, 'b> {
355 array: &'b dyn SomeArray<'a>,
356 idx: usize,
357}
358
359impl<'a> Iterator for ArrayIter<'a, '_> {
360 type Item = FieldType<'a>;
361
362 fn next(&mut self) -> Option<Self::Item> {
363 let this = self.idx;
364 self.idx += 1;
365 self.array.get(this)
366 }
367}
368
369impl<'a, T: Scalar + Into<FieldType<'a>>> SomeArray<'a> for &'a [BigEndian<T>]
370where
371 BigEndian<T>: Copy, {
373 fn len(&self) -> usize {
374 (*self).len()
375 }
376
377 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
378 (*self).get(idx).map(|val| val.get().into())
379 }
380
381 fn type_name(&self) -> &str {
382 let full_name = std::any::type_name::<T>();
383 full_name.split("::").last().unwrap_or(full_name)
384 }
385}
386
387impl<'a> SomeArray<'a> for &'a [u8] {
388 fn type_name(&self) -> &str {
389 "u8"
390 }
391
392 fn len(&self) -> usize {
393 (*self).len()
394 }
395
396 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
397 (*self).get(idx).copied().map(Into::into)
398 }
399}
400
401impl<'a> SomeArray<'a> for Box<dyn SomeArray<'a> + 'a> {
402 fn type_name(&self) -> &str {
403 self.deref().type_name()
404 }
405
406 fn len(&self) -> usize {
407 self.deref().len()
408 }
409
410 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
411 self.deref().get(idx)
412 }
413}
414
415pub trait SomeString<'a> {
416 fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>;
417}
418
419impl<'a> SomeString<'a> for Box<dyn SomeString<'a> + 'a> {
420 fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a> {
421 self.deref().iter_chars()
422 }
423}
424
425struct ArrayOfRecords<'a, T> {
427 pub(crate) type_name: &'static str,
428 pub(crate) data: FontData<'a>,
429 pub(crate) records: &'a [T],
430}
431
432struct ComputedArrayOfRecords<'a, T: ReadArgs> {
434 pub(crate) type_name: &'static str,
435 pub(crate) data: FontData<'a>,
436 pub(crate) array: ComputedArray<'a, T>,
437}
438
439struct VarLenArrayOfRecords<'a, T> {
440 pub(crate) type_name: &'static str,
441 pub(crate) data: FontData<'a>,
442 pub(crate) array: VarLenArray<'a, T>,
443}
444
445impl<'a, T> SomeArray<'a> for ComputedArrayOfRecords<'a, T>
446where
447 T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a,
448 T::Args: Copy + 'static,
449 Self: 'a,
450{
451 fn len(&self) -> usize {
452 self.array.len()
453 }
454
455 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
456 self.array
457 .get(idx)
458 .ok()
459 .map(|record| record.traverse(self.data).into())
460 }
461
462 fn type_name(&self) -> &str {
463 self.type_name
464 }
465}
466
467impl<'a, T: SomeRecord<'a> + Clone> SomeArray<'a> for ArrayOfRecords<'a, T> {
468 fn type_name(&self) -> &str {
469 self.type_name
470 }
471
472 fn len(&self) -> usize {
473 self.records.len()
474 }
475
476 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
477 self.records
478 .get(idx)
479 .map(|record| record.clone().traverse(self.data).into())
480 }
481}
482
483impl<'a, T> SomeArray<'a> for VarLenArrayOfRecords<'a, T>
484where
485 T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,
486 Self: 'a,
487{
488 fn len(&self) -> usize {
489 self.array.iter().count()
490 }
491
492 fn get(&self, idx: usize) -> Option<FieldType<'a>> {
493 self.array
494 .get(idx)?
495 .ok()
496 .map(|record| record.traverse(self.data).into())
497 }
498
499 fn type_name(&self) -> &str {
500 self.type_name
501 }
502}
503
504impl<'a> Field<'a> {
505 pub fn new(name: &'static str, value: impl Into<FieldType<'a>>) -> Self {
507 Field {
508 name,
509 value: value.into(),
510 }
511 }
512}
513
514struct DebugPrintTable<'a, 'b>(pub &'b (dyn SomeTable<'a> + 'a));
516
517struct DebugPrintArray<'a, 'b>(pub &'b (dyn SomeArray<'a> + 'a));
519
520impl<'a> Debug for FieldType<'a> {
521 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
522 match self {
523 Self::I8(arg0) => arg0.fmt(f),
524 Self::U8(arg0) => arg0.fmt(f),
525 Self::I16(arg0) => arg0.fmt(f),
526 Self::U16(arg0) => arg0.fmt(f),
527 Self::I32(arg0) => arg0.fmt(f),
528 Self::U32(arg0) => arg0.fmt(f),
529 Self::I24(arg0) => arg0.fmt(f),
530 Self::U24(arg0) => arg0.fmt(f),
531 Self::Tag(arg0) => arg0.fmt(f),
532 Self::FWord(arg0) => arg0.to_i16().fmt(f),
533 Self::UfWord(arg0) => arg0.to_u16().fmt(f),
534 Self::MajorMinor(arg0) => write!(f, "{}.{}", arg0.major, arg0.minor),
535 Self::Version16Dot16(arg0) => arg0.fmt(f),
536 Self::F2Dot14(arg0) => arg0.fmt(f),
537 Self::Fixed(arg0) => arg0.fmt(f),
538 Self::LongDateTime(arg0) => arg0.as_secs().fmt(f),
539 Self::GlyphId16(arg0) => {
540 write!(f, "g")?;
541 arg0.to_u16().fmt(f)
542 }
543 Self::NameId(arg0) => arg0.fmt(f),
544 Self::StringOffset(string) => match &string.target {
545 Ok(arg0) => arg0.as_ref().fmt(f),
546 Err(_) => string.target.fmt(f),
547 },
548 Self::ArrayOffset(array) => match &array.target {
549 Ok(arg0) => arg0.as_ref().fmt(f),
550 Err(_) => array.target.fmt(f),
551 },
552 Self::BareOffset(arg0) => write!(f, "0x{:04X}", arg0.to_u32()),
553 Self::ResolvedOffset(ResolvedOffset {
554 target: Ok(arg0), ..
555 }) => arg0.fmt(f),
556 Self::ResolvedOffset(arg0) => arg0.target.fmt(f),
557 Self::Record(arg0) => (arg0 as &(dyn SomeTable<'a> + 'a)).fmt(f),
558 Self::Array(arg0) => arg0.fmt(f),
559 Self::Unknown => write!(f, "no repr available"),
560 }
561 }
562}
563
564impl std::fmt::Debug for DebugPrintTable<'_, '_> {
565 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
566 let mut debug_struct = f.debug_struct(self.0.type_name());
567 for field in self.0.iter() {
568 debug_struct.field(field.name, &field.value);
569 }
570 debug_struct.finish()
571 }
572}
573
574impl<'a> Debug for dyn SomeTable<'a> + 'a {
575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576 DebugPrintTable(self).fmt(f)
577 }
578}
579
580impl<'a> Debug for dyn SomeString<'a> + 'a {
581 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
582 write!(f, "\"")?;
583 for c in self.iter_chars() {
584 write!(f, "{c}")?
585 }
586 write!(f, "\"")
587 }
588}
589
590impl std::fmt::Debug for DebugPrintArray<'_, '_> {
591 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
592 let mut debug_list = f.debug_list();
593 let mut idx = 0;
594 while let Some(item) = self.0.get(idx) {
595 idx += 1;
596 debug_list.entry(&item);
597 }
598 debug_list.finish()
599 }
600}
601
602impl<'a> Debug for dyn SomeArray<'a> + 'a {
603 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
604 DebugPrintArray(self).fmt(f)
605 }
606}
607
608impl std::fmt::Display for OffsetType {
609 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
610 write!(f, "{:+}", self.to_u32())
611 }
612}
613
614impl<'a> SomeTable<'a> for RecordResolver<'a> {
616 fn type_name(&self) -> &str {
617 self.name
618 }
619
620 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
621 (self.get_field)(idx, self.data)
622 }
623}
624
625impl<'a> From<u8> for FieldType<'a> {
626 fn from(src: u8) -> FieldType<'a> {
627 FieldType::U8(src)
628 }
629}
630
631impl<'a> From<i8> for FieldType<'a> {
632 fn from(src: i8) -> FieldType<'a> {
633 FieldType::I8(src)
634 }
635}
636
637impl<'a> From<u16> for FieldType<'a> {
638 fn from(src: u16) -> FieldType<'a> {
639 FieldType::U16(src)
640 }
641}
642
643impl<'a> From<i16> for FieldType<'a> {
644 fn from(src: i16) -> FieldType<'a> {
645 FieldType::I16(src)
646 }
647}
648
649impl<'a> From<u32> for FieldType<'a> {
650 fn from(src: u32) -> FieldType<'a> {
651 FieldType::U32(src)
652 }
653}
654
655impl<'a> From<i32> for FieldType<'a> {
656 fn from(src: i32) -> FieldType<'a> {
657 FieldType::I32(src)
658 }
659}
660
661impl<'a> From<Uint24> for FieldType<'a> {
662 fn from(src: Uint24) -> FieldType<'a> {
663 FieldType::U24(src)
664 }
665}
666
667impl<'a> From<Int24> for FieldType<'a> {
668 fn from(src: Int24) -> FieldType<'a> {
669 FieldType::I24(src)
670 }
671}
672
673impl<'a> From<Tag> for FieldType<'a> {
674 fn from(src: Tag) -> FieldType<'a> {
675 FieldType::Tag(src)
676 }
677}
678
679impl<'a> From<FWord> for FieldType<'a> {
680 fn from(src: FWord) -> FieldType<'a> {
681 FieldType::FWord(src)
682 }
683}
684
685impl<'a> From<UfWord> for FieldType<'a> {
686 fn from(src: UfWord) -> FieldType<'a> {
687 FieldType::UfWord(src)
688 }
689}
690
691impl<'a> From<Fixed> for FieldType<'a> {
692 fn from(src: Fixed) -> FieldType<'a> {
693 FieldType::Fixed(src)
694 }
695}
696
697impl<'a> From<F2Dot14> for FieldType<'a> {
698 fn from(src: F2Dot14) -> FieldType<'a> {
699 FieldType::F2Dot14(src)
700 }
701}
702
703impl<'a> From<LongDateTime> for FieldType<'a> {
704 fn from(src: LongDateTime) -> FieldType<'a> {
705 FieldType::LongDateTime(src)
706 }
707}
708
709impl<'a> From<MajorMinor> for FieldType<'a> {
710 fn from(src: MajorMinor) -> FieldType<'a> {
711 FieldType::MajorMinor(src)
712 }
713}
714
715impl<'a> From<Version16Dot16> for FieldType<'a> {
716 fn from(src: Version16Dot16) -> FieldType<'a> {
717 FieldType::Version16Dot16(src)
718 }
719}
720
721impl<'a> From<GlyphId16> for FieldType<'a> {
722 fn from(src: GlyphId16) -> FieldType<'a> {
723 FieldType::GlyphId16(src)
724 }
725}
726
727impl<'a> From<NameId> for FieldType<'a> {
728 fn from(src: NameId) -> FieldType<'a> {
729 FieldType::NameId(src)
730 }
731}
732
733impl<'a> From<RecordResolver<'a>> for FieldType<'a> {
734 fn from(src: RecordResolver<'a>) -> Self {
735 FieldType::Record(src)
736 }
737}
738
739impl<'a, T: SomeArray<'a> + 'a> From<T> for FieldType<'a> {
740 fn from(src: T) -> Self {
741 FieldType::Array(Box::new(src))
742 }
743}
744
745impl From<Offset16> for OffsetType {
746 fn from(src: Offset16) -> OffsetType {
747 OffsetType::Offset16(src.to_u32() as u16)
748 }
749}
750
751impl From<Offset24> for OffsetType {
752 fn from(src: Offset24) -> OffsetType {
753 OffsetType::Offset24(Uint24::new(src.to_u32()))
754 }
755}
756
757impl From<Offset32> for OffsetType {
758 fn from(src: Offset32) -> OffsetType {
759 OffsetType::Offset32(src.to_u32())
760 }
761}
762
763impl<'a> From<Offset16> for FieldType<'a> {
764 fn from(src: Offset16) -> FieldType<'a> {
765 FieldType::BareOffset(src.into())
766 }
767}
768
769impl<'a> From<Offset24> for FieldType<'a> {
770 fn from(src: Offset24) -> FieldType<'a> {
771 FieldType::BareOffset(src.into())
772 }
773}
774
775impl<'a> From<Offset32> for FieldType<'a> {
776 fn from(src: Offset32) -> FieldType<'a> {
777 FieldType::BareOffset(src.into())
778 }
779}
780
781impl<T: Into<OffsetType> + Clone> From<Nullable<T>> for OffsetType {
782 fn from(src: Nullable<T>) -> Self {
783 src.offset().clone().into()
784 }
785}