Merge pull request #99 from Ralith/display

impl Display for constants
This commit is contained in:
Maik Klein 2018-08-20 07:32:20 +02:00 committed by GitHub
commit 071fe412c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 3166 additions and 216 deletions

File diff suppressed because it is too large Load diff

12
ash/tests/display.rs Normal file
View file

@ -0,0 +1,12 @@
extern crate ash;
use ash::vk;
#[test]
fn display_flags() {
assert_eq!((vk::AccessFlags::INDIRECT_COMMAND_READ | vk::AccessFlags::VERTEX_ATTRIBUTE_READ).to_string(), "INDIRECT_COMMAND_READ | VERTEX_ATTRIBUTE_READ");
}
#[test]
fn display_enum() {
assert_eq!(vk::ChromaLocation::MIDPOINT.to_string(), "MIDPOINT");
}

View file

@ -786,6 +786,7 @@ pub fn generate_extension_constants<'a>(
extension_number: i64, extension_number: i64,
extension_items: &'a [vk_parse::ExtensionItem], extension_items: &'a [vk_parse::ExtensionItem],
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>,
) -> quote::Tokens { ) -> quote::Tokens {
let items = extension_items let items = extension_items
.iter() .iter()
@ -819,13 +820,14 @@ pub fn generate_extension_constants<'a>(
} }
_ => None, _ => None,
}?; }?;
let extends = extends?; let extends = extends?;
let ext_constant = ExtensionConstant { let ext_constant = ExtensionConstant {
name: &_enum.name, name: &_enum.name,
constant, constant,
}; };
let ident = name_to_tokens(&extends); let ident = name_to_tokens(&extends);
const_values.entry(ident.clone()).or_insert_with(Vec::new)
.push(ext_constant.variant_ident(&extends));
let impl_block = bitflags_impl_block(ident, &extends, &[&ext_constant]); let impl_block = bitflags_impl_block(ident, &extends, &[&ext_constant]);
let doc_string = format!("Generated from '{}'", extension_name); let doc_string = format!("Generated from '{}'", extension_name);
let q = quote!{ let q = quote!{
@ -867,6 +869,7 @@ pub fn generate_extension<'a>(
extension: &'a vk_parse::Extension, extension: &'a vk_parse::Extension,
cmd_map: &CommandMap, cmd_map: &CommandMap,
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
) -> Option<quote::Tokens> { ) -> Option<quote::Tokens> {
// Okay this is a little bit odd. We need to generate all extensions, even disabled ones, // Okay this is a little bit odd. We need to generate all extensions, even disabled ones,
// because otherwise some StructureTypes won't get generated. But we don't generate extensions // because otherwise some StructureTypes won't get generated. But we don't generate extensions
@ -879,6 +882,7 @@ pub fn generate_extension<'a>(
extension.number.unwrap_or(0), extension.number.unwrap_or(0),
&extension.items, &extension.items,
const_cache, const_cache,
const_values,
); );
let fp = generate_extension_commands(&extension.name, &extension.items, cmd_map); let fp = generate_extension_commands(&extension.name, &extension.items, cmd_map);
let q = quote!{ let q = quote!{
@ -991,6 +995,7 @@ pub fn bitflags_impl_block(
pub fn generate_enum<'a>( pub fn generate_enum<'a>(
_enum: &'a vkxml::Enumeration, _enum: &'a vkxml::Enumeration,
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
) -> EnumType { ) -> EnumType {
let name = &_enum.name[2..]; let name = &_enum.name[2..];
let _name = name.replace("FlagBits", "Flags"); let _name = name.replace("FlagBits", "Flags");
@ -1002,8 +1007,10 @@ pub fn generate_enum<'a>(
vkxml::EnumerationElement::Enum(ref constant) => Some(constant), vkxml::EnumerationElement::Enum(ref constant) => Some(constant),
_ => None, _ => None,
}).collect_vec(); }).collect_vec();
let values = const_values.entry(ident.clone()).or_insert_with(Vec::new);
for constant in &constants { for constant in &constants {
const_cache.insert(constant.name.as_str()); const_cache.insert(constant.name.as_str());
values.push(constant.variant_ident(&_enum.name));
} }
if name.contains("Bit") { if name.contains("Bit") {
@ -1061,22 +1068,31 @@ pub fn generate_result(ident: Ident, _enum: &vkxml::Enumeration) -> Tokens {
let variant_ident = variant_ident(&_enum.name, variant_name); let variant_ident = variant_ident(&_enum.name, variant_name);
Some(quote!{ Some(quote!{
#ident::#variant_ident => write!(fmt, #notation) #ident::#variant_ident => Some(#notation)
}) })
}); });
let notation2 = notation.clone();
quote!{ quote!{
impl ::std::error::Error for #ident { impl ::std::error::Error for #ident {
fn description(&self) -> &str { fn description(&self) -> &str {
"vk::Result" let name = match *self {
#(#notation),*,
_ => None,
};
name.unwrap_or("unknown error")
} }
} }
impl ::std::fmt::Display for #ident { impl fmt::Display for #ident {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
writeln!(fmt, "vk::Result::{:?}", self)?; let name = match *self {
match *self { #(#notation2),*,
#(#notation),*, _ => None,
_ => write!(fmt, "Unknown variant") };
if let Some(x) = name {
fmt.write_str(x)
} else {
write!(fmt, "{}", self.0)
} }
} }
} }
@ -1447,10 +1463,11 @@ pub fn generate_constant<'a>(
pub fn generate_feature_extension<'a>( pub fn generate_feature_extension<'a>(
registry: &'a vk_parse::Registry, registry: &'a vk_parse::Registry,
const_cache: &mut HashSet<&'a str>, const_cache: &mut HashSet<&'a str>,
const_values: &mut HashMap<Ident, Vec<Ident>>
) -> Tokens { ) -> Tokens {
let constants = registry.0.iter().filter_map(|item| match item { let constants = registry.0.iter().filter_map(|item| match item {
vk_parse::RegistryItem::Feature { name, items, .. } => { vk_parse::RegistryItem::Feature { name, items, .. } => {
Some(generate_extension_constants(name, 0, items, const_cache)) Some(generate_extension_constants(name, 0, items, const_cache, const_values))
} }
_ => None, _ => None,
}); });
@ -1459,6 +1476,68 @@ pub fn generate_feature_extension<'a>(
} }
} }
pub fn generate_const_displays<'a>(const_values: &HashMap<Ident, Vec<Ident>>) -> Tokens {
let impls = const_values.iter()
.filter(|(ty, _)| *ty != "Result")
.map(|(ty, values)| {
if ty.to_string().contains("Flags") {
let cases = values.iter().map(|value| {
let name = value.to_string();
quote!{ (#ty::#value.0, #name) }
});
quote!{
impl fmt::Display for #ty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
const KNOWN: &[(Flags, &str)] = &[#(#cases),*];
display_flags(f, KNOWN, self.0)
}
}
}
} else {
let cases = values.iter().map(|value| {
let name = value.to_string();
quote!{ Self::#value => Some(#name), }
});
quote!{
impl fmt::Display for #ty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let name = match *self {
#(#cases)*
_ => None,
};
if let Some(x) = name {
f.write_str(x)
} else {
write!(f, "{}", self.0)
}
}
}
}
}
});
quote!{
fn display_flags(f: &mut fmt::Formatter, known: &[(Flags, &'static str)], value: Flags) -> fmt::Result {
let mut first = true;
let mut accum = value;
for (bit, name) in known {
if accum & bit != 0 {
if !first { f.write_str(" | ")?; }
f.write_str(name)?;
first = false;
accum &= !bit;
}
}
if accum != 0 {
if !first { f.write_str(" | ")?; }
write!(f, "{:b}", accum)?;
}
Ok(())
}
#(#impls)*
}
}
pub fn write_source_code(path: &Path) { pub fn write_source_code(path: &Path) {
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
@ -1523,9 +1602,12 @@ pub fn write_source_code(path: &Path) {
.collect(); .collect();
let mut const_cache = HashSet::new(); let mut const_cache = HashSet::new();
let mut const_values: HashMap<Ident, Vec<Ident>> = HashMap::new();
let (enum_code, bitflags_code) = enums let (enum_code, bitflags_code) = enums
.into_iter() .into_iter()
.map(|e| generate_enum(e, &mut const_cache)) .map(|e| generate_enum(e, &mut const_cache, &mut const_values))
.fold((Vec::new(), Vec::new()), |mut acc, elem| { .fold((Vec::new(), Vec::new()), |mut acc, elem| {
match elem { match elem {
EnumType::Enum(token) => acc.0.push(token), EnumType::Enum(token) => acc.0.push(token),
@ -1533,13 +1615,14 @@ pub fn write_source_code(path: &Path) {
}; };
acc acc
}); });
let constants_code: Vec<_> = constants let constants_code: Vec<_> = constants
.iter() .iter()
.map(|constant| generate_constant(constant, &mut const_cache)) .map(|constant| generate_constant(constant, &mut const_cache))
.collect(); .collect();
let extension_code = extensions let extension_code = extensions
.iter() .iter()
.filter_map(|ext| generate_extension(ext, &commands, &mut const_cache)) .filter_map(|ext| generate_extension(ext, &commands, &mut const_cache, &mut const_values))
.collect_vec(); .collect_vec();
let union_types = definitions let union_types = definitions
@ -1558,7 +1641,9 @@ pub fn write_source_code(path: &Path) {
.iter() .iter()
.map(|feature| generate_feature(feature, &commands)) .map(|feature| generate_feature(feature, &commands))
.collect(); .collect();
let feature_extensions_code = generate_feature_extension(&spec2, &mut const_cache); let feature_extensions_code = generate_feature_extension(&spec2, &mut const_cache, &mut const_values);
let const_displays = generate_const_displays(&const_values);
let mut file = File::create("../ash/src/vk.rs").expect("vk"); let mut file = File::create("../ash/src/vk.rs").expect("vk");
let bitflags_macro = vk_bitflags_wrapped_macro(); let bitflags_macro = vk_bitflags_wrapped_macro();
@ -1567,6 +1652,7 @@ pub fn write_source_code(path: &Path) {
let version_macros = vk_version_macros(); let version_macros = vk_version_macros();
let platform_specific_types = platform_specific_types(); let platform_specific_types = platform_specific_types();
let source_code = quote!{ let source_code = quote!{
use std::fmt;
#[doc(hidden)] #[doc(hidden)]
pub use libc::*; pub use libc::*;
#[doc(hidden)] #[doc(hidden)]
@ -1598,6 +1684,7 @@ pub fn write_source_code(path: &Path) {
#(#extension_code)* #(#extension_code)*
#feature_extensions_code #feature_extensions_code
} }
#const_displays
}; };
write!(&mut file, "{}", source_code).expect("Unable to write to file"); write!(&mut file, "{}", source_code).expect("Unable to write to file");
} }