macro: allow optional option parameters

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-11-24 20:59:27 +01:00
parent 5491907876
commit 4dc236a2d4
2 changed files with 43 additions and 7 deletions

View File

@ -49,7 +49,6 @@ elsewhere.
Pending Changes before 1.0 Pending Changes before 1.0
========================== ==========================
* Don't export non-bootstrap methods anymore, we don't need them.
* Make some kind of perl-package-generation tool for generating the `.pm` * Make some kind of perl-package-generation tool for generating the `.pm`
files, we only need to call bootstrap functions after all. files, we only need to call bootstrap functions after all.
(So we may not even need to parse the rust code, rather, just provide a list (So we may not even need to parse the rust code, rather, just provide a list

View File

@ -118,14 +118,22 @@ pub fn handle_function(
arg_name.span(), arg_name.span(),
); );
extract_arguments.extend(quote! { let none_handling = if is_option_type(arg_type).is_some() {
let #extracted_name: ::perlmod::Value = match args.next() { quote! { ::perlmod::Value::new_undef(), }
Some(arg) => ::perlmod::Value::from(arg), } else {
None => { quote! {
{
return Err(::perlmod::Value::new_string(#missing_message) return Err(::perlmod::Value::new_string(#missing_message)
.into_mortal() .into_mortal()
.into_raw()); .into_raw());
} }
}
};
extract_arguments.extend(quote! {
let #extracted_name: ::perlmod::Value = match args.next() {
Some(arg) => ::perlmod::Value::from(arg),
None => #none_handling
}; };
}); });
@ -456,8 +464,8 @@ pub fn is_result_type(ty: &syn::Type) -> Option<&syn::Type> {
} }
let segs = &p.path.segments; let segs = &p.path.segments;
let is_result = match segs.len() { let is_result = match segs.len() {
1 => segs.last().unwrap().ident == "Result", 1 => segs[0].ident == "Result",
2 => segs.first().unwrap().ident == "std" && segs.last().unwrap().ident == "Result", 3 => segs[0].ident == "std" && segs[1].ident == "result" && segs[2].ident == "Result",
_ => false, _ => false,
}; };
if !is_result { if !is_result {
@ -491,3 +499,32 @@ pub fn get_result_type(ty: &syn::Type) -> (&syn::Type, bool) {
fn simple_usize(i: usize, span: Span) -> syn::LitInt { fn simple_usize(i: usize, span: Span) -> syn::LitInt {
syn::LitInt::new(&format!("{}", i), span) syn::LitInt::new(&format!("{}", i), span)
} }
/// Note that we cannot handle renamed imports at all here...
pub fn is_option_type(ty: &syn::Type) -> Option<&syn::Type> {
if let syn::Type::Path(p) = ty {
if p.qself.is_some() {
return None;
}
let segs = &p.path.segments;
let is_option = match segs.len() {
1 => segs[0].ident == "Option",
3 => segs[0].ident == "std" && segs[1].ident == "option" && segs[2].ident == "Option",
_ => false,
};
if !is_option {
return None;
}
if let syn::PathArguments::AngleBracketed(generic) = &segs.last().unwrap().arguments {
if generic.args.len() != 1 {
return None;
}
if let syn::GenericArgument::Type(ty) = generic.args.first().unwrap() {
return Some(ty);
}
}
}
None
}