diff options
Diffstat (limited to 'codegen/command/functions.rs')
-rw-r--r-- | codegen/command/functions.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/codegen/command/functions.rs b/codegen/command/functions.rs new file mode 100644 index 0000000..6d1a3d3 --- /dev/null +++ b/codegen/command/functions.rs @@ -0,0 +1,62 @@ +use std::error::Error; +use std::str::FromStr; + +use opengl_registry::command::Command; +use proc_macro2::{LexError, TokenStream}; +use quote::{format_ident, quote}; + +use crate::codegen::formatting::{clean_param_name, fix_type}; + +pub fn create_command_functions( + commands: &[Command], +) -> Result<Vec<TokenStream>, Box<dyn Error>> +{ + commands.iter().map(|command| { + let command_name_str = command.prototype().name(); + + let command_name = format_ident!("{}", command.prototype().name()); + + let command_name_prefixless = format_ident!("{}", command.prototype() + .name() + .strip_prefix("gl") + .unwrap_or_else(|| command.prototype().name())); + + let command_args = command + .parameters() + .iter() + .map(|param| { + let param_name = format_ident!("{}", clean_param_name(param.name())); + + let param_type = TokenStream::from_str(&fix_type(param.get_type()))?; + + Ok::<_, LexError>(quote! { #param_name: #param_type }) + }).collect::<Result<Vec<_>, _>>()?; + + let command_return_type = TokenStream::from_str(&fix_type(command.prototype().return_type()))?; + + let command_arg_types = command + .parameters() + .iter() + .map(|param| TokenStream::from_str(&fix_type(param.get_type()))) + .collect::<Result<Vec<_>, _>>()?; + + let command_arg_names = command + .parameters() + .iter() + .map(|param| format_ident!("{}", clean_param_name(param.name()))) + .collect::<Vec<_>>(); + + Ok(quote! { + #[doc = #command_name_str] + #[allow(non_snake_case, clippy::too_many_arguments)] + pub unsafe fn #command_name_prefixless(#(#command_args),*) -> #command_return_type { + type GLFunc = + unsafe extern "C" fn(#(#command_arg_types),*) -> #command_return_type; + + let gl_func = std::mem::transmute::<_, GLFunc>(functions::#command_name); + + gl_func(#(#command_arg_names),*) + } + }) + }).collect() +} |