Abstract over constants
This commit is contained in:
parent
a9bf74cebf
commit
3fc04b77a6
|
@ -179,35 +179,35 @@ pub fn vk_bitflags_wrapped_macro() -> Tokens {
|
||||||
|
|
||||||
impl Default for $name{
|
impl Default for $name{
|
||||||
fn default() -> $name {
|
fn default() -> $name {
|
||||||
$name {flags: 0}
|
$name(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ::std::fmt::Debug for $name {
|
impl ::std::fmt::Debug for $name {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
||||||
write!(f, "{}({:b})", stringify!($name), self.flags)
|
write!(f, "{}({:b})", stringify!($name), self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn empty() -> $name {
|
pub fn empty() -> $name {
|
||||||
$name {flags: 0}
|
$name(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn all() -> $name {
|
pub fn all() -> $name {
|
||||||
$name {flags: $all}
|
$name($all)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn flags(self) -> $flag_type {
|
pub fn flags(self) -> $flag_type {
|
||||||
self.flags
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_flags(flags: $flag_type) -> Option<$name> {
|
pub fn from_flags(flags: $flag_type) -> Option<$name> {
|
||||||
if flags & !$all == 0 {
|
if flags & !$all == 0 {
|
||||||
Some($name {flags: flags})
|
Some($name(flags))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ pub fn vk_bitflags_wrapped_macro() -> Tokens {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_flags_truncate(flags: $flag_type) -> $name {
|
pub fn from_flags_truncate(flags: $flag_type) -> $name {
|
||||||
$name {flags: flags & $all}
|
$name (flags & $all)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -245,7 +245,7 @@ pub fn vk_bitflags_wrapped_macro() -> Tokens {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(self, rhs: $name) -> $name {
|
fn bitor(self, rhs: $name) -> $name {
|
||||||
$name {flags: self.flags | rhs.flags }
|
$name (self.0 | rhs.0 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ pub fn vk_bitflags_wrapped_macro() -> Tokens {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitand(self, rhs: $name) -> $name {
|
fn bitand(self, rhs: $name) -> $name {
|
||||||
$name {flags: self.flags & rhs.flags}
|
$name (self.0 & rhs.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ pub fn vk_bitflags_wrapped_macro() -> Tokens {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitxor(self, rhs: $name) -> $name {
|
fn bitxor(self, rhs: $name) -> $name {
|
||||||
$name {flags: self.flags ^ rhs.flags}
|
$name (self.0 ^ rhs.0 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +365,23 @@ impl ConstVal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub trait ConstantExt {
|
||||||
|
fn variant_ident(&self, enum_name: &str) -> Ident;
|
||||||
|
fn to_tokens(&self) -> Tokens;
|
||||||
|
fn notation(&self) -> Option<&str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstantExt for vkxml::Constant {
|
||||||
|
fn variant_ident(&self, enum_name: &str) -> Ident {
|
||||||
|
variant_ident(enum_name, &self.name)
|
||||||
|
}
|
||||||
|
fn to_tokens(&self) -> Tokens {
|
||||||
|
Constant::from_constant(self).to_tokens()
|
||||||
|
}
|
||||||
|
fn notation(&self) -> Option<&str> {
|
||||||
|
self.notation.as_ref().map(|s| s.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
Number(i32),
|
Number(i32),
|
||||||
Hex(String),
|
Hex(String),
|
||||||
|
@ -431,6 +448,27 @@ impl Constant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_extension_enum(constant: &vkxml::ExtensionEnum) -> Self {
|
||||||
|
let number = constant.number.map(|n| Constant::Number(n));
|
||||||
|
let hex = constant.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
||||||
|
let bitpos = constant.bitpos.map(|bit| Constant::BitPos(bit));
|
||||||
|
let expr = constant
|
||||||
|
.c_expression
|
||||||
|
.as_ref()
|
||||||
|
.map(|e| Constant::CExpr(e.clone()));
|
||||||
|
number.or(hex).or(bitpos).or(expr).expect("")
|
||||||
|
}
|
||||||
|
pub fn from_extension_constant(constant: &vkxml::ExtensionConstant) -> Self {
|
||||||
|
let number = constant.number.map(|n| Constant::Number(n));
|
||||||
|
let hex = constant.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
||||||
|
let bitpos = constant.bitpos.map(|bit| Constant::BitPos(bit));
|
||||||
|
let text = constant.text.as_ref().map(|bit| Constant::Text(bit.clone()));
|
||||||
|
let expr = constant
|
||||||
|
.c_expression
|
||||||
|
.as_ref()
|
||||||
|
.map(|e| Constant::CExpr(e.clone()));
|
||||||
|
number.or(hex).or(bitpos).or(expr).or(text).expect("")
|
||||||
|
}
|
||||||
pub fn from_constant(constant: &vkxml::Constant) -> Self {
|
pub fn from_constant(constant: &vkxml::Constant) -> Self {
|
||||||
let number = constant.number.map(|n| Constant::Number(n));
|
let number = constant.number.map(|n| Constant::Number(n));
|
||||||
let hex = constant.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
let hex = constant.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
||||||
|
@ -454,8 +492,6 @@ impl Constant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ConstantExt {}
|
|
||||||
impl ConstantExt for vkxml::Constant {}
|
|
||||||
pub trait FeatureExt {
|
pub trait FeatureExt {
|
||||||
fn version_string(&self) -> String;
|
fn version_string(&self) -> String;
|
||||||
}
|
}
|
||||||
|
@ -723,26 +759,22 @@ fn generate_function_pointers(ident: Ident, commands: &[&vkxml::Command]) -> quo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_extension(extension: &vkxml::Extension, commands: &CommandMap) -> quote::Tokens {
|
pub fn generate_extension(extension: &vkxml::Extension, cmd_map: &CommandMap) -> quote::Tokens {
|
||||||
let extension_commands: Vec<&vkxml::Command> = extension
|
// Don't generate disabled or reserved extensions
|
||||||
|
if extension.disabled {
|
||||||
|
return quote!{};
|
||||||
|
}
|
||||||
|
let cmd_refs = extension
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|extension| {
|
.flat_map(|ext| {
|
||||||
if let &vkxml::ExtensionElement::Require(ref spec) = extension {
|
if let &vkxml::ExtensionElement::Require(ref spec) = ext {
|
||||||
spec.elements
|
spec.elements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|extension_spec| match extension_spec {
|
.filter_map(|extension_spec| match extension_spec {
|
||||||
vkxml::ExtensionSpecificationElement::CommandReference(ref cmd_ref) => {
|
vkxml::ExtensionSpecificationElement::CommandReference(ref cmd_ref) => {
|
||||||
Some(cmd_ref)
|
Some(cmd_ref)
|
||||||
}
|
}
|
||||||
vkxml::ExtensionSpecificationElement::Constant(ref field) => {
|
|
||||||
//println!("EXT {:?}", field);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
vkxml::ExtensionSpecificationElement::Enum(ref field) => {
|
|
||||||
//println!("Enum {:?}", field);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -750,15 +782,44 @@ pub fn generate_extension(extension: &vkxml::Extension, commands: &CommandMap) -
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter_map(|cmd_ref| commands.get(&cmd_ref.name))
|
.collect_vec();
|
||||||
.map(|&cmd| cmd)
|
let commands = cmd_refs
|
||||||
.collect();
|
.iter()
|
||||||
if extension_commands.is_empty() {
|
.filter_map(|cmd_ref| cmd_map.get(&cmd_ref.name).map(|c| *c))
|
||||||
return quote!{};
|
.collect_vec();
|
||||||
}
|
|
||||||
let name = format!("{}Fn", extension.name.to_camel_case());
|
let name = format!("{}Fn", extension.name.to_camel_case());
|
||||||
let ident = Ident::from(&name[2..]);
|
let ident = Ident::from(&name[2..]);
|
||||||
generate_function_pointers(ident, &extension_commands)
|
let fp = generate_function_pointers(ident, &commands);
|
||||||
|
let extension_enums = extension
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.flat_map(|ext| {
|
||||||
|
if let &vkxml::ExtensionElement::Require(ref spec) = ext {
|
||||||
|
spec.elements
|
||||||
|
.iter()
|
||||||
|
.filter_map(|extension_spec| match extension_spec {
|
||||||
|
vkxml::ExtensionSpecificationElement::Enum(ref _enum) => {
|
||||||
|
Some(_enum)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
let variants = extension_enums.iter().map(|&constant|{
|
||||||
|
let c = Constant::from_extension_enum(constant);
|
||||||
|
let variant_ident = variant_ident(&constant.name, &constant.name);
|
||||||
|
(variant_ident, c.to_tokens())
|
||||||
|
});
|
||||||
|
println!("{:?}", extension_enums);
|
||||||
|
//let enum_tokens = im
|
||||||
|
quote!{
|
||||||
|
#fp
|
||||||
|
//#(#enum_tokens)*
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_typedef(typedef: &vkxml::Typedef) -> Tokens {
|
pub fn generate_typedef(typedef: &vkxml::Typedef) -> Tokens {
|
||||||
let typedef_name = to_type_tokens(&typedef.name, None);
|
let typedef_name = to_type_tokens(&typedef.name, None);
|
||||||
|
@ -782,7 +843,7 @@ pub fn generate_bitmask(bitmask: &vkxml::Bitmask) -> Option<Tokens> {
|
||||||
Some(quote!{
|
Some(quote!{
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct #ident {flags: Flags}
|
pub struct #ident(Flags);
|
||||||
vk_bitflags_wrapped!(#ident, 0b0, Flags);
|
vk_bitflags_wrapped!(#ident, 0b0, Flags);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -820,12 +881,15 @@ pub enum EnumType {
|
||||||
Enum(Tokens),
|
Enum(Tokens),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn variant_ident(_enum: &vkxml::Enumeration, variant_name: &str) -> Ident {
|
pub fn variant_ident(enum_name: &str, variant_name: &str) -> Ident {
|
||||||
let _name = _enum.name.split("FlagBits").nth(0).expect("split");
|
let _name = enum_name.split("FlagBits").nth(0).expect("split");
|
||||||
let struct_name = _name.to_shouty_snake_case();
|
let struct_name = _name.to_shouty_snake_case();
|
||||||
let new_variant_name = variant_name.replace(&struct_name, "").replace("VK", "");
|
let new_variant_name = variant_name.replace(&struct_name, "").replace("VK", "");
|
||||||
// Not every variant in the vk.xml has a correct shouty snake case name
|
// Not every variant in the vk.xml has a correct shouty snake case name
|
||||||
let new_variant_name = new_variant_name.trim_matches('_').to_shouty_snake_case();
|
let new_variant_name = new_variant_name
|
||||||
|
.trim_matches('_')
|
||||||
|
.to_shouty_snake_case()
|
||||||
|
.replace("_BIT", "");
|
||||||
let is_digit = new_variant_name
|
let is_digit = new_variant_name
|
||||||
.chars()
|
.chars()
|
||||||
.nth(0)
|
.nth(0)
|
||||||
|
@ -838,6 +902,43 @@ pub fn variant_ident(_enum: &vkxml::Enumeration, variant_name: &str) -> Ident {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bitflags_impl_block(
|
||||||
|
ident: &Ident,
|
||||||
|
_enum: &vkxml::Enumeration,
|
||||||
|
constants: &[& impl ConstantExt],
|
||||||
|
) -> Tokens {
|
||||||
|
let variants = constants
|
||||||
|
.iter()
|
||||||
|
.map(|constant| {
|
||||||
|
let variant_ident = constant.variant_ident(&_enum.name);
|
||||||
|
let tokens = constant.to_tokens();
|
||||||
|
(variant_ident, tokens)
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let notations = constants.iter().map(|constant| {
|
||||||
|
constant.notation().map(|n| {
|
||||||
|
quote!{
|
||||||
|
#[doc = #n]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let variants = variants.iter().zip(notations.clone()).map(
|
||||||
|
|((variant_ident, value), ref notation)| {
|
||||||
|
quote!{
|
||||||
|
#notation
|
||||||
|
pub const #variant_ident: Self = #ident(#value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
quote!{
|
||||||
|
impl #ident {
|
||||||
|
#(#variants)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_enum(
|
pub fn generate_enum(
|
||||||
_enum: &vkxml::Enumeration,
|
_enum: &vkxml::Enumeration,
|
||||||
create_info_constants: &[&vkxml::Constant],
|
create_info_constants: &[&vkxml::Constant],
|
||||||
|
@ -845,68 +946,39 @@ pub fn generate_enum(
|
||||||
let name = &_enum.name[2..];
|
let name = &_enum.name[2..];
|
||||||
let _name = name.replace("FlagBits", "Flags");
|
let _name = name.replace("FlagBits", "Flags");
|
||||||
let ident = Ident::from(_name.as_str());
|
let ident = Ident::from(_name.as_str());
|
||||||
let variants = _enum
|
let constants: Vec<_> = _enum
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|elem| {
|
.filter_map(|elem| match *elem {
|
||||||
let (variant_name, value) = match *elem {
|
vkxml::EnumerationElement::Enum(ref constant) => Some(constant),
|
||||||
vkxml::EnumerationElement::Enum(ref constant) => {
|
|
||||||
let c = Constant::from_constant(constant);
|
|
||||||
(constant.name.as_str(), c.to_tokens())
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let variant_ident = variant_ident(_enum, variant_name);
|
|
||||||
Some((variant_ident, value))
|
|
||||||
})
|
|
||||||
.collect_vec();
|
|
||||||
if name.contains("Bit") {
|
|
||||||
let ident = Ident::from(_name.as_str());
|
|
||||||
let all_bits = _enum
|
|
||||||
.elements
|
|
||||||
.iter()
|
|
||||||
.filter_map(|elem| match elem {
|
|
||||||
vkxml::EnumerationElement::Enum(ref constant) => {
|
|
||||||
let c = Constant::from_constant(constant);
|
|
||||||
c.value()
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
if name.contains("Bit") {
|
||||||
|
let ident = Ident::from(_name.as_str());
|
||||||
|
let all_bits = constants
|
||||||
|
.iter()
|
||||||
|
.filter_map(|constant| Constant::from_constant(constant).value())
|
||||||
.fold(0, |acc, next| acc | next.bits());
|
.fold(0, |acc, next| acc | next.bits());
|
||||||
let all_bits_term = Term::intern(&format!("0b{:b}", all_bits));
|
let all_bits_term = Term::intern(&format!("0b{:b}", all_bits));
|
||||||
|
|
||||||
let variants = variants.iter().map(|(variant_ident, value)| {
|
let impl_bitflags = bitflags_impl_block(&ident, _enum, &constants);
|
||||||
quote!{
|
|
||||||
pub const #variant_ident: Self = #ident { flags: #value }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let q = quote!{
|
let q = quote!{
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct #ident {flags: Flags}
|
pub struct #ident(Flags);
|
||||||
vk_bitflags_wrapped!(#ident, #all_bits_term, Flags);
|
vk_bitflags_wrapped!(#ident, #all_bits_term, Flags);
|
||||||
impl #ident {
|
#impl_bitflags
|
||||||
#(#variants;)*
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
EnumType::Bitflags(q)
|
EnumType::Bitflags(q)
|
||||||
} else {
|
} else {
|
||||||
let variants = variants.iter().map(|(variant_ident, value)| {
|
let impl_block = bitflags_impl_block(&ident, _enum, &constants);
|
||||||
quote!{
|
|
||||||
pub const #variant_ident: Self = #ident(#value)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let enum_quote = quote!{
|
let enum_quote = quote!{
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct #ident(pub i32);
|
pub struct #ident(pub i32);
|
||||||
impl #ident {
|
#impl_block
|
||||||
#(
|
|
||||||
#variants;
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let special_quote = match _name.as_str() {
|
let special_quote = match _name.as_str() {
|
||||||
//"StructureType" => generate_structure_type(&_name, _enum, create_info_constants),
|
//"StructureType" => generate_structure_type(&_name, _enum, create_info_constants),
|
||||||
|
@ -936,7 +1008,7 @@ pub fn generate_result(ident: &Ident, _enum: &vkxml::Enumeration) -> Tokens {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let variant_ident = variant_ident(_enum, variant_name);
|
let variant_ident = variant_ident(&_enum.name, variant_name);
|
||||||
Some(quote!{
|
Some(quote!{
|
||||||
#ident::#variant_ident => write!(fmt, #notation)
|
#ident::#variant_ident => write!(fmt, #notation)
|
||||||
})
|
})
|
||||||
|
@ -1025,9 +1097,16 @@ pub fn generate_handle(handle: &vkxml::Handle) -> Option<Tokens> {
|
||||||
fn generate_funcptr(fnptr: &vkxml::FunctionPointer) -> Tokens {
|
fn generate_funcptr(fnptr: &vkxml::FunctionPointer) -> Tokens {
|
||||||
let name = Ident::from(fnptr.name.as_str());
|
let name = Ident::from(fnptr.name.as_str());
|
||||||
let ret_ty_tokens = fnptr.return_type.type_tokens();
|
let ret_ty_tokens = fnptr.return_type.type_tokens();
|
||||||
|
let params = fnptr.param.iter().map(|field| {
|
||||||
|
let ident = field.param_ident();
|
||||||
|
let type_tokens = field.type_tokens();
|
||||||
|
quote!{
|
||||||
|
#ident: #type_tokens
|
||||||
|
}
|
||||||
|
});
|
||||||
quote!{
|
quote!{
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type #name = unsafe extern "system" fn() -> #ret_ty_tokens;
|
pub type #name = unsafe extern "system" fn(#(#params),*) -> #ret_ty_tokens;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,6 +1212,10 @@ pub fn generate_constant(constant: &vkxml::Constant) -> Tokens {
|
||||||
let value = c.to_tokens();
|
let value = c.to_tokens();
|
||||||
let ty = c.ty().to_tokens();
|
let ty = c.ty().to_tokens();
|
||||||
quote!{
|
quote!{
|
||||||
|
// pub mod constants {
|
||||||
|
// pub const #ident: #ty = #value;
|
||||||
|
// }
|
||||||
|
//pub use constants::*;
|
||||||
pub const #ident: #ty = #value;
|
pub const #ident: #ty = #value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue