1
- use crate :: { attr:: * , IdentExt , camel_to_snake, r#struct:: * } ;
1
+ use crate :: { attr:: * , IdentExt , camel_to_snake, r#struct:: * , AsSnake } ;
2
2
3
3
use proc_macro2:: Span ;
4
4
use syn:: {
@@ -7,6 +7,7 @@ use syn::{
7
7
token, Attribute , Ident , LitStr ,
8
8
Meta :: * ,
9
9
MetaNameValue ,
10
+ Index ,
10
11
} ;
11
12
12
13
pub struct Input {
@@ -35,12 +36,12 @@ impl<'i, B: Builder<'i>> Builder<'i> for CustomTableMacro<B> {
35
36
}
36
37
}
37
38
38
- pub struct ModelWithId < B > ( pub B ) ;
39
+ pub struct ModelWithId ;
39
40
40
- impl < ' i , B : Builder < ' i > > Builder < ' i > for ModelWithId < B > {
41
+ impl < ' i > Builder < ' i > for ModelWithId {
41
42
fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
42
43
let model_name_with_id = input. parsed_struct . ident . append ( "WithId" ) ;
43
- let fields = self . 0 . build ( input) ?;
44
+ let fields = ModelWithIdFields . build ( input) ?;
44
45
45
46
Ok ( quote ! {
46
47
pub struct #model_name_with_id {
@@ -50,9 +51,9 @@ impl<'i, B: Builder<'i>> Builder<'i> for ModelWithId<B> {
50
51
}
51
52
}
52
53
53
- pub struct Fields ;
54
+ pub struct ModelWithIdFields ;
54
55
55
- impl < ' i > Builder < ' i > for Fields {
56
+ impl < ' i > Builder < ' i > for ModelWithIdFields {
56
57
fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
57
58
let mut fields = Vec :: new ( ) ;
58
59
fields. push ( quote ! ( pub id: i32 ) ) ;
@@ -72,12 +73,12 @@ impl<'i> Builder<'i> for Fields {
72
73
}
73
74
}
74
75
75
- pub struct Model < B > ( pub B ) ;
76
+ pub struct Model ;
76
77
77
- impl < ' i , B : Builder < ' i > > Builder < ' i > for Model < B > {
78
+ impl < ' i > Builder < ' i > for Model {
78
79
fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
79
80
let model_name = & input. parsed_struct . ident ;
80
- let fields = self . 0 . build ( input) ?;
81
+ let fields = ModelFields . build ( input) ?;
81
82
82
83
Ok ( quote ! {
83
84
pub struct #model_name {
@@ -87,9 +88,9 @@ impl<'i, B: Builder<'i>> Builder<'i> for Model<B> {
87
88
}
88
89
}
89
90
90
- pub struct InnerFields ;
91
+ pub struct ModelFields ;
91
92
92
- impl < ' i > Builder < ' i > for InnerFields {
93
+ impl < ' i > Builder < ' i > for ModelFields {
93
94
fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
94
95
let mut fields = Vec :: new ( ) ;
95
96
input. parsed_struct . fields . iter ( ) . for_each ( |field| {
@@ -104,3 +105,95 @@ impl<'i> Builder<'i> for InnerFields {
104
105
}
105
106
}
106
107
108
+ pub struct Table ;
109
+
110
+ impl < ' i > Builder < ' i > for Table {
111
+ fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
112
+ let model = input. parsed_struct . as_snake_plural ( ) ;
113
+ Ok ( quote ! ( crate :: schema:: #model) )
114
+ }
115
+ }
116
+
117
+ pub struct QueryableRow ;
118
+
119
+ impl < ' i > Builder < ' i > for QueryableRow {
120
+ fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
121
+ let mut fields = Vec :: new ( ) ;
122
+ fields. push ( quote ! ( i32 ) ) ;
123
+
124
+ input. parsed_struct . fields . iter ( ) . for_each ( |field| {
125
+ let ty = field. ty ( ) ;
126
+ fields. push ( quote ! ( #ty) ) ;
127
+ } ) ;
128
+
129
+ Ok ( quote ! ( type Row = ( #( #fields, ) * ) ; ) )
130
+ }
131
+ }
132
+
133
+ pub struct QueryableFields ;
134
+
135
+ impl < ' i > Builder < ' i > for QueryableFields {
136
+ fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
137
+ let mut fields = Vec :: new ( ) ;
138
+ let mut inner_fields = Vec :: new ( ) ;
139
+
140
+ let model_name = input. parsed_struct . inner_model_name ( ) ;
141
+
142
+ let mut index = 0 ;
143
+
144
+ // Push id
145
+ let idx = Index :: from ( index) ;
146
+ fields. push ( quote ! ( id: row. #idx) ) ;
147
+
148
+ input. parsed_struct . fields . iter ( ) . enumerate ( ) . for_each ( |( i, field) | {
149
+ let field_name = & field. name ;
150
+ if !field. fk ( ) {
151
+ index = i + 1 ;
152
+ let idx = Index :: from ( index) ;
153
+ inner_fields. push ( quote ! ( #field_name: row. #idx) ) ;
154
+ }
155
+ } ) ;
156
+
157
+ let generated_inner_fields = quote ! ( { #( #inner_fields, ) * } ) ;
158
+
159
+ // Push inner fields
160
+ fields. push ( quote ! ( inner: #model_name #generated_inner_fields) ) ;
161
+
162
+ // Push remaining fields
163
+ input. parsed_struct . fields . iter ( ) . for_each ( |field| {
164
+ if field. fk ( ) {
165
+ index = index + 1 ;
166
+ let name = & field. name ;
167
+ let idx = Index :: from ( index) ;
168
+ fields. push ( quote ! ( #name: row. #idx) ) ;
169
+ }
170
+ } ) ;
171
+
172
+ Ok ( quote ! ( #( #fields, ) * ) )
173
+ }
174
+ }
175
+
176
+ pub struct Queryable ;
177
+
178
+ impl < ' i > Builder < ' i > for Queryable {
179
+ fn build ( self , input : & ' i Input ) -> Result < proc_macro2:: TokenStream > {
180
+ let table = input. parsed_struct . as_snake_plural ( ) ;
181
+ let fields = QueryableFields . build ( input) ?;
182
+ let row = QueryableRow . build ( input) ?;
183
+
184
+ let model_with_id = input. parsed_struct . model_name ( ) ;
185
+
186
+ Ok ( quote ! {
187
+ impl diesel:: Queryable <#table:: SqlType , diesel:: pg:: Pg > for #model_with_id {
188
+ #row
189
+ fn build( row: Self :: Row ) -> Self {
190
+ #model_with_id {
191
+ #fields
192
+ }
193
+ }
194
+ }
195
+ } )
196
+ }
197
+ }
198
+
199
+
0 commit comments