Skip to content

Commit

Permalink
Generate push_next function for non root structs
Browse files Browse the repository at this point in the history
Fixes #229
  • Loading branch information
filnet committed May 24, 2020
1 parent 8d7dfee commit f134f90
Showing 1 changed file with 33 additions and 30 deletions.
63 changes: 33 additions & 30 deletions generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1749,46 +1749,49 @@ pub fn derive_setters(
.map(|extends| {
extends
.split(',')
.filter(|extend| root_struct_names.contains(*extend))
//.filter(|extend| root_struct_names.contains(*extend))
.map(|extends| name_to_tokens(&format!("Extends{}", name_to_tokens(&extends))))
.collect()
})
.unwrap_or_else(|| vec![]);

// We only implement a next methods for root structs with a `pnext` field.
let next_function = if has_next && root_structs.is_empty() {
quote! {
/// Prepends the given extension struct between the root and the first pointer. This
/// method only exists on structs that can be passed to a function directly. Only
/// valid extension structs can be pushed into the chain.
/// If the chain looks like `A -> B -> C`, and you call `builder.push_next(&mut D)`, then the
/// chain will look like `A -> D -> B -> C`.
pub fn push_next<T: #extends_name>(mut self, next: &'a mut T) -> #name_builder<'a> {
unsafe{
let next_ptr = next as *mut T as *mut BaseOutStructure;
// `next` here can contain a pointer chain. This means that we must correctly
// attach he head to the root and the tail to the rest of the chain
// For example:
//
// next = A -> B
// Before: `Root -> C -> D -> E`
// After: `Root -> A -> B -> C -> D -> E`
// ^^^^^^
// next chain
let last_next = ptr_chain_iter(next).last().unwrap();
(*last_next).p_next = self.inner.p_next as _;
self.inner.p_next = next_ptr as _;
// We only implement a push_next method for root structs with a `pnext` field.
let next_function =
if has_next && (root_structs.is_empty() || &_struct.name == "VkPhysicalDeviceFeatures2") {
quote! {
/// Prepends the given extension struct between the root and the first pointer. This
/// method only exists on structs that can be passed to a function directly. Only
/// valid extension structs can be pushed into the chain.
/// If the chain looks like `A -> B -> C`, and you call `builder.push_next(&mut D)`, then the
/// chain will look like `A -> D -> B -> C`.
pub fn push_next<T: #extends_name>(mut self, next: &'a mut T) -> #name_builder<'a> {
unsafe{
let next_ptr = next as *mut T as *mut BaseOutStructure;
// `next` here can contain a pointer chain. This means that we must correctly
// attach the head to the root and the tail to the rest of the chain
// For example:
//
// next = A -> B
// Before: `Root -> C -> D -> E`
// After: `Root -> A -> B -> C -> D -> E`
// ^^^^^^
// next chain
let last_next = ptr_chain_iter(next).last().unwrap();
(*last_next).p_next = self.inner.p_next as _;
self.inner.p_next = next_ptr as _;
}
self
}
self
}
}
} else {
quote! {}
};
} else {
quote! {}
};

// Root structs come with their own trait that structs that extends this struct will
// implement
let next_trait = if has_next && _struct.extends.is_none() {
let next_trait = if has_next
&& (_struct.extends.is_none() || &_struct.name == "VkPhysicalDeviceFeatures2")
{
quote! {
pub unsafe trait #extends_name {
}
Expand Down

0 comments on commit f134f90

Please sign in to comment.