Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Move helper methods to macro_utils
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianwithah committed Sep 7, 2019
1 parent 2899ba0 commit af4a942
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 158 deletions.
99 changes: 31 additions & 68 deletions macros/aggr_co_class_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,9 @@ use syn:: {

use std::iter::FromIterator;
use std::collections::HashMap;
use macro_utils::camel_to_snake;

// Helper functions (CURRENTLY DUPLICATED TO MOVE DURING REBASE)

pub fn get_vtable_ident(trait_ident: &Ident) -> Ident {
format_ident!("{}VTable", trait_ident)
}

pub fn get_vptr_ident(trait_ident: &Ident) -> Ident {
format_ident!("{}VPtr", trait_ident)
}

fn get_non_del_unk_field_ident() -> Ident {
format_ident!("__non_delegating_unk")
}

fn get_iunk_to_use_field_ident() -> Ident {
format_ident!("__iunk_to_use")
}

fn get_ref_count_ident() -> Ident {
format_ident!("__refcnt")
}

fn get_vptr_field_ident(trait_ident: &Ident) -> Ident {
format_ident!("__{}vptr", trait_ident.to_string().to_lowercase())
}

fn get_real_ident(struct_ident: &Ident) -> Ident {
if !struct_ident.to_string().starts_with("Init") {
panic!("The target struct's name must begin with Init")
}

format_ident!("{}", &struct_ident.to_string()[4..])
}

fn get_inner_init_field_ident() -> Ident {
format_ident!("__init_struct")
}
use macro_utils::*;

// Helper functions
fn get_base_interface_idents(struct_item: &ItemStruct) -> Vec<Ident> {
let mut base_itf_idents = Vec::new();

Expand Down Expand Up @@ -128,7 +91,7 @@ pub fn expand_derive_aggr_com_class(item: TokenStream) -> TokenStream {

fn gen_impl(base_itf_idents: &[Ident], aggr_itf_idents: &HashMap<Ident, Vec<Ident>>, struct_item: &ItemStruct) -> HelperTokenStream {

let real_ident = get_real_ident(&struct_item.ident);
let real_ident = macro_utils::get_real_ident(&struct_item.ident);
let allocate_fn = gen_allocate_fn(base_itf_idents, struct_item);
let set_iunknown_fn = gen_set_iunknown_fn();
let inner_iunknown_fns = gen_inner_iunknown_fns(base_itf_idents, aggr_itf_idents, struct_item);
Expand All @@ -143,8 +106,8 @@ fn gen_impl(base_itf_idents: &[Ident], aggr_itf_idents: &HashMap<Ident, Vec<Iden
}

fn gen_set_iunknown_fn() -> HelperTokenStream {
let iunk_to_use_field_ident = get_iunk_to_use_field_ident();
let non_del_unk_field_ident = get_non_del_unk_field_ident();
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();

quote!(
pub(crate) fn set_iunknown(&mut self, aggr: *mut IUnknownVPtr) {
Expand All @@ -158,8 +121,8 @@ fn gen_set_iunknown_fn() -> HelperTokenStream {
}

fn gen_inner_iunknown_fns(base_itf_idents: &[Ident], aggr_itf_idents: &HashMap<Ident, Vec<Ident>>, struct_item: &ItemStruct) -> HelperTokenStream {
let real_ident = get_real_ident(&struct_item.ident);
let ref_count_ident = get_ref_count_ident();
let real_ident = macro_utils::get_real_ident(&struct_item.ident);
let ref_count_ident = macro_utils::get_ref_count_ident();
let inner_query_interface = gen_inner_query_interface(base_itf_idents, aggr_itf_idents, struct_item);

quote!(
Expand All @@ -186,12 +149,12 @@ fn gen_inner_iunknown_fns(base_itf_idents: &[Ident], aggr_itf_idents: &HashMap<I
}

fn gen_inner_query_interface(base_itf_idents: &[Ident], aggr_itf_idents: &HashMap<Ident, Vec<Ident>>, struct_item: &ItemStruct) -> HelperTokenStream {
let non_del_unk_field_ident = get_non_del_unk_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();

// Generate match arms for implemented interfaces
let match_arms = base_itf_idents.iter().map(|base| {
let match_condition = quote!(<dyn #base as com::ComInterface>::iid_in_inheritance_chain(riid));
let vptr_field_ident = get_vptr_field_ident(&base);
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);

quote!(
else if #match_condition {
Expand Down Expand Up @@ -254,11 +217,11 @@ fn gen_inner_query_interface(base_itf_idents: &[Ident], aggr_itf_idents: &HashMa
}

fn gen_drop_impl(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let real_ident = get_real_ident(&struct_item.ident);
let non_del_unk_field_ident = get_non_del_unk_field_ident();
let real_ident = macro_utils::get_real_ident(&struct_item.ident);
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let box_from_raws = base_itf_idents.iter().map(|base| {
let vptr_field_ident = get_vptr_field_ident(&base);
let vtable_ident = get_vtable_ident(&base);
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);
let vtable_ident = macro_utils::get_vtable_ident(&base);
quote!(
Box::from_raw(self.#vptr_field_ident as *mut #vtable_ident);
)
Expand All @@ -278,8 +241,8 @@ fn gen_drop_impl(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperT

fn gen_deref_impl(struct_item: &ItemStruct) -> HelperTokenStream {
let init_ident = &struct_item.ident;
let real_ident = get_real_ident(init_ident);
let inner_init_field_ident = get_inner_init_field_ident();
let real_ident = macro_utils::get_real_ident(init_ident);
let inner_init_field_ident = macro_utils::get_inner_init_field_ident();

quote!(
impl std::ops::Deref for #real_ident {
Expand All @@ -292,8 +255,8 @@ fn gen_deref_impl(struct_item: &ItemStruct) -> HelperTokenStream {
}

fn gen_iunknown_impl(struct_item: &ItemStruct) -> HelperTokenStream {
let real_ident = get_real_ident(&struct_item.ident);
let iunk_to_use_field_ident = get_iunk_to_use_field_ident();
let real_ident = macro_utils::get_real_ident(&struct_item.ident);
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();

quote!(
impl com::IUnknown for #real_ident {
Expand Down Expand Up @@ -331,12 +294,12 @@ fn gen_iunknown_impl(struct_item: &ItemStruct) -> HelperTokenStream {

fn gen_allocate_fn(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let init_ident = &struct_item.ident;
let real_ident = get_real_ident(&struct_item.ident);
let real_ident = macro_utils::get_real_ident(&struct_item.ident);

let mut offset_count : usize = 0;
let base_inits = base_itf_idents.iter().map(|base| {
let vtable_var_ident = format_ident!("{}_vtable", base.to_string().to_lowercase());
let vptr_field_ident = get_vptr_field_ident(&base);
let vptr_field_ident = macro_utils::get_vptr_field_ident(&base);


let out = quote!(
Expand All @@ -348,13 +311,13 @@ fn gen_allocate_fn(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> Helpe
out
});
let base_fields = base_itf_idents.iter().map(|base| {
let vptr_field_ident = get_vptr_field_ident(base);
let vptr_field_ident = macro_utils::get_vptr_field_ident(base);
quote!(#vptr_field_ident)
});
let ref_count_ident = get_ref_count_ident();
let inner_init_field_ident = get_inner_init_field_ident();
let iunk_to_use_field_ident = get_iunk_to_use_field_ident();
let non_del_unk_field_ident = get_non_del_unk_field_ident();
let ref_count_ident = macro_utils::get_ref_count_ident();
let inner_init_field_ident = macro_utils::get_inner_init_field_ident();
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let non_del_unk_offset = base_itf_idents.len();

quote!(
Expand Down Expand Up @@ -407,19 +370,19 @@ fn gen_allocate_fn(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> Helpe

fn gen_real_struct(base_itf_idents: &[Ident], struct_item: &ItemStruct) -> HelperTokenStream {
let init_ident = &struct_item.ident;
let real_ident = get_real_ident(&struct_item.ident);
let real_ident = macro_utils::get_real_ident(&struct_item.ident);
let vis = &struct_item.vis;

let bases_itf_idents = base_itf_idents.iter().map(|base| {
let field_ident = get_vptr_field_ident(&base);
let vptr_ident = get_vptr_ident(&base);
let field_ident = macro_utils::get_vptr_field_ident(&base);
let vptr_ident = macro_utils::get_vptr_ident(&base);
quote!(#field_ident: #vptr_ident)
});

let ref_count_ident = get_ref_count_ident();
let inner_init_field_ident = get_inner_init_field_ident();
let non_del_unk_field_ident = get_non_del_unk_field_ident();
let iunk_to_use_field_ident = get_iunk_to_use_field_ident();
let ref_count_ident = macro_utils::get_ref_count_ident();
let inner_init_field_ident = macro_utils::get_inner_init_field_ident();
let non_del_unk_field_ident = macro_utils::get_non_del_unk_field_ident();
let iunk_to_use_field_ident = macro_utils::get_iunk_to_use_field_ident();

quote!(
#[repr(C)]
Expand Down
94 changes: 4 additions & 90 deletions macros/co_class_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,12 @@ use proc_macro::TokenStream;
type HelperTokenStream = proc_macro2::TokenStream;
use quote::{format_ident, quote,};
use syn:: {
ItemStruct, Ident, Meta, NestedMeta, Fields,
ItemStruct, Ident,
};

use std::iter::FromIterator;
use std::collections::HashMap;
use macro_utils::camel_to_snake;

// Helper functions (CURRENTLY DUPLICATED TO MOVE DURING REBASE)

pub fn get_vtable_ident(trait_ident: &Ident) -> Ident {
format_ident!("{}VTable", trait_ident)
}

pub fn get_vptr_ident(trait_ident: &Ident) -> Ident {
format_ident!("{}VPtr", trait_ident)
}

fn get_ref_count_ident() -> Ident {
format_ident!("__refcnt")
}

fn get_vptr_field_ident(trait_ident: &Ident) -> Ident {
format_ident!("__{}vptr", trait_ident.to_string().to_lowercase())
}

fn get_real_ident(struct_ident: &Ident) -> Ident {
if !struct_ident.to_string().starts_with("Init") {
panic!("The target struct's name must begin with Init")
}

format_ident!("{}", &struct_ident.to_string()[4..])
}

fn get_inner_init_field_ident() -> Ident {
format_ident!("__init_struct")
}

fn get_base_interface_idents(struct_item: &ItemStruct) -> Vec<Ident> {
let mut base_itf_idents = Vec::new();

for attr in &struct_item.attrs {
if let Ok(Meta::List(ref attr)) = attr.parse_meta() {
if attr.path.segments.last().unwrap().ident != "com_implements" {
continue;
}

for item in &attr.nested {
if let NestedMeta::Meta(Meta::Path(p)) = item {
assert!(p.segments.len() == 1, "Incapable of handling multiple path segments yet.");
base_itf_idents.push(p.segments.last().unwrap().ident.clone());
}
}
}
}

base_itf_idents
}

fn get_aggr_map(struct_item: &ItemStruct) -> HashMap<Ident, Vec<Ident>> {
let mut aggr_map = HashMap::new();

let fields = match &struct_item.fields {
Fields::Named(f) => &f.named,
_ => panic!("Found field other than named fields in struct")
};

for field in fields {
for attr in &field.attrs {
if let Ok(Meta::List(ref attr)) = attr.parse_meta() {
if attr.path.segments.last().unwrap().ident != "aggr" {
continue;
}

let mut aggr_interfaces_idents = Vec::new();


assert!(attr.nested.len() > 0, "Need to expose at least one interface from aggregated COM object.");

for item in &attr.nested {
if let NestedMeta::Meta(Meta::Path(p)) = item {
assert!(p.segments.len() == 1, "Incapable of handling multiple path segments yet.");
aggr_interfaces_idents.push(p.segments.last().unwrap().ident.clone());
}
}
let ident = field.ident.as_ref().unwrap().clone();
aggr_map.insert(ident, aggr_interfaces_idents);
}
}
}

aggr_map
}
use macro_utils::*;

// Macro expansion entry point.

Expand All @@ -103,8 +17,8 @@ pub fn expand_derive_com_class(item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as ItemStruct);

// Parse attributes
let base_itf_idents = get_base_interface_idents(&input);
let aggr_itf_idents = get_aggr_map(&input);
let base_itf_idents = macro_utils::get_base_interface_idents(&input);
let aggr_itf_idents = macro_utils::get_aggr_map(&input);

let mut out: Vec<TokenStream> = Vec::new();
out.push(gen_real_struct(&base_itf_idents, &input).into());
Expand Down
2 changes: 2 additions & 0 deletions macros/macro_utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
syn = { version = "1.0.5", features = ["full"] }
quote = "1.0"
Loading

0 comments on commit af4a942

Please sign in to comment.