Skip to content

Commit

Permalink
Now possible to run the full codegen plan
Browse files Browse the repository at this point in the history
  • Loading branch information
rsheeter committed Oct 23, 2022
1 parent 15ffb35 commit b9e61a4
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 96 deletions.
94 changes: 54 additions & 40 deletions font-codegen/src/fields.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! methods on fields
use std::{backtrace::Backtrace, ops::Deref};
use std::ops::Deref;

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
Expand Down Expand Up @@ -211,6 +211,13 @@ impl Fields {
}
}

fn big_endian(typ: &syn::Ident) -> TokenStream {
if typ == "u8" {
return quote!(#typ);
}
quote!(BigEndian<#typ>)
}

fn traversal_arm_for_field(
fld: &Field,
in_record: bool,
Expand All @@ -227,7 +234,7 @@ fn traversal_arm_for_field(
FieldType::Offset {
target: Some(OffsetTarget::Array(inner)),
..
} if matches!(inner.deref(), FieldType::PendingResolution { .. }) => {
} if matches!(inner.deref(), FieldType::Struct { .. }) => {
let typ = inner.cooked_type_tokens();
let getter = fld.offset_getter_name();
let offset_data = fld.offset_getter_data_src();
Expand Down Expand Up @@ -256,15 +263,14 @@ fn traversal_arm_for_field(
quote!(Field::new(#name_str, FieldType::unknown_offset(self.#name()#maybe_unwrap)))
}
FieldType::Scalar { .. } => quote!(Field::new(#name_str, self.#name()#maybe_unwrap)),
FieldType::Struct { .. } => quote!(Field::new(#name_str, self.#name()#maybe_unwrap)),

FieldType::Array { inner_typ } => match inner_typ.as_ref() {
FieldType::Scalar { .. } => quote!(Field::new(#name_str, self.#name()#maybe_unwrap)),
//HACK: glyf has fields that are [u8]
FieldType::PendingResolution { typ } if typ == "u8" => {
FieldType::Struct { typ } if typ == "u8" => {
quote!(Field::new( #name_str, self.#name()#maybe_unwrap))
}
FieldType::PendingResolution { typ } if !in_record => {
FieldType::Struct { typ } if !in_record => {
let offset_data = fld.offset_getter_data_src();
quote!(Field::new(
#name_str,
Expand Down Expand Up @@ -307,11 +313,12 @@ fn traversal_arm_for_field(
FieldType::Offset {
target: Some(OffsetTarget::Array(_)),
..
} => quote!(compile_error!(
"achievement unlocked: 'added arrays of offsets to arrays to OpenType spec'"
)),
} => panic!(
"achievement unlocked: 'added arrays of offsets to arrays to OpenType spec' {:#?}",
fld
),
FieldType::Offset { .. } => quote!(Field::new(#name_str, self.#name()#maybe_unwrap)),
_ => quote!(compile_error!("unhandled traversal case")),
_ => panic!("unhandled traversal case {:#?}", fld),
},
FieldType::ComputedArray(arr) => {
// if we are in a record, we pass in empty data. This lets us
Expand All @@ -335,13 +342,15 @@ fn traversal_arm_for_field(
FieldType::VarLenArray(_) => {
quote!(Field::new(#name_str, traversal::FieldType::var_array(self.#name()#maybe_unwrap)))
}
FieldType::PendingResolution { typ } if typ == "ValueRecord" => {
// HACK: who wouldn't want to hard-code ValueRecord handling
FieldType::Struct { typ } if typ == "ValueRecord" => {
let clone = in_record.then(|| quote!(.clone()));
quote!(Field::new(#name_str, self.#name() #clone #maybe_unwrap))
}
FieldType::PendingResolution { .. } => {
FieldType::Struct { .. } => {
quote!(compile_error!(concat!("another weird type: ", #name_str)))
}
FieldType::PendingResolution { .. } => panic!("Should have resolved {:#?}", fld),
}
}

Expand All @@ -350,7 +359,6 @@ fn check_resolution(phase: Phase, field_type: &FieldType) -> syn::Result<()> {
return Ok(());
}
if let FieldType::PendingResolution { typ } = field_type {
eprintln!("{}", Backtrace::capture()); // very helpful when troubleshooting
return Err(syn::Error::new(
typ.span(),
format!(
Expand All @@ -368,7 +376,7 @@ impl Field {
FieldType::Offset { typ, .. } if self.is_nullable() => {
quote!(BigEndian<Nullable<#typ>>)
}
FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => quote!(BigEndian<#typ>),
FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => big_endian(typ),
FieldType::Struct { typ } => typ.to_token_stream(),
FieldType::ComputedArray(array) => {
let inner = array.type_with_lifetime();
Expand All @@ -380,7 +388,8 @@ impl Field {
quote!(&'a [BigEndian<Nullable<#typ>>])
}
FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => {
quote!(&'a [BigEndian<#typ>])
let be = big_endian(typ);
quote!(&'a [#be])
}
FieldType::Struct { typ } => quote!( &[#typ] ),
FieldType::PendingResolution { typ } => {
Expand Down Expand Up @@ -496,19 +505,18 @@ impl Field {
// is this a scalar/offset? then it's just 'RAW_BYTE_LEN'
// is this computed? then it is stored
match &self.typ {
FieldType::Offset { typ, .. }
| FieldType::Scalar { typ }
| FieldType::Struct { typ } => {
FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => {
quote!(#typ::RAW_BYTE_LEN)
}
FieldType::PendingResolution { .. }
FieldType::Struct { .. }
| FieldType::Array { .. }
| FieldType::ComputedArray { .. }
| FieldType::VarLenArray(_) => {
let len_field = self.shape_byte_len_field_name();
let try_op = self.is_version_dependent().then(|| quote!(?));
quote!(self.#len_field #try_op)
}
FieldType::PendingResolution { .. } => panic!("Should have resolved {:?}", self),
}
}

Expand Down Expand Up @@ -553,13 +561,13 @@ impl Field {
FieldType::Offset { typ, .. }
| FieldType::Scalar { typ }
| FieldType::Struct { typ } => typ.to_token_stream(),
FieldType::PendingResolution { typ } => typ.to_token_stream(),
FieldType::Array { inner_typ } => match inner_typ.as_ref() {
FieldType::Offset { typ, .. } if self.is_nullable() => {
quote!(&'a [BigEndian<Nullable<#typ>>])
}
FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => {
quote!(&'a [BigEndian<#typ>])
let be = big_endian(typ);
quote!(&'a [#be])
}
FieldType::Struct { typ } => quote!(&'a [#typ]),
FieldType::PendingResolution { typ } => quote!( &'a [#typ] ),
Expand All @@ -573,6 +581,7 @@ impl Field {
let inner = array.type_with_lifetime();
quote!(VarLenArray<'a, #inner>)
}
FieldType::PendingResolution { .. } => panic!("Should have resolved {:?}", self),
}
}

Expand Down Expand Up @@ -640,18 +649,24 @@ impl Field {
// their fields on access.
let add_borrow_just_for_record = matches!(
self.typ,
FieldType::PendingResolution { .. } | FieldType::ComputedArray { .. }
FieldType::Struct { .. } | FieldType::ComputedArray { .. }
)
.then(|| quote!(&));

let getter_expr = match &self.typ {
FieldType::Scalar { .. } | FieldType::Offset { .. } | FieldType::Struct { .. } => {
quote!(self.#name.get())
FieldType::Scalar { typ } | FieldType::Offset { typ, .. } => {
if typ == "u8" {
quote!(self.#name)
} else {
quote!(self.#name.get())
}
}
FieldType::ComputedArray { .. } | FieldType::VarLenArray(_) => quote!(&self.#name),
FieldType::Struct { .. }
| FieldType::ComputedArray { .. }
| FieldType::VarLenArray(_) => quote!(&self.#name),
FieldType::Array { .. } => quote!(self.#name),
FieldType::PendingResolution { typ } => {
panic!("Should have resolved {}", quote! { #typ });
FieldType::PendingResolution { .. } => {
panic!("Should have resolved {:?}", self)
}
};

Expand Down Expand Up @@ -880,10 +895,12 @@ impl Field {
.as_deref()
.map(FieldReadArgs::to_tokens_for_validation);

if let FieldType::PendingResolution { typ } = &self.typ {
if let FieldType::Struct { typ } = &self.typ {
return Some(quote!( <#typ as ComputeSize>::compute_size(&#read_args)));
}

if let FieldType::PendingResolution { .. } = &self.typ {
panic!("Should have resolved {:?}", self)
}
let len_expr = match self.attrs.count.as_deref() {
Some(Count::All) => quote!(cursor.remaining_bytes()),
Some(other) => {
Expand Down Expand Up @@ -1031,7 +1048,7 @@ impl Field {
| FieldType::VarLenArray(_) => true,
FieldType::Array { inner_typ } => matches!(
inner_typ.as_ref(),
FieldType::Offset { .. } | FieldType::PendingResolution { .. }
FieldType::Offset { .. } | FieldType::Struct { .. }
),
FieldType::PendingResolution { typ } => {
panic!("Should have resolved {}", quote! { #typ });
Expand All @@ -1045,10 +1062,10 @@ impl Field {
_ if self.attrs.to_owned.is_some() => false,
FieldType::Offset { .. } => in_record,
FieldType::ComputedArray(_) | FieldType::VarLenArray(_) => true,
FieldType::PendingResolution { .. } => true,
FieldType::Struct { .. } => true,
FieldType::Array { inner_typ } => match inner_typ.as_ref() {
FieldType::Offset { .. } => in_record,
FieldType::PendingResolution { .. } => true,
FieldType::Struct { .. } => true,
_ => false,
},
_ => false,
Expand All @@ -1068,7 +1085,7 @@ impl Field {
self.attrs.to_owned.as_ref().unwrap().expr.to_token_stream()
}
FieldType::Scalar { .. } => quote!(obj.#name()),
FieldType::PendingResolution { .. } => quote!(obj.#name().to_owned_obj(offset_data)),
FieldType::Struct { .. } => quote!(obj.#name().to_owned_obj(offset_data)),
FieldType::Offset {
target: Some(_), ..
} => {
Expand All @@ -1082,7 +1099,7 @@ impl Field {
FieldType::Array { inner_typ } => {
// we write different code based on whether or not this is a versioned field
let (getter, converter) = match inner_typ.as_ref() {
FieldType::Scalar { .. } | FieldType::Struct { .. } => (
FieldType::Scalar { .. } => (
quote!(obj.#name()),
quote!(.iter().map(|x| x.get()).collect()),
),
Expand All @@ -1093,7 +1110,7 @@ impl Field {
quote!(.map(|x| x.into()).collect()),
)
}
FieldType::PendingResolution { .. } => (
FieldType::Struct { .. } => (
quote!(obj.#name()),
quote!(.iter().map(|x| FromObjRef::from_obj_ref(x, offset_data)).collect()),
),
Expand Down Expand Up @@ -1131,11 +1148,8 @@ impl FieldType {
FieldType::Offset { typ, .. }
| FieldType::Scalar { typ }
| FieldType::Struct { typ } => typ,
FieldType::PendingResolution { typ } => {
panic!(
"Should never cook a type pending resolution {}",
quote! { #typ }
);
FieldType::PendingResolution { .. } => {
panic!("Should never cook a type pending resolution {:#?}", self);
}
FieldType::Array { .. }
| FieldType::ComputedArray { .. }
Expand All @@ -1149,7 +1163,6 @@ impl FieldType {
let raw_type = match self {
FieldType::Scalar { typ } => typ.into_token_stream(),
FieldType::Struct { typ } => typ.into_token_stream(),
FieldType::PendingResolution { typ } => typ.into_token_stream(),
FieldType::Offset { typ, target } => {
let target = target
.as_ref()
Expand All @@ -1173,6 +1186,7 @@ impl FieldType {
quote!( Vec<#inner_tokens> )
}
FieldType::ComputedArray(array) | FieldType::VarLenArray(array) => array.compile_type(),
FieldType::PendingResolution { .. } => panic!("Should have resolved {:?}", self),
};
if version_dependent {
quote!( Option<#raw_type> )
Expand Down
Loading

0 comments on commit b9e61a4

Please sign in to comment.