postgres_derive/
accepts.rs

1use proc_macro2::{Span, TokenStream};
2use quote::quote;
3use std::iter;
4use syn::Ident;
5
6use crate::composites::Field;
7use crate::enums::Variant;
8
9pub fn transparent_body(field: &syn::Field) -> TokenStream {
10    let ty = &field.ty;
11
12    quote! {
13        <#ty as ::postgres_types::ToSql>::accepts(type_)
14    }
15}
16
17pub fn domain_body(name: &str, field: &syn::Field) -> TokenStream {
18    let ty = &field.ty;
19
20    quote! {
21        if type_.name() != #name {
22            return false;
23        }
24
25        match *type_.kind() {
26            ::postgres_types::Kind::Domain(ref type_) => {
27                <#ty as ::postgres_types::ToSql>::accepts(type_)
28            }
29            _ => false,
30        }
31    }
32}
33
34pub fn enum_body(name: &str, variants: &[Variant], allow_mismatch: bool) -> TokenStream {
35    let num_variants = variants.len();
36    let variant_names = variants.iter().map(|v| &v.name);
37
38    if allow_mismatch {
39        quote! {
40            type_.name() == #name
41        }
42    } else {
43        quote! {
44            if type_.name() != #name {
45                return false;
46            }
47
48            match *type_.kind() {
49                ::postgres_types::Kind::Enum(ref variants) => {
50                    if variants.len() != #num_variants {
51                        return false;
52                    }
53
54                    variants.iter().all(|v| {
55                        match &**v {
56                            #(
57                                #variant_names => true,
58                            )*
59                            _ => false,
60                        }
61                    })
62                }
63                _ => false,
64            }
65        }
66    }
67}
68
69pub fn composite_body(name: &str, trait_: &str, fields: &[Field]) -> TokenStream {
70    let num_fields = fields.len();
71    let trait_ = Ident::new(trait_, Span::call_site());
72    let traits = iter::repeat(&trait_);
73    let field_names = fields.iter().map(|f| &f.name);
74    let field_types = fields.iter().map(|f| &f.type_);
75
76    quote! {
77        if type_.name() != #name {
78            return false;
79        }
80
81        match *type_.kind() {
82            ::postgres_types::Kind::Composite(ref fields) => {
83                if fields.len() != #num_fields {
84                    return false;
85                }
86
87                fields.iter().all(|f| {
88                    match f.name() {
89                        #(
90                            #field_names => {
91                                <#field_types as ::postgres_types::#traits>::accepts(f.type_())
92                            }
93                        )*
94                        _ => false,
95                    }
96                })
97            }
98            _ => false,
99        }
100    }
101}