#[allow(unused_imports)]
use crate::codegen_prelude::*;
impl Discriminant for MyLookup<'_, ()> {
fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
data.read_at(0)
}
}
impl<'a, T> MinByteRange<'a> for MyLookup<'a, T> {
fn min_byte_range(&self) -> Range<usize> {
0..self.subtable_offsets_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a, T> FontRead<'a> for MyLookup<'a, T> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self {
data,
offset_type: std::marker::PhantomData,
})
}
}
impl<'a, T> MyLookup<'a, T> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> MyLookup<'a, ()> {
MyLookup {
data: self.data,
offset_type: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct MyLookup<'a, T = ()> {
data: FontData<'a>,
offset_type: std::marker::PhantomData<*const T>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a, T> MyLookup<'a, T> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn lookup_type(&self) -> u16 {
let range = self.lookup_type_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn sub_table_count(&self) -> u16 {
let range = self.sub_table_count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
let range = self.subtable_offsets_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
where
T: FontRead<'a>,
{
let data = self.data;
let offsets = self.subtable_offsets();
ArrayOfOffsets::new(offsets, data, ())
}
pub fn lookup_type_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn sub_table_count_byte_range(&self) -> Range<usize> {
let start = self.lookup_type_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
let sub_table_count = self.sub_table_count();
let start = self.sub_table_count_byte_range().end;
start..start + (sub_table_count as usize).saturating_mul(Offset16::RAW_BYTE_LEN)
}
}
const _: () = assert!(FontData::default_data_long_enough(MyLookup::<()>::MIN_SIZE));
impl<T> Default for MyLookup<'_, T> {
fn default() -> Self {
Self {
data: FontData::default_table_data(),
offset_type: std::marker::PhantomData,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for MyLookup<'a, T> {
fn type_name(&self) -> &str {
"MyLookup"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("lookup_type", self.lookup_type())),
1usize => Some(Field::new("sub_table_count", self.sub_table_count())),
2usize => Some(Field::new(
"subtable_offsets",
FieldType::from(self.subtables()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for MyLookup<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone)]
pub enum MySubtable<'a> {
Format1(MySubtableFormat1<'a>),
Format2(MySubtableFormat2<'a>),
}
impl Default for MySubtable<'_> {
fn default() -> Self {
Self::Format1(Default::default())
}
}
impl<'a> MySubtable<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format1(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format1(item) => item.format(),
Self::Format2(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for MySubtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
MySubtableFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
MySubtableFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MinByteRange<'a> for MySubtable<'a> {
fn min_byte_range(&self) -> Range<usize> {
match self {
Self::Format1(item) => item.min_byte_range(),
Self::Format2(item) => item.min_byte_range(),
}
}
fn min_table_bytes(&self) -> &'a [u8] {
match self {
Self::Format1(item) => item.min_table_bytes(),
Self::Format2(item) => item.min_table_bytes(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> MySubtable<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format1(table) => table,
Self::Format2(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for MySubtable<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.dyn_inner().fmt(f)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for MySubtable<'a> {
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
}
impl Format<u16> for MySubtableFormat1<'_> {
const FORMAT: u16 = 1;
}
impl<'a> MinByteRange<'a> for MySubtableFormat1<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.value_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for MySubtableFormat1<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct MySubtableFormat1<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> MySubtableFormat1<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn value(&self) -> u16 {
let range = self.value_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn value_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
}
const _: () = assert!(FontData::default_data_long_enough(
MySubtableFormat1::MIN_SIZE
));
impl Default for MySubtableFormat1<'_> {
fn default() -> Self {
Self {
data: FontData::default_format_1_u16_table_data(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for MySubtableFormat1<'a> {
fn type_name(&self) -> &str {
"MySubtableFormat1"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("value", self.value())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for MySubtableFormat1<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for MySubtableFormat2<'_> {
const FORMAT: u16 = 2;
}
impl<'a> MinByteRange<'a> for MySubtableFormat2<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.values_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for MySubtableFormat2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct MySubtableFormat2<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> MySubtableFormat2<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn format(&self) -> u16 {
let range = self.format_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn count(&self) -> u16 {
let range = self.count_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn values(&self) -> &'a [BigEndian<u16>] {
let range = self.values_byte_range();
self.data.read_array(range).ok().unwrap_or_default()
}
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn count_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn values_byte_range(&self) -> Range<usize> {
let count = self.count();
let start = self.count_byte_range().end;
start..start + (count as usize).saturating_mul(u16::RAW_BYTE_LEN)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for MySubtableFormat2<'a> {
fn type_name(&self) -> &str {
"MySubtableFormat2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("count", self.count())),
2usize => Some(Field::new("values", self.values())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for MySubtableFormat2<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
pub enum MyLookupGroup<'a> {
TypeOne(MyLookup<'a, MySubtable<'a>>),
TypeTwo(MyLookup<'a, MySubtableFormat1<'a>>),
}
impl Default for MyLookupGroup<'_> {
fn default() -> Self {
Self::TypeOne(Default::default())
}
}
impl<'a> FontRead<'a> for MyLookupGroup<'a> {
fn read(bytes: FontData<'a>) -> Result<Self, ReadError> {
let discriminant = MyLookup::read_discriminant(bytes)?;
match discriminant {
1 => Ok(MyLookupGroup::TypeOne(FontRead::read(bytes)?)),
2 => Ok(MyLookupGroup::TypeTwo(FontRead::read(bytes)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
impl<'a> MyLookupGroup<'a> {
#[allow(dead_code)]
pub(crate) fn of_unit_type(&self) -> MyLookup<'a, ()> {
match self {
MyLookupGroup::TypeOne(inner) => inner.of_unit_type(),
MyLookupGroup::TypeTwo(inner) => inner.of_unit_type(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> MyLookupGroup<'a> {
fn dyn_inner(&self) -> &(dyn SomeTable<'a> + 'a) {
match self {
MyLookupGroup::TypeOne(table) => table,
MyLookupGroup::TypeTwo(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for MyLookupGroup<'a> {
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for MyLookupGroup<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.dyn_inner().fmt(f)
}
}
impl<'a> MinByteRange<'a> for ContainsLookupGroup<'a> {
fn min_byte_range(&self) -> Range<usize> {
0..self.lookup_offset_byte_range().end
}
fn min_table_bytes(&self) -> &'a [u8] {
let range = self.min_byte_range();
self.data.as_bytes().get(range).unwrap_or_default()
}
}
impl<'a> FontRead<'a> for ContainsLookupGroup<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
#[allow(clippy::absurd_extreme_comparisons)]
if data.len() < Self::MIN_SIZE {
return Err(ReadError::OutOfBounds);
}
Ok(Self { data })
}
}
#[derive(Clone)]
pub struct ContainsLookupGroup<'a> {
data: FontData<'a>,
}
#[allow(clippy::needless_lifetimes)]
impl<'a> ContainsLookupGroup<'a> {
pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
basic_table_impls!(impl_the_methods);
pub fn version(&self) -> u16 {
let range = self.version_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lookup_offset(&self) -> Offset16 {
let range = self.lookup_offset_byte_range();
self.data.read_at(range.start).ok().unwrap()
}
pub fn lookup(&self) -> Result<MyLookupGroup<'a>, ReadError> {
let data = self.data;
self.lookup_offset().resolve(data)
}
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn lookup_offset_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + Offset16::RAW_BYTE_LEN
}
}
const _: () = assert!(FontData::default_data_long_enough(
ContainsLookupGroup::MIN_SIZE
));
impl Default for ContainsLookupGroup<'_> {
fn default() -> Self {
Self {
data: FontData::default_table_data(),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for ContainsLookupGroup<'a> {
fn type_name(&self) -> &str {
"ContainsLookupGroup"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new(
"lookup_offset",
FieldType::offset(self.lookup_offset(), self.lookup()),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for ContainsLookupGroup<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}