pgx_sql_entity_graph/pg_extern/
argument.rs

1/*
2Portions Copyright 2019-2021 ZomboDB, LLC.
3Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <support@tcdi.com>
4
5All rights reserved.
6
7Use of this source code is governed by the MIT license that can be found in the LICENSE file.
8*/
9/*!
10
11`#[pg_extern]` related argument macro expansion for Rust to SQL translation
12
13> Like all of the [`sql_entity_graph`][crate::pgx_sql_entity_graph] APIs, this is considered **internal**
14to the `pgx` framework and very subject to change between versions. While you may use this, please do it with caution.
15
16*/
17use crate::UsedType;
18use proc_macro2::{Span, TokenStream as TokenStream2};
19use quote::{quote, ToTokens, TokenStreamExt};
20use syn::{FnArg, Pat};
21
22/// A parsed `#[pg_extern]` argument.
23///
24/// It is created during [`PgExtern`](crate::PgExtern) parsing.
25#[derive(Debug, Clone)]
26pub struct PgExternArgument {
27    pub fn_arg: syn::FnArg,
28    pub pat: syn::Ident,
29    pub used_ty: UsedType,
30}
31
32impl PgExternArgument {
33    pub fn build(fn_arg: FnArg) -> Result<Self, syn::Error> {
34        match &fn_arg {
35            syn::FnArg::Typed(pat) => Self::build_from_pat_type(fn_arg.clone(), pat.clone()),
36            syn::FnArg::Receiver(_) => {
37                Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg that is Self"))
38            }
39        }
40    }
41
42    pub fn build_from_pat_type(
43        fn_arg: syn::FnArg,
44        value: syn::PatType,
45    ) -> Result<Self, syn::Error> {
46        let identifier = match *value.pat {
47            Pat::Ident(ref p) => p.ident.clone(),
48            Pat::Reference(ref p_ref) => match *p_ref.pat {
49                Pat::Ident(ref inner_ident) => inner_ident.ident.clone(),
50                _ => return Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg")),
51            },
52            _ => return Err(syn::Error::new(Span::call_site(), "Unable to parse FnArg")),
53        };
54
55        let used_ty = UsedType::new(*value.ty)?;
56
57        Ok(PgExternArgument { fn_arg, pat: identifier, used_ty })
58    }
59
60    pub fn entity_tokens(&self) -> TokenStream2 {
61        let pat = &self.pat;
62        let used_ty_entity = self.used_ty.entity_tokens();
63
64        let quoted = quote! {
65            ::pgx::pgx_sql_entity_graph::PgExternArgumentEntity {
66                pattern: stringify!(#pat),
67                used_ty: #used_ty_entity,
68            }
69        };
70        quoted
71    }
72}
73
74impl ToTokens for PgExternArgument {
75    fn to_tokens(&self, tokens: &mut TokenStream2) {
76        let fn_arg = &self.fn_arg;
77        let quoted = quote! {
78            #fn_arg
79        };
80        tokens.append_all(quoted);
81    }
82}