1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use super::get_pgx_attr_macro;
use crate::sql_entity_graph::NameMacro;
use proc_macro2::TokenStream as TokenStream2;
use quote::ToTokens;
use syn::{
parse::{Parse, ParseStream},
parse_quote, Expr, Type,
};
#[derive(Debug, Clone)]
pub struct AggregateTypeList {
pub found: Vec<AggregateType>,
pub original: syn::Type,
}
impl AggregateTypeList {
pub fn new(maybe_type_list: syn::Type) -> Result<Self, syn::Error> {
match &maybe_type_list {
Type::Tuple(tuple) => {
let mut coll = Vec::new();
for elem in &tuple.elems {
let parsed_elem = AggregateType::new(elem.clone())?;
coll.push(parsed_elem);
}
Ok(Self {
found: coll,
original: maybe_type_list,
})
}
ty => Ok(Self {
found: vec![AggregateType::new(ty.clone())?],
original: maybe_type_list,
}),
}
}
pub fn entity_tokens(&self) -> Expr {
let found = self.found.iter().map(|x| x.entity_tokens());
parse_quote! {
vec![#(#found),*]
}
}
}
impl Parse for AggregateTypeList {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
Self::new(input.parse()?)
}
}
impl ToTokens for AggregateTypeList {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.original.to_tokens(tokens)
}
}
#[derive(Debug, Clone)]
pub struct AggregateType {
pub ty: Type,
pub name: Option<String>,
}
impl AggregateType {
pub fn new(ty: syn::Type) -> Result<Self, syn::Error> {
let name_tokens = get_pgx_attr_macro("name", &ty);
let name = match name_tokens {
Some(tokens) => {
let name_macro =
syn::parse2::<NameMacro>(tokens).expect("Could not parse `name!()` macro");
Some(name_macro.ident)
}
None => None,
};
let retval = Self { name, ty };
Ok(retval)
}
pub fn entity_tokens(&self) -> Expr {
let ty = &self.ty;
let ty_string = ty.to_token_stream().to_string().replace(" ", "");
let name = self.name.iter();
parse_quote! {
::pgx::utils::sql_entity_graph::AggregateTypeEntity {
ty_source: #ty_string,
ty_id: core::any::TypeId::of::<#ty>(),
full_path: core::any::type_name::<#ty>(),
name: None #( .unwrap_or(Some(#name)) )*,
}
}
}
}
impl ToTokens for AggregateType {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.ty.to_tokens(tokens)
}
}
impl Parse for AggregateType {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
Self::new(input.parse()?)
}
}