1 // Copyright (c) 2022 The Vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9
10 use super::{write_file, VkRegistryData};
11 use heck::ToUpperCamelCase;
12 use proc_macro2::{Ident, TokenStream};
13 use quote::{format_ident, quote};
14
write(vk_data: &VkRegistryData)15 pub fn write(vk_data: &VkRegistryData) {
16 write_file(
17 "errors.rs",
18 format!(
19 "vk.xml header version {}.{}.{}",
20 vk_data.header_version.0, vk_data.header_version.1, vk_data.header_version.2
21 ),
22 errors_output(&errors_members(&vk_data.errors)),
23 );
24 }
25
26 #[derive(Clone, Debug)]
27 struct ErrorsMember {
28 name: Ident,
29 ffi_name: Ident,
30 }
31
errors_output(members: &[ErrorsMember]) -> TokenStream32 fn errors_output(members: &[ErrorsMember]) -> TokenStream {
33 let enum_items = members.iter().map(|ErrorsMember { name, .. }| {
34 quote! { #name, }
35 });
36 let try_from_items = members.iter().map(|ErrorsMember { name, ffi_name }| {
37 quote! { ash::vk::Result::#ffi_name => Self::#name, }
38 });
39
40 quote! {
41 /// An enumeration of runtime errors that can be returned by Vulkan.
42 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
43 #[repr(i32)]
44 #[non_exhaustive]
45 pub enum VulkanError {
46 #(#enum_items)*
47 Unnamed(ash::vk::Result),
48 }
49
50 impl From<ash::vk::Result> for VulkanError {
51 fn from(val: ash::vk::Result) -> VulkanError {
52 match val {
53 #(#try_from_items)*
54 x => Self::Unnamed(x),
55 }
56 }
57 }
58 }
59 }
60
errors_members(errors: &[&str]) -> Vec<ErrorsMember>61 fn errors_members(errors: &[&str]) -> Vec<ErrorsMember> {
62 errors
63 .iter()
64 .map(|error| {
65 let ffi_name = error.strip_prefix("VK_").unwrap();
66
67 let mut parts = ffi_name.split('_').collect::<Vec<_>>();
68
69 assert!(parts[0] == "ERROR");
70 parts.remove(0);
71
72 if ["EXT", "KHR", "NV"].contains(parts.last().unwrap()) {
73 parts.pop();
74 }
75
76 let name = parts.join("_").to_upper_camel_case();
77
78 ErrorsMember {
79 name: format_ident!("{}", name),
80 ffi_name: format_ident!("{}", ffi_name),
81 }
82 })
83 .collect()
84 }
85