support Option<T> arguments
@@ -257,18 +257,38 @@ impl FunctionSignatureRewriter {
let mut stream = proc_macro2::TokenStream::new();
let mut i = 0usize;
+ let mut have_option = false;
for arg in &self.func.sig.inputs {
match arg {
FnArg::Receiver(_) => panic!("Functions that take self are not supported"),
- FnArg::Typed(ty) => match ty.pat.deref() {
+ FnArg::Typed(ty) => {
+ match ty.pat.deref() {
Pat::Ident(ident) => {
let name = &ident.ident;
let type_ = &ty.ty;
+ let is_option = type_matches(type_, "Option");
+
+ let ts = if is_option {
+ have_option = true;
- let ts = quote_spanned! {ident.span()=>
+ let option_type = extract_option_type(type_);
+ quote_spanned! {ident.span()=>
+ let #name = if pg_arg_is_null(fcinfo, #i) {
+ None
+ } else {
+ Some(pg_bridge::pg_getarg::#option_type(fcinfo, #i).try_into()
+ .expect(&format!("argument '{}'", stringify! { #name })))
+ };
+ }
+ } else {
+ if have_option {
+ panic!("If one argument is Option<T>, all arguments must be Option<T>")
+ }
+ quote_spanned! {ident.span()=>
let #name: #type_ =
pg_bridge::pg_getarg::<#type_>(fcinfo, #i).try_into()
- .expect(&format!("argument '{}'", stringify! { #name }));
+ .expect(&format!("argument '{}'", stringify! { #name }))
+ }
};
stream.extend(ts);
@@ -276,7 +296,8 @@ impl FunctionSignatureRewriter {
i += 1;
}
_ => panic!("Unrecognized function arg type"),
- },
+ }
+ }
}
}
@@ -300,3 +321,19 @@ fn type_matches(ty: &Box<Type>, pattern: &str) -> bool {
_ => false,
}
}
+
+fn extract_option_type(ty: &Box<Type>) -> proc_macro2::TokenStream {
+ match ty.deref() {
+ Type::Path(path) => {
+ let mut stream = proc_macro2::TokenStream::new();
+ for segment in &path.path.segments {
+ let arguments = &segment.arguments;
+
+ stream.extend(quote! { #arguments });
+ }
+
+ stream
+ }
+ _ => panic!("No type found inside Option"),
+ }
+}
