Builder: next pattern

This commit is contained in:
Matus Talcik 2018-11-18 14:50:37 +01:00
parent 55c592e67d
commit 1be701f853
2 changed files with 5173 additions and 2233 deletions

File diff suppressed because it is too large Load diff

View file

@ -1353,6 +1353,10 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
}
pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" {
return None;
}
let name = name_to_tokens(&_struct.name);
let name_builder = name_to_tokens(&(_struct.name.clone() + "Builder"));
@ -1361,6 +1365,18 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
_ => None,
});
let (has_next, is_next_const) = match members
.clone()
.find(|field| field.param_ident().to_string() == "p_next")
{
Some(p_next) => if p_next.type_tokens().to_string().starts_with("*const") {
(true, true)
} else {
(true, false)
},
None => (false, false),
};
let nofilter_count_members = [
"VkPipelineViewportStateCreateInfo.pViewports",
"VkPipelineViewportStateCreateInfo.pScissors",
@ -1522,21 +1538,56 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
})
});
let mut nexts = Vec::new();
let name_builder_next = name_to_tokens(&(_struct.name.clone() + "BuilderNext"));
if let Some(extends) = &_struct.extends {
for target in extends.split(',') {
let target_ident = name_to_tokens(&(target.to_string() + "BuilderNext"));
nexts.push(quote! {
unsafe impl #target_ident for #name_builder_next {}
});
}
}
let next_function = if has_next {
if is_next_const {
quote!{
pub fn next<T>(mut self, next: &'a T) -> #name_builder<'a> where T: #name_builder_next {
self.inner.p_next = next as *const T as *const c_void;
self
}
}
} else {
quote!{
pub fn next<T>(mut self, next: &'a mut T) -> #name_builder<'a> where T: #name_builder_next {
self.inner.p_next = next as *mut T as *mut c_void;
self
}
}
}
} else {
quote!{}
};
let q = quote!{
impl #name {
pub fn builder<'a>() -> #name_builder<'a> {
pub fn builder<'a>() -> #name_builder<'a> {
#name_builder {
inner: #name::default(),
marker: ::std::marker::PhantomData,
}
}
}
}
}
pub struct #name_builder<'a> {
inner: #name,
marker: ::std::marker::PhantomData<&'a ()>,
}
pub unsafe trait #name_builder_next {}
#(#nexts)*
impl<'a> ::std::ops::Deref for #name_builder<'a> {
type Target = #name;
@ -1548,6 +1599,8 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
impl<'a> #name_builder<'a> {
#(#setters)*
#next_function
pub fn build(self) -> #name {
self.inner
}