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
mod from_row;
mod row;
mod table_templ;
mod to_row;

use ::quote::quote;
use from_row::expand_from_row;

use row::expand_row;
use syn::parse_macro_input;
use syn::DeriveInput;

use proc_macro::TokenStream as V1TokenStream;

use proc_macro2::{Ident, Span};

use proc_macro_crate::{crate_name, FoundCrate};
use table_templ::expand_table_templ;
use to_row::expand_to_row;

use crate::row::RowInput;

// inspired from https://github.com/serde-rs/serde/blob/master/serde_derive

#[proc_macro_derive(TableTempl, attributes(len, index, unique))]
pub fn derive_table_templ(input: V1TokenStream) -> V1TokenStream {
	let input = parse_macro_input!(input as DeriveInput);

	// crate name
	let name =
		crate_name("fire-postgres").expect("fire-postgres not in dependencies");
	let name = match name {
		FoundCrate::Itself => quote!(crate),
		FoundCrate::Name(n) => {
			let ident = Ident::new(&n, Span::call_site());
			quote!(#ident)
		}
	};

	expand_table_templ(&input, &name).unwrap_or_else(to_compile_error)
}

// attributes(len, index, unique)
#[proc_macro_derive(FromRow)]
pub fn derive_from_row(input: V1TokenStream) -> V1TokenStream {
	let input = parse_macro_input!(input as DeriveInput);

	// crate name
	let name =
		crate_name("fire-postgres").expect("fire-postgres not in dependencies");
	let name = match name {
		FoundCrate::Itself => quote!(crate),
		FoundCrate::Name(n) => {
			let ident = Ident::new(&n, Span::call_site());
			quote!(#ident)
		}
	};

	expand_from_row(&input, &name).unwrap_or_else(to_compile_error)
}

// attributes(len, index, unique)
#[proc_macro_derive(ToRow)]
pub fn derive_to_row(input: V1TokenStream) -> V1TokenStream {
	let input = parse_macro_input!(input as DeriveInput);

	// crate name
	let name =
		crate_name("fire-postgres").expect("fire-postgres not in dependencies");
	let name = match name {
		FoundCrate::Itself => quote!(crate),
		FoundCrate::Name(n) => {
			let ident = Ident::new(&n, Span::call_site());
			quote!(#ident)
		}
	};

	expand_to_row(&input, &name).unwrap_or_else(to_compile_error)
}

#[proc_macro]
pub fn row(input: V1TokenStream) -> V1TokenStream {
	let input = parse_macro_input!(input as RowInput);

	// crate name
	let name =
		crate_name("fire-postgres").expect("fire-postgres not in dependencies");
	let name = match name {
		FoundCrate::Itself => quote!(crate),
		FoundCrate::Name(n) => {
			let ident = Ident::new(&n, Span::call_site());
			quote!(#ident)
		}
	};

	expand_row(&input, &name).unwrap_or_else(to_compile_error)
}

fn to_compile_error(error: syn::Error) -> V1TokenStream {
	let compile_error = syn::Error::to_compile_error(&error);
	quote!(#compile_error).into()
}